diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..f6bca79 Binary files /dev/null and b/.DS_Store differ diff --git a/Agents/AgentHost.cs b/Agents/AgentHost.cs new file mode 100755 index 0000000..e47cd77 --- /dev/null +++ b/Agents/AgentHost.cs @@ -0,0 +1,85 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Diagnostics; +using System.Windows; +using PhoneVoIPApp.BackEnd; +using PhoneVoIPApp.BackEnd.OutOfProcess; + +namespace PhoneVoIPApp.Agents +{ + /// + /// A static class that does process-level initialization/deinitializations. + /// + public static class AgentHost + { + #region Methods + + /// + /// Indicates that an agent started running. + /// + internal static void OnAgentStarted() + { + // Initialize the native code - this only needs to be done once per process,s + // but the method below will effectively be a no-op if called more than once. + BackEnd.Globals.Instance.StartServer(RegistrationHelper.OutOfProcServerClassNames); + } + + #endregion + + #region Private members + + /// + /// Class constructor + /// + static AgentHost() + { + // Subscribe to the unhandled exception event + Deployment.Current.Dispatcher.BeginInvoke(delegate + { + Application.Current.UnhandledException += AgentHost.OnUnhandledException; + }); + + // Create the singleton video renderer + AgentHost.videoRenderer = new VideoRenderer(); + + AgentHost.mtProtoUpdater = new MTProtoUpdater(); + + // Store a pointer to the video renderer in the native Globals singleton, + // so that the renderer can be used by native code in this process. + Globals.Instance.VideoRenderer = AgentHost.videoRenderer; + + Globals.Instance.MTProtoUpdater = AgentHost.mtProtoUpdater; + } + + /// + /// Code to execute on unhandled exceptions. + /// + private static void OnUnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) + { + Debug.WriteLine("[AgentHost] An unhandled exception of type {0} has occurred. Error code: 0x{1:X8}. Message: {2}", + e.ExceptionObject.GetType(), e.ExceptionObject.HResult, e.ExceptionObject.Message); + + if (Debugger.IsAttached) + { + // An unhandled exception has occurred; break into the debugger + Debugger.Break(); + } + } + + #endregion + + #region Private + + // The singleton video renderer + static VideoRenderer videoRenderer; + + static MTProtoUpdater mtProtoUpdater; + + #endregion + } +} diff --git a/Agents/Agents.csproj b/Agents/Agents.csproj new file mode 100755 index 0000000..7bd5e67 --- /dev/null +++ b/Agents/Agents.csproj @@ -0,0 +1,128 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {820034C1-645D-4340-8813-D980C1EF77DE} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + PhoneVoIPApp.Agents + PhoneVoIPApp.Agents + WindowsPhone + v8.1 + + + false + true + 12.0 + true + + en-US + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\x86\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + pdbonly + true + Bin\x86\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + true + full + false + Bin\ARM\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + pdbonly + true + Bin\ARM\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + + + + + + + + + + + + + + + + + + {C8D75245-FFCF-4932-A228-C9CC8BB60B03} + BackEnd + + + {e79d5093-8038-4a5f-8a98-ca38c0d0886f} + Telegram.Api.WP8 + + + + + + + \ No newline at end of file diff --git a/Agents/CallInProgressAgentImpl.cs b/Agents/CallInProgressAgentImpl.cs new file mode 100755 index 0000000..6633af3 --- /dev/null +++ b/Agents/CallInProgressAgentImpl.cs @@ -0,0 +1,172 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using Microsoft.Phone.Networking.Voip; +using PhoneVoIPApp.BackEnd; +using Telegram.Api; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.Connection; +using Telegram.Api.Services.Updates; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Updates; +using Telegram.Api.Transport; + +namespace PhoneVoIPApp.Agents +{ + /// + /// An agent that is launched when the first call becomes active and is canceled when the last call ends. + /// + public class CallInProgressAgentImpl : VoipCallInProgressAgent + { + public static bool Suppress { get; set; } + + private bool _logEnabled = true; + + private void Log(string message, Action callback = null) + { + if (!_logEnabled) return; + + Telegram.Logs.Log.Write(string.Format("[CallInProgressAgentImpl] {0} {1}", GetHashCode(), message), callback.SafeInvoke); +#if DEBUG + //PushUtils.AddToast("push", message, string.Empty, string.Empty, null, null); +#endif + } + + private readonly object _initConnectionSyncRoot = new object(); + + private TLInitConnection GetInitConnection() + { + return TLUtils.OpenObjectFromMTProtoFile(_initConnectionSyncRoot, Constants.InitConnectionFileName) ?? + new TLInitConnection78 + { + Flags = new TLInt(0), + DeviceModel = new TLString("unknown"), + AppVersion = new TLString("background task"), + SystemVersion = new TLString("8.10.0.0") + }; + } + + private static IMTProtoService _mtProtoService; + + private static IMTProtoService MTProtoService + { + get + { + return _mtProtoService; + + } + set + { + _mtProtoService = value; + + } + } + + private static ITransportService _transportService; + + private void InitializeServiceAsync(System.Action callback) + { + Debug.WriteLine("[CallInProgressAgentImpl {0}] _mtProtoService == null {1}", GetHashCode(), _mtProtoService == null); + + if (MTProtoService == null) + { + var deviceInfoService = new Telegram.Api.Services.DeviceInfo.DeviceInfoService(GetInitConnection(), true, "BackgroundDifferenceLoader", 1); + var cacheService = new MockupCacheService(); + var updatesService = new MockupUpdatesService(); + + _transportService = new TransportService(); + var connectionService = new ConnectionService(deviceInfoService); + var publicConfigService = new MockupPublicConfigService(); + + var mtProtoService = new MTProtoService(deviceInfoService, updatesService, cacheService, _transportService, connectionService, publicConfigService); + mtProtoService.Initialized += (o, e) => + { + //Log(string.Format("[MTProtoUpdater {0}] Initialized", GetHashCode())); + Thread.Sleep(1000); + callback.SafeInvoke(); + }; + mtProtoService.InitializationFailed += (o, e) => + { + //Log(string.Format("[MTProtoUpdater {0}] InitializationFailed", GetHashCode())); + }; + mtProtoService.Initialize(); + + MTProtoService = mtProtoService; + } + else + { + callback.SafeInvoke(); + } + } + + /// + /// Constructor + /// + public CallInProgressAgentImpl() + : base() + { + _timer = new Timer(OnTimer); + } + + private Timer _timer; + + private void OnTimer(object state) + { + Log(string.Format("OnTimer call_id={0} suppress={1}", Globals.Instance.CallController != null ? Globals.Instance.CallController.CallId.ToString() : "null", Suppress)); + Debug.WriteLine("[CallInProgressAgentImpl {0}] OnTick.", GetHashCode()); + + //InitializeServiceAsync(() => + //{ + // var getStateAction = new TLGetState(); + // var actions = new List { getStateAction }; + // MTProtoService.SendActionsAsync(actions, (request, result) => + // { + // Log("[CallInProgressAgentImpl] getState result=" + result); + // }, + // error => + // { + // Log("[CallInProgressAgentImpl] getState error=" + error); + // }); + //}); + } + + /// + /// The first call has become active. + /// + protected override void OnFirstCallStarting() + { + Debug.WriteLine("[CallInProgressAgentImpl {0}] The first call has started.", GetHashCode()); + + Log("Start timer"); + // Indicate that an agent has started running + AgentHost.OnAgentStarted(); + _timer.Change(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)); + } + + /// + /// The last call has ended. + /// + protected override void OnCancel() + { + Debug.WriteLine("[CallInProgressAgentImpl {0}] The last call has ended. Calling NotifyComplete", GetHashCode()); + + if (MTProtoService != null) MTProtoService.Stop(); + Log("Stop timer"); + _timer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); + + // This agent is done + base.NotifyComplete(); + } + } +} diff --git a/Agents/ForegroundLifetimeAgentImpl.cs b/Agents/ForegroundLifetimeAgentImpl.cs new file mode 100755 index 0000000..3775111 --- /dev/null +++ b/Agents/ForegroundLifetimeAgentImpl.cs @@ -0,0 +1,57 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Microsoft.Phone.Networking.Voip; +using System.Diagnostics; +using System.Threading; +using Microsoft.Phone.Scheduler; + +namespace PhoneVoIPApp.Agents +{ + /// + /// An agent that is invoked when the UI process calls Microsoft.Phone.Networking.Voip.VoipBackgroundProcess.Launched() + /// and is canceled when the UI leaves the foreground. + /// + public sealed class ForegroundLifetimeAgentImpl : VoipForegroundLifetimeAgent + { + public ForegroundLifetimeAgentImpl() + : base() + { + + } + + /// + /// A method that is called as a result of + /// + protected override void OnLaunched() + { + Debug.WriteLine("[ForegroundLifetimeAgentImpl] The UI has entered the foreground."); + + // Indicate that an agent has started running + AgentHost.OnAgentStarted(); + } + + protected override void OnCancel() + { + Debug.WriteLine("[ForegroundLifetimeAgentImpl] The UI is leaving the foreground"); + + // Make sure that this process has finished becoming ready before trying to complete this agent. + // Otherwise, the process may exit without telling the UI that it is ready (and therefore make the UI unresponsive) + uint currentProcessId = PhoneVoIPApp.BackEnd.Globals.GetCurrentProcessId(); + string backgroundProcessReadyEventName = PhoneVoIPApp.BackEnd.Globals.GetBackgroundProcessReadyEventName(currentProcessId); + using (EventWaitHandle backgroundProcessReadyEvent = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset, name: backgroundProcessReadyEventName)) + { + backgroundProcessReadyEvent.WaitOne(); + Debug.WriteLine("[ForegroundLifetimeAgentImpl] Background process {0} is ready", currentProcessId); + } + + // This agent is done + Debug.WriteLine("[ForegroundLifetimeAgentImpl] Calling NotifyComplete"); + base.NotifyComplete(); + } + } +} diff --git a/Agents/MTProtoUpdater.cs b/Agents/MTProtoUpdater.cs new file mode 100755 index 0000000..3b80875 --- /dev/null +++ b/Agents/MTProtoUpdater.cs @@ -0,0 +1,90 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using PhoneVoIPApp.BackEnd; +using Telegram.Api; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.TL; + +namespace PhoneVoIPApp.Agents +{ + internal class MTProtoUpdater : IMTProtoUpdater, IHandle + { + private static bool _logEnabled = true; + + private static readonly int _id = new Random().Next(999); + + private static void Log(string message, Action callback = null) + { + if (!_logEnabled) return; + + Telegram.Logs.Log.Write(string.Format("::MTProtoUpdater {0} {1}", _id, message), callback.SafeInvoke); +#if DEBUG + //PushUtils.AddToast("push", message, string.Empty, string.Empty, null, null); +#endif + } + + private readonly object _initConnectionSyncRoot = new object(); + + private TLInitConnection GetInitConnection() + { + return TLUtils.OpenObjectFromMTProtoFile(_initConnectionSyncRoot, Constants.InitConnectionFileName) ?? + new TLInitConnection + { + DeviceModel = new TLString("unknown"), + AppVersion = new TLString("background task"), + SystemVersion = new TLString("8.10.0.0") + }; + } + + public void Start(int pts, int date, int qts) + { + Log(string.Format("[MTProtoUpdater {0}] Start timer", GetHashCode())); + + CallInProgressAgentImpl.Suppress = true; + } + + public void Stop() + { + Log(string.Format("[MTProtoUpdater {0}] Stop timer", GetHashCode())); + + CallInProgressAgentImpl.Suppress = false; + } + + public void ReceivedCall(long id, long accessHash) + { + } + + public void DiscardCall(long id, long accessHash) + { + + } + + public static void Handle(TLUpdateBase updateBase) + { + var updatePhoneCall = updateBase as TLUpdatePhoneCall; + if (updatePhoneCall != null) + { + var phoneCallDiscarded = updatePhoneCall.PhoneCall as TLPhoneCallDiscarded61; + //if (phoneCallDiscarded != null && Globals.Instance.CallController.CallId == phoneCallDiscarded.Id.Value) + //{ + // Globals.Instance.CallController.EndCall(); + //} + } + + //Globals.Instance.CallController.HandleUpdatePhoneCall(); + } + + void IHandle.Handle(TLUpdateBase message) + { + Handle(message); + } + } +} diff --git a/Agents/Properties/AssemblyInfo.cs b/Agents/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..c66bad7 --- /dev/null +++ b/Agents/Properties/AssemblyInfo.cs @@ -0,0 +1,44 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("Agents")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Agents")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[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("77ef4b49-898d-4cfc-b8d7-ef7338a0da79")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/Agents/PushPayload.cs b/Agents/PushPayload.cs new file mode 100755 index 0000000..e34225a --- /dev/null +++ b/Agents/PushPayload.cs @@ -0,0 +1,93 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace PhoneVoIPApp.Agents { + using System.Xml.Serialization; + + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.17613")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="WPNotification")] + [System.Xml.Serialization.XmlRootAttribute(Namespace="WPNotification", IsNullable=false)] + public partial class Notification { + + private string nameField; + + /// + [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + private string numberField; + + /// + [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] + public string Number { + get { + return this.numberField; + } + set { + this.numberField = value; + } + } + + private string locKey; + + /// + [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] + public string LocKey + { + get + { + return this.locKey; + } + set + { + this.locKey = value; + } + } + + private string locArguments; + + /// + [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] + public string LocArguments + { + get + { + return this.locArguments; + } + set + { + this.locArguments = value; + } + } + + private string data; + + /// + [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] + public string Data + { + get + { + return this.data; + } + set + { + this.data = value; + } + } + } +} diff --git a/Agents/PushPayload.xml b/Agents/PushPayload.xml new file mode 100755 index 0000000..a0fe862 --- /dev/null +++ b/Agents/PushPayload.xml @@ -0,0 +1,5 @@ + + + Kim Abercrombie + +1-555-555-1234 + diff --git a/Agents/PushUtils.cs b/Agents/PushUtils.cs new file mode 100755 index 0000000..a1416be --- /dev/null +++ b/Agents/PushUtils.cs @@ -0,0 +1,788 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define INTERACTIVE_NOTIFICATIONS +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization.Json; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Windows.Data.Xml.Dom; +using Windows.Storage; +#if WNS_PUSH_SERVICE +using Windows.UI.Notifications; +#endif +using Telegram.Api.Helpers; + +namespace PhoneVoIPApp.Agents +{ + public static class PushUtils2 + { + + private static readonly Dictionary _locKeys = new Dictionary + { + {"PINNED_AUDIO", "pinned a voice message"}, + {"PINNED_CONTACT", "pinned a contact"}, + {"PINNED_DOC", "pinned a file"}, + {"PINNED_GAME", "pinned a game"}, + {"PINNED_GEO", "pinned a map"}, + {"PINNED_GIF", "pinned a GIF"}, + {"PINNED_INVOICE", "pinned an invoice"}, + {"PINNED_NOTEXT", "pinned a message"}, + {"PINNED_PHOTO", "pinned a photo"}, + {"PINNED_STICKER", "pinned a sticker"}, + {"PINNED_TEXT", "pinned \"{1}\""}, + {"PINNED_VIDEO", "pinned a video"}, + + {"MESSAGE_FWDS", "forwarded you {1} messages"}, + {"MESSAGE_TEXT", "{1}"}, + {"MESSAGE_NOTEXT", "sent you a message"}, + {"MESSAGE_PHOTO", "sent you a photo"}, + {"MESSAGE_VIDEO", "sent you a video"}, + {"MESSAGE_DOC", "sent you a document"}, + {"MESSAGE_GIF", "sent you a GIF"}, + {"MESSAGE_AUDIO", "sent you a voice message"}, + {"MESSAGE_CONTACT", "shared a contact with you"}, + {"MESSAGE_GEO", "sent you a map"}, + {"MESSAGE_STICKER", "sent you a sticker"}, + {"MESSAGE_GAME", "invited you to play {1}"}, + {"MESSAGE_INVOICE", "sent you an invoice for {1}"}, + + {"CHAT_MESSAGE_FWDS", "{0} forwarded {2} messages to the group"}, + {"CHAT_MESSAGE_TEXT", "{0}: {2}"}, + {"CHAT_MESSAGE_NOTEXT", "{0} sent a message to the group"}, + {"CHAT_MESSAGE_PHOTO", "{0} sent a photo to the group"}, + {"CHAT_MESSAGE_VIDEO", "{0} sent a video to the group"}, + {"CHAT_MESSAGE_DOC", "{0} sent a document to the group"}, + {"CHAT_MESSAGE_GIF", "{0} sent a GIF to the group"}, + {"CHAT_MESSAGE_AUDIO", "{0} sent a voice message to the group"}, + {"CHAT_MESSAGE_CONTACT", "{0} shared a contact in the group"}, + {"CHAT_MESSAGE_GEO", "{0} sent a map to the group"}, + {"CHAT_MESSAGE_STICKER", "{0} sent a sticker to the group"}, + {"CHAT_MESSAGE_GAME", "{0} invited the group to play {2}"}, + {"CHAT_MESSAGE_INVOICE", "{0} sent an invoice for {2}"}, + + {"CHANNEL_MESSAGE_FWDS", "posted {1} forwarded messages"}, + {"CHANNEL_MESSAGE_TEXT", "{1}"}, + {"CHANNEL_MESSAGE_NOTEXT", "posted a message"}, + {"CHANNEL_MESSAGE_PHOTO", "posted a photo"}, + {"CHANNEL_MESSAGE_VIDEO", "posted a video"}, + {"CHANNEL_MESSAGE_DOC", "posted a document"}, + {"CHANNEL_MESSAGE_GIF", "posted a GIF"}, + {"CHANNEL_MESSAGE_AUDIO", "posted a voice message"}, + {"CHANNEL_MESSAGE_CONTACT", "posted a contact"}, + {"CHANNEL_MESSAGE_GEO", "posted a map"}, + {"CHANNEL_MESSAGE_STICKER", "posted a sticker"}, + {"CHANNEL_MESSAGE_GAME", "invited you to play {1}"}, + + {"CHAT_CREATED", "{0} invited you to the group"}, + {"CHAT_TITLE_EDITED", "{0} edited the group's name"}, + {"CHAT_PHOTO_EDITED", "{0} edited the group's photo"}, + {"CHAT_ADD_MEMBER", "{0} invited {2} to the group"}, + {"CHAT_ADD_YOU", "{0} invited you to the group"}, + {"CHAT_DELETE_MEMBER", "{0} kicked {2} from the group"}, + {"CHAT_DELETE_YOU", "{0} kicked you from the group"}, + {"CHAT_LEFT", "{0} has left the group"}, + {"CHAT_RETURNED", "{0} has returned to the group"}, + {"GEOCHAT_CHECKIN", "{0} has checked-in"}, + {"CHAT_JOINED", "{0} has joined the group"}, + + {"CONTACT_JOINED", "{0} joined the App!"}, + {"AUTH_UNKNOWN", "New login from unrecognized device {0}"}, + {"AUTH_REGION", "New login from unrecognized device {0}, location: {1}"}, + + {"CONTACT_PHOTO", "updated profile photo"}, + + {"ENCRYPTION_REQUEST", "You have a new message"}, + {"ENCRYPTION_ACCEPT", "You have a new message"}, + {"ENCRYPTED_MESSAGE", "You have a new message"}, + + {"DC_UPDATE", "Open this notification to update app settings"}, + + {"LOCKED_MESSAGE", "You have a new message"} + }; + + private static void AppendTile(XmlDocument toTile, XmlDocument fromTile) + { + var fromTileNode = toTile.ImportNode(fromTile.GetElementsByTagName("binding").Item(0), true); + toTile.GetElementsByTagName("visual")[0].AppendChild(fromTileNode); + } + + private static void UpdateTile(string caption, string message) + { +#if WNS_PUSH_SERVICE + var tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication("xcee0f789y8059y4881y8883y347265c01f93x"); + //tileUpdater.EnableNotificationQueue(false); + tileUpdater.EnableNotificationQueue(true); + tileUpdater.EnableNotificationQueueForSquare150x150(false); + //tileUpdater.EnableNotificationQueueForWide310x150(true); + + var wideTileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150IconWithBadgeAndText); + SetImage(wideTileXml, "IconicSmall110.png"); + SetText(wideTileXml, caption, message); + + var squareTile150Xml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150IconWithBadge); + SetImage(squareTile150Xml, "IconicTileMedium202.png"); + AppendTile(wideTileXml, squareTile150Xml); + + var squareTile71Xml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare71x71IconWithBadge); + SetImage(squareTile71Xml, "IconicSmall110.png"); + AppendTile(wideTileXml, squareTile71Xml); + + try + { + tileUpdater.Update(new TileNotification(wideTileXml)); + } + catch (Exception ex) + { + Telegram.Logs.Log.Write(ex.ToString()); + } +#endif + } + + private static void UpdateBadge(int badgeNumber) + { +#if WNS_PUSH_SERVICE + var badgeUpdater = BadgeUpdateManager.CreateBadgeUpdaterForApplication("xcee0f789y8059y4881y8883y347265c01f93x"); + if (badgeNumber == 0) + { + badgeUpdater.Clear(); + return; + } + + var badgeXml = BadgeUpdateManager.GetTemplateContent(BadgeTemplateType.BadgeNumber); + + var badgeElement = (XmlElement)badgeXml.SelectSingleNode("/badge"); + badgeElement.SetAttribute("value", badgeNumber.ToString()); + + try + { + badgeUpdater.Update(new BadgeNotification(badgeXml)); + } + catch (Exception ex) + { + Telegram.Logs.Log.Write(ex.ToString()); + } +#endif + } + + private static bool IsMuted(Data data) + { + return data.mute == "1"; + } + + private static bool IsServiceNotification(Data data) + { + return data.loc_key == "DC_UPDATE"; + } + + private static void RemoveToastGroup(string groupname) + { +#if WNS_PUSH_SERVICE + ToastNotificationManager.History.RemoveGroup(groupname); +#endif + } + + private static string GetCaption(Data data) + { + var locKey = data.loc_key; + if (locKey == null) + { + return "locKey=null"; + } + + if (locKey.StartsWith("CHAT") || locKey.StartsWith("GEOCHAT")) + { + return data.loc_args[1]; + } + + if (locKey.StartsWith("MESSAGE")) + { + return data.loc_args[0]; + } + + if (locKey.StartsWith("CHANNEL")) + { + return data.loc_args[0]; + } + + if (locKey.StartsWith("PINNED")) + { + return data.loc_args[0]; + } + + if (locKey.StartsWith("AUTH") + || locKey.StartsWith("CONTACT") + || locKey.StartsWith("ENCRYPTED") + || locKey.StartsWith("ENCRYPTION") + || locKey.StartsWith("PHONE")) + { + return "Telegram"; + } + +#if DEBUG + return locKey; +#else + return "Telegram"; +#endif + } + + private static string GetSound(Data data) + { + return data.sound; + } + + private static string GetGroup(Data data) + { + return data.group; + } + + private static string GetTag(Data data) + { + return data.tag; + } + + private static string GetLaunch(Data data) + { + var locKey = data.loc_key; + if (locKey == null) return null; + + var path = "/Views/ShellView.xaml"; + if (locKey == "DC_UPDATE") + { + path = "/Views/Additional/SettingsView.xaml"; + } + + var customParams = new List { "Action=" + locKey }; + if (data.custom != null) + { + customParams.AddRange(data.custom.GetParams()); + } + + return string.Format("{0}?{1}", path, string.Join("&", customParams)); + } + + private static string GetMessage(Data data) + { + var locKey = data.loc_key; + if (locKey == null) + { + Telegram.Logs.Log.Write("::PushNotificationsBackgroundTask locKey=null text=" + data.text); + return string.Empty; + } + + string locValue = ""; + if (_locKeys.TryGetValue(locKey, out locValue)) + { + + } + //var resourceLoader = ResourceLoader.GetForViewIndependentUse("TelegramClient.Tasks/Resources"); + //locValue = resourceLoader.GetString(locKey); + + if (locValue != "") + { + return string.Format(locValue, data.loc_args).Replace("\r\n", "\n").Replace("\n", " "); + } + var builder = new StringBuilder(); + if (data.loc_args != null) + { + builder.AppendLine("loc_args"); + foreach (var locArg in data.loc_args) + { + builder.AppendLine(locArg); + } + } + Telegram.Logs.Log.Write(string.Format("::PushNotificationsBackgroundTask missing locKey={0} locArgs={1}", locKey, builder.ToString())); + + //if (locKey.StartsWith("CHAT") || locKey.StartsWith("GEOCHAT")) + //{ + // return data.text; + //} + + //if (locKey.StartsWith("MESSAGE")) + //{ + // if (locKey == "MESSAGE_TEXT") + // { + // return data.loc_args[1]; + // } + + // return data.text; //add localization string here + //} + +#if DEBUG + return data.text; +#else + return string.Empty; +#endif + } + + public static void UpdateToastAndTiles(RootObject rootObject) + { + if (rootObject == null) return; + if (rootObject.data == null) return; + + if (rootObject.data.loc_key == null) + { + var groupname = GetGroup(rootObject.data); + RemoveToastGroup(groupname); + return; + } + + var caption = GetCaption(rootObject.data); + var message = GetMessage(rootObject.data); + var sound = GetSound(rootObject.data); + var launch = GetLaunch(rootObject.data); + var tag = GetTag(rootObject.data); + var group = GetGroup(rootObject.data); + + if (!IsMuted(rootObject.data) && !Notifications.IsDisabled) + { + AddToast(rootObject, caption, message, sound, launch, tag, group); + } + if (!IsServiceNotification(rootObject.data)) + { + UpdateTile(caption, message); + } + UpdateBadge(rootObject.data.badge); + } + + private static void SetToastImage(XmlDocument document, string imageSource, bool isUserPlaceholder) + { + var imageElements = document.GetElementsByTagName("image"); + if (imageSource == null) + { + ((XmlElement)imageElements[0]).SetAttribute("src", isUserPlaceholder ? "ms-appx:///Images/W10M/user_placeholder.png" : "ms-appx:///Images/W10M/group_placeholder.png"); + } + else + { + ((XmlElement)imageElements[0]).SetAttribute("src", "ms-appdata:///local/" + imageSource); + } + } + + private static void SetImage(XmlDocument document, string imageSource) + { + var imageElements = document.GetElementsByTagName("image"); + ((XmlElement)imageElements[0]).SetAttribute("src", imageSource); + } + + private static void SetSound(XmlDocument document, string soundSource) + { + //return; + + if (!Regex.IsMatch(soundSource, @"^sound[1-6]$", RegexOptions.IgnoreCase)) + { + return; + } + + var toastNode = document.SelectSingleNode("/toast"); + ((XmlElement)toastNode).SetAttribute("duration", "long"); + var audioElement = document.CreateElement("audio"); + audioElement.SetAttribute("src", "ms-appx:///Sounds/" + soundSource + ".wav"); + audioElement.SetAttribute("loop", "false"); + + toastNode.AppendChild(audioElement); + } + + private static void SetLaunch(RootObject rootObject, XmlDocument document, string launch) + { + if (string.IsNullOrEmpty(launch)) + { + return; + } + if (rootObject != null + && rootObject.data != null + && rootObject.data.system != null + && rootObject.data.system.StartsWith("10")) //10.0.10572.0 or less + { + try + { + var currentVersion = new Version(rootObject.data.system); + var minVersion = new Version("10.0.10572.0"); + if (currentVersion < minVersion) + { + return; + } + } + catch (Exception ex) + { + Telegram.Logs.Log.Write(ex.ToString()); + } + } + //launch = "/Views/ShellView.xaml"; + var toastNode = document.SelectSingleNode("/toast"); + ((XmlElement)toastNode).SetAttribute("launch", launch); + } + + private static void SetText(XmlDocument document, string caption, string message) + { + var toastTextElements = document.GetElementsByTagName("text"); + toastTextElements[0].InnerText = caption ?? string.Empty; + toastTextElements[1].InnerText = message ?? string.Empty; + } + + private static string GetArguments(string peer, string peerId, bool needAccessHash, Custom custom) + { + string arguments = null; + + if (custom.mtpeer != null && custom.mtpeer.ah != null || !needAccessHash) + { + arguments = string.Format("{0}={1}", peer, peerId); + + if (custom.mtpeer != null && custom.mtpeer.ah != null) + { + arguments += string.Format(" access_hash={0}", custom.mtpeer.ah); + } + + if (custom.msg_id != null) + { + arguments += string.Format(" msg_id={0}", custom.msg_id); + } + } + + return arguments; + } + + private static void GetArgumentsAndImageSource(RootObject rootObject, out string arguments, out string imageSource) + { + arguments = null; + imageSource = null; + + if (rootObject != null) + { + var data = rootObject.data; + if (data != null) + { + var custom = data.custom; + if (custom != null) + { + if (custom.from_id != null) + { + int fromId; + if (Int32.TryParse(custom.from_id, out fromId)) + { + arguments = GetArguments("from_id", custom.from_id, true, custom); + } + } + else if (custom.chat_id != null) + { + int chatId; + if (Int32.TryParse(custom.chat_id, out chatId)) + { + arguments = GetArguments("chat_id", custom.chat_id, false, custom); + } + } + else if (custom.channel_id != null) + { + int channelId; + if (Int32.TryParse(custom.channel_id, out channelId)) + { + if (data.loc_key != null + && data.loc_key.StartsWith("CHAT")) + { + arguments = GetArguments("channel_id", custom.channel_id, true, custom); + } + } + } + + imageSource = GetImageSource(custom); + } + } + } + } + + private static void SetActions(XmlDocument document, string arguments) + { + if (arguments == null) return; + + //var resourceLoader = ResourceLoader.GetForViewIndependentUse("TelegramClient.Tasks/Resources"); + + //"" + + //"" + + //"" + + //"" + + var toastNode = document.SelectSingleNode("/toast"); + var actionsElement = document.CreateElement("actions"); + + var inputElement = document.CreateElement("input"); + inputElement.SetAttribute("id", "message"); + inputElement.SetAttribute("type", "text"); + inputElement.SetAttribute("placeHolderContent", "Type reply"); //resourceLoader.GetString("TypeReply")); + actionsElement.AppendChild(inputElement); + + var replyAction = document.CreateElement("action"); + replyAction.SetAttribute("activationType", "background"); + replyAction.SetAttribute("content", "Reply"); //resourceLoader.GetString("Reply")); + replyAction.SetAttribute("arguments", "action=reply " + arguments); + replyAction.SetAttribute("hint-inputId", "message"); + replyAction.SetAttribute("imageUri", "Images/W10M/ic_send_2x.png"); + actionsElement.AppendChild(replyAction); + + var muteAction = document.CreateElement("action"); + muteAction.SetAttribute("activationType", "background"); + muteAction.SetAttribute("content", "Mute 1 hour"); //resourceLoader.GetString("Mute1Hour")); + muteAction.SetAttribute("arguments", "action=mute " + arguments); + actionsElement.AppendChild(muteAction); + + var disableAction = document.CreateElement("action"); + disableAction.SetAttribute("activationType", "background"); + disableAction.SetAttribute("content", "Disable"); //resourceLoader.GetString("Disable")); + disableAction.SetAttribute("arguments", "action=disable " + arguments); + actionsElement.AppendChild(disableAction); + + toastNode.AppendChild(actionsElement); + } + + public static void AddToast(RootObject rootObject, string caption, string message, string sound, string launch, string tag, string group) + { +#if WNS_PUSH_SERVICE + +#if INTERACTIVE_NOTIFICATIONS + + var toastNotifier = ToastNotificationManager.CreateToastNotifier("xcee0f789y8059y4881y8883y347265c01f93x"); //("xcee0f789y8059y4881y8883y347265c01f93x"); + //toastNotifier.Setting = + Version version = Environment.OSVersion.Version; + if (rootObject.data.system != null && rootObject.data.system != null) + { + Version.TryParse(rootObject.data.system, out version); + } + var toastXml = new XmlDocument(); + if (version != null && version.Major >= 10) + { + string arguments; + string imageSource; + GetArgumentsAndImageSource(rootObject, out arguments, out imageSource); + + var xml = + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + toastXml.LoadXml(xml); + SetToastImage(toastXml, imageSource, arguments != null && arguments.StartsWith("from_id")); + SetActions(toastXml, arguments); + } + else + { + toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); + } + + SetText(toastXml, caption, message); + SetLaunch(rootObject, toastXml, launch); + + if (!string.IsNullOrEmpty(sound) + && !string.Equals(sound, "default", StringComparison.OrdinalIgnoreCase)) + { + SetSound(toastXml, sound); + } + + try + { + var toast = new ToastNotification(toastXml); + if (tag != null) toast.Tag = tag; + if (group != null) toast.Group = group; + //RemoveToastGroup(group); + toastNotifier.Show(toast); + } + catch (Exception ex) + { + Telegram.Logs.Log.Write(ex.ToString()); + } +#else + var toastNotifier = ToastNotificationManager.CreateToastNotifier(); + + var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); + SetText(toastXml, caption, message); + SetLaunch(toastXml, launch); + + if (!string.IsNullOrEmpty(sound) + && !string.Equals(sound, "default", StringComparison.OrdinalIgnoreCase)) + { + SetSound(toastXml, sound); + } + + try + { + var toast = new ToastNotification(toastXml); + if (tag != null) toast.Tag = tag; + if (group != null) toast.Group = group; + //RemoveToastGroup(group); + toastNotifier.Show(toast); + } + catch (Exception ex) + { + Telegram.Logs.Log.Write(ex.ToString()); + } +#endif + +#endif + } + + public static T GetRootObject(string payload) where T : class + { + var serializer = new DataContractJsonSerializer(typeof(T)); + T rootObject; + using (var stream = new MemoryStream(Encoding.Unicode.GetBytes(payload))) + { + rootObject = serializer.ReadObject(stream) as T; + } + + return rootObject; + } + + private static async Task IsFileExists(string fileName) + { + bool fileExists = true; + Stream fileStream = null; + StorageFile file = null; + + try + { + file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName); + fileStream = await file.OpenStreamForReadAsync(); + fileStream.Dispose(); + } + catch (FileNotFoundException) + { + // If the file dosn't exits it throws an exception, make fileExists false in this case + fileExists = false; + } + finally + { + if (fileStream != null) + { + fileStream.Dispose(); + } + } + + return fileExists; + } + + private static string GetImageSource(Custom custom) + { + string imageSource = null; + if (custom.mtpeer != null) + { + var location = custom.mtpeer.ph; + if (location != null) + { + var fileName = String.Format("{0}_{1}_{2}.jpg", + location.volume_id, + location.local_id, + location.secret); + + if (IsFileExists(fileName).Result) + { + imageSource = fileName; + } + } + } + + return imageSource; + } + + public static string GetImageSource(MTPeer mtpeer) + { + string imageSource = null; + if (mtpeer != null) + { + var location = mtpeer.ph; + if (location != null) + { + var fileName = String.Format("{0}_{1}_{2}.jpg", + location.volume_id, + location.local_id, + location.secret); + + if (IsFileExists(fileName).Result) + { + imageSource = fileName; + } + } + } + + return imageSource; + } + } + + public sealed class Photo + { + public string volume_id { get; set; } + public string local_id { get; set; } + public string secret { get; set; } + public int dc_id { get; set; } + } + + public sealed class MTPeer + { + public string ah { get; set; } + public Photo ph { get; set; } + } + + public sealed class Custom + { + public string msg_id { get; set; } + public string from_id { get; set; } + public string chat_id { get; set; } + public string channel_id { get; set; } + public MTPeer mtpeer { get; set; } + public string call_id { get; set; } + public string call_ah { get; set; } + + public string group + { + get + { + if (chat_id != null) return "c" + chat_id; + if (channel_id != null) return "c" + chat_id; + if (from_id != null) return "u" + from_id; + return null; + } + } + + public string tag { get { return msg_id; } } + + public IEnumerable GetParams() + { + if (msg_id != null) yield return "msg_id=" + msg_id; + if (from_id != null) yield return "from_id=" + from_id; + if (chat_id != null) yield return "chat_id=" + chat_id; + if (channel_id != null) yield return "channel_id=" + channel_id; + } + } + + public sealed class Data + { + public Custom custom { get; set; } + public string sound { get; set; } + public string mute { get; set; } + public int badge { get; set; } + public string loc_key { get; set; } + public string[] loc_args { get; set; } + public int random_id { get; set; } + public int user_id { get; set; } + public string text { get; set; } + public string system { get; set; } + + public string group { get { return custom != null ? custom.group : null; } } + public string tag { get { return custom != null ? custom.tag : null; } } + } + + public sealed class RootObject + { + public int date { get; set; } + public Data data { get; set; } + } +} diff --git a/Agents/RegistrationHelper.cs b/Agents/RegistrationHelper.cs new file mode 100755 index 0000000..691a724 --- /dev/null +++ b/Agents/RegistrationHelper.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34011 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace PhoneVoIPApp.BackEnd.OutOfProcess { + + + internal sealed class RegistrationHelper { + + internal static string[] OutOfProcServerClassNames = new string[] { + "PhoneVoIPApp.BackEnd.OutOfProcess.Server"}; + } +} diff --git a/Agents/ScheduledAgentImpl.cs b/Agents/ScheduledAgentImpl.cs new file mode 100755 index 0000000..9e529be --- /dev/null +++ b/Agents/ScheduledAgentImpl.cs @@ -0,0 +1,354 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Net; +using System.Text; +using System.Threading; +using System.Xml.Serialization; +using Windows.Data.Xml.Dom; +using Windows.UI.Notifications; +using Microsoft.Phone.Networking.Voip; +using Microsoft.Phone.Scheduler; +using PhoneVoIPApp.BackEnd; +using Telegram.Api; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.Connection; +using Telegram.Api.Services.Location; +using Telegram.Api.Services.Updates; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Phone; +using Telegram.Api.Transport; + +namespace PhoneVoIPApp.Agents +{ + public class ScheduledAgentImpl : ScheduledTaskAgent + { + private readonly Mutex _appOpenMutex = new Mutex(false, Constants.TelegramMessengerMutexName); + + private static bool _logEnabled = true; + + private static readonly int _id = new Random().Next(999); + + private static void Log(string message, Action callback = null) + { + if (!_logEnabled) return; + + Telegram.Logs.Log.WriteSync = true; + Telegram.Logs.Log.Write(string.Format("::ScheduledAgentImpl {0} {1}", _id, message), callback); +#if DEBUG + //PushUtils.AddToast("push", message, string.Empty, string.Empty, null, null); +#endif + } + + public ScheduledAgentImpl() + { + } + + //private static void SetText(XmlDocument document, string caption, string message) + //{ + // var toastTextElements = document.GetElementsByTagName("text"); + // toastTextElements[0].InnerText = caption ?? string.Empty; + // toastTextElements[1].InnerText = message ?? string.Empty; + //} + + private static void SetText(XmlDocument document, string caption, string message) + { + var toastTextElements = document.GetElementsByTagName("text"); + toastTextElements[0].InnerText = caption ?? string.Empty; + toastTextElements[1].InnerText = message ?? string.Empty; + } + + protected override void OnInvoke(ScheduledTask task) + { + Debug.WriteLine("[ScheduledAgentImpl {0}] ScheduledAgentImpl has been invoked with argument of type {1}.", GetHashCode(), task.GetType()); + + // Indicate that an agent has started running + AgentHost.OnAgentStarted(); + + Log(string.Format("start with argument of type {0}", task.GetType())); + if (!_appOpenMutex.WaitOne(0)) + { + Log("cancel"); + Complete(); + return; + } + _appOpenMutex.ReleaseMutex(); + + var incomingCallTask = task as VoipHttpIncomingCallTask; + if (incomingCallTask != null) + { + isIncomingCallAgent = true; + + var messageBody = HttpUtility.HtmlDecode(Encoding.UTF8.GetString(incomingCallTask.MessageBody, 0, incomingCallTask.MessageBody.Length)); + Notification pushNotification = null; + try + { + using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(messageBody ?? string.Empty))) + { + var xs = new XmlSerializer(typeof(Notification)); + pushNotification = (Notification)xs.Deserialize(ms); + } + } + catch (Exception ex) + { + Log(string.Format("cannot deserialize message_body={0}", messageBody)); +#if DEBUG + var toastNotifier = ToastNotificationManager.CreateToastNotifier(); + + var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); + SetText(toastXml, "Notification Exception", string.Empty); + + try + { + var toast = new ToastNotification(toastXml); + //RemoveToastGroup(group); + toastNotifier.Show(toast); + } + catch (Exception ex2) + { + Telegram.Logs.Log.Write(ex.ToString()); + } +#endif + } + + if (pushNotification != null) + { + var rootObject = PushUtils2.GetRootObject(pushNotification.Data); + if (rootObject != null + && rootObject.data != null) + { + if (rootObject.data.custom != null + && rootObject.data.custom.from_id != null + && rootObject.data.custom.call_id != null + && rootObject.data.custom.call_ah != null) + { + var contactImage = PushUtils2.GetImageSource(rootObject.data.custom.mtpeer) ?? string.Empty; + var contactName = rootObject.data.loc_args != null && rootObject.data.loc_args.Length > 0 + ? rootObject.data.loc_args[0] + : string.Empty; + Debug.WriteLine("[{0}] Incoming call from caller {1}, id {2}", incomingCallAgentId, + contactName, rootObject.data.custom.from_id); + + long contactId = 0; + long callId = 0; + long callAccessHash = 0; + if (long.TryParse(rootObject.data.custom.from_id, out contactId) + && long.TryParse(rootObject.data.custom.call_id, out callId) + && long.TryParse(rootObject.data.custom.call_ah, out callAccessHash)) + { + if (string.Equals(rootObject.data.loc_key, "PHONE_CALL_REQUEST", + StringComparison.OrdinalIgnoreCase)) + { + if (BackEnd.Globals.Instance.CallController.CallStatus == CallStatus.InProgress) + { + OnIncomingCallDialogDismissed(callId, callAccessHash, true); + return; + } + + // Initiate incoming call processing + // If you want to pass in additional information such as pushNotification.Number, you can + var incomingCallProcessingStarted = + BackEnd.Globals.Instance.CallController.OnIncomingCallReceived(contactName, + contactId, contactImage, callId, callAccessHash, + OnIncomingCallDialogDismissed); + if (incomingCallProcessingStarted) + { + // will Complete() at OnIncomingCallDialogDismissed + return; + } + + //PushUtils2.AddToast(rootObject, "Caption", "Message", "", "", "tag", "group"); + } + else if (string.Equals(rootObject.data.loc_key, "PHONE_CALL_DECLINE", + StringComparison.OrdinalIgnoreCase)) + { + var currentCallId = BackEnd.Globals.Instance.CallController.CallId; + if (currentCallId == callId) + { + Log(string.Format("PHONE_CALL_DECLINE CallController.EndCall call_id={0}", callId)); + var result = BackEnd.Globals.Instance.CallController.EndCall(); + Log(string.Format("PHONE_CALL_DECLINE CallController.EndCall call_id={0} result={1}", callId, result)); + } + } + } + } + else if (string.Equals(rootObject.data.loc_key, "GEO_LIVE_PENDING")) + { + ProcessLiveLocations(); + } + else + { + //PushUtils2.UpdateToastAndTiles(rootObject); + } + } + } + + Complete(); + return; + } + else + { + VoipKeepAliveTask keepAliveTask = task as VoipKeepAliveTask; + if (keepAliveTask != null) + { + this.isIncomingCallAgent = false; + + // Refresh tokens, get new certs from server, etc. + BackEnd.Globals.Instance.DoPeriodicKeepAlive(); + this.Complete(); + } + else + { + throw new InvalidOperationException(string.Format("Unknown scheduled task type {0}", task.GetType())); + } + } + } + + // This is a request to complete this agent + protected override void OnCancel() + { + Debug.WriteLine("[{0}] Cancel requested.", this.isIncomingCallAgent ? ScheduledAgentImpl.incomingCallAgentId : ScheduledAgentImpl.keepAliveAgentId); + this.Complete(); + } + + private readonly object _initConnectionSyncRoot = new object(); + + private TLInitConnection GetInitConnection() + { + return TLUtils.OpenObjectFromMTProtoFile(_initConnectionSyncRoot, Constants.InitConnectionFileName) ?? + new TLInitConnection + { + DeviceModel = new TLString("unknown"), + AppVersion = new TLString("background task"), + SystemVersion = new TLString("8.10.0.0") + }; + } + + // This method is called when the incoming call processing is complete + private void OnIncomingCallDialogDismissed(long callId, long callAccessHash, bool rejected) + { + Debug.WriteLine("[IncomingCallAgent] Incoming call processing is now complete."); + + if (rejected) + { + var deviceInfoService = new Telegram.Api.Services.DeviceInfo.DeviceInfoService(GetInitConnection(), true, "BackgroundDifferenceLoader", 1); + var cacheService = new MockupCacheService(); + var updatesService = new MockupUpdatesService(); + var transportService = new TransportService(); + var connectionService = new ConnectionService(deviceInfoService); + var publicConfigService = new MockupPublicConfigService(); + + var manualResetEvent = new ManualResetEvent(false); + var mtProtoService = new MTProtoService(deviceInfoService, updatesService, cacheService, transportService, connectionService, publicConfigService); + mtProtoService.Initialized += (o, e) => + { + var peer = new TLInputPhoneCall + { + Id = new TLLong(callId), + AccessHash = new TLLong(callAccessHash) + }; + + var getStateAction = new TLDiscardCall + { + Peer = peer, + Duration = new TLInt(0), + Reason = new TLPhoneCallDiscardReasonBusy(), + ConnectionId = new TLLong(0) + }; + var actions = new List { getStateAction }; + + mtProtoService.SendActionsAsync(actions, + (request, result) => + { + manualResetEvent.Set(); + }, + error => + { + manualResetEvent.Set(); + }); + }; + mtProtoService.InitializationFailed += (o, e) => + { + manualResetEvent.Set(); + }; + mtProtoService.Initialize(); + +#if DEBUG + manualResetEvent.WaitOne(); +#else + manualResetEvent.WaitOne(TimeSpan.FromSeconds(10.0)); +#endif + + mtProtoService.Stop(); + } + + this.Complete(); + } + + private void ProcessLiveLocations() + { + var deviceInfoService = new Telegram.Api.Services.DeviceInfo.DeviceInfoService(GetInitConnection(), true, "BackgroundDifferenceLoader", 1); + var cacheService = new MockupCacheService(); + var updatesService = new MockupUpdatesService(); + var transportService = new TransportService(); + var connectionService = new ConnectionService(deviceInfoService); + var publicConfigService = new MockupPublicConfigService(); + + var manualResetEvent = new ManualResetEvent(false); + var eventAggregator = new TelegramEventAggregator(); + var mtProtoService = new MTProtoService(deviceInfoService, updatesService, cacheService, transportService, connectionService, publicConfigService); + mtProtoService.Initialized += (o, e) => + { + var liveLocationsService = new LiveLocationService(mtProtoService, eventAggregator); + + liveLocationsService.Load(); + + liveLocationsService.UpdateAll(); + + manualResetEvent.Set(); + }; + mtProtoService.InitializationFailed += (o, e) => + { + manualResetEvent.Set(); + }; + mtProtoService.Initialize(); + + var timeout = +#if DEBUG + Timeout.InfiniteTimeSpan; +#else + TimeSpan.FromSeconds(30.0); +#endif + + var result = manualResetEvent.WaitOne(timeout); + } + + // Complete this agent. + private void Complete() + { + Debug.WriteLine("[{0}] Calling NotifyComplete", this.isIncomingCallAgent ? ScheduledAgentImpl.incomingCallAgentId : ScheduledAgentImpl.keepAliveAgentId); + + Log(string.Format("[{0}] Calling NotifyComplete", this.isIncomingCallAgent ? ScheduledAgentImpl.incomingCallAgentId : ScheduledAgentImpl.keepAliveAgentId)); + + // This agent is done + base.NotifyComplete(); + } + + // Strings used in tracing + private const string keepAliveAgentId = "KeepAliveAgent"; + private const string incomingCallAgentId = "IncomingCallAgent"; + + // Indicates if this agent instance is handling an incoming call or not + private bool isIncomingCallAgent; + } +} diff --git a/Agents/VideoMediaStreamSource.cs b/Agents/VideoMediaStreamSource.cs new file mode 100755 index 0000000..2bfaa8d --- /dev/null +++ b/Agents/VideoMediaStreamSource.cs @@ -0,0 +1,222 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Windows.Media; +using System.Threading; + +namespace PhoneVoIPApp.Agents +{ + public class VideoMediaStreamSource : MediaStreamSource, IDisposable + { + public class VideoSample + { + public VideoSample(Windows.Storage.Streams.IBuffer _buffer, UInt64 _hnsPresentationTime, UInt64 _hnsSampleDuration) + { + buffer = _buffer; + hnsPresentationTime = _hnsPresentationTime; + hnsSampleDuration = _hnsSampleDuration; + } + + public Windows.Storage.Streams.IBuffer buffer; + public UInt64 hnsPresentationTime; + public UInt64 hnsSampleDuration; + } + + private const int maxQueueSize = 4; + private int _frameWidth; + private int _frameHeight; + private bool isDisposed = false; + private Queue _sampleQueue; + + private object lockObj = new object(); + private ManualResetEvent shutdownEvent; + + private int _outstandingGetVideoSampleCount; + + private MediaStreamDescription _videoDesc; + private Dictionary _emptySampleDict = new Dictionary(); + + public VideoMediaStreamSource(Stream audioStream, int frameWidth, int frameHeight) + { + _frameWidth = frameWidth; + _frameHeight = frameHeight; + shutdownEvent = new ManualResetEvent(false); + _sampleQueue = new Queue(VideoMediaStreamSource.maxQueueSize); + _outstandingGetVideoSampleCount = 0; + BackEnd.Globals.Instance.TransportController.VideoMessageReceived += TransportController_VideoMessageReceived; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public void Shutdown() + { + shutdownEvent.Set(); + lock (lockObj) + { + if (_outstandingGetVideoSampleCount > 0) + { + // ReportGetSampleCompleted must be called after GetSampleAsync to avoid memory leak. So, send + // an empty MediaStreamSample here. + MediaStreamSample msSamp = new MediaStreamSample( + _videoDesc, + null, + 0, + 0, + 0, + 0, + _emptySampleDict); + ReportGetSampleCompleted(msSamp); + _outstandingGetVideoSampleCount = 0; + } + } + } + + protected virtual void Dispose(bool disposing) + { + if (!this.isDisposed) + { + if (disposing) + { + BackEnd.Globals.Instance.TransportController.VideoMessageReceived -= TransportController_VideoMessageReceived; + } + isDisposed = true; + } + } + + void TransportController_VideoMessageReceived(Windows.Storage.Streams.IBuffer ibuffer, UInt64 hnsPresenationTime, UInt64 hnsSampleDuration) + { + lock (lockObj) + { + if (_sampleQueue.Count >= VideoMediaStreamSource.maxQueueSize) + { + // Dequeue and discard oldest + _sampleQueue.Dequeue(); + } + + _sampleQueue.Enqueue(new VideoSample(ibuffer, hnsPresenationTime, hnsSampleDuration)); + SendSamples(); + } + + } + + private void SendSamples() + { + while (_sampleQueue.Count() > 0 && _outstandingGetVideoSampleCount > 0) + { + if (!(shutdownEvent.WaitOne(0))) + { + VideoSample vs = _sampleQueue.Dequeue(); + Stream s = System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions.AsStream(vs.buffer); + + // Send out the next sample + MediaStreamSample msSamp = new MediaStreamSample( + _videoDesc, + s, + 0, + s.Length, + (long)vs.hnsPresentationTime, + (long)vs.hnsSampleDuration, + _emptySampleDict); + + ReportGetSampleCompleted(msSamp); + _outstandingGetVideoSampleCount--; + } + else + { + // If video rendering is shutting down we should no longer deliver frames + return; + } + } + } + + private void PrepareVideo() + { + // Stream Description + Dictionary streamAttributes = + new Dictionary(); + + // Select the same encoding and dimensions as the video capture + streamAttributes[MediaStreamAttributeKeys.VideoFourCC] = "H264"; + streamAttributes[MediaStreamAttributeKeys.Height] = _frameHeight.ToString(); + streamAttributes[MediaStreamAttributeKeys.Width] = _frameWidth.ToString(); + + MediaStreamDescription msd = + new MediaStreamDescription(MediaStreamType.Video, streamAttributes); + + _videoDesc = msd; + } + + private void PrepareAudio() + { + } + + protected override void OpenMediaAsync() + { + // Init + Dictionary sourceAttributes = + new Dictionary(); + List availableStreams = + new List(); + + PrepareVideo(); + + availableStreams.Add(_videoDesc); + + // a zero timespan is an infinite video + sourceAttributes[MediaSourceAttributesKeys.Duration] = + TimeSpan.FromSeconds(0).Ticks.ToString(CultureInfo.InvariantCulture); + + sourceAttributes[MediaSourceAttributesKeys.CanSeek] = false.ToString(); + + // tell Silverlight that we've prepared and opened our video + ReportOpenMediaCompleted(sourceAttributes, availableStreams); + } + + protected override void GetSampleAsync(MediaStreamType mediaStreamType) + { + if (mediaStreamType == MediaStreamType.Audio) + { + } + else if (mediaStreamType == MediaStreamType.Video) + { + lock (lockObj) + { + _outstandingGetVideoSampleCount++; + SendSamples(); + } + } + } + + protected override void CloseMedia() + { + } + + protected override void GetDiagnosticAsync(MediaStreamSourceDiagnosticKind diagnosticKind) + { + throw new NotImplementedException(); + } + + protected override void SwitchMediaStreamAsync(MediaStreamDescription mediaStreamDescription) + { + throw new NotImplementedException(); + } + + protected override void SeekAsync(long seekToTime) + { + ReportSeekCompleted(seekToTime); + } + } +} diff --git a/Agents/VideoRenderer.cs b/Agents/VideoRenderer.cs new file mode 100755 index 0000000..23ff741 --- /dev/null +++ b/Agents/VideoRenderer.cs @@ -0,0 +1,103 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Microsoft.Phone.Media; +using PhoneVoIPApp.BackEnd; +using System; +using System.Diagnostics; +using System.Windows; + +namespace PhoneVoIPApp.Agents +{ + /// + /// A class that renders video from the background process. + /// Note, the MediaElement that actually displays the video is in the UI process - + /// this class receives video from the remote party and writes it to a media streamer. + /// The media streamer handles connecting the rendered video stream to the media element that + /// displays it in the UI process. + /// + internal class VideoRenderer : IVideoRenderer + { + /// + /// Constructor + /// + internal VideoRenderer() + { + } + + #region IVideoRenderer methods + + /// + /// Start rendering video. + /// Note, this method may be called multiple times in a row. + /// + public void Start() + { + if (this.isRendering) + return; // Nothing more to be done + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + try + { + Debug.WriteLine("[VideoRenderer::Start] Video rendering setup"); + StartMediaStreamer(); + this.isRendering = true; + } + catch (Exception err) + { + Debug.WriteLine("[VideoRenderer::Start] " + err.Message); + } + }); + } + + private void StartMediaStreamer() + { + if (mediaStreamer == null) + { + mediaStreamer = MediaStreamerFactory.CreateMediaStreamer(123); + } + + // Using default resolution of 640x480 + mediaStreamSource = new VideoMediaStreamSource(null, 640, 480); + mediaStreamer.SetSource(mediaStreamSource); + } + + /// + /// Stop rendering video. + /// Note, this method may be called multiple times in a row. + /// + public void Stop() + { + Deployment.Current.Dispatcher.BeginInvoke(() => + { + if (!this.isRendering) + return; // Nothing more to be done + + Debug.WriteLine("[VoIP Background Process] Video rendering stopped."); + mediaStreamSource.Shutdown(); + mediaStreamSource.Dispose(); + mediaStreamSource = null; + mediaStreamer.Dispose(); + mediaStreamer = null; + + this.isRendering = false; + }); + } + + #endregion + + #region Private members + + // Indicates if rendering is already in progress or not + private bool isRendering; + private VideoMediaStreamSource mediaStreamSource; + private MediaStreamer mediaStreamer; + + #endregion + } +} diff --git a/BackEnd/ApiLock.cpp b/BackEnd/ApiLock.cpp new file mode 100755 index 0000000..5f1b902 --- /dev/null +++ b/BackEnd/ApiLock.cpp @@ -0,0 +1,17 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#include "ApiLock.h" + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + // A mutex used to protect objects accessible from the API surface exposed by this DLL + std::recursive_mutex g_apiLock; + } +} diff --git a/BackEnd/ApiLock.h b/BackEnd/ApiLock.h new file mode 100755 index 0000000..1c47cd7 --- /dev/null +++ b/BackEnd/ApiLock.h @@ -0,0 +1,18 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once +#include + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + // A mutex used to protect objects accessible from the API surface exposed by this DLL + extern std::recursive_mutex g_apiLock; + } +} diff --git a/BackEnd/BackEnd.vcxproj b/BackEnd/BackEnd.vcxproj new file mode 100755 index 0000000..1c6fa15 --- /dev/null +++ b/BackEnd/BackEnd.vcxproj @@ -0,0 +1,218 @@ + + + + + Debug + Win32 + + + Debug + ARM + + + Release + Win32 + + + Release + ARM + + + + {c8d75245-ffcf-4932-a228-c9cc8bb60b03} + PhoneVoIPApp.BackEnd + en-US + $(VCTargetsPath11) + 11.0 + Windows Phone + 8.0 + true + BackEnd + Windows Phone Silverlight + 8.1 + + + + DynamicLibrary + true + v120 + win32 + + + DynamicLibrary + true + v120 + arm32 + + + DynamicLibrary + false + true + v120 + win32 + + + DynamicLibrary + false + true + v120 + arm32 + + + + + + + + false + + + $(RootNamespace) + PostBuildEvent + $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ + $(PlatformTarget)\$(Configuration)\ + + + $(RootNamespace) + PostBuildEvent + $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ + $(PlatformTarget)\$(Configuration)\ + + + $(RootNamespace) + PostBuildEvent + $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ + $(PlatformTarget)\$(Configuration)\ + + + $(RootNamespace) + PostBuildEvent + $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ + $(PlatformTarget)\$(Configuration)\ + + + + _WINRT_DLL;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) + + + + + _WINRT_DLL;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) + + + + + _WINRT_DLL;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) + + + + + _WINRT_DLL;WIN32_LEAN_AND_MEAN;NDEBUG;%(PreprocessorDefinitions) + + + + + NotUsing + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + true + true + true + true + + + Console + false + windowsphonecore.lib;runtimeobject.lib;PhoneAudioSes.lib;%(AdditionalDependencies) + + ole32.lib;%(IgnoreSpecificDefaultLibraries) + true + true + true + true + + + + pushd "$(OutDir)" + WinMdIdl.exe "$(OutDir)$(RootNamespace).winmd" + MIdl.exe /env $(MidlEnv) /winrt /ns_prefix /metadata_dir "$(TargetPlatformSdkMetadataLocation)" /out "$(SolutionDir)$(ProjectName)ProxyStub" "$(OutDir)$(RootNamespace).idl" + MIdl.exe /env $(MidlEnv) /winrt /ns_prefix /metadata_dir "$(TargetPlatformSdkMetadataLocation)" /out "$(SolutionDir)$(ProjectName)ProxyStub" "$(OutDir)$(RootNamespace).OutOfProcess.idl" + popd + + + $(OutDir)$(RootNamespace).idl;$(OutDir)$(RootNamespace).OutOfProcess.idl;$(SolutionDir)$(ProjectName)ProxyStub\dlldata.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace)_i.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace)_p.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).h;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).OutOfProcess.h;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).OutOfProcess_i.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).OutOfProcess_p.c;%(Outputs) + + + + pushd "$(OutDir)" + WinMdIdl.exe "$(OutDir)$(RootNamespace).winmd" + MIdl.exe /env $(MidlEnv) /winrt /ns_prefix /metadata_dir "$(TargetPlatformSdkMetadataLocation)" /out "$(SolutionDir)$(ProjectName)ProxyStub" "$(OutDir)$(RootNamespace).idl" + MIdl.exe /env $(MidlEnv) /winrt /ns_prefix /metadata_dir "$(TargetPlatformSdkMetadataLocation)" /out "$(SolutionDir)$(ProjectName)ProxyStub" "$(OutDir)$(RootNamespace).OutOfProcess.idl" + popd + + + $(OutDir)$(RootNamespace).idl;$(OutDir)$(RootNamespace).OutOfProcess.idl;$(SolutionDir)$(ProjectName)ProxyStub\dlldata.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace)_i.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace)_p.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).h;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).OutOfProcess.h;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).OutOfProcess_i.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).OutOfProcess_p.c;%(Outputs) + + + + pushd "$(OutDir)" + WinMdIdl.exe "$(OutDir)$(RootNamespace).winmd" + MIdl.exe /env $(MidlEnv) /winrt /ns_prefix /metadata_dir "$(TargetPlatformSdkMetadataLocation)" /out "$(SolutionDir)$(ProjectName)ProxyStub" "$(OutDir)$(RootNamespace).idl" + MIdl.exe /env $(MidlEnv) /winrt /ns_prefix /metadata_dir "$(TargetPlatformSdkMetadataLocation)" /out "$(SolutionDir)$(ProjectName)ProxyStub" "$(OutDir)$(RootNamespace).OutOfProcess.idl" + popd + + + $(OutDir)$(RootNamespace).idl;$(OutDir)$(RootNamespace).OutOfProcess.idl;$(SolutionDir)$(ProjectName)ProxyStub\dlldata.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace)_i.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace)_p.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).h;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).OutOfProcess.h;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).OutOfProcess_i.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).OutOfProcess_p.c;%(Outputs) + + + + pushd "$(OutDir)" + WinMdIdl.exe "$(OutDir)$(RootNamespace).winmd" + MIdl.exe /env $(MidlEnv) /winrt /ns_prefix /metadata_dir "$(TargetPlatformSdkMetadataLocation)" /out "$(SolutionDir)$(ProjectName)ProxyStub" "$(OutDir)$(RootNamespace).idl" + MIdl.exe /env $(MidlEnv) /winrt /ns_prefix /metadata_dir "$(TargetPlatformSdkMetadataLocation)" /out "$(SolutionDir)$(ProjectName)ProxyStub" "$(OutDir)$(RootNamespace).OutOfProcess.idl" + popd + + + $(OutDir)$(RootNamespace).idl;$(OutDir)$(RootNamespace).OutOfProcess.idl;$(SolutionDir)$(ProjectName)ProxyStub\dlldata.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace)_i.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace)_p.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).h;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).OutOfProcess.h;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).OutOfProcess_i.c;$(SolutionDir)$(ProjectName)ProxyStub\$(RootNamespace).OutOfProcess_p.c;%(Outputs) + + + + + true + + + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + {21f10158-c078-4bd7-a82a-9c4aeb8e2f8e} + + + + + + + \ No newline at end of file diff --git a/BackEnd/BackEndAudio.cpp b/BackEnd/BackEndAudio.cpp new file mode 100755 index 0000000..4fdd077 --- /dev/null +++ b/BackEnd/BackEndAudio.cpp @@ -0,0 +1,459 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#include "BackEndAudio.h" +#include "ApiLock.h" +#include "BackEndNativeBuffer.h" + +using namespace PhoneVoIPApp::BackEnd; +using namespace Windows::System::Threading; + +// Begin of audio helpers +//size_t inline GetWaveFormatSize(const WAVEFORMATEX& format) +//{ +// return (sizeof WAVEFORMATEX) + (format.wFormatTag == WAVE_FORMAT_PCM ? 0 : format.cbSize); +//} +// +//void FillPcmFormat(WAVEFORMATEX& format, WORD wChannels, int nSampleRate, WORD wBits) +//{ +// format.wFormatTag = WAVE_FORMAT_PCM; +// format.nChannels = wChannels; +// format.nSamplesPerSec = nSampleRate; +// format.wBitsPerSample = wBits; +// format.nBlockAlign = format.nChannels * (format.wBitsPerSample / 8); +// format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; +// format.cbSize = 0; +//} +// +//size_t BytesFromDuration(int nDurationInMs, const WAVEFORMATEX& format) +//{ +// return size_t(nDurationInMs * FLOAT(format.nAvgBytesPerSec) / 1000); +//} +// +//size_t SamplesFromDuration(int nDurationInMs, const WAVEFORMATEX& format) +//{ +// return size_t(nDurationInMs * FLOAT(format.nSamplesPerSec) / 1000); +//} +//// End of audio helpers +// +//BOOL WaveFormatCompare(const WAVEFORMATEX& format1, const WAVEFORMATEX& format2) +//{ +// size_t cbSizeFormat1 = GetWaveFormatSize(format1); +// size_t cbSizeFormat2 = GetWaveFormatSize(format2); +// +// return (cbSizeFormat1 == cbSizeFormat2) && (memcmp(&format1, &format2, cbSizeFormat1) == 0); +//} +// +//BackEndAudio::BackEndAudio() : +// m_pDefaultRenderDevice(NULL), +// m_pRenderClient(NULL), +// m_pClock(NULL), +// m_pVolume(NULL), +// m_nMaxFrameCount(0), +// m_pwfx(NULL), +// m_pDefaultCaptureDevice(NULL), +// m_pCaptureClient(NULL), +// m_sourceFrameSizeInBytes(0), +// hCaptureEvent(NULL), +// hShutdownEvent(NULL), +// m_CaptureThread(nullptr), +// transportController(nullptr), +// started(false) +//{ +// this->onTransportMessageReceivedHandler = ref new MessageReceivedEventHandler(this, &BackEndAudio::OnTransportMessageReceived); +//} +// +//void BackEndAudio::OnTransportMessageReceived(Windows::Storage::Streams::IBuffer^ stream, UINT64, UINT64) +//{ +// BYTE* pBuffer = NativeBuffer::GetBytesFromIBuffer(stream); +// int size = stream->Length; +// +// while (m_pRenderClient && size && pBuffer) +// { +// HRESULT hr = E_FAIL; +// unsigned int padding = 0; +// +// hr = m_pDefaultRenderDevice->GetCurrentPadding(&padding); +// if (SUCCEEDED(hr)) +// { +// BYTE* pRenderBuffer = NULL; +// unsigned int incomingFrameCount = size / m_sourceFrameSizeInBytes; +// unsigned int framesToWrite = m_nMaxFrameCount - padding; +// +// if (framesToWrite > incomingFrameCount) +// { +// framesToWrite = incomingFrameCount; +// } +// +// if (framesToWrite) +// { +// hr = m_pRenderClient->GetBuffer(framesToWrite, &pRenderBuffer); +// +// if (SUCCEEDED(hr)) +// { +// unsigned int bytesToBeWritten = framesToWrite * m_sourceFrameSizeInBytes; +// +// memcpy(pRenderBuffer, pBuffer, bytesToBeWritten); +// +// // Release the buffer +// m_pRenderClient->ReleaseBuffer(framesToWrite, 0); +// +// pBuffer += bytesToBeWritten; +// size -= bytesToBeWritten; +// } +// } +// } +// } +//} +// +//void BackEndAudio::Start() +//{ +// // Make sure only one API call is in progress at a time +// std::lock_guard lock(g_apiLock); +// +// if (started) +// return; +// +// HRESULT hr = InitCapture(); +// if (SUCCEEDED(hr)) +// { +// hr = InitRender(); +// } +// +// if (SUCCEEDED(hr)) +// { +// hr = StartAudioThreads(); +// } +// +// if (FAILED(hr)) +// { +// Stop(); +// throw ref new Platform::COMException(hr, L"Unable to start audio"); +// } +// +// started = true; +//} +// +//void BackEndAudio::Stop() +//{ +// // Make sure only one API call is in progress at a time +// std::lock_guard lock(g_apiLock); +// +// if (!started) +// return; +// +// // Shutdown the threads +// if (hShutdownEvent) +// { +// SetEvent(hShutdownEvent); +// } +// +// if (m_CaptureThread != nullptr) +// { +// m_CaptureThread->Cancel(); +// m_CaptureThread->Close(); +// m_CaptureThread = nullptr; +// } +// +// if (m_pDefaultRenderDevice) +// { +// m_pDefaultRenderDevice->Stop(); +// } +// +// if (m_pDefaultCaptureDevice) +// { +// m_pDefaultCaptureDevice->Stop(); +// } +// +// if (m_pVolume) +// { +// m_pVolume->Release(); +// m_pVolume = NULL; +// } +// if (m_pClock) +// { +// m_pClock->Release(); +// m_pClock = NULL; +// } +// +// if (m_pRenderClient) +// { +// m_pRenderClient->Release(); +// m_pRenderClient = NULL; +// } +// +// +// +// if (m_pDefaultRenderDevice) +// { +// m_pDefaultRenderDevice->Release(); +// m_pDefaultRenderDevice = NULL; +// } +// +// if (m_pDefaultCaptureDevice) +// { +// m_pDefaultCaptureDevice->Release(); +// m_pDefaultCaptureDevice = NULL; +// } +// +// if (m_pCaptureClient) +// { +// m_pCaptureClient->Release(); +// m_pCaptureClient = NULL; +// } +// +// if (m_pwfx) +// { +// CoTaskMemFree((LPVOID)m_pwfx); +// m_pwfx = NULL; +// } +// +// if (hCaptureEvent) +// { +// CloseHandle(hCaptureEvent); +// hCaptureEvent = NULL; +// } +// +// if (hShutdownEvent) +// { +// CloseHandle(hShutdownEvent); +// hShutdownEvent = NULL; +// } +// +// started = false; +//} +// +//void BackEndAudio::CaptureThread(Windows::Foundation::IAsyncAction^ operation) +//{ +// HRESULT hr = m_pDefaultCaptureDevice->Start(); +// BYTE *pLocalBuffer = new BYTE[MAX_RAW_BUFFER_SIZE]; +// HANDLE eventHandles[] = { +// hCaptureEvent, // WAIT_OBJECT0 +// hShutdownEvent // WAIT_OBJECT0 + 1 +// }; +// +// if (SUCCEEDED(hr) && pLocalBuffer) +// { +// unsigned int uAccumulatedBytes = 0; +// while (SUCCEEDED(hr)) +// { +// DWORD waitResult = WaitForMultipleObjectsEx(SIZEOF_ARRAY(eventHandles), eventHandles, FALSE, INFINITE, FALSE); +// if (WAIT_OBJECT_0 == waitResult) +// { +// BYTE* pbData = nullptr; +// UINT32 nFrames = 0; +// DWORD dwFlags = 0; +// if (SUCCEEDED(hr)) +// { +// hr = m_pCaptureClient->GetBuffer(&pbData, &nFrames, &dwFlags, nullptr, nullptr); +// unsigned int incomingBufferSize = nFrames * m_sourceFrameSizeInBytes; +// +// if (MAX_RAW_BUFFER_SIZE - uAccumulatedBytes < incomingBufferSize) +// { +// // Send what has been accumulated +// if (transportController) +// { +// transportController->WriteAudio(pLocalBuffer, uAccumulatedBytes); +// } +// +// // Reset our counter +// uAccumulatedBytes = 0; +// } +// +// memcpy(pLocalBuffer + uAccumulatedBytes, pbData, incomingBufferSize); +// uAccumulatedBytes += incomingBufferSize; +// } +// +// if (SUCCEEDED(hr)) +// { +// hr = m_pCaptureClient->ReleaseBuffer(nFrames); +// } +// } +// else if (WAIT_OBJECT_0 + 1 == waitResult) +// { +// // We're being asked to shutdown +// break; +// } +// else +// { +// // Unknown return value +// DbgRaiseAssertionFailure(); +// } +// } +// } +// delete[] pLocalBuffer; +//} +// +//HRESULT BackEndAudio::StartAudioThreads() +//{ +// hShutdownEvent = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); +// if (!hShutdownEvent) +// { +// return HRESULT_FROM_WIN32(GetLastError()); +// } +// +// m_CaptureThread = ThreadPool::RunAsync(ref new WorkItemHandler(this, &BackEndAudio::CaptureThread), WorkItemPriority::High, WorkItemOptions::TimeSliced); +// return S_OK; +//} +// +//BackEndAudio::~BackEndAudio() +//{ +// if (transportController) +// { +// transportController->AudioMessageReceived -= onTransportMessageReceivedHandlerToken; +// transportController = nullptr; +// } +//} +// +//HRESULT BackEndAudio::InitRender() +//{ +// HRESULT hr = E_FAIL; +// +// LPCWSTR pwstrRendererId = GetDefaultAudioRenderId(AudioDeviceRole::Communications); +// +// if (NULL == pwstrRendererId) +// { +// hr = E_FAIL; +// } +// +// hr = ActivateAudioInterface(pwstrRendererId, __uuidof(IAudioClient2), (void**)&m_pDefaultRenderDevice); +// +// // Set the category through SetClientProperties +// AudioClientProperties properties = {}; +// if (SUCCEEDED(hr)) +// { +// properties.cbSize = sizeof AudioClientProperties; +// properties.eCategory = AudioCategory_Communications; +// hr = m_pDefaultRenderDevice->SetClientProperties(&properties); +// } +// +// WAVEFORMATEX* pwfx = nullptr; +// if (SUCCEEDED(hr)) +// { +// hr = m_pDefaultRenderDevice->GetMixFormat(&pwfx); +// } +// +// WAVEFORMATEX format = {}; +// if (SUCCEEDED(hr)) +// { +// FillPcmFormat(format, pwfx->nChannels, pwfx->nSamplesPerSec, pwfx->wBitsPerSample); +// hr = m_pDefaultRenderDevice->Initialize(AUDCLNT_SHAREMODE_SHARED, +// 0, +// 2000 * 10000, // Seconds in hns +// 0, // periodicity +// &format, +// NULL); +// } +// +// if (SUCCEEDED(hr)) +// { +// hr = m_pDefaultRenderDevice->GetService(__uuidof(IAudioRenderClient), (void**)&m_pRenderClient); +// } +// +// // Check for other supported GetService interfaces as well +// if (SUCCEEDED(hr)) +// { +// hr = m_pDefaultRenderDevice->GetService(__uuidof(IAudioClock), (void**)&m_pClock); +// } +// +// if (SUCCEEDED(hr)) +// { +// hr = m_pDefaultRenderDevice->GetService(__uuidof(ISimpleAudioVolume), (void**)&m_pVolume); +// } +// +// if (SUCCEEDED(hr)) +// { +// hr = m_pDefaultRenderDevice->GetBufferSize(&m_nMaxFrameCount); +// } +// +// if (SUCCEEDED(hr)) +// { +// hr = m_pDefaultRenderDevice->Start(); +// } +// +// if (pwstrRendererId) +// { +// CoTaskMemFree((LPVOID)pwstrRendererId); +// } +// +// return hr; +//} +// +//HRESULT BackEndAudio::InitCapture() +//{ +// HRESULT hr = E_FAIL; +// +// LPCWSTR pwstrCaptureId = GetDefaultAudioCaptureId(AudioDeviceRole::Communications); +// +// if (NULL == pwstrCaptureId) +// { +// hr = E_FAIL; +// } +// +// hr = ActivateAudioInterface(pwstrCaptureId, __uuidof(IAudioClient2), (void**)&m_pDefaultCaptureDevice); +// +// if (SUCCEEDED(hr)) +// { +// hr = m_pDefaultCaptureDevice->GetMixFormat(&m_pwfx); +// } +// +// // Set the category through SetClientProperties +// AudioClientProperties properties = {}; +// if (SUCCEEDED(hr)) +// { +// properties.cbSize = sizeof AudioClientProperties; +// properties.eCategory = AudioCategory_Communications; +// hr = m_pDefaultCaptureDevice->SetClientProperties(&properties); +// } +// +// if (SUCCEEDED(hr)) +// { +// WAVEFORMATEX format = {}; +// if (SUCCEEDED(hr)) +// { +// +// FillPcmFormat(format, m_pwfx->nChannels, m_pwfx->nSamplesPerSec, m_pwfx->wBitsPerSample); +// +// m_sourceFrameSizeInBytes = (format.wBitsPerSample / 8) * format.nChannels; +// hr = m_pDefaultCaptureDevice->Initialize(AUDCLNT_SHAREMODE_SHARED, 0x88140000, 1000 * 10000, 0, &format, NULL); +// } +// } +// +// if (SUCCEEDED(hr)) +// { +// hCaptureEvent = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS); +// if (NULL == hCaptureEvent) +// { +// hr = HRESULT_FROM_WIN32(GetLastError()); +// } +// } +// +// if (SUCCEEDED(hr)) +// { +// hr = m_pDefaultCaptureDevice->SetEventHandle(hCaptureEvent); +// } +// +// if (SUCCEEDED(hr)) +// { +// hr = m_pDefaultCaptureDevice->GetService(__uuidof(IAudioCaptureClient), (void**)&m_pCaptureClient); +// } +// +// if (pwstrCaptureId) +// { +// CoTaskMemFree((LPVOID)pwstrCaptureId); +// } +// return hr; +//} +// +//void BackEndAudio::SetTransport(BackEndTransport^ transport) +//{ +// transportController = transport; +// if (transportController != nullptr) +// { +// onTransportMessageReceivedHandlerToken = transportController->AudioMessageReceived += onTransportMessageReceivedHandler; +// } +//} diff --git a/BackEnd/BackEndAudio.h b/BackEnd/BackEndAudio.h new file mode 100755 index 0000000..bf59fd8 --- /dev/null +++ b/BackEnd/BackEndAudio.h @@ -0,0 +1,78 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once +#include "windows.h" + +#define MAX_RAW_BUFFER_SIZE 1024*128 + +#include +#include +#include + +#include "BackEndTransport.h" + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + //public ref class BackEndAudio sealed + //{ + //public: + // // Constructor + // BackEndAudio(); + + // // Destructor + // virtual ~BackEndAudio(); + + // void SetTransport(BackEndTransport^ transport); + // + // void Start(); + // void Stop(); + + //private: + // HRESULT InitRender(); + // HRESULT InitCapture(); + // HRESULT StartAudioThreads(); + // void CaptureThread(Windows::Foundation::IAsyncAction^ operation); + // void OnTransportMessageReceived(Windows::Storage::Streams::IBuffer^ stream, UINT64, UINT64); + // + // BackEndTransport^ transportController; + + // PhoneVoIPApp::BackEnd::MessageReceivedEventHandler^ onTransportMessageReceivedHandler; + // Windows::Foundation::EventRegistrationToken onTransportMessageReceivedHandlerToken; + + // int m_sourceFrameSizeInBytes; + + // WAVEFORMATEX* m_pwfx; + + // // Devices + // IAudioClient2* m_pDefaultRenderDevice; + // IAudioClient2* m_pDefaultCaptureDevice; + + // // Actual render and capture objects + // IAudioRenderClient* m_pRenderClient; + // IAudioCaptureClient* m_pCaptureClient; + + // // Misc interfaces + // IAudioClock* m_pClock; + // ISimpleAudioVolume* m_pVolume; + + // // Audio buffer size + // UINT32 m_nMaxFrameCount; + // HANDLE hCaptureEvent; + + // // Event for stopping audio capture/render + // HANDLE hShutdownEvent; + + // Windows::Foundation::IAsyncAction^ m_CaptureThread; + + // // Has audio started? + // bool started; + //}; + } +} diff --git a/BackEnd/BackEndCapture.cpp b/BackEnd/BackEndCapture.cpp new file mode 100755 index 0000000..57f10ab --- /dev/null +++ b/BackEnd/BackEndCapture.cpp @@ -0,0 +1,266 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#include "BackEndCapture.h" +#include "ApiLock.h" +#include + +using namespace PhoneVoIPApp::BackEnd; +using namespace Windows::System::Threading; +using namespace Microsoft::WRL; +using namespace Windows::Foundation; +using namespace Platform; +using namespace Windows::Phone::Media::Capture; +using namespace Windows::Storage::Streams; +using namespace Concurrency; + +BackEndCapture::BackEndCapture() : + started(false), + videoOnlyDevice(nullptr), + pVideoSink(NULL), + pVideoDevice(NULL), + cameraLocation(CameraSensorLocation::Front) +{ + hStopCompleted = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); + if (!hStopCompleted) + { + throw ref new Platform::Exception(HRESULT_FROM_WIN32(GetLastError()), L"Could not create shutdown event"); + } + + hStartCompleted = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); + if (!hStartCompleted) + { + throw ref new Platform::Exception(HRESULT_FROM_WIN32(GetLastError()), L"Could not create start event"); + } +} + +void BackEndCapture::Start(CameraLocation newCameraLocation) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (started) + return; + if(newCameraLocation == CameraLocation::Front) + { + cameraLocation = Windows::Phone::Media::Capture::CameraSensorLocation::Front; + } + else if(newCameraLocation == CameraLocation::Back) + { + cameraLocation = Windows::Phone::Media::Capture::CameraSensorLocation::Back; + } + + InitCapture(); + + started = true; +} + +void BackEndCapture::Stop() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + ::OutputDebugString(L"+[BackendCapture::Stop] => Trying to stop capture\n"); + if (!started) + { + ::OutputDebugString(L"-[BackendCapture::Stop] => finished stopping capture\n"); + return; + } + if (videoOnlyDevice) + { + OutputDebugString(L"Destroying VideoCaptureDevice\n"); + + try + { + videoOnlyDevice->StopRecordingAsync()->Completed = ref new AsyncActionCompletedHandler([this] (IAsyncAction ^action, Windows::Foundation::AsyncStatus status){ + if(status == Windows::Foundation::AsyncStatus::Completed) + { + OutputDebugString(L"[BackendCapture::StopRecordingAsync] Video successfully stopped.\n"); + } + else + { + OutputDebugString(L"[BackEndCapture::StopRecordingAsync] Error occurred while stopping recording.\n"); + } + this->videoCaptureAction = nullptr; + this->videoOnlyDevice = nullptr; + started = false; + SetEvent(hStopCompleted); + }); + } + catch(...) + { + // A Platform::ObjectDisposedException can be raised if the app has had its access + // to video revoked (most commonly when the app is going out of the foreground) + OutputDebugString(L"Exception caught while destroying video capture\n"); + this->videoCaptureAction = nullptr; + this->videoOnlyDevice = nullptr; + started = false; + SetEvent(hStopCompleted); + } + + if (pVideoDevice) + { + pVideoDevice->Release(); + pVideoDevice = NULL; + } + + if (pVideoSink) + { + pVideoSink->Release(); + pVideoSink = NULL; + } + } + ::OutputDebugString(L"-[BackendCapture::Stop] => finished stopping capture\n"); +} + +BackEndCapture::~BackEndCapture() +{ + if(m_ToggleThread) + { + m_ToggleThread->Cancel(); + m_ToggleThread->Close(); + m_ToggleThread = nullptr; + } +} + +void BackEndCapture::InitCapture() +{ + ::OutputDebugString(L"+[BackendCapture::InitCapture] => Initializing Capture\n"); + Windows::Foundation::Size dimensions; + dimensions.Width = 640; + dimensions.Height = 480; + Collections::IVectorView ^availableSizes = AudioVideoCaptureDevice::GetAvailableCaptureResolutions(this->cameraLocation); + Collections::IIterator ^availableSizesIterator = availableSizes->First(); + + IAsyncOperation ^openOperation = nullptr; + while(!openOperation && availableSizesIterator->HasCurrent) + { + // TODO: You should select the appropriate resolution that's supported here, + // TODO: and then setup your renderer with that selected res. + // TODO: This shows how to iterate through all supported resolutions. We're assuming 640x480 support + if(availableSizesIterator->Current.Height == 480 && availableSizesIterator->Current.Width == 640) + { + openOperation = AudioVideoCaptureDevice::OpenForVideoOnlyAsync(this->cameraLocation, dimensions); + } + availableSizesIterator->MoveNext(); + } + + openOperation->Completed = ref new AsyncOperationCompletedHandler([this] (IAsyncOperation ^operation, Windows::Foundation::AsyncStatus status) + { + if(status == Windows::Foundation::AsyncStatus::Completed) + { + std::lock_guard lock(g_apiLock); + + ::OutputDebugString(L"+[BackendCapture::InitCapture] => OpenAsyncOperation started\n"); + + auto videoDevice = operation->GetResults(); + + this->videoOnlyDevice = videoDevice; + IAudioVideoCaptureDeviceNative *pNativeDevice = NULL; + HRESULT hr = reinterpret_cast(videoDevice)->QueryInterface(__uuidof(IAudioVideoCaptureDeviceNative), (void**) &pNativeDevice); + + if (NULL == pNativeDevice || FAILED(hr)) + { + throw ref new FailureException("Unable to QI IAudioVideoCaptureDeviceNative"); + } + + // Save off the native device + this->pVideoDevice = pNativeDevice; + + // Create the sink + MakeAndInitialize(&(this->pVideoSink), transportController); + this->pVideoSink->SetTransport(this->transportController); + pNativeDevice->SetVideoSampleSink(this->pVideoSink); + + // Use the same encoding format as in VideoMediaStreamSource.cs + videoDevice->VideoEncodingFormat = CameraCaptureVideoFormat::H264; + + SetEvent(hStartCompleted); + + // Start recording to our sink + this->videoCaptureAction = videoDevice->StartRecordingToSinkAsync(); + videoCaptureAction->Completed = ref new AsyncActionCompletedHandler([this] (IAsyncAction ^asyncInfo, Windows::Foundation::AsyncStatus status) + { + if(status == Windows::Foundation::AsyncStatus::Completed) + { + ::OutputDebugString(L"[BackendCapture::InitCapture] => StartRecordingToSinkAsync completed\n"); + } + else if(status == Windows::Foundation::AsyncStatus::Error || status == Windows::Foundation::AsyncStatus::Canceled) + { + ::OutputDebugString(L"[BackendCapture::InitCapture] => StartRecordingToSinkAsync did not complete\n"); + } + }); + + ::OutputDebugString(L"-[BackendCapture::InitCapture] => OpenAsyncOperation Completed\n"); + } + else if(status == Windows::Foundation::AsyncStatus::Canceled) + { + ::OutputDebugString(L"[BackendCapture::InitCapture] => OpenAsyncOperation Canceled\n"); + } + else if(status == Windows::Foundation::AsyncStatus::Error) + { + ::OutputDebugString(L"[BackendCapture::InitCapture] => OpenAsyncOperation encountered an error.\n"); + } + }); + ::OutputDebugString(L"-[BackendCapture::InitCapture] => Initializing Capture\n"); +} + +void BackEndCapture::ToggleCamera() +{ + std::lock_guard lock(g_apiLock); + + if(m_ToggleThread) + { + m_ToggleThread->Cancel(); + m_ToggleThread->Close(); + m_ToggleThread = nullptr; + } + + m_ToggleThread = ThreadPool::RunAsync(ref new WorkItemHandler(this, &BackEndCapture::ToggleCameraThread), WorkItemPriority::High, WorkItemOptions::TimeSliced); +} + + +void BackEndCapture::ToggleCameraThread(Windows::Foundation::IAsyncAction^ operation) +{ + ::OutputDebugString(L"+[BackendCapture::ToggleCamera] => Toggling camera \n"); + CameraLocation newCameraLocation; + ResetEvent(hStopCompleted); + Stop(); + DWORD waitResult = WaitForSingleObjectEx(hStopCompleted, INFINITE, FALSE); + if(waitResult == WAIT_OBJECT_0) + { + ResetEvent(hStartCompleted); + if(cameraLocation == Windows::Phone::Media::Capture::CameraSensorLocation::Back) + { + newCameraLocation = CameraLocation::Front; + } + else + { + newCameraLocation = CameraLocation::Back; + } + Start(newCameraLocation); + } + else + { + throw ref new Platform::Exception(HRESULT_FROM_WIN32(waitResult), L"Error waiting for capture to stop when toggling cameras"); + } + + waitResult = WaitForSingleObjectEx(hStartCompleted, INFINITE, FALSE); + if(waitResult == WAIT_OBJECT_0) + { + CameraLocationChanged(newCameraLocation); + } + else + { + throw ref new Platform::Exception(HRESULT_FROM_WIN32(waitResult), L"Error waiting for capture to start when toggling cameras"); + } + ::OutputDebugString(L"-[BackendCapture::ToggleCamera] => Toggling camera \n"); +} + +void BackEndCapture::SetTransport(BackEndTransport^ transport) +{ + transportController = transport; +} diff --git a/BackEnd/BackEndCapture.h b/BackEnd/BackEndCapture.h new file mode 100755 index 0000000..d97aea3 --- /dev/null +++ b/BackEnd/BackEndCapture.h @@ -0,0 +1,110 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once +#include "windows.h" +#include "implements.h" +#include "ICallControllerStatusListener.h" +#include "BackEndTransport.h" +#include +#include + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + public delegate void CameraLocationChangedEventHandler(PhoneVoIPApp::BackEnd::CameraLocation); + + class CaptureSampleSink : + public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags, + ICameraCaptureSampleSink> + { + DWORD m_dwSampleCount; + BackEndTransport ^m_transport; + + public: + + STDMETHODIMP RuntimeClassInitialize(BackEndTransport ^transportController) + { + m_dwSampleCount = 0; + m_transport = transportController; + return S_OK; + } + + DWORD GetSampleCount() + { + return m_dwSampleCount; + } + + IFACEMETHODIMP_(void) + OnSampleAvailable( + ULONGLONG hnsPresentationTime, + ULONGLONG hnsSampleDuration, + DWORD cbSample, + BYTE* pSample) + { + m_dwSampleCount++; + if (m_transport) + { + m_transport->WriteVideo(pSample, cbSample, hnsPresentationTime, hnsSampleDuration); + } + } + + void SetTransport(BackEndTransport ^transport) + { + m_transport = transport; + } + }; + + public ref class BackEndCapture sealed + { + public: + // Constructor + BackEndCapture(); + + void SetTransport(BackEndTransport^ transport); + + void Start(CameraLocation cameraLocation); + void Stop(); + + void ToggleCamera(); + + event CameraLocationChangedEventHandler^ CameraLocationChanged; + + private: + // Destructor + ~BackEndCapture(); + + void InitCapture(); + + void ToggleCameraThread(Windows::Foundation::IAsyncAction^ operation); + + // Has capture started? + bool started; + + // Events to signal whether capture has stopped/started + HANDLE hStopCompleted; + HANDLE hStartCompleted; + + Windows::Foundation::IAsyncAction^ m_ToggleThread; + + // Transport + BackEndTransport^ transportController; + + // Native sink and video device + CaptureSampleSink *pVideoSink; + IAudioVideoCaptureDeviceNative *pVideoDevice; + + Windows::Phone::Media::Capture::CameraSensorLocation cameraLocation; + + Windows::Phone::Media::Capture::AudioVideoCaptureDevice ^videoOnlyDevice; + Windows::Foundation::IAsyncAction ^videoCaptureAction; + + }; + } +} diff --git a/BackEnd/BackEndNativeBuffer.h b/BackEnd/BackEndNativeBuffer.h new file mode 100755 index 0000000..50fd638 --- /dev/null +++ b/BackEnd/BackEndNativeBuffer.h @@ -0,0 +1,108 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once +#include "windows.h" +#include +#include +#include +#include +#include + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + + /// + /// The purpose of this class is to transform byte buffers into an IBuffer + /// + class NativeBuffer : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::WinRtClassicComMix >, + ABI::Windows::Storage::Streams::IBuffer, + Windows::Storage::Streams::IBufferByteAccess, + Microsoft::WRL::FtmBase> + { + + public: + virtual ~NativeBuffer() + { + if (m_pBuffer && m_bIsOwner) + { + delete[] m_pBuffer; + m_pBuffer = NULL; + } + } + + STDMETHODIMP RuntimeClassInitialize(UINT totalSize) + { + m_uLength = totalSize; + m_uFullSize = totalSize; + m_pBuffer = new BYTE[totalSize]; + m_bIsOwner = TRUE; + return S_OK; + } + + STDMETHODIMP RuntimeClassInitialize(BYTE* pBuffer, UINT totalSize, BOOL fTakeOwnershipOfPassedInBuffer) + { + m_uLength = totalSize; + m_uFullSize = totalSize; + m_pBuffer = pBuffer; + m_bIsOwner = fTakeOwnershipOfPassedInBuffer; + return S_OK; + } + + STDMETHODIMP Buffer( BYTE **value) + { + *value = m_pBuffer; + return S_OK; + } + + STDMETHODIMP get_Capacity(UINT32 *value) + { + *value = m_uFullSize; + return S_OK; + } + + STDMETHODIMP get_Length(UINT32 *value) + { + *value = m_uLength; + return S_OK; + } + + STDMETHODIMP put_Length(UINT32 value) + { + if(value > m_uFullSize) + { + return E_INVALIDARG; + } + m_uLength = value; + return S_OK; + } + + static Windows::Storage::Streams::IBuffer^ GetIBufferFromNativeBuffer(Microsoft::WRL::ComPtr spNativeBuffer) + { + auto iinspectable = reinterpret_cast(spNativeBuffer.Get()); + return reinterpret_cast(iinspectable); + } + static BYTE* GetBytesFromIBuffer(Windows::Storage::Streams::IBuffer^ buffer) + { + auto iinspectable = (IInspectable*)reinterpret_cast(buffer); + Microsoft::WRL::ComPtr spBuffAccess; + HRESULT hr = iinspectable->QueryInterface(__uuidof(Windows::Storage::Streams::IBufferByteAccess), (void **)&spBuffAccess); + UCHAR * pReadBuffer; + spBuffAccess->Buffer(&pReadBuffer); + return pReadBuffer; + } + private: + UINT32 m_uLength; + UINT32 m_uFullSize; + BYTE* m_pBuffer; + BOOL m_bIsOwner; + }; + } +} diff --git a/BackEnd/BackEndTransport.cpp b/BackEnd/BackEndTransport.cpp new file mode 100755 index 0000000..c17052c --- /dev/null +++ b/BackEnd/BackEndTransport.cpp @@ -0,0 +1,74 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#include "BackEndTransport.h" +#include "BackEndNativeBuffer.h" +#include + +using namespace PhoneVoIPApp::BackEnd; +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Storage::Streams; +using namespace Windows::System::Threading; +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Details; + +BackEndTransport::BackEndTransport() +{ +} + + +void BackEndTransport::WriteAudio(BYTE* bytes, int byteCount) +{ + Write(bytes, byteCount, TransportMessageType::Audio, 0, 0); +} + +void BackEndTransport::WriteVideo(BYTE* bytes, int byteCount, UINT64 hnsPresenationTime, UINT64 hnsSampleDuration) + +{ + Write(bytes, byteCount, TransportMessageType::Video, hnsPresenationTime, hnsSampleDuration); +} + +void BackEndTransport::Write(BYTE* bytes, int byteCount, TransportMessageType::Value dataType, UINT64 hnsPresenationTime, UINT64 hnsSampleDuration) +{ + + static const int MaxPacketSize = 10*1024*1024; + + int bytesToSend = byteCount; + + while (bytesToSend) + { + int chunkSize = bytesToSend > MaxPacketSize ? MaxPacketSize : bytesToSend; + ComPtr spNativeBuffer = NULL; + if (dataType == TransportMessageType::Audio) + { + MakeAndInitialize(&spNativeBuffer, bytes, chunkSize, FALSE); + AudioMessageReceived(NativeBuffer::GetIBufferFromNativeBuffer(spNativeBuffer), hnsPresenationTime, hnsSampleDuration); + } + else + { + // Temporarily duplicating this for sample so that MSS can own this + // buffer, and will be released when the stream itself is released + BYTE* pMem = new BYTE[chunkSize]; + + memcpy((void*) pMem, (void*) bytes, chunkSize); + + MakeAndInitialize(&spNativeBuffer, pMem, chunkSize, TRUE); + VideoMessageReceived(NativeBuffer::GetIBufferFromNativeBuffer(spNativeBuffer), hnsPresenationTime, hnsSampleDuration); + } + + // Increment byte position + bytes += chunkSize; + bytesToSend -= chunkSize; + } + return; + +} + +BackEndTransport::~BackEndTransport() +{ +} diff --git a/BackEnd/BackEndTransport.h b/BackEnd/BackEndTransport.h new file mode 100755 index 0000000..f8fb7bd --- /dev/null +++ b/BackEnd/BackEndTransport.h @@ -0,0 +1,49 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once +#include "windows.h" + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + namespace TransportMessageType + { + enum Value + { + Audio = 0, + Video = 1 + }; + } + + public delegate void MessageReceivedEventHandler(Windows::Storage::Streams::IBuffer ^pBuffer, UINT64 hnsPresentationTime, UINT64 hnsSampleDuration); + + /// + /// This is an abstraction of a network transport class + /// which does not actually send data over the network. + /// + public ref class BackEndTransport sealed + { + public: + // Constructor + BackEndTransport(); + + // Destructor + virtual ~BackEndTransport(); + + void WriteAudio(BYTE* bytes, int byteCount); + void WriteVideo(BYTE* bytes, int byteCount, UINT64 hnsPresentationTime, UINT64 hnsSampleDuration); + + event MessageReceivedEventHandler^ AudioMessageReceived; + event MessageReceivedEventHandler^ VideoMessageReceived; + + private: + void Write(BYTE* bytes, int byteCount, TransportMessageType::Value dataType, UINT64 hnsPresentationTime, UINT64 hnsSampleDurationTime); + }; + } +} diff --git a/BackEnd/BackgroundTask.cpp b/BackEnd/BackgroundTask.cpp new file mode 100755 index 0000000..1bf64e9 --- /dev/null +++ b/BackEnd/BackgroundTask.cpp @@ -0,0 +1,44 @@ +#include "BackgroundTask.h" +#include "Globals.h" +#include "CallController.h" + +using namespace PhoneVoIPApp::BackEnd; +using namespace Windows::ApplicationModel::Background; +using namespace Windows::Phone::Networking::Voip; +using namespace Windows::Foundation; +using namespace Platform; +using namespace Windows::Phone::Media::Devices; + +BackgroundTask::BackgroundTask() +{ + +} + +void BackgroundTask::Run(IBackgroundTaskInstance^ taskInstance){ + + return; + + VoipCallCoordinator^ callCoordinator = Windows::Phone::Networking::Voip::VoipCallCoordinator::GetDefault(); + + Windows::Phone::Networking::Voip::VoipPhoneCall^ incomingCall; + + String^ installFolder = String::Concat(Windows::ApplicationModel::Package::Current->InstalledLocation->Path, "\\"); + TimeSpan timeout; + timeout.Duration = 90 * 10 * 1000 * 1000; // in 100ns units + callCoordinator->RequestNewIncomingCall( + ref new String(L"/Views/ShellView.xaml"), + ref new String(L"test contact"), + ref new String(L"test number"), + ref new Uri(installFolder, "Assets\\DefaultContactImage.png"), + ref new String(L"PhoneVoIPApp"), + ref new Uri(installFolder, "Assets\\ApplicationIcon.png"), + ref new String(L"call details"), // Was this call forwarded/delegated to this user on behalf of someone else? At this time, we won't use this field + ref new Uri(installFolder, "Assets\\Ringtone.wma"), + VoipCallMedia::Audio, + timeout, // Maximum amount of time to ring for + &incomingCall); +} + +void BackgroundTask::IncomingCallDissmissed(){ + +} diff --git a/BackEnd/BackgroundTask.h b/BackEnd/BackgroundTask.h new file mode 100755 index 0000000..2188804 --- /dev/null +++ b/BackEnd/BackgroundTask.h @@ -0,0 +1,21 @@ +#pragma once + +using namespace Windows::ApplicationModel::Background; + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + [Windows::Foundation::Metadata::WebHostHidden] + public ref class BackgroundTask sealed : public IBackgroundTask + { + public: + BackgroundTask(); + virtual void Run(IBackgroundTaskInstance^ taskInstance); + + private: + void IncomingCallDissmissed(); + }; + } +} + diff --git a/BackEnd/CallController.cpp b/BackEnd/CallController.cpp new file mode 100755 index 0000000..b93689f --- /dev/null +++ b/BackEnd/CallController.cpp @@ -0,0 +1,1133 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#include "CallController.h" +#include "BackEndAudio.h" +#include "BackEndCapture.h" +#include "Server.h" + +using namespace PhoneVoIPApp::BackEnd; +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Phone::Media::Devices; +using namespace Windows::Phone::Networking::Voip; + +LibTgVoipStateListener::LibTgVoipStateListener(){ + +} + +void LibTgVoipStateListener::OnCallStateChanged(libtgvoip::VoIPControllerWrapper^ sender, libtgvoip::CallState newState) +{ + if (this->statusListener != nullptr){ + this->statusListener->OnCallStateChanged((CallState)newState); + } +} + +void LibTgVoipStateListener::OnSignalBarsChanged(libtgvoip::VoIPControllerWrapper^ sender, int newSignal) +{ + if (this->statusListener != nullptr){ + this->statusListener->OnSignalBarsChanged(newSignal); + } +} + +void LibTgVoipStateListener::SetStatusCallback(ICallControllerStatusListener^ statusListener) +{ + this->statusListener = statusListener; +} + +void CallController::StartMTProtoUpdater() +{ + if (Globals::Instance->MTProtoUpdater != nullptr) + { + Globals::Instance->MTProtoUpdater->Start(0, 0, 0); + } +} + +void CallController::StopMTProtoUpdater() +{ + if (Globals::Instance->MTProtoUpdater != nullptr) + { + Globals::Instance->MTProtoUpdater->Stop(); + } +} + +void CallController::HandleUpdatePhoneCall() +{ + + ::OutputDebugString(L"[CallController::HandleUpdatePhoneCall]\n"); +} + +void CallController::CreateVoIPControllerWrapper() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + wrapper = ref new libtgvoip::VoIPControllerWrapper(); + + //wrapper->SetStateCallback(stateListener); + wrapper->CallStateChanged += ref new libtgvoip::CallStateChangedEventHandler( + stateListener, + &LibTgVoipStateListener::OnCallStateChanged + ); + wrapper->SignalBarsChanged += ref new libtgvoip::SignalBarsChangedEventHandler( + stateListener, + &LibTgVoipStateListener::OnSignalBarsChanged + ); +} + +void CallController::DeleteVoIPControllerWrapper() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr){ + delete wrapper; + wrapper = nullptr; + } +} + +void CallController::SetConfig(Config config) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr) + { + wrapper->SetConfig(config.InitTimeout, config.RecvTimeout, (libtgvoip::DataSavingMode)config.DataSavingMode, config.EnableAEC, config.EnableNS, config.EnableAGC, config.LogFilePath, config.StatsDumpFilePath); + } +} + +void CallController::SetEncryptionKey(const Platform::Array^ key, bool isOutgoing) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr) + { + wrapper->SetEncryptionKey(key, isOutgoing); + } +} + +void CallController::SetPublicEndpoints(const Platform::Array^ endpoints, bool allowP2P, int connectionMaxLayer) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr) + { + auto points = ref new Platform::Array(endpoints->Length); + + for (int i = 0; i < endpoints->Length; i++) + { + auto point = ref new libtgvoip::Endpoint(); + point->id = endpoints[i].id; + point->port = endpoints[i].port; + point->ipv4 = endpoints[i].ipv4; + point->ipv6 = endpoints[i].ipv6; + + auto length = endpoints[i].peerTag->Length(); + auto it = endpoints[i].peerTag->Begin(); + auto peerTag = ref new Platform::Array(length); + for (size_t i = 0; i < length; i++) + { + peerTag[i] = (byte)it[i]; + } + point->peerTag = peerTag; + + points[i] = point; + } + + wrapper->SetPublicEndpoints(points, allowP2P, connectionMaxLayer); + } +} + +void CallController::SetProxy(ProxyStruct proxy) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr) + { + wrapper->SetProxy((libtgvoip::ProxyProtocol)proxy.protocol, proxy.address, proxy.port, proxy.username, proxy.password); + } +} + +void CallController::Start() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr) + { + wrapper->Start(); + } +} + +void Handler(Windows::System::Threading::ThreadPoolTimer^ timer){ + ::OutputDebugString(L"PeriodicTimer.Handler"); +} + +void CallController::Connect() +{ + ::OutputDebugString(L"[CallController::Connect]\n"); + + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr) + { + wrapper->Connect(); + } +} + +void CallController::SetMicMute(bool mute) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr){ + wrapper->SetMicMute(mute); + } +} +void CallController::SwitchSpeaker(bool external) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + libtgvoip::VoIPControllerWrapper::SwitchSpeaker(external); +} + +void CallController::SetStatusCallback(ICallControllerStatusListener^ statusListener) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + this->statusListener = statusListener; + this->stateListener->SetStatusCallback(statusListener); +} + +void CallController::UpdateServerConfig(Platform::String^ json) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + libtgvoip::VoIPControllerWrapper::UpdateServerConfig(json); +} + +int64 CallController::GetPreferredRelayID() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr){ + return wrapper->GetPreferredRelayID(); + } + + return 0; +} + +Error CallController::GetLastError() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr){ + return (Error)wrapper->GetLastError(); + } + + return Error::Unknown; +} + +Platform::String^ CallController::GetVersion() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + return libtgvoip::VoIPControllerWrapper::GetVersion(); +} + +int CallController::GetSignalBarsCount() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr){ + return wrapper->GetSignalBarsCount(); + } + + return 0; +} + +Platform::String^ CallController::GetDebugLog() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr){ + return wrapper->GetDebugLog(); + } + + return nullptr; +} + +Platform::String^ CallController::GetDebugString() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (wrapper != nullptr){ + return wrapper->GetDebugString(); + } + + return nullptr; +} + +bool CallController::InitiateOutgoingCall(Platform::String^ recepientName, int64 recepientId, int64 id, int64 accessHash, + Config config, const Platform::Array^ key, bool outgoing, const Platform::Array^ emojis, + const Platform::Array^ endpoints, bool allowP2P, int connectionMaxLayer, + ProxyStruct proxy) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + VoipPhoneCall^ outgoingCall = nullptr; + + // In this sample, we allow only one call at a time. + if (this->activeCall != nullptr) + { + ::OutputDebugString(L"[CallController::InitiateOutgoingCall] => Only one active call allowed in this sample at a time\n"); + + this->activeCall->NotifyCallEnded(); + + // If we receive a request to initiate an outgoing call when another call is in progress, + // we just ignore it. + //return false; + } + + ::OutputDebugString(L"[CallController::InitiateOutgoingCall] => Starting outgoing call\n"); + + // Start a new outgoing call. + this->callCoordinator->RequestNewOutgoingCall(this->callInProgressPageUri, recepientName, "Telegram", VoipCallMedia::Audio + //| VoipCallMedia::Video + , &outgoingCall); + + // Tell the phone service that this call is active. + // Normally, we do this only when the remote party has accepted the call. + outgoingCall->NotifyCallActive(); + + // Store it as the active call - assume we support both audio and video + this->SetActiveCall(outgoingCall, recepientId, id, accessHash, key, outgoing, emojis, VoipCallMedia::Audio + //| VoipCallMedia::Video + ); + + this->DeleteVoIPControllerWrapper(); + this->CreateVoIPControllerWrapper(); + this->SetConfig(config); + this->SetEncryptionKey(key, outgoing); + this->SetPublicEndpoints(endpoints, allowP2P, connectionMaxLayer); + this->SetProxy(proxy); + this->Start(); + //UpdateNetworkType(null); + this->Connect(); + + + return true; +} + +bool CallController::InitiateOutgoingCall(Platform::String^ recepientName, int64 recepientId, int64 callId, int64 callAccessHash) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + VoipPhoneCall^ outgoingCall = nullptr; + + // In this sample, we allow only one call at a time. + if (this->activeCall != nullptr) + { + ::OutputDebugString(L"[CallController::InitiateOutgoingCall] => Only one active call allowed in this sample at a time\n"); + + // If we receive a request to initiate an outgoing call when another call is in progress, + // we just ignore it. + return false; + } + + ::OutputDebugString(L"[CallController::InitiateOutgoingCall] => Starting outgoing call\n"); + + // Start a new outgoing call. + this->callCoordinator->RequestNewOutgoingCall(this->callInProgressPageUri, recepientName, "Telegram", VoipCallMedia::Audio + //| VoipCallMedia::Video + , &outgoingCall); + + // Tell the phone service that this call is active. + // Normally, we do this only when the remote party has accepted the call. + outgoingCall->NotifyCallActive(); + + // Store it as the active call - assume we support both audio and video + this->SetActiveCall(outgoingCall, recepientId, callId, callAccessHash, nullptr, true, nullptr, VoipCallMedia::Audio + //| VoipCallMedia::Video + ); + + return true; +} + +bool CallController::OnIncomingCallReceived(Platform::String^ contactName, int64 contactId, Platform::String^ contactImage, int64 callId, int64 callAccessHash, IncomingCallDialogDismissedCallback^ incomingCallDialogDismissedCallback) +{ + VoipPhoneCall^ incomingCall = nullptr; + + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + // TODO: If required, contact your cloud service here for more information about the incoming call. + + try + { + TimeSpan timeout; + timeout.Duration = 25 * 10 * 1000 * 1000; // in 100ns units + + ::OutputDebugString(L"[CallController::OnIncomingCallReceived] => Will time out in 90 seconds\n"); + + // Store the caller number of this incoming call + this->incomingId = contactId; + this->incomingCallId = callId; + this->incomingCallAccessHash = callAccessHash; + + // Store the callback that needs to be called when the incoming call dialog has been dismissed, + // either because the call was accepted or rejected by the user. + this->onIncomingCallDialogDismissed = incomingCallDialogDismissedCallback; + //Windows::ApplicationModel::Package::Current->InstalledLocation->Path + Uri^ contactImageUri = nullptr; + if (contactImage != nullptr) + { + String^ localFolder = String::Concat(Windows::Storage::ApplicationData::Current->LocalFolder->Path, "\\"); + contactImageUri = ref new Uri(localFolder, contactImage); + } + + // Ask the Phone Service to start a new incoming call + this->callCoordinator->RequestNewIncomingCall( + this->callInProgressPageUri, + contactName, + "Telegram Call", + contactImageUri, + this->voipServiceName, + this->brandingImageUri, + "", // Was this call forwarded/delegated to this user on behalf of someone else? At this time, we won't use this field + this->ringtoneUri, + VoipCallMedia::Audio, // | VoipCallMedia::Video, + timeout, // Maximum amount of time to ring for + &incomingCall); + } + catch(...) + { + // Requesting an incoming call can fail if there is already an incoming call in progress. + // This is rare, but possible. Treat this case like a missed call. + ::OutputDebugString(L"[CallController::OnIncomingCallReceived] => An exception has occurred\n"); + return false; + } + + // Register for events about this incoming call. + incomingCall->AnswerRequested += this->acceptCallRequestedHandler; + incomingCall->RejectRequested += this->rejectCallRequestedHandler; + + return true; +} + +bool CallController::HoldCall() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (this->activeCall == nullptr) + { + // Nothing to do - there is no call to put on hold + return false; + } + + ::OutputDebugString(L"[CallController::HoldCall] => Trying to put call on hold\n"); + + // Change the call status before notifying that the call is held because + // access to the camera will be removed once NotifyCallHeld is called + this->SetCallStatus(PhoneVoIPApp::BackEnd::CallStatus::Held); + + // Hold the active call + this->activeCall->NotifyCallHeld(); + + // TODO: Contact your cloud service and let it know that the active call has been put on hold. + + return true; +} + +bool CallController::ResumeCall() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (this->activeCall == nullptr) + { + // Nothing to do - there is no call to resume + return false; + } + + ::OutputDebugString(L"[CallController::ResumeCall] => Trying to resume a call\n"); + + // Resume the active call + this->activeCall->NotifyCallActive(); + + // TODO: Contact your cloud service and let it know that the active call has been resumed. + + // Change the call status after notifying that the call is active + // if it is done before access to the camera will not have been granted yet + this->SetCallStatus(PhoneVoIPApp::BackEnd::CallStatus::InProgress); + + return true; +} + +bool CallController::EndCall() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (this->activeCall == nullptr) + { + // Nothing to do - there is no call to end + return false; + } + + ::OutputDebugString(L"[CallController::EndCall] => Trying to end a call\n"); + + // Unregister from audio endpoint changes + this->audioRoutingManager->AudioEndpointChanged -= this->audioEndpointChangedHandlercookie; + + // TODO: Contact your cloud service and let it know that the active call has ended. + + // End the active call. + this->activeCall->NotifyCallEnded(); + this->activeCall = nullptr; + + // Reset libtgvoip call params + this->key = nullptr; + this->callId = -1; + this->callAccessHash = 0; + this->otherPartyId = 0; + this->emojis = nullptr; + + // Reset camera choice to front facing for next call + this->cameraLocation = PhoneVoIPApp::BackEnd::CameraLocation::Front; + + // Change the call status + this->SetCallStatus(PhoneVoIPApp::BackEnd::CallStatus::None); + + return true; +} + +bool CallController::ToggleCamera() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (this->activeCall == nullptr) + { + // Nothing to do - there is no call to end + return false; + } + ::OutputDebugString(L"[CallController::ToggleCamera] => Trying to toggle the camera\n"); + + Globals::Instance->CaptureController->ToggleCamera(); + + return true; +} + +PhoneVoIPApp::BackEnd::CallStatus CallController::CallStatus::get() +{ + // No need to lock - this get is idempotent + return this->callStatus; +} + +PhoneVoIPApp::BackEnd::CameraLocation CallController::CameraLocation::get() +{ + // No need to lock - this get is idempotent + return this->cameraLocation; +} + +PhoneVoIPApp::BackEnd::MediaOperations CallController::MediaOperations::get() +{ + // No need to lock - this get is idempotent + return this->mediaOperations; +} + +bool CallController::IsShowingVideo::get() +{ + // No need to lock - this get is idempotent + return this->isShowingVideo; +} + +void CallController::IsShowingVideo::set(bool value) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + // Has anything changed? + if (this->isShowingVideo == value) + return; // No + + // Update the value + this->isShowingVideo = value; + + // Start/stop video capture/render based on this change + this->UpdateMediaOperations(); +} + +bool CallController::IsRenderingVideo::get() +{ + // No need to lock - this get is idempotent + return this->isRenderingVideo; +} + +void CallController::IsRenderingVideo::set(bool value) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + // Has anything changed? + if (this->isRenderingVideo == value) + return; // No + + // Update the value + this->isRenderingVideo = value; + + // Start/stop video capture/render based on this change + this->UpdateMediaOperations(); +} + +CallAudioRoute CallController::AvailableAudioRoutes::get() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (this->activeCall == nullptr) + { + // There is no call in progress + return CallAudioRoute::None; + } + + return (CallAudioRoute)(this->audioRoutingManager->AvailableAudioEndpoints); +} + +CallAudioRoute CallController::AudioRoute::get() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (this->activeCall == nullptr) + { + // There is no call in progress + return CallAudioRoute::None; + } + + auto audioEndpoint = this->audioRoutingManager->GetAudioEndpoint(); + switch(audioEndpoint) + { + case AudioRoutingEndpoint::Earpiece: + case AudioRoutingEndpoint::WiredHeadset: + case AudioRoutingEndpoint::WiredHeadsetSpeakerOnly: + return CallAudioRoute::Earpiece; + + case AudioRoutingEndpoint::Default: + case AudioRoutingEndpoint::Speakerphone: + return CallAudioRoute::Speakerphone; + + case AudioRoutingEndpoint::Bluetooth: + case AudioRoutingEndpoint::BluetoothWithNoiseAndEchoCancellation: + return CallAudioRoute::Bluetooth; + + default: + throw ref new FailureException("Unexpected audio routing endpoint"); + } + +} + +void CallController::AudioRoute::set(CallAudioRoute newRoute) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (this->callStatus != PhoneVoIPApp::BackEnd::CallStatus::InProgress) + { + // There is no call in progress - do nothing + return; + } + + switch(newRoute) + { + case CallAudioRoute::Earpiece: + this->audioRoutingManager->SetAudioEndpoint(AudioRoutingEndpoint::Earpiece); + break; + + case CallAudioRoute::Speakerphone: + this->audioRoutingManager->SetAudioEndpoint(AudioRoutingEndpoint::Speakerphone); + break; + + case CallAudioRoute::Bluetooth: + this->audioRoutingManager->SetAudioEndpoint(AudioRoutingEndpoint::Bluetooth); + break; + + case CallAudioRoute::None: + default: + throw ref new FailureException("Cannot set audio route to CallAudioRoute::None"); + } +} + +Platform::String^ CallController::OtherPartyName::get() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + return this->otherPartyName; +} + +int64 CallController::OtherPartyId::get() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + return this->otherPartyId; +} + +Windows::Foundation::DateTime CallController::CallStartTime::get() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (this->activeCall != nullptr) + { + // There is a call in progress + return this->activeCall->StartTime; + } + else + { + // There is no call in progress + Windows::Foundation::DateTime minValue; + minValue.UniversalTime = 0; + return minValue; + } +} + +int64 CallController::CallId::get() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + return this->callId; +} + +int64 CallController::CallAccessHash::get() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + return this->callAccessHash; +} + +int64 CallController::AcceptedCallId::get() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + return this->acceptedCallId; +} + +void CallController::AcceptedCallId::set(int64 value) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + this->acceptedCallId = value; +} + +Platform::Array^ CallController::Key::get() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + return this->key; +} + +bool CallController::Outgoing::get() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + return this->outgoing; +} + +Platform::Array^ CallController::Emojis::get() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + return this->emojis; +} + +CallController::CallController() : + wrapper(nullptr), + callInProgressPageUri(L"/Views/ShellView.xaml"), + voipServiceName(nullptr), + defaultContactImageUri(nullptr), + brandingImageUri(nullptr), + ringtoneUri(nullptr), + statusListener(nullptr), + callStatus(PhoneVoIPApp::BackEnd::CallStatus::None), + otherPartyName(nullptr), + otherPartyId(-1), + incomingId(-1), + acceptedCallId(-1), + key(nullptr), + emojis(nullptr), + mediaOperations(PhoneVoIPApp::BackEnd::MediaOperations::None), + onIncomingCallDialogDismissed(nullptr), + activeCall(nullptr), + cameraLocation(PhoneVoIPApp::BackEnd::CameraLocation::Front) +{ + this->stateListener = ref new LibTgVoipStateListener(); + this->callCoordinator = VoipCallCoordinator::GetDefault(); + this->audioRoutingManager = AudioRoutingManager::GetDefault(); + + // URIs required for interactions with the VoipCallCoordinator + String^ installFolder = String::Concat(Windows::ApplicationModel::Package::Current->InstalledLocation->Path, "\\"); + //this->defaultContactImageUri = ref new Uri(installFolder, "Assets\\DefaultContactImage.png"); + this->voipServiceName = ref new String(L"Telegram"); + this->brandingImageUri = ref new Uri(installFolder, "SquareTile150x150.png"); + //this->ringtoneUri = ref new Uri(installFolder, "Assets\\Ringtone.wma"); + + // Event handler delegates - creating them once and storing them as member variables + // avoids having to create new delegate objects for each phone call. + this->acceptCallRequestedHandler = ref new TypedEventHandler(this, &CallController::OnAcceptCallRequested); + this->rejectCallRequestedHandler = ref new TypedEventHandler(this, &CallController::OnRejectCallRequested); + this->holdCallRequestedHandler = ref new TypedEventHandler(this, &CallController::OnHoldCallRequested); + this->resumeCallRequestedHandler = ref new TypedEventHandler(this, &CallController::OnResumeCallRequested); + this->endCallRequestedHandler = ref new TypedEventHandler(this, &CallController::OnEndCallRequested); + this->audioEndpointChangedHandler = ref new TypedEventHandler(this, &CallController::OnAudioEndpointChanged); + this->cameraLocationChangedHandler = ref new CameraLocationChangedEventHandler(this, &CallController::OnCameraLocationChanged); +} + +CallController::~CallController() +{ +} + +void CallController::SetCallStatus(PhoneVoIPApp::BackEnd::CallStatus newStatus) +{ + // No need to lock - private method + + if (newStatus == this->callStatus) + return; // Nothing more to do + + // Change the call status + this->callStatus = newStatus; + + // Update audio/video capture/render status, if required. + this->UpdateMediaOperations(); + + // If required, let the UI know. + if (this->statusListener != nullptr) + { + this->statusListener->OnCallStatusChanged(this->callStatus); + } +} + +void CallController::SetActiveCall(VoipPhoneCall^ call, int64 contactId, int64 callId, int64 callAccessHash, const Platform::Array^ key, bool outgoing, const Platform::Array^ emojis, VoipCallMedia callMedia) +{ + // No need to lock - private method + + // The specified call is now active. + // For an incoming call, this means that the local party has accepted the call. + // For an outoing call, this means that the remote party has accepted the call. + this->activeCall = call; + + // Listen to state changes of the active call. + call->HoldRequested += this->holdCallRequestedHandler; + call->ResumeRequested += this->resumeCallRequestedHandler; + call->EndRequested += this->endCallRequestedHandler; + + // Register for audio endpoint changes + this->audioEndpointChangedHandlercookie = this->audioRoutingManager->AudioEndpointChanged += this->audioEndpointChangedHandler; + + // Store information about the other party in the call + this->otherPartyName = this->activeCall->ContactName; + this->otherPartyId = contactId; + this->callId = callId; + this->callAccessHash = callAccessHash; + + if (key != nullptr) + { + this->key = ref new Platform::Array(key->Data, key->Length); + } + else + { + this->key = nullptr; + } + if (emojis != nullptr) + { + this->emojis = ref new Platform::Array(emojis->Data, emojis->Length); + } + else + { + this->emojis = nullptr; + } + + this->outgoing = outgoing; + + // Change the call status + this->SetCallStatus(PhoneVoIPApp::BackEnd::CallStatus::InProgress); + + // Figure out if video/audio capture/render are all allowed + PhoneVoIPApp::BackEnd::MediaOperations newOperations = PhoneVoIPApp::BackEnd::MediaOperations::None; + if ((callMedia & VoipCallMedia::Audio) != VoipCallMedia::None) + { + // Enable both audio capture and render by default + newOperations = PhoneVoIPApp::BackEnd::MediaOperations::AudioCapture | PhoneVoIPApp::BackEnd::MediaOperations::AudioRender; + } + if ((callMedia & VoipCallMedia::Video) != VoipCallMedia::None) + { + // Enable both video capture and render by default + newOperations = newOperations | PhoneVoIPApp::BackEnd::MediaOperations::VideoCapture | PhoneVoIPApp::BackEnd::MediaOperations::VideoRender; + + } + this->SetMediaOperations(newOperations); +} + +void CallController::OnAcceptCallRequested(VoipPhoneCall^ sender, CallAnswerEventArgs^ args) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + ::OutputDebugString(L"[CallController::OnAcceptCallRequested] => Incoming call accepted\n"); + + // The local user has accepted an incoming call. + VoipPhoneCall^ incomingCall = (VoipPhoneCall^)sender; + + // If there is was a call already in progress, end it + // As of now, we support only one call at a time in this application + this->EndCall(); + + // Reset camera choice to front facing for next call + this->cameraLocation = PhoneVoIPApp::BackEnd::CameraLocation::Front; + + // The incoming call is the new active call. + incomingCall->NotifyCallActive(); + + this->acceptedCallId = this->incomingCallId; + + // Let the incoming call agent know that incoming call processing is now complete + if (this->onIncomingCallDialogDismissed != nullptr) + this->onIncomingCallDialogDismissed(this->incomingCallId, this->incomingCallAccessHash, false); + + // Store it as the active call. + this->SetActiveCall(incomingCall, this->incomingId, this->incomingCallId, this->incomingCallAccessHash, nullptr, false, nullptr, args->AcceptedMedia); +} + +void CallController::OnRejectCallRequested(VoipPhoneCall^ sender, CallRejectEventArgs^ args) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + ::OutputDebugString(L"[CallController::OnRejectCallRequested] => Incoming call rejected\n"); + + // The local user has rejected an incoming call. + VoipPhoneCall^ incomingCall = (VoipPhoneCall^)sender; + + // End it. + incomingCall->NotifyCallEnded(); + + // TODO: Contact your cloud service and let it know that the incoming call was rejected. + + // Finally, let the incoming call agent know that incoming call processing is now complete + this->onIncomingCallDialogDismissed(this->incomingCallId, this->incomingCallAccessHash, true); +} + +void CallController::OnHoldCallRequested(VoipPhoneCall^ sender, CallStateChangeEventArgs^ args) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + // A request to put the active call on hold has been received. + VoipPhoneCall^ callToPutOnHold = (VoipPhoneCall^)sender; + + // Sanity test. + if (callToPutOnHold != this->activeCall) + { + throw ref new Platform::FailureException(L"Something is wrong. The call to put on hold is not the active call"); + } + + // Put the active call on hold. + this->HoldCall(); +} + +void CallController::OnResumeCallRequested(VoipPhoneCall^ sender, CallStateChangeEventArgs^ args) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + // A request to resumed the active call has been received. + VoipPhoneCall^ callToResume = (VoipPhoneCall^)sender; + + // Sanity test. + if (callToResume != this->activeCall) + { + throw ref new Platform::FailureException(L"Something is wrong. The call to resume is not the active call"); + } + + // Resume the active call + this->ResumeCall(); +} + +void CallController::OnEndCallRequested(VoipPhoneCall^ sender, CallStateChangeEventArgs^ args) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + // A request to end the active call has been received. + VoipPhoneCall^ callToEnd = (VoipPhoneCall^)sender; + + // Sanity test. + if (callToEnd != this->activeCall) + { + throw ref new Platform::FailureException(L"Something is wrong. The call to end is not the active call"); + } + + // End the active call + this->EndCall(); +} + +void CallController::OnAudioEndpointChanged(AudioRoutingManager^ sender, Object^ args) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + // If required, let the UI know. + if ((this->activeCall != nullptr) && (this->statusListener != nullptr)) + { + this->statusListener->OnCallAudioRouteChanged(this->AudioRoute); + } +} + +void CallController::OnCameraLocationChanged(PhoneVoIPApp::BackEnd::CameraLocation newCameraLocation) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if(this->cameraLocation == newCameraLocation || this->activeCall == nullptr) + { + // nothing to do + return; + } + + this->cameraLocation = newCameraLocation; + + // If required, let the UI know. + if ((this->statusListener != nullptr)) + { + this->statusListener->OnCameraLocationChanged(this->cameraLocation); + } + +} + +void CallController::SetMediaOperations(PhoneVoIPApp::BackEnd::MediaOperations value) +{ + // No need to lock - private method + + // Has anything changed? + if (this->mediaOperations == value) + return; // No + + // Update the value + this->mediaOperations = value; + + // Start/stop video/audio capture based on this change + this->UpdateMediaOperations(); +} + +void CallController::UpdateMediaOperations() +{ + // No need to lock - private method + + bool captureAudio = false, captureVideo = false, renderAudio = false, renderVideo = false; + + if (this->callStatus == PhoneVoIPApp::BackEnd::CallStatus::InProgress) + { + // A call is in progress + + // Start audio capture/render, if enabled + captureAudio = ((this->mediaOperations & PhoneVoIPApp::BackEnd::MediaOperations::AudioCapture) != PhoneVoIPApp::BackEnd::MediaOperations::None); + renderAudio = ((this->mediaOperations & PhoneVoIPApp::BackEnd::MediaOperations::AudioRender) != PhoneVoIPApp::BackEnd::MediaOperations::None); + + // Start video capture/render if enabled *and* the UI is showing video. + if (this->isShowingVideo) + { + if(isRenderingVideo) + { + renderVideo = ((this->mediaOperations & PhoneVoIPApp::BackEnd::MediaOperations::VideoRender) != PhoneVoIPApp::BackEnd::MediaOperations::None); + } + + // Does this phone have a camera? + auto availableCameras = Windows::Phone::Media::Capture::AudioVideoCaptureDevice::AvailableSensorLocations; + bool isCameraPresent = ((availableCameras != nullptr) && (availableCameras->Size > 0)); + + // Start capture only if there is a camera present + if (isCameraPresent) + { + captureVideo = ((this->mediaOperations & PhoneVoIPApp::BackEnd::MediaOperations::VideoCapture) != PhoneVoIPApp::BackEnd::MediaOperations::None); + } + } + } + // else: call is not in progress - all capture/rendering should stop + + // What are the new media operations? + PhoneVoIPApp::BackEnd::MediaOperations newOperations = PhoneVoIPApp::BackEnd::MediaOperations::None; + + // Start/stop audio capture and render + if (captureAudio || renderAudio) + { + ::OutputDebugString(L"[CallController::UpdateMediaOperations] => Starting audio\n"); + newOperations = newOperations | (PhoneVoIPApp::BackEnd::MediaOperations::AudioCapture | PhoneVoIPApp::BackEnd::MediaOperations::AudioRender); + //Globals::Instance->AudioController->Start(); + } + else + { + ::OutputDebugString(L"[CallController::UpdateMediaOperations] => Stopping audio\n"); + //Globals::Instance->AudioController->Stop(); + } + + // Start/stop video render + if (Globals::Instance->VideoRenderer != nullptr) + { + if (renderVideo) + { + ::OutputDebugString(L"[CallController::UpdateMediaOperations] => Starting video render\n"); + newOperations = newOperations | PhoneVoIPApp::BackEnd::MediaOperations::VideoRender; + Globals::Instance->VideoRenderer->Start(); + } + else + { + ::OutputDebugString(L"[CallController::UpdateMediaOperations] => Stopping video render\n"); + Globals::Instance->VideoRenderer->Stop(); + } + + if (captureVideo) + { + ::OutputDebugString(L"[CallController::UpdateMediaOperations] => Starting video capture\n"); + newOperations = newOperations | PhoneVoIPApp::BackEnd::MediaOperations::VideoCapture; + Globals::Instance->CaptureController->Start(cameraLocation); + Globals::Instance->CaptureController->CameraLocationChanged += cameraLocationChangedHandler; + } + else + { + ::OutputDebugString(L"[CallController::UpdateMediaOperations] => Stopping video capture\n"); + Globals::Instance->CaptureController->Stop(); + } + } + + // Let the listener know that the allowed media operation state has changed + if (this->statusListener != nullptr) + { + this->statusListener->OnMediaOperationsChanged(newOperations); + } +} diff --git a/BackEnd/CallController.h b/BackEnd/CallController.h new file mode 100755 index 0000000..ba21091 --- /dev/null +++ b/BackEnd/CallController.h @@ -0,0 +1,337 @@ +/* +Copyright (c) 2012 Microsoft Corporation. All rights reserved. +Use of this sample source code is subject to the terms of the Microsoft license +agreement under which you licensed this sample source code and is provided AS-IS. +If you did not accept the terms of the license agreement, you are not authorized +to use this sample source code. For the terms of the license, please see the +license agreement between you and Microsoft. + +To see all Code Samples for Windows Phone, visit http://go.microsoft.com/fwlink/?LinkID=219604 + +*/ +#pragma once +#include "BackEndCapture.h" +#include +#include "ICallControllerStatusListener.h" +#include "IConfig.h" +#include "ApiLock.h" + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + // Forward declaration + ref class Globals; + + // A method that is called back when the incoming call dialog has been dismissed. + // This callback is used to complete the incoming call agent. + public delegate void IncomingCallDialogDismissedCallback(int64 callId, int64 callAccessHash, bool rejected); + + ref class LibTgVoipStateListener sealed { + private: + ICallControllerStatusListener^ statusListener; + + public: + LibTgVoipStateListener(); + void SetStatusCallback(ICallControllerStatusListener^ statusListener); + virtual void OnCallStateChanged(libtgvoip::VoIPControllerWrapper^ sender, libtgvoip::CallState newState); + virtual void OnSignalBarsChanged(libtgvoip::VoIPControllerWrapper^ sender, int signal); + }; + + public value struct Config{ + double InitTimeout; + double RecvTimeout; + DataSavingMode DataSavingMode; + bool EnableAEC; + bool EnableNS; + bool EnableAGC; + Platform::String^ LogFilePath; + Platform::String^ StatsDumpFilePath; + }; + + // A class that provides methods and properties related to VoIP calls. + // It wraps Windows.Phone.Networking.Voip.VoipCallCoordinator, and provides app-specific call functionality. + public ref class CallController sealed + { + public: + + // The public methods below are just for illustration purposes - add your own methods here + // mtproto + void HandleUpdatePhoneCall(); + void StartMTProtoUpdater(); + void StopMTProtoUpdater(); + + // libtgvoip + void CreateVoIPControllerWrapper(); + void DeleteVoIPControllerWrapper(); + void SetConfig(Config config); + void SetEncryptionKey(const Platform::Array^ key, bool isOutgoing); + void SetPublicEndpoints(const Platform::Array^ endpoints, bool allowP2P, int connectionMaxLayer); + void SetProxy(ProxyStruct proxy); + void Start(); + void Connect(); + + void SetMicMute(bool mute); + void SwitchSpeaker(bool external); + void UpdateServerConfig(Platform::String^ json); + int64 GetPreferredRelayID(); + Error GetLastError(); + Platform::String^ GetDebugLog(); + Platform::String^ GetDebugString(); + Platform::String^ GetVersion(); + int GetSignalBarsCount(); + + // Provide an inteface that can be used to get call controller status change notifications + void SetStatusCallback(ICallControllerStatusListener^ statusListener); + + // Initiate an outgoing call. Called by the UI process. + // Returns true if the outgoing call processing was started, false otherwise. + bool InitiateOutgoingCall(Platform::String^ recepientName, int64 recepientId, int64 callId, int64 callAccessHash); + bool InitiateOutgoingCall(Platform::String^ recepientName, int64 recepientId, int64 callId, int64 callAccessHash, + Config config, const Platform::Array^ key, bool outgoing, + const Platform::Array^ emojis, const Platform::Array^ endpoints, + bool allowP2P, int connectionMaxLayer, + ProxyStruct proxy); + + // Start processing an incoming call. Called by managed code in this process (the VoIP agent host process). + // Returns true if the incoming call processing was started, false otherwise. + bool OnIncomingCallReceived(Platform::String^ contactName, int64 contactId, Platform::String^ contactImage, int64 callId, int64 callAccessHash, IncomingCallDialogDismissedCallback^ incomingCallDialogDismissedCallback); + + // Hold a call. Called by the UI process. + bool HoldCall(); + + // Resume a call. Called by the UI process. + bool ResumeCall(); + + // End a call. Called by the UI process. + bool EndCall(); + + // Toggle the camera location. Called by the UI process. + bool ToggleCamera(); + + // Get the call state + property PhoneVoIPApp::BackEnd::CallStatus CallStatus + { + PhoneVoIPApp::BackEnd::CallStatus get(); + }; + + // Get or set the media operations that are allowed for a call. + property PhoneVoIPApp::BackEnd::MediaOperations MediaOperations + { + PhoneVoIPApp::BackEnd::MediaOperations get(); + } + + // Indicates if video is currently being displayed or not + property bool IsShowingVideo + { + bool get(); + void set(bool value); + } + + // Indicates whether the video is being rendered or not. + property bool IsRenderingVideo + { + bool get(); + void set(bool value); + } + + // Get the current camera location + property PhoneVoIPApp::BackEnd::CameraLocation CameraLocation + { + PhoneVoIPApp::BackEnd::CameraLocation get(); + } + + // Get the possible routes for audio + property CallAudioRoute AvailableAudioRoutes + { + CallAudioRoute get(); + } + + // Get or set the current route for audio + property CallAudioRoute AudioRoute + { + CallAudioRoute get(); + void set(CallAudioRoute newRoute); + } + + // Get the name of the other party in the most recent call. + // Can return nullptr if there hasn't been a call yet. + property Platform::String^ OtherPartyName + { + Platform::String^ get(); + } + + // Get the name of the other party in the most recent call. + // Can return nullptr if there hasn't been a call yet. + property int64 OtherPartyId + { + int64 get(); + } + + // Get call start time + property Windows::Foundation::DateTime CallStartTime + { + Windows::Foundation::DateTime get(); + } + + property int64 CallId + { + int64 get(); + } + + property int64 CallAccessHash + { + int64 get(); + } + + property int64 AcceptedCallId + { + int64 get(); + void set(int64 value); + } + + property Platform::Array^ Key + { + Platform::Array^ get(); + } + + property bool Outgoing + { + bool get(); + } + + property Platform::Array^ Emojis + { + Platform::Array^ get(); + } + + private: + libtgvoip::VoIPControllerWrapper^ wrapper; + LibTgVoipStateListener^ stateListener; + + // Only the server can create an instance of this object + friend ref class PhoneVoIPApp::BackEnd::Globals; + + // Constructor and destructor + CallController(); + ~CallController(); + + // Set the call status + void SetCallStatus(PhoneVoIPApp::BackEnd::CallStatus newStatus); + + // Indicates that a call is now active + void SetActiveCall(Windows::Phone::Networking::Voip::VoipPhoneCall^ call, int64 contactId, int64 callId, int64 callAccessHash, const Platform::Array^ key, bool outgoing, const Platform::Array^ emojis, Windows::Phone::Networking::Voip::VoipCallMedia callMedia); + + // Called by the VoipCallCoordinator when the user accepts an incoming call. + void OnAcceptCallRequested(Windows::Phone::Networking::Voip::VoipPhoneCall^ sender, Windows::Phone::Networking::Voip::CallAnswerEventArgs^ args); + + // Called by the VoipCallCoordinator when the user rejects an incoming call. + void OnRejectCallRequested(Windows::Phone::Networking::Voip::VoipPhoneCall^ sender, Windows::Phone::Networking::Voip::CallRejectEventArgs^ args); + + // Called by the VoipCallCoordinator when a call is to be put on hold. + void OnHoldCallRequested(Windows::Phone::Networking::Voip::VoipPhoneCall^ sender, Windows::Phone::Networking::Voip::CallStateChangeEventArgs^ args); + + // Called by the VoipCallCoordinator when a call that was previously put on hold is to be resumed. + void OnResumeCallRequested(Windows::Phone::Networking::Voip::VoipPhoneCall^ sender, Windows::Phone::Networking::Voip::CallStateChangeEventArgs^ args); + + // Called by the VoipCallCoordinator when a call is to be ended. + void OnEndCallRequested(Windows::Phone::Networking::Voip::VoipPhoneCall^ sender, Windows::Phone::Networking::Voip::CallStateChangeEventArgs^ args); + + // Called by the AudioRoutingManager when call audio routing changes. + void OnAudioEndpointChanged(Windows::Phone::Media::Devices::AudioRoutingManager^ sender, Platform::Object^ args); + + // Called by the BackEndCapture when the camera is toggled + void OnCameraLocationChanged(PhoneVoIPApp::BackEnd::CameraLocation newCameraLocation); + + // Set a value that indicates if video/audio capture/render is enabled for a call or not. + void SetMediaOperations(PhoneVoIPApp::BackEnd::MediaOperations value); + + // Start/stop video/audio capture/playback based on the current state. + void UpdateMediaOperations(); + + // The relative URI to the call-in-progress page + Platform::String ^callInProgressPageUri; + + // The name of this service provider + Platform::String^ voipServiceName; + + // The URI to the default contact image + Windows::Foundation::Uri^ defaultContactImageUri; + + // The URI to the branding image + Windows::Foundation::Uri^ brandingImageUri; + + // The URI to the ringtone file + Windows::Foundation::Uri^ ringtoneUri; + + // Interface used to deliver status callbacks + ICallControllerStatusListener^ statusListener; + + // A VoIP call that is in progress + Windows::Phone::Networking::Voip::VoipPhoneCall^ activeCall; + + // The status of a call, if any + PhoneVoIPApp::BackEnd::CallStatus callStatus; + + // The name of the other party, if any + Platform::String^ otherPartyName; + + // The id of the other party, if any + int64 otherPartyId; + + int64 callId; + + int64 callAccessHash; + + // The id of the caller for the latest incoming call + int64 incomingId; + + int64 incomingCallId; + + int64 incomingCallAccessHash; + + int64 acceptedCallId; + + Platform::Array^ key; + + bool outgoing; + + Platform::Array^ emojis; + + // Indicates if video/audio capture/render is enabled for a call or not. + PhoneVoIPApp::BackEnd::MediaOperations mediaOperations; + + PhoneVoIPApp::BackEnd::CameraLocation cameraLocation; + + // Indicates if video is currently being displayed or not. + bool isShowingVideo; + + bool isRenderingVideo; + + // The method to be called when the incoming call dialog box is dismissed + IncomingCallDialogDismissedCallback^ onIncomingCallDialogDismissed; + + // The VoIP call coordinator + Windows::Phone::Networking::Voip::VoipCallCoordinator^ callCoordinator; + + // The phone audio routing manager + Windows::Phone::Media::Devices::AudioRoutingManager^ audioRoutingManager; + + // Phone call related event handlers + Windows::Foundation::TypedEventHandler^ acceptCallRequestedHandler; + Windows::Foundation::TypedEventHandler^ rejectCallRequestedHandler; + Windows::Foundation::TypedEventHandler^ holdCallRequestedHandler; + Windows::Foundation::TypedEventHandler^ resumeCallRequestedHandler; + Windows::Foundation::TypedEventHandler^ endCallRequestedHandler; + + // Audio related event handlers + Windows::Foundation::TypedEventHandler^ audioEndpointChangedHandler; + + // A cookie used to un-register the audio endpoint changed handler + Windows::Foundation::EventRegistrationToken audioEndpointChangedHandlercookie; + + // Camera location related event handlers + CameraLocationChangedEventHandler^ cameraLocationChangedHandler; + }; + } +} diff --git a/BackEnd/Globals.cpp b/BackEnd/Globals.cpp new file mode 100755 index 0000000..34804f9 --- /dev/null +++ b/BackEnd/Globals.cpp @@ -0,0 +1,321 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#include +#include +#include +#include +#include +#include "Globals.h" +#include "ApiLock.h" +#include "CallController.h" +#include "BackEndAudio.h" +#include "BackEndCapture.h" + +using namespace PhoneVoIPApp::BackEnd; +using namespace Windows::Foundation; +using namespace Windows::Phone::Media::Capture; + +HRESULT __declspec(dllexport) MyGetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ IInspectable **factory) +{ + *factory = nullptr; + + Microsoft::WRL::ComPtr activationFactory; + auto &module = Microsoft::WRL::Module::GetModule(); + + HRESULT hr = module.GetActivationFactory(activatableClassId, &activationFactory); + if (SUCCEEDED(hr)) + { + *factory = activationFactory.Detach(); + + if (*factory == nullptr) + { + return E_OUTOFMEMORY; + } + } + + return hr; +} + +// Maximum number of characters required to contain the string version of an unsigned integer +#define MAX_CHARS_IN_UINT_AS_STRING ((sizeof(unsigned int) * 4) + 1) + +const LPCWSTR Globals::noOtherBackgroundProcessEventName = L"PhoneVoIPApp.noOtherBackgroundProcess"; +const LPCWSTR Globals::uiDisconnectedEventName = L"PhoneVoIPApp.uiDisconnected."; +const LPCWSTR Globals::backgroundProcessReadyEventName = L"PhoneVoIPApp.backgroundProcessReady."; +Globals^ Globals::singleton = nullptr; + +void Globals::StartServer(const Platform::Array^ outOfProcServerClassNames) +{ + HRESULT hr = S_OK; + + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (outOfProcServerClassNames == nullptr) + { + throw ref new Platform::InvalidArgumentException(L"outOfProcServerClassNames cannot be null"); + } + + if (this->started) + { + return; // Nothing more to be done + } + + // Set an event that indicates that the background process is ready. + this->backgroundReadyEvent = ::CreateEventEx( + NULL, + Globals::GetBackgroundProcessReadyEventName(Globals::GetCurrentProcessId())->Data(), + CREATE_EVENT_INITIAL_SET | CREATE_EVENT_MANUAL_RESET, + EVENT_ALL_ACCESS); + if (this->backgroundReadyEvent == NULL) + { + // Something went wrong + DWORD dwErr = ::GetLastError(); + hr = HRESULT_FROM_WIN32(dwErr); + throw ref new Platform::COMException(hr, L"An error occurred trying to create an event that indicates that the background process is ready"); + } + + // Set the event + BOOL success = ::SetEvent(this->backgroundReadyEvent); + if (success == FALSE) + { + DWORD dwErr = ::GetLastError(); + hr = HRESULT_FROM_WIN32(dwErr); + throw ref new Platform::COMException(hr, L"An error occurred trying to set an event that indicates that the background process is ready"); + } + + this->started = true; +} + +void Globals::DoPeriodicKeepAlive() +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + // TODO: Do stuff here - refresh tokens, get new certs from server, etc. +} + +unsigned int Globals::GetCurrentProcessId() +{ + return ::GetCurrentProcessId(); +} + +Platform::String^ Globals::GetUiDisconnectedEventName(unsigned int backgroundProcessId) +{ + WCHAR backgroundProcessIdString[MAX_CHARS_IN_UINT_AS_STRING]; + if (swprintf_s<_countof(backgroundProcessIdString)>(backgroundProcessIdString, L"%u", backgroundProcessId) < 0) + throw ref new Platform::FailureException(L"Could not create string version of background process id"); + + auto eventName = ref new Platform::String(Globals::uiDisconnectedEventName) + ref new Platform::String(backgroundProcessIdString); + return eventName; +} + +Platform::String^ Globals::GetBackgroundProcessReadyEventName(unsigned int backgroundProcessId) +{ + WCHAR backgroundProcessIdString[MAX_CHARS_IN_UINT_AS_STRING]; + if (swprintf_s<_countof(backgroundProcessIdString)>(backgroundProcessIdString, L"%u", backgroundProcessId) < 0) + throw ref new Platform::FailureException(L"Could not create string version of background process id"); + + auto eventName = ref new Platform::String(Globals::backgroundProcessReadyEventName) + ref new Platform::String(backgroundProcessIdString); + return eventName; +} + +Globals^ Globals::Instance::get() +{ + if (Globals::singleton == nullptr) + { + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (Globals::singleton == nullptr) + { + Globals::singleton = ref new Globals(); + } + // else: some other thread has created an instance of the call controller + } + + return Globals::singleton; +} + +CallController^ Globals::CallController::get() +{ + if (this->callController == nullptr) + { + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + if (this->callController == nullptr) + { + this->callController = ref new PhoneVoIPApp::BackEnd::CallController(); + } + // else: some other thread has created an instance of the call controller + } + + return this->callController; +} + +IVideoRenderer^ Globals::VideoRenderer::get() +{ + // No need to lock - this get is idempotent + return this->videoRenderer; +} + +void Globals::VideoRenderer::set(IVideoRenderer^ value) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + this->videoRenderer = value; +} + +IMTProtoUpdater^ Globals::MTProtoUpdater::get() +{ + // No need to lock - this get is idempotent + return this->mtProtoUpdater; +} + +void Globals::MTProtoUpdater::set(IMTProtoUpdater^ value) +{ + // Make sure only one API call is in progress at a time + std::lock_guard lock(g_apiLock); + + this->mtProtoUpdater = value; +} + +//BackEndAudio^ Globals::AudioController::get() +//{ +// // No need to lock - this get is idempotent +// return this->audioController; +//} + +BackEndCapture^ Globals::CaptureController::get() +{ + // No need to lock - this get is idempotent + return this->captureController; +} + +BackEndTransport^ Globals::TransportController::get() +{ + // No need to lock - this get is idempotent + return this->transportController; +} + +Globals::Globals() : + started(false), + serverRegistrationCookie(NULL), + callController(nullptr), + videoRenderer(nullptr), + noOtherBackgroundProcessEvent(NULL), + backgroundReadyEvent(NULL), + //audioController(nullptr), + transportController(nullptr), + captureController(nullptr) +{ + { + WCHAR szBuffer[256]; + swprintf_s(szBuffer, L"[Globals::Globals] => VoIP background process with id %d starting up\n", this->GetCurrentProcessId()); + ::OutputDebugString(szBuffer); + } + + // Create an event that indicates if any other VoIP background exits or not + this->noOtherBackgroundProcessEvent = ::CreateEventEx(NULL, Globals::noOtherBackgroundProcessEventName, CREATE_EVENT_INITIAL_SET | CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); + if (this->noOtherBackgroundProcessEvent == NULL) + { + // Something went wrong + DWORD dwErr = ::GetLastError(); + HRESULT hr = HRESULT_FROM_WIN32(dwErr); + throw ref new Platform::COMException(hr, L"An error occurred trying to create an event that indicates if the background process exists or not"); + } + + // Wait for up to 30 seconds for the event to become set - if another instance of this process exists, this event would be in the reset state + DWORD reason = ::WaitForSingleObjectEx(this->noOtherBackgroundProcessEvent, 30 * 1000, FALSE); + _ASSERT(reason != WAIT_FAILED); // We don't care about any of the other reasons why WaitForSingleObjectEx returned + if (reason == WAIT_TIMEOUT) + { + throw ref new Platform::FailureException(L"Another instance of the VoIP background process exists and that process did not exit within 30 seconds. Cannot continue."); + } + + // Reset the event to indicate that there is a VoIP background process + BOOL success = ::ResetEvent(this->noOtherBackgroundProcessEvent); + if (success == FALSE) + { + // Something went wrong + DWORD dwErr = ::GetLastError(); + HRESULT hr = HRESULT_FROM_WIN32(dwErr); + throw ref new Platform::COMException(hr, L"An error occurred trying to reset the event that indicates if the background process exists or not"); + } + + // Initialize transport + this->transportController = ref new BackEndTransport(); // local + + // Initialize audio controller + //this->audioController = ref new BackEndAudio(); + + // Set the transport for audio + //this->audioController->SetTransport(this->transportController); + + // Initialize capture controller + this->captureController = ref new BackEndCapture(); + + // Set the transport on the controller + this->captureController->SetTransport(this->transportController); + + // Initialize the call controller + this->callController = ref new PhoneVoIPApp::BackEnd::CallController(); +} + +Globals::~Globals() +{ + // The destructor of this singleton object is called when the process is shutting down. + + // Before shutting down, make sure the UI process is not connected + HANDLE uiDisconnectedEvent = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, Globals::GetUiDisconnectedEventName(Globals::GetCurrentProcessId())->Data()); + if (uiDisconnectedEvent != NULL) + { + // The event exists - wait for it to get signaled (for a maximum of 30 seconds) + DWORD reason = ::WaitForSingleObjectEx(uiDisconnectedEvent, 30 * 1000, FALSE); + _ASSERT(reason != WAIT_FAILED); // We don't care about any of the other reasons why WaitForSingleObjectEx returned + } + + // At this point, the UI is no longer connected to the background process. + // It is possible that the UI now reconnects to the background process - this would be a bug, + // and we should exit the background process anyway. + + // Unset the event that indicates that the background process is ready + BOOL success; + if (this->backgroundReadyEvent != NULL) + { + success = ::ResetEvent(this->backgroundReadyEvent); + _ASSERT(success); + + ::CloseHandle(this->backgroundReadyEvent); + this->backgroundReadyEvent = NULL; + } + + // Unregister the activation factories for out-of-process objects hosted in this process + if (this->started) + { + RoRevokeActivationFactories(this->serverRegistrationCookie); + } + + // Set the event that indicates that no instance of the VoIP background process exists + if (this->noOtherBackgroundProcessEvent != NULL) + { + success = ::SetEvent(this->noOtherBackgroundProcessEvent); + _ASSERT(success); + + ::CloseHandle(this->noOtherBackgroundProcessEvent); + this->noOtherBackgroundProcessEvent = NULL; + } + + { + WCHAR szBuffer[256]; + swprintf_s(szBuffer, L"[Globals::~Globals] => VoIP background process with id %d shutting down\n", this->GetCurrentProcessId()); + ::OutputDebugString(szBuffer); + } +} diff --git a/BackEnd/Globals.h b/BackEnd/Globals.h new file mode 100755 index 0000000..c4b188b --- /dev/null +++ b/BackEnd/Globals.h @@ -0,0 +1,137 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once + +#include +#include "IVideoRenderer.h" +#include "IMTProtoUpdater.h" + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + // Forward declarations + ref class CallController; + //ref class BackEndAudio; + ref class BackEndTransport; + ref class BackEndCapture; + + // A singleton container that is used to hold other global singletons and background process-wide static state. + // Another purpose of this class is to start the out-of-process WinRT server, so that the UI process + // managed code can instantiate WinRT objects in this process. + public ref class Globals sealed + { + public: + // Start the out-of-process WinRT server, so that the UI process can instantiate WinRT objects in this process. + void StartServer(const Platform::Array^ outOfProcServerClassNames); + + // Do some app-specific periodic tasks, to let the remote server know that this endpoint is still alive. + void DoPeriodicKeepAlive(); + + // Get the process id of the current process + static unsigned int GetCurrentProcessId(); + + // Get the name of the event that indicates if the UI is connected to the background process or not + static Platform::String^ GetUiDisconnectedEventName(unsigned int backgroundProcessId); + + // Get the name of the event that indicates if the background process is ready or not + static Platform::String^ GetBackgroundProcessReadyEventName(unsigned int backgroundProcessId); + + // Get the single instance of this class + static property Globals^ Instance + { + Globals^ get(); + } + + // Get the call controller singleton object + property PhoneVoIPApp::BackEnd::CallController^ CallController + { + PhoneVoIPApp::BackEnd::CallController^ get(); + } + + // The singleton video renderer object. + property IVideoRenderer^ VideoRenderer + { + IVideoRenderer^ get(); + void set(IVideoRenderer^ value); + } + + property IMTProtoUpdater^ MTProtoUpdater + { + IMTProtoUpdater^ get(); + void set(IMTProtoUpdater^ value); + } + + // The singleton audio controller object. + /*property BackEndAudio^ AudioController + { + BackEndAudio^ get(); + }*/ + + // The singleton audio controller object. + property BackEndCapture^ CaptureController + { + BackEndCapture^ get(); + } + + // The singleton transport object. + property BackEndTransport^ TransportController + { + BackEndTransport^ get(); + } + + private: + // Default constructor + Globals(); + + // Destructor + ~Globals(); + + // Name of the event that indicates if another instance of the VoIP background process exists or not + static const LPCWSTR noOtherBackgroundProcessEventName; + + // Name of the event that indicates if the UI is connected to the background process or not + static const LPCWSTR uiDisconnectedEventName; + + // Name of the event that indicates if the background process is ready or not + static const LPCWSTR backgroundProcessReadyEventName; + + // The single instance of this class + static Globals^ singleton; + + // Indicates if the out-of-process server has started or not + bool started; + + // A cookie that is used to unregister remotely activatable objects in this process + RO_REGISTRATION_COOKIE serverRegistrationCookie; + + // An event that indicates if another instance of the background process exists or not + HANDLE noOtherBackgroundProcessEvent; + + // An event that indicates that the background process is ready + HANDLE backgroundReadyEvent; + + // The call controller object + PhoneVoIPApp::BackEnd::CallController^ callController; + + // The video renderer object + PhoneVoIPApp::BackEnd::IVideoRenderer^ videoRenderer; + + PhoneVoIPApp::BackEnd::IMTProtoUpdater^ mtProtoUpdater; + + // The audio capture/render controller + //BackEndAudio^ audioController; + + // The audio capture/render controller + BackEndCapture^ captureController; + + // The data transport + BackEndTransport^ transportController; + }; + } +} diff --git a/BackEnd/ICallControllerStatusListener.h b/BackEnd/ICallControllerStatusListener.h new file mode 100755 index 0000000..f42b123 --- /dev/null +++ b/BackEnd/ICallControllerStatusListener.h @@ -0,0 +1,143 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once + +#include + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + // libtgvoip Endpoint + public ref class Endpoint sealed{ + public: + property int64 id; + property uint16 port; + property Platform::String^ ipv4; + property Platform::String^ ipv6; + property Platform::Array^ peerTag; + }; + + public value struct EndpointStruct{ + int64 id; + uint16 port; + Platform::String^ ipv4; + Platform::String^ ipv6; + Platform::String^ peerTag; + }; + + // libtgvoip ProxyProtocol + public enum class ProxyProtocol : int{ + None = (int)libtgvoip::ProxyProtocol::None, + SOCKS5 = (int)libtgvoip::ProxyProtocol::SOCKS5 + }; + + public value struct ProxyStruct{ + ProxyProtocol protocol; + Platform::String^ address; + uint16 port; + Platform::String^ username; + Platform::String^ password; + }; + + // libtgvoip CallState + public enum class CallState : int{ + WaitInit = (int)libtgvoip::CallState::WaitInit, + WaitInitAck = (int)libtgvoip::CallState::WaitInitAck, + Established = (int)libtgvoip::CallState::Established, + Failed = (int)libtgvoip::CallState::Failed + }; + + // libtgvoip Error + public enum class Error : int{ + Unknown = (int)libtgvoip::Error::Unknown, + Incompatible = (int)libtgvoip::Error::Incompatible, + Timeout = (int)libtgvoip::Error::Timeout, + AudioIO = (int)libtgvoip::Error::AudioIO + }; + + // libtgvoip NetworkType + public enum class NetworkType : int{ + Unknown = (int)libtgvoip::NetworkType::Unknown, + GPRS = (int)libtgvoip::NetworkType::GPRS, + EDGE = (int)libtgvoip::NetworkType::EDGE, + UMTS = (int)libtgvoip::NetworkType::UMTS, + HSPA = (int)libtgvoip::NetworkType::HSPA, + LTE = (int)libtgvoip::NetworkType::LTE, + WiFi = (int)libtgvoip::NetworkType::WiFi, + Ethernet = (int)libtgvoip::NetworkType::Ethernet, + OtherHighSpeed = (int)libtgvoip::NetworkType::OtherHighSpeed, + OtherLowSpeed = (int)libtgvoip::NetworkType::OtherLowSpeed, + Dialup = (int)libtgvoip::NetworkType::Dialup, + OtherMobile = (int)libtgvoip::NetworkType::OtherMobile, + }; + + // libtgvoip DataSavingMode + public enum class DataSavingMode{ + Never = (int)libtgvoip::DataSavingMode::Never, + MobileOnly = (int)libtgvoip::DataSavingMode::MobileOnly, + Always = (int)libtgvoip::DataSavingMode::Always + }; + + // The status of a call + public enum class CallStatus + { + None = 0x00, + InProgress, + Held + }; + + // Where is the call audio going? + public enum class CallAudioRoute + { + None = (int)Windows::Phone::Media::Devices::AvailableAudioRoutingEndpoints::None, + Earpiece = (int)Windows::Phone::Media::Devices::AvailableAudioRoutingEndpoints::Earpiece, + Speakerphone = (int)Windows::Phone::Media::Devices::AvailableAudioRoutingEndpoints::Speakerphone, + Bluetooth = (int)Windows::Phone::Media::Devices::AvailableAudioRoutingEndpoints::Bluetooth + }; + + // Which camera are we using? + public enum class CameraLocation + { + Front = (int)Windows::Phone::Media::Capture::CameraSensorLocation::Front, + Back = (int)Windows::Phone::Media::Capture::CameraSensorLocation::Back + }; + + // Used to indicate the status of video/audio capture/render + public enum class MediaOperations + { + None = 0x00, + VideoCapture = 0x01, + VideoRender = 0x02, + AudioCapture = 0x04, + AudioRender = 0x08 + }; + + // An interface that is used by the call controller to deliver status change notifications. + // This interface is meant to be implemented in the UI process, and will be called back by + // the agent host process using out-of-process WinRT. + public interface class ICallControllerStatusListener + { + void OnSignalBarsChanged(int newSignal); + + void OnCallStateChanged(CallState newState); + + // The status of a call has changed. + void OnCallStatusChanged(CallStatus newStatus); + + // The call audio route has changed. Also called when the available audio routes have changed. + void OnCallAudioRouteChanged(CallAudioRoute newRoute); + + // Video/audio capture/render has started/stopped + void OnMediaOperationsChanged(MediaOperations newOperations); + + // Camera location has changed + void OnCameraLocationChanged(CameraLocation newCameraLocation); + }; + } +} diff --git a/BackEnd/IConfig.h b/BackEnd/IConfig.h new file mode 100755 index 0000000..4992c08 --- /dev/null +++ b/BackEnd/IConfig.h @@ -0,0 +1,13 @@ +#pragma once + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + public interface class IConfig + { + property double InitTimeout; + property double RecvTimeout; + }; + } +} \ No newline at end of file diff --git a/BackEnd/IMTProtoUpdater.h b/BackEnd/IMTProtoUpdater.h new file mode 100755 index 0000000..6458582 --- /dev/null +++ b/BackEnd/IMTProtoUpdater.h @@ -0,0 +1,30 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + // An interface that is used by the call controller to start and stop mtproto communication. + public interface class IMTProtoUpdater + { + // Start handle background updates. + void Start(int pts, int date, int qts); + + // Stop handle background updates. + void Stop(); + + // Discard incoming call + void DiscardCall(int64 id, int64 accessHash); + + // Received incoming call + void ReceivedCall(int64 id, int64 accessHash); + }; + } +} \ No newline at end of file diff --git a/BackEnd/IVideoRenderer.h b/BackEnd/IVideoRenderer.h new file mode 100755 index 0000000..d0bc771 --- /dev/null +++ b/BackEnd/IVideoRenderer.h @@ -0,0 +1,24 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + // An interface that is used by the call controller to start and stop video rendering. + public interface class IVideoRenderer + { + // Start rendering video. + void Start(); + + // Stop rendering video. + void Stop(); + }; + } +} diff --git a/BackEnd/Server.h b/BackEnd/Server.h new file mode 100755 index 0000000..6167299 --- /dev/null +++ b/BackEnd/Server.h @@ -0,0 +1,46 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once +#include +#include "Globals.h" + +namespace PhoneVoIPApp +{ + namespace BackEnd + { + namespace OutOfProcess + { + // A remotely activatable class that is used by the UI process and managed code within + // the VoIP background process to get access to native objects that exist in the VoIP background process. + public ref class Server sealed + { + public: + // Constructor + Server() + { + } + + // Destructor + virtual ~Server() + { + } + + // Called by the UI process to get the call controller object + property CallController^ CallController + { + PhoneVoIPApp::BackEnd::CallController^ get() + { + return Globals::Instance->CallController; + }; + } + + // Add methods and properties to get other objects here, as required. + }; + } + } +} diff --git a/BackEndProxyStub/BackEndProxyStub.def b/BackEndProxyStub/BackEndProxyStub.def new file mode 100755 index 0000000..31a09ed --- /dev/null +++ b/BackEndProxyStub/BackEndProxyStub.def @@ -0,0 +1,5 @@ +EXPORTS + DllGetClassObject PRIVATE + DllCanUnloadNow PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE \ No newline at end of file diff --git a/BackEndProxyStub/BackEndProxyStub.vcxproj b/BackEndProxyStub/BackEndProxyStub.vcxproj new file mode 100755 index 0000000..58eddf9 --- /dev/null +++ b/BackEndProxyStub/BackEndProxyStub.vcxproj @@ -0,0 +1,155 @@ + + + + + Debug + Win32 + + + Debug + ARM + + + Release + Win32 + + + Release + ARM + + + + {bbabeea1-494c-4618-96e3-399873a5558b} + BackEndProxyStub + en-US + $(VCTargetsPath11) + 11.0 + Windows Phone + 8.0 + Windows Phone Silverlight + 8.1 + + + + DynamicLibrary + true + v120 + false + + + DynamicLibrary + true + v120 + false + + + DynamicLibrary + false + true + v120 + false + + + DynamicLibrary + false + true + v120 + false + + + + + + + + false + + + PhoneVoIPApp.$(ProjectName) + $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ + $(PlatformTarget)\$(Configuration)\ + + + PhoneVoIPApp.$(ProjectName) + $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ + $(PlatformTarget)\$(Configuration)\ + + + PhoneVoIPApp.$(ProjectName) + $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ + $(PlatformTarget)\$(Configuration)\ + + + PhoneVoIPApp.$(ProjectName) + $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ + $(PlatformTarget)\$(Configuration)\ + + + + WIN32_LEAN_AND_MEAN;WIN32;REGISTER_PROXY_DLL;_USRDLL;%(PreprocessorDefinitions) + + + + + WIN32_LEAN_AND_MEAN;WIN32;REGISTER_PROXY_DLL;_USRDLL;NDEBUG;%(PreprocessorDefinitions) + + + + + WIN32_LEAN_AND_MEAN;_ARM_;WIN32;REGISTER_PROXY_DLL;_USRDLL;%(PreprocessorDefinitions) + + + + + WIN32_LEAN_AND_MEAN;_ARM_;WIN32;REGISTER_PROXY_DLL;_USRDLL;NDEBUG;%(PreprocessorDefinitions) + + + + + NotUsing + false + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + $(ProjectDir);%(AdditionalIncludeDirectories) + $(ProjectDir);%(AdditionalIncludeDirectories) + $(ProjectDir);%(AdditionalIncludeDirectories) + $(ProjectDir);%(AdditionalIncludeDirectories) + + + Console + false + windowsphonecore.lib;runtimeobject.lib;rpcrt4.lib;%(AdditionalDependencies) + false + $(ProjectName).def + $(ProjectName).def + $(ProjectName).def + $(ProjectName).def + + + + + true + + + true + false + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BackEndProxyStub/PhoneVoIPApp.BackEnd.OutOfProcess.h b/BackEndProxyStub/PhoneVoIPApp.BackEnd.OutOfProcess.h new file mode 100755 index 0000000..7a1cb37 --- /dev/null +++ b/BackEndProxyStub/PhoneVoIPApp.BackEnd.OutOfProcess.h @@ -0,0 +1,278 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* at Tue Jan 29 08:48:52 2019 + */ +/* Compiler settings for C:\Users\evgeny\AppData\Local\Temp\PhoneVoIPApp.BackEnd.OutOfProcess.idl-5b92719d: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=ARM 8.00.0603 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __PhoneVoIPApp2EBackEnd2EOutOfProcess_h__ +#define __PhoneVoIPApp2EBackEnd2EOutOfProcess_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + namespace OutOfProcess { + interface __IServerPublicNonVirtuals; + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "inspectable.h" +#include "AsyncInfo.h" +#include "EventToken.h" +#include "Windows.Foundation.h" +#include "PhoneVoIPApp.BackEnd.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd2EOutOfProcess_0000_0000 */ +/* [local] */ + +#if defined(__cplusplus) +} +#endif // defined(__cplusplus) +#include +#if !defined(__phonevoipapp2Ebackend_h__) +#include +#endif // !defined(__phonevoipapp2Ebackend_h__) +#if defined(__cplusplus) +extern "C" { +#endif // defined(__cplusplus) +#ifdef __cplusplus +namespace ABI { +namespace PhoneVoIPApp { +namespace BackEnd { +class CallController; +} /*BackEnd*/ +} /*PhoneVoIPApp*/ +} +#endif + + +#ifdef __cplusplus +namespace ABI { +namespace PhoneVoIPApp { +namespace BackEnd { +namespace OutOfProcess { +class Server; +} /*OutOfProcess*/ +} /*BackEnd*/ +} /*PhoneVoIPApp*/ +} +#endif +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd_OutOfProcess___IServerPublicNonVirtuals[] = L"PhoneVoIPApp.BackEnd.OutOfProcess.__IServerPublicNonVirtuals"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd2EOutOfProcess_0000_0000 */ +/* [local] */ + + + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd2EOutOfProcess_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd2EOutOfProcess_0000_0000_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::OutOfProcess::__IServerPublicNonVirtuals */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + namespace OutOfProcess { + + MIDL_INTERFACE("7BF79491-56BE-375A-BC22-0058B158F01F") + __IServerPublicNonVirtuals : public IInspectable + { + public: + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CallController( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::__ICallControllerPublicNonVirtuals **__returnValue) = 0; + + }; + + extern const __declspec(selectany) IID & IID___IServerPublicNonVirtuals = __uuidof(__IServerPublicNonVirtuals); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtualsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals * This, + /* [out] */ TrustLevel *trustLevel); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CallController )( + __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals **__returnValue); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtualsVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtualsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_get_CallController(This,__returnValue) \ + ( (This)->lpVtbl -> get_CallController(This,__returnValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd2EOutOfProcess_0000_0001 */ +/* [local] */ + +#ifndef RUNTIMECLASS_PhoneVoIPApp_BackEnd_OutOfProcess_Server_DEFINED +#define RUNTIMECLASS_PhoneVoIPApp_BackEnd_OutOfProcess_Server_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_PhoneVoIPApp_BackEnd_OutOfProcess_Server[] = L"PhoneVoIPApp.BackEnd.OutOfProcess.Server"; +#endif + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd2EOutOfProcess_0000_0001 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd2EOutOfProcess_0000_0001_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd2EOutOfProcess_0000_0001_v0_0_s_ifspec; + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/BackEndProxyStub/PhoneVoIPApp.BackEnd.OutOfProcess_i.c b/BackEndProxyStub/PhoneVoIPApp.BackEnd.OutOfProcess_i.c new file mode 100755 index 0000000..1e01d0d --- /dev/null +++ b/BackEndProxyStub/PhoneVoIPApp.BackEnd.OutOfProcess_i.c @@ -0,0 +1,79 @@ + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* at Tue Jan 29 08:48:52 2019 + */ +/* Compiler settings for C:\Users\evgeny\AppData\Local\Temp\PhoneVoIPApp.BackEnd.OutOfProcess.idl-5b92719d: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=ARM 8.00.0603 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals,0x7BF79491,0x56BE,0x375A,0xBC,0x22,0x00,0x58,0xB1,0x58,0xF0,0x1F); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/BackEndProxyStub/PhoneVoIPApp.BackEnd.OutOfProcess_p.c b/BackEndProxyStub/PhoneVoIPApp.BackEnd.OutOfProcess_p.c new file mode 100755 index 0000000..0a14e06 --- /dev/null +++ b/BackEndProxyStub/PhoneVoIPApp.BackEnd.OutOfProcess_p.c @@ -0,0 +1,338 @@ + + +/* this ALWAYS GENERATED file contains the proxy stub code */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* at Tue Jan 29 08:48:52 2019 + */ +/* Compiler settings for C:\Users\evgeny\AppData\Local\Temp\PhoneVoIPApp.BackEnd.OutOfProcess.idl-5b92719d: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=ARM 8.00.0603 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#if defined(_ARM_) + + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ +#if _MSC_VER >= 1200 +#pragma warning(push) +#endif + +#pragma warning( disable: 4211 ) /* redefine extern to static */ +#pragma warning( disable: 4232 ) /* dllimport identity*/ +#pragma warning( disable: 4024 ) /* array to pointer mapping*/ +#pragma warning( disable: 4152 ) /* function/data pointer conversion in expression */ + +#define USE_STUBLESS_PROXY + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REDQ_RPCPROXY_H_VERSION__ +#define __REQUIRED_RPCPROXY_H_VERSION__ 475 +#endif + + +#include "rpcproxy.h" +#ifndef __RPCPROXY_H_VERSION__ +#error this stub requires an updated version of +#endif /* __RPCPROXY_H_VERSION__ */ + + +#include "PhoneVoIPApp.BackEnd.OutOfProcess.h" + +#define TYPE_FORMAT_STRING_SIZE 25 +#define PROC_FORMAT_STRING_SIZE 43 +#define EXPR_FORMAT_STRING_SIZE 1 +#define TRANSMIT_AS_TABLE_SIZE 0 +#define WIRE_MARSHAL_TABLE_SIZE 0 + +typedef struct _PhoneVoIPApp2EBackEnd2EOutOfProcess_MIDL_TYPE_FORMAT_STRING + { + short Pad; + unsigned char Format[ TYPE_FORMAT_STRING_SIZE ]; + } PhoneVoIPApp2EBackEnd2EOutOfProcess_MIDL_TYPE_FORMAT_STRING; + +typedef struct _PhoneVoIPApp2EBackEnd2EOutOfProcess_MIDL_PROC_FORMAT_STRING + { + short Pad; + unsigned char Format[ PROC_FORMAT_STRING_SIZE ]; + } PhoneVoIPApp2EBackEnd2EOutOfProcess_MIDL_PROC_FORMAT_STRING; + +typedef struct _PhoneVoIPApp2EBackEnd2EOutOfProcess_MIDL_EXPR_FORMAT_STRING + { + long Pad; + unsigned char Format[ EXPR_FORMAT_STRING_SIZE ]; + } PhoneVoIPApp2EBackEnd2EOutOfProcess_MIDL_EXPR_FORMAT_STRING; + + +static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax = +{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}; + + +extern const PhoneVoIPApp2EBackEnd2EOutOfProcess_MIDL_TYPE_FORMAT_STRING PhoneVoIPApp2EBackEnd2EOutOfProcess__MIDL_TypeFormatString; +extern const PhoneVoIPApp2EBackEnd2EOutOfProcess_MIDL_PROC_FORMAT_STRING PhoneVoIPApp2EBackEnd2EOutOfProcess__MIDL_ProcFormatString; +extern const PhoneVoIPApp2EBackEnd2EOutOfProcess_MIDL_EXPR_FORMAT_STRING PhoneVoIPApp2EBackEnd2EOutOfProcess__MIDL_ExprFormatString; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_ProxyInfo; + + + +#if !defined(__RPC_ARM32__) +#error Invalid build platform for this stub. +#endif + +#if !(TARGET_IS_NT50_OR_LATER) +#error You need Windows 2000 or later to run this stub because it uses these features: +#error /robust command line switch. +#error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems. +#error This app will fail with the RPC_X_WRONG_STUB_VERSION error. +#endif + + +static const PhoneVoIPApp2EBackEnd2EOutOfProcess_MIDL_PROC_FORMAT_STRING PhoneVoIPApp2EBackEnd2EOutOfProcess__MIDL_ProcFormatString = + { + 0, + { + + /* Procedure get_CallController */ + + 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2 */ NdrFcLong( 0x0 ), /* 0 */ +/* 6 */ NdrFcShort( 0x6 ), /* 6 */ +/* 8 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 10 */ NdrFcShort( 0x0 ), /* 0 */ +/* 12 */ NdrFcShort( 0x8 ), /* 8 */ +/* 14 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 16 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 18 */ NdrFcShort( 0x0 ), /* 0 */ +/* 20 */ NdrFcShort( 0x0 ), /* 0 */ +/* 22 */ NdrFcShort( 0x0 ), /* 0 */ +/* 24 */ NdrFcShort( 0x2 ), /* 2 */ +/* 26 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 28 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 30 */ NdrFcShort( 0x13 ), /* Flags: must size, must free, out, */ +/* 32 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 34 */ NdrFcShort( 0x2 ), /* Type Offset=2 */ + + /* Return value */ + +/* 36 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 38 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 40 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + 0x0 + } + }; + +static const PhoneVoIPApp2EBackEnd2EOutOfProcess_MIDL_TYPE_FORMAT_STRING PhoneVoIPApp2EBackEnd2EOutOfProcess__MIDL_TypeFormatString = + { + 0, + { + NdrFcShort( 0x0 ), /* 0 */ +/* 2 */ + 0x11, 0x10, /* FC_RP [pointer_deref] */ +/* 4 */ NdrFcShort( 0x2 ), /* Offset= 2 (6) */ +/* 6 */ + 0x2f, /* FC_IP */ + 0x5a, /* FC_CONSTANT_IID */ +/* 8 */ NdrFcLong( 0x6b50718 ), /* 112527128 */ +/* 12 */ NdrFcShort( 0x3528 ), /* 13608 */ +/* 14 */ NdrFcShort( 0x3b66 ), /* 15206 */ +/* 16 */ 0xbe, /* 190 */ + 0x76, /* 118 */ +/* 18 */ 0xe1, /* 225 */ + 0x83, /* 131 */ +/* 20 */ 0xaa, /* 170 */ + 0x80, /* 128 */ +/* 22 */ 0xd4, /* 212 */ + 0xa5, /* 165 */ + + 0x0 + } + }; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd2EOutOfProcess_0000_0000, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: IUnknown, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */ + + +/* Object interface: IInspectable, ver. 0.0, + GUID={0xAF86E2E0,0xB12D,0x4c6a,{0x9C,0x5A,0xD7,0xAA,0x65,0x10,0x1E,0x90}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals, ver. 0.0, + GUID={0x7BF79491,0x56BE,0x375A,{0xBC,0x22,0x00,0x58,0xB1,0x58,0xF0,0x1F}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 0 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd2EOutOfProcess__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd2EOutOfProcess__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(7) ___x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtualsProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals::get_CallController */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + NdrStubCall2 +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtualsStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals, + &__x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_ServerInfo, + 7, + &__x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd2EOutOfProcess_0000_0001, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + +static const MIDL_STUB_DESC Object_StubDesc = + { + 0, + NdrOleAllocate, + NdrOleFree, + 0, + 0, + 0, + 0, + 0, + PhoneVoIPApp2EBackEnd2EOutOfProcess__MIDL_TypeFormatString.Format, + 1, /* -error bounds_check flag */ + 0x50002, /* Ndr library version */ + 0, + 0x800025b, /* MIDL Version 8.0.603 */ + 0, + 0, + 0, /* notify & notify_flag routine table */ + 0x1, /* MIDL flag */ + 0, /* cs routines */ + 0, /* proxy/server info */ + 0 + }; + +const CInterfaceProxyVtbl * const _PhoneVoIPApp2EBackEnd2EOutOfProcess_ProxyVtblList[] = +{ + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtualsProxyVtbl, + 0 +}; + +const CInterfaceStubVtbl * const _PhoneVoIPApp2EBackEnd2EOutOfProcess_StubVtblList[] = +{ + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtualsStubVtbl, + 0 +}; + +PCInterfaceName const _PhoneVoIPApp2EBackEnd2EOutOfProcess_InterfaceNamesList[] = +{ + "__x_ABI_CPhoneVoIPApp_CBackEnd_COutOfProcess_C____IServerPublicNonVirtuals", + 0 +}; + +const IID * const _PhoneVoIPApp2EBackEnd2EOutOfProcess_BaseIIDList[] = +{ + &IID_IInspectable, + 0 +}; + + +#define _PhoneVoIPApp2EBackEnd2EOutOfProcess_CHECK_IID(n) IID_GENERIC_CHECK_IID( _PhoneVoIPApp2EBackEnd2EOutOfProcess, pIID, n) + +int __stdcall _PhoneVoIPApp2EBackEnd2EOutOfProcess_IID_Lookup( const IID * pIID, int * pIndex ) +{ + + if(!_PhoneVoIPApp2EBackEnd2EOutOfProcess_CHECK_IID(0)) + { + *pIndex = 0; + return 1; + } + + return 0; +} + +const ExtendedProxyFileInfo PhoneVoIPApp2EBackEnd2EOutOfProcess_ProxyFileInfo = +{ + (PCInterfaceProxyVtblList *) & _PhoneVoIPApp2EBackEnd2EOutOfProcess_ProxyVtblList, + (PCInterfaceStubVtblList *) & _PhoneVoIPApp2EBackEnd2EOutOfProcess_StubVtblList, + (const PCInterfaceName * ) & _PhoneVoIPApp2EBackEnd2EOutOfProcess_InterfaceNamesList, + (const IID ** ) & _PhoneVoIPApp2EBackEnd2EOutOfProcess_BaseIIDList, + & _PhoneVoIPApp2EBackEnd2EOutOfProcess_IID_Lookup, + 1, + 2, + 0, /* table of [async_uuid] interfaces */ + 0, /* Filler1 */ + 0, /* Filler2 */ + 0 /* Filler3 */ +}; +#if _MSC_VER >= 1200 +#pragma warning(pop) +#endif + + +#endif /* if defined(_ARM_) */ + diff --git a/BackEndProxyStub/PhoneVoIPApp.BackEnd.h b/BackEndProxyStub/PhoneVoIPApp.BackEnd.h new file mode 100755 index 0000000..941662b --- /dev/null +++ b/BackEndProxyStub/PhoneVoIPApp.BackEnd.h @@ -0,0 +1,4046 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* at Tue Jan 29 08:48:50 2019 + */ +/* Compiler settings for C:\Users\evgeny\AppData\Local\Temp\PhoneVoIPApp.BackEnd.idl-35395493: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=ARM 8.00.0603 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __PhoneVoIPApp2EBackEnd_h__ +#define __PhoneVoIPApp2EBackEnd_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface IMessageReceivedEventHandler; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface ICameraLocationChangedEventHandler; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface IIncomingCallDialogDismissedCallback; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface __IBackEndTransportPublicNonVirtuals; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface __IBackEndTransportProtectedNonVirtuals; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface __IEndpointPublicNonVirtuals; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface ICallControllerStatusListener; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface __IBackEndCapturePublicNonVirtuals; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface __IBackEndCaptureProtectedNonVirtuals; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface IConfig; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface __ICallControllerPublicNonVirtuals; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface IVideoRenderer; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface IMTProtoUpdater; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface __IGlobalsPublicNonVirtuals; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_FWD_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_FWD_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_FWD_DEFINED__ +typedef interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics; + +#ifdef __cplusplus +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + interface __IGlobalsStatics; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +#endif /* __cplusplus */ + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "inspectable.h" +#include "AsyncInfo.h" +#include "EventToken.h" +#include "Windows.Foundation.h" +#include "Windows.Storage.Streams.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0000 */ +/* [local] */ + +#if defined(__cplusplus) +} +#endif // defined(__cplusplus) +#include +#if !defined(__windows2Estorage2Estreams_h__) +#include +#endif // !defined(__windows2Estorage2Estreams_h__) +#if defined(__cplusplus) +extern "C" { +#endif // defined(__cplusplus) +#if !defined(__cplusplus) +#if !defined(__cplusplus) + +typedef enum __x_ABI_CPhoneVoIPApp_CBackEnd_CProxyProtocol __x_ABI_CPhoneVoIPApp_CBackEnd_CProxyProtocol; + + +#endif /* end if !defined(__cplusplus) */ + + +#endif +#if !defined(__cplusplus) +#if !defined(__cplusplus) + +typedef enum __x_ABI_CPhoneVoIPApp_CBackEnd_CCallState __x_ABI_CPhoneVoIPApp_CBackEnd_CCallState; + + +#endif /* end if !defined(__cplusplus) */ + + +#endif +#if !defined(__cplusplus) +#if !defined(__cplusplus) + +typedef enum __x_ABI_CPhoneVoIPApp_CBackEnd_CError __x_ABI_CPhoneVoIPApp_CBackEnd_CError; + + +#endif /* end if !defined(__cplusplus) */ + + +#endif +#if !defined(__cplusplus) +#if !defined(__cplusplus) + +typedef enum __x_ABI_CPhoneVoIPApp_CBackEnd_CNetworkType __x_ABI_CPhoneVoIPApp_CBackEnd_CNetworkType; + + +#endif /* end if !defined(__cplusplus) */ + + +#endif +#if !defined(__cplusplus) +#if !defined(__cplusplus) + +typedef enum __x_ABI_CPhoneVoIPApp_CBackEnd_CDataSavingMode __x_ABI_CPhoneVoIPApp_CBackEnd_CDataSavingMode; + + +#endif /* end if !defined(__cplusplus) */ + + +#endif +#if !defined(__cplusplus) +#if !defined(__cplusplus) + +typedef enum __x_ABI_CPhoneVoIPApp_CBackEnd_CCallStatus __x_ABI_CPhoneVoIPApp_CBackEnd_CCallStatus; + + +#endif /* end if !defined(__cplusplus) */ + + +#endif +#if !defined(__cplusplus) +#if !defined(__cplusplus) + +typedef enum __x_ABI_CPhoneVoIPApp_CBackEnd_CCallAudioRoute __x_ABI_CPhoneVoIPApp_CBackEnd_CCallAudioRoute; + + +#endif /* end if !defined(__cplusplus) */ + + +#endif +#if !defined(__cplusplus) +#if !defined(__cplusplus) + +typedef enum __x_ABI_CPhoneVoIPApp_CBackEnd_CCameraLocation __x_ABI_CPhoneVoIPApp_CBackEnd_CCameraLocation; + + +#endif /* end if !defined(__cplusplus) */ + + +#endif +#if !defined(__cplusplus) +#if !defined(__cplusplus) + +typedef enum __x_ABI_CPhoneVoIPApp_CBackEnd_CMediaOperations __x_ABI_CPhoneVoIPApp_CBackEnd_CMediaOperations; + + +#endif /* end if !defined(__cplusplus) */ + + +#endif +#if !defined(__cplusplus) +typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_CEndpointStruct __x_ABI_CPhoneVoIPApp_CBackEnd_CEndpointStruct; + +#endif +#if !defined(__cplusplus) +typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_CProxyStruct __x_ABI_CPhoneVoIPApp_CBackEnd_CProxyStruct; + +#endif +#if !defined(__cplusplus) +typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_CConfig __x_ABI_CPhoneVoIPApp_CBackEnd_CConfig; + +#endif + + + + + + + + + + + + + + + +#ifdef __cplusplus +namespace ABI { +namespace PhoneVoIPApp { +namespace BackEnd { +class BackEndTransport; +} /*BackEnd*/ +} /*PhoneVoIPApp*/ +} +#endif +#ifdef __cplusplus +namespace ABI { +namespace PhoneVoIPApp { +namespace BackEnd { +class Endpoint; +} /*BackEnd*/ +} /*PhoneVoIPApp*/ +} +#endif +#ifdef __cplusplus +namespace ABI { +namespace PhoneVoIPApp { +namespace BackEnd { +class BackEndCapture; +} /*BackEnd*/ +} /*PhoneVoIPApp*/ +} +#endif +#ifdef __cplusplus +namespace ABI { +namespace PhoneVoIPApp { +namespace BackEnd { +class CallController; +} /*BackEnd*/ +} /*PhoneVoIPApp*/ +} +#endif +#ifdef __cplusplus +namespace ABI { +namespace PhoneVoIPApp { +namespace BackEnd { +class Globals; +} /*BackEnd*/ +} /*PhoneVoIPApp*/ +} +#endif +#if !defined(__cplusplus) + +#if !defined(__cplusplus) +/* [v1_enum] */ +enum __x_ABI_CPhoneVoIPApp_CBackEnd_CProxyProtocol + { + ProxyProtocol_None = 0, + ProxyProtocol_SOCKS5 = 1 + } ; +#endif /* end if !defined(__cplusplus) */ + +#endif +#if !defined(__cplusplus) + +#if !defined(__cplusplus) +/* [v1_enum] */ +enum __x_ABI_CPhoneVoIPApp_CBackEnd_CCallState + { + CallState_WaitInit = 1, + CallState_WaitInitAck = 2, + CallState_Established = 3, + CallState_Failed = 4 + } ; +#endif /* end if !defined(__cplusplus) */ + +#endif +#if !defined(__cplusplus) + +#if !defined(__cplusplus) +/* [v1_enum] */ +enum __x_ABI_CPhoneVoIPApp_CBackEnd_CError + { + Error_Unknown = 0, + Error_Incompatible = 1, + Error_Timeout = 2, + Error_AudioIO = 3 + } ; +#endif /* end if !defined(__cplusplus) */ + +#endif +#if !defined(__cplusplus) + +#if !defined(__cplusplus) +/* [v1_enum] */ +enum __x_ABI_CPhoneVoIPApp_CBackEnd_CNetworkType + { + NetworkType_Unknown = 0, + NetworkType_GPRS = 1, + NetworkType_EDGE = 2, + NetworkType_UMTS = 3, + NetworkType_HSPA = 4, + NetworkType_LTE = 5, + NetworkType_WiFi = 6, + NetworkType_Ethernet = 7, + NetworkType_OtherHighSpeed = 8, + NetworkType_OtherLowSpeed = 9, + NetworkType_Dialup = 10, + NetworkType_OtherMobile = 11 + } ; +#endif /* end if !defined(__cplusplus) */ + +#endif +#if !defined(__cplusplus) + +#if !defined(__cplusplus) +/* [v1_enum] */ +enum __x_ABI_CPhoneVoIPApp_CBackEnd_CDataSavingMode + { + DataSavingMode_Never = 0, + DataSavingMode_MobileOnly = 1, + DataSavingMode_Always = 2 + } ; +#endif /* end if !defined(__cplusplus) */ + +#endif +#if !defined(__cplusplus) + +#if !defined(__cplusplus) +/* [v1_enum] */ +enum __x_ABI_CPhoneVoIPApp_CBackEnd_CCallStatus + { + CallStatus_None = 0, + CallStatus_InProgress = 1, + CallStatus_Held = 2 + } ; +#endif /* end if !defined(__cplusplus) */ + +#endif +#if !defined(__cplusplus) + +#if !defined(__cplusplus) +/* [v1_enum] */ +enum __x_ABI_CPhoneVoIPApp_CBackEnd_CCallAudioRoute + { + CallAudioRoute_None = 0, + CallAudioRoute_Earpiece = 1, + CallAudioRoute_Speakerphone = 2, + CallAudioRoute_Bluetooth = 4 + } ; +#endif /* end if !defined(__cplusplus) */ + +#endif +#if !defined(__cplusplus) + +#if !defined(__cplusplus) +/* [v1_enum] */ +enum __x_ABI_CPhoneVoIPApp_CBackEnd_CCameraLocation + { + CameraLocation_Front = 1, + CameraLocation_Back = 0 + } ; +#endif /* end if !defined(__cplusplus) */ + +#endif +#if !defined(__cplusplus) + +#if !defined(__cplusplus) +/* [v1_enum] */ +enum __x_ABI_CPhoneVoIPApp_CBackEnd_CMediaOperations + { + MediaOperations_None = 0, + MediaOperations_VideoCapture = 1, + MediaOperations_VideoRender = 2, + MediaOperations_AudioCapture = 4, + MediaOperations_AudioRender = 8 + } ; +#endif /* end if !defined(__cplusplus) */ + +#endif +#if !defined(__cplusplus) +struct __x_ABI_CPhoneVoIPApp_CBackEnd_CEndpointStruct + { + INT64 id; + UINT16 port; + HSTRING ipv4; + HSTRING ipv6; + HSTRING peerTag; + } ; +#endif +#if !defined(__cplusplus) +struct __x_ABI_CPhoneVoIPApp_CBackEnd_CProxyStruct + { + __x_ABI_CPhoneVoIPApp_CBackEnd_CProxyProtocol protocol; + HSTRING address; + UINT16 port; + HSTRING username; + HSTRING password; + } ; +#endif +#if !defined(__cplusplus) +struct __x_ABI_CPhoneVoIPApp_CBackEnd_CConfig + { + DOUBLE InitTimeout; + DOUBLE RecvTimeout; + __x_ABI_CPhoneVoIPApp_CBackEnd_CDataSavingMode DataSavingMode; + boolean EnableAEC; + boolean EnableNS; + boolean EnableAGC; + HSTRING LogFilePath; + HSTRING StatsDumpFilePath; + } ; +#endif + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0000 */ +/* [local] */ + +#ifdef __cplusplus + +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + typedef enum ProxyProtocol ProxyProtocol; + + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus + +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + typedef enum CallState CallState; + + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus + +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + typedef enum Error Error; + + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus + +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + typedef enum NetworkType NetworkType; + + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus + +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + typedef enum DataSavingMode DataSavingMode; + + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus + +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + typedef enum CallStatus CallStatus; + + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus + +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + typedef enum CallAudioRoute CallAudioRoute; + + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus + +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + typedef enum CameraLocation CameraLocation; + + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus + +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + typedef enum MediaOperations MediaOperations; + + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus + +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + typedef struct EndpointStruct EndpointStruct; + + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus + +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + typedef struct ProxyStruct ProxyStruct; + + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus + +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + typedef struct Config Config; + + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + + + + + + + + + + + + + + + + +#ifdef __cplusplus +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + /* [v1_enum] */ + enum ProxyProtocol + { + ProxyProtocol_None = 0, + ProxyProtocol_SOCKS5 = 1 + } ; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + /* [v1_enum] */ + enum CallState + { + CallState_WaitInit = 1, + CallState_WaitInitAck = 2, + CallState_Established = 3, + CallState_Failed = 4 + } ; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + /* [v1_enum] */ + enum Error + { + Error_Unknown = 0, + Error_Incompatible = 1, + Error_Timeout = 2, + Error_AudioIO = 3 + } ; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + /* [v1_enum] */ + enum NetworkType + { + NetworkType_Unknown = 0, + NetworkType_GPRS = 1, + NetworkType_EDGE = 2, + NetworkType_UMTS = 3, + NetworkType_HSPA = 4, + NetworkType_LTE = 5, + NetworkType_WiFi = 6, + NetworkType_Ethernet = 7, + NetworkType_OtherHighSpeed = 8, + NetworkType_OtherLowSpeed = 9, + NetworkType_Dialup = 10, + NetworkType_OtherMobile = 11 + } ; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + /* [v1_enum] */ + enum DataSavingMode + { + DataSavingMode_Never = 0, + DataSavingMode_MobileOnly = 1, + DataSavingMode_Always = 2 + } ; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + /* [v1_enum] */ + enum CallStatus + { + CallStatus_None = 0, + CallStatus_InProgress = 1, + CallStatus_Held = 2 + } ; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + /* [v1_enum] */ + enum CallAudioRoute + { + CallAudioRoute_None = 0, + CallAudioRoute_Earpiece = 1, + CallAudioRoute_Speakerphone = 2, + CallAudioRoute_Bluetooth = 4 + } ; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + /* [v1_enum] */ + enum CameraLocation + { + CameraLocation_Front = 1, + CameraLocation_Back = 0 + } ; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + /* [v1_enum] */ + enum MediaOperations + { + MediaOperations_None = 0, + MediaOperations_VideoCapture = 1, + MediaOperations_VideoRender = 2, + MediaOperations_AudioCapture = 4, + MediaOperations_AudioRender = 8 + } ; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + struct EndpointStruct + { + INT64 id; + UINT16 port; + HSTRING ipv4; + HSTRING ipv6; + HSTRING peerTag; + } ; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + struct ProxyStruct + { + ProxyProtocol protocol; + HSTRING address; + UINT16 port; + HSTRING username; + HSTRING password; + } ; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + struct Config + { + DOUBLE InitTimeout; + DOUBLE RecvTimeout; + DataSavingMode DataSavingMode; + boolean EnableAEC; + boolean EnableNS; + boolean EnableAGC; + HSTRING LogFilePath; + HSTRING StatsDumpFilePath; + } ; + } /* end namespace */ + } /* end namespace */ +} /* end namespace */ + +extern "C" { +#endif + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0000_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::IMessageReceivedEventHandler */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("F2035E6A-8067-3ABB-A795-7B334C67A2ED") + IMessageReceivedEventHandler : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Invoke( + /* [in] */ ABI::Windows::Storage::Streams::IBuffer *pBuffer, + /* [in] */ UINT64 hnsPresentationTime, + /* [in] */ UINT64 hnsSampleDuration) = 0; + + }; + + extern const __declspec(selectany) IID & IID_IMessageReceivedEventHandler = __uuidof(IMessageReceivedEventHandler); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandlerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler * This); + + HRESULT ( STDMETHODCALLTYPE *Invoke )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler * This, + /* [in] */ __x_ABI_CWindows_CStorage_CStreams_CIBuffer *pBuffer, + /* [in] */ UINT64 hnsPresentationTime, + /* [in] */ UINT64 hnsSampleDuration); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandlerVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandlerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_Invoke(This,pBuffer,hnsPresentationTime,hnsSampleDuration) \ + ( (This)->lpVtbl -> Invoke(This,pBuffer,hnsPresentationTime,hnsSampleDuration) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_INTERFACE_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::ICameraLocationChangedEventHandler */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("1698B961-F90E-30D0-80FF-22E94CF66D7B") + ICameraLocationChangedEventHandler : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Invoke( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::CameraLocation __param0) = 0; + + }; + + extern const __declspec(selectany) IID & IID_ICameraLocationChangedEventHandler = __uuidof(ICameraLocationChangedEventHandler); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandlerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler * This); + + HRESULT ( STDMETHODCALLTYPE *Invoke )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CCameraLocation __param0); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandlerVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandlerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_Invoke(This,__param0) \ + ( (This)->lpVtbl -> Invoke(This,__param0) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_INTERFACE_DEFINED__ */ + + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::IIncomingCallDialogDismissedCallback */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("91DDEE70-AA90-38E7-B4E5-F7959569CB5C") + IIncomingCallDialogDismissedCallback : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Invoke( + /* [in] */ INT64 callId, + /* [in] */ INT64 callAccessHash, + /* [in] */ boolean rejected) = 0; + + }; + + extern const __declspec(selectany) IID & IID_IIncomingCallDialogDismissedCallback = __uuidof(IIncomingCallDialogDismissedCallback); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallbackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback * This); + + HRESULT ( STDMETHODCALLTYPE *Invoke )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback * This, + /* [in] */ INT64 callId, + /* [in] */ INT64 callAccessHash, + /* [in] */ boolean rejected); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallbackVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallbackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_Invoke(This,callId,callAccessHash,rejected) \ + ( (This)->lpVtbl -> Invoke(This,callId,callAccessHash,rejected) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0003 */ +/* [local] */ + +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd___IBackEndTransportPublicNonVirtuals[] = L"PhoneVoIPApp.BackEnd.__IBackEndTransportPublicNonVirtuals"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0003 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0003_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0003_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::__IBackEndTransportPublicNonVirtuals */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("F5A3C2AE-EF7B-3DE2-8B0E-8E8B3CD20D9D") + __IBackEndTransportPublicNonVirtuals : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE WriteAudio( + /* [out] */ BYTE *bytes, + /* [in] */ INT32 byteCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteVideo( + /* [out] */ BYTE *bytes, + /* [in] */ INT32 byteCount, + /* [in] */ UINT64 hnsPresentationTime, + /* [in] */ UINT64 hnsSampleDuration) = 0; + + virtual HRESULT STDMETHODCALLTYPE add_AudioMessageReceived( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::IMessageReceivedEventHandler *__param0, + /* [out][retval] */ EventRegistrationToken *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE remove_AudioMessageReceived( + /* [in] */ EventRegistrationToken __param0) = 0; + + virtual HRESULT STDMETHODCALLTYPE add_VideoMessageReceived( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::IMessageReceivedEventHandler *__param0, + /* [out][retval] */ EventRegistrationToken *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE remove_VideoMessageReceived( + /* [in] */ EventRegistrationToken __param0) = 0; + + }; + + extern const __declspec(selectany) IID & IID___IBackEndTransportPublicNonVirtuals = __uuidof(__IBackEndTransportPublicNonVirtuals); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtualsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals * This, + /* [out] */ TrustLevel *trustLevel); + + HRESULT ( STDMETHODCALLTYPE *WriteAudio )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals * This, + /* [out] */ BYTE *bytes, + /* [in] */ INT32 byteCount); + + HRESULT ( STDMETHODCALLTYPE *WriteVideo )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals * This, + /* [out] */ BYTE *bytes, + /* [in] */ INT32 byteCount, + /* [in] */ UINT64 hnsPresentationTime, + /* [in] */ UINT64 hnsSampleDuration); + + HRESULT ( STDMETHODCALLTYPE *add_AudioMessageReceived )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler *__param0, + /* [out][retval] */ EventRegistrationToken *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *remove_AudioMessageReceived )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals * This, + /* [in] */ EventRegistrationToken __param0); + + HRESULT ( STDMETHODCALLTYPE *add_VideoMessageReceived )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler *__param0, + /* [out][retval] */ EventRegistrationToken *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *remove_VideoMessageReceived )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals * This, + /* [in] */ EventRegistrationToken __param0); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtualsVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtualsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_WriteAudio(This,bytes,byteCount) \ + ( (This)->lpVtbl -> WriteAudio(This,bytes,byteCount) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_WriteVideo(This,bytes,byteCount,hnsPresentationTime,hnsSampleDuration) \ + ( (This)->lpVtbl -> WriteVideo(This,bytes,byteCount,hnsPresentationTime,hnsSampleDuration) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_add_AudioMessageReceived(This,__param0,__returnValue) \ + ( (This)->lpVtbl -> add_AudioMessageReceived(This,__param0,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_remove_AudioMessageReceived(This,__param0) \ + ( (This)->lpVtbl -> remove_AudioMessageReceived(This,__param0) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_add_VideoMessageReceived(This,__param0,__returnValue) \ + ( (This)->lpVtbl -> add_VideoMessageReceived(This,__param0,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_remove_VideoMessageReceived(This,__param0) \ + ( (This)->lpVtbl -> remove_VideoMessageReceived(This,__param0) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0004 */ +/* [local] */ + +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd___IBackEndTransportProtectedNonVirtuals[] = L"PhoneVoIPApp.BackEnd.__IBackEndTransportProtectedNonVirtuals"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0004 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0004_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0004_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::__IBackEndTransportProtectedNonVirtuals */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("044DEA28-0E8D-3A16-A2C1-BE95C0BED5E5") + __IBackEndTransportProtectedNonVirtuals : public IInspectable + { + public: + }; + + extern const __declspec(selectany) IID & IID___IBackEndTransportProtectedNonVirtuals = __uuidof(__IBackEndTransportProtectedNonVirtuals); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtualsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals * This, + /* [out] */ TrustLevel *trustLevel); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtualsVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtualsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0005 */ +/* [local] */ + +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd___IEndpointPublicNonVirtuals[] = L"PhoneVoIPApp.BackEnd.__IEndpointPublicNonVirtuals"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0005 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0005_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0005_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::__IEndpointPublicNonVirtuals */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("0CC88A54-89AF-3CC6-9B95-F8F22428ABED") + __IEndpointPublicNonVirtuals : public IInspectable + { + public: + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_id( + /* [out][retval] */ INT64 *__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_id( + /* [in] */ INT64 __set_formal) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_port( + /* [out][retval] */ UINT16 *__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_port( + /* [in] */ UINT16 __set_formal) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ipv4( + /* [out][retval] */ HSTRING *__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_ipv4( + /* [in] */ HSTRING __set_formal) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ipv6( + /* [out][retval] */ HSTRING *__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_ipv6( + /* [in] */ HSTRING __set_formal) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_peerTag( + /* [out] */ UINT32 *____returnValueSize, + /* [out][retval][size_is][size_is] */ BYTE **__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_peerTag( + /* [in] */ UINT32 ____set_formalSize, + /* [in][size_is] */ BYTE *__set_formal) = 0; + + }; + + extern const __declspec(selectany) IID & IID___IEndpointPublicNonVirtuals = __uuidof(__IEndpointPublicNonVirtuals); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtualsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [out] */ TrustLevel *trustLevel); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_id )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [out][retval] */ INT64 *__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_id )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [in] */ INT64 __set_formal); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_port )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [out][retval] */ UINT16 *__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_port )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [in] */ UINT16 __set_formal); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ipv4 )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [out][retval] */ HSTRING *__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_ipv4 )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [in] */ HSTRING __set_formal); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ipv6 )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [out][retval] */ HSTRING *__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_ipv6 )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [in] */ HSTRING __set_formal); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_peerTag )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [out] */ UINT32 *____returnValueSize, + /* [out][retval][size_is][size_is] */ BYTE **__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_peerTag )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals * This, + /* [in] */ UINT32 ____set_formalSize, + /* [in][size_is] */ BYTE *__set_formal); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtualsVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtualsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_get_id(This,__returnValue) \ + ( (This)->lpVtbl -> get_id(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_put_id(This,__set_formal) \ + ( (This)->lpVtbl -> put_id(This,__set_formal) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_get_port(This,__returnValue) \ + ( (This)->lpVtbl -> get_port(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_put_port(This,__set_formal) \ + ( (This)->lpVtbl -> put_port(This,__set_formal) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_get_ipv4(This,__returnValue) \ + ( (This)->lpVtbl -> get_ipv4(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_put_ipv4(This,__set_formal) \ + ( (This)->lpVtbl -> put_ipv4(This,__set_formal) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_get_ipv6(This,__returnValue) \ + ( (This)->lpVtbl -> get_ipv6(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_put_ipv6(This,__set_formal) \ + ( (This)->lpVtbl -> put_ipv6(This,__set_formal) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_get_peerTag(This,____returnValueSize,__returnValue) \ + ( (This)->lpVtbl -> get_peerTag(This,____returnValueSize,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_put_peerTag(This,____set_formalSize,__set_formal) \ + ( (This)->lpVtbl -> put_peerTag(This,____set_formalSize,__set_formal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0006 */ +/* [local] */ + +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd_ICallControllerStatusListener[] = L"PhoneVoIPApp.BackEnd.ICallControllerStatusListener"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0006 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0006_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0006_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::ICallControllerStatusListener */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("39126060-0292-36D6-B3F8-9AC4156C651D") + ICallControllerStatusListener : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE OnSignalBarsChanged( + /* [in] */ INT32 newSignal) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnCallStateChanged( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::CallState newState) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnCallStatusChanged( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::CallStatus newStatus) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnCallAudioRouteChanged( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::CallAudioRoute newRoute) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnMediaOperationsChanged( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::MediaOperations newOperations) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnCameraLocationChanged( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::CameraLocation newCameraLocation) = 0; + + }; + + extern const __declspec(selectany) IID & IID_ICallControllerStatusListener = __uuidof(ICallControllerStatusListener); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListenerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener * This, + /* [out] */ TrustLevel *trustLevel); + + HRESULT ( STDMETHODCALLTYPE *OnSignalBarsChanged )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener * This, + /* [in] */ INT32 newSignal); + + HRESULT ( STDMETHODCALLTYPE *OnCallStateChanged )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CCallState newState); + + HRESULT ( STDMETHODCALLTYPE *OnCallStatusChanged )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CCallStatus newStatus); + + HRESULT ( STDMETHODCALLTYPE *OnCallAudioRouteChanged )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CCallAudioRoute newRoute); + + HRESULT ( STDMETHODCALLTYPE *OnMediaOperationsChanged )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CMediaOperations newOperations); + + HRESULT ( STDMETHODCALLTYPE *OnCameraLocationChanged )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CCameraLocation newCameraLocation); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListenerVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListenerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_OnSignalBarsChanged(This,newSignal) \ + ( (This)->lpVtbl -> OnSignalBarsChanged(This,newSignal) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_OnCallStateChanged(This,newState) \ + ( (This)->lpVtbl -> OnCallStateChanged(This,newState) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_OnCallStatusChanged(This,newStatus) \ + ( (This)->lpVtbl -> OnCallStatusChanged(This,newStatus) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_OnCallAudioRouteChanged(This,newRoute) \ + ( (This)->lpVtbl -> OnCallAudioRouteChanged(This,newRoute) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_OnMediaOperationsChanged(This,newOperations) \ + ( (This)->lpVtbl -> OnMediaOperationsChanged(This,newOperations) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_OnCameraLocationChanged(This,newCameraLocation) \ + ( (This)->lpVtbl -> OnCameraLocationChanged(This,newCameraLocation) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0007 */ +/* [local] */ + +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd___IBackEndCapturePublicNonVirtuals[] = L"PhoneVoIPApp.BackEnd.__IBackEndCapturePublicNonVirtuals"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0007 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0007_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0007_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::__IBackEndCapturePublicNonVirtuals */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("8313DBEA-FD3B-3071-8035-7B611658DAD8") + __IBackEndCapturePublicNonVirtuals : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE SetTransport( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::__IBackEndTransportPublicNonVirtuals *transport) = 0; + + virtual HRESULT STDMETHODCALLTYPE Start( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::CameraLocation cameraLocation) = 0; + + virtual HRESULT STDMETHODCALLTYPE Stop( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ToggleCamera( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE add_CameraLocationChanged( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::ICameraLocationChangedEventHandler *__param0, + /* [out][retval] */ EventRegistrationToken *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE remove_CameraLocationChanged( + /* [in] */ EventRegistrationToken __param0) = 0; + + }; + + extern const __declspec(selectany) IID & IID___IBackEndCapturePublicNonVirtuals = __uuidof(__IBackEndCapturePublicNonVirtuals); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtualsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals * This, + /* [out] */ TrustLevel *trustLevel); + + HRESULT ( STDMETHODCALLTYPE *SetTransport )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals *transport); + + HRESULT ( STDMETHODCALLTYPE *Start )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CCameraLocation cameraLocation); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *ToggleCamera )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *add_CameraLocationChanged )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler *__param0, + /* [out][retval] */ EventRegistrationToken *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *remove_CameraLocationChanged )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals * This, + /* [in] */ EventRegistrationToken __param0); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtualsVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtualsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_SetTransport(This,transport) \ + ( (This)->lpVtbl -> SetTransport(This,transport) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_Start(This,cameraLocation) \ + ( (This)->lpVtbl -> Start(This,cameraLocation) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_Stop(This) \ + ( (This)->lpVtbl -> Stop(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_ToggleCamera(This) \ + ( (This)->lpVtbl -> ToggleCamera(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_add_CameraLocationChanged(This,__param0,__returnValue) \ + ( (This)->lpVtbl -> add_CameraLocationChanged(This,__param0,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_remove_CameraLocationChanged(This,__param0) \ + ( (This)->lpVtbl -> remove_CameraLocationChanged(This,__param0) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0008 */ +/* [local] */ + +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd___IBackEndCaptureProtectedNonVirtuals[] = L"PhoneVoIPApp.BackEnd.__IBackEndCaptureProtectedNonVirtuals"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0008 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0008_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0008_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::__IBackEndCaptureProtectedNonVirtuals */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("64B31D5B-1A27-37A8-BCBC-C0BBD5314C79") + __IBackEndCaptureProtectedNonVirtuals : public IInspectable + { + public: + }; + + extern const __declspec(selectany) IID & IID___IBackEndCaptureProtectedNonVirtuals = __uuidof(__IBackEndCaptureProtectedNonVirtuals); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtualsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals * This, + /* [out] */ TrustLevel *trustLevel); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtualsVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtualsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0009 */ +/* [local] */ + +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd_IConfig[] = L"PhoneVoIPApp.BackEnd.IConfig"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0009 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0009_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0009_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::IConfig */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("A9F22E31-D4E1-3940-BA20-DCB20973B09F") + IConfig : public IInspectable + { + public: + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_InitTimeout( + /* [out][retval] */ DOUBLE *__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_InitTimeout( + /* [in] */ DOUBLE __set_formal) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_RecvTimeout( + /* [out][retval] */ DOUBLE *__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_RecvTimeout( + /* [in] */ DOUBLE __set_formal) = 0; + + }; + + extern const __declspec(selectany) IID & IID_IConfig = __uuidof(IConfig); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfigVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig * This, + /* [out] */ TrustLevel *trustLevel); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_InitTimeout )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig * This, + /* [out][retval] */ DOUBLE *__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_InitTimeout )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig * This, + /* [in] */ DOUBLE __set_formal); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_RecvTimeout )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig * This, + /* [out][retval] */ DOUBLE *__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_RecvTimeout )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig * This, + /* [in] */ DOUBLE __set_formal); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfigVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfigVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_get_InitTimeout(This,__returnValue) \ + ( (This)->lpVtbl -> get_InitTimeout(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_put_InitTimeout(This,__set_formal) \ + ( (This)->lpVtbl -> put_InitTimeout(This,__set_formal) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_get_RecvTimeout(This,__returnValue) \ + ( (This)->lpVtbl -> get_RecvTimeout(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_put_RecvTimeout(This,__set_formal) \ + ( (This)->lpVtbl -> put_RecvTimeout(This,__set_formal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0010 */ +/* [local] */ + +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd___ICallControllerPublicNonVirtuals[] = L"PhoneVoIPApp.BackEnd.__ICallControllerPublicNonVirtuals"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0010 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0010_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0010_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::__ICallControllerPublicNonVirtuals */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("06B50718-3528-3B66-BE76-E183AA80D4A5") + __ICallControllerPublicNonVirtuals : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE HandleUpdatePhoneCall( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartMTProtoUpdater( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE StopMTProtoUpdater( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateVoIPControllerWrapper( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE DeleteVoIPControllerWrapper( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetConfig( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::Config config) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetEncryptionKey( + /* [in] */ UINT32 __keySize, + /* [in][size_is] */ BYTE *key, + /* [in] */ boolean isOutgoing) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetPublicEndpoints( + /* [in] */ UINT32 __endpointsSize, + /* [in][size_is] */ ABI::PhoneVoIPApp::BackEnd::EndpointStruct *endpoints, + /* [in] */ boolean allowP2P, + /* [in] */ INT32 connectionMaxLayer) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetProxy( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::ProxyStruct proxy) = 0; + + virtual HRESULT STDMETHODCALLTYPE Start( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Connect( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetMicMute( + /* [in] */ boolean mute) = 0; + + virtual HRESULT STDMETHODCALLTYPE SwitchSpeaker( + /* [in] */ boolean external) = 0; + + virtual HRESULT STDMETHODCALLTYPE UpdateServerConfig( + /* [in] */ HSTRING json) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetPreferredRelayID( + /* [out][retval] */ INT64 *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLastError( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::Error *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDebugLog( + /* [out][retval] */ HSTRING *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDebugString( + /* [out][retval] */ HSTRING *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVersion( + /* [out][retval] */ HSTRING *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSignalBarsCount( + /* [out][retval] */ INT32 *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetStatusCallback( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::ICallControllerStatusListener *statusListener) = 0; + + virtual HRESULT STDMETHODCALLTYPE InitiateOutgoingCall2( + /* [in] */ HSTRING recepientName, + /* [in] */ INT64 recepientId, + /* [in] */ INT64 callId, + /* [in] */ INT64 callAccessHash, + /* [out][retval] */ boolean *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE InitiateOutgoingCall1( + /* [in] */ HSTRING recepientName, + /* [in] */ INT64 recepientId, + /* [in] */ INT64 callId, + /* [in] */ INT64 callAccessHash, + /* [in] */ ABI::PhoneVoIPApp::BackEnd::Config config, + /* [in] */ UINT32 __keySize, + /* [in][size_is] */ BYTE *key, + /* [in] */ boolean outgoing, + /* [in] */ UINT32 __emojisSize, + /* [in][size_is] */ HSTRING *emojis, + /* [in] */ UINT32 __endpointsSize, + /* [in][size_is] */ ABI::PhoneVoIPApp::BackEnd::EndpointStruct *endpoints, + /* [in] */ boolean allowP2P, + /* [in] */ INT32 connectionMaxLayer, + /* [in] */ ABI::PhoneVoIPApp::BackEnd::ProxyStruct proxy, + /* [out][retval] */ boolean *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnIncomingCallReceived( + /* [in] */ HSTRING contactName, + /* [in] */ INT64 contactId, + /* [in] */ HSTRING contactImage, + /* [in] */ INT64 callId, + /* [in] */ INT64 callAccessHash, + /* [in] */ ABI::PhoneVoIPApp::BackEnd::IIncomingCallDialogDismissedCallback *incomingCallDialogDismissedCallback, + /* [out][retval] */ boolean *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE HoldCall( + /* [out][retval] */ boolean *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE ResumeCall( + /* [out][retval] */ boolean *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndCall( + /* [out][retval] */ boolean *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE ToggleCamera( + /* [out][retval] */ boolean *__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CallStatus( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::CallStatus *__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_MediaOperations( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::MediaOperations *__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsShowingVideo( + /* [out][retval] */ boolean *__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_IsShowingVideo( + /* [in] */ boolean value) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsRenderingVideo( + /* [out][retval] */ boolean *__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_IsRenderingVideo( + /* [in] */ boolean value) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CameraLocation( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::CameraLocation *__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_AvailableAudioRoutes( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::CallAudioRoute *__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_AudioRoute( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::CallAudioRoute *__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_AudioRoute( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::CallAudioRoute newRoute) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_OtherPartyName( + /* [out][retval] */ HSTRING *__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_OtherPartyId( + /* [out][retval] */ INT64 *__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CallStartTime( + /* [out][retval] */ ABI::Windows::Foundation::DateTime *__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CallId( + /* [out][retval] */ INT64 *__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CallAccessHash( + /* [out][retval] */ INT64 *__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_AcceptedCallId( + /* [out][retval] */ INT64 *__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_AcceptedCallId( + /* [in] */ INT64 value) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Key( + /* [out] */ UINT32 *____returnValueSize, + /* [out][retval][size_is][size_is] */ BYTE **__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Outgoing( + /* [out][retval] */ boolean *__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Emojis( + /* [out] */ UINT32 *____returnValueSize, + /* [out][retval][size_is][size_is] */ HSTRING **__returnValue) = 0; + + }; + + extern const __declspec(selectany) IID & IID___ICallControllerPublicNonVirtuals = __uuidof(__ICallControllerPublicNonVirtuals); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtualsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out] */ TrustLevel *trustLevel); + + HRESULT ( STDMETHODCALLTYPE *HandleUpdatePhoneCall )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *StartMTProtoUpdater )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *StopMTProtoUpdater )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *CreateVoIPControllerWrapper )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *DeleteVoIPControllerWrapper )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *SetConfig )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CConfig config); + + HRESULT ( STDMETHODCALLTYPE *SetEncryptionKey )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ UINT32 __keySize, + /* [in][size_is] */ BYTE *key, + /* [in] */ boolean isOutgoing); + + HRESULT ( STDMETHODCALLTYPE *SetPublicEndpoints )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ UINT32 __endpointsSize, + /* [in][size_is] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CEndpointStruct *endpoints, + /* [in] */ boolean allowP2P, + /* [in] */ INT32 connectionMaxLayer); + + HRESULT ( STDMETHODCALLTYPE *SetProxy )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CProxyStruct proxy); + + HRESULT ( STDMETHODCALLTYPE *Start )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *Connect )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *SetMicMute )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ boolean mute); + + HRESULT ( STDMETHODCALLTYPE *SwitchSpeaker )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ boolean external); + + HRESULT ( STDMETHODCALLTYPE *UpdateServerConfig )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ HSTRING json); + + HRESULT ( STDMETHODCALLTYPE *GetPreferredRelayID )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ INT64 *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *GetLastError )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CError *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *GetDebugLog )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ HSTRING *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *GetDebugString )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ HSTRING *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *GetVersion )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ HSTRING *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *GetSignalBarsCount )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ INT32 *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *SetStatusCallback )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener *statusListener); + + HRESULT ( STDMETHODCALLTYPE *InitiateOutgoingCall2 )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ HSTRING recepientName, + /* [in] */ INT64 recepientId, + /* [in] */ INT64 callId, + /* [in] */ INT64 callAccessHash, + /* [out][retval] */ boolean *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *InitiateOutgoingCall1 )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ HSTRING recepientName, + /* [in] */ INT64 recepientId, + /* [in] */ INT64 callId, + /* [in] */ INT64 callAccessHash, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CConfig config, + /* [in] */ UINT32 __keySize, + /* [in][size_is] */ BYTE *key, + /* [in] */ boolean outgoing, + /* [in] */ UINT32 __emojisSize, + /* [in][size_is] */ HSTRING *emojis, + /* [in] */ UINT32 __endpointsSize, + /* [in][size_is] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CEndpointStruct *endpoints, + /* [in] */ boolean allowP2P, + /* [in] */ INT32 connectionMaxLayer, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CProxyStruct proxy, + /* [out][retval] */ boolean *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *OnIncomingCallReceived )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ HSTRING contactName, + /* [in] */ INT64 contactId, + /* [in] */ HSTRING contactImage, + /* [in] */ INT64 callId, + /* [in] */ INT64 callAccessHash, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback *incomingCallDialogDismissedCallback, + /* [out][retval] */ boolean *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *HoldCall )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ boolean *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *ResumeCall )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ boolean *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *EndCall )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ boolean *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *ToggleCamera )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ boolean *__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CallStatus )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CCallStatus *__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_MediaOperations )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CMediaOperations *__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsShowingVideo )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ boolean *__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsShowingVideo )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ boolean value); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_IsRenderingVideo )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ boolean *__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_IsRenderingVideo )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ boolean value); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CameraLocation )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CCameraLocation *__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AvailableAudioRoutes )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CCallAudioRoute *__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AudioRoute )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CCallAudioRoute *__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AudioRoute )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CCallAudioRoute newRoute); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_OtherPartyName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ HSTRING *__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_OtherPartyId )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ INT64 *__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CallStartTime )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CWindows_CFoundation_CDateTime *__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CallId )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ INT64 *__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CallAccessHash )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ INT64 *__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_AcceptedCallId )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ INT64 *__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_AcceptedCallId )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [in] */ INT64 value); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Key )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out] */ UINT32 *____returnValueSize, + /* [out][retval][size_is][size_is] */ BYTE **__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Outgoing )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out][retval] */ boolean *__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Emojis )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals * This, + /* [out] */ UINT32 *____returnValueSize, + /* [out][retval][size_is][size_is] */ HSTRING **__returnValue); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtualsVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtualsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_HandleUpdatePhoneCall(This) \ + ( (This)->lpVtbl -> HandleUpdatePhoneCall(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_StartMTProtoUpdater(This) \ + ( (This)->lpVtbl -> StartMTProtoUpdater(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_StopMTProtoUpdater(This) \ + ( (This)->lpVtbl -> StopMTProtoUpdater(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_CreateVoIPControllerWrapper(This) \ + ( (This)->lpVtbl -> CreateVoIPControllerWrapper(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_DeleteVoIPControllerWrapper(This) \ + ( (This)->lpVtbl -> DeleteVoIPControllerWrapper(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_SetConfig(This,config) \ + ( (This)->lpVtbl -> SetConfig(This,config) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_SetEncryptionKey(This,__keySize,key,isOutgoing) \ + ( (This)->lpVtbl -> SetEncryptionKey(This,__keySize,key,isOutgoing) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_SetPublicEndpoints(This,__endpointsSize,endpoints,allowP2P,connectionMaxLayer) \ + ( (This)->lpVtbl -> SetPublicEndpoints(This,__endpointsSize,endpoints,allowP2P,connectionMaxLayer) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_SetProxy(This,proxy) \ + ( (This)->lpVtbl -> SetProxy(This,proxy) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_Start(This) \ + ( (This)->lpVtbl -> Start(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_Connect(This) \ + ( (This)->lpVtbl -> Connect(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_SetMicMute(This,mute) \ + ( (This)->lpVtbl -> SetMicMute(This,mute) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_SwitchSpeaker(This,external) \ + ( (This)->lpVtbl -> SwitchSpeaker(This,external) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_UpdateServerConfig(This,json) \ + ( (This)->lpVtbl -> UpdateServerConfig(This,json) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_GetPreferredRelayID(This,__returnValue) \ + ( (This)->lpVtbl -> GetPreferredRelayID(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_GetLastError(This,__returnValue) \ + ( (This)->lpVtbl -> GetLastError(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_GetDebugLog(This,__returnValue) \ + ( (This)->lpVtbl -> GetDebugLog(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_GetDebugString(This,__returnValue) \ + ( (This)->lpVtbl -> GetDebugString(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_GetVersion(This,__returnValue) \ + ( (This)->lpVtbl -> GetVersion(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_GetSignalBarsCount(This,__returnValue) \ + ( (This)->lpVtbl -> GetSignalBarsCount(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_SetStatusCallback(This,statusListener) \ + ( (This)->lpVtbl -> SetStatusCallback(This,statusListener) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_InitiateOutgoingCall2(This,recepientName,recepientId,callId,callAccessHash,__returnValue) \ + ( (This)->lpVtbl -> InitiateOutgoingCall2(This,recepientName,recepientId,callId,callAccessHash,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_InitiateOutgoingCall1(This,recepientName,recepientId,callId,callAccessHash,config,__keySize,key,outgoing,__emojisSize,emojis,__endpointsSize,endpoints,allowP2P,connectionMaxLayer,proxy,__returnValue) \ + ( (This)->lpVtbl -> InitiateOutgoingCall1(This,recepientName,recepientId,callId,callAccessHash,config,__keySize,key,outgoing,__emojisSize,emojis,__endpointsSize,endpoints,allowP2P,connectionMaxLayer,proxy,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_OnIncomingCallReceived(This,contactName,contactId,contactImage,callId,callAccessHash,incomingCallDialogDismissedCallback,__returnValue) \ + ( (This)->lpVtbl -> OnIncomingCallReceived(This,contactName,contactId,contactImage,callId,callAccessHash,incomingCallDialogDismissedCallback,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_HoldCall(This,__returnValue) \ + ( (This)->lpVtbl -> HoldCall(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_ResumeCall(This,__returnValue) \ + ( (This)->lpVtbl -> ResumeCall(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_EndCall(This,__returnValue) \ + ( (This)->lpVtbl -> EndCall(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_ToggleCamera(This,__returnValue) \ + ( (This)->lpVtbl -> ToggleCamera(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_CallStatus(This,__returnValue) \ + ( (This)->lpVtbl -> get_CallStatus(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_MediaOperations(This,__returnValue) \ + ( (This)->lpVtbl -> get_MediaOperations(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_IsShowingVideo(This,__returnValue) \ + ( (This)->lpVtbl -> get_IsShowingVideo(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_put_IsShowingVideo(This,value) \ + ( (This)->lpVtbl -> put_IsShowingVideo(This,value) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_IsRenderingVideo(This,__returnValue) \ + ( (This)->lpVtbl -> get_IsRenderingVideo(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_put_IsRenderingVideo(This,value) \ + ( (This)->lpVtbl -> put_IsRenderingVideo(This,value) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_CameraLocation(This,__returnValue) \ + ( (This)->lpVtbl -> get_CameraLocation(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_AvailableAudioRoutes(This,__returnValue) \ + ( (This)->lpVtbl -> get_AvailableAudioRoutes(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_AudioRoute(This,__returnValue) \ + ( (This)->lpVtbl -> get_AudioRoute(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_put_AudioRoute(This,newRoute) \ + ( (This)->lpVtbl -> put_AudioRoute(This,newRoute) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_OtherPartyName(This,__returnValue) \ + ( (This)->lpVtbl -> get_OtherPartyName(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_OtherPartyId(This,__returnValue) \ + ( (This)->lpVtbl -> get_OtherPartyId(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_CallStartTime(This,__returnValue) \ + ( (This)->lpVtbl -> get_CallStartTime(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_CallId(This,__returnValue) \ + ( (This)->lpVtbl -> get_CallId(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_CallAccessHash(This,__returnValue) \ + ( (This)->lpVtbl -> get_CallAccessHash(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_AcceptedCallId(This,__returnValue) \ + ( (This)->lpVtbl -> get_AcceptedCallId(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_put_AcceptedCallId(This,value) \ + ( (This)->lpVtbl -> put_AcceptedCallId(This,value) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_Key(This,____returnValueSize,__returnValue) \ + ( (This)->lpVtbl -> get_Key(This,____returnValueSize,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_Outgoing(This,__returnValue) \ + ( (This)->lpVtbl -> get_Outgoing(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_get_Emojis(This,____returnValueSize,__returnValue) \ + ( (This)->lpVtbl -> get_Emojis(This,____returnValueSize,__returnValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0011 */ +/* [local] */ + +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd_IVideoRenderer[] = L"PhoneVoIPApp.BackEnd.IVideoRenderer"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0011 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0011_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0011_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::IVideoRenderer */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("6928CA7B-166D-3B37-9010-FBAB2C7E92B0") + IVideoRenderer : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE Start( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Stop( void) = 0; + + }; + + extern const __declspec(selectany) IID & IID_IVideoRenderer = __uuidof(IVideoRenderer); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRendererVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer * This, + /* [out] */ TrustLevel *trustLevel); + + HRESULT ( STDMETHODCALLTYPE *Start )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer * This); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer * This); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRendererVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRendererVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_Start(This) \ + ( (This)->lpVtbl -> Start(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_Stop(This) \ + ( (This)->lpVtbl -> Stop(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0012 */ +/* [local] */ + +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd_IMTProtoUpdater[] = L"PhoneVoIPApp.BackEnd.IMTProtoUpdater"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0012 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0012_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0012_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::IMTProtoUpdater */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("4FA5F2C4-8612-35C9-BFAA-967C2C819FA7") + IMTProtoUpdater : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE Start( + /* [in] */ INT32 pts, + /* [in] */ INT32 date, + /* [in] */ INT32 qts) = 0; + + virtual HRESULT STDMETHODCALLTYPE Stop( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE DiscardCall( + /* [in] */ INT64 id, + /* [in] */ INT64 accessHash) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReceivedCall( + /* [in] */ INT64 id, + /* [in] */ INT64 accessHash) = 0; + + }; + + extern const __declspec(selectany) IID & IID_IMTProtoUpdater = __uuidof(IMTProtoUpdater); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdaterVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater * This, + /* [out] */ TrustLevel *trustLevel); + + HRESULT ( STDMETHODCALLTYPE *Start )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater * This, + /* [in] */ INT32 pts, + /* [in] */ INT32 date, + /* [in] */ INT32 qts); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater * This); + + HRESULT ( STDMETHODCALLTYPE *DiscardCall )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater * This, + /* [in] */ INT64 id, + /* [in] */ INT64 accessHash); + + HRESULT ( STDMETHODCALLTYPE *ReceivedCall )( + __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater * This, + /* [in] */ INT64 id, + /* [in] */ INT64 accessHash); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdaterVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdaterVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_Start(This,pts,date,qts) \ + ( (This)->lpVtbl -> Start(This,pts,date,qts) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_Stop(This) \ + ( (This)->lpVtbl -> Stop(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_DiscardCall(This,id,accessHash) \ + ( (This)->lpVtbl -> DiscardCall(This,id,accessHash) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_ReceivedCall(This,id,accessHash) \ + ( (This)->lpVtbl -> ReceivedCall(This,id,accessHash) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0013 */ +/* [local] */ + +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd___IGlobalsPublicNonVirtuals[] = L"PhoneVoIPApp.BackEnd.__IGlobalsPublicNonVirtuals"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0013 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0013_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0013_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::__IGlobalsPublicNonVirtuals */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("C8AFE1A8-92FC-3783-9520-D6BBC507B24A") + __IGlobalsPublicNonVirtuals : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE StartServer( + /* [in] */ UINT32 __outOfProcServerClassNamesSize, + /* [in][size_is] */ HSTRING *outOfProcServerClassNames) = 0; + + virtual HRESULT STDMETHODCALLTYPE DoPeriodicKeepAlive( void) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CallController( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::__ICallControllerPublicNonVirtuals **__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_VideoRenderer( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::IVideoRenderer **__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_VideoRenderer( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::IVideoRenderer *value) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_MTProtoUpdater( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::IMTProtoUpdater **__returnValue) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_MTProtoUpdater( + /* [in] */ ABI::PhoneVoIPApp::BackEnd::IMTProtoUpdater *value) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CaptureController( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::__IBackEndCapturePublicNonVirtuals **__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_TransportController( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::__IBackEndTransportPublicNonVirtuals **__returnValue) = 0; + + }; + + extern const __declspec(selectany) IID & IID___IGlobalsPublicNonVirtuals = __uuidof(__IGlobalsPublicNonVirtuals); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtualsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This, + /* [out] */ TrustLevel *trustLevel); + + HRESULT ( STDMETHODCALLTYPE *StartServer )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This, + /* [in] */ UINT32 __outOfProcServerClassNamesSize, + /* [in][size_is] */ HSTRING *outOfProcServerClassNames); + + HRESULT ( STDMETHODCALLTYPE *DoPeriodicKeepAlive )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CallController )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals **__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_VideoRenderer )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer **__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_VideoRenderer )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer *value); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_MTProtoUpdater )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater **__returnValue); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_MTProtoUpdater )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This, + /* [in] */ __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater *value); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CaptureController )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals **__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_TransportController )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals **__returnValue); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtualsVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtualsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_StartServer(This,__outOfProcServerClassNamesSize,outOfProcServerClassNames) \ + ( (This)->lpVtbl -> StartServer(This,__outOfProcServerClassNamesSize,outOfProcServerClassNames) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_DoPeriodicKeepAlive(This) \ + ( (This)->lpVtbl -> DoPeriodicKeepAlive(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_get_CallController(This,__returnValue) \ + ( (This)->lpVtbl -> get_CallController(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_get_VideoRenderer(This,__returnValue) \ + ( (This)->lpVtbl -> get_VideoRenderer(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_put_VideoRenderer(This,value) \ + ( (This)->lpVtbl -> put_VideoRenderer(This,value) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_get_MTProtoUpdater(This,__returnValue) \ + ( (This)->lpVtbl -> get_MTProtoUpdater(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_put_MTProtoUpdater(This,value) \ + ( (This)->lpVtbl -> put_MTProtoUpdater(This,value) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_get_CaptureController(This,__returnValue) \ + ( (This)->lpVtbl -> get_CaptureController(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_get_TransportController(This,__returnValue) \ + ( (This)->lpVtbl -> get_TransportController(This,__returnValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0014 */ +/* [local] */ + +#if !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_INTERFACE_DEFINED__) +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_PhoneVoIPApp_BackEnd___IGlobalsStatics[] = L"PhoneVoIPApp.BackEnd.__IGlobalsStatics"; +#endif /* !defined(____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_INTERFACE_DEFINED__) */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0014 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0014_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0014_v0_0_s_ifspec; + +#ifndef ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_INTERFACE_DEFINED__ +#define ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_INTERFACE_DEFINED__ + +/* interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics */ +/* [uuid][object] */ + + + +/* interface ABI::PhoneVoIPApp::BackEnd::__IGlobalsStatics */ +/* [uuid][object] */ + + +EXTERN_C const IID IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics; + +#if defined(__cplusplus) && !defined(CINTERFACE) + } /* end extern "C" */ + namespace ABI { + namespace PhoneVoIPApp { + namespace BackEnd { + + MIDL_INTERFACE("2C1E9C37-6827-38F7-857C-021642CA428B") + __IGlobalsStatics : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCurrentProcessId( + /* [out][retval] */ UINT32 *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetUiDisconnectedEventName( + /* [in] */ UINT32 backgroundProcessId, + /* [out][retval] */ HSTRING *__returnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBackgroundProcessReadyEventName( + /* [in] */ UINT32 backgroundProcessId, + /* [out][retval] */ HSTRING *__returnValue) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Instance( + /* [out][retval] */ ABI::PhoneVoIPApp::BackEnd::__IGlobalsPublicNonVirtuals **__returnValue) = 0; + + }; + + extern const __declspec(selectany) IID & IID___IGlobalsStatics = __uuidof(__IGlobalsStatics); + + + } /* end namespace */ + } /* end namespace */ + } /* end namespace */ + extern "C" { + +#else /* C style interface */ + + typedef struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStaticsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics * This); + + HRESULT ( STDMETHODCALLTYPE *GetIids )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics * This, + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeClassName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics * This, + /* [out] */ HSTRING *className); + + HRESULT ( STDMETHODCALLTYPE *GetTrustLevel )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics * This, + /* [out] */ TrustLevel *trustLevel); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentProcessId )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics * This, + /* [out][retval] */ UINT32 *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *GetUiDisconnectedEventName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics * This, + /* [in] */ UINT32 backgroundProcessId, + /* [out][retval] */ HSTRING *__returnValue); + + HRESULT ( STDMETHODCALLTYPE *GetBackgroundProcessReadyEventName )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics * This, + /* [in] */ UINT32 backgroundProcessId, + /* [out][retval] */ HSTRING *__returnValue); + + /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Instance )( + __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics * This, + /* [out][retval] */ __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals **__returnValue); + + END_INTERFACE + } __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStaticsVtbl; + + interface __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics + { + CONST_VTBL struct __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStaticsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_GetIids(This,iidCount,iids) \ + ( (This)->lpVtbl -> GetIids(This,iidCount,iids) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_GetRuntimeClassName(This,className) \ + ( (This)->lpVtbl -> GetRuntimeClassName(This,className) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_GetTrustLevel(This,trustLevel) \ + ( (This)->lpVtbl -> GetTrustLevel(This,trustLevel) ) + + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_GetCurrentProcessId(This,__returnValue) \ + ( (This)->lpVtbl -> GetCurrentProcessId(This,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_GetUiDisconnectedEventName(This,backgroundProcessId,__returnValue) \ + ( (This)->lpVtbl -> GetUiDisconnectedEventName(This,backgroundProcessId,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_GetBackgroundProcessReadyEventName(This,backgroundProcessId,__returnValue) \ + ( (This)->lpVtbl -> GetBackgroundProcessReadyEventName(This,backgroundProcessId,__returnValue) ) + +#define __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_get_Instance(This,__returnValue) \ + ( (This)->lpVtbl -> get_Instance(This,__returnValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* ____x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0015 */ +/* [local] */ + +#ifndef RUNTIMECLASS_PhoneVoIPApp_BackEnd_BackEndTransport_DEFINED +#define RUNTIMECLASS_PhoneVoIPApp_BackEnd_BackEndTransport_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_PhoneVoIPApp_BackEnd_BackEndTransport[] = L"PhoneVoIPApp.BackEnd.BackEndTransport"; +#endif +#ifndef RUNTIMECLASS_PhoneVoIPApp_BackEnd_Endpoint_DEFINED +#define RUNTIMECLASS_PhoneVoIPApp_BackEnd_Endpoint_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_PhoneVoIPApp_BackEnd_Endpoint[] = L"PhoneVoIPApp.BackEnd.Endpoint"; +#endif +#ifndef RUNTIMECLASS_PhoneVoIPApp_BackEnd_BackEndCapture_DEFINED +#define RUNTIMECLASS_PhoneVoIPApp_BackEnd_BackEndCapture_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_PhoneVoIPApp_BackEnd_BackEndCapture[] = L"PhoneVoIPApp.BackEnd.BackEndCapture"; +#endif +#ifndef RUNTIMECLASS_PhoneVoIPApp_BackEnd_CallController_DEFINED +#define RUNTIMECLASS_PhoneVoIPApp_BackEnd_CallController_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_PhoneVoIPApp_BackEnd_CallController[] = L"PhoneVoIPApp.BackEnd.CallController"; +#endif +#ifndef RUNTIMECLASS_PhoneVoIPApp_BackEnd_Globals_DEFINED +#define RUNTIMECLASS_PhoneVoIPApp_BackEnd_Globals_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_PhoneVoIPApp_BackEnd_Globals[] = L"PhoneVoIPApp.BackEnd.Globals"; +#endif + + +/* interface __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0015 */ +/* [local] */ + + + +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0015_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0015_v0_0_s_ifspec; + +/* Additional Prototypes for ALL interfaces */ + +unsigned long __RPC_USER HSTRING_UserSize( unsigned long *, unsigned long , HSTRING * ); +unsigned char * __RPC_USER HSTRING_UserMarshal( unsigned long *, unsigned char *, HSTRING * ); +unsigned char * __RPC_USER HSTRING_UserUnmarshal(unsigned long *, unsigned char *, HSTRING * ); +void __RPC_USER HSTRING_UserFree( unsigned long *, HSTRING * ); + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/BackEndProxyStub/PhoneVoIPApp.BackEnd_i.c b/BackEndProxyStub/PhoneVoIPApp.BackEnd_i.c new file mode 100755 index 0000000..315cace --- /dev/null +++ b/BackEndProxyStub/PhoneVoIPApp.BackEnd_i.c @@ -0,0 +1,121 @@ + + +/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ + +/* link this file in with the server and any clients */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* at Tue Jan 29 08:48:50 2019 + */ +/* Compiler settings for C:\Users\evgeny\AppData\Local\Temp\PhoneVoIPApp.BackEnd.idl-35395493: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=ARM 8.00.0603 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +#include +#include + +#ifdef _MIDL_USE_GUIDDEF_ + +#ifndef INITGUID +#define INITGUID +#include +#undef INITGUID +#else +#include +#endif + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) + +#else // !_MIDL_USE_GUIDDEF_ + +#ifndef __IID_DEFINED__ +#define __IID_DEFINED__ + +typedef struct _IID +{ + unsigned long x; + unsigned short s1; + unsigned short s2; + unsigned char c[8]; +} IID; + +#endif // __IID_DEFINED__ + +#ifndef CLSID_DEFINED +#define CLSID_DEFINED +typedef IID CLSID; +#endif // CLSID_DEFINED + +#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} + +#endif !_MIDL_USE_GUIDDEF_ + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler,0xF2035E6A,0x8067,0x3ABB,0xA7,0x95,0x7B,0x33,0x4C,0x67,0xA2,0xED); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler,0x1698B961,0xF90E,0x30D0,0x80,0xFF,0x22,0xE9,0x4C,0xF6,0x6D,0x7B); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback,0x91DDEE70,0xAA90,0x38E7,0xB4,0xE5,0xF7,0x95,0x95,0x69,0xCB,0x5C); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals,0xF5A3C2AE,0xEF7B,0x3DE2,0x8B,0x0E,0x8E,0x8B,0x3C,0xD2,0x0D,0x9D); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals,0x044DEA28,0x0E8D,0x3A16,0xA2,0xC1,0xBE,0x95,0xC0,0xBE,0xD5,0xE5); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals,0x0CC88A54,0x89AF,0x3CC6,0x9B,0x95,0xF8,0xF2,0x24,0x28,0xAB,0xED); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener,0x39126060,0x0292,0x36D6,0xB3,0xF8,0x9A,0xC4,0x15,0x6C,0x65,0x1D); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals,0x8313DBEA,0xFD3B,0x3071,0x80,0x35,0x7B,0x61,0x16,0x58,0xDA,0xD8); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals,0x64B31D5B,0x1A27,0x37A8,0xBC,0xBC,0xC0,0xBB,0xD5,0x31,0x4C,0x79); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig,0xA9F22E31,0xD4E1,0x3940,0xBA,0x20,0xDC,0xB2,0x09,0x73,0xB0,0x9F); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals,0x06B50718,0x3528,0x3B66,0xBE,0x76,0xE1,0x83,0xAA,0x80,0xD4,0xA5); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer,0x6928CA7B,0x166D,0x3B37,0x90,0x10,0xFB,0xAB,0x2C,0x7E,0x92,0xB0); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater,0x4FA5F2C4,0x8612,0x35C9,0xBF,0xAA,0x96,0x7C,0x2C,0x81,0x9F,0xA7); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals,0xC8AFE1A8,0x92FC,0x3783,0x95,0x20,0xD6,0xBB,0xC5,0x07,0xB2,0x4A); + + +MIDL_DEFINE_GUID(IID, IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics,0x2C1E9C37,0x6827,0x38F7,0x85,0x7C,0x02,0x16,0x42,0xCA,0x42,0x8B); + +#undef MIDL_DEFINE_GUID + +#ifdef __cplusplus +} +#endif + + + diff --git a/BackEndProxyStub/PhoneVoIPApp.BackEnd_p.c b/BackEndProxyStub/PhoneVoIPApp.BackEnd_p.c new file mode 100755 index 0000000..3b76f42 --- /dev/null +++ b/BackEndProxyStub/PhoneVoIPApp.BackEnd_p.c @@ -0,0 +1,5831 @@ + + +/* this ALWAYS GENERATED file contains the proxy stub code */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* at Tue Jan 29 08:48:50 2019 + */ +/* Compiler settings for C:\Users\evgeny\AppData\Local\Temp\PhoneVoIPApp.BackEnd.idl-35395493: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=ARM 8.00.0603 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#if defined(_ARM_) + + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ +#if _MSC_VER >= 1200 +#pragma warning(push) +#endif + +#pragma warning( disable: 4211 ) /* redefine extern to static */ +#pragma warning( disable: 4232 ) /* dllimport identity*/ +#pragma warning( disable: 4024 ) /* array to pointer mapping*/ +#pragma warning( disable: 4152 ) /* function/data pointer conversion in expression */ + +#define USE_STUBLESS_PROXY + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REDQ_RPCPROXY_H_VERSION__ +#define __REQUIRED_RPCPROXY_H_VERSION__ 475 +#endif + + +#include "rpcproxy.h" +#ifndef __RPCPROXY_H_VERSION__ +#error this stub requires an updated version of +#endif /* __RPCPROXY_H_VERSION__ */ + + +#include "PhoneVoIPApp.BackEnd.h" + +#define TYPE_FORMAT_STRING_SIZE 575 +#define PROC_FORMAT_STRING_SIZE 4275 +#define EXPR_FORMAT_STRING_SIZE 1 +#define TRANSMIT_AS_TABLE_SIZE 0 +#define WIRE_MARSHAL_TABLE_SIZE 1 + +typedef struct _PhoneVoIPApp2EBackEnd_MIDL_TYPE_FORMAT_STRING + { + short Pad; + unsigned char Format[ TYPE_FORMAT_STRING_SIZE ]; + } PhoneVoIPApp2EBackEnd_MIDL_TYPE_FORMAT_STRING; + +typedef struct _PhoneVoIPApp2EBackEnd_MIDL_PROC_FORMAT_STRING + { + short Pad; + unsigned char Format[ PROC_FORMAT_STRING_SIZE ]; + } PhoneVoIPApp2EBackEnd_MIDL_PROC_FORMAT_STRING; + +typedef struct _PhoneVoIPApp2EBackEnd_MIDL_EXPR_FORMAT_STRING + { + long Pad; + unsigned char Format[ EXPR_FORMAT_STRING_SIZE ]; + } PhoneVoIPApp2EBackEnd_MIDL_EXPR_FORMAT_STRING; + + +static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax = +{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}; + + +extern const PhoneVoIPApp2EBackEnd_MIDL_TYPE_FORMAT_STRING PhoneVoIPApp2EBackEnd__MIDL_TypeFormatString; +extern const PhoneVoIPApp2EBackEnd_MIDL_PROC_FORMAT_STRING PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString; +extern const PhoneVoIPApp2EBackEnd_MIDL_EXPR_FORMAT_STRING PhoneVoIPApp2EBackEnd__MIDL_ExprFormatString; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_ProxyInfo; + + +extern const MIDL_STUB_DESC Object_StubDesc; + + +extern const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_ServerInfo; +extern const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_ProxyInfo; + + +extern const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[ WIRE_MARSHAL_TABLE_SIZE ]; + +#if !defined(__RPC_ARM32__) +#error Invalid build platform for this stub. +#endif + +#if !(TARGET_IS_NT50_OR_LATER) +#error You need Windows 2000 or later to run this stub because it uses these features: +#error /robust command line switch. +#error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems. +#error This app will fail with the RPC_X_WRONG_STUB_VERSION error. +#endif + + +static const PhoneVoIPApp2EBackEnd_MIDL_PROC_FORMAT_STRING PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString = + { + 0, + { + + /* Procedure Invoke */ + + 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2 */ NdrFcLong( 0x0 ), /* 0 */ +/* 6 */ NdrFcShort( 0x3 ), /* 3 */ +/* 8 */ NdrFcShort( 0x1c ), /* ARM Stack size/offset = 28 */ +/* 10 */ NdrFcShort( 0x20 ), /* 32 */ +/* 12 */ NdrFcShort( 0x8 ), /* 8 */ +/* 14 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x4, /* 4 */ +/* 16 */ 0x12, /* 18 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 18 */ NdrFcShort( 0x0 ), /* 0 */ +/* 20 */ NdrFcShort( 0x0 ), /* 0 */ +/* 22 */ NdrFcShort( 0x0 ), /* 0 */ +/* 24 */ NdrFcShort( 0x6 ), /* 6 */ +/* 26 */ 0x6, /* 6 */ + 0x80, /* 128 */ +/* 28 */ 0x81, /* 129 */ + 0x82, /* 130 */ +/* 30 */ 0x83, /* 131 */ + 0xfc, /* 252 */ +/* 32 */ 0xfc, /* 252 */ + 0x0, /* 0 */ + + /* Parameter pBuffer */ + +/* 34 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 36 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 38 */ NdrFcShort( 0x2 ), /* Type Offset=2 */ + + /* Parameter hnsPresentationTime */ + +/* 40 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 42 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 44 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter hnsSampleDuration */ + +/* 46 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 48 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 50 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Return value */ + +/* 52 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 54 */ NdrFcShort( 0x18 ), /* ARM Stack size/offset = 24 */ +/* 56 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure Invoke */ + +/* 58 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 60 */ NdrFcLong( 0x0 ), /* 0 */ +/* 64 */ NdrFcShort( 0x3 ), /* 3 */ +/* 66 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 68 */ NdrFcShort( 0x8 ), /* 8 */ +/* 70 */ NdrFcShort( 0x8 ), /* 8 */ +/* 72 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 74 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 76 */ NdrFcShort( 0x0 ), /* 0 */ +/* 78 */ NdrFcShort( 0x0 ), /* 0 */ +/* 80 */ NdrFcShort( 0x0 ), /* 0 */ +/* 82 */ NdrFcShort( 0x2 ), /* 2 */ +/* 84 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 86 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __param0 */ + +/* 88 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 90 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 92 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + +/* 94 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 96 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 98 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure Invoke */ + +/* 100 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 102 */ NdrFcLong( 0x0 ), /* 0 */ +/* 106 */ NdrFcShort( 0x3 ), /* 3 */ +/* 108 */ NdrFcShort( 0x20 ), /* ARM Stack size/offset = 32 */ +/* 110 */ NdrFcShort( 0x25 ), /* 37 */ +/* 112 */ NdrFcShort( 0x8 ), /* 8 */ +/* 114 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x4, /* 4 */ +/* 116 */ 0x12, /* 18 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 118 */ NdrFcShort( 0x0 ), /* 0 */ +/* 120 */ NdrFcShort( 0x0 ), /* 0 */ +/* 122 */ NdrFcShort( 0x0 ), /* 0 */ +/* 124 */ NdrFcShort( 0x7 ), /* 7 */ +/* 126 */ 0x7, /* 7 */ + 0x80, /* 128 */ +/* 128 */ 0x9f, /* 159 */ + 0x82, /* 130 */ +/* 130 */ 0x83, /* 131 */ + 0xfc, /* 252 */ +/* 132 */ 0xfc, /* 252 */ + 0xfc, /* 252 */ + + /* Parameter callId */ + +/* 134 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 136 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 138 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter callAccessHash */ + +/* 140 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 142 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 144 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter rejected */ + +/* 146 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 148 */ NdrFcShort( 0x18 ), /* ARM Stack size/offset = 24 */ +/* 150 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 152 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 154 */ NdrFcShort( 0x1c ), /* ARM Stack size/offset = 28 */ +/* 156 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure WriteAudio */ + +/* 158 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 160 */ NdrFcLong( 0x0 ), /* 0 */ +/* 164 */ NdrFcShort( 0x6 ), /* 6 */ +/* 166 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 168 */ NdrFcShort( 0x8 ), /* 8 */ +/* 170 */ NdrFcShort( 0x21 ), /* 33 */ +/* 172 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x3, /* 3 */ +/* 174 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 176 */ NdrFcShort( 0x0 ), /* 0 */ +/* 178 */ NdrFcShort( 0x0 ), /* 0 */ +/* 180 */ NdrFcShort( 0x0 ), /* 0 */ +/* 182 */ NdrFcShort( 0x3 ), /* 3 */ +/* 184 */ 0x3, /* 3 */ + 0x80, /* 128 */ +/* 186 */ 0x81, /* 129 */ + 0x82, /* 130 */ + + /* Parameter bytes */ + +/* 188 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 190 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 192 */ 0x1, /* FC_BYTE */ + 0x0, /* 0 */ + + /* Parameter byteCount */ + +/* 194 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 196 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 198 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Return value */ + +/* 200 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 202 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 204 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure WriteVideo */ + +/* 206 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 208 */ NdrFcLong( 0x0 ), /* 0 */ +/* 212 */ NdrFcShort( 0x7 ), /* 7 */ +/* 214 */ NdrFcShort( 0x24 ), /* ARM Stack size/offset = 36 */ +/* 216 */ NdrFcShort( 0x28 ), /* 40 */ +/* 218 */ NdrFcShort( 0x21 ), /* 33 */ +/* 220 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x5, /* 5 */ +/* 222 */ 0x14, /* 20 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 224 */ NdrFcShort( 0x0 ), /* 0 */ +/* 226 */ NdrFcShort( 0x0 ), /* 0 */ +/* 228 */ NdrFcShort( 0x0 ), /* 0 */ +/* 230 */ NdrFcShort( 0x8 ), /* 8 */ +/* 232 */ 0x8, /* 8 */ + 0x80, /* 128 */ +/* 234 */ 0x81, /* 129 */ + 0x82, /* 130 */ +/* 236 */ 0x9f, /* 159 */ + 0x9d, /* 157 */ +/* 238 */ 0xfc, /* 252 */ + 0x4, /* 4 */ +/* 240 */ 0x0, /* 0 */ + 0x0, /* 0 */ + + /* Parameter bytes */ + +/* 242 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 244 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 246 */ 0x1, /* FC_BYTE */ + 0x0, /* 0 */ + + /* Parameter byteCount */ + +/* 248 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 250 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 252 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter hnsPresentationTime */ + +/* 254 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 256 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 258 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter hnsSampleDuration */ + +/* 260 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 262 */ NdrFcShort( 0x18 ), /* ARM Stack size/offset = 24 */ +/* 264 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Return value */ + +/* 266 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 268 */ NdrFcShort( 0x20 ), /* ARM Stack size/offset = 32 */ +/* 270 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure add_AudioMessageReceived */ + +/* 272 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 274 */ NdrFcLong( 0x0 ), /* 0 */ +/* 278 */ NdrFcShort( 0x8 ), /* 8 */ +/* 280 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 282 */ NdrFcShort( 0x0 ), /* 0 */ +/* 284 */ NdrFcShort( 0x34 ), /* 52 */ +/* 286 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x3, /* 3 */ +/* 288 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 290 */ NdrFcShort( 0x0 ), /* 0 */ +/* 292 */ NdrFcShort( 0x0 ), /* 0 */ +/* 294 */ NdrFcShort( 0x0 ), /* 0 */ +/* 296 */ NdrFcShort( 0x3 ), /* 3 */ +/* 298 */ 0x3, /* 3 */ + 0x80, /* 128 */ +/* 300 */ 0x81, /* 129 */ + 0x82, /* 130 */ + + /* Parameter __param0 */ + +/* 302 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 304 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 306 */ NdrFcShort( 0x18 ), /* Type Offset=24 */ + + /* Parameter __returnValue */ + +/* 308 */ NdrFcShort( 0x2112 ), /* Flags: must free, out, simple ref, srv alloc size=8 */ +/* 310 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 312 */ NdrFcShort( 0x2e ), /* Type Offset=46 */ + + /* Return value */ + +/* 314 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 316 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 318 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure remove_AudioMessageReceived */ + +/* 320 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 322 */ NdrFcLong( 0x0 ), /* 0 */ +/* 326 */ NdrFcShort( 0x9 ), /* 9 */ +/* 328 */ NdrFcShort( 0x14 ), /* ARM Stack size/offset = 20 */ +/* 330 */ NdrFcShort( 0x18 ), /* 24 */ +/* 332 */ NdrFcShort( 0x8 ), /* 8 */ +/* 334 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 336 */ 0x10, /* 16 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 338 */ NdrFcShort( 0x0 ), /* 0 */ +/* 340 */ NdrFcShort( 0x0 ), /* 0 */ +/* 342 */ NdrFcShort( 0x0 ), /* 0 */ +/* 344 */ NdrFcShort( 0x4 ), /* 4 */ +/* 346 */ 0x4, /* 4 */ + 0x80, /* 128 */ +/* 348 */ 0x9f, /* 159 */ + 0x82, /* 130 */ +/* 350 */ 0x83, /* 131 */ + 0x0, /* 0 */ + + /* Parameter __param0 */ + +/* 352 */ NdrFcShort( 0x8a ), /* Flags: must free, in, by val, */ +/* 354 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 356 */ NdrFcShort( 0x2e ), /* Type Offset=46 */ + + /* Return value */ + +/* 358 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 360 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 362 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure add_VideoMessageReceived */ + +/* 364 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 366 */ NdrFcLong( 0x0 ), /* 0 */ +/* 370 */ NdrFcShort( 0xa ), /* 10 */ +/* 372 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 374 */ NdrFcShort( 0x0 ), /* 0 */ +/* 376 */ NdrFcShort( 0x34 ), /* 52 */ +/* 378 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x3, /* 3 */ +/* 380 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 382 */ NdrFcShort( 0x0 ), /* 0 */ +/* 384 */ NdrFcShort( 0x0 ), /* 0 */ +/* 386 */ NdrFcShort( 0x0 ), /* 0 */ +/* 388 */ NdrFcShort( 0x3 ), /* 3 */ +/* 390 */ 0x3, /* 3 */ + 0x80, /* 128 */ +/* 392 */ 0x81, /* 129 */ + 0x82, /* 130 */ + + /* Parameter __param0 */ + +/* 394 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 396 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 398 */ NdrFcShort( 0x18 ), /* Type Offset=24 */ + + /* Parameter __returnValue */ + +/* 400 */ NdrFcShort( 0x2112 ), /* Flags: must free, out, simple ref, srv alloc size=8 */ +/* 402 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 404 */ NdrFcShort( 0x2e ), /* Type Offset=46 */ + + /* Return value */ + +/* 406 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 408 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 410 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure remove_CameraLocationChanged */ + + + /* Procedure remove_VideoMessageReceived */ + +/* 412 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 414 */ NdrFcLong( 0x0 ), /* 0 */ +/* 418 */ NdrFcShort( 0xb ), /* 11 */ +/* 420 */ NdrFcShort( 0x14 ), /* ARM Stack size/offset = 20 */ +/* 422 */ NdrFcShort( 0x18 ), /* 24 */ +/* 424 */ NdrFcShort( 0x8 ), /* 8 */ +/* 426 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 428 */ 0x10, /* 16 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 430 */ NdrFcShort( 0x0 ), /* 0 */ +/* 432 */ NdrFcShort( 0x0 ), /* 0 */ +/* 434 */ NdrFcShort( 0x0 ), /* 0 */ +/* 436 */ NdrFcShort( 0x4 ), /* 4 */ +/* 438 */ 0x4, /* 4 */ + 0x80, /* 128 */ +/* 440 */ 0x9f, /* 159 */ + 0x82, /* 130 */ +/* 442 */ 0x83, /* 131 */ + 0x0, /* 0 */ + + /* Parameter __param0 */ + + + /* Parameter __param0 */ + +/* 444 */ NdrFcShort( 0x8a ), /* Flags: must free, in, by val, */ +/* 446 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 448 */ NdrFcShort( 0x2e ), /* Type Offset=46 */ + + /* Return value */ + + + /* Return value */ + +/* 450 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 452 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 454 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_id */ + +/* 456 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 458 */ NdrFcLong( 0x0 ), /* 0 */ +/* 462 */ NdrFcShort( 0x6 ), /* 6 */ +/* 464 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 466 */ NdrFcShort( 0x0 ), /* 0 */ +/* 468 */ NdrFcShort( 0x2c ), /* 44 */ +/* 470 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 472 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 474 */ NdrFcShort( 0x0 ), /* 0 */ +/* 476 */ NdrFcShort( 0x0 ), /* 0 */ +/* 478 */ NdrFcShort( 0x0 ), /* 0 */ +/* 480 */ NdrFcShort( 0x2 ), /* 2 */ +/* 482 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 484 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 486 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 488 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 490 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Return value */ + +/* 492 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 494 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 496 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_id */ + +/* 498 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 500 */ NdrFcLong( 0x0 ), /* 0 */ +/* 504 */ NdrFcShort( 0x7 ), /* 7 */ +/* 506 */ NdrFcShort( 0x14 ), /* ARM Stack size/offset = 20 */ +/* 508 */ NdrFcShort( 0x10 ), /* 16 */ +/* 510 */ NdrFcShort( 0x8 ), /* 8 */ +/* 512 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 514 */ 0x10, /* 16 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 516 */ NdrFcShort( 0x0 ), /* 0 */ +/* 518 */ NdrFcShort( 0x0 ), /* 0 */ +/* 520 */ NdrFcShort( 0x0 ), /* 0 */ +/* 522 */ NdrFcShort( 0x4 ), /* 4 */ +/* 524 */ 0x4, /* 4 */ + 0x80, /* 128 */ +/* 526 */ 0x9f, /* 159 */ + 0x82, /* 130 */ +/* 528 */ 0x83, /* 131 */ + 0x0, /* 0 */ + + /* Parameter __set_formal */ + +/* 530 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 532 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 534 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Return value */ + +/* 536 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 538 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 540 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_port */ + +/* 542 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 544 */ NdrFcLong( 0x0 ), /* 0 */ +/* 548 */ NdrFcShort( 0x8 ), /* 8 */ +/* 550 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 552 */ NdrFcShort( 0x0 ), /* 0 */ +/* 554 */ NdrFcShort( 0x22 ), /* 34 */ +/* 556 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 558 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 560 */ NdrFcShort( 0x0 ), /* 0 */ +/* 562 */ NdrFcShort( 0x0 ), /* 0 */ +/* 564 */ NdrFcShort( 0x0 ), /* 0 */ +/* 566 */ NdrFcShort( 0x2 ), /* 2 */ +/* 568 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 570 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 572 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 574 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 576 */ 0x6, /* FC_SHORT */ + 0x0, /* 0 */ + + /* Return value */ + +/* 578 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 580 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 582 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_port */ + +/* 584 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 586 */ NdrFcLong( 0x0 ), /* 0 */ +/* 590 */ NdrFcShort( 0x9 ), /* 9 */ +/* 592 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 594 */ NdrFcShort( 0x6 ), /* 6 */ +/* 596 */ NdrFcShort( 0x8 ), /* 8 */ +/* 598 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 600 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 602 */ NdrFcShort( 0x0 ), /* 0 */ +/* 604 */ NdrFcShort( 0x0 ), /* 0 */ +/* 606 */ NdrFcShort( 0x0 ), /* 0 */ +/* 608 */ NdrFcShort( 0x2 ), /* 2 */ +/* 610 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 612 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __set_formal */ + +/* 614 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 616 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 618 */ 0x6, /* FC_SHORT */ + 0x0, /* 0 */ + + /* Return value */ + +/* 620 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 622 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 624 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_ipv4 */ + +/* 626 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 628 */ NdrFcLong( 0x0 ), /* 0 */ +/* 632 */ NdrFcShort( 0xa ), /* 10 */ +/* 634 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 636 */ NdrFcShort( 0x0 ), /* 0 */ +/* 638 */ NdrFcShort( 0x8 ), /* 8 */ +/* 640 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 642 */ 0xe, /* 14 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 644 */ NdrFcShort( 0x1 ), /* 1 */ +/* 646 */ NdrFcShort( 0x0 ), /* 0 */ +/* 648 */ NdrFcShort( 0x0 ), /* 0 */ +/* 650 */ NdrFcShort( 0x2 ), /* 2 */ +/* 652 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 654 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 656 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 658 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 660 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ + + /* Return value */ + +/* 662 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 664 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 666 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_ipv4 */ + +/* 668 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 670 */ NdrFcLong( 0x0 ), /* 0 */ +/* 674 */ NdrFcShort( 0xb ), /* 11 */ +/* 676 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 678 */ NdrFcShort( 0x0 ), /* 0 */ +/* 680 */ NdrFcShort( 0x8 ), /* 8 */ +/* 682 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 684 */ 0xe, /* 14 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 686 */ NdrFcShort( 0x0 ), /* 0 */ +/* 688 */ NdrFcShort( 0x1 ), /* 1 */ +/* 690 */ NdrFcShort( 0x0 ), /* 0 */ +/* 692 */ NdrFcShort( 0x2 ), /* 2 */ +/* 694 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 696 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __set_formal */ + +/* 698 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */ +/* 700 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 702 */ NdrFcShort( 0x68 ), /* Type Offset=104 */ + + /* Return value */ + +/* 704 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 706 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 708 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_ipv6 */ + +/* 710 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 712 */ NdrFcLong( 0x0 ), /* 0 */ +/* 716 */ NdrFcShort( 0xc ), /* 12 */ +/* 718 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 720 */ NdrFcShort( 0x0 ), /* 0 */ +/* 722 */ NdrFcShort( 0x8 ), /* 8 */ +/* 724 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 726 */ 0xe, /* 14 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 728 */ NdrFcShort( 0x1 ), /* 1 */ +/* 730 */ NdrFcShort( 0x0 ), /* 0 */ +/* 732 */ NdrFcShort( 0x0 ), /* 0 */ +/* 734 */ NdrFcShort( 0x2 ), /* 2 */ +/* 736 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 738 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 740 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 742 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 744 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ + + /* Return value */ + +/* 746 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 748 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 750 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_ipv6 */ + +/* 752 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 754 */ NdrFcLong( 0x0 ), /* 0 */ +/* 758 */ NdrFcShort( 0xd ), /* 13 */ +/* 760 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 762 */ NdrFcShort( 0x0 ), /* 0 */ +/* 764 */ NdrFcShort( 0x8 ), /* 8 */ +/* 766 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 768 */ 0xe, /* 14 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 770 */ NdrFcShort( 0x0 ), /* 0 */ +/* 772 */ NdrFcShort( 0x1 ), /* 1 */ +/* 774 */ NdrFcShort( 0x0 ), /* 0 */ +/* 776 */ NdrFcShort( 0x2 ), /* 2 */ +/* 778 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 780 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __set_formal */ + +/* 782 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */ +/* 784 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 786 */ NdrFcShort( 0x68 ), /* Type Offset=104 */ + + /* Return value */ + +/* 788 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 790 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 792 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_peerTag */ + +/* 794 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 796 */ NdrFcLong( 0x0 ), /* 0 */ +/* 800 */ NdrFcShort( 0xe ), /* 14 */ +/* 802 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 804 */ NdrFcShort( 0x0 ), /* 0 */ +/* 806 */ NdrFcShort( 0x24 ), /* 36 */ +/* 808 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x3, /* 3 */ +/* 810 */ 0xe, /* 14 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 812 */ NdrFcShort( 0x1 ), /* 1 */ +/* 814 */ NdrFcShort( 0x0 ), /* 0 */ +/* 816 */ NdrFcShort( 0x0 ), /* 0 */ +/* 818 */ NdrFcShort( 0x3 ), /* 3 */ +/* 820 */ 0x3, /* 3 */ + 0x80, /* 128 */ +/* 822 */ 0x81, /* 129 */ + 0x82, /* 130 */ + + /* Parameter ____returnValueSize */ + +/* 824 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 826 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 828 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 830 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */ +/* 832 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 834 */ NdrFcShort( 0x76 ), /* Type Offset=118 */ + + /* Return value */ + +/* 836 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 838 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 840 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_peerTag */ + +/* 842 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 844 */ NdrFcLong( 0x0 ), /* 0 */ +/* 848 */ NdrFcShort( 0xf ), /* 15 */ +/* 850 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 852 */ NdrFcShort( 0x8 ), /* 8 */ +/* 854 */ NdrFcShort( 0x8 ), /* 8 */ +/* 856 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x3, /* 3 */ +/* 858 */ 0xe, /* 14 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 860 */ NdrFcShort( 0x0 ), /* 0 */ +/* 862 */ NdrFcShort( 0x1 ), /* 1 */ +/* 864 */ NdrFcShort( 0x0 ), /* 0 */ +/* 866 */ NdrFcShort( 0x3 ), /* 3 */ +/* 868 */ 0x3, /* 3 */ + 0x80, /* 128 */ +/* 870 */ 0x81, /* 129 */ + 0x82, /* 130 */ + + /* Parameter ____set_formalSize */ + +/* 872 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 874 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 876 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter __set_formal */ + +/* 878 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 880 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 882 */ NdrFcShort( 0x8e ), /* Type Offset=142 */ + + /* Return value */ + +/* 884 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 886 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 888 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure OnSignalBarsChanged */ + +/* 890 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 892 */ NdrFcLong( 0x0 ), /* 0 */ +/* 896 */ NdrFcShort( 0x6 ), /* 6 */ +/* 898 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 900 */ NdrFcShort( 0x8 ), /* 8 */ +/* 902 */ NdrFcShort( 0x8 ), /* 8 */ +/* 904 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 906 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 908 */ NdrFcShort( 0x0 ), /* 0 */ +/* 910 */ NdrFcShort( 0x0 ), /* 0 */ +/* 912 */ NdrFcShort( 0x0 ), /* 0 */ +/* 914 */ NdrFcShort( 0x2 ), /* 2 */ +/* 916 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 918 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter newSignal */ + +/* 920 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 922 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 924 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Return value */ + +/* 926 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 928 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 930 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure Start */ + + + /* Procedure OnCallStateChanged */ + +/* 932 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 934 */ NdrFcLong( 0x0 ), /* 0 */ +/* 938 */ NdrFcShort( 0x7 ), /* 7 */ +/* 940 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 942 */ NdrFcShort( 0x8 ), /* 8 */ +/* 944 */ NdrFcShort( 0x8 ), /* 8 */ +/* 946 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 948 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 950 */ NdrFcShort( 0x0 ), /* 0 */ +/* 952 */ NdrFcShort( 0x0 ), /* 0 */ +/* 954 */ NdrFcShort( 0x0 ), /* 0 */ +/* 956 */ NdrFcShort( 0x2 ), /* 2 */ +/* 958 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 960 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter cameraLocation */ + + + /* Parameter newState */ + +/* 962 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 964 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 966 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + + + /* Return value */ + +/* 968 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 970 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 972 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure OnCallStatusChanged */ + +/* 974 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 976 */ NdrFcLong( 0x0 ), /* 0 */ +/* 980 */ NdrFcShort( 0x8 ), /* 8 */ +/* 982 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 984 */ NdrFcShort( 0x8 ), /* 8 */ +/* 986 */ NdrFcShort( 0x8 ), /* 8 */ +/* 988 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 990 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 992 */ NdrFcShort( 0x0 ), /* 0 */ +/* 994 */ NdrFcShort( 0x0 ), /* 0 */ +/* 996 */ NdrFcShort( 0x0 ), /* 0 */ +/* 998 */ NdrFcShort( 0x2 ), /* 2 */ +/* 1000 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 1002 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter newStatus */ + +/* 1004 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1006 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1008 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + +/* 1010 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1012 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1014 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure OnCallAudioRouteChanged */ + +/* 1016 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1018 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1022 */ NdrFcShort( 0x9 ), /* 9 */ +/* 1024 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1026 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1028 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1030 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 1032 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1034 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1036 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1038 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1040 */ NdrFcShort( 0x2 ), /* 2 */ +/* 1042 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 1044 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter newRoute */ + +/* 1046 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1048 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1050 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + +/* 1052 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1054 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1056 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure OnMediaOperationsChanged */ + +/* 1058 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1060 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1064 */ NdrFcShort( 0xa ), /* 10 */ +/* 1066 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1068 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1070 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1072 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 1074 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1076 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1078 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1080 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1082 */ NdrFcShort( 0x2 ), /* 2 */ +/* 1084 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 1086 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter newOperations */ + +/* 1088 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1090 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1092 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + +/* 1094 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1096 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1098 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure OnCameraLocationChanged */ + +/* 1100 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1102 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1106 */ NdrFcShort( 0xb ), /* 11 */ +/* 1108 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1110 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1112 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1114 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 1116 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1118 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1120 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1122 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1124 */ NdrFcShort( 0x2 ), /* 2 */ +/* 1126 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 1128 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter newCameraLocation */ + +/* 1130 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1132 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1134 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + +/* 1136 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1138 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1140 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure SetTransport */ + +/* 1142 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1144 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1148 */ NdrFcShort( 0x6 ), /* 6 */ +/* 1150 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1152 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1154 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1156 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 1158 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1160 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1162 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1164 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1166 */ NdrFcShort( 0x2 ), /* 2 */ +/* 1168 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 1170 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter transport */ + +/* 1172 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 1174 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1176 */ NdrFcShort( 0x9a ), /* Type Offset=154 */ + + /* Return value */ + +/* 1178 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1180 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1182 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure StopMTProtoUpdater */ + + + /* Procedure Stop */ + +/* 1184 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1186 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1190 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1192 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1194 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1196 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1198 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x1, /* 1 */ +/* 1200 */ 0xc, /* 12 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1202 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1204 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1206 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1208 */ NdrFcShort( 0x1 ), /* 1 */ +/* 1210 */ 0x1, /* 1 */ + 0x80, /* 128 */ + + /* Return value */ + + + /* Return value */ + +/* 1212 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1214 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1216 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure CreateVoIPControllerWrapper */ + + + /* Procedure ToggleCamera */ + +/* 1218 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1220 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1224 */ NdrFcShort( 0x9 ), /* 9 */ +/* 1226 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1228 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1230 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1232 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x1, /* 1 */ +/* 1234 */ 0xc, /* 12 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1236 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1238 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1240 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1242 */ NdrFcShort( 0x1 ), /* 1 */ +/* 1244 */ 0x1, /* 1 */ + 0x80, /* 128 */ + + /* Return value */ + + + /* Return value */ + +/* 1246 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1248 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1250 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure add_CameraLocationChanged */ + +/* 1252 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1254 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1258 */ NdrFcShort( 0xa ), /* 10 */ +/* 1260 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 1262 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1264 */ NdrFcShort( 0x34 ), /* 52 */ +/* 1266 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x3, /* 3 */ +/* 1268 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1270 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1272 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1274 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1276 */ NdrFcShort( 0x3 ), /* 3 */ +/* 1278 */ 0x3, /* 3 */ + 0x80, /* 128 */ +/* 1280 */ 0x81, /* 129 */ + 0x82, /* 130 */ + + /* Parameter __param0 */ + +/* 1282 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 1284 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1286 */ NdrFcShort( 0xac ), /* Type Offset=172 */ + + /* Parameter __returnValue */ + +/* 1288 */ NdrFcShort( 0x2112 ), /* Flags: must free, out, simple ref, srv alloc size=8 */ +/* 1290 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1292 */ NdrFcShort( 0x2e ), /* Type Offset=46 */ + + /* Return value */ + +/* 1294 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1296 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1298 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_InitTimeout */ + +/* 1300 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1302 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1306 */ NdrFcShort( 0x6 ), /* 6 */ +/* 1308 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1310 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1312 */ NdrFcShort( 0x2c ), /* 44 */ +/* 1314 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 1316 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1318 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1320 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1322 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1324 */ NdrFcShort( 0x2 ), /* 2 */ +/* 1326 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 1328 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 1330 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 1332 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1334 */ 0xc, /* FC_DOUBLE */ + 0x0, /* 0 */ + + /* Return value */ + +/* 1336 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1338 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1340 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_InitTimeout */ + +/* 1342 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1344 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1348 */ NdrFcShort( 0x7 ), /* 7 */ +/* 1350 */ NdrFcShort( 0x14 ), /* ARM Stack size/offset = 20 */ +/* 1352 */ NdrFcShort( 0x10 ), /* 16 */ +/* 1354 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1356 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 1358 */ 0x10, /* 16 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1360 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1362 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1364 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1366 */ NdrFcShort( 0x4 ), /* 4 */ +/* 1368 */ 0x4, /* 4 */ + 0x80, /* 128 */ +/* 1370 */ 0x9f, /* 159 */ + 0x84, /* 132 */ +/* 1372 */ 0x85, /* 133 */ + 0x0, /* 0 */ + + /* Parameter __set_formal */ + +/* 1374 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1376 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1378 */ 0xc, /* FC_DOUBLE */ + 0x0, /* 0 */ + + /* Return value */ + +/* 1380 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1382 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 1384 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_RecvTimeout */ + +/* 1386 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1388 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1392 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1394 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1396 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1398 */ NdrFcShort( 0x2c ), /* 44 */ +/* 1400 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 1402 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1404 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1406 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1408 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1410 */ NdrFcShort( 0x2 ), /* 2 */ +/* 1412 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 1414 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 1416 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 1418 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1420 */ 0xc, /* FC_DOUBLE */ + 0x0, /* 0 */ + + /* Return value */ + +/* 1422 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1424 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1426 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_RecvTimeout */ + +/* 1428 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1430 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1434 */ NdrFcShort( 0x9 ), /* 9 */ +/* 1436 */ NdrFcShort( 0x14 ), /* ARM Stack size/offset = 20 */ +/* 1438 */ NdrFcShort( 0x10 ), /* 16 */ +/* 1440 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1442 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 1444 */ 0x10, /* 16 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1446 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1448 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1450 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1452 */ NdrFcShort( 0x4 ), /* 4 */ +/* 1454 */ 0x4, /* 4 */ + 0x80, /* 128 */ +/* 1456 */ 0x9f, /* 159 */ + 0x84, /* 132 */ +/* 1458 */ 0x85, /* 133 */ + 0x0, /* 0 */ + + /* Parameter __set_formal */ + +/* 1460 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1462 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1464 */ 0xc, /* FC_DOUBLE */ + 0x0, /* 0 */ + + /* Return value */ + +/* 1466 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1468 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 1470 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure Start */ + + + /* Procedure HandleUpdatePhoneCall */ + +/* 1472 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1474 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1478 */ NdrFcShort( 0x6 ), /* 6 */ +/* 1480 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1482 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1484 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1486 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x1, /* 1 */ +/* 1488 */ 0xc, /* 12 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1490 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1492 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1494 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1496 */ NdrFcShort( 0x1 ), /* 1 */ +/* 1498 */ 0x1, /* 1 */ + 0x80, /* 128 */ + + /* Return value */ + + + /* Return value */ + +/* 1500 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1502 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1504 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure DoPeriodicKeepAlive */ + + + /* Procedure Stop */ + + + /* Procedure Stop */ + + + /* Procedure StartMTProtoUpdater */ + +/* 1506 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1508 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1512 */ NdrFcShort( 0x7 ), /* 7 */ +/* 1514 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1516 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1518 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1520 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x1, /* 1 */ +/* 1522 */ 0xc, /* 12 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1524 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1526 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1528 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1530 */ NdrFcShort( 0x1 ), /* 1 */ +/* 1532 */ 0x1, /* 1 */ + 0x80, /* 128 */ + + /* Return value */ + + + /* Return value */ + + + /* Return value */ + + + /* Return value */ + +/* 1534 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1536 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1538 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure DeleteVoIPControllerWrapper */ + +/* 1540 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1542 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1546 */ NdrFcShort( 0xa ), /* 10 */ +/* 1548 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1550 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1552 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1554 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x1, /* 1 */ +/* 1556 */ 0xc, /* 12 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1558 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1560 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1562 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1564 */ NdrFcShort( 0x1 ), /* 1 */ +/* 1566 */ 0x1, /* 1 */ + 0x80, /* 128 */ + + /* Return value */ + +/* 1568 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1570 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1572 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure SetConfig */ + +/* 1574 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1576 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1580 */ NdrFcShort( 0xb ), /* 11 */ +/* 1582 */ NdrFcShort( 0x2c ), /* ARM Stack size/offset = 44 */ +/* 1584 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1586 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1588 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 1590 */ 0x14, /* 20 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 1592 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1594 */ NdrFcShort( 0x1 ), /* 1 */ +/* 1596 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1598 */ NdrFcShort( 0xa ), /* 10 */ +/* 1600 */ 0x8, /* 8 */ + 0x80, /* 128 */ +/* 1602 */ 0x9f, /* 159 */ + 0x82, /* 130 */ +/* 1604 */ 0x83, /* 131 */ + 0x9d, /* 157 */ +/* 1606 */ 0xfc, /* 252 */ + 0x6, /* 6 */ +/* 1608 */ 0x0, /* 0 */ + 0x0, /* 0 */ + + /* Parameter config */ + +/* 1610 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */ +/* 1612 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1614 */ NdrFcShort( 0xc2 ), /* Type Offset=194 */ + + /* Return value */ + +/* 1616 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1618 */ NdrFcShort( 0x28 ), /* ARM Stack size/offset = 40 */ +/* 1620 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure SetEncryptionKey */ + +/* 1622 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1624 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1628 */ NdrFcShort( 0xc ), /* 12 */ +/* 1630 */ NdrFcShort( 0x14 ), /* ARM Stack size/offset = 20 */ +/* 1632 */ NdrFcShort( 0xd ), /* 13 */ +/* 1634 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1636 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x4, /* 4 */ +/* 1638 */ 0x10, /* 16 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 1640 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1642 */ NdrFcShort( 0x1 ), /* 1 */ +/* 1644 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1646 */ NdrFcShort( 0x4 ), /* 4 */ +/* 1648 */ 0x4, /* 4 */ + 0x80, /* 128 */ +/* 1650 */ 0x81, /* 129 */ + 0x82, /* 130 */ +/* 1652 */ 0x83, /* 131 */ + 0x0, /* 0 */ + + /* Parameter __keySize */ + +/* 1654 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1656 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1658 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter key */ + +/* 1660 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 1662 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1664 */ NdrFcShort( 0x8e ), /* Type Offset=142 */ + + /* Parameter isOutgoing */ + +/* 1666 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1668 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1670 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 1672 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1674 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 1676 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure SetPublicEndpoints */ + +/* 1678 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1680 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1684 */ NdrFcShort( 0xd ), /* 13 */ +/* 1686 */ NdrFcShort( 0x18 ), /* ARM Stack size/offset = 24 */ +/* 1688 */ NdrFcShort( 0x15 ), /* 21 */ +/* 1690 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1692 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x5, /* 5 */ +/* 1694 */ 0x10, /* 16 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 1696 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1698 */ NdrFcShort( 0x1 ), /* 1 */ +/* 1700 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1702 */ NdrFcShort( 0x5 ), /* 5 */ +/* 1704 */ 0x5, /* 5 */ + 0x80, /* 128 */ +/* 1706 */ 0x81, /* 129 */ + 0x82, /* 130 */ +/* 1708 */ 0x83, /* 131 */ + 0xfc, /* 252 */ + + /* Parameter __endpointsSize */ + +/* 1710 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1712 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1714 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter endpoints */ + +/* 1716 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 1718 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1720 */ NdrFcShort( 0xf6 ), /* Type Offset=246 */ + + /* Parameter allowP2P */ + +/* 1722 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1724 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1726 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Parameter connectionMaxLayer */ + +/* 1728 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1730 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 1732 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Return value */ + +/* 1734 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1736 */ NdrFcShort( 0x14 ), /* ARM Stack size/offset = 20 */ +/* 1738 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure SetProxy */ + +/* 1740 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1742 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1746 */ NdrFcShort( 0xe ), /* 14 */ +/* 1748 */ NdrFcShort( 0x1c ), /* ARM Stack size/offset = 28 */ +/* 1750 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1752 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1754 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 1756 */ 0x12, /* 18 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 1758 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1760 */ NdrFcShort( 0x1 ), /* 1 */ +/* 1762 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1764 */ NdrFcShort( 0x6 ), /* 6 */ +/* 1766 */ 0x6, /* 6 */ + 0x80, /* 128 */ +/* 1768 */ 0x81, /* 129 */ + 0x82, /* 130 */ +/* 1770 */ 0x83, /* 131 */ + 0xfc, /* 252 */ +/* 1772 */ 0xfc, /* 252 */ + 0x0, /* 0 */ + + /* Parameter proxy */ + +/* 1774 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */ +/* 1776 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1778 */ NdrFcShort( 0x10c ), /* Type Offset=268 */ + + /* Return value */ + +/* 1780 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1782 */ NdrFcShort( 0x18 ), /* ARM Stack size/offset = 24 */ +/* 1784 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure Start */ + +/* 1786 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1788 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1792 */ NdrFcShort( 0xf ), /* 15 */ +/* 1794 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1796 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1798 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1800 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x1, /* 1 */ +/* 1802 */ 0xc, /* 12 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1804 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1806 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1808 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1810 */ NdrFcShort( 0x1 ), /* 1 */ +/* 1812 */ 0x1, /* 1 */ + 0x80, /* 128 */ + + /* Return value */ + +/* 1814 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1816 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1818 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure Connect */ + +/* 1820 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1822 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1826 */ NdrFcShort( 0x10 ), /* 16 */ +/* 1828 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1830 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1832 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1834 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x1, /* 1 */ +/* 1836 */ 0xc, /* 12 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1838 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1840 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1842 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1844 */ NdrFcShort( 0x1 ), /* 1 */ +/* 1846 */ 0x1, /* 1 */ + 0x80, /* 128 */ + + /* Return value */ + +/* 1848 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1850 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1852 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure SetMicMute */ + +/* 1854 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1856 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1860 */ NdrFcShort( 0x11 ), /* 17 */ +/* 1862 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1864 */ NdrFcShort( 0x5 ), /* 5 */ +/* 1866 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1868 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 1870 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1872 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1874 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1876 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1878 */ NdrFcShort( 0x2 ), /* 2 */ +/* 1880 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 1882 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter mute */ + +/* 1884 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1886 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1888 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 1890 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1892 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1894 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure SwitchSpeaker */ + +/* 1896 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1898 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1902 */ NdrFcShort( 0x12 ), /* 18 */ +/* 1904 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1906 */ NdrFcShort( 0x5 ), /* 5 */ +/* 1908 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1910 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 1912 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1914 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1916 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1918 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1920 */ NdrFcShort( 0x2 ), /* 2 */ +/* 1922 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 1924 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter external */ + +/* 1926 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 1928 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1930 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 1932 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1934 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1936 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure UpdateServerConfig */ + +/* 1938 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1940 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1944 */ NdrFcShort( 0x13 ), /* 19 */ +/* 1946 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1948 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1950 */ NdrFcShort( 0x8 ), /* 8 */ +/* 1952 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 1954 */ 0xe, /* 14 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 1956 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1958 */ NdrFcShort( 0x1 ), /* 1 */ +/* 1960 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1962 */ NdrFcShort( 0x2 ), /* 2 */ +/* 1964 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 1966 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter json */ + +/* 1968 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */ +/* 1970 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 1972 */ NdrFcShort( 0x68 ), /* Type Offset=104 */ + + /* Return value */ + +/* 1974 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 1976 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 1978 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure GetPreferredRelayID */ + +/* 1980 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 1982 */ NdrFcLong( 0x0 ), /* 0 */ +/* 1986 */ NdrFcShort( 0x14 ), /* 20 */ +/* 1988 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 1990 */ NdrFcShort( 0x0 ), /* 0 */ +/* 1992 */ NdrFcShort( 0x2c ), /* 44 */ +/* 1994 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 1996 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 1998 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2000 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2002 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2004 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2006 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2008 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2010 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2012 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2014 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2016 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2018 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2020 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure GetLastError */ + +/* 2022 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2024 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2028 */ NdrFcShort( 0x15 ), /* 21 */ +/* 2030 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2032 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2034 */ NdrFcShort( 0x24 ), /* 36 */ +/* 2036 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 2038 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2040 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2042 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2044 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2046 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2048 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2050 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2052 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2054 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2056 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2058 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2060 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2062 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure GetDebugLog */ + +/* 2064 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2066 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2070 */ NdrFcShort( 0x16 ), /* 22 */ +/* 2072 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2074 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2076 */ NdrFcShort( 0x8 ), /* 8 */ +/* 2078 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 2080 */ 0xe, /* 14 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 2082 */ NdrFcShort( 0x1 ), /* 1 */ +/* 2084 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2086 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2088 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2090 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2092 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2094 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 2096 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2098 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ + + /* Return value */ + +/* 2100 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2102 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2104 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure GetDebugString */ + +/* 2106 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2108 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2112 */ NdrFcShort( 0x17 ), /* 23 */ +/* 2114 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2116 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2118 */ NdrFcShort( 0x8 ), /* 8 */ +/* 2120 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 2122 */ 0xe, /* 14 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 2124 */ NdrFcShort( 0x1 ), /* 1 */ +/* 2126 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2128 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2130 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2132 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2134 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2136 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 2138 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2140 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ + + /* Return value */ + +/* 2142 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2144 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2146 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure GetVersion */ + +/* 2148 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2150 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2154 */ NdrFcShort( 0x18 ), /* 24 */ +/* 2156 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2158 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2160 */ NdrFcShort( 0x8 ), /* 8 */ +/* 2162 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 2164 */ 0xe, /* 14 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 2166 */ NdrFcShort( 0x1 ), /* 1 */ +/* 2168 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2170 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2172 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2174 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2176 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2178 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 2180 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2182 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ + + /* Return value */ + +/* 2184 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2186 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2188 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure GetSignalBarsCount */ + +/* 2190 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2192 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2196 */ NdrFcShort( 0x19 ), /* 25 */ +/* 2198 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2200 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2202 */ NdrFcShort( 0x24 ), /* 36 */ +/* 2204 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 2206 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2208 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2210 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2212 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2214 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2216 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2218 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2220 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2222 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2224 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2226 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2228 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2230 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure SetStatusCallback */ + +/* 2232 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2234 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2238 */ NdrFcShort( 0x1a ), /* 26 */ +/* 2240 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2242 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2244 */ NdrFcShort( 0x8 ), /* 8 */ +/* 2246 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 2248 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2250 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2252 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2254 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2256 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2258 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2260 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter statusListener */ + +/* 2262 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 2264 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2266 */ NdrFcShort( 0x128 ), /* Type Offset=296 */ + + /* Return value */ + +/* 2268 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2270 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2272 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure InitiateOutgoingCall2 */ + +/* 2274 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2276 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2280 */ NdrFcShort( 0x1b ), /* 27 */ +/* 2282 */ NdrFcShort( 0x28 ), /* ARM Stack size/offset = 40 */ +/* 2284 */ NdrFcShort( 0x30 ), /* 48 */ +/* 2286 */ NdrFcShort( 0x21 ), /* 33 */ +/* 2288 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x6, /* 6 */ +/* 2290 */ 0x14, /* 20 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 2292 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2294 */ NdrFcShort( 0x1 ), /* 1 */ +/* 2296 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2298 */ NdrFcShort( 0x9 ), /* 9 */ +/* 2300 */ 0x8, /* 8 */ + 0x80, /* 128 */ +/* 2302 */ 0x81, /* 129 */ + 0x82, /* 130 */ +/* 2304 */ 0x83, /* 131 */ + 0x9d, /* 157 */ +/* 2306 */ 0xfc, /* 252 */ + 0x5, /* 5 */ +/* 2308 */ 0x0, /* 0 */ + 0x0, /* 0 */ + + /* Parameter recepientName */ + +/* 2310 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */ +/* 2312 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2314 */ NdrFcShort( 0x68 ), /* Type Offset=104 */ + + /* Parameter recepientId */ + +/* 2316 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2318 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2320 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter callId */ + +/* 2322 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2324 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 2326 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter callAccessHash */ + +/* 2328 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2330 */ NdrFcShort( 0x18 ), /* ARM Stack size/offset = 24 */ +/* 2332 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2334 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2336 */ NdrFcShort( 0x20 ), /* ARM Stack size/offset = 32 */ +/* 2338 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2340 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2342 */ NdrFcShort( 0x24 ), /* ARM Stack size/offset = 36 */ +/* 2344 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure InitiateOutgoingCall1 */ + +/* 2346 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2348 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2352 */ NdrFcShort( 0x1c ), /* 28 */ +/* 2354 */ NdrFcShort( 0x80 ), /* ARM Stack size/offset = 128 */ +/* 2356 */ NdrFcShort( 0x5a ), /* 90 */ +/* 2358 */ NdrFcShort( 0x21 ), /* 33 */ +/* 2360 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x11, /* 17 */ +/* 2362 */ 0x14, /* 20 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 2364 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2366 */ NdrFcShort( 0x1 ), /* 1 */ +/* 2368 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2370 */ NdrFcShort( 0x1f ), /* 31 */ +/* 2372 */ 0x8, /* 8 */ + 0x80, /* 128 */ +/* 2374 */ 0x81, /* 129 */ + 0x82, /* 130 */ +/* 2376 */ 0x83, /* 131 */ + 0x9d, /* 157 */ +/* 2378 */ 0xfc, /* 252 */ + 0x1b, /* 27 */ +/* 2380 */ 0x0, /* 0 */ + 0x0, /* 0 */ + + /* Parameter recepientName */ + +/* 2382 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */ +/* 2384 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2386 */ NdrFcShort( 0x68 ), /* Type Offset=104 */ + + /* Parameter recepientId */ + +/* 2388 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2390 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2392 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter callId */ + +/* 2394 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2396 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 2398 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter callAccessHash */ + +/* 2400 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2402 */ NdrFcShort( 0x18 ), /* ARM Stack size/offset = 24 */ +/* 2404 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter config */ + +/* 2406 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */ +/* 2408 */ NdrFcShort( 0x20 ), /* ARM Stack size/offset = 32 */ +/* 2410 */ NdrFcShort( 0xc2 ), /* Type Offset=194 */ + + /* Parameter __keySize */ + +/* 2412 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2414 */ NdrFcShort( 0x40 ), /* ARM Stack size/offset = 64 */ +/* 2416 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter key */ + +/* 2418 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 2420 */ NdrFcShort( 0x44 ), /* ARM Stack size/offset = 68 */ +/* 2422 */ NdrFcShort( 0x142 ), /* Type Offset=322 */ + + /* Parameter outgoing */ + +/* 2424 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2426 */ NdrFcShort( 0x48 ), /* ARM Stack size/offset = 72 */ +/* 2428 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Parameter __emojisSize */ + +/* 2430 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2432 */ NdrFcShort( 0x4c ), /* ARM Stack size/offset = 76 */ +/* 2434 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter emojis */ + +/* 2436 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 2438 */ NdrFcShort( 0x50 ), /* ARM Stack size/offset = 80 */ +/* 2440 */ NdrFcShort( 0x152 ), /* Type Offset=338 */ + + /* Parameter __endpointsSize */ + +/* 2442 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2444 */ NdrFcShort( 0x54 ), /* ARM Stack size/offset = 84 */ +/* 2446 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter endpoints */ + +/* 2448 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 2450 */ NdrFcShort( 0x58 ), /* ARM Stack size/offset = 88 */ +/* 2452 */ NdrFcShort( 0x16c ), /* Type Offset=364 */ + + /* Parameter allowP2P */ + +/* 2454 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2456 */ NdrFcShort( 0x5c ), /* ARM Stack size/offset = 92 */ +/* 2458 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Parameter connectionMaxLayer */ + +/* 2460 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2462 */ NdrFcShort( 0x60 ), /* ARM Stack size/offset = 96 */ +/* 2464 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter proxy */ + +/* 2466 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */ +/* 2468 */ NdrFcShort( 0x64 ), /* ARM Stack size/offset = 100 */ +/* 2470 */ NdrFcShort( 0x10c ), /* Type Offset=268 */ + + /* Parameter __returnValue */ + +/* 2472 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2474 */ NdrFcShort( 0x78 ), /* ARM Stack size/offset = 120 */ +/* 2476 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2478 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2480 */ NdrFcShort( 0x7c ), /* ARM Stack size/offset = 124 */ +/* 2482 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure OnIncomingCallReceived */ + +/* 2484 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2486 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2490 */ NdrFcShort( 0x1d ), /* 29 */ +/* 2492 */ NdrFcShort( 0x34 ), /* ARM Stack size/offset = 52 */ +/* 2494 */ NdrFcShort( 0x30 ), /* 48 */ +/* 2496 */ NdrFcShort( 0x21 ), /* 33 */ +/* 2498 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x8, /* 8 */ +/* 2500 */ 0x16, /* 22 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 2502 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2504 */ NdrFcShort( 0x1 ), /* 1 */ +/* 2506 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2508 */ NdrFcShort( 0xc ), /* 12 */ +/* 2510 */ 0xa, /* 10 */ + 0x80, /* 128 */ +/* 2512 */ 0x81, /* 129 */ + 0x82, /* 130 */ +/* 2514 */ 0x83, /* 131 */ + 0xfc, /* 252 */ +/* 2516 */ 0x9f, /* 159 */ + 0x9d, /* 157 */ +/* 2518 */ 0xfc, /* 252 */ + 0x6, /* 6 */ +/* 2520 */ 0x0, /* 0 */ + 0x0, /* 0 */ + + /* Parameter contactName */ + +/* 2522 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */ +/* 2524 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2526 */ NdrFcShort( 0x68 ), /* Type Offset=104 */ + + /* Parameter contactId */ + +/* 2528 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2530 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2532 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter contactImage */ + +/* 2534 */ NdrFcShort( 0x8b ), /* Flags: must size, must free, in, by val, */ +/* 2536 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 2538 */ NdrFcShort( 0x68 ), /* Type Offset=104 */ + + /* Parameter callId */ + +/* 2540 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2542 */ NdrFcShort( 0x18 ), /* ARM Stack size/offset = 24 */ +/* 2544 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter callAccessHash */ + +/* 2546 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2548 */ NdrFcShort( 0x20 ), /* ARM Stack size/offset = 32 */ +/* 2550 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter incomingCallDialogDismissedCallback */ + +/* 2552 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 2554 */ NdrFcShort( 0x28 ), /* ARM Stack size/offset = 40 */ +/* 2556 */ NdrFcShort( 0x182 ), /* Type Offset=386 */ + + /* Parameter __returnValue */ + +/* 2558 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2560 */ NdrFcShort( 0x2c ), /* ARM Stack size/offset = 44 */ +/* 2562 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2564 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2566 */ NdrFcShort( 0x30 ), /* ARM Stack size/offset = 48 */ +/* 2568 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure HoldCall */ + +/* 2570 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2572 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2576 */ NdrFcShort( 0x1e ), /* 30 */ +/* 2578 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2580 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2582 */ NdrFcShort( 0x21 ), /* 33 */ +/* 2584 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 2586 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2588 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2590 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2592 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2594 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2596 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2598 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2600 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2602 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2604 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2606 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2608 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2610 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure ResumeCall */ + +/* 2612 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2614 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2618 */ NdrFcShort( 0x1f ), /* 31 */ +/* 2620 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2622 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2624 */ NdrFcShort( 0x21 ), /* 33 */ +/* 2626 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 2628 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2630 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2632 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2634 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2636 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2638 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2640 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2642 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2644 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2646 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2648 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2650 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2652 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure EndCall */ + +/* 2654 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2656 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2660 */ NdrFcShort( 0x20 ), /* 32 */ +/* 2662 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2664 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2666 */ NdrFcShort( 0x21 ), /* 33 */ +/* 2668 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 2670 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2672 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2674 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2676 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2678 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2680 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2682 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2684 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2686 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2688 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2690 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2692 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2694 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure ToggleCamera */ + +/* 2696 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2698 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2702 */ NdrFcShort( 0x21 ), /* 33 */ +/* 2704 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2706 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2708 */ NdrFcShort( 0x21 ), /* 33 */ +/* 2710 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 2712 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2714 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2716 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2718 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2720 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2722 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2724 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2726 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2728 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2730 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2732 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2734 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2736 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_CallStatus */ + +/* 2738 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2740 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2744 */ NdrFcShort( 0x22 ), /* 34 */ +/* 2746 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2748 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2750 */ NdrFcShort( 0x24 ), /* 36 */ +/* 2752 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 2754 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2756 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2758 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2760 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2762 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2764 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2766 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2768 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2770 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2772 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2774 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2776 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2778 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_MediaOperations */ + +/* 2780 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2782 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2786 */ NdrFcShort( 0x23 ), /* 35 */ +/* 2788 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2790 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2792 */ NdrFcShort( 0x24 ), /* 36 */ +/* 2794 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 2796 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2798 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2800 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2802 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2804 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2806 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2808 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2810 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2812 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2814 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2816 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2818 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2820 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_IsShowingVideo */ + +/* 2822 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2824 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2828 */ NdrFcShort( 0x24 ), /* 36 */ +/* 2830 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2832 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2834 */ NdrFcShort( 0x21 ), /* 33 */ +/* 2836 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 2838 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2840 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2842 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2844 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2846 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2848 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2850 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2852 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2854 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2856 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2858 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2860 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2862 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_IsShowingVideo */ + +/* 2864 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2866 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2870 */ NdrFcShort( 0x25 ), /* 37 */ +/* 2872 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2874 */ NdrFcShort( 0x5 ), /* 5 */ +/* 2876 */ NdrFcShort( 0x8 ), /* 8 */ +/* 2878 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 2880 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2882 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2884 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2886 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2888 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2890 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2892 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter value */ + +/* 2894 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2896 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2898 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2900 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2902 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2904 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_IsRenderingVideo */ + +/* 2906 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2908 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2912 */ NdrFcShort( 0x26 ), /* 38 */ +/* 2914 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2916 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2918 */ NdrFcShort( 0x21 ), /* 33 */ +/* 2920 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 2922 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2924 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2926 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2928 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2930 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2932 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2934 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 2936 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 2938 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2940 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2942 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2944 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2946 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_IsRenderingVideo */ + +/* 2948 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2950 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2954 */ NdrFcShort( 0x27 ), /* 39 */ +/* 2956 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 2958 */ NdrFcShort( 0x5 ), /* 5 */ +/* 2960 */ NdrFcShort( 0x8 ), /* 8 */ +/* 2962 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 2964 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 2966 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2968 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2970 */ NdrFcShort( 0x0 ), /* 0 */ +/* 2972 */ NdrFcShort( 0x2 ), /* 2 */ +/* 2974 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 2976 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter value */ + +/* 2978 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 2980 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 2982 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 2984 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 2986 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 2988 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_CameraLocation */ + +/* 2990 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 2992 */ NdrFcLong( 0x0 ), /* 0 */ +/* 2996 */ NdrFcShort( 0x28 ), /* 40 */ +/* 2998 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3000 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3002 */ NdrFcShort( 0x24 ), /* 36 */ +/* 3004 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 3006 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3008 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3010 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3012 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3014 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3016 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3018 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3020 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 3022 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3024 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3026 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3028 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3030 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_AvailableAudioRoutes */ + +/* 3032 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3034 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3038 */ NdrFcShort( 0x29 ), /* 41 */ +/* 3040 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3042 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3044 */ NdrFcShort( 0x24 ), /* 36 */ +/* 3046 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 3048 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3050 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3052 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3054 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3056 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3058 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3060 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3062 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 3064 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3066 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3068 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3070 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3072 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_AudioRoute */ + +/* 3074 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3076 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3080 */ NdrFcShort( 0x2a ), /* 42 */ +/* 3082 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3084 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3086 */ NdrFcShort( 0x24 ), /* 36 */ +/* 3088 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 3090 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3092 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3094 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3096 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3098 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3100 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3102 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3104 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 3106 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3108 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3110 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3112 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3114 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_AudioRoute */ + +/* 3116 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3118 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3122 */ NdrFcShort( 0x2b ), /* 43 */ +/* 3124 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3126 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3128 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3130 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 3132 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3134 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3136 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3138 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3140 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3142 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3144 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter newRoute */ + +/* 3146 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 3148 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3150 */ 0xe, /* FC_ENUM32 */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3152 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3154 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3156 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_OtherPartyName */ + +/* 3158 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3160 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3164 */ NdrFcShort( 0x2c ), /* 44 */ +/* 3166 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3168 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3170 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3172 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 3174 */ 0xe, /* 14 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 3176 */ NdrFcShort( 0x1 ), /* 1 */ +/* 3178 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3180 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3182 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3184 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3186 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3188 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 3190 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3192 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ + + /* Return value */ + +/* 3194 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3196 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3198 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_OtherPartyId */ + +/* 3200 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3202 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3206 */ NdrFcShort( 0x2d ), /* 45 */ +/* 3208 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3210 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3212 */ NdrFcShort( 0x2c ), /* 44 */ +/* 3214 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 3216 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3218 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3220 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3222 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3224 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3226 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3228 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3230 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 3232 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3234 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3236 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3238 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3240 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_CallStartTime */ + +/* 3242 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3244 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3248 */ NdrFcShort( 0x2e ), /* 46 */ +/* 3250 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3252 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3254 */ NdrFcShort( 0x34 ), /* 52 */ +/* 3256 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 3258 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3260 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3262 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3264 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3266 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3268 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3270 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3272 */ NdrFcShort( 0x2112 ), /* Flags: must free, out, simple ref, srv alloc size=8 */ +/* 3274 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3276 */ NdrFcShort( 0x2e ), /* Type Offset=46 */ + + /* Return value */ + +/* 3278 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3280 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3282 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_CallId */ + +/* 3284 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3286 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3290 */ NdrFcShort( 0x2f ), /* 47 */ +/* 3292 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3294 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3296 */ NdrFcShort( 0x2c ), /* 44 */ +/* 3298 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 3300 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3302 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3304 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3306 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3308 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3310 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3312 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3314 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 3316 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3318 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3320 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3322 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3324 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_CallAccessHash */ + +/* 3326 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3328 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3332 */ NdrFcShort( 0x30 ), /* 48 */ +/* 3334 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3336 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3338 */ NdrFcShort( 0x2c ), /* 44 */ +/* 3340 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 3342 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3344 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3346 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3348 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3350 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3352 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3354 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3356 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 3358 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3360 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3362 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3364 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3366 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_AcceptedCallId */ + +/* 3368 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3370 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3374 */ NdrFcShort( 0x31 ), /* 49 */ +/* 3376 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3378 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3380 */ NdrFcShort( 0x2c ), /* 44 */ +/* 3382 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 3384 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3386 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3388 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3390 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3392 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3394 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3396 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3398 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 3400 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3402 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3404 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3406 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3408 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_AcceptedCallId */ + +/* 3410 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3412 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3416 */ NdrFcShort( 0x32 ), /* 50 */ +/* 3418 */ NdrFcShort( 0x14 ), /* ARM Stack size/offset = 20 */ +/* 3420 */ NdrFcShort( 0x10 ), /* 16 */ +/* 3422 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3424 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 3426 */ 0x10, /* 16 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3428 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3430 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3432 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3434 */ NdrFcShort( 0x4 ), /* 4 */ +/* 3436 */ 0x4, /* 4 */ + 0x80, /* 128 */ +/* 3438 */ 0x9f, /* 159 */ + 0x82, /* 130 */ +/* 3440 */ 0x83, /* 131 */ + 0x0, /* 0 */ + + /* Parameter value */ + +/* 3442 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 3444 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3446 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3448 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3450 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 3452 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_Key */ + +/* 3454 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3456 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3460 */ NdrFcShort( 0x33 ), /* 51 */ +/* 3462 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 3464 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3466 */ NdrFcShort( 0x24 ), /* 36 */ +/* 3468 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x3, /* 3 */ +/* 3470 */ 0xe, /* 14 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 3472 */ NdrFcShort( 0x1 ), /* 1 */ +/* 3474 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3476 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3478 */ NdrFcShort( 0x3 ), /* 3 */ +/* 3480 */ 0x3, /* 3 */ + 0x80, /* 128 */ +/* 3482 */ 0x81, /* 129 */ + 0x82, /* 130 */ + + /* Parameter ____returnValueSize */ + +/* 3484 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 3486 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3488 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3490 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */ +/* 3492 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3494 */ NdrFcShort( 0x76 ), /* Type Offset=118 */ + + /* Return value */ + +/* 3496 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3498 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3500 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_Outgoing */ + +/* 3502 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3504 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3508 */ NdrFcShort( 0x34 ), /* 52 */ +/* 3510 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3512 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3514 */ NdrFcShort( 0x21 ), /* 33 */ +/* 3516 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 3518 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3520 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3522 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3524 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3526 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3528 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3530 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3532 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 3534 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3536 */ 0x3, /* FC_SMALL */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3538 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3540 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3542 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_Emojis */ + +/* 3544 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3546 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3550 */ NdrFcShort( 0x35 ), /* 53 */ +/* 3552 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 3554 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3556 */ NdrFcShort( 0x24 ), /* 36 */ +/* 3558 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x3, /* 3 */ +/* 3560 */ 0xe, /* 14 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 3562 */ NdrFcShort( 0x1 ), /* 1 */ +/* 3564 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3566 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3568 */ NdrFcShort( 0x3 ), /* 3 */ +/* 3570 */ 0x3, /* 3 */ + 0x80, /* 128 */ +/* 3572 */ 0x81, /* 129 */ + 0x82, /* 130 */ + + /* Parameter ____returnValueSize */ + +/* 3574 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 3576 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3578 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3580 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */ +/* 3582 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3584 */ NdrFcShort( 0x194 ), /* Type Offset=404 */ + + /* Return value */ + +/* 3586 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3588 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3590 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure Start */ + +/* 3592 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3594 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3598 */ NdrFcShort( 0x6 ), /* 6 */ +/* 3600 */ NdrFcShort( 0x14 ), /* ARM Stack size/offset = 20 */ +/* 3602 */ NdrFcShort( 0x18 ), /* 24 */ +/* 3604 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3606 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x4, /* 4 */ +/* 3608 */ 0x10, /* 16 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3610 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3612 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3614 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3616 */ NdrFcShort( 0x4 ), /* 4 */ +/* 3618 */ 0x4, /* 4 */ + 0x80, /* 128 */ +/* 3620 */ 0x81, /* 129 */ + 0x82, /* 130 */ +/* 3622 */ 0x83, /* 131 */ + 0x0, /* 0 */ + + /* Parameter pts */ + +/* 3624 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 3626 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3628 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter date */ + +/* 3630 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 3632 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3634 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter qts */ + +/* 3636 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 3638 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3640 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3642 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3644 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 3646 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure DiscardCall */ + +/* 3648 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3650 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3654 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3656 */ NdrFcShort( 0x1c ), /* ARM Stack size/offset = 28 */ +/* 3658 */ NdrFcShort( 0x20 ), /* 32 */ +/* 3660 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3662 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x3, /* 3 */ +/* 3664 */ 0x12, /* 18 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3666 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3668 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3670 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3672 */ NdrFcShort( 0x6 ), /* 6 */ +/* 3674 */ 0x6, /* 6 */ + 0x80, /* 128 */ +/* 3676 */ 0x9f, /* 159 */ + 0x82, /* 130 */ +/* 3678 */ 0x83, /* 131 */ + 0xfc, /* 252 */ +/* 3680 */ 0xfc, /* 252 */ + 0x0, /* 0 */ + + /* Parameter id */ + +/* 3682 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 3684 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3686 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter accessHash */ + +/* 3688 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 3690 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 3692 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3694 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3696 */ NdrFcShort( 0x18 ), /* ARM Stack size/offset = 24 */ +/* 3698 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure ReceivedCall */ + +/* 3700 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3702 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3706 */ NdrFcShort( 0x9 ), /* 9 */ +/* 3708 */ NdrFcShort( 0x1c ), /* ARM Stack size/offset = 28 */ +/* 3710 */ NdrFcShort( 0x20 ), /* 32 */ +/* 3712 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3714 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x3, /* 3 */ +/* 3716 */ 0x12, /* 18 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3718 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3720 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3722 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3724 */ NdrFcShort( 0x6 ), /* 6 */ +/* 3726 */ 0x6, /* 6 */ + 0x80, /* 128 */ +/* 3728 */ 0x9f, /* 159 */ + 0x82, /* 130 */ +/* 3730 */ 0x83, /* 131 */ + 0xfc, /* 252 */ +/* 3732 */ 0xfc, /* 252 */ + 0x0, /* 0 */ + + /* Parameter id */ + +/* 3734 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 3736 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3738 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Parameter accessHash */ + +/* 3740 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 3742 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 3744 */ 0xb, /* FC_HYPER */ + 0x0, /* 0 */ + + /* Return value */ + +/* 3746 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3748 */ NdrFcShort( 0x18 ), /* ARM Stack size/offset = 24 */ +/* 3750 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure StartServer */ + +/* 3752 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3754 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3758 */ NdrFcShort( 0x6 ), /* 6 */ +/* 3760 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 3762 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3764 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3766 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x3, /* 3 */ +/* 3768 */ 0xe, /* 14 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 3770 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3772 */ NdrFcShort( 0x1 ), /* 1 */ +/* 3774 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3776 */ NdrFcShort( 0x3 ), /* 3 */ +/* 3778 */ 0x3, /* 3 */ + 0x80, /* 128 */ +/* 3780 */ 0x81, /* 129 */ + 0x82, /* 130 */ + + /* Parameter __outOfProcServerClassNamesSize */ + +/* 3782 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 3784 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3786 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter outOfProcServerClassNames */ + +/* 3788 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 3790 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3792 */ NdrFcShort( 0x1b6 ), /* Type Offset=438 */ + + /* Return value */ + +/* 3794 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3796 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3798 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_CallController */ + +/* 3800 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3802 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3806 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3808 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3810 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3812 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3814 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 3816 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3818 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3820 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3822 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3824 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3826 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3828 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3830 */ NdrFcShort( 0x13 ), /* Flags: must size, must free, out, */ +/* 3832 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3834 */ NdrFcShort( 0x1cc ), /* Type Offset=460 */ + + /* Return value */ + +/* 3836 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3838 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3840 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_VideoRenderer */ + +/* 3842 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3844 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3848 */ NdrFcShort( 0x9 ), /* 9 */ +/* 3850 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3852 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3854 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3856 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 3858 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3860 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3862 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3864 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3866 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3868 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3870 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3872 */ NdrFcShort( 0x13 ), /* Flags: must size, must free, out, */ +/* 3874 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3876 */ NdrFcShort( 0x1e2 ), /* Type Offset=482 */ + + /* Return value */ + +/* 3878 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3880 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3882 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_VideoRenderer */ + +/* 3884 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3886 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3890 */ NdrFcShort( 0xa ), /* 10 */ +/* 3892 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3894 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3896 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3898 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 3900 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3902 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3904 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3906 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3908 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3910 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3912 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter value */ + +/* 3914 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 3916 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3918 */ NdrFcShort( 0x1e6 ), /* Type Offset=486 */ + + /* Return value */ + +/* 3920 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3922 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3924 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_MTProtoUpdater */ + +/* 3926 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3928 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3932 */ NdrFcShort( 0xb ), /* 11 */ +/* 3934 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3936 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3938 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3940 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 3942 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3944 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3946 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3948 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3950 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3952 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3954 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 3956 */ NdrFcShort( 0x13 ), /* Flags: must size, must free, out, */ +/* 3958 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 3960 */ NdrFcShort( 0x1f8 ), /* Type Offset=504 */ + + /* Return value */ + +/* 3962 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 3964 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 3966 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure put_MTProtoUpdater */ + +/* 3968 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 3970 */ NdrFcLong( 0x0 ), /* 0 */ +/* 3974 */ NdrFcShort( 0xc ), /* 12 */ +/* 3976 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 3978 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3980 */ NdrFcShort( 0x8 ), /* 8 */ +/* 3982 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 3984 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 3986 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3988 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3990 */ NdrFcShort( 0x0 ), /* 0 */ +/* 3992 */ NdrFcShort( 0x2 ), /* 2 */ +/* 3994 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 3996 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter value */ + +/* 3998 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 4000 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 4002 */ NdrFcShort( 0x1fc ), /* Type Offset=508 */ + + /* Return value */ + +/* 4004 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 4006 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 4008 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_CaptureController */ + +/* 4010 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 4012 */ NdrFcLong( 0x0 ), /* 0 */ +/* 4016 */ NdrFcShort( 0xd ), /* 13 */ +/* 4018 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 4020 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4022 */ NdrFcShort( 0x8 ), /* 8 */ +/* 4024 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 4026 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 4028 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4030 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4032 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4034 */ NdrFcShort( 0x2 ), /* 2 */ +/* 4036 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 4038 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 4040 */ NdrFcShort( 0x13 ), /* Flags: must size, must free, out, */ +/* 4042 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 4044 */ NdrFcShort( 0x20e ), /* Type Offset=526 */ + + /* Return value */ + +/* 4046 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 4048 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 4050 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_TransportController */ + +/* 4052 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 4054 */ NdrFcLong( 0x0 ), /* 0 */ +/* 4058 */ NdrFcShort( 0xe ), /* 14 */ +/* 4060 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 4062 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4064 */ NdrFcShort( 0x8 ), /* 8 */ +/* 4066 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 4068 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 4070 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4072 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4074 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4076 */ NdrFcShort( 0x2 ), /* 2 */ +/* 4078 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 4080 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 4082 */ NdrFcShort( 0x13 ), /* Flags: must size, must free, out, */ +/* 4084 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 4086 */ NdrFcShort( 0x224 ), /* Type Offset=548 */ + + /* Return value */ + +/* 4088 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 4090 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 4092 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure GetCurrentProcessId */ + +/* 4094 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 4096 */ NdrFcLong( 0x0 ), /* 0 */ +/* 4100 */ NdrFcShort( 0x6 ), /* 6 */ +/* 4102 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 4104 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4106 */ NdrFcShort( 0x24 ), /* 36 */ +/* 4108 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 4110 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 4112 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4114 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4116 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4118 */ NdrFcShort( 0x2 ), /* 2 */ +/* 4120 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 4122 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 4124 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 4126 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 4128 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Return value */ + +/* 4130 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 4132 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 4134 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure GetUiDisconnectedEventName */ + +/* 4136 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 4138 */ NdrFcLong( 0x0 ), /* 0 */ +/* 4142 */ NdrFcShort( 0x7 ), /* 7 */ +/* 4144 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 4146 */ NdrFcShort( 0x8 ), /* 8 */ +/* 4148 */ NdrFcShort( 0x8 ), /* 8 */ +/* 4150 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x3, /* 3 */ +/* 4152 */ 0xe, /* 14 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 4154 */ NdrFcShort( 0x1 ), /* 1 */ +/* 4156 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4158 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4160 */ NdrFcShort( 0x3 ), /* 3 */ +/* 4162 */ 0x3, /* 3 */ + 0x80, /* 128 */ +/* 4164 */ 0x81, /* 129 */ + 0x82, /* 130 */ + + /* Parameter backgroundProcessId */ + +/* 4166 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 4168 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 4170 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 4172 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 4174 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 4176 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ + + /* Return value */ + +/* 4178 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 4180 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 4182 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure GetBackgroundProcessReadyEventName */ + +/* 4184 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 4186 */ NdrFcLong( 0x0 ), /* 0 */ +/* 4190 */ NdrFcShort( 0x8 ), /* 8 */ +/* 4192 */ NdrFcShort( 0x10 ), /* ARM Stack size/offset = 16 */ +/* 4194 */ NdrFcShort( 0x8 ), /* 8 */ +/* 4196 */ NdrFcShort( 0x8 ), /* 8 */ +/* 4198 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x3, /* 3 */ +/* 4200 */ 0xe, /* 14 */ + 0x3, /* Ext Flags: new corr desc, clt corr check, */ +/* 4202 */ NdrFcShort( 0x1 ), /* 1 */ +/* 4204 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4206 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4208 */ NdrFcShort( 0x3 ), /* 3 */ +/* 4210 */ 0x3, /* 3 */ + 0x80, /* 128 */ +/* 4212 */ 0x81, /* 129 */ + 0x82, /* 130 */ + + /* Parameter backgroundProcessId */ + +/* 4214 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 4216 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 4218 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 4220 */ NdrFcShort( 0x2113 ), /* Flags: must size, must free, out, simple ref, srv alloc size=8 */ +/* 4222 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 4224 */ NdrFcShort( 0x5a ), /* Type Offset=90 */ + + /* Return value */ + +/* 4226 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 4228 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 4230 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure get_Instance */ + +/* 4232 */ 0x33, /* FC_AUTO_HANDLE */ + 0x6c, /* Old Flags: object, Oi2 */ +/* 4234 */ NdrFcLong( 0x0 ), /* 0 */ +/* 4238 */ NdrFcShort( 0x9 ), /* 9 */ +/* 4240 */ NdrFcShort( 0xc ), /* ARM Stack size/offset = 12 */ +/* 4242 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4244 */ NdrFcShort( 0x8 ), /* 8 */ +/* 4246 */ 0x45, /* Oi2 Flags: srv must size, has return, has ext, */ + 0x2, /* 2 */ +/* 4248 */ 0xe, /* 14 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 4250 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4252 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4254 */ NdrFcShort( 0x0 ), /* 0 */ +/* 4256 */ NdrFcShort( 0x2 ), /* 2 */ +/* 4258 */ 0x2, /* 2 */ + 0x80, /* 128 */ +/* 4260 */ 0x81, /* 129 */ + 0x0, /* 0 */ + + /* Parameter __returnValue */ + +/* 4262 */ NdrFcShort( 0x13 ), /* Flags: must size, must free, out, */ +/* 4264 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 4266 */ NdrFcShort( 0x228 ), /* Type Offset=552 */ + + /* Return value */ + +/* 4268 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 4270 */ NdrFcShort( 0x8 ), /* ARM Stack size/offset = 8 */ +/* 4272 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + 0x0 + } + }; + +static const PhoneVoIPApp2EBackEnd_MIDL_TYPE_FORMAT_STRING PhoneVoIPApp2EBackEnd__MIDL_TypeFormatString = + { + 0, + { + NdrFcShort( 0x0 ), /* 0 */ +/* 2 */ + 0x2f, /* FC_IP */ + 0x5a, /* FC_CONSTANT_IID */ +/* 4 */ NdrFcLong( 0x905a0fe0 ), /* -1873145888 */ +/* 8 */ NdrFcShort( 0xbc53 ), /* -17325 */ +/* 10 */ NdrFcShort( 0x11df ), /* 4575 */ +/* 12 */ 0x8c, /* 140 */ + 0x49, /* 73 */ +/* 14 */ 0x0, /* 0 */ + 0x1e, /* 30 */ +/* 16 */ 0x4f, /* 79 */ + 0xc6, /* 198 */ +/* 18 */ 0x86, /* 134 */ + 0xda, /* 218 */ +/* 20 */ + 0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */ +/* 22 */ 0x1, /* FC_BYTE */ + 0x5c, /* FC_PAD */ +/* 24 */ + 0x2f, /* FC_IP */ + 0x5a, /* FC_CONSTANT_IID */ +/* 26 */ NdrFcLong( 0xf2035e6a ), /* -234660246 */ +/* 30 */ NdrFcShort( 0x8067 ), /* -32665 */ +/* 32 */ NdrFcShort( 0x3abb ), /* 15035 */ +/* 34 */ 0xa7, /* 167 */ + 0x95, /* 149 */ +/* 36 */ 0x7b, /* 123 */ + 0x33, /* 51 */ +/* 38 */ 0x4c, /* 76 */ + 0x67, /* 103 */ +/* 40 */ 0xa2, /* 162 */ + 0xed, /* 237 */ +/* 42 */ + 0x11, 0x4, /* FC_RP [alloced_on_stack] */ +/* 44 */ NdrFcShort( 0x2 ), /* Offset= 2 (46) */ +/* 46 */ + 0x15, /* FC_STRUCT */ + 0x7, /* 7 */ +/* 48 */ NdrFcShort( 0x8 ), /* 8 */ +/* 50 */ 0xb, /* FC_HYPER */ + 0x5b, /* FC_END */ +/* 52 */ + 0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */ +/* 54 */ 0xb, /* FC_HYPER */ + 0x5c, /* FC_PAD */ +/* 56 */ + 0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */ +/* 58 */ 0x6, /* FC_SHORT */ + 0x5c, /* FC_PAD */ +/* 60 */ + 0x11, 0x4, /* FC_RP [alloced_on_stack] */ +/* 62 */ NdrFcShort( 0x1c ), /* Offset= 28 (90) */ +/* 64 */ + 0x13, 0x0, /* FC_OP */ +/* 66 */ NdrFcShort( 0xe ), /* Offset= 14 (80) */ +/* 68 */ + 0x1b, /* FC_CARRAY */ + 0x1, /* 1 */ +/* 70 */ NdrFcShort( 0x2 ), /* 2 */ +/* 72 */ 0x9, /* Corr desc: FC_ULONG */ + 0x0, /* */ +/* 74 */ NdrFcShort( 0xfffc ), /* -4 */ +/* 76 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 78 */ 0x6, /* FC_SHORT */ + 0x5b, /* FC_END */ +/* 80 */ + 0x17, /* FC_CSTRUCT */ + 0x3, /* 3 */ +/* 82 */ NdrFcShort( 0x8 ), /* 8 */ +/* 84 */ NdrFcShort( 0xfff0 ), /* Offset= -16 (68) */ +/* 86 */ 0x8, /* FC_LONG */ + 0x8, /* FC_LONG */ +/* 88 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 90 */ 0xb4, /* FC_USER_MARSHAL */ + 0x83, /* 131 */ +/* 92 */ NdrFcShort( 0x0 ), /* 0 */ +/* 94 */ NdrFcShort( 0x4 ), /* 4 */ +/* 96 */ NdrFcShort( 0x0 ), /* 0 */ +/* 98 */ NdrFcShort( 0xffde ), /* Offset= -34 (64) */ +/* 100 */ + 0x12, 0x0, /* FC_UP */ +/* 102 */ NdrFcShort( 0xffea ), /* Offset= -22 (80) */ +/* 104 */ 0xb4, /* FC_USER_MARSHAL */ + 0x83, /* 131 */ +/* 106 */ NdrFcShort( 0x0 ), /* 0 */ +/* 108 */ NdrFcShort( 0x4 ), /* 4 */ +/* 110 */ NdrFcShort( 0x0 ), /* 0 */ +/* 112 */ NdrFcShort( 0xfff4 ), /* Offset= -12 (100) */ +/* 114 */ + 0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */ +/* 116 */ 0x8, /* FC_LONG */ + 0x5c, /* FC_PAD */ +/* 118 */ + 0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */ +/* 120 */ NdrFcShort( 0x2 ), /* Offset= 2 (122) */ +/* 122 */ + 0x13, 0x0, /* FC_OP */ +/* 124 */ NdrFcShort( 0x2 ), /* Offset= 2 (126) */ +/* 126 */ + 0x1b, /* FC_CARRAY */ + 0x0, /* 0 */ +/* 128 */ NdrFcShort( 0x1 ), /* 1 */ +/* 130 */ 0x29, /* Corr desc: parameter, FC_ULONG */ + 0x54, /* FC_DEREFERENCE */ +/* 132 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 134 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 136 */ 0x1, /* FC_BYTE */ + 0x5b, /* FC_END */ +/* 138 */ + 0x11, 0x0, /* FC_RP */ +/* 140 */ NdrFcShort( 0x2 ), /* Offset= 2 (142) */ +/* 142 */ + 0x1b, /* FC_CARRAY */ + 0x0, /* 0 */ +/* 144 */ NdrFcShort( 0x1 ), /* 1 */ +/* 146 */ 0x29, /* Corr desc: parameter, FC_ULONG */ + 0x0, /* */ +/* 148 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 150 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 152 */ 0x1, /* FC_BYTE */ + 0x5b, /* FC_END */ +/* 154 */ + 0x2f, /* FC_IP */ + 0x5a, /* FC_CONSTANT_IID */ +/* 156 */ NdrFcLong( 0xf5a3c2ae ), /* -173817170 */ +/* 160 */ NdrFcShort( 0xef7b ), /* -4229 */ +/* 162 */ NdrFcShort( 0x3de2 ), /* 15842 */ +/* 164 */ 0x8b, /* 139 */ + 0xe, /* 14 */ +/* 166 */ 0x8e, /* 142 */ + 0x8b, /* 139 */ +/* 168 */ 0x3c, /* 60 */ + 0xd2, /* 210 */ +/* 170 */ 0xd, /* 13 */ + 0x9d, /* 157 */ +/* 172 */ + 0x2f, /* FC_IP */ + 0x5a, /* FC_CONSTANT_IID */ +/* 174 */ NdrFcLong( 0x1698b961 ), /* 379107681 */ +/* 178 */ NdrFcShort( 0xf90e ), /* -1778 */ +/* 180 */ NdrFcShort( 0x30d0 ), /* 12496 */ +/* 182 */ 0x80, /* 128 */ + 0xff, /* 255 */ +/* 184 */ 0x22, /* 34 */ + 0xe9, /* 233 */ +/* 186 */ 0x4c, /* 76 */ + 0xf6, /* 246 */ +/* 188 */ 0x6d, /* 109 */ + 0x7b, /* 123 */ +/* 190 */ + 0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */ +/* 192 */ 0xc, /* FC_DOUBLE */ + 0x5c, /* FC_PAD */ +/* 194 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x7, /* 7 */ +/* 196 */ NdrFcShort( 0x20 ), /* 32 */ +/* 198 */ NdrFcShort( 0x0 ), /* 0 */ +/* 200 */ NdrFcShort( 0x0 ), /* Offset= 0 (200) */ +/* 202 */ 0xc, /* FC_DOUBLE */ + 0xc, /* FC_DOUBLE */ +/* 204 */ 0xe, /* FC_ENUM32 */ + 0x3, /* FC_SMALL */ +/* 206 */ 0x3, /* FC_SMALL */ + 0x3, /* FC_SMALL */ +/* 208 */ 0x3d, /* FC_STRUCTPAD1 */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 210 */ 0x0, /* 0 */ + NdrFcShort( 0xff95 ), /* Offset= -107 (104) */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 214 */ 0x0, /* 0 */ + NdrFcShort( 0xff91 ), /* Offset= -111 (104) */ + 0x5b, /* FC_END */ +/* 218 */ + 0x11, 0x0, /* FC_RP */ +/* 220 */ NdrFcShort( 0x1a ), /* Offset= 26 (246) */ +/* 222 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x7, /* 7 */ +/* 224 */ NdrFcShort( 0x18 ), /* 24 */ +/* 226 */ NdrFcShort( 0x0 ), /* 0 */ +/* 228 */ NdrFcShort( 0x0 ), /* Offset= 0 (228) */ +/* 230 */ 0xb, /* FC_HYPER */ + 0x6, /* FC_SHORT */ +/* 232 */ 0x3e, /* FC_STRUCTPAD2 */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 234 */ 0x0, /* 0 */ + NdrFcShort( 0xff7d ), /* Offset= -131 (104) */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 238 */ 0x0, /* 0 */ + NdrFcShort( 0xff79 ), /* Offset= -135 (104) */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 242 */ 0x0, /* 0 */ + NdrFcShort( 0xff75 ), /* Offset= -139 (104) */ + 0x5b, /* FC_END */ +/* 246 */ + 0x21, /* FC_BOGUS_ARRAY */ + 0x7, /* 7 */ +/* 248 */ NdrFcShort( 0x0 ), /* 0 */ +/* 250 */ 0x29, /* Corr desc: parameter, FC_ULONG */ + 0x0, /* */ +/* 252 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 254 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 256 */ NdrFcLong( 0xffffffff ), /* -1 */ +/* 260 */ NdrFcShort( 0x0 ), /* Corr flags: */ +/* 262 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 264 */ NdrFcShort( 0xffd6 ), /* Offset= -42 (222) */ +/* 266 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 268 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 270 */ NdrFcShort( 0x14 ), /* 20 */ +/* 272 */ NdrFcShort( 0x0 ), /* 0 */ +/* 274 */ NdrFcShort( 0x0 ), /* Offset= 0 (274) */ +/* 276 */ 0xe, /* FC_ENUM32 */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 278 */ 0x0, /* 0 */ + NdrFcShort( 0xff51 ), /* Offset= -175 (104) */ + 0x6, /* FC_SHORT */ +/* 282 */ 0x3e, /* FC_STRUCTPAD2 */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 284 */ 0x0, /* 0 */ + NdrFcShort( 0xff4b ), /* Offset= -181 (104) */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 288 */ 0x0, /* 0 */ + NdrFcShort( 0xff47 ), /* Offset= -185 (104) */ + 0x5b, /* FC_END */ +/* 292 */ + 0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */ +/* 294 */ 0xe, /* FC_ENUM32 */ + 0x5c, /* FC_PAD */ +/* 296 */ + 0x2f, /* FC_IP */ + 0x5a, /* FC_CONSTANT_IID */ +/* 298 */ NdrFcLong( 0x39126060 ), /* 957505632 */ +/* 302 */ NdrFcShort( 0x292 ), /* 658 */ +/* 304 */ NdrFcShort( 0x36d6 ), /* 14038 */ +/* 306 */ 0xb3, /* 179 */ + 0xf8, /* 248 */ +/* 308 */ 0x9a, /* 154 */ + 0xc4, /* 196 */ +/* 310 */ 0x15, /* 21 */ + 0x6c, /* 108 */ +/* 312 */ 0x65, /* 101 */ + 0x1d, /* 29 */ +/* 314 */ + 0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */ +/* 316 */ 0x3, /* FC_SMALL */ + 0x5c, /* FC_PAD */ +/* 318 */ + 0x11, 0x0, /* FC_RP */ +/* 320 */ NdrFcShort( 0x2 ), /* Offset= 2 (322) */ +/* 322 */ + 0x1b, /* FC_CARRAY */ + 0x0, /* 0 */ +/* 324 */ NdrFcShort( 0x1 ), /* 1 */ +/* 326 */ 0x29, /* Corr desc: parameter, FC_ULONG */ + 0x0, /* */ +/* 328 */ NdrFcShort( 0x40 ), /* ARM Stack size/offset = 64 */ +/* 330 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 332 */ 0x1, /* FC_BYTE */ + 0x5b, /* FC_END */ +/* 334 */ + 0x11, 0x0, /* FC_RP */ +/* 336 */ NdrFcShort( 0x2 ), /* Offset= 2 (338) */ +/* 338 */ + 0x21, /* FC_BOGUS_ARRAY */ + 0x3, /* 3 */ +/* 340 */ NdrFcShort( 0x0 ), /* 0 */ +/* 342 */ 0x29, /* Corr desc: parameter, FC_ULONG */ + 0x0, /* */ +/* 344 */ NdrFcShort( 0x4c ), /* ARM Stack size/offset = 76 */ +/* 346 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 348 */ NdrFcLong( 0xffffffff ), /* -1 */ +/* 352 */ NdrFcShort( 0x0 ), /* Corr flags: */ +/* 354 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 356 */ NdrFcShort( 0xff04 ), /* Offset= -252 (104) */ +/* 358 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 360 */ + 0x11, 0x0, /* FC_RP */ +/* 362 */ NdrFcShort( 0x2 ), /* Offset= 2 (364) */ +/* 364 */ + 0x21, /* FC_BOGUS_ARRAY */ + 0x7, /* 7 */ +/* 366 */ NdrFcShort( 0x0 ), /* 0 */ +/* 368 */ 0x29, /* Corr desc: parameter, FC_ULONG */ + 0x0, /* */ +/* 370 */ NdrFcShort( 0x54 ), /* ARM Stack size/offset = 84 */ +/* 372 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 374 */ NdrFcLong( 0xffffffff ), /* -1 */ +/* 378 */ NdrFcShort( 0x0 ), /* Corr flags: */ +/* 380 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 382 */ NdrFcShort( 0xff60 ), /* Offset= -160 (222) */ +/* 384 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 386 */ + 0x2f, /* FC_IP */ + 0x5a, /* FC_CONSTANT_IID */ +/* 388 */ NdrFcLong( 0x91ddee70 ), /* -1847726480 */ +/* 392 */ NdrFcShort( 0xaa90 ), /* -21872 */ +/* 394 */ NdrFcShort( 0x38e7 ), /* 14567 */ +/* 396 */ 0xb4, /* 180 */ + 0xe5, /* 229 */ +/* 398 */ 0xf7, /* 247 */ + 0x95, /* 149 */ +/* 400 */ 0x95, /* 149 */ + 0x69, /* 105 */ +/* 402 */ 0xcb, /* 203 */ + 0x5c, /* 92 */ +/* 404 */ + 0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */ +/* 406 */ NdrFcShort( 0x2 ), /* Offset= 2 (408) */ +/* 408 */ + 0x13, 0x0, /* FC_OP */ +/* 410 */ NdrFcShort( 0x2 ), /* Offset= 2 (412) */ +/* 412 */ + 0x21, /* FC_BOGUS_ARRAY */ + 0x3, /* 3 */ +/* 414 */ NdrFcShort( 0x0 ), /* 0 */ +/* 416 */ 0x29, /* Corr desc: parameter, FC_ULONG */ + 0x54, /* FC_DEREFERENCE */ +/* 418 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 420 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 422 */ NdrFcLong( 0xffffffff ), /* -1 */ +/* 426 */ NdrFcShort( 0x0 ), /* Corr flags: */ +/* 428 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 430 */ NdrFcShort( 0xfeac ), /* Offset= -340 (90) */ +/* 432 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 434 */ + 0x11, 0x0, /* FC_RP */ +/* 436 */ NdrFcShort( 0x2 ), /* Offset= 2 (438) */ +/* 438 */ + 0x21, /* FC_BOGUS_ARRAY */ + 0x3, /* 3 */ +/* 440 */ NdrFcShort( 0x0 ), /* 0 */ +/* 442 */ 0x29, /* Corr desc: parameter, FC_ULONG */ + 0x0, /* */ +/* 444 */ NdrFcShort( 0x4 ), /* ARM Stack size/offset = 4 */ +/* 446 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 448 */ NdrFcLong( 0xffffffff ), /* -1 */ +/* 452 */ NdrFcShort( 0x0 ), /* Corr flags: */ +/* 454 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 456 */ NdrFcShort( 0xfea0 ), /* Offset= -352 (104) */ +/* 458 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 460 */ + 0x11, 0x10, /* FC_RP [pointer_deref] */ +/* 462 */ NdrFcShort( 0x2 ), /* Offset= 2 (464) */ +/* 464 */ + 0x2f, /* FC_IP */ + 0x5a, /* FC_CONSTANT_IID */ +/* 466 */ NdrFcLong( 0x6b50718 ), /* 112527128 */ +/* 470 */ NdrFcShort( 0x3528 ), /* 13608 */ +/* 472 */ NdrFcShort( 0x3b66 ), /* 15206 */ +/* 474 */ 0xbe, /* 190 */ + 0x76, /* 118 */ +/* 476 */ 0xe1, /* 225 */ + 0x83, /* 131 */ +/* 478 */ 0xaa, /* 170 */ + 0x80, /* 128 */ +/* 480 */ 0xd4, /* 212 */ + 0xa5, /* 165 */ +/* 482 */ + 0x11, 0x10, /* FC_RP [pointer_deref] */ +/* 484 */ NdrFcShort( 0x2 ), /* Offset= 2 (486) */ +/* 486 */ + 0x2f, /* FC_IP */ + 0x5a, /* FC_CONSTANT_IID */ +/* 488 */ NdrFcLong( 0x6928ca7b ), /* 1764280955 */ +/* 492 */ NdrFcShort( 0x166d ), /* 5741 */ +/* 494 */ NdrFcShort( 0x3b37 ), /* 15159 */ +/* 496 */ 0x90, /* 144 */ + 0x10, /* 16 */ +/* 498 */ 0xfb, /* 251 */ + 0xab, /* 171 */ +/* 500 */ 0x2c, /* 44 */ + 0x7e, /* 126 */ +/* 502 */ 0x92, /* 146 */ + 0xb0, /* 176 */ +/* 504 */ + 0x11, 0x10, /* FC_RP [pointer_deref] */ +/* 506 */ NdrFcShort( 0x2 ), /* Offset= 2 (508) */ +/* 508 */ + 0x2f, /* FC_IP */ + 0x5a, /* FC_CONSTANT_IID */ +/* 510 */ NdrFcLong( 0x4fa5f2c4 ), /* 1336275652 */ +/* 514 */ NdrFcShort( 0x8612 ), /* -31214 */ +/* 516 */ NdrFcShort( 0x35c9 ), /* 13769 */ +/* 518 */ 0xbf, /* 191 */ + 0xaa, /* 170 */ +/* 520 */ 0x96, /* 150 */ + 0x7c, /* 124 */ +/* 522 */ 0x2c, /* 44 */ + 0x81, /* 129 */ +/* 524 */ 0x9f, /* 159 */ + 0xa7, /* 167 */ +/* 526 */ + 0x11, 0x10, /* FC_RP [pointer_deref] */ +/* 528 */ NdrFcShort( 0x2 ), /* Offset= 2 (530) */ +/* 530 */ + 0x2f, /* FC_IP */ + 0x5a, /* FC_CONSTANT_IID */ +/* 532 */ NdrFcLong( 0x8313dbea ), /* -2095850518 */ +/* 536 */ NdrFcShort( 0xfd3b ), /* -709 */ +/* 538 */ NdrFcShort( 0x3071 ), /* 12401 */ +/* 540 */ 0x80, /* 128 */ + 0x35, /* 53 */ +/* 542 */ 0x7b, /* 123 */ + 0x61, /* 97 */ +/* 544 */ 0x16, /* 22 */ + 0x58, /* 88 */ +/* 546 */ 0xda, /* 218 */ + 0xd8, /* 216 */ +/* 548 */ + 0x11, 0x10, /* FC_RP [pointer_deref] */ +/* 550 */ NdrFcShort( 0xfe74 ), /* Offset= -396 (154) */ +/* 552 */ + 0x11, 0x10, /* FC_RP [pointer_deref] */ +/* 554 */ NdrFcShort( 0x2 ), /* Offset= 2 (556) */ +/* 556 */ + 0x2f, /* FC_IP */ + 0x5a, /* FC_CONSTANT_IID */ +/* 558 */ NdrFcLong( 0xc8afe1a8 ), /* -927997528 */ +/* 562 */ NdrFcShort( 0x92fc ), /* -27908 */ +/* 564 */ NdrFcShort( 0x3783 ), /* 14211 */ +/* 566 */ 0x95, /* 149 */ + 0x20, /* 32 */ +/* 568 */ 0xd6, /* 214 */ + 0xbb, /* 187 */ +/* 570 */ 0xc5, /* 197 */ + 0x7, /* 7 */ +/* 572 */ 0xb2, /* 178 */ + 0x4a, /* 74 */ + + 0x0 + } + }; + +static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[ WIRE_MARSHAL_TABLE_SIZE ] = + { + + { + HSTRING_UserSize + ,HSTRING_UserMarshal + ,HSTRING_UserUnmarshal + ,HSTRING_UserFree + } + + }; + + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0000, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: IUnknown, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler, ver. 0.0, + GUID={0xF2035E6A,0x8067,0x3ABB,{0xA7,0x95,0x7B,0x33,0x4C,0x67,0xA2,0xED}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_FormatStringOffsetTable[] = + { + 0 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(4) ___x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandlerProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler::Invoke */ +}; + +const CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandlerStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler_ServerInfo, + 4, + 0, /* pure interpreted */ + CStdStubBuffer_METHODS +}; + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler, ver. 0.0, + GUID={0x1698B961,0xF90E,0x30D0,{0x80,0xFF,0x22,0xE9,0x4C,0xF6,0x6D,0x7B}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_FormatStringOffsetTable[] = + { + 58 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(4) ___x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandlerProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler::Invoke */ +}; + +const CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandlerStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler_ServerInfo, + 4, + 0, /* pure interpreted */ + CStdStubBuffer_METHODS +}; + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback, ver. 0.0, + GUID={0x91DDEE70,0xAA90,0x38E7,{0xB4,0xE5,0xF7,0x95,0x95,0x69,0xCB,0x5C}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_FormatStringOffsetTable[] = + { + 100 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(4) ___x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallbackProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback::Invoke */ +}; + +const CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallbackStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback_ServerInfo, + 4, + 0, /* pure interpreted */ + CStdStubBuffer_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0003, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: IInspectable, ver. 0.0, + GUID={0xAF86E2E0,0xB12D,0x4c6a,{0x9C,0x5A,0xD7,0xAA,0x65,0x10,0x1E,0x90}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals, ver. 0.0, + GUID={0xF5A3C2AE,0xEF7B,0x3DE2,{0x8B,0x0E,0x8E,0x8B,0x3C,0xD2,0x0D,0x9D}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 158, + 206, + 272, + 320, + 364, + 412 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(12) ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtualsProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals::WriteAudio */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals::WriteVideo */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals::add_AudioMessageReceived */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals::remove_AudioMessageReceived */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals::add_VideoMessageReceived */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals::remove_VideoMessageReceived */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2 +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtualsStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_ServerInfo, + 12, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0004, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals, ver. 0.0, + GUID={0x044DEA28,0x0E8D,0x3A16,{0xA2,0xC1,0xBE,0x95,0xC0,0xBE,0xD5,0xE5}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 0 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(6) ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtualsProxyVtbl = +{ + 0, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtualsStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_ServerInfo, + 6, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0005, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals, ver. 0.0, + GUID={0x0CC88A54,0x89AF,0x3CC6,{0x9B,0x95,0xF8,0xF2,0x24,0x28,0xAB,0xED}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 456, + 498, + 542, + 584, + 626, + 668, + 710, + 752, + 794, + 842 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(16) ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtualsProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals::get_id */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals::put_id */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals::get_port */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals::put_port */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals::get_ipv4 */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals::put_ipv4 */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals::get_ipv6 */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals::put_ipv6 */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals::get_peerTag */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals::put_peerTag */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2 +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtualsStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_ServerInfo, + 16, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0006, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener, ver. 0.0, + GUID={0x39126060,0x0292,0x36D6,{0xB3,0xF8,0x9A,0xC4,0x15,0x6C,0x65,0x1D}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 890, + 932, + 974, + 1016, + 1058, + 1100 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(12) ___x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListenerProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener::OnSignalBarsChanged */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener::OnCallStateChanged */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener::OnCallStatusChanged */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener::OnCallAudioRouteChanged */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener::OnMediaOperationsChanged */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener::OnCameraLocationChanged */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2 +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListenerStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_ServerInfo, + 12, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0007, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals, ver. 0.0, + GUID={0x8313DBEA,0xFD3B,0x3071,{0x80,0x35,0x7B,0x61,0x16,0x58,0xDA,0xD8}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 1142, + 932, + 1184, + 1218, + 1252, + 412 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(12) ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtualsProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals::SetTransport */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals::Start */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals::Stop */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals::ToggleCamera */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals::add_CameraLocationChanged */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals::remove_CameraLocationChanged */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2 +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtualsStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_ServerInfo, + 12, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0008, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals, ver. 0.0, + GUID={0x64B31D5B,0x1A27,0x37A8,{0xBC,0xBC,0xC0,0xBB,0xD5,0x31,0x4C,0x79}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 0 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(6) ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtualsProxyVtbl = +{ + 0, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtualsStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_ServerInfo, + 6, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0009, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig, ver. 0.0, + GUID={0xA9F22E31,0xD4E1,0x3940,{0xBA,0x20,0xDC,0xB2,0x09,0x73,0xB0,0x9F}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 1300, + 1342, + 1386, + 1428 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(10) ___x_ABI_CPhoneVoIPApp_CBackEnd_CIConfigProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig::get_InitTimeout */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig::put_InitTimeout */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig::get_RecvTimeout */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig::put_RecvTimeout */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2 +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_CIConfigStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_ServerInfo, + 10, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0010, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals, ver. 0.0, + GUID={0x06B50718,0x3528,0x3B66,{0xBE,0x76,0xE1,0x83,0xAA,0x80,0xD4,0xA5}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 1472, + 1506, + 1184, + 1218, + 1540, + 1574, + 1622, + 1678, + 1740, + 1786, + 1820, + 1854, + 1896, + 1938, + 1980, + 2022, + 2064, + 2106, + 2148, + 2190, + 2232, + 2274, + 2346, + 2484, + 2570, + 2612, + 2654, + 2696, + 2738, + 2780, + 2822, + 2864, + 2906, + 2948, + 2990, + 3032, + 3074, + 3116, + 3158, + 3200, + 3242, + 3284, + 3326, + 3368, + 3410, + 3454, + 3502, + 3544 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(54) ___x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtualsProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::HandleUpdatePhoneCall */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::StartMTProtoUpdater */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::StopMTProtoUpdater */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::CreateVoIPControllerWrapper */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::DeleteVoIPControllerWrapper */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::SetConfig */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::SetEncryptionKey */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::SetPublicEndpoints */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::SetProxy */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::Start */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::Connect */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::SetMicMute */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::SwitchSpeaker */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::UpdateServerConfig */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::GetPreferredRelayID */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::GetLastError */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::GetDebugLog */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::GetDebugString */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::GetVersion */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::GetSignalBarsCount */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::SetStatusCallback */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::InitiateOutgoingCall2 */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::InitiateOutgoingCall1 */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::OnIncomingCallReceived */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::HoldCall */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::ResumeCall */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::EndCall */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::ToggleCamera */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_CallStatus */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_MediaOperations */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_IsShowingVideo */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::put_IsShowingVideo */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_IsRenderingVideo */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::put_IsRenderingVideo */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_CameraLocation */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_AvailableAudioRoutes */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_AudioRoute */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::put_AudioRoute */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_OtherPartyName */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_OtherPartyId */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_CallStartTime */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_CallId */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_CallAccessHash */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_AcceptedCallId */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::put_AcceptedCallId */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_Key */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_Outgoing */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals::get_Emojis */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2 +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtualsStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_ServerInfo, + 54, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0011, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer, ver. 0.0, + GUID={0x6928CA7B,0x166D,0x3B37,{0x90,0x10,0xFB,0xAB,0x2C,0x7E,0x92,0xB0}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 1472, + 1506 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(8) ___x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRendererProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer::Start */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer::Stop */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + NdrStubCall2, + NdrStubCall2 +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRendererStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_ServerInfo, + 8, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0012, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater, ver. 0.0, + GUID={0x4FA5F2C4,0x8612,0x35C9,{0xBF,0xAA,0x96,0x7C,0x2C,0x81,0x9F,0xA7}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 3592, + 1506, + 3648, + 3700 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(10) ___x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdaterProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater::Start */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater::Stop */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater::DiscardCall */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater::ReceivedCall */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2 +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdaterStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_ServerInfo, + 10, + &__x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0013, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals, ver. 0.0, + GUID={0xC8AFE1A8,0x92FC,0x3783,{0x95,0x20,0xD6,0xBB,0xC5,0x07,0xB2,0x4A}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 3752, + 1506, + 3800, + 3842, + 3884, + 3926, + 3968, + 4010, + 4052 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(15) ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtualsProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals::StartServer */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals::DoPeriodicKeepAlive */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals::get_CallController */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals::get_VideoRenderer */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals::put_VideoRenderer */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals::get_MTProtoUpdater */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals::put_MTProtoUpdater */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals::get_CaptureController */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals::get_TransportController */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2 +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtualsStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_ServerInfo, + 15, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0014, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + + +/* Object interface: __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics, ver. 0.0, + GUID={0x2C1E9C37,0x6827,0x38F7,{0x85,0x7C,0x02,0x16,0x42,0xCA,0x42,0x8B}} */ + +#pragma code_seg(".orpc") +static const unsigned short __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 4094, + 4136, + 4184, + 4232 + }; + +static const MIDL_STUBLESS_PROXY_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_ProxyInfo = + { + &Object_StubDesc, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_FormatStringOffsetTable[-3], + 0, + 0, + 0 + }; + + +static const MIDL_SERVER_INFO __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_ServerInfo = + { + &Object_StubDesc, + 0, + PhoneVoIPApp2EBackEnd__MIDL_ProcFormatString.Format, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; +CINTERFACE_PROXY_VTABLE(10) ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStaticsProxyVtbl = +{ + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_ProxyInfo, + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics, + IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0 /* IInspectable::GetIids */ , + 0 /* IInspectable::GetRuntimeClassName */ , + 0 /* IInspectable::GetTrustLevel */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics::GetCurrentProcessId */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics::GetUiDisconnectedEventName */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics::GetBackgroundProcessReadyEventName */ , + (void *) (INT_PTR) -1 /* __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics::get_Instance */ +}; + + +static const PRPC_STUB_FUNCTION __x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2, + NdrStubCall2 +}; + +CInterfaceStubVtbl ___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStaticsStubVtbl = +{ + &IID___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_ServerInfo, + 10, + &__x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics_table[-3], + CStdStubBuffer_DELEGATING_METHODS +}; + + +/* Standard interface: __MIDL_itf_PhoneVoIPApp2EBackEnd_0000_0015, ver. 0.0, + GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ + +static const MIDL_STUB_DESC Object_StubDesc = + { + 0, + NdrOleAllocate, + NdrOleFree, + 0, + 0, + 0, + 0, + 0, + PhoneVoIPApp2EBackEnd__MIDL_TypeFormatString.Format, + 1, /* -error bounds_check flag */ + 0x50002, /* Ndr library version */ + 0, + 0x800025b, /* MIDL Version 8.0.603 */ + 0, + UserMarshalRoutines, + 0, /* notify & notify_flag routine table */ + 0x1, /* MIDL flag */ + 0, /* cs routines */ + 0, /* proxy/server info */ + 0 + }; + +const CInterfaceProxyVtbl * const _PhoneVoIPApp2EBackEnd_ProxyVtblList[] = +{ + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtualsProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtualsProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CIConfigProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStaticsProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtualsProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtualsProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListenerProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandlerProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandlerProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallbackProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRendererProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtualsProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtualsProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdaterProxyVtbl, + ( CInterfaceProxyVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtualsProxyVtbl, + 0 +}; + +const CInterfaceStubVtbl * const _PhoneVoIPApp2EBackEnd_StubVtblList[] = +{ + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtualsStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtualsStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CIConfigStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStaticsStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtualsStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtualsStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListenerStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandlerStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandlerStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallbackStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRendererStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtualsStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtualsStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdaterStubVtbl, + ( CInterfaceStubVtbl *) &___x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtualsStubVtbl, + 0 +}; + +PCInterfaceName const _PhoneVoIPApp2EBackEnd_InterfaceNamesList[] = +{ + "__x_ABI_CPhoneVoIPApp_CBackEnd_C____ICallControllerPublicNonVirtuals", + "__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportProtectedNonVirtuals", + "__x_ABI_CPhoneVoIPApp_CBackEnd_CIConfig", + "__x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsStatics", + "__x_ABI_CPhoneVoIPApp_CBackEnd_C____IEndpointPublicNonVirtuals", + "__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCaptureProtectedNonVirtuals", + "__x_ABI_CPhoneVoIPApp_CBackEnd_CICallControllerStatusListener", + "__x_ABI_CPhoneVoIPApp_CBackEnd_CICameraLocationChangedEventHandler", + "__x_ABI_CPhoneVoIPApp_CBackEnd_CIMessageReceivedEventHandler", + "__x_ABI_CPhoneVoIPApp_CBackEnd_CIIncomingCallDialogDismissedCallback", + "__x_ABI_CPhoneVoIPApp_CBackEnd_CIVideoRenderer", + "__x_ABI_CPhoneVoIPApp_CBackEnd_C____IGlobalsPublicNonVirtuals", + "__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndTransportPublicNonVirtuals", + "__x_ABI_CPhoneVoIPApp_CBackEnd_CIMTProtoUpdater", + "__x_ABI_CPhoneVoIPApp_CBackEnd_C____IBackEndCapturePublicNonVirtuals", + 0 +}; + +const IID * const _PhoneVoIPApp2EBackEnd_BaseIIDList[] = +{ + &IID_IInspectable, + &IID_IInspectable, + &IID_IInspectable, + &IID_IInspectable, + &IID_IInspectable, + &IID_IInspectable, + &IID_IInspectable, + 0, + 0, + 0, + &IID_IInspectable, + &IID_IInspectable, + &IID_IInspectable, + &IID_IInspectable, + &IID_IInspectable, + 0 +}; + + +#define _PhoneVoIPApp2EBackEnd_CHECK_IID(n) IID_GENERIC_CHECK_IID( _PhoneVoIPApp2EBackEnd, pIID, n) + +int __stdcall _PhoneVoIPApp2EBackEnd_IID_Lookup( const IID * pIID, int * pIndex ) +{ + IID_BS_LOOKUP_SETUP + + IID_BS_LOOKUP_INITIAL_TEST( _PhoneVoIPApp2EBackEnd, 15, 8 ) + IID_BS_LOOKUP_NEXT_TEST( _PhoneVoIPApp2EBackEnd, 4 ) + IID_BS_LOOKUP_NEXT_TEST( _PhoneVoIPApp2EBackEnd, 2 ) + IID_BS_LOOKUP_NEXT_TEST( _PhoneVoIPApp2EBackEnd, 1 ) + IID_BS_LOOKUP_RETURN_RESULT( _PhoneVoIPApp2EBackEnd, 15, *pIndex ) + +} + +const ExtendedProxyFileInfo PhoneVoIPApp2EBackEnd_ProxyFileInfo = +{ + (PCInterfaceProxyVtblList *) & _PhoneVoIPApp2EBackEnd_ProxyVtblList, + (PCInterfaceStubVtblList *) & _PhoneVoIPApp2EBackEnd_StubVtblList, + (const PCInterfaceName * ) & _PhoneVoIPApp2EBackEnd_InterfaceNamesList, + (const IID ** ) & _PhoneVoIPApp2EBackEnd_BaseIIDList, + & _PhoneVoIPApp2EBackEnd_IID_Lookup, + 15, + 2, + 0, /* table of [async_uuid] interfaces */ + 0, /* Filler1 */ + 0, /* Filler2 */ + 0 /* Filler3 */ +}; +#if _MSC_VER >= 1200 +#pragma warning(pop) +#endif + + +#endif /* if defined(_ARM_) */ + diff --git a/BackEndProxyStub/dlldata.c b/BackEndProxyStub/dlldata.c new file mode 100755 index 0000000..8e8c732 --- /dev/null +++ b/BackEndProxyStub/dlldata.c @@ -0,0 +1,40 @@ +/********************************************************* + DllData file -- generated by MIDL compiler + + DO NOT ALTER THIS FILE + + This file is regenerated by MIDL on every IDL file compile. + + To completely reconstruct this file, delete it and rerun MIDL + on all the IDL files in this DLL, specifying this file for the + /dlldata command line option + +*********************************************************/ + +#define PROXY_DELEGATION + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +EXTERN_PROXY_FILE( PhoneVoIPApp2EBackEnd ) +EXTERN_PROXY_FILE( PhoneVoIPApp2EBackEnd2EOutOfProcess ) + + +PROXYFILE_LIST_START +/* Start of list */ + REFERENCE_PROXY_FILE( PhoneVoIPApp2EBackEnd ), + REFERENCE_PROXY_FILE( PhoneVoIPApp2EBackEnd2EOutOfProcess ), +/* End of list */ +PROXYFILE_LIST_END + + +DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID ) + +#ifdef __cplusplus +} /*extern "C" */ +#endif + +/* end of generated dlldata file */ diff --git a/EmojiPanel/EmojiPanel/App.xaml b/EmojiPanel/EmojiPanel/App.xaml new file mode 100755 index 0000000..826d731 --- /dev/null +++ b/EmojiPanel/EmojiPanel/App.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/EmojiPanel/EmojiPanel/App.xaml.cs b/EmojiPanel/EmojiPanel/App.xaml.cs new file mode 100755 index 0000000..bcc2b02 --- /dev/null +++ b/EmojiPanel/EmojiPanel/App.xaml.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Navigation; +using System.Windows.Shapes; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; + +namespace EmojiPanel +{ + public partial class App : Application + { + /// + /// Provides easy access to the root frame of the Phone Application. + /// + /// The root frame of the Phone Application. + public PhoneApplicationFrame RootFrame { get; private set; } + + /// + /// Constructor for the Application object. + /// + public App() + { + // Global handler for uncaught exceptions. + UnhandledException += Application_UnhandledException; + + // Standard Silverlight initialization + InitializeComponent(); + + // Phone-specific initialization + InitializePhoneApplication(); + + // Show graphics profiling information while debugging. + if (Debugger.IsAttached) + { + // Display the current frame rate counters. + Current.Host.Settings.EnableFrameRateCounter = true; + + // Show the areas of the app that are being redrawn in each frame. + //Application.Current.Host.Settings.EnableRedrawRegions = true; + + // Enable non-production analysis visualization mode, + // which shows areas of a page that are handed off to GPU with a colored overlay. + //Application.Current.Host.Settings.EnableCacheVisualization = true; + + // Disable the application idle detection by setting the UserIdleDetectionMode property of the + // application's PhoneApplicationService object to Disabled. + // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run + // and consume battery power when the user is not using the phone. + PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled; + } + + } + + // Code to execute when the application is launching (eg, from Start) + // This code will not execute when the application is reactivated + private void Application_Launching(object sender, LaunchingEventArgs e) + { + } + + // Code to execute when the application is activated (brought to foreground) + // This code will not execute when the application is first launched + private void Application_Activated(object sender, ActivatedEventArgs e) + { + } + + // Code to execute when the application is deactivated (sent to background) + // This code will not execute when the application is closing + private void Application_Deactivated(object sender, DeactivatedEventArgs e) + { + } + + // Code to execute when the application is closing (eg, user hit Back) + // This code will not execute when the application is deactivated + private void Application_Closing(object sender, ClosingEventArgs e) + { + } + + // Code to execute if a navigation fails + private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e) + { + if (Debugger.IsAttached) + { + // A navigation has failed; break into the debugger + Debugger.Break(); + } + } + + // Code to execute on Unhandled Exceptions + private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) + { + if (Debugger.IsAttached) + { + // An unhandled exception has occurred; break into the debugger + Debugger.Break(); + } + } + + #region Phone application initialization + + // Avoid double-initialization + private bool phoneApplicationInitialized = false; + + // Do not add any additional code to this method + private void InitializePhoneApplication() + { + if (phoneApplicationInitialized) + return; + + // Create the frame but don't set it as RootVisual yet; this allows the splash + // screen to remain active until the application is ready to render. + RootFrame = new PhoneApplicationFrame(); + RootFrame.Navigated += CompleteInitializePhoneApplication; + + // Handle navigation failures + RootFrame.NavigationFailed += RootFrame_NavigationFailed; + + // Ensure we don't initialize again + phoneApplicationInitialized = true; + } + + // Do not add any additional code to this method + private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e) + { + // Set the root visual to allow the application to render + if (RootVisual != RootFrame) + RootVisual = RootFrame; + + // Remove this handler since it is no longer needed + RootFrame.Navigated -= CompleteInitializePhoneApplication; + } + + #endregion + } +} \ No newline at end of file diff --git a/EmojiPanel/EmojiPanel/ApplicationIcon.png b/EmojiPanel/EmojiPanel/ApplicationIcon.png new file mode 100755 index 0000000..5859393 Binary files /dev/null and b/EmojiPanel/EmojiPanel/ApplicationIcon.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/AppBarIcons/appbar.smile.png b/EmojiPanel/EmojiPanel/Assets/AppBarIcons/appbar.smile.png new file mode 100755 index 0000000..a19ddb9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/AppBarIcons/appbar.smile.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0023-fe0f-20e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0023-fe0f-20e3.png new file mode 100755 index 0000000..6765d7d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0023-fe0f-20e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0030-fe0f-20e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0030-fe0f-20e3.png new file mode 100755 index 0000000..15e7446 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0030-fe0f-20e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0031-fe0f-20e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0031-fe0f-20e3.png new file mode 100755 index 0000000..2d1f9f8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0031-fe0f-20e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0032-fe0f-20e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0032-fe0f-20e3.png new file mode 100755 index 0000000..c191f8a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0032-fe0f-20e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0033-fe0f-20e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0033-fe0f-20e3.png new file mode 100755 index 0000000..55644c9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0033-fe0f-20e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0034-fe0f-20e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0034-fe0f-20e3.png new file mode 100755 index 0000000..14782ba Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0034-fe0f-20e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0035-fe0f-20e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0035-fe0f-20e3.png new file mode 100755 index 0000000..794321a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0035-fe0f-20e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0036-fe0f-20e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0036-fe0f-20e3.png new file mode 100755 index 0000000..5688055 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0036-fe0f-20e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0037-fe0f-20e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0037-fe0f-20e3.png new file mode 100755 index 0000000..354e89a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0037-fe0f-20e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0038-fe0f-20e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0038-fe0f-20e3.png new file mode 100755 index 0000000..7bdb422 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0038-fe0f-20e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0039-fe0f-20e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0039-fe0f-20e3.png new file mode 100755 index 0000000..8006cc9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/0039-fe0f-20e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/00a9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/00a9.png new file mode 100755 index 0000000..d59f580 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/00a9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/00ae.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/00ae.png new file mode 100755 index 0000000..e539410 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/00ae.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f004-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f004-fe0f.png new file mode 100755 index 0000000..f51ce65 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f004-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f0cf.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f0cf.png new file mode 100755 index 0000000..4c78f36 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f0cf.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f170.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f170.png new file mode 100755 index 0000000..4908a44 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f170.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f171.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f171.png new file mode 100755 index 0000000..8742b3d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f171.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f17e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f17e.png new file mode 100755 index 0000000..d85f9fb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f17e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f17f-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f17f-fe0f.png new file mode 100755 index 0000000..c24af81 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f17f-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f18e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f18e.png new file mode 100755 index 0000000..2a52220 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f18e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f191.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f191.png new file mode 100755 index 0000000..15ac675 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f191.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f192.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f192.png new file mode 100755 index 0000000..937dcd7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f192.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f193.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f193.png new file mode 100755 index 0000000..c886cf2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f193.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f194.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f194.png new file mode 100755 index 0000000..47437a7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f194.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f195.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f195.png new file mode 100755 index 0000000..28d1570 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f195.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f196.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f196.png new file mode 100755 index 0000000..2ca180a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f196.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f197.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f197.png new file mode 100755 index 0000000..6433d1a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f197.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f198.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f198.png new file mode 100755 index 0000000..e3e16ef Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f198.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f199.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f199.png new file mode 100755 index 0000000..829219a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f199.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f19a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f19a.png new file mode 100755 index 0000000..8636388 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f19a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1e8-1f1f3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1e8-1f1f3.png new file mode 100755 index 0000000..b30dcc5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1e8-1f1f3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1e9-1f1ea.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1e9-1f1ea.png new file mode 100755 index 0000000..16a2854 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1e9-1f1ea.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1ea-1f1f8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1ea-1f1f8.png new file mode 100755 index 0000000..71b30bf Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1ea-1f1f8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1eb-1f1f7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1eb-1f1f7.png new file mode 100755 index 0000000..6311c91 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1eb-1f1f7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1ec-1f1e7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1ec-1f1e7.png new file mode 100755 index 0000000..2a62c7a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1ec-1f1e7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1ee-1f1f9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1ee-1f1f9.png new file mode 100755 index 0000000..70bc9f3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1ee-1f1f9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1ef-1f1f5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1ef-1f1f5.png new file mode 100755 index 0000000..b786efb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1ef-1f1f5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1f0-1f1f7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1f0-1f1f7.png new file mode 100755 index 0000000..b4c0c1b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1f0-1f1f7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1f7-1f1fa.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1f7-1f1fa.png new file mode 100755 index 0000000..55fcf35 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1f7-1f1fa.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1fa-1f1f8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1fa-1f1f8.png new file mode 100755 index 0000000..3813766 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f1fa-1f1f8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f201.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f201.png new file mode 100755 index 0000000..3bef28c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f201.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f202.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f202.png new file mode 100755 index 0000000..387f098 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f202.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f21a-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f21a-fe0f.png new file mode 100755 index 0000000..25f694e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f21a-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f22f-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f22f-fe0f.png new file mode 100755 index 0000000..6557f56 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f22f-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f232.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f232.png new file mode 100755 index 0000000..f550a57 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f232.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f233.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f233.png new file mode 100755 index 0000000..c05f5cf Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f233.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f234.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f234.png new file mode 100755 index 0000000..03ab0d8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f234.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f235.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f235.png new file mode 100755 index 0000000..5df1cb8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f235.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f236.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f236.png new file mode 100755 index 0000000..cd8fb3f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f236.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f237.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f237.png new file mode 100755 index 0000000..e4dfe5a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f237.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f238.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f238.png new file mode 100755 index 0000000..fc4a990 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f238.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f239.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f239.png new file mode 100755 index 0000000..2148253 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f239.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f23a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f23a.png new file mode 100755 index 0000000..ba946d3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f23a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f250.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f250.png new file mode 100755 index 0000000..e79af78 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f250.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f251.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f251.png new file mode 100755 index 0000000..2d20090 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f251.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f300.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f300.png new file mode 100755 index 0000000..6c49f64 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f300.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f301.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f301.png new file mode 100755 index 0000000..3c7b8b0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f301.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f302.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f302.png new file mode 100755 index 0000000..072c5c2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f302.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f303.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f303.png new file mode 100755 index 0000000..d4de585 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f303.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f304.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f304.png new file mode 100755 index 0000000..ebc3db1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f304.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f305.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f305.png new file mode 100755 index 0000000..ec58dcc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f305.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f306.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f306.png new file mode 100755 index 0000000..7cb178a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f306.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f307.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f307.png new file mode 100755 index 0000000..91ca2a4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f307.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f308.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f308.png new file mode 100755 index 0000000..6b1faa0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f308.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f309.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f309.png new file mode 100755 index 0000000..495b06c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f309.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30a.png new file mode 100755 index 0000000..f8d520c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30b.png new file mode 100755 index 0000000..9b43453 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30c.png new file mode 100755 index 0000000..901090a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30d.png new file mode 100755 index 0000000..44ce5ec Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30e.png new file mode 100755 index 0000000..97d7176 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30f.png new file mode 100755 index 0000000..95ec357 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f30f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f310.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f310.png new file mode 100755 index 0000000..b198646 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f310.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f311.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f311.png new file mode 100755 index 0000000..540239b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f311.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f312.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f312.png new file mode 100755 index 0000000..c8f13dd Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f312.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f313.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f313.png new file mode 100755 index 0000000..f38c236 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f313.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f314.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f314.png new file mode 100755 index 0000000..dd8c484 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f314.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f315.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f315.png new file mode 100755 index 0000000..8ff657a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f315.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f316.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f316.png new file mode 100755 index 0000000..8e324ec Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f316.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f317.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f317.png new file mode 100755 index 0000000..355e3c3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f317.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f318.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f318.png new file mode 100755 index 0000000..3038778 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f318.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f319.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f319.png new file mode 100755 index 0000000..afdb450 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f319.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31a.png new file mode 100755 index 0000000..b9aff7a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31b.png new file mode 100755 index 0000000..85ae2ce Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31c.png new file mode 100755 index 0000000..9ece82d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31d.png new file mode 100755 index 0000000..94395a4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31e.png new file mode 100755 index 0000000..ee27663 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31f.png new file mode 100755 index 0000000..8b40ff4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f31f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f320.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f320.png new file mode 100755 index 0000000..097a842 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f320.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f330.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f330.png new file mode 100755 index 0000000..066fb6b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f330.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f331.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f331.png new file mode 100755 index 0000000..f0eb5a6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f331.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f332.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f332.png new file mode 100755 index 0000000..ae8ad10 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f332.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f333.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f333.png new file mode 100755 index 0000000..9bb16bd Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f333.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f334.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f334.png new file mode 100755 index 0000000..d534785 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f334.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f335.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f335.png new file mode 100755 index 0000000..5a2c3cc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f335.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f337.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f337.png new file mode 100755 index 0000000..b3ee110 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f337.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f338.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f338.png new file mode 100755 index 0000000..e031554 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f338.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f339.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f339.png new file mode 100755 index 0000000..3479fbc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f339.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33a.png new file mode 100755 index 0000000..32a3774 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33b.png new file mode 100755 index 0000000..d9bad19 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33c.png new file mode 100755 index 0000000..55a9735 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33d.png new file mode 100755 index 0000000..fe5d8b1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33e.png new file mode 100755 index 0000000..a9bba5c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33f.png new file mode 100755 index 0000000..de1ff1b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f33f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f340.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f340.png new file mode 100755 index 0000000..f2014be Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f340.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f341.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f341.png new file mode 100755 index 0000000..4e9b472 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f341.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f342.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f342.png new file mode 100755 index 0000000..d49f9c1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f342.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f343.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f343.png new file mode 100755 index 0000000..801e578 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f343.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f344.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f344.png new file mode 100755 index 0000000..5eeed8e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f344.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f345.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f345.png new file mode 100755 index 0000000..a129700 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f345.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f346.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f346.png new file mode 100755 index 0000000..566d6a8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f346.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f347.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f347.png new file mode 100755 index 0000000..0f9f007 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f347.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f348.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f348.png new file mode 100755 index 0000000..11c13cb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f348.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f349.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f349.png new file mode 100755 index 0000000..fc212be Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f349.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34a.png new file mode 100755 index 0000000..fc9d4f8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34b.png new file mode 100755 index 0000000..9814dc9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34c.png new file mode 100755 index 0000000..a0563af Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34d.png new file mode 100755 index 0000000..d6f8e28 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34e.png new file mode 100755 index 0000000..08aa17b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34f.png new file mode 100755 index 0000000..337205c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f34f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f350.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f350.png new file mode 100755 index 0000000..f24aca8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f350.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f351.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f351.png new file mode 100755 index 0000000..ee2139e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f351.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f352.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f352.png new file mode 100755 index 0000000..8d3e044 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f352.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f353.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f353.png new file mode 100755 index 0000000..13eb827 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f353.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f354.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f354.png new file mode 100755 index 0000000..9f1a3fd Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f354.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f355.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f355.png new file mode 100755 index 0000000..460367d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f355.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f356.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f356.png new file mode 100755 index 0000000..d6b311b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f356.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f357.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f357.png new file mode 100755 index 0000000..43ad859 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f357.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f358.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f358.png new file mode 100755 index 0000000..954c901 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f358.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f359.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f359.png new file mode 100755 index 0000000..04f8a88 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f359.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35a.png new file mode 100755 index 0000000..f4773ed Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35b.png new file mode 100755 index 0000000..7983c70 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35c.png new file mode 100755 index 0000000..78dc7d5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35d.png new file mode 100755 index 0000000..08de243 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35e.png new file mode 100755 index 0000000..7e7c637 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35f.png new file mode 100755 index 0000000..cfef669 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f35f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f360.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f360.png new file mode 100755 index 0000000..32117fa Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f360.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f361.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f361.png new file mode 100755 index 0000000..2d042ae Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f361.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f362.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f362.png new file mode 100755 index 0000000..73add1c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f362.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f363.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f363.png new file mode 100755 index 0000000..0d179bd Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f363.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f364.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f364.png new file mode 100755 index 0000000..c8c284b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f364.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f365.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f365.png new file mode 100755 index 0000000..a8f2261 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f365.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f366.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f366.png new file mode 100755 index 0000000..871ce09 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f366.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f367.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f367.png new file mode 100755 index 0000000..0d0b382 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f367.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f368.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f368.png new file mode 100755 index 0000000..190be01 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f368.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f369.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f369.png new file mode 100755 index 0000000..ccf8691 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f369.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36a.png new file mode 100755 index 0000000..653edb2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36b.png new file mode 100755 index 0000000..c7ec19d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36c.png new file mode 100755 index 0000000..33722f2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36d.png new file mode 100755 index 0000000..ba55e70 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36e.png new file mode 100755 index 0000000..9f843b4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36f.png new file mode 100755 index 0000000..7327889 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f36f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f370.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f370.png new file mode 100755 index 0000000..efeb9b4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f370.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f371.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f371.png new file mode 100755 index 0000000..c6d99e8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f371.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f372.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f372.png new file mode 100755 index 0000000..6e80b4a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f372.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f373.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f373.png new file mode 100755 index 0000000..c3de6ae Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f373.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f374.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f374.png new file mode 100755 index 0000000..8ba4bc6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f374.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f375.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f375.png new file mode 100755 index 0000000..3ece0b7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f375.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f376.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f376.png new file mode 100755 index 0000000..1f69907 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f376.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f377.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f377.png new file mode 100755 index 0000000..82b0f00 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f377.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f378.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f378.png new file mode 100755 index 0000000..28b45ea Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f378.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f379.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f379.png new file mode 100755 index 0000000..55ca9ee Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f379.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f37a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f37a.png new file mode 100755 index 0000000..cd78bed Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f37a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f37b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f37b.png new file mode 100755 index 0000000..cc5e4ab Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f37b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f37c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f37c.png new file mode 100755 index 0000000..1b2cfe5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f37c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f380.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f380.png new file mode 100755 index 0000000..63ee5ba Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f380.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f381.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f381.png new file mode 100755 index 0000000..552cfdc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f381.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f382.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f382.png new file mode 100755 index 0000000..36e8edc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f382.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f383.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f383.png new file mode 100755 index 0000000..1f7667e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f383.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f384.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f384.png new file mode 100755 index 0000000..d813b95 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f384.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f385.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f385.png new file mode 100755 index 0000000..a2240c0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f385.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f386.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f386.png new file mode 100755 index 0000000..b4eccd5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f386.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f387.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f387.png new file mode 100755 index 0000000..4aabd7e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f387.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f388.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f388.png new file mode 100755 index 0000000..a4d3207 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f388.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f389.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f389.png new file mode 100755 index 0000000..7411b52 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f389.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38a.png new file mode 100755 index 0000000..bd293e3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38b.png new file mode 100755 index 0000000..4733464 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38c.png new file mode 100755 index 0000000..2ffbb26 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38d.png new file mode 100755 index 0000000..fc858d0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38e.png new file mode 100755 index 0000000..47ce339 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38f.png new file mode 100755 index 0000000..540164e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f38f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f390.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f390.png new file mode 100755 index 0000000..efacf5d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f390.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f391.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f391.png new file mode 100755 index 0000000..1436198 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f391.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f392.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f392.png new file mode 100755 index 0000000..edfb19a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f392.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f393.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f393.png new file mode 100755 index 0000000..2e811b0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f393.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a0.png new file mode 100755 index 0000000..765d2c0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a1.png new file mode 100755 index 0000000..54a1dcf Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a2.png new file mode 100755 index 0000000..9180b98 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a3.png new file mode 100755 index 0000000..d84609c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a4.png new file mode 100755 index 0000000..ce19a2b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a5.png new file mode 100755 index 0000000..9c14384 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a6.png new file mode 100755 index 0000000..a990ccf Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a7.png new file mode 100755 index 0000000..ad83000 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a8.png new file mode 100755 index 0000000..d45212b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a9.png new file mode 100755 index 0000000..7d27134 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3a9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3aa.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3aa.png new file mode 100755 index 0000000..4af8719 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3aa.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ab.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ab.png new file mode 100755 index 0000000..cdacf1a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ab.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ac.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ac.png new file mode 100755 index 0000000..4e1dc11 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ac.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ad.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ad.png new file mode 100755 index 0000000..899fbe5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ad.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ae.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ae.png new file mode 100755 index 0000000..59d45ba Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ae.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3af.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3af.png new file mode 100755 index 0000000..0438fe5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3af.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b0.png new file mode 100755 index 0000000..26f1148 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b1.png new file mode 100755 index 0000000..c2c710d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b2.png new file mode 100755 index 0000000..4136e78 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b3.png new file mode 100755 index 0000000..13d8ece Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b4.png new file mode 100755 index 0000000..cc46a6a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b5.png new file mode 100755 index 0000000..68b261b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b6.png new file mode 100755 index 0000000..a13147f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b7.png new file mode 100755 index 0000000..011559a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b8.png new file mode 100755 index 0000000..2b7fa43 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b9.png new file mode 100755 index 0000000..93647a4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3b9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ba.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ba.png new file mode 100755 index 0000000..8d4703f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ba.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3bb.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3bb.png new file mode 100755 index 0000000..0dba5ba Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3bb.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3bc.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3bc.png new file mode 100755 index 0000000..0c927d3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3bc.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3bd.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3bd.png new file mode 100755 index 0000000..0d68bba Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3bd.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3be.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3be.png new file mode 100755 index 0000000..278d904 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3be.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3bf.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3bf.png new file mode 100755 index 0000000..c97de3e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3bf.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c0.png new file mode 100755 index 0000000..ef694be Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c1.png new file mode 100755 index 0000000..ead4a68 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c2.png new file mode 100755 index 0000000..aeda5c8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c3.png new file mode 100755 index 0000000..1ecfd90 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c4.png new file mode 100755 index 0000000..b067e8c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c6.png new file mode 100755 index 0000000..95d3b63 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c7.png new file mode 100755 index 0000000..e3bbaec Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c8.png new file mode 100755 index 0000000..0e4e168 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c9.png new file mode 100755 index 0000000..f8db67d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3c9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ca.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ca.png new file mode 100755 index 0000000..d3878a0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ca.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e0.png new file mode 100755 index 0000000..95b9ee0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e1.png new file mode 100755 index 0000000..eccbfe9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e2.png new file mode 100755 index 0000000..3f20b56 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e3.png new file mode 100755 index 0000000..43b59e3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e4.png new file mode 100755 index 0000000..0f65b14 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e5.png new file mode 100755 index 0000000..c05c493 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e6.png new file mode 100755 index 0000000..1faa877 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e7.png new file mode 100755 index 0000000..c2846e7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e8.png new file mode 100755 index 0000000..d29f276 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e9.png new file mode 100755 index 0000000..44d7db8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3e9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ea.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ea.png new file mode 100755 index 0000000..671696c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ea.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3eb.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3eb.png new file mode 100755 index 0000000..afd922b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3eb.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ec.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ec.png new file mode 100755 index 0000000..68d959c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ec.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ed.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ed.png new file mode 100755 index 0000000..6404634 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ed.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ee.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ee.png new file mode 100755 index 0000000..18730ad Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ee.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ef.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ef.png new file mode 100755 index 0000000..f225ab2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3ef.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3f0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3f0.png new file mode 100755 index 0000000..8229b8a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f3f0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f400.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f400.png new file mode 100755 index 0000000..1c463df Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f400.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f401.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f401.png new file mode 100755 index 0000000..2d777e5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f401.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f402.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f402.png new file mode 100755 index 0000000..f766980 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f402.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f403.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f403.png new file mode 100755 index 0000000..3bcde3e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f403.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f404.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f404.png new file mode 100755 index 0000000..594c921 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f404.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f405.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f405.png new file mode 100755 index 0000000..b0c7d8d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f405.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f406.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f406.png new file mode 100755 index 0000000..8abfc4a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f406.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f407.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f407.png new file mode 100755 index 0000000..5bc993e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f407.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f408.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f408.png new file mode 100755 index 0000000..977c992 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f408.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f409.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f409.png new file mode 100755 index 0000000..e399d60 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f409.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40a.png new file mode 100755 index 0000000..7435d5a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40b.png new file mode 100755 index 0000000..4af657b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40c.png new file mode 100755 index 0000000..e75e69a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40d.png new file mode 100755 index 0000000..ef58933 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40e.png new file mode 100755 index 0000000..4d09c64 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40f.png new file mode 100755 index 0000000..5ea7bfb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f40f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f410.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f410.png new file mode 100755 index 0000000..4be9cf3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f410.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f411.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f411.png new file mode 100755 index 0000000..c7277d2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f411.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f412.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f412.png new file mode 100755 index 0000000..6407035 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f412.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f413.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f413.png new file mode 100755 index 0000000..fab23ad Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f413.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f414.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f414.png new file mode 100755 index 0000000..6d25c0e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f414.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f415.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f415.png new file mode 100755 index 0000000..c7f6a24 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f415.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f416.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f416.png new file mode 100755 index 0000000..fec3374 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f416.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f417.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f417.png new file mode 100755 index 0000000..8196ad4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f417.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f418.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f418.png new file mode 100755 index 0000000..5ca0457 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f418.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f419.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f419.png new file mode 100755 index 0000000..52ce64b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f419.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41a.png new file mode 100755 index 0000000..3145b56 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41b.png new file mode 100755 index 0000000..c2eaf7a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41c.png new file mode 100755 index 0000000..b92d1cc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41d.png new file mode 100755 index 0000000..f537339 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41e.png new file mode 100755 index 0000000..222577c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41f.png new file mode 100755 index 0000000..dc2a3f5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f41f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f420.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f420.png new file mode 100755 index 0000000..a6d7349 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f420.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f421.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f421.png new file mode 100755 index 0000000..a1d47cb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f421.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f422.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f422.png new file mode 100755 index 0000000..04d1d96 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f422.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f423.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f423.png new file mode 100755 index 0000000..005a555 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f423.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f424.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f424.png new file mode 100755 index 0000000..9be8d29 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f424.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f425.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f425.png new file mode 100755 index 0000000..39c25bc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f425.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f426.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f426.png new file mode 100755 index 0000000..e6be8c0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f426.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f427.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f427.png new file mode 100755 index 0000000..d8edbcb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f427.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f428.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f428.png new file mode 100755 index 0000000..e17bd3c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f428.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f429.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f429.png new file mode 100755 index 0000000..adac80b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f429.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42a.png new file mode 100755 index 0000000..c8c7b9f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42b.png new file mode 100755 index 0000000..496c186 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42c.png new file mode 100755 index 0000000..9326077 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42d.png new file mode 100755 index 0000000..8ff162e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42e.png new file mode 100755 index 0000000..12e1ab6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42f.png new file mode 100755 index 0000000..d6cc84a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f42f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f430.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f430.png new file mode 100755 index 0000000..5cb3ef6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f430.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f431.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f431.png new file mode 100755 index 0000000..09b9ef7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f431.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f432.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f432.png new file mode 100755 index 0000000..e5e556b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f432.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f433.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f433.png new file mode 100755 index 0000000..5bb113e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f433.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f434.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f434.png new file mode 100755 index 0000000..78d580a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f434.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f435.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f435.png new file mode 100755 index 0000000..6964cf4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f435.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f436.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f436.png new file mode 100755 index 0000000..389a02b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f436.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f437.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f437.png new file mode 100755 index 0000000..f7f273c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f437.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f438.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f438.png new file mode 100755 index 0000000..cfe11b1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f438.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f439.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f439.png new file mode 100755 index 0000000..ada9c31 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f439.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43a.png new file mode 100755 index 0000000..c60c968 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43b.png new file mode 100755 index 0000000..f5afe92 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43c.png new file mode 100755 index 0000000..a794fb1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43d.png new file mode 100755 index 0000000..38d6124 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43e.png new file mode 100755 index 0000000..89b9fec Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f43e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f440.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f440.png new file mode 100755 index 0000000..dc2216f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f440.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f442.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f442.png new file mode 100755 index 0000000..2bbbf10 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f442.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f443.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f443.png new file mode 100755 index 0000000..ad17c16 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f443.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f444.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f444.png new file mode 100755 index 0000000..826ed11 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f444.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f445.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f445.png new file mode 100755 index 0000000..b0bab12 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f445.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f446.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f446.png new file mode 100755 index 0000000..196d109 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f446.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f447.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f447.png new file mode 100755 index 0000000..658c6d9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f447.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f448.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f448.png new file mode 100755 index 0000000..fee9cac Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f448.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f449.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f449.png new file mode 100755 index 0000000..b04e284 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f449.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44a.png new file mode 100755 index 0000000..2d41fd3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44b.png new file mode 100755 index 0000000..e78402e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44c.png new file mode 100755 index 0000000..3177439 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44d.png new file mode 100755 index 0000000..3a43eca Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44e.png new file mode 100755 index 0000000..e44c042 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44f.png new file mode 100755 index 0000000..d01c982 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f44f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f450.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f450.png new file mode 100755 index 0000000..2cc25bd Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f450.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f451.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f451.png new file mode 100755 index 0000000..39da1d5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f451.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f452.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f452.png new file mode 100755 index 0000000..4cb2e6a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f452.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f453.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f453.png new file mode 100755 index 0000000..a3cf75a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f453.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f454.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f454.png new file mode 100755 index 0000000..80461c6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f454.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f455.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f455.png new file mode 100755 index 0000000..297a6d6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f455.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f456.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f456.png new file mode 100755 index 0000000..d721cea Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f456.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f457.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f457.png new file mode 100755 index 0000000..6434e2e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f457.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f458.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f458.png new file mode 100755 index 0000000..34ffe13 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f458.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f459.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f459.png new file mode 100755 index 0000000..4ff63b4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f459.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45a.png new file mode 100755 index 0000000..aa297c7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45b.png new file mode 100755 index 0000000..8f06a2b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45c.png new file mode 100755 index 0000000..d7adf04 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45d.png new file mode 100755 index 0000000..0bc5879 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45e.png new file mode 100755 index 0000000..ecba9ba Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45f.png new file mode 100755 index 0000000..45b82e6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f45f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f460.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f460.png new file mode 100755 index 0000000..525b6a0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f460.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f461.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f461.png new file mode 100755 index 0000000..aa62cca Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f461.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f462.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f462.png new file mode 100755 index 0000000..58d0fdb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f462.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f463.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f463.png new file mode 100755 index 0000000..d7a2561 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f463.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f464.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f464.png new file mode 100755 index 0000000..d131398 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f464.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f465.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f465.png new file mode 100755 index 0000000..1f3aabc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f465.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f466.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f466.png new file mode 100755 index 0000000..f79f1f2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f466.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f467.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f467.png new file mode 100755 index 0000000..ea41269 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f467.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f468.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f468.png new file mode 100755 index 0000000..d9bfa26 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f468.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f469.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f469.png new file mode 100755 index 0000000..6bf0d2b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f469.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46a.png new file mode 100755 index 0000000..b4b365f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46b.png new file mode 100755 index 0000000..9e51f40 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46c.png new file mode 100755 index 0000000..d1099f2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46d.png new file mode 100755 index 0000000..619646c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46e.png new file mode 100755 index 0000000..43a5a84 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46f.png new file mode 100755 index 0000000..2dfb451 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f46f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f470.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f470.png new file mode 100755 index 0000000..dd0b0cf Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f470.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f471.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f471.png new file mode 100755 index 0000000..c144301 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f471.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f472.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f472.png new file mode 100755 index 0000000..7aad74b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f472.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f473.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f473.png new file mode 100755 index 0000000..036604c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f473.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f474.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f474.png new file mode 100755 index 0000000..149f0cf Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f474.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f475.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f475.png new file mode 100755 index 0000000..f839565 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f475.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f476.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f476.png new file mode 100755 index 0000000..3b29da4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f476.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f477.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f477.png new file mode 100755 index 0000000..4d64860 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f477.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f478.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f478.png new file mode 100755 index 0000000..1ebb2ce Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f478.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f479.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f479.png new file mode 100755 index 0000000..e9f5471 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f479.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47a.png new file mode 100755 index 0000000..bd21b18 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47b.png new file mode 100755 index 0000000..671dd0c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47c.png new file mode 100755 index 0000000..da52c31 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47d.png new file mode 100755 index 0000000..e3fd76a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47e.png new file mode 100755 index 0000000..3840491 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47f.png new file mode 100755 index 0000000..48e5701 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f47f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f480.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f480.png new file mode 100755 index 0000000..bd4ee38 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f480.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f481.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f481.png new file mode 100755 index 0000000..52c0a50 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f481.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f482.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f482.png new file mode 100755 index 0000000..b67b335 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f482.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f483.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f483.png new file mode 100755 index 0000000..6885a0b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f483.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f484.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f484.png new file mode 100755 index 0000000..82f990c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f484.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f485.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f485.png new file mode 100755 index 0000000..6a66e63 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f485.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f486.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f486.png new file mode 100755 index 0000000..dd30d15 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f486.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f487.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f487.png new file mode 100755 index 0000000..902d273 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f487.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f488.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f488.png new file mode 100755 index 0000000..a10cb23 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f488.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f489.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f489.png new file mode 100755 index 0000000..e7e7ab6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f489.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48a.png new file mode 100755 index 0000000..cd84a78 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48b.png new file mode 100755 index 0000000..4ae2c2b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48c.png new file mode 100755 index 0000000..e29981f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48d.png new file mode 100755 index 0000000..8a57fd6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48e.png new file mode 100755 index 0000000..8a5d8da Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48f.png new file mode 100755 index 0000000..d027908 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f48f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f490.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f490.png new file mode 100755 index 0000000..ce63783 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f490.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f491.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f491.png new file mode 100755 index 0000000..c503f40 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f491.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f492.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f492.png new file mode 100755 index 0000000..ead19d5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f492.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f493.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f493.png new file mode 100755 index 0000000..b6628f6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f493.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f494.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f494.png new file mode 100755 index 0000000..a1bc850 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f494.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f495.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f495.png new file mode 100755 index 0000000..b189e9a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f495.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f496.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f496.png new file mode 100755 index 0000000..0826bbc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f496.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f497.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f497.png new file mode 100755 index 0000000..a7491cb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f497.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f498.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f498.png new file mode 100755 index 0000000..4987284 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f498.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f499.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f499.png new file mode 100755 index 0000000..baa29b3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f499.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49a.png new file mode 100755 index 0000000..7289cb8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49b.png new file mode 100755 index 0000000..fa41ce7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49c.png new file mode 100755 index 0000000..d5f8750 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49d.png new file mode 100755 index 0000000..f31c26a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49e.png new file mode 100755 index 0000000..ea3317c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49f.png new file mode 100755 index 0000000..b40a486 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f49f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a0.png new file mode 100755 index 0000000..dfd1098 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a1.png new file mode 100755 index 0000000..23afca1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a2.png new file mode 100755 index 0000000..6fb4dca Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a3.png new file mode 100755 index 0000000..3289787 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a4.png new file mode 100755 index 0000000..30be046 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a5.png new file mode 100755 index 0000000..bddeb8f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a6.png new file mode 100755 index 0000000..a83b3e9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a7.png new file mode 100755 index 0000000..9eff463 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a8.png new file mode 100755 index 0000000..dc2c0a8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a9.png new file mode 100755 index 0000000..73a4dc8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4a9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4aa.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4aa.png new file mode 100755 index 0000000..19f92ef Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4aa.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ab.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ab.png new file mode 100755 index 0000000..55213d2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ab.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ac.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ac.png new file mode 100755 index 0000000..2896c27 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ac.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ad.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ad.png new file mode 100755 index 0000000..701bdf0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ad.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ae.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ae.png new file mode 100755 index 0000000..c0929d0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ae.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4af.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4af.png new file mode 100755 index 0000000..bce9ab1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4af.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b0.png new file mode 100755 index 0000000..5546c04 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b1.png new file mode 100755 index 0000000..d5ee21f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b2.png new file mode 100755 index 0000000..361e26a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b3.png new file mode 100755 index 0000000..be1c1dd Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b4.png new file mode 100755 index 0000000..139bc93 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b5.png new file mode 100755 index 0000000..63de884 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b6.png new file mode 100755 index 0000000..1c5904b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b7.png new file mode 100755 index 0000000..f8be91d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b8.png new file mode 100755 index 0000000..135e398 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b9.png new file mode 100755 index 0000000..ac2c4bb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4b9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ba.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ba.png new file mode 100755 index 0000000..d1cb864 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ba.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4bb.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4bb.png new file mode 100755 index 0000000..d4d2687 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4bb.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4bc.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4bc.png new file mode 100755 index 0000000..46e82b0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4bc.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4bd.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4bd.png new file mode 100755 index 0000000..e19cc5d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4bd.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4be.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4be.png new file mode 100755 index 0000000..4ad5631 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4be.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4bf.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4bf.png new file mode 100755 index 0000000..baff835 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4bf.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c0.png new file mode 100755 index 0000000..363c83d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c1.png new file mode 100755 index 0000000..4d8bebf Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c2.png new file mode 100755 index 0000000..2bbbbf5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c3.png new file mode 100755 index 0000000..bf8f979 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c4.png new file mode 100755 index 0000000..64cd2e1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c5.png new file mode 100755 index 0000000..6ad2efa Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c6.png new file mode 100755 index 0000000..900b868 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c7.png new file mode 100755 index 0000000..374e94e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c8.png new file mode 100755 index 0000000..de3e9ba Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c9.png new file mode 100755 index 0000000..65b82f0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4c9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ca.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ca.png new file mode 100755 index 0000000..7871cc6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ca.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4cb.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4cb.png new file mode 100755 index 0000000..e2c74e6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4cb.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4cc.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4cc.png new file mode 100755 index 0000000..540c4ec Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4cc.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4cd.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4cd.png new file mode 100755 index 0000000..e498e92 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4cd.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ce.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ce.png new file mode 100755 index 0000000..774412d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ce.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4cf.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4cf.png new file mode 100755 index 0000000..af8cb4b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4cf.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d0.png new file mode 100755 index 0000000..383677c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d1.png new file mode 100755 index 0000000..0c4e3bf Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d2.png new file mode 100755 index 0000000..e4f72ac Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d3.png new file mode 100755 index 0000000..07ea608 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d4.png new file mode 100755 index 0000000..4f3b14c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d5.png new file mode 100755 index 0000000..484029c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d6.png new file mode 100755 index 0000000..8b69841 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d7.png new file mode 100755 index 0000000..e86651e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d8.png new file mode 100755 index 0000000..e2b9e8c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d9.png new file mode 100755 index 0000000..49650d5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4d9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4da.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4da.png new file mode 100755 index 0000000..dca06a1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4da.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4db.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4db.png new file mode 100755 index 0000000..2b712dc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4db.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4dc.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4dc.png new file mode 100755 index 0000000..c5a10e6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4dc.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4dd.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4dd.png new file mode 100755 index 0000000..fc97ddb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4dd.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4de.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4de.png new file mode 100755 index 0000000..36e21e0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4de.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4df.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4df.png new file mode 100755 index 0000000..e3e1fc4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4df.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e0.png new file mode 100755 index 0000000..62be2c9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e1.png new file mode 100755 index 0000000..3481cc2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e2.png new file mode 100755 index 0000000..752385e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e3.png new file mode 100755 index 0000000..5d9319e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e4.png new file mode 100755 index 0000000..7ad15e6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e5.png new file mode 100755 index 0000000..e2df0f8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e6.png new file mode 100755 index 0000000..26602af Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e7.png new file mode 100755 index 0000000..176a8e1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e8.png new file mode 100755 index 0000000..afc8271 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e9.png new file mode 100755 index 0000000..0e01fd5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4e9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ea.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ea.png new file mode 100755 index 0000000..a5982b6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ea.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4eb.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4eb.png new file mode 100755 index 0000000..8351e70 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4eb.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ec.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ec.png new file mode 100755 index 0000000..dae3459 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ec.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ed.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ed.png new file mode 100755 index 0000000..59f15c5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ed.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ee.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ee.png new file mode 100755 index 0000000..ce04b70 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ee.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ef.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ef.png new file mode 100755 index 0000000..e9b713b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4ef.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f0.png new file mode 100755 index 0000000..d171394 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f1.png new file mode 100755 index 0000000..df00710 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f2.png new file mode 100755 index 0000000..837897f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f3.png new file mode 100755 index 0000000..a716e96 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f4.png new file mode 100755 index 0000000..fa16c76 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f5.png new file mode 100755 index 0000000..41df57c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f6.png new file mode 100755 index 0000000..a4bd23e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f7.png new file mode 100755 index 0000000..397d03b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f9.png new file mode 100755 index 0000000..274cecd Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4f9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4fa.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4fa.png new file mode 100755 index 0000000..803dc3d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4fa.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4fb.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4fb.png new file mode 100755 index 0000000..ea589ef Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4fb.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4fc.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4fc.png new file mode 100755 index 0000000..881081c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f4fc.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f500.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f500.png new file mode 100755 index 0000000..25cde18 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f500.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f501.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f501.png new file mode 100755 index 0000000..80113b6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f501.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f502.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f502.png new file mode 100755 index 0000000..3c47bcc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f502.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f503.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f503.png new file mode 100755 index 0000000..5f84d7e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f503.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f504.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f504.png new file mode 100755 index 0000000..1933ae1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f504.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f505.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f505.png new file mode 100755 index 0000000..ea15bde Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f505.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f506.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f506.png new file mode 100755 index 0000000..ba9de7d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f506.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f507.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f507.png new file mode 100755 index 0000000..4cf67c3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f507.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f508.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f508.png new file mode 100755 index 0000000..c884bd4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f508.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f509.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f509.png new file mode 100755 index 0000000..6aa4dbf Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f509.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50a.png new file mode 100755 index 0000000..f63e814 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50b.png new file mode 100755 index 0000000..aa7eedc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50c.png new file mode 100755 index 0000000..7a3d6ce Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50d.png new file mode 100755 index 0000000..aa5b1d7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50e.png new file mode 100755 index 0000000..6e6cf11 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50f.png new file mode 100755 index 0000000..375e67e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f50f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f510.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f510.png new file mode 100755 index 0000000..e6fdf6c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f510.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f511.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f511.png new file mode 100755 index 0000000..3467321 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f511.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f512.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f512.png new file mode 100755 index 0000000..4892b02 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f512.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f513.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f513.png new file mode 100755 index 0000000..22b429c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f513.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f514.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f514.png new file mode 100755 index 0000000..69acceb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f514.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f515.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f515.png new file mode 100755 index 0000000..613b81c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f515.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f516.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f516.png new file mode 100755 index 0000000..dbee45c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f516.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f517.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f517.png new file mode 100755 index 0000000..ffb8f62 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f517.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f518.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f518.png new file mode 100755 index 0000000..63755ee Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f518.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f519.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f519.png new file mode 100755 index 0000000..0cde628 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f519.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51a.png new file mode 100755 index 0000000..edb0bda Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51b.png new file mode 100755 index 0000000..3595387 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51c.png new file mode 100755 index 0000000..9386615 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51d.png new file mode 100755 index 0000000..5aa4dd4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51e.png new file mode 100755 index 0000000..a789b3c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51f.png new file mode 100755 index 0000000..71dac1c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f51f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f520.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f520.png new file mode 100755 index 0000000..ffc0cba Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f520.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f521.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f521.png new file mode 100755 index 0000000..5218470 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f521.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f522.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f522.png new file mode 100755 index 0000000..c47c2e1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f522.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f523.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f523.png new file mode 100755 index 0000000..16bc1da Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f523.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f524.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f524.png new file mode 100755 index 0000000..505d40a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f524.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f525.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f525.png new file mode 100755 index 0000000..f2a3149 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f525.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f526.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f526.png new file mode 100755 index 0000000..215940a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f526.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f527.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f527.png new file mode 100755 index 0000000..a87072a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f527.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f528.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f528.png new file mode 100755 index 0000000..6b75bc3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f528.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f529.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f529.png new file mode 100755 index 0000000..bddfa72 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f529.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52a.png new file mode 100755 index 0000000..18eade0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52b.png new file mode 100755 index 0000000..c49dc52 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52c.png new file mode 100755 index 0000000..f11d54c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52d.png new file mode 100755 index 0000000..51fd8a0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52e.png new file mode 100755 index 0000000..6d2c6c4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52f.png new file mode 100755 index 0000000..010f8f5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f52f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f530.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f530.png new file mode 100755 index 0000000..1f022d1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f530.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f531.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f531.png new file mode 100755 index 0000000..d79a7b4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f531.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f532.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f532.png new file mode 100755 index 0000000..7332e39 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f532.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f533.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f533.png new file mode 100755 index 0000000..63c7a3e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f533.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f534.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f534.png new file mode 100755 index 0000000..b391289 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f534.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f535.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f535.png new file mode 100755 index 0000000..a5b4ad4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f535.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f536.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f536.png new file mode 100755 index 0000000..46d52e5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f536.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f537.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f537.png new file mode 100755 index 0000000..f4598ec Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f537.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f538.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f538.png new file mode 100755 index 0000000..04941d3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f538.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f539.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f539.png new file mode 100755 index 0000000..5a7b5d5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f539.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f53a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f53a.png new file mode 100755 index 0000000..8c4428d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f53a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f53b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f53b.png new file mode 100755 index 0000000..94832f0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f53b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f53c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f53c.png new file mode 100755 index 0000000..1217331 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f53c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f53d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f53d.png new file mode 100755 index 0000000..f7f2d51 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f53d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f550.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f550.png new file mode 100755 index 0000000..ca34e89 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f550.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f551.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f551.png new file mode 100755 index 0000000..1a12524 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f551.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f552.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f552.png new file mode 100755 index 0000000..cd99bb1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f552.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f553.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f553.png new file mode 100755 index 0000000..7274e8b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f553.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f554.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f554.png new file mode 100755 index 0000000..3ed5a81 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f554.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f555.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f555.png new file mode 100755 index 0000000..ac38cb9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f555.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f556.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f556.png new file mode 100755 index 0000000..6a138df Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f556.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f557.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f557.png new file mode 100755 index 0000000..6690cd7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f557.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f558.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f558.png new file mode 100755 index 0000000..c4ad746 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f558.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f559.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f559.png new file mode 100755 index 0000000..f710bef Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f559.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55a.png new file mode 100755 index 0000000..fbc165b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55b.png new file mode 100755 index 0000000..c1ca82f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55c.png new file mode 100755 index 0000000..df93920 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55d.png new file mode 100755 index 0000000..f12c691 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55e.png new file mode 100755 index 0000000..1dc9628 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55f.png new file mode 100755 index 0000000..7726aae Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f55f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f560.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f560.png new file mode 100755 index 0000000..e08d4ad Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f560.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f561.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f561.png new file mode 100755 index 0000000..46f0681 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f561.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f562.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f562.png new file mode 100755 index 0000000..18aab22 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f562.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f563.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f563.png new file mode 100755 index 0000000..ec3e382 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f563.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f564.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f564.png new file mode 100755 index 0000000..fd35221 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f564.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f565.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f565.png new file mode 100755 index 0000000..84a3bc8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f565.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f566.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f566.png new file mode 100755 index 0000000..415999e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f566.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f567.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f567.png new file mode 100755 index 0000000..a652715 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f567.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5fb.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5fb.png new file mode 100755 index 0000000..4c313e5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5fb.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5fc.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5fc.png new file mode 100755 index 0000000..e1cbd7a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5fc.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5fd.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5fd.png new file mode 100755 index 0000000..9ad9028 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5fd.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5fe.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5fe.png new file mode 100755 index 0000000..4593280 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5fe.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5ff.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5ff.png new file mode 100755 index 0000000..61a1a9c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f5ff.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f600.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f600.png new file mode 100755 index 0000000..0ef00d7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f600.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f601.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f601.png new file mode 100755 index 0000000..591cfce Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f601.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f602.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f602.png new file mode 100755 index 0000000..47df693 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f602.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f603.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f603.png new file mode 100755 index 0000000..77b581d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f603.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f604.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f604.png new file mode 100755 index 0000000..81a8396 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f604.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f605.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f605.png new file mode 100755 index 0000000..3903f71 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f605.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f606.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f606.png new file mode 100755 index 0000000..11c91eb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f606.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f607.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f607.png new file mode 100755 index 0000000..503b614 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f607.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f608.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f608.png new file mode 100755 index 0000000..d904049 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f608.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f609.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f609.png new file mode 100755 index 0000000..756766d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f609.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60a.png new file mode 100755 index 0000000..1e9021c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60b.png new file mode 100755 index 0000000..fc39637 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60c.png new file mode 100755 index 0000000..820cf31 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60d.png new file mode 100755 index 0000000..0e57942 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60e.png new file mode 100755 index 0000000..1c468a1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60f.png new file mode 100755 index 0000000..bc6e508 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f60f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f610.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f610.png new file mode 100755 index 0000000..682a1ba Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f610.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f611.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f611.png new file mode 100755 index 0000000..1798f24 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f611.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f612.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f612.png new file mode 100755 index 0000000..3722e6f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f612.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f613.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f613.png new file mode 100755 index 0000000..e894b76 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f613.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f614.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f614.png new file mode 100755 index 0000000..2f3bad9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f614.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f615.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f615.png new file mode 100755 index 0000000..18ff760 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f615.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f616.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f616.png new file mode 100755 index 0000000..a5877a0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f616.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f617.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f617.png new file mode 100755 index 0000000..eb049c8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f617.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f618.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f618.png new file mode 100755 index 0000000..af9a80b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f618.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f619.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f619.png new file mode 100755 index 0000000..d85706e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f619.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61a.png new file mode 100755 index 0000000..449de19 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61b.png new file mode 100755 index 0000000..53c4143 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61c.png new file mode 100755 index 0000000..6ae9d49 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61d.png new file mode 100755 index 0000000..333716e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61e.png new file mode 100755 index 0000000..8255200 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61f.png new file mode 100755 index 0000000..afd9283 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f61f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f620.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f620.png new file mode 100755 index 0000000..34174f5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f620.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f621.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f621.png new file mode 100755 index 0000000..c65ddff Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f621.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f622.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f622.png new file mode 100755 index 0000000..6d0d9af Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f622.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f623.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f623.png new file mode 100755 index 0000000..c7e433e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f623.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f624.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f624.png new file mode 100755 index 0000000..92f93bd Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f624.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f625.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f625.png new file mode 100755 index 0000000..fa5f9e7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f625.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f626.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f626.png new file mode 100755 index 0000000..7f8b6c7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f626.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f627.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f627.png new file mode 100755 index 0000000..c2edad7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f627.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f628.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f628.png new file mode 100755 index 0000000..513fce4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f628.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f629.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f629.png new file mode 100755 index 0000000..0c54754 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f629.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62a.png new file mode 100755 index 0000000..df4f55e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62b.png new file mode 100755 index 0000000..3a8eefe Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62c.png new file mode 100755 index 0000000..f78e940 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62d.png new file mode 100755 index 0000000..7d43318 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62e.png new file mode 100755 index 0000000..e528358 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62f.png new file mode 100755 index 0000000..afa3f66 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f62f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f630.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f630.png new file mode 100755 index 0000000..b9e39bc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f630.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f631.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f631.png new file mode 100755 index 0000000..76bfc6b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f631.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f632.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f632.png new file mode 100755 index 0000000..858a834 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f632.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f633.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f633.png new file mode 100755 index 0000000..9b49410 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f633.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f634.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f634.png new file mode 100755 index 0000000..a2f3bf7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f634.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f635.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f635.png new file mode 100755 index 0000000..8001d6f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f635.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f636.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f636.png new file mode 100755 index 0000000..d9ec7ca Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f636.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f637.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f637.png new file mode 100755 index 0000000..05887e9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f637.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f638.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f638.png new file mode 100755 index 0000000..ad333ba Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f638.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f639.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f639.png new file mode 100755 index 0000000..6c60cb0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f639.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63a.png new file mode 100755 index 0000000..dbf1b02 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63b.png new file mode 100755 index 0000000..eeba240 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63c.png new file mode 100755 index 0000000..351565e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63d.png new file mode 100755 index 0000000..adc62fb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63e.png new file mode 100755 index 0000000..4325fd4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63f.png new file mode 100755 index 0000000..42d4c27 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f63f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f640.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f640.png new file mode 100755 index 0000000..d94cd34 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f640.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f645.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f645.png new file mode 100755 index 0000000..d459a35 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f645.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f646.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f646.png new file mode 100755 index 0000000..e8b9819 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f646.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f647.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f647.png new file mode 100755 index 0000000..024cb61 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f647.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f648.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f648.png new file mode 100755 index 0000000..0890a62 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f648.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f649.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f649.png new file mode 100755 index 0000000..f97a1f9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f649.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64a.png new file mode 100755 index 0000000..87944c4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64b.png new file mode 100755 index 0000000..e1741a4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64c.png new file mode 100755 index 0000000..e03142b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64d.png new file mode 100755 index 0000000..6f34d5e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64e.png new file mode 100755 index 0000000..c4a95c3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64f.png new file mode 100755 index 0000000..f86c992 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f64f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f680.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f680.png new file mode 100755 index 0000000..783078d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f680.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f681.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f681.png new file mode 100755 index 0000000..8e82a0d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f681.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f682.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f682.png new file mode 100755 index 0000000..5495077 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f682.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f683.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f683.png new file mode 100755 index 0000000..2236115 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f683.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f684.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f684.png new file mode 100755 index 0000000..8eca368 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f684.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f685.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f685.png new file mode 100755 index 0000000..16651ac Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f685.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f686.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f686.png new file mode 100755 index 0000000..9c0d3ab Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f686.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f687.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f687.png new file mode 100755 index 0000000..7f34f6b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f687.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f688.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f688.png new file mode 100755 index 0000000..bcfe801 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f688.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f689.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f689.png new file mode 100755 index 0000000..e77daa8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f689.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68a.png new file mode 100755 index 0000000..5eb29fb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68b.png new file mode 100755 index 0000000..0a8ea52 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68c.png new file mode 100755 index 0000000..823aa39 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68d.png new file mode 100755 index 0000000..3695f76 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68e.png new file mode 100755 index 0000000..b9740a5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68f.png new file mode 100755 index 0000000..99af232 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f68f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f690.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f690.png new file mode 100755 index 0000000..c52cef2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f690.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f691.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f691.png new file mode 100755 index 0000000..b740f45 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f691.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f692.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f692.png new file mode 100755 index 0000000..9e6c59c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f692.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f693.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f693.png new file mode 100755 index 0000000..b8f1727 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f693.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f694.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f694.png new file mode 100755 index 0000000..af20e7e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f694.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f695.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f695.png new file mode 100755 index 0000000..60a50d3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f695.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f696.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f696.png new file mode 100755 index 0000000..f78cf31 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f696.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f697.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f697.png new file mode 100755 index 0000000..d70a2f0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f697.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f698.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f698.png new file mode 100755 index 0000000..cb46de2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f698.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f699.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f699.png new file mode 100755 index 0000000..978291e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f699.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69a.png new file mode 100755 index 0000000..3f25ba1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69b.png new file mode 100755 index 0000000..81ec1f9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69c.png new file mode 100755 index 0000000..058fd3e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69d.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69d.png new file mode 100755 index 0000000..913d300 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69d.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69e.png new file mode 100755 index 0000000..1f3d1aa Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69f.png new file mode 100755 index 0000000..aaa45f6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f69f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a0.png new file mode 100755 index 0000000..5688bb2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a1.png new file mode 100755 index 0000000..38f6dfe Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a2.png new file mode 100755 index 0000000..5d2d8b6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a3.png new file mode 100755 index 0000000..fe8ae3e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a4.png new file mode 100755 index 0000000..da6689b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a5.png new file mode 100755 index 0000000..42eaf70 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a6.png new file mode 100755 index 0000000..7a5ba35 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a7.png new file mode 100755 index 0000000..523e9f1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a8.png new file mode 100755 index 0000000..6cf4a77 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a9.png new file mode 100755 index 0000000..f9a3f32 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6a9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6aa.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6aa.png new file mode 100755 index 0000000..83c819a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6aa.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ab.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ab.png new file mode 100755 index 0000000..a8444d1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ab.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ac.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ac.png new file mode 100755 index 0000000..4aad6cb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ac.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ad.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ad.png new file mode 100755 index 0000000..eb11d79 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ad.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ae.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ae.png new file mode 100755 index 0000000..c2e350c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ae.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6af.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6af.png new file mode 100755 index 0000000..38c7ae7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6af.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b0.png new file mode 100755 index 0000000..e9fd560 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b1.png new file mode 100755 index 0000000..1b29d35 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b2.png new file mode 100755 index 0000000..6573860 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b3.png new file mode 100755 index 0000000..4b26216 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b4.png new file mode 100755 index 0000000..4e3e054 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b5.png new file mode 100755 index 0000000..b698897 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b6.png new file mode 100755 index 0000000..7a2bfac Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b7.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b7.png new file mode 100755 index 0000000..c35f530 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b7.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b8.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b8.png new file mode 100755 index 0000000..b0302ae Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b8.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b9.png new file mode 100755 index 0000000..abccfc9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6b9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ba.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ba.png new file mode 100755 index 0000000..518b76a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6ba.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6bb.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6bb.png new file mode 100755 index 0000000..312ca3d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6bb.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6bc.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6bc.png new file mode 100755 index 0000000..2e58725 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6bc.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6bd.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6bd.png new file mode 100755 index 0000000..e5cc411 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6bd.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6be.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6be.png new file mode 100755 index 0000000..dfe84d2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6be.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6bf.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6bf.png new file mode 100755 index 0000000..94f82aa Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6bf.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c0.png new file mode 100755 index 0000000..8f75d1d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c1.png new file mode 100755 index 0000000..1c3f844 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c2.png new file mode 100755 index 0000000..675b76d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c3.png new file mode 100755 index 0000000..92691e3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c4.png new file mode 100755 index 0000000..59ae044 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c5.png new file mode 100755 index 0000000..1c08b46 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/1f6c5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/203c-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/203c-fe0f.png new file mode 100755 index 0000000..7270f0a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/203c-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2049-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2049-fe0f.png new file mode 100755 index 0000000..64304b9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2049-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2122.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2122.png new file mode 100755 index 0000000..9ba71b7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2122.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2139-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2139-fe0f.png new file mode 100755 index 0000000..9cb8b09 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2139-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2194-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2194-fe0f.png new file mode 100755 index 0000000..b9fd11c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2194-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2195-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2195-fe0f.png new file mode 100755 index 0000000..b718c21 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2195-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2196-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2196-fe0f.png new file mode 100755 index 0000000..12aebd9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2196-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2197-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2197-fe0f.png new file mode 100755 index 0000000..0daf4e9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2197-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2198-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2198-fe0f.png new file mode 100755 index 0000000..2a15cc7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2198-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2199-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2199-fe0f.png new file mode 100755 index 0000000..a4438cb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2199-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/21a9-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/21a9-fe0f.png new file mode 100755 index 0000000..bc45dfe Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/21a9-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/21aa-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/21aa-fe0f.png new file mode 100755 index 0000000..8b4ea6e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/21aa-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/231a-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/231a-fe0f.png new file mode 100755 index 0000000..d503bb8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/231a-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/231b-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/231b-fe0f.png new file mode 100755 index 0000000..405aab4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/231b-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23e9.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23e9.png new file mode 100755 index 0000000..b94a117 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23e9.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23ea.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23ea.png new file mode 100755 index 0000000..13ba866 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23ea.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23eb.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23eb.png new file mode 100755 index 0000000..d42979d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23eb.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23ec.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23ec.png new file mode 100755 index 0000000..2ecbebc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23ec.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23f0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23f0.png new file mode 100755 index 0000000..86ca8c8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23f0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23f3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23f3.png new file mode 100755 index 0000000..52c9eb7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/23f3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/24c2-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/24c2-fe0f.png new file mode 100755 index 0000000..7424665 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/24c2-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25aa-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25aa-fe0f.png new file mode 100755 index 0000000..a247751 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25aa-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25ab-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25ab-fe0f.png new file mode 100755 index 0000000..24ba879 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25ab-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25b6-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25b6-fe0f.png new file mode 100755 index 0000000..fbfe711 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25b6-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25c0-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25c0-fe0f.png new file mode 100755 index 0000000..2be422b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25c0-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25fb-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25fb-fe0f.png new file mode 100755 index 0000000..199808b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25fb-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25fc-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25fc-fe0f.png new file mode 100755 index 0000000..204cce1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25fc-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25fd-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25fd-fe0f.png new file mode 100755 index 0000000..a115cdc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25fd-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25fe-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25fe-fe0f.png new file mode 100755 index 0000000..25bfe9c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/25fe-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2600-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2600-fe0f.png new file mode 100755 index 0000000..d23c095 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2600-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2601-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2601-fe0f.png new file mode 100755 index 0000000..b31c08c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2601-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/260e-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/260e-fe0f.png new file mode 100755 index 0000000..87d2559 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/260e-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2611-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2611-fe0f.png new file mode 100755 index 0000000..f07a466 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2611-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2614-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2614-fe0f.png new file mode 100755 index 0000000..1db722f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2614-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2615-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2615-fe0f.png new file mode 100755 index 0000000..57e1adc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2615-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/261d-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/261d-fe0f.png new file mode 100755 index 0000000..01896e2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/261d-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/263a-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/263a-fe0f.png new file mode 100755 index 0000000..bbab82d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/263a-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2648-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2648-fe0f.png new file mode 100755 index 0000000..d676fd3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2648-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2649-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2649-fe0f.png new file mode 100755 index 0000000..6af582f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2649-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264a-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264a-fe0f.png new file mode 100755 index 0000000..d926f6e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264a-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264b-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264b-fe0f.png new file mode 100755 index 0000000..ea43a4a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264b-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264c-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264c-fe0f.png new file mode 100755 index 0000000..e025933 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264c-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264d-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264d-fe0f.png new file mode 100755 index 0000000..72e1763 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264d-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264e-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264e-fe0f.png new file mode 100755 index 0000000..c9062dd Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264e-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264f-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264f-fe0f.png new file mode 100755 index 0000000..67fcea1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/264f-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2650-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2650-fe0f.png new file mode 100755 index 0000000..8b5435b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2650-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2651-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2651-fe0f.png new file mode 100755 index 0000000..f2044e7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2651-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2652-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2652-fe0f.png new file mode 100755 index 0000000..cbff66e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2652-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2653-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2653-fe0f.png new file mode 100755 index 0000000..5a2da0a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2653-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2660-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2660-fe0f.png new file mode 100755 index 0000000..133a1ab Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2660-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2663-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2663-fe0f.png new file mode 100755 index 0000000..bfab536 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2663-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2665-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2665-fe0f.png new file mode 100755 index 0000000..e894715 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2665-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2666-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2666-fe0f.png new file mode 100755 index 0000000..fe08277 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2666-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2668-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2668-fe0f.png new file mode 100755 index 0000000..a0bc9d7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2668-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/267b-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/267b-fe0f.png new file mode 100755 index 0000000..99104c0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/267b-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/267f-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/267f-fe0f.png new file mode 100755 index 0000000..eddcdd7 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/267f-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2693-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2693-fe0f.png new file mode 100755 index 0000000..0c5192e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2693-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26a0-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26a0-fe0f.png new file mode 100755 index 0000000..466658d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26a0-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26a1-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26a1-fe0f.png new file mode 100755 index 0000000..260c531 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26a1-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26aa-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26aa-fe0f.png new file mode 100755 index 0000000..da782ae Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26aa-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26ab-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26ab-fe0f.png new file mode 100755 index 0000000..e46f9df Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26ab-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26bd-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26bd-fe0f.png new file mode 100755 index 0000000..1e118b5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26bd-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26be-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26be-fe0f.png new file mode 100755 index 0000000..da004e2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26be-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26c4-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26c4-fe0f.png new file mode 100755 index 0000000..a97902e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26c4-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26c5-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26c5-fe0f.png new file mode 100755 index 0000000..020dd5f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26c5-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26ce.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26ce.png new file mode 100755 index 0000000..4eef715 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26ce.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26d4-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26d4-fe0f.png new file mode 100755 index 0000000..cf2086a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26d4-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26ea-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26ea-fe0f.png new file mode 100755 index 0000000..4c07c6b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26ea-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26f2-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26f2-fe0f.png new file mode 100755 index 0000000..da126e6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26f2-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26f3-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26f3-fe0f.png new file mode 100755 index 0000000..cba2116 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26f3-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26f5-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26f5-fe0f.png new file mode 100755 index 0000000..ff656dc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26f5-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26fa-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26fa-fe0f.png new file mode 100755 index 0000000..5c0d20e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26fa-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26fd-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26fd-fe0f.png new file mode 100755 index 0000000..54c29ae Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/26fd-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2702-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2702-fe0f.png new file mode 100755 index 0000000..020e052 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2702-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2705.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2705.png new file mode 100755 index 0000000..61dc058 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2705.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2708-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2708-fe0f.png new file mode 100755 index 0000000..8407cb6 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2708-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2709-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2709-fe0f.png new file mode 100755 index 0000000..3631861 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2709-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/270a.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/270a.png new file mode 100755 index 0000000..ecc8874 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/270a.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/270b.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/270b.png new file mode 100755 index 0000000..5e45c25 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/270b.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/270c-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/270c-fe0f.png new file mode 100755 index 0000000..f61267c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/270c-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/270f-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/270f-fe0f.png new file mode 100755 index 0000000..e624373 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/270f-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2712-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2712-fe0f.png new file mode 100755 index 0000000..29f6994 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2712-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2714-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2714-fe0f.png new file mode 100755 index 0000000..336d262 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2714-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2716-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2716-fe0f.png new file mode 100755 index 0000000..13d6660 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2716-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2728.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2728.png new file mode 100755 index 0000000..9213882 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2728.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2733-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2733-fe0f.png new file mode 100755 index 0000000..946a203 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2733-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2734-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2734-fe0f.png new file mode 100755 index 0000000..73dc6a0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2734-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2744-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2744-fe0f.png new file mode 100755 index 0000000..54b68ff Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2744-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2747-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2747-fe0f.png new file mode 100755 index 0000000..23a68ce Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2747-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/274c.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/274c.png new file mode 100755 index 0000000..b84f635 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/274c.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/274e.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/274e.png new file mode 100755 index 0000000..b47a0ce Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/274e.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2753.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2753.png new file mode 100755 index 0000000..63fd7f8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2753.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2754.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2754.png new file mode 100755 index 0000000..57db41e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2754.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2755.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2755.png new file mode 100755 index 0000000..a50d265 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2755.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2757-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2757-fe0f.png new file mode 100755 index 0000000..4c560f5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2757-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2764-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2764-fe0f.png new file mode 100755 index 0000000..7d7790c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2764-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2795.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2795.png new file mode 100755 index 0000000..6159538 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2795.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2796.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2796.png new file mode 100755 index 0000000..b8d3d82 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2796.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2797.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2797.png new file mode 100755 index 0000000..ac757a2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2797.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/27a1-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/27a1-fe0f.png new file mode 100755 index 0000000..e5cca85 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/27a1-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/27b0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/27b0.png new file mode 100755 index 0000000..8f051ac Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/27b0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/27bf.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/27bf.png new file mode 100755 index 0000000..ef34df3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/27bf.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2934-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2934-fe0f.png new file mode 100755 index 0000000..c8f670a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2934-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2935-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2935-fe0f.png new file mode 100755 index 0000000..56dd3b9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2935-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b05-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b05-fe0f.png new file mode 100755 index 0000000..9d7d1b5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b05-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b06-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b06-fe0f.png new file mode 100755 index 0000000..565ce29 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b06-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b07-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b07-fe0f.png new file mode 100755 index 0000000..3956eb3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b07-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b1b-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b1b-fe0f.png new file mode 100755 index 0000000..71da10d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b1b-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b1c-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b1c-fe0f.png new file mode 100755 index 0000000..60cb19a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b1c-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b50-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b50-fe0f.png new file mode 100755 index 0000000..1bfddc8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b50-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b55-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b55-fe0f.png new file mode 100755 index 0000000..0ededeb Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/2b55-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/3030.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/3030.png new file mode 100755 index 0000000..77f626c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/3030.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/303d-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/303d-fe0f.png new file mode 100755 index 0000000..45dc9b8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/303d-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/3297-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/3297-fe0f.png new file mode 100755 index 0000000..dcbb1d2 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/3297-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/3299-fe0f.png b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/3299-fe0f.png new file mode 100755 index 0000000..82e383a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/Separated/3299-fe0f.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part0.png new file mode 100755 index 0000000..89ac8ac Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part1.png new file mode 100755 index 0000000..28bce47 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part2.png new file mode 100755 index 0000000..ec21682 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part3.png new file mode 100755 index 0000000..b0a67f3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part4.png new file mode 100755 index 0000000..61c5437 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part5.png new file mode 100755 index 0000000..16ddf15 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part0.png new file mode 100755 index 0000000..5e5e4cd Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part1.png new file mode 100755 index 0000000..87b7425 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part2.png new file mode 100755 index 0000000..a06ef4e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part3.png new file mode 100755 index 0000000..1ce74a4 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part0.png new file mode 100755 index 0000000..665bb59 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part1.png new file mode 100755 index 0000000..6addd30 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part2.png new file mode 100755 index 0000000..f581833 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part3.png new file mode 100755 index 0000000..bc7e5d1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part4.png new file mode 100755 index 0000000..ddaa1e9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part5.png new file mode 100755 index 0000000..2b494ae Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part6.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part6.png new file mode 100755 index 0000000..a06875b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part6.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part0.png new file mode 100755 index 0000000..c506439 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part1.png new file mode 100755 index 0000000..6b2aac1 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part2.png new file mode 100755 index 0000000..3e2c0c5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part0.png new file mode 100755 index 0000000..36f31a3 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part1.png new file mode 100755 index 0000000..1bc77a8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part2.png new file mode 100755 index 0000000..c9ea9d5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part3.png new file mode 100755 index 0000000..da0064b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part4.png new file mode 100755 index 0000000..04531d0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part5.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part5.png new file mode 100755 index 0000000..e5b3a88 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part5.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part0.png new file mode 100755 index 0000000..a1aab42 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part1.png new file mode 100755 index 0000000..e3b9d22 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part2.png new file mode 100755 index 0000000..36b2727 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part3.png new file mode 100755 index 0000000..dd4ca7b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part0.png new file mode 100755 index 0000000..53daf0e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part1.png new file mode 100755 index 0000000..7eb3b0c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part2.png new file mode 100755 index 0000000..37ec77c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part0.png new file mode 100755 index 0000000..c0b216b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part1.png new file mode 100755 index 0000000..082786c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part2.png new file mode 100755 index 0000000..bdf3a94 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part3.png new file mode 100755 index 0000000..96a1804 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part4.png new file mode 100755 index 0000000..539ae11 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part0.png new file mode 100755 index 0000000..7e80868 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part1.png new file mode 100755 index 0000000..7c72d23 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part2.png new file mode 100755 index 0000000..b8ab291 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part0.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part0.png new file mode 100755 index 0000000..ed22b18 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part0.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part1.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part1.png new file mode 100755 index 0000000..38840e9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part1.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part2.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part2.png new file mode 100755 index 0000000..f07b4a8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part2.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part3.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part3.png new file mode 100755 index 0000000..8bbe910 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part3.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part4.png b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part4.png new file mode 100755 index 0000000..7a630f9 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part4.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/Sounds/KbdFunction.wav b/EmojiPanel/EmojiPanel/Assets/Sounds/KbdFunction.wav new file mode 100755 index 0000000..bf68554 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Sounds/KbdFunction.wav differ diff --git a/EmojiPanel/EmojiPanel/Assets/Sounds/KbdKeyTap.wav b/EmojiPanel/EmojiPanel/Assets/Sounds/KbdKeyTap.wav new file mode 100755 index 0000000..e67780f Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/Sounds/KbdKeyTap.wav differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.abc-720p.png b/EmojiPanel/EmojiPanel/Assets/emoji.abc-720p.png new file mode 100755 index 0000000..92e3496 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.abc-720p.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.abc-WVGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.abc-WVGA.png new file mode 100755 index 0000000..3aa1199 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.abc-WVGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.abc-WXGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.abc-WXGA.png new file mode 100755 index 0000000..51b5d34 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.abc-WXGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.backspace-720p.png b/EmojiPanel/EmojiPanel/Assets/emoji.backspace-720p.png new file mode 100755 index 0000000..6ab19a0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.backspace-720p.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.backspace-WVGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.backspace-WVGA.png new file mode 100755 index 0000000..3a2cd7e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.backspace-WVGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.backspace-WXGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.backspace-WXGA.png new file mode 100755 index 0000000..849473c Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.backspace-WXGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.1-720p.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.1-720p.png new file mode 100755 index 0000000..c7eaf20 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.1-720p.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.1-WVGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.1-WVGA.png new file mode 100755 index 0000000..605311d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.1-WVGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.1-WXGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.1-WXGA.png new file mode 100755 index 0000000..6a87e8a Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.1-WXGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.2-720p.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.2-720p.png new file mode 100755 index 0000000..bf756ab Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.2-720p.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.2-WVGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.2-WVGA.png new file mode 100755 index 0000000..838b601 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.2-WVGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.2-WXGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.2-WXGA.png new file mode 100755 index 0000000..3015a13 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.2-WXGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.3-720p.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.3-720p.png new file mode 100755 index 0000000..79401f5 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.3-720p.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.3-WVGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.3-WVGA.png new file mode 100755 index 0000000..b8ac7e8 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.3-WVGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.3-WXGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.3-WXGA.png new file mode 100755 index 0000000..1d446d0 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.3-WXGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.4-720p.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.4-720p.png new file mode 100755 index 0000000..6f95b3b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.4-720p.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.4-WVGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.4-WVGA.png new file mode 100755 index 0000000..ee2908e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.4-WVGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.4-WXGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.4-WXGA.png new file mode 100755 index 0000000..97cfc53 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.4-WXGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.5-720p.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.5-720p.png new file mode 100755 index 0000000..b0fb3bc Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.5-720p.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.5-WVGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.5-WVGA.png new file mode 100755 index 0000000..b78dbcd Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.5-WVGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.category.5-WXGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.category.5-WXGA.png new file mode 100755 index 0000000..6ca64ed Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.category.5-WXGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.recent-720p.png b/EmojiPanel/EmojiPanel/Assets/emoji.recent-720p.png new file mode 100755 index 0000000..e19d42b Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.recent-720p.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.recent-WVGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.recent-WVGA.png new file mode 100755 index 0000000..977a942 Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.recent-WVGA.png differ diff --git a/EmojiPanel/EmojiPanel/Assets/emoji.recent-WXGA.png b/EmojiPanel/EmojiPanel/Assets/emoji.recent-WXGA.png new file mode 100755 index 0000000..0680b5e Binary files /dev/null and b/EmojiPanel/EmojiPanel/Assets/emoji.recent-WXGA.png differ diff --git a/EmojiPanel/EmojiPanel/Background.png b/EmojiPanel/EmojiPanel/Background.png new file mode 100755 index 0000000..e46f21d Binary files /dev/null and b/EmojiPanel/EmojiPanel/Background.png differ diff --git a/EmojiPanel/EmojiPanel/Controls/Emoji/EmojiControl.xaml b/EmojiPanel/EmojiPanel/Controls/Emoji/EmojiControl.xaml new file mode 100755 index 0000000..23df76b --- /dev/null +++ b/EmojiPanel/EmojiPanel/Controls/Emoji/EmojiControl.xaml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EmojiPanel/EmojiPanel/Controls/Emoji/EmojiControl.xaml.cs b/EmojiPanel/EmojiPanel/Controls/Emoji/EmojiControl.xaml.cs new file mode 100755 index 0000000..c5454a8 --- /dev/null +++ b/EmojiPanel/EmojiPanel/Controls/Emoji/EmojiControl.xaml.cs @@ -0,0 +1,654 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.IO.IsolatedStorage; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using EmojiPanel.Controls.Utilites; +using Microsoft.Phone.Controls; +using Telegram.Controls.VirtualizedView; + +namespace EmojiPanel.Controls.Emoji +{ + public partial class EmojiControl + { + private List _category1Sprites; + private List _category2Sprites; + private List _category3Sprites; + private List _category4Sprites; + private List _category5Sprites; + + public EventHandler IsOpenedChanged = delegate { }; + + public TextBox TextBoxTarget { get; set; } + + private const int AlbumOrientationHeight = 328; + private const int PortraitOrientationHeight = 408; + + private bool _isOpen; + private bool _isPortrait = true; + private bool _isTextBoxTargetFocused; + private bool _isBlocked; // Block IsOpen during animation + private int _currentCategory; + private bool _wasRendered; + private readonly TranslateTransform _frameTransform; + private static EmojiControl _instance; + + public static EmojiControl GetInstance() + { + return _instance ?? (_instance = new EmojiControl()); + } + + public static readonly DependencyProperty RootFrameTransformProperty = DependencyProperty.Register( + "RootFrameTransform", + typeof(double), + typeof(EmojiControl), + new PropertyMetadata(OnRootFrameTransformChanged)); + + public EmojiControl() + { + InitializeComponent(); + + var frame = (Frame)Application.Current.RootVisual; + _frameTransform = ((TranslateTransform)((TransformGroup)frame.RenderTransform).Children[0]); + var binding = new Binding("Y") + { + Source = _frameTransform + }; + SetBinding(RootFrameTransformProperty, binding); + + VirtPanel.InitializeWithScrollViewer(CSV); + VirtPanel.ScrollPositionChanged += VirtPanelOnScrollPositionChanged; + SizeChanged += OnSizeChanged; + OnSizeChanged(null, null); + + LoadButtons(); + CurrentCategory = 0; + + + } + + public void BindTextBox(TextBox textBox) + { + TextBoxTarget = textBox; + textBox.GotFocus += TextBoxOnGotFocus; + textBox.LostFocus += TextBoxOnLostFocus; + } + + public void UnbindTextBox() + { + TextBoxTarget.GotFocus -= TextBoxOnGotFocus; + TextBoxTarget.LostFocus -= TextBoxOnLostFocus; + TextBoxTarget = null; + } + + public bool IsOpen + { + get + { + return !_isTextBoxTargetFocused && _isOpen; + } + set + { + // Dont hide EmojiControl when keyboard is shown (or to be shown) + if (!_isTextBoxTargetFocused && _isOpen == value || _isBlocked) return; + + if (value) Open(); + else Hide(); + IsOpenedChanged(null, value); + } + } + + private void Open() + { + _isOpen = true; + + VisualStateManager.GoToState(TextBoxTarget, "Focused", false); + + var frame = (PhoneApplicationFrame)Application.Current.RootVisual; + EmojiContainer.Visibility = Visibility.Visible; + frame.BackKeyPress += OnBackKeyPress; + + if (!(EmojiContainer.RenderTransform is TranslateTransform)) + EmojiContainer.RenderTransform = new TranslateTransform(); + var transform = (TranslateTransform)EmojiContainer.RenderTransform; + + var offset = _isPortrait ? PortraitOrientationHeight : AlbumOrientationHeight; + EmojiContainer.Height = offset; + + var from = 0; + + if (_frameTransform.Y < 0) // Keyboard is in view + { + from = (int)_frameTransform.Y; + //_frameTransform.Y = -offset; + //transform.Y = offset;// -72; + } + transform.Y = offset;// -72 + + if (from == offset) return; + + frame.IsHitTestVisible = false; + _isBlocked = true; + + var storyboard = new Storyboard(); + var doubleTransformFrame = new DoubleAnimation + { + From = from, + To = -offset, + Duration = TimeSpan.FromMilliseconds(440), + EasingFunction = new ExponentialEase + { + EasingMode = EasingMode.EaseOut, + Exponent = 6 + } + }; + storyboard.Children.Add(doubleTransformFrame); + Storyboard.SetTarget(doubleTransformFrame, _frameTransform); + Storyboard.SetTargetProperty(doubleTransformFrame, new PropertyPath("Y")); + + EmojiContainer.Dispatcher.BeginInvoke(async () => + { + storyboard.Begin(); + + if (_frameTransform.Y < 0) // Keyboard is in view + { + Focus(); + TextBoxTarget.Dispatcher.BeginInvoke(() // no effect without dispatcher + => VisualStateManager.GoToState(TextBoxTarget, "Focused", false)); + } + + if (_wasRendered) return; + await Task.Delay(50); + LoadCategory(0); + }); + + storyboard.Completed += (sender, args) => + { + frame.IsHitTestVisible = true; + _isBlocked = false; + }; + } + + private void Hide() + { + _isOpen = false; + + var frame = (PhoneApplicationFrame)Application.Current.RootVisual; + frame.BackKeyPress -= OnBackKeyPress; + + if (_isTextBoxTargetFocused) + { + _frameTransform.Y = 0; + + EmojiContainer.Visibility = Visibility.Collapsed; + + return; + } + + VisualStateManager.GoToState(TextBoxTarget, "Unfocused", false); + + frame.IsHitTestVisible = false; + _isBlocked = true; + + var transform = (TranslateTransform)EmojiContainer.RenderTransform; + + var storyboard = new Storyboard(); + var doubleTransformFrame = new DoubleAnimation + { + From = -transform.Y, + To = 0, + Duration = TimeSpan.FromMilliseconds(440), + EasingFunction = new ExponentialEase + { + EasingMode = EasingMode.EaseOut, + Exponent = 6 + } + }; + storyboard.Children.Add(doubleTransformFrame); + Storyboard.SetTarget(doubleTransformFrame, _frameTransform); + Storyboard.SetTargetProperty(doubleTransformFrame, new PropertyPath("Y")); + storyboard.Begin(); + + storyboard.Completed += (sender, args) => + { + EmojiContainer.Visibility = Visibility.Collapsed; + + frame.IsHitTestVisible = true; + _isBlocked = false; + transform.Y = 0; + }; + + } + + #region _isTextBoxTargetFocused listeners + private void TextBoxOnGotFocus(object sender, RoutedEventArgs routedEventArgs) + { + _isTextBoxTargetFocused = true; + } + private void TextBoxOnLostFocus(object sender, RoutedEventArgs routedEventArgs) + { + _isTextBoxTargetFocused = false; + } + #endregion + + /// + /// Hide instance on pressing hardware Back button. Fires only when instance is opened. + /// + private void OnBackKeyPress(object sender, CancelEventArgs cancelEventArgs) + { + IsOpen = false; + cancelEventArgs.Cancel = true; + } + + /// + /// Clear current highlight on scroll + /// + private static void VirtPanelOnScrollPositionChanged(object sender, MyVirtualizingPanel.ScrollPositionChangedEventAgrs scrollPositionChangedEventAgrs) + { + EmojiSpriteItem.ClearCurrentHighlight(); + } + + /// + /// Changes tabs in UI and _currentCategory property + /// + public int CurrentCategory + { + get { return _currentCategory; } + set + { + var previousCategory = GetCategoryButtonByIndex(_currentCategory); + var nextCategory = GetCategoryButtonByIndex(value); + + if (previousCategory != null) + previousCategory.Background = new SolidColorBrush(Color.FromArgb(255, 71, 71, 71)); + + nextCategory.Background = (Brush)Application.Current.Resources["PhoneAccentBrush"]; + _currentCategory = value; + } + } + + public async void LoadCategory(int index) + { + VirtPanel.ClearItems(); + + if (_currentCategory == RecentsCategoryIndex) + UnloadRecents(); + + if (index == RecentsCategoryIndex) + { + LoadRecents(); + return; + } + + List sprites = null; + + switch (index) + { + case 0: + sprites = _category1Sprites; + break; + case 1: + sprites = _category2Sprites; + break; + case 2: + sprites = _category3Sprites; + break; + case 3: + sprites = _category4Sprites; + break; + case 4: + sprites = _category5Sprites; + break; + } + + if (sprites == null) + { + sprites = new List(); + + for (var i = 0; i < EmojiData.SpritesByCategory[index].Length; i++) + { + //var item = new EmojiSpriteItem(index, i); + var item = new EmojiSpriteItem(EmojiData.SpritesByCategory[index][i], index, i); + item.EmojiSelected += OnEmojiSelected; + sprites.Add(item); + } + + switch (index) + { + case 0: + _category1Sprites = sprites; + break; + case 1: + _category2Sprites = sprites; + break; + case 2: + _category3Sprites = sprites; + break; + case 3: + _category4Sprites = sprites; + break; + case 4: + _category5Sprites = sprites; + break; + } + } + + CurrentCategory = index; + + VirtPanel.AddItems(new List { sprites[0] }); + CreateButtonsBackgrounds(index); + + if (!_wasRendered) + { + // Display LoadingProgressBar only once + LoadingProgressBar.Visibility = Visibility.Collapsed; + _wasRendered = true; + } + + // Delayed rendering of the rest parts - speeds up initial load + await Task.Delay(100); + if (_currentCategory != index) + return; + + var listList = sprites.ToList(); + listList.RemoveAt(0); + VirtPanel.AddItems(listList); + } + + public static void OnRootFrameTransformChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) + { + ((EmojiControl)source).OnRootFrameTransformChanged(); + } + + public void OnRootFrameTransformChanged() + { + if (!_isOpen) return; + + var offset = _isPortrait ? -PortraitOrientationHeight : -AlbumOrientationHeight; + _frameTransform.Y = offset; + } + + #region Recents + public void LoadRecents() + { + CurrentCategory = RecentsCategoryIndex; + + var recents = EmojiData.Recents; + //recents = recents.ToList(); + } + + public void UnloadRecents() + { + + } + + + #endregion Recents + + private void OnEmojiSelected(object sender, EmojiDataItem emojiDataItem) + { + TextBoxTarget.Dispatcher.BeginInvoke(() => + { + var selectionStart = TextBoxTarget.SelectionStart; + TextBoxTarget.Text = TextBoxTarget.Text.Insert(selectionStart, emojiDataItem.String); + TextBoxTarget.Select(selectionStart + emojiDataItem.String.Length, 0); + }); + + if (_currentCategory == RecentsCategoryIndex) return; + + var that = emojiDataItem; + ThreadPool.QueueUserWorkItem(state => EmojiData.AddToRecents(that)); + } + + + /// + /// Emoji control backspace button logic + /// + private void BackspaceButtonOnClick(object sender, RoutedEventArgs routedEventArgs) + { + var text = TextBoxTarget.Text; + var selectionStart = TextBoxTarget.SelectionStart; + + if (text.Length <= 0) return; + if (selectionStart == 0) return; + + int toSubstring; + + if (text.Length > 1) + { + var prevSymbol = text[selectionStart - 2]; + var prevBytes = BitConverter.GetBytes(prevSymbol); + + var curSymbol = text[selectionStart - 1]; + var curBytes = BitConverter.GetBytes(curSymbol); + + if (prevBytes[1] == 0xD8 && (prevBytes[0] == 0x3D || prevBytes[0] == 0x3C)) + toSubstring = 2; + else if (curBytes[1] == 0x20 && curBytes[0] == 0xE3) + toSubstring = 2; + else + toSubstring = 1; + } + else + { + toSubstring = 1; + } + + TextBoxTarget.Text = text.Remove(selectionStart - toSubstring, toSubstring); + TextBoxTarget.SelectionStart = selectionStart - toSubstring; + } + + #region User Interface + + private readonly Button _abcButton = new Button { ClickMode = ClickMode.Release }; + private readonly Button _recentsButton = new Button { ClickMode = ClickMode.Press }; + private readonly Button _cat0Button = new Button { ClickMode = ClickMode.Press }; + private readonly Button _cat1Button = new Button { ClickMode = ClickMode.Press }; + private readonly Button _cat2Button = new Button { ClickMode = ClickMode.Press }; + private readonly Button _cat3Button = new Button { ClickMode = ClickMode.Press }; + private readonly Button _cat4Button = new Button { ClickMode = ClickMode.Press }; + private readonly RepeatButton _backspaceButton = new RepeatButton { ClickMode = ClickMode.Release, Interval = 100 }; + public const int RecentsCategoryIndex = 5; + + private Button GetCategoryButtonByIndex(int index) + { + switch (index) + { + case 0: + return _cat0Button; + case 1: + return _cat1Button; + case 2: + return _cat2Button; + case 3: + return _cat3Button; + case 4: + return _cat4Button; + case RecentsCategoryIndex: + return _recentsButton; + default: + return null; + } + } + public void LoadButtons() + { + var buttonStyle = (Style)Resources["CategoryButtonStyle"]; + _abcButton.Style = buttonStyle; + _recentsButton.Style = buttonStyle; + _cat0Button.Style = buttonStyle; + _cat1Button.Style = buttonStyle; + _cat2Button.Style = buttonStyle; + _cat3Button.Style = buttonStyle; + _cat4Button.Style = buttonStyle; + _backspaceButton.Style = (Style)Resources["RepeatButtonStyle"]; + + _abcButton.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri("emoji.abc")), + Width = 34, + Height = 32 + }; + _recentsButton.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri("emoji.recent")), + Width = 34, + Height = 32 + }; + _cat0Button.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri("emoji.category.1")), + Width = 34, + Height = 32 + }; + _cat1Button.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri("emoji.category.2")), + Width = 34, + Height = 32 + }; + _cat2Button.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri("emoji.category.3")), + Width = 34, + Height = 32 + }; + _cat3Button.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri("emoji.category.4")), + Width = 34, + Height = 32 + }; + _cat4Button.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri("emoji.category.5")), + Width = 34, + Height = 32 + }; + _backspaceButton.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri("emoji.backspace")), + Width = 34, + Height = 32 + }; + + Grid.SetColumn(_abcButton, 0); + Grid.SetColumn(_recentsButton, 1); + Grid.SetColumn(_cat0Button, 2); + Grid.SetColumn(_cat1Button, 3); + Grid.SetColumn(_cat2Button, 4); + Grid.SetColumn(_cat3Button, 5); + Grid.SetColumn(_cat4Button, 6); + Grid.SetColumn(_backspaceButton, 7); + + ButtonsGrid.Children.Add(_abcButton); + ButtonsGrid.Children.Add(_recentsButton); + ButtonsGrid.Children.Add(_cat0Button); + ButtonsGrid.Children.Add(_cat1Button); + ButtonsGrid.Children.Add(_cat2Button); + ButtonsGrid.Children.Add(_cat3Button); + ButtonsGrid.Children.Add(_cat4Button); + ButtonsGrid.Children.Add(_backspaceButton); + + _abcButton.Click += AbcButtonOnClick; + _cat0Button.Click += CategoryButtonClick; + _cat1Button.Click += CategoryButtonClick; + _cat2Button.Click += CategoryButtonClick; + _cat3Button.Click += CategoryButtonClick; + _cat4Button.Click += CategoryButtonClick; + _recentsButton.Click += CategoryButtonClick; + _backspaceButton.Click += BackspaceButtonOnClick; + } + + private void AbcButtonOnClick(object sender, RoutedEventArgs routedEventArgs) + { + TextBoxTarget.Focus(); + } + + private void CategoryButtonClick(object sender, RoutedEventArgs routedEventArgs) + { + if (sender == _cat0Button) + LoadCategory(0); + else if (sender == _cat1Button) + LoadCategory(1); + else if (sender == _cat2Button) + LoadCategory(2); + else if (sender == _cat3Button) + LoadCategory(3); + else if (sender == _cat4Button) + LoadCategory(4); + else if (sender == _recentsButton) + LoadCategory(RecentsCategoryIndex); + } + + private void CreateButtonsBackgrounds(int categoryIndex) + { + var sprites = EmojiData.SpriteRowsCountByCategory[categoryIndex]; + + for (var i = 0; i < sprites.Length; i++) + { + var rowsCount = sprites[i]; + + var block = new Rectangle + { + Width = EmojiSpriteItem.SpriteWidth, + Height = EmojiSpriteItem.RowHeight * rowsCount, + Fill = new SolidColorBrush(Color.FromArgb(255, 71, 71, 71)), + Margin = new Thickness(4, 0, 4, 0) + }; + Canvas.SetTop(block, (EmojiSpriteItem.SpriteHeight) * i); + VirtPanel.Children.Insert(0, block); + } + } + + private void InitializeOrientation(Orientation orientation) + { + switch (orientation) + { + case Orientation.Vertical: + ButtonsGrid.Height = 78; + ButtonsGrid.Margin = new Thickness(0, 6, 0, 0); + EmojiContainer.Height = PortraitOrientationHeight; + _frameTransform.Y = -PortraitOrientationHeight; + break; + + case Orientation.Horizontal: + ButtonsGrid.Height = 58; + ButtonsGrid.Margin = new Thickness(0, 6, 0, 3); + EmojiContainer.Height = AlbumOrientationHeight; + _frameTransform.Y = -AlbumOrientationHeight; + break; + } + } + + #endregion User Interface + + + /// + /// Orientation change handler + /// + private void OnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs) + { + var currentOrientation = ((PhoneApplicationFrame)Application.Current.RootVisual).Orientation; + var isPortrait = currentOrientation == PageOrientation.PortraitUp || + currentOrientation == PageOrientation.PortraitDown || + currentOrientation == PageOrientation.Portrait; + + if (_isPortrait == isPortrait && _wasRendered) return; + + _isPortrait = isPortrait; + InitializeOrientation(isPortrait ? Orientation.Vertical : Orientation.Horizontal); + } + } +} diff --git a/EmojiPanel/EmojiPanel/Controls/Emoji/EmojiData.cs b/EmojiPanel/EmojiPanel/Controls/Emoji/EmojiData.cs new file mode 100755 index 0000000..e4b4409 --- /dev/null +++ b/EmojiPanel/EmojiPanel/Controls/Emoji/EmojiData.cs @@ -0,0 +1,389 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.IsolatedStorage; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EmojiPanel.Controls.Emoji +{ + public class EmojiDataItem + { + public EmojiDataItem() { } + + public EmojiDataItem(string string2, ulong code) + { + String = string2; + Code = code; + } + + public string String { get; set; } + public ulong Code { get; set; } + public Uri Uri { get; set; } + + public static string BuildString(ulong code) + { + var bytes = BitConverter.GetBytes(code); + + var char1 = BitConverter.ToChar(bytes, 6); + var char2 = BitConverter.ToChar(bytes, 4); + var char3 = BitConverter.ToChar(bytes, 2); + var char4 = BitConverter.ToChar(bytes, 0); + + string text; + + if (char1 != 0) + { + text = new string(new [] { char1, char2, char3, char4 }); + } + else if (char3 != 0) + { + text = new string(new [] { char3, char4 }); + } + else + { + text = char4.ToString(); + } + + return text; + } + + public static Uri BuildUri(string string2) + { + //var string3 = BitConverter.ToString(bytes.Take(4).Reverse().ToArray()) + var string3 = string.Format("{0:X}", (Int16) string2[0]); + + switch (string2.Length) + { + case 2: + { + uint emoji = 0; + emoji |= (uint) string2[0] << 16; + emoji |= (uint) string2[1]; + + return new Uri(string.Format("/Assets/Emoji/Separated/{0:X}.png", emoji), UriKind.Relative); + } + case 4: + { + uint emoji1 = 0; + emoji1 |= (uint) string2[0] << 16; + emoji1 |= (uint) string2[1]; + + ulong emoji2 = 0; + emoji2 |= (uint) string2[2] << 16; + emoji2 |= (uint) string2[3]; + + return new Uri(string.Format("/Assets/Emoji/Separated/{0:X}-{1:X}.png", emoji1, emoji2), UriKind.Relative); + } + default: + return new Uri(string.Format("/Assets/Emoji/Separated/{0:X}.png", (Int16) string2[0]), UriKind.Relative); + } + } + + public static EmojiDataItem GetByIndex(int categoryIndex, int spriteIndex, int itemIndex) + { + + var category = EmojiData.CodesByCategory[categoryIndex]; + var emojiIndex = spriteIndex * EmojiData.ItemsInSprite + itemIndex; + + if (category.Length <= emojiIndex) return null; // out of bounds + + ulong code = category[emojiIndex]; + + var result = new EmojiDataItem + { + Code = code, + String = BuildString(code) + }; + result.Uri = BuildUri(result.String); + + return result; + } + } + + public static class EmojiData + { + public static List Recents; + + public static void AddToRecents(EmojiDataItem emojiDataItem) + { + if (Recents == null) + { + LoadRecents(); + if (Recents == null) return; + } + + var prevItem = Recents.FirstOrDefault(x => x.Code == emojiDataItem.Code); + if (prevItem != null) + { + Recents.Remove(prevItem); + Recents.Insert(0, prevItem); + } + else + { + Recents.Insert(0, emojiDataItem); + Recents = Recents.Take(30).ToList(); + } + + SaveRecents(); + } + + public static void LoadRecents() + { + + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (!store.FileExists("EmojiRecents")) return; + using (var stream = new IsolatedStorageFileStream("EmojiRecents", FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite, store)) + { + if (stream.Length <= 0) return; + + using (var br = new BinaryReader(stream)) + { + var count = br.ReadInt32(); + + Recents = new List(); + + for (var i = 0; i < count; i++) + { + var emoji = new EmojiDataItem(br.ReadString(), br.ReadUInt64()); + Recents.Add(emoji); + } + } + } + } + } + + public static void SaveRecents() + { + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + using (var stream = new IsolatedStorageFileStream("EmojiRecents", FileMode.Create, FileAccess.Write, FileShare.ReadWrite, store)) + { + using (var bw = new BinaryWriter(stream)) + { + var emojies = Recents.ToList(); + + bw.Write(emojies.Count); + + foreach (var item in emojies) + { + bw.Write(item.String); + bw.Write(item.Code); + } + } + } + } + } + + public const int ItemsInRow = 6; + public const int ItemsInSprite = 36; + + /// + /// Custom spaced sprites by category + /// + public static Uri[][] SpritesByCategory = + { + new[] + { + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat0_part0.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat0_part1.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat0_part2.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat0_part3.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat0_part4.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat0_part5.png", UriKind.Relative), + }, + new[] + { + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat1_part0.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat1_part1.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat1_part2.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat1_part3.png", UriKind.Relative), + }, + new[] + { + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part0.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part1.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part2.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part3.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part4.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part5.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part6.png", UriKind.Relative), + }, + new[] + { + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat3_part0.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat3_part1.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat3_part2.png", UriKind.Relative), + }, + new[] + { + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat4_part0.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat4_part1.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat4_part2.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat4_part3.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat4_part4.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat4_part5.png", UriKind.Relative), + }, + }; + + /// + /// Config of rows count for sprites in categories + /// + public static int[][] SpriteRowsCountByCategory = + { + new [] { 6, 6, 6, 6, 6, 2 }, + new [] { 6, 6, 6, 2 }, + new [] { 6, 6, 6, 6, 6, 6, 3 }, + new [] { 6, 6, 5 }, + new [] { 6, 6, 6, 6, 6, 5 } + }; + + /// + /// Config of missing cells in last row for each last category's sprite + /// + public static int[] SpriteMissingCellsByCategory = + { + 3, 4, 4, 1, 1 + }; + + /// + /// Emoji codes combined into the groups corresponding to the categories in the interface + /// + public static ulong[][] CodesByCategory = { + new ulong[]{ + 0x00000000D83DDE04L, 0x00000000D83DDE03L, 0x00000000D83DDE00L, 0x00000000D83DDE0AL, 0x000000000000263AL, 0x00000000D83DDE09L, 0x00000000D83DDE0DL, + 0x00000000D83DDE18L, 0x00000000D83DDE1AL, 0x00000000D83DDE17L, 0x00000000D83DDE19L, 0x00000000D83DDE1CL, 0x00000000D83DDE1DL, 0x00000000D83DDE1BL, + 0x00000000D83DDE33L, 0x00000000D83DDE01L, 0x00000000D83DDE14L, 0x00000000D83DDE0CL, 0x00000000D83DDE12L, 0x00000000D83DDE1EL, 0x00000000D83DDE23L, + 0x00000000D83DDE22L, 0x00000000D83DDE02L, 0x00000000D83DDE2DL, 0x00000000D83DDE2AL, 0x00000000D83DDE25L, 0x00000000D83DDE30L, 0x00000000D83DDE05L, + 0x00000000D83DDE13L, 0x00000000D83DDE29L, 0x00000000D83DDE2BL, 0x00000000D83DDE28L, 0x00000000D83DDE31L, 0x00000000D83DDE20L, 0x00000000D83DDE21L, + 0x00000000D83DDE24L, 0x00000000D83DDE16L, 0x00000000D83DDE06L, 0x00000000D83DDE0BL, 0x00000000D83DDE37L, 0x00000000D83DDE0EL, 0x00000000D83DDE34L, + 0x00000000D83DDE35L, 0x00000000D83DDE32L, 0x00000000D83DDE1FL, 0x00000000D83DDE26L, 0x00000000D83DDE27L, 0x00000000D83DDE08L, 0x00000000D83DDC7FL, + 0x00000000D83DDE2EL, 0x00000000D83DDE2CL, 0x00000000D83DDE10L, 0x00000000D83DDE15L, 0x00000000D83DDE2FL, 0x00000000D83DDE36L, 0x00000000D83DDE07L, + 0x00000000D83DDE0FL, 0x00000000D83DDE11L, 0x00000000D83DDC72L, 0x00000000D83DDC73L, 0x00000000D83DDC6EL, 0x00000000D83DDC77L, 0x00000000D83DDC82L, + 0x00000000D83DDC76L, 0x00000000D83DDC66L, 0x00000000D83DDC67L, 0x00000000D83DDC68L, 0x00000000D83DDC69L, 0x00000000D83DDC74L, 0x00000000D83DDC75L, + 0x00000000D83DDC71L, 0x00000000D83DDC7CL, 0x00000000D83DDC78L, 0x00000000D83DDE3AL, 0x00000000D83DDE38L, 0x00000000D83DDE3BL, 0x00000000D83DDE3DL, + 0x00000000D83DDE3CL, 0x00000000D83DDE40L, 0x00000000D83DDE3FL, 0x00000000D83DDE39L, 0x00000000D83DDE3EL, 0x00000000D83DDC79L, 0x00000000D83DDC7AL, + 0x00000000D83DDE48L, 0x00000000D83DDE49L, 0x00000000D83DDE4AL, 0x00000000D83DDC80L, 0x00000000D83DDC7DL, 0x00000000D83DDCA9L, 0x00000000D83DDD25L, + 0x0000000000002728L, 0x00000000D83CDF1FL, 0x00000000D83DDCABL, 0x00000000D83DDCA5L, 0x00000000D83DDCA2L, 0x00000000D83DDCA6L, 0x00000000D83DDCA7L, + 0x00000000D83DDCA4L, 0x00000000D83DDCA8L, 0x00000000D83DDC42L, 0x00000000D83DDC40L, 0x00000000D83DDC43L, 0x00000000D83DDC45L, 0x00000000D83DDC44L, + 0x00000000D83DDC4DL, 0x00000000D83DDC4EL, 0x00000000D83DDC4CL, 0x00000000D83DDC4AL, 0x000000000000270AL, 0x000000000000270CL, 0x00000000D83DDC4BL, + 0x000000000000270BL, 0x00000000D83DDC50L, 0x00000000D83DDC46L, 0x00000000D83DDC47L, 0x00000000D83DDC49L, 0x00000000D83DDC48L, 0x00000000D83DDE4CL, + 0x00000000D83DDE4FL, 0x000000000000261DL, 0x00000000D83DDC4FL, 0x00000000D83DDCAAL, 0x00000000D83DDEB6L, 0x00000000D83CDFC3L, 0x00000000D83DDC83L, + 0x00000000D83DDC6BL, 0x00000000D83DDC6AL, 0x00000000D83DDC6CL, 0x00000000D83DDC6DL, 0x00000000D83DDC8FL, 0x00000000D83DDC91L, 0x00000000D83DDC6FL, + 0x00000000D83DDE46L, 0x00000000D83DDE45L, 0x00000000D83DDC81L, 0x00000000D83DDE4BL, 0x00000000D83DDC86L, 0x00000000D83DDC87L, 0x00000000D83DDC85L, + 0x00000000D83DDC70L, 0x00000000D83DDE4EL, 0x00000000D83DDE4DL, 0x00000000D83DDE47L, 0x00000000D83CDFA9L, 0x00000000D83DDC51L, 0x00000000D83DDC52L, + 0x00000000D83DDC5FL, 0x00000000D83DDC5EL, 0x00000000D83DDC61L, 0x00000000D83DDC60L, 0x00000000D83DDC62L, 0x00000000D83DDC55L, 0x00000000D83DDC54L, + 0x00000000D83DDC5AL, 0x00000000D83DDC57L, 0x00000000D83CDFBDL, 0x00000000D83DDC56L, 0x00000000D83DDC58L, 0x00000000D83DDC59L, 0x00000000D83DDCBCL, + 0x00000000D83DDC5CL, 0x00000000D83DDC5DL, 0x00000000D83DDC5BL, 0x00000000D83DDC53L, 0x00000000D83CDF80L, 0x00000000D83CDF02L, 0x00000000D83DDC84L, + 0x00000000D83DDC9BL, 0x00000000D83DDC99L, 0x00000000D83DDC9CL, 0x00000000D83DDC9AL, 0x0000000000002764L, 0x00000000D83DDC94L, 0x00000000D83DDC97L, + 0x00000000D83DDC93L, 0x00000000D83DDC95L, 0x00000000D83DDC96L, 0x00000000D83DDC9EL, 0x00000000D83DDC98L, 0x00000000D83DDC8CL, 0x00000000D83DDC8BL, + 0x00000000D83DDC8DL, 0x00000000D83DDC8EL, 0x00000000D83DDC64L, 0x00000000D83DDC65L, 0x00000000D83DDCACL, 0x00000000D83DDC63L, 0x00000000D83DDCADL}, + new ulong[]{ + 0x00000000D83DDC36L, 0x00000000D83DDC3AL, 0x00000000D83DDC31L, 0x00000000D83DDC2DL, 0x00000000D83DDC39L, 0x00000000D83DDC30L, 0x00000000D83DDC38L, 0x00000000D83DDC2FL, + 0x00000000D83DDC28L, 0x00000000D83DDC3BL, 0x00000000D83DDC37L, 0x00000000D83DDC3DL, 0x00000000D83DDC2EL, 0x00000000D83DDC17L, 0x00000000D83DDC35L, + 0x00000000D83DDC12L, 0x00000000D83DDC34L, 0x00000000D83DDC11L, 0x00000000D83DDC18L, 0x00000000D83DDC3CL, 0x00000000D83DDC27L, 0x00000000D83DDC26L, + 0x00000000D83DDC24L, 0x00000000D83DDC25L, 0x00000000D83DDC23L, 0x00000000D83DDC14L, 0x00000000D83DDC0DL, 0x00000000D83DDC22L, 0x00000000D83DDC1BL, + 0x00000000D83DDC1DL, 0x00000000D83DDC1CL, 0x00000000D83DDC1EL, 0x00000000D83DDC0CL, 0x00000000D83DDC19L, 0x00000000D83DDC1AL, 0x00000000D83DDC20L, + 0x00000000D83DDC1FL, 0x00000000D83DDC2CL, 0x00000000D83DDC33L, 0x00000000D83DDC0BL, 0x00000000D83DDC04L, 0x00000000D83DDC0FL, 0x00000000D83DDC00L, + 0x00000000D83DDC03L, 0x00000000D83DDC05L, 0x00000000D83DDC07L, 0x00000000D83DDC09L, 0x00000000D83DDC0EL, 0x00000000D83DDC10L, 0x00000000D83DDC13L, + 0x00000000D83DDC15L, 0x00000000D83DDC16L, 0x00000000D83DDC01L, 0x00000000D83DDC02L, 0x00000000D83DDC32L, 0x00000000D83DDC21L, 0x00000000D83DDC0AL, + 0x00000000D83DDC2BL, 0x00000000D83DDC2AL, 0x00000000D83DDC06L, 0x00000000D83DDC08L, 0x00000000D83DDC29L, 0x00000000D83DDC3EL, 0x00000000D83DDC90L, + 0x00000000D83CDF38L, 0x00000000D83CDF37L, 0x00000000D83CDF40L, 0x00000000D83CDF39L, 0x00000000D83CDF3BL, 0x00000000D83CDF3AL, 0x00000000D83CDF41L, + 0x00000000D83CDF43L, 0x00000000D83CDF42L, 0x00000000D83CDF3FL, 0x00000000D83CDF3EL, 0x00000000D83CDF44L, 0x00000000D83CDF35L, 0x00000000D83CDF34L, + 0x00000000D83CDF32L, 0x00000000D83CDF33L, 0x00000000D83CDF30L, 0x00000000D83CDF31L, 0x00000000D83CDF3CL, 0x00000000D83CDF10L, 0x00000000D83CDF1EL, + 0x00000000D83CDF1DL, 0x00000000D83CDF1AL, 0x00000000D83CDF11L, 0x00000000D83CDF12L, 0x00000000D83CDF13L, 0x00000000D83CDF14L, 0x00000000D83CDF15L, + 0x00000000D83CDF16L, 0x00000000D83CDF17L, 0x00000000D83CDF18L, 0x00000000D83CDF1CL, 0x00000000D83CDF1BL, 0x00000000D83CDF19L, 0x00000000D83CDF0DL, + 0x00000000D83CDF0EL, 0x00000000D83CDF0FL, 0x00000000D83CDF0BL, 0x00000000D83CDF0CL, 0x00000000D83CDF20L, 0x0000000000002B50L, 0x0000000000002600L, + 0x00000000000026C5L, 0x0000000000002601L, 0x00000000000026A1L, 0x0000000000002614L, 0x0000000000002744L, 0x00000000000026C4L, 0x00000000D83CDF00L, + 0x00000000D83CDF01L, 0x00000000D83CDF08L, 0x00000000D83CDF0AL}, + new ulong[]{ + 0x00000000D83CDF8DL, 0x00000000D83DDC9DL, 0x00000000D83CDF8EL, 0x00000000D83CDF92L, 0x00000000D83CDF93L, 0x00000000D83CDF8FL, 0x00000000D83CDF86L, 0x00000000D83CDF87L, + 0x00000000D83CDF90L, 0x00000000D83CDF91L, 0x00000000D83CDF83L, 0x00000000D83DDC7BL, 0x00000000D83CDF85L, 0x00000000D83CDF84L, 0x00000000D83CDF81L, + 0x00000000D83CDF8BL, 0x00000000D83CDF89L, 0x00000000D83CDF8AL, 0x00000000D83CDF88L, 0x00000000D83CDF8CL, 0x00000000D83DDD2EL, 0x00000000D83CDFA5L, + 0x00000000D83DDCF7L, 0x00000000D83DDCF9L, 0x00000000D83DDCFCL, 0x00000000D83DDCBFL, 0x00000000D83DDCC0L, 0x00000000D83DDCBDL, 0x00000000D83DDCBEL, + 0x00000000D83DDCBBL, 0x00000000D83DDCF1L, 0x000000000000260EL, 0x00000000D83DDCDEL, 0x00000000D83DDCDFL, 0x00000000D83DDCE0L, 0x00000000D83DDCE1L, + 0x00000000D83DDCFAL, 0x00000000D83DDCFBL, 0x00000000D83DDD0AL, 0x00000000D83DDD09L, 0x00000000D83DDD08L, 0x00000000D83DDD07L, 0x00000000D83DDD14L, + 0x00000000D83DDD14L, 0x00000000D83DDCE2L, 0x00000000D83DDCE3L, 0x00000000000023F3L, 0x000000000000231BL, 0x00000000000023F0L, 0x000000000000231AL, + 0x00000000D83DDD13L, 0x00000000D83DDD12L, 0x00000000D83DDD0FL, 0x00000000D83DDD10L, 0x00000000D83DDD11L, 0x00000000D83DDD0EL, 0x00000000D83DDCA1L, + 0x00000000D83DDD26L, 0x00000000D83DDD06L, 0x00000000D83DDD05L, 0x00000000D83DDD0CL, 0x00000000D83DDD0BL, 0x00000000D83DDD0DL, 0x00000000D83DDEC1L /* was missing */, 0x00000000D83DDEC0L, + 0x00000000D83DDEBFL, 0x00000000D83DDEBDL, 0x00000000D83DDD27L, 0x00000000D83DDD29L, 0x00000000D83DDD28L, 0x00000000D83DDEAAL, 0x00000000D83DDEACL, + 0x00000000D83DDCA3L, 0x00000000D83DDD2BL, 0x00000000D83DDD2AL, 0x00000000D83DDC8AL, 0x00000000D83DDC89L, 0x00000000D83DDCB0L, 0x00000000D83DDCB4L, + 0x00000000D83DDCB5L, 0x00000000D83DDCB7L, 0x00000000D83DDCB6L, 0x00000000D83DDCB3L, 0x00000000D83DDCB8L, 0x00000000D83DDCF2L, 0x00000000D83DDCE7L, + 0x00000000D83DDCE5L, 0x00000000D83DDCE4L, 0x0000000000002709L, 0x00000000D83DDCE9L, 0x00000000D83DDCE8L, 0x00000000D83DDCEFL, 0x00000000D83DDCEBL, + 0x00000000D83DDCEAL, 0x00000000D83DDCECL, 0x00000000D83DDCEDL, 0x00000000D83DDCEEL, 0x00000000D83DDCE6L, 0x00000000D83DDCDDL, 0x00000000D83DDCC4L, + 0x00000000D83DDCC3L, 0x00000000D83DDCD1L, 0x00000000D83DDCCAL, 0x00000000D83DDCC8L, 0x00000000D83DDCC9L, 0x00000000D83DDCDCL, 0x00000000D83DDCCBL, + 0x00000000D83DDCC5L, 0x00000000D83DDCC6L, 0x00000000D83DDCC7L, 0x00000000D83DDCC1L, 0x00000000D83DDCC2L, 0x0000000000002702L, 0x00000000D83DDCCCL, + 0x00000000D83DDCCEL, 0x0000000000002712L, 0x000000000000270FL, 0x00000000D83DDCCFL, 0x00000000D83DDCD0L, 0x00000000D83DDCD5L, 0x00000000D83DDCD7L, + 0x00000000D83DDCD8L, 0x00000000D83DDCD9L, 0x00000000D83DDCD3L, 0x00000000D83DDCD4L, 0x00000000D83DDCD2L, 0x00000000D83DDCDAL, 0x00000000D83DDCD6L, + 0x00000000D83DDD16L, 0x00000000D83DDCDBL, 0x00000000D83DDD2CL, 0x00000000D83DDD2DL, 0x00000000D83DDCF0L, 0x00000000D83CDFA8L, 0x00000000D83CDFACL, + 0x00000000D83CDFA4L, 0x00000000D83CDFA7L, 0x00000000D83CDFBCL, 0x00000000D83CDFB5L, 0x00000000D83CDFB6L, 0x00000000D83CDFB9L, 0x00000000D83CDFBBL, + 0x00000000D83CDFBAL, 0x00000000D83CDFB7L, 0x00000000D83CDFB8L, 0x00000000D83DDC7EL, 0x00000000D83CDFAEL, 0x00000000D83CDCCFL, 0x00000000D83CDFB4L, + 0x00000000D83CDC04L, 0x00000000D83CDFB2L, 0x00000000D83CDFAFL, 0x00000000D83CDFC8L, 0x00000000D83CDFC0L, 0x00000000000026BDL, 0x00000000000026BEL, + 0x00000000D83CDFBEL, 0x00000000D83CDFB1L, 0x00000000D83CDFC9L, 0x00000000D83CDFB3L, 0x00000000000026F3L, 0x00000000D83DDEB5L, 0x00000000D83DDEB4L, + 0x00000000D83CDFC1L, 0x00000000D83CDFC7L, 0x00000000D83CDFC6L, 0x00000000D83CDFBFL, 0x00000000D83CDFC2L, 0x00000000D83CDFCAL, 0x00000000D83CDFC4L, + 0x00000000D83CDFA3L, 0x0000000000002615L, 0x00000000D83CDF75L, 0x00000000D83CDF76L, 0x00000000D83CDF7CL, 0x00000000D83CDF7AL, 0x00000000D83CDF7BL, + 0x00000000D83CDF78L, 0x00000000D83CDF79L, 0x00000000D83CDF77L, 0x00000000D83CDF74L, 0x00000000D83CDF55L, 0x00000000D83CDF54L, 0x00000000D83CDF5FL, + 0x00000000D83CDF57L, 0x00000000D83CDF56L, 0x00000000D83CDF5DL, 0x00000000D83CDF5BL, 0x00000000D83CDF64L, 0x00000000D83CDF71L, 0x00000000D83CDF63L, + 0x00000000D83CDF65L, 0x00000000D83CDF59L, 0x00000000D83CDF58L, 0x00000000D83CDF5AL, 0x00000000D83CDF5CL, 0x00000000D83CDF72L, 0x00000000D83CDF62L, + 0x00000000D83CDF61L, 0x00000000D83CDF73L, 0x00000000D83CDF5EL, 0x00000000D83CDF69L, 0x00000000D83CDF6EL, 0x00000000D83CDF66L, 0x00000000D83CDF68L, + 0x00000000D83CDF67L, 0x00000000D83CDF82L, 0x00000000D83CDF70L, 0x00000000D83CDF6AL, 0x00000000D83CDF6BL, 0x00000000D83CDF6CL, 0x00000000D83CDF6DL, + 0x00000000D83CDF6FL, 0x00000000D83CDF4EL, 0x00000000D83CDF4FL, 0x00000000D83CDF4AL, 0x00000000D83CDF4BL, 0x00000000D83CDF52L, 0x00000000D83CDF47L, + 0x00000000D83CDF49L, 0x00000000D83CDF53L, 0x00000000D83CDF51L, 0x00000000D83CDF48L, 0x00000000D83CDF4CL, 0x00000000D83CDF50L, 0x00000000D83CDF4DL, + 0x00000000D83CDF60L, 0x00000000D83CDF46L, 0x00000000D83CDF45L, 0x00000000D83CDF3DL}, + new ulong[]{ + 0x00000000D83CDFE0L, 0x00000000D83CDFE1L, 0x00000000D83CDFEBL, 0x00000000D83CDFE2L, 0x00000000D83CDFE3L, 0x00000000D83CDFE5L, 0x00000000D83CDFE6L, 0x00000000D83CDFEAL, + 0x00000000D83CDFE9L, 0x00000000D83CDFE8L, 0x00000000D83DDC92L, 0x00000000000026EAL, 0x00000000D83CDFECL, 0x00000000D83CDFE4L, 0x00000000D83CDF07L, + 0x00000000D83CDF06L, 0x00000000D83CDFEFL, 0x00000000D83CDFF0L, 0x00000000000026FAL, 0x00000000D83CDFEDL, 0x00000000D83DDDFCL, 0x00000000D83DDDFEL, + 0x00000000D83DDDFBL, 0x00000000D83CDF04L, 0x00000000D83CDF05L, 0x00000000D83CDF03L, 0x00000000D83DDDFDL, 0x00000000D83CDF09L, 0x00000000D83CDFA0L, + 0x00000000D83CDFA1L, 0x00000000000026F2L, 0x00000000D83CDFA2L, 0x00000000D83DDEA2L, 0x00000000000026F5L, 0x00000000D83DDEA4L, 0x00000000D83DDEA3L, + 0x0000000000002693L, 0x00000000D83DDE80L, 0x0000000000002708L, 0x00000000D83DDCBAL, 0x00000000D83DDE81L, 0x00000000D83DDE82L, 0x00000000D83DDE8AL, + 0x00000000D83DDE89L, 0x00000000D83DDE9EL, 0x00000000D83DDE86L, 0x00000000D83DDE84L, 0x00000000D83DDE85L, 0x00000000D83DDE88L, 0x00000000D83DDE87L, + 0x00000000D83DDE9DL, 0x00000000D83DDE8BL, 0x00000000D83DDE83L, 0x00000000D83DDE8EL, 0x00000000D83DDE8CL, 0x00000000D83DDE8DL, 0x00000000D83DDE99L, + 0x00000000D83DDE98L, 0x00000000D83DDE97L, 0x00000000D83DDE95L, 0x00000000D83DDE96L, 0x00000000D83DDE9BL, 0x00000000D83DDE9AL, 0x00000000D83DDEA8L, + 0x00000000D83DDE93L, 0x00000000D83DDE94L, 0x00000000D83DDE92L, 0x00000000D83DDE91L, 0x00000000D83DDE90L, 0x00000000D83DDEB2L, 0x00000000D83DDEA1L, + 0x00000000D83DDE9FL, 0x00000000D83DDEA0L, 0x00000000D83DDE9CL, 0x00000000D83DDC88L, 0x00000000D83DDE8FL, 0x00000000D83CDFABL, 0x00000000D83DDEA6L, + 0x00000000D83DDEA5L, 0x00000000000026A0L, 0x00000000D83DDEA7L, 0x00000000D83DDD30L, 0x00000000000026FDL, 0x00000000D83CDFEEL, 0x00000000D83CDFB0L, + 0x0000000000002668L, 0x00000000D83DDDFFL, 0x00000000D83CDFAAL, 0x00000000D83CDFADL, 0x00000000D83DDCCDL, 0x00000000D83DDEA9L, 0xD83CDDEFD83CDDF5L, + 0xD83CDDF0D83CDDF7L, 0xD83CDDE9D83CDDEAL, 0xD83CDDE8D83CDDF3L, 0xD83CDDFAD83CDDF8L, 0xD83CDDEBD83CDDF7L, 0xD83CDDEAD83CDDF8L, 0xD83CDDEED83CDDF9L, + 0xD83CDDF7D83CDDFAL, 0xD83CDDECD83CDDE7L}, + new ulong[]{ + 0x00000000003120E3L, 0x00000000003220E3L, 0x00000000003320E3L, 0x00000000003420E3L, 0x00000000003520E3L, 0x00000000003620E3L, 0x00000000003720E3L, 0x00000000003820E3L, + 0x00000000003920E3L, 0x00000000003020E3L, 0x00000000D83DDD1FL, 0x00000000D83DDD22L, 0x00000000002320E3L, 0x00000000D83DDD23L, 0x0000000000002B06L, + 0x0000000000002B07L, 0x0000000000002B05L, 0x00000000000027A1L, 0x00000000D83DDD20L, 0x00000000D83DDD21L, 0x00000000D83DDD24L, 0x0000000000002197L, + 0x0000000000002196L, 0x0000000000002198L, 0x0000000000002199L, 0x0000000000002194L, 0x0000000000002195L, 0x00000000D83DDD04L, 0x00000000000025C0L, + 0x00000000000025B6L, 0x00000000D83DDD3CL, 0x00000000D83DDD3DL, 0x00000000000021A9L, 0x00000000000021AAL, 0x0000000000002139L, 0x00000000000023EAL, + 0x00000000000023E9L, 0x00000000000023EBL, 0x00000000000023ECL, 0x0000000000002935L, 0x0000000000002934L, 0x00000000D83CDD97L, 0x00000000D83DDD00L, + 0x00000000D83DDD01L, 0x00000000D83DDD02L, 0x00000000D83CDD95L, 0x00000000D83CDD99L, 0x00000000D83CDD92L, 0x00000000D83CDD93L, 0x00000000D83CDD96L, + 0x00000000D83DDCF6L, 0x00000000D83CDFA6L, 0x00000000D83CDE01L, 0x00000000D83CDE2FL, 0x00000000D83CDE33L, 0x00000000D83CDE35L, 0x00000000D83CDE34L /* was missing */, 0x00000000D83CDE32L, + 0x00000000D83CDE50L /* //34 was wrong */, 0x00000000D83CDE39L /* //32 was duplicate */, /* removed 3 */ 0x00000000D83CDE3AL, 0x00000000D83CDE36L, 0x00000000D83CDE1AL, + 0x00000000D83DDEBBL, 0x00000000D83DDEB9L, 0x00000000D83DDEBAL, 0x00000000D83DDEBCL, 0x00000000D83DDEBEL, 0x00000000D83DDEB0L, 0x00000000D83DDEAEL, + 0x00000000D83CDD7FL, 0x000000000000267FL, 0x00000000D83DDEADL, 0x00000000D83CDE37L, 0x00000000D83CDE38L, 0x00000000D83CDE02L, 0x00000000000024C2L, + /* missing 4 unicodes */ + 0x00000000D83DDEC2L, 0x00000000D83DDEC4L, 0x00000000D83DDEC5L, 0x00000000D83DDEC3L, + 0x00000000D83CDE51L, 0x0000000000003299L, 0x0000000000003297L, 0x00000000D83CDD91L, 0x00000000D83CDD98L, 0x00000000D83CDD94L, 0x00000000D83DDEABL, + 0x00000000D83DDD1EL, 0x00000000D83DDCF5L, 0x00000000D83DDEAFL, 0x00000000D83DDEB1L, 0x00000000D83DDEB3L, 0x00000000D83DDEB7L, 0x00000000D83DDEB8L, + 0x00000000000026D4L, 0x0000000000002733L, 0x0000000000002747L, 0x000000000000274EL, 0x0000000000002705L, 0x0000000000002734L, 0x00000000D83DDC9FL, + 0x00000000D83CDD9AL, 0x00000000D83DDCF3L, 0x00000000D83DDCF4L, 0x00000000D83CDD70L, 0x00000000D83CDD71L, 0x00000000D83CDD8EL, 0x00000000D83CDD7EL, + 0x00000000D83DDCA0L, 0x00000000000027BFL, 0x000000000000267BL, 0x0000000000002648L, 0x0000000000002649L, 0x000000000000264AL, 0x000000000000264BL, + 0x000000000000264CL, 0x000000000000264DL, 0x000000000000264EL, 0x000000000000264FL, 0x0000000000002650L, 0x0000000000002651L, 0x0000000000002652L, + 0x0000000000002653L, 0x00000000000026CEL, 0x00000000D83DDD2FL, 0x00000000D83CDFE7L, 0x00000000D83DDCB9L, 0x00000000D83DDCB2L, 0x00000000D83DDCB1L, + 0x00000000000000A9L, 0x00000000000000AEL, 0x0000000000002122L /* TM */, + /* was mixed, missing 2-3 */ + 0x000000000000274CL, 0x000000000000203CL, 0x0000000000002049L, 0x0000000000002757L, 0x0000000000002753L, 0x0000000000002755L, 0x0000000000002754L, 0x0000000000002B55L, + 0x00000000D83DDD1DL, 0x00000000D83DDD1AL, + 0x00000000D83DDD19L, 0x00000000D83DDD1BL, 0x00000000D83DDD1CL, + 0x00000000D83DDD03L, 0x00000000D83DDD5BL, 0x00000000D83DDD67L, 0x00000000D83DDD50L, 0x00000000D83DDD5CL, + 0x00000000D83DDD51L, 0x00000000D83DDD5DL, 0x00000000D83DDD52L, 0x00000000D83DDD5EL, 0x00000000D83DDD53L, 0x00000000D83DDD5FL, 0x00000000D83DDD54L, + 0x00000000D83DDD60L, 0x00000000D83DDD55L, 0x00000000D83DDD56L, 0x00000000D83DDD57L, 0x00000000D83DDD58L, 0x00000000D83DDD59L, 0x00000000D83DDD5AL, + 0x00000000D83DDD61L, 0x00000000D83DDD62L, 0x00000000D83DDD63L, 0x00000000D83DDD64L, 0x00000000D83DDD65L, 0x00000000D83DDD66L, 0x0000000000002716L, + 0x0000000000002795L, 0x0000000000002796L, 0x0000000000002797L, 0x0000000000002660L, 0x0000000000002665L, 0x0000000000002663L, 0x0000000000002666L, + 0x00000000D83DDCAEL, 0x00000000D83DDCAFL, 0x0000000000002714L, 0x0000000000002611L, 0x00000000D83DDD18L, 0x00000000D83DDD17L, 0x00000000000027B0L, + 0x0000000000003030L, 0x000000000000303DL, 0x00000000D83DDD31L, + 0x00000000000025FCL, 0x00000000000025FBL, 0x00000000000025FEL, 0x00000000000025FDL, + 0x00000000000025AAL, 0x00000000000025ABL, + 0x00000000D83DDD3AL, 0x00000000D83DDD32L, 0x00000000D83DDD33L, 0x00000000000026ABL, 0x00000000000026AAL, + 0x00000000D83DDD34L, 0x00000000D83DDD35L, 0x00000000D83DDD3BL, 0x0000000000002B1CL, 0x0000000000002B1BL, 0x00000000D83DDD36L, 0x00000000D83DDD37L, 0x00000000D83DDD38L, 0x00000000D83DDD39L}}; + } +} diff --git a/EmojiPanel/EmojiPanel/Controls/Emoji/EmojiSpriteItem.cs b/EmojiPanel/EmojiPanel/Controls/Emoji/EmojiSpriteItem.cs new file mode 100755 index 0000000..edcdc34 --- /dev/null +++ b/EmojiPanel/EmojiPanel/Controls/Emoji/EmojiSpriteItem.cs @@ -0,0 +1,244 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using Telegram.Controls.VirtualizedView; + +namespace EmojiPanel.Controls.Emoji +{ + public class EmojiSpriteItem : VListItemBase + { + public int CategoryIndex; + public int SpriteOffset; + public int Rows; + + public EventHandler EmojiSelected = delegate { }; + + public EmojiSpriteItem(int categoryIndex, int spriteOffset) + { + CategoryIndex = categoryIndex; + SpriteOffset = spriteOffset; + Rows = EmojiData.SpriteRowsCountByCategory[categoryIndex][spriteOffset]; + + var emojiInCategory = EmojiData.CodesByCategory[categoryIndex]; + ulong[] emojis = null; + emojis = spriteOffset != 0 ? + emojiInCategory.Skip(spriteOffset*EmojiData.ItemsInSprite).Take(EmojiData.ItemsInSprite).ToArray() : + emojiInCategory.Take(EmojiData.ItemsInSprite).ToArray(); + + View.Width = SpriteWidth + 8; + var decodePixelWidth = SpriteWidth; + switch (Application.Current.Host.Content.ScaleFactor) + { + case 100: + break; + case 150: + decodePixelWidth = 711; + break; + case 160: + decodePixelWidth = 758; + break; + } + + var image = new Image + { + Width = SpriteWidth, + Source = new BitmapImage + { + DecodePixelWidth = decodePixelWidth, + DecodePixelType = DecodePixelType.Physical + //UriSource = spriteUri + }, + Margin = new Thickness(4, 1, 4, 1), + VerticalAlignment = VerticalAlignment.Top + }; + Children.Add(image); + + View.MouseLeftButtonDown += ViewOnMouseLeftButtonDown; + View.LostMouseCapture += ViewOnLostMouseCapture; + View.MouseLeftButtonUp += ViewOnLostMouseCapture; + View.MouseLeave += ViewOnLostMouseCapture; + View.Tap += ViewOnTap; + + CreateBorders(); + } + + public EmojiSpriteItem(Uri spriteUri, int categoryIndex, int spriteOffset) + { + CategoryIndex = categoryIndex; + SpriteOffset = spriteOffset; + Rows = EmojiData.SpriteRowsCountByCategory[categoryIndex][spriteOffset]; + + View.Width = SpriteWidth + 8; + var decodePixelWidth = SpriteWidth; + switch (Application.Current.Host.Content.ScaleFactor) + { + case 100: + break; + case 150: + decodePixelWidth = 711; + break; + case 160: + decodePixelWidth = 758; + break; + } + + var image = new Image + { + Width = SpriteWidth, + Source = new BitmapImage + { + DecodePixelWidth = decodePixelWidth, + DecodePixelType = DecodePixelType.Physical, + UriSource = spriteUri + }, + Margin = new Thickness(4, 1, 4, 1), + VerticalAlignment = VerticalAlignment.Top + }; + Children.Add(image); + + View.MouseLeftButtonDown += ViewOnMouseLeftButtonDown; + View.LostMouseCapture += ViewOnLostMouseCapture; + View.MouseLeftButtonUp += ViewOnLostMouseCapture; + View.MouseLeave += ViewOnLostMouseCapture; + View.Tap += ViewOnTap; + + CreateBorders(); + } + + private static void ViewOnLostMouseCapture(object sender, MouseEventArgs mouseEventArgs) + { + ClearCurrentHighlight(); + } + + public static void ClearCurrentHighlight() + { + if (_currentHighlight == null) return; + + var parent = _currentHighlight.Parent as Grid; + if (parent != null) + parent.Children.Remove(_currentHighlight); + + _currentHighlight = null; + } + + private void ViewOnMouseLeftButtonDown(object sender, MouseButtonEventArgs args) + { + var point = args.GetPosition(View); + var column = (int) Math.Ceiling(point.X / ColumnWidth); + var row = (int) Math.Ceiling(point.Y / RowHeight); + + if (column <= 0 || row <= 0) return; + if (Rows < MaxRowsInSprite && row == Rows) + { + if (EmojiData.ItemsInRow - EmojiData.SpriteMissingCellsByCategory[CategoryIndex] < column) + return; + } + + var emojiHoverBackground = new Rectangle + { + Width = ColumnWidth - 2, //width without 2px border + Height = RowHeight, + Fill = (Brush) Application.Current.Resources["PhoneAccentBrush"], + Margin = new Thickness((column - 1) * 79 + 4, (row - 1) * 70 + 2, 0, 0), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top + }; + View.Children.Insert(0, emojiHoverBackground); + + ClearCurrentHighlight(); + _currentHighlight = emojiHoverBackground; + } + + private void ViewOnTap(object sender, GestureEventArgs args) + { + var point = args.GetPosition(View); + var column = (int) Math.Ceiling(point.X / 79); + var row = (int) Math.Ceiling(point.Y / 70); + + if (column <= 0 || row <= 0) return; + + //Debug.WriteLine("{0}-{1}", column, row); + + var itemIndex = (row - 1) * EmojiData.ItemsInRow + (column - 1); + + var emoji = EmojiDataItem.GetByIndex(CategoryIndex, SpriteOffset, itemIndex); + if (emoji != null) + EmojiSelected(null, emoji); + } + + private static Rectangle _currentHighlight; + + private void CreateBorders() + { + for (int i = 0; i < Rows + 1; i++) + { + var line = new Rectangle + { + Width = SpriteWidth + 4, + Height = 2, + Fill = (Brush) Application.Current.Resources["PhoneChromeBrush"], + Margin = new Thickness(0, i * RowHeight, 0, 0), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top + }; + Children.Add(line); + } + + for (int i = 0; i < 5; i++) + { + var line = new Rectangle + { + Width = 2, + Height = RowHeight * Rows, + Fill = (Brush) Application.Current.Resources["PhoneChromeBrush"], + Margin = new Thickness((i + 1) * ColumnWidth + 2, 0, 0, 0), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top + }; + Children.Add(line); + } + + if (Rows < MaxRowsInSprite) + { + var missingRows = EmojiData.SpriteMissingCellsByCategory[CategoryIndex]; + var startIndex = EmojiData.ItemsInRow - missingRows; + + var width = missingRows * ColumnWidth; + var horizontalOffset = startIndex * ColumnWidth + 4; + + var rect = new Rectangle + { + Fill = (Brush) Application.Current.Resources["PhoneChromeBrush"], + Width = width, + Height = RowHeight, + Margin = new Thickness(horizontalOffset, (Rows - 1) * RowHeight, 0, 0), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top + }; + Children.Add(rect); + } + } + + public const int SpriteWidth = 472; + public const int SpriteHeight = 420; + public const int ColumnWidth = 79; + public const int RowHeight = 70; // 105 in pixel logic + + public const int MaxRowsInSprite = 6; + + public override double FixedHeight + { + get { return RowHeight * Rows; } + set { } + } + } +} diff --git a/EmojiPanel/EmojiPanel/Controls/Utilites/DelayedExecutor.cs b/EmojiPanel/EmojiPanel/Controls/Utilites/DelayedExecutor.cs new file mode 100755 index 0000000..5dd7a1e --- /dev/null +++ b/EmojiPanel/EmojiPanel/Controls/Utilites/DelayedExecutor.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Phone.Logging; + +namespace Telegram.Controls.Utilities +{ + public class DelayedExecutor + { + class ExecutionInfo + { + public Action Action { get; set; } + public DateTime Timestamp { get; set; } + } + + ExecutionInfo m_executionInfo; + Timer m_timer; + int m_delay; + bool m_timerIsActive; + object m_lockObj = new object(); + + public DelayedExecutor(int delay) // TO DO : add IDateTimeProvider dependency to remove dependency on DateTime + { + m_delay = delay; + m_timer = new Timer(TimerCallback); + } + + public void AddToDelayedExecution(Action action) + { + lock (m_lockObj) + { + m_executionInfo = new ExecutionInfo() { Action = action, Timestamp = DateTime.Now }; + } + + ChangeTimer(true); + } + + private void TimerCallback(object state) + { + Action executeAction = null; + + lock (m_lockObj) + { + if (m_executionInfo != null) + { + if (DateTime.Now - m_executionInfo.Timestamp >= TimeSpan.FromMilliseconds(m_delay)) + { + Debug.WriteLine("Action is set to be executed."); + executeAction = m_executionInfo.Action; + m_executionInfo = null; + ChangeTimer(false); + } + } + } + if (executeAction != null) + { + try + { + executeAction(); + } + catch (Exception exc) + { + //Logger.Instance.Error("Exeption during delayed execution", exc); + } + } + } + + private void ChangeTimer(bool activate) + { + if (activate && !m_timerIsActive) + { + lock (m_timer) + { + m_timerIsActive = true; + m_timer.Change(m_delay, m_delay); + } + } + else if (!activate && m_timerIsActive) + { + lock (m_timer) + { + m_timerIsActive = false; + m_timer.Change(Timeout.Infinite, 0); + } + } + } + } +} diff --git a/EmojiPanel/EmojiPanel/Controls/Utilites/Helpers.cs b/EmojiPanel/EmojiPanel/Controls/Utilites/Helpers.cs new file mode 100755 index 0000000..6f067e5 --- /dev/null +++ b/EmojiPanel/EmojiPanel/Controls/Utilites/Helpers.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace EmojiPanel.Controls.Utilites +{ + public static class Helpers + { + public static Uri GetAssetUri(string assetName) + { + switch (Application.Current.Host.Content.ScaleFactor) + { + case 100: + return new Uri(String.Format("/Assets/{0}-WVGA.png", assetName), UriKind.Relative); + case 160: + return new Uri(String.Format("/Assets/{0}-WXGA.png", assetName), UriKind.Relative); + case 150: + return new Uri(String.Format("/Assets/{0}-720p.png", assetName), UriKind.Relative); + default: + return new Uri(String.Format("/Assets/{0}-WVGA.png", assetName), UriKind.Relative); + } + } + } +} diff --git a/EmojiPanel/EmojiPanel/Controls/Utilites/MyListItemBase.cs b/EmojiPanel/EmojiPanel/Controls/Utilites/MyListItemBase.cs new file mode 100755 index 0000000..8ef5c45 --- /dev/null +++ b/EmojiPanel/EmojiPanel/Controls/Utilites/MyListItemBase.cs @@ -0,0 +1,25 @@ +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using Telegram.Controls.VirtualizedView; + +namespace Telegram.Controls.VirtualizedView +{ + public class MyListItemBase : Grid + { + //private Panel _contentPanel; + //public Panel ContentPanel + //{ + // get + // { + // return _contentPanel; + // } + // set + // { + // _contentPanel = value; + // Content = _contentPanel; + // } + //} + + public VListItemBase VirtSource { get; set; } + } +} diff --git a/EmojiPanel/EmojiPanel/Controls/Utilites/MyVirtualizingPanel.cs b/EmojiPanel/EmojiPanel/Controls/Utilites/MyVirtualizingPanel.cs new file mode 100755 index 0000000..597b8ea --- /dev/null +++ b/EmojiPanel/EmojiPanel/Controls/Utilites/MyVirtualizingPanel.cs @@ -0,0 +1,586 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Media; +using Telegram.Controls.Utilities; + +namespace Telegram.Controls.VirtualizedView +{ + public class MyVirtualizingPanel : Canvas + { + private const bool IsLogEnabled = false; + + private static void Log(string str) + { + if (IsLogEnabled) + { + Debug.WriteLine(str); + } + } + + + private const double LoadUnloadThreshold = 500; + private const double LoadedHeightUpwards = 300; + private const double LoadedHeightDownwards = 900; + private const double LoadedHeightDownwardsNotScrolling = 800; + + private bool _changingVerticalOffset = false; + + readonly DependencyProperty _listVerticalOffsetProperty = DependencyProperty.Register( + "ListVerticalOffset", + typeof(double), + typeof(MyVirtualizingPanel), + new PropertyMetadata(new PropertyChangedCallback(OnListVerticalOffsetChanged))); + + public double ListVerticalOffset + { + get { return (double) this.GetValue(_listVerticalOffsetProperty); } + set { this.SetValue(_listVerticalOffsetProperty, value); } + } + + private static void OnListVerticalOffsetChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) + { + var control = (MyVirtualizingPanel) obj; + control.OnListVerticalOffsetChanged(); + } + + private ScrollViewer _scrollViewer; + bool _isScrolling = false; + + public ScrollViewer ScrollViewer + { + get { return _scrollViewer; } + } + + public void InitializeWithScrollViewer(ScrollViewer scrollViewer) + { + _scrollViewer = scrollViewer; + EnsureBoundToScrollViewer(); + } + + protected void EnsureBoundToScrollViewer() + { + Binding binding = new Binding + { + Source = _scrollViewer, + Path = new PropertyPath("VerticalOffset"), + Mode = BindingMode.OneWay + }; + this.SetBinding(_listVerticalOffsetProperty, binding); + + + } + + bool _notReactToScroll = false; + private double _savedDelta; + //private DelayedExecutor _de = new DelayedExecutor(300); + //internal void PrepareForScrollToBottom() + //{ + // _notReactToScroll = true; + // _savedDelta = DeltaOffset; + // // load in the end + // DeltaOffset = _scrollViewer.ExtentHeight - _scrollViewer.ViewportHeight - _scrollViewer.VerticalOffset; + // Debug.WriteLine("PrepareForScrollToBottom"); + // PerformLoadUnload2(VirtualizableState.LoadedPartially, false); + // _de.AddToDelayedExecution(() => + // { + // Execute.ExecuteOnUIThread(() => ScrollToBottomCompleted()); + // }); + //} + + //internal void ScrollToBottomCompleted() + //{ + // _notReactToScroll = false; + // DeltaOffset = _savedDelta; + // PerformLoadUnload(VirtualizableState.LoadedFully); + // Debug.WriteLine("ScrolltoBottomCompleted"); + //} + + private void group_CurrentStateChanging(object sender, VisualStateChangedEventArgs e) + { + if (e.NewState.Name == "Scrolling") + { + _isScrolling = true; + } + else + { + _isScrolling = false; + PerformLoadUnload(true); + } + } + + private static VisualStateGroup FindVisualState(FrameworkElement element, string name) + { + if (element == null) + return null; + + IList groups = VisualStateManager.GetVisualStateGroups(element); + foreach (VisualStateGroup group in groups) + if (group.Name == name) + return group; + + return null; + } + + public class ScrollPositionChangedEventAgrs : EventArgs + { + public double CurrentPosition { get; private set; } + public double ScrollHeight { get; private set; } + + public ScrollPositionChangedEventAgrs(double currentPosition, + double scrollHeight) + { + CurrentPosition = currentPosition; + ScrollHeight = scrollHeight; + } + } + + public event EventHandler ScrollPositionChanged; + + private double _previousScrollOffset = 0; + private DateTime _previousScrollOffsetChangedTime = DateTime.MinValue; + private const double PixelsPerSecondThreshold = 200; + + private void OnListVerticalOffsetChanged() + { + if (_notReactToScroll) return; + + if (!_changingVerticalOffset) + { + + var w = new Stopwatch(); + w.Start(); + PerformLoadUnload(true); + w.Stop(); + + Log("LOADUNLOAD performed in " + w.ElapsedMilliseconds); + + if (ScrollPositionChanged != null) + { + ScrollPositionChanged(this, new ScrollPositionChangedEventAgrs( + _scrollViewer.VerticalOffset, + Height)); + } + + Log("Reported Offset: " + _scrollViewer.VerticalOffset); + } + } + + private bool DetermineIfScrollingIsFast() + { + var now = DateTime.Now; + var result = false; + if (_previousScrollOffsetChangedTime != DateTime.Now) + { + var scrolledPixels = Math.Abs(_scrollViewer.VerticalOffset - _previousScrollOffset); + var timeInSeconds = (now - _previousScrollOffsetChangedTime).TotalSeconds; + + if (scrolledPixels != 0) + { + var speedPixelsPerSecond = scrolledPixels / timeInSeconds; + Log(String.Format("Speed of scroll {0} ", speedPixelsPerSecond)); + + if (speedPixelsPerSecond > PixelsPerSecondThreshold) + { + result = true; + } + } + } + + _previousScrollOffsetChangedTime = now; + _previousScrollOffset = _scrollViewer.VerticalOffset; + return result; + } + + private readonly List _virtItems = new List(); + + // indexes of loaded items + private Segment _loadedSegment = new Segment(); + + // maps a point to its index in _virtItems + // covers only points 0, LoadUnloadThreshold, 2*LoadUnloadThreshold, etc + private readonly Dictionary _thresholdPointIndexes = new Dictionary(); + + + // do not change through this property + public List VirtItems + { + get { return _virtItems; } + } + + public MyVirtualizingPanel() + { + Loaded += MyVirtualizingPanel_Loaded; + } + + void MyVirtualizingPanel_Loaded(object sender, RoutedEventArgs e) + { + if (!DesignerProperties.GetIsInDesignMode(this)) + { + // Visual States are always on the first child of the control template + FrameworkElement element = VisualTreeHelper.GetChild(_scrollViewer, 0) as FrameworkElement; + if (element != null) + { + VisualStateGroup group = FindVisualState(element, "ScrollStates"); + if (group != null) + { + group.CurrentStateChanging += group_CurrentStateChanging; + } + } + } + } + + public void AddItems(IEnumerable _itemsToBeAdded) + { + var sw = new Stopwatch(); + sw.Start(); + + double topMargin = 0; + + if (_virtItems.Count > 0) + { + topMargin = _virtItems.Sum(vi => vi.FixedHeight); + } + + foreach (var itemToBeAdded in _itemsToBeAdded) + { + itemToBeAdded.View.Margin = new Thickness(itemToBeAdded.Margin.Left, itemToBeAdded.Margin.Top + topMargin, itemToBeAdded.Margin.Right, itemToBeAdded.Margin.Bottom); + + _virtItems.Add(itemToBeAdded); + + var itemHeightIncludingMargin = itemToBeAdded.FixedHeight; + + List coveredPoints = GetCoveredPoints(topMargin, topMargin + itemHeightIncludingMargin); + + foreach (var coveredPoint in coveredPoints) + { + _thresholdPointIndexes[coveredPoint] = _virtItems.Count - 1; // index of the last + } + + topMargin += itemHeightIncludingMargin; + } + + PerformLoadUnload(true); + + Height = topMargin; + + sw.Stop(); + + Log(String.Format("MyVirtualizingPanel.AddItems {0}", sw.ElapsedMilliseconds)); + } + + + public void InsertRemoveItems(int index, List itemsToInsert, bool keepItemsBelowIndexFixed = false, VListItemBase itemToRemove = null) + { + bool needToAdjustScrollPositionAfterInsertion = false; + + if (keepItemsBelowIndexFixed) + { + double totalHeightOfAllItemsBeforeIndex = 0; + + for (int i = 0; i < index; i++) + { + totalHeightOfAllItemsBeforeIndex += VirtItems[i].FixedHeight + VirtItems[i].Margin.Top + VirtItems[i].Margin.Bottom; + } + + if (totalHeightOfAllItemsBeforeIndex < _scrollViewer.VerticalOffset + _scrollViewer.ViewportHeight) + { + needToAdjustScrollPositionAfterInsertion = true; + } + } + + // UnloadItemsInSegment(_loadedSegment); + _loadedSegment = new Segment(); + + var totalHeight = itemsToInsert.Sum(i => i.FixedHeight + i.Margin.Top + i.Margin.Bottom); + + _virtItems.InsertRange(index, itemsToInsert); + + if (itemToRemove != null) + { + itemToRemove.IsVLoaded = false; + totalHeight -= itemToRemove.FixedHeight + itemToRemove.Margin.Top + itemToRemove.Margin.Bottom; + _virtItems.Remove(itemToRemove); + } + + + RearrangeAllItems(); + + + if (needToAdjustScrollPositionAfterInsertion) + { + _changingVerticalOffset = true; + //Debug.WriteLine("SCROLLING TO " + _scrollViewer.VerticalOffset + totalHeight + " scroll height : " + _scrollViewer.ExtentHeight); + _scrollViewer.ScrollToVerticalOffset(_scrollViewer.VerticalOffset + totalHeight); + _changingVerticalOffset = false; + } + + PerformLoadUnload(false); + } + + public void RemoveItem(VListItemBase itemToBeRemoved) + { + itemToBeRemoved.IsVLoaded = false; + + + _virtItems.Remove(itemToBeRemoved); + _loadedSegment = new Segment(); + RearrangeAllItems(); + + PerformLoadUnload(true); + } + + private void RearrangeAllItems() + { + double topMargin = 0; + _thresholdPointIndexes.Clear(); + int ind = 0; + foreach (var item in _virtItems) + { + item.View.Margin = new Thickness(item.Margin.Left, item.Margin.Top + topMargin, item.Margin.Right, item.Margin.Bottom); + + var itemHeightIncludingMargin = item.FixedHeight + item.Margin.Top + item.Margin.Bottom; + + List coveredPoints = GetCoveredPoints(topMargin, topMargin + itemHeightIncludingMargin); + + foreach (var coveredPoint in coveredPoints) + { + _thresholdPointIndexes[coveredPoint] = ind; // index of the last + } + + topMargin += itemHeightIncludingMargin; + ind++; + } + + Height = topMargin; + _scrollViewer.UpdateLayout(); + } + + private void PerformLoadUnload2(bool isToLoad, bool bypassUnload = false) + { + if (_virtItems.Count == 0) + return; + + double currentOffset = GetRealOffset(); + + int lowestLoadedInd = 0; + int upperInd = 0; + + bool triggerLoading = false; + + if (isToLoad || _loadedSegment.IsEmpty) + { + triggerLoading = true; + } + else + { + lowestLoadedInd = _loadedSegment.LowerBound; + upperInd = _loadedSegment.UpperBound; + + double topPoint = _virtItems[lowestLoadedInd].View.Margin.Top; + double bottomPoint = _virtItems[upperInd].View.Margin.Top + _virtItems[upperInd].FixedHeight; + + if (currentOffset - topPoint < 500 || + bottomPoint - currentOffset < 1500) + { + triggerLoading = true; + } + } + + if (triggerLoading) + { + if (_scrollViewer.ExtentHeight < 3000 && _isScrolling) + { + //Debug.WriteLine("Detected short scroll; loading all items"); + // otherwise there are glitches in scrolling + lowestLoadedInd = 0; + upperInd = VirtItems.Count - 1; + isToLoad = true; + } + else + { + var threshold = (int) Math.Floor((currentOffset - (currentOffset % LoadUnloadThreshold))); + + int indexOfBaseItem = _thresholdPointIndexes.ContainsKey(threshold) ? _thresholdPointIndexes[threshold] : -1; + + lowestLoadedInd = upperInd = indexOfBaseItem < 0 ? 0 : indexOfBaseItem; + + double loadUpwards = LoadedHeightUpwards; + double loadDownwards = _isScrolling ? LoadedHeightDownwards : LoadedHeightDownwardsNotScrolling; + + //if (_isScrolling) + //{ + // loadUpwards = LoadUpwardsWhenScrolling; + // loadDownwards = LoadDownwardsWhenScrolling; + //} + + // count up from the lower point on view + while (lowestLoadedInd > 0 && currentOffset - _virtItems[lowestLoadedInd].View.Margin.Top < loadUpwards) + { + lowestLoadedInd--; + } + + while (upperInd < _virtItems.Count - 1 && _virtItems[upperInd].View.Margin.Top - currentOffset < loadDownwards) + { + upperInd++; + } + + } + + SetLoadedBounds(lowestLoadedInd, upperInd, isToLoad, bypassUnload); + + + if (IsLogEnabled) + { + string loadedIndexes = "Loaded indexes : "; + for (int i = 0; i < _virtItems.Count; i++) + { + if (_virtItems[i].IsVLoaded) + { + loadedIndexes += i + ","; + } + } + + Log(loadedIndexes); + } + } + + } + + public double DeltaOffset + { + get; + set; + } + + private double GetRealOffset() + { + //// it might throw exception + //try + //{ + // GeneralTransform childTransform = this.TransformToVisual(_listScrollViewer); + + // var p = childTransform.Transform(new Point(0, 0)); + + // var delta = p.Y; + // Debug.WriteLine("DELTA offset =" + delta + "; VerticalOffset=" + _listScrollViewer.VerticalOffset); + + // return -delta; + //} + //catch (Exception exc) + //{ + // return _listScrollViewer.VerticalOffset; + //} + + return _scrollViewer.VerticalOffset + DeltaOffset; + } + + private void PerformLoadUnload(bool isToLoad) + { + PerformLoadUnload2(isToLoad); + } + + private void SetLoadedBounds(int lowerBoundInd, int upperBoundInd, bool isToLoad, bool bypassUnload = false) + { + var newLoadedSegment = new Segment(lowerBoundInd, upperBoundInd); + + Segment newMinusLoaded1; + Segment newMinusLoaded2; + Segment intersection; + Segment loadedMinusNew1; + Segment loadedMinusNew2; + + newLoadedSegment.CompareToSegment(_loadedSegment, + out newMinusLoaded1, + out newMinusLoaded2, + out intersection, + out loadedMinusNew1, + out loadedMinusNew2); + + + Log(String.Format("LoadedSegment:{0}, NewSegment:{1}, NewMinusLoaded1:{2}, NewMinusLoaded2:{3}, loadedMinusNew1:{4}, loadedMinusNew2:{5}", + _loadedSegment, + newLoadedSegment, + newMinusLoaded1, + newMinusLoaded2, + loadedMinusNew1, + loadedMinusNew2)); + + if (isToLoad) + { + // ensure items are loaded fully for the whole segment + LoadItemsInSegment(newLoadedSegment); + } + + if (!bypassUnload) + { + UnloadItemsInSegment(loadedMinusNew1); + UnloadItemsInSegment(loadedMinusNew2); + } + _loadedSegment = newLoadedSegment; + + } + + private void UnloadItemsInSegment(Segment segment) + { + for (int i = segment.LowerBound; i <= segment.UpperBound; i++) + { + var item = _virtItems[i]; + + Children.Remove(item.View); + + item.IsVLoaded = false; + } + } + + private void LoadItemsInSegment(Segment segment) + { + for (int i = segment.LowerBound; i <= segment.UpperBound; i++) + { + var item = _virtItems[i]; + + item.IsVLoaded = true; + + if (!Children.Contains(item.View)) + { + Children.Add(item.View); + } + } + } + + private List GetCoveredPoints(double from, double to) + { + + var result = new List(); + + var candidate = from - (from % LoadUnloadThreshold); + + while (candidate <= to) + { + if (candidate >= from) + { + result.Add((int) Math.Floor(candidate)); + } + candidate += LoadUnloadThreshold; + } + + return result; + } + + public void ClearItems() + { + _virtItems.Clear(); + Children.Clear(); + _loadedSegment = new Segment(); + _thresholdPointIndexes.Clear(); + _scrollViewer.ScrollToVerticalOffset(0); + Height = 0; + } + } +} diff --git a/EmojiPanel/EmojiPanel/Controls/Utilites/VListItemBase.cs b/EmojiPanel/EmojiPanel/Controls/Utilites/VListItemBase.cs new file mode 100755 index 0000000..edfeb47 --- /dev/null +++ b/EmojiPanel/EmojiPanel/Controls/Utilites/VListItemBase.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using System.Windows; +using Rectangle = System.Windows.Shapes.Rectangle; + +namespace Telegram.Controls.VirtualizedView +{ + public abstract class VListItemBase + { + private readonly List _children = new List(); + + public MyListItemBase View { get; private set; } + + public List Children + { + get { return _children; } + } + + protected VListItemBase() + { + View = new MyListItemBase + { + VirtSource = this, + Width = 440 + }; + } + public abstract double FixedHeight { get; set; } + + public Thickness Margin = new Thickness(); + + public virtual object ItemSource { get; set; } + + private bool _isVLoaded; + + public bool IsVLoaded + { + get { return _isVLoaded; } + set + { + if (value != IsVLoaded) + { + if (value) Load(); + else Unload(); + } + _isVLoaded = value; + } + } + + public virtual void Load() + { + if (View.Children.Count == 0) + foreach (var child in _children) + View.Children.Add(child); + } + + public virtual void Unload() + { + View.Children.Clear(); + } + } +} diff --git a/EmojiPanel/EmojiPanel/Controls/Utilites/VirtSegment.cs b/EmojiPanel/EmojiPanel/Controls/Utilites/VirtSegment.cs new file mode 100755 index 0000000..bc883aa --- /dev/null +++ b/EmojiPanel/EmojiPanel/Controls/Utilites/VirtSegment.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Telegram.Controls.Utilities +{ + public class Segment + { + public int LowerBound { get; private set; } + public int UpperBound { get; private set; } + + public bool IsEmpty { get { return UpperBound < LowerBound; } } + + public Segment(int lowerBound, int upperBound) + { + LowerBound = lowerBound; + UpperBound = upperBound; + } + + public Segment() + : this(0, -1) + { + } + + public override string ToString() + { + if (IsEmpty) return "[]"; + return String.Format("[{0},{1}]", LowerBound, UpperBound); + } + + public void CompareToSegment( + Segment otherSegment, + out Segment thisMinusOther1, + out Segment thisMinusOther2, + out Segment intersection, + out Segment otherMinusThis1, + out Segment otherMinusThis2) + { + + thisMinusOther1 = new Segment(); + thisMinusOther2 = new Segment(); + intersection = new Segment(); + otherMinusThis1 = new Segment(); + otherMinusThis2 = new Segment(); + + + if (this.IsEmpty) + { + otherMinusThis1 = otherSegment; + return; + } + + if (otherSegment.IsEmpty) + { + thisMinusOther1 = this; + return; + } + + if (this.UpperBound < otherSegment.LowerBound) + { + + // do not intersect + + thisMinusOther1 = this; + + otherMinusThis1 = otherSegment; + + return; + } + + + if (this.LowerBound < otherSegment.LowerBound && + this.UpperBound >= otherSegment.LowerBound && + this.UpperBound <= otherSegment.UpperBound) + { + thisMinusOther1 = new Segment(this.LowerBound, otherSegment.LowerBound - 1); + intersection = new Segment(otherSegment.LowerBound, this.UpperBound); + otherMinusThis1 = new Segment(this.UpperBound + 1, otherSegment.UpperBound); + return; + } + + if (this.LowerBound >= otherSegment.LowerBound && + this.UpperBound <= otherSegment.UpperBound) + { + intersection = this; + otherMinusThis1 = new Segment(otherSegment.LowerBound, this.LowerBound - 1); + otherMinusThis2 = new Segment(this.UpperBound + 1, otherSegment.UpperBound); + return; + } + + otherSegment.CompareToSegment(this, + out otherMinusThis1, + out otherMinusThis2, + out intersection, + out thisMinusOther1, + out thisMinusOther2); + + } + } +} diff --git a/EmojiPanel/EmojiPanel/EmojiPanel.csproj b/EmojiPanel/EmojiPanel/EmojiPanel.csproj new file mode 100755 index 0000000..b71ac5a --- /dev/null +++ b/EmojiPanel/EmojiPanel/EmojiPanel.csproj @@ -0,0 +1,1094 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {2FCB4C15-FE40-496F-87D6-84220F3F07F8} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + EmojiPanel + EmojiPanel + v8.0 + + + + + WindowsPhone + true + + + true + true + EmojiPanel_$(Configuration)_$(Platform).xap + Properties\AppManifest.xml + EmojiPanel.App + true + true + + + + + 4.0 + 11.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + Bin\x86\Debug + true + full + false + + + + Bin\x86\Release + pdbonly + true + + + + Bin\ARM\Debug + true + full + false + + + + Bin\ARM\Release + pdbonly + true + + + + App.xaml + + + EmojiControl.xaml + + + + + + + + + + + MainPage.xaml + + + + + + Designer + MSBuild:Compile + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + MSBuild:Compile + Designer + + + + + + Designer + + + + + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + False + Клиентский профиль .NET Framework 3.5 с пакетом обновления 1 %28SP1%29 + false + + + False + .NET Framework 3.5 SP1 + false + + + + + + + + + + \ No newline at end of file diff --git a/EmojiPanel/EmojiPanel/MainPage.xaml b/EmojiPanel/EmojiPanel/MainPage.xaml new file mode 100755 index 0000000..034be70 --- /dev/null +++ b/EmojiPanel/EmojiPanel/MainPage.xaml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EmojiPanel/EmojiPanel/MainPage.xaml.cs b/EmojiPanel/EmojiPanel/MainPage.xaml.cs new file mode 100755 index 0000000..164fff5 --- /dev/null +++ b/EmojiPanel/EmojiPanel/MainPage.xaml.cs @@ -0,0 +1,52 @@ +using System; +using System.ComponentModel; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Navigation; +using EmojiPanel.Controls.Emoji; +using Microsoft.Phone.Controls; + +namespace EmojiPanel +{ + public partial class MainPage + { + public EmojiControl EmojiInstance; + + public MainPage() + { + InitializeComponent(); + } + + private void OnSmileIconClick(object sender, EventArgs e) + { + if (EmojiInstance == null) + { + // Initialize EmojiControl + EmojiInstance = EmojiControl.GetInstance(); + EmojiInstance.BindTextBox(InputTextBox); + + ContentPanel.Children.Add(EmojiInstance); // Add to view + } + + EmojiInstance.IsOpen = !EmojiInstance.IsOpen; + } + + protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) + { + base.OnNavigatingFrom(e); + + if (EmojiInstance == null) return; + + // Destroy EmojiControl + EmojiInstance.IsOpen = false; + EmojiInstance.UnbindTextBox(); + ContentPanel.Children.Remove(EmojiInstance); // Remove from view + EmojiInstance = null; + } + + private void ClearAllButtonClick(object sender, EventArgs e) + { + InputTextBox.Text = ""; + } + } +} \ No newline at end of file diff --git a/EmojiPanel/EmojiPanel/Properties/AppManifest.xml b/EmojiPanel/EmojiPanel/Properties/AppManifest.xml new file mode 100755 index 0000000..a955232 --- /dev/null +++ b/EmojiPanel/EmojiPanel/Properties/AppManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/EmojiPanel/EmojiPanel/Properties/AssemblyInfo.cs b/EmojiPanel/EmojiPanel/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..077d49d --- /dev/null +++ b/EmojiPanel/EmojiPanel/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("EmojiPanel")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("EmojiPanel")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[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("d6cfdaad-1212-43b4-9539-203b0c855191")] + +// 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")] +[assembly: NeutralResourcesLanguage("en-US")] diff --git a/EmojiPanel/EmojiPanel/Properties/WMAppManifest.xml b/EmojiPanel/EmojiPanel/Properties/WMAppManifest.xml new file mode 100755 index 0000000..39197ce --- /dev/null +++ b/EmojiPanel/EmojiPanel/Properties/WMAppManifest.xml @@ -0,0 +1,52 @@ + + + + + ApplicationIcon.png + + + + + + + + + + + + + + + + + + + + + + + + + Background.png + 0 + Background.png + EmojiPanel + + + + + + + + + False + + + + + + + + + + \ No newline at end of file diff --git a/ExifLib.WP8/ExifLib.WP8.csproj b/ExifLib.WP8/ExifLib.WP8.csproj new file mode 100755 index 0000000..8d275bd --- /dev/null +++ b/ExifLib.WP8/ExifLib.WP8.csproj @@ -0,0 +1,113 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {ED7BD6FE-8929-490A-81BE-521BB2C6D6F5} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + ExifLib.WP8 + ExifLib.WP8 + WindowsPhone + v8.0 + $(TargetFrameworkVersion) + false + true + 11.0 + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\x86\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\x86\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\ARM\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\ARM\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + ExifIds.cs + + + ExifIO.cs + + + ExifReader.cs + + + ExifTag.cs + + + JpegInfo.cs + + + + + + + + \ No newline at end of file diff --git a/ExifLib.WP8/Properties/AssemblyInfo.cs b/ExifLib.WP8/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..c4494f0 --- /dev/null +++ b/ExifLib.WP8/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("ExifLib.WP8")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ExifLib.WP8")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[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("ed7bd6fe-8929-490a-81be-521bb2c6d6f5")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/ExifLib/ExifIO.cs b/ExifLib/ExifIO.cs new file mode 100755 index 0000000..26d1a1d --- /dev/null +++ b/ExifLib/ExifIO.cs @@ -0,0 +1,100 @@ +using System; + +namespace ExifLib +{ + /// + /// Utility to handle multi-byte primitives in both big and little endian. + /// http://msdn.microsoft.com/en-us/library/system.bitconverter.islittleendian.aspx + /// http://en.wikipedia.org/wiki/Endianness + /// + public static class ExifIO + { + public static short ReadShort(byte[] Data, int offset, bool littleEndian) + { + if ((littleEndian && BitConverter.IsLittleEndian) || + (!littleEndian && !BitConverter.IsLittleEndian)) + { + return BitConverter.ToInt16(Data, offset); + } + else + { + byte[] beBytes = new byte[2] { Data[offset + 1], Data[offset] }; + return BitConverter.ToInt16(beBytes, 0); + } + } + + public static ushort ReadUShort(byte[] Data, int offset, bool littleEndian) + { + if ((littleEndian && BitConverter.IsLittleEndian) || + (!littleEndian && !BitConverter.IsLittleEndian)) + { + return BitConverter.ToUInt16(Data, offset); + } + else + { + byte[] beBytes = new byte[2] { Data[offset + 1], Data[offset] }; + return BitConverter.ToUInt16(beBytes, 0); + } + } + + public static int ReadInt(byte[] Data, int offset, bool littleEndian) + { + if ((littleEndian && BitConverter.IsLittleEndian) || + (!littleEndian && !BitConverter.IsLittleEndian)) + { + return BitConverter.ToInt32(Data, offset); + } + else + { + byte[] beBytes = new byte[4] { Data[offset + 3], Data[offset + 2], Data[offset + 1], Data[offset] }; + return BitConverter.ToInt32(beBytes, 0); + } + } + + public static uint ReadUInt(byte[] Data, int offset, bool littleEndian) + { + if ((littleEndian && BitConverter.IsLittleEndian) || + (!littleEndian && !BitConverter.IsLittleEndian)) + { + return BitConverter.ToUInt32(Data, offset); + } + else + { + byte[] beBytes = new byte[4] { Data[offset + 3], Data[offset + 2], Data[offset + 1], Data[offset] }; + return BitConverter.ToUInt32(beBytes, 0); + } + } + + public static float ReadSingle(byte[] Data, int offset, bool littleEndian) + { + if ((littleEndian && BitConverter.IsLittleEndian) || + (!littleEndian && !BitConverter.IsLittleEndian)) + { + return BitConverter.ToSingle(Data, offset); + } + else + { + // need to swap the data first + byte[] beBytes = new byte[4] { Data[offset + 3], Data[offset + 2], Data[offset + 1], Data[offset] }; + return BitConverter.ToSingle(beBytes, 0); + } + } + + public static double ReadDouble(byte[] Data, int offset, bool littleEndian) + { + if ((littleEndian && BitConverter.IsLittleEndian) || + (!littleEndian && !BitConverter.IsLittleEndian)) + { + return BitConverter.ToDouble(Data, offset); + } + else + { + // need to swap the data first + byte[] beBytes = new byte[8] { + Data[offset + 7], Data[offset + 6], Data[offset + 5], Data[offset + 4], + Data[offset + 3], Data[offset + 2], Data[offset + 1], Data[offset]}; + return BitConverter.ToDouble(beBytes, 0); + } + } + } +} diff --git a/ExifLib/ExifIds.cs b/ExifLib/ExifIds.cs new file mode 100755 index 0000000..a476151 --- /dev/null +++ b/ExifLib/ExifIds.cs @@ -0,0 +1,128 @@ +using System; + +namespace ExifLib +{ + public static class JpegId + { + public const int START = 0xFF; + public const int SOI = 0xD8; + public const int SOS = 0xDA; + public const int EOI = 0xD9; + public const int COM = 0xFE; + public const int JFIF = 0xE0; + public const int EXIF = 0xE1; + public const int IPTC = 0xED; + } + + public enum ExifIFD + { + Exif = 0x8769, + Gps = 0x8825 + } + + public enum ExifId + { + Unknown = -1, + + ImageWidth = 0x100, + ImageHeight = 0x101, + Orientation = 0x112, + XResolution = 0x11A, + YResolution = 0x11B, + ResolutionUnit = 0x128, + DateTime = 0x132, + Description = 0x10E, + Make = 0x10F, + Model = 0x110, + Software = 0x131, + Artist = 0x13B, + ThumbnailOffset = 0x201, + ThumbnailLength = 0x202, + ExposureTime = 0x829A, + FNumber = 0x829D, + Copyright = 0x8298, + FlashUsed = 0x9209, + UserComment = 0x9286 + } + + public enum ExifGps + { + Version = 0x0, + LatitudeRef = 0x1, + Latitude = 0x2, + LongitudeRef = 0x3, + Longitude = 0x4, + AltitudeRef = 0x5, + Altitude = 0x6, + TimeStamp = 0x7, + Satellites = 0x8, + Status = 0x9, + MeasureMode = 0xA, + DOP = 0xB, + SpeedRef = 0xC, + Speed = 0xD, + TrackRef = 0xE, + Track = 0xF, + ImgDirectionRef = 0x10, + ImgDirection = 0x11, + MapDatum = 0x12, + DestLatitudeRef = 0x13, + DestLatitude = 0x14, + DestLongitudeRef = 0x15, + DestLongitude = 0x16, + DestBearingRef = 0x17, + DestBearing = 0x18, + DestDistanceRef = 0x19, + DestDistance = 0x1A, + ProcessingMethod = 0x1B, + AreaInformation = 0x1C, + DateStamp = 0x1D, + Differential = 0x1E + } + + public enum ExifOrientation + { + TopLeft = 1, + BottomRight = 3, + TopRight = 6, + BottomLeft = 8, + Undefined = 9 + } + + public enum ExifUnit + { + Undefined = 1, + Inch = 2, + Centimeter = 3 + } + + /// + /// As per http://www.exif.org/Exif2-2.PDF + /// + [Flags] + public enum ExifFlash + { + No = 0x0, + Fired = 0x1, + StrobeReturnLightDetected = 0x6, + On = 0x8, + Off = 0x10, + Auto = 0x18, + FlashFunctionPresent = 0x20, + RedEyeReduction = 0x40 + } + + public enum ExifGpsLatitudeRef + { + Unknown = 0, + North, + South + } + + public enum ExifGpsLongitudeRef + { + Unknown = 0, + East, + West + } +} diff --git a/ExifLib/ExifLib.csproj b/ExifLib/ExifLib.csproj new file mode 100755 index 0000000..0cf0f44 --- /dev/null +++ b/ExifLib/ExifLib.csproj @@ -0,0 +1,69 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {1E7F202B-8830-42F6-BCDA-2A6C590A7E10} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + ExifLib + ExifLib + v4.0 + $(TargetFrameworkVersion) + WindowsPhone71 + Silverlight + false + true + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ExifLib/ExifReader.cs b/ExifLib/ExifReader.cs new file mode 100755 index 0000000..9e2b7b2 --- /dev/null +++ b/ExifLib/ExifReader.cs @@ -0,0 +1,262 @@ +using System; +using System.IO; + +namespace ExifLib +{ + /// + /// Based on http://www.media.mit.edu/pia/Research/deepview/exif.html + /// http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html + /// + public class ExifReader + { + public JpegInfo info { get; private set; } + private bool littleEndian = false; + + public static JpegInfo ReadJpeg(FileInfo fi) + { + DateTime then = DateTime.Now; + using (FileStream fs = fi.OpenRead()) + { + ExifReader reader = new ExifReader(fs); + reader.info.FileSize = (int)fi.Length; + reader.info.FileName = fi.Name; + reader.info.LoadTime = (DateTime.Now - then); + return reader.info; + } + } + + public static JpegInfo ReadJpeg(Stream stream) + { + var reader = new ExifReader(stream); + return reader.info; + } + + protected ExifReader(Stream stream) + { + info = new JpegInfo(); + int a = stream.ReadByte(); + + // ensure SOI marker + if (a != JpegId.START || stream.ReadByte() != JpegId.SOI) + return; + + info.IsValid = true; + + for (; ; ) + { + int marker = 0, prev = 0; + + // find next marker + for (a = 0; ; ++a) + { + marker = stream.ReadByte(); + if (marker != JpegId.START && prev == JpegId.START) break; + prev = marker; + } + + // read section length + int lenHigh = stream.ReadByte(); + int lenLow = stream.ReadByte(); + int itemlen = (lenHigh << 8) | lenLow; + + // read the section + byte[] section = new byte[itemlen]; + section[0] = (byte)lenHigh; + section[1] = (byte)lenLow; + int bytesRead = stream.Read(section, 2, itemlen - 2); + if (bytesRead != itemlen - 2) + return; + + switch (marker) + { + case JpegId.SOS: + // start of stream: and we're done + return; + case JpegId.EOI: + // no data? no good. + return; + case JpegId.EXIF: + { + if (section[2] == 'E' && + section[3] == 'x' && + section[4] == 'i' && + section[5] == 'f') + { + ProcessExif(section); + } + } break; + case JpegId.IPTC: + { + // don't care. + } break; + case 0xC0: + case 0xC1: + case 0xC2: + case 0xC3: + // case 0xC4: // not SOF + case 0xC5: + case 0xC6: + case 0xC7: + // case 0xC8: // not SOF + case 0xC9: + case 0xCA: + case 0xCB: + // case 0xCC: // not SOF + case 0xCD: + case 0xCE: + case 0xCF: + { + ProcessSOF(section, marker); + } break; + default: + { + // don't care. + } break; + } + + section = null; + GC.Collect(); + } + } + + private void ProcessExif(byte[] section) + { + int idx = 6; + if (section[idx++] != 0 || + section[idx++] != 0) + { + // "Exif" is not followed by 2 null bytes. + return; + } + + if (section[idx] == 'I' && section[idx + 1] == 'I') + { + // intel order + littleEndian = true; + } + else + { + if (section[idx] == 'M' && section[idx + 1] == 'M') + littleEndian = false; + else + { + // unknown order... + return; + } + } + idx += 2; + + int a = ExifIO.ReadUShort(section, idx, littleEndian); + idx += 2; + + if (a != 0x002A) + { + // bad start... + return; + } + + a = ExifIO.ReadInt(section, idx, littleEndian); + idx += 4; + + if (a < 8 || a > 16) + { + if (a < 16 || a > section.Length - 16) + { + // invalid offset + return; + } + } + + ProcessExifDir(section, a + 8, 8, section.Length - 8, 0, ExifIFD.Exif); + } + + private int DirOffset(int start, int num) + { + return start + 2 + 12 * num; + } + + private void ProcessExifDir(byte[] section, int offsetDir, int offsetBase, int length, int depth, ExifIFD ifd) + { + if (depth > 4) + { + // corrupted Exif header... + return; + } + + ushort numEntries = ExifIO.ReadUShort(section, offsetDir, littleEndian); + if (offsetDir + 2 + 12 * numEntries >= offsetDir + length) + { + // too long + return; + } + + int offset = 0; + + for (int de = 0; de < numEntries; ++de) + { + offset = DirOffset(offsetDir, de); + ExifTag exifTag = new ExifTag(section, offset, offsetBase, length, littleEndian); + + if (!exifTag.IsValid) + continue; + + switch (exifTag.Tag) + { + case (int)ExifIFD.Exif: + { + int dirStart = offsetBase + exifTag.GetInt(0); + if (dirStart <= offsetBase + length) + { + ProcessExifDir(section, dirStart, offsetBase, length, depth + 1, ExifIFD.Exif); + } + } break; + case (int)ExifIFD.Gps: + { + int dirStart = offsetBase + exifTag.GetInt(0); + if (dirStart <= offsetBase + length) + { + ProcessExifDir(section, dirStart, offsetBase, length, depth + 1, ExifIFD.Gps); + } + } break; + default: + { + exifTag.Populate(info, ifd); + } break; + } + } + + // final link defined? + offset = DirOffset(offsetDir, numEntries) + 4; + if (offset <= offsetBase + length) + { + offset = ExifIO.ReadInt(section, offsetDir + 2 + 12 * numEntries, littleEndian); + if (offset > 0) + { + int subDirStart = offsetBase + offset; + if (subDirStart <= offsetBase + length && subDirStart >= offsetBase) + { + ProcessExifDir(section, subDirStart, offsetBase, length, depth + 1, ifd); + } + } + } + + if (info.ThumbnailData == null && info.ThumbnailOffset > 0 && info.ThumbnailSize > 0) + { + // store it. + info.ThumbnailData = new byte[info.ThumbnailSize]; + Array.Copy(section, offsetBase + info.ThumbnailOffset, info.ThumbnailData, 0, info.ThumbnailSize); + } + } + + private void ProcessSOF(byte[] section, int marker) + { + // bytes 1,2 is section len + // byte 3 is precision (bytes per sample) + info.Height = ((int)section[3] << 8) | (int)section[4]; + info.Width = ((int)section[5] << 8) | (int)section[6]; + int components = (int)section[7]; + + info.IsColor = (components == 3); + } + } +} diff --git a/ExifLib/ExifTag.cs b/ExifLib/ExifTag.cs new file mode 100755 index 0000000..f046958 --- /dev/null +++ b/ExifLib/ExifTag.cs @@ -0,0 +1,254 @@ +using System; +using System.Text; + +namespace ExifLib +{ + /// + /// As per: http://www.media.mit.edu/pia/Research/deepview/exif.html + /// + public enum ExifTagFormat + { + BYTE = 1, + STRING = 2, + USHORT = 3, + ULONG = 4, + URATIONAL = 5, + SBYTE = 6, + UNDEFINED = 7, + SSHORT = 8, + SLONG = 9, + SRATIONAL = 10, + SINGLE = 11, + DOUBLE = 12, + + NUM_FORMATS = 12 + } + + public class ExifTag + { + public int Tag { get; private set; } + public ExifTagFormat Format { get; private set; } + public int Components { get; private set; } + public byte[] Data { get; private set; } + public bool LittleEndian { get; private set; } + + private static int[] BytesPerFormat = new int[] { 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8 }; + + public ExifTag(byte[] section, int sectionOffset, int offsetBase, int length, bool littleEndian) + { + this.IsValid = false; + this.Tag = ExifIO.ReadUShort(section, sectionOffset, littleEndian); + int format = ExifIO.ReadUShort(section, sectionOffset + 2, littleEndian); + if (format < 1 || format > 12) + return; + this.Format = (ExifTagFormat)format; + this.Components = ExifIO.ReadInt(section, sectionOffset + 4, littleEndian); + if (this.Components > 0x10000) + return; + this.LittleEndian = littleEndian; + + int byteCount = this.Components * BytesPerFormat[format]; + int valueOffset = 0; + + if (byteCount > 4) + { + int offsetVal = ExifIO.ReadInt(section, sectionOffset + 8, littleEndian); + if (offsetVal + byteCount > length) + { + // bad offset... + return; + } + valueOffset = offsetBase + offsetVal; + } + else + { + valueOffset = sectionOffset + 8; + } + this.Data = new byte[byteCount]; + Array.Copy(section, valueOffset, this.Data, 0, byteCount); + this.IsValid = true; + } + + public bool IsValid { get; private set; } + + private short ReadShort(int offset) + { + return ExifIO.ReadShort(Data, offset, LittleEndian); + } + + private ushort ReadUShort(int offset) + { + return ExifIO.ReadUShort(Data, offset, LittleEndian); + } + + private int ReadInt(int offset) + { + return ExifIO.ReadInt(Data, offset, LittleEndian); + } + + private uint ReadUInt(int offset) + { + return ExifIO.ReadUInt(Data, offset, LittleEndian); + } + + private float ReadSingle(int offset) + { + return ExifIO.ReadSingle(Data, offset, LittleEndian); + } + + private double ReadDouble(int offset) + { + return ExifIO.ReadDouble(Data, offset, LittleEndian); + } + + public bool IsNumeric + { + get + { + switch (Format) + { + case ExifTagFormat.STRING: + case ExifTagFormat.UNDEFINED: + return false; + default: + return true; + } + } + } + + public int GetInt(int componentIndex) + { + return (int)GetNumericValue(componentIndex); + } + + public double GetNumericValue(int componentIndex) + { + switch (Format) + { + case ExifTagFormat.BYTE: return (double)this.Data[componentIndex]; + case ExifTagFormat.USHORT: return (double)ReadUShort(componentIndex * 2); + case ExifTagFormat.ULONG: return (double)ReadUInt(componentIndex * 4); + case ExifTagFormat.URATIONAL: return (double)ReadUInt(componentIndex * 8) / (double)ReadUInt((componentIndex * 8) + 4); + case ExifTagFormat.SBYTE: + { + unchecked + { + return (double)(sbyte)this.Data[componentIndex]; + } + } + case ExifTagFormat.SSHORT: return (double)ReadShort(componentIndex * 2); + case ExifTagFormat.SLONG: return (double)ReadInt(componentIndex * 4); + case ExifTagFormat.SRATIONAL: return (double)ReadInt(componentIndex * 8) / (double)ReadInt((componentIndex * 8) + 4); + case ExifTagFormat.SINGLE: return (double)ReadSingle(componentIndex * 4); + case ExifTagFormat.DOUBLE: return ReadDouble(componentIndex * 8); + default: return 0.0; + } + } + + public string GetStringValue() + { + return GetStringValue(0); + } + + public string GetStringValue(int componentIndex) + { + switch (Format) + { + case ExifTagFormat.STRING: + case ExifTagFormat.UNDEFINED: + return Encoding.UTF8.GetString(this.Data, 0, this.Data.Length).Trim(' ', '\t', '\r', '\n', '\0'); + case ExifTagFormat.URATIONAL: + return ReadUInt(componentIndex * 8).ToString() + "/" + ReadUInt((componentIndex * 8) + 4).ToString(); + case ExifTagFormat.SRATIONAL: + return ReadInt(componentIndex * 8).ToString() + "/" + ReadInt((componentIndex * 8) + 4).ToString(); + default: + return GetNumericValue(componentIndex).ToString(); + } + } + + public virtual void Populate(JpegInfo info, ExifIFD ifd) + { + if (ifd == ExifIFD.Exif) + { + switch ((ExifId)this.Tag) + { + case ExifId.ImageWidth: info.Width = GetInt(0); break; + case ExifId.ImageHeight: info.Height = GetInt(0); break; + case ExifId.Orientation: info.Orientation = (ExifOrientation)GetInt(0); break; + case ExifId.XResolution: info.XResolution = GetNumericValue(0); break; + case ExifId.YResolution: info.YResolution = GetNumericValue(0); break; + case ExifId.ResolutionUnit: info.ResolutionUnit = (ExifUnit)GetInt(0); break; + case ExifId.DateTime: info.DateTime = GetStringValue(); break; + case ExifId.Description: info.Description = GetStringValue(); break; + case ExifId.Make: info.Make = GetStringValue(); break; + case ExifId.Model: info.Model = GetStringValue(); break; + case ExifId.Software: info.Software = GetStringValue(); break; + case ExifId.Artist: info.Artist = GetStringValue(); break; + case ExifId.ThumbnailOffset: info.ThumbnailOffset = GetInt(0); break; + case ExifId.ThumbnailLength: info.ThumbnailSize = GetInt(0); break; + case ExifId.Copyright: info.Copyright = GetStringValue(); break; + case ExifId.UserComment: info.UserComment = GetStringValue(); break; + case ExifId.ExposureTime: info.ExposureTime = GetNumericValue(0); break; + case ExifId.FNumber: info.FNumber = GetNumericValue(0); break; + case ExifId.FlashUsed: info.Flash = (ExifFlash)GetInt(0); break; + default: break; + } + } + else if (ifd == ExifIFD.Gps) + { + switch ((ExifGps)this.Tag) + { + case ExifGps.LatitudeRef: + { + if (GetStringValue() == "N") info.GpsLatitudeRef = ExifGpsLatitudeRef.North; + else if (GetStringValue() == "S") info.GpsLatitudeRef = ExifGpsLatitudeRef.South; + } break; + case ExifGps.LongitudeRef: + { + if (GetStringValue() == "E") info.GpsLongitudeRef = ExifGpsLongitudeRef.East; + else if (GetStringValue() == "W") info.GpsLongitudeRef = ExifGpsLongitudeRef.West; + } break; + case ExifGps.Latitude: + { + if (Components == 3) + { + info.GpsLatitude[0] = GetNumericValue(0); + info.GpsLatitude[1] = GetNumericValue(1); + info.GpsLatitude[2] = GetNumericValue(2); + } + } break; + case ExifGps.Longitude: + { + if (Components == 3) + { + info.GpsLongitude[0] = GetNumericValue(0); + info.GpsLongitude[1] = GetNumericValue(1); + info.GpsLongitude[2] = GetNumericValue(2); + } + } break; + } + } + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(64); + sb.Append("0x"); + sb.Append(this.Tag.ToString("X4")); + sb.Append("-"); + sb.Append(((ExifId)this.Tag).ToString()); + if (this.Components > 0) + { + sb.Append(": ("); + sb.Append(GetStringValue(0)); + if (Format != ExifTagFormat.UNDEFINED && Format != ExifTagFormat.STRING) + { + for (int i = 1; i < Components; ++i) + sb.Append(", " + GetStringValue(i)); + } + sb.Append(")"); + } + return sb.ToString(); + } + } +} diff --git a/ExifLib/JpegInfo.cs b/ExifLib/JpegInfo.cs new file mode 100755 index 0000000..6d640df --- /dev/null +++ b/ExifLib/JpegInfo.cs @@ -0,0 +1,119 @@ +using System; + +namespace ExifLib +{ + public class JpegInfo + { + /// + /// The Jpeg file name (excluding path). + /// + public string FileName; + /// + /// The Jpeg file size, in bytes. + /// + public int FileSize; + /// + /// True if the provided Stream was detected to be a Jpeg image, False otherwise. + /// + public bool IsValid; + + /// + /// Image dimensions, in pixels. + /// + public int Width, Height; + /// + /// True if the image data is expressed in 3 components (RGB), False otherwise. + /// + public bool IsColor; + + /// + /// Orientation of the image. + /// + public ExifOrientation Orientation; + /// + /// The X and Y resolutions of the image, expressed in ResolutionUnit. + /// + public double XResolution, YResolution; + /// + /// Resolution unit of the image. + /// + public ExifUnit ResolutionUnit; + + /// + /// Date at which the image was taken. + /// + public string DateTime; + /// + /// Description of the image. + /// + public string Description; + /// + /// Camera manufacturer. + /// + public string Make; + /// + /// Camera model. + /// + public string Model; + /// + /// Software used to create the image. + /// + public string Software; + /// + /// Image artist. + /// + public string Artist; + /// + /// Image copyright. + /// + public string Copyright; + /// + /// Image user comments. + /// + public string UserComment; + /// + /// Exposure time, in seconds. + /// + public double ExposureTime; + /// + /// F-number (F-stop) of the camera lens when the image was taken. + /// + public double FNumber; + /// + /// Flash settings of the camera when the image was taken. + /// + public ExifFlash Flash; + + /// + /// GPS latitude reference (North, South). + /// + public ExifGpsLatitudeRef GpsLatitudeRef; + /// + /// GPS latitude (degrees, minutes, seconds). + /// + public double[] GpsLatitude = new double[3]; + /// + /// GPS longitude reference (East, West). + /// + public ExifGpsLongitudeRef GpsLongitudeRef; + /// + /// GPS longitude (degrees, minutes, seconds). + /// + public double[] GpsLongitude = new double[3]; + + /// + /// Byte offset and size of the thumbnail data within the Exif section of the image file. + /// Used internally. + /// + public int ThumbnailOffset, ThumbnailSize; + /// + /// Thumbnail data found in the Exif section. + /// + public byte[] ThumbnailData; + + /// + /// Time taken to load the image information. + /// + public TimeSpan LoadTime; + } +} diff --git a/ExifLib/Properties/AssemblyInfo.cs b/ExifLib/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..e2ab74a --- /dev/null +++ b/ExifLib/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("ExifLib")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ExifLib")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[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("1e7f202b-8830-42f6-bcda-2a6c590a7e10")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/FFmpegInterop/Source/FFmpegInteropMSS.cpp b/FFmpegInterop/Source/FFmpegInteropMSS.cpp new file mode 100755 index 0000000..5ae3726 --- /dev/null +++ b/FFmpegInterop/Source/FFmpegInteropMSS.cpp @@ -0,0 +1,604 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#include "pch.h" +#include "FFmpegInteropMSS.h" +#include "MediaSampleProvider.h" +#include "H264AVCSampleProvider.h" +#include "H264SampleProvider.h" +#include "UncompressedAudioSampleProvider.h" +#include "UncompressedVideoSampleProvider.h" +#include "shcore.h" + +extern "C" +{ +#include +} + +using namespace concurrency; +using namespace FFmpegInterop; +using namespace Platform; +using namespace Windows::Storage::Streams; +using namespace Windows::Media::MediaProperties; + +// Size of the buffer when reading a stream +const int FILESTREAMBUFFERSZ = 16384; + +// Static functions passed to FFmpeg for stream interop +static int FileStreamRead(void* ptr, uint8_t* buf, int bufSize); +static int64_t FileStreamSeek(void* ptr, int64_t pos, int whence); + +// Initialize an FFmpegInteropObject +FFmpegInteropMSS::FFmpegInteropMSS() + : avDict(nullptr) + , avIOCtx(nullptr) + , avFormatCtx(nullptr) + , avAudioCodecCtx(nullptr) + , avVideoCodecCtx(nullptr) + , audioStreamIndex(AVERROR_STREAM_NOT_FOUND) + , videoStreamIndex(AVERROR_STREAM_NOT_FOUND) + , fileStreamData(nullptr) + , fileStreamBuffer(nullptr) +{ + av_register_all(); +} + +FFmpegInteropMSS::~FFmpegInteropMSS() +{ + if (mss) + { + mss->Starting -= startingRequestedToken; + mss->SampleRequested -= sampleRequestedToken; + mss = nullptr; + } + + // Clear our data + audioSampleProvider = nullptr; + videoSampleProvider = nullptr; + + if (m_pReader != nullptr) + { + m_pReader->SetAudioStream(AVERROR_STREAM_NOT_FOUND, nullptr); + m_pReader->SetVideoStream(AVERROR_STREAM_NOT_FOUND, nullptr); + m_pReader = nullptr; + } + + avcodec_close(avVideoCodecCtx); + avcodec_close(avAudioCodecCtx); + avformat_close_input(&avFormatCtx); + av_free(avIOCtx); + av_dict_free(&avDict); +} + +FFmpegInteropMSS^ FFmpegInteropMSS::CreateFFmpegInteropMSSFromStream(IRandomAccessStream^ stream, bool forceAudioDecode, bool forceVideoDecode, PropertySet^ ffmpegOptions) +{ + auto interopMSS = ref new FFmpegInteropMSS(); + if (FAILED(interopMSS->CreateMediaStreamSource(stream, forceAudioDecode, forceVideoDecode, ffmpegOptions))) + { + // We failed to initialize, clear the variable to return failure + interopMSS = nullptr; + } + + return interopMSS; +} + + +FFmpegInteropMSS^ FFmpegInteropMSS::CreateFFmpegInteropMSSFromStream(IRandomAccessStream^ stream, bool forceAudioDecode, bool forceVideoDecode) +{ + return CreateFFmpegInteropMSSFromStream(stream, forceAudioDecode, forceVideoDecode, nullptr); +} + +FFmpegInteropMSS^ FFmpegInteropMSS::CreateFFmpegInteropMSSFromUri(String^ uri, bool forceAudioDecode, bool forceVideoDecode, PropertySet^ ffmpegOptions) +{ + auto interopMSS = ref new FFmpegInteropMSS(); + if (FAILED(interopMSS->CreateMediaStreamSource(uri, forceAudioDecode, forceVideoDecode, ffmpegOptions))) + { + // We failed to initialize, clear the variable to return failure + interopMSS = nullptr; + } + + return interopMSS; +} + +FFmpegInteropMSS^ FFmpegInteropMSS::CreateFFmpegInteropMSSFromUri(String^ uri, bool forceAudioDecode, bool forceVideoDecode) +{ + return CreateFFmpegInteropMSSFromUri(uri, forceAudioDecode, forceVideoDecode, nullptr); +} + +MediaStreamSource^ FFmpegInteropMSS::GetMediaStreamSource() +{ + return mss; +} + +HRESULT FFmpegInteropMSS::CreateMediaStreamSource(String^ uri, bool forceAudioDecode, bool forceVideoDecode, PropertySet^ ffmpegOptions) +{ + HRESULT hr = S_OK; + const char* charStr = nullptr; + if (!uri) + { + hr = E_INVALIDARG; + } + + if (SUCCEEDED(hr)) + { + avFormatCtx = avformat_alloc_context(); + if (avFormatCtx == nullptr) + { + hr = E_OUTOFMEMORY; + } + } + + if (SUCCEEDED(hr)) + { + // Populate AVDictionary avDict based on PropertySet ffmpegOptions. List of options can be found in https://www.ffmpeg.org/ffmpeg-protocols.html + hr = ParseOptions(ffmpegOptions); + } + + if (SUCCEEDED(hr)) + { + std::wstring uriW(uri->Begin()); + std::string uriA(uriW.begin(), uriW.end()); + charStr = uriA.c_str(); + + // Open media in the given URI using the specified options + if (avformat_open_input(&avFormatCtx, charStr, NULL, &avDict) < 0) + { + hr = E_FAIL; // Error opening file + } + + // avDict is not NULL only when there is an issue with the given ffmpegOptions such as invalid key, value type etc. Iterate through it to see which one is causing the issue. + if (avDict != nullptr) + { + DebugMessage(L"Invalid FFmpeg option(s)"); + av_dict_free(&avDict); + avDict = nullptr; + } + } + + if (SUCCEEDED(hr)) + { + hr = InitFFmpegContext(forceAudioDecode, forceVideoDecode); + } + + return hr; +} + +HRESULT FFmpegInteropMSS::CreateMediaStreamSource(IRandomAccessStream^ stream, bool forceAudioDecode, bool forceVideoDecode, PropertySet^ ffmpegOptions) +{ + HRESULT hr = S_OK; + if (!stream) + { + hr = E_INVALIDARG; + } + + if (SUCCEEDED(hr)) + { + // Convert asynchronous IRandomAccessStream to synchronous IStream. This API requires shcore.h and shcore.lib + hr = CreateStreamOverRandomAccessStream(reinterpret_cast(stream), IID_PPV_ARGS(&fileStreamData)); + } + + if (SUCCEEDED(hr)) + { + // Setup FFmpeg custom IO to access file as stream. This is necessary when accessing any file outside of app installation directory and appdata folder. + // Credit to Philipp Sch http://www.codeproject.com/Tips/489450/Creating-Custom-FFmpeg-IO-Context + fileStreamBuffer = (unsigned char*)av_malloc(FILESTREAMBUFFERSZ); + if (fileStreamBuffer == nullptr) + { + hr = E_OUTOFMEMORY; + } + } + + if (SUCCEEDED(hr)) + { + avIOCtx = avio_alloc_context(fileStreamBuffer, FILESTREAMBUFFERSZ, 0, fileStreamData, FileStreamRead, 0, FileStreamSeek); + if (avIOCtx == nullptr) + { + hr = E_OUTOFMEMORY; + } + } + + if (SUCCEEDED(hr)) + { + avFormatCtx = avformat_alloc_context(); + if (avFormatCtx == nullptr) + { + hr = E_OUTOFMEMORY; + } + } + + if (SUCCEEDED(hr)) + { + // Populate AVDictionary avDict based on PropertySet ffmpegOptions. List of options can be found in https://www.ffmpeg.org/ffmpeg-protocols.html + hr = ParseOptions(ffmpegOptions); + } + + if (SUCCEEDED(hr)) + { + avFormatCtx->pb = avIOCtx; + avFormatCtx->flags |= AVFMT_FLAG_CUSTOM_IO; + + // Open media file using custom IO setup above instead of using file name. Opening a file using file name will invoke fopen C API call that only have + // access within the app installation directory and appdata folder. Custom IO allows access to file selected using FilePicker dialog. + if (avformat_open_input(&avFormatCtx, "", NULL, &avDict) < 0) + { + hr = E_FAIL; // Error opening file + } + + // avDict is not NULL only when there is an issue with the given ffmpegOptions such as invalid key, value type etc. Iterate through it to see which one is causing the issue. + if (avDict != nullptr) + { + DebugMessage(L"Invalid FFmpeg option(s)"); + av_dict_free(&avDict); + avDict = nullptr; + } + } + + if (SUCCEEDED(hr)) + { + hr = InitFFmpegContext(forceAudioDecode, forceVideoDecode); + } + + return hr; +} + +HRESULT FFmpegInteropMSS::InitFFmpegContext(bool forceAudioDecode, bool forceVideoDecode) +{ + HRESULT hr = S_OK; + + if (SUCCEEDED(hr)) + { + if (avformat_find_stream_info(avFormatCtx, NULL) < 0) + { + hr = E_FAIL; // Error finding info + } + } + + if (SUCCEEDED(hr)) + { + m_pReader = ref new FFmpegReader(avFormatCtx); + if (m_pReader == nullptr) + { + hr = E_OUTOFMEMORY; + } + } + + if (SUCCEEDED(hr)) + { + // Find the audio stream and its decoder + AVCodec* avAudioCodec = nullptr; + audioStreamIndex = av_find_best_stream(avFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, &avAudioCodec, 0); + if (audioStreamIndex != AVERROR_STREAM_NOT_FOUND && avAudioCodec) + { + avAudioCodecCtx = avFormatCtx->streams[audioStreamIndex]->codec; + if (avcodec_open2(avAudioCodecCtx, avAudioCodec, NULL) < 0) + { + avAudioCodecCtx = nullptr; + hr = E_FAIL; + } + else + { + // Detect audio format and create audio stream descriptor accordingly + hr = CreateAudioStreamDescriptor(forceAudioDecode); + if (SUCCEEDED(hr)) + { + hr = audioSampleProvider->AllocateResources(); + if (SUCCEEDED(hr)) + { + m_pReader->SetAudioStream(audioStreamIndex, audioSampleProvider); + } + } + } + } + } + + if (SUCCEEDED(hr)) + { + // Find the video stream and its decoder + AVCodec* avVideoCodec = nullptr; + videoStreamIndex = av_find_best_stream(avFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, &avVideoCodec, 0); + if (videoStreamIndex != AVERROR_STREAM_NOT_FOUND && avVideoCodec) + { + // FFmpeg identifies album/cover art from a music file as a video stream + // Avoid creating unnecessarily video stream from this album/cover art + if (avFormatCtx->streams[videoStreamIndex]->disposition == AV_DISPOSITION_ATTACHED_PIC) + { + videoStreamIndex = AVERROR_STREAM_NOT_FOUND; + avVideoCodec = nullptr; + } + else + { + avVideoCodecCtx = avFormatCtx->streams[videoStreamIndex]->codec; + if (avcodec_open2(avVideoCodecCtx, avVideoCodec, NULL) < 0) + { + avVideoCodecCtx = nullptr; + hr = E_FAIL; // Cannot open the video codec + } + else + { + // Detect video format and create video stream descriptor accordingly + hr = CreateVideoStreamDescriptor(forceVideoDecode); + if (SUCCEEDED(hr)) + { + hr = videoSampleProvider->AllocateResources(); + if (SUCCEEDED(hr)) + { + m_pReader->SetVideoStream(videoStreamIndex, videoSampleProvider); + } + } + } + } + } + } + + if (SUCCEEDED(hr)) + { + // Convert media duration from AV_TIME_BASE to TimeSpan unit + mediaDuration = { LONGLONG(avFormatCtx->duration * 10000000 / double(AV_TIME_BASE)) }; + + if (audioStreamDescriptor) + { + if (videoStreamDescriptor) + { + mss = ref new MediaStreamSource(videoStreamDescriptor, audioStreamDescriptor); + } + else + { + mss = ref new MediaStreamSource(audioStreamDescriptor); + } + } + else if (videoStreamDescriptor) + { + mss = ref new MediaStreamSource(videoStreamDescriptor); + } + if (mss) + { + if (mediaDuration.Duration > 0) + { + mss->Duration = mediaDuration; + mss->CanSeek = true; + } + else + { + // Set buffer time to 0 for realtime streaming to reduce latency + mss->BufferTime = { 0 }; + } + + startingRequestedToken = mss->Starting += ref new TypedEventHandler(this, &FFmpegInteropMSS::OnStarting); + sampleRequestedToken = mss->SampleRequested += ref new TypedEventHandler(this, &FFmpegInteropMSS::OnSampleRequested); + } + else + { + hr = E_OUTOFMEMORY; + } + } + + return hr; +} + +HRESULT FFmpegInteropMSS::CreateAudioStreamDescriptor(bool forceAudioDecode) +{ + if (avAudioCodecCtx->codec_id == AV_CODEC_ID_AAC && !forceAudioDecode) + { + if (avAudioCodecCtx->extradata_size == 0) + { + audioStreamDescriptor = ref new AudioStreamDescriptor(AudioEncodingProperties::CreateAacAdts(avAudioCodecCtx->sample_rate, avAudioCodecCtx->channels, avAudioCodecCtx->bit_rate)); + } + else + { + audioStreamDescriptor = ref new AudioStreamDescriptor(AudioEncodingProperties::CreateAac(avAudioCodecCtx->sample_rate, avAudioCodecCtx->channels, avAudioCodecCtx->bit_rate)); + } + audioSampleProvider = ref new MediaSampleProvider(m_pReader, avFormatCtx, avAudioCodecCtx); + } + else if (avAudioCodecCtx->codec_id == AV_CODEC_ID_MP3 && !forceAudioDecode) + { + audioStreamDescriptor = ref new AudioStreamDescriptor(AudioEncodingProperties::CreateMp3(avAudioCodecCtx->sample_rate, avAudioCodecCtx->channels, avAudioCodecCtx->bit_rate)); + audioSampleProvider = ref new MediaSampleProvider(m_pReader, avFormatCtx, avAudioCodecCtx); + } + else + { + // Set default 16 bits when bits per sample value is unknown (0) + unsigned int bitsPerSample = avAudioCodecCtx->bits_per_coded_sample ? avAudioCodecCtx->bits_per_coded_sample : 16; + audioStreamDescriptor = ref new AudioStreamDescriptor(AudioEncodingProperties::CreatePcm(avAudioCodecCtx->sample_rate, avAudioCodecCtx->channels, bitsPerSample)); + audioSampleProvider = ref new UncompressedAudioSampleProvider(m_pReader, avFormatCtx, avAudioCodecCtx); + } + + return (audioStreamDescriptor != nullptr && audioSampleProvider != nullptr) ? S_OK : E_OUTOFMEMORY; +} + +HRESULT FFmpegInteropMSS::CreateVideoStreamDescriptor(bool forceVideoDecode) +{ + VideoEncodingProperties^ videoProperties; + + if (avVideoCodecCtx->codec_id == AV_CODEC_ID_H264 && !forceVideoDecode) + { + videoProperties = VideoEncodingProperties::CreateH264(); + videoProperties->ProfileId = avVideoCodecCtx->profile; + videoProperties->Height = avVideoCodecCtx->height; + videoProperties->Width = avVideoCodecCtx->width; + + // Check for H264 bitstream flavor. H.264 AVC extradata starts with 1 while non AVC one starts with 0 + if (avVideoCodecCtx->extradata != nullptr && avVideoCodecCtx->extradata_size > 0 && avVideoCodecCtx->extradata[0] == 1) + { + videoSampleProvider = ref new H264AVCSampleProvider(m_pReader, avFormatCtx, avVideoCodecCtx); + } + else + { + videoSampleProvider = ref new H264SampleProvider(m_pReader, avFormatCtx, avVideoCodecCtx); + } + } + else + { + videoProperties = VideoEncodingProperties::CreateUncompressed(MediaEncodingSubtypes::Nv12, avVideoCodecCtx->width, avVideoCodecCtx->height); + videoSampleProvider = ref new UncompressedVideoSampleProvider(m_pReader, avFormatCtx, avVideoCodecCtx); + + if (avVideoCodecCtx->sample_aspect_ratio.num > 0 && avVideoCodecCtx->sample_aspect_ratio.den != 0) + { + videoProperties->PixelAspectRatio->Numerator = avVideoCodecCtx->sample_aspect_ratio.num; + videoProperties->PixelAspectRatio->Denominator = avVideoCodecCtx->sample_aspect_ratio.den; + } + } + + // Detect the correct framerate + if (avVideoCodecCtx->framerate.num != 0 || avVideoCodecCtx->framerate.den != 1) + { + videoProperties->FrameRate->Numerator = avVideoCodecCtx->framerate.num; + videoProperties->FrameRate->Denominator = avVideoCodecCtx->framerate.den; + } + else if (avFormatCtx->streams[videoStreamIndex]->avg_frame_rate.num != 0 || avFormatCtx->streams[videoStreamIndex]->avg_frame_rate.den != 0) + { + videoProperties->FrameRate->Numerator = avFormatCtx->streams[videoStreamIndex]->avg_frame_rate.num; + videoProperties->FrameRate->Denominator = avFormatCtx->streams[videoStreamIndex]->avg_frame_rate.den; + } + + videoProperties->Bitrate = avVideoCodecCtx->bit_rate; + videoStreamDescriptor = ref new VideoStreamDescriptor(videoProperties); + + return (videoStreamDescriptor != nullptr && videoSampleProvider != nullptr) ? S_OK : E_OUTOFMEMORY; +} + +HRESULT FFmpegInteropMSS::ParseOptions(PropertySet^ ffmpegOptions) +{ + HRESULT hr = S_OK; + + // Convert FFmpeg options given in PropertySet to AVDictionary. List of options can be found in https://www.ffmpeg.org/ffmpeg-protocols.html + if (ffmpegOptions != nullptr) + { + auto options = ffmpegOptions->First(); + + while (options->HasCurrent) + { + String^ key = options->Current->Key; + std::wstring keyW(key->Begin()); + std::string keyA(keyW.begin(), keyW.end()); + const char* keyChar = keyA.c_str(); + + // Convert value from Object^ to const char*. avformat_open_input will internally convert value from const char* to the correct type + String^ value = options->Current->Value->ToString(); + std::wstring valueW(value->Begin()); + std::string valueA(valueW.begin(), valueW.end()); + const char* valueChar = valueA.c_str(); + + // Add key and value pair entry + if (av_dict_set(&avDict, keyChar, valueChar, 0) < 0) + { + hr = E_INVALIDARG; + break; + } + + options->MoveNext(); + } + } + + return hr; +} + +void FFmpegInteropMSS::OnStarting(MediaStreamSource ^sender, MediaStreamSourceStartingEventArgs ^args) +{ + MediaStreamSourceStartingRequest^ request = args->Request; + + // Perform seek operation when MediaStreamSource received seek event from MediaElement + if (request->StartPosition && request->StartPosition->Value.Duration <= mediaDuration.Duration) + { + // Select the first valid stream either from video or audio + int streamIndex = videoStreamIndex >= 0 ? videoStreamIndex : audioStreamIndex >= 0 ? audioStreamIndex : -1; + + if (streamIndex >= 0) + { + // Convert TimeSpan unit to AV_TIME_BASE + int64_t seekTarget = static_cast(request->StartPosition->Value.Duration / (av_q2d(avFormatCtx->streams[streamIndex]->time_base) * 10000000)); + + if (av_seek_frame(avFormatCtx, streamIndex, seekTarget, 0) < 0) + { + DebugMessage(L" - ### Error while seeking\n"); + } + else + { + // Add deferral + + // Flush the AudioSampleProvider + if (audioSampleProvider != nullptr) + { + audioSampleProvider->Flush(); + avcodec_flush_buffers(avAudioCodecCtx); + } + + // Flush the VideoSampleProvider + if (videoSampleProvider != nullptr) + { + videoSampleProvider->Flush(); + avcodec_flush_buffers(avVideoCodecCtx); + } + } + } + + request->SetActualStartPosition(request->StartPosition->Value); + } +} + +void FFmpegInteropMSS::OnSampleRequested(Windows::Media::Core::MediaStreamSource ^sender, MediaStreamSourceSampleRequestedEventArgs ^args) +{ + if (args->Request->StreamDescriptor == audioStreamDescriptor && audioSampleProvider != nullptr) + { + args->Request->Sample = audioSampleProvider->GetNextSample(); + } + else if (args->Request->StreamDescriptor == videoStreamDescriptor && videoSampleProvider != nullptr) + { + args->Request->Sample = videoSampleProvider->GetNextSample(); + } + else + { + args->Request->Sample = nullptr; + } +} + +// Static function to read file stream and pass data to FFmpeg. Credit to Philipp Sch http://www.codeproject.com/Tips/489450/Creating-Custom-FFmpeg-IO-Context +static int FileStreamRead(void* ptr, uint8_t* buf, int bufSize) +{ + IStream* pStream = reinterpret_cast(ptr); + ULONG bytesRead = 0; + HRESULT hr = pStream->Read(buf, bufSize, &bytesRead); + + if (FAILED(hr)) + { + return -1; + } + + // If we succeed but don't have any bytes, assume end of file + if (bytesRead == 0) + { + return AVERROR_EOF; // Let FFmpeg know that we have reached eof + } + + return bytesRead; +} + +// Static function to seek in file stream. Credit to Philipp Sch http://www.codeproject.com/Tips/489450/Creating-Custom-FFmpeg-IO-Context +static int64_t FileStreamSeek(void* ptr, int64_t pos, int whence) +{ + IStream* pStream = reinterpret_cast(ptr); + LARGE_INTEGER in; + in.QuadPart = pos; + ULARGE_INTEGER out = { 0 }; + + if (FAILED(pStream->Seek(in, whence, &out))) + { + return -1; + } + + return out.QuadPart; // Return the new position: +} diff --git a/FFmpegInterop/Source/FFmpegInteropMSS.h b/FFmpegInterop/Source/FFmpegInteropMSS.h new file mode 100755 index 0000000..133e059 --- /dev/null +++ b/FFmpegInterop/Source/FFmpegInteropMSS.h @@ -0,0 +1,88 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#pragma once +#include +#include "MediaSampleProvider.h" +#include "FFmpegReader.h" + +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; +using namespace Windows::Media::Core; + +extern "C" +{ +#include +} + +namespace FFmpegInterop +{ + public ref class FFmpegInteropMSS sealed + { + public: + static FFmpegInteropMSS^ CreateFFmpegInteropMSSFromStream(IRandomAccessStream^ stream, bool forceAudioDecode, bool forceVideoDecode, PropertySet^ ffmpegOptions); + static FFmpegInteropMSS^ CreateFFmpegInteropMSSFromStream(IRandomAccessStream^ stream, bool forceAudioDecode, bool forceVideoDecode); + static FFmpegInteropMSS^ CreateFFmpegInteropMSSFromUri(String^ uri, bool forceAudioDecode, bool forceVideoDecode, PropertySet^ ffmpegOptions); + static FFmpegInteropMSS^ CreateFFmpegInteropMSSFromUri(String^ uri, bool forceAudioDecode, bool forceVideoDecode); + + // Contructor + MediaStreamSource^ GetMediaStreamSource(); + virtual ~FFmpegInteropMSS(); + + internal: + int ReadPacket(); + + private: + FFmpegInteropMSS(); + + HRESULT CreateMediaStreamSource(IRandomAccessStream^ stream, bool forceAudioDecode, bool forceVideoDecode, PropertySet^ ffmpegOptions); + HRESULT CreateMediaStreamSource(String^ uri, bool forceAudioDecode, bool forceVideoDecode, PropertySet^ ffmpegOptions); + HRESULT InitFFmpegContext(bool forceAudioDecode, bool forceVideoDecode); + HRESULT CreateAudioStreamDescriptor(bool forceAudioDecode); + HRESULT CreateVideoStreamDescriptor(bool forceVideoDecode); + HRESULT ParseOptions(PropertySet^ ffmpegOptions); + void OnStarting(MediaStreamSource ^sender, MediaStreamSourceStartingEventArgs ^args); + void OnSampleRequested(MediaStreamSource ^sender, MediaStreamSourceSampleRequestedEventArgs ^args); + + MediaStreamSource^ mss; + EventRegistrationToken startingRequestedToken; + EventRegistrationToken sampleRequestedToken; + + internal: + AVDictionary* avDict; + AVIOContext* avIOCtx; + AVFormatContext* avFormatCtx; + AVCodecContext* avAudioCodecCtx; + AVCodecContext* avVideoCodecCtx; + + private: + AudioStreamDescriptor^ audioStreamDescriptor; + VideoStreamDescriptor^ videoStreamDescriptor; + int audioStreamIndex; + int videoStreamIndex; + + MediaSampleProvider^ audioSampleProvider; + MediaSampleProvider^ videoSampleProvider; + + TimeSpan mediaDuration; + IStream* fileStreamData; + unsigned char* fileStreamBuffer; + FFmpegReader^ m_pReader; + }; +} diff --git a/FFmpegInterop/Source/FFmpegReader.cpp b/FFmpegInterop/Source/FFmpegReader.cpp new file mode 100755 index 0000000..2d3d28d --- /dev/null +++ b/FFmpegInterop/Source/FFmpegReader.cpp @@ -0,0 +1,88 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#include "pch.h" +#include "FFmpegReader.h" + +using namespace FFmpegInterop; + +FFmpegReader::FFmpegReader(AVFormatContext* avFormatCtx) + : m_pAvFormatCtx(avFormatCtx) + , m_audioStreamIndex(AVERROR_STREAM_NOT_FOUND) + , m_videoStreamIndex(AVERROR_STREAM_NOT_FOUND) +{ +} + +FFmpegReader::~FFmpegReader() +{ +} + +// Read the next packet from the stream and push it into the appropriate +// sample provider +int FFmpegReader::ReadPacket() +{ + int ret; + AVPacket avPacket; + av_init_packet(&avPacket); + avPacket.data = NULL; + avPacket.size = 0; + + ret = av_read_frame(m_pAvFormatCtx, &avPacket); + if (ret < 0) + { + return ret; + } + + // Push the packet to the appropriate + if (avPacket.stream_index == m_audioStreamIndex && m_audioSampleProvider != nullptr) + { + m_audioSampleProvider->PushPacket(avPacket); + } + else if (avPacket.stream_index == m_videoStreamIndex && m_videoSampleProvider != nullptr) + { + m_videoSampleProvider->PushPacket(avPacket); + } + else + { + DebugMessage(L"Ignoring unused stream\n"); + //av_free_packet(&avPacket); + } + + return ret; +} + +void FFmpegReader::SetAudioStream(int audioStreamIndex, MediaSampleProvider^ audioSampleProvider) +{ + m_audioStreamIndex = audioStreamIndex; + m_audioSampleProvider = audioSampleProvider; + if (audioSampleProvider != nullptr) + { + audioSampleProvider->SetCurrentStreamIndex(m_audioStreamIndex); + } +} + +void FFmpegReader::SetVideoStream(int videoStreamIndex, MediaSampleProvider^ videoSampleProvider) +{ + m_videoStreamIndex = videoStreamIndex; + m_videoSampleProvider = videoSampleProvider; + if (videoSampleProvider != nullptr) + { + videoSampleProvider->SetCurrentStreamIndex(m_videoStreamIndex); + } +} + diff --git a/FFmpegInterop/Source/FFmpegReader.h b/FFmpegInterop/Source/FFmpegReader.h new file mode 100755 index 0000000..dfe98ae --- /dev/null +++ b/FFmpegInterop/Source/FFmpegReader.h @@ -0,0 +1,44 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#pragma once + +#include "MediaSampleProvider.h" + +namespace FFmpegInterop +{ + + ref class FFmpegReader + { + public: + virtual ~FFmpegReader(); + int ReadPacket(); + void SetAudioStream(int audioStreamIndex, MediaSampleProvider^ audioSampleProvider); + void SetVideoStream(int videoStreamIndex, MediaSampleProvider^ videoSampleProvider); + + internal: + FFmpegReader(AVFormatContext* avFormatCtx); + + private: + AVFormatContext* m_pAvFormatCtx; + MediaSampleProvider^ m_audioSampleProvider; + int m_audioStreamIndex; + MediaSampleProvider^ m_videoSampleProvider; + int m_videoStreamIndex; + }; +} diff --git a/FFmpegInterop/Source/H264AVCSampleProvider.cpp b/FFmpegInterop/Source/H264AVCSampleProvider.cpp new file mode 100755 index 0000000..d1e99b0 --- /dev/null +++ b/FFmpegInterop/Source/H264AVCSampleProvider.cpp @@ -0,0 +1,169 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#include "pch.h" +#include "H264AVCSampleProvider.h" + +using namespace FFmpegInterop; + +H264AVCSampleProvider::H264AVCSampleProvider( + FFmpegReader^ reader, + AVFormatContext* avFormatCtx, + AVCodecContext* avCodecCtx) + : MediaSampleProvider(reader, avFormatCtx, avCodecCtx) +{ +} + +H264AVCSampleProvider::~H264AVCSampleProvider() +{ +} + +HRESULT H264AVCSampleProvider::WriteAVPacketToStream(DataWriter^ dataWriter, AVPacket* avPacket) +{ + HRESULT hr = S_OK; + // On a KeyFrame, write the SPS and PPS + if (avPacket->flags & AV_PKT_FLAG_KEY) + { + hr = GetSPSAndPPSBuffer(dataWriter); + } + + if (SUCCEEDED(hr)) + { + // Convert the packet to NAL format + hr = WriteNALPacket(dataWriter, avPacket); + } + + // We have a complete frame + return hr; +} + +HRESULT H264AVCSampleProvider::GetSPSAndPPSBuffer(DataWriter^ dataWriter) +{ + HRESULT hr = S_OK; + int spsLength = 0; + int ppsLength = 0; + + // Get the position of the SPS + if (m_pAvCodecCtx->extradata == nullptr && m_pAvCodecCtx->extradata_size < 8) + { + // The data isn't present + hr = E_FAIL; + } + if (SUCCEEDED(hr)) + { + byte* spsPos = m_pAvCodecCtx->extradata + 8; + spsLength = spsPos[-1]; + + if (m_pAvCodecCtx->extradata_size < (8 + spsLength)) + { + // We don't have a complete SPS + hr = E_FAIL; + } + else + { + auto vSPS = ref new Platform::Array(spsPos, spsLength); + + // Write the NAL unit for the SPS + dataWriter->WriteByte(0); + dataWriter->WriteByte(0); + dataWriter->WriteByte(0); + dataWriter->WriteByte(1); + + // Write the SPS + dataWriter->WriteBytes(vSPS); + } + } + + if (SUCCEEDED(hr)) + { + if (m_pAvCodecCtx->extradata_size < (8 + spsLength + 3)) + { + hr = E_FAIL; + } + + if (SUCCEEDED(hr)) + { + byte* ppsPos = m_pAvCodecCtx->extradata + 8 + spsLength + 3; + ppsLength = ppsPos[-1]; + + if (m_pAvCodecCtx->extradata_size < (8 + spsLength + 3 + ppsLength)) + { + hr = E_FAIL; + } + else + { + auto vPPS = ref new Platform::Array(ppsPos, ppsLength); + + // Write the NAL unit for the PPS + dataWriter->WriteByte(0); + dataWriter->WriteByte(0); + dataWriter->WriteByte(0); + dataWriter->WriteByte(1); + + // Write the PPS + dataWriter->WriteBytes(vPPS); + } + } + } + + return hr; +} + +// Write out an H.264 packet converting stream offsets to start-codes +HRESULT H264AVCSampleProvider::WriteNALPacket(DataWriter^ dataWriter, AVPacket* avPacket) +{ + HRESULT hr = S_OK; + uint32 index = 0; + uint32 size = 0; + uint32 packetSize = (uint32)avPacket->size; + + do + { + // Make sure we have enough data + if (packetSize < (index + 4)) + { + hr = E_FAIL; + break; + } + + // Grab the size of the blob + size = (avPacket->data[index] << 24) + (avPacket->data[index + 1] << 16) + (avPacket->data[index + 2] << 8) + avPacket->data[index + 3]; + + // Write the NAL unit to the stream + dataWriter->WriteByte(0); + dataWriter->WriteByte(0); + dataWriter->WriteByte(0); + dataWriter->WriteByte(1); + index += 4; + + // Stop if index and size goes beyond packet size or overflow + if (packetSize < (index + size) || (UINT32_MAX - index) < size) + { + hr = E_FAIL; + break; + } + + // Write the rest of the packet to the stream + auto vBuffer = ref new Platform::Array(&(avPacket->data[index]), size); + dataWriter->WriteBytes(vBuffer); + index += size; + } while (index < packetSize); + + return hr; +} + diff --git a/FFmpegInterop/Source/H264AVCSampleProvider.h b/FFmpegInterop/Source/H264AVCSampleProvider.h new file mode 100755 index 0000000..a13e775 --- /dev/null +++ b/FFmpegInterop/Source/H264AVCSampleProvider.h @@ -0,0 +1,41 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#pragma once +#include "MediaSampleProvider.h" + +namespace FFmpegInterop +{ + ref class H264AVCSampleProvider : + public MediaSampleProvider + { + public: + virtual ~H264AVCSampleProvider(); + + private: + HRESULT WriteNALPacket(DataWriter^ dataWriter, AVPacket* avPacket); + HRESULT GetSPSAndPPSBuffer(DataWriter^ dataWriter); + + internal: + H264AVCSampleProvider( + FFmpegReader^ reader, + AVFormatContext* avFormatCtx, + AVCodecContext* avCodecCtx); + virtual HRESULT WriteAVPacketToStream(DataWriter^ writer, AVPacket* avPacket) override; + }; +} diff --git a/FFmpegInterop/Source/H264SampleProvider.cpp b/FFmpegInterop/Source/H264SampleProvider.cpp new file mode 100755 index 0000000..0136701 --- /dev/null +++ b/FFmpegInterop/Source/H264SampleProvider.cpp @@ -0,0 +1,72 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#include "pch.h" +#include "H264SampleProvider.h" + +using namespace FFmpegInterop; + +H264SampleProvider::H264SampleProvider( + FFmpegReader^ reader, + AVFormatContext* avFormatCtx, + AVCodecContext* avCodecCtx) + : MediaSampleProvider(reader, avFormatCtx, avCodecCtx) +{ +} + +H264SampleProvider::~H264SampleProvider() +{ +} + +HRESULT H264SampleProvider::WriteAVPacketToStream(DataWriter^ dataWriter, AVPacket* avPacket) +{ + HRESULT hr = S_OK; + // On a KeyFrame, write the SPS and PPS + if (avPacket->flags & AV_PKT_FLAG_KEY) + { + hr = GetSPSAndPPSBuffer(dataWriter); + } + + if (SUCCEEDED(hr)) + { + // Call base class method that simply write the packet to stream as is + hr = MediaSampleProvider::WriteAVPacketToStream(dataWriter, avPacket); + } + + // We have a complete frame + return hr; +} + +HRESULT H264SampleProvider::GetSPSAndPPSBuffer(DataWriter^ dataWriter) +{ + HRESULT hr = S_OK; + + if (m_pAvCodecCtx->extradata == nullptr && m_pAvCodecCtx->extradata_size < 8) + { + // The data isn't present + hr = E_FAIL; + } + else + { + // Write both SPS and PPS sequence as is from extradata + auto vSPSPPS = ref new Platform::Array(m_pAvCodecCtx->extradata, m_pAvCodecCtx->extradata_size); + dataWriter->WriteBytes(vSPSPPS); + } + + return hr; +} \ No newline at end of file diff --git a/FFmpegInterop/Source/H264SampleProvider.h b/FFmpegInterop/Source/H264SampleProvider.h new file mode 100755 index 0000000..82600c1 --- /dev/null +++ b/FFmpegInterop/Source/H264SampleProvider.h @@ -0,0 +1,40 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#pragma once +#include "MediaSampleProvider.h" + +namespace FFmpegInterop +{ + ref class H264SampleProvider : + public MediaSampleProvider + { + public: + virtual ~H264SampleProvider(); + + private: + HRESULT GetSPSAndPPSBuffer(DataWriter^ dataWriter); + + internal: + H264SampleProvider( + FFmpegReader^ reader, + AVFormatContext* avFormatCtx, + AVCodecContext* avCodecCtx); + virtual HRESULT WriteAVPacketToStream(DataWriter^ writer, AVPacket* avPacket) override; + }; +} diff --git a/FFmpegInterop/Source/MediaSampleProvider.cpp b/FFmpegInterop/Source/MediaSampleProvider.cpp new file mode 100755 index 0000000..2035e1d --- /dev/null +++ b/FFmpegInterop/Source/MediaSampleProvider.cpp @@ -0,0 +1,164 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#include "pch.h" +#include "MediaSampleProvider.h" +#include "FFmpegInteropMSS.h" +#include "FFmpegReader.h" + +using namespace FFmpegInterop; + +MediaSampleProvider::MediaSampleProvider( + FFmpegReader^ reader, + AVFormatContext* avFormatCtx, + AVCodecContext* avCodecCtx) + : m_pReader(reader) + , m_pAvFormatCtx(avFormatCtx) + , m_pAvCodecCtx(avCodecCtx) + , m_streamIndex(AVERROR_STREAM_NOT_FOUND) +{ +} + +HRESULT MediaSampleProvider::AllocateResources() +{ + return S_OK; +} + +MediaSampleProvider::~MediaSampleProvider() +{ +} + +void MediaSampleProvider::SetCurrentStreamIndex(int streamIndex) +{ + if (m_pAvCodecCtx != nullptr && m_pAvFormatCtx->nb_streams > (unsigned int)streamIndex) + { + m_streamIndex = streamIndex; + } + else + { + m_streamIndex = AVERROR_STREAM_NOT_FOUND; + } +} + +MediaStreamSample^ MediaSampleProvider::GetNextSample() +{ + DebugMessage(L"GetNextSample\n"); + + HRESULT hr = S_OK; + + MediaStreamSample^ sample; + AVPacket avPacket; + av_init_packet(&avPacket); + avPacket.data = NULL; + avPacket.size = 0; + DataWriter^ dataWriter = ref new DataWriter(); + + bool frameComplete = false; + bool decodeSuccess = true; + + while (SUCCEEDED(hr) && !frameComplete) + { + // Continue reading until there is an appropriate packet in the stream + while (m_packetQueue.empty()) + { + if (m_pReader->ReadPacket() < 0) + { + DebugMessage(L"GetNextSample reaching EOF\n"); + hr = E_FAIL; + break; + } + } + + if (!m_packetQueue.empty()) + { + // Pick the packets from the queue one at a time + avPacket = PopPacket(); + + // Decode the packet if necessary + hr = DecodeAVPacket(dataWriter, &avPacket); + frameComplete = (hr == S_OK); + } + } + + if (SUCCEEDED(hr)) + { + // Write the packet out + hr = WriteAVPacketToStream(dataWriter, &avPacket); + + Windows::Foundation::TimeSpan pts = { LONGLONG(av_q2d(m_pAvFormatCtx->streams[m_streamIndex]->time_base) * 10000000 * avPacket.pts) }; + Windows::Foundation::TimeSpan dur = { LONGLONG(av_q2d(m_pAvFormatCtx->streams[m_streamIndex]->time_base) * 10000000 * avPacket.duration) }; + + sample = MediaStreamSample::CreateFromBuffer(dataWriter->DetachBuffer(), pts); + sample->Duration = dur; + } + + //av_free_packet(&avPacket); + + return sample; +} + +HRESULT MediaSampleProvider::WriteAVPacketToStream(DataWriter^ dataWriter, AVPacket* avPacket) +{ + // This is the simplest form of transfer. Copy the packet directly to the stream + // This works for most compressed formats + auto aBuffer = ref new Platform::Array(avPacket->data, avPacket->size); + dataWriter->WriteBytes(aBuffer); + return S_OK; +} + +HRESULT MediaSampleProvider::DecodeAVPacket(DataWriter^ dataWriter, AVPacket *avPacket) +{ + // For the simple case of compressed samples, each packet is a sample + return S_OK; +} + +void MediaSampleProvider::PushPacket(AVPacket packet) +{ + DebugMessage(L" - PushPacket\n"); + + m_packetQueue.push(packet); +} + +AVPacket MediaSampleProvider::PopPacket() +{ + DebugMessage(L" - PopPacket\n"); + + AVPacket avPacket; + av_init_packet(&avPacket); + avPacket.data = NULL; + avPacket.size = 0; + + if (!m_packetQueue.empty()) + { + avPacket = m_packetQueue.front(); + m_packetQueue.pop(); + } + + return avPacket; +} + +void MediaSampleProvider::Flush() +{ + /*while (!m_packetQueue.empty()) + { + av_free_packet(&PopPacket()); + }*/ +} + + + diff --git a/FFmpegInterop/Source/MediaSampleProvider.h b/FFmpegInterop/Source/MediaSampleProvider.h new file mode 100755 index 0000000..5e16828 --- /dev/null +++ b/FFmpegInterop/Source/MediaSampleProvider.h @@ -0,0 +1,68 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#pragma once +#include + +extern "C" +{ +#include +} + +using namespace Windows::Storage::Streams; +using namespace Windows::Media::Core; + +namespace FFmpegInterop +{ + ref class FFmpegInteropMSS; + ref class FFmpegReader; + + ref class MediaSampleProvider + { + public: + virtual ~MediaSampleProvider(); + virtual MediaStreamSample^ GetNextSample(); + virtual void Flush(); + virtual void SetCurrentStreamIndex(int streamIndex); + + internal: + void PushPacket(AVPacket packet); + AVPacket PopPacket(); + + private: + std::queue m_packetQueue; + int m_streamIndex; + + internal: + // The FFmpeg context. Because they are complex types + // we declare them as internal so they don't get exposed + // externally + FFmpegReader^ m_pReader; + AVFormatContext* m_pAvFormatCtx; + AVCodecContext* m_pAvCodecCtx; + + internal: + MediaSampleProvider( + FFmpegReader^ reader, + AVFormatContext* avFormatCtx, + AVCodecContext* avCodecCtx); + virtual HRESULT AllocateResources(); + virtual HRESULT WriteAVPacketToStream(DataWriter^ writer, AVPacket* avPacket); + virtual HRESULT DecodeAVPacket(DataWriter^ dataWriter, AVPacket* avPacket); + }; +} \ No newline at end of file diff --git a/FFmpegInterop/Source/UncompressedAudioSampleProvider.cpp b/FFmpegInterop/Source/UncompressedAudioSampleProvider.cpp new file mode 100755 index 0000000..ccedb48 --- /dev/null +++ b/FFmpegInterop/Source/UncompressedAudioSampleProvider.cpp @@ -0,0 +1,145 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#include "pch.h" +#include "UncompressedAudioSampleProvider.h" + +using namespace FFmpegInterop; + +UncompressedAudioSampleProvider::UncompressedAudioSampleProvider( + FFmpegReader^ reader, + AVFormatContext* avFormatCtx, + AVCodecContext* avCodecCtx) + : MediaSampleProvider(reader, avFormatCtx, avCodecCtx) + , m_pAvFrame(nullptr) + , m_pSwrCtx(nullptr) +{ +} + +HRESULT UncompressedAudioSampleProvider::AllocateResources() +{ + HRESULT hr = S_OK; + hr = MediaSampleProvider::AllocateResources(); + if (SUCCEEDED(hr)) + { + // Set default channel layout when the value is unknown (0) + int64 inChannelLayout = m_pAvCodecCtx->channel_layout ? m_pAvCodecCtx->channel_layout : av_get_default_channel_layout(m_pAvCodecCtx->channels); + int64 outChannelLayout = av_get_default_channel_layout(m_pAvCodecCtx->channels); + + // Set up resampler to convert any PCM format (e.g. AV_SAMPLE_FMT_FLTP) to AV_SAMPLE_FMT_S16 PCM format that is expected by Media Element. + // Additional logic can be added to avoid resampling PCM data that is already in AV_SAMPLE_FMT_S16_PCM. + m_pSwrCtx = swr_alloc_set_opts( + NULL, + outChannelLayout, + AV_SAMPLE_FMT_S16, + m_pAvCodecCtx->sample_rate, + inChannelLayout, + m_pAvCodecCtx->sample_fmt, + m_pAvCodecCtx->sample_rate, + 0, + NULL); + + if (!m_pSwrCtx) + { + hr = E_OUTOFMEMORY; + } + } + + if (SUCCEEDED(hr)) + { + if (swr_init(m_pSwrCtx) < 0) + { + hr = E_FAIL; + } + } + + if (SUCCEEDED(hr)) + { + m_pAvFrame = av_frame_alloc(); + if (!m_pAvFrame) + { + hr = E_OUTOFMEMORY; + } + } + + return hr; +} + +UncompressedAudioSampleProvider::~UncompressedAudioSampleProvider() +{ + if (m_pAvFrame) + { + av_freep(m_pAvFrame); + } + + // Free + swr_free(&m_pSwrCtx); +} + +HRESULT UncompressedAudioSampleProvider::WriteAVPacketToStream(DataWriter^ dataWriter, AVPacket* avPacket) +{ + // Because each packet can contain multiple frames, we have already written the packet to the stream + // during the decode stage. + return S_OK; +} + +HRESULT UncompressedAudioSampleProvider::DecodeAVPacket(DataWriter^ dataWriter, AVPacket* avPacket) +{ + HRESULT hr = S_OK; + int frameComplete = 0; + // Each audio packet may contain multiple frames which requires calling avcodec_decode_audio4 for each frame. Loop through the entire packet data + while (avPacket->size > 0) + { + frameComplete = 0; + int decodedBytes = avcodec_decode_audio4(m_pAvCodecCtx, m_pAvFrame, &frameComplete, avPacket); + + if (decodedBytes < 0) + { + DebugMessage(L"Fail To Decode!\n"); + hr = E_FAIL; + break; // Skip broken frame + } + + if (SUCCEEDED(hr) && frameComplete) + { + // Resample uncompressed frame to AV_SAMPLE_FMT_S16 PCM format that is expected by Media Element + uint8_t *resampledData = nullptr; + unsigned int aBufferSize = av_samples_alloc(&resampledData, NULL, m_pAvFrame->channels, m_pAvFrame->nb_samples, AV_SAMPLE_FMT_S16, 0); + int resampledDataSize = swr_convert(m_pSwrCtx, &resampledData, aBufferSize, (const uint8_t **)m_pAvFrame->extended_data, m_pAvFrame->nb_samples); + auto aBuffer = ref new Platform::Array(resampledData, min(aBufferSize, (unsigned int)(resampledDataSize * m_pAvFrame->channels * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)))); + dataWriter->WriteBytes(aBuffer); + av_freep(&resampledData); + av_frame_unref(m_pAvFrame); + } + + if (SUCCEEDED(hr)) + { + // Advance to the next frame data that have not been decoded if any + avPacket->size -= decodedBytes; + avPacket->data += decodedBytes; + } + } + + if (SUCCEEDED(hr)) + { + // We've completed the packet. Return S_FALSE to indicate an incomplete frame + hr = (frameComplete != 0) ? S_OK : S_FALSE; + } + + return hr; +} diff --git a/FFmpegInterop/Source/UncompressedAudioSampleProvider.h b/FFmpegInterop/Source/UncompressedAudioSampleProvider.h new file mode 100755 index 0000000..3619603 --- /dev/null +++ b/FFmpegInterop/Source/UncompressedAudioSampleProvider.h @@ -0,0 +1,48 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#pragma once +#include "MediaSampleProvider.h" + +extern "C" +{ +#include +} + +namespace FFmpegInterop +{ + ref class UncompressedAudioSampleProvider: MediaSampleProvider + { + public: + virtual ~UncompressedAudioSampleProvider(); + + internal: + UncompressedAudioSampleProvider( + FFmpegReader^ reader, + AVFormatContext* avFormatCtx, + AVCodecContext* avCodecCtx); + virtual HRESULT WriteAVPacketToStream(DataWriter^ writer, AVPacket* avPacket) override; + virtual HRESULT DecodeAVPacket(DataWriter^ dataWriter, AVPacket* avPacket) override; + virtual HRESULT AllocateResources() override; + + private: + AVFrame* m_pAvFrame; + SwrContext* m_pSwrCtx; + }; +} + diff --git a/FFmpegInterop/Source/UncompressedVideoSampleProvider.cpp b/FFmpegInterop/Source/UncompressedVideoSampleProvider.cpp new file mode 100755 index 0000000..7634a60 --- /dev/null +++ b/FFmpegInterop/Source/UncompressedVideoSampleProvider.cpp @@ -0,0 +1,137 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#include "pch.h" +#include "UncompressedVideoSampleProvider.h" + +extern "C" +{ +#include +} + + +using namespace FFmpegInterop; + +UncompressedVideoSampleProvider::UncompressedVideoSampleProvider( + FFmpegReader^ reader, + AVFormatContext* avFormatCtx, + AVCodecContext* avCodecCtx) + : MediaSampleProvider(reader, avFormatCtx, avCodecCtx) + , m_pAvFrame(nullptr) + , m_pSwsCtx(nullptr) +{ + for (int i = 0; i < 4; i++) + { + m_rgVideoBufferLineSize[i] = 0; + m_rgVideoBufferData[i] = nullptr; + } +} + +HRESULT UncompressedVideoSampleProvider::AllocateResources() +{ + HRESULT hr = S_OK; + hr = MediaSampleProvider::AllocateResources(); + if (SUCCEEDED(hr)) + { + // Setup software scaler to convert any decoder pixel format (e.g. YUV420P) to NV12 that is supported in Windows & Windows Phone MediaElement + m_pSwsCtx = sws_getContext( + m_pAvCodecCtx->width, + m_pAvCodecCtx->height, + m_pAvCodecCtx->pix_fmt, + m_pAvCodecCtx->width, + m_pAvCodecCtx->height, + AV_PIX_FMT_NV12, + SWS_BICUBIC, + NULL, + NULL, + NULL); + + if (m_pSwsCtx == nullptr) + { + hr = E_OUTOFMEMORY; + } + } + + if (SUCCEEDED(hr)) + { + m_pAvFrame = av_frame_alloc(); + if (m_pAvFrame == nullptr) + { + hr = E_OUTOFMEMORY; + } + } + + if (SUCCEEDED(hr)) + { + if (av_image_alloc(m_rgVideoBufferData, m_rgVideoBufferLineSize, m_pAvCodecCtx->width, m_pAvCodecCtx->height, AV_PIX_FMT_NV12, 1) < 0) + { + hr = E_FAIL; + } + } + + return hr; +} + +UncompressedVideoSampleProvider::~UncompressedVideoSampleProvider() +{ + if (m_pAvFrame) + { + av_freep(m_pAvFrame); + } + + if (m_rgVideoBufferData) + { + av_freep(m_rgVideoBufferData); + } +} + +HRESULT UncompressedVideoSampleProvider::WriteAVPacketToStream(DataWriter^ dataWriter, AVPacket* avPacket) +{ + // Convert decoded video pixel format to NV12 using FFmpeg software scaler + if (sws_scale(m_pSwsCtx, (const uint8_t **)(m_pAvFrame->data), m_pAvFrame->linesize, 0, m_pAvCodecCtx->height, m_rgVideoBufferData, m_rgVideoBufferLineSize) < 0) + { + return E_FAIL; + } + + auto YBuffer = ref new Platform::Array(m_rgVideoBufferData[0], m_rgVideoBufferLineSize[0] * m_pAvCodecCtx->height); + auto UVBuffer = ref new Platform::Array(m_rgVideoBufferData[1], m_rgVideoBufferLineSize[1] * m_pAvCodecCtx->height / 2); + dataWriter->WriteBytes(YBuffer); + dataWriter->WriteBytes(UVBuffer); + av_frame_unref(m_pAvFrame); + + return S_OK; +} + +HRESULT UncompressedVideoSampleProvider::DecodeAVPacket(DataWriter^ dataWriter, AVPacket* avPacket) +{ + int frameComplete = 0; + if (avcodec_decode_video2(m_pAvCodecCtx, m_pAvFrame, &frameComplete, avPacket) < 0) + { + DebugMessage(L"DecodeAVPacket Failed\n"); + frameComplete = 1; + } + else + { + if (frameComplete) + { + avPacket->pts = av_frame_get_best_effort_timestamp(m_pAvFrame); + } + } + + return frameComplete ? S_OK : S_FALSE; +} diff --git a/FFmpegInterop/Source/UncompressedVideoSampleProvider.h b/FFmpegInterop/Source/UncompressedVideoSampleProvider.h new file mode 100755 index 0000000..2b621e9 --- /dev/null +++ b/FFmpegInterop/Source/UncompressedVideoSampleProvider.h @@ -0,0 +1,51 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#pragma once +#include "MediaSampleProvider.h" + +extern "C" +{ +#include +} + + +namespace FFmpegInterop +{ + ref class UncompressedVideoSampleProvider: MediaSampleProvider + { + public: + virtual ~UncompressedVideoSampleProvider(); + + internal: + UncompressedVideoSampleProvider( + FFmpegReader^ reader, + AVFormatContext* avFormatCtx, + AVCodecContext* avCodecCtx); + virtual HRESULT WriteAVPacketToStream(DataWriter^ writer, AVPacket* avPacket) override; + virtual HRESULT DecodeAVPacket(DataWriter^ dataWriter, AVPacket* avPacket) override; + virtual HRESULT AllocateResources() override; + + private: + AVFrame* m_pAvFrame; + SwsContext* m_pSwsCtx; + int m_rgVideoBufferLineSize[4]; + uint8_t* m_rgVideoBufferData[4]; + }; +} + diff --git a/FFmpegInterop/Win8.1/FFmpegInterop.Shared/FFmpegGifDecoder.cpp b/FFmpegInterop/Win8.1/FFmpegInterop.Shared/FFmpegGifDecoder.cpp new file mode 100755 index 0000000..d5af303 --- /dev/null +++ b/FFmpegInterop/Win8.1/FFmpegInterop.Shared/FFmpegGifDecoder.cpp @@ -0,0 +1,585 @@ +#include "pch.h" +#include "FFmpegGifDecoder.h" +#include +#include +#include + +#ifndef NOMINMAX +#undef min +#undef max +#endif + +extern "C" +{ +#include +} +using namespace FFmpegInterop; + +typedef struct VideoInfo { + + ~VideoInfo() { + if (video_dec_ctx) { + avcodec_close(video_dec_ctx); + video_dec_ctx = nullptr; + } + if (fmt_ctx) { + avformat_close_input(&fmt_ctx); + fmt_ctx = nullptr; + } + if (frame) { + av_frame_free(&frame); + frame = nullptr; + } + if (src) { + delete[] src; + src = nullptr; + } + if (free_orig_pkt) + { + av_free_packet(&orig_pkt); + free_orig_pkt = false; + } + //av_packet_unref(&orig_pkt); + + video_stream_idx = -1; + video_stream = nullptr; + } + + AVFormatContext *fmt_ctx = nullptr; + char *src = nullptr; + int video_stream_idx = -1; + AVStream *video_stream = nullptr; + AVCodecContext *video_dec_ctx = nullptr; + AVFrame *frame = nullptr; + bool has_decoded_frames = false; + bool free_orig_pkt = false; + AVPacket pkt; + AVPacket orig_pkt; +}; + +void Log(Platform::String^ message, Platform::Object^ parameter1, Platform::Object^ parameter2){ + auto para1String = parameter1->ToString(); + auto para2String = parameter2->ToString(); + auto msg = std::wstring(message->Data()); + auto para1 = std::wstring(safe_cast(para1String)->Data()); + auto para2 = std::wstring(safe_cast(para2String)->Data()); + + auto offset1 = msg.find(L"{0}"); + + auto formattedText = msg.replace(offset1, 3, para1);// .append(L"\r\n"); + + auto offset2 = formattedText.find(L"{1}"); + + formattedText = formattedText.replace(offset2, 3, para2).append(L"\r\n"); + + ::OutputDebugString(formattedText.c_str()); +} + +void Log(Platform::String^ message, Platform::Object^ parameter){ + auto paraString = parameter->ToString(); + auto msg = std::wstring(message->Data()); + auto para = std::wstring(safe_cast(paraString)->Data()); + + auto offset = msg.find(L"{0}"); + + auto formattedText = msg.replace(offset, 3, para).append(L"\r\n"); + + ::OutputDebugString(formattedText.c_str()); +} + +int open_codec_context(int *stream_idx, AVFormatContext *fmt_ctx, enum AVMediaType type) { + int ret; + AVStream *st; + AVCodecContext *dec_ctx = NULL; + AVCodec *dec = NULL; + AVDictionary *opts = NULL; + + ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0); + if (ret < 0) { + //LOGE("can't find %s stream in input file\n", av_get_media_type_string(type)); + return ret; + } + else { + *stream_idx = ret; + st = fmt_ctx->streams[*stream_idx]; + + dec_ctx = st->codec; + dec = avcodec_find_decoder(dec_ctx->codec_id); + if (!dec) { + //LOGE("failed to find %s codec\n", av_get_media_type_string(type)); + return ret; + } + + av_dict_set(&opts, "refcounted_frames", "1", 0); + if ((ret = avcodec_open2(dec_ctx, dec, &opts)) < 0) { + //LOGE("failed to open %s codec\n", av_get_media_type_string(type)); + return ret; + } + } + + return 0; +} + +int decode_packet(VideoInfo *info, int *got_frame) { + try{ + + int ret = 0; + int decoded = info->pkt.size; + + *got_frame = 0; + if (info->pkt.stream_index == info->video_stream_idx) { + ret = avcodec_decode_video2(info->video_dec_ctx, info->frame, got_frame, &info->pkt); + if (ret != 0) { + return ret; + } + } + + return decoded; + } + catch (Platform::Exception^ e) + { + + } + + return -1; +} + +static bool _once; + +int FFmpegGifDecoder::CreateDecoder(Platform::String^ src, Platform::WriteOnlyArray^ data) +{ + //if (!_once) + { + _once = true; + av_register_all(); + } + + VideoInfo *info = new VideoInfo(); + + Platform::String^ fooRT = src; + std::wstring fooW(fooRT->Begin()); + std::string fooA(fooW.begin(), fooW.end()); + const char* srcString = fooA.c_str(); + + int len = strlen(srcString); + info->src = new char[len + 1]; + memcpy(info->src, srcString, len); + info->src[len] = '\0'; + if (srcString != 0) { + //delete[] srcString; + //env->ReleaseStringUTFChars(src, srcString); + } + + int ret; + if ((ret = avformat_open_input(&info->fmt_ctx, info->src, NULL, NULL)) < 0) { + //LOGE("can't open source file %s, %s", info->src, av_err2str(ret)); + char* error = new char[256]; + auto str = av_strerror(ret, error, 256); + delete info; + return 0; + } + + if ((ret = avformat_find_stream_info(info->fmt_ctx, NULL)) < 0) { + //LOGE("can't find stream information %s, %s", info->src, av_err2str(ret)); + delete info; + return 0; + } + + if (open_codec_context(&info->video_stream_idx, info->fmt_ctx, AVMEDIA_TYPE_VIDEO) >= 0) { + info->video_stream = info->fmt_ctx->streams[info->video_stream_idx]; + info->video_dec_ctx = info->video_stream->codec; + } + + if (info->video_stream <= 0) { + //LOGE("can't find video stream in the input, aborting %s", info->src); + delete info; + return 0; + } + + info->frame = av_frame_alloc(); + if (info->frame == nullptr) { + //LOGE("can't allocate frame %s", info->src); + delete info; + return 0; + } + + av_init_packet(&info->pkt); + info->pkt.data = NULL; + info->pkt.size = 0; + info->orig_pkt = info->pkt; + + //jint *dataArr = env->GetIntArrayElements(data, 0); + if (data != nullptr && data->Length >= 2) { + data[0] = info->video_dec_ctx->width; + data[1] = info->video_dec_ctx->height; + //env->ReleaseIntArrayElements(data, dataArr, 0); + } + + //LOGD("successfully opened file %s", info->src); + + return (int)info; +} + +void FFmpegGifDecoder::DestroyDecoder(int ptr) +{ + if (ptr == NULL) { + return; + } + + VideoInfo *info = (VideoInfo *)ptr; + delete info; +} + +#define USE_BRANCHLESS 0 +#if USE_BRANCHLESS +static __inline int32 clamp0(int32 v) { + return ((-(v) >> 31) & (v)); +} + +static __inline int32 clamp255(int32 v) { + return (((255 - (v)) >> 31) | (v)) & 255; +} + +static __inline uint32 Clamp(int32 val) { + int v = clamp0(val); + return (uint32)(clamp255(v)); +} + +static __inline uint32 Abs(int32 v) { + int m = v >> 31; + return (v + m) ^ m; +} +#else // USE_BRANCHLESS +static __inline int32 clamp0(int32 v) { + return (v < 0) ? 0 : v; +} + +static __inline int32 clamp255(int32 v) { + return (v > 255) ? 255 : v; +} + +static __inline uint32 Clamp(int32 val) { + int v = clamp0(val); + return (uint32)(clamp255(v)); +} + +static __inline uint32 Abs(int32 v) { + return (v < 0) ? -v : v; +} +#endif // USE_BRANCHLESS + +#define YG 74 /* (int8)(1.164 * 64 + 0.5) */ + +#define UB 127 /* min(63,(int8)(2.018 * 64)) */ +#define UG -25 /* (int8)(-0.391 * 64 - 0.5) */ +#define UR 0 + +#define VB 0 +#define VG -52 /* (int8)(-0.813 * 64 - 0.5) */ +#define VR 102 /* (int8)(1.596 * 64 + 0.5) */ + +// Bias +#define BB UB * 128 + VB * 128 +#define BG UG * 128 + VG * 128 +#define BR UR * 128 + VR * 128 + +static __inline void YuvPixel(uint8 y, uint8 u, uint8 v, + uint8* b, uint8* g, uint8* r) { + int32 y1 = ((int32)(y)-16) * YG; + *b = Clamp((int32)((u * UB + v * VB) - (BB)+y1) >> 6); + *g = Clamp((int32)((u * UG + v * VG) - (BG)+y1) >> 6); + *r = Clamp((int32)((u * UR + v * VR) - (BR)+y1) >> 6); +} + +// Also used for 420 +void I422ToARGBRow_C(const uint8* src_y, + const uint8* src_u, + const uint8* src_v, + uint8* rgb_buf, + int width) { + int x; + for (x = 0; x < width - 1; x += 2) { + YuvPixel(src_y[0], src_u[0], src_v[0], + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf[3] = 255; + YuvPixel(src_y[1], src_u[0], src_v[0], + rgb_buf + 4, rgb_buf + 5, rgb_buf + 6); + rgb_buf[7] = 255; + src_y += 2; + src_u += 1; + src_v += 1; + rgb_buf += 8; // Advance 2 pixels. + } + if (width & 1) { + YuvPixel(src_y[0], src_u[0], src_v[0], + rgb_buf + 0, rgb_buf + 1, rgb_buf + 2); + rgb_buf[3] = 255; + } +} + +// Convert I420 to ARGB. +// LIBYUV_API +int I420ToARGB(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_argb, int dst_stride_argb, + int width, int height) { + if (!src_y || !src_u || !src_v || !dst_argb || + width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + dst_argb = dst_argb + (height - 1) * dst_stride_argb; + dst_stride_argb = -dst_stride_argb; + } + void(*I422ToARGBRow)(const uint8* y_buf, + const uint8* u_buf, + const uint8* v_buf, + uint8* rgb_buf, + int width) = I422ToARGBRow_C; +#if defined(HAS_I422TOARGBROW_SSSE3) + if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { + I422ToARGBRow = I422ToARGBRow_Any_SSSE3; + if (IS_ALIGNED(width, 8)) { + I422ToARGBRow = I422ToARGBRow_Unaligned_SSSE3; + if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { + I422ToARGBRow = I422ToARGBRow_SSSE3; + } + } + } +#endif +#if defined(HAS_I422TOARGBROW_AVX2) + if (TestCpuFlag(kCpuHasAVX2) && width >= 16) { + I422ToARGBRow = I422ToARGBRow_Any_AVX2; + if (IS_ALIGNED(width, 16)) { + I422ToARGBRow = I422ToARGBRow_AVX2; + } + } +#endif +#if defined(HAS_I422TOARGBROW_NEON) + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { + I422ToARGBRow = I422ToARGBRow_Any_NEON; + if (IS_ALIGNED(width, 8)) { + I422ToARGBRow = I422ToARGBRow_NEON; + } + } +#endif +#if defined(HAS_I422TOARGBROW_MIPS_DSPR2) + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && + IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && + IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && + IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && + IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) { + I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2; + } +#endif + + for (int y = 0; y < height; ++y) { + I422ToARGBRow(src_y, src_u, src_v, dst_argb, width); + dst_argb += dst_stride_argb; + src_y += src_stride_y; + if (y & 1) { + src_u += src_stride_u; + src_v += src_stride_v; + } + } + return 0; +} + + +// Use first 4 shuffler values to reorder ARGB channels. +void ARGBShuffleRow_C(const uint8* src_argb, uint8* dst_argb, + const uint8* shuffler, int pix) { + int index0 = shuffler[0]; + int index1 = shuffler[1]; + int index2 = shuffler[2]; + int index3 = shuffler[3]; + // Shuffle a row of ARGB. + int x; + for (x = 0; x < pix; ++x) { + // To support in-place conversion. + uint8 b = src_argb[index0]; + uint8 g = src_argb[index1]; + uint8 r = src_argb[index2]; + uint8 a = src_argb[index3]; + dst_argb[0] = b; + dst_argb[1] = g; + dst_argb[2] = r; + dst_argb[3] = a; + src_argb += 4; + dst_argb += 4; + } +} + +int ARGBShuffle(const uint8* src_bgra, int src_stride_bgra, + uint8* dst_argb, int dst_stride_argb, + const uint8* shuffler, int width, int height) { + int y; + void(*ARGBShuffleRow)(const uint8* src_bgra, uint8* dst_argb, + const uint8* shuffler, int pix) = ARGBShuffleRow_C; + if (!src_bgra || !dst_argb || + width <= 0 || height == 0) { + return -1; + } + // Negative height means invert the image. + if (height < 0) { + height = -height; + src_bgra = src_bgra + (height - 1) * src_stride_bgra; + src_stride_bgra = -src_stride_bgra; + } + // Coalesce rows. + if (src_stride_bgra == width * 4 && + dst_stride_argb == width * 4) { + width *= height; + height = 1; + src_stride_bgra = dst_stride_argb = 0; + } + + for (y = 0; y < height; ++y) { + ARGBShuffleRow(src_bgra, dst_argb, shuffler, width); + src_bgra += src_stride_bgra; + dst_argb += dst_stride_argb; + } + return 0; +} + + +// Shuffle table for converting ABGR to ARGB. +static uint8 kShuffleMaskABGRToARGB[16] = { + 2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u +}; + +// Convert ABGR to ARGB. +int ABGRToARGB(const uint8* src_abgr, int src_stride_abgr, +uint8* dst_argb, int dst_stride_argb, +int width, int height) { + return ARGBShuffle(src_abgr, src_stride_abgr, + dst_argb, dst_stride_argb, + (const uint8*)(&kShuffleMaskABGRToARGB), + width, height); +} + +Platform::Array^ FFmpegGifDecoder::GetVideoFrame(int ptr, Platform::WriteOnlyArray^ data) { + auto emptyArray = ref new Platform::Array(0); + unsigned int start = clock(); + + //Log("start={0}", start); + if (ptr == NULL) { + return emptyArray; + } + VideoInfo *info = (VideoInfo *)ptr; + int ret = 0; + int got_frame = 0; + + while (true) { + if (info->pkt.size == 0) { + ret = av_read_frame(info->fmt_ctx, &info->pkt); + //LOGD("got packet with size %d", info->pkt.size); + if (ret >= 0) { + info->orig_pkt = info->pkt; + info->free_orig_pkt = true; + } + } + + if (info->pkt.size > 0) { + ret = decode_packet(info, &got_frame); + if (ret < 0) { + if (info->has_decoded_frames) { + ret = 0; + } + info->pkt.size = 0; + } + else { + //LOGD("read size %d from packet", ret); + info->pkt.data += ret; + info->pkt.size -= ret; + } + + if (info->pkt.size == 0) { + if (info->free_orig_pkt){ + info->free_orig_pkt = false; + av_free_packet(&info->orig_pkt); + } + //av_packet_unref(&info->orig_pkt); + } + } + else { + info->pkt.data = NULL; + info->pkt.size = 0; + ret = decode_packet(info, &got_frame); + if (ret < 0) { + //LOGE("can't decode packet flushed %s", info->src); + return emptyArray; + } + if (got_frame == 0) { + if (info->has_decoded_frames) { + //LOGD("file end reached %s", info->src); + if ((ret = avformat_seek_file(info->fmt_ctx, -1, std::numeric_limits::min(), 0, std::numeric_limits::max(), 0)) < 0) { + //LOGE("can't seek to begin of file %s, %s", info->src, av_err2str(ret)); + return emptyArray; + } + else { + avcodec_flush_buffers(info->video_dec_ctx); + } + } + } + } + if (ret < 0) { + return emptyArray; + } + + if (got_frame) { + + auto prevStop = start; + auto stop = (clock() - start); + Log("elapsed1={0} {1}", (double)stop, (double)(stop - prevStop)); + + //LOGD("decoded frame with w = %d, h = %d, format = %d", info->frame->width, info->frame->height, info->frame->format); + auto pixelsLength = info->frame->width * info->frame->height * 4; + auto pixels = ref new Platform::Array(pixelsLength); + + if (info->frame->format == AV_PIX_FMT_YUV420P || info->frame->format == AV_PIX_FMT_BGRA) { + //jint *dataArr = env->GetIntArrayElements(data, 0); + if (data != nullptr && data->Length >= 3) { + data[2] = (int)(1000 * info->frame->pkt_pts * av_q2d(info->video_stream->time_base)); + //env->ReleaseIntArrayElements(data, dataArr, 0); + } + + if (info->frame->format == AV_PIX_FMT_YUV420P) { + I420ToARGB(info->frame->data[0], info->frame->linesize[0], info->frame->data[2], info->frame->linesize[2], info->frame->data[1], info->frame->linesize[1], pixels->Data, info->frame->width * 4, info->frame->width, info->frame->height); + } + else if (info->frame->format == AV_PIX_FMT_BGRA) { + ABGRToARGB(info->frame->data[0], info->frame->linesize[0], pixels->Data, info->frame->width * 4, info->frame->width, info->frame->height); + } + } + prevStop = stop; + stop = (clock() - start); + Log("elapsed2={0} {1}", (double)stop, (double)(stop - prevStop)); + info->has_decoded_frames = true; + av_frame_unref(info->frame); + + //prevStop = stop; + //stop = (clock() - start); + //Log("elapsed3={0} {1}", (double)stop, (double)(stop - prevStop)); + //auto returnBitmap = ref new Platform::Array(pixelsLength / 4); + //for (int j = 0; j < pixelsLength / 4; j++){ + // returnBitmap[j] = + // (pixels[j * 4 + 3] << 24) + //b + // (pixels[j * 4 + 2] << 0) + //g + // (pixels[j * 4 + 1] << 8) + //r + // (pixels[j * 4] << 16); //a + // //returnBitmap[i] = pixels[i]; + //} + + //delete[] pixels; + + prevStop = stop; + stop = (clock() - start);// / (double)CLOCKS_PER_SEC; + Log("elapsed4={0} {1}", (double)stop, (double)(stop - prevStop)); + return pixels; + } + } + return emptyArray; +} \ No newline at end of file diff --git a/FFmpegInterop/Win8.1/FFmpegInterop.Shared/FFmpegGifDecoder.h b/FFmpegInterop/Win8.1/FFmpegInterop.Shared/FFmpegGifDecoder.h new file mode 100755 index 0000000..98a6991 --- /dev/null +++ b/FFmpegInterop/Win8.1/FFmpegInterop.Shared/FFmpegGifDecoder.h @@ -0,0 +1,13 @@ +#pragma once + +namespace FFmpegInterop +{ + public ref class FFmpegGifDecoder sealed + { + public: + static int FFmpegGifDecoder::CreateDecoder(Platform::String^ src, Platform::WriteOnlyArray^ data); + static void FFmpegGifDecoder::DestroyDecoder(int ptr); + static Platform::Array^ FFmpegGifDecoder::GetVideoFrame(int ptr, Platform::WriteOnlyArray^ data); + }; +} + diff --git a/FFmpegInterop/Win8.1/FFmpegInterop.Shared/FFmpegInterop.Shared.vcxitems b/FFmpegInterop/Win8.1/FFmpegInterop.Shared/FFmpegInterop.Shared.vcxitems new file mode 100755 index 0000000..5a73ffa --- /dev/null +++ b/FFmpegInterop/Win8.1/FFmpegInterop.Shared/FFmpegInterop.Shared.vcxitems @@ -0,0 +1,43 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + {b290d2ce-e857-4ace-8541-d80a3b9ab04e} + FFmpeg + FFmpegInterop.Shared + 248F659F-DAC5-46E8-AC09-60EC9FC95053 + + + + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + + + + + + + + + + + + + + + + + + + + + + + + Create + + + + + + \ No newline at end of file diff --git a/FFmpegInterop/Win8.1/FFmpegInterop.Shared/FFmpegInterop.Shared.vcxitems.filters b/FFmpegInterop/Win8.1/FFmpegInterop.Shared/FFmpegInterop.Shared.vcxitems.filters new file mode 100755 index 0000000..3e1daf9 --- /dev/null +++ b/FFmpegInterop/Win8.1/FFmpegInterop.Shared/FFmpegInterop.Shared.vcxitems.filters @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + Create + + + + + + + + + + + \ No newline at end of file diff --git a/FFmpegInterop/Win8.1/FFmpegInterop.Shared/pch.cpp b/FFmpegInterop/Win8.1/FFmpegInterop.Shared/pch.cpp new file mode 100755 index 0000000..c66dd80 --- /dev/null +++ b/FFmpegInterop/Win8.1/FFmpegInterop.Shared/pch.cpp @@ -0,0 +1,19 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#include "pch.h" diff --git a/FFmpegInterop/Win8.1/FFmpegInterop.Shared/pch.h b/FFmpegInterop/Win8.1/FFmpegInterop.Shared/pch.h new file mode 100755 index 0000000..f9f1e7f --- /dev/null +++ b/FFmpegInterop/Win8.1/FFmpegInterop.Shared/pch.h @@ -0,0 +1,29 @@ +//***************************************************************************** +// +// Copyright 2015 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http ://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//***************************************************************************** + +#pragma once + +#include +#include + +// Disable debug string output on non-debug build +#if !_DEBUG +#define DebugMessage(x) +#else +#define DebugMessage(x) OutputDebugString(x) +#endif \ No newline at end of file diff --git a/FFmpegInterop/Win8.1/FFmpegInterop.WindowsPhone/FFmpegInterop.WindowsPhone.vcxproj b/FFmpegInterop/Win8.1/FFmpegInterop.WindowsPhone/FFmpegInterop.WindowsPhone.vcxproj new file mode 100755 index 0000000..31d1b58 --- /dev/null +++ b/FFmpegInterop/Win8.1/FFmpegInterop.WindowsPhone/FFmpegInterop.WindowsPhone.vcxproj @@ -0,0 +1,154 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + + + true + false + + + + {ebc5ca98-87f1-4a01-a48d-69659c103e72} + FFmpegInterop + en-US + 12.0 + true + Windows Phone + 8.1 + CodeSharingWindowsRuntimeComponent + FFmpegInterop.WindowsPhone + + + + DynamicLibrary + true + v120_wp81 + + + DynamicLibrary + true + v120_wp81 + + + DynamicLibrary + false + true + v120_wp81 + + + DynamicLibrary + false + true + v120_wp81 + + + + + + + + + + + + + + + + + + + + + + + + + + Use + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + /bigobj %(AdditionalOptions) + true + $(SolutionDir)ffmpeg\Build\WindowsPhone8.1\$(PlatformTarget)\include;%(AdditionalIncludeDirectories) + + + Console + false + avcodec.lib;avdevice.lib;avfilter.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;shcore.lib;%(AdditionalDependencies) + $(SolutionDir)ffmpeg\Build\WindowsPhone8.1\$(PlatformTarget)\bin;%(AdditionalLibraryDirectories) + + + + + Use + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + /bigobj %(AdditionalOptions) + true + $(SolutionDir)ffmpeg\Build\WindowsPhone8.1\$(PlatformTarget)\include;%(AdditionalIncludeDirectories) + + + Console + false + avcodec.lib;avdevice.lib;avfilter.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;shcore.lib;%(AdditionalDependencies) + $(SolutionDir)ffmpeg\Build\WindowsPhone8.1\$(PlatformTarget)\bin;%(AdditionalLibraryDirectories) + + + + + Use + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + /bigobj %(AdditionalOptions) + false + $(SolutionDir)ffmpeg\Build\WindowsPhone8.1\$(PlatformTarget)\include;%(AdditionalIncludeDirectories) + + + Console + false + avcodec.lib;avdevice.lib;avfilter.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;shcore.lib;%(AdditionalDependencies) + $(SolutionDir)ffmpeg\Build\WindowsPhone8.1\$(PlatformTarget)\bin;%(AdditionalLibraryDirectories) + + + + + Use + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + /bigobj %(AdditionalOptions) + false + $(SolutionDir)ffmpeg\Build\WindowsPhone8.1\$(PlatformTarget)\include;%(AdditionalIncludeDirectories) + + + Console + false + avcodec.lib;avdevice.lib;avfilter.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;shcore.lib;%(AdditionalDependencies) + $(SolutionDir)ffmpeg\Build\WindowsPhone8.1\$(PlatformTarget)\bin;%(AdditionalLibraryDirectories) + + + + + + \ No newline at end of file diff --git a/FFmpegInterop/Win8.1/FFmpegInterop.WindowsPhone/FFmpegInterop.WindowsPhone.vcxproj.filters b/FFmpegInterop/Win8.1/FFmpegInterop.WindowsPhone/FFmpegInterop.WindowsPhone.vcxproj.filters new file mode 100755 index 0000000..342b103 --- /dev/null +++ b/FFmpegInterop/Win8.1/FFmpegInterop.WindowsPhone/FFmpegInterop.WindowsPhone.vcxproj.filters @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 index 0ad25db..63e41a4 --- a/LICENSE +++ b/LICENSE @@ -1,661 +1,339 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. \ No newline at end of file diff --git a/Libraries/BouncyCastle.Crypto.WP71.dll b/Libraries/BouncyCastle.Crypto.WP71.dll new file mode 100755 index 0000000..63ad86d Binary files /dev/null and b/Libraries/BouncyCastle.Crypto.WP71.dll differ diff --git a/Libraries/BugSense-WP8.dll b/Libraries/BugSense-WP8.dll new file mode 100755 index 0000000..8016da5 Binary files /dev/null and b/Libraries/BugSense-WP8.dll differ diff --git a/Libraries/BugSense.dll b/Libraries/BugSense.dll new file mode 100755 index 0000000..1e73f1d Binary files /dev/null and b/Libraries/BugSense.dll differ diff --git a/Libraries/Google.WebAnalytics.dll b/Libraries/Google.WebAnalytics.dll new file mode 100755 index 0000000..42c6796 Binary files /dev/null and b/Libraries/Google.WebAnalytics.dll differ diff --git a/Libraries/Id3.Files.dll b/Libraries/Id3.Files.dll new file mode 100755 index 0000000..76f8eaa Binary files /dev/null and b/Libraries/Id3.Files.dll differ diff --git a/Libraries/Id3.dll b/Libraries/Id3.dll new file mode 100755 index 0000000..8462283 Binary files /dev/null and b/Libraries/Id3.dll differ diff --git a/Libraries/LayoutTransformer.dll b/Libraries/LayoutTransformer.dll new file mode 100755 index 0000000..aedc1d0 Binary files /dev/null and b/Libraries/LayoutTransformer.dll differ diff --git a/Libraries/Microsoft.SilverlightMediaFramework.Compatibility.Phone.dll b/Libraries/Microsoft.SilverlightMediaFramework.Compatibility.Phone.dll new file mode 100755 index 0000000..7436f1a Binary files /dev/null and b/Libraries/Microsoft.SilverlightMediaFramework.Compatibility.Phone.dll differ diff --git a/Libraries/Microsoft.WebAnalytics.Behaviors.dll b/Libraries/Microsoft.WebAnalytics.Behaviors.dll new file mode 100755 index 0000000..1eda12f Binary files /dev/null and b/Libraries/Microsoft.WebAnalytics.Behaviors.dll differ diff --git a/Libraries/Microsoft.WebAnalytics.dll b/Libraries/Microsoft.WebAnalytics.dll new file mode 100755 index 0000000..0693ef6 Binary files /dev/null and b/Libraries/Microsoft.WebAnalytics.dll differ diff --git a/Libraries/PerstWP7.dll b/Libraries/PerstWP7.dll new file mode 100755 index 0000000..94400e6 Binary files /dev/null and b/Libraries/PerstWP7.dll differ diff --git a/Libraries/System.Windows.Interactivity.dll b/Libraries/System.Windows.Interactivity.dll new file mode 100755 index 0000000..786d6de Binary files /dev/null and b/Libraries/System.Windows.Interactivity.dll differ diff --git a/OpenCVComponent/Assets/haarcascade_eye.xml b/OpenCVComponent/Assets/haarcascade_eye.xml new file mode 100755 index 0000000..b21e3b9 --- /dev/null +++ b/OpenCVComponent/Assets/haarcascade_eye.xml @@ -0,0 +1,12213 @@ + + + +BOOST + HAAR + 20 + 20 + + 93 + + 0 + 24 + + <_> + 6 + -1.4562760591506958e+00 + + <_> + + 0 -1 0 1.2963959574699402e-01 + + -7.7304208278656006e-01 6.8350148200988770e-01 + <_> + + 0 -1 1 -4.6326808631420135e-02 + + 5.7352751493453979e-01 -4.9097689986228943e-01 + <_> + + 0 -1 2 -1.6173090785741806e-02 + + 6.0254341363906860e-01 -3.1610709428787231e-01 + <_> + + 0 -1 3 -4.5828841626644135e-02 + + 6.4177548885345459e-01 -1.5545040369033813e-01 + <_> + + 0 -1 4 -5.3759619593620300e-02 + + 5.4219317436218262e-01 -2.0480829477310181e-01 + <_> + + 0 -1 5 3.4171190112829208e-02 + + -2.3388190567493439e-01 4.8410901427268982e-01 + <_> + 12 + -1.2550230026245117e+00 + + <_> + + 0 -1 6 -2.1727620065212250e-01 + + 7.1098899841308594e-01 -5.9360730648040771e-01 + <_> + + 0 -1 7 1.2071969918906689e-02 + + -2.8240481019020081e-01 5.9013551473617554e-01 + <_> + + 0 -1 8 -1.7854139208793640e-02 + + 5.3137522935867310e-01 -2.2758960723876953e-01 + <_> + + 0 -1 9 2.2333610802888870e-02 + + -1.7556099593639374e-01 6.3356137275695801e-01 + <_> + + 0 -1 10 -9.1420017182826996e-02 + + 6.1563092470169067e-01 -1.6899530589580536e-01 + <_> + + 0 -1 11 2.8973650187253952e-02 + + -1.2250079959630966e-01 7.4401170015335083e-01 + <_> + + 0 -1 12 7.8203463926911354e-03 + + 1.6974370181560516e-01 -6.5441650152206421e-01 + <_> + + 0 -1 13 2.0340489223599434e-02 + + -1.2556649744510651e-01 8.2710450887680054e-01 + <_> + + 0 -1 14 -1.1926149949431419e-02 + + 3.8605681061744690e-01 -2.0992340147495270e-01 + <_> + + 0 -1 15 -9.7281101625412703e-04 + + -6.3761192560195923e-01 1.2952390313148499e-01 + <_> + + 0 -1 16 1.8322050891583785e-05 + + -3.4631478786468506e-01 2.2924269735813141e-01 + <_> + + 0 -1 17 -8.0854417756199837e-03 + + -6.3665801286697388e-01 1.3078659772872925e-01 + <_> + 9 + -1.3728189468383789e+00 + + <_> + + 0 -1 18 -1.1812269687652588e-01 + + 6.7844521999359131e-01 -5.0045782327651978e-01 + <_> + + 0 -1 19 -3.4332759678363800e-02 + + 6.7186361551284790e-01 -3.5744878649711609e-01 + <_> + + 0 -1 20 -2.1530799567699432e-02 + + 7.2220700979232788e-01 -1.8192419409751892e-01 + <_> + + 0 -1 21 -2.1909970790147781e-02 + + 6.6529387235641479e-01 -2.7510228753089905e-01 + <_> + + 0 -1 22 -2.8713539242744446e-02 + + 6.9955700635910034e-01 -1.9615580141544342e-01 + <_> + + 0 -1 23 -1.1467480100691319e-02 + + 5.9267348051071167e-01 -2.2097350656986237e-01 + <_> + + 0 -1 24 -2.2611169144511223e-02 + + 3.4483069181442261e-01 -3.8379558920860291e-01 + <_> + + 0 -1 25 -1.9308089977130294e-03 + + -7.9445719718933105e-01 1.5628659725189209e-01 + <_> + + 0 -1 26 5.6419910833938047e-05 + + -3.0896010994911194e-01 3.5431089997291565e-01 + <_> + 16 + -1.2879480123519897e+00 + + <_> + + 0 -1 27 1.9886520504951477e-01 + + -5.2860701084136963e-01 3.5536721348762512e-01 + <_> + + 0 -1 28 -3.6008939146995544e-02 + + 4.2109689116477966e-01 -3.9348980784416199e-01 + <_> + + 0 -1 29 -7.7569849789142609e-02 + + 4.7991541028022766e-01 -2.5122168660163879e-01 + <_> + + 0 -1 30 8.2630853285081685e-05 + + -3.8475489616394043e-01 3.1849220395088196e-01 + <_> + + 0 -1 31 3.2773229759186506e-04 + + -2.6427319645881653e-01 3.2547241449356079e-01 + <_> + + 0 -1 32 -1.8574850633740425e-02 + + 4.6736589074134827e-01 -1.5067270398139954e-01 + <_> + + 0 -1 33 -7.0008762122597545e-05 + + 2.9313150048255920e-01 -2.5365099310874939e-01 + <_> + + 0 -1 34 -1.8552130088210106e-02 + + 4.6273660659790039e-01 -1.3148050010204315e-01 + <_> + + 0 -1 35 -1.3030420057475567e-02 + + 4.1627219319343567e-01 -1.7751489579677582e-01 + <_> + + 0 -1 36 6.5694141085259616e-05 + + -2.8035101294517517e-01 2.6680740714073181e-01 + <_> + + 0 -1 37 1.7005260451696813e-04 + + -2.7027249336242676e-01 2.3981650173664093e-01 + <_> + + 0 -1 38 -3.3129199873656034e-03 + + 4.4411438703536987e-01 -1.4428889751434326e-01 + <_> + + 0 -1 39 1.7583490116521716e-03 + + -1.6126190125942230e-01 4.2940768599510193e-01 + <_> + + 0 -1 40 -2.5194749236106873e-02 + + 4.0687298774719238e-01 -1.8202580511569977e-01 + <_> + + 0 -1 41 1.4031709870323539e-03 + + 8.4759786725044250e-02 -8.0018568038940430e-01 + <_> + + 0 -1 42 -7.3991729877889156e-03 + + 5.5766099691390991e-01 -1.1843159794807434e-01 + <_> + 23 + -1.2179850339889526e+00 + + <_> + + 0 -1 43 -2.9943080618977547e-02 + + 3.5810810327529907e-01 -3.8487631082534790e-01 + <_> + + 0 -1 44 -1.2567380070686340e-01 + + 3.9316931366920471e-01 -3.0012258887290955e-01 + <_> + + 0 -1 45 5.3635272197425365e-03 + + -4.3908619880676270e-01 1.9257010519504547e-01 + <_> + + 0 -1 46 -8.0971820279955864e-03 + + 3.9906668663024902e-01 -2.3407870531082153e-01 + <_> + + 0 -1 47 -1.6597909852862358e-02 + + 4.2095288634300232e-01 -2.2674840688705444e-01 + <_> + + 0 -1 48 -2.0199299324303865e-03 + + -7.4156731367111206e-01 1.2601189315319061e-01 + <_> + + 0 -1 49 -1.5202340437099338e-03 + + -7.6154601573944092e-01 8.6373612284660339e-02 + <_> + + 0 -1 50 -4.9663940444588661e-03 + + 4.2182239890098572e-01 -1.7904919385910034e-01 + <_> + + 0 -1 51 -1.9207600504159927e-02 + + 4.6894899010658264e-01 -1.4378750324249268e-01 + <_> + + 0 -1 52 -1.2222680263221264e-02 + + 3.2842078804969788e-01 -2.1802149713039398e-01 + <_> + + 0 -1 53 5.7548668235540390e-02 + + -3.6768808960914612e-01 2.4357110261917114e-01 + <_> + + 0 -1 54 -9.5794079825282097e-03 + + -7.2245067358016968e-01 6.3664563000202179e-02 + <_> + + 0 -1 55 -2.9545740690082312e-03 + + 3.5846439003944397e-01 -1.6696329414844513e-01 + <_> + + 0 -1 56 -4.2017991654574871e-03 + + 3.9094808697700500e-01 -1.2041790038347244e-01 + <_> + + 0 -1 57 -1.3624990358948708e-02 + + -5.8767718076705933e-01 8.8404729962348938e-02 + <_> + + 0 -1 58 6.2853112467564642e-05 + + -2.6348459720611572e-01 2.1419279277324677e-01 + <_> + + 0 -1 59 -2.6782939676195383e-03 + + -7.8390169143676758e-01 8.0526962876319885e-02 + <_> + + 0 -1 60 -7.0597179234027863e-02 + + 4.1469261050224304e-01 -1.3989959657192230e-01 + <_> + + 0 -1 61 9.2093646526336670e-02 + + -1.3055180013179779e-01 5.0435781478881836e-01 + <_> + + 0 -1 62 -8.8004386052489281e-03 + + 3.6609750986099243e-01 -1.4036649465560913e-01 + <_> + + 0 -1 63 7.5080977694597095e-05 + + -2.9704439640045166e-01 2.0702940225601196e-01 + <_> + + 0 -1 64 -2.9870450962334871e-03 + + 3.5615700483322144e-01 -1.5445969998836517e-01 + <_> + + 0 -1 65 -2.6441509835422039e-03 + + -5.4353517293930054e-01 1.0295110195875168e-01 + <_> + 27 + -1.2905240058898926e+00 + + <_> + + 0 -1 66 -4.7862470149993896e-02 + + 4.1528239846229553e-01 -3.4185820817947388e-01 + <_> + + 0 -1 67 8.7350532412528992e-02 + + -3.8749781250953674e-01 2.4204200506210327e-01 + <_> + + 0 -1 68 -1.6849499195814133e-02 + + 5.3082478046417236e-01 -1.7282910645008087e-01 + <_> + + 0 -1 69 -2.8870029374957085e-02 + + 3.5843509435653687e-01 -2.2402590513229370e-01 + <_> + + 0 -1 70 2.5679389946162701e-03 + + 1.4990499615669250e-01 -6.5609407424926758e-01 + <_> + + 0 -1 71 -2.4116659536957741e-02 + + 5.5889678001403809e-01 -1.4810280501842499e-01 + <_> + + 0 -1 72 -3.2826658338308334e-02 + + 4.6468681097030640e-01 -1.0785529762506485e-01 + <_> + + 0 -1 73 -1.5233060345053673e-02 + + -7.3954427242279053e-01 5.6236881762742996e-02 + <_> + + 0 -1 74 -3.0209511169232428e-04 + + -4.5548820495605469e-01 9.7069837152957916e-02 + <_> + + 0 -1 75 7.5365108205005527e-04 + + 9.5147296786308289e-02 -5.4895019531250000e-01 + <_> + + 0 -1 76 -1.0638950392603874e-02 + + 4.0912970900535583e-01 -1.2308409810066223e-01 + <_> + + 0 -1 77 -7.5217830017209053e-03 + + 4.0289148688316345e-01 -1.6048780083656311e-01 + <_> + + 0 -1 78 -1.0677099972963333e-01 + + 6.1759322881698608e-01 -7.3091186583042145e-02 + <_> + + 0 -1 79 1.6256919130682945e-02 + + -1.3103680312633514e-01 3.7453651428222656e-01 + <_> + + 0 -1 80 -2.0679360255599022e-02 + + -7.1402907371520996e-01 5.2390009164810181e-02 + <_> + + 0 -1 81 1.7052369192242622e-02 + + 1.2822860479354858e-01 -3.1080681085586548e-01 + <_> + + 0 -1 82 -5.7122060097754002e-03 + + -6.0556507110595703e-01 8.1884756684303284e-02 + <_> + + 0 -1 83 2.0851430235779844e-05 + + -2.6812988519668579e-01 1.4453840255737305e-01 + <_> + + 0 -1 84 7.9284431412816048e-03 + + -7.8795351088047028e-02 5.6762582063674927e-01 + <_> + + 0 -1 85 -2.5217379443347454e-03 + + 3.7068629264831543e-01 -1.3620570302009583e-01 + <_> + + 0 -1 86 -2.2426199167966843e-02 + + -6.8704998493194580e-01 5.1062859594821930e-02 + <_> + + 0 -1 87 -7.6451441273093224e-03 + + 2.3492220044136047e-01 -1.7905959486961365e-01 + <_> + + 0 -1 88 -1.1175329564139247e-03 + + -5.9869050979614258e-01 7.4324436485767365e-02 + <_> + + 0 -1 89 1.9212789833545685e-02 + + -1.5702550113201141e-01 2.9737469553947449e-01 + <_> + + 0 -1 90 5.6293429806828499e-03 + + -9.9769018590450287e-02 4.2130270600318909e-01 + <_> + + 0 -1 91 -9.5671862363815308e-03 + + -6.0858798027038574e-01 7.3506258428096771e-02 + <_> + + 0 -1 92 1.1217960156500340e-02 + + -1.0320810228586197e-01 4.1909849643707275e-01 + <_> + 28 + -1.1600480079650879e+00 + + <_> + + 0 -1 93 -1.7486440017819405e-02 + + 3.1307280063629150e-01 -3.3681181073188782e-01 + <_> + + 0 -1 94 3.0714649707078934e-02 + + -1.8766190111637115e-01 5.3780800104141235e-01 + <_> + + 0 -1 95 -2.2188719362020493e-02 + + 3.6637881398200989e-01 -1.6124810278415680e-01 + <_> + + 0 -1 96 -5.0700771680567414e-05 + + 2.1245710551738739e-01 -2.8444620966911316e-01 + <_> + + 0 -1 97 -7.0170420221984386e-03 + + 3.9543110132217407e-01 -1.3173590600490570e-01 + <_> + + 0 -1 98 -6.8563609384000301e-03 + + 3.0373859405517578e-01 -2.0657819509506226e-01 + <_> + + 0 -1 99 -1.4129259623587132e-02 + + -7.6503008604049683e-01 9.8213188350200653e-02 + <_> + + 0 -1 100 -4.7915481030941010e-02 + + 4.8307389020919800e-01 -1.3006809353828430e-01 + <_> + + 0 -1 101 4.7032979637151584e-05 + + -2.5216570496559143e-01 2.4386680126190186e-01 + <_> + + 0 -1 102 1.0221180273219943e-03 + + 6.8857602775096893e-02 -6.5861141681671143e-01 + <_> + + 0 -1 103 -2.6056109927594662e-03 + + 4.2942029237747192e-01 -1.3022460043430328e-01 + <_> + + 0 -1 104 5.4505340813193470e-05 + + -1.9288620352745056e-01 2.8958499431610107e-01 + <_> + + 0 -1 105 -6.6721157054416835e-05 + + 3.0290710926055908e-01 -1.9854369759559631e-01 + <_> + + 0 -1 106 2.6281431317329407e-01 + + -2.3293940722942352e-01 2.3692460358142853e-01 + <_> + + 0 -1 107 -2.3569669574499130e-02 + + 1.9401040673255920e-01 -2.8484618663787842e-01 + <_> + + 0 -1 108 -3.9120172150433064e-03 + + 5.5378979444503784e-01 -9.5665678381919861e-02 + <_> + + 0 -1 109 5.0788799853762612e-05 + + -2.3912659287452698e-01 2.1799489855766296e-01 + <_> + + 0 -1 110 -7.8732017427682877e-03 + + 4.0697428584098816e-01 -1.2768040597438812e-01 + <_> + + 0 -1 111 -1.6778609715402126e-03 + + -5.7744657993316650e-01 9.7324788570404053e-02 + <_> + + 0 -1 112 -2.6832430739887059e-04 + + 2.9021880030632019e-01 -1.6831269860267639e-01 + <_> + + 0 -1 113 7.8687182394787669e-05 + + -1.9551570713520050e-01 2.7720969915390015e-01 + <_> + + 0 -1 114 1.2953500263392925e-02 + + -9.6838317811489105e-02 4.0323871374130249e-01 + <_> + + 0 -1 115 -1.3043959625065327e-02 + + 4.7198569774627686e-01 -8.9287549257278442e-02 + <_> + + 0 -1 116 3.0261781066656113e-03 + + -1.3623380661010742e-01 3.0686271190643311e-01 + <_> + + 0 -1 117 -6.0438038781285286e-03 + + -7.7954101562500000e-01 5.7316310703754425e-02 + <_> + + 0 -1 118 -2.2507249377667904e-03 + + 3.0877059698104858e-01 -1.5006309747695923e-01 + <_> + + 0 -1 119 1.5826810151338577e-02 + + 6.4551889896392822e-02 -7.2455567121505737e-01 + <_> + + 0 -1 120 6.5864507632795721e-05 + + -1.7598840594291687e-01 2.3210389912128448e-01 + <_> + 36 + -1.2257250547409058e+00 + + <_> + + 0 -1 121 -2.7854869142174721e-02 + + 4.5518448948860168e-01 -1.8099910020828247e-01 + <_> + + 0 -1 122 1.2895040214061737e-01 + + -5.2565532922744751e-01 1.6188900172710419e-01 + <_> + + 0 -1 123 2.4403180927038193e-02 + + -1.4974960684776306e-01 4.2357379198074341e-01 + <_> + + 0 -1 124 -2.4458570405840874e-03 + + 3.2948669791221619e-01 -1.7447690665721893e-01 + <_> + + 0 -1 125 -3.5336529836058617e-03 + + 4.7426640987396240e-01 -7.3618359863758087e-02 + <_> + + 0 -1 126 5.1358150813030079e-05 + + -3.0421930551528931e-01 1.5633270144462585e-01 + <_> + + 0 -1 127 -1.6225680708885193e-02 + + 2.3002180457115173e-01 -2.0359820127487183e-01 + <_> + + 0 -1 128 -4.6007009223103523e-03 + + 4.0459269285202026e-01 -1.3485440611839294e-01 + <_> + + 0 -1 129 -2.1928999572992325e-02 + + -6.8724489212036133e-01 8.0684266984462738e-02 + <_> + + 0 -1 130 -2.8971210122108459e-03 + + -6.9619607925415039e-01 4.8545219004154205e-02 + <_> + + 0 -1 131 -4.4074649922549725e-03 + + 2.5166261196136475e-01 -1.6236649453639984e-01 + <_> + + 0 -1 132 2.8437169268727303e-02 + + 6.0394261032342911e-02 -6.6744458675384521e-01 + <_> + + 0 -1 133 8.3212882280349731e-02 + + 6.4357921481132507e-02 -5.3626042604446411e-01 + <_> + + 0 -1 134 -1.2419329956173897e-02 + + -7.0816862583160400e-01 5.7526610791683197e-02 + <_> + + 0 -1 135 -4.6992599964141846e-03 + + 5.1254332065582275e-01 -8.7350800633430481e-02 + <_> + + 0 -1 136 -7.8025809489190578e-04 + + 2.6687660813331604e-01 -1.7961509525775909e-01 + <_> + + 0 -1 137 -1.9724339246749878e-02 + + -6.7563730478286743e-01 7.2941906750202179e-02 + <_> + + 0 -1 138 1.0269250487908721e-03 + + 5.3919319063425064e-02 -5.5540180206298828e-01 + <_> + + 0 -1 139 -2.5957189500331879e-02 + + 5.6362527608871460e-01 -7.1898393332958221e-02 + <_> + + 0 -1 140 -1.2552699772641063e-03 + + -5.0346630811691284e-01 8.9691452682018280e-02 + <_> + + 0 -1 141 -4.9970578402280807e-02 + + 1.7685119807720184e-01 -2.2301959991455078e-01 + <_> + + 0 -1 142 -2.9899610672146082e-03 + + 3.9122420549392700e-01 -1.0149750113487244e-01 + <_> + + 0 -1 143 4.8546842299401760e-03 + + -1.1770179867744446e-01 4.2190939188003540e-01 + <_> + + 0 -1 144 1.0448860120959580e-04 + + -1.7333979904651642e-01 2.2344440221786499e-01 + <_> + + 0 -1 145 5.9689260524464771e-05 + + -2.3409630358219147e-01 1.6558240354061127e-01 + <_> + + 0 -1 146 -1.3423919677734375e-02 + + 4.3023818731307983e-01 -9.9723652005195618e-02 + <_> + + 0 -1 147 2.2581999655812979e-03 + + 7.2720989584922791e-02 -5.7501018047332764e-01 + <_> + + 0 -1 148 -1.2546280398964882e-02 + + 3.6184579133987427e-01 -1.1457010358572006e-01 + <_> + + 0 -1 149 -2.8705769218504429e-03 + + 2.8210538625717163e-01 -1.2367550283670425e-01 + <_> + + 0 -1 150 1.9785640761256218e-02 + + 4.7876749187707901e-02 -8.0666238069534302e-01 + <_> + + 0 -1 151 4.7588930465281010e-03 + + -1.0925389826297760e-01 3.3746978640556335e-01 + <_> + + 0 -1 152 -6.9974269717931747e-03 + + -8.0295938253402710e-01 4.5706700533628464e-02 + <_> + + 0 -1 153 -1.3033480383455753e-02 + + 1.8680439889431000e-01 -1.7688910663127899e-01 + <_> + + 0 -1 154 -1.3742579612880945e-03 + + 2.7725479006767273e-01 -1.2809009850025177e-01 + <_> + + 0 -1 155 2.7657810132950544e-03 + + 9.0758942067623138e-02 -4.2594739794731140e-01 + <_> + + 0 -1 156 2.8941841446794569e-04 + + -3.8816329836845398e-01 8.9267797768115997e-02 + <_> + 47 + -1.2863140106201172e+00 + + <_> + + 0 -1 157 -1.4469229616224766e-02 + + 3.7507829070091248e-01 -2.4928289651870728e-01 + <_> + + 0 -1 158 -1.3317629694938660e-01 + + 3.0166378617286682e-01 -2.2414070367813110e-01 + <_> + + 0 -1 159 -1.0132160037755966e-02 + + 3.6985591053962708e-01 -1.7850010097026825e-01 + <_> + + 0 -1 160 -7.8511182218790054e-03 + + 4.6086761355400085e-01 -1.2931390106678009e-01 + <_> + + 0 -1 161 -1.4295839704573154e-02 + + 4.4841429591178894e-01 -1.0226240009069443e-01 + <_> + + 0 -1 162 -5.9606940485537052e-03 + + 2.7927988767623901e-01 -1.5323829650878906e-01 + <_> + + 0 -1 163 1.0932769626379013e-02 + + -1.5141740441322327e-01 3.9889648556709290e-01 + <_> + + 0 -1 164 5.0430990086169913e-05 + + -2.2681570053100586e-01 2.1644389629364014e-01 + <_> + + 0 -1 165 -5.8431681245565414e-03 + + 4.5420148968696594e-01 -1.2587159872055054e-01 + <_> + + 0 -1 166 -2.2346209734678268e-02 + + -6.2690192461013794e-01 8.2403123378753662e-02 + <_> + + 0 -1 167 -4.8836669884622097e-03 + + 2.6359251141548157e-01 -1.4686630666255951e-01 + <_> + + 0 -1 168 7.5506002758629620e-05 + + -2.4507020413875580e-01 1.6678880155086517e-01 + <_> + + 0 -1 169 -4.9026997294276953e-04 + + -4.2649960517883301e-01 8.9973561465740204e-02 + <_> + + 0 -1 170 1.4861579984426498e-03 + + -1.2040250003337860e-01 3.0097651481628418e-01 + <_> + + 0 -1 171 -1.1988339945673943e-02 + + 2.7852478623390198e-01 -1.2244340032339096e-01 + <_> + + 0 -1 172 1.0502239689230919e-02 + + 4.0452759712934494e-02 -7.4050408601760864e-01 + <_> + + 0 -1 173 -3.0963009223341942e-02 + + -6.2842690944671631e-01 4.8013761639595032e-02 + <_> + + 0 -1 174 1.1414520442485809e-02 + + 3.9405211806297302e-02 -7.1674120426177979e-01 + <_> + + 0 -1 175 -1.2337000109255314e-02 + + 1.9941329956054688e-01 -1.9274300336837769e-01 + <_> + + 0 -1 176 -5.9942267835140228e-03 + + 5.1318162679672241e-01 -6.1658058315515518e-02 + <_> + + 0 -1 177 -1.1923230485990644e-03 + + -7.2605299949645996e-01 5.0652720034122467e-02 + <_> + + 0 -1 178 -7.4582789093255997e-03 + + 2.9603078961372375e-01 -1.1754789948463440e-01 + <_> + + 0 -1 179 2.7877509128302336e-03 + + 4.5068711042404175e-02 -6.9535410404205322e-01 + <_> + + 0 -1 180 -2.2503209766000509e-04 + + 2.0047250390052795e-01 -1.5775249898433685e-01 + <_> + + 0 -1 181 -5.0367889925837517e-03 + + 2.9299819469451904e-01 -1.1700499802827835e-01 + <_> + + 0 -1 182 7.4742160737514496e-02 + + -1.1392319947481155e-01 3.0256620049476624e-01 + <_> + + 0 -1 183 2.0255519077181816e-02 + + -1.0515890270471573e-01 4.0670460462570190e-01 + <_> + + 0 -1 184 4.4214509427547455e-02 + + -2.7631640434265137e-01 1.2363869696855545e-01 + <_> + + 0 -1 185 -8.7259558495134115e-04 + + 2.4355030059814453e-01 -1.3300949335098267e-01 + <_> + + 0 -1 186 -2.4453739169985056e-03 + + -5.3866171836853027e-01 6.2510646879673004e-02 + <_> + + 0 -1 187 8.2725353422574699e-05 + + -2.0772209763526917e-01 1.6270439326763153e-01 + <_> + + 0 -1 188 -3.6627110093832016e-02 + + 3.6568409204483032e-01 -9.0330280363559723e-02 + <_> + + 0 -1 189 3.0996399000287056e-03 + + -1.3183020055294037e-01 2.5354298949241638e-01 + <_> + + 0 -1 190 -2.4709280114620924e-03 + + -5.6853497028350830e-01 5.3505431860685349e-02 + <_> + + 0 -1 191 -1.4114670455455780e-02 + + -4.8599010705947876e-01 5.8485250920057297e-02 + <_> + + 0 -1 192 8.4537261864170432e-04 + + -8.0093637108802795e-02 4.0265649557113647e-01 + <_> + + 0 -1 193 -7.1098632179200649e-03 + + 4.4703239202499390e-01 -6.2947437167167664e-02 + <_> + + 0 -1 194 -1.9125960767269135e-02 + + -6.6422867774963379e-01 4.9822770059108734e-02 + <_> + + 0 -1 195 -5.0773010589182377e-03 + + 1.7379400134086609e-01 -1.6850599646568298e-01 + <_> + + 0 -1 196 -2.9198289848864079e-03 + + -6.0110282897949219e-01 5.7427939027547836e-02 + <_> + + 0 -1 197 -2.4902150034904480e-02 + + 2.3397980630397797e-01 -1.1818459630012512e-01 + <_> + + 0 -1 198 2.0147779956459999e-02 + + -8.9459821581840515e-02 3.6024400591850281e-01 + <_> + + 0 -1 199 1.7597640398889780e-03 + + 4.9458440393209457e-02 -6.3102620840072632e-01 + <_> + + 0 -1 200 1.3812039978802204e-03 + + -1.5218059718608856e-01 1.8971739709377289e-01 + <_> + + 0 -1 201 -1.0904540307819843e-02 + + -5.8097380399703979e-01 4.4862728565931320e-02 + <_> + + 0 -1 202 7.5157178798690438e-05 + + -1.3777349889278412e-01 1.9543160498142242e-01 + <_> + + 0 -1 203 3.8649770431220531e-03 + + -1.0302229970693588e-01 2.5374969840049744e-01 + <_> + 48 + -1.1189440488815308e+00 + + <_> + + 0 -1 204 -1.0215889662504196e-01 + + 4.1681259870529175e-01 -1.6655629873275757e-01 + <_> + + 0 -1 205 -5.1939819008111954e-02 + + 3.3023950457572937e-01 -2.0715710520744324e-01 + <_> + + 0 -1 206 -4.2717780917882919e-02 + + 2.6093730330467224e-01 -1.6013890504837036e-01 + <_> + + 0 -1 207 4.3890418601222336e-04 + + -3.4750530123710632e-01 1.3918919861316681e-01 + <_> + + 0 -1 208 2.4264389649033546e-02 + + -4.2552059888839722e-01 1.3578380644321442e-01 + <_> + + 0 -1 209 -2.3820599541068077e-02 + + 3.1749808788299561e-01 -1.6652040183544159e-01 + <_> + + 0 -1 210 -7.0518180727958679e-03 + + 3.0947178602218628e-01 -1.3338300585746765e-01 + <_> + + 0 -1 211 -6.8517157342284918e-04 + + -6.0082262754440308e-01 8.7747000157833099e-02 + <_> + + 0 -1 212 5.3705149330198765e-03 + + -1.2311449646949768e-01 3.8333550095558167e-01 + <_> + + 0 -1 213 -1.3403539545834064e-02 + + 3.3877369761466980e-01 -1.0140489786863327e-01 + <_> + + 0 -1 214 -6.6856360062956810e-03 + + -6.1193597316741943e-01 4.7740221023559570e-02 + <_> + + 0 -1 215 -4.2887418530881405e-03 + + 2.5275790691375732e-01 -1.4434510469436646e-01 + <_> + + 0 -1 216 -1.0876749642193317e-02 + + 5.4775732755661011e-01 -5.9455480426549911e-02 + <_> + + 0 -1 217 3.7882640026509762e-04 + + 8.3410300314426422e-02 -4.4226369261741638e-01 + <_> + + 0 -1 218 -2.4550149682909250e-03 + + 2.3330999910831451e-01 -1.3964480161666870e-01 + <_> + + 0 -1 219 1.2721839593723416e-03 + + 6.0480289161205292e-02 -4.9456089735031128e-01 + <_> + + 0 -1 220 -4.8933159559965134e-03 + + -6.6833269596099854e-01 4.6218499541282654e-02 + <_> + + 0 -1 221 2.6449989527463913e-02 + + -7.3235362768173218e-02 4.4425961375236511e-01 + <_> + + 0 -1 222 -3.3706070389598608e-03 + + -4.2464339733123779e-01 6.8676561117172241e-02 + <_> + + 0 -1 223 -2.9559480026364326e-03 + + 1.6218039393424988e-01 -1.8222999572753906e-01 + <_> + + 0 -1 224 3.0619909986853600e-02 + + -5.8643341064453125e-02 5.3263628482818604e-01 + <_> + + 0 -1 225 -9.5765907317399979e-03 + + -6.0562682151794434e-01 5.3345989435911179e-02 + <_> + + 0 -1 226 6.6372493165545166e-05 + + -1.6680839657783508e-01 1.9284160435199738e-01 + <_> + + 0 -1 227 5.0975950434803963e-03 + + 4.4119510799646378e-02 -5.7458841800689697e-01 + <_> + + 0 -1 228 3.7112718564458191e-04 + + -1.1086399853229523e-01 2.3105390369892120e-01 + <_> + + 0 -1 229 -8.6607588455080986e-03 + + 4.0456289052963257e-01 -6.2446091324090958e-02 + <_> + + 0 -1 230 8.7489158613607287e-04 + + 6.4875148236751556e-02 -4.4871041178703308e-01 + <_> + + 0 -1 231 1.1120870476588607e-03 + + -9.3861460685729980e-02 3.0453911423683167e-01 + <_> + + 0 -1 232 -2.3837819695472717e-02 + + -5.8887428045272827e-01 4.6659421175718307e-02 + <_> + + 0 -1 233 2.2272899514064193e-04 + + -1.4898599684238434e-01 1.7701950669288635e-01 + <_> + + 0 -1 234 2.4467470124363899e-02 + + -5.5789601057767868e-02 4.9208301305770874e-01 + <_> + + 0 -1 235 -1.4239320158958435e-01 + + 1.5192000567913055e-01 -1.8778899312019348e-01 + <_> + + 0 -1 236 -2.0123120397329330e-02 + + 2.1780100464820862e-01 -1.2081900238990784e-01 + <_> + + 0 -1 237 1.1513679783092812e-04 + + -1.6856589913368225e-01 1.6451929509639740e-01 + <_> + + 0 -1 238 -2.7556740678846836e-03 + + -6.9442039728164673e-01 3.9449468255043030e-02 + <_> + + 0 -1 239 -7.5843912782147527e-05 + + 1.8941369652748108e-01 -1.5183840692043304e-01 + <_> + + 0 -1 240 -7.0697711780667305e-03 + + 4.7064599394798279e-01 -5.7927619665861130e-02 + <_> + + 0 -1 241 -3.7393178790807724e-02 + + -7.5892448425292969e-01 3.4116048365831375e-02 + <_> + + 0 -1 242 -1.5995610505342484e-02 + + 3.0670469999313354e-01 -8.7525576353073120e-02 + <_> + + 0 -1 243 -3.1183990649878979e-03 + + 2.6195371150970459e-01 -9.1214887797832489e-02 + <_> + + 0 -1 244 1.0651360498741269e-03 + + -1.7427560687065125e-01 1.5277640521526337e-01 + <_> + + 0 -1 245 -1.6029420075938106e-03 + + 3.5612630844116211e-01 -7.6629996299743652e-02 + <_> + + 0 -1 246 4.3619908392429352e-03 + + 4.9356970936059952e-02 -5.9228771924972534e-01 + <_> + + 0 -1 247 -1.0779909789562225e-02 + + -6.3922178745269775e-01 3.3204540610313416e-02 + <_> + + 0 -1 248 -4.3590869754552841e-03 + + 1.6107389330863953e-01 -1.5221320092678070e-01 + <_> + + 0 -1 249 7.4596069753170013e-03 + + 3.3172961324453354e-02 -7.5007742643356323e-01 + <_> + + 0 -1 250 8.1385448575019836e-03 + + 2.6325279846787453e-02 -7.1731162071228027e-01 + <_> + + 0 -1 251 -3.3338490873575211e-02 + + 3.3536610007286072e-01 -7.0803590118885040e-02 + <_> + 55 + -1.1418989896774292e+00 + + <_> + + 0 -1 252 1.9553979858756065e-02 + + -1.0439720004796982e-01 5.3128951787948608e-01 + <_> + + 0 -1 253 2.2122919559478760e-02 + + -2.4747270345687866e-01 2.0847250521183014e-01 + <_> + + 0 -1 254 -4.1829389519989491e-03 + + 3.8289439678192139e-01 -1.4711579680442810e-01 + <_> + + 0 -1 255 -8.6381728760898113e-04 + + -6.2632888555526733e-01 1.1993259936571121e-01 + <_> + + 0 -1 256 7.9958612332120538e-04 + + 9.2573471367359161e-02 -5.5168831348419189e-01 + <_> + + 0 -1 257 9.1527570039033890e-03 + + -7.2929807007312775e-02 5.5512511730194092e-01 + <_> + + 0 -1 258 -3.9388681761920452e-03 + + 2.0196039974689484e-01 -2.0912039279937744e-01 + <_> + + 0 -1 259 1.4613410166930407e-04 + + -2.7861818671226501e-01 1.3817410171031952e-01 + <_> + + 0 -1 260 -3.1691689509898424e-03 + + 3.6685898900032043e-01 -7.6308242976665497e-02 + <_> + + 0 -1 261 -2.2189389914274216e-02 + + 3.9096599817276001e-01 -1.0971540212631226e-01 + <_> + + 0 -1 262 -7.4523608200252056e-03 + + 1.2838590145111084e-01 -2.4159869551658630e-01 + <_> + + 0 -1 263 7.7997002517804503e-04 + + 7.1978069841861725e-02 -4.3976500630378723e-01 + <_> + + 0 -1 264 -4.6783639118075371e-03 + + 2.1569849550724030e-01 -1.4205920696258545e-01 + <_> + + 0 -1 265 -1.5188639983534813e-02 + + 3.6458781361579895e-01 -8.2675926387310028e-02 + <_> + + 0 -1 266 5.0619798712432384e-03 + + -3.4380409121513367e-01 9.2068232595920563e-02 + <_> + + 0 -1 267 -1.7351920250803232e-03 + + -6.1725497245788574e-01 4.9214478582143784e-02 + <_> + + 0 -1 268 -1.2423450127243996e-02 + + -5.8558952808380127e-01 4.6112600713968277e-02 + <_> + + 0 -1 269 -1.3031429611146450e-02 + + -5.9710788726806641e-01 4.0672458708286285e-02 + <_> + + 0 -1 270 -1.2369629694148898e-03 + + -6.8334168195724487e-01 3.3156178891658783e-02 + <_> + + 0 -1 271 6.1022108420729637e-03 + + -9.4729237258434296e-02 3.0102241039276123e-01 + <_> + + 0 -1 272 6.6952849738299847e-04 + + 8.1816866993904114e-02 -3.5196030139923096e-01 + <_> + + 0 -1 273 -1.7970580374822021e-03 + + 2.3718979954719543e-01 -1.1768709868192673e-01 + <_> + + 0 -1 274 -7.1074528386816382e-04 + + -4.4763788580894470e-01 5.7682480663061142e-02 + <_> + + 0 -1 275 -5.9126471169292927e-03 + + 4.3425410985946655e-01 -6.6868573427200317e-02 + <_> + + 0 -1 276 -3.3132149837911129e-03 + + 1.8150010704994202e-01 -1.4180320501327515e-01 + <_> + + 0 -1 277 -6.0814660042524338e-02 + + 4.7221711277961731e-01 -6.1410639435052872e-02 + <_> + + 0 -1 278 -9.6714183688163757e-02 + + 2.7683168649673462e-01 -9.4490036368370056e-02 + <_> + + 0 -1 279 3.9073550142347813e-03 + + -1.2278530001640320e-01 2.1057400107383728e-01 + <_> + + 0 -1 280 -9.0431869029998779e-03 + + 3.5641568899154663e-01 -7.7806226909160614e-02 + <_> + + 0 -1 281 -4.8800031654536724e-03 + + -4.1034790873527527e-01 6.9694377481937408e-02 + <_> + + 0 -1 282 -4.3547428213059902e-03 + + -7.3017889261245728e-01 3.6655150353908539e-02 + <_> + + 0 -1 283 -9.6500627696514130e-03 + + 5.5181127786636353e-01 -5.3168080747127533e-02 + <_> + + 0 -1 284 -1.7397310584783554e-02 + + -5.7084232568740845e-01 5.0214089453220367e-02 + <_> + + 0 -1 285 -6.8304329179227352e-03 + + -4.6180281043052673e-01 5.0202690064907074e-02 + <_> + + 0 -1 286 3.3255619928240776e-04 + + -9.5362730324268341e-02 2.5983759760856628e-01 + <_> + + 0 -1 287 -2.3100529797375202e-03 + + 2.2872470319271088e-01 -1.0533530265092850e-01 + <_> + + 0 -1 288 -7.5426651164889336e-03 + + -5.6990510225296021e-01 4.8863459378480911e-02 + <_> + + 0 -1 289 -5.2723060362040997e-03 + + 3.5145181417465210e-01 -8.2390107214450836e-02 + <_> + + 0 -1 290 -4.8578968271613121e-03 + + -6.0417622327804565e-01 4.4539440423250198e-02 + <_> + + 0 -1 291 1.5867310576140881e-03 + + -1.0340909659862518e-01 2.3282019793987274e-01 + <_> + + 0 -1 292 -4.7427811659872532e-03 + + 2.8490281105041504e-01 -9.8090499639511108e-02 + <_> + + 0 -1 293 -1.3515240279957652e-03 + + 2.3096430301666260e-01 -1.1361840367317200e-01 + <_> + + 0 -1 294 2.2526069078594446e-03 + + 6.4478322863578796e-02 -4.2205891013145447e-01 + <_> + + 0 -1 295 -3.8038659840822220e-04 + + -3.8076201081275940e-01 6.0043290257453918e-02 + <_> + + 0 -1 296 4.9043921753764153e-03 + + -7.6104998588562012e-02 3.3232170343399048e-01 + <_> + + 0 -1 297 -9.0969670563936234e-03 + + 1.4287790656089783e-01 -1.6887800395488739e-01 + <_> + + 0 -1 298 -6.9317929446697235e-03 + + 2.7255409955978394e-01 -9.2879563570022583e-02 + <_> + + 0 -1 299 1.1471060570329428e-03 + + -1.5273059904575348e-01 1.9702400267124176e-01 + <_> + + 0 -1 300 -3.7662889808416367e-02 + + -5.9320437908172607e-01 4.0738601237535477e-02 + <_> + + 0 -1 301 -6.8165571428835392e-03 + + 2.5494089722633362e-01 -9.4081960618495941e-02 + <_> + + 0 -1 302 6.6205562325194478e-04 + + 4.6795718371868134e-02 -4.8454371094703674e-01 + <_> + + 0 -1 303 -4.2202551849186420e-03 + + 2.4682149291038513e-01 -9.4673976302146912e-02 + <_> + + 0 -1 304 -6.8986512720584869e-02 + + -6.6514801979064941e-01 3.5926390439271927e-02 + <_> + + 0 -1 305 6.1707608401775360e-03 + + 2.5833319872617722e-02 -7.2686272859573364e-01 + <_> + + 0 -1 306 1.0536249727010727e-02 + + -8.1828996539115906e-02 2.9760798811912537e-01 + <_> + 32 + -1.1255199909210205e+00 + + <_> + + 0 -1 307 -6.2758728861808777e-02 + + 2.7899080514907837e-01 -2.9656109213829041e-01 + <_> + + 0 -1 308 3.4516479354351759e-03 + + -3.4635880589485168e-01 2.0903840661048889e-01 + <_> + + 0 -1 309 -7.8699486330151558e-03 + + 2.4144889414310455e-01 -1.9205570220947266e-01 + <_> + + 0 -1 310 -3.4624869003891945e-03 + + -5.9151780605316162e-01 1.2486449629068375e-01 + <_> + + 0 -1 311 -9.4818761572241783e-03 + + 1.8391540646553040e-01 -2.4858260154724121e-01 + <_> + + 0 -1 312 2.3226840130519122e-04 + + -3.3047258853912354e-01 1.0999260097742081e-01 + <_> + + 0 -1 313 1.8101120367646217e-03 + + 9.8744012415409088e-02 -4.9634781479835510e-01 + <_> + + 0 -1 314 -5.4422430694103241e-03 + + 2.9344418644905090e-01 -1.3094750046730042e-01 + <_> + + 0 -1 315 7.4148122221231461e-03 + + -1.4762699604034424e-01 3.3277168869972229e-01 + <_> + + 0 -1 316 -1.5565140172839165e-02 + + -6.8404901027679443e-01 9.9872693419456482e-02 + <_> + + 0 -1 317 2.8720520436763763e-02 + + -1.4833280444145203e-01 3.0902579426765442e-01 + <_> + + 0 -1 318 9.6687392215244472e-05 + + -1.7431040108203888e-01 2.1402959525585175e-01 + <_> + + 0 -1 319 5.2371058613061905e-02 + + -7.0156857371330261e-02 4.9222990870475769e-01 + <_> + + 0 -1 320 -8.6485691368579865e-02 + + 5.0757247209548950e-01 -7.5294211506843567e-02 + <_> + + 0 -1 321 -4.2169868946075439e-02 + + 4.5680961012840271e-01 -9.0219900012016296e-02 + <_> + + 0 -1 322 4.5369830331765115e-05 + + -2.6538279652595520e-01 1.6189539432525635e-01 + <_> + + 0 -1 323 5.2918000146746635e-03 + + 7.4890151619911194e-02 -5.4054671525955200e-01 + <_> + + 0 -1 324 -7.5511651812121272e-04 + + -4.9261990189552307e-01 5.8723948895931244e-02 + <_> + + 0 -1 325 7.5108138844370842e-05 + + -2.1432100236415863e-01 1.4077760279178619e-01 + <_> + + 0 -1 326 4.9981209449470043e-03 + + -9.0547338128089905e-02 3.5716068744659424e-01 + <_> + + 0 -1 327 -1.4929979806765914e-03 + + 2.5623458623886108e-01 -1.4229069650173187e-01 + <_> + + 0 -1 328 2.7239411137998104e-03 + + -1.5649250149726868e-01 2.1088710427284241e-01 + <_> + + 0 -1 329 2.2218320518732071e-03 + + -1.5072989463806152e-01 2.6801869273185730e-01 + <_> + + 0 -1 330 -7.3993072146549821e-04 + + 2.9546990990638733e-01 -1.0692390054464340e-01 + <_> + + 0 -1 331 2.0113459322601557e-03 + + 5.0614349544048309e-02 -7.1683371067047119e-01 + <_> + + 0 -1 332 1.1452870443463326e-02 + + -1.2719069421291351e-01 2.4152779579162598e-01 + <_> + + 0 -1 333 -1.0782170575112104e-03 + + 2.4813009798526764e-01 -1.3461199402809143e-01 + <_> + + 0 -1 334 3.3417691010981798e-03 + + 5.3578309714794159e-02 -5.2274167537689209e-01 + <_> + + 0 -1 335 6.9398651248775423e-05 + + -2.1698740124702454e-01 1.2812179327011108e-01 + <_> + + 0 -1 336 -4.0982551872730255e-03 + + 2.4401889741420746e-01 -1.1570589989423752e-01 + <_> + + 0 -1 337 -1.6289720078930259e-03 + + 2.8261470794677734e-01 -1.0659469664096832e-01 + <_> + + 0 -1 338 1.3984859921038151e-02 + + 4.2715899646282196e-02 -7.3646312952041626e-01 + <_> + 30 + -1.1729990243911743e+00 + + <_> + + 0 -1 339 1.6416519880294800e-01 + + -4.8960301280021667e-01 1.7607709765434265e-01 + <_> + + 0 -1 340 8.3413062384352088e-04 + + -2.8220430016517639e-01 2.4199579656124115e-01 + <_> + + 0 -1 341 -1.7193210078403354e-03 + + -7.1485888957977295e-01 8.6162216961383820e-02 + <_> + + 0 -1 342 -1.5654950402677059e-03 + + -7.2972381114959717e-01 9.4070672988891602e-02 + <_> + + 0 -1 343 1.9124479731544852e-03 + + -3.1187158823013306e-01 1.8143390119075775e-01 + <_> + + 0 -1 344 -1.3512369990348816e-01 + + 2.9577299952507019e-01 -2.2179250419139862e-01 + <_> + + 0 -1 345 -4.0300549007952213e-03 + + -6.6595137119293213e-01 8.5431016981601715e-02 + <_> + + 0 -1 346 -2.8640460222959518e-03 + + -6.2086361646652222e-01 5.3106021136045456e-02 + <_> + + 0 -1 347 -1.4065420255064964e-03 + + 2.2346289455890656e-01 -2.0211009681224823e-01 + <_> + + 0 -1 348 -3.5820449702441692e-03 + + -5.4030400514602661e-01 6.8213619291782379e-02 + <_> + + 0 -1 349 4.1544470936059952e-02 + + -6.5215840935707092e-02 6.2109231948852539e-01 + <_> + + 0 -1 350 -9.1709550470113754e-03 + + -7.5553297996520996e-01 5.2640449255704880e-02 + <_> + + 0 -1 351 6.1552738770842552e-03 + + 9.0939402580261230e-02 -4.4246131181716919e-01 + <_> + + 0 -1 352 -1.0043520014733076e-03 + + 2.4292330443859100e-01 -1.8669790029525757e-01 + <_> + + 0 -1 353 1.1519829742610455e-02 + + -1.1763150244951248e-01 3.6723458766937256e-01 + <_> + + 0 -1 354 -8.9040733873844147e-03 + + -4.8931330442428589e-01 1.0897020250558853e-01 + <_> + + 0 -1 355 5.3973670583218336e-04 + + -2.1850399672985077e-01 1.8489989638328552e-01 + <_> + + 0 -1 356 1.3727260520681739e-03 + + -1.5072910487651825e-01 2.9173129796981812e-01 + <_> + + 0 -1 357 -1.0807390324771404e-02 + + 4.2897450923919678e-01 -1.0280139744281769e-01 + <_> + + 0 -1 358 1.2670770520344377e-03 + + 7.4192158877849579e-02 -6.4208251237869263e-01 + <_> + + 0 -1 359 2.2991129662841558e-03 + + 4.7100279480218887e-02 -7.2335231304168701e-01 + <_> + + 0 -1 360 2.7187510859221220e-03 + + -1.7086869478225708e-01 2.3513509333133698e-01 + <_> + + 0 -1 361 -6.6619180142879486e-03 + + -7.8975427150726318e-01 4.5084670186042786e-02 + <_> + + 0 -1 362 -4.8266649246215820e-02 + + -6.9579917192459106e-01 4.1976079344749451e-02 + <_> + + 0 -1 363 1.5214690007269382e-02 + + -1.0818280279636383e-01 3.6460620164871216e-01 + <_> + + 0 -1 364 -6.0080131515860558e-03 + + 3.0970990657806396e-01 -1.1359210312366486e-01 + <_> + + 0 -1 365 6.6127157770097256e-03 + + 8.0665342509746552e-02 -4.6658530831336975e-01 + <_> + + 0 -1 366 -7.9607013612985611e-03 + + -8.7201941013336182e-01 3.6774590611457825e-02 + <_> + + 0 -1 367 3.8847199175506830e-03 + + -1.1666289716959000e-01 3.3070269227027893e-01 + <_> + + 0 -1 368 -1.0988810099661350e-03 + + 2.3872570693492889e-01 -1.7656759917736053e-01 + <_> + 44 + -1.0368299484252930e+00 + + <_> + + 0 -1 369 3.5903379321098328e-03 + + -2.3688079416751862e-01 2.4631640315055847e-01 + <_> + + 0 -1 370 6.4815930090844631e-03 + + -3.1373620033264160e-01 1.8675759434700012e-01 + <_> + + 0 -1 371 7.3048402555286884e-05 + + -2.7644351124763489e-01 1.6496239602565765e-01 + <_> + + 0 -1 372 -3.8514640182256699e-03 + + -5.6014508008956909e-01 1.1294739693403244e-01 + <_> + + 0 -1 373 3.8588210009038448e-03 + + 3.9848998188972473e-02 -5.8071857690811157e-01 + <_> + + 0 -1 374 -2.4651220068335533e-02 + + 1.6755010187625885e-01 -2.5343671441078186e-01 + <_> + + 0 -1 375 4.7245521098375320e-02 + + -1.0662080347537994e-01 3.9451980590820312e-01 + <_> + + 0 -1 376 6.5964651294052601e-03 + + -1.7744250595569611e-01 2.7280190587043762e-01 + <_> + + 0 -1 377 -1.3177490327507257e-03 + + -5.4272651672363281e-01 4.8606589436531067e-02 + <_> + + 0 -1 378 -5.0261709839105606e-03 + + 2.4394249916076660e-01 -1.3143649697303772e-01 + <_> + + 0 -1 379 3.4632768947631121e-03 + + 6.9049343466758728e-02 -7.0336240530014038e-01 + <_> + + 0 -1 380 2.1692588925361633e-03 + + -1.3289460539817810e-01 2.2098529338836670e-01 + <_> + + 0 -1 381 2.9395870864391327e-02 + + -2.8530520200729370e-01 1.3543990254402161e-01 + <_> + + 0 -1 382 -9.6181448316201568e-04 + + -5.8041381835937500e-01 3.7450648844242096e-02 + <_> + + 0 -1 383 -1.0820999741554260e-01 + + 3.9467281103134155e-01 -7.8655943274497986e-02 + <_> + + 0 -1 384 -1.8024869263172150e-02 + + 2.7355629205703735e-01 -1.3415299355983734e-01 + <_> + + 0 -1 385 6.2509840354323387e-03 + + 2.3388059809803963e-02 -8.0088591575622559e-01 + <_> + + 0 -1 386 -1.6088379779830575e-03 + + -5.6762522459030151e-01 4.1215669363737106e-02 + <_> + + 0 -1 387 7.7564752427861094e-04 + + -1.4891269803047180e-01 1.9086180627346039e-01 + <_> + + 0 -1 388 8.7122338300105184e-05 + + -1.5557530522346497e-01 1.9428220391273499e-01 + <_> + + 0 -1 389 -2.0755320787429810e-02 + + -6.3006532192230225e-01 3.6134380847215652e-02 + <_> + + 0 -1 390 -6.2931738793849945e-03 + + 2.5609248876571655e-01 -1.0588269680738449e-01 + <_> + + 0 -1 391 1.0844149626791477e-02 + + -1.0124850273132324e-01 3.0322128534317017e-01 + <_> + + 0 -1 392 -6.3752777350600809e-05 + + 1.9111579656600952e-01 -1.3849230110645294e-01 + <_> + + 0 -1 393 6.6480963141657412e-05 + + -1.5205250680446625e-01 2.1706309914588928e-01 + <_> + + 0 -1 394 1.3560829684138298e-03 + + 4.9431789666414261e-02 -6.4279842376708984e-01 + <_> + + 0 -1 395 -9.0662558795884252e-04 + + 1.7982010543346405e-01 -1.4044609665870667e-01 + <_> + + 0 -1 396 1.0473709553480148e-03 + + -1.0933549702167511e-01 2.4265940487384796e-01 + <_> + + 0 -1 397 -1.0243969736620784e-03 + + 2.7162680029869080e-01 -1.1820919811725616e-01 + <_> + + 0 -1 398 -1.2024149764329195e-03 + + -7.0151102542877197e-01 3.9489898830652237e-02 + <_> + + 0 -1 399 7.6911649666726589e-03 + + -9.2218913137912750e-02 3.1046289205551147e-01 + <_> + + 0 -1 400 -1.3966549932956696e-01 + + 6.8979388475418091e-01 -3.9706118404865265e-02 + <_> + + 0 -1 401 2.1276050247251987e-03 + + 9.7277611494064331e-02 -2.8841799497604370e-01 + <_> + + 0 -1 402 -2.7594310231506824e-03 + + 2.4168670177459717e-01 -1.1277820169925690e-01 + <_> + + 0 -1 403 5.2236132323741913e-03 + + -1.1430279910564423e-01 2.4256780743598938e-01 + <_> + + 0 -1 404 -1.2590440455824137e-03 + + -5.9679388999938965e-01 4.7663960605859756e-02 + <_> + + 0 -1 405 -3.7192099262028933e-03 + + -4.6414130926132202e-01 5.2847690880298615e-02 + <_> + + 0 -1 406 5.9696151874959469e-03 + + -7.3244288563728333e-02 3.8743090629577637e-01 + <_> + + 0 -1 407 -5.1776720210909843e-03 + + -7.4193227291107178e-01 4.0496710687875748e-02 + <_> + + 0 -1 408 5.0035100430250168e-03 + + -1.3888800144195557e-01 1.8767620623111725e-01 + <_> + + 0 -1 409 -5.2013457752764225e-04 + + -5.4940617084503174e-01 4.9417849630117416e-02 + <_> + + 0 -1 410 5.3168768063187599e-03 + + -8.2482978701591492e-02 3.1740561127662659e-01 + <_> + + 0 -1 411 -1.4774589799344540e-02 + + 2.0816099643707275e-01 -1.2115559726953506e-01 + <_> + + 0 -1 412 -4.1416451334953308e-02 + + -8.2437807321548462e-01 3.3329188823699951e-02 + <_> + 53 + -1.0492420196533203e+00 + + <_> + + 0 -1 413 9.0962520334869623e-04 + + 8.4579966962337494e-02 -5.6118410825729370e-01 + <_> + + 0 -1 414 -5.6139789521694183e-02 + + 1.5341749787330627e-01 -2.6967319846153259e-01 + <_> + + 0 -1 415 1.0292009683325887e-03 + + -2.0489980280399323e-01 2.0153179764747620e-01 + <_> + + 0 -1 416 2.8783010784536600e-03 + + -1.7351140081882477e-01 2.1297949552536011e-01 + <_> + + 0 -1 417 -7.4144392274320126e-03 + + -5.9624868631362915e-01 4.7077950090169907e-02 + <_> + + 0 -1 418 -1.4831849839538336e-03 + + 1.9024610519409180e-01 -1.5986390411853790e-01 + <_> + + 0 -1 419 4.5968941412866116e-03 + + 3.1447131186723709e-02 -6.8694341182708740e-01 + <_> + + 0 -1 420 2.4255330208688974e-03 + + -2.3609359562397003e-01 1.1036109924316406e-01 + <_> + + 0 -1 421 -8.4950566291809082e-02 + + 2.3107160627841949e-01 -1.3776530325412750e-01 + <_> + + 0 -1 422 -5.0145681016147137e-03 + + 3.8676109910011292e-01 -5.6217379868030548e-02 + <_> + + 0 -1 423 -2.1482061129063368e-03 + + 1.8191599845886230e-01 -1.7615699768066406e-01 + <_> + + 0 -1 424 -1.0396770201623440e-02 + + -7.5351381301879883e-01 2.4091970175504684e-02 + <_> + + 0 -1 425 -1.3466750271618366e-02 + + -7.2118860483169556e-01 3.4949369728565216e-02 + <_> + + 0 -1 426 -8.4435477852821350e-02 + + -3.3792638778686523e-01 7.1113817393779755e-02 + <_> + + 0 -1 427 2.4771490134298801e-03 + + -1.1765109747648239e-01 2.2541989386081696e-01 + <_> + + 0 -1 428 1.5828050673007965e-02 + + -6.9536216557025909e-02 3.1395369768142700e-01 + <_> + + 0 -1 429 6.4916983246803284e-02 + + -7.5043588876724243e-02 4.0677338838577271e-01 + <_> + + 0 -1 430 2.9652469675056636e-04 + + 7.3953360319137573e-02 -3.4544008970260620e-01 + <_> + + 0 -1 431 1.3129520229995251e-03 + + -1.6909439861774445e-01 1.5258370339870453e-01 + <_> + + 0 -1 432 -5.8032129891216755e-03 + + 3.5260149836540222e-01 -8.3444066345691681e-02 + <_> + + 0 -1 433 -1.4791679382324219e-01 + + 4.3004658818244934e-01 -5.7309929281473160e-02 + <_> + + 0 -1 434 -1.6584150493144989e-02 + + 2.3432689905166626e-01 -1.0907640308141708e-01 + <_> + + 0 -1 435 3.0183270573616028e-03 + + -1.3600939512252808e-01 2.6409289240837097e-01 + <_> + + 0 -1 436 -3.6471918225288391e-02 + + -6.2809741497039795e-01 4.3545108288526535e-02 + <_> + + 0 -1 437 -7.3119226726703346e-05 + + 1.6470630466938019e-01 -1.6463780403137207e-01 + <_> + + 0 -1 438 -3.6719450727105141e-03 + + -4.7421360015869141e-01 4.8586919903755188e-02 + <_> + + 0 -1 439 -4.0151178836822510e-03 + + 1.8222180008888245e-01 -1.4097510278224945e-01 + <_> + + 0 -1 440 1.9948020577430725e-02 + + -6.9787658751010895e-02 3.6707460880279541e-01 + <_> + + 0 -1 441 7.6699437340721488e-04 + + 5.5729299783706665e-02 -4.4585430622100830e-01 + <_> + + 0 -1 442 -1.1806039838120341e-03 + + -4.6876621246337891e-01 4.8902221024036407e-02 + <_> + + 0 -1 443 1.5847349539399147e-02 + + -1.2120209634304047e-01 2.0566530525684357e-01 + <_> + + 0 -1 444 -1.1985700111836195e-03 + + 2.0262099802494049e-01 -1.2823820114135742e-01 + <_> + + 0 -1 445 -1.0964959859848022e-01 + + -8.6619192361831665e-01 3.0351849272847176e-02 + <_> + + 0 -1 446 -9.2532606795430183e-03 + + 2.9343119263648987e-01 -8.5361950099468231e-02 + <_> + + 0 -1 447 1.4686530455946922e-02 + + 3.2798621803522110e-02 -7.7556562423706055e-01 + <_> + + 0 -1 448 -1.3514430029317737e-03 + + 2.4426999688148499e-01 -1.1503250151872635e-01 + <_> + + 0 -1 449 -4.3728090822696686e-03 + + 2.1687670052051544e-01 -1.3984480500221252e-01 + <_> + + 0 -1 450 3.4263390116393566e-03 + + 4.5614220201969147e-02 -5.4567712545394897e-01 + <_> + + 0 -1 451 -3.8404068909585476e-03 + + 1.4949500560760498e-01 -1.5062509477138519e-01 + <_> + + 0 -1 452 3.7988980766385794e-03 + + -8.7301626801490784e-02 2.5481531023979187e-01 + <_> + + 0 -1 453 -2.0094281062483788e-03 + + 1.7259070277214050e-01 -1.4288470149040222e-01 + <_> + + 0 -1 454 -2.4370709434151649e-03 + + 2.6848098635673523e-01 -8.1898219883441925e-02 + <_> + + 0 -1 455 1.0485399980098009e-03 + + 4.6113260090351105e-02 -4.7243279218673706e-01 + <_> + + 0 -1 456 1.7460780218243599e-03 + + -1.1030430346727371e-01 2.0379729568958282e-01 + <_> + + 0 -1 457 5.8608627878129482e-03 + + -1.5619659423828125e-01 1.5927439928054810e-01 + <_> + + 0 -1 458 -2.7724979445338249e-02 + + 1.1349119991064072e-01 -2.1885140240192413e-01 + <_> + + 0 -1 459 4.7080639749765396e-02 + + -4.1688729077577591e-02 5.3630048036575317e-01 + <_> + + 0 -1 460 -7.9283770173788071e-03 + + -5.3595131635665894e-01 4.4237509369850159e-02 + <_> + + 0 -1 461 -1.2880540452897549e-02 + + 2.3237949609756470e-01 -1.0246250033378601e-01 + <_> + + 0 -1 462 2.3604769259691238e-02 + + -8.8291436433792114e-02 3.0561059713363647e-01 + <_> + + 0 -1 463 1.5902200713753700e-02 + + -1.2238109856843948e-01 1.7849120497703552e-01 + <_> + + 0 -1 464 7.9939495772123337e-03 + + -8.3729006350040436e-02 3.2319590449333191e-01 + <_> + + 0 -1 465 5.7100867852568626e-03 + + 3.8479208946228027e-02 -6.8138152360916138e-01 + <_> + 51 + -1.1122100353240967e+00 + + <_> + + 0 -1 466 2.2480720654129982e-03 + + -1.6416870057582855e-01 4.1648530960083008e-01 + <_> + + 0 -1 467 4.5813550241291523e-03 + + -1.2465959787368774e-01 4.0385121107101440e-01 + <_> + + 0 -1 468 -1.6073239967226982e-03 + + 2.6082459092140198e-01 -2.0282520353794098e-01 + <_> + + 0 -1 469 2.5205370038747787e-03 + + -1.0557229816913605e-01 3.6669111251831055e-01 + <_> + + 0 -1 470 2.4119189474731684e-03 + + -1.3877600431442261e-01 2.9959911108016968e-01 + <_> + + 0 -1 471 5.7156179100275040e-03 + + -7.7683463692665100e-02 4.8481920361518860e-01 + <_> + + 0 -1 472 3.1093840952962637e-03 + + -1.1229000240564346e-01 2.9215508699417114e-01 + <_> + + 0 -1 473 -8.6836628615856171e-02 + + -3.6779600381851196e-01 7.2597242891788483e-02 + <_> + + 0 -1 474 5.2652182057499886e-03 + + -1.0890290141105652e-01 3.1791260838508606e-01 + <_> + + 0 -1 475 -1.9913529977202415e-02 + + -5.3373438119888306e-01 7.0585712790489197e-02 + <_> + + 0 -1 476 3.8297839928418398e-03 + + -1.3575910031795502e-01 2.2788879275321960e-01 + <_> + + 0 -1 477 1.0431859642267227e-02 + + 8.8797912001609802e-02 -4.7958970069885254e-01 + <_> + + 0 -1 478 -2.0040439441800117e-02 + + 1.5745539963245392e-01 -1.7771570384502411e-01 + <_> + + 0 -1 479 -5.2967290394008160e-03 + + -6.8434917926788330e-01 3.5671461373567581e-02 + <_> + + 0 -1 480 -2.1624139044433832e-03 + + 2.8318038582801819e-01 -9.8511278629302979e-02 + <_> + + 0 -1 481 -3.5464888787828386e-04 + + -3.7077340483665466e-01 8.0932952463626862e-02 + <_> + + 0 -1 482 -1.8152060511056334e-04 + + -3.2207030057907104e-01 7.7551059424877167e-02 + <_> + + 0 -1 483 -2.7563021285459399e-04 + + -3.2441279292106628e-01 8.7949477136135101e-02 + <_> + + 0 -1 484 6.3823810778558254e-03 + + -8.8924713432788849e-02 3.1727218627929688e-01 + <_> + + 0 -1 485 1.1150909587740898e-02 + + 7.1019843220710754e-02 -4.0494039654731750e-01 + <_> + + 0 -1 486 -1.0593760525807738e-03 + + 2.6050668954849243e-01 -1.1765640228986740e-01 + <_> + + 0 -1 487 2.3906480055302382e-03 + + -8.4388621151447296e-02 3.1230551004409790e-01 + <_> + + 0 -1 488 -1.1000749655067921e-02 + + 1.9152249395847321e-01 -1.5210020542144775e-01 + <_> + + 0 -1 489 -2.4643228971399367e-04 + + -3.1765159964561462e-01 8.6582258343696594e-02 + <_> + + 0 -1 490 2.3053269833326340e-02 + + -1.0089760273694992e-01 2.5769290328025818e-01 + <_> + + 0 -1 491 -2.2135660983622074e-03 + + 4.5689210295677185e-01 -5.2404791116714478e-02 + <_> + + 0 -1 492 -9.7139709396287799e-04 + + -3.5518380999565125e-01 8.0094382166862488e-02 + <_> + + 0 -1 493 1.5676229959353805e-03 + + 1.0091420263051987e-01 -2.1603040397167206e-01 + <_> + + 0 -1 494 7.5460801599547267e-04 + + 5.7896178215742111e-02 -4.0461111068725586e-01 + <_> + + 0 -1 495 -2.0698970183730125e-02 + + 3.1543630361557007e-01 -8.0713048577308655e-02 + <_> + + 0 -1 496 -2.0619940012693405e-02 + + 2.7181661128997803e-01 -7.6358616352081299e-02 + <_> + + 0 -1 497 2.1611129865050316e-02 + + 3.9493449032306671e-02 -5.9429651498794556e-01 + <_> + + 0 -1 498 6.5676742233335972e-03 + + -9.8353669047355652e-02 2.3649279773235321e-01 + <_> + + 0 -1 499 -8.8434796780347824e-03 + + -5.2523428201675415e-01 4.3099921196699142e-02 + <_> + + 0 -1 500 -9.4260741025209427e-03 + + 2.4665130674839020e-01 -9.4130717217922211e-02 + <_> + + 0 -1 501 -1.9830230157822371e-03 + + 2.6743701100349426e-01 -9.0069316327571869e-02 + <_> + + 0 -1 502 -1.7358399927616119e-03 + + 1.5940019488334656e-01 -1.5789410471916199e-01 + <_> + + 0 -1 503 -1.3513869605958462e-02 + + 4.0792331099510193e-01 -6.4223118126392365e-02 + <_> + + 0 -1 504 -1.9394010305404663e-02 + + 1.8015649914741516e-01 -1.3731400668621063e-01 + <_> + + 0 -1 505 -3.2684770412743092e-03 + + 2.9080390930175781e-01 -8.0161906778812408e-02 + <_> + + 0 -1 506 4.1773589327931404e-04 + + -2.1412980556488037e-01 1.1273439973592758e-01 + <_> + + 0 -1 507 -7.6351119205355644e-03 + + -4.5365959405899048e-01 5.4625060409307480e-02 + <_> + + 0 -1 508 -8.3652976900339127e-03 + + 2.6472920179367065e-01 -9.4334110617637634e-02 + <_> + + 0 -1 509 2.7768449857831001e-02 + + -1.0136710107326508e-01 2.0743979513645172e-01 + <_> + + 0 -1 510 -5.4891228675842285e-02 + + 2.8840309381484985e-01 -7.5312040746212006e-02 + <_> + + 0 -1 511 2.5793339591473341e-03 + + -1.1088529974222183e-01 2.1724960207939148e-01 + <_> + + 0 -1 512 6.6196516854688525e-05 + + -1.8872100114822388e-01 1.4440689980983734e-01 + <_> + + 0 -1 513 5.0907251425087452e-03 + + -7.7601231634616852e-02 2.9398378729820251e-01 + <_> + + 0 -1 514 -1.0444259643554688e-01 + + 2.0133109390735626e-01 -1.0903970152139664e-01 + <_> + + 0 -1 515 -6.7273090826347470e-04 + + 1.7945900559425354e-01 -1.2023670226335526e-01 + <_> + + 0 -1 516 3.2412849832326174e-03 + + 4.0688131004571915e-02 -5.4600572586059570e-01 + <_> + 44 + -1.2529590129852295e+00 + + <_> + + 0 -1 517 5.2965320646762848e-03 + + -1.2154529988765717e-01 6.4420372247695923e-01 + <_> + + 0 -1 518 -2.5326260365545750e-03 + + 5.1233220100402832e-01 -1.1108259856700897e-01 + <_> + + 0 -1 519 -2.9183230362832546e-03 + + -5.0615429878234863e-01 1.1501979827880859e-01 + <_> + + 0 -1 520 -2.3692339658737183e-02 + + 3.7167280912399292e-01 -1.4672680199146271e-01 + <_> + + 0 -1 521 2.0177470520138741e-02 + + -1.7388840019702911e-01 4.7759491205215454e-01 + <_> + + 0 -1 522 -2.1723210811614990e-02 + + -4.3880090117454529e-01 1.3576899468898773e-01 + <_> + + 0 -1 523 2.8369780629873276e-03 + + -1.2512069940567017e-01 4.6789029240608215e-01 + <_> + + 0 -1 524 2.7148420922458172e-03 + + -8.8018856942653656e-02 3.6866518855094910e-01 + <_> + + 0 -1 525 3.2625689636915922e-03 + + -8.5335306823253632e-02 5.1644730567932129e-01 + <_> + + 0 -1 526 -3.5618850961327553e-03 + + -4.4503930211067200e-01 9.1738171875476837e-02 + <_> + + 0 -1 527 1.9227749435231090e-03 + + -1.1077310144901276e-01 3.9416998624801636e-01 + <_> + + 0 -1 528 -3.5111969918943942e-04 + + -3.7775701284408569e-01 1.2166170030832291e-01 + <_> + + 0 -1 529 1.9121779769193381e-04 + + 7.4816018342971802e-02 -4.0767100453376770e-01 + <_> + + 0 -1 530 -2.6525629800744355e-04 + + -3.3151718974113464e-01 1.1291120201349258e-01 + <_> + + 0 -1 531 2.0086700096726418e-02 + + -6.1598118394613266e-02 5.6128817796707153e-01 + <_> + + 0 -1 532 3.6783248186111450e-02 + + -6.0251388698816299e-02 5.2192491292953491e-01 + <_> + + 0 -1 533 1.3941619545221329e-03 + + -3.5503050684928894e-01 1.0863020271062851e-01 + <_> + + 0 -1 534 -1.5181669965386391e-02 + + 2.2739650309085846e-01 -1.6252990067005157e-01 + <_> + + 0 -1 535 4.6796840615570545e-03 + + -5.7535041123628616e-02 4.8124238848686218e-01 + <_> + + 0 -1 536 -1.7988319450523704e-04 + + -3.0587670207023621e-01 1.0868159681558609e-01 + <_> + + 0 -1 537 -3.5850999411195517e-03 + + 3.8596940040588379e-01 -9.2194072902202606e-02 + <_> + + 0 -1 538 1.0793360415846109e-03 + + -1.1190389841794968e-01 3.1125208735466003e-01 + <_> + + 0 -1 539 7.3285802500322461e-05 + + -2.0239910483360291e-01 1.5586680173873901e-01 + <_> + + 0 -1 540 1.3678739964962006e-01 + + -2.1672859787940979e-01 1.4420390129089355e-01 + <_> + + 0 -1 541 -1.1729259975254536e-02 + + 4.3503770232200623e-01 -7.4886530637741089e-02 + <_> + + 0 -1 542 3.9230841211974621e-03 + + -5.0289329141378403e-02 5.8831161260604858e-01 + <_> + + 0 -1 543 -2.9819121118634939e-04 + + -3.8232401013374329e-01 9.2451132833957672e-02 + <_> + + 0 -1 544 -4.7992770560085773e-03 + + 4.8488789796829224e-01 -7.3136523365974426e-02 + <_> + + 0 -1 545 -3.0155890271998942e-04 + + -3.5757359862327576e-01 1.0581880062818527e-01 + <_> + + 0 -1 546 1.0390769690275192e-02 + + 5.2920468151569366e-02 -5.7249659299850464e-01 + <_> + + 0 -1 547 -9.4488041941076517e-04 + + 4.4966828823089600e-01 -8.3075523376464844e-02 + <_> + + 0 -1 548 1.2651870492845774e-03 + + -9.6695438027381897e-02 3.1302270293235779e-01 + <_> + + 0 -1 549 1.7094539478421211e-02 + + -8.1248976290225983e-02 3.6113831400871277e-01 + <_> + + 0 -1 550 2.5973359588533640e-03 + + -1.1338350176811218e-01 2.2233949601650238e-01 + <_> + + 0 -1 551 1.4527440071105957e-03 + + 6.9750443100929260e-02 -3.6720710992813110e-01 + <_> + + 0 -1 552 4.7638658434152603e-03 + + -6.5788961946964264e-02 3.8328540325164795e-01 + <_> + + 0 -1 553 -6.2501081265509129e-03 + + -7.0754468441009521e-01 3.8350198417901993e-02 + <_> + + 0 -1 554 -3.1765329185873270e-03 + + 1.3755400478839874e-01 -2.3240029811859131e-01 + <_> + + 0 -1 555 3.2191169448196888e-03 + + -1.2935450673103333e-01 2.2737880051136017e-01 + <_> + + 0 -1 556 -5.6365579366683960e-03 + + 3.8067150115966797e-01 -6.7246839404106140e-02 + <_> + + 0 -1 557 -2.3844049428589642e-04 + + -3.1122380495071411e-01 8.3838358521461487e-02 + <_> + + 0 -1 558 -4.1017560288310051e-03 + + 2.6067280769348145e-01 -1.0449740290641785e-01 + <_> + + 0 -1 559 1.3336989795789123e-03 + + -5.8250140398740768e-02 4.7682440280914307e-01 + <_> + + 0 -1 560 -1.2090239906683564e-03 + + 1.4834509789943695e-01 -1.7329469323158264e-01 + <_> + 72 + -1.1188739538192749e+00 + + <_> + + 0 -1 561 -3.1760931015014648e-03 + + 3.3333331346511841e-01 -1.6642349958419800e-01 + <_> + + 0 -1 562 2.4858079850673676e-02 + + -7.2728872299194336e-02 5.6674581766128540e-01 + <_> + + 0 -1 563 -7.7597280032932758e-03 + + 4.6258568763732910e-01 -9.3112178146839142e-02 + <_> + + 0 -1 564 7.8239021822810173e-03 + + -2.7414610981941223e-01 1.3243049383163452e-01 + <_> + + 0 -1 565 -1.0948839597404003e-02 + + 2.2345480322837830e-01 -1.4965449273586273e-01 + <_> + + 0 -1 566 -3.4349008928984404e-03 + + 3.8724988698959351e-01 -6.6121727228164673e-02 + <_> + + 0 -1 567 -3.1156290322542191e-02 + + 2.4078279733657837e-01 -1.1406909674406052e-01 + <_> + + 0 -1 568 1.1100519914180040e-03 + + -2.8207978606224060e-01 1.3275429606437683e-01 + <_> + + 0 -1 569 3.1762740109115839e-03 + + 3.4585930407047272e-02 -5.1374310255050659e-01 + <_> + + 0 -1 570 -2.7977459132671356e-02 + + 2.3926779627799988e-01 -1.3255919516086578e-01 + <_> + + 0 -1 571 -2.3097939789295197e-02 + + 3.9019620418548584e-01 -7.8478008508682251e-02 + <_> + + 0 -1 572 -3.9731930010020733e-03 + + 3.0691069364547729e-01 -7.0601403713226318e-02 + <_> + + 0 -1 573 3.0335749033838511e-03 + + -1.4002190530300140e-01 1.9134859740734100e-01 + <_> + + 0 -1 574 -1.0844370350241661e-02 + + 1.6548730432987213e-01 -1.5657779574394226e-01 + <_> + + 0 -1 575 -1.8150510266423225e-02 + + -6.3243591785430908e-01 3.9561819285154343e-02 + <_> + + 0 -1 576 7.1052298881113529e-04 + + -1.8515570461750031e-01 1.3408809900283813e-01 + <_> + + 0 -1 577 1.0893340222537518e-02 + + -2.6730230078101158e-02 6.0971802473068237e-01 + <_> + + 0 -1 578 -2.8780900174751878e-04 + + -3.0065140128135681e-01 7.3171459138393402e-02 + <_> + + 0 -1 579 -3.5855069290846586e-03 + + 2.6217609643936157e-01 -7.9714097082614899e-02 + <_> + + 0 -1 580 -1.9759280607104301e-02 + + -5.9039229154586792e-01 4.0698971599340439e-02 + <_> + + 0 -1 581 -1.0845210403203964e-02 + + 1.6364559531211853e-01 -1.2586060166358948e-01 + <_> + + 0 -1 582 -4.3183090165257454e-03 + + -5.7474881410598755e-01 3.7644311785697937e-02 + <_> + + 0 -1 583 1.4913700288161635e-03 + + 6.0913469642400742e-02 -3.0222928524017334e-01 + <_> + + 0 -1 584 1.5675699338316917e-02 + + -7.3145911097526550e-02 2.9379451274871826e-01 + <_> + + 0 -1 585 -1.1033560149371624e-02 + + 3.9318808913230896e-01 -4.7084320336580276e-02 + <_> + + 0 -1 586 8.8555756956338882e-03 + + 3.7601381540298462e-02 -4.9108490347862244e-01 + <_> + + 0 -1 587 -8.9665671112015843e-04 + + 1.7952020466327667e-01 -1.1086239665746689e-01 + <_> + + 0 -1 588 -3.0592409893870354e-03 + + -4.4429460167884827e-01 5.1005430519580841e-02 + <_> + + 0 -1 589 6.3201179727911949e-03 + + -5.2841089665889740e-02 3.7197101116180420e-01 + <_> + + 0 -1 590 2.0682830363512039e-02 + + 5.7667169719934464e-02 -3.6901599168777466e-01 + <_> + + 0 -1 591 9.9822662770748138e-02 + + -3.7377018481492996e-02 5.8165591955184937e-01 + <_> + + 0 -1 592 -6.5854229032993317e-03 + + 2.8509441018104553e-01 -6.0978069901466370e-02 + <_> + + 0 -1 593 -6.0900300741195679e-02 + + -5.1031768321990967e-01 3.7787400186061859e-02 + <_> + + 0 -1 594 -2.9991709161549807e-03 + + -4.7943010926246643e-01 3.8833890110254288e-02 + <_> + + 0 -1 595 -9.8906438797712326e-03 + + 4.0609079599380493e-01 -4.7869648784399033e-02 + <_> + + 0 -1 596 -8.2688927650451660e-02 + + -7.0671182870864868e-01 2.7487749233841896e-02 + <_> + + 0 -1 597 5.0060399807989597e-03 + + 2.8208440169692039e-02 -5.2909690141677856e-01 + <_> + + 0 -1 598 6.1695030890405178e-03 + + -5.4554861038923264e-02 3.2837980985641479e-01 + <_> + + 0 -1 599 -3.3914761152118444e-03 + + 9.2117667198181152e-02 -2.1637110412120819e-01 + <_> + + 0 -1 600 -2.6131230406463146e-03 + + 1.3651019334793091e-01 -1.3781130313873291e-01 + <_> + + 0 -1 601 8.0490659456700087e-04 + + -6.8637110292911530e-02 3.3581069111824036e-01 + <_> + + 0 -1 602 -3.8106508553028107e-02 + + 2.9445430636405945e-01 -6.8239226937294006e-02 + <_> + + 0 -1 603 7.2450799052603543e-05 + + -1.6750130057334900e-01 1.2178230285644531e-01 + <_> + + 0 -1 604 1.5837959945201874e-03 + + -9.2042848467826843e-02 2.1348990499973297e-01 + <_> + + 0 -1 605 1.2924340553581715e-03 + + 6.2917232513427734e-02 -3.6174508929252625e-01 + <_> + + 0 -1 606 9.9146775901317596e-03 + + 1.9534060731530190e-02 -8.1015038490295410e-01 + <_> + + 0 -1 607 -1.7086310544982553e-03 + + 2.5525239109992981e-01 -6.8229459226131439e-02 + <_> + + 0 -1 608 2.1844399161636829e-03 + + 2.3314049467444420e-02 -8.4296780824661255e-01 + <_> + + 0 -1 609 -3.4244330599904060e-03 + + 2.7213689684867859e-01 -7.6395228505134583e-02 + <_> + + 0 -1 610 2.7591470279730856e-04 + + -1.0742840170860291e-01 2.2888970375061035e-01 + <_> + + 0 -1 611 -6.0005177510902286e-04 + + -2.9854211211204529e-01 6.3479736447334290e-02 + <_> + + 0 -1 612 -2.5001438916660845e-04 + + -2.7178969979286194e-01 6.9615006446838379e-02 + <_> + + 0 -1 613 6.8751391954720020e-03 + + -5.7185899466276169e-02 3.6695951223373413e-01 + <_> + + 0 -1 614 1.2761900201439857e-02 + + 6.7955687642097473e-02 -2.8534150123596191e-01 + <_> + + 0 -1 615 -1.4752789866179228e-03 + + 2.0680660009384155e-01 -1.0059390217065811e-01 + <_> + + 0 -1 616 1.2138819694519043e-01 + + -9.7126796841621399e-02 1.9789619743824005e-01 + <_> + + 0 -1 617 -5.0081279128789902e-02 + + 2.8417178988456726e-01 -6.7879997193813324e-02 + <_> + + 0 -1 618 3.1454950571060181e-02 + + -8.9468672871589661e-02 2.1298420429229736e-01 + <_> + + 0 -1 619 1.8878319533541799e-03 + + -1.1656440049409866e-01 1.6663520038127899e-01 + <_> + + 0 -1 620 -5.7211960665881634e-03 + + 2.3702140152454376e-01 -9.0776607394218445e-02 + <_> + + 0 -1 621 -1.8076719425152987e-04 + + 1.7951929569244385e-01 -1.0793480277061462e-01 + <_> + + 0 -1 622 -1.9761849939823151e-01 + + 4.5674291253089905e-01 -4.0480159223079681e-02 + <_> + + 0 -1 623 -2.3846809926908463e-04 + + -2.3733009397983551e-01 7.5922161340713501e-02 + <_> + + 0 -1 624 2.1540730085689574e-04 + + 8.1688016653060913e-02 -2.8685030341148376e-01 + <_> + + 0 -1 625 1.0163090191781521e-02 + + -4.1250020265579224e-02 4.8038348555564880e-01 + <_> + + 0 -1 626 -7.2184870950877666e-03 + + 1.7458580434322357e-01 -1.0146500170230865e-01 + <_> + + 0 -1 627 2.4263170361518860e-01 + + 5.3426481783390045e-02 -3.2318529486656189e-01 + <_> + + 0 -1 628 6.9304101634770632e-04 + + -1.1499179899692535e-01 1.4793939888477325e-01 + <_> + + 0 -1 629 3.5475199110805988e-03 + + -3.9424978196620941e-02 5.3126180171966553e-01 + <_> + + 0 -1 630 2.1403690334409475e-04 + + 6.9753833115100861e-02 -2.7319580316543579e-01 + <_> + + 0 -1 631 -5.7119462871924043e-04 + + 3.4369900822639465e-01 -5.7699009776115417e-02 + <_> + + 0 -1 632 -6.6290069371461868e-03 + + 1.1758489906787872e-01 -1.5020139515399933e-01 + <_> + 66 + -1.0888810157775879e+00 + + <_> + + 0 -1 633 -2.6513449847698212e-02 + + 2.0568640530109406e-01 -2.6473900675773621e-01 + <_> + + 0 -1 634 9.7727458924055099e-03 + + -1.1192840337753296e-01 3.2570549845695496e-01 + <_> + + 0 -1 635 3.2290350645780563e-02 + + -9.8574757575988770e-02 3.1779170036315918e-01 + <_> + + 0 -1 636 -2.8103240765631199e-03 + + 1.5213899314403534e-01 -1.9686409831047058e-01 + <_> + + 0 -1 637 -1.0991429910063744e-02 + + 5.1407659053802490e-01 -4.3707210570573807e-02 + <_> + + 0 -1 638 6.3133831135928631e-03 + + -9.2781022191047668e-02 3.4702470898628235e-01 + <_> + + 0 -1 639 8.7105982005596161e-02 + + 3.0053649097681046e-02 -8.2814818620681763e-01 + <_> + + 0 -1 640 1.1799359926953912e-03 + + -1.2928420305252075e-01 2.0646120607852936e-01 + <_> + + 0 -1 641 -9.3056890182197094e-04 + + -5.0021439790725708e-01 9.3666993081569672e-02 + <_> + + 0 -1 642 -1.3687170110642910e-02 + + -7.9358148574829102e-01 -6.6733639687299728e-03 + <_> + + 0 -1 643 -7.5917452573776245e-02 + + 3.0469641089439392e-01 -7.9655893146991730e-02 + <_> + + 0 -1 644 -2.8559709899127483e-03 + + 2.0961460471153259e-01 -1.2732550501823425e-01 + <_> + + 0 -1 645 -4.0231510065495968e-03 + + -6.5817278623580933e-01 5.0683639943599701e-02 + <_> + + 0 -1 646 1.7558040097355843e-02 + + -8.5382692515850067e-02 3.6174559593200684e-01 + <_> + + 0 -1 647 2.1988239139318466e-02 + + 6.2943696975708008e-02 -7.0896339416503906e-01 + <_> + + 0 -1 648 -2.8599589131772518e-03 + + 1.4683780074119568e-01 -1.6465979814529419e-01 + <_> + + 0 -1 649 -1.0030849836766720e-02 + + 4.9579939246177673e-01 -2.7188340201973915e-02 + <_> + + 0 -1 650 -6.9560329429805279e-03 + + 2.7977779507637024e-01 -7.7953331172466278e-02 + <_> + + 0 -1 651 -3.8356808945536613e-03 + + -5.8163982629776001e-01 3.5739939659833908e-02 + <_> + + 0 -1 652 -3.2647319603711367e-03 + + -4.9945080280303955e-01 4.6986490488052368e-02 + <_> + + 0 -1 653 -7.8412350267171860e-03 + + 3.4532830119132996e-01 -6.8810403347015381e-02 + <_> + + 0 -1 654 -8.1718113506212831e-05 + + 1.5041710436344147e-01 -1.4146679639816284e-01 + <_> + + 0 -1 655 -3.2448628917336464e-03 + + 2.2724510729312897e-01 -9.2860206961631775e-02 + <_> + + 0 -1 656 -7.8561151167377830e-04 + + -4.4319018721580505e-01 5.7812441140413284e-02 + <_> + + 0 -1 657 -6.2474247533828020e-04 + + 1.3952389359474182e-01 -1.4668719470500946e-01 + <_> + + 0 -1 658 -3.2942948746494949e-04 + + -2.9901570081710815e-01 7.6066739857196808e-02 + <_> + + 0 -1 659 1.2605739757418633e-03 + + -1.6125600039958954e-01 1.3953800499439240e-01 + <_> + + 0 -1 660 -5.1667019724845886e-02 + + -5.3142839670181274e-01 4.0719520300626755e-02 + <_> + + 0 -1 661 -1.5285619534552097e-02 + + -7.8206378221511841e-01 2.7183769270777702e-02 + <_> + + 0 -1 662 6.9029822945594788e-02 + + -3.6427021026611328e-02 7.1102517843246460e-01 + <_> + + 0 -1 663 1.4522749697789550e-03 + + -9.6890516579151154e-02 2.1668420732021332e-01 + <_> + + 0 -1 664 -2.4765590205788612e-03 + + 1.1645310372114182e-01 -1.8227979540824890e-01 + <_> + + 0 -1 665 -1.5134819550439715e-03 + + 1.7863979935646057e-01 -1.2214969843626022e-01 + <_> + + 0 -1 666 -1.5099470037966967e-03 + + 1.8086239695549011e-01 -1.1446069926023483e-01 + <_> + + 0 -1 667 -6.7054620012640953e-03 + + 2.5106599926948547e-01 -9.1871462762355804e-02 + <_> + + 0 -1 668 -1.4075200073421001e-02 + + 1.3707509636878967e-01 -1.7333500087261200e-01 + <_> + + 0 -1 669 -2.2400720044970512e-03 + + 4.0092980861663818e-01 -4.7576878219842911e-02 + <_> + + 0 -1 670 1.9782369956374168e-02 + + -1.9040350615978241e-01 1.4923410117626190e-01 + <_> + + 0 -1 671 2.6002870872616768e-03 + + 4.6971768140792847e-02 -4.3307659029960632e-01 + <_> + + 0 -1 672 -5.3445628145709634e-04 + + -4.3744230270385742e-01 4.1520189493894577e-02 + <_> + + 0 -1 673 -1.7466509714722633e-02 + + 6.5818172693252563e-01 -3.4447491168975830e-02 + <_> + + 0 -1 674 -2.0425589755177498e-03 + + 3.9657929539680481e-01 -4.4052429497241974e-02 + <_> + + 0 -1 675 2.6661779265850782e-03 + + 5.8770958334207535e-02 -3.2806369662284851e-01 + <_> + + 0 -1 676 -5.5982369929552078e-02 + + -5.1735472679138184e-01 3.5791840404272079e-02 + <_> + + 0 -1 677 -1.5066330088302493e-03 + + 1.5123869478702545e-01 -1.2520180642604828e-01 + <_> + + 0 -1 678 -1.1472369544208050e-02 + + -6.2930530309677124e-01 3.4704331308603287e-02 + <_> + + 0 -1 679 2.3409629240632057e-02 + + -5.8063350617885590e-02 3.8668221235275269e-01 + <_> + + 0 -1 680 -2.3243729956448078e-03 + + 1.8754099309444427e-01 -9.8394669592380524e-02 + <_> + + 0 -1 681 -2.9039299115538597e-02 + + -5.4486900568008423e-01 4.0926340967416763e-02 + <_> + + 0 -1 682 -1.4474649913609028e-02 + + -6.7248392105102539e-01 2.3128850385546684e-02 + <_> + + 0 -1 683 -5.2086091600358486e-03 + + -4.3271440267562866e-01 4.3780650943517685e-02 + <_> + + 0 -1 684 4.9382899887859821e-03 + + -1.0878620296716690e-01 1.9342589378356934e-01 + <_> + + 0 -1 685 -4.3193930760025978e-03 + + 2.4080930650234222e-01 -1.0380800068378448e-01 + <_> + + 0 -1 686 2.3705669445917010e-04 + + -8.7349072098731995e-02 2.0466239750385284e-01 + <_> + + 0 -1 687 4.7858079778961837e-04 + + 4.5624580234289169e-02 -3.8854670524597168e-01 + <_> + + 0 -1 688 -8.5342838428914547e-04 + + -5.5077940225601196e-01 3.5825889557600021e-02 + <_> + + 0 -1 689 5.4772121075075120e-05 + + -1.1225239932537079e-01 1.7503519356250763e-01 + <_> + + 0 -1 690 -3.8445889949798584e-03 + + 2.4526700377464294e-01 -8.1132568418979645e-02 + <_> + + 0 -1 691 -4.0128458291292191e-02 + + -6.3122707605361938e-01 2.6972670108079910e-02 + <_> + + 0 -1 692 -1.7886360001284629e-04 + + 1.9855099916458130e-01 -1.0333680361509323e-01 + <_> + + 0 -1 693 1.7668239888735116e-04 + + -9.1359011828899384e-02 1.9848720729351044e-01 + <_> + + 0 -1 694 7.2763383388519287e-02 + + 5.0075579434633255e-02 -3.3852630853652954e-01 + <_> + + 0 -1 695 1.0181630030274391e-02 + + -9.3229979276657104e-02 2.0059590041637421e-01 + <_> + + 0 -1 696 2.4409969337284565e-03 + + 6.4636632800102234e-02 -2.6921740174293518e-01 + <_> + + 0 -1 697 -3.6227488890290260e-03 + + 1.3169890642166138e-01 -1.2514840066432953e-01 + <_> + + 0 -1 698 -1.3635610230267048e-03 + + 1.6350460052490234e-01 -1.0665939748287201e-01 + <_> + 69 + -1.0408929586410522e+00 + + <_> + + 0 -1 699 -9.6991164609789848e-03 + + 6.1125320196151733e-01 -6.6225312650203705e-02 + <_> + + 0 -1 700 -9.6426531672477722e-03 + + -1. 2.7699959464371204e-03 + <_> + + 0 -1 701 -9.6381865441799164e-03 + + 1. -2.9904270195402205e-04 + <_> + + 0 -1 702 -4.2553939856588840e-03 + + 2.8464388847351074e-01 -1.5540120005607605e-01 + <_> + + 0 -1 703 -9.6223521977663040e-03 + + -1. 4.3999180197715759e-02 + <_> + + 0 -1 704 -9.1231241822242737e-03 + + 8.6869341135025024e-01 -2.7267890982329845e-03 + <_> + + 0 -1 705 -8.6240433156490326e-03 + + 4.5352488756179810e-01 -8.6071379482746124e-02 + <_> + + 0 -1 706 -8.9324144646525383e-03 + + 1.3375559449195862e-01 -2.6012519001960754e-01 + <_> + + 0 -1 707 -1.4207810163497925e-02 + + 3.2077640295028687e-01 -9.7226411104202271e-02 + <_> + + 0 -1 708 2.5911010801792145e-02 + + -1.2964080274105072e-01 2.6218649744987488e-01 + <_> + + 0 -1 709 2.0531509653665125e-04 + + -1.2404280155897141e-01 2.1062959730625153e-01 + <_> + + 0 -1 710 -5.4795680625829846e-05 + + 1.1974299699068069e-01 -2.3201279342174530e-01 + <_> + + 0 -1 711 6.8555199541151524e-03 + + -6.3276126980781555e-02 4.1044250130653381e-01 + <_> + + 0 -1 712 -1.2253040447831154e-02 + + 5.4883331060409546e-01 -3.9731100201606750e-02 + <_> + + 0 -1 713 -3.9058770053088665e-03 + + 2.4190980195999146e-01 -9.7096011042594910e-02 + <_> + + 0 -1 714 2.7560980524867773e-03 + + -1.2569679319858551e-01 1.9456650316715240e-01 + <_> + + 0 -1 715 -7.7662160620093346e-03 + + 2.9765701293945312e-01 -9.6818156540393829e-02 + <_> + + 0 -1 716 3.8997188676148653e-04 + + 6.2188401818275452e-02 -4.2040899395942688e-01 + <_> + + 0 -1 717 3.3579880837351084e-03 + + 4.7498140484094620e-02 -6.3216882944107056e-01 + <_> + + 0 -1 718 -1.6745539382100105e-02 + + 7.1098130941390991e-01 -3.9157349616289139e-02 + <_> + + 0 -1 719 -6.5409899689257145e-03 + + -3.5043171048164368e-01 7.0616953074932098e-02 + <_> + + 0 -1 720 3.0016340315341949e-04 + + 9.1902457177639008e-02 -2.4618670344352722e-01 + <_> + + 0 -1 721 1.4918990433216095e-02 + + -5.1909450441598892e-02 5.6636041402816772e-01 + <_> + + 0 -1 722 4.8153079114854336e-04 + + 6.4659558236598969e-02 -3.6590608954429626e-01 + <_> + + 0 -1 723 -3.0211321427486837e-04 + + 1.7926569283008575e-01 -1.1410660296678543e-01 + <_> + + 0 -1 724 3.8521419628523290e-04 + + 1.0345619916915894e-01 -2.0072460174560547e-01 + <_> + + 0 -1 725 8.0837132409214973e-03 + + -6.6073462367057800e-02 3.0284249782562256e-01 + <_> + + 0 -1 726 -2.2804969921708107e-02 + + 5.2962350845336914e-01 -4.0118999779224396e-02 + <_> + + 0 -1 727 1.9440450705587864e-04 + + 8.1854820251464844e-02 -2.4663360416889191e-01 + <_> + + 0 -1 728 -1.2848090380430222e-02 + + -3.4973311424255371e-01 5.6916229426860809e-02 + <_> + + 0 -1 729 -1.0937290498986840e-03 + + 2.3368680477142334e-01 -9.1604806482791901e-02 + <_> + + 0 -1 730 1.0032650316134095e-03 + + 1.1852180212736130e-01 -1.8469190597534180e-01 + <_> + + 0 -1 731 -4.4688429683446884e-02 + + -6.4362460374832153e-01 3.0363269150257111e-02 + <_> + + 0 -1 732 8.1657543778419495e-03 + + 4.3674658983945847e-02 -4.3002089858055115e-01 + <_> + + 0 -1 733 -1.1717810295522213e-02 + + 4.1781479120254517e-01 -4.8233699053525925e-02 + <_> + + 0 -1 734 8.4277130663394928e-02 + + 5.3461279720067978e-02 -3.7952190637588501e-01 + <_> + + 0 -1 735 1.4211839996278286e-02 + + 4.4900938868522644e-02 -4.2981499433517456e-01 + <_> + + 0 -1 736 1.5028340276330709e-03 + + 8.2227639853954315e-02 -2.4706399440765381e-01 + <_> + + 0 -1 737 1.0003579780459404e-02 + + -5.7221669703722000e-02 3.4609371423721313e-01 + <_> + + 0 -1 738 -9.0706320479512215e-03 + + 4.5058089494705200e-01 -4.2795319110155106e-02 + <_> + + 0 -1 739 -3.3141620224341750e-04 + + 1.8336910009384155e-01 -1.0759949684143066e-01 + <_> + + 0 -1 740 1.9723279774188995e-01 + + -3.0363829806447029e-02 6.6423428058624268e-01 + <_> + + 0 -1 741 -7.1258801035583019e-03 + + -8.9225047826766968e-01 2.5669990107417107e-02 + <_> + + 0 -1 742 8.6921341717243195e-03 + + -7.0764370262622833e-02 2.8210529685020447e-01 + <_> + + 0 -1 743 8.9262127876281738e-03 + + 7.1078233420848846e-02 -3.0232560634613037e-01 + <_> + + 0 -1 744 5.7286009192466736e-02 + + 5.0974130630493164e-02 -3.9196950197219849e-01 + <_> + + 0 -1 745 3.7920880131423473e-03 + + 3.3841941505670547e-02 -5.1016288995742798e-01 + <_> + + 0 -1 746 -1.4508679741993546e-03 + + 3.0879148840904236e-01 -6.3845083117485046e-02 + <_> + + 0 -1 747 9.8390132188796997e-04 + + -1.3029569387435913e-01 1.4604410529136658e-01 + <_> + + 0 -1 748 -1.7221809830516577e-03 + + 2.9157009720802307e-01 -6.8549558520317078e-02 + <_> + + 0 -1 749 1.0948250070214272e-02 + + 3.4351408481597900e-02 -4.7702258825302124e-01 + <_> + + 0 -1 750 -1.7176309484057128e-05 + + 1.6055269539356232e-01 -1.1690840125083923e-01 + <_> + + 0 -1 751 -5.4884208366274834e-03 + + -4.3415889143943787e-01 4.6106241643428802e-02 + <_> + + 0 -1 752 -3.0975250992923975e-03 + + 3.7943339347839355e-01 -5.6860551238059998e-02 + <_> + + 0 -1 753 6.4182081259787083e-03 + + -1.5858210623264313e-01 1.2335419654846191e-01 + <_> + + 0 -1 754 1.1831239797174931e-02 + + -4.0929291397333145e-02 4.5878958702087402e-01 + <_> + + 0 -1 755 1.3540499843657017e-02 + + -5.3725559264421463e-02 3.5056120157241821e-01 + <_> + + 0 -1 756 -2.5932150892913342e-03 + + 1.1010520160198212e-01 -1.6752210259437561e-01 + <_> + + 0 -1 757 1.6856270376592875e-03 + + 6.6574357450008392e-02 -3.0835020542144775e-01 + <_> + + 0 -1 758 2.6524690911173820e-03 + + 6.6318482160568237e-02 -2.7861338853836060e-01 + <_> + + 0 -1 759 -7.7341729775071144e-03 + + 1.9718359410762787e-01 -1.0782919824123383e-01 + <_> + + 0 -1 760 5.0944271497428417e-03 + + 8.5337489843368530e-02 -2.4847009778022766e-01 + <_> + + 0 -1 761 -2.9162371065467596e-03 + + -4.7476351261138916e-01 3.3566489815711975e-02 + <_> + + 0 -1 762 3.0121419113129377e-03 + + -4.7575380653142929e-02 4.2586800456047058e-01 + <_> + + 0 -1 763 3.1694869976490736e-03 + + -1.0519450157880783e-01 1.7163459956645966e-01 + <_> + + 0 -1 764 2.2327560186386108e-01 + + -1.4370209537446499e-02 9.2483651638031006e-01 + <_> + + 0 -1 765 -9.5585048198699951e-02 + + -7.4206638336181641e-01 2.7818970382213593e-02 + <_> + + 0 -1 766 3.4773729566950351e-05 + + -1.2765780091285706e-01 1.2926669418811798e-01 + <_> + + 0 -1 767 7.2459770308341831e-05 + + -1.6518579423427582e-01 1.0036809742450714e-01 + <_> + 59 + -1.0566600561141968e+00 + + <_> + + 0 -1 768 -6.5778270363807678e-03 + + 3.3815258741378784e-01 -1.5281909704208374e-01 + <_> + + 0 -1 769 -1.0922809597104788e-03 + + 2.2282369434833527e-01 -1.9308499991893768e-01 + <_> + + 0 -1 770 -2.9759589582681656e-02 + + 2.5959870219230652e-01 -1.5409409999847412e-01 + <_> + + 0 -1 771 -1.3147540390491486e-02 + + 1.9033810496330261e-01 -1.6543999314308167e-01 + <_> + + 0 -1 772 -1.4396329643204808e-03 + + 2.0071710646152496e-01 -1.2338940054178238e-01 + <_> + + 0 -1 773 -3.5928250290453434e-03 + + 2.3985520005226135e-01 -1.2922149896621704e-01 + <_> + + 0 -1 774 -1.5314699849113822e-03 + + -4.9014899134635925e-01 1.0275030136108398e-01 + <_> + + 0 -1 775 -6.2372139655053616e-03 + + 3.1214639544487000e-01 -1.1405629664659500e-01 + <_> + + 0 -1 776 -3.3364649862051010e-02 + + -4.9520879983901978e-01 5.1328450441360474e-02 + <_> + + 0 -1 777 -2.2827699780464172e-02 + + 3.2558828592300415e-01 -6.5089307725429535e-02 + <_> + + 0 -1 778 -8.6199097335338593e-02 + + -6.7646330595016479e-01 2.6985699310898781e-02 + <_> + + 0 -1 779 -2.1065981127321720e-03 + + 2.2452430427074432e-01 -1.2610229849815369e-01 + <_> + + 0 -1 780 3.9120148867368698e-02 + + 1.1329399794340134e-01 -2.6860630512237549e-01 + <_> + + 0 -1 781 3.5082739777863026e-03 + + -1.1359959840774536e-01 2.5649771094322205e-01 + <_> + + 0 -1 782 5.9289898490533233e-04 + + -1.4942969381809235e-01 1.6409839689731598e-01 + <_> + + 0 -1 783 7.1766850305721164e-04 + + 9.9905692040920258e-02 -2.1967969834804535e-01 + <_> + + 0 -1 784 -2.1803600713610649e-02 + + -3.1711721420288086e-01 8.2889586687088013e-02 + <_> + + 0 -1 785 -3.2962779514491558e-03 + + -3.8048729300498962e-01 6.0819379985332489e-02 + <_> + + 0 -1 786 2.4196270387619734e-03 + + -9.6013016998767853e-02 2.8540581464767456e-01 + <_> + + 0 -1 787 -4.4187481398694217e-04 + + 2.2127939760684967e-01 -9.7434908151626587e-02 + <_> + + 0 -1 788 3.4523929934948683e-03 + + 3.7553120404481888e-02 -5.7969051599502563e-01 + <_> + + 0 -1 789 -2.1834600716829300e-02 + + 2.9562139511108398e-01 -8.0048300325870514e-02 + <_> + + 0 -1 790 -2.1309500152710825e-04 + + 2.2814509272575378e-01 -1.0114189982414246e-01 + <_> + + 0 -1 791 -1.6166249988600612e-03 + + -5.0541198253631592e-01 4.4764541089534760e-02 + <_> + + 0 -1 792 7.5959609821438789e-03 + + 4.5986540615558624e-02 -4.1197681427001953e-01 + <_> + + 0 -1 793 3.8601809646934271e-03 + + -8.6563169956207275e-02 2.4809999763965607e-01 + <_> + + 0 -1 794 6.0622231103479862e-03 + + -7.5557373464107513e-02 2.8433260321617126e-01 + <_> + + 0 -1 795 -1.7097420059144497e-03 + + -3.5295820236206055e-01 5.8410499244928360e-02 + <_> + + 0 -1 796 1.6515579074621201e-02 + + -8.0486953258514404e-02 2.3537430167198181e-01 + <_> + + 0 -1 797 4.8465100117027760e-03 + + 4.1895218193531036e-02 -4.8443049192428589e-01 + <_> + + 0 -1 798 -3.1167170032858849e-02 + + 1.9192309677600861e-01 -1.0268159955739975e-01 + <_> + + 0 -1 799 6.1892281519249082e-04 + + -2.1085770428180695e-01 9.3886926770210266e-02 + <_> + + 0 -1 800 1.1946310289204121e-02 + + 3.9096169173717499e-02 -6.2248629331588745e-01 + <_> + + 0 -1 801 -7.5677200220525265e-03 + + 1.5936839580535889e-01 -1.2250780314207077e-01 + <_> + + 0 -1 802 -5.3747411817312241e-02 + + -5.5622178316116333e-01 4.1190009564161301e-02 + <_> + + 0 -1 803 1.5513530001044273e-02 + + -3.9826881140470505e-02 6.2400728464126587e-01 + <_> + + 0 -1 804 1.5246650436893106e-03 + + 7.0138677954673767e-02 -3.0789071321487427e-01 + <_> + + 0 -1 805 -4.8315100139006972e-04 + + 1.7887659370899200e-01 -1.0958620160818100e-01 + <_> + + 0 -1 806 2.7374739293009043e-03 + + 2.7478590607643127e-02 -8.8489568233489990e-01 + <_> + + 0 -1 807 -6.5787717700004578e-02 + + -4.6432140469551086e-01 3.5037148743867874e-02 + <_> + + 0 -1 808 1.2409730115905404e-03 + + -9.6479237079620361e-02 2.8779220581054688e-01 + <_> + + 0 -1 809 8.1398809561505914e-04 + + 1.1511719971895218e-01 -1.6766160726547241e-01 + <_> + + 0 -1 810 2.3901820182800293e-02 + + -3.2603189349174500e-02 6.0017347335815430e-01 + <_> + + 0 -1 811 2.7556600049138069e-02 + + -6.6137343645095825e-02 2.9994478821754456e-01 + <_> + + 0 -1 812 -3.8070970913395286e-04 + + -3.3881181478500366e-01 6.4450770616531372e-02 + <_> + + 0 -1 813 -1.3335429830476642e-03 + + 1.4588660001754761e-01 -1.3217620551586151e-01 + <_> + + 0 -1 814 -9.3507990241050720e-03 + + -5.1177829504013062e-01 3.4969471395015717e-02 + <_> + + 0 -1 815 7.6215229928493500e-03 + + 2.3249529302120209e-02 -6.9619411230087280e-01 + <_> + + 0 -1 816 -5.3407860832521692e-05 + + 2.3727379739284515e-01 -8.6910709738731384e-02 + <_> + + 0 -1 817 -1.5332329785451293e-03 + + 1.9228410720825195e-01 -1.0422399640083313e-01 + <_> + + 0 -1 818 4.3135890737175941e-03 + + -9.6219547092914581e-02 2.5601211190223694e-01 + <_> + + 0 -1 819 -2.3042880638968199e-04 + + -3.1564751267433167e-01 5.8838598430156708e-02 + <_> + + 0 -1 820 -7.8411828726530075e-03 + + -6.6340929269790649e-01 2.4500999599695206e-02 + <_> + + 0 -1 821 1.7103740572929382e-01 + + 3.3831499516963959e-02 -4.5615941286087036e-01 + <_> + + 0 -1 822 -1.6011140542104840e-03 + + 2.1574890613555908e-01 -8.3622530102729797e-02 + <_> + + 0 -1 823 -1.0535780340433121e-02 + + 2.4552319943904877e-01 -8.2384489476680756e-02 + <_> + + 0 -1 824 -5.8351638726890087e-03 + + -4.7807329893112183e-01 4.4086221605539322e-02 + <_> + + 0 -1 825 -1.8706109374761581e-02 + + -6.0024029016494751e-01 2.1410040557384491e-02 + <_> + + 0 -1 826 -9.3307439237833023e-04 + + 2.4323590099811554e-01 -7.4165716767311096e-02 + <_> + 88 + -9.7693431377410889e-01 + + <_> + + 0 -1 827 1.0646229609847069e-02 + + -1.3861389458179474e-01 2.6494070887565613e-01 + <_> + + 0 -1 828 3.5298269242048264e-02 + + -7.5821727514266968e-02 3.9021068811416626e-01 + <_> + + 0 -1 829 7.5638387352228165e-04 + + -9.5521442592144012e-02 2.9061999917030334e-01 + <_> + + 0 -1 830 9.2497706413269043e-02 + + -2.7704238891601562e-01 7.9474702477455139e-02 + <_> + + 0 -1 831 -2.9340879991650581e-03 + + 2.2989539802074432e-01 -7.8550010919570923e-02 + <_> + + 0 -1 832 -8.6535848677158356e-02 + + 4.7744810581207275e-01 -6.8231220357120037e-03 + <_> + + 0 -1 833 5.4699288739357144e-05 + + -2.2642609477043152e-01 8.8192112743854523e-02 + <_> + + 0 -1 834 -3.6592520773410797e-02 + + 2.7353870868682861e-01 -9.8606742918491364e-02 + <_> + + 0 -1 835 2.6469118893146515e-03 + + -4.4083978980779648e-02 3.1445288658142090e-01 + <_> + + 0 -1 836 -4.4271810911595821e-03 + + 2.3822729289531708e-01 -8.6784273386001587e-02 + <_> + + 0 -1 837 -5.1882481202483177e-03 + + 1.5042769908905029e-01 -1.2672109901905060e-01 + <_> + + 0 -1 838 4.5530400238931179e-03 + + -5.5945020169019699e-02 3.6501631140708923e-01 + <_> + + 0 -1 839 1.4562410302460194e-02 + + 3.6397770047187805e-02 -5.3559190034866333e-01 + <_> + + 0 -1 840 6.8677567469421774e-05 + + -1.7479629814624786e-01 1.1068709939718246e-01 + <_> + + 0 -1 841 -5.9744901955127716e-03 + + 3.1077870726585388e-01 -6.6530227661132812e-02 + <_> + + 0 -1 842 -5.8691250160336494e-03 + + -3.1901490688323975e-01 6.3931830227375031e-02 + <_> + + 0 -1 843 -1.1140310205519199e-02 + + 2.4364790320396423e-01 -8.0935180187225342e-02 + <_> + + 0 -1 844 -5.8643531054258347e-02 + + -7.6083260774612427e-01 3.0809629708528519e-02 + <_> + + 0 -1 845 -4.6097282320261002e-03 + + -4.5315021276473999e-01 2.9879059642553329e-02 + <_> + + 0 -1 846 -9.3032103031873703e-03 + + 1.4513379335403442e-01 -1.1033169925212860e-01 + <_> + + 0 -1 847 1.3253629440441728e-03 + + -9.7698956727981567e-02 1.9646440446376801e-01 + <_> + + 0 -1 848 4.9800761044025421e-03 + + 3.3648081123828888e-02 -3.9792209863662720e-01 + <_> + + 0 -1 849 -7.6542161405086517e-03 + + 9.0841993689537048e-02 -1.5967549383640289e-01 + <_> + + 0 -1 850 -3.8920590281486511e-01 + + -6.6571092605590820e-01 1.9028829410672188e-02 + <_> + + 0 -1 851 -1.0019669681787491e-01 + + -5.7559269666671753e-01 2.4282779544591904e-02 + <_> + + 0 -1 852 7.3541211895644665e-04 + + 8.7919801473617554e-02 -1.6195340454578400e-01 + <_> + + 0 -1 853 -3.4802639856934547e-03 + + 2.6064491271972656e-01 -6.0200810432434082e-02 + <_> + + 0 -1 854 8.4000425413250923e-03 + + -1.0979729890823364e-01 1.5707309544086456e-01 + <_> + + 0 -1 855 2.3786011151969433e-03 + + 3.6058239638805389e-02 -4.7277191281318665e-01 + <_> + + 0 -1 856 7.3831682093441486e-03 + + -3.5756360739469528e-02 4.9498590826988220e-01 + <_> + + 0 -1 857 3.2115620560944080e-03 + + -1.0125560313463211e-01 1.5747989714145660e-01 + <_> + + 0 -1 858 -7.8209668397903442e-02 + + -7.6627081632614136e-01 2.2965829819440842e-02 + <_> + + 0 -1 859 5.3303989261621609e-05 + + -1.3414350152015686e-01 1.1114919930696487e-01 + <_> + + 0 -1 860 -9.6419155597686768e-03 + + 2.5068029761314392e-01 -6.6608138382434845e-02 + <_> + + 0 -1 861 -7.1092672646045685e-02 + + -4.0056818723678589e-01 4.0297791361808777e-02 + <_> + + 0 -1 862 3.5171560011804104e-04 + + 4.1861180216073990e-02 -3.2961198687553406e-01 + <_> + + 0 -1 863 -3.3458150574006140e-04 + + -2.6029831171035767e-01 6.7892737686634064e-02 + <_> + + 0 -1 864 -4.1451421566307545e-03 + + 2.3967699706554413e-01 -7.2093337774276733e-02 + <_> + + 0 -1 865 3.1754500232636929e-03 + + -7.1235269308090210e-02 2.4128450453281403e-01 + <_> + + 0 -1 866 -5.5184490047395229e-03 + + 5.0320237874984741e-01 -2.9686680063605309e-02 + <_> + + 0 -1 867 -3.0242869979701936e-04 + + 2.4879050254821777e-01 -5.6758578866720200e-02 + <_> + + 0 -1 868 -1.3125919504091144e-03 + + 3.1747800111770630e-01 -4.1845861822366714e-02 + <_> + + 0 -1 869 -2.7123570907860994e-04 + + -2.7042070031166077e-01 5.6828990578651428e-02 + <_> + + 0 -1 870 -7.3241777718067169e-03 + + 2.7556678652763367e-01 -5.4252970963716507e-02 + <_> + + 0 -1 871 -1.6851710155606270e-02 + + -3.4852910041809082e-01 4.5368999242782593e-02 + <_> + + 0 -1 872 2.9902100563049316e-02 + + 3.1621079891920090e-02 -4.3114370107650757e-01 + <_> + + 0 -1 873 2.8902660124003887e-03 + + 3.8029961287975311e-02 -3.7027099728584290e-01 + <_> + + 0 -1 874 -1.9242949783802032e-03 + + 2.4800279736518860e-01 -5.9333298355340958e-02 + <_> + + 0 -1 875 4.9354149959981441e-03 + + -8.3068400621414185e-02 2.2043809294700623e-01 + <_> + + 0 -1 876 8.2075603306293488e-02 + + -1.9413439556956291e-02 6.9089287519454956e-01 + <_> + + 0 -1 877 -2.4699489586055279e-04 + + -2.4660569429397583e-01 6.4776450395584106e-02 + <_> + + 0 -1 878 -1.8365769647061825e-03 + + 2.8836160898208618e-01 -5.3390458226203918e-02 + <_> + + 0 -1 879 -4.9553811550140381e-03 + + 1.2740829586982727e-01 -1.2559419870376587e-01 + <_> + + 0 -1 880 -8.3086621016263962e-03 + + 2.3478110134601593e-01 -7.1676492691040039e-02 + <_> + + 0 -1 881 -1.0879919677972794e-01 + + -2.5992238521575928e-01 5.8689739555120468e-02 + <_> + + 0 -1 882 -9.6786450594663620e-03 + + -7.0720428228378296e-01 1.8749259412288666e-02 + <_> + + 0 -1 883 -2.7136830613017082e-02 + + -5.8384227752685547e-01 2.1684130653738976e-02 + <_> + + 0 -1 884 -6.5389778465032578e-03 + + -5.9748911857604980e-01 2.1480310708284378e-02 + <_> + + 0 -1 885 -1.2095630168914795e-02 + + 1.3269039988517761e-01 -9.9722720682621002e-02 + <_> + + 0 -1 886 -1.6776099801063538e-01 + + -5.6655067205429077e-01 3.2123088836669922e-02 + <_> + + 0 -1 887 -1.3262550346553326e-02 + + 1.1495590209960938e-01 -1.1738389730453491e-01 + <_> + + 0 -1 888 7.6744519174098969e-02 + + -3.1413231045007706e-02 5.9935492277145386e-01 + <_> + + 0 -1 889 5.0785229541361332e-03 + + -5.2911940962076187e-02 2.3342399299144745e-01 + <_> + + 0 -1 890 3.1800279393792152e-03 + + -7.7734388411045074e-02 1.7652909457683563e-01 + <_> + + 0 -1 891 -1.7729829996824265e-03 + + 1.9591629505157471e-01 -7.9752199351787567e-02 + <_> + + 0 -1 892 -4.8560940194875002e-04 + + -2.8800371289253235e-01 4.9047119915485382e-02 + <_> + + 0 -1 893 3.6554320831783116e-04 + + 6.7922897636890411e-02 -2.2499430179595947e-01 + <_> + + 0 -1 894 -2.6938671362586319e-04 + + 1.6582170128822327e-01 -8.9744098484516144e-02 + <_> + + 0 -1 895 7.8684233129024506e-02 + + 2.6081679388880730e-02 -5.5693739652633667e-01 + <_> + + 0 -1 896 -7.3774810880422592e-04 + + 1.4036870002746582e-01 -1.1800300329923630e-01 + <_> + + 0 -1 897 2.3957829922437668e-02 + + 3.0470740050077438e-02 -4.6159979701042175e-01 + <_> + + 0 -1 898 -1.6239080578088760e-03 + + 2.6327079534530640e-01 -5.6765370070934296e-02 + <_> + + 0 -1 899 -9.0819748584181070e-04 + + 1.5462459623813629e-01 -1.1087069660425186e-01 + <_> + + 0 -1 900 3.9806248969398439e-04 + + 5.5630370974540710e-02 -2.8331959247589111e-01 + <_> + + 0 -1 901 2.0506449509412050e-03 + + -9.1604836285114288e-02 1.7585539817810059e-01 + <_> + + 0 -1 902 2.6742549613118172e-02 + + 6.2003031373023987e-02 -2.4487000703811646e-01 + <_> + + 0 -1 903 -2.1497008856385946e-03 + + 2.9449298977851868e-01 -5.3218148648738861e-02 + <_> + + 0 -1 904 5.6671658530831337e-03 + + -6.4298242330551147e-02 2.4905680119991302e-01 + <_> + + 0 -1 905 6.8317902332637459e-05 + + -1.6819630563259125e-01 9.6548579633235931e-02 + <_> + + 0 -1 906 1.7600439605303109e-04 + + 6.5308012068271637e-02 -2.4267880618572235e-01 + <_> + + 0 -1 907 4.1861608624458313e-03 + + -9.7988583147525787e-02 1.8052889406681061e-01 + <_> + + 0 -1 908 -2.1808340679854155e-03 + + 1.9231270253658295e-01 -9.4123929738998413e-02 + <_> + + 0 -1 909 2.1730400621891022e-02 + + 3.5578511655330658e-02 -4.5088538527488708e-01 + <_> + + 0 -1 910 -1.4780269935727119e-02 + + -4.3927010893821716e-01 3.1735591590404510e-02 + <_> + + 0 -1 911 -3.6145891062915325e-03 + + 1.9811479747295380e-01 -7.7701419591903687e-02 + <_> + + 0 -1 912 1.8892709631472826e-03 + + 1.9962439313530922e-02 -7.2041720151901245e-01 + <_> + + 0 -1 913 -1.3822480104863644e-03 + + 9.8466947674751282e-02 -1.4881080389022827e-01 + <_> + + 0 -1 914 -3.9505911991000175e-03 + + 1.1593230068683624e-01 -1.2791970372200012e-01 + <_> + 58 + -1.0129359960556030e+00 + + <_> + + 0 -1 915 -1.9395539537072182e-02 + + 4.7474750876426697e-01 -1.1721090227365494e-01 + <_> + + 0 -1 916 1.3118919916450977e-02 + + -2.5552129745483398e-01 1.6378800570964813e-01 + <_> + + 0 -1 917 -5.1606801571324468e-04 + + 1.9452619552612305e-01 -1.7448890209197998e-01 + <_> + + 0 -1 918 -1.3184159994125366e-02 + + 4.4181451201438904e-01 -9.0048752725124359e-02 + <_> + + 0 -1 919 3.4657081123441458e-03 + + -1.3477090001106262e-01 1.8056340515613556e-01 + <_> + + 0 -1 920 6.2980200164020061e-03 + + -5.4164979606866837e-02 3.6033380031585693e-01 + <_> + + 0 -1 921 1.6879989998415112e-03 + + -1.9997949898242950e-01 1.2021599709987640e-01 + <_> + + 0 -1 922 3.6039709812030196e-04 + + 1.0524140298366547e-01 -2.4116060137748718e-01 + <_> + + 0 -1 923 -1.5276849735528231e-03 + + 2.8135529160499573e-01 -6.8964816629886627e-02 + <_> + + 0 -1 924 3.5033570602536201e-03 + + -8.2519583404064178e-02 4.0713590383529663e-01 + <_> + + 0 -1 925 -4.7337161377072334e-03 + + 1.9727009534835815e-01 -1.1710140109062195e-01 + <_> + + 0 -1 926 -1.1557149700820446e-02 + + -5.6061112880706787e-01 6.8170957267284393e-02 + <_> + + 0 -1 927 -2.7445720508694649e-02 + + 4.9718621373176575e-01 -6.2380149960517883e-02 + <_> + + 0 -1 928 -5.2825778722763062e-02 + + 1.6921220719814301e-01 -1.3093550503253937e-01 + <_> + + 0 -1 929 -2.9849699139595032e-01 + + -6.4649671316146851e-01 4.0076818317174911e-02 + <_> + + 0 -1 930 -2.6307269581593573e-04 + + 2.5127941370010376e-01 -8.9494839310646057e-02 + <_> + + 0 -1 931 2.3261709429789335e-04 + + -8.6843989789485931e-02 2.3831979930400848e-01 + <_> + + 0 -1 932 2.3631360090803355e-04 + + 1.1554460227489471e-01 -1.8936349451541901e-01 + <_> + + 0 -1 933 2.0742209162563086e-03 + + -4.8594851046800613e-02 5.7485991716384888e-01 + <_> + + 0 -1 934 -7.0308889262378216e-03 + + -5.4120808839797974e-01 4.8743750900030136e-02 + <_> + + 0 -1 935 8.2652270793914795e-03 + + 2.6494519785046577e-02 -6.1728459596633911e-01 + <_> + + 0 -1 936 2.0042760297656059e-04 + + -1.1768630146980286e-01 1.6333860158920288e-01 + <_> + + 0 -1 937 1.6470040427520871e-03 + + -5.9954918920993805e-02 3.5179701447486877e-01 + <_> + + 0 -1 938 -3.5642538568936288e-04 + + -3.4420299530029297e-01 6.4948253333568573e-02 + <_> + + 0 -1 939 -3.0935870483517647e-02 + + 1.9979700446128845e-01 -9.7693696618080139e-02 + <_> + + 0 -1 940 -6.3578772824257612e-04 + + -3.1481391191482544e-01 5.9425041079521179e-02 + <_> + + 0 -1 941 -1.1862180195748806e-02 + + 2.0043690502643585e-01 -8.9447543025016785e-02 + <_> + + 0 -1 942 7.1508930996060371e-03 + + -3.9006061851978302e-02 5.3327161073684692e-01 + <_> + + 0 -1 943 -2.0059191156178713e-03 + + -2.8469720482826233e-01 7.0723608136177063e-02 + <_> + + 0 -1 944 3.6412389017641544e-03 + + -1.0660319775342941e-01 2.4944800138473511e-01 + <_> + + 0 -1 945 -1.3467429578304291e-01 + + 4.9910080432891846e-01 -4.0332220494747162e-02 + <_> + + 0 -1 946 -2.2547659464180470e-03 + + 1.6851690411567688e-01 -1.1119280010461807e-01 + <_> + + 0 -1 947 4.3842289596796036e-03 + + 8.6139492690563202e-02 -2.7431771159172058e-01 + <_> + + 0 -1 948 -7.3361168615520000e-03 + + 2.4875210225582123e-01 -9.5919162034988403e-02 + <_> + + 0 -1 949 6.4666912658140063e-04 + + 6.7431576550006866e-02 -3.3754080533981323e-01 + <_> + + 0 -1 950 2.2983769304119051e-04 + + -8.3903051912784576e-02 2.4584099650382996e-01 + <_> + + 0 -1 951 6.7039071582257748e-03 + + 2.9079329222440720e-02 -6.9055938720703125e-01 + <_> + + 0 -1 952 5.0734888645820320e-05 + + -1.5696719288825989e-01 1.1965429782867432e-01 + <_> + + 0 -1 953 -2.0335559546947479e-01 + + -6.9506347179412842e-01 2.7507519349455833e-02 + <_> + + 0 -1 954 9.4939414411783218e-03 + + -8.7449371814727783e-02 2.3968330025672913e-01 + <_> + + 0 -1 955 -2.4055240210145712e-03 + + 2.1150960028171539e-01 -1.3148930668830872e-01 + <_> + + 0 -1 956 -1.1342419747961685e-04 + + 1.5233789384365082e-01 -1.2725900113582611e-01 + <_> + + 0 -1 957 1.4992210082709789e-02 + + -3.4127969294786453e-02 5.0624072551727295e-01 + <_> + + 0 -1 958 7.4068200774490833e-04 + + 4.8764750361442566e-02 -4.0225321054458618e-01 + <_> + + 0 -1 959 -4.2459447868168354e-03 + + 2.1554760634899139e-01 -8.7126992642879486e-02 + <_> + + 0 -1 960 6.8655109498649836e-04 + + -7.5418718159198761e-02 2.6405909657478333e-01 + <_> + + 0 -1 961 -1.6751460731029510e-02 + + -6.7729032039642334e-01 3.2918728888034821e-02 + <_> + + 0 -1 962 -2.6301678735762835e-04 + + 2.2725869715213776e-01 -9.0534873306751251e-02 + <_> + + 0 -1 963 4.3398610432632267e-04 + + 5.5894378572702408e-02 -3.5592669248580933e-01 + <_> + + 0 -1 964 -2.0150149241089821e-02 + + 1.9162760674953461e-01 -9.4929970800876617e-02 + <_> + + 0 -1 965 -1.4452129602432251e-02 + + -6.8510341644287109e-01 2.5422170758247375e-02 + <_> + + 0 -1 966 -2.1149739623069763e-02 + + 3.7533190846443176e-01 -5.1496580243110657e-02 + <_> + + 0 -1 967 2.1137770265340805e-02 + + 2.9083080589771271e-02 -8.9430367946624756e-01 + <_> + + 0 -1 968 1.1524349683895707e-03 + + -6.9694936275482178e-02 2.7299800515174866e-01 + <_> + + 0 -1 969 -1.9070580310653895e-04 + + 1.8228119611740112e-01 -9.8367072641849518e-02 + <_> + + 0 -1 970 -3.6349631845951080e-02 + + -8.3693099021911621e-01 2.5055760517716408e-02 + <_> + + 0 -1 971 -9.0632075443863869e-03 + + 4.1463500261306763e-01 -5.4413449019193649e-02 + <_> + + 0 -1 972 -2.0535490475594997e-03 + + -1.9750310480594635e-01 1.0506899654865265e-01 + <_> + 93 + -9.7747492790222168e-01 + + <_> + + 0 -1 973 -2.2717019543051720e-02 + + 2.4288550019264221e-01 -1.4745520055294037e-01 + <_> + + 0 -1 974 2.5505950674414635e-02 + + -2.8551739454269409e-01 1.0837209969758987e-01 + <_> + + 0 -1 975 -2.6640091091394424e-03 + + 2.9275730252265930e-01 -1.0372710227966309e-01 + <_> + + 0 -1 976 -3.8115289062261581e-03 + + 2.1426899731159210e-01 -1.3811139762401581e-01 + <_> + + 0 -1 977 -1.6732690855860710e-02 + + 2.6550260186195374e-01 -4.3911330401897430e-02 + <_> + + 0 -1 978 4.9277010839432478e-04 + + 2.1104559302330017e-02 -4.2971360683441162e-01 + <_> + + 0 -1 979 -3.6691110581159592e-02 + + 5.3992420434951782e-01 -4.3648801743984222e-02 + <_> + + 0 -1 980 1.2615970335900784e-03 + + -1.2933869659900665e-01 1.6638770699501038e-01 + <_> + + 0 -1 981 -8.4106856957077980e-03 + + -9.4698411226272583e-01 2.1465849131345749e-02 + <_> + + 0 -1 982 6.4902722835540771e-02 + + -7.1727760136127472e-02 2.6613479852676392e-01 + <_> + + 0 -1 983 3.0305000022053719e-02 + + -8.2782492041587830e-02 2.7694320678710938e-01 + <_> + + 0 -1 984 2.5875340215861797e-03 + + -1.2966169416904449e-01 1.7756630480289459e-01 + <_> + + 0 -1 985 -7.0240451022982597e-03 + + -6.4243179559707642e-01 3.9943210780620575e-02 + <_> + + 0 -1 986 -1.0099769569933414e-03 + + 1.4176610112190247e-01 -1.1659970134496689e-01 + <_> + + 0 -1 987 -4.1179071558872238e-05 + + 1.5687669813632965e-01 -1.1127340048551559e-01 + <_> + + 0 -1 988 -4.7293151146732271e-04 + + -3.3554559946060181e-01 4.5977730304002762e-02 + <_> + + 0 -1 989 -1.7178079579025507e-03 + + 1.6952909529209137e-01 -1.0578069835901260e-01 + <_> + + 0 -1 990 -1.3333169743418694e-02 + + -5.8257812261581421e-01 3.0978430062532425e-02 + <_> + + 0 -1 991 -1.8783430568873882e-03 + + 1.4266879856586456e-01 -1.1131259799003601e-01 + <_> + + 0 -1 992 -6.5765981562435627e-03 + + 2.7561360597610474e-01 -5.3100328892469406e-02 + <_> + + 0 -1 993 -7.7210381277836859e-05 + + 1.3240240514278412e-01 -1.1167799681425095e-01 + <_> + + 0 -1 994 2.1968539804220200e-02 + + -2.6968160644173622e-02 5.0067168474197388e-01 + <_> + + 0 -1 995 -2.7445750311017036e-02 + + -2.4086740612983704e-01 6.0478270053863525e-02 + <_> + + 0 -1 996 7.8305849456228316e-05 + + -1.3334889709949493e-01 1.0123469680547714e-01 + <_> + + 0 -1 997 7.0190683007240295e-02 + + -5.4863780736923218e-02 2.4809940159320831e-01 + <_> + + 0 -1 998 -7.1902133524417877e-02 + + -3.7846690416336060e-01 4.2210999876260757e-02 + <_> + + 0 -1 999 -1.0780979692935944e-01 + + -3.7486588954925537e-01 4.2833440005779266e-02 + <_> + + 0 -1 1000 1.4364200178533792e-03 + + 8.0476358532905579e-02 -1.7263789474964142e-01 + <_> + + 0 -1 1001 6.8289190530776978e-02 + + -3.5595789551734924e-02 4.0761318802833557e-01 + <_> + + 0 -1 1002 -6.8037179298698902e-03 + + 1.9233790040016174e-01 -8.2368023693561554e-02 + <_> + + 0 -1 1003 -5.6193489581346512e-04 + + 1.3057120144367218e-01 -1.4355149865150452e-01 + <_> + + 0 -1 1004 -5.8276649564504623e-02 + + -3.0125439167022705e-01 5.2819650620222092e-02 + <_> + + 0 -1 1005 -6.1205718666315079e-03 + + 2.2043900191783905e-01 -7.5691752135753632e-02 + <_> + + 0 -1 1006 -1.3594309799373150e-02 + + -3.9049360156059265e-01 4.1857108473777771e-02 + <_> + + 0 -1 1007 1.3626200379803777e-03 + + -9.5363423228263855e-02 1.4970320463180542e-01 + <_> + + 0 -1 1008 -1.5074219845701009e-04 + + -2.3945580422878265e-01 6.4798332750797272e-02 + <_> + + 0 -1 1009 -7.7414259314537048e-02 + + 5.5941981077194214e-01 -2.4516880512237549e-02 + <_> + + 0 -1 1010 9.2117872554808855e-04 + + 5.4928861558437347e-02 -2.7934810519218445e-01 + <_> + + 0 -1 1011 1.0250780032947659e-03 + + -6.2167309224605560e-02 2.4976369738578796e-01 + <_> + + 0 -1 1012 -8.1174750812351704e-04 + + 2.3437939584255219e-01 -6.5725810825824738e-02 + <_> + + 0 -1 1013 8.3431020379066467e-02 + + 5.0954800099134445e-02 -3.1020981073379517e-01 + <_> + + 0 -1 1014 -9.2014456167817116e-03 + + -3.9242538809776306e-01 3.2926950603723526e-02 + <_> + + 0 -1 1015 -2.9086650465615094e-04 + + -3.1039750576019287e-01 4.9711819738149643e-02 + <_> + + 0 -1 1016 7.7576898038387299e-03 + + -4.4040750712156296e-02 3.6431351304054260e-01 + <_> + + 0 -1 1017 -1.2466090172529221e-01 + + -8.1957077980041504e-01 1.9150640815496445e-02 + <_> + + 0 -1 1018 1.3242550194263458e-02 + + 3.8988839834928513e-02 -3.3230680227279663e-01 + <_> + + 0 -1 1019 -6.6770128905773163e-03 + + -3.5790139436721802e-01 4.0460210293531418e-02 + <_> + + 0 -1 1020 -2.7479929849505424e-03 + + 2.5253900885581970e-01 -5.6427821516990662e-02 + <_> + + 0 -1 1021 8.2659651525318623e-04 + + -7.1988657116889954e-02 2.2780479490756989e-01 + <_> + + 0 -1 1022 -5.0153400748968124e-02 + + -6.3036471605300903e-01 2.7462050318717957e-02 + <_> + + 0 -1 1023 7.4203149415552616e-03 + + -6.6610716283321381e-02 2.7787339687347412e-01 + <_> + + 0 -1 1024 -6.7951780511066318e-04 + + -3.6327061057090759e-01 4.2795430868864059e-02 + <_> + + 0 -1 1025 -1.9305750029161572e-03 + + 1.4196230471134186e-01 -1.0759980231523514e-01 + <_> + + 0 -1 1026 -3.8132671033963561e-04 + + 2.1591760218143463e-01 -7.0202663540840149e-02 + <_> + + 0 -1 1027 -7.0990346372127533e-02 + + 4.5266601443290710e-01 -4.0750481188297272e-02 + <_> + + 0 -1 1028 -5.3368080407381058e-02 + + -6.7674058675765991e-01 1.9288340583443642e-02 + <_> + + 0 -1 1029 -2.0064849406480789e-02 + + -4.3365430831909180e-01 3.1853288412094116e-02 + <_> + + 0 -1 1030 1.1976360110566020e-03 + + -2.6559870690107346e-02 5.0797182321548462e-01 + <_> + + 0 -1 1031 -2.2697300300933421e-04 + + 1.8012599647045135e-01 -8.3606548607349396e-02 + <_> + + 0 -1 1032 1.5262699685990810e-02 + + -2.0238929986953735e-01 6.7422017455101013e-02 + <_> + + 0 -1 1033 -2.0811769366264343e-01 + + 6.6943860054016113e-01 -2.2452110424637794e-02 + <_> + + 0 -1 1034 1.5514369588345289e-03 + + -7.5121842324733734e-02 1.7326919734477997e-01 + <_> + + 0 -1 1035 -5.2924010902643204e-02 + + 2.4992519617080688e-01 -6.2879167497158051e-02 + <_> + + 0 -1 1036 -2.1648850291967392e-02 + + -2.9194280505180359e-01 5.2614491432905197e-02 + <_> + + 0 -1 1037 -2.2905069636180997e-04 + + -2.2117300331592560e-01 6.3168339431285858e-02 + <_> + + 0 -1 1038 5.0170070608146489e-05 + + -1.1510709673166275e-01 1.1611440032720566e-01 + <_> + + 0 -1 1039 -1.6416069411206990e-04 + + 1.5871520340442657e-01 -8.2600601017475128e-02 + <_> + + 0 -1 1040 -1.2003289535641670e-02 + + 1.2218090146780014e-01 -1.1229699850082397e-01 + <_> + + 0 -1 1041 -1.7784100025892258e-02 + + -3.5072788596153259e-01 3.1341921538114548e-02 + <_> + + 0 -1 1042 -6.3457582145929337e-03 + + 1.3078069686889648e-01 -1.0574410110712051e-01 + <_> + + 0 -1 1043 -7.9523242311552167e-04 + + 1.7204670608043671e-01 -8.6001992225646973e-02 + <_> + + 0 -1 1044 -3.1029590172693133e-04 + + -2.8433170914649963e-01 5.1817119121551514e-02 + <_> + + 0 -1 1045 -1.7053710296750069e-02 + + 3.9242428541183472e-01 -4.0143270045518875e-02 + <_> + + 0 -1 1046 4.6504959464073181e-03 + + -3.1837560236454010e-02 4.1237699985504150e-01 + <_> + + 0 -1 1047 -1.0358760133385658e-02 + + -5.6993198394775391e-01 2.9248379170894623e-02 + <_> + + 0 -1 1048 -2.2196240723133087e-02 + + -4.5605289936065674e-01 2.6285989210009575e-02 + <_> + + 0 -1 1049 -7.0536029525101185e-03 + + 1.5998320281505585e-01 -9.1594859957695007e-02 + <_> + + 0 -1 1050 -5.7094299700111151e-04 + + -1.4076329767704010e-01 1.0287419706583023e-01 + <_> + + 0 -1 1051 -2.2152599412947893e-03 + + 1.6593599319458008e-01 -8.5273988544940948e-02 + <_> + + 0 -1 1052 -2.8084890916943550e-02 + + 2.7022340893745422e-01 -5.5873811244964600e-02 + <_> + + 0 -1 1053 2.1515151020139456e-03 + + 4.2472891509532928e-02 -3.2005849480628967e-01 + <_> + + 0 -1 1054 -2.9733829433098435e-04 + + 1.6177169978618622e-01 -8.5115589201450348e-02 + <_> + + 0 -1 1055 -1.6694780439138412e-02 + + -4.2858770489692688e-01 3.0541609972715378e-02 + <_> + + 0 -1 1056 1.1982990056276321e-01 + + -1.6277290880680084e-02 7.9846781492233276e-01 + <_> + + 0 -1 1057 -3.5499420482665300e-04 + + 1.5935939550399780e-01 -8.3272881805896759e-02 + <_> + + 0 -1 1058 -1.8226269632577896e-02 + + 1.9527280330657959e-01 -7.3939889669418335e-02 + <_> + + 0 -1 1059 -4.0238600922748446e-04 + + 7.9101808369159698e-02 -2.0806129276752472e-01 + <_> + + 0 -1 1060 4.0892060496844351e-04 + + 1.0036630183458328e-01 -1.5128210186958313e-01 + <_> + + 0 -1 1061 9.5368112670257688e-04 + + -7.3011666536331177e-02 2.1752020716667175e-01 + <_> + + 0 -1 1062 4.3081799149513245e-01 + + -2.7450699359178543e-02 5.7061582803726196e-01 + <_> + + 0 -1 1063 5.3564831614494324e-04 + + 1.1587540060281754e-01 -1.2790560722351074e-01 + <_> + + 0 -1 1064 2.4430730263702571e-05 + + -1.6816629469394684e-01 8.0449983477592468e-02 + <_> + + 0 -1 1065 -5.5345650762319565e-02 + + 4.5338949561119080e-01 -3.1222779303789139e-02 + + <_> + + <_> + 0 8 20 12 -1. + <_> + 0 14 20 6 2. + <_> + + <_> + 9 1 4 15 -1. + <_> + 9 6 4 5 3. + <_> + + <_> + 6 10 9 2 -1. + <_> + 9 10 3 2 3. + <_> + + <_> + 7 0 10 9 -1. + <_> + 7 3 10 3 3. + <_> + + <_> + 12 2 2 18 -1. + <_> + 12 8 2 6 3. + <_> + + <_> + 8 6 8 6 -1. + <_> + 8 9 8 3 2. + <_> + + <_> + 2 0 17 18 -1. + <_> + 2 6 17 6 3. + <_> + + <_> + 10 10 1 8 -1. + <_> + 10 14 1 4 2. + <_> + + <_> + 7 10 9 2 -1. + <_> + 10 10 3 2 3. + <_> + + <_> + 5 1 6 6 -1. + <_> + 5 3 6 2 3. + <_> + + <_> + 3 1 15 9 -1. + <_> + 3 4 15 3 3. + <_> + + <_> + 6 3 9 6 -1. + <_> + 6 5 9 2 3. + <_> + + <_> + 8 17 6 3 -1. + <_> + 10 17 2 3 3. + <_> + + <_> + 9 10 9 1 -1. + <_> + 12 10 3 1 3. + <_> + + <_> + 1 7 6 11 -1. + <_> + 3 7 2 11 3. + <_> + + <_> + 9 18 3 1 -1. + <_> + 10 18 1 1 3. + <_> + + <_> + 16 16 1 2 -1. + <_> + 16 17 1 1 2. + <_> + + <_> + 9 17 6 3 -1. + <_> + 11 17 2 3 3. + <_> + + <_> + 8 0 5 18 -1. + <_> + 8 6 5 6 3. + <_> + + <_> + 6 7 9 7 -1. + <_> + 9 7 3 7 3. + <_> + + <_> + 14 6 6 10 -1. + <_> + 16 6 2 10 3. + <_> + + <_> + 9 8 9 5 -1. + <_> + 12 8 3 5 3. + <_> + + <_> + 3 7 9 6 -1. + <_> + 6 7 3 6 3. + <_> + + <_> + 1 7 6 6 -1. + <_> + 3 7 2 6 3. + <_> + + <_> + 16 0 4 18 -1. + <_> + 16 6 4 6 3. + <_> + + <_> + 0 17 3 3 -1. + <_> + 0 18 3 1 3. + <_> + + <_> + 16 0 2 1 -1. + <_> + 17 0 1 1 2. + <_> + + <_> + 0 8 20 12 -1. + <_> + 0 14 20 6 2. + <_> + + <_> + 6 6 9 8 -1. + <_> + 9 6 3 8 3. + <_> + + <_> + 5 3 12 9 -1. + <_> + 5 6 12 3 3. + <_> + + <_> + 4 16 1 2 -1. + <_> + 4 17 1 1 2. + <_> + + <_> + 18 10 2 1 -1. + <_> + 19 10 1 1 2. + <_> + + <_> + 9 8 6 5 -1. + <_> + 11 8 2 5 3. + <_> + + <_> + 0 0 2 1 -1. + <_> + 1 0 1 1 2. + <_> + + <_> + 6 8 6 6 -1. + <_> + 8 8 2 6 3. + <_> + + <_> + 11 7 6 7 -1. + <_> + 13 7 2 7 3. + <_> + + <_> + 19 14 1 2 -1. + <_> + 19 15 1 1 2. + <_> + + <_> + 6 17 1 2 -1. + <_> + 6 18 1 1 2. + <_> + + <_> + 14 7 2 7 -1. + <_> + 15 7 1 7 2. + <_> + + <_> + 6 8 2 4 -1. + <_> + 7 8 1 4 2. + <_> + + <_> + 5 8 12 6 -1. + <_> + 5 10 12 2 3. + <_> + + <_> + 2 17 1 3 -1. + <_> + 2 18 1 1 3. + <_> + + <_> + 6 7 3 6 -1. + <_> + 7 7 1 6 3. + <_> + + <_> + 6 7 9 12 -1. + <_> + 9 7 3 12 3. + <_> + + <_> + 6 2 11 12 -1. + <_> + 6 6 11 4 3. + <_> + + <_> + 1 12 5 8 -1. + <_> + 1 16 5 4 2. + <_> + + <_> + 14 7 6 7 -1. + <_> + 16 7 2 7 3. + <_> + + <_> + 10 8 6 6 -1. + <_> + 12 8 2 6 3. + <_> + + <_> + 16 18 4 2 -1. + <_> + 16 19 4 1 2. + <_> + + <_> + 18 17 2 3 -1. + <_> + 18 18 2 1 3. + <_> + + <_> + 9 7 3 7 -1. + <_> + 10 7 1 7 3. + <_> + + <_> + 5 6 6 8 -1. + <_> + 7 6 2 8 3. + <_> + + <_> + 2 6 6 11 -1. + <_> + 4 6 2 11 3. + <_> + + <_> + 8 10 12 8 -1. + <_> + 8 14 12 4 2. + <_> + + <_> + 7 17 6 3 -1. + <_> + 9 17 2 3 3. + <_> + + <_> + 10 9 3 3 -1. + <_> + 11 9 1 3 3. + <_> + + <_> + 8 8 3 6 -1. + <_> + 9 8 1 6 3. + <_> + + <_> + 7 0 6 5 -1. + <_> + 9 0 2 5 3. + <_> + + <_> + 6 17 1 3 -1. + <_> + 6 18 1 1 3. + <_> + + <_> + 0 18 4 2 -1. + <_> + 0 19 4 1 2. + <_> + + <_> + 4 1 11 9 -1. + <_> + 4 4 11 3 3. + <_> + + <_> + 3 1 14 9 -1. + <_> + 3 4 14 3 3. + <_> + + <_> + 0 9 6 4 -1. + <_> + 2 9 2 4 3. + <_> + + <_> + 18 13 1 2 -1. + <_> + 18 14 1 1 2. + <_> + + <_> + 13 5 3 11 -1. + <_> + 14 5 1 11 3. + <_> + + <_> + 0 18 8 2 -1. + <_> + 0 18 4 1 2. + <_> + 4 19 4 1 2. + <_> + + <_> + 5 8 12 5 -1. + <_> + 9 8 4 5 3. + <_> + + <_> + 4 7 11 10 -1. + <_> + 4 12 11 5 2. + <_> + + <_> + 14 9 6 4 -1. + <_> + 16 9 2 4 3. + <_> + + <_> + 0 7 6 8 -1. + <_> + 3 7 3 8 2. + <_> + + <_> + 0 16 3 3 -1. + <_> + 0 17 3 1 3. + <_> + + <_> + 7 11 12 1 -1. + <_> + 11 11 4 1 3. + <_> + + <_> + 4 8 9 4 -1. + <_> + 7 8 3 4 3. + <_> + + <_> + 5 16 6 4 -1. + <_> + 7 16 2 4 3. + <_> + + <_> + 18 17 1 3 -1. + <_> + 18 18 1 1 3. + <_> + + <_> + 18 17 1 3 -1. + <_> + 18 18 1 1 3. + <_> + + <_> + 4 9 4 10 -1. + <_> + 4 9 2 5 2. + <_> + 6 14 2 5 2. + <_> + + <_> + 4 8 6 4 -1. + <_> + 6 8 2 4 3. + <_> + + <_> + 10 2 2 18 -1. + <_> + 10 8 2 6 3. + <_> + + <_> + 0 5 8 6 -1. + <_> + 0 5 4 3 2. + <_> + 4 8 4 3 2. + <_> + + <_> + 6 0 6 5 -1. + <_> + 8 0 2 5 3. + <_> + + <_> + 18 0 2 14 -1. + <_> + 18 7 2 7 2. + <_> + + <_> + 8 18 4 2 -1. + <_> + 10 18 2 2 2. + <_> + + <_> + 1 17 6 3 -1. + <_> + 1 18 6 1 3. + <_> + + <_> + 11 8 3 5 -1. + <_> + 12 8 1 5 3. + <_> + + <_> + 11 8 3 4 -1. + <_> + 12 8 1 4 3. + <_> + + <_> + 11 0 6 5 -1. + <_> + 13 0 2 5 3. + <_> + + <_> + 1 7 6 7 -1. + <_> + 3 7 2 7 3. + <_> + + <_> + 0 13 1 3 -1. + <_> + 0 14 1 1 3. + <_> + + <_> + 3 2 9 6 -1. + <_> + 3 4 9 2 3. + <_> + + <_> + 8 6 9 2 -1. + <_> + 8 7 9 1 2. + <_> + + <_> + 0 14 3 6 -1. + <_> + 0 16 3 2 3. + <_> + + <_> + 1 11 6 4 -1. + <_> + 3 11 2 4 3. + <_> + + <_> + 6 9 9 3 -1. + <_> + 9 9 3 3 3. + <_> + + <_> + 6 0 9 6 -1. + <_> + 6 2 9 2 3. + <_> + + <_> + 8 5 6 6 -1. + <_> + 8 7 6 2 3. + <_> + + <_> + 1 12 2 1 -1. + <_> + 2 12 1 1 2. + <_> + + <_> + 10 10 6 2 -1. + <_> + 12 10 2 2 3. + <_> + + <_> + 13 8 6 6 -1. + <_> + 15 8 2 6 3. + <_> + + <_> + 6 16 6 4 -1. + <_> + 8 16 2 4 3. + <_> + + <_> + 8 0 9 9 -1. + <_> + 8 3 9 3 3. + <_> + + <_> + 18 17 1 3 -1. + <_> + 18 18 1 1 3. + <_> + + <_> + 18 17 1 3 -1. + <_> + 18 18 1 1 3. + <_> + + <_> + 7 10 3 3 -1. + <_> + 8 10 1 3 3. + <_> + + <_> + 9 14 2 2 -1. + <_> + 9 14 1 1 2. + <_> + 10 15 1 1 2. + <_> + + <_> + 9 14 2 2 -1. + <_> + 9 14 1 1 2. + <_> + 10 15 1 1 2. + <_> + + <_> + 0 8 19 12 -1. + <_> + 0 14 19 6 2. + <_> + + <_> + 7 6 9 14 -1. + <_> + 10 6 3 14 3. + <_> + + <_> + 13 8 3 4 -1. + <_> + 14 8 1 4 3. + <_> + + <_> + 4 17 1 3 -1. + <_> + 4 18 1 1 3. + <_> + + <_> + 4 9 6 3 -1. + <_> + 6 9 2 3 3. + <_> + + <_> + 2 18 5 2 -1. + <_> + 2 19 5 1 2. + <_> + + <_> + 7 8 2 2 -1. + <_> + 7 8 1 1 2. + <_> + 8 9 1 1 2. + <_> + + <_> + 7 8 2 2 -1. + <_> + 7 8 1 1 2. + <_> + 8 9 1 1 2. + <_> + + <_> + 5 10 13 2 -1. + <_> + 5 11 13 1 2. + <_> + + <_> + 10 8 1 9 -1. + <_> + 10 11 1 3 3. + <_> + + <_> + 15 8 2 12 -1. + <_> + 15 8 1 6 2. + <_> + 16 14 1 6 2. + <_> + + <_> + 4 0 3 5 -1. + <_> + 5 0 1 5 3. + <_> + + <_> + 12 6 3 7 -1. + <_> + 13 6 1 7 3. + <_> + + <_> + 7 16 6 4 -1. + <_> + 9 16 2 4 3. + <_> + + <_> + 9 16 2 1 -1. + <_> + 10 16 1 1 2. + <_> + + <_> + 6 10 9 2 -1. + <_> + 9 10 3 2 3. + <_> + + <_> + 0 6 15 14 -1. + <_> + 0 13 15 7 2. + <_> + + <_> + 9 1 5 6 -1. + <_> + 9 3 5 2 3. + <_> + + <_> + 3 9 3 4 -1. + <_> + 4 9 1 4 3. + <_> + + <_> + 5 7 3 6 -1. + <_> + 6 7 1 6 3. + <_> + + <_> + 17 16 1 2 -1. + <_> + 17 17 1 1 2. + <_> + + <_> + 9 8 6 12 -1. + <_> + 11 8 2 12 3. + <_> + + <_> + 6 10 6 1 -1. + <_> + 8 10 2 1 3. + <_> + + <_> + 7 17 9 3 -1. + <_> + 10 17 3 3 3. + <_> + + <_> + 14 18 6 2 -1. + <_> + 14 19 6 1 2. + <_> + + <_> + 9 5 3 14 -1. + <_> + 10 5 1 14 3. + <_> + + <_> + 8 16 9 4 -1. + <_> + 11 16 3 4 3. + <_> + + <_> + 0 0 4 14 -1. + <_> + 0 7 4 7 2. + <_> + + <_> + 8 1 6 3 -1. + <_> + 10 1 2 3 3. + <_> + + <_> + 6 8 3 4 -1. + <_> + 7 8 1 4 3. + <_> + + <_> + 4 8 3 4 -1. + <_> + 5 8 1 4 3. + <_> + + <_> + 5 1 6 5 -1. + <_> + 7 1 2 5 3. + <_> + + <_> + 1 18 1 2 -1. + <_> + 1 19 1 1 2. + <_> + + <_> + 7 0 6 6 -1. + <_> + 7 2 6 2 3. + <_> + + <_> + 0 18 4 2 -1. + <_> + 0 19 4 1 2. + <_> + + <_> + 12 3 8 12 -1. + <_> + 12 7 8 4 3. + <_> + + <_> + 12 9 3 4 -1. + <_> + 13 9 1 4 3. + <_> + + <_> + 12 8 3 5 -1. + <_> + 13 8 1 5 3. + <_> + + <_> + 16 0 2 1 -1. + <_> + 17 0 1 1 2. + <_> + + <_> + 5 17 1 3 -1. + <_> + 5 18 1 1 3. + <_> + + <_> + 10 2 3 6 -1. + <_> + 10 4 3 2 3. + <_> + + <_> + 4 17 2 3 -1. + <_> + 4 18 2 1 3. + <_> + + <_> + 12 7 1 9 -1. + <_> + 12 10 1 3 3. + <_> + + <_> + 7 6 3 9 -1. + <_> + 8 6 1 9 3. + <_> + + <_> + 17 13 3 6 -1. + <_> + 17 15 3 2 3. + <_> + + <_> + 7 7 3 8 -1. + <_> + 8 7 1 8 3. + <_> + + <_> + 5 0 3 5 -1. + <_> + 6 0 1 5 3. + <_> + + <_> + 4 6 9 8 -1. + <_> + 7 6 3 8 3. + <_> + + <_> + 2 9 3 3 -1. + <_> + 3 9 1 3 3. + <_> + + <_> + 16 18 4 2 -1. + <_> + 16 19 4 1 2. + <_> + + <_> + 17 10 3 10 -1. + <_> + 17 15 3 5 2. + <_> + + <_> + 8 9 6 4 -1. + <_> + 10 9 2 4 3. + <_> + + <_> + 5 2 10 12 -1. + <_> + 5 6 10 4 3. + <_> + + <_> + 6 9 6 3 -1. + <_> + 8 9 2 3 3. + <_> + + <_> + 11 7 3 7 -1. + <_> + 12 7 1 7 3. + <_> + + <_> + 12 8 6 4 -1. + <_> + 14 8 2 4 3. + <_> + + <_> + 14 8 6 5 -1. + <_> + 16 8 2 5 3. + <_> + + <_> + 12 12 2 4 -1. + <_> + 12 14 2 2 2. + <_> + + <_> + 3 15 1 2 -1. + <_> + 3 16 1 1 2. + <_> + + <_> + 12 7 3 4 -1. + <_> + 13 7 1 4 3. + <_> + + <_> + 10 0 6 6 -1. + <_> + 12 0 2 6 3. + <_> + + <_> + 10 6 3 8 -1. + <_> + 11 6 1 8 3. + <_> + + <_> + 16 17 1 2 -1. + <_> + 16 18 1 1 2. + <_> + + <_> + 16 16 1 3 -1. + <_> + 16 17 1 1 3. + <_> + + <_> + 11 11 1 2 -1. + <_> + 11 12 1 1 2. + <_> + + <_> + 3 7 6 9 -1. + <_> + 5 7 2 9 3. + <_> + + <_> + 4 18 9 1 -1. + <_> + 7 18 3 1 3. + <_> + + <_> + 0 11 4 9 -1. + <_> + 0 14 4 3 3. + <_> + + <_> + 9 17 6 3 -1. + <_> + 11 17 2 3 3. + <_> + + <_> + 7 8 6 12 -1. + <_> + 9 8 2 12 3. + <_> + + <_> + 6 8 3 4 -1. + <_> + 7 8 1 4 3. + <_> + + <_> + 3 17 1 3 -1. + <_> + 3 18 1 1 3. + <_> + + <_> + 11 9 6 4 -1. + <_> + 13 9 2 4 3. + <_> + + <_> + 6 1 3 2 -1. + <_> + 7 1 1 2 3. + <_> + + <_> + 1 0 2 1 -1. + <_> + 2 0 1 1 2. + <_> + + <_> + 1 0 2 14 -1. + <_> + 1 0 1 7 2. + <_> + 2 7 1 7 2. + <_> + + <_> + 5 5 11 8 -1. + <_> + 5 9 11 4 2. + <_> + + <_> + 9 3 5 6 -1. + <_> + 9 5 5 2 3. + <_> + + <_> + 7 9 5 10 -1. + <_> + 7 14 5 5 2. + <_> + + <_> + 15 10 2 2 -1. + <_> + 16 10 1 2 2. + <_> + + <_> + 0 18 8 2 -1. + <_> + 0 19 8 1 2. + <_> + + <_> + 7 17 1 3 -1. + <_> + 7 18 1 1 3. + <_> + + <_> + 7 2 11 6 -1. + <_> + 7 4 11 2 3. + <_> + + <_> + 8 3 9 3 -1. + <_> + 8 4 9 1 3. + <_> + + <_> + 0 9 2 2 -1. + <_> + 0 10 2 1 2. + <_> + + <_> + 0 5 3 6 -1. + <_> + 0 7 3 2 3. + <_> + + <_> + 6 7 2 2 -1. + <_> + 6 7 1 1 2. + <_> + 7 8 1 1 2. + <_> + + <_> + 7 6 3 6 -1. + <_> + 8 6 1 6 3. + <_> + + <_> + 12 1 6 4 -1. + <_> + 14 1 2 4 3. + <_> + + <_> + 9 11 6 8 -1. + <_> + 11 11 2 8 3. + <_> + + <_> + 17 15 3 3 -1. + <_> + 17 16 3 1 3. + <_> + + <_> + 6 6 3 9 -1. + <_> + 6 9 3 3 3. + <_> + + <_> + 0 5 8 6 -1. + <_> + 0 5 4 3 2. + <_> + 4 8 4 3 2. + <_> + + <_> + 0 6 1 3 -1. + <_> + 0 7 1 1 3. + <_> + + <_> + 17 0 2 6 -1. + <_> + 18 0 1 6 2. + <_> + + <_> + 10 17 6 3 -1. + <_> + 12 17 2 3 3. + <_> + + <_> + 13 15 2 2 -1. + <_> + 13 15 1 1 2. + <_> + 14 16 1 1 2. + <_> + + <_> + 4 0 12 3 -1. + <_> + 4 1 12 1 3. + <_> + + <_> + 5 3 10 9 -1. + <_> + 5 6 10 3 3. + <_> + + <_> + 7 7 9 7 -1. + <_> + 10 7 3 7 3. + <_> + + <_> + 5 8 9 6 -1. + <_> + 8 8 3 6 3. + <_> + + <_> + 0 16 6 2 -1. + <_> + 0 17 6 1 2. + <_> + + <_> + 12 6 7 14 -1. + <_> + 12 13 7 7 2. + <_> + + <_> + 13 7 6 8 -1. + <_> + 15 7 2 8 3. + <_> + + <_> + 2 10 6 3 -1. + <_> + 4 10 2 3 3. + <_> + + <_> + 18 17 1 3 -1. + <_> + 18 18 1 1 3. + <_> + + <_> + 7 1 6 2 -1. + <_> + 7 2 6 1 2. + <_> + + <_> + 6 0 6 4 -1. + <_> + 6 2 6 2 2. + <_> + + <_> + 8 18 6 2 -1. + <_> + 10 18 2 2 3. + <_> + + <_> + 7 6 5 2 -1. + <_> + 7 7 5 1 2. + <_> + + <_> + 6 7 3 6 -1. + <_> + 7 7 1 6 3. + <_> + + <_> + 18 18 2 2 -1. + <_> + 18 18 1 1 2. + <_> + 19 19 1 1 2. + <_> + + <_> + 16 8 3 7 -1. + <_> + 17 8 1 7 3. + <_> + + <_> + 0 16 2 3 -1. + <_> + 0 17 2 1 3. + <_> + + <_> + 5 19 6 1 -1. + <_> + 7 19 2 1 3. + <_> + + <_> + 9 5 6 6 -1. + <_> + 9 7 6 2 3. + <_> + + <_> + 0 10 2 4 -1. + <_> + 0 12 2 2 2. + <_> + + <_> + 0 9 4 3 -1. + <_> + 2 9 2 3 2. + <_> + + <_> + 1 10 6 9 -1. + <_> + 3 10 2 9 3. + <_> + + <_> + 9 0 6 2 -1. + <_> + 11 0 2 2 3. + <_> + + <_> + 14 1 2 1 -1. + <_> + 15 1 1 1 2. + <_> + + <_> + 0 8 1 4 -1. + <_> + 0 10 1 2 2. + <_> + + <_> + 15 6 2 2 -1. + <_> + 15 6 1 1 2. + <_> + 16 7 1 1 2. + <_> + + <_> + 7 5 3 6 -1. + <_> + 8 5 1 6 3. + <_> + + <_> + 19 17 1 3 -1. + <_> + 19 18 1 1 3. + <_> + + <_> + 7 10 3 1 -1. + <_> + 8 10 1 1 3. + <_> + + <_> + 12 1 6 6 -1. + <_> + 14 1 2 6 3. + <_> + + <_> + 15 5 2 1 -1. + <_> + 16 5 1 1 2. + <_> + + <_> + 8 2 7 4 -1. + <_> + 8 4 7 2 2. + <_> + + <_> + 4 0 14 15 -1. + <_> + 4 5 14 5 3. + <_> + + <_> + 7 8 6 6 -1. + <_> + 9 8 2 6 3. + <_> + + <_> + 11 17 1 3 -1. + <_> + 11 18 1 1 3. + <_> + + <_> + 12 16 2 4 -1. + <_> + 12 16 1 2 2. + <_> + 13 18 1 2 2. + <_> + + <_> + 10 13 2 1 -1. + <_> + 11 13 1 1 2. + <_> + + <_> + 11 8 3 3 -1. + <_> + 12 8 1 3 3. + <_> + + <_> + 2 0 6 8 -1. + <_> + 4 0 2 8 3. + <_> + + <_> + 3 5 6 6 -1. + <_> + 3 5 3 3 2. + <_> + 6 8 3 3 2. + <_> + + <_> + 10 8 3 3 -1. + <_> + 11 8 1 3 3. + <_> + + <_> + 5 17 4 2 -1. + <_> + 5 18 4 1 2. + <_> + + <_> + 8 16 5 2 -1. + <_> + 8 17 5 1 2. + <_> + + <_> + 0 4 3 3 -1. + <_> + 0 5 3 1 3. + <_> + + <_> + 6 3 6 2 -1. + <_> + 8 3 2 2 3. + <_> + + <_> + 4 4 9 3 -1. + <_> + 7 4 3 3 3. + <_> + + <_> + 0 13 1 4 -1. + <_> + 0 15 1 2 2. + <_> + + <_> + 0 17 8 3 -1. + <_> + 0 18 8 1 3. + <_> + + <_> + 6 1 11 6 -1. + <_> + 6 3 11 2 3. + <_> + + <_> + 4 10 6 2 -1. + <_> + 6 10 2 2 3. + <_> + + <_> + 10 8 1 12 -1. + <_> + 10 14 1 6 2. + <_> + + <_> + 5 8 3 4 -1. + <_> + 6 8 1 4 3. + <_> + + <_> + 0 17 1 3 -1. + <_> + 0 18 1 1 3. + <_> + + <_> + 0 17 1 3 -1. + <_> + 0 18 1 1 3. + <_> + + <_> + 13 8 3 4 -1. + <_> + 14 8 1 4 3. + <_> + + <_> + 1 5 5 4 -1. + <_> + 1 7 5 2 2. + <_> + + <_> + 18 14 1 2 -1. + <_> + 18 15 1 1 2. + <_> + + <_> + 13 8 2 4 -1. + <_> + 14 8 1 4 2. + <_> + + <_> + 10 6 6 8 -1. + <_> + 12 6 2 8 3. + <_> + + <_> + 8 6 6 10 -1. + <_> + 10 6 2 10 3. + <_> + + <_> + 17 16 1 3 -1. + <_> + 17 17 1 1 3. + <_> + + <_> + 1 7 2 10 -1. + <_> + 2 7 1 10 2. + <_> + + <_> + 5 9 6 3 -1. + <_> + 7 9 2 3 3. + <_> + + <_> + 0 8 5 12 -1. + <_> + 0 14 5 6 2. + <_> + + <_> + 0 11 1 3 -1. + <_> + 0 12 1 1 3. + <_> + + <_> + 6 16 6 4 -1. + <_> + 8 16 2 4 3. + <_> + + <_> + 0 6 2 6 -1. + <_> + 0 8 2 2 3. + <_> + + <_> + 11 18 2 1 -1. + <_> + 12 18 1 1 2. + <_> + + <_> + 5 1 9 2 -1. + <_> + 5 2 9 1 2. + <_> + + <_> + 0 0 1 2 -1. + <_> + 0 1 1 1 2. + <_> + + <_> + 15 9 3 3 -1. + <_> + 16 9 1 3 3. + <_> + + <_> + 18 16 1 3 -1. + <_> + 18 17 1 1 3. + <_> + + <_> + 11 10 6 1 -1. + <_> + 13 10 2 1 3. + <_> + + <_> + 1 3 4 4 -1. + <_> + 3 3 2 4 2. + <_> + + <_> + 11 2 1 18 -1. + <_> + 11 8 1 6 3. + <_> + + <_> + 9 1 5 12 -1. + <_> + 9 5 5 4 3. + <_> + + <_> + 12 0 8 1 -1. + <_> + 16 0 4 1 2. + <_> + + <_> + 8 6 3 10 -1. + <_> + 9 6 1 10 3. + <_> + + <_> + 19 2 1 6 -1. + <_> + 19 4 1 2 3. + <_> + + <_> + 18 6 2 2 -1. + <_> + 18 7 2 1 2. + <_> + + <_> + 7 7 3 4 -1. + <_> + 8 7 1 4 3. + <_> + + <_> + 5 0 6 5 -1. + <_> + 7 0 2 5 3. + <_> + + <_> + 0 3 7 3 -1. + <_> + 0 4 7 1 3. + <_> + + <_> + 1 6 2 1 -1. + <_> + 2 6 1 1 2. + <_> + + <_> + 4 8 2 10 -1. + <_> + 4 8 1 5 2. + <_> + 5 13 1 5 2. + <_> + + <_> + 2 18 18 2 -1. + <_> + 2 18 9 1 2. + <_> + 11 19 9 1 2. + <_> + + <_> + 2 7 4 4 -1. + <_> + 2 7 2 2 2. + <_> + 4 9 2 2 2. + <_> + + <_> + 17 3 3 4 -1. + <_> + 18 3 1 4 3. + <_> + + <_> + 16 9 2 8 -1. + <_> + 16 9 1 4 2. + <_> + 17 13 1 4 2. + <_> + + <_> + 15 7 1 6 -1. + <_> + 15 9 1 2 3. + <_> + + <_> + 14 2 2 2 -1. + <_> + 14 3 2 1 2. + <_> + + <_> + 17 0 2 3 -1. + <_> + 17 1 2 1 3. + <_> + + <_> + 16 18 2 2 -1. + <_> + 16 18 1 1 2. + <_> + 17 19 1 1 2. + <_> + + <_> + 10 4 4 3 -1. + <_> + 10 5 4 1 3. + <_> + + <_> + 0 2 8 6 -1. + <_> + 4 2 4 6 2. + <_> + + <_> + 7 14 6 6 -1. + <_> + 7 16 6 2 3. + <_> + + <_> + 11 15 2 2 -1. + <_> + 11 16 2 1 2. + <_> + + <_> + 7 1 9 4 -1. + <_> + 10 1 3 4 3. + <_> + + <_> + 9 7 3 7 -1. + <_> + 10 7 1 7 3. + <_> + + <_> + 6 17 2 2 -1. + <_> + 6 17 1 1 2. + <_> + 7 18 1 1 2. + <_> + + <_> + 4 6 3 9 -1. + <_> + 5 6 1 9 3. + <_> + + <_> + 0 10 19 10 -1. + <_> + 0 15 19 5 2. + <_> + + <_> + 5 17 6 1 -1. + <_> + 7 17 2 1 3. + <_> + + <_> + 0 12 6 3 -1. + <_> + 3 12 3 3 2. + <_> + + <_> + 2 5 18 5 -1. + <_> + 8 5 6 5 3. + <_> + + <_> + 1 15 6 4 -1. + <_> + 1 17 6 2 2. + <_> + + <_> + 14 10 6 6 -1. + <_> + 16 10 2 6 3. + <_> + + <_> + 0 14 4 3 -1. + <_> + 0 15 4 1 3. + <_> + + <_> + 1 7 6 11 -1. + <_> + 3 7 2 11 3. + <_> + + <_> + 13 17 7 2 -1. + <_> + 13 18 7 1 2. + <_> + + <_> + 0 14 2 3 -1. + <_> + 0 15 2 1 3. + <_> + + <_> + 0 0 6 2 -1. + <_> + 3 0 3 2 2. + <_> + + <_> + 0 1 6 3 -1. + <_> + 3 1 3 3 2. + <_> + + <_> + 0 8 2 6 -1. + <_> + 0 10 2 2 3. + <_> + + <_> + 1 2 6 14 -1. + <_> + 1 2 3 7 2. + <_> + 4 9 3 7 2. + <_> + + <_> + 17 5 2 2 -1. + <_> + 17 5 1 1 2. + <_> + 18 6 1 1 2. + <_> + + <_> + 11 10 9 4 -1. + <_> + 14 10 3 4 3. + <_> + + <_> + 2 9 12 4 -1. + <_> + 6 9 4 4 3. + <_> + + <_> + 7 10 12 2 -1. + <_> + 11 10 4 2 3. + <_> + + <_> + 2 13 1 2 -1. + <_> + 2 14 1 1 2. + <_> + + <_> + 16 7 4 3 -1. + <_> + 16 8 4 1 3. + <_> + + <_> + 19 16 1 3 -1. + <_> + 19 17 1 1 3. + <_> + + <_> + 18 11 1 2 -1. + <_> + 18 12 1 1 2. + <_> + + <_> + 12 7 8 2 -1. + <_> + 12 7 4 1 2. + <_> + 16 8 4 1 2. + <_> + + <_> + 14 9 2 4 -1. + <_> + 15 9 1 4 2. + <_> + + <_> + 14 2 6 4 -1. + <_> + 14 2 3 2 2. + <_> + 17 4 3 2 2. + <_> + + <_> + 14 0 6 1 -1. + <_> + 17 0 3 1 2. + <_> + + <_> + 3 12 2 1 -1. + <_> + 4 12 1 1 2. + <_> + + <_> + 17 2 3 1 -1. + <_> + 18 2 1 1 3. + <_> + + <_> + 1 16 18 2 -1. + <_> + 7 16 6 2 3. + <_> + + <_> + 2 19 8 1 -1. + <_> + 6 19 4 1 2. + <_> + + <_> + 1 17 4 3 -1. + <_> + 1 18 4 1 3. + <_> + + <_> + 19 13 1 2 -1. + <_> + 19 14 1 1 2. + <_> + + <_> + 9 16 10 4 -1. + <_> + 9 16 5 2 2. + <_> + 14 18 5 2 2. + <_> + + <_> + 12 9 2 4 -1. + <_> + 12 9 1 2 2. + <_> + 13 11 1 2 2. + <_> + + <_> + 19 11 1 9 -1. + <_> + 19 14 1 3 3. + <_> + + <_> + 6 6 14 14 -1. + <_> + 6 13 14 7 2. + <_> + + <_> + 2 17 4 2 -1. + <_> + 2 18 4 1 2. + <_> + + <_> + 0 2 1 3 -1. + <_> + 0 3 1 1 3. + <_> + + <_> + 0 12 1 3 -1. + <_> + 0 13 1 1 3. + <_> + + <_> + 15 15 4 4 -1. + <_> + 15 17 4 2 2. + <_> + + <_> + 2 5 18 7 -1. + <_> + 8 5 6 7 3. + <_> + + <_> + 1 16 5 3 -1. + <_> + 1 17 5 1 3. + <_> + + <_> + 0 4 2 3 -1. + <_> + 0 5 2 1 3. + <_> + + <_> + 0 6 2 6 -1. + <_> + 1 6 1 6 2. + <_> + + <_> + 16 14 4 3 -1. + <_> + 16 15 4 1 3. + <_> + + <_> + 0 0 10 6 -1. + <_> + 0 0 5 3 2. + <_> + 5 3 5 3 2. + <_> + + <_> + 2 2 3 6 -1. + <_> + 3 2 1 6 3. + <_> + + <_> + 2 0 3 10 -1. + <_> + 3 0 1 10 3. + <_> + + <_> + 5 5 2 2 -1. + <_> + 5 6 2 1 2. + <_> + + <_> + 12 6 4 4 -1. + <_> + 12 8 4 2 2. + <_> + + <_> + 13 5 7 3 -1. + <_> + 13 6 7 1 3. + <_> + + <_> + 10 13 1 2 -1. + <_> + 10 14 1 1 2. + <_> + + <_> + 16 16 4 2 -1. + <_> + 18 16 2 2 2. + <_> + + <_> + 16 12 4 7 -1. + <_> + 18 12 2 7 2. + <_> + + <_> + 16 17 1 3 -1. + <_> + 16 18 1 1 3. + <_> + + <_> + 19 9 1 3 -1. + <_> + 19 10 1 1 3. + <_> + + <_> + 18 7 2 6 -1. + <_> + 19 7 1 6 2. + <_> + + <_> + 8 1 3 4 -1. + <_> + 9 1 1 4 3. + <_> + + <_> + 14 0 6 9 -1. + <_> + 16 0 2 9 3. + <_> + + <_> + 4 2 10 2 -1. + <_> + 9 2 5 2 2. + <_> + + <_> + 2 12 8 4 -1. + <_> + 2 12 4 2 2. + <_> + 6 14 4 2 2. + <_> + + <_> + 0 4 7 3 -1. + <_> + 0 5 7 1 3. + <_> + + <_> + 14 14 3 3 -1. + <_> + 15 14 1 3 3. + <_> + + <_> + 0 3 4 3 -1. + <_> + 2 3 2 3 2. + <_> + + <_> + 1 0 2 7 -1. + <_> + 2 0 1 7 2. + <_> + + <_> + 15 16 4 4 -1. + <_> + 15 18 4 2 2. + <_> + + <_> + 5 8 12 4 -1. + <_> + 5 10 12 2 2. + <_> + + <_> + 3 17 1 2 -1. + <_> + 3 18 1 1 2. + <_> + + <_> + 6 1 3 4 -1. + <_> + 7 1 1 4 3. + <_> + + <_> + 6 2 3 4 -1. + <_> + 7 2 1 4 3. + <_> + + <_> + 6 8 9 12 -1. + <_> + 9 8 3 12 3. + <_> + + <_> + 8 1 8 6 -1. + <_> + 8 3 8 2 3. + <_> + + <_> + 14 2 6 3 -1. + <_> + 17 2 3 3 2. + <_> + + <_> + 0 6 1 3 -1. + <_> + 0 7 1 1 3. + <_> + + <_> + 10 0 10 2 -1. + <_> + 15 0 5 2 2. + <_> + + <_> + 11 0 3 2 -1. + <_> + 12 0 1 2 3. + <_> + + <_> + 3 19 10 1 -1. + <_> + 8 19 5 1 2. + <_> + + <_> + 0 4 7 16 -1. + <_> + 0 12 7 8 2. + <_> + + <_> + 2 16 1 3 -1. + <_> + 2 17 1 1 3. + <_> + + <_> + 7 8 12 6 -1. + <_> + 11 8 4 6 3. + <_> + + <_> + 14 9 6 7 -1. + <_> + 16 9 2 7 3. + <_> + + <_> + 12 17 6 1 -1. + <_> + 14 17 2 1 3. + <_> + + <_> + 16 1 3 1 -1. + <_> + 17 1 1 1 3. + <_> + + <_> + 0 17 8 2 -1. + <_> + 0 17 4 1 2. + <_> + 4 18 4 1 2. + <_> + + <_> + 17 0 2 1 -1. + <_> + 18 0 1 1 2. + <_> + + <_> + 4 15 6 5 -1. + <_> + 6 15 2 5 3. + <_> + + <_> + 7 2 8 2 -1. + <_> + 7 3 8 1 2. + <_> + + <_> + 4 1 8 4 -1. + <_> + 4 3 8 2 2. + <_> + + <_> + 5 19 2 1 -1. + <_> + 6 19 1 1 2. + <_> + + <_> + 5 19 2 1 -1. + <_> + 6 19 1 1 2. + <_> + + <_> + 16 17 1 3 -1. + <_> + 16 18 1 1 3. + <_> + + <_> + 0 11 2 3 -1. + <_> + 1 11 1 3 2. + <_> + + <_> + 0 19 4 1 -1. + <_> + 2 19 2 1 2. + <_> + + <_> + 0 18 4 2 -1. + <_> + 2 18 2 2 2. + <_> + + <_> + 2 17 1 3 -1. + <_> + 2 18 1 1 3. + <_> + + <_> + 5 7 11 2 -1. + <_> + 5 8 11 1 2. + <_> + + <_> + 9 2 4 10 -1. + <_> + 9 7 4 5 2. + <_> + + <_> + 0 2 4 3 -1. + <_> + 0 3 4 1 3. + <_> + + <_> + 10 19 10 1 -1. + <_> + 15 19 5 1 2. + <_> + + <_> + 11 17 8 3 -1. + <_> + 15 17 4 3 2. + <_> + + <_> + 8 19 3 1 -1. + <_> + 9 19 1 1 3. + <_> + + <_> + 14 0 3 4 -1. + <_> + 15 0 1 4 3. + <_> + + <_> + 10 6 4 3 -1. + <_> + 10 7 4 1 3. + <_> + + <_> + 0 8 3 2 -1. + <_> + 0 9 3 1 2. + <_> + + <_> + 7 12 3 6 -1. + <_> + 7 14 3 2 3. + <_> + + <_> + 1 18 1 2 -1. + <_> + 1 19 1 1 2. + <_> + + <_> + 0 12 4 4 -1. + <_> + 2 12 2 4 2. + <_> + + <_> + 1 8 6 7 -1. + <_> + 3 8 2 7 3. + <_> + + <_> + 0 8 4 5 -1. + <_> + 2 8 2 5 2. + <_> + + <_> + 19 16 1 3 -1. + <_> + 19 17 1 1 3. + <_> + + <_> + 1 5 18 6 -1. + <_> + 7 5 6 6 3. + <_> + + <_> + 2 15 4 2 -1. + <_> + 2 16 4 1 2. + <_> + + <_> + 18 6 2 11 -1. + <_> + 19 6 1 11 2. + <_> + + <_> + 0 12 2 6 -1. + <_> + 0 14 2 2 3. + <_> + + <_> + 12 5 3 2 -1. + <_> + 12 6 3 1 2. + <_> + + <_> + 1 3 2 3 -1. + <_> + 1 4 2 1 3. + <_> + + <_> + 16 14 4 4 -1. + <_> + 16 16 4 2 2. + <_> + + <_> + 6 8 12 5 -1. + <_> + 10 8 4 5 3. + <_> + + <_> + 13 7 2 7 -1. + <_> + 14 7 1 7 2. + <_> + + <_> + 1 8 2 6 -1. + <_> + 2 8 1 6 2. + <_> + + <_> + 15 0 3 7 -1. + <_> + 16 0 1 7 3. + <_> + + <_> + 4 2 6 2 -1. + <_> + 6 2 2 2 3. + <_> + + <_> + 0 9 20 9 -1. + <_> + 0 12 20 3 3. + <_> + + <_> + 10 14 2 2 -1. + <_> + 10 15 2 1 2. + <_> + + <_> + 6 5 10 4 -1. + <_> + 6 7 10 2 2. + <_> + + <_> + 6 1 5 9 -1. + <_> + 6 4 5 3 3. + <_> + + <_> + 16 18 2 2 -1. + <_> + 16 18 1 1 2. + <_> + 17 19 1 1 2. + <_> + + <_> + 0 14 2 4 -1. + <_> + 0 16 2 2 2. + <_> + + <_> + 10 8 2 5 -1. + <_> + 11 8 1 5 2. + <_> + + <_> + 3 7 12 7 -1. + <_> + 7 7 4 7 3. + <_> + + <_> + 0 0 6 6 -1. + <_> + 3 0 3 6 2. + <_> + + <_> + 1 0 4 4 -1. + <_> + 3 0 2 4 2. + <_> + + <_> + 0 0 6 8 -1. + <_> + 2 0 2 8 3. + <_> + + <_> + 0 0 2 1 -1. + <_> + 1 0 1 1 2. + <_> + + <_> + 0 0 3 3 -1. + <_> + 0 1 3 1 3. + <_> + + <_> + 5 4 2 4 -1. + <_> + 5 6 2 2 2. + <_> + + <_> + 2 10 9 1 -1. + <_> + 5 10 3 1 3. + <_> + + <_> + 1 17 1 3 -1. + <_> + 1 18 1 1 3. + <_> + + <_> + 0 17 2 3 -1. + <_> + 0 18 2 1 3. + <_> + + <_> + 0 15 16 3 -1. + <_> + 8 15 8 3 2. + <_> + + <_> + 0 5 4 1 -1. + <_> + 2 5 2 1 2. + <_> + + <_> + 1 0 6 20 -1. + <_> + 3 0 2 20 3. + <_> + + <_> + 2 5 4 6 -1. + <_> + 2 5 2 3 2. + <_> + 4 8 2 3 2. + <_> + + <_> + 9 16 6 3 -1. + <_> + 11 16 2 3 3. + <_> + + <_> + 11 17 6 1 -1. + <_> + 14 17 3 1 2. + <_> + + <_> + 3 17 15 2 -1. + <_> + 8 17 5 2 3. + <_> + + <_> + 18 0 2 3 -1. + <_> + 18 1 2 1 3. + <_> + + <_> + 13 1 7 4 -1. + <_> + 13 3 7 2 2. + <_> + + <_> + 13 6 4 4 -1. + <_> + 13 6 2 2 2. + <_> + 15 8 2 2 2. + <_> + + <_> + 17 6 3 4 -1. + <_> + 17 8 3 2 2. + <_> + + <_> + 14 9 2 2 -1. + <_> + 15 9 1 2 2. + <_> + + <_> + 17 17 1 3 -1. + <_> + 17 18 1 1 3. + <_> + + <_> + 3 19 8 1 -1. + <_> + 7 19 4 1 2. + <_> + + <_> + 0 9 3 6 -1. + <_> + 0 12 3 3 2. + <_> + + <_> + 4 7 15 5 -1. + <_> + 9 7 5 5 3. + <_> + + <_> + 6 9 9 5 -1. + <_> + 9 9 3 5 3. + <_> + + <_> + 8 1 6 2 -1. + <_> + 10 1 2 2 3. + <_> + + <_> + 4 0 12 2 -1. + <_> + 10 0 6 2 2. + <_> + + <_> + 7 0 10 3 -1. + <_> + 12 0 5 3 2. + <_> + + <_> + 5 0 9 6 -1. + <_> + 5 2 9 2 3. + <_> + + <_> + 8 3 6 4 -1. + <_> + 8 5 6 2 2. + <_> + + <_> + 17 4 2 3 -1. + <_> + 17 5 2 1 3. + <_> + + <_> + 5 2 4 3 -1. + <_> + 5 3 4 1 3. + <_> + + <_> + 5 9 2 6 -1. + <_> + 6 9 1 6 2. + <_> + + <_> + 14 10 2 6 -1. + <_> + 15 10 1 6 2. + <_> + + <_> + 7 4 3 3 -1. + <_> + 7 5 3 1 3. + <_> + + <_> + 12 4 8 2 -1. + <_> + 12 4 4 1 2. + <_> + 16 5 4 1 2. + <_> + + <_> + 15 8 1 6 -1. + <_> + 15 10 1 2 3. + <_> + + <_> + 4 17 11 3 -1. + <_> + 4 18 11 1 3. + <_> + + <_> + 3 0 16 20 -1. + <_> + 3 10 16 10 2. + <_> + + <_> + 12 4 4 6 -1. + <_> + 12 6 4 2 3. + <_> + + <_> + 11 0 6 6 -1. + <_> + 13 0 2 6 3. + <_> + + <_> + 13 1 6 4 -1. + <_> + 13 1 3 2 2. + <_> + 16 3 3 2 2. + <_> + + <_> + 11 0 6 4 -1. + <_> + 13 0 2 4 3. + <_> + + <_> + 8 6 6 9 -1. + <_> + 10 6 2 9 3. + <_> + + <_> + 7 0 3 4 -1. + <_> + 8 0 1 4 3. + <_> + + <_> + 0 17 14 2 -1. + <_> + 0 17 7 1 2. + <_> + 7 18 7 1 2. + <_> + + <_> + 6 18 2 2 -1. + <_> + 6 18 1 1 2. + <_> + 7 19 1 1 2. + <_> + + <_> + 18 17 1 3 -1. + <_> + 18 18 1 1 3. + <_> + + <_> + 17 18 2 2 -1. + <_> + 17 18 1 1 2. + <_> + 18 19 1 1 2. + <_> + + <_> + 5 7 1 9 -1. + <_> + 5 10 1 3 3. + <_> + + <_> + 5 3 6 4 -1. + <_> + 7 3 2 4 3. + <_> + + <_> + 1 9 6 2 -1. + <_> + 1 9 3 1 2. + <_> + 4 10 3 1 2. + <_> + + <_> + 6 9 2 3 -1. + <_> + 7 9 1 3 2. + <_> + + <_> + 6 8 6 12 -1. + <_> + 8 8 2 12 3. + <_> + + <_> + 4 18 2 2 -1. + <_> + 4 18 1 1 2. + <_> + 5 19 1 1 2. + <_> + + <_> + 9 1 6 6 -1. + <_> + 9 3 6 2 3. + <_> + + <_> + 6 17 6 2 -1. + <_> + 6 18 6 1 2. + <_> + + <_> + 3 18 16 2 -1. + <_> + 3 19 16 1 2. + <_> + + <_> + 3 0 3 11 -1. + <_> + 4 0 1 11 3. + <_> + + <_> + 13 18 3 1 -1. + <_> + 14 18 1 1 3. + <_> + + <_> + 6 0 9 6 -1. + <_> + 6 2 9 2 3. + <_> + + <_> + 1 2 12 4 -1. + <_> + 1 2 6 2 2. + <_> + 7 4 6 2 2. + <_> + + <_> + 3 3 6 4 -1. + <_> + 5 3 2 4 3. + <_> + + <_> + 12 0 8 1 -1. + <_> + 16 0 4 1 2. + <_> + + <_> + 9 0 6 2 -1. + <_> + 11 0 2 2 3. + <_> + + <_> + 3 3 12 1 -1. + <_> + 9 3 6 1 2. + <_> + + <_> + 2 7 6 2 -1. + <_> + 2 7 3 1 2. + <_> + 5 8 3 1 2. + <_> + + <_> + 0 8 4 6 -1. + <_> + 0 10 4 2 3. + <_> + + <_> + 9 6 3 7 -1. + <_> + 10 6 1 7 3. + <_> + + <_> + 9 6 6 13 -1. + <_> + 11 6 2 13 3. + <_> + + <_> + 11 12 6 1 -1. + <_> + 13 12 2 1 3. + <_> + + <_> + 18 9 2 6 -1. + <_> + 18 12 2 3 2. + <_> + + <_> + 17 2 3 9 -1. + <_> + 18 2 1 9 3. + <_> + + <_> + 13 8 4 6 -1. + <_> + 13 8 2 3 2. + <_> + 15 11 2 3 2. + <_> + + <_> + 4 2 12 6 -1. + <_> + 10 2 6 6 2. + <_> + + <_> + 4 14 16 6 -1. + <_> + 12 14 8 6 2. + <_> + + <_> + 6 19 10 1 -1. + <_> + 11 19 5 1 2. + <_> + + <_> + 6 17 1 3 -1. + <_> + 6 18 1 1 3. + <_> + + <_> + 4 14 10 3 -1. + <_> + 4 15 10 1 3. + <_> + + <_> + 6 0 12 12 -1. + <_> + 6 4 12 4 3. + <_> + + <_> + 5 7 4 2 -1. + <_> + 5 7 2 1 2. + <_> + 7 8 2 1 2. + <_> + + <_> + 17 5 3 2 -1. + <_> + 18 5 1 2 3. + <_> + + <_> + 8 13 6 3 -1. + <_> + 8 14 6 1 3. + <_> + + <_> + 8 13 5 3 -1. + <_> + 8 14 5 1 3. + <_> + + <_> + 13 2 1 18 -1. + <_> + 13 11 1 9 2. + <_> + + <_> + 6 10 9 2 -1. + <_> + 9 10 3 2 3. + <_> + + <_> + 11 0 7 4 -1. + <_> + 11 2 7 2 2. + <_> + + <_> + 1 0 6 8 -1. + <_> + 3 0 2 8 3. + <_> + + <_> + 9 15 3 3 -1. + <_> + 9 16 3 1 3. + <_> + + <_> + 9 17 9 3 -1. + <_> + 9 18 9 1 3. + <_> + + <_> + 12 12 3 3 -1. + <_> + 12 13 3 1 3. + <_> + + <_> + 4 1 3 5 -1. + <_> + 5 1 1 5 3. + <_> + + <_> + 10 14 2 3 -1. + <_> + 10 15 2 1 3. + <_> + + <_> + 18 17 2 2 -1. + <_> + 18 17 1 1 2. + <_> + 19 18 1 1 2. + <_> + + <_> + 18 18 2 2 -1. + <_> + 18 18 1 1 2. + <_> + 19 19 1 1 2. + <_> + + <_> + 18 18 2 2 -1. + <_> + 18 18 1 1 2. + <_> + 19 19 1 1 2. + <_> + + <_> + 4 10 9 1 -1. + <_> + 7 10 3 1 3. + <_> + + <_> + 3 9 6 5 -1. + <_> + 5 9 2 5 3. + <_> + + <_> + 18 8 1 12 -1. + <_> + 18 14 1 6 2. + <_> + + <_> + 0 2 8 6 -1. + <_> + 0 2 4 3 2. + <_> + 4 5 4 3 2. + <_> + + <_> + 9 4 3 3 -1. + <_> + 9 5 3 1 3. + <_> + + <_> + 3 18 2 2 -1. + <_> + 3 18 1 1 2. + <_> + 4 19 1 1 2. + <_> + + <_> + 6 4 4 3 -1. + <_> + 6 5 4 1 3. + <_> + + <_> + 16 7 4 2 -1. + <_> + 16 7 2 1 2. + <_> + 18 8 2 1 2. + <_> + + <_> + 5 17 1 3 -1. + <_> + 5 18 1 1 3. + <_> + + <_> + 2 0 15 20 -1. + <_> + 2 10 15 10 2. + <_> + + <_> + 8 11 6 4 -1. + <_> + 8 11 3 2 2. + <_> + 11 13 3 2 2. + <_> + + <_> + 8 16 4 3 -1. + <_> + 8 17 4 1 3. + <_> + + <_> + 8 18 2 2 -1. + <_> + 8 18 1 1 2. + <_> + 9 19 1 1 2. + <_> + + <_> + 2 16 13 3 -1. + <_> + 2 17 13 1 3. + <_> + + <_> + 16 16 2 2 -1. + <_> + 16 16 1 1 2. + <_> + 17 17 1 1 2. + <_> + + <_> + 8 1 6 3 -1. + <_> + 10 1 2 3 3. + <_> + + <_> + 16 7 2 2 -1. + <_> + 16 7 1 1 2. + <_> + 17 8 1 1 2. + <_> + + <_> + 14 7 4 2 -1. + <_> + 14 7 2 1 2. + <_> + 16 8 2 1 2. + <_> + + <_> + 4 0 14 1 -1. + <_> + 11 0 7 1 2. + <_> + + <_> + 10 4 8 2 -1. + <_> + 10 4 4 1 2. + <_> + 14 5 4 1 2. + <_> + + <_> + 8 2 3 2 -1. + <_> + 9 2 1 2 3. + <_> + + <_> + 12 11 6 3 -1. + <_> + 12 12 6 1 3. + <_> + + <_> + 1 5 1 4 -1. + <_> + 1 7 1 2 2. + <_> + + <_> + 1 1 1 18 -1. + <_> + 1 7 1 6 3. + <_> + + <_> + 11 13 3 2 -1. + <_> + 11 14 3 1 2. + <_> + + <_> + 0 1 12 2 -1. + <_> + 0 1 6 1 2. + <_> + 6 2 6 1 2. + <_> + + <_> + 10 18 2 2 -1. + <_> + 10 18 1 1 2. + <_> + 11 19 1 1 2. + <_> + + <_> + 4 5 4 4 -1. + <_> + 4 5 2 2 2. + <_> + 6 7 2 2 2. + <_> + + <_> + 6 7 1 3 -1. + <_> + 6 8 1 1 3. + <_> + + <_> + 14 10 6 2 -1. + <_> + 16 10 2 2 3. + <_> + + <_> + 16 8 3 6 -1. + <_> + 17 8 1 6 3. + <_> + + <_> + 4 10 6 2 -1. + <_> + 6 10 2 2 3. + <_> + + <_> + 6 5 3 7 -1. + <_> + 7 5 1 7 3. + <_> + + <_> + 0 13 6 6 -1. + <_> + 0 16 6 3 2. + <_> + + <_> + 12 5 1 9 -1. + <_> + 12 8 1 3 3. + <_> + + <_> + 5 9 3 3 -1. + <_> + 6 9 1 3 3. + <_> + + <_> + 7 5 6 13 -1. + <_> + 9 5 2 13 3. + <_> + + <_> + 19 8 1 10 -1. + <_> + 19 13 1 5 2. + <_> + + <_> + 11 18 6 1 -1. + <_> + 13 18 2 1 3. + <_> + + <_> + 9 7 6 12 -1. + <_> + 11 7 2 12 3. + <_> + + <_> + 12 7 6 6 -1. + <_> + 14 7 2 6 3. + <_> + + <_> + 15 8 3 4 -1. + <_> + 16 8 1 4 3. + <_> + + <_> + 6 11 4 2 -1. + <_> + 6 12 4 1 2. + <_> + + <_> + 1 6 6 8 -1. + <_> + 3 6 2 8 3. + <_> + + <_> + 11 15 6 5 -1. + <_> + 13 15 2 5 3. + <_> + + <_> + 15 17 4 2 -1. + <_> + 15 18 4 1 2. + <_> + + <_> + 13 11 6 1 -1. + <_> + 15 11 2 1 3. + <_> + + <_> + 5 18 2 2 -1. + <_> + 5 18 1 1 2. + <_> + 6 19 1 1 2. + <_> + + <_> + 4 8 4 4 -1. + <_> + 4 8 2 2 2. + <_> + 6 10 2 2 2. + <_> + + <_> + 11 7 9 3 -1. + <_> + 11 8 9 1 3. + <_> + + <_> + 0 3 10 4 -1. + <_> + 0 3 5 2 2. + <_> + 5 5 5 2 2. + <_> + + <_> + 7 18 6 1 -1. + <_> + 9 18 2 1 3. + <_> + + <_> + 0 8 3 3 -1. + <_> + 0 9 3 1 3. + <_> + + <_> + 0 0 6 8 -1. + <_> + 0 0 3 4 2. + <_> + 3 4 3 4 2. + <_> + + <_> + 7 6 3 8 -1. + <_> + 8 6 1 8 3. + <_> + + <_> + 13 7 7 3 -1. + <_> + 13 8 7 1 3. + <_> + + <_> + 3 3 2 2 -1. + <_> + 3 4 2 1 2. + <_> + + <_> + 0 3 3 3 -1. + <_> + 0 4 3 1 3. + <_> + + <_> + 9 3 5 2 -1. + <_> + 9 4 5 1 2. + <_> + + <_> + 6 5 9 4 -1. + <_> + 9 5 3 4 3. + <_> + + <_> + 3 10 12 3 -1. + <_> + 7 10 4 3 3. + <_> + + <_> + 8 7 3 6 -1. + <_> + 9 7 1 6 3. + <_> + + <_> + 5 5 6 5 -1. + <_> + 8 5 3 5 2. + <_> + + <_> + 0 5 2 3 -1. + <_> + 0 6 2 1 3. + <_> + + <_> + 9 7 3 4 -1. + <_> + 10 7 1 4 3. + <_> + + <_> + 1 0 6 15 -1. + <_> + 3 0 2 15 3. + <_> + + <_> + 15 1 3 5 -1. + <_> + 16 1 1 5 3. + <_> + + <_> + 9 2 3 10 -1. + <_> + 10 2 1 10 3. + <_> + + <_> + 8 8 6 12 -1. + <_> + 10 8 2 12 3. + <_> + + <_> + 16 4 3 4 -1. + <_> + 16 6 3 2 2. + <_> + + <_> + 16 7 2 2 -1. + <_> + 16 7 1 1 2. + <_> + 17 8 1 1 2. + <_> + + <_> + 13 0 6 9 -1. + <_> + 13 3 6 3 3. + <_> + + <_> + 7 17 1 3 -1. + <_> + 7 18 1 1 3. + <_> + + <_> + 12 1 4 2 -1. + <_> + 12 2 4 1 2. + <_> + + <_> + 17 3 1 3 -1. + <_> + 17 4 1 1 3. + <_> + + <_> + 0 16 9 3 -1. + <_> + 0 17 9 1 3. + <_> + + <_> + 3 6 2 4 -1. + <_> + 3 6 1 2 2. + <_> + 4 8 1 2 2. + <_> + + <_> + 13 18 3 1 -1. + <_> + 14 18 1 1 3. + <_> + + <_> + 0 18 4 2 -1. + <_> + 2 18 2 2 2. + <_> + + <_> + 1 19 2 1 -1. + <_> + 2 19 1 1 2. + <_> + + <_> + 0 18 4 2 -1. + <_> + 0 19 4 1 2. + <_> + + <_> + 2 17 1 3 -1. + <_> + 2 18 1 1 3. + <_> + + <_> + 4 8 3 5 -1. + <_> + 5 8 1 5 3. + <_> + + <_> + 2 1 6 7 -1. + <_> + 4 1 2 7 3. + <_> + + <_> + 3 6 2 8 -1. + <_> + 3 6 1 4 2. + <_> + 4 10 1 4 2. + <_> + + <_> + 4 5 11 10 -1. + <_> + 4 10 11 5 2. + <_> + + <_> + 0 13 20 2 -1. + <_> + 10 13 10 2 2. + <_> + + <_> + 1 13 16 3 -1. + <_> + 9 13 8 3 2. + <_> + + <_> + 16 4 4 4 -1. + <_> + 16 4 2 2 2. + <_> + 18 6 2 2 2. + <_> + + <_> + 16 0 4 12 -1. + <_> + 16 0 2 6 2. + <_> + 18 6 2 6 2. + <_> + + <_> + 14 15 3 1 -1. + <_> + 15 15 1 1 3. + <_> + + <_> + 3 4 12 10 -1. + <_> + 3 9 12 5 2. + <_> + + <_> + 9 18 2 2 -1. + <_> + 9 18 1 1 2. + <_> + 10 19 1 1 2. + <_> + + <_> + 9 18 2 2 -1. + <_> + 9 18 1 1 2. + <_> + 10 19 1 1 2. + <_> + + <_> + 13 4 2 14 -1. + <_> + 13 4 1 7 2. + <_> + 14 11 1 7 2. + <_> + + <_> + 4 2 6 4 -1. + <_> + 7 2 3 4 2. + <_> + + <_> + 0 0 18 20 -1. + <_> + 0 0 9 10 2. + <_> + 9 10 9 10 2. + <_> + + <_> + 15 11 1 2 -1. + <_> + 15 12 1 1 2. + <_> + + <_> + 16 10 2 4 -1. + <_> + 16 10 1 2 2. + <_> + 17 12 1 2 2. + <_> + + <_> + 18 17 2 2 -1. + <_> + 18 17 1 1 2. + <_> + 19 18 1 1 2. + <_> + + <_> + 9 17 1 2 -1. + <_> + 9 18 1 1 2. + <_> + + <_> + 8 4 9 6 -1. + <_> + 11 4 3 6 3. + <_> + + <_> + 6 9 9 10 -1. + <_> + 9 9 3 10 3. + <_> + + <_> + 5 0 5 4 -1. + <_> + 5 2 5 2 2. + <_> + + <_> + 5 7 11 4 -1. + <_> + 5 9 11 2 2. + <_> + + <_> + 2 4 2 14 -1. + <_> + 3 4 1 14 2. + <_> + + <_> + 8 6 3 5 -1. + <_> + 9 6 1 5 3. + <_> + + <_> + 8 4 3 9 -1. + <_> + 9 4 1 9 3. + <_> + + <_> + 0 8 20 6 -1. + <_> + 0 10 20 2 3. + <_> + + <_> + 14 16 6 1 -1. + <_> + 17 16 3 1 2. + <_> + + <_> + 17 18 2 2 -1. + <_> + 17 19 2 1 2. + <_> + + <_> + 8 17 6 3 -1. + <_> + 10 17 2 3 3. + <_> + + <_> + 4 1 9 15 -1. + <_> + 7 1 3 15 3. + <_> + + <_> + 11 5 3 12 -1. + <_> + 12 5 1 12 3. + <_> + + <_> + 0 15 4 3 -1. + <_> + 0 16 4 1 3. + <_> + + <_> + 0 0 15 1 -1. + <_> + 5 0 5 1 3. + <_> + + <_> + 6 0 6 4 -1. + <_> + 8 0 2 4 3. + <_> + + <_> + 2 0 9 3 -1. + <_> + 5 0 3 3 3. + <_> + + <_> + 13 6 3 7 -1. + <_> + 14 6 1 7 3. + <_> + + <_> + 7 6 4 2 -1. + <_> + 7 7 4 1 2. + <_> + + <_> + 6 18 6 1 -1. + <_> + 8 18 2 1 3. + <_> + + <_> + 18 6 2 2 -1. + <_> + 18 7 2 1 2. + <_> + + <_> + 6 4 7 3 -1. + <_> + 6 5 7 1 3. + <_> + + <_> + 12 7 3 1 -1. + <_> + 13 7 1 1 3. + <_> + + <_> + 15 1 2 10 -1. + <_> + 15 1 1 5 2. + <_> + 16 6 1 5 2. + <_> + + <_> + 0 18 2 2 -1. + <_> + 0 19 2 1 2. + <_> + + <_> + 19 4 1 8 -1. + <_> + 19 8 1 4 2. + <_> + + <_> + 1 17 1 3 -1. + <_> + 1 18 1 1 3. + <_> + + <_> + 0 15 6 4 -1. + <_> + 0 15 3 2 2. + <_> + 3 17 3 2 2. + <_> + + <_> + 19 0 1 18 -1. + <_> + 19 6 1 6 3. + <_> + + <_> + 10 2 6 2 -1. + <_> + 12 2 2 2 3. + <_> + + <_> + 2 8 12 2 -1. + <_> + 6 8 4 2 3. + <_> + + <_> + 16 0 4 1 -1. + <_> + 18 0 2 1 2. + <_> + + <_> + 8 4 2 6 -1. + <_> + 8 7 2 3 2. + <_> + + <_> + 14 5 2 10 -1. + <_> + 15 5 1 10 2. + <_> + + <_> + 13 4 2 2 -1. + <_> + 13 5 2 1 2. + <_> + + <_> + 11 1 3 6 -1. + <_> + 11 3 3 2 3. + <_> + + <_> + 6 9 12 2 -1. + <_> + 10 9 4 2 3. + <_> + + <_> + 9 16 4 2 -1. + <_> + 9 17 4 1 2. + <_> + + <_> + 5 14 15 4 -1. + <_> + 5 16 15 2 2. + <_> + + <_> + 18 16 2 2 -1. + <_> + 18 17 2 1 2. + <_> + + <_> + 16 18 2 2 -1. + <_> + 16 18 1 1 2. + <_> + 17 19 1 1 2. + <_> + + <_> + 6 4 3 8 -1. + <_> + 7 4 1 8 3. + <_> + + <_> + 5 9 3 1 -1. + <_> + 6 9 1 1 3. + <_> + + <_> + 0 8 1 6 -1. + <_> + 0 10 1 2 3. + <_> + + <_> + 11 2 9 6 -1. + <_> + 14 2 3 6 3. + <_> + + <_> + 12 2 6 4 -1. + <_> + 14 2 2 4 3. + <_> + + <_> + 1 7 2 4 -1. + <_> + 1 9 2 2 2. + <_> + + <_> + 13 1 6 4 -1. + <_> + 13 3 6 2 2. + <_> + + <_> + 4 10 2 10 -1. + <_> + 4 10 1 5 2. + <_> + 5 15 1 5 2. + <_> + + <_> + 2 16 9 3 -1. + <_> + 5 16 3 3 3. + <_> + + <_> + 1 2 3 9 -1. + <_> + 2 2 1 9 3. + <_> + + <_> + 19 7 1 4 -1. + <_> + 19 9 1 2 2. + <_> + + <_> + 14 11 6 8 -1. + <_> + 14 11 3 4 2. + <_> + 17 15 3 4 2. + <_> + + <_> + 15 12 4 6 -1. + <_> + 15 12 2 3 2. + <_> + 17 15 2 3 2. + <_> + + <_> + 16 15 2 2 -1. + <_> + 16 15 1 1 2. + <_> + 17 16 1 1 2. + <_> + + <_> + 17 16 2 2 -1. + <_> + 17 16 1 1 2. + <_> + 18 17 1 1 2. + <_> + + <_> + 17 16 2 2 -1. + <_> + 17 16 1 1 2. + <_> + 18 17 1 1 2. + <_> + + <_> + 2 3 2 2 -1. + <_> + 2 3 1 1 2. + <_> + 3 4 1 1 2. + <_> + + <_> + 10 10 3 3 -1. + <_> + 11 10 1 3 3. + <_> + + <_> + 5 9 7 8 -1. + <_> + 5 13 7 4 2. + <_> + + <_> + 7 16 2 2 -1. + <_> + 7 16 1 1 2. + <_> + 8 17 1 1 2. + <_> + + <_> + 7 16 2 2 -1. + <_> + 7 16 1 1 2. + <_> + 8 17 1 1 2. + <_> + + <_> + 9 8 10 3 -1. + <_> + 14 8 5 3 2. + <_> + + <_> + 6 7 4 8 -1. + <_> + 6 7 2 4 2. + <_> + 8 11 2 4 2. + <_> + + <_> + 1 6 4 3 -1. + <_> + 1 7 4 1 3. + <_> + + <_> + 6 10 6 10 -1. + <_> + 8 10 2 10 3. + <_> + + <_> + 4 6 3 6 -1. + <_> + 5 6 1 6 3. + <_> + + <_> + 3 10 4 4 -1. + <_> + 3 10 2 2 2. + <_> + 5 12 2 2 2. + <_> + + <_> + 3 10 4 4 -1. + <_> + 3 10 2 2 2. + <_> + 5 12 2 2 2. + <_> + + <_> + 3 10 4 4 -1. + <_> + 3 10 2 2 2. + <_> + 5 12 2 2 2. + <_> + + <_> + 14 8 2 6 -1. + <_> + 15 8 1 6 2. + <_> + + <_> + 3 10 4 4 -1. + <_> + 3 10 2 2 2. + <_> + 5 12 2 2 2. + <_> + + <_> + 3 10 4 4 -1. + <_> + 3 10 2 2 2. + <_> + 5 12 2 2 2. + <_> + + <_> + 12 4 3 9 -1. + <_> + 13 4 1 9 3. + <_> + + <_> + 12 3 1 12 -1. + <_> + 12 7 1 4 3. + <_> + + <_> + 2 0 18 1 -1. + <_> + 8 0 6 1 3. + <_> + + <_> + 10 0 10 6 -1. + <_> + 10 0 5 3 2. + <_> + 15 3 5 3 2. + <_> + + <_> + 18 16 2 2 -1. + <_> + 18 17 2 1 2. + <_> + + <_> + 3 5 4 2 -1. + <_> + 3 5 2 1 2. + <_> + 5 6 2 1 2. + <_> + + <_> + 11 8 3 3 -1. + <_> + 12 8 1 3 3. + <_> + + <_> + 11 7 3 5 -1. + <_> + 12 7 1 5 3. + <_> + + <_> + 3 19 15 1 -1. + <_> + 8 19 5 1 3. + <_> + + <_> + 8 13 3 2 -1. + <_> + 8 14 3 1 2. + <_> + + <_> + 2 12 8 4 -1. + <_> + 2 12 4 2 2. + <_> + 6 14 4 2 2. + <_> + + <_> + 16 16 2 2 -1. + <_> + 16 16 1 1 2. + <_> + 17 17 1 1 2. + <_> + + <_> + 7 0 3 2 -1. + <_> + 8 0 1 2 3. + <_> + + <_> + 6 7 2 5 -1. + <_> + 7 7 1 5 2. + <_> + + <_> + 18 0 2 17 -1. + <_> + 19 0 1 17 2. + <_> + + <_> + 16 16 1 3 -1. + <_> + 16 17 1 1 3. + <_> + + <_> + 14 8 3 7 -1. + <_> + 15 8 1 7 3. + <_> + + <_> + 10 17 2 2 -1. + <_> + 10 17 1 1 2. + <_> + 11 18 1 1 2. + <_> + + <_> + 4 9 1 3 -1. + <_> + 4 10 1 1 3. + <_> + + <_> + 18 10 2 3 -1. + <_> + 18 11 2 1 3. + <_> + + <_> + 12 1 3 10 -1. + <_> + 13 1 1 10 3. + <_> + + <_> + 8 12 9 1 -1. + <_> + 11 12 3 1 3. + <_> + + <_> + 5 18 2 2 -1. + <_> + 5 18 1 1 2. + <_> + 6 19 1 1 2. + <_> + + <_> + 19 6 1 9 -1. + <_> + 19 9 1 3 3. + <_> + + <_> + 4 7 2 4 -1. + <_> + 4 7 1 2 2. + <_> + 5 9 1 2 2. + <_> + + <_> + 1 4 6 14 -1. + <_> + 3 4 2 14 3. + <_> + + <_> + 10 5 9 3 -1. + <_> + 13 5 3 3 3. + <_> + + <_> + 18 7 2 6 -1. + <_> + 18 9 2 2 3. + <_> + + <_> + 5 6 2 7 -1. + <_> + 6 6 1 7 2. + <_> + + <_> + 10 4 6 8 -1. + <_> + 13 4 3 8 2. + <_> + + <_> + 0 8 2 9 -1. + <_> + 0 11 2 3 3. + <_> + + <_> + 0 7 5 3 -1. + <_> + 0 8 5 1 3. + <_> + + <_> + 8 1 7 2 -1. + <_> + 8 2 7 1 2. + <_> + + <_> + 7 5 3 5 -1. + <_> + 8 5 1 5 3. + <_> + + <_> + 19 2 1 2 -1. + <_> + 19 3 1 1 2. + <_> + + <_> + 6 7 10 11 -1. + <_> + 11 7 5 11 2. + <_> + + <_> + 9 19 6 1 -1. + <_> + 11 19 2 1 3. + <_> + + <_> + 3 0 12 1 -1. + <_> + 7 0 4 1 3. + <_> + + <_> + 4 1 6 5 -1. + <_> + 6 1 2 5 3. + <_> + + <_> + 6 12 12 6 -1. + <_> + 10 12 4 6 3. + <_> + + <_> + 16 13 2 3 -1. + <_> + 16 14 2 1 3. + <_> + + <_> + 7 14 4 2 -1. + <_> + 7 15 4 1 2. + <_> + + <_> + 7 14 2 2 -1. + <_> + 7 15 2 1 2. + <_> + + <_> + 3 10 2 4 -1. + <_> + 3 10 1 2 2. + <_> + 4 12 1 2 2. + <_> + + <_> + 0 3 2 6 -1. + <_> + 0 5 2 2 3. + <_> + + <_> + 1 10 2 2 -1. + <_> + 1 10 1 1 2. + <_> + 2 11 1 1 2. + <_> + + <_> + 16 4 4 3 -1. + <_> + 16 5 4 1 3. + <_> + + <_> + 5 10 2 4 -1. + <_> + 5 10 1 2 2. + <_> + 6 12 1 2 2. + <_> + + <_> + 5 11 13 2 -1. + <_> + 5 12 13 1 2. + <_> + + <_> + 10 2 3 11 -1. + <_> + 11 2 1 11 3. + <_> + + <_> + 10 2 4 4 -1. + <_> + 10 4 4 2 2. + <_> + + <_> + 8 8 6 2 -1. + <_> + 10 8 2 2 3. + <_> + + <_> + 11 2 3 3 -1. + <_> + 12 2 1 3 3. + <_> + + <_> + 6 18 14 2 -1. + <_> + 6 18 7 1 2. + <_> + 13 19 7 1 2. + <_> + + <_> + 17 7 1 12 -1. + <_> + 17 11 1 4 3. + <_> + + <_> + 10 5 10 3 -1. + <_> + 10 6 10 1 3. + <_> + + <_> + 6 1 3 3 -1. + <_> + 7 1 1 3 3. + <_> + + <_> + 13 8 3 1 -1. + <_> + 14 8 1 1 3. + <_> + + <_> + 10 14 2 6 -1. + <_> + 10 16 2 2 3. + <_> + + <_> + 4 1 12 14 -1. + <_> + 8 1 4 14 3. + <_> + + <_> + 14 1 6 14 -1. + <_> + 16 1 2 14 3. + <_> + + <_> + 3 16 2 2 -1. + <_> + 3 16 1 1 2. + <_> + 4 17 1 1 2. + <_> + + <_> + 0 16 2 2 -1. + <_> + 0 17 2 1 2. + <_> + + <_> + 15 6 4 6 -1. + <_> + 15 6 2 3 2. + <_> + 17 9 2 3 2. + <_> + + <_> + 12 5 2 2 -1. + <_> + 12 6 2 1 2. + <_> + + <_> + 7 6 6 13 -1. + <_> + 9 6 2 13 3. + <_> + + <_> + 1 9 6 5 -1. + <_> + 3 9 2 5 3. + <_> + + <_> + 0 5 3 4 -1. + <_> + 0 7 3 2 2. + <_> + + <_> + 4 1 16 2 -1. + <_> + 4 1 8 1 2. + <_> + 12 2 8 1 2. + <_> + + <_> + 1 18 4 2 -1. + <_> + 1 18 2 1 2. + <_> + 3 19 2 1 2. + <_> + + <_> + 7 7 3 4 -1. + <_> + 8 7 1 4 3. + <_> + + <_> + 3 4 9 3 -1. + <_> + 6 4 3 3 3. + <_> + + <_> + 4 6 6 10 -1. + <_> + 6 6 2 10 3. + <_> + + <_> + 9 0 8 10 -1. + <_> + 13 0 4 10 2. + <_> + + <_> + 8 0 8 1 -1. + <_> + 12 0 4 1 2. + <_> + + <_> + 6 2 8 16 -1. + <_> + 6 2 4 8 2. + <_> + 10 10 4 8 2. + <_> + + <_> + 14 10 2 10 -1. + <_> + 14 10 1 5 2. + <_> + 15 15 1 5 2. + <_> + + <_> + 12 11 1 2 -1. + <_> + 12 12 1 1 2. + <_> + + <_> + 16 0 3 8 -1. + <_> + 17 0 1 8 3. + <_> + + <_> + 14 0 6 10 -1. + <_> + 17 0 3 10 2. + <_> + + <_> + 16 0 3 5 -1. + <_> + 17 0 1 5 3. + <_> + + <_> + 4 5 11 2 -1. + <_> + 4 6 11 1 2. + <_> + + <_> + 1 0 2 1 -1. + <_> + 2 0 1 1 2. + <_> + + <_> + 0 0 2 3 -1. + <_> + 0 1 2 1 3. + <_> + + <_> + 11 6 6 11 -1. + <_> + 13 6 2 11 3. + <_> + + <_> + 14 0 3 1 -1. + <_> + 15 0 1 1 3. + <_> + + <_> + 19 7 1 2 -1. + <_> + 19 8 1 1 2. + <_> + + <_> + 17 0 3 9 -1. + <_> + 18 0 1 9 3. + <_> + + <_> + 12 7 3 4 -1. + <_> + 13 7 1 4 3. + <_> + + <_> + 0 1 14 2 -1. + <_> + 0 1 7 1 2. + <_> + 7 2 7 1 2. + <_> + + <_> + 3 1 3 2 -1. + <_> + 4 1 1 2 3. + <_> + + <_> + 4 0 15 2 -1. + <_> + 9 0 5 2 3. + <_> + + <_> + 10 2 6 1 -1. + <_> + 12 2 2 1 3. + <_> + + <_> + 9 4 6 11 -1. + <_> + 11 4 2 11 3. + <_> + + <_> + 2 16 2 4 -1. + <_> + 2 18 2 2 2. + <_> + + <_> + 6 17 6 3 -1. + <_> + 8 17 2 3 3. + <_> + + <_> + 7 9 6 2 -1. + <_> + 9 9 2 2 3. + <_> + + <_> + 6 8 9 2 -1. + <_> + 9 8 3 2 3. + <_> + + <_> + 6 6 2 10 -1. + <_> + 6 6 1 5 2. + <_> + 7 11 1 5 2. + <_> + + <_> + 0 11 2 3 -1. + <_> + 0 12 2 1 3. + <_> + + <_> + 11 15 4 1 -1. + <_> + 13 15 2 1 2. + <_> + + <_> + 6 17 1 2 -1. + <_> + 6 18 1 1 2. + <_> + + <_> + 0 0 6 20 -1. + <_> + 2 0 2 20 3. + <_> + + <_> + 3 10 2 2 -1. + <_> + 4 10 1 2 2. + <_> + + <_> + 4 7 3 5 -1. + <_> + 5 7 1 5 3. + <_> + + <_> + 3 12 6 2 -1. + <_> + 5 12 2 2 3. + <_> + + <_> + 6 15 7 4 -1. + <_> + 6 17 7 2 2. + <_> + + <_> + 17 16 2 2 -1. + <_> + 17 16 1 1 2. + <_> + 18 17 1 1 2. + <_> + + <_> + 15 1 3 16 -1. + <_> + 16 1 1 16 3. + <_> + + <_> + 6 16 6 3 -1. + <_> + 8 16 2 3 3. + <_> + + <_> + 15 14 3 2 -1. + <_> + 15 15 3 1 2. + <_> + + <_> + 12 16 1 2 -1. + <_> + 12 17 1 1 2. + <_> + + <_> + 0 2 4 4 -1. + <_> + 0 2 2 2 2. + <_> + 2 4 2 2 2. + <_> + + <_> + 1 1 6 4 -1. + <_> + 1 1 3 2 2. + <_> + 4 3 3 2 2. + <_> + + <_> + 1 18 1 2 -1. + <_> + 1 19 1 1 2. + <_> + + <_> + 4 7 2 3 -1. + <_> + 4 8 2 1 3. + <_> + + <_> + 1 0 9 14 -1. + <_> + 1 7 9 7 2. + <_> + + <_> + 4 9 2 6 -1. + <_> + 4 9 1 3 2. + <_> + 5 12 1 3 2. + <_> + + <_> + 3 9 4 3 -1. + <_> + 5 9 2 3 2. + <_> + + <_> + 0 9 2 4 -1. + <_> + 0 11 2 2 2. + <_> + + <_> + 16 6 3 10 -1. + <_> + 17 6 1 10 3. + <_> + + <_> + 16 11 2 1 -1. + <_> + 17 11 1 1 2. + <_> + + <_> + 5 7 4 4 -1. + <_> + 5 9 4 2 2. + <_> + + <_> + 10 11 9 2 -1. + <_> + 13 11 3 2 3. + <_> + + <_> + 15 10 2 2 -1. + <_> + 15 10 1 1 2. + <_> + 16 11 1 1 2. + <_> + + <_> + 10 6 6 14 -1. + <_> + 10 13 6 7 2. + <_> + + <_> + 14 7 3 5 -1. + <_> + 15 7 1 5 3. + <_> + + <_> + 6 11 12 3 -1. + <_> + 10 11 4 3 3. + <_> + + <_> + 17 16 1 2 -1. + <_> + 17 17 1 1 2. + <_> + + <_> + 8 5 5 4 -1. + <_> + 8 7 5 2 2. + <_> + + <_> + 11 6 4 2 -1. + <_> + 11 7 4 1 2. + <_> + + <_> + 3 4 8 2 -1. + <_> + 3 4 4 1 2. + <_> + 7 5 4 1 2. + <_> + + <_> + 0 8 6 6 -1. + <_> + 2 8 2 6 3. + <_> + + <_> + 7 4 6 2 -1. + <_> + 7 5 6 1 2. + <_> + + <_> + 7 3 6 3 -1. + <_> + 9 3 2 3 3. + <_> + + <_> + 2 17 3 3 -1. + <_> + 2 18 3 1 3. + <_> + + <_> + 3 10 6 1 -1. + <_> + 5 10 2 1 3. + <_> + + <_> + 7 2 6 2 -1. + <_> + 9 2 2 2 3. + <_> + + <_> + 4 11 9 1 -1. + <_> + 7 11 3 1 3. + <_> + + <_> + 7 7 11 12 -1. + <_> + 7 13 11 6 2. + <_> + + <_> + 3 2 3 4 -1. + <_> + 4 2 1 4 3. + <_> + + <_> + 9 7 9 3 -1. + <_> + 12 7 3 3 3. + <_> + + <_> + 15 11 2 6 -1. + <_> + 15 11 1 3 2. + <_> + 16 14 1 3 2. + <_> + + <_> + 0 5 5 3 -1. + <_> + 0 6 5 1 3. + <_> + + <_> + 8 1 6 12 -1. + <_> + 10 1 2 12 3. + <_> + + <_> + 3 7 15 13 -1. + <_> + 8 7 5 13 3. + <_> + + <_> + 0 9 9 9 -1. + <_> + 0 12 9 3 3. + <_> + + <_> + 16 0 3 8 -1. + <_> + 17 0 1 8 3. + <_> + + <_> + 16 2 4 2 -1. + <_> + 18 2 2 2 2. + <_> + + <_> + 13 0 6 5 -1. + <_> + 16 0 3 5 2. + <_> + + <_> + 15 1 3 2 -1. + <_> + 16 1 1 2 3. + <_> + + <_> + 11 8 3 2 -1. + <_> + 12 8 1 2 3. + <_> + + <_> + 1 8 2 12 -1. + <_> + 1 8 1 6 2. + <_> + 2 14 1 6 2. + <_> + + <_> + 0 1 6 12 -1. + <_> + 2 1 2 12 3. + <_> + + <_> + 19 17 1 3 -1. + <_> + 19 18 1 1 3. + <_> + + <_> + 11 3 3 10 -1. + <_> + 12 3 1 10 3. + <_> + + <_> + 8 1 9 8 -1. + <_> + 11 1 3 8 3. + <_> + + <_> + 18 16 2 2 -1. + <_> + 18 16 1 1 2. + <_> + 19 17 1 1 2. + <_> + + <_> + 18 16 2 2 -1. + <_> + 18 16 1 1 2. + <_> + 19 17 1 1 2. + <_> + + <_> + 6 13 2 6 -1. + <_> + 6 15 2 2 3. + <_> + + <_> + 9 14 2 2 -1. + <_> + 9 15 2 1 2. + <_> + + <_> + 14 10 2 4 -1. + <_> + 14 10 1 2 2. + <_> + 15 12 1 2 2. + <_> + + <_> + 0 15 2 2 -1. + <_> + 0 15 1 1 2. + <_> + 1 16 1 1 2. + <_> + + <_> + 6 7 2 2 -1. + <_> + 6 7 1 1 2. + <_> + 7 8 1 1 2. + <_> + + <_> + 11 18 2 2 -1. + <_> + 11 18 1 1 2. + <_> + 12 19 1 1 2. + <_> + + <_> + 0 0 6 4 -1. + <_> + 0 0 3 2 2. + <_> + 3 2 3 2 2. + <_> + + <_> + 4 1 6 6 -1. + <_> + 6 1 2 6 3. + <_> + + <_> + 15 13 5 4 -1. + <_> + 15 15 5 2 2. + <_> + + <_> + 7 17 6 1 -1. + <_> + 9 17 2 1 3. + <_> + + <_> + 16 19 4 1 -1. + <_> + 18 19 2 1 2. + <_> + + <_> + 16 16 4 4 -1. + <_> + 18 16 2 4 2. + <_> + + <_> + 7 8 9 4 -1. + <_> + 10 8 3 4 3. + <_> + + <_> + 16 18 2 2 -1. + <_> + 16 18 1 1 2. + <_> + 17 19 1 1 2. + <_> + + <_> + 2 9 2 4 -1. + <_> + 2 9 1 2 2. + <_> + 3 11 1 2 2. + <_> + + <_> + 0 3 8 4 -1. + <_> + 0 3 4 2 2. + <_> + 4 5 4 2 2. + <_> + + <_> + 0 1 8 1 -1. + <_> + 4 1 4 1 2. + <_> + + <_> + 0 5 8 9 -1. + <_> + 4 5 4 9 2. + <_> + + <_> + 7 18 6 2 -1. + <_> + 9 18 2 2 3. + <_> + + <_> + 0 4 1 12 -1. + <_> + 0 8 1 4 3. + <_> + + <_> + 19 13 1 6 -1. + <_> + 19 15 1 2 3. + <_> + + <_> + 2 8 6 8 -1. + <_> + 4 8 2 8 3. + <_> + + <_> + 0 0 9 17 -1. + <_> + 3 0 3 17 3. + <_> + + <_> + 7 9 6 8 -1. + <_> + 9 9 2 8 3. + <_> + + <_> + 5 10 9 4 -1. + <_> + 8 10 3 4 3. + <_> + + <_> + 5 0 8 3 -1. + <_> + 5 1 8 1 3. + <_> + + <_> + 16 6 4 4 -1. + <_> + 16 6 2 2 2. + <_> + 18 8 2 2 2. + <_> + + <_> + 17 4 2 8 -1. + <_> + 17 4 1 4 2. + <_> + 18 8 1 4 2. + <_> + + <_> + 2 16 1 3 -1. + <_> + 2 17 1 1 3. + <_> + + <_> + 2 16 1 3 -1. + <_> + 2 17 1 1 3. + <_> + + <_> + 11 0 1 3 -1. + <_> + 11 1 1 1 3. + <_> + + <_> + 11 2 9 7 -1. + <_> + 14 2 3 7 3. + <_> + + <_> + 10 2 3 6 -1. + <_> + 11 2 1 6 3. + <_> + + <_> + 5 9 15 2 -1. + <_> + 5 10 15 1 2. + <_> + + <_> + 8 16 6 2 -1. + <_> + 8 17 6 1 2. + <_> + + <_> + 9 16 10 2 -1. + <_> + 9 16 5 1 2. + <_> + 14 17 5 1 2. + <_> + + <_> + 9 17 2 2 -1. + <_> + 9 17 1 1 2. + <_> + 10 18 1 1 2. + <_> + + <_> + 10 15 6 4 -1. + <_> + 10 15 3 2 2. + <_> + 13 17 3 2 2. + <_> + + <_> + 4 5 15 12 -1. + <_> + 9 5 5 12 3. + <_> + + <_> + 11 13 2 3 -1. + <_> + 11 14 2 1 3. + <_> + + <_> + 8 13 7 3 -1. + <_> + 8 14 7 1 3. + <_> + + <_> + 1 12 1 2 -1. + <_> + 1 13 1 1 2. + <_> + + <_> + 16 18 2 2 -1. + <_> + 16 18 1 1 2. + <_> + 17 19 1 1 2. + <_> + + <_> + 1 19 18 1 -1. + <_> + 7 19 6 1 3. + <_> + + <_> + 1 17 6 1 -1. + <_> + 4 17 3 1 2. + <_> + + <_> + 1 3 1 12 -1. + <_> + 1 9 1 6 2. + <_> + + <_> + 0 9 3 6 -1. + <_> + 0 11 3 2 3. + <_> + + <_> + 5 4 3 10 -1. + <_> + 6 4 1 10 3. + <_> + + <_> + 6 17 2 1 -1. + <_> + 7 17 1 1 2. + <_> + + <_> + 1 0 6 12 -1. + <_> + 3 0 2 12 3. + <_> + + <_> + 4 7 9 2 -1. + <_> + 7 7 3 2 3. + <_> + + <_> + 6 11 9 1 -1. + <_> + 9 11 3 1 3. + <_> + + <_> + 17 10 2 10 -1. + <_> + 17 15 2 5 2. + <_> + + <_> + 4 10 2 10 -1. + <_> + 4 10 1 5 2. + <_> + 5 15 1 5 2. + <_> + + <_> + 12 3 3 12 -1. + <_> + 13 3 1 12 3. + <_> + + <_> + 15 3 4 6 -1. + <_> + 15 3 2 3 2. + <_> + 17 6 2 3 2. + <_> + + <_> + 12 8 3 3 -1. + <_> + 13 8 1 3 3. + <_> + + <_> + 4 14 2 4 -1. + <_> + 4 16 2 2 2. + <_> + + <_> + 6 16 1 3 -1. + <_> + 6 17 1 1 3. + <_> + + <_> + 1 1 2 3 -1. + <_> + 2 1 1 3 2. + <_> + + <_> + 0 2 4 1 -1. + <_> + 2 2 2 1 2. + <_> + + <_> + 8 17 12 3 -1. + <_> + 12 17 4 3 3. + <_> + + <_> + 9 16 6 4 -1. + <_> + 11 16 2 4 3. + <_> + + <_> + 4 6 3 6 -1. + <_> + 4 9 3 3 2. + <_> + + <_> + 6 2 12 9 -1. + <_> + 6 5 12 3 3. + <_> + + <_> + 6 0 14 20 -1. + <_> + 6 0 7 10 2. + <_> + 13 10 7 10 2. + <_> + + <_> + 15 16 2 2 -1. + <_> + 15 16 1 1 2. + <_> + 16 17 1 1 2. + <_> + + <_> + 15 16 2 2 -1. + <_> + 15 16 1 1 2. + <_> + 16 17 1 1 2. + <_> + + <_> + 19 8 1 3 -1. + <_> + 19 9 1 1 3. + <_> + + <_> + 13 4 1 2 -1. + <_> + 13 5 1 1 2. + <_> + + <_> + 0 4 4 2 -1. + <_> + 0 5 4 1 2. + <_> + + <_> + 19 5 1 6 -1. + <_> + 19 7 1 2 3. + <_> + + <_> + 16 0 2 1 -1. + <_> + 17 0 1 1 2. + <_> + + <_> + 13 1 1 3 -1. + <_> + 13 2 1 1 3. + <_> + + <_> + 17 17 1 3 -1. + <_> + 17 18 1 1 3. + <_> + + <_> + 5 4 8 8 -1. + <_> + 5 4 4 4 2. + <_> + 9 8 4 4 2. + <_> + + <_> + 1 2 2 2 -1. + <_> + 1 2 1 1 2. + <_> + 2 3 1 1 2. + <_> + + <_> + 0 0 8 6 -1. + <_> + 0 0 4 3 2. + <_> + 4 3 4 3 2. + <_> + + <_> + 6 3 4 2 -1. + <_> + 6 4 4 1 2. + <_> + + <_> + 1 0 3 3 -1. + <_> + 1 1 3 1 3. + <_> + + <_> + 6 1 7 2 -1. + <_> + 6 2 7 1 2. + <_> + + <_> + 2 6 12 6 -1. + <_> + 6 6 4 6 3. + <_> + + <_> + 1 16 9 2 -1. + <_> + 4 16 3 2 3. + <_> + + <_> + 7 15 6 4 -1. + <_> + 9 15 2 4 3. + <_> + + <_> + 6 15 12 1 -1. + <_> + 12 15 6 1 2. + <_> + + <_> + 17 17 1 3 -1. + <_> + 17 18 1 1 3. + <_> + + <_> + 17 15 2 2 -1. + <_> + 17 15 1 1 2. + <_> + 18 16 1 1 2. + <_> + + <_> + 3 13 3 3 -1. + <_> + 3 14 3 1 3. + <_> + + <_> + 10 17 1 3 -1. + <_> + 10 18 1 1 3. + <_> + + <_> + 4 0 14 8 -1. + <_> + 11 0 7 8 2. + <_> + + <_> + 2 0 12 2 -1. + <_> + 6 0 4 2 3. + <_> + + <_> + 2 0 4 3 -1. + <_> + 4 0 2 3 2. + <_> + + <_> + 13 1 1 2 -1. + <_> + 13 2 1 1 2. + <_> + + <_> + 7 5 3 6 -1. + <_> + 8 5 1 6 3. + <_> + + <_> + 18 2 2 2 -1. + <_> + 18 2 1 1 2. + <_> + 19 3 1 1 2. + <_> + + <_> + 15 1 2 14 -1. + <_> + 16 1 1 14 2. + <_> + + <_> + 15 6 2 2 -1. + <_> + 15 6 1 1 2. + <_> + 16 7 1 1 2. + <_> + + <_> + 3 1 6 3 -1. + <_> + 5 1 2 3 3. + <_> + + <_> + 7 16 2 2 -1. + <_> + 7 16 1 1 2. + <_> + 8 17 1 1 2. + <_> + + <_> + 5 17 2 2 -1. + <_> + 5 17 1 1 2. + <_> + 6 18 1 1 2. + <_> + + <_> + 9 10 6 10 -1. + <_> + 11 10 2 10 3. + <_> + + <_> + 10 17 6 3 -1. + <_> + 12 17 2 3 3. + <_> + + <_> + 14 5 2 10 -1. + <_> + 14 10 2 5 2. + <_> + + <_> + 11 12 6 2 -1. + <_> + 11 13 6 1 2. + <_> + + <_> + 8 1 1 3 -1. + <_> + 8 2 1 1 3. + <_> + + <_> + 12 15 2 2 -1. + <_> + 12 15 1 1 2. + <_> + 13 16 1 1 2. + <_> + + <_> + 6 8 6 4 -1. + <_> + 6 8 3 2 2. + <_> + 9 10 3 2 2. + <_> + + <_> + 7 5 3 5 -1. + <_> + 8 5 1 5 3. + <_> + + <_> + 0 5 7 3 -1. + <_> + 0 6 7 1 3. + <_> + + <_> + 7 9 6 6 -1. + <_> + 9 9 2 6 3. + <_> + + <_> + 5 7 8 8 -1. + <_> + 5 11 8 4 2. + <_> + + <_> + 4 9 2 6 -1. + <_> + 4 9 1 3 2. + <_> + 5 12 1 3 2. + <_> + + <_> + 10 11 6 1 -1. + <_> + 12 11 2 1 3. + <_> + + <_> + 13 6 6 11 -1. + <_> + 15 6 2 11 3. + <_> + + <_> + 8 17 2 2 -1. + <_> + 8 17 1 1 2. + <_> + 9 18 1 1 2. + <_> + + <_> + 4 12 12 1 -1. + <_> + 8 12 4 1 3. + <_> + + <_> + 11 17 3 2 -1. + <_> + 11 18 3 1 2. + <_> + + <_> + 8 17 6 1 -1. + <_> + 10 17 2 1 3. + <_> + + <_> + 4 1 14 6 -1. + <_> + 4 3 14 2 3. + <_> + + <_> + 14 2 2 12 -1. + <_> + 14 8 2 6 2. + <_> + + <_> + 12 13 3 2 -1. + <_> + 12 14 3 1 2. + <_> + + <_> + 6 1 6 1 -1. + <_> + 8 1 2 1 3. + <_> + + <_> + 10 6 6 1 -1. + <_> + 12 6 2 1 3. + <_> + + <_> + 3 19 2 1 -1. + <_> + 4 19 1 1 2. + <_> + + <_> + 18 16 2 2 -1. + <_> + 18 16 1 1 2. + <_> + 19 17 1 1 2. + <_> + + <_> + 16 11 3 7 -1. + <_> + 17 11 1 7 3. + <_> + + <_> + 19 5 1 6 -1. + <_> + 19 8 1 3 2. + <_> + + <_> + 9 8 4 3 -1. + <_> + 9 9 4 1 3. + <_> + + <_> + 16 8 4 4 -1. + <_> + 16 8 2 2 2. + <_> + 18 10 2 2 2. + <_> + + <_> + 2 8 2 2 -1. + <_> + 2 8 1 1 2. + <_> + 3 9 1 1 2. + <_> + + <_> + 3 5 6 4 -1. + <_> + 3 5 3 2 2. + <_> + 6 7 3 2 2. + <_> + + <_> + 2 3 8 16 -1. + <_> + 2 3 4 8 2. + <_> + 6 11 4 8 2. + <_> + + <_> + 17 17 1 3 -1. + <_> + 17 18 1 1 3. + <_> + + <_> + 7 2 8 11 -1. + <_> + 11 2 4 11 2. + <_> + + <_> + 13 3 6 14 -1. + <_> + 16 3 3 14 2. + <_> + + <_> + 0 9 18 2 -1. + <_> + 6 9 6 2 3. + <_> + + <_> + 6 10 14 3 -1. + <_> + 6 11 14 1 3. + <_> + + <_> + 10 9 9 3 -1. + <_> + 13 9 3 3 3. + <_> + + <_> + 3 5 4 6 -1. + <_> + 3 5 2 3 2. + <_> + 5 8 2 3 2. + <_> + + <_> + 3 7 3 7 -1. + <_> + 4 7 1 7 3. + <_> + + <_> + 2 8 11 6 -1. + <_> + 2 10 11 2 3. + <_> + + <_> + 8 9 6 3 -1. + <_> + 8 10 6 1 3. + <_> + + <_> + 3 3 3 11 -1. + <_> + 4 3 1 11 3. + <_> + + <_> + 0 19 6 1 -1. + <_> + 3 19 3 1 2. + <_> + + <_> + 18 18 1 2 -1. + <_> + 18 19 1 1 2. + <_> + + <_> + 8 0 12 6 -1. + <_> + 8 0 6 3 2. + <_> + 14 3 6 3 2. + <_> + + <_> + 19 5 1 3 -1. + <_> + 19 6 1 1 3. + <_> + + <_> + 5 8 2 1 -1. + <_> + 6 8 1 1 2. + <_> + + <_> + 13 11 2 1 -1. + <_> + 14 11 1 1 2. + <_> + + <_> + 3 6 15 13 -1. + <_> + 8 6 5 13 3. + <_> + + <_> + 4 3 6 2 -1. + <_> + 6 3 2 2 3. + <_> + + <_> + 0 18 1 2 -1. + <_> + 0 19 1 1 2. + <_> + + <_> + 7 8 2 6 -1. + <_> + 8 8 1 6 2. + <_> + + <_> + 3 0 6 19 -1. + <_> + 5 0 2 19 3. + <_> + + <_> + 3 1 6 5 -1. + <_> + 5 1 2 5 3. + <_> + + <_> + 17 14 3 6 -1. + <_> + 17 16 3 2 3. + <_> + + <_> + 17 13 2 6 -1. + <_> + 18 13 1 6 2. + <_> + + <_> + 17 18 2 2 -1. + <_> + 18 18 1 2 2. + <_> + + <_> + 11 14 9 4 -1. + <_> + 14 14 3 4 3. + <_> + + <_> + 15 8 4 6 -1. + <_> + 15 8 2 3 2. + <_> + 17 11 2 3 2. + <_> + + <_> + 1 16 1 3 -1. + <_> + 1 17 1 1 3. + <_> + + <_> + 7 0 3 14 -1. + <_> + 8 0 1 14 3. + <_> + + <_> + 12 0 2 1 -1. + <_> + 13 0 1 1 2. + <_> + + <_> + 7 9 6 5 -1. + <_> + 10 9 3 5 2. + <_> + + <_> + 15 5 4 9 -1. + <_> + 17 5 2 9 2. + <_> + + <_> + 11 0 6 6 -1. + <_> + 13 0 2 6 3. + <_> + + <_> + 16 15 2 2 -1. + <_> + 16 15 1 1 2. + <_> + 17 16 1 1 2. + <_> + + <_> + 16 15 2 2 -1. + <_> + 16 15 1 1 2. + <_> + 17 16 1 1 2. + <_> + + <_> + 13 2 2 18 -1. + <_> + 13 11 2 9 2. + <_> + + <_> + 8 4 8 10 -1. + <_> + 8 9 8 5 2. + <_> + + <_> + 8 3 2 3 -1. + <_> + 8 4 2 1 3. + <_> + + <_> + 11 1 6 9 -1. + <_> + 11 4 6 3 3. + <_> + + <_> + 15 4 5 6 -1. + <_> + 15 6 5 2 3. + <_> + + <_> + 12 18 2 2 -1. + <_> + 12 18 1 1 2. + <_> + 13 19 1 1 2. + <_> + + <_> + 1 17 1 3 -1. + <_> + 1 18 1 1 3. + <_> + + <_> + 12 19 2 1 -1. + <_> + 13 19 1 1 2. + <_> + + <_> + 8 10 6 6 -1. + <_> + 10 10 2 6 3. + <_> + + <_> + 14 2 6 5 -1. + <_> + 16 2 2 5 3. + <_> + + <_> + 9 5 2 6 -1. + <_> + 9 7 2 2 3. + <_> + + <_> + 1 15 2 2 -1. + <_> + 2 15 1 2 2. + <_> + + <_> + 18 17 1 3 -1. + <_> + 18 18 1 1 3. + <_> + + <_> + 10 14 4 6 -1. + <_> + 10 16 4 2 3. + <_> + + <_> + 9 7 3 2 -1. + <_> + 10 7 1 2 3. + <_> + + <_> + 6 9 6 2 -1. + <_> + 6 9 3 1 2. + <_> + 9 10 3 1 2. + <_> + + <_> + 0 2 1 12 -1. + <_> + 0 6 1 4 3. + <_> + + <_> + 4 0 15 1 -1. + <_> + 9 0 5 1 3. + <_> + + <_> + 9 0 8 2 -1. + <_> + 9 0 4 1 2. + <_> + 13 1 4 1 2. + <_> + + <_> + 12 2 8 1 -1. + <_> + 16 2 4 1 2. + <_> + + <_> + 7 1 10 6 -1. + <_> + 7 3 10 2 3. + <_> + + <_> + 18 6 2 3 -1. + <_> + 18 7 2 1 3. + <_> + + <_> + 4 12 2 2 -1. + <_> + 4 12 1 1 2. + <_> + 5 13 1 1 2. + <_> + + <_> + 6 6 6 2 -1. + <_> + 8 6 2 2 3. + <_> + + <_> + 0 9 9 6 -1. + <_> + 3 9 3 6 3. + <_> + + <_> + 17 18 2 2 -1. + <_> + 18 18 1 2 2. + <_> + + <_> + 11 2 6 16 -1. + <_> + 13 2 2 16 3. + <_> + + <_> + 2 4 15 13 -1. + <_> + 7 4 5 13 3. + <_> + + <_> + 16 2 3 10 -1. + <_> + 17 2 1 10 3. + <_> + + <_> + 6 10 2 1 -1. + <_> + 7 10 1 1 2. + <_> + + <_> + 1 1 18 16 -1. + <_> + 10 1 9 16 2. + <_> + + <_> + 14 4 3 15 -1. + <_> + 15 4 1 15 3. + <_> + + <_> + 19 13 1 2 -1. + <_> + 19 14 1 1 2. + <_> + + <_> + 2 6 5 8 -1. + <_> + 2 10 5 4 2. + diff --git a/OpenCVComponent/Assets/haarcascade_frontalface_alt.xml b/OpenCVComponent/Assets/haarcascade_frontalface_alt.xml new file mode 100755 index 0000000..ade4b21 --- /dev/null +++ b/OpenCVComponent/Assets/haarcascade_frontalface_alt.xml @@ -0,0 +1,24350 @@ + + + +BOOST + HAAR + 20 + 20 + + 213 + + 0 + 22 + + <_> + 3 + 8.2268941402435303e-01 + + <_> + + 0 -1 0 4.0141958743333817e-03 + + 3.3794190734624863e-02 8.3781069517135620e-01 + <_> + + 0 -1 1 1.5151339583098888e-02 + + 1.5141320228576660e-01 7.4888122081756592e-01 + <_> + + 0 -1 2 4.2109931819140911e-03 + + 9.0049281716346741e-02 6.3748198747634888e-01 + <_> + 16 + 6.9566087722778320e+00 + + <_> + + 0 -1 3 1.6227109590545297e-03 + + 6.9308586418628693e-02 7.1109461784362793e-01 + <_> + + 0 -1 4 2.2906649392098188e-03 + + 1.7958030104637146e-01 6.6686922311782837e-01 + <_> + + 0 -1 5 5.0025708042085171e-03 + + 1.6936729848384857e-01 6.5540069341659546e-01 + <_> + + 0 -1 6 7.9659894108772278e-03 + + 5.8663320541381836e-01 9.1414518654346466e-02 + <_> + + 0 -1 7 -3.5227010957896709e-03 + + 1.4131669700145721e-01 6.0318958759307861e-01 + <_> + + 0 -1 8 3.6667689681053162e-02 + + 3.6756721138954163e-01 7.9203182458877563e-01 + <_> + + 0 -1 9 9.3361474573612213e-03 + + 6.1613857746124268e-01 2.0885099470615387e-01 + <_> + + 0 -1 10 8.6961314082145691e-03 + + 2.8362309932708740e-01 6.3602739572525024e-01 + <_> + + 0 -1 11 1.1488880263641477e-03 + + 2.2235809266567230e-01 5.8007007837295532e-01 + <_> + + 0 -1 12 -2.1484689787030220e-03 + + 2.4064640700817108e-01 5.7870548963546753e-01 + <_> + + 0 -1 13 2.1219060290604830e-03 + + 5.5596548318862915e-01 1.3622370362281799e-01 + <_> + + 0 -1 14 -9.3949146568775177e-02 + + 8.5027372837066650e-01 4.7177401185035706e-01 + <_> + + 0 -1 15 1.3777789426967502e-03 + + 5.9936738014221191e-01 2.8345298767089844e-01 + <_> + + 0 -1 16 7.3063157498836517e-02 + + 4.3418860435485840e-01 7.0600342750549316e-01 + <_> + + 0 -1 17 3.6767389974556863e-04 + + 3.0278879404067993e-01 6.0515749454498291e-01 + <_> + + 0 -1 18 -6.0479710809886456e-03 + + 1.7984339594841003e-01 5.6752568483352661e-01 + <_> + 21 + 9.4985427856445312e+00 + + <_> + + 0 -1 19 -1.6510689631104469e-02 + + 6.6442251205444336e-01 1.4248579740524292e-01 + <_> + + 0 -1 20 2.7052499353885651e-03 + + 6.3253521919250488e-01 1.2884770333766937e-01 + <_> + + 0 -1 21 2.8069869149476290e-03 + + 1.2402880191802979e-01 6.1931931972503662e-01 + <_> + + 0 -1 22 -1.5402400167658925e-03 + + 1.4321430027484894e-01 5.6700158119201660e-01 + <_> + + 0 -1 23 -5.6386279175058007e-04 + + 1.6574330627918243e-01 5.9052079916000366e-01 + <_> + + 0 -1 24 1.9253729842603207e-03 + + 2.6955071091651917e-01 5.7388240098953247e-01 + <_> + + 0 -1 25 -5.0214841030538082e-03 + + 1.8935389816761017e-01 5.7827740907669067e-01 + <_> + + 0 -1 26 2.6365420781075954e-03 + + 2.3093290627002716e-01 5.6954258680343628e-01 + <_> + + 0 -1 27 -1.5127769438549876e-03 + + 2.7596020698547363e-01 5.9566420316696167e-01 + <_> + + 0 -1 28 -1.0157439857721329e-02 + + 1.7325380444526672e-01 5.5220472812652588e-01 + <_> + + 0 -1 29 -1.1953660286962986e-02 + + 1.3394099473953247e-01 5.5590140819549561e-01 + <_> + + 0 -1 30 4.8859491944313049e-03 + + 3.6287039518356323e-01 6.1888492107391357e-01 + <_> + + 0 -1 31 -8.0132916569709778e-02 + + 9.1211050748825073e-02 5.4759448766708374e-01 + <_> + + 0 -1 32 1.0643280111253262e-03 + + 3.7151429057121277e-01 5.7113999128341675e-01 + <_> + + 0 -1 33 -1.3419450260698795e-03 + + 5.9533137083053589e-01 3.3180978894233704e-01 + <_> + + 0 -1 34 -5.4601140320301056e-02 + + 1.8440659344196320e-01 5.6028461456298828e-01 + <_> + + 0 -1 35 2.9071690514683723e-03 + + 3.5942441225051880e-01 6.1317151784896851e-01 + <_> + + 0 -1 36 7.4718717951327562e-04 + + 5.9943532943725586e-01 3.4595629572868347e-01 + <_> + + 0 -1 37 4.3013808317482471e-03 + + 4.1726520657539368e-01 6.9908452033996582e-01 + <_> + + 0 -1 38 4.5017572119832039e-03 + + 4.5097151398658752e-01 7.8014570474624634e-01 + <_> + + 0 -1 39 2.4138500913977623e-02 + + 5.4382127523422241e-01 1.3198269903659821e-01 + <_> + 39 + 1.8412969589233398e+01 + + <_> + + 0 -1 40 1.9212230108678341e-03 + + 1.4152669906616211e-01 6.1998707056045532e-01 + <_> + + 0 -1 41 -1.2748669541906565e-04 + + 6.1910742521286011e-01 1.8849289417266846e-01 + <_> + + 0 -1 42 5.1409931620582938e-04 + + 1.4873969554901123e-01 5.8579277992248535e-01 + <_> + + 0 -1 43 4.1878609918057919e-03 + + 2.7469098567962646e-01 6.3592398166656494e-01 + <_> + + 0 -1 44 5.1015717908740044e-03 + + 5.8708512783050537e-01 2.1756289899349213e-01 + <_> + + 0 -1 45 -2.1448440384119749e-03 + + 5.8809447288513184e-01 2.9795908927917480e-01 + <_> + + 0 -1 46 -2.8977119363844395e-03 + + 2.3733270168304443e-01 5.8766472339630127e-01 + <_> + + 0 -1 47 -2.1610679104924202e-02 + + 1.2206549942493439e-01 5.1942020654678345e-01 + <_> + + 0 -1 48 -4.6299318782985210e-03 + + 2.6312309503555298e-01 5.8174091577529907e-01 + <_> + + 0 -1 49 5.9393711853772402e-04 + + 3.6386200785636902e-01 5.6985449790954590e-01 + <_> + + 0 -1 50 5.3878661245107651e-02 + + 4.3035310506820679e-01 7.5593662261962891e-01 + <_> + + 0 -1 51 1.8887349870055914e-03 + + 2.1226030588150024e-01 5.6134271621704102e-01 + <_> + + 0 -1 52 -2.3635339457541704e-03 + + 5.6318491697311401e-01 2.6427671313285828e-01 + <_> + + 0 -1 53 2.4017799645662308e-02 + + 5.7971078157424927e-01 2.7517059445381165e-01 + <_> + + 0 -1 54 2.0543030404951423e-04 + + 2.7052420377731323e-01 5.7525688409805298e-01 + <_> + + 0 -1 55 8.4790197433903813e-04 + + 5.4356247186660767e-01 2.3348769545555115e-01 + <_> + + 0 -1 56 1.4091329649090767e-03 + + 5.3194248676300049e-01 2.0631550252437592e-01 + <_> + + 0 -1 57 1.4642629539594054e-03 + + 5.4189807176589966e-01 3.0688610672950745e-01 + <_> + + 0 -1 58 1.6352549428120255e-03 + + 3.6953729391098022e-01 6.1128681898117065e-01 + <_> + + 0 -1 59 8.3172752056270838e-04 + + 3.5650369524955750e-01 6.0252362489700317e-01 + <_> + + 0 -1 60 -2.0998890977352858e-03 + + 1.9139820337295532e-01 5.3628271818161011e-01 + <_> + + 0 -1 61 -7.4213981861248612e-04 + + 3.8355550169944763e-01 5.5293101072311401e-01 + <_> + + 0 -1 62 3.2655049581080675e-03 + + 4.3128961324691772e-01 7.1018958091735840e-01 + <_> + + 0 -1 63 8.9134991867467761e-04 + + 3.9848309755325317e-01 6.3919639587402344e-01 + <_> + + 0 -1 64 -1.5284179709851742e-02 + + 2.3667329549789429e-01 5.4337137937545776e-01 + <_> + + 0 -1 65 4.8381411470472813e-03 + + 5.8175009489059448e-01 3.2391890883445740e-01 + <_> + + 0 -1 66 -9.1093179071322083e-04 + + 5.5405938625335693e-01 2.9118689894676208e-01 + <_> + + 0 -1 67 -6.1275060288608074e-03 + + 1.7752550542354584e-01 5.1966291666030884e-01 + <_> + + 0 -1 68 -4.4576259097084403e-04 + + 3.0241701006889343e-01 5.5335938930511475e-01 + <_> + + 0 -1 69 2.2646540775895119e-02 + + 4.4149309396743774e-01 6.9753772020339966e-01 + <_> + + 0 -1 70 -1.8804960418492556e-03 + + 2.7913948893547058e-01 5.4979521036148071e-01 + <_> + + 0 -1 71 7.0889107882976532e-03 + + 5.2631992101669312e-01 2.3855470120906830e-01 + <_> + + 0 -1 72 1.7318050377070904e-03 + + 4.3193790316581726e-01 6.9836008548736572e-01 + <_> + + 0 -1 73 -6.8482700735330582e-03 + + 3.0820429325103760e-01 5.3909200429916382e-01 + <_> + + 0 -1 74 -1.5062530110299122e-05 + + 5.5219221115112305e-01 3.1203660368919373e-01 + <_> + + 0 -1 75 2.9475569725036621e-02 + + 5.4013228416442871e-01 1.7706030607223511e-01 + <_> + + 0 -1 76 8.1387329846620560e-03 + + 5.1786178350448608e-01 1.2110190093517303e-01 + <_> + + 0 -1 77 2.0942950621247292e-02 + + 5.2902942895889282e-01 3.3112218976020813e-01 + <_> + + 0 -1 78 -9.5665529370307922e-03 + + 7.4719941616058350e-01 4.4519689679145813e-01 + <_> + 33 + 1.5324139595031738e+01 + + <_> + + 0 -1 79 -2.8206960996612906e-04 + + 2.0640860497951508e-01 6.0767322778701782e-01 + <_> + + 0 -1 80 1.6790600493550301e-03 + + 5.8519971370697021e-01 1.2553839385509491e-01 + <_> + + 0 -1 81 6.9827912375330925e-04 + + 9.4018429517745972e-02 5.7289612293243408e-01 + <_> + + 0 -1 82 7.8959012171253562e-04 + + 1.7819879949092865e-01 5.6943088769912720e-01 + <_> + + 0 -1 83 -2.8560499195009470e-03 + + 1.6383990645408630e-01 5.7886648178100586e-01 + <_> + + 0 -1 84 -3.8122469559311867e-03 + + 2.0854400098323822e-01 5.5085647106170654e-01 + <_> + + 0 -1 85 1.5896620461717248e-03 + + 5.7027608156204224e-01 1.8572150170803070e-01 + <_> + + 0 -1 86 1.0078339837491512e-02 + + 5.1169431209564209e-01 2.1897700428962708e-01 + <_> + + 0 -1 87 -6.3526302576065063e-02 + + 7.1313798427581787e-01 4.0438130497932434e-01 + <_> + + 0 -1 88 -9.1031491756439209e-03 + + 2.5671818852424622e-01 5.4639732837677002e-01 + <_> + + 0 -1 89 -2.4035000242292881e-03 + + 1.7006659507751465e-01 5.5909740924835205e-01 + <_> + + 0 -1 90 1.5226360410451889e-03 + + 5.4105567932128906e-01 2.6190540194511414e-01 + <_> + + 0 -1 91 1.7997439950704575e-02 + + 3.7324368953704834e-01 6.5352207422256470e-01 + <_> + + 0 -1 92 -6.4538191072642803e-03 + + 2.6264819502830505e-01 5.5374461412429810e-01 + <_> + + 0 -1 93 -1.1880760081112385e-02 + + 2.0037539303302765e-01 5.5447459220886230e-01 + <_> + + 0 -1 94 1.2713660253211856e-03 + + 5.5919027328491211e-01 3.0319759249687195e-01 + <_> + + 0 -1 95 1.1376109905540943e-03 + + 2.7304071187973022e-01 5.6465089321136475e-01 + <_> + + 0 -1 96 -4.2651998810470104e-03 + + 1.4059090614318848e-01 5.4618209600448608e-01 + <_> + + 0 -1 97 -2.9602861031889915e-03 + + 1.7950350046157837e-01 5.4592901468276978e-01 + <_> + + 0 -1 98 -8.8448226451873779e-03 + + 5.7367831468582153e-01 2.8092199563980103e-01 + <_> + + 0 -1 99 -6.6430689767003059e-03 + + 2.3706759512424469e-01 5.5038261413574219e-01 + <_> + + 0 -1 100 3.9997808635234833e-03 + + 5.6081998348236084e-01 3.3042821288108826e-01 + <_> + + 0 -1 101 -4.1221720166504383e-03 + + 1.6401059925556183e-01 5.3789931535720825e-01 + <_> + + 0 -1 102 1.5624909661710262e-02 + + 5.2276492118835449e-01 2.2886039316654205e-01 + <_> + + 0 -1 103 -1.0356419719755650e-02 + + 7.0161938667297363e-01 4.2529278993606567e-01 + <_> + + 0 -1 104 -8.7960809469223022e-03 + + 2.7673470973968506e-01 5.3558301925659180e-01 + <_> + + 0 -1 105 1.6226939857006073e-01 + + 4.3422400951385498e-01 7.4425792694091797e-01 + <_> + + 0 -1 106 4.5542530715465546e-03 + + 5.7264858484268188e-01 2.5821250677108765e-01 + <_> + + 0 -1 107 -2.1309209987521172e-03 + + 2.1068480610847473e-01 5.3610187768936157e-01 + <_> + + 0 -1 108 -1.3208420015871525e-02 + + 7.5937908887863159e-01 4.5524680614471436e-01 + <_> + + 0 -1 109 -6.5996676683425903e-02 + + 1.2524759769439697e-01 5.3440397977828979e-01 + <_> + + 0 -1 110 7.9142656177282333e-03 + + 3.3153840899467468e-01 5.6010431051254272e-01 + <_> + + 0 -1 111 2.0894279703497887e-02 + + 5.5060499906539917e-01 2.7688381075859070e-01 + <_> + 44 + 2.1010639190673828e+01 + + <_> + + 0 -1 112 1.1961159761995077e-03 + + 1.7626909911632538e-01 6.1562412977218628e-01 + <_> + + 0 -1 113 -1.8679830245673656e-03 + + 6.1181068420410156e-01 1.8323999643325806e-01 + <_> + + 0 -1 114 -1.9579799845814705e-04 + + 9.9044263362884521e-02 5.7238161563873291e-01 + <_> + + 0 -1 115 -8.0255657667294145e-04 + + 5.5798798799514771e-01 2.3772829771041870e-01 + <_> + + 0 -1 116 -2.4510810617357492e-03 + + 2.2314579784870148e-01 5.8589351177215576e-01 + <_> + + 0 -1 117 5.0361850298941135e-04 + + 2.6539939641952515e-01 5.7941037416458130e-01 + <_> + + 0 -1 118 4.0293349884450436e-03 + + 5.8038270473480225e-01 2.4848650395870209e-01 + <_> + + 0 -1 119 -1.4451709575951099e-02 + + 1.8303519487380981e-01 5.4842048883438110e-01 + <_> + + 0 -1 120 2.0380979403853416e-03 + + 3.3635589480400085e-01 6.0510927438735962e-01 + <_> + + 0 -1 121 -1.6155190533027053e-03 + + 2.2866420447826385e-01 5.4412460327148438e-01 + <_> + + 0 -1 122 3.3458340913057327e-03 + + 5.6259131431579590e-01 2.3923380672931671e-01 + <_> + + 0 -1 123 1.6379579901695251e-03 + + 3.9069938659667969e-01 5.9646219015121460e-01 + <_> + + 0 -1 124 3.0251210555434227e-02 + + 5.2484822273254395e-01 1.5757469832897186e-01 + <_> + + 0 -1 125 3.7251990288496017e-02 + + 4.1943109035491943e-01 6.7484188079833984e-01 + <_> + + 0 -1 126 -2.5109790265560150e-02 + + 1.8825499713420868e-01 5.4734510183334351e-01 + <_> + + 0 -1 127 -5.3099058568477631e-03 + + 1.3399730622768402e-01 5.2271109819412231e-01 + <_> + + 0 -1 128 1.2086479691788554e-03 + + 3.7620881199836731e-01 6.1096358299255371e-01 + <_> + + 0 -1 129 -2.1907679736614227e-02 + + 2.6631429791450500e-01 5.4040068387985229e-01 + <_> + + 0 -1 130 5.4116579703986645e-03 + + 5.3635787963867188e-01 2.2322730720043182e-01 + <_> + + 0 -1 131 6.9946326315402985e-02 + + 5.3582328557968140e-01 2.4536980688571930e-01 + <_> + + 0 -1 132 3.4520021290518343e-04 + + 2.4096719920635223e-01 5.3769302368164062e-01 + <_> + + 0 -1 133 1.2627709656953812e-03 + + 5.4258567094802856e-01 3.1556931138038635e-01 + <_> + + 0 -1 134 2.2719509899616241e-02 + + 4.1584059596061707e-01 6.5978652238845825e-01 + <_> + + 0 -1 135 -1.8111000536009669e-03 + + 2.8112530708312988e-01 5.5052447319030762e-01 + <_> + + 0 -1 136 3.3469670452177525e-03 + + 5.2600282430648804e-01 1.8914650380611420e-01 + <_> + + 0 -1 137 4.0791751234792173e-04 + + 5.6735092401504517e-01 3.3442100882530212e-01 + <_> + + 0 -1 138 1.2734799645841122e-02 + + 5.3435921669006348e-01 2.3956120014190674e-01 + <_> + + 0 -1 139 -7.3119727894663811e-03 + + 6.0108900070190430e-01 4.0222078561782837e-01 + <_> + + 0 -1 140 -5.6948751211166382e-02 + + 8.1991511583328247e-01 4.5431908965110779e-01 + <_> + + 0 -1 141 -5.0116591155529022e-03 + + 2.2002810239791870e-01 5.3577107191085815e-01 + <_> + + 0 -1 142 6.0334368608891964e-03 + + 4.4130811095237732e-01 7.1817511320114136e-01 + <_> + + 0 -1 143 3.9437441155314445e-03 + + 5.4788607358932495e-01 2.7917331457138062e-01 + <_> + + 0 -1 144 -3.6591119132936001e-03 + + 6.3578677177429199e-01 3.9897239208221436e-01 + <_> + + 0 -1 145 -3.8456181064248085e-03 + + 3.4936860203742981e-01 5.3006649017333984e-01 + <_> + + 0 -1 146 -7.1926261298358440e-03 + + 1.1196149885654449e-01 5.2296727895736694e-01 + <_> + + 0 -1 147 -5.2798941731452942e-02 + + 2.3871029913425446e-01 5.4534512758255005e-01 + <_> + + 0 -1 148 -7.9537667334079742e-03 + + 7.5869178771972656e-01 4.4393768906593323e-01 + <_> + + 0 -1 149 -2.7344180271029472e-03 + + 2.5654768943786621e-01 5.4893219470977783e-01 + <_> + + 0 -1 150 -1.8507939530536532e-03 + + 6.7343479394912720e-01 4.2524749040603638e-01 + <_> + + 0 -1 151 1.5918919816613197e-02 + + 5.4883527755737305e-01 2.2926619648933411e-01 + <_> + + 0 -1 152 -1.2687679845839739e-03 + + 6.1043310165405273e-01 4.0223899483680725e-01 + <_> + + 0 -1 153 6.2883910723030567e-03 + + 5.3108531236648560e-01 1.5361930429935455e-01 + <_> + + 0 -1 154 -6.2259892001748085e-03 + + 1.7291119694709778e-01 5.2416062355041504e-01 + <_> + + 0 -1 155 -1.2132599949836731e-02 + + 6.5977597236633301e-01 4.3251821398735046e-01 + <_> + 50 + 2.3918790817260742e+01 + + <_> + + 0 -1 156 -3.9184908382594585e-03 + + 6.1034351587295532e-01 1.4693309366703033e-01 + <_> + + 0 -1 157 1.5971299726516008e-03 + + 2.6323631405830383e-01 5.8964669704437256e-01 + <_> + + 0 -1 158 1.7780110239982605e-02 + + 5.8728742599487305e-01 1.7603619396686554e-01 + <_> + + 0 -1 159 6.5334769897162914e-04 + + 1.5678019821643829e-01 5.5960661172866821e-01 + <_> + + 0 -1 160 -2.8353091329336166e-04 + + 1.9131539762020111e-01 5.7320362329483032e-01 + <_> + + 0 -1 161 1.6104689566418529e-03 + + 2.9149138927459717e-01 5.6230807304382324e-01 + <_> + + 0 -1 162 -9.7750619053840637e-02 + + 1.9434769451618195e-01 5.6482332944869995e-01 + <_> + + 0 -1 163 5.5182358482852578e-04 + + 3.1346169114112854e-01 5.5046397447586060e-01 + <_> + + 0 -1 164 -1.2858220376074314e-02 + + 2.5364819169044495e-01 5.7601428031921387e-01 + <_> + + 0 -1 165 4.1530239395797253e-03 + + 5.7677221298217773e-01 3.6597740650177002e-01 + <_> + + 0 -1 166 1.7092459602281451e-03 + + 2.8431910276412964e-01 5.9189391136169434e-01 + <_> + + 0 -1 167 7.5217359699308872e-03 + + 4.0524271130561829e-01 6.1831092834472656e-01 + <_> + + 0 -1 168 2.2479810286313295e-03 + + 5.7837551832199097e-01 3.1354010105133057e-01 + <_> + + 0 -1 169 5.2006211131811142e-02 + + 5.5413120985031128e-01 1.9166369736194611e-01 + <_> + + 0 -1 170 1.2085529975593090e-02 + + 4.0326559543609619e-01 6.6445910930633545e-01 + <_> + + 0 -1 171 1.4687820112158079e-05 + + 3.5359779000282288e-01 5.7093828916549683e-01 + <_> + + 0 -1 172 7.1395188570022583e-06 + + 3.0374449491500854e-01 5.6102699041366577e-01 + <_> + + 0 -1 173 -4.6001640148460865e-03 + + 7.1810871362686157e-01 4.5803260803222656e-01 + <_> + + 0 -1 174 2.0058949012309313e-03 + + 5.6219518184661865e-01 2.9536840319633484e-01 + <_> + + 0 -1 175 4.5050270855426788e-03 + + 4.6153879165649414e-01 7.6190179586410522e-01 + <_> + + 0 -1 176 1.1746830306947231e-02 + + 5.3438371419906616e-01 1.7725290358066559e-01 + <_> + + 0 -1 177 -5.8316338807344437e-02 + + 1.6862459480762482e-01 5.3407722711563110e-01 + <_> + + 0 -1 178 2.3629379575140774e-04 + + 3.7920561432838440e-01 6.0268038511276245e-01 + <_> + + 0 -1 179 -7.8156180679798126e-03 + + 1.5128670632839203e-01 5.3243237733840942e-01 + <_> + + 0 -1 180 -1.0876160115003586e-02 + + 2.0818220078945160e-01 5.3199452161788940e-01 + <_> + + 0 -1 181 -2.7745519764721394e-03 + + 4.0982469916343689e-01 5.2103281021118164e-01 + <_> + + 0 -1 182 -7.8276381827890873e-04 + + 5.6932741403579712e-01 3.4788420796394348e-01 + <_> + + 0 -1 183 1.3870409689843655e-02 + + 5.3267508745193481e-01 2.2576980292797089e-01 + <_> + + 0 -1 184 -2.3674910888075829e-02 + + 1.5513050556182861e-01 5.2007079124450684e-01 + <_> + + 0 -1 185 -1.4879409718560055e-05 + + 5.5005669593811035e-01 3.8201761245727539e-01 + <_> + + 0 -1 186 3.6190641112625599e-03 + + 4.2386838793754578e-01 6.6397482156753540e-01 + <_> + + 0 -1 187 -1.9817110151052475e-02 + + 2.1500380337238312e-01 5.3823578357696533e-01 + <_> + + 0 -1 188 -3.8154039066284895e-03 + + 6.6757112741470337e-01 4.2152971029281616e-01 + <_> + + 0 -1 189 -4.9775829538702965e-03 + + 2.2672890126705170e-01 5.3863281011581421e-01 + <_> + + 0 -1 190 2.2441020701080561e-03 + + 4.3086910247802734e-01 6.8557357788085938e-01 + <_> + + 0 -1 191 1.2282459996640682e-02 + + 5.8366149663925171e-01 3.4674790501594543e-01 + <_> + + 0 -1 192 -2.8548699337989092e-03 + + 7.0169448852539062e-01 4.3114539980888367e-01 + <_> + + 0 -1 193 -3.7875669077038765e-03 + + 2.8953450918197632e-01 5.2249461412429810e-01 + <_> + + 0 -1 194 -1.2201230274513364e-03 + + 2.9755708575248718e-01 5.4816448688507080e-01 + <_> + + 0 -1 195 1.0160599835216999e-02 + + 4.8888179659843445e-01 8.1826978921890259e-01 + <_> + + 0 -1 196 -1.6174569725990295e-02 + + 1.4814929664134979e-01 5.2399927377700806e-01 + <_> + + 0 -1 197 1.9292460754513741e-02 + + 4.7863098978996277e-01 7.3781907558441162e-01 + <_> + + 0 -1 198 -3.2479539513587952e-03 + + 7.3742228746414185e-01 4.4706439971923828e-01 + <_> + + 0 -1 199 -9.3803480267524719e-03 + + 3.4891548752784729e-01 5.5379962921142578e-01 + <_> + + 0 -1 200 -1.2606129981577396e-02 + + 2.3796869814395905e-01 5.3154432773590088e-01 + <_> + + 0 -1 201 -2.5621930137276649e-02 + + 1.9646880030632019e-01 5.1387697458267212e-01 + <_> + + 0 -1 202 -7.5741496402770281e-05 + + 5.5905228853225708e-01 3.3658531308174133e-01 + <_> + + 0 -1 203 -8.9210882782936096e-02 + + 6.3404656946659088e-02 5.1626348495483398e-01 + <_> + + 0 -1 204 -2.7670480776578188e-03 + + 7.3234677314758301e-01 4.4907060265541077e-01 + <_> + + 0 -1 205 2.7152578695677221e-04 + + 4.1148349642753601e-01 5.9855180978775024e-01 + <_> + 51 + 2.4527879714965820e+01 + + <_> + + 0 -1 206 1.4786219689995050e-03 + + 2.6635450124740601e-01 6.6433167457580566e-01 + <_> + + 0 -1 207 -1.8741659587249160e-03 + + 6.1438488960266113e-01 2.5185129046440125e-01 + <_> + + 0 -1 208 -1.7151009524241090e-03 + + 5.7663410902023315e-01 2.3974630236625671e-01 + <_> + + 0 -1 209 -1.8939269939437509e-03 + + 5.6820458173751831e-01 2.5291448831558228e-01 + <_> + + 0 -1 210 -5.3006052039563656e-03 + + 1.6406759619712830e-01 5.5560797452926636e-01 + <_> + + 0 -1 211 -4.6662531793117523e-02 + + 6.1231541633605957e-01 4.7628301382064819e-01 + <_> + + 0 -1 212 -7.9431332414969802e-04 + + 5.7078588008880615e-01 2.8394040465354919e-01 + <_> + + 0 -1 213 1.4891670085489750e-02 + + 4.0896728634834290e-01 6.0063672065734863e-01 + <_> + + 0 -1 214 -1.2046529445797205e-03 + + 5.7124507427215576e-01 2.7052891254425049e-01 + <_> + + 0 -1 215 6.0619381256401539e-03 + + 5.2625042200088501e-01 3.2622259855270386e-01 + <_> + + 0 -1 216 -2.5286648888140917e-03 + + 6.8538308143615723e-01 4.1992568969726562e-01 + <_> + + 0 -1 217 -5.9010218828916550e-03 + + 3.2662820816040039e-01 5.4348129034042358e-01 + <_> + + 0 -1 218 5.6702760048210621e-03 + + 5.4684108495712280e-01 2.3190039396286011e-01 + <_> + + 0 -1 219 -3.0304100364446640e-03 + + 5.5706679821014404e-01 2.7082380652427673e-01 + <_> + + 0 -1 220 2.9803649522364140e-03 + + 3.7005689740180969e-01 5.8906257152557373e-01 + <_> + + 0 -1 221 -7.5840510427951813e-02 + + 2.1400700509548187e-01 5.4199481010437012e-01 + <_> + + 0 -1 222 1.9262539222836494e-02 + + 5.5267721414566040e-01 2.7265900373458862e-01 + <_> + + 0 -1 223 1.8888259364757687e-04 + + 3.9580118656158447e-01 6.0172098875045776e-01 + <_> + + 0 -1 224 2.9369549825787544e-02 + + 5.2413737773895264e-01 1.4357580244541168e-01 + <_> + + 0 -1 225 1.0417619487270713e-03 + + 3.3854091167449951e-01 5.9299832582473755e-01 + <_> + + 0 -1 226 2.6125640142709017e-03 + + 5.4853779077529907e-01 3.0215978622436523e-01 + <_> + + 0 -1 227 9.6977467183023691e-04 + + 3.3752760291099548e-01 5.5320328474044800e-01 + <_> + + 0 -1 228 5.9512659208849072e-04 + + 5.6317430734634399e-01 3.3593991398811340e-01 + <_> + + 0 -1 229 -1.0156559944152832e-01 + + 6.3735038042068481e-02 5.2304250001907349e-01 + <_> + + 0 -1 230 3.6156699061393738e-02 + + 5.1369631290435791e-01 1.0295289754867554e-01 + <_> + + 0 -1 231 3.4624140243977308e-03 + + 3.8793200254440308e-01 5.5582892894744873e-01 + <_> + + 0 -1 232 1.9554980099201202e-02 + + 5.2500867843627930e-01 1.8758599460124969e-01 + <_> + + 0 -1 233 -2.3121440317481756e-03 + + 6.6720288991928101e-01 4.6796411275863647e-01 + <_> + + 0 -1 234 -1.8605289515107870e-03 + + 7.1633791923522949e-01 4.3346709012985229e-01 + <_> + + 0 -1 235 -9.4026362057775259e-04 + + 3.0213609337806702e-01 5.6502032279968262e-01 + <_> + + 0 -1 236 -5.2418331615626812e-03 + + 1.8200090527534485e-01 5.2502560615539551e-01 + <_> + + 0 -1 237 1.1729019752237946e-04 + + 3.3891880512237549e-01 5.4459732770919800e-01 + <_> + + 0 -1 238 1.1878840159624815e-03 + + 4.0853491425514221e-01 6.2535631656646729e-01 + <_> + + 0 -1 239 -1.0881359688937664e-02 + + 3.3783990144729614e-01 5.7000827789306641e-01 + <_> + + 0 -1 240 1.7354859737679362e-03 + + 4.2046359181404114e-01 6.5230387449264526e-01 + <_> + + 0 -1 241 -6.5119052305817604e-03 + + 2.5952160358428955e-01 5.4281437397003174e-01 + <_> + + 0 -1 242 -1.2136430013924837e-03 + + 6.1651438474655151e-01 3.9778938889503479e-01 + <_> + + 0 -1 243 -1.0354240424931049e-02 + + 1.6280280053615570e-01 5.2195048332214355e-01 + <_> + + 0 -1 244 5.5858830455690622e-04 + + 3.1996509432792664e-01 5.5035740137100220e-01 + <_> + + 0 -1 245 1.5299649909138680e-02 + + 4.1039940714836121e-01 6.1223882436752319e-01 + <_> + + 0 -1 246 -2.1588210016489029e-02 + + 1.0349129885435104e-01 5.1973849534988403e-01 + <_> + + 0 -1 247 -1.2834629416465759e-01 + + 8.4938651323318481e-01 4.8931029438972473e-01 + <_> + + 0 -1 248 -2.2927189711481333e-03 + + 3.1301578879356384e-01 5.4715752601623535e-01 + <_> + + 0 -1 249 7.9915106296539307e-02 + + 4.8563209176063538e-01 6.0739892721176147e-01 + <_> + + 0 -1 250 -7.9441092908382416e-02 + + 8.3946740627288818e-01 4.6245330572128296e-01 + <_> + + 0 -1 251 -5.2800010889768600e-03 + + 1.8816959857940674e-01 5.3066980838775635e-01 + <_> + + 0 -1 252 1.0463109938427806e-03 + + 5.2712291479110718e-01 2.5830659270286560e-01 + <_> + + 0 -1 253 2.6317298761568964e-04 + + 4.2353048920631409e-01 5.7354408502578735e-01 + <_> + + 0 -1 254 -3.6173160187900066e-03 + + 6.9343960285186768e-01 4.4954448938369751e-01 + <_> + + 0 -1 255 1.1421879753470421e-02 + + 5.9009212255477905e-01 4.1381931304931641e-01 + <_> + + 0 -1 256 -1.9963278900831938e-03 + + 6.4663827419281006e-01 4.3272399902343750e-01 + <_> + 56 + 2.7153350830078125e+01 + + <_> + + 0 -1 257 -9.9691245704889297e-03 + + 6.1423242092132568e-01 2.4822120368480682e-01 + <_> + + 0 -1 258 7.3073059320449829e-04 + + 5.7049518823623657e-01 2.3219659924507141e-01 + <_> + + 0 -1 259 6.4045301405712962e-04 + + 2.1122519671916962e-01 5.8149331808090210e-01 + <_> + + 0 -1 260 4.5424019917845726e-03 + + 2.9504820704460144e-01 5.8663117885589600e-01 + <_> + + 0 -1 261 9.2477443104144186e-05 + + 2.9909908771514893e-01 5.7913267612457275e-01 + <_> + + 0 -1 262 -8.6603146046400070e-03 + + 2.8130298852920532e-01 5.6355422735214233e-01 + <_> + + 0 -1 263 8.0515816807746887e-03 + + 3.5353690385818481e-01 6.0547572374343872e-01 + <_> + + 0 -1 264 4.3835240649059415e-04 + + 5.5965322256088257e-01 2.7315109968185425e-01 + <_> + + 0 -1 265 -9.8168973636347800e-05 + + 5.9780317544937134e-01 3.6385610699653625e-01 + <_> + + 0 -1 266 -1.1298790341243148e-03 + + 2.7552521228790283e-01 5.4327291250228882e-01 + <_> + + 0 -1 267 6.4356150105595589e-03 + + 4.3056419491767883e-01 7.0698332786560059e-01 + <_> + + 0 -1 268 -5.6829329580068588e-02 + + 2.4952429533004761e-01 5.2949970960617065e-01 + <_> + + 0 -1 269 4.0668169967830181e-03 + + 5.4785531759262085e-01 2.4977239966392517e-01 + <_> + + 0 -1 270 4.8164798499783501e-05 + + 3.9386010169982910e-01 5.7063561677932739e-01 + <_> + + 0 -1 271 6.1795017682015896e-03 + + 4.4076061248779297e-01 7.3947668075561523e-01 + <_> + + 0 -1 272 6.4985752105712891e-03 + + 5.4452431201934814e-01 2.4791529774665833e-01 + <_> + + 0 -1 273 -1.0211090557277203e-03 + + 2.5447669625282288e-01 5.3389710187911987e-01 + <_> + + 0 -1 274 -5.4247528314590454e-03 + + 2.7188581228256226e-01 5.3240692615509033e-01 + <_> + + 0 -1 275 -1.0559899965301156e-03 + + 3.1782880425453186e-01 5.5345088243484497e-01 + <_> + + 0 -1 276 6.6465808777138591e-04 + + 4.2842191457748413e-01 6.5581941604614258e-01 + <_> + + 0 -1 277 -2.7524109464138746e-04 + + 5.9028607606887817e-01 3.8102629780769348e-01 + <_> + + 0 -1 278 4.2293202131986618e-03 + + 3.8164898753166199e-01 5.7093858718872070e-01 + <_> + + 0 -1 279 -3.2868210691958666e-03 + + 1.7477439343929291e-01 5.2595442533493042e-01 + <_> + + 0 -1 280 1.5611879643984139e-04 + + 3.6017221212387085e-01 5.7256120443344116e-01 + <_> + + 0 -1 281 -7.3621381488919724e-06 + + 5.4018580913543701e-01 3.0444970726966858e-01 + <_> + + 0 -1 282 -1.4767250046133995e-02 + + 3.2207700610160828e-01 5.5734348297119141e-01 + <_> + + 0 -1 283 2.4489590898156166e-02 + + 4.3015280365943909e-01 6.5188127756118774e-01 + <_> + + 0 -1 284 -3.7652091123163700e-04 + + 3.5645830631256104e-01 5.5982369184494019e-01 + <_> + + 0 -1 285 7.3657688517414499e-06 + + 3.4907829761505127e-01 5.5618977546691895e-01 + <_> + + 0 -1 286 -1.5099939890205860e-02 + + 1.7762720584869385e-01 5.3352999687194824e-01 + <_> + + 0 -1 287 -3.8316650316119194e-03 + + 6.1496877670288086e-01 4.2213940620422363e-01 + <_> + + 0 -1 288 1.6925400123000145e-02 + + 5.4130148887634277e-01 2.1665850281715393e-01 + <_> + + 0 -1 289 -3.0477850232273340e-03 + + 6.4494907855987549e-01 4.3546178936958313e-01 + <_> + + 0 -1 290 3.2140589319169521e-03 + + 5.4001551866531372e-01 3.5232171416282654e-01 + <_> + + 0 -1 291 -4.0023201145231724e-03 + + 2.7745240926742554e-01 5.3384172916412354e-01 + <_> + + 0 -1 292 7.4182129465043545e-03 + + 5.6767392158508301e-01 3.7028178572654724e-01 + <_> + + 0 -1 293 -8.8764587417244911e-03 + + 7.7492219209671021e-01 4.5836889743804932e-01 + <_> + + 0 -1 294 2.7311739977449179e-03 + + 5.3387218713760376e-01 3.9966610074043274e-01 + <_> + + 0 -1 295 -2.5082379579544067e-03 + + 5.6119632720947266e-01 3.7774989008903503e-01 + <_> + + 0 -1 296 -8.0541074275970459e-03 + + 2.9152289032936096e-01 5.1791828870773315e-01 + <_> + + 0 -1 297 -9.7938813269138336e-04 + + 5.5364328622817993e-01 3.7001928687095642e-01 + <_> + + 0 -1 298 -5.8745909482240677e-03 + + 3.7543910741806030e-01 5.6793761253356934e-01 + <_> + + 0 -1 299 -4.4936719350516796e-03 + + 7.0196992158889771e-01 4.4809499382972717e-01 + <_> + + 0 -1 300 -5.4389229044318199e-03 + + 2.3103649914264679e-01 5.3133869171142578e-01 + <_> + + 0 -1 301 -7.5094640487805009e-04 + + 5.8648687601089478e-01 4.1293430328369141e-01 + <_> + + 0 -1 302 1.4528800420521293e-05 + + 3.7324070930480957e-01 5.6196212768554688e-01 + <_> + + 0 -1 303 4.0758069604635239e-02 + + 5.3120911121368408e-01 2.7205219864845276e-01 + <_> + + 0 -1 304 6.6505931317806244e-03 + + 4.7100159525871277e-01 6.6934937238693237e-01 + <_> + + 0 -1 305 4.5759351924061775e-03 + + 5.1678192615509033e-01 1.6372759640216827e-01 + <_> + + 0 -1 306 6.5269311890006065e-03 + + 5.3976088762283325e-01 2.9385319352149963e-01 + <_> + + 0 -1 307 -1.3660379685461521e-02 + + 7.0864880084991455e-01 4.5322000980377197e-01 + <_> + + 0 -1 308 2.7358869090676308e-02 + + 5.2064812183380127e-01 3.5892319679260254e-01 + <_> + + 0 -1 309 6.2197551596909761e-04 + + 3.5070759057998657e-01 5.4411232471466064e-01 + <_> + + 0 -1 310 -3.3077080734074116e-03 + + 5.8595228195190430e-01 4.0248918533325195e-01 + <_> + + 0 -1 311 -1.0631109587848186e-02 + + 6.7432671785354614e-01 4.4226029515266418e-01 + <_> + + 0 -1 312 1.9441649317741394e-02 + + 5.2827161550521851e-01 1.7979049682617188e-01 + <_> + 71 + 3.4554111480712891e+01 + + <_> + + 0 -1 313 -5.5052167735993862e-03 + + 5.9147310256958008e-01 2.6265591382980347e-01 + <_> + + 0 -1 314 1.9562279339879751e-03 + + 2.3125819861888885e-01 5.7416272163391113e-01 + <_> + + 0 -1 315 -8.8924784213304520e-03 + + 1.6565300524234772e-01 5.6266540288925171e-01 + <_> + + 0 -1 316 8.3638377487659454e-02 + + 5.4234498739242554e-01 1.9572949409484863e-01 + <_> + + 0 -1 317 1.2282270472496748e-03 + + 3.4179040789604187e-01 5.9925037622451782e-01 + <_> + + 0 -1 318 5.7629169896245003e-03 + + 3.7195819616317749e-01 6.0799038410186768e-01 + <_> + + 0 -1 319 -1.6417410224676132e-03 + + 2.5774860382080078e-01 5.5769157409667969e-01 + <_> + + 0 -1 320 3.4113149158656597e-03 + + 2.9507490992546082e-01 5.5141717195510864e-01 + <_> + + 0 -1 321 -1.1069320142269135e-02 + + 7.5693589448928833e-01 4.4770789146423340e-01 + <_> + + 0 -1 322 3.4865971654653549e-02 + + 5.5837088823318481e-01 2.6696211099624634e-01 + <_> + + 0 -1 323 6.5701099811121821e-04 + + 5.6273132562637329e-01 2.9888901114463806e-01 + <_> + + 0 -1 324 -2.4339130148291588e-02 + + 2.7711850404739380e-01 5.1088631153106689e-01 + <_> + + 0 -1 325 5.9435202274471521e-04 + + 5.5806517601013184e-01 3.1203418970108032e-01 + <_> + + 0 -1 326 2.2971509024500847e-03 + + 3.3302500844001770e-01 5.6790757179260254e-01 + <_> + + 0 -1 327 -3.7801829166710377e-03 + + 2.9905349016189575e-01 5.3448081016540527e-01 + <_> + + 0 -1 328 -1.3420669734477997e-01 + + 1.4638589322566986e-01 5.3925681114196777e-01 + <_> + + 0 -1 329 7.5224548345431685e-04 + + 3.7469539046287537e-01 5.6927347183227539e-01 + <_> + + 0 -1 330 -4.0545541793107986e-02 + + 2.7547478675842285e-01 5.4842978715896606e-01 + <_> + + 0 -1 331 1.2572970008477569e-03 + + 3.7445840239524841e-01 5.7560759782791138e-01 + <_> + + 0 -1 332 -7.4249948374927044e-03 + + 7.5138592720031738e-01 4.7282311320304871e-01 + <_> + + 0 -1 333 5.0908129196614027e-04 + + 5.4048967361450195e-01 2.9323211312294006e-01 + <_> + + 0 -1 334 -1.2808450264856219e-03 + + 6.1697798967361450e-01 4.2733490467071533e-01 + <_> + + 0 -1 335 -1.8348860321566463e-03 + + 2.0484960079193115e-01 5.2064722776412964e-01 + <_> + + 0 -1 336 2.7484869584441185e-02 + + 5.2529847621917725e-01 1.6755220293998718e-01 + <_> + + 0 -1 337 2.2372419480234385e-03 + + 5.2677828073501587e-01 2.7776581048965454e-01 + <_> + + 0 -1 338 -8.8635291904211044e-03 + + 6.9545578956604004e-01 4.8120489716529846e-01 + <_> + + 0 -1 339 4.1753971017897129e-03 + + 4.2918878793716431e-01 6.3491958379745483e-01 + <_> + + 0 -1 340 -1.7098189564421773e-03 + + 2.9305368661880493e-01 5.3612488508224487e-01 + <_> + + 0 -1 341 6.5328548662364483e-03 + + 4.4953250885009766e-01 7.4096941947937012e-01 + <_> + + 0 -1 342 -9.5372907817363739e-03 + + 3.1491199135780334e-01 5.4165017604827881e-01 + <_> + + 0 -1 343 2.5310989469289780e-02 + + 5.1218920946121216e-01 1.3117079436779022e-01 + <_> + + 0 -1 344 3.6460969597101212e-02 + + 5.1759117841720581e-01 2.5913399457931519e-01 + <_> + + 0 -1 345 2.0854329690337181e-02 + + 5.1371401548385620e-01 1.5823160111904144e-01 + <_> + + 0 -1 346 -8.7207747856155038e-04 + + 5.5743098258972168e-01 4.3989789485931396e-01 + <_> + + 0 -1 347 -1.5227000403683633e-05 + + 5.5489408969879150e-01 3.7080699205398560e-01 + <_> + + 0 -1 348 -8.4316509310156107e-04 + + 3.3874198794364929e-01 5.5542111396789551e-01 + <_> + + 0 -1 349 3.6037859972566366e-03 + + 5.3580617904663086e-01 3.4111711382865906e-01 + <_> + + 0 -1 350 -6.8057891912758350e-03 + + 6.1252027750015259e-01 4.3458628654479980e-01 + <_> + + 0 -1 351 -4.7021660953760147e-02 + + 2.3581659793853760e-01 5.1937389373779297e-01 + <_> + + 0 -1 352 -3.6954108625650406e-02 + + 7.3231112957000732e-01 4.7609439492225647e-01 + <_> + + 0 -1 353 1.0439479956403375e-03 + + 5.4194551706314087e-01 3.4113308787345886e-01 + <_> + + 0 -1 354 -2.1050689974799752e-04 + + 2.8216940164566040e-01 5.5549472570419312e-01 + <_> + + 0 -1 355 -8.0831587314605713e-02 + + 9.1299301385879517e-01 4.6974349021911621e-01 + <_> + + 0 -1 356 -3.6579059087671340e-04 + + 6.0226702690124512e-01 3.9782929420471191e-01 + <_> + + 0 -1 357 -1.2545920617412776e-04 + + 5.6132131814956665e-01 3.8455399870872498e-01 + <_> + + 0 -1 358 -6.8786486983299255e-02 + + 2.2616119682788849e-01 5.3004968166351318e-01 + <_> + + 0 -1 359 1.2415789999067783e-02 + + 4.0756919980049133e-01 5.8288121223449707e-01 + <_> + + 0 -1 360 -4.7174817882478237e-03 + + 2.8272539377212524e-01 5.2677577733993530e-01 + <_> + + 0 -1 361 3.8136858493089676e-02 + + 5.0747412443161011e-01 1.0236159712076187e-01 + <_> + + 0 -1 362 -2.8168049175292253e-03 + + 6.1690068244934082e-01 4.3596929311752319e-01 + <_> + + 0 -1 363 8.1303603947162628e-03 + + 4.5244330167770386e-01 7.6060950756072998e-01 + <_> + + 0 -1 364 6.0056019574403763e-03 + + 5.2404087781906128e-01 1.8597120046615601e-01 + <_> + + 0 -1 365 1.9139319658279419e-02 + + 5.2093791961669922e-01 2.3320719599723816e-01 + <_> + + 0 -1 366 1.6445759683847427e-02 + + 5.4507029056549072e-01 3.2642349600791931e-01 + <_> + + 0 -1 367 -3.7356890738010406e-02 + + 6.9990468025207520e-01 4.5332419872283936e-01 + <_> + + 0 -1 368 -1.9727900624275208e-02 + + 2.6536649465560913e-01 5.4128098487854004e-01 + <_> + + 0 -1 369 6.6972579807043076e-03 + + 4.4805660843849182e-01 7.1386522054672241e-01 + <_> + + 0 -1 370 7.4457528535276651e-04 + + 4.2313501238822937e-01 5.4713201522827148e-01 + <_> + + 0 -1 371 1.1790640419349074e-03 + + 5.3417021036148071e-01 3.1304550170898438e-01 + <_> + + 0 -1 372 3.4980610013008118e-02 + + 5.1186597347259521e-01 3.4305301308631897e-01 + <_> + + 0 -1 373 5.6859792675822973e-04 + + 3.5321870446205139e-01 5.4686397314071655e-01 + <_> + + 0 -1 374 -1.1340649798512459e-02 + + 2.8423538804054260e-01 5.3487008810043335e-01 + <_> + + 0 -1 375 -6.6228108480572701e-03 + + 6.8836402893066406e-01 4.4926649332046509e-01 + <_> + + 0 -1 376 -8.0160330981016159e-03 + + 1.7098939418792725e-01 5.2243089675903320e-01 + <_> + + 0 -1 377 1.4206819469109178e-03 + + 5.2908462285995483e-01 2.9933831095695496e-01 + <_> + + 0 -1 378 -2.7801711112260818e-03 + + 6.4988541603088379e-01 4.4604998826980591e-01 + <_> + + 0 -1 379 -1.4747589593753219e-03 + + 3.2604381442070007e-01 5.3881132602691650e-01 + <_> + + 0 -1 380 -2.3830339312553406e-02 + + 7.5289410352706909e-01 4.8012199997901917e-01 + <_> + + 0 -1 381 6.9369790144264698e-03 + + 5.3351658582687378e-01 3.2614278793334961e-01 + <_> + + 0 -1 382 8.2806255668401718e-03 + + 4.5803940296173096e-01 5.7378298044204712e-01 + <_> + + 0 -1 383 -1.0439500212669373e-02 + + 2.5923201441764832e-01 5.2338278293609619e-01 + <_> + 80 + 3.9107288360595703e+01 + + <_> + + 0 -1 384 7.2006587870419025e-03 + + 3.2588860392570496e-01 6.8498080968856812e-01 + <_> + + 0 -1 385 -2.8593589086085558e-03 + + 5.8388811349868774e-01 2.5378298759460449e-01 + <_> + + 0 -1 386 6.8580528022721410e-04 + + 5.7080817222595215e-01 2.8124240040779114e-01 + <_> + + 0 -1 387 7.9580191522836685e-03 + + 2.5010511279106140e-01 5.5442607402801514e-01 + <_> + + 0 -1 388 -1.2124150525778532e-03 + + 2.3853680491447449e-01 5.4333502054214478e-01 + <_> + + 0 -1 389 7.9426132142543793e-03 + + 3.9550709724426270e-01 6.2207579612731934e-01 + <_> + + 0 -1 390 2.4630590341985226e-03 + + 5.6397080421447754e-01 2.9923579096794128e-01 + <_> + + 0 -1 391 -6.0396599583327770e-03 + + 2.1865129470825195e-01 5.4116767644882202e-01 + <_> + + 0 -1 392 -1.2988339876756072e-03 + + 2.3507060110569000e-01 5.3645849227905273e-01 + <_> + + 0 -1 393 2.2299369447864592e-04 + + 3.8041129708290100e-01 5.7296061515808105e-01 + <_> + + 0 -1 394 1.4654280385002494e-03 + + 2.5101679563522339e-01 5.2582687139511108e-01 + <_> + + 0 -1 395 -8.1210042117163539e-04 + + 5.9928238391876221e-01 3.8511589169502258e-01 + <_> + + 0 -1 396 -1.3836020370945334e-03 + + 5.6813961267471313e-01 3.6365869641304016e-01 + <_> + + 0 -1 397 -2.7936449274420738e-02 + + 1.4913170039653778e-01 5.3775602579116821e-01 + <_> + + 0 -1 398 -4.6919551095925272e-04 + + 3.6924299597740173e-01 5.5724847316741943e-01 + <_> + + 0 -1 399 -4.9829659983515739e-03 + + 6.7585092782974243e-01 4.5325040817260742e-01 + <_> + + 0 -1 400 1.8815309740602970e-03 + + 5.3680229187011719e-01 2.9325398802757263e-01 + <_> + + 0 -1 401 -1.9067550078034401e-02 + + 1.6493770480155945e-01 5.3300672769546509e-01 + <_> + + 0 -1 402 -4.6906559728085995e-03 + + 1.9639259576797485e-01 5.1193618774414062e-01 + <_> + + 0 -1 403 5.9777139686048031e-03 + + 4.6711719036102295e-01 7.0083981752395630e-01 + <_> + + 0 -1 404 -3.3303130418062210e-02 + + 1.1554169654846191e-01 5.1041620969772339e-01 + <_> + + 0 -1 405 9.0744107961654663e-02 + + 5.1496601104736328e-01 1.3061730563640594e-01 + <_> + + 0 -1 406 9.3555898638442159e-04 + + 3.6054810881614685e-01 5.4398590326309204e-01 + <_> + + 0 -1 407 1.4901650138199329e-02 + + 4.8862120509147644e-01 7.6875698566436768e-01 + <_> + + 0 -1 408 6.1594118596985936e-04 + + 5.3568130731582642e-01 3.2409390807151794e-01 + <_> + + 0 -1 409 -5.0670988857746124e-02 + + 1.8486219644546509e-01 5.2304041385650635e-01 + <_> + + 0 -1 410 6.8665749859064817e-04 + + 3.8405799865722656e-01 5.5179458856582642e-01 + <_> + + 0 -1 411 8.3712432533502579e-03 + + 4.2885640263557434e-01 6.1317539215087891e-01 + <_> + + 0 -1 412 -1.2953069526702166e-03 + + 2.9136741161346436e-01 5.2807378768920898e-01 + <_> + + 0 -1 413 -4.1941680014133453e-02 + + 7.5547999143600464e-01 4.8560309410095215e-01 + <_> + + 0 -1 414 -2.3529380559921265e-02 + + 2.8382799029350281e-01 5.2560812234878540e-01 + <_> + + 0 -1 415 4.0857449173927307e-02 + + 4.8709350824356079e-01 6.2772971391677856e-01 + <_> + + 0 -1 416 -2.5406869128346443e-02 + + 7.0997077226638794e-01 4.5750290155410767e-01 + <_> + + 0 -1 417 -4.1415440500713885e-04 + + 4.0308868885040283e-01 5.4694122076034546e-01 + <_> + + 0 -1 418 2.1824119612574577e-02 + + 4.5020240545272827e-01 6.7687010765075684e-01 + <_> + + 0 -1 419 1.4114039950072765e-02 + + 5.4428607225418091e-01 3.7917000055313110e-01 + <_> + + 0 -1 420 6.7214590671937913e-05 + + 4.2004638910293579e-01 5.8734762668609619e-01 + <_> + + 0 -1 421 -7.9417638480663300e-03 + + 3.7925618886947632e-01 5.5852657556533813e-01 + <_> + + 0 -1 422 -7.2144409641623497e-03 + + 7.2531038522720337e-01 4.6035489439964294e-01 + <_> + + 0 -1 423 2.5817339774221182e-03 + + 4.6933019161224365e-01 5.9002387523651123e-01 + <_> + + 0 -1 424 1.3409319519996643e-01 + + 5.1492130756378174e-01 1.8088449537754059e-01 + <_> + + 0 -1 425 2.2962710354477167e-03 + + 5.3997439146041870e-01 3.7178671360015869e-01 + <_> + + 0 -1 426 -2.1575849968940020e-03 + + 2.4084959924221039e-01 5.1488637924194336e-01 + <_> + + 0 -1 427 -4.9196188338100910e-03 + + 6.5735882520675659e-01 4.7387400269508362e-01 + <_> + + 0 -1 428 1.6267469618469477e-03 + + 4.1928219795227051e-01 6.3031142950057983e-01 + <_> + + 0 -1 429 3.3413388882763684e-04 + + 5.5402982234954834e-01 3.7021011114120483e-01 + <_> + + 0 -1 430 -2.6698080822825432e-02 + + 1.7109179496765137e-01 5.1014107465744019e-01 + <_> + + 0 -1 431 -3.0561879277229309e-02 + + 1.9042180478572845e-01 5.1687937974929810e-01 + <_> + + 0 -1 432 2.8511548880487680e-03 + + 4.4475069642066956e-01 6.3138538599014282e-01 + <_> + + 0 -1 433 -3.6211479455232620e-02 + + 2.4907270073890686e-01 5.3773492574691772e-01 + <_> + + 0 -1 434 -2.4115189444273710e-03 + + 5.3812432289123535e-01 3.6642369627952576e-01 + <_> + + 0 -1 435 -7.7253201743587852e-04 + + 5.5302321910858154e-01 3.5415500402450562e-01 + <_> + + 0 -1 436 2.9481729143299162e-04 + + 4.1326990723609924e-01 5.6672430038452148e-01 + <_> + + 0 -1 437 -6.2334560789167881e-03 + + 9.8787233233451843e-02 5.1986688375473022e-01 + <_> + + 0 -1 438 -2.6274729520082474e-02 + + 9.1127492487430573e-02 5.0281071662902832e-01 + <_> + + 0 -1 439 5.3212260827422142e-03 + + 4.7266489267349243e-01 6.2227207422256470e-01 + <_> + + 0 -1 440 -4.1129058226943016e-03 + + 2.1574570238590240e-01 5.1378047466278076e-01 + <_> + + 0 -1 441 3.2457809429615736e-03 + + 5.4107707738876343e-01 3.7217769026756287e-01 + <_> + + 0 -1 442 -1.6359709203243256e-02 + + 7.7878749370574951e-01 4.6852919459342957e-01 + <_> + + 0 -1 443 3.2166109303943813e-04 + + 5.4789870977401733e-01 4.2403739690780640e-01 + <_> + + 0 -1 444 6.4452440710738301e-04 + + 5.3305608034133911e-01 3.5013249516487122e-01 + <_> + + 0 -1 445 -7.8909732401371002e-03 + + 6.9235211610794067e-01 4.7265690565109253e-01 + <_> + + 0 -1 446 4.8336211591959000e-02 + + 5.0559002161026001e-01 7.5749203562736511e-02 + <_> + + 0 -1 447 -7.5178127735853195e-04 + + 3.7837418913841248e-01 5.5385738611221313e-01 + <_> + + 0 -1 448 -2.4953910615295172e-03 + + 3.0816510319709778e-01 5.3596121072769165e-01 + <_> + + 0 -1 449 -2.2385010961443186e-03 + + 6.6339588165283203e-01 4.6493428945541382e-01 + <_> + + 0 -1 450 -1.7988430336117744e-03 + + 6.5968447923660278e-01 4.3471878767013550e-01 + <_> + + 0 -1 451 8.7860915809869766e-03 + + 5.2318328619003296e-01 2.3155799508094788e-01 + <_> + + 0 -1 452 3.6715380847454071e-03 + + 5.2042502164840698e-01 2.9773768782615662e-01 + <_> + + 0 -1 453 -3.5336449742317200e-02 + + 7.2388780117034912e-01 4.8615050315856934e-01 + <_> + + 0 -1 454 -6.9189240457490087e-04 + + 3.1050220131874084e-01 5.2298247814178467e-01 + <_> + + 0 -1 455 -3.3946109469980001e-03 + + 3.1389680504798889e-01 5.2101737260818481e-01 + <_> + + 0 -1 456 9.8569283727556467e-04 + + 4.5365801453590393e-01 6.5850979089736938e-01 + <_> + + 0 -1 457 -5.0163101404905319e-02 + + 1.8044540286064148e-01 5.1989167928695679e-01 + <_> + + 0 -1 458 -2.2367259953171015e-03 + + 7.2557020187377930e-01 4.6513590216636658e-01 + <_> + + 0 -1 459 7.4326287722215056e-04 + + 4.4129210710525513e-01 5.8985459804534912e-01 + <_> + + 0 -1 460 -9.3485182151198387e-04 + + 3.5000529885292053e-01 5.3660178184509277e-01 + <_> + + 0 -1 461 1.7497939988970757e-02 + + 4.9121949076652527e-01 8.3152848482131958e-01 + <_> + + 0 -1 462 -1.5200000489130616e-03 + + 3.5702759027481079e-01 5.3705602884292603e-01 + <_> + + 0 -1 463 7.8003940870985389e-04 + + 4.3537721037864685e-01 5.9673351049423218e-01 + <_> + 103 + 5.0610481262207031e+01 + + <_> + + 0 -1 464 -9.9945552647113800e-03 + + 6.1625832319259644e-01 3.0545330047607422e-01 + <_> + + 0 -1 465 -1.1085229925811291e-03 + + 5.8182948827743530e-01 3.1555780768394470e-01 + <_> + + 0 -1 466 1.0364380432292819e-03 + + 2.5520521402359009e-01 5.6929117441177368e-01 + <_> + + 0 -1 467 6.8211311008781195e-04 + + 3.6850899457931519e-01 5.9349310398101807e-01 + <_> + + 0 -1 468 -6.8057340104132891e-04 + + 2.3323920369148254e-01 5.4747921228408813e-01 + <_> + + 0 -1 469 2.6068789884448051e-04 + + 3.2574570178985596e-01 5.6675457954406738e-01 + <_> + + 0 -1 470 5.1607372006401420e-04 + + 3.7447169423103333e-01 5.8454728126525879e-01 + <_> + + 0 -1 471 8.5007521556690335e-04 + + 3.4203711152076721e-01 5.5228072404861450e-01 + <_> + + 0 -1 472 -1.8607829697430134e-03 + + 2.8044199943542480e-01 5.3754240274429321e-01 + <_> + + 0 -1 473 -1.5033970121294260e-03 + + 2.5790509581565857e-01 5.4989522695541382e-01 + <_> + + 0 -1 474 2.3478909861296415e-03 + + 4.1751560568809509e-01 6.3137108087539673e-01 + <_> + + 0 -1 475 -2.8880240279249847e-04 + + 5.8651697635650635e-01 4.0526661276817322e-01 + <_> + + 0 -1 476 8.9405477046966553e-03 + + 5.2111411094665527e-01 2.3186540603637695e-01 + <_> + + 0 -1 477 -1.9327739253640175e-02 + + 2.7534329891204834e-01 5.2415257692337036e-01 + <_> + + 0 -1 478 -2.0202060113660991e-04 + + 5.7229787111282349e-01 3.6771959066390991e-01 + <_> + + 0 -1 479 2.1179069299250841e-03 + + 4.4661080837249756e-01 5.5424308776855469e-01 + <_> + + 0 -1 480 -1.7743760254234076e-03 + + 2.8132531046867371e-01 5.3009599447250366e-01 + <_> + + 0 -1 481 4.2234458960592747e-03 + + 4.3997099995613098e-01 5.7954281568527222e-01 + <_> + + 0 -1 482 -1.4375220052897930e-02 + + 2.9811179637908936e-01 5.2920591831207275e-01 + <_> + + 0 -1 483 -1.5349180437624454e-02 + + 7.7052152156829834e-01 4.7481718659400940e-01 + <_> + + 0 -1 484 1.5152279956964776e-05 + + 3.7188440561294556e-01 5.5768972635269165e-01 + <_> + + 0 -1 485 -9.1293919831514359e-03 + + 3.6151960492134094e-01 5.2867668867111206e-01 + <_> + + 0 -1 486 2.2512159775942564e-03 + + 5.3647047281265259e-01 3.4862980246543884e-01 + <_> + + 0 -1 487 -4.9696918576955795e-03 + + 6.9276517629623413e-01 4.6768361330032349e-01 + <_> + + 0 -1 488 -1.2829010374844074e-02 + + 7.7121537923812866e-01 4.6607351303100586e-01 + <_> + + 0 -1 489 -9.3660065904259682e-03 + + 3.3749839663505554e-01 5.3512877225875854e-01 + <_> + + 0 -1 490 3.2452319283038378e-03 + + 5.3251898288726807e-01 3.2896101474761963e-01 + <_> + + 0 -1 491 -1.1723560281097889e-02 + + 6.8376529216766357e-01 4.7543001174926758e-01 + <_> + + 0 -1 492 2.9257940695970319e-05 + + 3.5720878839492798e-01 5.3605020046234131e-01 + <_> + + 0 -1 493 -2.2244219508138485e-05 + + 5.5414271354675293e-01 3.5520640015602112e-01 + <_> + + 0 -1 494 5.0881509669125080e-03 + + 5.0708442926406860e-01 1.2564620375633240e-01 + <_> + + 0 -1 495 2.7429679408669472e-02 + + 5.2695602178573608e-01 1.6258180141448975e-01 + <_> + + 0 -1 496 -6.4142867922782898e-03 + + 7.1455889940261841e-01 4.5841971039772034e-01 + <_> + + 0 -1 497 3.3479959238320589e-03 + + 5.3986120223999023e-01 3.4946969151496887e-01 + <_> + + 0 -1 498 -8.2635492086410522e-02 + + 2.4391929805278778e-01 5.1602262258529663e-01 + <_> + + 0 -1 499 1.0261740535497665e-03 + + 3.8868919014930725e-01 5.7679080963134766e-01 + <_> + + 0 -1 500 -1.6307090409100056e-03 + + 3.3894580602645874e-01 5.3477007150650024e-01 + <_> + + 0 -1 501 2.4546680506318808e-03 + + 4.6014139056205750e-01 6.3872468471527100e-01 + <_> + + 0 -1 502 -9.9476519972085953e-04 + + 5.7698792219161987e-01 4.1203960776329041e-01 + <_> + + 0 -1 503 1.5409190207719803e-02 + + 4.8787090182304382e-01 7.0898222923278809e-01 + <_> + + 0 -1 504 1.1784400558099151e-03 + + 5.2635532617568970e-01 2.8952449560165405e-01 + <_> + + 0 -1 505 -2.7701919898390770e-02 + + 1.4988289773464203e-01 5.2196067571640015e-01 + <_> + + 0 -1 506 -2.9505399987101555e-02 + + 2.4893319234251976e-02 4.9998161196708679e-01 + <_> + + 0 -1 507 4.5159430010244250e-04 + + 5.4646229743957520e-01 4.0296629071235657e-01 + <_> + + 0 -1 508 7.1772639639675617e-03 + + 4.2710569500923157e-01 5.8662968873977661e-01 + <_> + + 0 -1 509 -7.4182048439979553e-02 + + 6.8741792440414429e-01 4.9190279841423035e-01 + <_> + + 0 -1 510 -1.7254160717129707e-02 + + 3.3706760406494141e-01 5.3487390279769897e-01 + <_> + + 0 -1 511 1.4851559884846210e-02 + + 4.6267929673194885e-01 6.1299049854278564e-01 + <_> + + 0 -1 512 1.0002000257372856e-02 + + 5.3461229801177979e-01 3.4234538674354553e-01 + <_> + + 0 -1 513 2.0138120744377375e-03 + + 4.6438300609588623e-01 5.8243042230606079e-01 + <_> + + 0 -1 514 1.5135470312088728e-03 + + 5.1963961124420166e-01 2.8561499714851379e-01 + <_> + + 0 -1 515 3.1381431035697460e-03 + + 4.8381629586219788e-01 5.9585297107696533e-01 + <_> + + 0 -1 516 -5.1450440660119057e-03 + + 8.9203029870986938e-01 4.7414121031761169e-01 + <_> + + 0 -1 517 -4.4736708514392376e-03 + + 2.0339429378509521e-01 5.3372788429260254e-01 + <_> + + 0 -1 518 1.9628470763564110e-03 + + 4.5716339349746704e-01 6.7258632183074951e-01 + <_> + + 0 -1 519 5.4260450415313244e-03 + + 5.2711081504821777e-01 2.8456708788871765e-01 + <_> + + 0 -1 520 4.9611460417509079e-04 + + 4.1383129358291626e-01 5.7185977697372437e-01 + <_> + + 0 -1 521 9.3728788197040558e-03 + + 5.2251511812210083e-01 2.8048470616340637e-01 + <_> + + 0 -1 522 6.0500897234305739e-04 + + 5.2367687225341797e-01 3.3145239949226379e-01 + <_> + + 0 -1 523 5.6792551185935736e-04 + + 4.5310598611831665e-01 6.2769711017608643e-01 + <_> + + 0 -1 524 2.4644339457154274e-02 + + 5.1308518648147583e-01 2.0171439647674561e-01 + <_> + + 0 -1 525 -1.0290450416505337e-02 + + 7.7865952253341675e-01 4.8766410350799561e-01 + <_> + + 0 -1 526 2.0629419013857841e-03 + + 4.2885988950729370e-01 5.8812642097473145e-01 + <_> + + 0 -1 527 -5.0519481301307678e-03 + + 3.5239779949188232e-01 5.2860087156295776e-01 + <_> + + 0 -1 528 -5.7692620903253555e-03 + + 6.8410861492156982e-01 4.5880940556526184e-01 + <_> + + 0 -1 529 -4.5789941214025021e-04 + + 3.5655200481414795e-01 5.4859781265258789e-01 + <_> + + 0 -1 530 -7.5918837683275342e-04 + + 3.3687931299209595e-01 5.2541971206665039e-01 + <_> + + 0 -1 531 -1.7737259622663260e-03 + + 3.4221610426902771e-01 5.4540151357650757e-01 + <_> + + 0 -1 532 -8.5610467940568924e-03 + + 6.5336120128631592e-01 4.4858568906784058e-01 + <_> + + 0 -1 533 1.7277270089834929e-03 + + 5.3075802326202393e-01 3.9253529906272888e-01 + <_> + + 0 -1 534 -2.8199609369039536e-02 + + 6.8574589490890503e-01 4.5885840058326721e-01 + <_> + + 0 -1 535 -1.7781109781935811e-03 + + 4.0378510951995850e-01 5.3698569536209106e-01 + <_> + + 0 -1 536 3.3177141449414194e-04 + + 5.3997987508773804e-01 3.7057501077651978e-01 + <_> + + 0 -1 537 2.6385399978607893e-03 + + 4.6654370427131653e-01 6.4527308940887451e-01 + <_> + + 0 -1 538 -2.1183069329708815e-03 + + 5.9147810935974121e-01 4.0646770596504211e-01 + <_> + + 0 -1 539 -1.4773289673030376e-02 + + 3.6420381069183350e-01 5.2947628498077393e-01 + <_> + + 0 -1 540 -1.6815440729260445e-02 + + 2.6642319560050964e-01 5.1449728012084961e-01 + <_> + + 0 -1 541 -6.3370140269398689e-03 + + 6.7795312404632568e-01 4.8520979285240173e-01 + <_> + + 0 -1 542 -4.4560048991115764e-05 + + 5.6139647960662842e-01 4.1530540585517883e-01 + <_> + + 0 -1 543 -1.0240620467811823e-03 + + 5.9644782543182373e-01 4.5663040876388550e-01 + <_> + + 0 -1 544 -2.3161689750850201e-03 + + 2.9761150479316711e-01 5.1881599426269531e-01 + <_> + + 0 -1 545 5.3217571973800659e-01 + + 5.1878392696380615e-01 2.2026319801807404e-01 + <_> + + 0 -1 546 -1.6643050312995911e-01 + + 1.8660229444503784e-01 5.0603431463241577e-01 + <_> + + 0 -1 547 1.1253529787063599e-01 + + 5.2121251821517944e-01 1.1850229650735855e-01 + <_> + + 0 -1 548 9.3046864494681358e-03 + + 4.5899370312690735e-01 6.8261492252349854e-01 + <_> + + 0 -1 549 -4.6255099587142467e-03 + + 3.0799409747123718e-01 5.2250087261199951e-01 + <_> + + 0 -1 550 -1.1116469651460648e-01 + + 2.1010440587997437e-01 5.0808018445968628e-01 + <_> + + 0 -1 551 -1.0888439603149891e-02 + + 5.7653552293777466e-01 4.7904640436172485e-01 + <_> + + 0 -1 552 5.8564301580190659e-03 + + 5.0651001930236816e-01 1.5635989606380463e-01 + <_> + + 0 -1 553 5.4854389280080795e-02 + + 4.9669149518013000e-01 7.2305107116699219e-01 + <_> + + 0 -1 554 -1.1197339743375778e-02 + + 2.1949790418148041e-01 5.0987982749938965e-01 + <_> + + 0 -1 555 4.4069071300327778e-03 + + 4.7784018516540527e-01 6.7709028720855713e-01 + <_> + + 0 -1 556 -6.3665293157100677e-02 + + 1.9363629817962646e-01 5.0810241699218750e-01 + <_> + + 0 -1 557 -9.8081491887569427e-03 + + 5.9990632534027100e-01 4.8103410005569458e-01 + <_> + + 0 -1 558 -2.1717099007219076e-03 + + 3.3383339643478394e-01 5.2354729175567627e-01 + <_> + + 0 -1 559 -1.3315520249307156e-02 + + 6.6170698404312134e-01 4.9192130565643311e-01 + <_> + + 0 -1 560 2.5442079640924931e-03 + + 4.4887441396713257e-01 6.0821849107742310e-01 + <_> + + 0 -1 561 1.2037839740514755e-02 + + 5.4093921184539795e-01 3.2924321293830872e-01 + <_> + + 0 -1 562 -2.0701050758361816e-02 + + 6.8191200494766235e-01 4.5949959754943848e-01 + <_> + + 0 -1 563 2.7608279138803482e-02 + + 4.6307921409606934e-01 5.7672828435897827e-01 + <_> + + 0 -1 564 1.2370620388537645e-03 + + 5.1653790473937988e-01 2.6350161433219910e-01 + <_> + + 0 -1 565 -3.7669338285923004e-02 + + 2.5363931059837341e-01 5.2789801359176636e-01 + <_> + + 0 -1 566 -1.8057259730994701e-03 + + 3.9851561188697815e-01 5.5175000429153442e-01 + <_> + 111 + 5.4620071411132812e+01 + + <_> + + 0 -1 567 4.4299028813838959e-03 + + 2.8910180926322937e-01 6.3352262973785400e-01 + <_> + + 0 -1 568 -2.3813319858163595e-03 + + 6.2117892503738403e-01 3.4774878621101379e-01 + <_> + + 0 -1 569 2.2915711160749197e-03 + + 2.2544120252132416e-01 5.5821180343627930e-01 + <_> + + 0 -1 570 9.9457940086722374e-04 + + 3.7117108702659607e-01 5.9300708770751953e-01 + <_> + + 0 -1 571 7.7164667891338468e-04 + + 5.6517201662063599e-01 3.3479958772659302e-01 + <_> + + 0 -1 572 -1.1386410333216190e-03 + + 3.0691260099411011e-01 5.5086308717727661e-01 + <_> + + 0 -1 573 -1.6403039626311511e-04 + + 5.7628279924392700e-01 3.6990478634834290e-01 + <_> + + 0 -1 574 2.9793529392918572e-05 + + 2.6442441344261169e-01 5.4379111528396606e-01 + <_> + + 0 -1 575 8.5774902254343033e-03 + + 5.0511389970779419e-01 1.7957249283790588e-01 + <_> + + 0 -1 576 -2.6032689493149519e-04 + + 5.8269691467285156e-01 4.4468268752098083e-01 + <_> + + 0 -1 577 -6.1404630541801453e-03 + + 3.1138521432876587e-01 5.3469717502593994e-01 + <_> + + 0 -1 578 -2.3086950182914734e-02 + + 3.2779461145401001e-01 5.3311979770660400e-01 + <_> + + 0 -1 579 -1.4243650250136852e-02 + + 7.3817098140716553e-01 4.5880630612373352e-01 + <_> + + 0 -1 580 1.9487129524350166e-02 + + 5.2566307783126831e-01 2.2744719684123993e-01 + <_> + + 0 -1 581 -9.6681108698248863e-04 + + 5.5112308263778687e-01 3.8150069117546082e-01 + <_> + + 0 -1 582 3.1474709976464510e-03 + + 5.4256367683410645e-01 2.5437268614768982e-01 + <_> + + 0 -1 583 -1.8026070029009134e-04 + + 5.3801918029785156e-01 3.4063041210174561e-01 + <_> + + 0 -1 584 -6.0266260989010334e-03 + + 3.0358019471168518e-01 5.4205721616744995e-01 + <_> + + 0 -1 585 4.4462960795499384e-04 + + 3.9909970760345459e-01 5.6601101160049438e-01 + <_> + + 0 -1 586 2.2609760053455830e-03 + + 5.5628067255020142e-01 3.9406880736351013e-01 + <_> + + 0 -1 587 5.1133058965206146e-02 + + 4.6096539497375488e-01 7.1185618638992310e-01 + <_> + + 0 -1 588 -1.7786309123039246e-02 + + 2.3161660134792328e-01 5.3221440315246582e-01 + <_> + + 0 -1 589 -4.9679628573358059e-03 + + 2.3307719826698303e-01 5.1220291852951050e-01 + <_> + + 0 -1 590 2.0667689386755228e-03 + + 4.6574440598487854e-01 6.4554882049560547e-01 + <_> + + 0 -1 591 7.4413768015801907e-03 + + 5.1543921232223511e-01 2.3616339266300201e-01 + <_> + + 0 -1 592 -3.6277279723435640e-03 + + 6.2197732925415039e-01 4.4766610860824585e-01 + <_> + + 0 -1 593 -5.3530759178102016e-03 + + 1.8373550474643707e-01 5.1022082567214966e-01 + <_> + + 0 -1 594 1.4530919492244720e-01 + + 5.1459872722625732e-01 1.5359309315681458e-01 + <_> + + 0 -1 595 2.4394490756094456e-03 + + 5.3436601161956787e-01 3.6246618628501892e-01 + <_> + + 0 -1 596 -3.1283390708267689e-03 + + 6.2150079011917114e-01 4.8455920815467834e-01 + <_> + + 0 -1 597 1.7940260004252195e-03 + + 4.2992618680000305e-01 5.8241981267929077e-01 + <_> + + 0 -1 598 3.6253821104764938e-02 + + 5.2603340148925781e-01 1.4394679665565491e-01 + <_> + + 0 -1 599 -5.1746722310781479e-03 + + 3.5065388679504395e-01 5.2870452404022217e-01 + <_> + + 0 -1 600 6.5383297624066472e-04 + + 4.8096409440040588e-01 6.1220401525497437e-01 + <_> + + 0 -1 601 -2.6480229571461678e-02 + + 1.1393620073795319e-01 5.0455862283706665e-01 + <_> + + 0 -1 602 -3.0440660193562508e-03 + + 6.3520950078964233e-01 4.7947341203689575e-01 + <_> + + 0 -1 603 3.6993520334362984e-03 + + 5.1311182975769043e-01 2.4985109269618988e-01 + <_> + + 0 -1 604 -3.6762931267730892e-04 + + 5.4213947057723999e-01 3.7095320224761963e-01 + <_> + + 0 -1 605 -4.1382260620594025e-02 + + 1.8949599564075470e-01 5.0816917419433594e-01 + <_> + + 0 -1 606 -1.0532729793339968e-03 + + 6.4543670415878296e-01 4.7836089134216309e-01 + <_> + + 0 -1 607 -2.1648600231856108e-03 + + 6.2150311470031738e-01 4.4998261332511902e-01 + <_> + + 0 -1 608 -5.6747748749330640e-04 + + 3.7126109004020691e-01 5.4193347692489624e-01 + <_> + + 0 -1 609 1.7375840246677399e-01 + + 5.0236439704895020e-01 1.2157420068979263e-01 + <_> + + 0 -1 610 -2.9049699660390615e-03 + + 3.2402679324150085e-01 5.3818839788436890e-01 + <_> + + 0 -1 611 1.2299539521336555e-03 + + 4.1655078530311584e-01 5.7034862041473389e-01 + <_> + + 0 -1 612 -5.4329237900674343e-04 + + 3.8540428876876831e-01 5.5475491285324097e-01 + <_> + + 0 -1 613 -8.3297258242964745e-03 + + 2.2044940292835236e-01 5.0970828533172607e-01 + <_> + + 0 -1 614 -1.0417630255687982e-04 + + 5.6070661544799805e-01 4.3030360341072083e-01 + <_> + + 0 -1 615 3.1204700469970703e-02 + + 4.6216571331024170e-01 6.9820040464401245e-01 + <_> + + 0 -1 616 7.8943502157926559e-03 + + 5.2695941925048828e-01 2.2690680623054504e-01 + <_> + + 0 -1 617 -4.3645310215651989e-03 + + 6.3592231273651123e-01 4.5379561185836792e-01 + <_> + + 0 -1 618 7.6793059706687927e-03 + + 5.2747678756713867e-01 2.7404838800430298e-01 + <_> + + 0 -1 619 -2.5431139394640923e-02 + + 2.0385199785232544e-01 5.0717329978942871e-01 + <_> + + 0 -1 620 8.2000601105391979e-04 + + 4.5874550938606262e-01 6.1198681592941284e-01 + <_> + + 0 -1 621 2.9284600168466568e-03 + + 5.0712740421295166e-01 2.0282049477100372e-01 + <_> + + 0 -1 622 4.5256470912136137e-05 + + 4.8121041059494019e-01 5.4308217763900757e-01 + <_> + + 0 -1 623 1.3158309739083052e-03 + + 4.6258139610290527e-01 6.7793232202529907e-01 + <_> + + 0 -1 624 1.5870389761403203e-03 + + 5.3862917423248291e-01 3.4314650297164917e-01 + <_> + + 0 -1 625 -2.1539660170674324e-02 + + 2.5942500680685043e-02 5.0032228231430054e-01 + <_> + + 0 -1 626 1.4334480278193951e-02 + + 5.2028447389602661e-01 1.5906329452991486e-01 + <_> + + 0 -1 627 -8.3881383761763573e-03 + + 7.2824811935424805e-01 4.6480441093444824e-01 + <_> + + 0 -1 628 9.1906841844320297e-03 + + 5.5623567104339600e-01 3.9231911301612854e-01 + <_> + + 0 -1 629 -5.8453059755265713e-03 + + 6.8033927679061890e-01 4.6291279792785645e-01 + <_> + + 0 -1 630 -5.4707799106836319e-02 + + 2.5616711378097534e-01 5.2061259746551514e-01 + <_> + + 0 -1 631 9.1142775490880013e-03 + + 5.1896202564239502e-01 3.0538770556449890e-01 + <_> + + 0 -1 632 -1.5575000084936619e-02 + + 1.2950749695301056e-01 5.1690948009490967e-01 + <_> + + 0 -1 633 -1.2050600344082341e-04 + + 5.7350981235504150e-01 4.2308250069618225e-01 + <_> + + 0 -1 634 1.2273970060050488e-03 + + 5.2898782491683960e-01 4.0797919034957886e-01 + <_> + + 0 -1 635 -1.2186600361019373e-03 + + 6.5756398439407349e-01 4.5744091272354126e-01 + <_> + + 0 -1 636 -3.3256649039685726e-03 + + 3.6280471086502075e-01 5.1950198411941528e-01 + <_> + + 0 -1 637 -1.3288309797644615e-02 + + 1.2842659652233124e-01 5.0434887409210205e-01 + <_> + + 0 -1 638 -3.3839771058410406e-03 + + 6.2922400236129761e-01 4.7575059533119202e-01 + <_> + + 0 -1 639 -2.1954220533370972e-01 + + 1.4877319335937500e-01 5.0650137662887573e-01 + <_> + + 0 -1 640 4.9111708067357540e-03 + + 4.2561021447181702e-01 5.6658387184143066e-01 + <_> + + 0 -1 641 -1.8744950648397207e-04 + + 4.0041440725326538e-01 5.5868571996688843e-01 + <_> + + 0 -1 642 -5.2178641781210899e-03 + + 6.0091161727905273e-01 4.8127061128616333e-01 + <_> + + 0 -1 643 -1.1111519997939467e-03 + + 3.5149338841438293e-01 5.2870899438858032e-01 + <_> + + 0 -1 644 4.4036400504410267e-03 + + 4.6422758698463440e-01 5.9240859746932983e-01 + <_> + + 0 -1 645 1.2299499660730362e-01 + + 5.0255292654037476e-01 6.9152481853961945e-02 + <_> + + 0 -1 646 -1.2313510291278362e-02 + + 5.8845919370651245e-01 4.9340128898620605e-01 + <_> + + 0 -1 647 4.1471039876341820e-03 + + 4.3722391128540039e-01 5.8934777975082397e-01 + <_> + + 0 -1 648 -3.5502649843692780e-03 + + 4.3275511264801025e-01 5.3962701559066772e-01 + <_> + + 0 -1 649 -1.9224269315600395e-02 + + 1.9131340086460114e-01 5.0683307647705078e-01 + <_> + + 0 -1 650 1.4395059552043676e-03 + + 5.3081780672073364e-01 4.2435330152511597e-01 + <_> + + 0 -1 651 -6.7751999013125896e-03 + + 6.3653957843780518e-01 4.5400860905647278e-01 + <_> + + 0 -1 652 7.0119630545377731e-03 + + 5.1898342370986938e-01 3.0261999368667603e-01 + <_> + + 0 -1 653 5.4014651104807854e-03 + + 5.1050621271133423e-01 2.5576829910278320e-01 + <_> + + 0 -1 654 9.0274988906458020e-04 + + 4.6969148516654968e-01 5.8618277311325073e-01 + <_> + + 0 -1 655 1.1474450118839741e-02 + + 5.0536459684371948e-01 1.5271779894828796e-01 + <_> + + 0 -1 656 -6.7023430019617081e-03 + + 6.5089809894561768e-01 4.8906040191650391e-01 + <_> + + 0 -1 657 -2.0462959073483944e-03 + + 6.2418168783187866e-01 4.5146000385284424e-01 + <_> + + 0 -1 658 -9.9951568990945816e-03 + + 3.4327811002731323e-01 5.4009538888931274e-01 + <_> + + 0 -1 659 -3.5700708627700806e-02 + + 1.8780590593814850e-01 5.0740778446197510e-01 + <_> + + 0 -1 660 4.5584561303257942e-04 + + 3.8052770495414734e-01 5.4025697708129883e-01 + <_> + + 0 -1 661 -5.4260600358247757e-02 + + 6.8437147140502930e-01 4.5950970053672791e-01 + <_> + + 0 -1 662 6.0600461438298225e-03 + + 5.5029052495956421e-01 4.5005279779434204e-01 + <_> + + 0 -1 663 -6.4791832119226456e-03 + + 3.3688580989837646e-01 5.3107571601867676e-01 + <_> + + 0 -1 664 -1.4939469983801246e-03 + + 6.4876401424407959e-01 4.7561758756637573e-01 + <_> + + 0 -1 665 1.4610530342906713e-05 + + 4.0345790982246399e-01 5.4510641098022461e-01 + <_> + + 0 -1 666 -7.2321938350796700e-03 + + 6.3868737220764160e-01 4.8247399926185608e-01 + <_> + + 0 -1 667 -4.0645818226039410e-03 + + 2.9864218831062317e-01 5.1573359966278076e-01 + <_> + + 0 -1 668 3.0463080853223801e-02 + + 5.0221997499465942e-01 7.1599560976028442e-01 + <_> + + 0 -1 669 -8.0544911324977875e-03 + + 6.4924520254135132e-01 4.6192750334739685e-01 + <_> + + 0 -1 670 3.9505138993263245e-02 + + 5.1505708694458008e-01 2.4506139755249023e-01 + <_> + + 0 -1 671 8.4530208259820938e-03 + + 4.5736691355705261e-01 6.3940370082855225e-01 + <_> + + 0 -1 672 -1.1688120430335402e-03 + + 3.8655120134353638e-01 5.4836612939834595e-01 + <_> + + 0 -1 673 2.8070670086890459e-03 + + 5.1285791397094727e-01 2.7014800906181335e-01 + <_> + + 0 -1 674 4.7365209320560098e-04 + + 4.0515819191932678e-01 5.3874611854553223e-01 + <_> + + 0 -1 675 1.1741080321371555e-02 + + 5.2959501743316650e-01 3.7194138765335083e-01 + <_> + + 0 -1 676 3.1833238899707794e-03 + + 4.7894069552421570e-01 6.8951261043548584e-01 + <_> + + 0 -1 677 7.0241501089185476e-04 + + 5.3844892978668213e-01 3.9180809259414673e-01 + <_> + 102 + 5.0169731140136719e+01 + + <_> + + 0 -1 678 1.7059929668903351e-02 + + 3.9485278725624084e-01 7.1425348520278931e-01 + <_> + + 0 -1 679 2.1840840578079224e-02 + + 3.3703160285949707e-01 6.0900169610977173e-01 + <_> + + 0 -1 680 2.4520049919374287e-04 + + 3.5005760192871094e-01 5.9879022836685181e-01 + <_> + + 0 -1 681 8.3272606134414673e-03 + + 3.2675281167030334e-01 5.6972408294677734e-01 + <_> + + 0 -1 682 5.7148298947140574e-04 + + 3.0445998907089233e-01 5.5316567420959473e-01 + <_> + + 0 -1 683 6.7373987985774875e-04 + + 3.6500120162963867e-01 5.6726312637329102e-01 + <_> + + 0 -1 684 3.4681590477703139e-05 + + 3.3135411143302917e-01 5.3887271881103516e-01 + <_> + + 0 -1 685 -5.8563398197293282e-03 + + 2.6979428529739380e-01 5.4987788200378418e-01 + <_> + + 0 -1 686 8.5102273151278496e-03 + + 5.2693581581115723e-01 2.7628791332244873e-01 + <_> + + 0 -1 687 -6.9817207753658295e-02 + + 2.9096031188964844e-01 5.2592468261718750e-01 + <_> + + 0 -1 688 -8.6113670840859413e-04 + + 5.8925771713256836e-01 4.0736979246139526e-01 + <_> + + 0 -1 689 9.7149249631911516e-04 + + 3.5235640406608582e-01 5.4158622026443481e-01 + <_> + + 0 -1 690 -1.4727490452060010e-05 + + 5.4230177402496338e-01 3.5031560063362122e-01 + <_> + + 0 -1 691 4.8420291393995285e-02 + + 5.1939457654953003e-01 3.4111958742141724e-01 + <_> + + 0 -1 692 1.3257140526548028e-03 + + 3.1577691435813904e-01 5.3353762626647949e-01 + <_> + + 0 -1 693 1.4922149603080470e-05 + + 4.4512999057769775e-01 5.5365538597106934e-01 + <_> + + 0 -1 694 -2.7173398993909359e-03 + + 3.0317419767379761e-01 5.2480888366699219e-01 + <_> + + 0 -1 695 2.9219500720500946e-03 + + 4.7814530134201050e-01 6.6060417890548706e-01 + <_> + + 0 -1 696 -1.9804988987743855e-03 + + 3.1863081455230713e-01 5.2876251935958862e-01 + <_> + + 0 -1 697 -4.0012109093368053e-03 + + 6.4135968685150146e-01 4.7499281167984009e-01 + <_> + + 0 -1 698 -4.3491991236805916e-03 + + 1.5074980258941650e-01 5.0989967584609985e-01 + <_> + + 0 -1 699 1.3490889687091112e-03 + + 4.3161588907241821e-01 5.8811670541763306e-01 + <_> + + 0 -1 700 1.8597070127725601e-02 + + 4.7355538606643677e-01 9.0897941589355469e-01 + <_> + + 0 -1 701 -1.8562379991635680e-03 + + 3.5531890392303467e-01 5.5778372287750244e-01 + <_> + + 0 -1 702 2.2940430790185928e-03 + + 4.5000949501991272e-01 6.5808779001235962e-01 + <_> + + 0 -1 703 2.9982850537635386e-04 + + 5.6292420625686646e-01 3.9758789539337158e-01 + <_> + + 0 -1 704 3.5455459728837013e-03 + + 5.3815472126007080e-01 3.6054858565330505e-01 + <_> + + 0 -1 705 9.6104722470045090e-03 + + 5.2559971809387207e-01 1.7967459559440613e-01 + <_> + + 0 -1 706 -6.2783220782876015e-03 + + 2.2728569805622101e-01 5.1140302419662476e-01 + <_> + + 0 -1 707 3.4598479978740215e-03 + + 4.6263080835342407e-01 6.6082191467285156e-01 + <_> + + 0 -1 708 -1.3112019514665008e-03 + + 6.3175398111343384e-01 4.4368579983711243e-01 + <_> + + 0 -1 709 2.6876179035753012e-03 + + 5.4211097955703735e-01 4.0540221333503723e-01 + <_> + + 0 -1 710 3.9118169806897640e-03 + + 5.3584778308868408e-01 3.2734549045562744e-01 + <_> + + 0 -1 711 -1.4206450432538986e-02 + + 7.7935767173767090e-01 4.9757811427116394e-01 + <_> + + 0 -1 712 7.1705528534948826e-04 + + 5.2973198890686035e-01 3.5609039664268494e-01 + <_> + + 0 -1 713 1.6635019565001130e-03 + + 4.6780940890312195e-01 5.8164817094802856e-01 + <_> + + 0 -1 714 3.3686188980937004e-03 + + 5.2767342329025269e-01 3.4464201331138611e-01 + <_> + + 0 -1 715 1.2799530290067196e-02 + + 4.8346799612045288e-01 7.4721592664718628e-01 + <_> + + 0 -1 716 3.3901201095432043e-03 + + 4.5118591189384460e-01 6.4017212390899658e-01 + <_> + + 0 -1 717 4.7070779837667942e-03 + + 5.3356587886810303e-01 3.5552209615707397e-01 + <_> + + 0 -1 718 1.4819339849054813e-03 + + 4.2507070302963257e-01 5.7727241516113281e-01 + <_> + + 0 -1 719 -6.9995759986341000e-03 + + 3.0033200979232788e-01 5.2929002046585083e-01 + <_> + + 0 -1 720 1.5939010307192802e-02 + + 5.0673192739486694e-01 1.6755819320678711e-01 + <_> + + 0 -1 721 7.6377349905669689e-03 + + 4.7950699925422668e-01 7.0856010913848877e-01 + <_> + + 0 -1 722 6.7334040068089962e-03 + + 5.1331132650375366e-01 2.1624700725078583e-01 + <_> + + 0 -1 723 -1.2858809903264046e-02 + + 1.9388419389724731e-01 5.2513718605041504e-01 + <_> + + 0 -1 724 -6.2270800117403269e-04 + + 5.6865382194519043e-01 4.1978681087493896e-01 + <_> + + 0 -1 725 -5.2651681471616030e-04 + + 4.2241689562797546e-01 5.4296958446502686e-01 + <_> + + 0 -1 726 1.1075099930167198e-02 + + 5.1137751340866089e-01 2.5145179033279419e-01 + <_> + + 0 -1 727 -3.6728251725435257e-02 + + 7.1946620941162109e-01 4.8496189713478088e-01 + <_> + + 0 -1 728 -2.8207109426148236e-04 + + 3.8402619957923889e-01 5.3944462537765503e-01 + <_> + + 0 -1 729 -2.7489690110087395e-03 + + 5.9370887279510498e-01 4.5691820979118347e-01 + <_> + + 0 -1 730 1.0047519579529762e-02 + + 5.1385760307312012e-01 2.8022980690002441e-01 + <_> + + 0 -1 731 -8.1497840583324432e-03 + + 6.0900372266769409e-01 4.6361210942268372e-01 + <_> + + 0 -1 732 -6.8833888508379459e-03 + + 3.4586110711097717e-01 5.2546602487564087e-01 + <_> + + 0 -1 733 -1.4039360394235700e-05 + + 5.6931042671203613e-01 4.0820831060409546e-01 + <_> + + 0 -1 734 1.5498419525101781e-03 + + 4.3505370616912842e-01 5.8065170049667358e-01 + <_> + + 0 -1 735 -6.7841499112546444e-03 + + 1.4688730239868164e-01 5.1827752590179443e-01 + <_> + + 0 -1 736 2.1705629478674382e-04 + + 5.2935242652893066e-01 3.4561741352081299e-01 + <_> + + 0 -1 737 3.1198898795992136e-04 + + 4.6524509787559509e-01 5.9424138069152832e-01 + <_> + + 0 -1 738 5.4507530294358730e-03 + + 4.6535089612007141e-01 7.0248460769653320e-01 + <_> + + 0 -1 739 -2.5818689027801156e-04 + + 5.4972952604293823e-01 3.7689670920372009e-01 + <_> + + 0 -1 740 -1.7442539334297180e-02 + + 3.9190879464149475e-01 5.4574978351593018e-01 + <_> + + 0 -1 741 -4.5343529433012009e-02 + + 1.6313570737838745e-01 5.1549088954925537e-01 + <_> + + 0 -1 742 1.9190689781680703e-03 + + 5.1458978652954102e-01 2.7918958663940430e-01 + <_> + + 0 -1 743 -6.0177869163453579e-03 + + 6.5176361799240112e-01 4.7563329339027405e-01 + <_> + + 0 -1 744 -4.0720738470554352e-03 + + 5.5146527290344238e-01 4.0926858782768250e-01 + <_> + + 0 -1 745 3.9855059003457427e-04 + + 3.1652408838272095e-01 5.2855509519577026e-01 + <_> + + 0 -1 746 -6.5418570302426815e-03 + + 6.8533778190612793e-01 4.6528089046478271e-01 + <_> + + 0 -1 747 3.4845089539885521e-03 + + 5.4845881462097168e-01 4.5027598738670349e-01 + <_> + + 0 -1 748 -1.3696780428290367e-02 + + 6.3957798480987549e-01 4.5725551247596741e-01 + <_> + + 0 -1 749 -1.7347140237689018e-02 + + 2.7510729432106018e-01 5.1816147565841675e-01 + <_> + + 0 -1 750 -4.0885428898036480e-03 + + 3.3256360888481140e-01 5.1949840784072876e-01 + <_> + + 0 -1 751 -9.4687901437282562e-03 + + 5.9422808885574341e-01 4.8518198728561401e-01 + <_> + + 0 -1 752 1.7084840219467878e-03 + + 4.1671109199523926e-01 5.5198061466217041e-01 + <_> + + 0 -1 753 9.4809094443917274e-03 + + 5.4338949918746948e-01 4.2085149884223938e-01 + <_> + + 0 -1 754 -4.7389650717377663e-03 + + 6.4071899652481079e-01 4.5606550574302673e-01 + <_> + + 0 -1 755 6.5761050209403038e-03 + + 5.2145552635192871e-01 2.2582270205020905e-01 + <_> + + 0 -1 756 -2.1690549328923225e-03 + + 3.1515279412269592e-01 5.1567047834396362e-01 + <_> + + 0 -1 757 1.4660170301795006e-02 + + 4.8708370327949524e-01 6.6899412870407104e-01 + <_> + + 0 -1 758 1.7231999663636088e-04 + + 3.5697489976882935e-01 5.2510780096054077e-01 + <_> + + 0 -1 759 -2.1803760901093483e-02 + + 8.8259208202362061e-01 4.9663299322128296e-01 + <_> + + 0 -1 760 -9.4736106693744659e-02 + + 1.4461620151996613e-01 5.0611138343811035e-01 + <_> + + 0 -1 761 5.5825551971793175e-03 + + 5.3964787721633911e-01 4.2380660772323608e-01 + <_> + + 0 -1 762 1.9517090404406190e-03 + + 4.1704109311103821e-01 5.4977869987487793e-01 + <_> + + 0 -1 763 1.2149900197982788e-02 + + 4.6983671188354492e-01 5.6642740964889526e-01 + <_> + + 0 -1 764 -7.5169620104134083e-03 + + 6.2677729129791260e-01 4.4631358981132507e-01 + <_> + + 0 -1 765 -7.1667909622192383e-02 + + 3.0970111489295959e-01 5.2210032939910889e-01 + <_> + + 0 -1 766 -8.8292419910430908e-02 + + 8.1123888492584229e-02 5.0063651800155640e-01 + <_> + + 0 -1 767 3.1063079833984375e-02 + + 5.1555037498474121e-01 1.2822559475898743e-01 + <_> + + 0 -1 768 4.6621840447187424e-02 + + 4.6997779607772827e-01 7.3639607429504395e-01 + <_> + + 0 -1 769 -1.2189489789307117e-02 + + 3.9205300807952881e-01 5.5189967155456543e-01 + <_> + + 0 -1 770 1.3016110286116600e-02 + + 5.2606582641601562e-01 3.6851361393928528e-01 + <_> + + 0 -1 771 -3.4952899441123009e-03 + + 6.3392949104309082e-01 4.7162809967994690e-01 + <_> + + 0 -1 772 -4.4015039748046547e-05 + + 5.3330272436141968e-01 3.7761849164962769e-01 + <_> + + 0 -1 773 -1.0966490209102631e-01 + + 1.7653420567512512e-01 5.1983469724655151e-01 + <_> + + 0 -1 774 -9.0279558207839727e-04 + + 5.3241598606109619e-01 3.8389080762863159e-01 + <_> + + 0 -1 775 7.1126641705632210e-04 + + 4.6479299664497375e-01 5.7552242279052734e-01 + <_> + + 0 -1 776 -3.1250279862433672e-03 + + 3.2367089390754700e-01 5.1667708158493042e-01 + <_> + + 0 -1 777 2.4144679773598909e-03 + + 4.7874391078948975e-01 6.4597177505493164e-01 + <_> + + 0 -1 778 4.4391240226104856e-04 + + 4.4093081355094910e-01 6.0102558135986328e-01 + <_> + + 0 -1 779 -2.2611189342569560e-04 + + 4.0381139516830444e-01 5.4932558536529541e-01 + <_> + 135 + 6.6669120788574219e+01 + + <_> + + 0 -1 780 -4.6901289373636246e-02 + + 6.6001719236373901e-01 3.7438011169433594e-01 + <_> + + 0 -1 781 -1.4568349579349160e-03 + + 5.7839912176132202e-01 3.4377971291542053e-01 + <_> + + 0 -1 782 5.5598369799554348e-03 + + 3.6222669482231140e-01 5.9082162380218506e-01 + <_> + + 0 -1 783 7.3170487303286791e-04 + + 5.5004191398620605e-01 2.8735581040382385e-01 + <_> + + 0 -1 784 1.3318009441718459e-03 + + 2.6731699705123901e-01 5.4310190677642822e-01 + <_> + + 0 -1 785 2.4347059661522508e-04 + + 3.8550278544425964e-01 5.7413887977600098e-01 + <_> + + 0 -1 786 -3.0512469820678234e-03 + + 5.5032098293304443e-01 3.4628450870513916e-01 + <_> + + 0 -1 787 -6.8657199153676629e-04 + + 3.2912218570709229e-01 5.4295092821121216e-01 + <_> + + 0 -1 788 1.4668200165033340e-03 + + 3.5883820056915283e-01 5.3518110513687134e-01 + <_> + + 0 -1 789 3.2021870720200241e-04 + + 4.2968419194221497e-01 5.7002341747283936e-01 + <_> + + 0 -1 790 7.4122188379988074e-04 + + 5.2821648120880127e-01 3.3668708801269531e-01 + <_> + + 0 -1 791 3.8330298848450184e-03 + + 4.5595678687095642e-01 6.2573361396789551e-01 + <_> + + 0 -1 792 -1.5456439927220345e-02 + + 2.3501169681549072e-01 5.1294529438018799e-01 + <_> + + 0 -1 793 2.6796779129654169e-03 + + 5.3294152021408081e-01 4.1550621390342712e-01 + <_> + + 0 -1 794 2.8296569362282753e-03 + + 4.2730879783630371e-01 5.8045381307601929e-01 + <_> + + 0 -1 795 -3.9444249123334885e-03 + + 2.9126119613647461e-01 5.2026861906051636e-01 + <_> + + 0 -1 796 2.7179559692740440e-03 + + 5.3076881170272827e-01 3.5856771469116211e-01 + <_> + + 0 -1 797 5.9077627956867218e-03 + + 4.7037750482559204e-01 5.9415858983993530e-01 + <_> + + 0 -1 798 -4.2240349575877190e-03 + + 2.1415670216083527e-01 5.0887960195541382e-01 + <_> + + 0 -1 799 4.0725888684391975e-03 + + 4.7664138674736023e-01 6.8410611152648926e-01 + <_> + + 0 -1 800 1.0149530135095119e-02 + + 5.3607988357543945e-01 3.7484970688819885e-01 + <_> + + 0 -1 801 -1.8864999583456665e-04 + + 5.7201302051544189e-01 3.8538050651550293e-01 + <_> + + 0 -1 802 -4.8864358104765415e-03 + + 3.6931228637695312e-01 5.3409588336944580e-01 + <_> + + 0 -1 803 2.6158479973673820e-02 + + 4.9623748660087585e-01 6.0599899291992188e-01 + <_> + + 0 -1 804 4.8560759751126170e-04 + + 4.4389459490776062e-01 6.0124689340591431e-01 + <_> + + 0 -1 805 1.1268709786236286e-02 + + 5.2442502975463867e-01 1.8403880298137665e-01 + <_> + + 0 -1 806 -2.8114619199186563e-03 + + 6.0602837800979614e-01 4.4098970293998718e-01 + <_> + + 0 -1 807 -5.6112729944288731e-03 + + 3.8911709189414978e-01 5.5892372131347656e-01 + <_> + + 0 -1 808 8.5680093616247177e-03 + + 5.0693458318710327e-01 2.0626190304756165e-01 + <_> + + 0 -1 809 -3.8172779022715986e-04 + + 5.8822017908096313e-01 4.1926109790802002e-01 + <_> + + 0 -1 810 -1.7680290329735726e-04 + + 5.5336058139801025e-01 4.0033689141273499e-01 + <_> + + 0 -1 811 6.5112537704408169e-03 + + 3.3101469278335571e-01 5.4441910982131958e-01 + <_> + + 0 -1 812 -6.5948683186434209e-05 + + 5.4338318109512329e-01 3.9449059963226318e-01 + <_> + + 0 -1 813 6.9939051754772663e-03 + + 5.6003582477569580e-01 4.1927140951156616e-01 + <_> + + 0 -1 814 -4.6744439750909805e-03 + + 6.6854667663574219e-01 4.6049609780311584e-01 + <_> + + 0 -1 815 1.1589850299060345e-02 + + 5.3571212291717529e-01 2.9268300533294678e-01 + <_> + + 0 -1 816 1.3007840141654015e-02 + + 4.6798178553581238e-01 7.3074632883071899e-01 + <_> + + 0 -1 817 -1.1008579749614000e-03 + + 3.9375010132789612e-01 5.4150652885437012e-01 + <_> + + 0 -1 818 6.0472649056464434e-04 + + 4.2423760890960693e-01 5.6040412187576294e-01 + <_> + + 0 -1 819 -1.4494840055704117e-02 + + 3.6312100291252136e-01 5.2931827306747437e-01 + <_> + + 0 -1 820 -5.3056948818266392e-03 + + 6.8604522943496704e-01 4.6218210458755493e-01 + <_> + + 0 -1 821 -8.1829127157106996e-04 + + 3.9440968632698059e-01 5.4204392433166504e-01 + <_> + + 0 -1 822 -1.9077520817518234e-02 + + 1.9626219570636749e-01 5.0378918647766113e-01 + <_> + + 0 -1 823 3.5549470339901745e-04 + + 4.0862590074539185e-01 5.6139731407165527e-01 + <_> + + 0 -1 824 1.9679730758070946e-03 + + 4.4891211390495300e-01 5.9261232614517212e-01 + <_> + + 0 -1 825 6.9189141504466534e-03 + + 5.3359258174896240e-01 3.7283858656883240e-01 + <_> + + 0 -1 826 2.9872779268771410e-03 + + 5.1113212108612061e-01 2.9756438732147217e-01 + <_> + + 0 -1 827 -6.2264618463814259e-03 + + 5.5414897203445435e-01 4.8245379328727722e-01 + <_> + + 0 -1 828 1.3353300280869007e-02 + + 4.5864239335060120e-01 6.4147979021072388e-01 + <_> + + 0 -1 829 3.3505238592624664e-02 + + 5.3924250602722168e-01 3.4299948811531067e-01 + <_> + + 0 -1 830 -2.5294460356235504e-03 + + 1.7037139832973480e-01 5.0133150815963745e-01 + <_> + + 0 -1 831 -1.2801629491150379e-03 + + 5.3054618835449219e-01 4.6974050998687744e-01 + <_> + + 0 -1 832 7.0687388069927692e-03 + + 4.6155458688735962e-01 6.4365047216415405e-01 + <_> + + 0 -1 833 9.6880499040707946e-04 + + 4.8335990309715271e-01 6.0438942909240723e-01 + <_> + + 0 -1 834 3.9647659286856651e-03 + + 5.1876372098922729e-01 3.2318168878555298e-01 + <_> + + 0 -1 835 -2.2057730704545975e-02 + + 4.0792569518089294e-01 5.2009809017181396e-01 + <_> + + 0 -1 836 -6.6906312713399529e-04 + + 5.3316092491149902e-01 3.8156008720397949e-01 + <_> + + 0 -1 837 -6.7009328631684184e-04 + + 5.6554222106933594e-01 4.6889019012451172e-01 + <_> + + 0 -1 838 7.4284552829340100e-04 + + 4.5343810319900513e-01 6.2874001264572144e-01 + <_> + + 0 -1 839 2.2227810695767403e-03 + + 5.3506332635879517e-01 3.3036559820175171e-01 + <_> + + 0 -1 840 -5.4130521602928638e-03 + + 1.1136870086193085e-01 5.0054347515106201e-01 + <_> + + 0 -1 841 -1.4520040167553816e-05 + + 5.6287378072738647e-01 4.3251338601112366e-01 + <_> + + 0 -1 842 2.3369169502984732e-04 + + 4.1658350825309753e-01 5.4477912187576294e-01 + <_> + + 0 -1 843 4.2894547805190086e-03 + + 4.8603910207748413e-01 6.7786490917205811e-01 + <_> + + 0 -1 844 5.9103150852024555e-03 + + 5.2623051404953003e-01 3.6121138930320740e-01 + <_> + + 0 -1 845 1.2900539673864841e-02 + + 5.3193771839141846e-01 3.2502880692481995e-01 + <_> + + 0 -1 846 4.6982979401946068e-03 + + 4.6182450652122498e-01 6.6659259796142578e-01 + <_> + + 0 -1 847 1.0439859703183174e-02 + + 5.5056709051132202e-01 3.8836041092872620e-01 + <_> + + 0 -1 848 3.0443191062659025e-03 + + 4.6978530287742615e-01 7.3018449544906616e-01 + <_> + + 0 -1 849 -6.1593751888722181e-04 + + 3.8308390974998474e-01 5.4649841785430908e-01 + <_> + + 0 -1 850 -3.4247159492224455e-03 + + 2.5663000345230103e-01 5.0895309448242188e-01 + <_> + + 0 -1 851 -9.3538565561175346e-03 + + 6.4699661731719971e-01 4.9407958984375000e-01 + <_> + + 0 -1 852 5.2338998764753342e-02 + + 4.7459828853607178e-01 7.8787708282470703e-01 + <_> + + 0 -1 853 3.5765620414167643e-03 + + 5.3066647052764893e-01 2.7484980225563049e-01 + <_> + + 0 -1 854 7.1555317845195532e-04 + + 5.4131257534027100e-01 4.0419089794158936e-01 + <_> + + 0 -1 855 -1.0516679845750332e-02 + + 6.1585122346878052e-01 4.8152831196784973e-01 + <_> + + 0 -1 856 7.7347927726805210e-03 + + 4.6958059072494507e-01 7.0289808511734009e-01 + <_> + + 0 -1 857 -4.3226778507232666e-03 + + 2.8495660424232483e-01 5.3046840429306030e-01 + <_> + + 0 -1 858 -2.5534399319440126e-03 + + 7.0569849014282227e-01 4.6888920664787292e-01 + <_> + + 0 -1 859 1.0268510231981054e-04 + + 3.9029321074485779e-01 5.5734640359878540e-01 + <_> + + 0 -1 860 7.1395188570022583e-06 + + 3.6842319369316101e-01 5.2639877796173096e-01 + <_> + + 0 -1 861 -1.6711989883333445e-03 + + 3.8491758704185486e-01 5.3872710466384888e-01 + <_> + + 0 -1 862 4.9260449595749378e-03 + + 4.7297719120979309e-01 7.4472510814666748e-01 + <_> + + 0 -1 863 4.3908702209591866e-03 + + 4.8091810941696167e-01 5.5919218063354492e-01 + <_> + + 0 -1 864 -1.7793629318475723e-02 + + 6.9036781787872314e-01 4.6769270300865173e-01 + <_> + + 0 -1 865 2.0469669252634048e-03 + + 5.3706902265548706e-01 3.3081620931625366e-01 + <_> + + 0 -1 866 2.9891489073634148e-02 + + 5.1398652791976929e-01 3.3090591430664062e-01 + <_> + + 0 -1 867 1.5494900289922953e-03 + + 4.6602371335029602e-01 6.0783427953720093e-01 + <_> + + 0 -1 868 1.4956969534978271e-03 + + 4.4048359990119934e-01 5.8639198541641235e-01 + <_> + + 0 -1 869 9.5885928021743894e-04 + + 5.4359710216522217e-01 4.2085230350494385e-01 + <_> + + 0 -1 870 4.9643701640889049e-04 + + 5.3705781698226929e-01 4.0006220340728760e-01 + <_> + + 0 -1 871 -2.7280810754746199e-03 + + 5.6594127416610718e-01 4.2596429586410522e-01 + <_> + + 0 -1 872 2.3026480339467525e-03 + + 5.1616579294204712e-01 3.3508691191673279e-01 + <_> + + 0 -1 873 2.5151631236076355e-01 + + 4.8696619272232056e-01 7.1473097801208496e-01 + <_> + + 0 -1 874 -4.6328022144734859e-03 + + 2.7274489402770996e-01 5.0837898254394531e-01 + <_> + + 0 -1 875 -4.0434490889310837e-02 + + 6.8514388799667358e-01 5.0217670202255249e-01 + <_> + + 0 -1 876 1.4972220014897175e-05 + + 4.2844650149345398e-01 5.5225551128387451e-01 + <_> + + 0 -1 877 -2.4050309730228037e-04 + + 4.2261189222335815e-01 5.3900748491287231e-01 + <_> + + 0 -1 878 2.3657839745283127e-02 + + 4.7446319460868835e-01 7.5043660402297974e-01 + <_> + + 0 -1 879 -8.1449104472994804e-03 + + 4.2450588941574097e-01 5.5383628606796265e-01 + <_> + + 0 -1 880 -3.6992130335420370e-03 + + 5.9523570537567139e-01 4.5297130942344666e-01 + <_> + + 0 -1 881 -6.7718601785600185e-03 + + 4.1377940773963928e-01 5.4733997583389282e-01 + <_> + + 0 -1 882 4.2669530957937241e-03 + + 4.4841149449348450e-01 5.7979941368103027e-01 + <_> + + 0 -1 883 1.7791989957913756e-03 + + 5.6248587369918823e-01 4.4324448704719543e-01 + <_> + + 0 -1 884 1.6774770338088274e-03 + + 4.6377518773078918e-01 6.3642418384552002e-01 + <_> + + 0 -1 885 1.1732629500329494e-03 + + 4.5445030927658081e-01 5.9144157171249390e-01 + <_> + + 0 -1 886 8.6998171173036098e-04 + + 5.3347527980804443e-01 3.8859179615974426e-01 + <_> + + 0 -1 887 7.6378340600058436e-04 + + 5.3985852003097534e-01 3.7449419498443604e-01 + <_> + + 0 -1 888 1.5684569370932877e-04 + + 4.3178731203079224e-01 5.6146162748336792e-01 + <_> + + 0 -1 889 -2.1511370316147804e-02 + + 1.7859250307083130e-01 5.1855427026748657e-01 + <_> + + 0 -1 890 1.3081369979772717e-04 + + 4.3424990773200989e-01 5.6828498840332031e-01 + <_> + + 0 -1 891 2.1992040798068047e-02 + + 5.1617169380187988e-01 2.3793940246105194e-01 + <_> + + 0 -1 892 -8.0136500764638186e-04 + + 5.9867632389068604e-01 4.4664269685745239e-01 + <_> + + 0 -1 893 -8.2736099138855934e-03 + + 4.1082179546356201e-01 5.2510571479797363e-01 + <_> + + 0 -1 894 3.6831789184361696e-03 + + 5.1738142967224121e-01 3.3975180983543396e-01 + <_> + + 0 -1 895 -7.9525681212544441e-03 + + 6.8889832496643066e-01 4.8459240794181824e-01 + <_> + + 0 -1 896 1.5382299898192286e-03 + + 5.1785671710968018e-01 3.4541139006614685e-01 + <_> + + 0 -1 897 -1.4043530449271202e-02 + + 1.6784210503101349e-01 5.1886677742004395e-01 + <_> + + 0 -1 898 1.4315890148282051e-03 + + 4.3682569265365601e-01 5.6557738780975342e-01 + <_> + + 0 -1 899 -3.4014228731393814e-02 + + 7.8022962808609009e-01 4.9592170119285583e-01 + <_> + + 0 -1 900 -1.2027299962937832e-02 + + 1.5851010382175446e-01 5.0322318077087402e-01 + <_> + + 0 -1 901 1.3316619396209717e-01 + + 5.1633048057556152e-01 2.7551281452178955e-01 + <_> + + 0 -1 902 -1.5221949433907866e-03 + + 3.7283179163932800e-01 5.2145522832870483e-01 + <_> + + 0 -1 903 -9.3929271679371595e-04 + + 5.8383792638778687e-01 4.5111650228500366e-01 + <_> + + 0 -1 904 2.7719739824533463e-02 + + 4.7282868623733521e-01 7.3315447568893433e-01 + <_> + + 0 -1 905 3.1030150130391121e-03 + + 5.3022021055221558e-01 4.1015630960464478e-01 + <_> + + 0 -1 906 7.7861219644546509e-02 + + 4.9983340501785278e-01 1.2729619443416595e-01 + <_> + + 0 -1 907 -1.5854939818382263e-02 + + 5.0833359360694885e-02 5.1656562089920044e-01 + <_> + + 0 -1 908 -4.9725300632417202e-03 + + 6.7981338500976562e-01 4.6842318773269653e-01 + <_> + + 0 -1 909 -9.7676506265997887e-04 + + 6.0107719898223877e-01 4.7889319062232971e-01 + <_> + + 0 -1 910 -2.4647710379213095e-03 + + 3.3933979272842407e-01 5.2205038070678711e-01 + <_> + + 0 -1 911 -6.7937700077891350e-03 + + 4.3651369214057922e-01 5.2396631240844727e-01 + <_> + + 0 -1 912 3.2608021050691605e-02 + + 5.0527238845825195e-01 2.4252149462699890e-01 + <_> + + 0 -1 913 -5.8514421107247472e-04 + + 5.7339739799499512e-01 4.7585740685462952e-01 + <_> + + 0 -1 914 -2.9632600024342537e-02 + + 3.8922891020774841e-01 5.2635979652404785e-01 + <_> + 137 + 6.7698921203613281e+01 + + <_> + + 0 -1 915 4.6550851315259933e-02 + + 3.2769501209259033e-01 6.2405228614807129e-01 + <_> + + 0 -1 916 7.9537127166986465e-03 + + 4.2564851045608521e-01 6.9429391622543335e-01 + <_> + + 0 -1 917 6.8221561377868056e-04 + + 3.7114870548248291e-01 5.9007328748703003e-01 + <_> + + 0 -1 918 -1.9348249770700932e-04 + + 2.0411339402198792e-01 5.3005450963973999e-01 + <_> + + 0 -1 919 -2.6710508973337710e-04 + + 5.4161262512207031e-01 3.1031790375709534e-01 + <_> + + 0 -1 920 2.7818060480058193e-03 + + 5.2778327465057373e-01 3.4670698642730713e-01 + <_> + + 0 -1 921 -4.6779078547842801e-04 + + 5.3082311153411865e-01 3.2944920659065247e-01 + <_> + + 0 -1 922 -3.0335160772665404e-05 + + 5.7738727331161499e-01 3.8520970940589905e-01 + <_> + + 0 -1 923 7.8038009814918041e-04 + + 4.3174389004707336e-01 6.1500579118728638e-01 + <_> + + 0 -1 924 -4.2553851380944252e-03 + + 2.9339039325714111e-01 5.3242927789688110e-01 + <_> + + 0 -1 925 -2.4735610350035131e-04 + + 5.4688447713851929e-01 3.8430300354957581e-01 + <_> + + 0 -1 926 -1.4724259381182492e-04 + + 4.2815428972244263e-01 5.7555872201919556e-01 + <_> + + 0 -1 927 1.1864770203828812e-03 + + 3.7473011016845703e-01 5.4714661836624146e-01 + <_> + + 0 -1 928 2.3936580400913954e-03 + + 4.5377838611602783e-01 6.1115288734436035e-01 + <_> + + 0 -1 929 -1.5390539774671197e-03 + + 2.9713419079780579e-01 5.1895380020141602e-01 + <_> + + 0 -1 930 -7.1968790143728256e-03 + + 6.6990667581558228e-01 4.7264769673347473e-01 + <_> + + 0 -1 931 -4.1499789222143590e-04 + + 3.3849540352821350e-01 5.2603179216384888e-01 + <_> + + 0 -1 932 4.4359830208122730e-03 + + 5.3991222381591797e-01 3.9201408624649048e-01 + <_> + + 0 -1 933 2.6606200262904167e-03 + + 4.4825780391693115e-01 6.1196178197860718e-01 + <_> + + 0 -1 934 -1.5287200221791863e-03 + + 3.7112379074096680e-01 5.3402662277221680e-01 + <_> + + 0 -1 935 -4.7397250309586525e-03 + + 6.0310882329940796e-01 4.4551450014114380e-01 + <_> + + 0 -1 936 -1.4829129911959171e-02 + + 2.8387540578842163e-01 5.3418618440628052e-01 + <_> + + 0 -1 937 9.2275557108223438e-04 + + 5.2095472812652588e-01 3.3616539835929871e-01 + <_> + + 0 -1 938 8.3529807627201080e-02 + + 5.1199698448181152e-01 8.1164449453353882e-02 + <_> + + 0 -1 939 -7.5633148662745953e-04 + + 3.3171200752258301e-01 5.1898312568664551e-01 + <_> + + 0 -1 940 9.8403859883546829e-03 + + 5.2475982904434204e-01 2.3349590599536896e-01 + <_> + + 0 -1 941 -1.5953830443322659e-03 + + 5.7500940561294556e-01 4.2956221103668213e-01 + <_> + + 0 -1 942 3.4766020689858124e-05 + + 4.3424451351165771e-01 5.5640292167663574e-01 + <_> + + 0 -1 943 2.9862910509109497e-02 + + 4.5791471004486084e-01 6.5791881084442139e-01 + <_> + + 0 -1 944 1.1325590312480927e-02 + + 5.2743119001388550e-01 3.6738881468772888e-01 + <_> + + 0 -1 945 -8.7828645482659340e-03 + + 7.1003687381744385e-01 4.6421670913696289e-01 + <_> + + 0 -1 946 4.3639959767460823e-03 + + 5.2792161703109741e-01 2.7058771252632141e-01 + <_> + + 0 -1 947 4.1804728098213673e-03 + + 5.0725251436233521e-01 2.4490830302238464e-01 + <_> + + 0 -1 948 -4.5668511302210391e-04 + + 4.2831051349639893e-01 5.5486911535263062e-01 + <_> + + 0 -1 949 -3.7140368949621916e-03 + + 5.5193877220153809e-01 4.1036531329154968e-01 + <_> + + 0 -1 950 -2.5304289534687996e-02 + + 6.8670022487640381e-01 4.8698890209197998e-01 + <_> + + 0 -1 951 -3.4454080741852522e-04 + + 3.7288740277290344e-01 5.2876931428909302e-01 + <_> + + 0 -1 952 -8.3935231668874621e-04 + + 6.0601520538330078e-01 4.6160620450973511e-01 + <_> + + 0 -1 953 1.7280049622058868e-02 + + 5.0496357679367065e-01 1.8198239803314209e-01 + <_> + + 0 -1 954 -6.3595077954232693e-03 + + 1.6312399506568909e-01 5.2327787876129150e-01 + <_> + + 0 -1 955 1.0298109846189618e-03 + + 4.4632780551910400e-01 6.1765491962432861e-01 + <_> + + 0 -1 956 1.0117109632119536e-03 + + 5.4733848571777344e-01 4.3006989359855652e-01 + <_> + + 0 -1 957 -1.0308800265192986e-02 + + 1.1669850349426270e-01 5.0008672475814819e-01 + <_> + + 0 -1 958 5.4682018235325813e-03 + + 4.7692871093750000e-01 6.7192137241363525e-01 + <_> + + 0 -1 959 -9.1696460731327534e-04 + + 3.4710898995399475e-01 5.1781648397445679e-01 + <_> + + 0 -1 960 2.3922820109874010e-03 + + 4.7852361202239990e-01 6.2163108587265015e-01 + <_> + + 0 -1 961 -7.5573818758130074e-03 + + 5.8147960901260376e-01 4.4100850820541382e-01 + <_> + + 0 -1 962 -7.7024032361805439e-04 + + 3.8780000805854797e-01 5.4657220840454102e-01 + <_> + + 0 -1 963 -8.7125990539789200e-03 + + 1.6600510478019714e-01 4.9958360195159912e-01 + <_> + + 0 -1 964 -1.0306320153176785e-02 + + 4.0933910012245178e-01 5.2742338180541992e-01 + <_> + + 0 -1 965 -2.0940979011356831e-03 + + 6.2061947584152222e-01 4.5722800493240356e-01 + <_> + + 0 -1 966 6.8099051713943481e-03 + + 5.5677592754364014e-01 4.1556000709533691e-01 + <_> + + 0 -1 967 -1.0746059706434608e-03 + + 5.6389278173446655e-01 4.3530249595642090e-01 + <_> + + 0 -1 968 2.1550289820879698e-03 + + 4.8262658715248108e-01 6.7497581243515015e-01 + <_> + + 0 -1 969 3.1742319464683533e-02 + + 5.0483798980712891e-01 1.8832489848136902e-01 + <_> + + 0 -1 970 -7.8382723033428192e-02 + + 2.3695489764213562e-01 5.2601581811904907e-01 + <_> + + 0 -1 971 5.7415119372308254e-03 + + 5.0488287210464478e-01 2.7764698863029480e-01 + <_> + + 0 -1 972 -2.9014600440859795e-03 + + 6.2386047840118408e-01 4.6933171153068542e-01 + <_> + + 0 -1 973 -2.6427931152284145e-03 + + 3.3141419291496277e-01 5.1697772741317749e-01 + <_> + + 0 -1 974 -1.0949660092592239e-01 + + 2.3800450563430786e-01 5.1834410429000854e-01 + <_> + + 0 -1 975 7.4075913289561868e-05 + + 4.0696358680725098e-01 5.3621500730514526e-01 + <_> + + 0 -1 976 -5.0593802006915212e-04 + + 5.5067062377929688e-01 4.3745940923690796e-01 + <_> + + 0 -1 977 -8.2131777890026569e-04 + + 5.5257099866867065e-01 4.2093759775161743e-01 + <_> + + 0 -1 978 -6.0276539443293586e-05 + + 5.4554748535156250e-01 4.7482660412788391e-01 + <_> + + 0 -1 979 6.8065142259001732e-03 + + 5.1579958200454712e-01 3.4245771169662476e-01 + <_> + + 0 -1 980 1.7202789895236492e-03 + + 5.0132077932357788e-01 6.3312637805938721e-01 + <_> + + 0 -1 981 -1.3016929733566940e-04 + + 5.5397182703018188e-01 4.2268699407577515e-01 + <_> + + 0 -1 982 -4.8016388900578022e-03 + + 4.4250950217247009e-01 5.4307800531387329e-01 + <_> + + 0 -1 983 -2.5399310979992151e-03 + + 7.1457821130752563e-01 4.6976050734519958e-01 + <_> + + 0 -1 984 -1.4278929447755218e-03 + + 4.0704450011253357e-01 5.3996050357818604e-01 + <_> + + 0 -1 985 -2.5142550468444824e-02 + + 7.8846907615661621e-01 4.7473520040512085e-01 + <_> + + 0 -1 986 -3.8899609353393316e-03 + + 4.2961919307708740e-01 5.5771100521087646e-01 + <_> + + 0 -1 987 4.3947459198534489e-03 + + 4.6931621432304382e-01 7.0239442586898804e-01 + <_> + + 0 -1 988 2.4678420275449753e-02 + + 5.2423220872879028e-01 3.8125100731849670e-01 + <_> + + 0 -1 989 3.8047678768634796e-02 + + 5.0117397308349609e-01 1.6878280043601990e-01 + <_> + + 0 -1 990 7.9424865543842316e-03 + + 4.8285821080207825e-01 6.3695681095123291e-01 + <_> + + 0 -1 991 -1.5110049862414598e-03 + + 5.9064859151840210e-01 4.4876679778099060e-01 + <_> + + 0 -1 992 6.4201741479337215e-03 + + 5.2410978078842163e-01 2.9905700683593750e-01 + <_> + + 0 -1 993 -2.9802159406244755e-03 + + 3.0414658784866333e-01 5.0784897804260254e-01 + <_> + + 0 -1 994 -7.4580078944563866e-04 + + 4.1281390190124512e-01 5.2568262815475464e-01 + <_> + + 0 -1 995 -1.0470950044691563e-02 + + 5.8083951473236084e-01 4.4942960143089294e-01 + <_> + + 0 -1 996 9.3369204550981522e-03 + + 5.2465528249740601e-01 2.6589488983154297e-01 + <_> + + 0 -1 997 2.7936900034546852e-02 + + 4.6749550104141235e-01 7.0872569084167480e-01 + <_> + + 0 -1 998 7.4277678504586220e-03 + + 5.4094868898391724e-01 3.7585180997848511e-01 + <_> + + 0 -1 999 -2.3584509268403053e-02 + + 3.7586399912834167e-01 5.2385509014129639e-01 + <_> + + 0 -1 1000 1.1452640173956752e-03 + + 4.3295788764953613e-01 5.8042472600936890e-01 + <_> + + 0 -1 1001 -4.3468660442158580e-04 + + 5.2806180715560913e-01 3.8730698823928833e-01 + <_> + + 0 -1 1002 1.0648540221154690e-02 + + 4.9021130800247192e-01 5.6812518835067749e-01 + <_> + + 0 -1 1003 -3.9418050437234342e-04 + + 5.5708801746368408e-01 4.3182510137557983e-01 + <_> + + 0 -1 1004 -1.3270479394122958e-04 + + 5.6584399938583374e-01 4.3435549736022949e-01 + <_> + + 0 -1 1005 -2.0125510636717081e-03 + + 6.0567390918731689e-01 4.5375239849090576e-01 + <_> + + 0 -1 1006 2.4854319635778666e-03 + + 5.3904771804809570e-01 4.1380101442337036e-01 + <_> + + 0 -1 1007 1.8237880431115627e-03 + + 4.3548288941383362e-01 5.7171887159347534e-01 + <_> + + 0 -1 1008 -1.6656659543514252e-02 + + 3.0109131336212158e-01 5.2161228656768799e-01 + <_> + + 0 -1 1009 8.0349558265879750e-04 + + 5.3001511096954346e-01 3.8183969259262085e-01 + <_> + + 0 -1 1010 3.4170378930866718e-03 + + 5.3280287981033325e-01 4.2414000630378723e-01 + <_> + + 0 -1 1011 -3.6222729249857366e-04 + + 5.4917281866073608e-01 4.1869771480560303e-01 + <_> + + 0 -1 1012 -1.1630020290613174e-01 + + 1.4407220482826233e-01 5.2264511585235596e-01 + <_> + + 0 -1 1013 -1.4695010147988796e-02 + + 7.7477252483367920e-01 4.7157171368598938e-01 + <_> + + 0 -1 1014 2.1972130052745342e-03 + + 5.3554338216781616e-01 3.3156448602676392e-01 + <_> + + 0 -1 1015 -4.6965209185145795e-04 + + 5.7672351598739624e-01 4.4581368565559387e-01 + <_> + + 0 -1 1016 6.5144998952746391e-03 + + 5.2156740427017212e-01 3.6478888988494873e-01 + <_> + + 0 -1 1017 2.1300060674548149e-02 + + 4.9942049384117126e-01 1.5679509937763214e-01 + <_> + + 0 -1 1018 3.1881409231573343e-03 + + 4.7422000765800476e-01 6.2872701883316040e-01 + <_> + + 0 -1 1019 9.0019777417182922e-04 + + 5.3479540348052979e-01 3.9437520503997803e-01 + <_> + + 0 -1 1020 -5.1772277802228928e-03 + + 6.7271918058395386e-01 5.0131380558013916e-01 + <_> + + 0 -1 1021 -4.3764649890363216e-03 + + 3.1066751480102539e-01 5.1287931203842163e-01 + <_> + + 0 -1 1022 2.6299960445612669e-03 + + 4.8863101005554199e-01 5.7552158832550049e-01 + <_> + + 0 -1 1023 -2.0458688959479332e-03 + + 6.0257941484451294e-01 4.5580768585205078e-01 + <_> + + 0 -1 1024 6.9482706487178802e-02 + + 5.2407479286193848e-01 2.1852590143680573e-01 + <_> + + 0 -1 1025 2.4048939347267151e-02 + + 5.0118672847747803e-01 2.0906220376491547e-01 + <_> + + 0 -1 1026 3.1095340382307768e-03 + + 4.8667120933532715e-01 7.1085482835769653e-01 + <_> + + 0 -1 1027 -1.2503260513767600e-03 + + 3.4078910946846008e-01 5.1561951637268066e-01 + <_> + + 0 -1 1028 -1.0281190043315291e-03 + + 5.5755722522735596e-01 4.4394320249557495e-01 + <_> + + 0 -1 1029 -8.8893622159957886e-03 + + 6.4020007848739624e-01 4.6204420924186707e-01 + <_> + + 0 -1 1030 -6.1094801640138030e-04 + + 3.7664419412612915e-01 5.4488998651504517e-01 + <_> + + 0 -1 1031 -5.7686357758939266e-03 + + 3.3186489343643188e-01 5.1336771249771118e-01 + <_> + + 0 -1 1032 1.8506490159779787e-03 + + 4.9035701155662537e-01 6.4069348573684692e-01 + <_> + + 0 -1 1033 -9.9799469113349915e-02 + + 1.5360510349273682e-01 5.0155621767044067e-01 + <_> + + 0 -1 1034 -3.5128349065780640e-01 + + 5.8823131024837494e-02 5.1743787527084351e-01 + <_> + + 0 -1 1035 -4.5244570821523666e-02 + + 6.9614887237548828e-01 4.6778729557991028e-01 + <_> + + 0 -1 1036 7.1481578052043915e-02 + + 5.1679861545562744e-01 1.0380929708480835e-01 + <_> + + 0 -1 1037 2.1895780228078365e-03 + + 4.2730781435966492e-01 5.5320608615875244e-01 + <_> + + 0 -1 1038 -5.9242651332169771e-04 + + 4.6389439702033997e-01 5.2763891220092773e-01 + <_> + + 0 -1 1039 1.6788389766588807e-03 + + 5.3016489744186401e-01 3.9320349693298340e-01 + <_> + + 0 -1 1040 -2.2163488902151585e-03 + + 5.6306940317153931e-01 4.7570338845252991e-01 + <_> + + 0 -1 1041 1.1568699846975505e-04 + + 4.3075358867645264e-01 5.5357027053833008e-01 + <_> + + 0 -1 1042 -7.2017288766801357e-03 + + 1.4448820054531097e-01 5.1930642127990723e-01 + <_> + + 0 -1 1043 8.9081272017210722e-04 + + 4.3844321370124817e-01 5.5936211347579956e-01 + <_> + + 0 -1 1044 1.9605009583756328e-04 + + 5.3404158353805542e-01 4.7059568762779236e-01 + <_> + + 0 -1 1045 5.2022142335772514e-04 + + 5.2138561010360718e-01 3.8100790977478027e-01 + <_> + + 0 -1 1046 9.4588572392240167e-04 + + 4.7694149613380432e-01 6.1307388544082642e-01 + <_> + + 0 -1 1047 9.1698471806012094e-05 + + 4.2450091242790222e-01 5.4293632507324219e-01 + <_> + + 0 -1 1048 2.1833200007677078e-03 + + 5.4577308893203735e-01 4.1910758614540100e-01 + <_> + + 0 -1 1049 -8.6039671441540122e-04 + + 5.7645887136459351e-01 4.4716599583625793e-01 + <_> + + 0 -1 1050 -1.3236239552497864e-02 + + 6.3728231191635132e-01 4.6950098872184753e-01 + <_> + + 0 -1 1051 4.3376701069064438e-04 + + 5.3178739547729492e-01 3.9458298683166504e-01 + <_> + 140 + 6.9229873657226562e+01 + + <_> + + 0 -1 1052 -2.4847149848937988e-02 + + 6.5555167198181152e-01 3.8733118772506714e-01 + <_> + + 0 -1 1053 6.1348611488938332e-03 + + 3.7480720877647400e-01 5.9739977121353149e-01 + <_> + + 0 -1 1054 6.4498498104512691e-03 + + 5.4254919290542603e-01 2.5488111376762390e-01 + <_> + + 0 -1 1055 6.3491211039945483e-04 + + 2.4624420702457428e-01 5.3872537612915039e-01 + <_> + + 0 -1 1056 1.4023890253156424e-03 + + 5.5943220853805542e-01 3.5286578536033630e-01 + <_> + + 0 -1 1057 3.0044000595808029e-04 + + 3.9585039019584656e-01 5.7659381628036499e-01 + <_> + + 0 -1 1058 1.0042409849120304e-04 + + 3.6989969015121460e-01 5.5349981784820557e-01 + <_> + + 0 -1 1059 -5.0841490738093853e-03 + + 3.7110909819602966e-01 5.5478000640869141e-01 + <_> + + 0 -1 1060 -1.9537260755896568e-02 + + 7.4927550554275513e-01 4.5792970061302185e-01 + <_> + + 0 -1 1061 -7.4532740654831287e-06 + + 5.6497871875762939e-01 3.9040699601173401e-01 + <_> + + 0 -1 1062 -3.6079459823668003e-03 + + 3.3810880780220032e-01 5.2678012847900391e-01 + <_> + + 0 -1 1063 2.0697501022368670e-03 + + 5.5192911624908447e-01 3.7143889069557190e-01 + <_> + + 0 -1 1064 -4.6463840408250690e-04 + + 5.6082147359848022e-01 4.1135668754577637e-01 + <_> + + 0 -1 1065 7.5490452582016587e-04 + + 3.5592061281204224e-01 5.3293561935424805e-01 + <_> + + 0 -1 1066 -9.8322238773107529e-04 + + 5.4147958755493164e-01 3.7632051110267639e-01 + <_> + + 0 -1 1067 -1.9940640777349472e-02 + + 6.3479030132293701e-01 4.7052991390228271e-01 + <_> + + 0 -1 1068 3.7680300883948803e-03 + + 3.9134898781776428e-01 5.5637162923812866e-01 + <_> + + 0 -1 1069 -9.4528505578637123e-03 + + 2.5548928976058960e-01 5.2151167392730713e-01 + <_> + + 0 -1 1070 2.9560849070549011e-03 + + 5.1746791601181030e-01 3.0639201402664185e-01 + <_> + + 0 -1 1071 9.1078737750649452e-03 + + 5.3884482383728027e-01 2.8859630227088928e-01 + <_> + + 0 -1 1072 1.8219229532405734e-03 + + 4.3360430002212524e-01 5.8521968126296997e-01 + <_> + + 0 -1 1073 1.4688739553093910e-02 + + 5.2873617410659790e-01 2.8700059652328491e-01 + <_> + + 0 -1 1074 -1.4387990348041058e-02 + + 7.0194488763809204e-01 4.6473708748817444e-01 + <_> + + 0 -1 1075 -1.8986649811267853e-02 + + 2.9865521192550659e-01 5.2470117807388306e-01 + <_> + + 0 -1 1076 1.1527639580890536e-03 + + 4.3234738707542419e-01 5.9316617250442505e-01 + <_> + + 0 -1 1077 1.0933670215308666e-02 + + 5.2868640422821045e-01 3.1303191184997559e-01 + <_> + + 0 -1 1078 -1.4932730235159397e-02 + + 2.6584190130233765e-01 5.0840771198272705e-01 + <_> + + 0 -1 1079 -2.9970539617352188e-04 + + 5.4635268449783325e-01 3.7407240271568298e-01 + <_> + + 0 -1 1080 4.1677621193230152e-03 + + 4.7034969925880432e-01 7.4357217550277710e-01 + <_> + + 0 -1 1081 -6.3905320130288601e-03 + + 2.0692589879035950e-01 5.2805382013320923e-01 + <_> + + 0 -1 1082 4.5029609464108944e-03 + + 5.1826488971710205e-01 3.4835430979728699e-01 + <_> + + 0 -1 1083 -9.2040365561842918e-03 + + 6.8037772178649902e-01 4.9323600530624390e-01 + <_> + + 0 -1 1084 8.1327259540557861e-02 + + 5.0583988428115845e-01 2.2530519962310791e-01 + <_> + + 0 -1 1085 -1.5079280734062195e-01 + + 2.9634249210357666e-01 5.2646797895431519e-01 + <_> + + 0 -1 1086 3.3179009333252907e-03 + + 4.6554958820343018e-01 7.0729321241378784e-01 + <_> + + 0 -1 1087 7.7402801252901554e-04 + + 4.7803479433059692e-01 5.6682378053665161e-01 + <_> + + 0 -1 1088 6.8199541419744492e-04 + + 4.2869961261749268e-01 5.7221567630767822e-01 + <_> + + 0 -1 1089 5.3671570494771004e-03 + + 5.2993071079254150e-01 3.1146219372749329e-01 + <_> + + 0 -1 1090 9.7018666565418243e-05 + + 3.6746388673782349e-01 5.2694618701934814e-01 + <_> + + 0 -1 1091 -1.2534089386463165e-01 + + 2.3514920473098755e-01 5.2457910776138306e-01 + <_> + + 0 -1 1092 -5.2516269497573376e-03 + + 7.1159368753433228e-01 4.6937671303749084e-01 + <_> + + 0 -1 1093 -7.8342109918594360e-03 + + 4.4626510143280029e-01 5.4090857505798340e-01 + <_> + + 0 -1 1094 -1.1310069821774960e-03 + + 5.9456187486648560e-01 4.4176620244979858e-01 + <_> + + 0 -1 1095 1.7601120052859187e-03 + + 5.3532499074935913e-01 3.9734530448913574e-01 + <_> + + 0 -1 1096 -8.1581249833106995e-04 + + 3.7602680921554565e-01 5.2647268772125244e-01 + <_> + + 0 -1 1097 -3.8687589112669230e-03 + + 6.3099128007888794e-01 4.7498199343681335e-01 + <_> + + 0 -1 1098 1.5207129763439298e-03 + + 5.2301818132400513e-01 3.3612239360809326e-01 + <_> + + 0 -1 1099 5.4586738348007202e-01 + + 5.1671397686004639e-01 1.1726350337266922e-01 + <_> + + 0 -1 1100 1.5650190412998199e-02 + + 4.9794390797615051e-01 1.3932949304580688e-01 + <_> + + 0 -1 1101 -1.1731860227882862e-02 + + 7.1296507120132446e-01 4.9211961030960083e-01 + <_> + + 0 -1 1102 -6.1765122227370739e-03 + + 2.2881029546260834e-01 5.0497019290924072e-01 + <_> + + 0 -1 1103 2.2457661107182503e-03 + + 4.6324339509010315e-01 6.0487258434295654e-01 + <_> + + 0 -1 1104 -5.1915869116783142e-03 + + 6.4674210548400879e-01 4.6021929383277893e-01 + <_> + + 0 -1 1105 -2.3827880620956421e-02 + + 1.4820009469985962e-01 5.2260792255401611e-01 + <_> + + 0 -1 1106 1.0284580057486892e-03 + + 5.1354891061782837e-01 3.3759570121765137e-01 + <_> + + 0 -1 1107 -1.0078850202262402e-02 + + 2.7405610680580139e-01 5.3035670518875122e-01 + <_> + + 0 -1 1108 2.6168930344283581e-03 + + 5.3326708078384399e-01 3.9724540710449219e-01 + <_> + + 0 -1 1109 5.4385367548093200e-04 + + 5.3656041622161865e-01 4.0634119510650635e-01 + <_> + + 0 -1 1110 5.3510512225329876e-03 + + 4.6537590026855469e-01 6.8890458345413208e-01 + <_> + + 0 -1 1111 -1.5274790348485112e-03 + + 5.4495012760162354e-01 3.6247238516807556e-01 + <_> + + 0 -1 1112 -8.0624416470527649e-02 + + 1.6560870409011841e-01 5.0002872943878174e-01 + <_> + + 0 -1 1113 2.2192029282450676e-02 + + 5.1327311992645264e-01 2.0028080046176910e-01 + <_> + + 0 -1 1114 7.3100631125271320e-03 + + 4.6179479360580444e-01 6.3665360212326050e-01 + <_> + + 0 -1 1115 -6.4063072204589844e-03 + + 5.9162509441375732e-01 4.8678609728813171e-01 + <_> + + 0 -1 1116 -7.6415040530264378e-04 + + 3.8884091377258301e-01 5.3157979249954224e-01 + <_> + + 0 -1 1117 7.6734489994123578e-04 + + 4.1590648889541626e-01 5.6052798032760620e-01 + <_> + + 0 -1 1118 6.1474501853808761e-04 + + 3.0890220403671265e-01 5.1201480627059937e-01 + <_> + + 0 -1 1119 -5.0105270929634571e-03 + + 3.9721998572349548e-01 5.2073061466217041e-01 + <_> + + 0 -1 1120 -8.6909132078289986e-03 + + 6.2574082612991333e-01 4.6085759997367859e-01 + <_> + + 0 -1 1121 -1.6391459852457047e-02 + + 2.0852099359035492e-01 5.2422660589218140e-01 + <_> + + 0 -1 1122 4.0973909199237823e-04 + + 5.2224272489547729e-01 3.7803208827972412e-01 + <_> + + 0 -1 1123 -2.5242289993911982e-03 + + 5.8039271831512451e-01 4.6118900179862976e-01 + <_> + + 0 -1 1124 5.0945312250405550e-04 + + 4.4012719392776489e-01 5.8460158109664917e-01 + <_> + + 0 -1 1125 1.9656419754028320e-03 + + 5.3223252296447754e-01 4.1845908761024475e-01 + <_> + + 0 -1 1126 5.6298897834494710e-04 + + 3.7418448925018311e-01 5.2345657348632812e-01 + <_> + + 0 -1 1127 -6.7946797935292125e-04 + + 4.6310418844223022e-01 5.3564780950546265e-01 + <_> + + 0 -1 1128 7.2856349870562553e-03 + + 5.0446701049804688e-01 2.3775640130043030e-01 + <_> + + 0 -1 1129 -1.7459489405155182e-02 + + 7.2891211509704590e-01 5.0504350662231445e-01 + <_> + + 0 -1 1130 -2.5421749800443649e-02 + + 6.6671347618103027e-01 4.6781000494956970e-01 + <_> + + 0 -1 1131 -1.5647639520466328e-03 + + 4.3917590379714966e-01 5.3236269950866699e-01 + <_> + + 0 -1 1132 1.1444360017776489e-02 + + 4.3464401364326477e-01 5.6800121068954468e-01 + <_> + + 0 -1 1133 -6.7352550104260445e-04 + + 4.4771409034729004e-01 5.2968120574951172e-01 + <_> + + 0 -1 1134 9.3194209039211273e-03 + + 4.7402000427246094e-01 7.4626070261001587e-01 + <_> + + 0 -1 1135 1.3328490604180843e-04 + + 5.3650617599487305e-01 4.7521349787712097e-01 + <_> + + 0 -1 1136 -7.8815799206495285e-03 + + 1.7522190511226654e-01 5.0152552127838135e-01 + <_> + + 0 -1 1137 -5.7985680177807808e-03 + + 7.2712367773056030e-01 4.8962008953094482e-01 + <_> + + 0 -1 1138 -3.8922499516047537e-04 + + 4.0039089322090149e-01 5.3449410200119019e-01 + <_> + + 0 -1 1139 -1.9288610201328993e-03 + + 5.6056129932403564e-01 4.8039558529853821e-01 + <_> + + 0 -1 1140 8.4214154630899429e-03 + + 4.7532469034194946e-01 7.6236087083816528e-01 + <_> + + 0 -1 1141 8.1655876711010933e-03 + + 5.3932619094848633e-01 4.1916438937187195e-01 + <_> + + 0 -1 1142 4.8280550981871784e-04 + + 4.2408001422882080e-01 5.3998219966888428e-01 + <_> + + 0 -1 1143 -2.7186630759388208e-03 + + 4.2445999383926392e-01 5.4249238967895508e-01 + <_> + + 0 -1 1144 -1.2507230043411255e-02 + + 5.8958417177200317e-01 4.5504111051559448e-01 + <_> + + 0 -1 1145 -2.4286519736051559e-02 + + 2.6471349596977234e-01 5.1891797780990601e-01 + <_> + + 0 -1 1146 -2.9676330741494894e-03 + + 7.3476827144622803e-01 4.7497498989105225e-01 + <_> + + 0 -1 1147 -1.2528999708592892e-02 + + 2.7560499310493469e-01 5.1775997877120972e-01 + <_> + + 0 -1 1148 -1.0104000102728605e-03 + + 3.5105609893798828e-01 5.1447242498397827e-01 + <_> + + 0 -1 1149 -2.1348530426621437e-03 + + 5.6379258632659912e-01 4.6673199534416199e-01 + <_> + + 0 -1 1150 1.9564259797334671e-02 + + 4.6145731210708618e-01 6.1376398801803589e-01 + <_> + + 0 -1 1151 -9.7146347165107727e-02 + + 2.9983788728713989e-01 5.1935559511184692e-01 + <_> + + 0 -1 1152 4.5014568604528904e-03 + + 5.0778847932815552e-01 3.0457559227943420e-01 + <_> + + 0 -1 1153 6.3706971704959869e-03 + + 4.8610189557075500e-01 6.8875008821487427e-01 + <_> + + 0 -1 1154 -9.0721528977155685e-03 + + 1.6733959317207336e-01 5.0175631046295166e-01 + <_> + + 0 -1 1155 -5.3537208586931229e-03 + + 2.6927569508552551e-01 5.2426332235336304e-01 + <_> + + 0 -1 1156 -1.0932840406894684e-02 + + 7.1838641166687012e-01 4.7360289096832275e-01 + <_> + + 0 -1 1157 8.2356072962284088e-03 + + 5.2239668369293213e-01 2.3898629844188690e-01 + <_> + + 0 -1 1158 -1.0038160253316164e-03 + + 5.7193559408187866e-01 4.4339430332183838e-01 + <_> + + 0 -1 1159 4.0859128348529339e-03 + + 5.4728418588638306e-01 4.1488361358642578e-01 + <_> + + 0 -1 1160 1.5485419332981110e-01 + + 4.9738121032714844e-01 6.1061598360538483e-02 + <_> + + 0 -1 1161 2.0897459762636572e-04 + + 4.7091740369796753e-01 5.4238891601562500e-01 + <_> + + 0 -1 1162 3.3316991175524890e-04 + + 4.0896269679069519e-01 5.3009921312332153e-01 + <_> + + 0 -1 1163 -1.0813400149345398e-02 + + 6.1043697595596313e-01 4.9573341012001038e-01 + <_> + + 0 -1 1164 4.5656010508537292e-02 + + 5.0696891546249390e-01 2.8666600584983826e-01 + <_> + + 0 -1 1165 1.2569549726322293e-03 + + 4.8469170928001404e-01 6.3181710243225098e-01 + <_> + + 0 -1 1166 -1.2015070021152496e-01 + + 6.0526140034198761e-02 4.9809598922729492e-01 + <_> + + 0 -1 1167 -1.0533799650147557e-04 + + 5.3631097078323364e-01 4.7080421447753906e-01 + <_> + + 0 -1 1168 -2.0703190565109253e-01 + + 5.9660330414772034e-02 4.9790981411933899e-01 + <_> + + 0 -1 1169 1.2909180077258497e-04 + + 4.7129771113395691e-01 5.3779977560043335e-01 + <_> + + 0 -1 1170 3.8818528992123902e-04 + + 4.3635380268096924e-01 5.5341911315917969e-01 + <_> + + 0 -1 1171 -2.9243610333651304e-03 + + 5.8111858367919922e-01 4.8252159357070923e-01 + <_> + + 0 -1 1172 8.3882332546636462e-04 + + 5.3117001056671143e-01 4.0381389856338501e-01 + <_> + + 0 -1 1173 -1.9061550265178084e-03 + + 3.7707018852233887e-01 5.2600151300430298e-01 + <_> + + 0 -1 1174 8.9514348655939102e-03 + + 4.7661679983139038e-01 7.6821839809417725e-01 + <_> + + 0 -1 1175 1.3083459809422493e-02 + + 5.2644628286361694e-01 3.0622220039367676e-01 + <_> + + 0 -1 1176 -2.1159330010414124e-01 + + 6.7371982336044312e-01 4.6958100795745850e-01 + <_> + + 0 -1 1177 3.1493250280618668e-03 + + 5.6448352336883545e-01 4.3869531154632568e-01 + <_> + + 0 -1 1178 3.9754100725986063e-04 + + 4.5260611176490784e-01 5.8956301212310791e-01 + <_> + + 0 -1 1179 -1.3814480043947697e-03 + + 6.0705822706222534e-01 4.9424138665199280e-01 + <_> + + 0 -1 1180 -5.8122188784182072e-04 + + 5.9982132911682129e-01 4.5082521438598633e-01 + <_> + + 0 -1 1181 -2.3905329871922731e-03 + + 4.2055889964103699e-01 5.2238482236862183e-01 + <_> + + 0 -1 1182 2.7268929407000542e-02 + + 5.2064472436904907e-01 3.5633018612861633e-01 + <_> + + 0 -1 1183 -3.7658358924090862e-03 + + 3.1447041034698486e-01 5.2188140153884888e-01 + <_> + + 0 -1 1184 -1.4903489500284195e-03 + + 3.3801960945129395e-01 5.1244372129440308e-01 + <_> + + 0 -1 1185 -1.7428230494260788e-02 + + 5.8299607038497925e-01 4.9197259545326233e-01 + <_> + + 0 -1 1186 -1.5278030186891556e-02 + + 6.1631447076797485e-01 4.6178871393203735e-01 + <_> + + 0 -1 1187 3.1995609402656555e-02 + + 5.1663571596145630e-01 1.7127640545368195e-01 + <_> + + 0 -1 1188 -3.8256710395216942e-03 + + 3.4080120921134949e-01 5.1313877105712891e-01 + <_> + + 0 -1 1189 -8.5186436772346497e-03 + + 6.1055189371109009e-01 4.9979418516159058e-01 + <_> + + 0 -1 1190 9.0641621500253677e-04 + + 4.3272709846496582e-01 5.5823111534118652e-01 + <_> + + 0 -1 1191 1.0344849899411201e-02 + + 4.8556530475616455e-01 5.4524201154708862e-01 + <_> + 160 + 7.9249076843261719e+01 + + <_> + + 0 -1 1192 7.8981826081871986e-03 + + 3.3325248956680298e-01 5.9464621543884277e-01 + <_> + + 0 -1 1193 1.6170160379260778e-03 + + 3.4906411170959473e-01 5.5778688192367554e-01 + <_> + + 0 -1 1194 -5.5449741194024682e-04 + + 5.5425661802291870e-01 3.2915300130844116e-01 + <_> + + 0 -1 1195 1.5428980113938451e-03 + + 3.6125791072845459e-01 5.5459791421890259e-01 + <_> + + 0 -1 1196 -1.0329450014978647e-03 + + 3.5301390290260315e-01 5.5761402845382690e-01 + <_> + + 0 -1 1197 7.7698158565908670e-04 + + 3.9167788624763489e-01 5.6453210115432739e-01 + <_> + + 0 -1 1198 1.4320300519466400e-01 + + 4.6674820780754089e-01 7.0236331224441528e-01 + <_> + + 0 -1 1199 -7.3866490274667740e-03 + + 3.0736848711967468e-01 5.2892577648162842e-01 + <_> + + 0 -1 1200 -6.2936742324382067e-04 + + 5.6221181154251099e-01 4.0370491147041321e-01 + <_> + + 0 -1 1201 7.8893528552725911e-04 + + 5.2676612138748169e-01 3.5578748583793640e-01 + <_> + + 0 -1 1202 -1.2228050269186497e-02 + + 6.6683208942413330e-01 4.6255499124526978e-01 + <_> + + 0 -1 1203 3.5420239437371492e-03 + + 5.5214381217956543e-01 3.8696730136871338e-01 + <_> + + 0 -1 1204 -1.0585320414975286e-03 + + 3.6286780238151550e-01 5.3209269046783447e-01 + <_> + + 0 -1 1205 1.4935660146875307e-05 + + 4.6324449777603149e-01 5.3633230924606323e-01 + <_> + + 0 -1 1206 5.2537708543241024e-03 + + 5.1322317123413086e-01 3.2657089829444885e-01 + <_> + + 0 -1 1207 -8.2338023930788040e-03 + + 6.6936898231506348e-01 4.7741401195526123e-01 + <_> + + 0 -1 1208 2.1866810129722580e-05 + + 4.0538620948791504e-01 5.4579311609268188e-01 + <_> + + 0 -1 1209 -3.8150229956954718e-03 + + 6.4549958705902100e-01 4.7931781411170959e-01 + <_> + + 0 -1 1210 1.1105879675596952e-03 + + 5.2704071998596191e-01 3.5296788811683655e-01 + <_> + + 0 -1 1211 -5.7707689702510834e-03 + + 3.8035470247268677e-01 5.3529578447341919e-01 + <_> + + 0 -1 1212 -3.0158339068293571e-03 + + 5.3394031524658203e-01 3.8871330022811890e-01 + <_> + + 0 -1 1213 -8.5453689098358154e-04 + + 3.5646161437034607e-01 5.2736037969589233e-01 + <_> + + 0 -1 1214 1.1050510220229626e-02 + + 4.6719071269035339e-01 6.8497377634048462e-01 + <_> + + 0 -1 1215 4.2605839669704437e-02 + + 5.1514732837677002e-01 7.0220090448856354e-02 + <_> + + 0 -1 1216 -3.0781750101596117e-03 + + 3.0416610836982727e-01 5.1526021957397461e-01 + <_> + + 0 -1 1217 -5.4815728217363358e-03 + + 6.4302957057952881e-01 4.8972299695014954e-01 + <_> + + 0 -1 1218 3.1881860923022032e-03 + + 5.3074932098388672e-01 3.8262099027633667e-01 + <_> + + 0 -1 1219 3.5947180003859103e-04 + + 4.6500471234321594e-01 5.4219049215316772e-01 + <_> + + 0 -1 1220 -4.0705031715333462e-03 + + 2.8496798872947693e-01 5.0791162252426147e-01 + <_> + + 0 -1 1221 -1.4594170264899731e-02 + + 2.9716458916664124e-01 5.1284617185592651e-01 + <_> + + 0 -1 1222 -1.1947689927183092e-04 + + 5.6310981512069702e-01 4.3430820107460022e-01 + <_> + + 0 -1 1223 -6.9344649091362953e-04 + + 4.4035780429840088e-01 5.3599590063095093e-01 + <_> + + 0 -1 1224 1.4834799912932795e-05 + + 3.4210088849067688e-01 5.1646977663040161e-01 + <_> + + 0 -1 1225 9.0296985581517220e-03 + + 4.6393430233001709e-01 6.1140751838684082e-01 + <_> + + 0 -1 1226 -8.0640818923711777e-03 + + 2.8201588988304138e-01 5.0754940509796143e-01 + <_> + + 0 -1 1227 2.6062119752168655e-02 + + 5.2089059352874756e-01 2.6887780427932739e-01 + <_> + + 0 -1 1228 1.7314659431576729e-02 + + 4.6637138724327087e-01 6.7385399341583252e-01 + <_> + + 0 -1 1229 2.2666640579700470e-02 + + 5.2093499898910522e-01 2.2127239406108856e-01 + <_> + + 0 -1 1230 -2.1965929772704840e-03 + + 6.0631012916564941e-01 4.5381900668144226e-01 + <_> + + 0 -1 1231 -9.5282476395368576e-03 + + 4.6352049708366394e-01 5.2474308013916016e-01 + <_> + + 0 -1 1232 8.0943619832396507e-03 + + 5.2894401550292969e-01 3.9138820767402649e-01 + <_> + + 0 -1 1233 -7.2877332568168640e-02 + + 7.7520018815994263e-01 4.9902349710464478e-01 + <_> + + 0 -1 1234 -6.9009521976113319e-03 + + 2.4280390143394470e-01 5.0480902194976807e-01 + <_> + + 0 -1 1235 -1.1308239772915840e-02 + + 5.7343649864196777e-01 4.8423761129379272e-01 + <_> + + 0 -1 1236 5.9613201767206192e-02 + + 5.0298362970352173e-01 2.5249770283699036e-01 + <_> + + 0 -1 1237 -2.8624620754271746e-03 + + 6.0730451345443726e-01 4.8984599113464355e-01 + <_> + + 0 -1 1238 4.4781449250876904e-03 + + 5.0152891874313354e-01 2.2203169763088226e-01 + <_> + + 0 -1 1239 -1.7513240454718471e-03 + + 6.6144287586212158e-01 4.9338689446449280e-01 + <_> + + 0 -1 1240 4.0163420140743256e-02 + + 5.1808780431747437e-01 3.7410449981689453e-01 + <_> + + 0 -1 1241 3.4768949262797832e-04 + + 4.7204169631004333e-01 5.8180320262908936e-01 + <_> + + 0 -1 1242 2.6551650371402502e-03 + + 3.8050109148025513e-01 5.2213358879089355e-01 + <_> + + 0 -1 1243 -8.7706279009580612e-03 + + 2.9441660642623901e-01 5.2312952280044556e-01 + <_> + + 0 -1 1244 -5.5122091434895992e-03 + + 7.3461771011352539e-01 4.7228169441223145e-01 + <_> + + 0 -1 1245 6.8672042107209563e-04 + + 5.4528760910034180e-01 4.2424130439758301e-01 + <_> + + 0 -1 1246 5.6019669864326715e-04 + + 4.3988621234893799e-01 5.6012850999832153e-01 + <_> + + 0 -1 1247 2.4143769405782223e-03 + + 4.7416868805885315e-01 6.1366218328475952e-01 + <_> + + 0 -1 1248 -1.5680900542065501e-03 + + 6.0445529222488403e-01 4.5164099335670471e-01 + <_> + + 0 -1 1249 -3.6827491130679846e-03 + + 2.4524590373039246e-01 5.2949821949005127e-01 + <_> + + 0 -1 1250 -2.9409190756268799e-04 + + 3.7328380346298218e-01 5.2514511346817017e-01 + <_> + + 0 -1 1251 4.2847759323194623e-04 + + 5.4988098144531250e-01 4.0655350685119629e-01 + <_> + + 0 -1 1252 -4.8817070201039314e-03 + + 2.1399089694023132e-01 4.9999570846557617e-01 + <_> + + 0 -1 1253 2.7272020815871656e-04 + + 4.6502870321273804e-01 5.8134287595748901e-01 + <_> + + 0 -1 1254 2.0947199664078653e-04 + + 4.3874868750572205e-01 5.5727928876876831e-01 + <_> + + 0 -1 1255 4.8501189798116684e-02 + + 5.2449727058410645e-01 3.2128891348838806e-01 + <_> + + 0 -1 1256 -4.5166411437094212e-03 + + 6.0568130016326904e-01 4.5458820462226868e-01 + <_> + + 0 -1 1257 -1.2291680090129375e-02 + + 2.0409290492534637e-01 5.1522141695022583e-01 + <_> + + 0 -1 1258 4.8549679922871292e-04 + + 5.2376049757003784e-01 3.7395030260086060e-01 + <_> + + 0 -1 1259 3.0556049197912216e-02 + + 4.9605339765548706e-01 5.9382462501525879e-01 + <_> + + 0 -1 1260 -1.5105320198927075e-04 + + 5.3513038158416748e-01 4.1452041268348694e-01 + <_> + + 0 -1 1261 2.4937440175563097e-03 + + 4.6933668851852417e-01 5.5149412155151367e-01 + <_> + + 0 -1 1262 -1.2382130138576031e-02 + + 6.7913967370986938e-01 4.6816679835319519e-01 + <_> + + 0 -1 1263 -5.1333461888134480e-03 + + 3.6087390780448914e-01 5.2291601896286011e-01 + <_> + + 0 -1 1264 5.1919277757406235e-04 + + 5.3000730276107788e-01 3.6336138844490051e-01 + <_> + + 0 -1 1265 1.5060420334339142e-01 + + 5.1573169231414795e-01 2.2117820382118225e-01 + <_> + + 0 -1 1266 7.7144149690866470e-03 + + 4.4104969501495361e-01 5.7766091823577881e-01 + <_> + + 0 -1 1267 9.4443522393703461e-03 + + 5.4018551111221313e-01 3.7566500902175903e-01 + <_> + + 0 -1 1268 2.5006249779835343e-04 + + 4.3682709336280823e-01 5.6073749065399170e-01 + <_> + + 0 -1 1269 -3.3077150583267212e-03 + + 4.2447990179061890e-01 5.5182307958602905e-01 + <_> + + 0 -1 1270 7.4048910755664110e-04 + + 4.4969621300697327e-01 5.9005767107009888e-01 + <_> + + 0 -1 1271 4.4092051684856415e-02 + + 5.2934932708740234e-01 3.1563550233840942e-01 + <_> + + 0 -1 1272 3.3639909233897924e-03 + + 4.4832968711853027e-01 5.8486622571945190e-01 + <_> + + 0 -1 1273 -3.9760079234838486e-03 + + 4.5595070719718933e-01 5.4836392402648926e-01 + <_> + + 0 -1 1274 2.7716930489987135e-03 + + 5.3417861461639404e-01 3.7924841046333313e-01 + <_> + + 0 -1 1275 -2.4123019829858094e-04 + + 5.6671887636184692e-01 4.5769730210304260e-01 + <_> + + 0 -1 1276 4.9425667384639382e-04 + + 4.4212448596954346e-01 5.6287872791290283e-01 + <_> + + 0 -1 1277 -3.8876468897797167e-04 + + 4.2883709073066711e-01 5.3910630941390991e-01 + <_> + + 0 -1 1278 -5.0048898905515671e-02 + + 6.8995130062103271e-01 4.7037428617477417e-01 + <_> + + 0 -1 1279 -3.6635480821132660e-02 + + 2.2177790105342865e-01 5.1918262243270874e-01 + <_> + + 0 -1 1280 2.4273579474538565e-03 + + 5.1362240314483643e-01 3.4973978996276855e-01 + <_> + + 0 -1 1281 1.9558030180633068e-03 + + 4.8261928558349609e-01 6.4083808660507202e-01 + <_> + + 0 -1 1282 -1.7494610510766506e-03 + + 3.9228358864784241e-01 5.2726852893829346e-01 + <_> + + 0 -1 1283 1.3955079950392246e-02 + + 5.0782018899917603e-01 8.4165048599243164e-01 + <_> + + 0 -1 1284 -2.1896739781368524e-04 + + 5.5204898118972778e-01 4.3142348527908325e-01 + <_> + + 0 -1 1285 -1.5131309628486633e-03 + + 3.9346051216125488e-01 5.3825712203979492e-01 + <_> + + 0 -1 1286 -4.3622800149023533e-03 + + 7.3706287145614624e-01 4.7364759445190430e-01 + <_> + + 0 -1 1287 6.5160587430000305e-02 + + 5.1592797040939331e-01 3.2815951108932495e-01 + <_> + + 0 -1 1288 -2.3567399475723505e-03 + + 3.6728268861770630e-01 5.1728862524032593e-01 + <_> + + 0 -1 1289 1.5146659687161446e-02 + + 5.0314939022064209e-01 6.6876041889190674e-01 + <_> + + 0 -1 1290 -2.2850960493087769e-02 + + 6.7675197124481201e-01 4.7095969319343567e-01 + <_> + + 0 -1 1291 4.8867650330066681e-03 + + 5.2579981088638306e-01 4.0598788857460022e-01 + <_> + + 0 -1 1292 1.7619599821045995e-03 + + 4.6962729096412659e-01 6.6882789134979248e-01 + <_> + + 0 -1 1293 -1.2942519970238209e-03 + + 4.3207129836082458e-01 5.3442817926406860e-01 + <_> + + 0 -1 1294 1.0929949581623077e-02 + + 4.9977061152458191e-01 1.6374860703945160e-01 + <_> + + 0 -1 1295 2.9958489903947338e-05 + + 4.2824178934097290e-01 5.6332242488861084e-01 + <_> + + 0 -1 1296 -6.5884361974895000e-03 + + 6.7721211910247803e-01 4.7005268931388855e-01 + <_> + + 0 -1 1297 3.2527779694646597e-03 + + 5.3133970499038696e-01 4.5361489057540894e-01 + <_> + + 0 -1 1298 -4.0435739792883396e-03 + + 5.6600618362426758e-01 4.4133889675140381e-01 + <_> + + 0 -1 1299 -1.2523540062829852e-03 + + 3.7319138646125793e-01 5.3564518690109253e-01 + <_> + + 0 -1 1300 1.9246719602961093e-04 + + 5.1899862289428711e-01 3.7388110160827637e-01 + <_> + + 0 -1 1301 -3.8589671254158020e-02 + + 2.9563739895820618e-01 5.1888108253479004e-01 + <_> + + 0 -1 1302 1.5489870565943420e-04 + + 4.3471351265907288e-01 5.5095332860946655e-01 + <_> + + 0 -1 1303 -3.3763848245143890e-02 + + 3.2303300499916077e-01 5.1954758167266846e-01 + <_> + + 0 -1 1304 -8.2657067105174065e-03 + + 5.9754890203475952e-01 4.5521140098571777e-01 + <_> + + 0 -1 1305 1.4481440302915871e-05 + + 4.7456780076026917e-01 5.4974269866943359e-01 + <_> + + 0 -1 1306 1.4951299817766994e-05 + + 4.3244731426239014e-01 5.4806441068649292e-01 + <_> + + 0 -1 1307 -1.8741799518465996e-02 + + 1.5800529718399048e-01 5.1785331964492798e-01 + <_> + + 0 -1 1308 1.7572239739820361e-03 + + 4.5176368951797485e-01 5.7737642526626587e-01 + <_> + + 0 -1 1309 -3.1391119118779898e-03 + + 4.1496479511260986e-01 5.4608422517776489e-01 + <_> + + 0 -1 1310 6.6656779381446540e-05 + + 4.0390908718109131e-01 5.2930849790573120e-01 + <_> + + 0 -1 1311 6.7743421532213688e-03 + + 4.7676518559455872e-01 6.1219561100006104e-01 + <_> + + 0 -1 1312 -7.3868161998689175e-03 + + 3.5862588882446289e-01 5.1872807741165161e-01 + <_> + + 0 -1 1313 1.4040930196642876e-02 + + 4.7121399641036987e-01 5.5761557817459106e-01 + <_> + + 0 -1 1314 -5.5258329957723618e-03 + + 2.6610270142555237e-01 5.0392812490463257e-01 + <_> + + 0 -1 1315 3.8684239983558655e-01 + + 5.1443397998809814e-01 2.5258991122245789e-01 + <_> + + 0 -1 1316 1.1459240340627730e-04 + + 4.2849949002265930e-01 5.4233711957931519e-01 + <_> + + 0 -1 1317 -1.8467569723725319e-02 + + 3.8858351111412048e-01 5.2130621671676636e-01 + <_> + + 0 -1 1318 -4.5907011372037232e-04 + + 5.4125630855560303e-01 4.2359098792076111e-01 + <_> + + 0 -1 1319 1.2527540093287826e-03 + + 4.8993051052093506e-01 6.6240912675857544e-01 + <_> + + 0 -1 1320 1.4910609461367130e-03 + + 5.2867782115936279e-01 4.0400519967079163e-01 + <_> + + 0 -1 1321 -7.5435562757775187e-04 + + 6.0329902172088623e-01 4.7951200604438782e-01 + <_> + + 0 -1 1322 -6.9478838704526424e-03 + + 4.0844011306762695e-01 5.3735041618347168e-01 + <_> + + 0 -1 1323 2.8092920547351241e-04 + + 4.8460629582405090e-01 5.7593822479248047e-01 + <_> + + 0 -1 1324 9.6073717577382922e-04 + + 5.1647412776947021e-01 3.5549798607826233e-01 + <_> + + 0 -1 1325 -2.6883929967880249e-04 + + 5.6775820255279541e-01 4.7317659854888916e-01 + <_> + + 0 -1 1326 2.1599370520561934e-03 + + 4.7314870357513428e-01 7.0705670118331909e-01 + <_> + + 0 -1 1327 5.6235301308333874e-03 + + 5.2402430772781372e-01 2.7817919850349426e-01 + <_> + + 0 -1 1328 -5.0243991427123547e-03 + + 2.8370139002799988e-01 5.0623041391372681e-01 + <_> + + 0 -1 1329 -9.7611639648675919e-03 + + 7.4007177352905273e-01 4.9345690011978149e-01 + <_> + + 0 -1 1330 4.1515100747346878e-03 + + 5.1191312074661255e-01 3.4070080518722534e-01 + <_> + + 0 -1 1331 6.2465080991387367e-03 + + 4.9237880110740662e-01 6.5790587663650513e-01 + <_> + + 0 -1 1332 -7.0597478188574314e-03 + + 2.4347110092639923e-01 5.0328421592712402e-01 + <_> + + 0 -1 1333 -2.0587709732353687e-03 + + 5.9003108739852905e-01 4.6950870752334595e-01 + <_> + + 0 -1 1334 -2.4146060459315777e-03 + + 3.6473178863525391e-01 5.1892018318176270e-01 + <_> + + 0 -1 1335 -1.4817609917372465e-03 + + 6.0349482297897339e-01 4.9401280283927917e-01 + <_> + + 0 -1 1336 -6.3016400672495365e-03 + + 5.8189898729324341e-01 4.5604279637336731e-01 + <_> + + 0 -1 1337 3.4763428848236799e-03 + + 5.2174758911132812e-01 3.4839931130409241e-01 + <_> + + 0 -1 1338 -2.2250870242714882e-02 + + 2.3607000708580017e-01 5.0320827960968018e-01 + <_> + + 0 -1 1339 -3.0612550675868988e-02 + + 6.4991867542266846e-01 4.9149191379547119e-01 + <_> + + 0 -1 1340 1.3057479634881020e-02 + + 4.4133231043815613e-01 5.6837642192840576e-01 + <_> + + 0 -1 1341 -6.0095742810517550e-04 + + 4.3597310781478882e-01 5.3334832191467285e-01 + <_> + + 0 -1 1342 -4.1514250915497541e-04 + + 5.5040627717971802e-01 4.3260601162910461e-01 + <_> + + 0 -1 1343 -1.3776290230453014e-02 + + 4.0641129016876221e-01 5.2015489339828491e-01 + <_> + + 0 -1 1344 -3.2296508550643921e-02 + + 4.7351971268653870e-02 4.9771949648857117e-01 + <_> + + 0 -1 1345 5.3556978702545166e-02 + + 4.8817330598831177e-01 6.6669392585754395e-01 + <_> + + 0 -1 1346 8.1889545544981956e-03 + + 5.4000371694564819e-01 4.2408201098442078e-01 + <_> + + 0 -1 1347 2.1055320394225419e-04 + + 4.8020479083061218e-01 5.5638527870178223e-01 + <_> + + 0 -1 1348 -2.4382730480283499e-03 + + 7.3877930641174316e-01 4.7736850380897522e-01 + <_> + + 0 -1 1349 3.2835570164024830e-03 + + 5.2885460853576660e-01 3.1712919473648071e-01 + <_> + + 0 -1 1350 2.3729570675641298e-03 + + 4.7508129477500916e-01 7.0601707696914673e-01 + <_> + + 0 -1 1351 -1.4541699783876538e-03 + + 3.8117301464080811e-01 5.3307390213012695e-01 + <_> + 177 + 8.7696029663085938e+01 + + <_> + + 0 -1 1352 5.5755238980054855e-02 + + 4.0191569924354553e-01 6.8060368299484253e-01 + <_> + + 0 -1 1353 2.4730248842388391e-03 + + 3.3511489629745483e-01 5.9657198190689087e-01 + <_> + + 0 -1 1354 -3.5031698644161224e-04 + + 5.5577081441879272e-01 3.4822869300842285e-01 + <_> + + 0 -1 1355 5.4167630150914192e-04 + + 4.2608588933944702e-01 5.6933808326721191e-01 + <_> + + 0 -1 1356 7.7193678589537740e-04 + + 3.4942400455474854e-01 5.4336887598037720e-01 + <_> + + 0 -1 1357 -1.5999219613149762e-03 + + 4.0284991264343262e-01 5.4843592643737793e-01 + <_> + + 0 -1 1358 -1.1832080053864047e-04 + + 3.8069018721580505e-01 5.4254651069641113e-01 + <_> + + 0 -1 1359 3.2909031142480671e-04 + + 2.6201000809669495e-01 5.4295217990875244e-01 + <_> + + 0 -1 1360 2.9518108931370080e-04 + + 3.7997689843177795e-01 5.3992640972137451e-01 + <_> + + 0 -1 1361 9.0466710389591753e-05 + + 4.4336450099945068e-01 5.4402261972427368e-01 + <_> + + 0 -1 1362 1.5007190086180344e-05 + + 3.7196549773216248e-01 5.4091197252273560e-01 + <_> + + 0 -1 1363 1.3935610651969910e-01 + + 5.5253958702087402e-01 4.4790428876876831e-01 + <_> + + 0 -1 1364 1.6461990308016539e-03 + + 4.2645010352134705e-01 5.7721698284149170e-01 + <_> + + 0 -1 1365 4.9984431825578213e-04 + + 4.3595260381698608e-01 5.6858712434768677e-01 + <_> + + 0 -1 1366 -1.0971280280500650e-03 + + 3.3901369571685791e-01 5.2054089307785034e-01 + <_> + + 0 -1 1367 6.6919892560690641e-04 + + 4.5574560761451721e-01 5.9806597232818604e-01 + <_> + + 0 -1 1368 8.6471042595803738e-04 + + 5.1348412036895752e-01 2.9440331459045410e-01 + <_> + + 0 -1 1369 -2.7182599296793342e-04 + + 3.9065781235694885e-01 5.3771811723709106e-01 + <_> + + 0 -1 1370 3.0249499104684219e-05 + + 3.6796098947525024e-01 5.2256888151168823e-01 + <_> + + 0 -1 1371 -8.5225896909832954e-03 + + 7.2931021451950073e-01 4.8923650383949280e-01 + <_> + + 0 -1 1372 1.6705560265108943e-03 + + 4.3453249335289001e-01 5.6961381435394287e-01 + <_> + + 0 -1 1373 -7.1433838456869125e-03 + + 2.5912800431251526e-01 5.2256238460540771e-01 + <_> + + 0 -1 1374 -1.6319369897246361e-02 + + 6.9222790002822876e-01 4.6515759825706482e-01 + <_> + + 0 -1 1375 4.8034260980784893e-03 + + 5.3522628545761108e-01 3.2863029837608337e-01 + <_> + + 0 -1 1376 -7.5421929359436035e-03 + + 2.0405440032482147e-01 5.0345462560653687e-01 + <_> + + 0 -1 1377 -1.4363110065460205e-02 + + 6.8048888444900513e-01 4.8890590667724609e-01 + <_> + + 0 -1 1378 8.9063588529825211e-04 + + 5.3106957674026489e-01 3.8954809308052063e-01 + <_> + + 0 -1 1379 -4.4060191139578819e-03 + + 5.7415628433227539e-01 4.3724268674850464e-01 + <_> + + 0 -1 1380 -1.8862540309783071e-04 + + 2.8317859768867493e-01 5.0982052087783813e-01 + <_> + + 0 -1 1381 -3.7979281041771173e-03 + + 3.3725079894065857e-01 5.2465802431106567e-01 + <_> + + 0 -1 1382 1.4627049677073956e-04 + + 5.3066742420196533e-01 3.9117100834846497e-01 + <_> + + 0 -1 1383 -4.9164638767251745e-05 + + 5.4624962806701660e-01 3.9427208900451660e-01 + <_> + + 0 -1 1384 -3.3582501113414764e-02 + + 2.1578240394592285e-01 5.0482118129730225e-01 + <_> + + 0 -1 1385 -3.5339309833943844e-03 + + 6.4653122425079346e-01 4.8726969957351685e-01 + <_> + + 0 -1 1386 5.0144111737608910e-03 + + 4.6176680922508240e-01 6.2480747699737549e-01 + <_> + + 0 -1 1387 1.8817370757460594e-02 + + 5.2206891775131226e-01 2.0000520348548889e-01 + <_> + + 0 -1 1388 -1.3434339780360460e-03 + + 4.0145379304885864e-01 5.3016197681427002e-01 + <_> + + 0 -1 1389 1.7557960236445069e-03 + + 4.7940391302108765e-01 5.6531697511672974e-01 + <_> + + 0 -1 1390 -9.5637463033199310e-02 + + 2.0341950654983521e-01 5.0067067146301270e-01 + <_> + + 0 -1 1391 -2.2241229191422462e-02 + + 7.6724731922149658e-01 5.0463402271270752e-01 + <_> + + 0 -1 1392 -1.5575819648802280e-02 + + 7.4903422594070435e-01 4.7558510303497314e-01 + <_> + + 0 -1 1393 5.3599118255078793e-03 + + 5.3653037548065186e-01 4.0046709775924683e-01 + <_> + + 0 -1 1394 -2.1763499826192856e-02 + + 7.4015498161315918e-02 4.9641749262809753e-01 + <_> + + 0 -1 1395 -1.6561590135097504e-01 + + 2.8591030836105347e-01 5.2180862426757812e-01 + <_> + + 0 -1 1396 1.6461320046801120e-04 + + 4.1916158795356750e-01 5.3807932138442993e-01 + <_> + + 0 -1 1397 -8.9077502489089966e-03 + + 6.2731927633285522e-01 4.8774048686027527e-01 + <_> + + 0 -1 1398 8.6346449097618461e-04 + + 5.1599407196044922e-01 3.6710259318351746e-01 + <_> + + 0 -1 1399 -1.3751760125160217e-03 + + 5.8843767642974854e-01 4.5790839195251465e-01 + <_> + + 0 -1 1400 -1.4081239933148026e-03 + + 3.5605099797248840e-01 5.1399451494216919e-01 + <_> + + 0 -1 1401 -3.9342888630926609e-03 + + 5.9942889213562012e-01 4.6642720699310303e-01 + <_> + + 0 -1 1402 -3.1966928392648697e-02 + + 3.3454620838165283e-01 5.1441830396652222e-01 + <_> + + 0 -1 1403 -1.5089280168467667e-05 + + 5.5826562643051147e-01 4.4140571355819702e-01 + <_> + + 0 -1 1404 5.1994470413774252e-04 + + 4.6236801147460938e-01 6.1689937114715576e-01 + <_> + + 0 -1 1405 -3.4220460802316666e-03 + + 6.5570747852325439e-01 4.9748051166534424e-01 + <_> + + 0 -1 1406 1.7723299970384687e-04 + + 5.2695018053054810e-01 3.9019080996513367e-01 + <_> + + 0 -1 1407 1.5716759953647852e-03 + + 4.6333730220794678e-01 5.7904577255249023e-01 + <_> + + 0 -1 1408 -8.9041329920291901e-03 + + 2.6896080374717712e-01 5.0535911321640015e-01 + <_> + + 0 -1 1409 4.0677518700249493e-04 + + 5.4566031694412231e-01 4.3298989534378052e-01 + <_> + + 0 -1 1410 6.7604780197143555e-03 + + 4.6489939093589783e-01 6.6897618770599365e-01 + <_> + + 0 -1 1411 2.9100088868290186e-03 + + 5.3097039461135864e-01 3.3778399229049683e-01 + <_> + + 0 -1 1412 1.3885459629818797e-03 + + 4.0747389197349548e-01 5.3491330146789551e-01 + <_> + + 0 -1 1413 -7.6764263212680817e-02 + + 1.9921760261058807e-01 5.2282422780990601e-01 + <_> + + 0 -1 1414 -2.2688310127705336e-04 + + 5.4385018348693848e-01 4.2530721426010132e-01 + <_> + + 0 -1 1415 -6.3094152137637138e-03 + + 4.2591789364814758e-01 5.3789097070693970e-01 + <_> + + 0 -1 1416 -1.1007279902696609e-01 + + 6.9041568040847778e-01 4.7217491269111633e-01 + <_> + + 0 -1 1417 2.8619659133255482e-04 + + 4.5249149203300476e-01 5.5483061075210571e-01 + <_> + + 0 -1 1418 2.9425329557852820e-05 + + 5.3703737258911133e-01 4.2364639043807983e-01 + <_> + + 0 -1 1419 -2.4886570870876312e-02 + + 6.4235579967498779e-01 4.9693039059638977e-01 + <_> + + 0 -1 1420 3.3148851245641708e-02 + + 4.9884751439094543e-01 1.6138119995594025e-01 + <_> + + 0 -1 1421 7.8491691965609789e-04 + + 5.4160261154174805e-01 4.2230090498924255e-01 + <_> + + 0 -1 1422 4.7087189741432667e-03 + + 4.5763289928436279e-01 6.0275578498840332e-01 + <_> + + 0 -1 1423 2.4144479539245367e-03 + + 5.3089731931686401e-01 4.4224989414215088e-01 + <_> + + 0 -1 1424 1.9523180089890957e-03 + + 4.7056341171264648e-01 6.6633248329162598e-01 + <_> + + 0 -1 1425 1.3031980488449335e-03 + + 4.4061261415481567e-01 5.5269622802734375e-01 + <_> + + 0 -1 1426 4.4735497795045376e-03 + + 5.1290237903594971e-01 3.3014988899230957e-01 + <_> + + 0 -1 1427 -2.6652868837118149e-03 + + 3.1354710459709167e-01 5.1750361919403076e-01 + <_> + + 0 -1 1428 1.3666770246345550e-04 + + 4.1193708777427673e-01 5.3068768978118896e-01 + <_> + + 0 -1 1429 -1.7126450315117836e-02 + + 6.1778062582015991e-01 4.8365789651870728e-01 + <_> + + 0 -1 1430 -2.6601430727168918e-04 + + 3.6543309688568115e-01 5.1697367429733276e-01 + <_> + + 0 -1 1431 -2.2932380437850952e-02 + + 3.4909150004386902e-01 5.1639920473098755e-01 + <_> + + 0 -1 1432 2.3316550068557262e-03 + + 5.1662999391555786e-01 3.7093898653984070e-01 + <_> + + 0 -1 1433 1.6925660893321037e-02 + + 5.0147360563278198e-01 8.0539882183074951e-01 + <_> + + 0 -1 1434 -8.9858826249837875e-03 + + 6.4707887172698975e-01 4.6570208668708801e-01 + <_> + + 0 -1 1435 -1.1874699965119362e-02 + + 3.2463788986206055e-01 5.2587550878524780e-01 + <_> + + 0 -1 1436 1.9350569345988333e-04 + + 5.1919418573379517e-01 3.8396438956260681e-01 + <_> + + 0 -1 1437 5.8713490143418312e-03 + + 4.9181339144706726e-01 6.1870431900024414e-01 + <_> + + 0 -1 1438 -2.4838790297508240e-01 + + 1.8368029594421387e-01 4.9881500005722046e-01 + <_> + + 0 -1 1439 1.2256000190973282e-02 + + 5.2270537614822388e-01 3.6320298910140991e-01 + <_> + + 0 -1 1440 8.3990179700776935e-04 + + 4.4902500510215759e-01 5.7741481065750122e-01 + <_> + + 0 -1 1441 2.5407369248569012e-03 + + 4.8047870397567749e-01 5.8582991361618042e-01 + <_> + + 0 -1 1442 -1.4822429977357388e-02 + + 2.5210499763488770e-01 5.0235372781753540e-01 + <_> + + 0 -1 1443 -5.7973959483206272e-03 + + 5.9966957569122314e-01 4.8537150025367737e-01 + <_> + + 0 -1 1444 7.2662148158997297e-04 + + 5.1537168025970459e-01 3.6717799305915833e-01 + <_> + + 0 -1 1445 -1.7232580110430717e-02 + + 6.6217190027236938e-01 4.9946561455726624e-01 + <_> + + 0 -1 1446 7.8624086454510689e-03 + + 4.6333950757980347e-01 6.2561017274856567e-01 + <_> + + 0 -1 1447 -4.7343620099127293e-03 + + 3.6155730485916138e-01 5.2818852663040161e-01 + <_> + + 0 -1 1448 8.3048478700220585e-04 + + 4.4428890943527222e-01 5.5509579181671143e-01 + <_> + + 0 -1 1449 7.6602199114859104e-03 + + 5.1629352569580078e-01 2.6133549213409424e-01 + <_> + + 0 -1 1450 -4.1048377752304077e-03 + + 2.7896320819854736e-01 5.0190317630767822e-01 + <_> + + 0 -1 1451 4.8512578941881657e-03 + + 4.9689841270446777e-01 5.6616681814193726e-01 + <_> + + 0 -1 1452 9.9896453320980072e-04 + + 4.4456079602241516e-01 5.5518132448196411e-01 + <_> + + 0 -1 1453 -2.7023631334304810e-01 + + 2.9388209804892540e-02 5.1513141393661499e-01 + <_> + + 0 -1 1454 -1.3090680353343487e-02 + + 5.6993997097015381e-01 4.4474598765373230e-01 + <_> + + 0 -1 1455 -9.4342790544033051e-03 + + 4.3054661154747009e-01 5.4878950119018555e-01 + <_> + + 0 -1 1456 -1.5482039889320731e-03 + + 3.6803171038627625e-01 5.1280808448791504e-01 + <_> + + 0 -1 1457 5.3746132180094719e-03 + + 4.8389169573783875e-01 6.1015558242797852e-01 + <_> + + 0 -1 1458 1.5786769799888134e-03 + + 5.3252232074737549e-01 4.1185480356216431e-01 + <_> + + 0 -1 1459 3.6856050137430429e-03 + + 4.8109480738639832e-01 6.2523031234741211e-01 + <_> + + 0 -1 1460 9.3887019902467728e-03 + + 5.2002298831939697e-01 3.6294108629226685e-01 + <_> + + 0 -1 1461 1.2792630121111870e-02 + + 4.9617099761962891e-01 6.7380160093307495e-01 + <_> + + 0 -1 1462 -3.3661040943115950e-03 + + 4.0602791309356689e-01 5.2835988998413086e-01 + <_> + + 0 -1 1463 3.9771420415490866e-04 + + 4.6741139888763428e-01 5.9007751941680908e-01 + <_> + + 0 -1 1464 1.4868030557408929e-03 + + 4.5191168785095215e-01 6.0820537805557251e-01 + <_> + + 0 -1 1465 -8.8686749339103699e-02 + + 2.8078991174697876e-01 5.1809918880462646e-01 + <_> + + 0 -1 1466 -7.4296112870797515e-05 + + 5.2955842018127441e-01 4.0876251459121704e-01 + <_> + + 0 -1 1467 -1.4932939848222304e-05 + + 5.4614001512527466e-01 4.5385429263114929e-01 + <_> + + 0 -1 1468 5.9162238612771034e-03 + + 5.3291612863540649e-01 4.1921341419219971e-01 + <_> + + 0 -1 1469 1.1141640134155750e-03 + + 4.5120179653167725e-01 5.7062172889709473e-01 + <_> + + 0 -1 1470 8.9249362645205110e-05 + + 4.5778059959411621e-01 5.8976382017135620e-01 + <_> + + 0 -1 1471 2.5319510605186224e-03 + + 5.2996039390563965e-01 3.3576390147209167e-01 + <_> + + 0 -1 1472 1.2426200322806835e-02 + + 4.9590590596199036e-01 1.3466019928455353e-01 + <_> + + 0 -1 1473 2.8335750102996826e-02 + + 5.1170790195465088e-01 6.1043637106195092e-04 + <_> + + 0 -1 1474 6.6165882162749767e-03 + + 4.7363498806953430e-01 7.0116281509399414e-01 + <_> + + 0 -1 1475 8.0468766391277313e-03 + + 5.2164179086685181e-01 3.2828199863433838e-01 + <_> + + 0 -1 1476 -1.1193980462849140e-03 + + 5.8098608255386353e-01 4.5637390017509460e-01 + <_> + + 0 -1 1477 1.3277590274810791e-02 + + 5.3983622789382935e-01 4.1039010882377625e-01 + <_> + + 0 -1 1478 4.8794739996083081e-04 + + 4.2492860555648804e-01 5.4105907678604126e-01 + <_> + + 0 -1 1479 1.1243170127272606e-02 + + 5.2699637413024902e-01 3.4382158517837524e-01 + <_> + + 0 -1 1480 -8.9896668214350939e-04 + + 5.6330758333206177e-01 4.4566130638122559e-01 + <_> + + 0 -1 1481 6.6677159629762173e-03 + + 5.3128892183303833e-01 4.3626791238784790e-01 + <_> + + 0 -1 1482 2.8947299346327782e-02 + + 4.7017949819564819e-01 6.5757977962493896e-01 + <_> + + 0 -1 1483 -2.3400049656629562e-02 + + 0. 5.1373988389968872e-01 + <_> + + 0 -1 1484 -8.9117050170898438e-02 + + 2.3745279759168625e-02 4.9424308538436890e-01 + <_> + + 0 -1 1485 -1.4054600149393082e-02 + + 3.1273230910301208e-01 5.1175111532211304e-01 + <_> + + 0 -1 1486 8.1239398568868637e-03 + + 5.0090491771697998e-01 2.5200259685516357e-01 + <_> + + 0 -1 1487 -4.9964650534093380e-03 + + 6.3871437311172485e-01 4.9278119206428528e-01 + <_> + + 0 -1 1488 3.1253970228135586e-03 + + 5.1368498802185059e-01 3.6804521083831787e-01 + <_> + + 0 -1 1489 6.7669642157852650e-03 + + 5.5098438262939453e-01 4.3636319041252136e-01 + <_> + + 0 -1 1490 -2.3711440153419971e-03 + + 6.1623352766036987e-01 4.5869469642639160e-01 + <_> + + 0 -1 1491 -5.3522791713476181e-03 + + 6.1854577064514160e-01 4.9204909801483154e-01 + <_> + + 0 -1 1492 -1.5968859195709229e-02 + + 1.3826179504394531e-01 4.9832528829574585e-01 + <_> + + 0 -1 1493 4.7676060348749161e-03 + + 4.6880578994750977e-01 5.4900461435317993e-01 + <_> + + 0 -1 1494 -2.4714691098779440e-03 + + 2.3685149848461151e-01 5.0039529800415039e-01 + <_> + + 0 -1 1495 -7.1033788844943047e-04 + + 5.8563941717147827e-01 4.7215330600738525e-01 + <_> + + 0 -1 1496 -1.4117559790611267e-01 + + 8.6900062859058380e-02 4.9615910649299622e-01 + <_> + + 0 -1 1497 1.0651809722185135e-01 + + 5.1388370990753174e-01 1.7410050332546234e-01 + <_> + + 0 -1 1498 -5.2744749933481216e-02 + + 7.3536360263824463e-01 4.7728818655014038e-01 + <_> + + 0 -1 1499 -4.7431760467588902e-03 + + 3.8844060897827148e-01 5.2927017211914062e-01 + <_> + + 0 -1 1500 9.9676765967160463e-04 + + 5.2234929800033569e-01 4.0034240484237671e-01 + <_> + + 0 -1 1501 8.0284131690859795e-03 + + 4.9591061472892761e-01 7.2129642963409424e-01 + <_> + + 0 -1 1502 8.6025858763605356e-04 + + 4.4448840618133545e-01 5.5384761095046997e-01 + <_> + + 0 -1 1503 9.3191501218825579e-04 + + 5.3983712196350098e-01 4.1632440686225891e-01 + <_> + + 0 -1 1504 -2.5082060601562262e-03 + + 5.8542650938034058e-01 4.5625001192092896e-01 + <_> + + 0 -1 1505 -2.1378761157393456e-03 + + 4.6080690622329712e-01 5.2802592515945435e-01 + <_> + + 0 -1 1506 -2.1546049974858761e-03 + + 3.7911269068717957e-01 5.2559971809387207e-01 + <_> + + 0 -1 1507 -7.6214009895920753e-03 + + 5.9986090660095215e-01 4.9520739912986755e-01 + <_> + + 0 -1 1508 2.2055360022932291e-03 + + 4.4842061400413513e-01 5.5885308980941772e-01 + <_> + + 0 -1 1509 1.2586950324475765e-03 + + 5.4507470130920410e-01 4.4238409399986267e-01 + <_> + + 0 -1 1510 -5.0926720723509789e-03 + + 4.1182750463485718e-01 5.2630358934402466e-01 + <_> + + 0 -1 1511 -2.5095739401876926e-03 + + 5.7879078388214111e-01 4.9984949827194214e-01 + <_> + + 0 -1 1512 -7.7327556908130646e-02 + + 8.3978658914566040e-01 4.8111200332641602e-01 + <_> + + 0 -1 1513 -4.1485819965600967e-02 + + 2.4086110293865204e-01 5.1769930124282837e-01 + <_> + + 0 -1 1514 1.0355669655837119e-04 + + 4.3553608655929565e-01 5.4170542955398560e-01 + <_> + + 0 -1 1515 1.3255809899419546e-03 + + 5.4539710283279419e-01 4.8940950632095337e-01 + <_> + + 0 -1 1516 -8.0598732456564903e-03 + + 5.7710242271423340e-01 4.5779189467430115e-01 + <_> + + 0 -1 1517 1.9058620557188988e-02 + + 5.1698678731918335e-01 3.4004750847816467e-01 + <_> + + 0 -1 1518 -3.5057891160249710e-02 + + 2.2032439708709717e-01 5.0005030632019043e-01 + <_> + + 0 -1 1519 5.7296059094369411e-03 + + 5.0434082746505737e-01 6.5975707769393921e-01 + <_> + + 0 -1 1520 -1.1648329906165600e-02 + + 2.1862849593162537e-01 4.9966529011726379e-01 + <_> + + 0 -1 1521 1.4544479781761765e-03 + + 5.0076818466186523e-01 5.5037277936935425e-01 + <_> + + 0 -1 1522 -2.5030909455381334e-04 + + 4.1298410296440125e-01 5.2416700124740601e-01 + <_> + + 0 -1 1523 -8.2907272735610604e-04 + + 5.4128682613372803e-01 4.9744960665702820e-01 + <_> + + 0 -1 1524 1.0862209601327777e-03 + + 4.6055299043655396e-01 5.8792287111282349e-01 + <_> + + 0 -1 1525 2.0000500080641359e-04 + + 5.2788549661636353e-01 4.7052091360092163e-01 + <_> + + 0 -1 1526 2.9212920926511288e-03 + + 5.1296097040176392e-01 3.7555369734764099e-01 + <_> + + 0 -1 1527 2.5387400761246681e-02 + + 4.8226919770240784e-01 5.7907682657241821e-01 + <_> + + 0 -1 1528 -3.1968469265848398e-03 + + 5.2483952045440674e-01 3.9628401398658752e-01 + <_> + 182 + 9.0253349304199219e+01 + + <_> + + 0 -1 1529 5.8031738735735416e-03 + + 3.4989839792251587e-01 5.9619832038879395e-01 + <_> + + 0 -1 1530 -9.0003069490194321e-03 + + 6.8166369199752808e-01 4.4785520434379578e-01 + <_> + + 0 -1 1531 -1.1549659539014101e-03 + + 5.5857062339782715e-01 3.5782510042190552e-01 + <_> + + 0 -1 1532 -1.1069850297644734e-03 + + 5.3650361299514771e-01 3.0504280328750610e-01 + <_> + + 0 -1 1533 1.0308309720130637e-04 + + 3.6390951275825500e-01 5.3446358442306519e-01 + <_> + + 0 -1 1534 -5.0984839908778667e-03 + + 2.8591570258140564e-01 5.5042648315429688e-01 + <_> + + 0 -1 1535 8.2572200335562229e-04 + + 5.2365237474441528e-01 3.4760418534278870e-01 + <_> + + 0 -1 1536 9.9783325567841530e-03 + + 4.7503221035003662e-01 6.2196469306945801e-01 + <_> + + 0 -1 1537 -3.7402529269456863e-02 + + 3.3433759212493896e-01 5.2780628204345703e-01 + <_> + + 0 -1 1538 4.8548257909715176e-03 + + 5.1921808719635010e-01 3.7004441022872925e-01 + <_> + + 0 -1 1539 -1.8664470408111811e-03 + + 2.9298439621925354e-01 5.0919449329376221e-01 + <_> + + 0 -1 1540 1.6888890415430069e-02 + + 3.6868458986282349e-01 5.4312258958816528e-01 + <_> + + 0 -1 1541 -5.8372621424496174e-03 + + 3.6321839690208435e-01 5.2213358879089355e-01 + <_> + + 0 -1 1542 -1.4713739510625601e-03 + + 5.8706837892532349e-01 4.7006508708000183e-01 + <_> + + 0 -1 1543 -1.1522950371727347e-03 + + 3.1958949565887451e-01 5.1409542560577393e-01 + <_> + + 0 -1 1544 -4.2560300789773464e-03 + + 6.3018590211868286e-01 4.8149210214614868e-01 + <_> + + 0 -1 1545 -6.7378291860222816e-03 + + 1.9770480692386627e-01 5.0258082151412964e-01 + <_> + + 0 -1 1546 1.1382670141756535e-02 + + 4.9541321396827698e-01 6.8670457601547241e-01 + <_> + + 0 -1 1547 5.1794708706438541e-03 + + 5.1644277572631836e-01 3.3506479859352112e-01 + <_> + + 0 -1 1548 -1.1743789911270142e-01 + + 2.3152460157871246e-01 5.2344137430191040e-01 + <_> + + 0 -1 1549 2.8703449293971062e-02 + + 4.6642971038818359e-01 6.7225211858749390e-01 + <_> + + 0 -1 1550 4.8231030814349651e-03 + + 5.2208751440048218e-01 2.7235329151153564e-01 + <_> + + 0 -1 1551 2.6798530016094446e-03 + + 5.0792771577835083e-01 2.9069489240646362e-01 + <_> + + 0 -1 1552 8.0504082143306732e-03 + + 4.8859509825706482e-01 6.3950210809707642e-01 + <_> + + 0 -1 1553 4.8054959625005722e-03 + + 5.1972568035125732e-01 3.6566638946533203e-01 + <_> + + 0 -1 1554 -2.2420159075409174e-03 + + 6.1534678936004639e-01 4.7637018561363220e-01 + <_> + + 0 -1 1555 -1.3757710345089436e-02 + + 2.6373448967933655e-01 5.0309032201766968e-01 + <_> + + 0 -1 1556 -1.0338299721479416e-01 + + 2.2875219583511353e-01 5.1824611425399780e-01 + <_> + + 0 -1 1557 -9.4432085752487183e-03 + + 6.9533038139343262e-01 4.6949490904808044e-01 + <_> + + 0 -1 1558 8.0271181650459766e-04 + + 5.4506552219390869e-01 4.2687839269638062e-01 + <_> + + 0 -1 1559 -4.1945669800043106e-03 + + 6.0913878679275513e-01 4.5716428756713867e-01 + <_> + + 0 -1 1560 1.0942210443317890e-02 + + 5.2410632371902466e-01 3.2845470309257507e-01 + <_> + + 0 -1 1561 -5.7841069065034389e-04 + + 5.3879290819168091e-01 4.1793689131736755e-01 + <_> + + 0 -1 1562 -2.0888620056211948e-03 + + 4.2926910519599915e-01 5.3017157316207886e-01 + <_> + + 0 -1 1563 3.2383969519287348e-03 + + 3.7923479080200195e-01 5.2207440137863159e-01 + <_> + + 0 -1 1564 4.9075027927756310e-03 + + 5.2372831106185913e-01 4.1267579793930054e-01 + <_> + + 0 -1 1565 -3.2277941703796387e-02 + + 1.9476559758186340e-01 4.9945020675659180e-01 + <_> + + 0 -1 1566 -8.9711230248212814e-03 + + 6.0112851858139038e-01 4.9290320277214050e-01 + <_> + + 0 -1 1567 1.5321089886128902e-02 + + 5.0097537040710449e-01 2.0398220419883728e-01 + <_> + + 0 -1 1568 2.0855569746345282e-03 + + 4.8621898889541626e-01 5.7216948270797729e-01 + <_> + + 0 -1 1569 5.0615021027624607e-03 + + 5.0002187490463257e-01 1.8018059432506561e-01 + <_> + + 0 -1 1570 -3.7174751050770283e-03 + + 5.5301171541213989e-01 4.8975929617881775e-01 + <_> + + 0 -1 1571 -1.2170500122010708e-02 + + 4.1786059737205505e-01 5.3837239742279053e-01 + <_> + + 0 -1 1572 4.6248398721218109e-03 + + 4.9971699714660645e-01 5.7613271474838257e-01 + <_> + + 0 -1 1573 -2.1040429419372231e-04 + + 5.3318071365356445e-01 4.0976810455322266e-01 + <_> + + 0 -1 1574 -1.4641780406236649e-02 + + 5.7559251785278320e-01 5.0517761707305908e-01 + <_> + + 0 -1 1575 3.3199489116668701e-03 + + 4.5769768953323364e-01 6.0318058729171753e-01 + <_> + + 0 -1 1576 3.7236879579722881e-03 + + 4.3803969025611877e-01 5.4158830642700195e-01 + <_> + + 0 -1 1577 8.2951161311939359e-04 + + 5.1630318164825439e-01 3.7022191286087036e-01 + <_> + + 0 -1 1578 -1.1408490128815174e-02 + + 6.0729467868804932e-01 4.8625651001930237e-01 + <_> + + 0 -1 1579 -4.5320121571421623e-03 + + 3.2924759387969971e-01 5.0889629125595093e-01 + <_> + + 0 -1 1580 5.1276017911732197e-03 + + 4.8297679424285889e-01 6.1227089166641235e-01 + <_> + + 0 -1 1581 9.8583158105611801e-03 + + 4.6606799960136414e-01 6.5561771392822266e-01 + <_> + + 0 -1 1582 3.6985918879508972e-02 + + 5.2048492431640625e-01 1.6904720664024353e-01 + <_> + + 0 -1 1583 4.6491161920130253e-03 + + 5.1673221588134766e-01 3.7252250313758850e-01 + <_> + + 0 -1 1584 -4.2664702050387859e-03 + + 6.4064931869506836e-01 4.9873429536819458e-01 + <_> + + 0 -1 1585 -4.7956590424291790e-04 + + 5.8972930908203125e-01 4.4648739695549011e-01 + <_> + + 0 -1 1586 3.6827160511165857e-03 + + 5.4415607452392578e-01 3.4726628661155701e-01 + <_> + + 0 -1 1587 -1.0059880092740059e-02 + + 2.1431629359722137e-01 5.0048297643661499e-01 + <_> + + 0 -1 1588 -3.0361840617842972e-04 + + 5.3864240646362305e-01 4.5903238654136658e-01 + <_> + + 0 -1 1589 -1.4545479789376259e-03 + + 5.7511842250823975e-01 4.4970950484275818e-01 + <_> + + 0 -1 1590 1.6515209572389722e-03 + + 5.4219377040863037e-01 4.2385208606719971e-01 + <_> + + 0 -1 1591 -7.8468639403581619e-03 + + 4.0779209136962891e-01 5.2581572532653809e-01 + <_> + + 0 -1 1592 -5.1259850151836872e-03 + + 4.2292758822441101e-01 5.4794532060623169e-01 + <_> + + 0 -1 1593 -3.6890961229801178e-02 + + 6.5963757038116455e-01 4.6746781468391418e-01 + <_> + + 0 -1 1594 2.4035639944486320e-04 + + 4.2511358857154846e-01 5.5732029676437378e-01 + <_> + + 0 -1 1595 -1.5150169929256663e-05 + + 5.2592468261718750e-01 4.0741148591041565e-01 + <_> + + 0 -1 1596 2.2108471021056175e-03 + + 4.6717229485511780e-01 5.8863520622253418e-01 + <_> + + 0 -1 1597 -1.1568620102480054e-03 + + 5.7110661268234253e-01 4.4871619343757629e-01 + <_> + + 0 -1 1598 4.9996292218565941e-03 + + 5.2641981840133667e-01 2.8983271121978760e-01 + <_> + + 0 -1 1599 -1.4656189596280456e-03 + + 3.8917380571365356e-01 5.1978719234466553e-01 + <_> + + 0 -1 1600 -1.1975039960816503e-03 + + 5.7958728075027466e-01 4.9279558658599854e-01 + <_> + + 0 -1 1601 -4.4954330660402775e-03 + + 2.3776030540466309e-01 5.0125551223754883e-01 + <_> + + 0 -1 1602 1.4997160178609192e-04 + + 4.8766261339187622e-01 5.6176078319549561e-01 + <_> + + 0 -1 1603 2.6391509454697371e-03 + + 5.1680880784988403e-01 3.7655091285705566e-01 + <_> + + 0 -1 1604 -2.9368131072260439e-04 + + 5.4466491937637329e-01 4.8746308684349060e-01 + <_> + + 0 -1 1605 1.4211760135367513e-03 + + 4.6878978610038757e-01 6.6913318634033203e-01 + <_> + + 0 -1 1606 7.9427637159824371e-02 + + 5.1934438943862915e-01 2.7329459786415100e-01 + <_> + + 0 -1 1607 7.9937502741813660e-02 + + 4.9717310070991516e-01 1.7820839583873749e-01 + <_> + + 0 -1 1608 1.1089259758591652e-02 + + 5.1659947633743286e-01 3.2094758749008179e-01 + <_> + + 0 -1 1609 1.6560709627810866e-04 + + 4.0584719181060791e-01 5.3072762489318848e-01 + <_> + + 0 -1 1610 -5.3354292176663876e-03 + + 3.4450569748878479e-01 5.1581299304962158e-01 + <_> + + 0 -1 1611 1.1287260567769408e-03 + + 4.5948630571365356e-01 6.0755330324172974e-01 + <_> + + 0 -1 1612 -2.1969219669699669e-02 + + 1.6804009675979614e-01 5.2285957336425781e-01 + <_> + + 0 -1 1613 -2.1775320055894554e-04 + + 3.8615968823432922e-01 5.2156728506088257e-01 + <_> + + 0 -1 1614 2.0200149447191507e-04 + + 5.5179792642593384e-01 4.3630391359329224e-01 + <_> + + 0 -1 1615 -2.1733149886131287e-02 + + 7.9994601011276245e-01 4.7898510098457336e-01 + <_> + + 0 -1 1616 -8.4399932529777288e-04 + + 4.0859758853912354e-01 5.3747731447219849e-01 + <_> + + 0 -1 1617 -4.3895249837078154e-04 + + 5.4704052209854126e-01 4.3661430478096008e-01 + <_> + + 0 -1 1618 1.5092400135472417e-03 + + 4.9889969825744629e-01 5.8421492576599121e-01 + <_> + + 0 -1 1619 -3.5547839943319559e-03 + + 6.7536902427673340e-01 4.7210058569908142e-01 + <_> + + 0 -1 1620 4.8191400128416717e-04 + + 5.4158538579940796e-01 4.3571090698242188e-01 + <_> + + 0 -1 1621 -6.0264398343861103e-03 + + 2.2585099935531616e-01 4.9918809533119202e-01 + <_> + + 0 -1 1622 -1.1668140068650246e-02 + + 6.2565547227859497e-01 4.9274989962577820e-01 + <_> + + 0 -1 1623 -2.8718370012938976e-03 + + 3.9477849006652832e-01 5.2458018064498901e-01 + <_> + + 0 -1 1624 1.7051169648766518e-02 + + 4.7525110840797424e-01 5.7942241430282593e-01 + <_> + + 0 -1 1625 -1.3352080248296261e-02 + + 6.0411047935485840e-01 4.5445358753204346e-01 + <_> + + 0 -1 1626 -3.9301801007241011e-04 + + 4.2582759261131287e-01 5.5449050664901733e-01 + <_> + + 0 -1 1627 3.0483349692076445e-03 + + 5.2334201335906982e-01 3.7802729010581970e-01 + <_> + + 0 -1 1628 -4.3579288758337498e-03 + + 6.3718891143798828e-01 4.8386740684509277e-01 + <_> + + 0 -1 1629 5.6661018170416355e-03 + + 5.3747057914733887e-01 4.1636660695075989e-01 + <_> + + 0 -1 1630 6.0677339206449687e-05 + + 4.6387958526611328e-01 5.3116250038146973e-01 + <_> + + 0 -1 1631 3.6738160997629166e-02 + + 4.6886560320854187e-01 6.4665240049362183e-01 + <_> + + 0 -1 1632 8.6528137326240540e-03 + + 5.2043187618255615e-01 2.1886579692363739e-01 + <_> + + 0 -1 1633 -1.5371359884738922e-01 + + 1.6303719580173492e-01 4.9588400125503540e-01 + <_> + + 0 -1 1634 -4.1560421232134104e-04 + + 5.7744592428207397e-01 4.6964588761329651e-01 + <_> + + 0 -1 1635 -1.2640169588848948e-03 + + 3.9771759510040283e-01 5.2171981334686279e-01 + <_> + + 0 -1 1636 -3.5473341122269630e-03 + + 6.0465282201766968e-01 4.8083150386810303e-01 + <_> + + 0 -1 1637 3.0019069527043030e-05 + + 3.9967238903045654e-01 5.2282011508941650e-01 + <_> + + 0 -1 1638 1.3113019522279501e-03 + + 4.7121581435203552e-01 5.7659977674484253e-01 + <_> + + 0 -1 1639 -1.3374709524214268e-03 + + 4.1095849871635437e-01 5.2531701326370239e-01 + <_> + + 0 -1 1640 2.0876709371805191e-02 + + 5.2029937505722046e-01 1.7579819262027740e-01 + <_> + + 0 -1 1641 -7.5497948564589024e-03 + + 6.5666097402572632e-01 4.6949750185012817e-01 + <_> + + 0 -1 1642 2.4188550189137459e-02 + + 5.1286739110946655e-01 3.3702209591865540e-01 + <_> + + 0 -1 1643 -2.9358828905969858e-03 + + 6.5807867050170898e-01 4.6945410966873169e-01 + <_> + + 0 -1 1644 5.7557929307222366e-02 + + 5.1464450359344482e-01 2.7752599120140076e-01 + <_> + + 0 -1 1645 -1.1343370424583554e-03 + + 3.8366019725799561e-01 5.1926672458648682e-01 + <_> + + 0 -1 1646 1.6816999763250351e-02 + + 5.0855928659439087e-01 6.1772608757019043e-01 + <_> + + 0 -1 1647 5.0535178743302822e-03 + + 5.1387631893157959e-01 3.6847919225692749e-01 + <_> + + 0 -1 1648 -4.5874710194766521e-03 + + 5.9896552562713623e-01 4.8352020978927612e-01 + <_> + + 0 -1 1649 1.6882460331544280e-03 + + 4.5094868540763855e-01 5.7230567932128906e-01 + <_> + + 0 -1 1650 -1.6554000321775675e-03 + + 3.4967708587646484e-01 5.2433192729949951e-01 + <_> + + 0 -1 1651 -1.9373800605535507e-02 + + 1.1205369979143143e-01 4.9687129259109497e-01 + <_> + + 0 -1 1652 1.0374450124800205e-02 + + 5.1481968164443970e-01 4.3952131271362305e-01 + <_> + + 0 -1 1653 1.4973050565458834e-04 + + 4.0849998593330383e-01 5.2698868513107300e-01 + <_> + + 0 -1 1654 -4.2981930077075958e-02 + + 6.3941049575805664e-01 5.0185042619705200e-01 + <_> + + 0 -1 1655 8.3065936341881752e-03 + + 4.7075539827346802e-01 6.6983532905578613e-01 + <_> + + 0 -1 1656 -4.1285790503025055e-03 + + 4.5413690805435181e-01 5.3236472606658936e-01 + <_> + + 0 -1 1657 1.7399420030415058e-03 + + 4.3339619040489197e-01 5.4398661851882935e-01 + <_> + + 0 -1 1658 1.1739750334527344e-04 + + 4.5796871185302734e-01 5.5434262752532959e-01 + <_> + + 0 -1 1659 1.8585780344437808e-04 + + 4.3246439099311829e-01 5.4267549514770508e-01 + <_> + + 0 -1 1660 5.5587692186236382e-03 + + 5.2572208642959595e-01 3.5506111383438110e-01 + <_> + + 0 -1 1661 -7.9851560294628143e-03 + + 6.0430181026458740e-01 4.6306359767913818e-01 + <_> + + 0 -1 1662 6.0594122624024749e-04 + + 4.5982548594474792e-01 5.5331951379776001e-01 + <_> + + 0 -1 1663 -2.2983040253166109e-04 + + 4.1307520866394043e-01 5.3224611282348633e-01 + <_> + + 0 -1 1664 4.3740210821852088e-04 + + 4.0430399775505066e-01 5.4092890024185181e-01 + <_> + + 0 -1 1665 2.9482020181603730e-04 + + 4.4949638843536377e-01 5.6288522481918335e-01 + <_> + + 0 -1 1666 1.0312659665942192e-02 + + 5.1775109767913818e-01 2.7043169736862183e-01 + <_> + + 0 -1 1667 -7.7241109684109688e-03 + + 1.9880190491676331e-01 4.9805539846420288e-01 + <_> + + 0 -1 1668 -4.6797208487987518e-03 + + 6.6447502374649048e-01 5.0182962417602539e-01 + <_> + + 0 -1 1669 -5.0755459815263748e-03 + + 3.8983049988746643e-01 5.1852691173553467e-01 + <_> + + 0 -1 1670 2.2479740437120199e-03 + + 4.8018088936805725e-01 5.6603360176086426e-01 + <_> + + 0 -1 1671 8.3327008178457618e-04 + + 5.2109199762344360e-01 3.9571881294250488e-01 + <_> + + 0 -1 1672 -4.1279330849647522e-02 + + 6.1545419692993164e-01 5.0070542097091675e-01 + <_> + + 0 -1 1673 -5.0930189900100231e-04 + + 3.9759421348571777e-01 5.2284038066864014e-01 + <_> + + 0 -1 1674 1.2568780221045017e-03 + + 4.9791380763053894e-01 5.9391832351684570e-01 + <_> + + 0 -1 1675 8.0048497766256332e-03 + + 4.9844971299171448e-01 1.6333660483360291e-01 + <_> + + 0 -1 1676 -1.1879300000146031e-03 + + 5.9049648046493530e-01 4.9426248669624329e-01 + <_> + + 0 -1 1677 6.1948952497914433e-04 + + 4.1995579004287720e-01 5.3287261724472046e-01 + <_> + + 0 -1 1678 6.6829859279096127e-03 + + 5.4186028242111206e-01 4.9058890342712402e-01 + <_> + + 0 -1 1679 -3.7062340416014194e-03 + + 3.7259390950202942e-01 5.1380002498626709e-01 + <_> + + 0 -1 1680 -3.9739411324262619e-02 + + 6.4789611101150513e-01 5.0503468513488770e-01 + <_> + + 0 -1 1681 1.4085009461268783e-03 + + 4.6823391318321228e-01 6.3778841495513916e-01 + <_> + + 0 -1 1682 3.9322688826359808e-04 + + 5.4585301876068115e-01 4.1504821181297302e-01 + <_> + + 0 -1 1683 -1.8979819724336267e-03 + + 3.6901599168777466e-01 5.1497042179107666e-01 + <_> + + 0 -1 1684 -1.3970440253615379e-02 + + 6.0505628585815430e-01 4.8113578557968140e-01 + <_> + + 0 -1 1685 -1.0100819915533066e-01 + + 2.0170800387859344e-01 4.9923619627952576e-01 + <_> + + 0 -1 1686 -1.7346920445561409e-02 + + 5.7131487131118774e-01 4.8994860053062439e-01 + <_> + + 0 -1 1687 1.5619759506080300e-04 + + 4.2153888940811157e-01 5.3926420211791992e-01 + <_> + + 0 -1 1688 1.3438929617404938e-01 + + 5.1361519098281860e-01 3.7676128745079041e-01 + <_> + + 0 -1 1689 -2.4582240730524063e-02 + + 7.0273578166961670e-01 4.7479069232940674e-01 + <_> + + 0 -1 1690 -3.8553720805794001e-03 + + 4.3174090981483459e-01 5.4277169704437256e-01 + <_> + + 0 -1 1691 -2.3165249731391668e-03 + + 5.9426987171173096e-01 4.6186479926109314e-01 + <_> + + 0 -1 1692 -4.8518120311200619e-03 + + 6.1915689706802368e-01 4.8848950862884521e-01 + <_> + + 0 -1 1693 2.4699938949197531e-03 + + 5.2566647529602051e-01 4.0171998739242554e-01 + <_> + + 0 -1 1694 4.5496959239244461e-02 + + 5.2378678321838379e-01 2.6857739686965942e-01 + <_> + + 0 -1 1695 -2.0319599658250809e-02 + + 2.1304459869861603e-01 4.9797388911247253e-01 + <_> + + 0 -1 1696 2.6994998916052282e-04 + + 4.8140418529510498e-01 5.5431222915649414e-01 + <_> + + 0 -1 1697 -1.8232699949294329e-03 + + 6.4825797080993652e-01 4.7099891304969788e-01 + <_> + + 0 -1 1698 -6.3015790656208992e-03 + + 4.5819279551506042e-01 5.3062361478805542e-01 + <_> + + 0 -1 1699 -2.4139499873854220e-04 + + 5.2320867776870728e-01 4.0517631173133850e-01 + <_> + + 0 -1 1700 -1.0330369696021080e-03 + + 5.5562019348144531e-01 4.7891938686370850e-01 + <_> + + 0 -1 1701 1.8041160365100950e-04 + + 5.2294427156448364e-01 4.0118101239204407e-01 + <_> + + 0 -1 1702 -6.1407860368490219e-02 + + 6.2986820936203003e-01 5.0107032060623169e-01 + <_> + + 0 -1 1703 -6.9543913006782532e-02 + + 7.2282809019088745e-01 4.7731840610504150e-01 + <_> + + 0 -1 1704 -7.0542663335800171e-02 + + 2.2695130109786987e-01 5.1825290918350220e-01 + <_> + + 0 -1 1705 2.4423799477517605e-03 + + 5.2370971441268921e-01 4.0981510281562805e-01 + <_> + + 0 -1 1706 1.5494349645450711e-03 + + 4.7737509012222290e-01 5.4680430889129639e-01 + <_> + + 0 -1 1707 -2.3914219811558723e-02 + + 7.1469759941101074e-01 4.7838249802589417e-01 + <_> + + 0 -1 1708 -1.2453690171241760e-02 + + 2.6352968811988831e-01 5.2411228418350220e-01 + <_> + + 0 -1 1709 -2.0760179904755205e-04 + + 3.6237570643424988e-01 5.1136088371276855e-01 + <_> + + 0 -1 1710 2.9781080229440704e-05 + + 4.7059321403503418e-01 5.4328018426895142e-01 + <_> + 211 + 1.0474919891357422e+02 + + <_> + + 0 -1 1711 1.1772749945521355e-02 + + 3.8605189323425293e-01 6.4211672544479370e-01 + <_> + + 0 -1 1712 2.7037570253014565e-02 + + 4.3856549263000488e-01 6.7540389299392700e-01 + <_> + + 0 -1 1713 -3.6419500247575343e-05 + + 5.4871010780334473e-01 3.4233158826828003e-01 + <_> + + 0 -1 1714 1.9995409529656172e-03 + + 3.2305321097373962e-01 5.4003179073333740e-01 + <_> + + 0 -1 1715 4.5278300531208515e-03 + + 5.0916397571563721e-01 2.9350438714027405e-01 + <_> + + 0 -1 1716 4.7890920541249216e-04 + + 4.1781538724899292e-01 5.3440642356872559e-01 + <_> + + 0 -1 1717 1.1720920447260141e-03 + + 2.8991821408271790e-01 5.1320707798004150e-01 + <_> + + 0 -1 1718 9.5305702416226268e-04 + + 4.2801249027252197e-01 5.5608451366424561e-01 + <_> + + 0 -1 1719 1.5099150004971307e-05 + + 4.0448719263076782e-01 5.4047602415084839e-01 + <_> + + 0 -1 1720 -6.0817901976406574e-04 + + 4.2717689275741577e-01 5.5034661293029785e-01 + <_> + + 0 -1 1721 3.3224520739167929e-03 + + 3.9627239108085632e-01 5.3697347640991211e-01 + <_> + + 0 -1 1722 -1.1037490330636501e-03 + + 4.7271779179573059e-01 5.2377498149871826e-01 + <_> + + 0 -1 1723 -1.4350269921123981e-03 + + 5.6030082702636719e-01 4.2235091328620911e-01 + <_> + + 0 -1 1724 2.0767399109899998e-03 + + 5.2259171009063721e-01 4.7327259182929993e-01 + <_> + + 0 -1 1725 -1.6412809782195836e-04 + + 3.9990758895874023e-01 5.4327398538589478e-01 + <_> + + 0 -1 1726 8.8302437216043472e-03 + + 4.6783858537673950e-01 6.0273271799087524e-01 + <_> + + 0 -1 1727 -1.0552070103585720e-02 + + 3.4939670562744141e-01 5.2139747142791748e-01 + <_> + + 0 -1 1728 -2.2731600329279900e-03 + + 6.1858189105987549e-01 4.7490629553794861e-01 + <_> + + 0 -1 1729 -8.4786332445219159e-04 + + 5.2853411436080933e-01 3.8434821367263794e-01 + <_> + + 0 -1 1730 1.2081359745934606e-03 + + 5.3606408834457397e-01 3.4473359584808350e-01 + <_> + + 0 -1 1731 2.6512730401009321e-03 + + 4.5582920312881470e-01 6.1939620971679688e-01 + <_> + + 0 -1 1732 -1.1012479662895203e-03 + + 3.6802300810813904e-01 5.3276282548904419e-01 + <_> + + 0 -1 1733 4.9561518244445324e-04 + + 3.9605951309204102e-01 5.2749407291412354e-01 + <_> + + 0 -1 1734 -4.3901771306991577e-02 + + 7.0204448699951172e-01 4.9928390979766846e-01 + <_> + + 0 -1 1735 3.4690350294113159e-02 + + 5.0491642951965332e-01 2.7666029334068298e-01 + <_> + + 0 -1 1736 -2.7442190330475569e-03 + + 2.6726329326629639e-01 5.2749711275100708e-01 + <_> + + 0 -1 1737 3.3316588960587978e-03 + + 4.5794829726219177e-01 6.0011017322540283e-01 + <_> + + 0 -1 1738 -2.0044570788741112e-02 + + 3.1715941429138184e-01 5.2357178926467896e-01 + <_> + + 0 -1 1739 1.3492030557245016e-03 + + 5.2653628587722778e-01 4.0343248844146729e-01 + <_> + + 0 -1 1740 2.9702018946409225e-03 + + 5.3324568271636963e-01 4.5719841122627258e-01 + <_> + + 0 -1 1741 6.3039981760084629e-03 + + 4.5933109521865845e-01 6.0346359014511108e-01 + <_> + + 0 -1 1742 -1.2936590239405632e-02 + + 4.4379639625549316e-01 5.3729712963104248e-01 + <_> + + 0 -1 1743 4.0148729458451271e-03 + + 4.6803238987922668e-01 6.4378339052200317e-01 + <_> + + 0 -1 1744 -2.6401679497212172e-03 + + 3.7096318602561951e-01 5.3143328428268433e-01 + <_> + + 0 -1 1745 1.3918439857661724e-02 + + 4.7235551476478577e-01 7.1308088302612305e-01 + <_> + + 0 -1 1746 -4.5087869511917233e-04 + + 4.4923940300941467e-01 5.3704041242599487e-01 + <_> + + 0 -1 1747 2.5384349282830954e-04 + + 4.4068640470504761e-01 5.5144029855728149e-01 + <_> + + 0 -1 1748 2.2710000630468130e-03 + + 4.6824169158935547e-01 5.9679841995239258e-01 + <_> + + 0 -1 1749 2.4120779708027840e-03 + + 5.0793921947479248e-01 3.0185988545417786e-01 + <_> + + 0 -1 1750 -3.6025670851813629e-05 + + 5.6010371446609497e-01 4.4710969924926758e-01 + <_> + + 0 -1 1751 -7.4905529618263245e-03 + + 2.2075350582599640e-01 4.9899441003799438e-01 + <_> + + 0 -1 1752 -1.7513120546936989e-02 + + 6.5312159061431885e-01 5.0176489353179932e-01 + <_> + + 0 -1 1753 1.4281630516052246e-01 + + 4.9679630994796753e-01 1.4820620417594910e-01 + <_> + + 0 -1 1754 5.5345268920063972e-03 + + 4.8989468812942505e-01 5.9542238712310791e-01 + <_> + + 0 -1 1755 -9.6323591424152255e-04 + + 3.9271169900894165e-01 5.1960742473602295e-01 + <_> + + 0 -1 1756 -2.0370010752230883e-03 + + 5.6133252382278442e-01 4.8848581314086914e-01 + <_> + + 0 -1 1757 1.6614829655736685e-03 + + 4.4728800654411316e-01 5.5788809061050415e-01 + <_> + + 0 -1 1758 -3.1188090797513723e-03 + + 3.8405328989028931e-01 5.3974777460098267e-01 + <_> + + 0 -1 1759 -6.4000617712736130e-03 + + 5.8439838886260986e-01 4.5332181453704834e-01 + <_> + + 0 -1 1760 3.1319601112045348e-04 + + 5.4392218589782715e-01 4.2347279191017151e-01 + <_> + + 0 -1 1761 -1.8222099170088768e-02 + + 1.2884649634361267e-01 4.9584048986434937e-01 + <_> + + 0 -1 1762 8.7969247251749039e-03 + + 4.9512979388237000e-01 7.1534800529479980e-01 + <_> + + 0 -1 1763 -4.2395070195198059e-03 + + 3.9465999603271484e-01 5.1949369907379150e-01 + <_> + + 0 -1 1764 9.7086271271109581e-03 + + 4.8975038528442383e-01 6.0649001598358154e-01 + <_> + + 0 -1 1765 -3.9934171363711357e-03 + + 3.2454401254653931e-01 5.0608289241790771e-01 + <_> + + 0 -1 1766 -1.6785059124231339e-02 + + 1.5819530189037323e-01 5.2037787437438965e-01 + <_> + + 0 -1 1767 1.8272090703248978e-02 + + 4.6809351444244385e-01 6.6269791126251221e-01 + <_> + + 0 -1 1768 5.6872838176786900e-03 + + 5.2116978168487549e-01 3.5121849179267883e-01 + <_> + + 0 -1 1769 -1.0739039862528443e-03 + + 5.7683861255645752e-01 4.5298451185226440e-01 + <_> + + 0 -1 1770 -3.7093870341777802e-03 + + 4.5077630877494812e-01 5.3135812282562256e-01 + <_> + + 0 -1 1771 -2.1110709349159151e-04 + + 5.4608201980590820e-01 4.3333768844604492e-01 + <_> + + 0 -1 1772 1.0670139454305172e-03 + + 5.3718560934066772e-01 4.0783908963203430e-01 + <_> + + 0 -1 1773 3.5943021066486835e-03 + + 4.4712871313095093e-01 5.6438362598419189e-01 + <_> + + 0 -1 1774 -5.1776031032204628e-03 + + 4.4993931055068970e-01 5.2803301811218262e-01 + <_> + + 0 -1 1775 -2.5414369883947074e-04 + + 5.5161732435226440e-01 4.4077080488204956e-01 + <_> + + 0 -1 1776 6.3522560521960258e-03 + + 5.1941901445388794e-01 2.4652279913425446e-01 + <_> + + 0 -1 1777 -4.4205080484971404e-04 + + 3.8307058811187744e-01 5.1396822929382324e-01 + <_> + + 0 -1 1778 7.4488727841526270e-04 + + 4.8910909891128540e-01 5.9747868776321411e-01 + <_> + + 0 -1 1779 -3.5116379149258137e-03 + + 7.4136817455291748e-01 4.7687649726867676e-01 + <_> + + 0 -1 1780 -1.2540910392999649e-02 + + 3.6488190293312073e-01 5.2528268098831177e-01 + <_> + + 0 -1 1781 9.4931852072477341e-03 + + 5.1004928350448608e-01 3.6295869946479797e-01 + <_> + + 0 -1 1782 1.2961150147020817e-02 + + 5.2324420213699341e-01 4.3335610628128052e-01 + <_> + + 0 -1 1783 4.7209449112415314e-03 + + 4.6481490135192871e-01 6.3310527801513672e-01 + <_> + + 0 -1 1784 -2.3119079414755106e-03 + + 5.9303098917007446e-01 4.5310580730438232e-01 + <_> + + 0 -1 1785 -2.8262299019843340e-03 + + 3.8704779744148254e-01 5.2571010589599609e-01 + <_> + + 0 -1 1786 -1.4311339473351836e-03 + + 5.5225032567977905e-01 4.5618548989295959e-01 + <_> + + 0 -1 1787 1.9378310535103083e-03 + + 4.5462208986282349e-01 5.7369667291641235e-01 + <_> + + 0 -1 1788 2.6343559147790074e-04 + + 5.3457391262054443e-01 4.5718750357627869e-01 + <_> + + 0 -1 1789 7.8257522545754910e-04 + + 3.9678159356117249e-01 5.2201879024505615e-01 + <_> + + 0 -1 1790 -1.9550440832972527e-02 + + 2.8296428918838501e-01 5.2435082197189331e-01 + <_> + + 0 -1 1791 4.3914958951063454e-04 + + 4.5900669693946838e-01 5.8990901708602905e-01 + <_> + + 0 -1 1792 2.1452000364661217e-02 + + 5.2314108610153198e-01 2.8553789854049683e-01 + <_> + + 0 -1 1793 5.8973580598831177e-04 + + 4.3972569704055786e-01 5.5064219236373901e-01 + <_> + + 0 -1 1794 -2.6157610118389130e-02 + + 3.1350791454315186e-01 5.1891750097274780e-01 + <_> + + 0 -1 1795 -1.3959860429167747e-02 + + 3.2132729887962341e-01 5.0407177209854126e-01 + <_> + + 0 -1 1796 -6.3699018210172653e-03 + + 6.3875448703765869e-01 4.8495069146156311e-01 + <_> + + 0 -1 1797 -8.5613820701837540e-03 + + 2.7591320872306824e-01 5.0320190191268921e-01 + <_> + + 0 -1 1798 9.6622901037335396e-04 + + 4.6856409311294556e-01 5.8348792791366577e-01 + <_> + + 0 -1 1799 7.6550268568098545e-04 + + 5.1752072572708130e-01 3.8964220881462097e-01 + <_> + + 0 -1 1800 -8.1833340227603912e-03 + + 2.0691369473934174e-01 5.2081221342086792e-01 + <_> + + 0 -1 1801 -9.3976939097046852e-03 + + 6.1340910196304321e-01 4.6412229537963867e-01 + <_> + + 0 -1 1802 4.8028980381786823e-03 + + 5.4541081190109253e-01 4.3952199816703796e-01 + <_> + + 0 -1 1803 -3.5680569708347321e-03 + + 6.3444852828979492e-01 4.6810939908027649e-01 + <_> + + 0 -1 1804 4.0733120404183865e-03 + + 5.2926832437515259e-01 4.0156200528144836e-01 + <_> + + 0 -1 1805 1.2568129459396005e-03 + + 4.3929880857467651e-01 5.4528248310089111e-01 + <_> + + 0 -1 1806 -2.9065010603517294e-03 + + 5.8988320827484131e-01 4.8633798956871033e-01 + <_> + + 0 -1 1807 -2.4409340694546700e-03 + + 4.0693649649620056e-01 5.2474218606948853e-01 + <_> + + 0 -1 1808 2.4830700829625130e-02 + + 5.1827257871627808e-01 3.6825248599052429e-01 + <_> + + 0 -1 1809 -4.8854008316993713e-02 + + 1.3075779378414154e-01 4.9612811207771301e-01 + <_> + + 0 -1 1810 -1.6110379947349429e-03 + + 6.4210057258605957e-01 4.8726621270179749e-01 + <_> + + 0 -1 1811 -9.7009479999542236e-02 + + 4.7769349068403244e-02 4.9509888887405396e-01 + <_> + + 0 -1 1812 1.1209240183234215e-03 + + 4.6162670850753784e-01 5.3547459840774536e-01 + <_> + + 0 -1 1813 -1.3064090162515640e-03 + + 6.2618541717529297e-01 4.6388059854507446e-01 + <_> + + 0 -1 1814 4.5771620352752507e-04 + + 5.3844177722930908e-01 4.6466401219367981e-01 + <_> + + 0 -1 1815 -6.3149951165542006e-04 + + 3.8040471076965332e-01 5.1302570104598999e-01 + <_> + + 0 -1 1816 1.4505970466416329e-04 + + 4.5543101429939270e-01 5.6644618511199951e-01 + <_> + + 0 -1 1817 -1.6474550589919090e-02 + + 6.5969580411911011e-01 4.7158598899841309e-01 + <_> + + 0 -1 1818 1.3369579799473286e-02 + + 5.1954662799835205e-01 3.0359649658203125e-01 + <_> + + 0 -1 1819 1.0271780047332868e-04 + + 5.2291762828826904e-01 4.1070660948753357e-01 + <_> + + 0 -1 1820 -5.5311559699475765e-03 + + 6.3528877496719360e-01 4.9609071016311646e-01 + <_> + + 0 -1 1821 -2.6187049224972725e-03 + + 3.8245460391044617e-01 5.1409840583801270e-01 + <_> + + 0 -1 1822 5.0834268331527710e-03 + + 4.9504399299621582e-01 6.2208187580108643e-01 + <_> + + 0 -1 1823 7.9818159341812134e-02 + + 4.9523359537124634e-01 1.3224759697914124e-01 + <_> + + 0 -1 1824 -9.9226586520671844e-02 + + 7.5427287817001343e-01 5.0084167718887329e-01 + <_> + + 0 -1 1825 -6.5174017800018191e-04 + + 3.6993029713630676e-01 5.1301211118698120e-01 + <_> + + 0 -1 1826 -1.8996849656105042e-02 + + 6.6891789436340332e-01 4.9212029576301575e-01 + <_> + + 0 -1 1827 1.7346899956464767e-02 + + 4.9833008646965027e-01 1.8591980636119843e-01 + <_> + + 0 -1 1828 5.5082101607695222e-04 + + 4.5744240283966064e-01 5.5221217870712280e-01 + <_> + + 0 -1 1829 2.0056050270795822e-03 + + 5.1317447423934937e-01 3.8564699888229370e-01 + <_> + + 0 -1 1830 -7.7688191086053848e-03 + + 4.3617001175880432e-01 5.4343092441558838e-01 + <_> + + 0 -1 1831 5.0878278911113739e-02 + + 4.6827208995819092e-01 6.8406397104263306e-01 + <_> + + 0 -1 1832 -2.2901780903339386e-03 + + 4.3292450904846191e-01 5.3060990571975708e-01 + <_> + + 0 -1 1833 -1.5715380141045898e-04 + + 5.3700572252273560e-01 4.3781641125679016e-01 + <_> + + 0 -1 1834 1.0519240051507950e-01 + + 5.1372742652893066e-01 6.7361466586589813e-02 + <_> + + 0 -1 1835 2.7198919560760260e-03 + + 4.1120609641075134e-01 5.2556651830673218e-01 + <_> + + 0 -1 1836 4.8337779939174652e-02 + + 5.4046237468719482e-01 4.4389671087265015e-01 + <_> + + 0 -1 1837 9.5703761326149106e-04 + + 4.3559691309928894e-01 5.3995108604431152e-01 + <_> + + 0 -1 1838 -2.5371259078383446e-02 + + 5.9951752424240112e-01 5.0310248136520386e-01 + <_> + + 0 -1 1839 5.2457951009273529e-02 + + 4.9502879381179810e-01 1.3983510434627533e-01 + <_> + + 0 -1 1840 -1.2365629896521568e-02 + + 6.3972991704940796e-01 4.9641060829162598e-01 + <_> + + 0 -1 1841 -1.4589719474315643e-01 + + 1.0016699880361557e-01 4.9463221430778503e-01 + <_> + + 0 -1 1842 -1.5908600762486458e-02 + + 3.3123299479484558e-01 5.2083408832550049e-01 + <_> + + 0 -1 1843 3.9486068999394774e-04 + + 4.4063639640808105e-01 5.4261028766632080e-01 + <_> + + 0 -1 1844 -5.2454001270234585e-03 + + 2.7995899319648743e-01 5.1899671554565430e-01 + <_> + + 0 -1 1845 -5.0421799533069134e-03 + + 6.9875800609588623e-01 4.7521421313285828e-01 + <_> + + 0 -1 1846 2.9812189750373363e-03 + + 4.9832889437675476e-01 6.3074797391891479e-01 + <_> + + 0 -1 1847 -7.2884308174252510e-03 + + 2.9823330044746399e-01 5.0268697738647461e-01 + <_> + + 0 -1 1848 1.5094350092113018e-03 + + 5.3084421157836914e-01 3.8329708576202393e-01 + <_> + + 0 -1 1849 -9.3340799212455750e-03 + + 2.0379640161991119e-01 4.9698171019554138e-01 + <_> + + 0 -1 1850 2.8667140752077103e-02 + + 5.0256967544555664e-01 6.9280272722244263e-01 + <_> + + 0 -1 1851 1.7019680142402649e-01 + + 4.9600529670715332e-01 1.4764429628849030e-01 + <_> + + 0 -1 1852 -3.2614478841423988e-03 + + 5.6030637025833130e-01 4.8260560631752014e-01 + <_> + + 0 -1 1853 5.5769277969375253e-04 + + 5.2055621147155762e-01 4.1296330094337463e-01 + <_> + + 0 -1 1854 3.6258339881896973e-01 + + 5.2216529846191406e-01 3.7686121463775635e-01 + <_> + + 0 -1 1855 -1.1615130119025707e-02 + + 6.0226827859878540e-01 4.6374899148941040e-01 + <_> + + 0 -1 1856 -4.0795197710394859e-03 + + 4.0704470872879028e-01 5.3374791145324707e-01 + <_> + + 0 -1 1857 5.7204300537705421e-04 + + 4.6018350124359131e-01 5.9003931283950806e-01 + <_> + + 0 -1 1858 6.7543348995968699e-04 + + 5.3982520103454590e-01 4.3454289436340332e-01 + <_> + + 0 -1 1859 6.3295697327703238e-04 + + 5.2015632390975952e-01 4.0513589978218079e-01 + <_> + + 0 -1 1860 1.2435320531949401e-03 + + 4.6423879265785217e-01 5.5474412441253662e-01 + <_> + + 0 -1 1861 -4.7363857738673687e-03 + + 6.1985671520233154e-01 4.6725520491600037e-01 + <_> + + 0 -1 1862 -6.4658462069928646e-03 + + 6.8373328447341919e-01 5.0190007686614990e-01 + <_> + + 0 -1 1863 3.5017321351915598e-04 + + 4.3448030948638916e-01 5.3636229038238525e-01 + <_> + + 0 -1 1864 1.5754920605104417e-04 + + 4.7600790858268738e-01 5.7320207357406616e-01 + <_> + + 0 -1 1865 9.9774366244673729e-03 + + 5.0909858942031860e-01 3.6350399255752563e-01 + <_> + + 0 -1 1866 -4.1464529931545258e-04 + + 5.5700647830963135e-01 4.5938020944595337e-01 + <_> + + 0 -1 1867 -3.5888899583369493e-04 + + 5.3568458557128906e-01 4.3391349911689758e-01 + <_> + + 0 -1 1868 4.0463250479660928e-04 + + 4.4398030638694763e-01 5.4367768764495850e-01 + <_> + + 0 -1 1869 -8.2184787606820464e-04 + + 4.0422949194908142e-01 5.1762992143630981e-01 + <_> + + 0 -1 1870 5.9467419050633907e-03 + + 4.9276518821716309e-01 5.6337797641754150e-01 + <_> + + 0 -1 1871 -2.1753389388322830e-02 + + 8.0062937736511230e-01 4.8008409142494202e-01 + <_> + + 0 -1 1872 -1.4540379866957664e-02 + + 3.9460548758506775e-01 5.1822227239608765e-01 + <_> + + 0 -1 1873 -4.0510769933462143e-02 + + 2.1324990317225456e-02 4.9357929825782776e-01 + <_> + + 0 -1 1874 -5.8458268176764250e-04 + + 4.0127959847450256e-01 5.3140252828598022e-01 + <_> + + 0 -1 1875 5.5151800625026226e-03 + + 4.6424189209938049e-01 5.8962607383728027e-01 + <_> + + 0 -1 1876 -6.0626221820712090e-03 + + 6.5021592378616333e-01 5.0164777040481567e-01 + <_> + + 0 -1 1877 9.4535842537879944e-02 + + 5.2647089958190918e-01 4.1268271207809448e-01 + <_> + + 0 -1 1878 4.7315051779150963e-03 + + 4.8791998624801636e-01 5.8924478292465210e-01 + <_> + + 0 -1 1879 -5.2571471314877272e-04 + + 3.9172801375389099e-01 5.1894128322601318e-01 + <_> + + 0 -1 1880 -2.5464049540460110e-03 + + 5.8375990390777588e-01 4.9857059121131897e-01 + <_> + + 0 -1 1881 -2.6075689122080803e-02 + + 1.2619839608669281e-01 4.9558219313621521e-01 + <_> + + 0 -1 1882 -5.4779709316790104e-03 + + 5.7225137948989868e-01 5.0102657079696655e-01 + <_> + + 0 -1 1883 5.1337741315364838e-03 + + 5.2732622623443604e-01 4.2263761162757874e-01 + <_> + + 0 -1 1884 4.7944980906322598e-04 + + 4.4500669836997986e-01 5.8195871114730835e-01 + <_> + + 0 -1 1885 -2.1114079281687737e-03 + + 5.7576531171798706e-01 4.5117148756980896e-01 + <_> + + 0 -1 1886 -1.3179990462958813e-02 + + 1.8843810260295868e-01 5.1607340574264526e-01 + <_> + + 0 -1 1887 -4.7968099825084209e-03 + + 6.5897899866104126e-01 4.7361189126968384e-01 + <_> + + 0 -1 1888 6.7483168095350266e-03 + + 5.2594298124313354e-01 3.3563950657844543e-01 + <_> + + 0 -1 1889 1.4623369788751006e-03 + + 5.3552711009979248e-01 4.2640921473503113e-01 + <_> + + 0 -1 1890 4.7645159065723419e-03 + + 5.0344067811965942e-01 5.7868278026580811e-01 + <_> + + 0 -1 1891 6.8066660314798355e-03 + + 4.7566050291061401e-01 6.6778290271759033e-01 + <_> + + 0 -1 1892 3.6608621012419462e-03 + + 5.3696119785308838e-01 4.3115469813346863e-01 + <_> + + 0 -1 1893 2.1449640393257141e-02 + + 4.9686419963836670e-01 1.8888160586357117e-01 + <_> + + 0 -1 1894 4.1678901761770248e-03 + + 4.9307331442832947e-01 5.8153688907623291e-01 + <_> + + 0 -1 1895 8.6467564105987549e-03 + + 5.2052050828933716e-01 4.1325950622558594e-01 + <_> + + 0 -1 1896 -3.6114078829996288e-04 + + 5.4835551977157593e-01 4.8009279370307922e-01 + <_> + + 0 -1 1897 1.0808729566633701e-03 + + 4.6899020671844482e-01 6.0414212942123413e-01 + <_> + + 0 -1 1898 5.7719959877431393e-03 + + 5.1711422204971313e-01 3.0532771348953247e-01 + <_> + + 0 -1 1899 1.5720770461484790e-03 + + 5.2199780941009521e-01 4.1788038611412048e-01 + <_> + + 0 -1 1900 -1.9307859474793077e-03 + + 5.8603698015213013e-01 4.8129200935363770e-01 + <_> + + 0 -1 1901 -7.8926272690296173e-03 + + 1.7492769658565521e-01 4.9717339873313904e-01 + <_> + + 0 -1 1902 -2.2224679123610258e-03 + + 4.3425890803337097e-01 5.2128481864929199e-01 + <_> + + 0 -1 1903 1.9011989934369922e-03 + + 4.7651869058609009e-01 6.8920552730560303e-01 + <_> + + 0 -1 1904 2.7576119173318148e-03 + + 5.2621912956237793e-01 4.3374860286712646e-01 + <_> + + 0 -1 1905 5.1787449046969414e-03 + + 4.8040691018104553e-01 7.8437292575836182e-01 + <_> + + 0 -1 1906 -9.0273341629654169e-04 + + 4.1208469867706299e-01 5.3534239530563354e-01 + <_> + + 0 -1 1907 5.1797959022223949e-03 + + 4.7403728961944580e-01 6.4259600639343262e-01 + <_> + + 0 -1 1908 -1.0114000178873539e-02 + + 2.4687920510768890e-01 5.1750177145004272e-01 + <_> + + 0 -1 1909 -1.8617060035467148e-02 + + 5.7562941312789917e-01 4.6289789676666260e-01 + <_> + + 0 -1 1910 5.9225959703326225e-03 + + 5.1696258783340454e-01 3.2142710685729980e-01 + <_> + + 0 -1 1911 -6.2945079989731312e-03 + + 3.8720148801803589e-01 5.1416367292404175e-01 + <_> + + 0 -1 1912 6.5353019163012505e-03 + + 4.8530489206314087e-01 6.3104897737503052e-01 + <_> + + 0 -1 1913 1.0878399480134249e-03 + + 5.1173150539398193e-01 3.7232589721679688e-01 + <_> + + 0 -1 1914 -2.2542240098118782e-02 + + 5.6927400827407837e-01 4.8871129751205444e-01 + <_> + + 0 -1 1915 -3.0065660830587149e-03 + + 2.5560128688812256e-01 5.0039929151535034e-01 + <_> + + 0 -1 1916 7.4741272255778313e-03 + + 4.8108729720115662e-01 5.6759268045425415e-01 + <_> + + 0 -1 1917 2.6162320747971535e-02 + + 4.9711948633193970e-01 1.7772370576858521e-01 + <_> + + 0 -1 1918 9.4352738233283162e-04 + + 4.9400109052658081e-01 5.4912507534027100e-01 + <_> + + 0 -1 1919 3.3363241702318192e-02 + + 5.0076121091842651e-01 2.7907240390777588e-01 + <_> + + 0 -1 1920 -1.5118650160729885e-02 + + 7.0595788955688477e-01 4.9730318784713745e-01 + <_> + + 0 -1 1921 9.8648946732282639e-04 + + 5.1286202669143677e-01 3.7767618894577026e-01 + <_> + 213 + 1.0576110076904297e+02 + + <_> + + 0 -1 1922 -9.5150798559188843e-02 + + 6.4707571268081665e-01 4.0172868967056274e-01 + <_> + + 0 -1 1923 6.2702340073883533e-03 + + 3.9998221397399902e-01 5.7464492321014404e-01 + <_> + + 0 -1 1924 3.0018089455552399e-04 + + 3.5587701201438904e-01 5.5388098955154419e-01 + <_> + + 0 -1 1925 1.1757409665733576e-03 + + 4.2565348744392395e-01 5.3826177120208740e-01 + <_> + + 0 -1 1926 4.4235268433112651e-05 + + 3.6829081177711487e-01 5.5899268388748169e-01 + <_> + + 0 -1 1927 -2.9936920327600092e-05 + + 5.4524701833724976e-01 4.0203678607940674e-01 + <_> + + 0 -1 1928 3.0073199886828661e-03 + + 5.2390581369400024e-01 3.3178439736366272e-01 + <_> + + 0 -1 1929 -1.0513889603316784e-02 + + 4.3206891417503357e-01 5.3079837560653687e-01 + <_> + + 0 -1 1930 8.3476826548576355e-03 + + 4.5046371221542358e-01 6.4532989263534546e-01 + <_> + + 0 -1 1931 -3.1492270063608885e-03 + + 4.3134251236915588e-01 5.3705251216888428e-01 + <_> + + 0 -1 1932 -1.4435649973165710e-05 + + 5.3266030550003052e-01 3.8179719448089600e-01 + <_> + + 0 -1 1933 -4.2855090578086674e-04 + + 4.3051639199256897e-01 5.3820097446441650e-01 + <_> + + 0 -1 1934 1.5062429883982986e-04 + + 4.2359709739685059e-01 5.5449652671813965e-01 + <_> + + 0 -1 1935 7.1559831500053406e-02 + + 5.3030598163604736e-01 2.6788029074668884e-01 + <_> + + 0 -1 1936 8.4095180500298738e-04 + + 3.5571089386940002e-01 5.2054339647293091e-01 + <_> + + 0 -1 1937 6.2986500561237335e-02 + + 5.2253627777099609e-01 2.8613761067390442e-01 + <_> + + 0 -1 1938 -3.3798629883676767e-03 + + 3.6241859197616577e-01 5.2016979455947876e-01 + <_> + + 0 -1 1939 -1.1810739670181647e-04 + + 5.4744768142700195e-01 3.9598938822746277e-01 + <_> + + 0 -1 1940 -5.4505601292476058e-04 + + 3.7404221296310425e-01 5.2157157659530640e-01 + <_> + + 0 -1 1941 -1.8454910023137927e-03 + + 5.8930522203445435e-01 4.5844489336013794e-01 + <_> + + 0 -1 1942 -4.3832371011376381e-04 + + 4.0845820307731628e-01 5.3853511810302734e-01 + <_> + + 0 -1 1943 -2.4000830017030239e-03 + + 3.7774550914764404e-01 5.2935802936553955e-01 + <_> + + 0 -1 1944 -9.8795741796493530e-02 + + 2.9636120796203613e-01 5.0700891017913818e-01 + <_> + + 0 -1 1945 3.1798239797353745e-03 + + 4.8776328563690186e-01 6.7264437675476074e-01 + <_> + + 0 -1 1946 3.2406419632025063e-04 + + 4.3669110536575317e-01 5.5611097812652588e-01 + <_> + + 0 -1 1947 -3.2547250390052795e-02 + + 3.1281578540802002e-01 5.3086161613464355e-01 + <_> + + 0 -1 1948 -7.7561130747199059e-03 + + 6.5602248907089233e-01 4.6398720145225525e-01 + <_> + + 0 -1 1949 1.6027249395847321e-02 + + 5.1726800203323364e-01 3.1418979167938232e-01 + <_> + + 0 -1 1950 7.1002350523485802e-06 + + 4.0844461321830750e-01 5.3362947702407837e-01 + <_> + + 0 -1 1951 7.3422808200120926e-03 + + 4.9669221043586731e-01 6.6034650802612305e-01 + <_> + + 0 -1 1952 -1.6970280557870865e-03 + + 5.9082370996475220e-01 4.5001828670501709e-01 + <_> + + 0 -1 1953 2.4118260480463505e-03 + + 5.3151607513427734e-01 3.5997208952903748e-01 + <_> + + 0 -1 1954 -5.5300937965512276e-03 + + 2.3340409994125366e-01 4.9968141317367554e-01 + <_> + + 0 -1 1955 -2.6478730142116547e-03 + + 5.8809357881546021e-01 4.6847340464591980e-01 + <_> + + 0 -1 1956 1.1295629665255547e-02 + + 4.9837771058082581e-01 1.8845909833908081e-01 + <_> + + 0 -1 1957 -6.6952878842130303e-04 + + 5.8721381425857544e-01 4.7990199923515320e-01 + <_> + + 0 -1 1958 1.4410680159926414e-03 + + 5.1311892271041870e-01 3.5010111331939697e-01 + <_> + + 0 -1 1959 2.4637870956212282e-03 + + 5.3393721580505371e-01 4.1176390647888184e-01 + <_> + + 0 -1 1960 3.3114518737420440e-04 + + 4.3133831024169922e-01 5.3982460498809814e-01 + <_> + + 0 -1 1961 -3.3557269722223282e-02 + + 2.6753368973731995e-01 5.1791548728942871e-01 + <_> + + 0 -1 1962 1.8539419397711754e-02 + + 4.9738699197769165e-01 2.3171770572662354e-01 + <_> + + 0 -1 1963 -2.9698139405809343e-04 + + 5.5297082662582397e-01 4.6436640620231628e-01 + <_> + + 0 -1 1964 -4.5577259152196348e-04 + + 5.6295841932296753e-01 4.4691911339759827e-01 + <_> + + 0 -1 1965 -1.0158980265259743e-02 + + 6.7062127590179443e-01 4.9259188771247864e-01 + <_> + + 0 -1 1966 -2.2413829356082715e-05 + + 5.2394217252731323e-01 3.9129018783569336e-01 + <_> + + 0 -1 1967 7.2034963523037732e-05 + + 4.7994381189346313e-01 5.5017888545989990e-01 + <_> + + 0 -1 1968 -6.9267209619283676e-03 + + 6.9300097227096558e-01 4.6980848908424377e-01 + <_> + + 0 -1 1969 -7.6997838914394379e-03 + + 4.0996238589286804e-01 5.4808831214904785e-01 + <_> + + 0 -1 1970 -7.3130549862980843e-03 + + 3.2834759354591370e-01 5.0578862428665161e-01 + <_> + + 0 -1 1971 1.9650589674711227e-03 + + 4.9780470132827759e-01 6.3982498645782471e-01 + <_> + + 0 -1 1972 7.1647600270807743e-03 + + 4.6611601114273071e-01 6.2221372127532959e-01 + <_> + + 0 -1 1973 -2.4078639224171638e-02 + + 2.3346449434757233e-01 5.2221620082855225e-01 + <_> + + 0 -1 1974 -2.1027969196438789e-02 + + 1.1836539953947067e-01 4.9382260441780090e-01 + <_> + + 0 -1 1975 3.6017020465806127e-04 + + 5.3250199556350708e-01 4.1167110204696655e-01 + <_> + + 0 -1 1976 -1.7219729721546173e-02 + + 6.2787622213363647e-01 4.6642690896987915e-01 + <_> + + 0 -1 1977 -7.8672142699360847e-03 + + 3.4034150838851929e-01 5.2497369050979614e-01 + <_> + + 0 -1 1978 -4.4777389848604798e-04 + + 3.6104118824005127e-01 5.0862592458724976e-01 + <_> + + 0 -1 1979 5.5486010387539864e-03 + + 4.8842659592628479e-01 6.2034982442855835e-01 + <_> + + 0 -1 1980 -6.9461148232221603e-03 + + 2.6259300112724304e-01 5.0110971927642822e-01 + <_> + + 0 -1 1981 1.3569870498031378e-04 + + 4.3407949805259705e-01 5.6283122301101685e-01 + <_> + + 0 -1 1982 -4.5880250632762909e-02 + + 6.5079987049102783e-01 4.6962749958038330e-01 + <_> + + 0 -1 1983 -2.1582560613751411e-02 + + 3.8265028595924377e-01 5.2876168489456177e-01 + <_> + + 0 -1 1984 -2.0209539681673050e-02 + + 3.2333680987358093e-01 5.0744771957397461e-01 + <_> + + 0 -1 1985 5.8496710844337940e-03 + + 5.1776039600372314e-01 4.4896709918975830e-01 + <_> + + 0 -1 1986 -5.7476379879517481e-05 + + 4.0208509564399719e-01 5.2463638782501221e-01 + <_> + + 0 -1 1987 -1.1513100471347570e-03 + + 6.3150721788406372e-01 4.9051541090011597e-01 + <_> + + 0 -1 1988 1.9862831104546785e-03 + + 4.7024598717689514e-01 6.4971512556076050e-01 + <_> + + 0 -1 1989 -5.2719512023031712e-03 + + 3.6503839492797852e-01 5.2276527881622314e-01 + <_> + + 0 -1 1990 1.2662699446082115e-03 + + 5.1661008596420288e-01 3.8776180148124695e-01 + <_> + + 0 -1 1991 -6.2919440679252148e-03 + + 7.3758941888809204e-01 5.0238478183746338e-01 + <_> + + 0 -1 1992 6.7360111279413104e-04 + + 4.4232261180877686e-01 5.4955857992172241e-01 + <_> + + 0 -1 1993 -1.0523450328037143e-03 + + 5.9763962030410767e-01 4.8595830798149109e-01 + <_> + + 0 -1 1994 -4.4216238893568516e-04 + + 5.9559392929077148e-01 4.3989309668540955e-01 + <_> + + 0 -1 1995 1.1747940443456173e-03 + + 5.3498882055282593e-01 4.6050581336021423e-01 + <_> + + 0 -1 1996 5.2457437850534916e-03 + + 5.0491911172866821e-01 2.9415771365165710e-01 + <_> + + 0 -1 1997 -2.4539720267057419e-02 + + 2.5501778721809387e-01 5.2185869216918945e-01 + <_> + + 0 -1 1998 7.3793041519820690e-04 + + 4.4248610734939575e-01 5.4908162355422974e-01 + <_> + + 0 -1 1999 1.4233799884095788e-03 + + 5.3195142745971680e-01 4.0813559293746948e-01 + <_> + + 0 -1 2000 -2.4149110540747643e-03 + + 4.0876591205596924e-01 5.2389502525329590e-01 + <_> + + 0 -1 2001 -1.2165299849584699e-03 + + 5.6745791435241699e-01 4.9080529808998108e-01 + <_> + + 0 -1 2002 -1.2438809499144554e-03 + + 4.1294258832931519e-01 5.2561181783676147e-01 + <_> + + 0 -1 2003 6.1942739412188530e-03 + + 5.0601941347122192e-01 7.3136532306671143e-01 + <_> + + 0 -1 2004 -1.6607169527560472e-03 + + 5.9796321392059326e-01 4.5963698625564575e-01 + <_> + + 0 -1 2005 -2.7316259220242500e-02 + + 4.1743651032447815e-01 5.3088420629501343e-01 + <_> + + 0 -1 2006 -1.5845570014789701e-03 + + 5.6158047914505005e-01 4.5194861292839050e-01 + <_> + + 0 -1 2007 -1.5514739789068699e-03 + + 4.0761870145797729e-01 5.3607851266860962e-01 + <_> + + 0 -1 2008 3.8446558755822480e-04 + + 4.3472939729690552e-01 5.4304420948028564e-01 + <_> + + 0 -1 2009 -1.4672259800136089e-02 + + 1.6593049466609955e-01 5.1460939645767212e-01 + <_> + + 0 -1 2010 8.1608882173895836e-03 + + 4.9618190526962280e-01 1.8847459554672241e-01 + <_> + + 0 -1 2011 1.1121659772470593e-03 + + 4.8682639002799988e-01 6.0938161611557007e-01 + <_> + + 0 -1 2012 -7.2603770531713963e-03 + + 6.2843251228332520e-01 4.6903759241104126e-01 + <_> + + 0 -1 2013 -2.4046430189628154e-04 + + 5.5750000476837158e-01 4.0460440516471863e-01 + <_> + + 0 -1 2014 -2.3348190006799996e-04 + + 4.1157621145248413e-01 5.2528482675552368e-01 + <_> + + 0 -1 2015 5.5736480280756950e-03 + + 4.7300729155540466e-01 5.6901007890701294e-01 + <_> + + 0 -1 2016 3.0623769387602806e-02 + + 4.9718868732452393e-01 1.7400950193405151e-01 + <_> + + 0 -1 2017 9.2074798885732889e-04 + + 5.3721177577972412e-01 4.3548721075057983e-01 + <_> + + 0 -1 2018 -4.3550739064812660e-05 + + 5.3668838739395142e-01 4.3473169207572937e-01 + <_> + + 0 -1 2019 -6.6452710889279842e-03 + + 3.4355181455612183e-01 5.1605331897735596e-01 + <_> + + 0 -1 2020 4.3221998959779739e-02 + + 4.7667920589447021e-01 7.2936528921127319e-01 + <_> + + 0 -1 2021 2.2331769578158855e-03 + + 5.0293159484863281e-01 5.6331712007522583e-01 + <_> + + 0 -1 2022 3.1829739455133677e-03 + + 4.0160921216011047e-01 5.1921367645263672e-01 + <_> + + 0 -1 2023 -1.8027749320026487e-04 + + 4.0883159637451172e-01 5.4179197549819946e-01 + <_> + + 0 -1 2024 -5.2934689447283745e-03 + + 4.0756770968437195e-01 5.2435618638992310e-01 + <_> + + 0 -1 2025 1.2750959722325206e-03 + + 4.9132829904556274e-01 6.3870108127593994e-01 + <_> + + 0 -1 2026 4.3385322205722332e-03 + + 5.0316721200942993e-01 2.9473468661308289e-01 + <_> + + 0 -1 2027 8.5250744596123695e-03 + + 4.9497890472412109e-01 6.3088691234588623e-01 + <_> + + 0 -1 2028 -9.4266352243721485e-04 + + 5.3283667564392090e-01 4.2856499552726746e-01 + <_> + + 0 -1 2029 1.3609660090878606e-03 + + 4.9915251135826111e-01 5.9415012598037720e-01 + <_> + + 0 -1 2030 4.4782509212382138e-04 + + 4.5735040307044983e-01 5.8544808626174927e-01 + <_> + + 0 -1 2031 1.3360050506889820e-03 + + 4.6043589711189270e-01 5.8490520715713501e-01 + <_> + + 0 -1 2032 -6.0967548051849008e-04 + + 3.9693889021873474e-01 5.2294230461120605e-01 + <_> + + 0 -1 2033 -2.3656780831515789e-03 + + 5.8083200454711914e-01 4.8983570933341980e-01 + <_> + + 0 -1 2034 1.0734340175986290e-03 + + 4.3512108922004700e-01 5.4700392484664917e-01 + <_> + + 0 -1 2035 2.1923359017819166e-03 + + 5.3550601005554199e-01 3.8429039716720581e-01 + <_> + + 0 -1 2036 5.4968618787825108e-03 + + 5.0181388854980469e-01 2.8271919488906860e-01 + <_> + + 0 -1 2037 -7.5368821620941162e-02 + + 1.2250760197639465e-01 5.1488268375396729e-01 + <_> + + 0 -1 2038 2.5134470313787460e-02 + + 4.7317668795585632e-01 7.0254462957382202e-01 + <_> + + 0 -1 2039 -2.9358599931583740e-05 + + 5.4305320978164673e-01 4.6560868620872498e-01 + <_> + + 0 -1 2040 -5.8355910005047917e-04 + + 4.0310400724411011e-01 5.1901197433471680e-01 + <_> + + 0 -1 2041 -2.6639450807124376e-03 + + 4.3081268668174744e-01 5.1617711782455444e-01 + <_> + + 0 -1 2042 -1.3804089976474643e-03 + + 6.2198299169540405e-01 4.6955159306526184e-01 + <_> + + 0 -1 2043 1.2313219485804439e-03 + + 5.3793638944625854e-01 4.4258311390876770e-01 + <_> + + 0 -1 2044 -1.4644179827882908e-05 + + 5.2816402912139893e-01 4.2225030064582825e-01 + <_> + + 0 -1 2045 -1.2818809598684311e-02 + + 2.5820928812026978e-01 5.1799327135086060e-01 + <_> + + 0 -1 2046 2.2852189838886261e-02 + + 4.7786930203437805e-01 7.6092642545700073e-01 + <_> + + 0 -1 2047 8.2305970136076212e-04 + + 5.3409922122955322e-01 4.6717241406440735e-01 + <_> + + 0 -1 2048 1.2770120054483414e-02 + + 4.9657610058784485e-01 1.4723660051822662e-01 + <_> + + 0 -1 2049 -5.0051510334014893e-02 + + 6.4149940013885498e-01 5.0165921449661255e-01 + <_> + + 0 -1 2050 1.5775270760059357e-02 + + 4.5223200321197510e-01 5.6853622198104858e-01 + <_> + + 0 -1 2051 -1.8501620739698410e-02 + + 2.7647489309310913e-01 5.1379591226577759e-01 + <_> + + 0 -1 2052 2.4626250378787518e-03 + + 5.1419419050216675e-01 3.7954080104827881e-01 + <_> + + 0 -1 2053 6.2916167080402374e-02 + + 5.0606489181518555e-01 6.5804338455200195e-01 + <_> + + 0 -1 2054 -2.1648500478477217e-05 + + 5.1953881978988647e-01 4.0198868513107300e-01 + <_> + + 0 -1 2055 2.1180990152060986e-03 + + 4.9623650312423706e-01 5.9544587135314941e-01 + <_> + + 0 -1 2056 -1.6634890809655190e-02 + + 3.7579330801963806e-01 5.1754468679428101e-01 + <_> + + 0 -1 2057 -2.8899470344185829e-03 + + 6.6240137815475464e-01 5.0571787357330322e-01 + <_> + + 0 -1 2058 7.6783262193202972e-02 + + 4.7957968711853027e-01 8.0477148294448853e-01 + <_> + + 0 -1 2059 3.9170677773654461e-03 + + 4.9378821253776550e-01 5.7199418544769287e-01 + <_> + + 0 -1 2060 -7.2670601308345795e-02 + + 5.3894560784101486e-02 4.9439039826393127e-01 + <_> + + 0 -1 2061 5.4039502143859863e-01 + + 5.1297742128372192e-01 1.1433389782905579e-01 + <_> + + 0 -1 2062 2.9510019812732935e-03 + + 4.5283439755439758e-01 5.6985741853713989e-01 + <_> + + 0 -1 2063 3.4508369863033295e-03 + + 5.3577268123626709e-01 4.2187309265136719e-01 + <_> + + 0 -1 2064 -4.2077939724549651e-04 + + 5.9161728620529175e-01 4.6379259228706360e-01 + <_> + + 0 -1 2065 3.3051050268113613e-03 + + 5.2733850479125977e-01 4.3820428848266602e-01 + <_> + + 0 -1 2066 4.7735060798004270e-04 + + 4.0465280413627625e-01 5.1818847656250000e-01 + <_> + + 0 -1 2067 -2.5928510352969170e-02 + + 7.4522358179092407e-01 5.0893861055374146e-01 + <_> + + 0 -1 2068 -2.9729790985584259e-03 + + 3.2954359054565430e-01 5.0587952136993408e-01 + <_> + + 0 -1 2069 5.8508329093456268e-03 + + 4.8571440577507019e-01 5.7930248975753784e-01 + <_> + + 0 -1 2070 -4.5967519283294678e-02 + + 4.3127310276031494e-01 5.3806531429290771e-01 + <_> + + 0 -1 2071 1.5585960447788239e-01 + + 5.1961702108383179e-01 1.6847139596939087e-01 + <_> + + 0 -1 2072 1.5164829790592194e-02 + + 4.7357571125030518e-01 6.7350268363952637e-01 + <_> + + 0 -1 2073 -1.0604249546304345e-03 + + 5.8229267597198486e-01 4.7757029533386230e-01 + <_> + + 0 -1 2074 6.6476291976869106e-03 + + 4.9991989135742188e-01 2.3195350170135498e-01 + <_> + + 0 -1 2075 -1.2231130152940750e-02 + + 4.7508931159973145e-01 5.2629822492599487e-01 + <_> + + 0 -1 2076 5.6528882123529911e-03 + + 5.0697678327560425e-01 3.5618188977241516e-01 + <_> + + 0 -1 2077 1.2977829901501536e-03 + + 4.8756939172744751e-01 5.6190627813339233e-01 + <_> + + 0 -1 2078 1.0781589895486832e-02 + + 4.7507700324058533e-01 6.7823082208633423e-01 + <_> + + 0 -1 2079 2.8654779307544231e-03 + + 5.3054618835449219e-01 4.2907360196113586e-01 + <_> + + 0 -1 2080 2.8663428965955973e-03 + + 4.5184791088104248e-01 5.5393511056900024e-01 + <_> + + 0 -1 2081 -5.1983320154249668e-03 + + 4.1491198539733887e-01 5.4341888427734375e-01 + <_> + + 0 -1 2082 5.3739990107715130e-03 + + 4.7178968787193298e-01 6.5076571702957153e-01 + <_> + + 0 -1 2083 -1.4641529880464077e-02 + + 2.1721640229225159e-01 5.1617771387100220e-01 + <_> + + 0 -1 2084 -1.5042580344015732e-05 + + 5.3373837471008301e-01 4.2988368868827820e-01 + <_> + + 0 -1 2085 -1.1875660129589960e-04 + + 4.6045941114425659e-01 5.5824470520019531e-01 + <_> + + 0 -1 2086 1.6995530575513840e-02 + + 4.9458950757980347e-01 7.3880076408386230e-02 + <_> + + 0 -1 2087 -3.5095941275358200e-02 + + 7.0055091381072998e-01 4.9775910377502441e-01 + <_> + + 0 -1 2088 2.4217350874096155e-03 + + 4.4662651419639587e-01 5.4776942729949951e-01 + <_> + + 0 -1 2089 -9.6340337768197060e-04 + + 4.7140988707542419e-01 5.3133380413055420e-01 + <_> + + 0 -1 2090 1.6391130338888615e-04 + + 4.3315461277961731e-01 5.3422421216964722e-01 + <_> + + 0 -1 2091 -2.1141460165381432e-02 + + 2.6447001099586487e-01 5.2044987678527832e-01 + <_> + + 0 -1 2092 8.7775202700868249e-04 + + 5.2083498239517212e-01 4.1527429223060608e-01 + <_> + + 0 -1 2093 -2.7943920344114304e-02 + + 6.3441252708435059e-01 5.0188118219375610e-01 + <_> + + 0 -1 2094 6.7297378554940224e-03 + + 5.0504380464553833e-01 3.5008639097213745e-01 + <_> + + 0 -1 2095 2.3281039670109749e-02 + + 4.9663180112838745e-01 6.9686770439147949e-01 + <_> + + 0 -1 2096 -1.1644979938864708e-02 + + 3.3002600073814392e-01 5.0496298074722290e-01 + <_> + + 0 -1 2097 1.5764309093356133e-02 + + 4.9915981292724609e-01 7.3211538791656494e-01 + <_> + + 0 -1 2098 -1.3611479662358761e-03 + + 3.9117351174354553e-01 5.1606708765029907e-01 + <_> + + 0 -1 2099 -8.1522337859496474e-04 + + 5.6289112567901611e-01 4.9497190117835999e-01 + <_> + + 0 -1 2100 -6.0066272271797061e-04 + + 5.8535951375961304e-01 4.5505958795547485e-01 + <_> + + 0 -1 2101 4.9715518252924085e-04 + + 4.2714700102806091e-01 5.4435992240905762e-01 + <_> + + 0 -1 2102 2.3475370835512877e-03 + + 5.1431107521057129e-01 3.8876569271087646e-01 + <_> + + 0 -1 2103 -8.9261569082736969e-03 + + 6.0445022583007812e-01 4.9717208743095398e-01 + <_> + + 0 -1 2104 -1.3919910416007042e-02 + + 2.5831609964370728e-01 5.0003677606582642e-01 + <_> + + 0 -1 2105 1.0209949687123299e-03 + + 4.8573741316795349e-01 5.5603581666946411e-01 + <_> + + 0 -1 2106 -2.7441629208624363e-03 + + 5.9368848800659180e-01 4.6457770466804504e-01 + <_> + + 0 -1 2107 -1.6200130805373192e-02 + + 3.1630149483680725e-01 5.1934951543807983e-01 + <_> + + 0 -1 2108 4.3331980705261230e-03 + + 5.0612241029739380e-01 3.4588789939880371e-01 + <_> + + 0 -1 2109 5.8497930876910686e-04 + + 4.7790178656578064e-01 5.8701777458190918e-01 + <_> + + 0 -1 2110 -2.2466450463980436e-03 + + 4.2978510260581970e-01 5.3747731447219849e-01 + <_> + + 0 -1 2111 2.3146099410951138e-03 + + 5.4386717081069946e-01 4.6409699320793152e-01 + <_> + + 0 -1 2112 8.7679121643304825e-03 + + 4.7268930077552795e-01 6.7717897891998291e-01 + <_> + + 0 -1 2113 -2.2448020172305405e-04 + + 4.2291730642318726e-01 5.4280489683151245e-01 + <_> + + 0 -1 2114 -7.4336021207273006e-03 + + 6.0988807678222656e-01 4.6836739778518677e-01 + <_> + + 0 -1 2115 -2.3189240600913763e-03 + + 5.6894367933273315e-01 4.4242420792579651e-01 + <_> + + 0 -1 2116 -2.1042178850620985e-03 + + 3.7622210383415222e-01 5.1870870590209961e-01 + <_> + + 0 -1 2117 4.6034841216169298e-04 + + 4.6994051337242126e-01 5.7712072134017944e-01 + <_> + + 0 -1 2118 1.0547629790380597e-03 + + 4.4652169942855835e-01 5.6017017364501953e-01 + <_> + + 0 -1 2119 8.7148818420246243e-04 + + 5.4498052597045898e-01 3.9147090911865234e-01 + <_> + + 0 -1 2120 3.3364820410497487e-04 + + 4.5640090107917786e-01 5.6457388401031494e-01 + <_> + + 0 -1 2121 -1.4853250468149781e-03 + + 5.7473778724670410e-01 4.6927788853645325e-01 + <_> + + 0 -1 2122 3.0251620337367058e-03 + + 5.1661968231201172e-01 3.7628141045570374e-01 + <_> + + 0 -1 2123 5.0280741415917873e-03 + + 5.0021117925643921e-01 6.1515271663665771e-01 + <_> + + 0 -1 2124 -5.8164511574432254e-04 + + 5.3945982456207275e-01 4.3907511234283447e-01 + <_> + + 0 -1 2125 4.5141529291868210e-02 + + 5.1883268356323242e-01 2.0630359649658203e-01 + <_> + + 0 -1 2126 -1.0795620037242770e-03 + + 3.9046850800514221e-01 5.1379072666168213e-01 + <_> + + 0 -1 2127 1.5995999274309725e-04 + + 4.8953229188919067e-01 5.4275041818618774e-01 + <_> + + 0 -1 2128 -1.9359270110726357e-02 + + 6.9752287864685059e-01 4.7735071182250977e-01 + <_> + + 0 -1 2129 2.0725509524345398e-01 + + 5.2336359024047852e-01 3.0349919199943542e-01 + <_> + + 0 -1 2130 -4.1953290929086506e-04 + + 5.4193967580795288e-01 4.4601860642433167e-01 + <_> + + 0 -1 2131 2.2582069505006075e-03 + + 4.8157641291618347e-01 6.0274088382720947e-01 + <_> + + 0 -1 2132 -6.7811207845807076e-03 + + 3.9802789688110352e-01 5.1833057403564453e-01 + <_> + + 0 -1 2133 1.1154309846460819e-02 + + 5.4312318563461304e-01 4.1887599229812622e-01 + <_> + + 0 -1 2134 4.3162431567907333e-02 + + 4.7382280230522156e-01 6.5229612588882446e-01 + + <_> + + <_> + 3 7 14 4 -1. + <_> + 3 9 14 2 2. + <_> + + <_> + 1 2 18 4 -1. + <_> + 7 2 6 4 3. + <_> + + <_> + 1 7 15 9 -1. + <_> + 1 10 15 3 3. + <_> + + <_> + 5 6 2 6 -1. + <_> + 5 9 2 3 2. + <_> + + <_> + 7 5 6 3 -1. + <_> + 9 5 2 3 3. + <_> + + <_> + 4 0 12 9 -1. + <_> + 4 3 12 3 3. + <_> + + <_> + 6 9 10 8 -1. + <_> + 6 13 10 4 2. + <_> + + <_> + 3 6 14 8 -1. + <_> + 3 10 14 4 2. + <_> + + <_> + 14 1 6 10 -1. + <_> + 14 1 3 10 2. + <_> + + <_> + 7 8 5 12 -1. + <_> + 7 12 5 4 3. + <_> + + <_> + 1 1 18 3 -1. + <_> + 7 1 6 3 3. + <_> + + <_> + 1 8 17 2 -1. + <_> + 1 9 17 1 2. + <_> + + <_> + 16 6 4 2 -1. + <_> + 16 7 4 1 2. + <_> + + <_> + 5 17 2 2 -1. + <_> + 5 18 2 1 2. + <_> + + <_> + 14 2 6 12 -1. + <_> + 14 2 3 12 2. + <_> + + <_> + 4 0 4 12 -1. + <_> + 4 0 2 6 2. + <_> + 6 6 2 6 2. + <_> + + <_> + 2 11 18 8 -1. + <_> + 8 11 6 8 3. + <_> + + <_> + 5 7 10 2 -1. + <_> + 5 8 10 1 2. + <_> + + <_> + 15 11 5 3 -1. + <_> + 15 12 5 1 3. + <_> + + <_> + 5 3 10 9 -1. + <_> + 5 6 10 3 3. + <_> + + <_> + 9 4 2 14 -1. + <_> + 9 11 2 7 2. + <_> + + <_> + 3 5 4 12 -1. + <_> + 3 9 4 4 3. + <_> + + <_> + 4 5 12 5 -1. + <_> + 8 5 4 5 3. + <_> + + <_> + 5 6 10 8 -1. + <_> + 5 10 10 4 2. + <_> + + <_> + 8 0 6 9 -1. + <_> + 8 3 6 3 3. + <_> + + <_> + 9 12 1 8 -1. + <_> + 9 16 1 4 2. + <_> + + <_> + 0 7 20 6 -1. + <_> + 0 9 20 2 3. + <_> + + <_> + 7 0 6 17 -1. + <_> + 9 0 2 17 3. + <_> + + <_> + 9 0 6 4 -1. + <_> + 11 0 2 4 3. + <_> + + <_> + 5 1 6 4 -1. + <_> + 7 1 2 4 3. + <_> + + <_> + 12 1 6 16 -1. + <_> + 14 1 2 16 3. + <_> + + <_> + 0 5 18 8 -1. + <_> + 0 5 9 4 2. + <_> + 9 9 9 4 2. + <_> + + <_> + 8 15 10 4 -1. + <_> + 13 15 5 2 2. + <_> + 8 17 5 2 2. + <_> + + <_> + 3 1 4 8 -1. + <_> + 3 1 2 4 2. + <_> + 5 5 2 4 2. + <_> + + <_> + 3 6 14 10 -1. + <_> + 10 6 7 5 2. + <_> + 3 11 7 5 2. + <_> + + <_> + 2 1 6 16 -1. + <_> + 4 1 2 16 3. + <_> + + <_> + 0 18 20 2 -1. + <_> + 0 19 20 1 2. + <_> + + <_> + 8 13 4 3 -1. + <_> + 8 14 4 1 3. + <_> + + <_> + 9 14 2 3 -1. + <_> + 9 15 2 1 3. + <_> + + <_> + 0 12 9 6 -1. + <_> + 0 14 9 2 3. + <_> + + <_> + 5 7 3 4 -1. + <_> + 5 9 3 2 2. + <_> + + <_> + 9 3 2 16 -1. + <_> + 9 11 2 8 2. + <_> + + <_> + 3 6 13 8 -1. + <_> + 3 10 13 4 2. + <_> + + <_> + 12 3 8 2 -1. + <_> + 12 3 4 2 2. + <_> + + <_> + 8 8 4 12 -1. + <_> + 8 12 4 4 3. + <_> + + <_> + 11 3 8 6 -1. + <_> + 15 3 4 3 2. + <_> + 11 6 4 3 2. + <_> + + <_> + 7 1 6 19 -1. + <_> + 9 1 2 19 3. + <_> + + <_> + 9 0 6 4 -1. + <_> + 11 0 2 4 3. + <_> + + <_> + 3 1 9 3 -1. + <_> + 6 1 3 3 3. + <_> + + <_> + 8 15 10 4 -1. + <_> + 13 15 5 2 2. + <_> + 8 17 5 2 2. + <_> + + <_> + 0 3 6 10 -1. + <_> + 3 3 3 10 2. + <_> + + <_> + 3 4 15 15 -1. + <_> + 3 9 15 5 3. + <_> + + <_> + 6 5 8 6 -1. + <_> + 6 7 8 2 3. + <_> + + <_> + 4 4 12 10 -1. + <_> + 10 4 6 5 2. + <_> + 4 9 6 5 2. + <_> + + <_> + 6 4 4 4 -1. + <_> + 8 4 2 4 2. + <_> + + <_> + 15 11 1 2 -1. + <_> + 15 12 1 1 2. + <_> + + <_> + 3 11 2 2 -1. + <_> + 3 12 2 1 2. + <_> + + <_> + 16 11 1 3 -1. + <_> + 16 12 1 1 3. + <_> + + <_> + 3 15 6 4 -1. + <_> + 3 15 3 2 2. + <_> + 6 17 3 2 2. + <_> + + <_> + 6 7 8 2 -1. + <_> + 6 8 8 1 2. + <_> + + <_> + 3 11 1 3 -1. + <_> + 3 12 1 1 3. + <_> + + <_> + 6 0 12 2 -1. + <_> + 6 1 12 1 2. + <_> + + <_> + 9 14 2 3 -1. + <_> + 9 15 2 1 3. + <_> + + <_> + 7 15 6 2 -1. + <_> + 7 16 6 1 2. + <_> + + <_> + 0 5 4 6 -1. + <_> + 0 7 4 2 3. + <_> + + <_> + 4 12 12 2 -1. + <_> + 8 12 4 2 3. + <_> + + <_> + 6 3 1 9 -1. + <_> + 6 6 1 3 3. + <_> + + <_> + 10 17 3 2 -1. + <_> + 11 17 1 2 3. + <_> + + <_> + 9 9 2 2 -1. + <_> + 9 10 2 1 2. + <_> + + <_> + 7 6 6 4 -1. + <_> + 9 6 2 4 3. + <_> + + <_> + 7 17 3 2 -1. + <_> + 8 17 1 2 3. + <_> + + <_> + 10 17 3 3 -1. + <_> + 11 17 1 3 3. + <_> + + <_> + 8 12 3 2 -1. + <_> + 8 13 3 1 2. + <_> + + <_> + 9 3 6 2 -1. + <_> + 11 3 2 2 3. + <_> + + <_> + 3 11 14 4 -1. + <_> + 3 13 14 2 2. + <_> + + <_> + 1 10 18 4 -1. + <_> + 10 10 9 2 2. + <_> + 1 12 9 2 2. + <_> + + <_> + 0 10 3 3 -1. + <_> + 0 11 3 1 3. + <_> + + <_> + 9 1 6 6 -1. + <_> + 11 1 2 6 3. + <_> + + <_> + 8 7 3 6 -1. + <_> + 9 7 1 6 3. + <_> + + <_> + 1 0 18 9 -1. + <_> + 1 3 18 3 3. + <_> + + <_> + 12 10 2 6 -1. + <_> + 12 13 2 3 2. + <_> + + <_> + 0 5 19 8 -1. + <_> + 0 9 19 4 2. + <_> + + <_> + 7 0 6 9 -1. + <_> + 9 0 2 9 3. + <_> + + <_> + 5 3 6 1 -1. + <_> + 7 3 2 1 3. + <_> + + <_> + 11 3 6 1 -1. + <_> + 13 3 2 1 3. + <_> + + <_> + 5 10 4 6 -1. + <_> + 5 13 4 3 2. + <_> + + <_> + 11 3 6 1 -1. + <_> + 13 3 2 1 3. + <_> + + <_> + 4 4 12 6 -1. + <_> + 4 6 12 2 3. + <_> + + <_> + 15 12 2 6 -1. + <_> + 15 14 2 2 3. + <_> + + <_> + 9 3 2 2 -1. + <_> + 10 3 1 2 2. + <_> + + <_> + 9 3 3 1 -1. + <_> + 10 3 1 1 3. + <_> + + <_> + 1 1 4 14 -1. + <_> + 3 1 2 14 2. + <_> + + <_> + 9 0 4 4 -1. + <_> + 11 0 2 2 2. + <_> + 9 2 2 2 2. + <_> + + <_> + 7 5 1 14 -1. + <_> + 7 12 1 7 2. + <_> + + <_> + 19 0 1 4 -1. + <_> + 19 2 1 2 2. + <_> + + <_> + 5 5 6 4 -1. + <_> + 8 5 3 4 2. + <_> + + <_> + 9 18 3 2 -1. + <_> + 10 18 1 2 3. + <_> + + <_> + 8 18 3 2 -1. + <_> + 9 18 1 2 3. + <_> + + <_> + 4 5 12 6 -1. + <_> + 4 7 12 2 3. + <_> + + <_> + 3 12 2 6 -1. + <_> + 3 14 2 2 3. + <_> + + <_> + 10 8 2 12 -1. + <_> + 10 12 2 4 3. + <_> + + <_> + 7 18 3 2 -1. + <_> + 8 18 1 2 3. + <_> + + <_> + 9 0 6 2 -1. + <_> + 11 0 2 2 3. + <_> + + <_> + 5 11 9 3 -1. + <_> + 5 12 9 1 3. + <_> + + <_> + 9 0 6 2 -1. + <_> + 11 0 2 2 3. + <_> + + <_> + 1 1 18 5 -1. + <_> + 7 1 6 5 3. + <_> + + <_> + 8 0 4 4 -1. + <_> + 10 0 2 2 2. + <_> + 8 2 2 2 2. + <_> + + <_> + 3 12 1 3 -1. + <_> + 3 13 1 1 3. + <_> + + <_> + 8 14 5 3 -1. + <_> + 8 15 5 1 3. + <_> + + <_> + 5 4 10 12 -1. + <_> + 5 4 5 6 2. + <_> + 10 10 5 6 2. + <_> + + <_> + 9 6 9 12 -1. + <_> + 9 10 9 4 3. + <_> + + <_> + 2 2 12 14 -1. + <_> + 2 2 6 7 2. + <_> + 8 9 6 7 2. + <_> + + <_> + 4 7 12 2 -1. + <_> + 8 7 4 2 3. + <_> + + <_> + 7 4 6 4 -1. + <_> + 7 6 6 2 2. + <_> + + <_> + 4 5 11 8 -1. + <_> + 4 9 11 4 2. + <_> + + <_> + 3 10 16 4 -1. + <_> + 3 12 16 2 2. + <_> + + <_> + 0 0 16 2 -1. + <_> + 0 1 16 1 2. + <_> + + <_> + 7 5 6 2 -1. + <_> + 9 5 2 2 3. + <_> + + <_> + 3 2 6 10 -1. + <_> + 3 2 3 5 2. + <_> + 6 7 3 5 2. + <_> + + <_> + 10 5 8 15 -1. + <_> + 10 10 8 5 3. + <_> + + <_> + 3 14 8 6 -1. + <_> + 3 14 4 3 2. + <_> + 7 17 4 3 2. + <_> + + <_> + 14 2 2 2 -1. + <_> + 14 3 2 1 2. + <_> + + <_> + 1 10 7 6 -1. + <_> + 1 13 7 3 2. + <_> + + <_> + 15 4 4 3 -1. + <_> + 15 4 2 3 2. + <_> + + <_> + 2 9 14 6 -1. + <_> + 2 9 7 3 2. + <_> + 9 12 7 3 2. + <_> + + <_> + 5 7 10 4 -1. + <_> + 5 9 10 2 2. + <_> + + <_> + 6 9 8 8 -1. + <_> + 6 9 4 4 2. + <_> + 10 13 4 4 2. + <_> + + <_> + 14 1 3 2 -1. + <_> + 14 2 3 1 2. + <_> + + <_> + 1 4 4 2 -1. + <_> + 3 4 2 2 2. + <_> + + <_> + 11 10 2 8 -1. + <_> + 11 14 2 4 2. + <_> + + <_> + 0 0 5 3 -1. + <_> + 0 1 5 1 3. + <_> + + <_> + 2 5 18 8 -1. + <_> + 11 5 9 4 2. + <_> + 2 9 9 4 2. + <_> + + <_> + 6 6 1 6 -1. + <_> + 6 9 1 3 2. + <_> + + <_> + 19 1 1 3 -1. + <_> + 19 2 1 1 3. + <_> + + <_> + 7 6 6 6 -1. + <_> + 9 6 2 6 3. + <_> + + <_> + 19 1 1 3 -1. + <_> + 19 2 1 1 3. + <_> + + <_> + 3 13 2 3 -1. + <_> + 3 14 2 1 3. + <_> + + <_> + 8 4 8 12 -1. + <_> + 12 4 4 6 2. + <_> + 8 10 4 6 2. + <_> + + <_> + 5 2 6 3 -1. + <_> + 7 2 2 3 3. + <_> + + <_> + 6 1 9 10 -1. + <_> + 6 6 9 5 2. + <_> + + <_> + 0 4 6 12 -1. + <_> + 2 4 2 12 3. + <_> + + <_> + 15 13 2 3 -1. + <_> + 15 14 2 1 3. + <_> + + <_> + 7 14 5 3 -1. + <_> + 7 15 5 1 3. + <_> + + <_> + 15 13 3 3 -1. + <_> + 15 14 3 1 3. + <_> + + <_> + 6 14 8 3 -1. + <_> + 6 15 8 1 3. + <_> + + <_> + 15 13 3 3 -1. + <_> + 15 14 3 1 3. + <_> + + <_> + 2 13 3 3 -1. + <_> + 2 14 3 1 3. + <_> + + <_> + 4 7 12 12 -1. + <_> + 10 7 6 6 2. + <_> + 4 13 6 6 2. + <_> + + <_> + 9 7 2 6 -1. + <_> + 10 7 1 6 2. + <_> + + <_> + 8 9 5 2 -1. + <_> + 8 10 5 1 2. + <_> + + <_> + 8 6 3 4 -1. + <_> + 9 6 1 4 3. + <_> + + <_> + 9 6 2 8 -1. + <_> + 9 10 2 4 2. + <_> + + <_> + 7 7 3 6 -1. + <_> + 8 7 1 6 3. + <_> + + <_> + 11 3 3 3 -1. + <_> + 12 3 1 3 3. + <_> + + <_> + 5 4 6 1 -1. + <_> + 7 4 2 1 3. + <_> + + <_> + 5 6 10 3 -1. + <_> + 5 7 10 1 3. + <_> + + <_> + 7 3 6 9 -1. + <_> + 7 6 6 3 3. + <_> + + <_> + 6 7 9 1 -1. + <_> + 9 7 3 1 3. + <_> + + <_> + 2 8 16 8 -1. + <_> + 2 12 16 4 2. + <_> + + <_> + 14 6 2 6 -1. + <_> + 14 9 2 3 2. + <_> + + <_> + 1 5 6 15 -1. + <_> + 1 10 6 5 3. + <_> + + <_> + 10 0 6 9 -1. + <_> + 10 3 6 3 3. + <_> + + <_> + 6 6 7 14 -1. + <_> + 6 13 7 7 2. + <_> + + <_> + 13 7 3 6 -1. + <_> + 13 9 3 2 3. + <_> + + <_> + 1 8 15 4 -1. + <_> + 6 8 5 4 3. + <_> + + <_> + 11 2 3 10 -1. + <_> + 11 7 3 5 2. + <_> + + <_> + 3 7 4 6 -1. + <_> + 3 9 4 2 3. + <_> + + <_> + 13 3 6 10 -1. + <_> + 15 3 2 10 3. + <_> + + <_> + 5 7 8 10 -1. + <_> + 5 7 4 5 2. + <_> + 9 12 4 5 2. + <_> + + <_> + 4 4 12 12 -1. + <_> + 10 4 6 6 2. + <_> + 4 10 6 6 2. + <_> + + <_> + 1 4 6 9 -1. + <_> + 3 4 2 9 3. + <_> + + <_> + 11 3 2 5 -1. + <_> + 11 3 1 5 2. + <_> + + <_> + 7 3 2 5 -1. + <_> + 8 3 1 5 2. + <_> + + <_> + 10 14 2 3 -1. + <_> + 10 15 2 1 3. + <_> + + <_> + 5 12 6 2 -1. + <_> + 8 12 3 2 2. + <_> + + <_> + 9 14 2 3 -1. + <_> + 9 15 2 1 3. + <_> + + <_> + 4 11 12 6 -1. + <_> + 4 14 12 3 2. + <_> + + <_> + 11 11 5 9 -1. + <_> + 11 14 5 3 3. + <_> + + <_> + 6 15 3 2 -1. + <_> + 6 16 3 1 2. + <_> + + <_> + 11 0 3 5 -1. + <_> + 12 0 1 5 3. + <_> + + <_> + 5 5 6 7 -1. + <_> + 8 5 3 7 2. + <_> + + <_> + 13 0 1 9 -1. + <_> + 13 3 1 3 3. + <_> + + <_> + 3 2 4 8 -1. + <_> + 3 2 2 4 2. + <_> + 5 6 2 4 2. + <_> + + <_> + 13 12 4 6 -1. + <_> + 13 14 4 2 3. + <_> + + <_> + 3 12 4 6 -1. + <_> + 3 14 4 2 3. + <_> + + <_> + 13 11 3 4 -1. + <_> + 13 13 3 2 2. + <_> + + <_> + 4 4 4 3 -1. + <_> + 4 5 4 1 3. + <_> + + <_> + 7 5 11 8 -1. + <_> + 7 9 11 4 2. + <_> + + <_> + 7 8 3 4 -1. + <_> + 8 8 1 4 3. + <_> + + <_> + 9 1 6 1 -1. + <_> + 11 1 2 1 3. + <_> + + <_> + 5 5 3 3 -1. + <_> + 5 6 3 1 3. + <_> + + <_> + 0 9 20 6 -1. + <_> + 10 9 10 3 2. + <_> + 0 12 10 3 2. + <_> + + <_> + 8 6 3 5 -1. + <_> + 9 6 1 5 3. + <_> + + <_> + 11 0 1 3 -1. + <_> + 11 1 1 1 3. + <_> + + <_> + 4 2 4 2 -1. + <_> + 4 3 4 1 2. + <_> + + <_> + 12 6 4 3 -1. + <_> + 12 7 4 1 3. + <_> + + <_> + 5 0 6 4 -1. + <_> + 7 0 2 4 3. + <_> + + <_> + 9 7 3 8 -1. + <_> + 10 7 1 8 3. + <_> + + <_> + 9 7 2 2 -1. + <_> + 10 7 1 2 2. + <_> + + <_> + 6 7 14 4 -1. + <_> + 13 7 7 2 2. + <_> + 6 9 7 2 2. + <_> + + <_> + 0 5 3 6 -1. + <_> + 0 7 3 2 3. + <_> + + <_> + 13 11 3 4 -1. + <_> + 13 13 3 2 2. + <_> + + <_> + 4 11 3 4 -1. + <_> + 4 13 3 2 2. + <_> + + <_> + 5 9 12 8 -1. + <_> + 11 9 6 4 2. + <_> + 5 13 6 4 2. + <_> + + <_> + 9 12 1 3 -1. + <_> + 9 13 1 1 3. + <_> + + <_> + 10 15 2 4 -1. + <_> + 10 17 2 2 2. + <_> + + <_> + 7 7 6 1 -1. + <_> + 9 7 2 1 3. + <_> + + <_> + 12 3 6 6 -1. + <_> + 15 3 3 3 2. + <_> + 12 6 3 3 2. + <_> + + <_> + 0 4 10 6 -1. + <_> + 0 6 10 2 3. + <_> + + <_> + 8 3 8 14 -1. + <_> + 12 3 4 7 2. + <_> + 8 10 4 7 2. + <_> + + <_> + 4 4 7 15 -1. + <_> + 4 9 7 5 3. + <_> + + <_> + 12 2 6 8 -1. + <_> + 15 2 3 4 2. + <_> + 12 6 3 4 2. + <_> + + <_> + 2 2 6 8 -1. + <_> + 2 2 3 4 2. + <_> + 5 6 3 4 2. + <_> + + <_> + 2 13 18 7 -1. + <_> + 8 13 6 7 3. + <_> + + <_> + 4 3 8 14 -1. + <_> + 4 3 4 7 2. + <_> + 8 10 4 7 2. + <_> + + <_> + 18 1 2 6 -1. + <_> + 18 3 2 2 3. + <_> + + <_> + 9 11 2 3 -1. + <_> + 9 12 2 1 3. + <_> + + <_> + 18 1 2 6 -1. + <_> + 18 3 2 2 3. + <_> + + <_> + 0 1 2 6 -1. + <_> + 0 3 2 2 3. + <_> + + <_> + 1 5 18 6 -1. + <_> + 1 7 18 2 3. + <_> + + <_> + 0 2 6 7 -1. + <_> + 3 2 3 7 2. + <_> + + <_> + 7 3 6 14 -1. + <_> + 7 10 6 7 2. + <_> + + <_> + 3 7 13 10 -1. + <_> + 3 12 13 5 2. + <_> + + <_> + 11 15 2 2 -1. + <_> + 11 16 2 1 2. + <_> + + <_> + 2 11 16 4 -1. + <_> + 2 11 8 2 2. + <_> + 10 13 8 2 2. + <_> + + <_> + 13 7 6 4 -1. + <_> + 16 7 3 2 2. + <_> + 13 9 3 2 2. + <_> + + <_> + 6 10 3 9 -1. + <_> + 6 13 3 3 3. + <_> + + <_> + 14 6 1 6 -1. + <_> + 14 9 1 3 2. + <_> + + <_> + 5 10 4 1 -1. + <_> + 7 10 2 1 2. + <_> + + <_> + 3 8 15 5 -1. + <_> + 8 8 5 5 3. + <_> + + <_> + 1 6 5 4 -1. + <_> + 1 8 5 2 2. + <_> + + <_> + 3 1 17 6 -1. + <_> + 3 3 17 2 3. + <_> + + <_> + 6 7 8 2 -1. + <_> + 10 7 4 2 2. + <_> + + <_> + 9 7 3 2 -1. + <_> + 10 7 1 2 3. + <_> + + <_> + 8 7 3 2 -1. + <_> + 9 7 1 2 3. + <_> + + <_> + 8 9 4 2 -1. + <_> + 8 10 4 1 2. + <_> + + <_> + 8 8 4 3 -1. + <_> + 8 9 4 1 3. + <_> + + <_> + 9 5 6 4 -1. + <_> + 9 5 3 4 2. + <_> + + <_> + 8 13 4 3 -1. + <_> + 8 14 4 1 3. + <_> + + <_> + 4 7 12 6 -1. + <_> + 10 7 6 3 2. + <_> + 4 10 6 3 2. + <_> + + <_> + 8 14 4 3 -1. + <_> + 8 15 4 1 3. + <_> + + <_> + 9 7 3 3 -1. + <_> + 9 8 3 1 3. + <_> + + <_> + 7 4 3 8 -1. + <_> + 8 4 1 8 3. + <_> + + <_> + 10 0 3 6 -1. + <_> + 11 0 1 6 3. + <_> + + <_> + 6 3 4 8 -1. + <_> + 8 3 2 8 2. + <_> + + <_> + 14 3 6 13 -1. + <_> + 14 3 3 13 2. + <_> + + <_> + 8 13 3 6 -1. + <_> + 8 16 3 3 2. + <_> + + <_> + 14 3 6 13 -1. + <_> + 14 3 3 13 2. + <_> + + <_> + 0 7 10 4 -1. + <_> + 0 7 5 2 2. + <_> + 5 9 5 2 2. + <_> + + <_> + 14 3 6 13 -1. + <_> + 14 3 3 13 2. + <_> + + <_> + 0 3 6 13 -1. + <_> + 3 3 3 13 2. + <_> + + <_> + 9 1 4 1 -1. + <_> + 9 1 2 1 2. + <_> + + <_> + 8 0 2 1 -1. + <_> + 9 0 1 1 2. + <_> + + <_> + 10 16 4 4 -1. + <_> + 12 16 2 2 2. + <_> + 10 18 2 2 2. + <_> + + <_> + 9 6 2 3 -1. + <_> + 10 6 1 3 2. + <_> + + <_> + 4 5 12 2 -1. + <_> + 8 5 4 2 3. + <_> + + <_> + 8 7 3 5 -1. + <_> + 9 7 1 5 3. + <_> + + <_> + 6 4 8 6 -1. + <_> + 6 6 8 2 3. + <_> + + <_> + 9 5 2 12 -1. + <_> + 9 11 2 6 2. + <_> + + <_> + 4 6 6 8 -1. + <_> + 4 10 6 4 2. + <_> + + <_> + 12 2 8 5 -1. + <_> + 12 2 4 5 2. + <_> + + <_> + 0 8 18 3 -1. + <_> + 0 9 18 1 3. + <_> + + <_> + 8 12 4 8 -1. + <_> + 8 16 4 4 2. + <_> + + <_> + 0 2 8 5 -1. + <_> + 4 2 4 5 2. + <_> + + <_> + 13 11 3 4 -1. + <_> + 13 13 3 2 2. + <_> + + <_> + 5 11 6 1 -1. + <_> + 7 11 2 1 3. + <_> + + <_> + 11 3 3 1 -1. + <_> + 12 3 1 1 3. + <_> + + <_> + 7 13 5 3 -1. + <_> + 7 14 5 1 3. + <_> + + <_> + 11 11 7 6 -1. + <_> + 11 14 7 3 2. + <_> + + <_> + 2 11 7 6 -1. + <_> + 2 14 7 3 2. + <_> + + <_> + 12 14 2 6 -1. + <_> + 12 16 2 2 3. + <_> + + <_> + 8 14 3 3 -1. + <_> + 8 15 3 1 3. + <_> + + <_> + 11 0 3 5 -1. + <_> + 12 0 1 5 3. + <_> + + <_> + 6 1 4 9 -1. + <_> + 8 1 2 9 2. + <_> + + <_> + 10 3 6 1 -1. + <_> + 12 3 2 1 3. + <_> + + <_> + 8 8 3 4 -1. + <_> + 8 10 3 2 2. + <_> + + <_> + 8 12 4 2 -1. + <_> + 8 13 4 1 2. + <_> + + <_> + 5 18 4 2 -1. + <_> + 5 19 4 1 2. + <_> + + <_> + 2 1 18 6 -1. + <_> + 2 3 18 2 3. + <_> + + <_> + 6 0 3 2 -1. + <_> + 7 0 1 2 3. + <_> + + <_> + 13 8 6 2 -1. + <_> + 16 8 3 1 2. + <_> + 13 9 3 1 2. + <_> + + <_> + 6 10 3 6 -1. + <_> + 6 13 3 3 2. + <_> + + <_> + 0 13 20 4 -1. + <_> + 10 13 10 2 2. + <_> + 0 15 10 2 2. + <_> + + <_> + 7 7 6 5 -1. + <_> + 9 7 2 5 3. + <_> + + <_> + 11 0 2 2 -1. + <_> + 11 1 2 1 2. + <_> + + <_> + 1 8 6 2 -1. + <_> + 1 8 3 1 2. + <_> + 4 9 3 1 2. + <_> + + <_> + 0 2 20 2 -1. + <_> + 10 2 10 1 2. + <_> + 0 3 10 1 2. + <_> + + <_> + 7 14 5 3 -1. + <_> + 7 15 5 1 3. + <_> + + <_> + 7 13 6 6 -1. + <_> + 10 13 3 3 2. + <_> + 7 16 3 3 2. + <_> + + <_> + 9 12 2 3 -1. + <_> + 9 13 2 1 3. + <_> + + <_> + 16 11 1 6 -1. + <_> + 16 13 1 2 3. + <_> + + <_> + 3 11 1 6 -1. + <_> + 3 13 1 2 3. + <_> + + <_> + 4 4 14 12 -1. + <_> + 11 4 7 6 2. + <_> + 4 10 7 6 2. + <_> + + <_> + 5 4 3 3 -1. + <_> + 5 5 3 1 3. + <_> + + <_> + 12 3 3 3 -1. + <_> + 13 3 1 3 3. + <_> + + <_> + 6 6 8 3 -1. + <_> + 6 7 8 1 3. + <_> + + <_> + 12 3 3 3 -1. + <_> + 13 3 1 3 3. + <_> + + <_> + 3 1 4 10 -1. + <_> + 3 1 2 5 2. + <_> + 5 6 2 5 2. + <_> + + <_> + 5 7 10 2 -1. + <_> + 5 7 5 2 2. + <_> + + <_> + 8 7 3 3 -1. + <_> + 9 7 1 3 3. + <_> + + <_> + 15 12 2 3 -1. + <_> + 15 13 2 1 3. + <_> + + <_> + 7 8 3 4 -1. + <_> + 8 8 1 4 3. + <_> + + <_> + 13 4 1 12 -1. + <_> + 13 10 1 6 2. + <_> + + <_> + 4 5 12 12 -1. + <_> + 4 5 6 6 2. + <_> + 10 11 6 6 2. + <_> + + <_> + 7 14 7 3 -1. + <_> + 7 15 7 1 3. + <_> + + <_> + 3 12 2 3 -1. + <_> + 3 13 2 1 3. + <_> + + <_> + 3 2 14 2 -1. + <_> + 10 2 7 1 2. + <_> + 3 3 7 1 2. + <_> + + <_> + 0 1 3 10 -1. + <_> + 1 1 1 10 3. + <_> + + <_> + 9 0 6 5 -1. + <_> + 11 0 2 5 3. + <_> + + <_> + 5 7 6 2 -1. + <_> + 8 7 3 2 2. + <_> + + <_> + 7 1 6 10 -1. + <_> + 7 6 6 5 2. + <_> + + <_> + 1 1 18 3 -1. + <_> + 7 1 6 3 3. + <_> + + <_> + 16 3 3 6 -1. + <_> + 16 5 3 2 3. + <_> + + <_> + 6 3 7 6 -1. + <_> + 6 6 7 3 2. + <_> + + <_> + 4 7 12 2 -1. + <_> + 8 7 4 2 3. + <_> + + <_> + 0 4 17 10 -1. + <_> + 0 9 17 5 2. + <_> + + <_> + 3 4 15 16 -1. + <_> + 3 12 15 8 2. + <_> + + <_> + 7 15 6 4 -1. + <_> + 7 17 6 2 2. + <_> + + <_> + 15 2 4 9 -1. + <_> + 15 2 2 9 2. + <_> + + <_> + 2 3 3 2 -1. + <_> + 2 4 3 1 2. + <_> + + <_> + 13 6 7 9 -1. + <_> + 13 9 7 3 3. + <_> + + <_> + 8 11 4 3 -1. + <_> + 8 12 4 1 3. + <_> + + <_> + 0 2 20 6 -1. + <_> + 10 2 10 3 2. + <_> + 0 5 10 3 2. + <_> + + <_> + 3 2 6 10 -1. + <_> + 3 2 3 5 2. + <_> + 6 7 3 5 2. + <_> + + <_> + 13 10 3 4 -1. + <_> + 13 12 3 2 2. + <_> + + <_> + 4 10 3 4 -1. + <_> + 4 12 3 2 2. + <_> + + <_> + 7 5 6 3 -1. + <_> + 9 5 2 3 3. + <_> + + <_> + 7 6 6 8 -1. + <_> + 7 10 6 4 2. + <_> + + <_> + 0 11 20 6 -1. + <_> + 0 14 20 3 2. + <_> + + <_> + 4 13 4 6 -1. + <_> + 4 13 2 3 2. + <_> + 6 16 2 3 2. + <_> + + <_> + 6 0 8 12 -1. + <_> + 10 0 4 6 2. + <_> + 6 6 4 6 2. + <_> + + <_> + 2 0 15 2 -1. + <_> + 2 1 15 1 2. + <_> + + <_> + 9 12 2 3 -1. + <_> + 9 13 2 1 3. + <_> + + <_> + 3 12 1 2 -1. + <_> + 3 13 1 1 2. + <_> + + <_> + 9 11 2 3 -1. + <_> + 9 12 2 1 3. + <_> + + <_> + 7 3 3 1 -1. + <_> + 8 3 1 1 3. + <_> + + <_> + 17 7 3 6 -1. + <_> + 17 9 3 2 3. + <_> + + <_> + 7 2 3 2 -1. + <_> + 8 2 1 2 3. + <_> + + <_> + 11 4 5 3 -1. + <_> + 11 5 5 1 3. + <_> + + <_> + 4 4 5 3 -1. + <_> + 4 5 5 1 3. + <_> + + <_> + 19 3 1 2 -1. + <_> + 19 4 1 1 2. + <_> + + <_> + 5 5 4 3 -1. + <_> + 5 6 4 1 3. + <_> + + <_> + 17 7 3 6 -1. + <_> + 17 9 3 2 3. + <_> + + <_> + 0 7 3 6 -1. + <_> + 0 9 3 2 3. + <_> + + <_> + 14 2 6 9 -1. + <_> + 14 5 6 3 3. + <_> + + <_> + 0 4 5 6 -1. + <_> + 0 6 5 2 3. + <_> + + <_> + 10 5 6 2 -1. + <_> + 12 5 2 2 3. + <_> + + <_> + 4 5 6 2 -1. + <_> + 6 5 2 2 3. + <_> + + <_> + 8 1 4 6 -1. + <_> + 8 3 4 2 3. + <_> + + <_> + 0 2 3 6 -1. + <_> + 0 4 3 2 3. + <_> + + <_> + 6 6 8 3 -1. + <_> + 6 7 8 1 3. + <_> + + <_> + 0 1 5 9 -1. + <_> + 0 4 5 3 3. + <_> + + <_> + 16 0 4 15 -1. + <_> + 16 0 2 15 2. + <_> + + <_> + 1 10 3 2 -1. + <_> + 1 11 3 1 2. + <_> + + <_> + 14 4 1 10 -1. + <_> + 14 9 1 5 2. + <_> + + <_> + 0 1 4 12 -1. + <_> + 2 1 2 12 2. + <_> + + <_> + 11 11 4 2 -1. + <_> + 11 11 2 2 2. + <_> + + <_> + 5 11 4 2 -1. + <_> + 7 11 2 2 2. + <_> + + <_> + 3 8 15 5 -1. + <_> + 8 8 5 5 3. + <_> + + <_> + 0 0 6 10 -1. + <_> + 3 0 3 10 2. + <_> + + <_> + 11 4 3 2 -1. + <_> + 12 4 1 2 3. + <_> + + <_> + 8 12 3 8 -1. + <_> + 8 16 3 4 2. + <_> + + <_> + 8 14 5 3 -1. + <_> + 8 15 5 1 3. + <_> + + <_> + 7 14 4 3 -1. + <_> + 7 15 4 1 3. + <_> + + <_> + 11 4 3 2 -1. + <_> + 12 4 1 2 3. + <_> + + <_> + 3 15 14 4 -1. + <_> + 3 15 7 2 2. + <_> + 10 17 7 2 2. + <_> + + <_> + 2 2 16 4 -1. + <_> + 10 2 8 2 2. + <_> + 2 4 8 2 2. + <_> + + <_> + 0 8 6 12 -1. + <_> + 3 8 3 12 2. + <_> + + <_> + 5 7 10 2 -1. + <_> + 5 7 5 2 2. + <_> + + <_> + 9 7 2 5 -1. + <_> + 10 7 1 5 2. + <_> + + <_> + 13 7 6 4 -1. + <_> + 16 7 3 2 2. + <_> + 13 9 3 2 2. + <_> + + <_> + 0 13 8 2 -1. + <_> + 0 14 8 1 2. + <_> + + <_> + 13 7 6 4 -1. + <_> + 16 7 3 2 2. + <_> + 13 9 3 2 2. + <_> + + <_> + 1 7 6 4 -1. + <_> + 1 7 3 2 2. + <_> + 4 9 3 2 2. + <_> + + <_> + 12 6 1 12 -1. + <_> + 12 12 1 6 2. + <_> + + <_> + 9 5 2 6 -1. + <_> + 10 5 1 6 2. + <_> + + <_> + 14 12 2 3 -1. + <_> + 14 13 2 1 3. + <_> + + <_> + 4 12 2 3 -1. + <_> + 4 13 2 1 3. + <_> + + <_> + 8 12 4 3 -1. + <_> + 8 13 4 1 3. + <_> + + <_> + 5 2 2 4 -1. + <_> + 5 2 1 2 2. + <_> + 6 4 1 2 2. + <_> + + <_> + 5 5 11 3 -1. + <_> + 5 6 11 1 3. + <_> + + <_> + 7 6 4 12 -1. + <_> + 7 12 4 6 2. + <_> + + <_> + 12 13 8 5 -1. + <_> + 12 13 4 5 2. + <_> + + <_> + 7 6 1 12 -1. + <_> + 7 12 1 6 2. + <_> + + <_> + 1 2 6 3 -1. + <_> + 4 2 3 3 2. + <_> + + <_> + 9 5 6 10 -1. + <_> + 12 5 3 5 2. + <_> + 9 10 3 5 2. + <_> + + <_> + 5 5 8 12 -1. + <_> + 5 5 4 6 2. + <_> + 9 11 4 6 2. + <_> + + <_> + 0 7 20 6 -1. + <_> + 0 9 20 2 3. + <_> + + <_> + 4 2 2 2 -1. + <_> + 4 3 2 1 2. + <_> + + <_> + 4 18 12 2 -1. + <_> + 8 18 4 2 3. + <_> + + <_> + 7 4 4 16 -1. + <_> + 7 12 4 8 2. + <_> + + <_> + 7 6 7 8 -1. + <_> + 7 10 7 4 2. + <_> + + <_> + 6 3 3 1 -1. + <_> + 7 3 1 1 3. + <_> + + <_> + 11 15 2 4 -1. + <_> + 11 17 2 2 2. + <_> + + <_> + 3 5 4 8 -1. + <_> + 3 9 4 4 2. + <_> + + <_> + 7 1 6 12 -1. + <_> + 7 7 6 6 2. + <_> + + <_> + 4 6 6 2 -1. + <_> + 6 6 2 2 3. + <_> + + <_> + 16 4 4 6 -1. + <_> + 16 6 4 2 3. + <_> + + <_> + 3 3 5 2 -1. + <_> + 3 4 5 1 2. + <_> + + <_> + 9 11 2 3 -1. + <_> + 9 12 2 1 3. + <_> + + <_> + 2 16 4 2 -1. + <_> + 2 17 4 1 2. + <_> + + <_> + 7 13 6 6 -1. + <_> + 10 13 3 3 2. + <_> + 7 16 3 3 2. + <_> + + <_> + 7 0 3 4 -1. + <_> + 8 0 1 4 3. + <_> + + <_> + 8 15 4 3 -1. + <_> + 8 16 4 1 3. + <_> + + <_> + 0 4 4 6 -1. + <_> + 0 6 4 2 3. + <_> + + <_> + 5 6 12 3 -1. + <_> + 9 6 4 3 3. + <_> + + <_> + 7 6 6 14 -1. + <_> + 9 6 2 14 3. + <_> + + <_> + 9 7 3 3 -1. + <_> + 10 7 1 3 3. + <_> + + <_> + 6 12 2 4 -1. + <_> + 6 14 2 2 2. + <_> + + <_> + 10 12 7 6 -1. + <_> + 10 14 7 2 3. + <_> + + <_> + 1 0 15 2 -1. + <_> + 1 1 15 1 2. + <_> + + <_> + 14 0 6 6 -1. + <_> + 14 0 3 6 2. + <_> + + <_> + 5 3 3 1 -1. + <_> + 6 3 1 1 3. + <_> + + <_> + 14 0 6 6 -1. + <_> + 14 0 3 6 2. + <_> + + <_> + 0 3 20 10 -1. + <_> + 0 8 20 5 2. + <_> + + <_> + 14 0 6 6 -1. + <_> + 14 0 3 6 2. + <_> + + <_> + 0 0 6 6 -1. + <_> + 3 0 3 6 2. + <_> + + <_> + 19 15 1 2 -1. + <_> + 19 16 1 1 2. + <_> + + <_> + 0 2 4 8 -1. + <_> + 2 2 2 8 2. + <_> + + <_> + 2 1 18 4 -1. + <_> + 11 1 9 2 2. + <_> + 2 3 9 2 2. + <_> + + <_> + 8 12 1 2 -1. + <_> + 8 13 1 1 2. + <_> + + <_> + 5 2 10 6 -1. + <_> + 10 2 5 3 2. + <_> + 5 5 5 3 2. + <_> + + <_> + 9 7 2 4 -1. + <_> + 10 7 1 4 2. + <_> + + <_> + 9 7 3 3 -1. + <_> + 10 7 1 3 3. + <_> + + <_> + 4 5 12 8 -1. + <_> + 8 5 4 8 3. + <_> + + <_> + 15 15 4 3 -1. + <_> + 15 16 4 1 3. + <_> + + <_> + 8 18 3 1 -1. + <_> + 9 18 1 1 3. + <_> + + <_> + 9 13 4 3 -1. + <_> + 9 14 4 1 3. + <_> + + <_> + 7 13 4 3 -1. + <_> + 7 14 4 1 3. + <_> + + <_> + 19 15 1 2 -1. + <_> + 19 16 1 1 2. + <_> + + <_> + 0 15 8 4 -1. + <_> + 0 17 8 2 2. + <_> + + <_> + 9 3 6 4 -1. + <_> + 11 3 2 4 3. + <_> + + <_> + 8 14 4 3 -1. + <_> + 8 15 4 1 3. + <_> + + <_> + 3 14 14 6 -1. + <_> + 3 16 14 2 3. + <_> + + <_> + 6 3 6 6 -1. + <_> + 6 6 6 3 2. + <_> + + <_> + 5 11 10 6 -1. + <_> + 5 14 10 3 2. + <_> + + <_> + 3 10 3 4 -1. + <_> + 4 10 1 4 3. + <_> + + <_> + 13 9 2 2 -1. + <_> + 13 9 1 2 2. + <_> + + <_> + 5 3 6 4 -1. + <_> + 7 3 2 4 3. + <_> + + <_> + 9 7 3 3 -1. + <_> + 10 7 1 3 3. + <_> + + <_> + 2 12 2 3 -1. + <_> + 2 13 2 1 3. + <_> + + <_> + 9 8 3 12 -1. + <_> + 9 12 3 4 3. + <_> + + <_> + 3 14 4 6 -1. + <_> + 3 14 2 3 2. + <_> + 5 17 2 3 2. + <_> + + <_> + 16 15 2 2 -1. + <_> + 16 16 2 1 2. + <_> + + <_> + 2 15 2 2 -1. + <_> + 2 16 2 1 2. + <_> + + <_> + 8 12 4 3 -1. + <_> + 8 13 4 1 3. + <_> + + <_> + 0 7 20 1 -1. + <_> + 10 7 10 1 2. + <_> + + <_> + 7 6 8 3 -1. + <_> + 7 6 4 3 2. + <_> + + <_> + 5 7 8 2 -1. + <_> + 9 7 4 2 2. + <_> + + <_> + 9 7 3 5 -1. + <_> + 10 7 1 5 3. + <_> + + <_> + 8 7 3 5 -1. + <_> + 9 7 1 5 3. + <_> + + <_> + 11 1 3 5 -1. + <_> + 12 1 1 5 3. + <_> + + <_> + 6 2 3 6 -1. + <_> + 7 2 1 6 3. + <_> + + <_> + 14 14 6 5 -1. + <_> + 14 14 3 5 2. + <_> + + <_> + 9 8 2 2 -1. + <_> + 9 9 2 1 2. + <_> + + <_> + 10 7 1 3 -1. + <_> + 10 8 1 1 3. + <_> + + <_> + 6 6 2 2 -1. + <_> + 6 6 1 1 2. + <_> + 7 7 1 1 2. + <_> + + <_> + 2 11 18 4 -1. + <_> + 11 11 9 2 2. + <_> + 2 13 9 2 2. + <_> + + <_> + 6 6 2 2 -1. + <_> + 6 6 1 1 2. + <_> + 7 7 1 1 2. + <_> + + <_> + 0 15 20 2 -1. + <_> + 0 16 20 1 2. + <_> + + <_> + 4 14 2 3 -1. + <_> + 4 15 2 1 3. + <_> + + <_> + 8 14 4 3 -1. + <_> + 8 15 4 1 3. + <_> + + <_> + 8 7 2 3 -1. + <_> + 8 8 2 1 3. + <_> + + <_> + 9 10 2 3 -1. + <_> + 9 11 2 1 3. + <_> + + <_> + 5 4 10 4 -1. + <_> + 5 6 10 2 2. + <_> + + <_> + 9 7 6 4 -1. + <_> + 12 7 3 2 2. + <_> + 9 9 3 2 2. + <_> + + <_> + 4 7 3 6 -1. + <_> + 4 9 3 2 3. + <_> + + <_> + 11 15 4 4 -1. + <_> + 13 15 2 2 2. + <_> + 11 17 2 2 2. + <_> + + <_> + 7 8 4 2 -1. + <_> + 7 9 4 1 2. + <_> + + <_> + 13 1 4 3 -1. + <_> + 13 1 2 3 2. + <_> + + <_> + 5 15 4 4 -1. + <_> + 5 15 2 2 2. + <_> + 7 17 2 2 2. + <_> + + <_> + 9 5 4 7 -1. + <_> + 9 5 2 7 2. + <_> + + <_> + 5 6 8 3 -1. + <_> + 9 6 4 3 2. + <_> + + <_> + 9 9 2 2 -1. + <_> + 9 10 2 1 2. + <_> + + <_> + 7 15 5 3 -1. + <_> + 7 16 5 1 3. + <_> + + <_> + 11 10 4 3 -1. + <_> + 11 10 2 3 2. + <_> + + <_> + 6 9 8 10 -1. + <_> + 6 14 8 5 2. + <_> + + <_> + 10 11 6 2 -1. + <_> + 10 11 3 2 2. + <_> + + <_> + 4 11 6 2 -1. + <_> + 7 11 3 2 2. + <_> + + <_> + 11 3 8 1 -1. + <_> + 11 3 4 1 2. + <_> + + <_> + 6 3 3 2 -1. + <_> + 7 3 1 2 3. + <_> + + <_> + 14 5 6 5 -1. + <_> + 14 5 3 5 2. + <_> + + <_> + 7 5 2 12 -1. + <_> + 7 11 2 6 2. + <_> + + <_> + 8 11 4 3 -1. + <_> + 8 12 4 1 3. + <_> + + <_> + 4 1 2 3 -1. + <_> + 5 1 1 3 2. + <_> + + <_> + 18 3 2 6 -1. + <_> + 18 5 2 2 3. + <_> + + <_> + 0 3 2 6 -1. + <_> + 0 5 2 2 3. + <_> + + <_> + 9 12 2 3 -1. + <_> + 9 13 2 1 3. + <_> + + <_> + 7 13 4 3 -1. + <_> + 7 14 4 1 3. + <_> + + <_> + 18 0 2 6 -1. + <_> + 18 2 2 2 3. + <_> + + <_> + 0 0 2 6 -1. + <_> + 0 2 2 2 3. + <_> + + <_> + 8 14 6 3 -1. + <_> + 8 15 6 1 3. + <_> + + <_> + 7 4 2 4 -1. + <_> + 8 4 1 4 2. + <_> + + <_> + 8 5 4 6 -1. + <_> + 8 7 4 2 3. + <_> + + <_> + 6 4 2 2 -1. + <_> + 7 4 1 2 2. + <_> + + <_> + 3 14 14 4 -1. + <_> + 10 14 7 2 2. + <_> + 3 16 7 2 2. + <_> + + <_> + 6 15 6 2 -1. + <_> + 6 15 3 1 2. + <_> + 9 16 3 1 2. + <_> + + <_> + 14 15 6 2 -1. + <_> + 14 16 6 1 2. + <_> + + <_> + 2 12 12 8 -1. + <_> + 2 16 12 4 2. + <_> + + <_> + 7 7 7 2 -1. + <_> + 7 8 7 1 2. + <_> + + <_> + 0 2 18 2 -1. + <_> + 0 3 18 1 2. + <_> + + <_> + 9 6 2 5 -1. + <_> + 9 6 1 5 2. + <_> + + <_> + 7 5 3 8 -1. + <_> + 8 5 1 8 3. + <_> + + <_> + 9 6 3 4 -1. + <_> + 10 6 1 4 3. + <_> + + <_> + 4 13 3 2 -1. + <_> + 4 14 3 1 2. + <_> + + <_> + 9 4 6 3 -1. + <_> + 11 4 2 3 3. + <_> + + <_> + 5 4 6 3 -1. + <_> + 7 4 2 3 3. + <_> + + <_> + 14 11 5 2 -1. + <_> + 14 12 5 1 2. + <_> + + <_> + 1 2 6 9 -1. + <_> + 3 2 2 9 3. + <_> + + <_> + 14 6 6 13 -1. + <_> + 14 6 3 13 2. + <_> + + <_> + 3 6 14 8 -1. + <_> + 3 6 7 4 2. + <_> + 10 10 7 4 2. + <_> + + <_> + 16 0 4 11 -1. + <_> + 16 0 2 11 2. + <_> + + <_> + 3 4 12 12 -1. + <_> + 3 4 6 6 2. + <_> + 9 10 6 6 2. + <_> + + <_> + 11 4 5 3 -1. + <_> + 11 5 5 1 3. + <_> + + <_> + 4 11 4 2 -1. + <_> + 4 12 4 1 2. + <_> + + <_> + 10 7 2 2 -1. + <_> + 10 7 1 2 2. + <_> + + <_> + 8 7 2 2 -1. + <_> + 9 7 1 2 2. + <_> + + <_> + 9 17 3 2 -1. + <_> + 10 17 1 2 3. + <_> + + <_> + 5 6 3 3 -1. + <_> + 5 7 3 1 3. + <_> + + <_> + 10 0 3 3 -1. + <_> + 11 0 1 3 3. + <_> + + <_> + 5 6 6 2 -1. + <_> + 5 6 3 1 2. + <_> + 8 7 3 1 2. + <_> + + <_> + 12 16 4 3 -1. + <_> + 12 17 4 1 3. + <_> + + <_> + 3 12 3 2 -1. + <_> + 3 13 3 1 2. + <_> + + <_> + 9 12 3 2 -1. + <_> + 9 13 3 1 2. + <_> + + <_> + 1 11 16 4 -1. + <_> + 1 11 8 2 2. + <_> + 9 13 8 2 2. + <_> + + <_> + 12 4 3 3 -1. + <_> + 12 5 3 1 3. + <_> + + <_> + 4 4 5 3 -1. + <_> + 4 5 5 1 3. + <_> + + <_> + 12 16 4 3 -1. + <_> + 12 17 4 1 3. + <_> + + <_> + 5 4 3 3 -1. + <_> + 5 5 3 1 3. + <_> + + <_> + 9 0 2 2 -1. + <_> + 9 1 2 1 2. + <_> + + <_> + 8 9 4 2 -1. + <_> + 8 10 4 1 2. + <_> + + <_> + 8 8 4 3 -1. + <_> + 8 9 4 1 3. + <_> + + <_> + 0 13 6 3 -1. + <_> + 2 13 2 3 3. + <_> + + <_> + 16 14 3 2 -1. + <_> + 16 15 3 1 2. + <_> + + <_> + 1 18 18 2 -1. + <_> + 7 18 6 2 3. + <_> + + <_> + 16 14 3 2 -1. + <_> + 16 15 3 1 2. + <_> + + <_> + 1 14 3 2 -1. + <_> + 1 15 3 1 2. + <_> + + <_> + 7 14 6 3 -1. + <_> + 7 15 6 1 3. + <_> + + <_> + 5 14 8 3 -1. + <_> + 5 15 8 1 3. + <_> + + <_> + 10 6 4 14 -1. + <_> + 10 6 2 14 2. + <_> + + <_> + 6 6 4 14 -1. + <_> + 8 6 2 14 2. + <_> + + <_> + 13 5 2 3 -1. + <_> + 13 6 2 1 3. + <_> + + <_> + 7 16 6 1 -1. + <_> + 9 16 2 1 3. + <_> + + <_> + 9 12 3 3 -1. + <_> + 9 13 3 1 3. + <_> + + <_> + 7 0 3 3 -1. + <_> + 8 0 1 3 3. + <_> + + <_> + 4 0 16 18 -1. + <_> + 4 9 16 9 2. + <_> + + <_> + 1 1 16 14 -1. + <_> + 1 8 16 7 2. + <_> + + <_> + 3 9 15 4 -1. + <_> + 8 9 5 4 3. + <_> + + <_> + 6 12 7 3 -1. + <_> + 6 13 7 1 3. + <_> + + <_> + 14 15 2 3 -1. + <_> + 14 16 2 1 3. + <_> + + <_> + 2 3 16 14 -1. + <_> + 2 3 8 7 2. + <_> + 10 10 8 7 2. + <_> + + <_> + 16 2 4 18 -1. + <_> + 18 2 2 9 2. + <_> + 16 11 2 9 2. + <_> + + <_> + 4 15 2 3 -1. + <_> + 4 16 2 1 3. + <_> + + <_> + 16 2 4 18 -1. + <_> + 18 2 2 9 2. + <_> + 16 11 2 9 2. + <_> + + <_> + 1 1 8 3 -1. + <_> + 1 2 8 1 3. + <_> + + <_> + 8 11 4 3 -1. + <_> + 8 12 4 1 3. + <_> + + <_> + 5 11 5 9 -1. + <_> + 5 14 5 3 3. + <_> + + <_> + 16 0 4 11 -1. + <_> + 16 0 2 11 2. + <_> + + <_> + 7 0 6 1 -1. + <_> + 9 0 2 1 3. + <_> + + <_> + 16 3 3 7 -1. + <_> + 17 3 1 7 3. + <_> + + <_> + 1 3 3 7 -1. + <_> + 2 3 1 7 3. + <_> + + <_> + 7 8 6 12 -1. + <_> + 7 12 6 4 3. + <_> + + <_> + 0 0 4 11 -1. + <_> + 2 0 2 11 2. + <_> + + <_> + 14 0 6 20 -1. + <_> + 14 0 3 20 2. + <_> + + <_> + 0 3 1 2 -1. + <_> + 0 4 1 1 2. + <_> + + <_> + 5 5 10 8 -1. + <_> + 10 5 5 4 2. + <_> + 5 9 5 4 2. + <_> + + <_> + 4 7 12 4 -1. + <_> + 4 7 6 2 2. + <_> + 10 9 6 2 2. + <_> + + <_> + 2 1 6 4 -1. + <_> + 5 1 3 4 2. + <_> + + <_> + 9 7 6 4 -1. + <_> + 12 7 3 2 2. + <_> + 9 9 3 2 2. + <_> + + <_> + 5 6 2 6 -1. + <_> + 5 9 2 3 2. + <_> + + <_> + 9 16 6 4 -1. + <_> + 12 16 3 2 2. + <_> + 9 18 3 2 2. + <_> + + <_> + 9 4 2 12 -1. + <_> + 9 10 2 6 2. + <_> + + <_> + 7 1 6 18 -1. + <_> + 9 1 2 18 3. + <_> + + <_> + 4 12 12 2 -1. + <_> + 8 12 4 2 3. + <_> + + <_> + 8 8 6 2 -1. + <_> + 8 9 6 1 2. + <_> + + <_> + 8 0 3 6 -1. + <_> + 9 0 1 6 3. + <_> + + <_> + 11 18 3 2 -1. + <_> + 11 19 3 1 2. + <_> + + <_> + 1 1 17 4 -1. + <_> + 1 3 17 2 2. + <_> + + <_> + 11 8 4 12 -1. + <_> + 11 8 2 12 2. + <_> + + <_> + 8 14 4 3 -1. + <_> + 8 15 4 1 3. + <_> + + <_> + 12 3 2 17 -1. + <_> + 12 3 1 17 2. + <_> + + <_> + 4 7 6 1 -1. + <_> + 6 7 2 1 3. + <_> + + <_> + 18 3 2 3 -1. + <_> + 18 4 2 1 3. + <_> + + <_> + 8 4 3 4 -1. + <_> + 8 6 3 2 2. + <_> + + <_> + 4 5 12 10 -1. + <_> + 4 10 12 5 2. + <_> + + <_> + 5 18 4 2 -1. + <_> + 7 18 2 2 2. + <_> + + <_> + 17 2 3 6 -1. + <_> + 17 4 3 2 3. + <_> + + <_> + 7 7 6 6 -1. + <_> + 9 7 2 6 3. + <_> + + <_> + 17 2 3 6 -1. + <_> + 17 4 3 2 3. + <_> + + <_> + 8 0 3 4 -1. + <_> + 9 0 1 4 3. + <_> + + <_> + 9 14 2 3 -1. + <_> + 9 15 2 1 3. + <_> + + <_> + 0 12 6 3 -1. + <_> + 0 13 6 1 3. + <_> + + <_> + 8 14 4 3 -1. + <_> + 8 15 4 1 3. + <_> + + <_> + 3 12 2 3 -1. + <_> + 3 13 2 1 3. + <_> + + <_> + 5 6 12 7 -1. + <_> + 9 6 4 7 3. + <_> + + <_> + 0 2 3 6 -1. + <_> + 0 4 3 2 3. + <_> + + <_> + 14 6 1 3 -1. + <_> + 14 7 1 1 3. + <_> + + <_> + 2 0 3 14 -1. + <_> + 3 0 1 14 3. + <_> + + <_> + 12 14 5 6 -1. + <_> + 12 16 5 2 3. + <_> + + <_> + 4 14 5 6 -1. + <_> + 4 16 5 2 3. + <_> + + <_> + 11 10 2 2 -1. + <_> + 12 10 1 1 2. + <_> + 11 11 1 1 2. + <_> + + <_> + 5 0 3 14 -1. + <_> + 6 0 1 14 3. + <_> + + <_> + 10 15 2 3 -1. + <_> + 10 16 2 1 3. + <_> + + <_> + 0 2 2 3 -1. + <_> + 0 3 2 1 3. + <_> + + <_> + 5 11 12 6 -1. + <_> + 5 14 12 3 2. + <_> + + <_> + 6 11 3 9 -1. + <_> + 6 14 3 3 3. + <_> + + <_> + 11 10 2 2 -1. + <_> + 12 10 1 1 2. + <_> + 11 11 1 1 2. + <_> + + <_> + 5 6 1 3 -1. + <_> + 5 7 1 1 3. + <_> + + <_> + 4 9 13 3 -1. + <_> + 4 10 13 1 3. + <_> + + <_> + 1 7 15 6 -1. + <_> + 6 7 5 6 3. + <_> + + <_> + 4 5 12 6 -1. + <_> + 8 5 4 6 3. + <_> + + <_> + 8 10 4 3 -1. + <_> + 8 11 4 1 3. + <_> + + <_> + 15 14 1 3 -1. + <_> + 15 15 1 1 3. + <_> + + <_> + 1 11 5 3 -1. + <_> + 1 12 5 1 3. + <_> + + <_> + 7 1 7 12 -1. + <_> + 7 7 7 6 2. + <_> + + <_> + 0 1 6 10 -1. + <_> + 0 1 3 5 2. + <_> + 3 6 3 5 2. + <_> + + <_> + 16 1 4 3 -1. + <_> + 16 2 4 1 3. + <_> + + <_> + 5 5 2 3 -1. + <_> + 5 6 2 1 3. + <_> + + <_> + 12 2 3 5 -1. + <_> + 13 2 1 5 3. + <_> + + <_> + 0 3 4 6 -1. + <_> + 0 5 4 2 3. + <_> + + <_> + 8 12 4 2 -1. + <_> + 8 13 4 1 2. + <_> + + <_> + 8 18 3 1 -1. + <_> + 9 18 1 1 3. + <_> + + <_> + 11 10 2 2 -1. + <_> + 12 10 1 1 2. + <_> + 11 11 1 1 2. + <_> + + <_> + 7 10 2 2 -1. + <_> + 7 10 1 1 2. + <_> + 8 11 1 1 2. + <_> + + <_> + 11 11 4 4 -1. + <_> + 11 13 4 2 2. + <_> + + <_> + 8 12 3 8 -1. + <_> + 9 12 1 8 3. + <_> + + <_> + 13 0 6 3 -1. + <_> + 13 1 6 1 3. + <_> + + <_> + 8 8 3 4 -1. + <_> + 9 8 1 4 3. + <_> + + <_> + 5 7 10 10 -1. + <_> + 10 7 5 5 2. + <_> + 5 12 5 5 2. + <_> + + <_> + 3 18 8 2 -1. + <_> + 3 18 4 1 2. + <_> + 7 19 4 1 2. + <_> + + <_> + 10 2 6 8 -1. + <_> + 12 2 2 8 3. + <_> + + <_> + 4 2 6 8 -1. + <_> + 6 2 2 8 3. + <_> + + <_> + 11 0 3 7 -1. + <_> + 12 0 1 7 3. + <_> + + <_> + 7 11 2 1 -1. + <_> + 8 11 1 1 2. + <_> + + <_> + 15 14 1 3 -1. + <_> + 15 15 1 1 3. + <_> + + <_> + 7 15 2 2 -1. + <_> + 7 15 1 1 2. + <_> + 8 16 1 1 2. + <_> + + <_> + 15 14 1 3 -1. + <_> + 15 15 1 1 3. + <_> + + <_> + 6 0 3 7 -1. + <_> + 7 0 1 7 3. + <_> + + <_> + 18 1 2 7 -1. + <_> + 18 1 1 7 2. + <_> + + <_> + 2 0 8 20 -1. + <_> + 2 10 8 10 2. + <_> + + <_> + 3 0 15 6 -1. + <_> + 3 2 15 2 3. + <_> + + <_> + 4 3 12 2 -1. + <_> + 4 4 12 1 2. + <_> + + <_> + 16 0 4 5 -1. + <_> + 16 0 2 5 2. + <_> + + <_> + 7 0 3 4 -1. + <_> + 8 0 1 4 3. + <_> + + <_> + 16 0 4 5 -1. + <_> + 16 0 2 5 2. + <_> + + <_> + 1 7 6 13 -1. + <_> + 3 7 2 13 3. + <_> + + <_> + 16 0 4 5 -1. + <_> + 16 0 2 5 2. + <_> + + <_> + 0 0 4 5 -1. + <_> + 2 0 2 5 2. + <_> + + <_> + 14 12 3 6 -1. + <_> + 14 14 3 2 3. + <_> + + <_> + 3 12 3 6 -1. + <_> + 3 14 3 2 3. + <_> + + <_> + 16 1 4 3 -1. + <_> + 16 2 4 1 3. + <_> + + <_> + 8 7 2 10 -1. + <_> + 8 7 1 5 2. + <_> + 9 12 1 5 2. + <_> + + <_> + 11 11 4 4 -1. + <_> + 11 13 4 2 2. + <_> + + <_> + 0 1 4 3 -1. + <_> + 0 2 4 1 3. + <_> + + <_> + 13 4 1 3 -1. + <_> + 13 5 1 1 3. + <_> + + <_> + 7 15 3 5 -1. + <_> + 8 15 1 5 3. + <_> + + <_> + 9 7 3 5 -1. + <_> + 10 7 1 5 3. + <_> + + <_> + 8 7 3 5 -1. + <_> + 9 7 1 5 3. + <_> + + <_> + 10 6 4 14 -1. + <_> + 10 6 2 14 2. + <_> + + <_> + 0 5 5 6 -1. + <_> + 0 7 5 2 3. + <_> + + <_> + 9 5 6 4 -1. + <_> + 9 5 3 4 2. + <_> + + <_> + 0 0 18 10 -1. + <_> + 6 0 6 10 3. + <_> + + <_> + 10 6 4 14 -1. + <_> + 10 6 2 14 2. + <_> + + <_> + 6 6 4 14 -1. + <_> + 8 6 2 14 2. + <_> + + <_> + 13 4 1 3 -1. + <_> + 13 5 1 1 3. + <_> + + <_> + 5 1 2 3 -1. + <_> + 6 1 1 3 2. + <_> + + <_> + 18 1 2 18 -1. + <_> + 19 1 1 9 2. + <_> + 18 10 1 9 2. + <_> + + <_> + 2 1 4 3 -1. + <_> + 2 2 4 1 3. + <_> + + <_> + 18 1 2 18 -1. + <_> + 19 1 1 9 2. + <_> + 18 10 1 9 2. + <_> + + <_> + 1 14 4 6 -1. + <_> + 1 14 2 3 2. + <_> + 3 17 2 3 2. + <_> + + <_> + 10 11 7 6 -1. + <_> + 10 13 7 2 3. + <_> + + <_> + 0 10 6 10 -1. + <_> + 0 10 3 5 2. + <_> + 3 15 3 5 2. + <_> + + <_> + 11 0 3 4 -1. + <_> + 12 0 1 4 3. + <_> + + <_> + 5 10 5 6 -1. + <_> + 5 13 5 3 2. + <_> + + <_> + 14 6 1 8 -1. + <_> + 14 10 1 4 2. + <_> + + <_> + 1 7 18 6 -1. + <_> + 1 7 9 3 2. + <_> + 10 10 9 3 2. + <_> + + <_> + 9 7 2 2 -1. + <_> + 9 7 1 2 2. + <_> + + <_> + 5 9 4 5 -1. + <_> + 7 9 2 5 2. + <_> + + <_> + 7 6 6 3 -1. + <_> + 9 6 2 3 3. + <_> + + <_> + 1 0 18 4 -1. + <_> + 7 0 6 4 3. + <_> + + <_> + 7 15 2 4 -1. + <_> + 7 17 2 2 2. + <_> + + <_> + 1 0 19 9 -1. + <_> + 1 3 19 3 3. + <_> + + <_> + 3 7 3 6 -1. + <_> + 3 9 3 2 3. + <_> + + <_> + 13 7 4 4 -1. + <_> + 15 7 2 2 2. + <_> + 13 9 2 2 2. + <_> + + <_> + 3 7 4 4 -1. + <_> + 3 7 2 2 2. + <_> + 5 9 2 2 2. + <_> + + <_> + 9 6 10 8 -1. + <_> + 9 10 10 4 2. + <_> + + <_> + 3 8 14 12 -1. + <_> + 3 14 14 6 2. + <_> + + <_> + 6 5 10 12 -1. + <_> + 11 5 5 6 2. + <_> + 6 11 5 6 2. + <_> + + <_> + 9 11 2 3 -1. + <_> + 9 12 2 1 3. + <_> + + <_> + 9 5 6 5 -1. + <_> + 9 5 3 5 2. + <_> + + <_> + 9 4 2 4 -1. + <_> + 9 6 2 2 2. + <_> + + <_> + 9 5 6 5 -1. + <_> + 9 5 3 5 2. + <_> + + <_> + 5 5 6 5 -1. + <_> + 8 5 3 5 2. + <_> + + <_> + 11 2 6 1 -1. + <_> + 13 2 2 1 3. + <_> + + <_> + 3 2 6 1 -1. + <_> + 5 2 2 1 3. + <_> + + <_> + 13 5 2 3 -1. + <_> + 13 6 2 1 3. + <_> + + <_> + 0 10 1 4 -1. + <_> + 0 12 1 2 2. + <_> + + <_> + 13 5 2 3 -1. + <_> + 13 6 2 1 3. + <_> + + <_> + 8 18 3 2 -1. + <_> + 9 18 1 2 3. + <_> + + <_> + 6 15 9 2 -1. + <_> + 6 16 9 1 2. + <_> + + <_> + 8 14 4 3 -1. + <_> + 8 15 4 1 3. + <_> + + <_> + 18 4 2 4 -1. + <_> + 18 6 2 2 2. + <_> + + <_> + 5 5 2 3 -1. + <_> + 5 6 2 1 3. + <_> + + <_> + 15 16 3 2 -1. + <_> + 15 17 3 1 2. + <_> + + <_> + 0 0 3 9 -1. + <_> + 0 3 3 3 3. + <_> + + <_> + 9 7 3 3 -1. + <_> + 9 8 3 1 3. + <_> + + <_> + 8 7 3 3 -1. + <_> + 8 8 3 1 3. + <_> + + <_> + 9 5 2 6 -1. + <_> + 9 5 1 6 2. + <_> + + <_> + 8 6 3 4 -1. + <_> + 9 6 1 4 3. + <_> + + <_> + 7 6 8 12 -1. + <_> + 11 6 4 6 2. + <_> + 7 12 4 6 2. + <_> + + <_> + 5 6 8 12 -1. + <_> + 5 6 4 6 2. + <_> + 9 12 4 6 2. + <_> + + <_> + 12 4 3 3 -1. + <_> + 12 5 3 1 3. + <_> + + <_> + 2 16 3 2 -1. + <_> + 2 17 3 1 2. + <_> + + <_> + 12 4 3 3 -1. + <_> + 12 5 3 1 3. + <_> + + <_> + 2 12 6 6 -1. + <_> + 2 14 6 2 3. + <_> + + <_> + 7 13 6 3 -1. + <_> + 7 14 6 1 3. + <_> + + <_> + 6 14 6 3 -1. + <_> + 6 15 6 1 3. + <_> + + <_> + 14 15 5 3 -1. + <_> + 14 16 5 1 3. + <_> + + <_> + 5 4 3 3 -1. + <_> + 5 5 3 1 3. + <_> + + <_> + 14 15 5 3 -1. + <_> + 14 16 5 1 3. + <_> + + <_> + 5 3 6 2 -1. + <_> + 7 3 2 2 3. + <_> + + <_> + 8 15 4 3 -1. + <_> + 8 16 4 1 3. + <_> + + <_> + 1 15 5 3 -1. + <_> + 1 16 5 1 3. + <_> + + <_> + 8 13 4 6 -1. + <_> + 10 13 2 3 2. + <_> + 8 16 2 3 2. + <_> + + <_> + 7 8 3 3 -1. + <_> + 8 8 1 3 3. + <_> + + <_> + 12 0 5 4 -1. + <_> + 12 2 5 2 2. + <_> + + <_> + 0 2 20 2 -1. + <_> + 0 2 10 1 2. + <_> + 10 3 10 1 2. + <_> + + <_> + 1 0 18 4 -1. + <_> + 7 0 6 4 3. + <_> + + <_> + 4 3 6 1 -1. + <_> + 6 3 2 1 3. + <_> + + <_> + 4 18 13 2 -1. + <_> + 4 19 13 1 2. + <_> + + <_> + 2 10 3 6 -1. + <_> + 2 12 3 2 3. + <_> + + <_> + 14 12 6 8 -1. + <_> + 17 12 3 4 2. + <_> + 14 16 3 4 2. + <_> + + <_> + 4 13 10 6 -1. + <_> + 4 13 5 3 2. + <_> + 9 16 5 3 2. + <_> + + <_> + 14 12 1 2 -1. + <_> + 14 13 1 1 2. + <_> + + <_> + 8 13 4 3 -1. + <_> + 8 14 4 1 3. + <_> + + <_> + 14 12 2 2 -1. + <_> + 14 13 2 1 2. + <_> + + <_> + 4 12 2 2 -1. + <_> + 4 13 2 1 2. + <_> + + <_> + 8 12 9 2 -1. + <_> + 8 13 9 1 2. + <_> + + <_> + 9 14 2 3 -1. + <_> + 9 15 2 1 3. + <_> + + <_> + 11 10 3 6 -1. + <_> + 11 13 3 3 2. + <_> + + <_> + 5 6 9 12 -1. + <_> + 5 12 9 6 2. + <_> + + <_> + 11 10 3 6 -1. + <_> + 11 13 3 3 2. + <_> + + <_> + 6 10 3 6 -1. + <_> + 6 13 3 3 2. + <_> + + <_> + 5 4 11 3 -1. + <_> + 5 5 11 1 3. + <_> + + <_> + 7 1 5 10 -1. + <_> + 7 6 5 5 2. + <_> + + <_> + 2 8 18 2 -1. + <_> + 2 9 18 1 2. + <_> + + <_> + 7 17 5 3 -1. + <_> + 7 18 5 1 3. + <_> + + <_> + 5 9 12 1 -1. + <_> + 9 9 4 1 3. + <_> + + <_> + 0 14 6 6 -1. + <_> + 0 14 3 3 2. + <_> + 3 17 3 3 2. + <_> + + <_> + 5 9 12 1 -1. + <_> + 9 9 4 1 3. + <_> + + <_> + 3 9 12 1 -1. + <_> + 7 9 4 1 3. + <_> + + <_> + 14 10 6 7 -1. + <_> + 14 10 3 7 2. + <_> + + <_> + 1 0 16 2 -1. + <_> + 1 1 16 1 2. + <_> + + <_> + 10 9 10 9 -1. + <_> + 10 12 10 3 3. + <_> + + <_> + 0 1 10 2 -1. + <_> + 5 1 5 2 2. + <_> + + <_> + 17 3 2 3 -1. + <_> + 17 4 2 1 3. + <_> + + <_> + 1 3 2 3 -1. + <_> + 1 4 2 1 3. + <_> + + <_> + 9 7 3 6 -1. + <_> + 10 7 1 6 3. + <_> + + <_> + 6 5 4 3 -1. + <_> + 8 5 2 3 2. + <_> + + <_> + 7 5 6 6 -1. + <_> + 9 5 2 6 3. + <_> + + <_> + 3 4 12 12 -1. + <_> + 3 4 6 6 2. + <_> + 9 10 6 6 2. + <_> + + <_> + 9 2 6 15 -1. + <_> + 11 2 2 15 3. + <_> + + <_> + 2 2 6 17 -1. + <_> + 4 2 2 17 3. + <_> + + <_> + 14 10 6 7 -1. + <_> + 14 10 3 7 2. + <_> + + <_> + 0 10 6 7 -1. + <_> + 3 10 3 7 2. + <_> + + <_> + 9 2 6 15 -1. + <_> + 11 2 2 15 3. + <_> + + <_> + 5 2 6 15 -1. + <_> + 7 2 2 15 3. + <_> + + <_> + 17 9 3 6 -1. + <_> + 17 11 3 2 3. + <_> + + <_> + 6 7 6 6 -1. + <_> + 8 7 2 6 3. + <_> + + <_> + 1 10 18 6 -1. + <_> + 10 10 9 3 2. + <_> + 1 13 9 3 2. + <_> + + <_> + 0 9 10 9 -1. + <_> + 0 12 10 3 3. + <_> + + <_> + 8 15 4 3 -1. + <_> + 8 16 4 1 3. + <_> + + <_> + 5 12 3 4 -1. + <_> + 5 14 3 2 2. + <_> + + <_> + 3 3 16 12 -1. + <_> + 3 9 16 6 2. + <_> + + <_> + 1 1 12 12 -1. + <_> + 1 1 6 6 2. + <_> + 7 7 6 6 2. + <_> + + <_> + 10 4 2 4 -1. + <_> + 11 4 1 2 2. + <_> + 10 6 1 2 2. + <_> + + <_> + 0 9 10 2 -1. + <_> + 0 9 5 1 2. + <_> + 5 10 5 1 2. + <_> + + <_> + 9 11 3 3 -1. + <_> + 9 12 3 1 3. + <_> + + <_> + 3 12 9 2 -1. + <_> + 3 13 9 1 2. + <_> + + <_> + 9 9 2 2 -1. + <_> + 9 10 2 1 2. + <_> + + <_> + 3 4 13 6 -1. + <_> + 3 6 13 2 3. + <_> + + <_> + 9 7 6 4 -1. + <_> + 12 7 3 2 2. + <_> + 9 9 3 2 2. + <_> + + <_> + 1 0 6 8 -1. + <_> + 4 0 3 8 2. + <_> + + <_> + 9 5 2 12 -1. + <_> + 9 11 2 6 2. + <_> + + <_> + 4 4 3 10 -1. + <_> + 4 9 3 5 2. + <_> + + <_> + 6 17 8 3 -1. + <_> + 6 18 8 1 3. + <_> + + <_> + 0 5 10 6 -1. + <_> + 0 7 10 2 3. + <_> + + <_> + 13 2 3 2 -1. + <_> + 13 3 3 1 2. + <_> + + <_> + 7 5 4 5 -1. + <_> + 9 5 2 5 2. + <_> + + <_> + 12 14 3 6 -1. + <_> + 12 16 3 2 3. + <_> + + <_> + 1 11 8 2 -1. + <_> + 1 12 8 1 2. + <_> + + <_> + 7 13 6 3 -1. + <_> + 7 14 6 1 3. + <_> + + <_> + 0 5 3 6 -1. + <_> + 0 7 3 2 3. + <_> + + <_> + 13 2 3 2 -1. + <_> + 13 3 3 1 2. + <_> + + <_> + 4 14 4 6 -1. + <_> + 4 14 2 3 2. + <_> + 6 17 2 3 2. + <_> + + <_> + 13 2 3 2 -1. + <_> + 13 3 3 1 2. + <_> + + <_> + 8 2 4 12 -1. + <_> + 8 6 4 4 3. + <_> + + <_> + 14 0 6 8 -1. + <_> + 17 0 3 4 2. + <_> + 14 4 3 4 2. + <_> + + <_> + 7 17 3 2 -1. + <_> + 8 17 1 2 3. + <_> + + <_> + 8 12 4 2 -1. + <_> + 8 13 4 1 2. + <_> + + <_> + 6 0 8 12 -1. + <_> + 6 0 4 6 2. + <_> + 10 6 4 6 2. + <_> + + <_> + 14 0 2 10 -1. + <_> + 15 0 1 5 2. + <_> + 14 5 1 5 2. + <_> + + <_> + 5 3 8 6 -1. + <_> + 5 3 4 3 2. + <_> + 9 6 4 3 2. + <_> + + <_> + 14 0 6 10 -1. + <_> + 17 0 3 5 2. + <_> + 14 5 3 5 2. + <_> + + <_> + 9 14 1 2 -1. + <_> + 9 15 1 1 2. + <_> + + <_> + 15 10 4 3 -1. + <_> + 15 11 4 1 3. + <_> + + <_> + 8 14 2 3 -1. + <_> + 8 15 2 1 3. + <_> + + <_> + 3 13 14 4 -1. + <_> + 10 13 7 2 2. + <_> + 3 15 7 2 2. + <_> + + <_> + 1 10 4 3 -1. + <_> + 1 11 4 1 3. + <_> + + <_> + 9 11 6 1 -1. + <_> + 11 11 2 1 3. + <_> + + <_> + 5 11 6 1 -1. + <_> + 7 11 2 1 3. + <_> + + <_> + 3 5 16 15 -1. + <_> + 3 10 16 5 3. + <_> + + <_> + 6 12 4 2 -1. + <_> + 8 12 2 2 2. + <_> + + <_> + 4 4 12 10 -1. + <_> + 10 4 6 5 2. + <_> + 4 9 6 5 2. + <_> + + <_> + 8 6 3 4 -1. + <_> + 9 6 1 4 3. + <_> + + <_> + 8 12 4 8 -1. + <_> + 10 12 2 4 2. + <_> + 8 16 2 4 2. + <_> + + <_> + 8 14 4 3 -1. + <_> + 8 15 4 1 3. + <_> + + <_> + 12 2 3 2 -1. + <_> + 13 2 1 2 3. + <_> + + <_> + 8 15 3 2 -1. + <_> + 8 16 3 1 2. + <_> + + <_> + 6 0 9 14 -1. + <_> + 9 0 3 14 3. + <_> + + <_> + 9 6 2 3 -1. + <_> + 10 6 1 3 2. + <_> + + <_> + 10 8 2 3 -1. + <_> + 10 9 2 1 3. + <_> + + <_> + 0 9 4 6 -1. + <_> + 0 11 4 2 3. + <_> + + <_> + 6 0 8 2 -1. + <_> + 6 1 8 1 2. + <_> + + <_> + 6 14 7 3 -1. + <_> + 6 15 7 1 3. + <_> + + <_> + 8 10 8 9 -1. + <_> + 8 13 8 3 3. + <_> + + <_> + 5 2 3 2 -1. + <_> + 6 2 1 2 3. + <_> + + <_> + 14 1 6 8 -1. + <_> + 17 1 3 4 2. + <_> + 14 5 3 4 2. + <_> + + <_> + 0 1 6 8 -1. + <_> + 0 1 3 4 2. + <_> + 3 5 3 4 2. + <_> + + <_> + 1 2 18 6 -1. + <_> + 10 2 9 3 2. + <_> + 1 5 9 3 2. + <_> + + <_> + 9 3 2 1 -1. + <_> + 10 3 1 1 2. + <_> + + <_> + 13 2 4 6 -1. + <_> + 15 2 2 3 2. + <_> + 13 5 2 3 2. + <_> + + <_> + 5 4 3 3 -1. + <_> + 5 5 3 1 3. + <_> + + <_> + 13 5 1 3 -1. + <_> + 13 6 1 1 3. + <_> + + <_> + 2 16 5 3 -1. + <_> + 2 17 5 1 3. + <_> + + <_> + 13 2 4 6 -1. + <_> + 15 2 2 3 2. + <_> + 13 5 2 3 2. + <_> + + <_> + 3 2 4 6 -1. + <_> + 3 2 2 3 2. + <_> + 5 5 2 3 2. + <_> + + <_> + 13 5 1 2 -1. + <_> + 13 6 1 1 2. + <_> + + <_> + 5 5 2 2 -1. + <_> + 5 6 2 1 2. + <_> + + <_> + 13 9 2 2 -1. + <_> + 13 9 1 2 2. + <_> + + <_> + 5 9 2 2 -1. + <_> + 6 9 1 2 2. + <_> + + <_> + 13 17 3 2 -1. + <_> + 13 18 3 1 2. + <_> + + <_> + 6 16 4 4 -1. + <_> + 6 16 2 2 2. + <_> + 8 18 2 2 2. + <_> + + <_> + 9 16 2 3 -1. + <_> + 9 17 2 1 3. + <_> + + <_> + 0 13 9 6 -1. + <_> + 0 15 9 2 3. + <_> + + <_> + 9 14 2 6 -1. + <_> + 9 17 2 3 2. + <_> + + <_> + 9 15 2 3 -1. + <_> + 9 16 2 1 3. + <_> + + <_> + 1 10 18 6 -1. + <_> + 1 12 18 2 3. + <_> + + <_> + 8 11 4 2 -1. + <_> + 8 12 4 1 2. + <_> + + <_> + 7 9 6 2 -1. + <_> + 7 10 6 1 2. + <_> + + <_> + 8 8 2 3 -1. + <_> + 8 9 2 1 3. + <_> + + <_> + 17 5 3 4 -1. + <_> + 18 5 1 4 3. + <_> + + <_> + 1 19 18 1 -1. + <_> + 7 19 6 1 3. + <_> + + <_> + 9 0 3 2 -1. + <_> + 10 0 1 2 3. + <_> + + <_> + 1 8 1 6 -1. + <_> + 1 10 1 2 3. + <_> + + <_> + 12 17 8 3 -1. + <_> + 12 17 4 3 2. + <_> + + <_> + 0 5 3 4 -1. + <_> + 1 5 1 4 3. + <_> + + <_> + 9 7 2 3 -1. + <_> + 9 8 2 1 3. + <_> + + <_> + 7 11 2 2 -1. + <_> + 7 11 1 1 2. + <_> + 8 12 1 1 2. + <_> + + <_> + 11 3 2 5 -1. + <_> + 11 3 1 5 2. + <_> + + <_> + 7 3 2 5 -1. + <_> + 8 3 1 5 2. + <_> + + <_> + 15 13 2 3 -1. + <_> + 15 14 2 1 3. + <_> + + <_> + 5 6 2 3 -1. + <_> + 5 7 2 1 3. + <_> + + <_> + 4 19 15 1 -1. + <_> + 9 19 5 1 3. + <_> + + <_> + 1 19 15 1 -1. + <_> + 6 19 5 1 3. + <_> + + <_> + 15 13 2 3 -1. + <_> + 15 14 2 1 3. + <_> + + <_> + 5 0 4 15 -1. + <_> + 7 0 2 15 2. + <_> + + <_> + 9 6 2 5 -1. + <_> + 9 6 1 5 2. + <_> + + <_> + 9 5 2 7 -1. + <_> + 10 5 1 7 2. + <_> + + <_> + 16 11 3 3 -1. + <_> + 16 12 3 1 3. + <_> + + <_> + 1 11 3 3 -1. + <_> + 1 12 3 1 3. + <_> + + <_> + 6 6 8 3 -1. + <_> + 6 7 8 1 3. + <_> + + <_> + 0 15 6 2 -1. + <_> + 0 16 6 1 2. + <_> + + <_> + 1 0 18 6 -1. + <_> + 7 0 6 6 3. + <_> + + <_> + 6 0 3 4 -1. + <_> + 7 0 1 4 3. + <_> + + <_> + 14 10 4 10 -1. + <_> + 16 10 2 5 2. + <_> + 14 15 2 5 2. + <_> + + <_> + 3 2 3 2 -1. + <_> + 4 2 1 2 3. + <_> + + <_> + 11 2 2 2 -1. + <_> + 11 3 2 1 2. + <_> + + <_> + 2 10 4 10 -1. + <_> + 2 10 2 5 2. + <_> + 4 15 2 5 2. + <_> + + <_> + 0 13 20 6 -1. + <_> + 10 13 10 3 2. + <_> + 0 16 10 3 2. + <_> + + <_> + 0 5 2 15 -1. + <_> + 1 5 1 15 2. + <_> + + <_> + 1 7 18 4 -1. + <_> + 10 7 9 2 2. + <_> + 1 9 9 2 2. + <_> + + <_> + 0 0 2 17 -1. + <_> + 1 0 1 17 2. + <_> + + <_> + 2 6 16 6 -1. + <_> + 10 6 8 3 2. + <_> + 2 9 8 3 2. + <_> + + <_> + 8 14 1 3 -1. + <_> + 8 15 1 1 3. + <_> + + <_> + 8 15 4 2 -1. + <_> + 8 16 4 1 2. + <_> + + <_> + 5 2 8 2 -1. + <_> + 5 2 4 1 2. + <_> + 9 3 4 1 2. + <_> + + <_> + 6 11 8 6 -1. + <_> + 6 14 8 3 2. + <_> + + <_> + 9 13 2 2 -1. + <_> + 9 14 2 1 2. + <_> + + <_> + 18 4 2 6 -1. + <_> + 18 6 2 2 3. + <_> + + <_> + 9 12 2 2 -1. + <_> + 9 13 2 1 2. + <_> + + <_> + 18 4 2 6 -1. + <_> + 18 6 2 2 3. + <_> + + <_> + 9 13 1 3 -1. + <_> + 9 14 1 1 3. + <_> + + <_> + 18 4 2 6 -1. + <_> + 18 6 2 2 3. + <_> + + <_> + 0 4 2 6 -1. + <_> + 0 6 2 2 3. + <_> + + <_> + 9 12 3 3 -1. + <_> + 9 13 3 1 3. + <_> + + <_> + 3 13 2 3 -1. + <_> + 3 14 2 1 3. + <_> + + <_> + 13 13 4 3 -1. + <_> + 13 14 4 1 3. + <_> + + <_> + 5 4 3 3 -1. + <_> + 5 5 3 1 3. + <_> + + <_> + 5 2 10 6 -1. + <_> + 5 4 10 2 3. + <_> + + <_> + 3 13 4 3 -1. + <_> + 3 14 4 1 3. + <_> + + <_> + 3 7 15 5 -1. + <_> + 8 7 5 5 3. + <_> + + <_> + 3 7 12 2 -1. + <_> + 7 7 4 2 3. + <_> + + <_> + 10 3 3 9 -1. + <_> + 11 3 1 9 3. + <_> + + <_> + 8 6 4 6 -1. + <_> + 10 6 2 6 2. + <_> + + <_> + 9 7 4 3 -1. + <_> + 9 8 4 1 3. + <_> + + <_> + 0 9 4 9 -1. + <_> + 2 9 2 9 2. + <_> + + <_> + 9 13 3 5 -1. + <_> + 10 13 1 5 3. + <_> + + <_> + 7 7 6 3 -1. + <_> + 9 7 2 3 3. + <_> + + <_> + 9 7 3 5 -1. + <_> + 10 7 1 5 3. + <_> + + <_> + 5 7 8 2 -1. + <_> + 9 7 4 2 2. + <_> + + <_> + 5 9 12 2 -1. + <_> + 9 9 4 2 3. + <_> + + <_> + 5 6 10 3 -1. + <_> + 10 6 5 3 2. + <_> + + <_> + 10 12 3 1 -1. + <_> + 11 12 1 1 3. + <_> + + <_> + 0 1 11 15 -1. + <_> + 0 6 11 5 3. + <_> + + <_> + 1 0 18 6 -1. + <_> + 7 0 6 6 3. + <_> + + <_> + 7 7 6 1 -1. + <_> + 9 7 2 1 3. + <_> + + <_> + 5 16 6 4 -1. + <_> + 5 16 3 2 2. + <_> + 8 18 3 2 2. + <_> + + <_> + 6 5 9 8 -1. + <_> + 6 9 9 4 2. + <_> + + <_> + 5 10 2 6 -1. + <_> + 5 13 2 3 2. + <_> + + <_> + 7 6 8 10 -1. + <_> + 11 6 4 5 2. + <_> + 7 11 4 5 2. + <_> + + <_> + 5 6 8 10 -1. + <_> + 5 6 4 5 2. + <_> + 9 11 4 5 2. + <_> + + <_> + 9 5 2 2 -1. + <_> + 9 6 2 1 2. + <_> + + <_> + 5 12 8 2 -1. + <_> + 5 13 8 1 2. + <_> + + <_> + 10 2 8 2 -1. + <_> + 10 3 8 1 2. + <_> + + <_> + 4 0 2 10 -1. + <_> + 4 0 1 5 2. + <_> + 5 5 1 5 2. + <_> + + <_> + 9 10 2 2 -1. + <_> + 9 11 2 1 2. + <_> + + <_> + 2 8 15 3 -1. + <_> + 2 9 15 1 3. + <_> + + <_> + 8 13 4 3 -1. + <_> + 8 14 4 1 3. + <_> + + <_> + 7 2 3 2 -1. + <_> + 8 2 1 2 3. + <_> + + <_> + 7 13 6 3 -1. + <_> + 7 14 6 1 3. + <_> + + <_> + 9 9 2 2 -1. + <_> + 9 10 2 1 2. + <_> + + <_> + 17 2 3 6 -1. + <_> + 17 4 3 2 3. + <_> + + <_> + 1 5 3 4 -1. + <_> + 2 5 1 4 3. + <_> + + <_> + 14 8 4 6 -1. + <_> + 14 10 4 2 3. + <_> + + <_> + 1 4 3 8 -1. + <_> + 2 4 1 8 3. + <_> + + <_> + 8 13 4 6 -1. + <_> + 8 16 4 3 2. + <_> + + <_> + 3 14 2 2 -1. + <_> + 3 15 2 1 2. + <_> + + <_> + 14 8 4 6 -1. + <_> + 14 10 4 2 3. + <_> + + <_> + 2 8 4 6 -1. + <_> + 2 10 4 2 3. + <_> + + <_> + 10 14 1 6 -1. + <_> + 10 17 1 3 2. + <_> + + <_> + 7 5 3 6 -1. + <_> + 8 5 1 6 3. + <_> + + <_> + 11 2 2 6 -1. + <_> + 12 2 1 3 2. + <_> + 11 5 1 3 2. + <_> + + <_> + 6 6 6 5 -1. + <_> + 8 6 2 5 3. + <_> + + <_> + 17 1 3 6 -1. + <_> + 17 3 3 2 3. + <_> + + <_> + 8 7 3 5 -1. + <_> + 9 7 1 5 3. + <_> + + <_> + 9 18 3 2 -1. + <_> + 10 18 1 2 3. + <_> + + <_> + 8 18 3 2 -1. + <_> + 9 18 1 2 3. + <_> + + <_> + 12 3 5 2 -1. + <_> + 12 4 5 1 2. + <_> + + <_> + 7 1 5 12 -1. + <_> + 7 7 5 6 2. + <_> + + <_> + 1 0 18 4 -1. + <_> + 7 0 6 4 3. + <_> + + <_> + 4 2 2 2 -1. + <_> + 4 3 2 1 2. + <_> + + <_> + 11 14 4 2 -1. + <_> + 13 14 2 1 2. + <_> + 11 15 2 1 2. + <_> + + <_> + 0 2 3 6 -1. + <_> + 0 4 3 2 3. + <_> + + <_> + 9 7 2 3 -1. + <_> + 9 8 2 1 3. + <_> + + <_> + 5 5 1 3 -1. + <_> + 5 6 1 1 3. + <_> + + <_> + 10 10 6 1 -1. + <_> + 10 10 3 1 2. + <_> + + <_> + 4 10 6 1 -1. + <_> + 7 10 3 1 2. + <_> + + <_> + 9 17 3 3 -1. + <_> + 9 18 3 1 3. + <_> + + <_> + 4 14 1 3 -1. + <_> + 4 15 1 1 3. + <_> + + <_> + 12 5 3 3 -1. + <_> + 12 6 3 1 3. + <_> + + <_> + 4 5 12 3 -1. + <_> + 4 6 12 1 3. + <_> + + <_> + 9 8 2 3 -1. + <_> + 9 9 2 1 3. + <_> + + <_> + 4 9 3 3 -1. + <_> + 5 9 1 3 3. + <_> + + <_> + 6 0 9 17 -1. + <_> + 9 0 3 17 3. + <_> + + <_> + 9 12 1 3 -1. + <_> + 9 13 1 1 3. + <_> + + <_> + 9 5 2 15 -1. + <_> + 9 10 2 5 3. + <_> + + <_> + 8 14 2 3 -1. + <_> + 8 15 2 1 3. + <_> + + <_> + 10 14 1 3 -1. + <_> + 10 15 1 1 3. + <_> + + <_> + 7 1 6 5 -1. + <_> + 9 1 2 5 3. + <_> + + <_> + 0 0 20 2 -1. + <_> + 0 0 10 2 2. + <_> + + <_> + 2 13 5 3 -1. + <_> + 2 14 5 1 3. + <_> + + <_> + 9 11 2 3 -1. + <_> + 9 12 2 1 3. + <_> + + <_> + 2 5 9 15 -1. + <_> + 2 10 9 5 3. + <_> + + <_> + 5 0 12 10 -1. + <_> + 11 0 6 5 2. + <_> + 5 5 6 5 2. + <_> + + <_> + 5 1 2 3 -1. + <_> + 6 1 1 3 2. + <_> + + <_> + 10 7 6 1 -1. + <_> + 12 7 2 1 3. + <_> + + <_> + 3 1 2 10 -1. + <_> + 3 1 1 5 2. + <_> + 4 6 1 5 2. + <_> + + <_> + 13 7 2 1 -1. + <_> + 13 7 1 1 2. + <_> + + <_> + 4 13 4 6 -1. + <_> + 4 15 4 2 3. + <_> + + <_> + 13 7 2 1 -1. + <_> + 13 7 1 1 2. + <_> + + <_> + 5 7 2 1 -1. + <_> + 6 7 1 1 2. + <_> + + <_> + 2 12 18 4 -1. + <_> + 11 12 9 2 2. + <_> + 2 14 9 2 2. + <_> + + <_> + 5 7 2 2 -1. + <_> + 5 7 1 1 2. + <_> + 6 8 1 1 2. + <_> + + <_> + 16 3 4 2 -1. + <_> + 16 4 4 1 2. + <_> + + <_> + 0 2 2 18 -1. + <_> + 0 2 1 9 2. + <_> + 1 11 1 9 2. + <_> + + <_> + 1 2 18 4 -1. + <_> + 10 2 9 2 2. + <_> + 1 4 9 2 2. + <_> + + <_> + 9 14 1 3 -1. + <_> + 9 15 1 1 3. + <_> + + <_> + 2 12 18 4 -1. + <_> + 11 12 9 2 2. + <_> + 2 14 9 2 2. + <_> + + <_> + 0 12 18 4 -1. + <_> + 0 12 9 2 2. + <_> + 9 14 9 2 2. + <_> + + <_> + 11 4 5 3 -1. + <_> + 11 5 5 1 3. + <_> + + <_> + 6 4 7 3 -1. + <_> + 6 5 7 1 3. + <_> + + <_> + 13 17 3 3 -1. + <_> + 13 18 3 1 3. + <_> + + <_> + 8 1 3 4 -1. + <_> + 9 1 1 4 3. + <_> + + <_> + 11 4 2 4 -1. + <_> + 11 4 1 4 2. + <_> + + <_> + 0 17 9 3 -1. + <_> + 3 17 3 3 3. + <_> + + <_> + 11 0 2 8 -1. + <_> + 12 0 1 4 2. + <_> + 11 4 1 4 2. + <_> + + <_> + 0 8 6 12 -1. + <_> + 0 8 3 6 2. + <_> + 3 14 3 6 2. + <_> + + <_> + 10 7 4 12 -1. + <_> + 10 13 4 6 2. + <_> + + <_> + 5 3 8 14 -1. + <_> + 5 10 8 7 2. + <_> + + <_> + 14 10 6 1 -1. + <_> + 14 10 3 1 2. + <_> + + <_> + 0 4 10 4 -1. + <_> + 0 6 10 2 2. + <_> + + <_> + 10 0 5 8 -1. + <_> + 10 4 5 4 2. + <_> + + <_> + 8 1 4 8 -1. + <_> + 8 1 2 4 2. + <_> + 10 5 2 4 2. + <_> + + <_> + 9 11 6 1 -1. + <_> + 11 11 2 1 3. + <_> + + <_> + 8 9 3 4 -1. + <_> + 9 9 1 4 3. + <_> + + <_> + 18 4 2 6 -1. + <_> + 18 6 2 2 3. + <_> + + <_> + 8 8 3 4 -1. + <_> + 9 8 1 4 3. + <_> + + <_> + 7 1 13 3 -1. + <_> + 7 2 13 1 3. + <_> + + <_> + 7 13 6 1 -1. + <_> + 9 13 2 1 3. + <_> + + <_> + 12 11 3 6 -1. + <_> + 12 13 3 2 3. + <_> + + <_> + 5 11 6 1 -1. + <_> + 7 11 2 1 3. + <_> + + <_> + 1 4 18 10 -1. + <_> + 10 4 9 5 2. + <_> + 1 9 9 5 2. + <_> + + <_> + 8 6 4 9 -1. + <_> + 8 9 4 3 3. + <_> + + <_> + 8 6 4 3 -1. + <_> + 8 7 4 1 3. + <_> + + <_> + 8 7 3 3 -1. + <_> + 9 7 1 3 3. + <_> + + <_> + 14 15 4 3 -1. + <_> + 14 16 4 1 3. + <_> + + <_> + 5 10 3 10 -1. + <_> + 6 10 1 10 3. + <_> + + <_> + 8 15 4 3 -1. + <_> + 8 16 4 1 3. + <_> + + <_> + 0 8 1 6 -1. + <_> + 0 10 1 2 3. + <_> + + <_> + 10 15 1 3 -1. + <_> + 10 16 1 1 3. + <_> + + <_> + 2 15 4 3 -1. + <_> + 2 16 4 1 3. + <_> + + <_> + 18 3 2 8 -1. + <_> + 19 3 1 4 2. + <_> + 18 7 1 4 2. + <_> + + <_> + 0 3 2 8 -1. + <_> + 0 3 1 4 2. + <_> + 1 7 1 4 2. + <_> + + <_> + 3 7 14 10 -1. + <_> + 10 7 7 5 2. + <_> + 3 12 7 5 2. + <_> + + <_> + 0 7 19 3 -1. + <_> + 0 8 19 1 3. + <_> + + <_> + 12 6 3 3 -1. + <_> + 12 7 3 1 3. + <_> + + <_> + 0 6 1 3 -1. + <_> + 0 7 1 1 3. + <_> + + <_> + 12 6 3 3 -1. + <_> + 12 7 3 1 3. + <_> + + <_> + 5 6 3 3 -1. + <_> + 5 7 3 1 3. + <_> + + <_> + 8 2 4 2 -1. + <_> + 8 3 4 1 2. + <_> + + <_> + 6 3 4 12 -1. + <_> + 8 3 2 12 2. + <_> + + <_> + 13 6 2 3 -1. + <_> + 13 7 2 1 3. + <_> + + <_> + 0 10 20 4 -1. + <_> + 0 12 20 2 2. + <_> + + <_> + 2 0 17 14 -1. + <_> + 2 7 17 7 2. + <_> + + <_> + 0 0 6 10 -1. + <_> + 0 0 3 5 2. + <_> + 3 5 3 5 2. + <_> + + <_> + 14 6 6 4 -1. + <_> + 14 6 3 4 2. + <_> + + <_> + 0 6 6 4 -1. + <_> + 3 6 3 4 2. + <_> + + <_> + 13 2 7 2 -1. + <_> + 13 3 7 1 2. + <_> + + <_> + 0 2 7 2 -1. + <_> + 0 3 7 1 2. + <_> + + <_> + 6 11 14 2 -1. + <_> + 13 11 7 1 2. + <_> + 6 12 7 1 2. + <_> + + <_> + 8 5 2 2 -1. + <_> + 8 5 1 1 2. + <_> + 9 6 1 1 2. + <_> + + <_> + 13 9 2 3 -1. + <_> + 13 9 1 3 2. + <_> + + <_> + 1 1 3 12 -1. + <_> + 2 1 1 12 3. + <_> + + <_> + 17 4 1 3 -1. + <_> + 17 5 1 1 3. + <_> + + <_> + 2 4 1 3 -1. + <_> + 2 5 1 1 3. + <_> + + <_> + 14 5 1 3 -1. + <_> + 14 6 1 1 3. + <_> + + <_> + 7 16 2 3 -1. + <_> + 7 17 2 1 3. + <_> + + <_> + 8 13 4 6 -1. + <_> + 10 13 2 3 2. + <_> + 8 16 2 3 2. + <_> + + <_> + 5 5 1 3 -1. + <_> + 5 6 1 1 3. + <_> + + <_> + 16 0 4 20 -1. + <_> + 16 0 2 20 2. + <_> + + <_> + 5 1 2 6 -1. + <_> + 5 1 1 3 2. + <_> + 6 4 1 3 2. + <_> + + <_> + 5 4 10 4 -1. + <_> + 5 6 10 2 2. + <_> + + <_> + 15 2 4 12 -1. + <_> + 15 2 2 12 2. + <_> + + <_> + 7 6 4 12 -1. + <_> + 7 12 4 6 2. + <_> + + <_> + 14 5 1 8 -1. + <_> + 14 9 1 4 2. + <_> + + <_> + 1 4 14 10 -1. + <_> + 1 4 7 5 2. + <_> + 8 9 7 5 2. + <_> + + <_> + 11 6 6 14 -1. + <_> + 14 6 3 7 2. + <_> + 11 13 3 7 2. + <_> + + <_> + 3 6 6 14 -1. + <_> + 3 6 3 7 2. + <_> + 6 13 3 7 2. + <_> + + <_> + 4 9 15 2 -1. + <_> + 9 9 5 2 3. + <_> + + <_> + 7 14 6 3 -1. + <_> + 7 15 6 1 3. + <_> + + <_> + 6 3 14 4 -1. + <_> + 13 3 7 2 2. + <_> + 6 5 7 2 2. + <_> + + <_> + 1 9 15 2 -1. + <_> + 6 9 5 2 3. + <_> + + <_> + 6 11 8 9 -1. + <_> + 6 14 8 3 3. + <_> + + <_> + 7 4 3 8 -1. + <_> + 8 4 1 8 3. + <_> + + <_> + 14 6 2 6 -1. + <_> + 14 9 2 3 2. + <_> + + <_> + 5 7 6 4 -1. + <_> + 5 7 3 2 2. + <_> + 8 9 3 2 2. + <_> + + <_> + 1 1 18 19 -1. + <_> + 7 1 6 19 3. + <_> + + <_> + 1 2 6 5 -1. + <_> + 4 2 3 5 2. + <_> + + <_> + 12 17 6 2 -1. + <_> + 12 18 6 1 2. + <_> + + <_> + 2 17 6 2 -1. + <_> + 2 18 6 1 2. + <_> + + <_> + 17 3 3 6 -1. + <_> + 17 5 3 2 3. + <_> + + <_> + 8 17 3 3 -1. + <_> + 8 18 3 1 3. + <_> + + <_> + 10 13 2 6 -1. + <_> + 10 16 2 3 2. + <_> + + <_> + 7 13 6 3 -1. + <_> + 7 14 6 1 3. + <_> + + <_> + 17 3 3 6 -1. + <_> + 17 5 3 2 3. + <_> + + <_> + 8 13 2 3 -1. + <_> + 8 14 2 1 3. + <_> + + <_> + 9 3 6 2 -1. + <_> + 11 3 2 2 3. + <_> + + <_> + 0 3 3 6 -1. + <_> + 0 5 3 2 3. + <_> + + <_> + 8 5 4 6 -1. + <_> + 8 7 4 2 3. + <_> + + <_> + 5 5 3 2 -1. + <_> + 5 6 3 1 2. + <_> + + <_> + 10 1 3 4 -1. + <_> + 11 1 1 4 3. + <_> + + <_> + 1 2 5 9 -1. + <_> + 1 5 5 3 3. + <_> + + <_> + 13 6 2 3 -1. + <_> + 13 7 2 1 3. + <_> + + <_> + 0 6 14 3 -1. + <_> + 7 6 7 3 2. + <_> + + <_> + 2 11 18 8 -1. + <_> + 2 15 18 4 2. + <_> + + <_> + 5 6 2 3 -1. + <_> + 5 7 2 1 3. + <_> + + <_> + 10 6 4 2 -1. + <_> + 12 6 2 1 2. + <_> + 10 7 2 1 2. + <_> + + <_> + 6 6 4 2 -1. + <_> + 6 6 2 1 2. + <_> + 8 7 2 1 2. + <_> + + <_> + 10 1 3 4 -1. + <_> + 11 1 1 4 3. + <_> + + <_> + 7 1 2 7 -1. + <_> + 8 1 1 7 2. + <_> + + <_> + 4 2 15 14 -1. + <_> + 4 9 15 7 2. + <_> + + <_> + 8 7 3 2 -1. + <_> + 9 7 1 2 3. + <_> + + <_> + 2 3 18 4 -1. + <_> + 11 3 9 2 2. + <_> + 2 5 9 2 2. + <_> + + <_> + 9 7 2 2 -1. + <_> + 10 7 1 2 2. + <_> + + <_> + 13 9 2 3 -1. + <_> + 13 9 1 3 2. + <_> + + <_> + 5 2 6 2 -1. + <_> + 7 2 2 2 3. + <_> + + <_> + 9 5 2 7 -1. + <_> + 9 5 1 7 2. + <_> + + <_> + 5 9 2 3 -1. + <_> + 6 9 1 3 2. + <_> + + <_> + 6 0 14 18 -1. + <_> + 6 9 14 9 2. + <_> + + <_> + 2 16 6 3 -1. + <_> + 2 17 6 1 3. + <_> + + <_> + 9 7 3 6 -1. + <_> + 10 7 1 6 3. + <_> + + <_> + 7 8 4 3 -1. + <_> + 7 9 4 1 3. + <_> + + <_> + 7 12 6 3 -1. + <_> + 7 13 6 1 3. + <_> + + <_> + 9 12 2 3 -1. + <_> + 9 13 2 1 3. + <_> + + <_> + 7 12 6 2 -1. + <_> + 9 12 2 2 3. + <_> + + <_> + 5 11 4 6 -1. + <_> + 5 14 4 3 2. + <_> + + <_> + 11 12 7 2 -1. + <_> + 11 13 7 1 2. + <_> + + <_> + 6 10 8 6 -1. + <_> + 6 10 4 3 2. + <_> + 10 13 4 3 2. + <_> + + <_> + 11 10 3 4 -1. + <_> + 11 12 3 2 2. + <_> + + <_> + 9 16 2 3 -1. + <_> + 9 17 2 1 3. + <_> + + <_> + 13 3 1 9 -1. + <_> + 13 6 1 3 3. + <_> + + <_> + 1 13 14 6 -1. + <_> + 1 15 14 2 3. + <_> + + <_> + 13 6 1 6 -1. + <_> + 13 9 1 3 2. + <_> + + <_> + 0 4 3 8 -1. + <_> + 1 4 1 8 3. + <_> + + <_> + 18 0 2 18 -1. + <_> + 18 0 1 18 2. + <_> + + <_> + 2 3 6 2 -1. + <_> + 2 4 6 1 2. + <_> + + <_> + 9 0 8 6 -1. + <_> + 9 2 8 2 3. + <_> + + <_> + 6 6 1 6 -1. + <_> + 6 9 1 3 2. + <_> + + <_> + 14 8 6 3 -1. + <_> + 14 9 6 1 3. + <_> + + <_> + 0 0 2 18 -1. + <_> + 1 0 1 18 2. + <_> + + <_> + 1 18 18 2 -1. + <_> + 10 18 9 1 2. + <_> + 1 19 9 1 2. + <_> + + <_> + 3 15 2 2 -1. + <_> + 3 16 2 1 2. + <_> + + <_> + 8 14 5 3 -1. + <_> + 8 15 5 1 3. + <_> + + <_> + 8 14 2 3 -1. + <_> + 8 15 2 1 3. + <_> + + <_> + 12 3 3 3 -1. + <_> + 13 3 1 3 3. + <_> + + <_> + 7 5 6 2 -1. + <_> + 9 5 2 2 3. + <_> + + <_> + 15 5 5 2 -1. + <_> + 15 6 5 1 2. + <_> + + <_> + 0 5 5 2 -1. + <_> + 0 6 5 1 2. + <_> + + <_> + 17 14 1 6 -1. + <_> + 17 17 1 3 2. + <_> + + <_> + 2 9 9 3 -1. + <_> + 5 9 3 3 3. + <_> + + <_> + 12 3 3 3 -1. + <_> + 13 3 1 3 3. + <_> + + <_> + 0 0 4 18 -1. + <_> + 2 0 2 18 2. + <_> + + <_> + 17 6 1 3 -1. + <_> + 17 7 1 1 3. + <_> + + <_> + 2 14 1 6 -1. + <_> + 2 17 1 3 2. + <_> + + <_> + 19 8 1 2 -1. + <_> + 19 9 1 1 2. + <_> + + <_> + 5 3 3 3 -1. + <_> + 6 3 1 3 3. + <_> + + <_> + 9 16 2 3 -1. + <_> + 9 17 2 1 3. + <_> + + <_> + 2 6 1 3 -1. + <_> + 2 7 1 1 3. + <_> + + <_> + 12 4 8 2 -1. + <_> + 16 4 4 1 2. + <_> + 12 5 4 1 2. + <_> + + <_> + 0 4 8 2 -1. + <_> + 0 4 4 1 2. + <_> + 4 5 4 1 2. + <_> + + <_> + 2 16 18 4 -1. + <_> + 2 18 18 2 2. + <_> + + <_> + 7 15 2 4 -1. + <_> + 7 17 2 2 2. + <_> + + <_> + 4 0 14 3 -1. + <_> + 4 1 14 1 3. + <_> + + <_> + 0 0 4 20 -1. + <_> + 2 0 2 20 2. + <_> + + <_> + 12 4 4 8 -1. + <_> + 14 4 2 4 2. + <_> + 12 8 2 4 2. + <_> + + <_> + 6 7 2 2 -1. + <_> + 6 7 1 1 2. + <_> + 7 8 1 1 2. + <_> + + <_> + 10 6 2 3 -1. + <_> + 10 7 2 1 3. + <_> + + <_> + 8 7 3 2 -1. + <_> + 8 8 3 1 2. + <_> + + <_> + 8 2 6 12 -1. + <_> + 8 8 6 6 2. + <_> + + <_> + 4 0 11 12 -1. + <_> + 4 4 11 4 3. + <_> + + <_> + 14 9 6 11 -1. + <_> + 16 9 2 11 3. + <_> + + <_> + 0 14 4 3 -1. + <_> + 0 15 4 1 3. + <_> + + <_> + 9 10 2 3 -1. + <_> + 9 11 2 1 3. + <_> + + <_> + 5 11 3 2 -1. + <_> + 5 12 3 1 2. + <_> + + <_> + 9 15 3 3 -1. + <_> + 10 15 1 3 3. + <_> + + <_> + 8 8 3 4 -1. + <_> + 9 8 1 4 3. + <_> + + <_> + 9 15 3 3 -1. + <_> + 10 15 1 3 3. + <_> + + <_> + 7 7 3 2 -1. + <_> + 8 7 1 2 3. + <_> + + <_> + 2 10 16 4 -1. + <_> + 10 10 8 2 2. + <_> + 2 12 8 2 2. + <_> + + <_> + 2 3 4 17 -1. + <_> + 4 3 2 17 2. + <_> + + <_> + 15 13 2 7 -1. + <_> + 15 13 1 7 2. + <_> + + <_> + 2 2 6 1 -1. + <_> + 5 2 3 1 2. + <_> + + <_> + 5 2 12 4 -1. + <_> + 9 2 4 4 3. + <_> + + <_> + 6 0 8 12 -1. + <_> + 6 0 4 6 2. + <_> + 10 6 4 6 2. + <_> + + <_> + 13 7 2 2 -1. + <_> + 14 7 1 1 2. + <_> + 13 8 1 1 2. + <_> + + <_> + 0 12 20 6 -1. + <_> + 0 14 20 2 3. + <_> + + <_> + 14 7 2 3 -1. + <_> + 14 7 1 3 2. + <_> + + <_> + 0 8 9 12 -1. + <_> + 3 8 3 12 3. + <_> + + <_> + 3 0 16 2 -1. + <_> + 3 0 8 2 2. + <_> + + <_> + 6 15 3 3 -1. + <_> + 6 16 3 1 3. + <_> + + <_> + 8 15 6 3 -1. + <_> + 8 16 6 1 3. + <_> + + <_> + 0 10 1 6 -1. + <_> + 0 12 1 2 3. + <_> + + <_> + 10 9 4 3 -1. + <_> + 10 10 4 1 3. + <_> + + <_> + 9 15 2 3 -1. + <_> + 9 16 2 1 3. + <_> + + <_> + 5 7 10 1 -1. + <_> + 5 7 5 1 2. + <_> + + <_> + 4 0 12 19 -1. + <_> + 10 0 6 19 2. + <_> + + <_> + 0 6 20 6 -1. + <_> + 10 6 10 3 2. + <_> + 0 9 10 3 2. + <_> + + <_> + 3 6 2 2 -1. + <_> + 3 6 1 1 2. + <_> + 4 7 1 1 2. + <_> + + <_> + 15 6 2 2 -1. + <_> + 16 6 1 1 2. + <_> + 15 7 1 1 2. + <_> + + <_> + 3 6 2 2 -1. + <_> + 3 6 1 1 2. + <_> + 4 7 1 1 2. + <_> + + <_> + 14 4 1 12 -1. + <_> + 14 10 1 6 2. + <_> + + <_> + 2 5 16 10 -1. + <_> + 2 5 8 5 2. + <_> + 10 10 8 5 2. + <_> + + <_> + 9 17 3 2 -1. + <_> + 10 17 1 2 3. + <_> + + <_> + 1 4 2 2 -1. + <_> + 1 5 2 1 2. + <_> + + <_> + 5 0 15 5 -1. + <_> + 10 0 5 5 3. + <_> + + <_> + 0 0 15 5 -1. + <_> + 5 0 5 5 3. + <_> + + <_> + 11 2 2 17 -1. + <_> + 11 2 1 17 2. + <_> + + <_> + 7 2 2 17 -1. + <_> + 8 2 1 17 2. + <_> + + <_> + 15 11 2 9 -1. + <_> + 15 11 1 9 2. + <_> + + <_> + 3 11 2 9 -1. + <_> + 4 11 1 9 2. + <_> + + <_> + 5 16 14 4 -1. + <_> + 5 16 7 4 2. + <_> + + <_> + 1 4 18 1 -1. + <_> + 7 4 6 1 3. + <_> + + <_> + 13 7 6 4 -1. + <_> + 16 7 3 2 2. + <_> + 13 9 3 2 2. + <_> + + <_> + 9 8 2 12 -1. + <_> + 9 12 2 4 3. + <_> + + <_> + 12 1 6 6 -1. + <_> + 12 3 6 2 3. + <_> + + <_> + 5 2 6 6 -1. + <_> + 5 2 3 3 2. + <_> + 8 5 3 3 2. + <_> + + <_> + 9 16 6 4 -1. + <_> + 12 16 3 2 2. + <_> + 9 18 3 2 2. + <_> + + <_> + 1 2 18 3 -1. + <_> + 7 2 6 3 3. + <_> + + <_> + 7 4 9 10 -1. + <_> + 7 9 9 5 2. + <_> + + <_> + 5 9 4 4 -1. + <_> + 7 9 2 4 2. + <_> + + <_> + 11 10 3 6 -1. + <_> + 11 13 3 3 2. + <_> + + <_> + 7 11 5 3 -1. + <_> + 7 12 5 1 3. + <_> + + <_> + 7 11 6 6 -1. + <_> + 10 11 3 3 2. + <_> + 7 14 3 3 2. + <_> + + <_> + 0 0 10 9 -1. + <_> + 0 3 10 3 3. + <_> + + <_> + 13 14 1 6 -1. + <_> + 13 16 1 2 3. + <_> + + <_> + 0 2 3 6 -1. + <_> + 0 4 3 2 3. + <_> + + <_> + 8 14 4 3 -1. + <_> + 8 15 4 1 3. + <_> + + <_> + 6 14 1 6 -1. + <_> + 6 16 1 2 3. + <_> + + <_> + 9 15 2 3 -1. + <_> + 9 16 2 1 3. + <_> + + <_> + 6 4 3 3 -1. + <_> + 7 4 1 3 3. + <_> + + <_> + 9 0 11 3 -1. + <_> + 9 1 11 1 3. + <_> + + <_> + 0 6 20 3 -1. + <_> + 0 7 20 1 3. + <_> + + <_> + 10 1 1 2 -1. + <_> + 10 2 1 1 2. + <_> + + <_> + 9 6 2 6 -1. + <_> + 10 6 1 6 2. + <_> + + <_> + 5 8 12 1 -1. + <_> + 9 8 4 1 3. + <_> + + <_> + 3 8 12 1 -1. + <_> + 7 8 4 1 3. + <_> + + <_> + 9 7 3 5 -1. + <_> + 10 7 1 5 3. + <_> + + <_> + 3 9 6 2 -1. + <_> + 6 9 3 2 2. + <_> + + <_> + 12 9 3 3 -1. + <_> + 12 10 3 1 3. + <_> + + <_> + 7 0 6 1 -1. + <_> + 9 0 2 1 3. + <_> + + <_> + 12 9 3 3 -1. + <_> + 12 10 3 1 3. + <_> + + <_> + 7 10 2 1 -1. + <_> + 8 10 1 1 2. + <_> + + <_> + 6 4 9 13 -1. + <_> + 9 4 3 13 3. + <_> + + <_> + 6 8 4 2 -1. + <_> + 6 9 4 1 2. + <_> + + <_> + 16 2 4 6 -1. + <_> + 16 2 2 6 2. + <_> + + <_> + 0 17 6 3 -1. + <_> + 0 18 6 1 3. + <_> + + <_> + 10 10 3 10 -1. + <_> + 10 15 3 5 2. + <_> + + <_> + 8 7 3 5 -1. + <_> + 9 7 1 5 3. + <_> + + <_> + 10 4 4 3 -1. + <_> + 10 4 2 3 2. + <_> + + <_> + 8 4 3 8 -1. + <_> + 9 4 1 8 3. + <_> + + <_> + 6 6 9 13 -1. + <_> + 9 6 3 13 3. + <_> + + <_> + 6 0 8 12 -1. + <_> + 6 0 4 6 2. + <_> + 10 6 4 6 2. + <_> + + <_> + 14 2 6 8 -1. + <_> + 16 2 2 8 3. + <_> + + <_> + 6 0 3 6 -1. + <_> + 7 0 1 6 3. + <_> + + <_> + 14 2 6 8 -1. + <_> + 16 2 2 8 3. + <_> + + <_> + 0 5 6 6 -1. + <_> + 0 8 6 3 2. + <_> + + <_> + 9 12 6 2 -1. + <_> + 12 12 3 1 2. + <_> + 9 13 3 1 2. + <_> + + <_> + 8 17 3 2 -1. + <_> + 9 17 1 2 3. + <_> + + <_> + 11 6 2 2 -1. + <_> + 12 6 1 1 2. + <_> + 11 7 1 1 2. + <_> + + <_> + 1 9 18 2 -1. + <_> + 7 9 6 2 3. + <_> + + <_> + 11 6 2 2 -1. + <_> + 12 6 1 1 2. + <_> + 11 7 1 1 2. + <_> + + <_> + 3 4 12 8 -1. + <_> + 7 4 4 8 3. + <_> + + <_> + 13 11 5 3 -1. + <_> + 13 12 5 1 3. + <_> + + <_> + 9 10 2 3 -1. + <_> + 9 11 2 1 3. + <_> + + <_> + 14 7 2 3 -1. + <_> + 14 7 1 3 2. + <_> + + <_> + 5 4 1 3 -1. + <_> + 5 5 1 1 3. + <_> + + <_> + 13 4 2 3 -1. + <_> + 13 5 2 1 3. + <_> + + <_> + 5 4 2 3 -1. + <_> + 5 5 2 1 3. + <_> + + <_> + 9 8 2 3 -1. + <_> + 9 9 2 1 3. + <_> + + <_> + 8 9 2 2 -1. + <_> + 8 10 2 1 2. + <_> + + <_> + 15 14 1 4 -1. + <_> + 15 16 1 2 2. + <_> + + <_> + 3 12 2 2 -1. + <_> + 3 13 2 1 2. + <_> + + <_> + 12 15 2 2 -1. + <_> + 13 15 1 1 2. + <_> + 12 16 1 1 2. + <_> + + <_> + 9 13 2 2 -1. + <_> + 9 14 2 1 2. + <_> + + <_> + 4 11 14 9 -1. + <_> + 4 14 14 3 3. + <_> + + <_> + 7 13 4 3 -1. + <_> + 7 14 4 1 3. + <_> + + <_> + 15 14 1 4 -1. + <_> + 15 16 1 2 2. + <_> + + <_> + 4 14 1 4 -1. + <_> + 4 16 1 2 2. + <_> + + <_> + 14 0 6 13 -1. + <_> + 16 0 2 13 3. + <_> + + <_> + 4 1 2 12 -1. + <_> + 4 1 1 6 2. + <_> + 5 7 1 6 2. + <_> + + <_> + 11 14 6 6 -1. + <_> + 14 14 3 3 2. + <_> + 11 17 3 3 2. + <_> + + <_> + 3 14 6 6 -1. + <_> + 3 14 3 3 2. + <_> + 6 17 3 3 2. + <_> + + <_> + 14 17 3 2 -1. + <_> + 14 18 3 1 2. + <_> + + <_> + 3 17 3 2 -1. + <_> + 3 18 3 1 2. + <_> + + <_> + 14 0 6 13 -1. + <_> + 16 0 2 13 3. + <_> + + <_> + 0 0 6 13 -1. + <_> + 2 0 2 13 3. + <_> + + <_> + 10 10 7 6 -1. + <_> + 10 12 7 2 3. + <_> + + <_> + 6 15 2 2 -1. + <_> + 6 15 1 1 2. + <_> + 7 16 1 1 2. + <_> + + <_> + 6 11 8 6 -1. + <_> + 10 11 4 3 2. + <_> + 6 14 4 3 2. + <_> + + <_> + 7 6 2 2 -1. + <_> + 7 6 1 1 2. + <_> + 8 7 1 1 2. + <_> + + <_> + 2 2 16 6 -1. + <_> + 10 2 8 3 2. + <_> + 2 5 8 3 2. + <_> + + <_> + 5 4 3 3 -1. + <_> + 5 5 3 1 3. + <_> + + <_> + 11 7 3 10 -1. + <_> + 11 12 3 5 2. + <_> + + <_> + 6 7 3 10 -1. + <_> + 6 12 3 5 2. + <_> + + <_> + 10 7 3 2 -1. + <_> + 11 7 1 2 3. + <_> + + <_> + 8 12 4 2 -1. + <_> + 8 13 4 1 2. + <_> + + <_> + 10 1 1 3 -1. + <_> + 10 2 1 1 3. + <_> + + <_> + 1 2 4 18 -1. + <_> + 1 2 2 9 2. + <_> + 3 11 2 9 2. + <_> + + <_> + 12 4 4 12 -1. + <_> + 12 10 4 6 2. + <_> + + <_> + 0 0 1 6 -1. + <_> + 0 2 1 2 3. + <_> + + <_> + 9 11 2 3 -1. + <_> + 9 12 2 1 3. + <_> + + <_> + 8 7 4 3 -1. + <_> + 8 8 4 1 3. + <_> + + <_> + 10 7 3 2 -1. + <_> + 11 7 1 2 3. + <_> + + <_> + 7 7 3 2 -1. + <_> + 8 7 1 2 3. + <_> + + <_> + 9 4 6 1 -1. + <_> + 11 4 2 1 3. + <_> + + <_> + 8 7 2 3 -1. + <_> + 9 7 1 3 2. + <_> + + <_> + 12 7 8 6 -1. + <_> + 16 7 4 3 2. + <_> + 12 10 4 3 2. + <_> + + <_> + 0 7 8 6 -1. + <_> + 0 7 4 3 2. + <_> + 4 10 4 3 2. + <_> + + <_> + 18 2 2 10 -1. + <_> + 19 2 1 5 2. + <_> + 18 7 1 5 2. + <_> + + <_> + 0 2 6 4 -1. + <_> + 3 2 3 4 2. + <_> + + <_> + 9 4 6 1 -1. + <_> + 11 4 2 1 3. + <_> + + <_> + 7 15 2 2 -1. + <_> + 7 15 1 1 2. + <_> + 8 16 1 1 2. + <_> + + <_> + 11 13 1 6 -1. + <_> + 11 16 1 3 2. + <_> + + <_> + 8 13 1 6 -1. + <_> + 8 16 1 3 2. + <_> + + <_> + 14 3 2 1 -1. + <_> + 14 3 1 1 2. + <_> + + <_> + 8 15 2 3 -1. + <_> + 8 16 2 1 3. + <_> + + <_> + 12 15 7 4 -1. + <_> + 12 17 7 2 2. + <_> + + <_> + 4 14 12 3 -1. + <_> + 4 15 12 1 3. + <_> + + <_> + 10 3 3 2 -1. + <_> + 11 3 1 2 3. + <_> + + <_> + 4 12 2 2 -1. + <_> + 4 13 2 1 2. + <_> + + <_> + 10 11 4 6 -1. + <_> + 10 14 4 3 2. + <_> + + <_> + 7 13 2 2 -1. + <_> + 7 13 1 1 2. + <_> + 8 14 1 1 2. + <_> + + <_> + 4 11 14 4 -1. + <_> + 11 11 7 2 2. + <_> + 4 13 7 2 2. + <_> + + <_> + 1 18 18 2 -1. + <_> + 7 18 6 2 3. + <_> + + <_> + 11 18 2 2 -1. + <_> + 12 18 1 1 2. + <_> + 11 19 1 1 2. + <_> + + <_> + 7 18 2 2 -1. + <_> + 7 18 1 1 2. + <_> + 8 19 1 1 2. + <_> + + <_> + 12 18 8 2 -1. + <_> + 12 19 8 1 2. + <_> + + <_> + 7 14 6 2 -1. + <_> + 7 15 6 1 2. + <_> + + <_> + 8 12 4 8 -1. + <_> + 10 12 2 4 2. + <_> + 8 16 2 4 2. + <_> + + <_> + 4 9 3 3 -1. + <_> + 4 10 3 1 3. + <_> + + <_> + 7 10 6 2 -1. + <_> + 9 10 2 2 3. + <_> + + <_> + 5 0 4 15 -1. + <_> + 7 0 2 15 2. + <_> + + <_> + 8 6 12 14 -1. + <_> + 12 6 4 14 3. + <_> + + <_> + 5 16 3 3 -1. + <_> + 5 17 3 1 3. + <_> + + <_> + 8 1 12 19 -1. + <_> + 12 1 4 19 3. + <_> + + <_> + 3 0 3 2 -1. + <_> + 3 1 3 1 2. + <_> + + <_> + 10 12 4 5 -1. + <_> + 10 12 2 5 2. + <_> + + <_> + 6 12 4 5 -1. + <_> + 8 12 2 5 2. + <_> + + <_> + 11 11 2 2 -1. + <_> + 12 11 1 1 2. + <_> + 11 12 1 1 2. + <_> + + <_> + 0 2 3 6 -1. + <_> + 0 4 3 2 3. + <_> + + <_> + 11 11 2 2 -1. + <_> + 12 11 1 1 2. + <_> + 11 12 1 1 2. + <_> + + <_> + 7 6 4 10 -1. + <_> + 7 11 4 5 2. + <_> + + <_> + 11 11 2 2 -1. + <_> + 12 11 1 1 2. + <_> + 11 12 1 1 2. + <_> + + <_> + 2 13 5 2 -1. + <_> + 2 14 5 1 2. + <_> + + <_> + 11 11 2 2 -1. + <_> + 12 11 1 1 2. + <_> + 11 12 1 1 2. + <_> + + <_> + 7 11 2 2 -1. + <_> + 7 11 1 1 2. + <_> + 8 12 1 1 2. + <_> + + <_> + 14 13 3 3 -1. + <_> + 14 14 3 1 3. + <_> + + <_> + 3 13 3 3 -1. + <_> + 3 14 3 1 3. + <_> + + <_> + 9 14 2 3 -1. + <_> + 9 15 2 1 3. + <_> + + <_> + 8 7 3 3 -1. + <_> + 8 8 3 1 3. + <_> + + <_> + 13 5 3 3 -1. + <_> + 13 6 3 1 3. + <_> + + <_> + 0 9 5 3 -1. + <_> + 0 10 5 1 3. + <_> + + <_> + 13 5 3 3 -1. + <_> + 13 6 3 1 3. + <_> + + <_> + 9 12 2 8 -1. + <_> + 9 12 1 4 2. + <_> + 10 16 1 4 2. + <_> + + <_> + 11 7 2 2 -1. + <_> + 12 7 1 1 2. + <_> + 11 8 1 1 2. + <_> + + <_> + 0 16 6 4 -1. + <_> + 3 16 3 4 2. + <_> + + <_> + 10 6 2 3 -1. + <_> + 10 7 2 1 3. + <_> + + <_> + 9 5 2 6 -1. + <_> + 9 7 2 2 3. + <_> + + <_> + 12 15 8 4 -1. + <_> + 12 15 4 4 2. + <_> + + <_> + 0 14 8 6 -1. + <_> + 4 14 4 6 2. + <_> + + <_> + 9 0 3 2 -1. + <_> + 10 0 1 2 3. + <_> + + <_> + 4 15 4 2 -1. + <_> + 6 15 2 2 2. + <_> + + <_> + 12 7 3 13 -1. + <_> + 13 7 1 13 3. + <_> + + <_> + 5 7 3 13 -1. + <_> + 6 7 1 13 3. + <_> + + <_> + 9 6 3 9 -1. + <_> + 9 9 3 3 3. + <_> + + <_> + 4 4 7 12 -1. + <_> + 4 10 7 6 2. + <_> + + <_> + 12 12 2 2 -1. + <_> + 13 12 1 1 2. + <_> + 12 13 1 1 2. + <_> + + <_> + 6 12 2 2 -1. + <_> + 6 12 1 1 2. + <_> + 7 13 1 1 2. + <_> + + <_> + 8 9 4 2 -1. + <_> + 10 9 2 1 2. + <_> + 8 10 2 1 2. + <_> + + <_> + 3 6 2 2 -1. + <_> + 3 6 1 1 2. + <_> + 4 7 1 1 2. + <_> + + <_> + 16 6 3 2 -1. + <_> + 16 7 3 1 2. + <_> + + <_> + 0 7 19 4 -1. + <_> + 0 9 19 2 2. + <_> + + <_> + 10 2 10 1 -1. + <_> + 10 2 5 1 2. + <_> + + <_> + 9 4 2 12 -1. + <_> + 9 10 2 6 2. + <_> + + <_> + 12 18 4 1 -1. + <_> + 12 18 2 1 2. + <_> + + <_> + 1 7 6 4 -1. + <_> + 1 7 3 2 2. + <_> + 4 9 3 2 2. + <_> + + <_> + 12 0 6 13 -1. + <_> + 14 0 2 13 3. + <_> + + <_> + 2 0 6 13 -1. + <_> + 4 0 2 13 3. + <_> + + <_> + 10 5 8 8 -1. + <_> + 10 9 8 4 2. + <_> + + <_> + 8 3 2 5 -1. + <_> + 9 3 1 5 2. + <_> + + <_> + 8 4 9 1 -1. + <_> + 11 4 3 1 3. + <_> + + <_> + 3 4 9 1 -1. + <_> + 6 4 3 1 3. + <_> + + <_> + 1 0 18 10 -1. + <_> + 7 0 6 10 3. + <_> + + <_> + 7 17 5 3 -1. + <_> + 7 18 5 1 3. + <_> + + <_> + 7 11 6 1 -1. + <_> + 9 11 2 1 3. + <_> + + <_> + 2 2 3 2 -1. + <_> + 2 3 3 1 2. + <_> + + <_> + 8 12 4 2 -1. + <_> + 8 13 4 1 2. + <_> + + <_> + 6 10 3 6 -1. + <_> + 6 13 3 3 2. + <_> + + <_> + 11 4 2 4 -1. + <_> + 11 4 1 4 2. + <_> + + <_> + 7 4 2 4 -1. + <_> + 8 4 1 4 2. + <_> + + <_> + 9 6 2 4 -1. + <_> + 9 6 1 4 2. + <_> + + <_> + 6 13 8 3 -1. + <_> + 6 14 8 1 3. + <_> + + <_> + 9 15 3 4 -1. + <_> + 10 15 1 4 3. + <_> + + <_> + 9 2 2 17 -1. + <_> + 10 2 1 17 2. + <_> + + <_> + 7 0 6 1 -1. + <_> + 9 0 2 1 3. + <_> + + <_> + 8 15 3 4 -1. + <_> + 9 15 1 4 3. + <_> + + <_> + 7 13 7 3 -1. + <_> + 7 14 7 1 3. + <_> + + <_> + 8 16 3 3 -1. + <_> + 9 16 1 3 3. + <_> + + <_> + 6 2 8 10 -1. + <_> + 6 7 8 5 2. + <_> + + <_> + 2 5 8 8 -1. + <_> + 2 9 8 4 2. + <_> + + <_> + 14 16 2 2 -1. + <_> + 14 17 2 1 2. + <_> + + <_> + 4 16 2 2 -1. + <_> + 4 17 2 1 2. + <_> + + <_> + 10 11 4 6 -1. + <_> + 10 14 4 3 2. + <_> + + <_> + 6 11 4 6 -1. + <_> + 6 14 4 3 2. + <_> + + <_> + 10 14 1 3 -1. + <_> + 10 15 1 1 3. + <_> + + <_> + 8 14 4 3 -1. + <_> + 8 15 4 1 3. + <_> + + <_> + 10 0 4 6 -1. + <_> + 12 0 2 3 2. + <_> + 10 3 2 3 2. + <_> + + <_> + 0 3 20 2 -1. + <_> + 0 4 20 1 2. + <_> + + <_> + 12 0 8 2 -1. + <_> + 16 0 4 1 2. + <_> + 12 1 4 1 2. + <_> + + <_> + 2 12 10 8 -1. + <_> + 2 16 10 4 2. + <_> + + <_> + 17 7 2 10 -1. + <_> + 18 7 1 5 2. + <_> + 17 12 1 5 2. + <_> + + <_> + 1 7 2 10 -1. + <_> + 1 7 1 5 2. + <_> + 2 12 1 5 2. + <_> + + <_> + 15 10 3 6 -1. + <_> + 15 12 3 2 3. + <_> + + <_> + 4 4 6 2 -1. + <_> + 6 4 2 2 3. + <_> + + <_> + 0 5 20 6 -1. + <_> + 0 7 20 2 3. + <_> + + <_> + 0 0 8 2 -1. + <_> + 0 0 4 1 2. + <_> + 4 1 4 1 2. + <_> + + <_> + 1 0 18 4 -1. + <_> + 7 0 6 4 3. + <_> + + <_> + 1 13 6 2 -1. + <_> + 1 14 6 1 2. + <_> + + <_> + 10 8 3 4 -1. + <_> + 11 8 1 4 3. + <_> + + <_> + 6 1 6 1 -1. + <_> + 8 1 2 1 3. + <_> + + <_> + 8 14 4 3 -1. + <_> + 8 15 4 1 3. + <_> + + <_> + 1 6 18 2 -1. + <_> + 10 6 9 2 2. + <_> + + <_> + 15 11 1 2 -1. + <_> + 15 12 1 1 2. + <_> + + <_> + 6 5 1 2 -1. + <_> + 6 6 1 1 2. + <_> + + <_> + 13 4 1 3 -1. + <_> + 13 5 1 1 3. + <_> + + <_> + 2 15 1 2 -1. + <_> + 2 16 1 1 2. + <_> + + <_> + 12 4 4 3 -1. + <_> + 12 5 4 1 3. + <_> + + <_> + 0 0 7 3 -1. + <_> + 0 1 7 1 3. + <_> + + <_> + 9 12 6 2 -1. + <_> + 9 12 3 2 2. + <_> + + <_> + 5 4 2 3 -1. + <_> + 5 5 2 1 3. + <_> + + <_> + 18 4 2 3 -1. + <_> + 18 5 2 1 3. + <_> + + <_> + 3 0 8 6 -1. + <_> + 3 2 8 2 3. + <_> + + <_> + 0 2 20 6 -1. + <_> + 10 2 10 3 2. + <_> + 0 5 10 3 2. + <_> + + <_> + 4 7 2 4 -1. + <_> + 5 7 1 4 2. + <_> + + <_> + 3 10 15 2 -1. + <_> + 8 10 5 2 3. + <_> + + <_> + 3 0 12 11 -1. + <_> + 9 0 6 11 2. + <_> + + <_> + 13 0 2 6 -1. + <_> + 13 0 1 6 2. + <_> + + <_> + 0 19 2 1 -1. + <_> + 1 19 1 1 2. + <_> + + <_> + 16 10 4 10 -1. + <_> + 18 10 2 5 2. + <_> + 16 15 2 5 2. + <_> + + <_> + 4 8 10 3 -1. + <_> + 4 9 10 1 3. + <_> + + <_> + 14 12 3 3 -1. + <_> + 14 13 3 1 3. + <_> + + <_> + 0 10 4 10 -1. + <_> + 0 10 2 5 2. + <_> + 2 15 2 5 2. + <_> + + <_> + 18 3 2 6 -1. + <_> + 18 5 2 2 3. + <_> + + <_> + 6 6 1 3 -1. + <_> + 6 7 1 1 3. + <_> + + <_> + 7 7 7 2 -1. + <_> + 7 8 7 1 2. + <_> + + <_> + 0 3 2 6 -1. + <_> + 0 5 2 2 3. + <_> + + <_> + 11 1 3 1 -1. + <_> + 12 1 1 1 3. + <_> + + <_> + 5 0 2 6 -1. + <_> + 6 0 1 6 2. + <_> + + <_> + 1 1 18 14 -1. + <_> + 7 1 6 14 3. + <_> + + <_> + 4 6 8 3 -1. + <_> + 8 6 4 3 2. + <_> + + <_> + 9 12 6 2 -1. + <_> + 9 12 3 2 2. + <_> + + <_> + 5 12 6 2 -1. + <_> + 8 12 3 2 2. + <_> + + <_> + 10 7 3 5 -1. + <_> + 11 7 1 5 3. + <_> + + <_> + 7 7 3 5 -1. + <_> + 8 7 1 5 3. + <_> + + <_> + 13 0 3 10 -1. + <_> + 14 0 1 10 3. + <_> + + <_> + 4 11 3 2 -1. + <_> + 4 12 3 1 2. + <_> + + <_> + 17 3 3 6 -1. + <_> + 18 3 1 6 3. + <_> + + <_> + 1 8 18 10 -1. + <_> + 1 13 18 5 2. + <_> + + <_> + 13 0 3 10 -1. + <_> + 14 0 1 10 3. + <_> + + <_> + 9 14 2 3 -1. + <_> + 9 15 2 1 3. + <_> + + <_> + 16 3 3 7 -1. + <_> + 17 3 1 7 3. + <_> + + <_> + 4 0 3 10 -1. + <_> + 5 0 1 10 3. + <_> + + <_> + 16 3 3 7 -1. + <_> + 17 3 1 7 3. + <_> + + <_> + 0 9 1 2 -1. + <_> + 0 10 1 1 2. + <_> + + <_> + 18 1 2 10 -1. + <_> + 18 1 1 10 2. + <_> + + <_> + 0 1 2 10 -1. + <_> + 1 1 1 10 2. + <_> + + <_> + 10 16 3 4 -1. + <_> + 11 16 1 4 3. + <_> + + <_> + 2 8 3 3 -1. + <_> + 3 8 1 3 3. + <_> + + <_> + 11 0 2 6 -1. + <_> + 12 0 1 3 2. + <_> + 11 3 1 3 2. + <_> + + <_> + 7 0 2 6 -1. + <_> + 7 0 1 3 2. + <_> + 8 3 1 3 2. + <_> + + <_> + 16 3 3 7 -1. + <_> + 17 3 1 7 3. + <_> + + <_> + 1 3 3 7 -1. + <_> + 2 3 1 7 3. + <_> + + <_> + 14 1 6 16 -1. + <_> + 16 1 2 16 3. + <_> + + <_> + 0 1 6 16 -1. + <_> + 2 1 2 16 3. + <_> + + <_> + 2 0 16 8 -1. + <_> + 10 0 8 4 2. + <_> + 2 4 8 4 2. + <_> + + <_> + 6 8 5 3 -1. + <_> + 6 9 5 1 3. + <_> + + <_> + 9 7 3 3 -1. + <_> + 10 7 1 3 3. + <_> + + <_> + 8 8 4 3 -1. + <_> + 8 9 4 1 3. + <_> + + <_> + 9 6 2 4 -1. + <_> + 9 6 1 4 2. + <_> + + <_> + 0 7 15 1 -1. + <_> + 5 7 5 1 3. + <_> + + <_> + 8 2 7 9 -1. + <_> + 8 5 7 3 3. + <_> + + <_> + 1 7 16 4 -1. + <_> + 1 7 8 2 2. + <_> + 9 9 8 2 2. + <_> + + <_> + 6 12 8 2 -1. + <_> + 6 13 8 1 2. + <_> + + <_> + 8 11 3 3 -1. + <_> + 8 12 3 1 3. + <_> + + <_> + 4 5 14 10 -1. + <_> + 11 5 7 5 2. + <_> + 4 10 7 5 2. + <_> + + <_> + 4 12 3 2 -1. + <_> + 4 13 3 1 2. + <_> + + <_> + 9 11 6 1 -1. + <_> + 11 11 2 1 3. + <_> + + <_> + 4 9 7 6 -1. + <_> + 4 11 7 2 3. + <_> + + <_> + 7 10 6 3 -1. + <_> + 7 11 6 1 3. + <_> + + <_> + 9 11 2 2 -1. + <_> + 9 12 2 1 2. + <_> + + <_> + 0 5 20 6 -1. + <_> + 0 7 20 2 3. + <_> + + <_> + 6 4 6 1 -1. + <_> + 8 4 2 1 3. + <_> + + <_> + 9 11 6 1 -1. + <_> + 11 11 2 1 3. + <_> + + <_> + 5 11 6 1 -1. + <_> + 7 11 2 1 3. + <_> + + <_> + 10 16 3 4 -1. + <_> + 11 16 1 4 3. + <_> + + <_> + 8 7 3 3 -1. + <_> + 9 7 1 3 3. + <_> + + <_> + 2 12 16 8 -1. + <_> + 2 16 16 4 2. + <_> + + <_> + 0 15 15 2 -1. + <_> + 0 16 15 1 2. + <_> + + <_> + 15 4 5 6 -1. + <_> + 15 6 5 2 3. + <_> + + <_> + 9 5 2 4 -1. + <_> + 10 5 1 4 2. + <_> + + <_> + 8 10 9 6 -1. + <_> + 8 12 9 2 3. + <_> + + <_> + 2 19 15 1 -1. + <_> + 7 19 5 1 3. + <_> + + <_> + 10 16 3 4 -1. + <_> + 11 16 1 4 3. + <_> + + <_> + 0 15 20 4 -1. + <_> + 0 17 20 2 2. + <_> + + <_> + 10 16 3 4 -1. + <_> + 11 16 1 4 3. + <_> + + <_> + 7 16 3 4 -1. + <_> + 8 16 1 4 3. + <_> + + <_> + 9 16 3 3 -1. + <_> + 9 17 3 1 3. + <_> + + <_> + 8 11 4 6 -1. + <_> + 8 14 4 3 2. + <_> + + <_> + 9 6 2 12 -1. + <_> + 9 10 2 4 3. + <_> + + <_> + 8 17 4 3 -1. + <_> + 8 18 4 1 3. + <_> + + <_> + 9 18 8 2 -1. + <_> + 13 18 4 1 2. + <_> + 9 19 4 1 2. + <_> + + <_> + 1 18 8 2 -1. + <_> + 1 19 8 1 2. + <_> + + <_> + 13 5 6 15 -1. + <_> + 15 5 2 15 3. + <_> + + <_> + 9 8 2 2 -1. + <_> + 9 9 2 1 2. + <_> + + <_> + 9 5 2 3 -1. + <_> + 9 5 1 3 2. + <_> + + <_> + 1 5 6 15 -1. + <_> + 3 5 2 15 3. + <_> + + <_> + 4 1 14 8 -1. + <_> + 11 1 7 4 2. + <_> + 4 5 7 4 2. + <_> + + <_> + 2 4 4 16 -1. + <_> + 2 4 2 8 2. + <_> + 4 12 2 8 2. + <_> + + <_> + 12 4 3 12 -1. + <_> + 12 10 3 6 2. + <_> + + <_> + 4 5 10 12 -1. + <_> + 4 5 5 6 2. + <_> + 9 11 5 6 2. + <_> + + <_> + 9 14 2 3 -1. + <_> + 9 15 2 1 3. + <_> + + <_> + 5 4 2 3 -1. + <_> + 5 5 2 1 3. + <_> + + <_> + 12 2 4 10 -1. + <_> + 14 2 2 5 2. + <_> + 12 7 2 5 2. + <_> + + <_> + 6 4 7 3 -1. + <_> + 6 5 7 1 3. + <_> + + <_> + 2 0 18 2 -1. + <_> + 11 0 9 1 2. + <_> + 2 1 9 1 2. + <_> + + <_> + 0 0 18 2 -1. + <_> + 0 0 9 1 2. + <_> + 9 1 9 1 2. + <_> + + <_> + 13 13 4 6 -1. + <_> + 15 13 2 3 2. + <_> + 13 16 2 3 2. + <_> + + <_> + 3 13 4 6 -1. + <_> + 3 13 2 3 2. + <_> + 5 16 2 3 2. + <_> + + <_> + 10 12 2 6 -1. + <_> + 10 15 2 3 2. + <_> + + <_> + 5 9 10 10 -1. + <_> + 5 9 5 5 2. + <_> + 10 14 5 5 2. + <_> + + <_> + 11 4 4 2 -1. + <_> + 13 4 2 1 2. + <_> + 11 5 2 1 2. + <_> + + <_> + 7 12 6 8 -1. + <_> + 10 12 3 8 2. + <_> + + <_> + 12 2 4 10 -1. + <_> + 14 2 2 5 2. + <_> + 12 7 2 5 2. + <_> + + <_> + 8 11 2 1 -1. + <_> + 9 11 1 1 2. + <_> + + <_> + 10 5 1 12 -1. + <_> + 10 9 1 4 3. + <_> + + <_> + 0 11 6 9 -1. + <_> + 3 11 3 9 2. + <_> + + <_> + 12 2 4 10 -1. + <_> + 14 2 2 5 2. + <_> + 12 7 2 5 2. + <_> + + <_> + 4 2 4 10 -1. + <_> + 4 2 2 5 2. + <_> + 6 7 2 5 2. + <_> + + <_> + 11 4 4 2 -1. + <_> + 13 4 2 1 2. + <_> + 11 5 2 1 2. + <_> + + <_> + 0 14 6 3 -1. + <_> + 0 15 6 1 3. + <_> + + <_> + 11 4 4 2 -1. + <_> + 13 4 2 1 2. + <_> + 11 5 2 1 2. + <_> + + <_> + 6 1 3 2 -1. + <_> + 7 1 1 2 3. + <_> + + <_> + 11 4 4 2 -1. + <_> + 13 4 2 1 2. + <_> + 11 5 2 1 2. + <_> + + <_> + 5 4 4 2 -1. + <_> + 5 4 2 1 2. + <_> + 7 5 2 1 2. + <_> + + <_> + 13 0 2 12 -1. + <_> + 14 0 1 6 2. + <_> + 13 6 1 6 2. + <_> + + <_> + 6 0 3 10 -1. + <_> + 7 0 1 10 3. + <_> + + <_> + 3 0 17 8 -1. + <_> + 3 4 17 4 2. + <_> + + <_> + 0 4 20 4 -1. + <_> + 0 6 20 2 2. + <_> + + <_> + 0 3 8 2 -1. + <_> + 4 3 4 2 2. + <_> + + <_> + 8 11 4 3 -1. + <_> + 8 12 4 1 3. + <_> + + <_> + 5 7 6 4 -1. + <_> + 5 7 3 2 2. + <_> + 8 9 3 2 2. + <_> + + <_> + 8 3 4 9 -1. + <_> + 8 6 4 3 3. + <_> + + <_> + 8 15 1 4 -1. + <_> + 8 17 1 2 2. + <_> + + <_> + 4 5 12 7 -1. + <_> + 8 5 4 7 3. + <_> + + <_> + 4 2 4 10 -1. + <_> + 4 2 2 5 2. + <_> + 6 7 2 5 2. + <_> + + <_> + 3 0 17 2 -1. + <_> + 3 1 17 1 2. + <_> + + <_> + 2 2 16 15 -1. + <_> + 2 7 16 5 3. + <_> + + <_> + 15 2 5 2 -1. + <_> + 15 3 5 1 2. + <_> + + <_> + 9 3 2 2 -1. + <_> + 10 3 1 2 2. + <_> + + <_> + 4 5 16 15 -1. + <_> + 4 10 16 5 3. + <_> + + <_> + 7 13 5 6 -1. + <_> + 7 16 5 3 2. + <_> + + <_> + 10 7 3 2 -1. + <_> + 11 7 1 2 3. + <_> + + <_> + 8 3 3 1 -1. + <_> + 9 3 1 1 3. + <_> + + <_> + 9 16 3 3 -1. + <_> + 9 17 3 1 3. + <_> + + <_> + 0 2 5 2 -1. + <_> + 0 3 5 1 2. + <_> + + <_> + 12 5 4 3 -1. + <_> + 12 6 4 1 3. + <_> + + <_> + 1 7 12 1 -1. + <_> + 5 7 4 1 3. + <_> + + <_> + 7 5 6 14 -1. + <_> + 7 12 6 7 2. + <_> + + <_> + 0 0 8 10 -1. + <_> + 0 0 4 5 2. + <_> + 4 5 4 5 2. + <_> + + <_> + 9 1 3 2 -1. + <_> + 10 1 1 2 3. + <_> + + <_> + 8 1 3 2 -1. + <_> + 9 1 1 2 3. + <_> + + <_> + 12 4 3 3 -1. + <_> + 12 5 3 1 3. + <_> + + <_> + 7 4 6 16 -1. + <_> + 7 12 6 8 2. + <_> + + <_> + 12 4 3 3 -1. + <_> + 12 5 3 1 3. + <_> + + <_> + 2 3 2 6 -1. + <_> + 2 5 2 2 3. + <_> + + <_> + 14 2 6 9 -1. + <_> + 14 5 6 3 3. + <_> + + <_> + 5 4 3 3 -1. + <_> + 5 5 3 1 3. + <_> + + <_> + 9 17 3 2 -1. + <_> + 10 17 1 2 3. + <_> + + <_> + 5 5 2 3 -1. + <_> + 5 6 2 1 3. + <_> + + <_> + 13 11 3 6 -1. + <_> + 13 13 3 2 3. + <_> + + <_> + 3 14 2 6 -1. + <_> + 3 17 2 3 2. + <_> + + <_> + 14 3 6 2 -1. + <_> + 14 4 6 1 2. + <_> + + <_> + 0 8 16 2 -1. + <_> + 0 9 16 1 2. + <_> + + <_> + 14 3 6 2 -1. + <_> + 14 4 6 1 2. + <_> + + <_> + 0 0 5 6 -1. + <_> + 0 2 5 2 3. + <_> + + <_> + 12 5 4 3 -1. + <_> + 12 6 4 1 3. + <_> + + <_> + 4 11 3 6 -1. + <_> + 4 13 3 2 3. + <_> + + <_> + 12 5 4 3 -1. + <_> + 12 6 4 1 3. + <_> + + <_> + 9 5 1 3 -1. + <_> + 9 6 1 1 3. + <_> + + <_> + 12 5 4 3 -1. + <_> + 12 6 4 1 3. + <_> + + <_> + 6 6 8 12 -1. + <_> + 6 12 8 6 2. + <_> + + <_> + 12 5 4 3 -1. + <_> + 12 6 4 1 3. + <_> + + <_> + 5 12 9 2 -1. + <_> + 8 12 3 2 3. + <_> + + <_> + 12 5 4 3 -1. + <_> + 12 6 4 1 3. + <_> + + <_> + 4 5 4 3 -1. + <_> + 4 6 4 1 3. + <_> + + <_> + 6 6 9 2 -1. + <_> + 9 6 3 2 3. + <_> + + <_> + 4 11 1 3 -1. + <_> + 4 12 1 1 3. + <_> + + <_> + 14 12 6 6 -1. + <_> + 14 12 3 6 2. + <_> + + <_> + 7 0 3 7 -1. + <_> + 8 0 1 7 3. + <_> + + <_> + 9 8 3 3 -1. + <_> + 10 8 1 3 3. + <_> + + <_> + 8 8 3 3 -1. + <_> + 9 8 1 3 3. + <_> + + <_> + 5 10 11 3 -1. + <_> + 5 11 11 1 3. + <_> + + <_> + 5 7 10 1 -1. + <_> + 10 7 5 1 2. + <_> + + <_> + 9 7 3 2 -1. + <_> + 10 7 1 2 3. + <_> + + <_> + 8 7 3 2 -1. + <_> + 9 7 1 2 3. + <_> + + <_> + 11 9 4 2 -1. + <_> + 11 9 2 2 2. + <_> + + <_> + 5 9 4 2 -1. + <_> + 7 9 2 2 2. + <_> + + <_> + 14 10 2 4 -1. + <_> + 14 12 2 2 2. + <_> + + <_> + 7 7 3 2 -1. + <_> + 8 7 1 2 3. + <_> + + <_> + 14 17 6 3 -1. + <_> + 14 18 6 1 3. + <_> + + <_> + 4 5 12 12 -1. + <_> + 4 5 6 6 2. + <_> + 10 11 6 6 2. + <_> + + <_> + 6 9 8 8 -1. + <_> + 10 9 4 4 2. + <_> + 6 13 4 4 2. + <_> + + <_> + 0 4 15 4 -1. + <_> + 5 4 5 4 3. + <_> + + <_> + 13 2 4 1 -1. + <_> + 13 2 2 1 2. + <_> + + <_> + 4 12 2 2 -1. + <_> + 4 13 2 1 2. + <_> + + <_> + 8 13 4 3 -1. + <_> + 8 14 4 1 3. + <_> + + <_> + 9 13 2 3 -1. + <_> + 9 14 2 1 3. + <_> + + <_> + 13 11 2 3 -1. + <_> + 13 12 2 1 3. + <_> + + <_> + 7 12 4 4 -1. + <_> + 7 12 2 2 2. + <_> + 9 14 2 2 2. + <_> + + <_> + 10 11 2 2 -1. + <_> + 11 11 1 1 2. + <_> + 10 12 1 1 2. + <_> + + <_> + 8 17 3 2 -1. + <_> + 9 17 1 2 3. + <_> + + <_> + 10 11 2 2 -1. + <_> + 11 11 1 1 2. + <_> + 10 12 1 1 2. + <_> + + <_> + 0 17 6 3 -1. + <_> + 0 18 6 1 3. + <_> + + <_> + 10 11 2 2 -1. + <_> + 11 11 1 1 2. + <_> + 10 12 1 1 2. + <_> + + <_> + 8 11 2 2 -1. + <_> + 8 11 1 1 2. + <_> + 9 12 1 1 2. + <_> + + <_> + 12 5 8 4 -1. + <_> + 12 5 4 4 2. + <_> + + <_> + 0 5 8 4 -1. + <_> + 4 5 4 4 2. + <_> + + <_> + 13 2 4 1 -1. + <_> + 13 2 2 1 2. + <_> + + <_> + 3 2 4 1 -1. + <_> + 5 2 2 1 2. + <_> + + <_> + 10 0 4 2 -1. + <_> + 12 0 2 1 2. + <_> + 10 1 2 1 2. + <_> + + <_> + 7 12 3 1 -1. + <_> + 8 12 1 1 3. + <_> + + <_> + 8 11 4 8 -1. + <_> + 10 11 2 4 2. + <_> + 8 15 2 4 2. + <_> + + <_> + 9 9 2 2 -1. + <_> + 9 10 2 1 2. + <_> + + <_> + 3 18 15 2 -1. + <_> + 3 19 15 1 2. + <_> + + <_> + 2 6 2 12 -1. + <_> + 2 6 1 6 2. + <_> + 3 12 1 6 2. + <_> + + <_> + 9 8 2 3 -1. + <_> + 9 9 2 1 3. + <_> + + <_> + 7 10 3 2 -1. + <_> + 8 10 1 2 3. + <_> + + <_> + 11 11 3 1 -1. + <_> + 12 11 1 1 3. + <_> + + <_> + 6 11 3 1 -1. + <_> + 7 11 1 1 3. + <_> + + <_> + 9 2 4 2 -1. + <_> + 11 2 2 1 2. + <_> + 9 3 2 1 2. + <_> + + <_> + 4 12 2 3 -1. + <_> + 4 13 2 1 3. + <_> + + <_> + 2 1 18 3 -1. + <_> + 8 1 6 3 3. + <_> + + <_> + 5 1 4 14 -1. + <_> + 7 1 2 14 2. + <_> + + <_> + 8 16 12 3 -1. + <_> + 8 16 6 3 2. + <_> + + <_> + 1 17 18 3 -1. + <_> + 7 17 6 3 3. + <_> + + <_> + 9 14 2 6 -1. + <_> + 9 17 2 3 2. + <_> + + <_> + 9 12 1 8 -1. + <_> + 9 16 1 4 2. + <_> + + <_> + 9 14 2 3 -1. + <_> + 9 15 2 1 3. + <_> + + <_> + 9 6 2 12 -1. + <_> + 9 10 2 4 3. + <_> + + <_> + 12 9 3 3 -1. + <_> + 12 10 3 1 3. + <_> + + <_> + 0 1 4 8 -1. + <_> + 2 1 2 8 2. + <_> + + <_> + 9 1 6 2 -1. + <_> + 12 1 3 1 2. + <_> + 9 2 3 1 2. + <_> + + <_> + 1 3 12 14 -1. + <_> + 1 10 12 7 2. + <_> + + <_> + 8 12 4 2 -1. + <_> + 10 12 2 1 2. + <_> + 8 13 2 1 2. + <_> + + <_> + 1 9 10 2 -1. + <_> + 1 9 5 1 2. + <_> + 6 10 5 1 2. + <_> + + <_> + 8 15 4 3 -1. + <_> + 8 16 4 1 3. + <_> + + <_> + 6 8 8 3 -1. + <_> + 6 9 8 1 3. + <_> + + <_> + 9 15 5 3 -1. + <_> + 9 16 5 1 3. + <_> + + <_> + 8 7 4 3 -1. + <_> + 8 8 4 1 3. + <_> + + <_> + 7 7 6 2 -1. + <_> + 7 8 6 1 2. + <_> + + <_> + 5 7 8 2 -1. + <_> + 5 7 4 1 2. + <_> + 9 8 4 1 2. + <_> + + <_> + 12 9 3 3 -1. + <_> + 12 10 3 1 3. + <_> + + <_> + 4 7 4 2 -1. + <_> + 4 8 4 1 2. + <_> + + <_> + 14 2 6 9 -1. + <_> + 14 5 6 3 3. + <_> + + <_> + 4 9 3 3 -1. + <_> + 5 9 1 3 3. + <_> + + <_> + 12 9 3 3 -1. + <_> + 12 10 3 1 3. + <_> + + <_> + 0 2 6 9 -1. + <_> + 0 5 6 3 3. + <_> + + <_> + 17 3 3 6 -1. + <_> + 18 3 1 6 3. + <_> + + <_> + 0 3 3 6 -1. + <_> + 1 3 1 6 3. + <_> + + <_> + 17 14 1 2 -1. + <_> + 17 15 1 1 2. + <_> + + <_> + 4 9 4 3 -1. + <_> + 6 9 2 3 2. + <_> + + <_> + 12 9 3 3 -1. + <_> + 12 10 3 1 3. + <_> + + <_> + 5 9 3 3 -1. + <_> + 5 10 3 1 3. + <_> + + <_> + 9 5 6 8 -1. + <_> + 12 5 3 4 2. + <_> + 9 9 3 4 2. + <_> + + <_> + 5 5 6 8 -1. + <_> + 5 5 3 4 2. + <_> + 8 9 3 4 2. + <_> + + <_> + 16 1 4 6 -1. + <_> + 16 4 4 3 2. + <_> + + <_> + 1 0 6 20 -1. + <_> + 3 0 2 20 3. + <_> + + <_> + 12 11 3 2 -1. + <_> + 13 11 1 2 3. + <_> + + <_> + 5 11 3 2 -1. + <_> + 6 11 1 2 3. + <_> + + <_> + 9 4 6 1 -1. + <_> + 11 4 2 1 3. + <_> + + <_> + 0 0 8 3 -1. + <_> + 4 0 4 3 2. + <_> + + <_> + 15 0 2 5 -1. + <_> + 15 0 1 5 2. + <_> + + <_> + 4 1 3 2 -1. + <_> + 5 1 1 2 3. + <_> + + <_> + 7 0 6 15 -1. + <_> + 9 0 2 15 3. + <_> + + <_> + 6 11 3 1 -1. + <_> + 7 11 1 1 3. + <_> + + <_> + 12 0 3 4 -1. + <_> + 13 0 1 4 3. + <_> + + <_> + 5 4 6 1 -1. + <_> + 7 4 2 1 3. + <_> + + <_> + 12 7 3 2 -1. + <_> + 12 8 3 1 2. + <_> + + <_> + 0 1 4 6 -1. + <_> + 0 4 4 3 2. + <_> + + <_> + 12 7 3 2 -1. + <_> + 12 8 3 1 2. + <_> + + <_> + 2 16 3 3 -1. + <_> + 2 17 3 1 3. + <_> + + <_> + 13 8 6 10 -1. + <_> + 16 8 3 5 2. + <_> + 13 13 3 5 2. + <_> + + <_> + 0 9 5 2 -1. + <_> + 0 10 5 1 2. + <_> + + <_> + 12 11 2 2 -1. + <_> + 13 11 1 1 2. + <_> + 12 12 1 1 2. + <_> + + <_> + 3 15 3 3 -1. + <_> + 3 16 3 1 3. + <_> + + <_> + 12 7 3 2 -1. + <_> + 12 8 3 1 2. + <_> + + <_> + 5 7 3 2 -1. + <_> + 5 8 3 1 2. + <_> + + <_> + 9 5 9 9 -1. + <_> + 9 8 9 3 3. + <_> + + <_> + 5 0 3 7 -1. + <_> + 6 0 1 7 3. + <_> + + <_> + 5 2 12 5 -1. + <_> + 9 2 4 5 3. + <_> + + <_> + 6 11 2 2 -1. + <_> + 6 11 1 1 2. + <_> + 7 12 1 1 2. + <_> + + <_> + 15 15 3 2 -1. + <_> + 15 16 3 1 2. + <_> + + <_> + 2 15 3 2 -1. + <_> + 2 16 3 1 2. + <_> + + <_> + 14 12 6 8 -1. + <_> + 17 12 3 4 2. + <_> + 14 16 3 4 2. + <_> + + <_> + 2 8 15 6 -1. + <_> + 7 8 5 6 3. + <_> + + <_> + 2 2 18 17 -1. + <_> + 8 2 6 17 3. + <_> + + <_> + 5 1 4 1 -1. + <_> + 7 1 2 1 2. + <_> + + <_> + 5 2 12 5 -1. + <_> + 9 2 4 5 3. + <_> + + <_> + 3 2 12 5 -1. + <_> + 7 2 4 5 3. + <_> + + <_> + 4 9 12 4 -1. + <_> + 10 9 6 2 2. + <_> + 4 11 6 2 2. + <_> + + <_> + 5 15 6 2 -1. + <_> + 5 15 3 1 2. + <_> + 8 16 3 1 2. + <_> + + <_> + 10 14 2 3 -1. + <_> + 10 15 2 1 3. + <_> + + <_> + 0 13 20 2 -1. + <_> + 0 13 10 1 2. + <_> + 10 14 10 1 2. + <_> + + <_> + 4 9 12 8 -1. + <_> + 10 9 6 4 2. + <_> + 4 13 6 4 2. + <_> + + <_> + 8 13 3 6 -1. + <_> + 8 16 3 3 2. + <_> + + <_> + 10 12 2 2 -1. + <_> + 10 13 2 1 2. + <_> + + <_> + 9 12 2 2 -1. + <_> + 9 12 1 1 2. + <_> + 10 13 1 1 2. + <_> + + <_> + 4 11 14 4 -1. + <_> + 11 11 7 2 2. + <_> + 4 13 7 2 2. + <_> + + <_> + 8 5 4 2 -1. + <_> + 8 6 4 1 2. + <_> + + <_> + 10 10 6 3 -1. + <_> + 12 10 2 3 3. + <_> + + <_> + 2 14 1 2 -1. + <_> + 2 15 1 1 2. + <_> + + <_> + 13 8 6 12 -1. + <_> + 16 8 3 6 2. + <_> + 13 14 3 6 2. + <_> + + <_> + 1 8 6 12 -1. + <_> + 1 8 3 6 2. + <_> + 4 14 3 6 2. + <_> + + <_> + 10 0 6 10 -1. + <_> + 12 0 2 10 3. + <_> + + <_> + 5 11 8 4 -1. + <_> + 5 11 4 2 2. + <_> + 9 13 4 2 2. + <_> + + <_> + 10 16 8 4 -1. + <_> + 14 16 4 2 2. + <_> + 10 18 4 2 2. + <_> + + <_> + 7 7 6 6 -1. + <_> + 9 7 2 6 3. + <_> + + <_> + 10 2 4 10 -1. + <_> + 10 2 2 10 2. + <_> + + <_> + 6 1 4 9 -1. + <_> + 8 1 2 9 2. + <_> + + <_> + 12 19 2 1 -1. + <_> + 12 19 1 1 2. + <_> + + <_> + 1 2 4 9 -1. + <_> + 3 2 2 9 2. + <_> + + <_> + 7 5 6 4 -1. + <_> + 9 5 2 4 3. + <_> + + <_> + 9 4 2 4 -1. + <_> + 9 6 2 2 2. + <_> + + <_> + 14 5 2 8 -1. + <_> + 14 9 2 4 2. + <_> + + <_> + 7 6 5 12 -1. + <_> + 7 12 5 6 2. + <_> + + <_> + 14 6 2 6 -1. + <_> + 14 9 2 3 2. + <_> + + <_> + 4 6 2 6 -1. + <_> + 4 9 2 3 2. + <_> + + <_> + 8 15 10 4 -1. + <_> + 13 15 5 2 2. + <_> + 8 17 5 2 2. + <_> + + <_> + 6 18 2 2 -1. + <_> + 7 18 1 2 2. + <_> + + <_> + 11 3 6 2 -1. + <_> + 11 4 6 1 2. + <_> + + <_> + 2 0 16 6 -1. + <_> + 2 2 16 2 3. + <_> + + <_> + 11 3 6 2 -1. + <_> + 11 4 6 1 2. + <_> + + <_> + 4 11 10 3 -1. + <_> + 4 12 10 1 3. + <_> + + <_> + 11 3 6 2 -1. + <_> + 11 4 6 1 2. + <_> + + <_> + 3 3 6 2 -1. + <_> + 3 4 6 1 2. + <_> + + <_> + 16 0 4 7 -1. + <_> + 16 0 2 7 2. + <_> + + <_> + 0 14 9 6 -1. + <_> + 0 16 9 2 3. + <_> + + <_> + 9 16 3 3 -1. + <_> + 9 17 3 1 3. + <_> + + <_> + 4 6 6 2 -1. + <_> + 6 6 2 2 3. + <_> + + <_> + 15 11 1 3 -1. + <_> + 15 12 1 1 3. + <_> + + <_> + 5 5 2 3 -1. + <_> + 5 6 2 1 3. + <_> + + <_> + 10 9 2 2 -1. + <_> + 10 10 2 1 2. + <_> + + <_> + 3 1 4 3 -1. + <_> + 5 1 2 3 2. + <_> + + <_> + 16 0 4 7 -1. + <_> + 16 0 2 7 2. + <_> + + <_> + 0 0 20 1 -1. + <_> + 10 0 10 1 2. + <_> + + <_> + 15 11 1 3 -1. + <_> + 15 12 1 1 3. + <_> + + <_> + 0 4 3 4 -1. + <_> + 1 4 1 4 3. + <_> + + <_> + 16 3 3 6 -1. + <_> + 16 5 3 2 3. + <_> + + <_> + 1 3 3 6 -1. + <_> + 1 5 3 2 3. + <_> + + <_> + 6 2 12 6 -1. + <_> + 12 2 6 3 2. + <_> + 6 5 6 3 2. + <_> + + <_> + 8 10 4 3 -1. + <_> + 8 11 4 1 3. + <_> + + <_> + 4 2 14 6 -1. + <_> + 11 2 7 3 2. + <_> + 4 5 7 3 2. + <_> + + <_> + 9 11 2 3 -1. + <_> + 9 12 2 1 3. + <_> + + <_> + 15 13 2 3 -1. + <_> + 15 14 2 1 3. + <_> + + <_> + 8 12 4 3 -1. + <_> + 8 13 4 1 3. + <_> + + <_> + 15 11 1 3 -1. + <_> + 15 12 1 1 3. + <_> + + <_> + 7 13 5 2 -1. + <_> + 7 14 5 1 2. + <_> + + <_> + 7 12 6 3 -1. + <_> + 7 13 6 1 3. + <_> + + <_> + 5 11 4 4 -1. + <_> + 5 13 4 2 2. + <_> + + <_> + 11 4 3 3 -1. + <_> + 12 4 1 3 3. + <_> + + <_> + 6 4 3 3 -1. + <_> + 7 4 1 3 3. + <_> + + <_> + 16 5 3 6 -1. + <_> + 17 5 1 6 3. + <_> + + <_> + 3 6 12 7 -1. + <_> + 7 6 4 7 3. + <_> + + <_> + 16 5 3 6 -1. + <_> + 17 5 1 6 3. + <_> + + <_> + 3 13 2 3 -1. + <_> + 3 14 2 1 3. + <_> + + <_> + 16 5 3 6 -1. + <_> + 17 5 1 6 3. + <_> + + <_> + 1 5 3 6 -1. + <_> + 2 5 1 6 3. + <_> + + <_> + 1 9 18 1 -1. + <_> + 7 9 6 1 3. + <_> + + <_> + 0 9 8 7 -1. + <_> + 4 9 4 7 2. + <_> + + <_> + 12 11 8 2 -1. + <_> + 12 12 8 1 2. + <_> + + <_> + 0 11 8 2 -1. + <_> + 0 12 8 1 2. + <_> + + <_> + 9 13 2 3 -1. + <_> + 9 14 2 1 3. + <_> + + <_> + 4 10 12 4 -1. + <_> + 4 10 6 2 2. + <_> + 10 12 6 2 2. + <_> + + <_> + 9 3 3 7 -1. + <_> + 10 3 1 7 3. + <_> + + <_> + 7 2 3 5 -1. + <_> + 8 2 1 5 3. + <_> + + <_> + 9 12 4 6 -1. + <_> + 11 12 2 3 2. + <_> + 9 15 2 3 2. + <_> + + <_> + 8 7 3 6 -1. + <_> + 9 7 1 6 3. + <_> + + <_> + 15 4 4 2 -1. + <_> + 15 5 4 1 2. + <_> + + <_> + 8 7 3 3 -1. + <_> + 9 7 1 3 3. + <_> + + <_> + 14 2 6 4 -1. + <_> + 14 4 6 2 2. + <_> + + <_> + 7 16 6 1 -1. + <_> + 9 16 2 1 3. + <_> + + <_> + 15 13 2 3 -1. + <_> + 15 14 2 1 3. + <_> + + <_> + 8 7 3 10 -1. + <_> + 9 7 1 10 3. + <_> + + <_> + 11 10 2 6 -1. + <_> + 11 12 2 2 3. + <_> + + <_> + 6 10 4 1 -1. + <_> + 8 10 2 1 2. + <_> + + <_> + 10 9 2 2 -1. + <_> + 10 10 2 1 2. + <_> + + <_> + 8 9 2 2 -1. + <_> + 8 10 2 1 2. + <_> + + <_> + 12 7 2 2 -1. + <_> + 13 7 1 1 2. + <_> + 12 8 1 1 2. + <_> + + <_> + 5 7 2 2 -1. + <_> + 5 7 1 1 2. + <_> + 6 8 1 1 2. + <_> + + <_> + 13 0 3 14 -1. + <_> + 14 0 1 14 3. + <_> + + <_> + 4 0 3 14 -1. + <_> + 5 0 1 14 3. + <_> + + <_> + 13 4 3 14 -1. + <_> + 14 4 1 14 3. + <_> + + <_> + 9 14 2 3 -1. + <_> + 9 15 2 1 3. + <_> + + <_> + 8 14 4 3 -1. + <_> + 8 15 4 1 3. + <_> + + <_> + 4 2 3 16 -1. + <_> + 5 2 1 16 3. + <_> + + <_> + 7 2 8 10 -1. + <_> + 7 7 8 5 2. + <_> + + <_> + 6 14 7 3 -1. + <_> + 6 15 7 1 3. + <_> + + <_> + 9 2 10 12 -1. + <_> + 14 2 5 6 2. + <_> + 9 8 5 6 2. + <_> + + <_> + 6 7 8 2 -1. + <_> + 6 8 8 1 2. + <_> + + <_> + 8 13 4 6 -1. + <_> + 8 16 4 3 2. + <_> + + <_> + 6 6 1 3 -1. + <_> + 6 7 1 1 3. + <_> + + <_> + 16 2 4 6 -1. + <_> + 16 4 4 2 3. + <_> + + <_> + 6 6 4 2 -1. + <_> + 6 6 2 1 2. + <_> + 8 7 2 1 2. + <_> + + <_> + 16 2 4 6 -1. + <_> + 16 4 4 2 3. + <_> + + <_> + 0 2 4 6 -1. + <_> + 0 4 4 2 3. + <_> + + <_> + 9 6 2 6 -1. + <_> + 9 6 1 6 2. + <_> + + <_> + 3 4 6 10 -1. + <_> + 3 9 6 5 2. + <_> + + <_> + 9 5 2 6 -1. + <_> + 9 5 1 6 2. + <_> + + <_> + 3 13 2 3 -1. + <_> + 3 14 2 1 3. + <_> + + <_> + 13 13 3 2 -1. + <_> + 13 14 3 1 2. + <_> + + <_> + 2 16 10 4 -1. + <_> + 2 16 5 2 2. + <_> + 7 18 5 2 2. + <_> + + <_> + 5 6 10 6 -1. + <_> + 10 6 5 3 2. + <_> + 5 9 5 3 2. + <_> + + <_> + 7 14 1 3 -1. + <_> + 7 15 1 1 3. + <_> + + <_> + 14 16 6 3 -1. + <_> + 14 17 6 1 3. + <_> + + <_> + 5 4 3 3 -1. + <_> + 5 5 3 1 3. + <_> + + <_> + 7 4 10 3 -1. + <_> + 7 5 10 1 3. + <_> + + <_> + 0 4 5 4 -1. + <_> + 0 6 5 2 2. + <_> + + <_> + 13 11 3 9 -1. + <_> + 13 14 3 3 3. + <_> + + <_> + 4 11 3 9 -1. + <_> + 4 14 3 3 3. + <_> + + <_> + 9 7 2 1 -1. + <_> + 9 7 1 1 2. + <_> + + <_> + 5 0 6 17 -1. + <_> + 7 0 2 17 3. + <_> + + <_> + 10 3 6 3 -1. + <_> + 10 3 3 3 2. + <_> + + <_> + 2 2 15 4 -1. + <_> + 7 2 5 4 3. + <_> + + <_> + 8 2 8 2 -1. + <_> + 12 2 4 1 2. + <_> + 8 3 4 1 2. + <_> + + <_> + 8 1 3 6 -1. + <_> + 8 3 3 2 3. + <_> + + <_> + 9 17 2 2 -1. + <_> + 9 18 2 1 2. + <_> + + <_> + 0 0 2 14 -1. + <_> + 1 0 1 14 2. + <_> + + <_> + 12 0 7 3 -1. + <_> + 12 1 7 1 3. + <_> + + <_> + 1 14 1 2 -1. + <_> + 1 15 1 1 2. + <_> + + <_> + 14 12 2 8 -1. + <_> + 15 12 1 4 2. + <_> + 14 16 1 4 2. + <_> + + <_> + 1 0 7 3 -1. + <_> + 1 1 7 1 3. + <_> + + <_> + 14 12 2 8 -1. + <_> + 15 12 1 4 2. + <_> + 14 16 1 4 2. + <_> + + <_> + 6 0 8 12 -1. + <_> + 6 0 4 6 2. + <_> + 10 6 4 6 2. + <_> + + <_> + 6 1 8 9 -1. + <_> + 6 4 8 3 3. + <_> + + <_> + 5 2 2 2 -1. + <_> + 5 3 2 1 2. + <_> + + <_> + 13 14 6 6 -1. + <_> + 16 14 3 3 2. + <_> + 13 17 3 3 2. + <_> + + <_> + 0 17 20 2 -1. + <_> + 0 17 10 1 2. + <_> + 10 18 10 1 2. + <_> + + <_> + 10 3 2 6 -1. + <_> + 11 3 1 3 2. + <_> + 10 6 1 3 2. + <_> + + <_> + 5 12 6 2 -1. + <_> + 8 12 3 2 2. + <_> + + <_> + 10 7 6 13 -1. + <_> + 10 7 3 13 2. + <_> + + <_> + 5 15 10 5 -1. + <_> + 10 15 5 5 2. + <_> + + <_> + 10 4 4 10 -1. + <_> + 10 4 2 10 2. + <_> + + <_> + 5 7 2 1 -1. + <_> + 6 7 1 1 2. + <_> + + <_> + 10 3 6 7 -1. + <_> + 10 3 3 7 2. + <_> + + <_> + 4 3 6 7 -1. + <_> + 7 3 3 7 2. + <_> + + <_> + 1 7 18 5 -1. + <_> + 7 7 6 5 3. + <_> + + <_> + 3 17 4 3 -1. + <_> + 5 17 2 3 2. + <_> + + <_> + 8 14 12 6 -1. + <_> + 14 14 6 3 2. + <_> + 8 17 6 3 2. + <_> + + <_> + 0 13 20 4 -1. + <_> + 0 13 10 2 2. + <_> + 10 15 10 2 2. + <_> + + <_> + 4 5 14 2 -1. + <_> + 11 5 7 1 2. + <_> + 4 6 7 1 2. + <_> + + <_> + 1 2 10 12 -1. + <_> + 1 2 5 6 2. + <_> + 6 8 5 6 2. + <_> + + <_> + 6 1 14 3 -1. + <_> + 6 2 14 1 3. + <_> + + <_> + 8 16 2 3 -1. + <_> + 8 17 2 1 3. + <_> + + <_> + 9 17 3 2 -1. + <_> + 10 17 1 2 3. + <_> + + <_> + 5 15 4 2 -1. + <_> + 5 15 2 1 2. + <_> + 7 16 2 1 2. + <_> + + <_> + 10 15 1 3 -1. + <_> + 10 16 1 1 3. + <_> + + <_> + 8 16 4 4 -1. + <_> + 8 16 2 2 2. + <_> + 10 18 2 2 2. + <_> + + <_> + 6 11 8 6 -1. + <_> + 6 14 8 3 2. + <_> + + <_> + 2 13 5 2 -1. + <_> + 2 14 5 1 2. + <_> + + <_> + 13 14 6 6 -1. + <_> + 16 14 3 3 2. + <_> + 13 17 3 3 2. + <_> + + <_> + 1 9 18 4 -1. + <_> + 7 9 6 4 3. + <_> + + <_> + 13 14 6 6 -1. + <_> + 16 14 3 3 2. + <_> + 13 17 3 3 2. + <_> + + <_> + 0 2 1 6 -1. + <_> + 0 4 1 2 3. + <_> + + <_> + 5 0 15 20 -1. + <_> + 5 10 15 10 2. + <_> + + <_> + 1 14 6 6 -1. + <_> + 1 14 3 3 2. + <_> + 4 17 3 3 2. + <_> + + <_> + 8 14 4 6 -1. + <_> + 10 14 2 3 2. + <_> + 8 17 2 3 2. + <_> + + <_> + 7 11 2 1 -1. + <_> + 8 11 1 1 2. + <_> + + <_> + 9 17 3 2 -1. + <_> + 10 17 1 2 3. + <_> + + <_> + 8 17 3 2 -1. + <_> + 9 17 1 2 3. + <_> + + <_> + 12 14 4 6 -1. + <_> + 14 14 2 3 2. + <_> + 12 17 2 3 2. + <_> + + <_> + 4 14 4 6 -1. + <_> + 4 14 2 3 2. + <_> + 6 17 2 3 2. + <_> + + <_> + 13 14 2 6 -1. + <_> + 14 14 1 3 2. + <_> + 13 17 1 3 2. + <_> + + <_> + 5 14 2 6 -1. + <_> + 5 14 1 3 2. + <_> + 6 17 1 3 2. + <_> + + <_> + 7 0 6 12 -1. + <_> + 7 4 6 4 3. + <_> + + <_> + 0 7 12 2 -1. + <_> + 4 7 4 2 3. + <_> + + <_> + 10 3 3 13 -1. + <_> + 11 3 1 13 3. + <_> + + <_> + 7 3 3 13 -1. + <_> + 8 3 1 13 3. + <_> + + <_> + 10 8 6 3 -1. + <_> + 10 9 6 1 3. + <_> + + <_> + 3 11 3 2 -1. + <_> + 4 11 1 2 3. + <_> + + <_> + 13 12 6 8 -1. + <_> + 16 12 3 4 2. + <_> + 13 16 3 4 2. + <_> + + <_> + 7 6 6 5 -1. + <_> + 9 6 2 5 3. + <_> + + <_> + 17 11 2 7 -1. + <_> + 17 11 1 7 2. + <_> + + <_> + 3 13 8 2 -1. + <_> + 7 13 4 2 2. + <_> + + <_> + 6 9 8 3 -1. + <_> + 6 10 8 1 3. + <_> + + <_> + 4 3 4 3 -1. + <_> + 4 4 4 1 3. + <_> + + <_> + 11 3 4 3 -1. + <_> + 11 4 4 1 3. + <_> + + <_> + 1 4 17 12 -1. + <_> + 1 8 17 4 3. + <_> + + <_> + 11 3 4 3 -1. + <_> + 11 4 4 1 3. + <_> + + <_> + 4 8 6 3 -1. + <_> + 4 9 6 1 3. + <_> + + <_> + 12 3 5 3 -1. + <_> + 12 4 5 1 3. + <_> + + <_> + 1 11 2 7 -1. + <_> + 2 11 1 7 2. + <_> + + <_> + 15 12 2 8 -1. + <_> + 16 12 1 4 2. + <_> + 15 16 1 4 2. + <_> + + <_> + 4 8 11 3 -1. + <_> + 4 9 11 1 3. + <_> + + <_> + 9 13 6 2 -1. + <_> + 12 13 3 1 2. + <_> + 9 14 3 1 2. + <_> + + <_> + 6 13 4 3 -1. + <_> + 6 14 4 1 3. + <_> + + <_> + 9 12 3 3 -1. + <_> + 10 12 1 3 3. + <_> + + <_> + 5 3 3 3 -1. + <_> + 5 4 3 1 3. + <_> + + <_> + 9 4 2 3 -1. + <_> + 9 5 2 1 3. + <_> + + <_> + 0 2 16 3 -1. + <_> + 0 3 16 1 3. + <_> + + <_> + 15 12 2 8 -1. + <_> + 16 12 1 4 2. + <_> + 15 16 1 4 2. + <_> + + <_> + 3 12 2 8 -1. + <_> + 3 12 1 4 2. + <_> + 4 16 1 4 2. + <_> + + <_> + 14 13 3 6 -1. + <_> + 14 15 3 2 3. + <_> + + <_> + 3 13 3 6 -1. + <_> + 3 15 3 2 3. + <_> + + <_> + 6 5 10 2 -1. + <_> + 11 5 5 1 2. + <_> + 6 6 5 1 2. + <_> + + <_> + 2 14 14 6 -1. + <_> + 2 17 14 3 2. + <_> + + <_> + 10 14 1 3 -1. + <_> + 10 15 1 1 3. + <_> + + <_> + 4 16 2 2 -1. + <_> + 4 16 1 1 2. + <_> + 5 17 1 1 2. + <_> + + <_> + 10 6 2 3 -1. + <_> + 10 7 2 1 3. + <_> + + <_> + 0 17 20 2 -1. + <_> + 0 17 10 1 2. + <_> + 10 18 10 1 2. + <_> + + <_> + 13 6 1 3 -1. + <_> + 13 7 1 1 3. + <_> + + <_> + 8 13 3 2 -1. + <_> + 9 13 1 2 3. + <_> + + <_> + 12 2 3 3 -1. + <_> + 13 2 1 3 3. + <_> + + <_> + 3 18 2 2 -1. + <_> + 3 18 1 1 2. + <_> + 4 19 1 1 2. + <_> + + <_> + 9 16 3 4 -1. + <_> + 10 16 1 4 3. + <_> + + <_> + 6 6 1 3 -1. + <_> + 6 7 1 1 3. + <_> + + <_> + 13 1 5 2 -1. + <_> + 13 2 5 1 2. + <_> + + <_> + 7 14 6 2 -1. + <_> + 7 14 3 1 2. + <_> + 10 15 3 1 2. + <_> + + <_> + 11 3 3 4 -1. + <_> + 12 3 1 4 3. + <_> + + <_> + 1 13 12 6 -1. + <_> + 5 13 4 6 3. + <_> + + <_> + 14 11 5 2 -1. + <_> + 14 12 5 1 2. + <_> + + <_> + 2 15 14 4 -1. + <_> + 2 15 7 2 2. + <_> + 9 17 7 2 2. + <_> + + <_> + 3 7 14 2 -1. + <_> + 10 7 7 1 2. + <_> + 3 8 7 1 2. + <_> + + <_> + 1 11 4 2 -1. + <_> + 1 12 4 1 2. + <_> + + <_> + 14 0 6 14 -1. + <_> + 16 0 2 14 3. + <_> + + <_> + 4 11 1 3 -1. + <_> + 4 12 1 1 3. + <_> + + <_> + 14 0 6 14 -1. + <_> + 16 0 2 14 3. + <_> + + <_> + 1 10 3 7 -1. + <_> + 2 10 1 7 3. + <_> + + <_> + 8 12 9 2 -1. + <_> + 8 13 9 1 2. + <_> + + <_> + 0 6 20 1 -1. + <_> + 10 6 10 1 2. + <_> + + <_> + 8 4 4 4 -1. + <_> + 8 4 2 4 2. + <_> + + <_> + 0 0 2 2 -1. + <_> + 0 1 2 1 2. + <_> + + <_> + 5 3 10 9 -1. + <_> + 5 6 10 3 3. + <_> + + <_> + 15 2 4 10 -1. + <_> + 15 2 2 10 2. + <_> + + <_> + 8 2 2 7 -1. + <_> + 9 2 1 7 2. + <_> + + <_> + 7 4 12 1 -1. + <_> + 11 4 4 1 3. + <_> + + <_> + 3 4 9 1 -1. + <_> + 6 4 3 1 3. + <_> + + <_> + 15 10 1 4 -1. + <_> + 15 12 1 2 2. + <_> + + <_> + 4 10 6 4 -1. + <_> + 7 10 3 4 2. + <_> + + <_> + 15 9 1 6 -1. + <_> + 15 12 1 3 2. + <_> + + <_> + 7 17 6 3 -1. + <_> + 7 18 6 1 3. + <_> + + <_> + 14 3 2 16 -1. + <_> + 15 3 1 8 2. + <_> + 14 11 1 8 2. + <_> + + <_> + 4 9 1 6 -1. + <_> + 4 12 1 3 2. + <_> + + <_> + 12 1 5 2 -1. + <_> + 12 2 5 1 2. + <_> + + <_> + 6 18 4 2 -1. + <_> + 6 18 2 1 2. + <_> + 8 19 2 1 2. + <_> + + <_> + 2 4 16 10 -1. + <_> + 10 4 8 5 2. + <_> + 2 9 8 5 2. + <_> + + <_> + 6 5 1 10 -1. + <_> + 6 10 1 5 2. + <_> + + <_> + 4 8 15 2 -1. + <_> + 9 8 5 2 3. + <_> + + <_> + 1 8 15 2 -1. + <_> + 6 8 5 2 3. + <_> + + <_> + 9 5 3 6 -1. + <_> + 9 7 3 2 3. + <_> + + <_> + 5 7 8 2 -1. + <_> + 9 7 4 2 2. + <_> + + <_> + 9 11 2 3 -1. + <_> + 9 12 2 1 3. + <_> + + <_> + 1 0 16 3 -1. + <_> + 1 1 16 1 3. + <_> + + <_> + 11 2 7 2 -1. + <_> + 11 3 7 1 2. + <_> + + <_> + 5 1 10 18 -1. + <_> + 5 7 10 6 3. + <_> + + <_> + 17 4 3 2 -1. + <_> + 18 4 1 2 3. + <_> + + <_> + 8 13 1 3 -1. + <_> + 8 14 1 1 3. + <_> + + <_> + 3 14 14 6 -1. + <_> + 3 16 14 2 3. + <_> + + <_> + 0 2 3 4 -1. + <_> + 1 2 1 4 3. + <_> + + <_> + 12 1 5 2 -1. + <_> + 12 2 5 1 2. + <_> + + <_> + 3 1 5 2 -1. + <_> + 3 2 5 1 2. + <_> + + <_> + 10 13 2 3 -1. + <_> + 10 14 2 1 3. + <_> + + <_> + 8 13 2 3 -1. + <_> + 8 14 2 1 3. + <_> + + <_> + 14 12 2 3 -1. + <_> + 14 13 2 1 3. + <_> + + <_> + 7 2 2 3 -1. + <_> + 7 3 2 1 3. + <_> + + <_> + 5 6 10 4 -1. + <_> + 10 6 5 2 2. + <_> + 5 8 5 2 2. + <_> + + <_> + 9 13 1 6 -1. + <_> + 9 16 1 3 2. + <_> + + <_> + 10 12 2 2 -1. + <_> + 11 12 1 1 2. + <_> + 10 13 1 1 2. + <_> + + <_> + 4 12 2 3 -1. + <_> + 4 13 2 1 3. + <_> + + <_> + 14 4 6 6 -1. + <_> + 14 6 6 2 3. + <_> + + <_> + 8 17 2 3 -1. + <_> + 8 18 2 1 3. + <_> + + <_> + 16 4 4 6 -1. + <_> + 16 6 4 2 3. + <_> + + <_> + 0 4 4 6 -1. + <_> + 0 6 4 2 3. + <_> + + <_> + 14 6 2 3 -1. + <_> + 14 6 1 3 2. + <_> + + <_> + 4 9 8 1 -1. + <_> + 8 9 4 1 2. + <_> + + <_> + 8 12 4 3 -1. + <_> + 8 13 4 1 3. + <_> + + <_> + 5 12 10 6 -1. + <_> + 5 14 10 2 3. + <_> + + <_> + 11 12 1 2 -1. + <_> + 11 13 1 1 2. + <_> + + <_> + 8 15 4 2 -1. + <_> + 8 16 4 1 2. + <_> + + <_> + 6 9 8 8 -1. + <_> + 10 9 4 4 2. + <_> + 6 13 4 4 2. + <_> + + <_> + 7 12 4 6 -1. + <_> + 7 12 2 3 2. + <_> + 9 15 2 3 2. + <_> + + <_> + 10 11 3 1 -1. + <_> + 11 11 1 1 3. + <_> + + <_> + 9 7 2 10 -1. + <_> + 9 7 1 5 2. + <_> + 10 12 1 5 2. + <_> + + <_> + 8 0 6 6 -1. + <_> + 10 0 2 6 3. + <_> + + <_> + 3 11 2 6 -1. + <_> + 3 13 2 2 3. + <_> + + <_> + 16 12 1 2 -1. + <_> + 16 13 1 1 2. + <_> + + <_> + 1 14 6 6 -1. + <_> + 1 14 3 3 2. + <_> + 4 17 3 3 2. + <_> + + <_> + 13 1 3 6 -1. + <_> + 14 1 1 6 3. + <_> + + <_> + 8 8 2 2 -1. + <_> + 8 9 2 1 2. + <_> + + <_> + 9 9 3 3 -1. + <_> + 10 9 1 3 3. + <_> + + <_> + 8 7 3 3 -1. + <_> + 8 8 3 1 3. + <_> + + <_> + 14 0 2 3 -1. + <_> + 14 0 1 3 2. + <_> + + <_> + 1 0 18 9 -1. + <_> + 7 0 6 9 3. + <_> + + <_> + 11 5 4 15 -1. + <_> + 11 5 2 15 2. + <_> + + <_> + 5 5 4 15 -1. + <_> + 7 5 2 15 2. + <_> + + <_> + 14 0 2 3 -1. + <_> + 14 0 1 3 2. + <_> + + <_> + 4 0 2 3 -1. + <_> + 5 0 1 3 2. + <_> + + <_> + 11 12 2 2 -1. + <_> + 12 12 1 1 2. + <_> + 11 13 1 1 2. + <_> + + <_> + 7 12 2 2 -1. + <_> + 7 12 1 1 2. + <_> + 8 13 1 1 2. + <_> + + <_> + 12 0 3 4 -1. + <_> + 13 0 1 4 3. + <_> + + <_> + 4 11 3 3 -1. + <_> + 4 12 3 1 3. + <_> + + <_> + 12 7 4 2 -1. + <_> + 12 8 4 1 2. + <_> + + <_> + 8 10 3 2 -1. + <_> + 9 10 1 2 3. + <_> + + <_> + 9 9 3 2 -1. + <_> + 10 9 1 2 3. + <_> + + <_> + 8 9 3 2 -1. + <_> + 9 9 1 2 3. + <_> + + <_> + 12 0 3 4 -1. + <_> + 13 0 1 4 3. + <_> + + <_> + 5 0 3 4 -1. + <_> + 6 0 1 4 3. + <_> + + <_> + 4 14 12 4 -1. + <_> + 10 14 6 2 2. + <_> + 4 16 6 2 2. + <_> + + <_> + 8 13 2 3 -1. + <_> + 8 14 2 1 3. + <_> + + <_> + 10 10 3 8 -1. + <_> + 10 14 3 4 2. + <_> + + <_> + 8 10 4 8 -1. + <_> + 8 10 2 4 2. + <_> + 10 14 2 4 2. + <_> + + <_> + 10 8 3 1 -1. + <_> + 11 8 1 1 3. + <_> + + <_> + 9 12 1 6 -1. + <_> + 9 15 1 3 2. + <_> + + <_> + 10 8 3 1 -1. + <_> + 11 8 1 1 3. + <_> + + <_> + 7 8 3 1 -1. + <_> + 8 8 1 1 3. + <_> + + <_> + 5 2 15 14 -1. + <_> + 5 9 15 7 2. + <_> + + <_> + 2 1 2 10 -1. + <_> + 2 1 1 5 2. + <_> + 3 6 1 5 2. + <_> + + <_> + 14 14 2 3 -1. + <_> + 14 15 2 1 3. + <_> + + <_> + 2 7 3 3 -1. + <_> + 3 7 1 3 3. + <_> + + <_> + 17 4 3 3 -1. + <_> + 17 5 3 1 3. + <_> + + <_> + 0 4 3 3 -1. + <_> + 0 5 3 1 3. + <_> + + <_> + 13 5 6 2 -1. + <_> + 16 5 3 1 2. + <_> + 13 6 3 1 2. + <_> + + <_> + 4 19 12 1 -1. + <_> + 8 19 4 1 3. + <_> + + <_> + 12 12 2 4 -1. + <_> + 12 14 2 2 2. + <_> + + <_> + 3 15 1 3 -1. + <_> + 3 16 1 1 3. + <_> + + <_> + 11 16 6 4 -1. + <_> + 11 16 3 4 2. + <_> + + <_> + 2 10 3 10 -1. + <_> + 3 10 1 10 3. + <_> + + <_> + 12 8 2 4 -1. + <_> + 12 8 1 4 2. + <_> + + <_> + 6 8 2 4 -1. + <_> + 7 8 1 4 2. + <_> + + <_> + 10 14 2 3 -1. + <_> + 10 14 1 3 2. + <_> + + <_> + 5 1 10 3 -1. + <_> + 10 1 5 3 2. + <_> + + <_> + 10 7 3 2 -1. + <_> + 11 7 1 2 3. + <_> + + <_> + 5 6 9 2 -1. + <_> + 8 6 3 2 3. + <_> + + <_> + 9 8 2 2 -1. + <_> + 9 9 2 1 2. + <_> + + <_> + 2 11 16 6 -1. + <_> + 2 11 8 3 2. + <_> + 10 14 8 3 2. + <_> + + <_> + 12 7 2 2 -1. + <_> + 13 7 1 1 2. + <_> + 12 8 1 1 2. + <_> + + <_> + 9 5 2 3 -1. + <_> + 9 6 2 1 3. + <_> + + <_> + 9 7 3 2 -1. + <_> + 10 7 1 2 3. + <_> + + <_> + 5 1 8 12 -1. + <_> + 5 7 8 6 2. + <_> + + <_> + 13 5 2 2 -1. + <_> + 13 6 2 1 2. + <_> + + <_> + 5 5 2 2 -1. + <_> + 5 6 2 1 2. + <_> + + <_> + 12 4 3 3 -1. + <_> + 12 5 3 1 3. + <_> + + <_> + 4 14 2 3 -1. + <_> + 4 15 2 1 3. + <_> + + <_> + 12 4 3 3 -1. + <_> + 12 5 3 1 3. + <_> + + <_> + 5 4 3 3 -1. + <_> + 5 5 3 1 3. + <_> + + <_> + 9 14 2 6 -1. + <_> + 10 14 1 3 2. + <_> + 9 17 1 3 2. + <_> + + <_> + 8 14 3 2 -1. + <_> + 9 14 1 2 3. + <_> + + <_> + 9 5 6 6 -1. + <_> + 11 5 2 6 3. + <_> + + <_> + 5 5 6 6 -1. + <_> + 7 5 2 6 3. + <_> + + <_> + 13 13 1 2 -1. + <_> + 13 14 1 1 2. + <_> + + <_> + 0 2 10 2 -1. + <_> + 0 3 10 1 2. + <_> + + <_> + 13 13 1 2 -1. + <_> + 13 14 1 1 2. + <_> + + <_> + 5 7 2 2 -1. + <_> + 5 7 1 1 2. + <_> + 6 8 1 1 2. + <_> + + <_> + 13 5 2 7 -1. + <_> + 13 5 1 7 2. + <_> + + <_> + 6 13 1 2 -1. + <_> + 6 14 1 1 2. + <_> + + <_> + 11 0 3 7 -1. + <_> + 12 0 1 7 3. + <_> + + <_> + 0 3 2 16 -1. + <_> + 0 3 1 8 2. + <_> + 1 11 1 8 2. + <_> + + <_> + 11 0 3 7 -1. + <_> + 12 0 1 7 3. + <_> + + <_> + 6 0 3 7 -1. + <_> + 7 0 1 7 3. + <_> + + <_> + 11 16 8 4 -1. + <_> + 11 16 4 4 2. + <_> + + <_> + 1 16 8 4 -1. + <_> + 5 16 4 4 2. + <_> + + <_> + 13 5 2 7 -1. + <_> + 13 5 1 7 2. + <_> + + <_> + 5 5 2 7 -1. + <_> + 6 5 1 7 2. + <_> + + <_> + 18 6 2 14 -1. + <_> + 18 13 2 7 2. + <_> + + <_> + 6 10 3 4 -1. + <_> + 6 12 3 2 2. + <_> + + <_> + 14 7 1 2 -1. + <_> + 14 8 1 1 2. + <_> + + <_> + 0 1 18 6 -1. + <_> + 0 1 9 3 2. + <_> + 9 4 9 3 2. + <_> + + <_> + 14 7 1 2 -1. + <_> + 14 8 1 1 2. + <_> + + <_> + 0 6 2 14 -1. + <_> + 0 13 2 7 2. + <_> + + <_> + 17 0 3 12 -1. + <_> + 18 0 1 12 3. + <_> + + <_> + 0 6 18 3 -1. + <_> + 0 7 18 1 3. + <_> + + <_> + 6 0 14 16 -1. + <_> + 6 8 14 8 2. + <_> + + <_> + 0 0 3 12 -1. + <_> + 1 0 1 12 3. + <_> + + <_> + 13 0 3 7 -1. + <_> + 14 0 1 7 3. + <_> + + <_> + 5 7 1 2 -1. + <_> + 5 8 1 1 2. + <_> + + <_> + 14 4 6 6 -1. + <_> + 14 6 6 2 3. + <_> + + <_> + 5 7 7 2 -1. + <_> + 5 8 7 1 2. + <_> + + <_> + 8 6 6 9 -1. + <_> + 8 9 6 3 3. + <_> + + <_> + 5 4 6 1 -1. + <_> + 7 4 2 1 3. + <_> + + <_> + 13 0 6 4 -1. + <_> + 16 0 3 2 2. + <_> + 13 2 3 2 2. + <_> + + <_> + 1 2 18 12 -1. + <_> + 1 6 18 4 3. + <_> + + <_> + 3 2 17 12 -1. + <_> + 3 6 17 4 3. + <_> + + <_> + 5 14 7 3 -1. + <_> + 5 15 7 1 3. + <_> + + <_> + 10 14 1 3 -1. + <_> + 10 15 1 1 3. + <_> + + <_> + 3 14 3 3 -1. + <_> + 3 15 3 1 3. + <_> + + <_> + 14 4 6 6 -1. + <_> + 14 6 6 2 3. + <_> + + <_> + 0 4 6 6 -1. + <_> + 0 6 6 2 3. + <_> + + <_> + 12 5 4 3 -1. + <_> + 12 6 4 1 3. + <_> + + <_> + 4 5 4 3 -1. + <_> + 4 6 4 1 3. + <_> + + <_> + 18 0 2 6 -1. + <_> + 18 2 2 2 3. + <_> + + <_> + 8 1 4 9 -1. + <_> + 10 1 2 9 2. + <_> + + <_> + 6 6 8 2 -1. + <_> + 6 6 4 2 2. + <_> + + <_> + 6 5 4 2 -1. + <_> + 6 5 2 1 2. + <_> + 8 6 2 1 2. + <_> + + <_> + 10 5 2 3 -1. + <_> + 10 6 2 1 3. + <_> + + <_> + 9 5 1 3 -1. + <_> + 9 6 1 1 3. + <_> + + <_> + 9 10 2 2 -1. + <_> + 9 11 2 1 2. + <_> + + <_> + 0 8 4 3 -1. + <_> + 0 9 4 1 3. + <_> + + <_> + 6 0 8 6 -1. + <_> + 6 3 8 3 2. + <_> + + <_> + 1 0 6 4 -1. + <_> + 1 0 3 2 2. + <_> + 4 2 3 2 2. + <_> + + <_> + 13 0 3 7 -1. + <_> + 14 0 1 7 3. + <_> + + <_> + 9 16 2 2 -1. + <_> + 9 17 2 1 2. + <_> + + <_> + 11 4 6 10 -1. + <_> + 11 9 6 5 2. + <_> + + <_> + 0 10 19 2 -1. + <_> + 0 11 19 1 2. + <_> + + <_> + 9 5 8 9 -1. + <_> + 9 8 8 3 3. + <_> + + <_> + 4 0 3 7 -1. + <_> + 5 0 1 7 3. + <_> + + <_> + 8 6 4 12 -1. + <_> + 10 6 2 6 2. + <_> + 8 12 2 6 2. + <_> + + <_> + 0 2 6 4 -1. + <_> + 0 4 6 2 2. + <_> + + <_> + 8 15 4 3 -1. + <_> + 8 16 4 1 3. + <_> + + <_> + 8 0 3 7 -1. + <_> + 9 0 1 7 3. + <_> + + <_> + 9 5 3 4 -1. + <_> + 10 5 1 4 3. + <_> + + <_> + 8 5 3 4 -1. + <_> + 9 5 1 4 3. + <_> + + <_> + 7 6 6 1 -1. + <_> + 9 6 2 1 3. + <_> + + <_> + 7 14 4 4 -1. + <_> + 7 14 2 2 2. + <_> + 9 16 2 2 2. + <_> + + <_> + 13 14 4 6 -1. + <_> + 15 14 2 3 2. + <_> + 13 17 2 3 2. + <_> + + <_> + 7 8 1 8 -1. + <_> + 7 12 1 4 2. + <_> + + <_> + 16 0 2 8 -1. + <_> + 17 0 1 4 2. + <_> + 16 4 1 4 2. + <_> + + <_> + 2 0 2 8 -1. + <_> + 2 0 1 4 2. + <_> + 3 4 1 4 2. + <_> + + <_> + 6 1 14 3 -1. + <_> + 6 2 14 1 3. + <_> + + <_> + 7 9 3 10 -1. + <_> + 7 14 3 5 2. + <_> + + <_> + 9 14 2 2 -1. + <_> + 9 15 2 1 2. + <_> + + <_> + 7 7 6 8 -1. + <_> + 7 11 6 4 2. + <_> + + <_> + 9 7 3 6 -1. + <_> + 9 10 3 3 2. + <_> + + <_> + 7 13 3 3 -1. + <_> + 7 14 3 1 3. + <_> + + <_> + 9 9 2 2 -1. + <_> + 9 10 2 1 2. + <_> + + <_> + 0 1 18 2 -1. + <_> + 6 1 6 2 3. + <_> + + <_> + 7 1 6 14 -1. + <_> + 7 8 6 7 2. + <_> + + <_> + 1 9 18 1 -1. + <_> + 7 9 6 1 3. + <_> + + <_> + 9 7 2 2 -1. + <_> + 9 7 1 2 2. + <_> + + <_> + 9 3 2 9 -1. + <_> + 10 3 1 9 2. + <_> + + <_> + 18 14 2 3 -1. + <_> + 18 15 2 1 3. + <_> + + <_> + 7 11 3 1 -1. + <_> + 8 11 1 1 3. + <_> + + <_> + 10 8 3 4 -1. + <_> + 11 8 1 4 3. + <_> + + <_> + 7 14 3 6 -1. + <_> + 8 14 1 6 3. + <_> + + <_> + 10 8 3 4 -1. + <_> + 11 8 1 4 3. + <_> + + <_> + 7 8 3 4 -1. + <_> + 8 8 1 4 3. + <_> + + <_> + 7 9 6 9 -1. + <_> + 7 12 6 3 3. + <_> + + <_> + 0 14 2 3 -1. + <_> + 0 15 2 1 3. + <_> + + <_> + 11 12 1 2 -1. + <_> + 11 13 1 1 2. + <_> + + <_> + 4 3 8 3 -1. + <_> + 8 3 4 3 2. + <_> + + <_> + 0 4 20 6 -1. + <_> + 0 4 10 6 2. + <_> + + <_> + 9 14 1 3 -1. + <_> + 9 15 1 1 3. + <_> + + <_> + 8 14 4 3 -1. + <_> + 8 15 4 1 3. + <_> + + <_> + 0 15 14 4 -1. + <_> + 0 17 14 2 2. + <_> + + <_> + 1 14 18 6 -1. + <_> + 1 17 18 3 2. + <_> + + <_> + 0 0 10 6 -1. + <_> + 0 0 5 3 2. + <_> + 5 3 5 3 2. + diff --git a/OpenCVComponent/Assets/haarcascade_mouth.xml b/OpenCVComponent/Assets/haarcascade_mouth.xml new file mode 100755 index 0000000..ae4ee24 --- /dev/null +++ b/OpenCVComponent/Assets/haarcascade_mouth.xml @@ -0,0 +1,21991 @@ + + + + + + 25 15 + + <_> + + + <_> + + <_> + + + + <_> + 0 0 14 9 -1. + <_> + 0 3 14 3 3. + 0 + -0.1192855015397072 + 0.7854182124137878 + -0.4541360139846802 + <_> + + <_> + + + + <_> + 17 1 8 14 -1. + <_> + 17 8 8 7 2. + 0 + -0.0641647726297379 + -0.7407680749893189 + 0.2652035951614380 + <_> + + <_> + + + + <_> + 7 3 11 6 -1. + <_> + 7 5 11 2 3. + 0 + 0.0910761803388596 + -0.2063370943069458 + 0.8400946259498596 + <_> + + <_> + + + + <_> + 5 2 15 6 -1. + <_> + 5 4 15 2 3. + 0 + -0.1129330024123192 + 0.8284121751785278 + -0.1866362988948822 + <_> + + <_> + + + + <_> + 6 4 11 6 -1. + <_> + 6 6 11 2 3. + 0 + -0.0741933435201645 + 0.8354660272598267 + -0.1527701020240784 + <_> + + <_> + + + + <_> + 17 1 6 3 -1. + <_> + 19 1 2 3 3. + 0 + 2.1404659491963685e-005 + -0.0716945603489876 + 0.1858334988355637 + <_> + + <_> + + + + <_> + 5 0 15 6 -1. + <_> + 5 2 15 2 3. + 0 + -0.0996975302696228 + 0.6870458126068115 + -0.1721730977296829 + <_> + + <_> + + + + <_> + 7 3 13 6 -1. + <_> + 7 5 13 2 3. + 0 + -0.0900413617491722 + 0.7310237884521484 + -0.1368771940469742 + <_> + + <_> + + + + <_> + 5 3 6 5 -1. + <_> + 8 3 3 5 2. + 0 + 2.5138311320915818e-004 + -0.3469826877117157 + 0.3647777140140533 + <_> + + <_> + + + + <_> + 21 14 4 1 -1. + <_> + 21 14 2 1 2. + 0 + 1.6144449546118267e-005 + -0.3085466027259827 + 0.2320024073123932 + <_> + + <_> + + + + <_> + 0 3 3 12 -1. + <_> + 0 7 3 4 3. + 0 + 1.9363909814273939e-005 + -0.3819856047630310 + 0.2404107004404068 + <_> + + <_> + + + + <_> + 22 10 3 4 -1. + <_> + 22 11 3 2 2. + 0 + 6.9673648104071617e-003 + 0.0545878112316132 + -0.7487065792083740 + <_> + + <_> + + + + <_> + 0 10 3 4 -1. + <_> + 0 11 3 2 2. + 0 + -4.7189309261739254e-003 + -0.7476686835289002 + 0.1205869019031525 + -1.4372119903564453 + -1 + -1 + <_> + + + <_> + + <_> + + + + <_> + 5 0 15 8 -1. + <_> + 5 2 15 4 2. + 0 + -0.1006335020065308 + 0.7848083972930908 + -0.3866829872131348 + <_> + + <_> + + + + <_> + 20 0 5 9 -1. + <_> + 20 3 5 3 3. + 0 + -0.0366767607629299 + 0.5453233718872070 + -0.4012677967548370 + <_> + + <_> + + + + <_> + 6 2 13 4 -1. + <_> + 6 4 13 2 2. + 0 + 0.0815562233328819 + -0.1315398067235947 + 0.8084958195686340 + <_> + + <_> + + + + <_> + 7 2 15 6 -1. + <_> + 7 4 15 2 3. + 0 + -0.1064186021685600 + 0.6782389879226685 + -0.2083356976509094 + <_> + + <_> + + + + <_> + 2 3 4 12 -1. + <_> + 2 9 4 6 2. + 0 + 0.0156307406723499 + -0.3749788105487824 + 0.3150509893894196 + <_> + + <_> + + + + <_> + 6 1 14 6 -1. + <_> + 6 3 14 2 3. + 0 + 0.0711290463805199 + -0.1557385027408600 + 0.7050542831420898 + <_> + + <_> + + + + <_> + 8 3 9 6 -1. + <_> + 8 5 9 2 3. + 0 + 0.0736639127135277 + -0.1547683030366898 + 0.6715884804725647 + <_> + + <_> + + + + <_> + 21 0 4 6 -1. + <_> + 21 3 4 3 2. + 0 + -1.0592950275167823e-004 + 0.1365388035774231 + -0.2670182883739471 + <_> + + <_> + + + + <_> + 1 12 1 3 -1. + <_> + 1 13 1 1 3. + 0 + -1.9239520188421011e-003 + -0.7261438965797424 + 0.1364576965570450 + <_> + + <_> + + + + <_> + 23 12 1 3 -1. + <_> + 23 13 1 1 3. + 0 + 2.3057300131767988e-003 + 0.0706136971712112 + -0.6423184275627136 + <_> + + <_> + + + + <_> + 1 12 1 3 -1. + <_> + 1 13 1 1 3. + 0 + 1.8073299434036016e-003 + 0.1355642974376679 + -0.7050786018371582 + <_> + + <_> + + + + <_> + 7 7 11 8 -1. + <_> + 7 9 11 4 2. + 0 + -0.0664333626627922 + 0.6158788204193115 + -0.1400263011455536 + <_> + + <_> + + + + <_> + 8 4 9 6 -1. + <_> + 8 6 9 2 3. + 0 + -0.0689277201890945 + 0.6765924096107483 + -0.1224988028407097 + -1.5416599512100220 + 0 + -1 + <_> + + + <_> + + <_> + + + + <_> + 1 0 15 9 -1. + <_> + 1 3 15 3 3. + 0 + -0.1822655051946640 + 0.5961514711380005 + -0.3195483088493347 + <_> + + <_> + + + + <_> + 9 0 11 15 -1. + <_> + 9 5 11 5 3. + 0 + 0.2893281877040863 + -0.0240151602774858 + 0.3762707114219666 + <_> + + <_> + + + + <_> + 0 8 3 4 -1. + <_> + 0 9 3 2 2. + 0 + -4.2456621304154396e-003 + -0.7117397785186768 + 0.1214720010757446 + <_> + + <_> + + + + <_> + 7 9 12 6 -1. + <_> + 7 12 12 3 2. + 0 + 0.0545681491494179 + -0.1822118014097214 + 0.4597271978855133 + <_> + + <_> + + + + <_> + 0 5 2 6 -1. + <_> + 0 7 2 2 3. + 0 + -4.4434829615056515e-003 + -0.5354676842689514 + 0.1655835956335068 + <_> + + <_> + + + + <_> + 14 0 2 11 -1. + <_> + 14 0 1 11 2. + 0 + -0.0204923897981644 + -0.8770608901977539 + -0.0151639897376299 + <_> + + <_> + + + + <_> + 0 9 2 6 -1. + <_> + 0 11 2 2 3. + 0 + -4.8007471486926079e-003 + -0.5431423187255859 + 0.1356130987405777 + <_> + + <_> + + + + <_> + 1 0 24 12 -1. + <_> + 13 0 12 6 2. + <_> + 1 6 12 6 2. + 0 + 0.1226660013198853 + 0.1124472022056580 + -0.6574401855468750 + <_> + + <_> + + + + <_> + 0 0 3 4 -1. + <_> + 0 2 3 2 2. + 0 + -5.5254979088203982e-005 + 0.1536739021539688 + -0.3841981887817383 + <_> + + <_> + + + + <_> + 7 3 14 6 -1. + <_> + 7 5 14 2 3. + 0 + -0.1131860986351967 + 0.4927195906639099 + -0.1094276010990143 + <_> + + <_> + + + + <_> + 5 3 15 4 -1. + <_> + 5 5 15 2 2. + 0 + 0.0792956873774529 + -0.1647461056709290 + 0.4720517992973328 + <_> + + <_> + + + + <_> + 8 13 12 1 -1. + <_> + 12 13 4 1 3. + 0 + 0.0148729300126433 + 0.0740143731236458 + -0.5926275849342346 + <_> + + <_> + + + + <_> + 2 3 12 6 -1. + <_> + 8 3 6 6 2. + 0 + 0.0538397915661335 + -0.2111544013023377 + 0.3537890911102295 + <_> + + <_> + + + + <_> + 21 2 4 9 -1. + <_> + 21 2 2 9 2. + 1 + -0.0759592726826668 + 0.5931801795959473 + -0.1090068966150284 + <_> + + <_> + + + + <_> + 6 2 13 6 -1. + <_> + 6 4 13 2 3. + 0 + 0.1158166006207466 + -0.0984905213117599 + 0.5940334796905518 + <_> + + <_> + + + + <_> + 5 3 15 2 -1. + <_> + 5 4 15 1 2. + 0 + -0.0160826407372952 + 0.3794195055961609 + -0.1654051989316940 + <_> + + <_> + + + + <_> + 0 11 5 3 -1. + <_> + 0 12 5 1 3. + 0 + 6.7254770547151566e-003 + 0.0937571078538895 + -0.7060937881469727 + <_> + + <_> + + + + <_> + 14 0 11 14 -1. + <_> + 14 7 11 7 2. + 0 + -0.0611884109675884 + -0.4381029903888702 + 0.0796229690313339 + <_> + + <_> + + + + <_> + 2 10 4 1 -1. + <_> + 3 11 2 1 2. + 1 + -5.5152038112282753e-003 + -0.7019357085227966 + 0.0781789273023605 + <_> + + <_> + + + + <_> + 1 0 24 12 -1. + <_> + 13 0 12 6 2. + <_> + 1 6 12 6 2. + 0 + -0.1988534033298492 + -0.6726130843162537 + 0.0560497716069222 + <_> + + <_> + + + + <_> + 0 4 6 6 -1. + <_> + 0 4 3 3 2. + <_> + 3 7 3 3 2. + 0 + 0.0194473192095757 + -0.1165110021829605 + 0.4151527881622315 + <_> + + <_> + + + + <_> + 23 9 1 4 -1. + <_> + 22 10 1 2 2. + 1 + -4.6706218272447586e-003 + -0.6090158820152283 + 0.1049979999661446 + <_> + + <_> + + + + <_> + 2 9 4 1 -1. + <_> + 3 10 2 1 2. + 1 + 4.0827528573572636e-003 + 0.0689968466758728 + -0.5490871071815491 + <_> + + <_> + + + + <_> + 16 4 8 10 -1. + <_> + 20 4 4 5 2. + <_> + 16 9 4 5 2. + 0 + -0.0201979596167803 + 0.2884930074214935 + -0.1804888993501663 + <_> + + <_> + + + + <_> + 8 7 9 6 -1. + <_> + 8 9 9 2 3. + 0 + 0.0504430681467056 + -0.0897706300020218 + 0.4609920978546143 + <_> + + <_> + + + + <_> + 11 12 4 3 -1. + <_> + 12 12 2 3 2. + 0 + -5.0139562226831913e-003 + -0.4820869863033295 + 0.0588099807500839 + <_> + + <_> + + + + <_> + 0 0 3 3 -1. + <_> + 0 1 3 1 3. + 0 + 8.5741933435201645e-003 + 0.0568646714091301 + -0.5979083180427551 + <_> + + <_> + + + + <_> + 11 9 14 2 -1. + <_> + 11 9 7 2 2. + 0 + -0.0121624497696757 + 0.1446305960416794 + -0.1168325990438461 + <_> + + <_> + + + + <_> + 9 13 4 1 -1. + <_> + 10 13 2 1 2. + 0 + -1.9329390488564968e-003 + -0.5450860857963562 + 0.0609783902764320 + -1.5324319601058960 + 1 + -1 + <_> + + + <_> + + <_> + + + + <_> + 0 0 8 6 -1. + <_> + 0 3 8 3 2. + 0 + -0.0320550985634327 + 0.4280030131340027 + -0.4258942902088165 + <_> + + <_> + + + + <_> + 5 1 15 6 -1. + <_> + 5 3 15 2 3. + 0 + -0.1231034025549889 + 0.5121241807937622 + -0.2055584937334061 + <_> + + <_> + + + + <_> + 0 7 4 3 -1. + <_> + 0 8 4 1 3. + 0 + -5.8588259853422642e-003 + -0.7101820707321167 + 0.1075906008481979 + <_> + + <_> + + + + <_> + 3 3 20 6 -1. + <_> + 8 3 10 6 2. + 0 + 0.0977141335606575 + -0.1477957963943481 + 0.4571174979209900 + <_> + + <_> + + + + <_> + 0 6 24 5 -1. + <_> + 6 6 12 5 2. + 0 + -0.0527394600212574 + 0.3743767142295837 + -0.2183827012777329 + <_> + + <_> + + + + <_> + 8 5 9 6 -1. + <_> + 8 7 9 2 3. + 0 + 0.0584189109504223 + -0.1386294066905975 + 0.4993282854557037 + <_> + + <_> + + + + <_> + 5 2 14 4 -1. + <_> + 5 4 14 2 2. + 0 + 0.0887569189071655 + -0.1315895020961762 + 0.6216561794281006 + <_> + + <_> + + + + <_> + 22 8 3 6 -1. + <_> + 22 10 3 2 3. + 0 + 0.0145876696333289 + 0.0915696695446968 + -0.5815675258636475 + <_> + + <_> + + + + <_> + 3 9 18 2 -1. + <_> + 3 9 9 1 2. + <_> + 12 10 9 1 2. + 0 + 0.1044600009918213 + 5.2740359678864479e-003 + -5.6644519531250000e+004 + <_> + + <_> + + + + <_> + 22 8 3 6 -1. + <_> + 22 10 3 2 3. + 0 + -8.4322784096002579e-003 + -0.4866046011447907 + 0.0979617610573769 + <_> + + <_> + + + + <_> + 0 0 24 6 -1. + <_> + 0 0 12 3 2. + <_> + 12 3 12 3 2. + 0 + 0.0406559295952320 + 0.1391579061746597 + -0.3656015992164612 + <_> + + <_> + + + + <_> + 14 11 4 4 -1. + <_> + 15 11 2 4 2. + 0 + 6.3366899266839027e-003 + 0.0641745477914810 + -0.6245471239089966 + <_> + + <_> + + + + <_> + 5 5 15 2 -1. + <_> + 5 6 15 1 2. + 0 + 0.0158455893397331 + -0.1791914999485016 + 0.2889905869960785 + <_> + + <_> + + + + <_> + 5 4 15 6 -1. + <_> + 5 6 15 2 3. + 0 + -0.0746863335371017 + 0.5424023270606995 + -0.1314727962017059 + <_> + + <_> + + + + <_> + 0 7 2 3 -1. + <_> + 0 8 2 1 3. + 0 + 4.7695250250399113e-003 + 0.0965340435504913 + -0.6561154723167419 + <_> + + <_> + + + + <_> + 6 6 13 6 -1. + <_> + 6 8 13 2 3. + 0 + -0.0535226687788963 + 0.4636800885200501 + -0.1353430002927780 + <_> + + <_> + + + + <_> + 0 11 6 3 -1. + <_> + 0 12 6 1 3. + 0 + -6.3648750074207783e-003 + -0.6624563932418823 + 0.0684857368469238 + <_> + + <_> + + + + <_> + 11 0 14 14 -1. + <_> + 11 7 14 7 2. + 0 + -0.2447337061166763 + -0.8181337118148804 + 0.0450799688696861 + <_> + + <_> + + + + <_> + 7 13 4 1 -1. + <_> + 8 13 2 1 2. + 0 + -2.4634969886392355e-003 + -0.7681804895401001 + 0.0495845898985863 + <_> + + <_> + + + + <_> + 6 9 13 6 -1. + <_> + 6 11 13 2 3. + 0 + -0.0358034893870354 + 0.3749603927135468 + -0.1447928994894028 + <_> + + <_> + + + + <_> + 0 9 4 4 -1. + <_> + 0 10 4 2 2. + 0 + -5.6720529682934284e-003 + -0.6127536296844482 + 0.0935847163200378 + <_> + + <_> + + + + <_> + 21 0 4 6 -1. + <_> + 21 3 4 3 2. + 0 + -0.0132687101140618 + 0.2863784134387970 + -0.2551889121532440 + <_> + + <_> + + + + <_> + 0 12 6 3 -1. + <_> + 0 13 6 1 3. + 0 + -6.2518939375877380e-003 + -0.5896773934364319 + 0.0677111670374870 + <_> + + <_> + + + + <_> + 16 11 4 3 -1. + <_> + 17 11 2 3 2. + 0 + 7.3092570528388023e-003 + 0.0272198095917702 + -0.5714861154556274 + <_> + + <_> + + + + <_> + 0 7 10 8 -1. + <_> + 0 7 5 4 2. + <_> + 5 11 5 4 2. + 0 + 0.0258194394409657 + -0.1326007992029190 + 0.3050251901149750 + <_> + + <_> + + + + <_> + 22 2 3 8 -1. + <_> + 22 2 3 4 2. + 1 + -0.0211078803986311 + 0.1200629025697708 + -0.1475265026092529 + <_> + + <_> + + + + <_> + 1 3 16 4 -1. + <_> + 9 3 8 4 2. + 0 + 0.0408483408391476 + -0.1736883074045181 + 0.2530446052551270 + <_> + + <_> + + + + <_> + 1 13 24 2 -1. + <_> + 13 13 12 1 2. + <_> + 1 14 12 1 2. + 0 + -0.0179475992918015 + -0.7117617130279541 + 0.0583698004484177 + <_> + + <_> + + + + <_> + 5 5 4 10 -1. + <_> + 6 5 2 10 2. + 0 + -0.0138895902782679 + -0.6778132915496826 + 0.0435630008578300 + <_> + + <_> + + + + <_> + 13 7 2 6 -1. + <_> + 11 9 2 2 3. + 1 + -9.8488982766866684e-003 + 0.1479212939739227 + -0.0897465273737907 + <_> + + <_> + + + + <_> + 8 9 8 6 -1. + <_> + 8 12 8 3 2. + 0 + -0.0659847036004066 + 0.5683801770210266 + -0.0681742578744888 + <_> + + <_> + + + + <_> + 24 7 1 4 -1. + <_> + 24 8 1 2 2. + 0 + -1.8370660254731774e-003 + -0.4986937940120697 + 0.0779643580317497 + <_> + + <_> + + + + <_> + 5 7 15 6 -1. + <_> + 5 9 15 2 3. + 0 + -0.0277651809155941 + 0.2679949104785919 + -0.1382624953985214 + <_> + + <_> + + + + <_> + 21 8 4 3 -1. + <_> + 21 9 4 1 3. + 0 + 9.9889356642961502e-003 + 0.0445619411766529 + -0.7317379117012024 + -1.4849940538406372 + 2 + -1 + <_> + + + <_> + + <_> + + + + <_> + 5 2 15 4 -1. + <_> + 5 3 15 2 2. + 0 + -0.0456383489072323 + 0.6275423169136047 + -0.2494937032461166 + <_> + + <_> + + + + <_> + 6 4 15 3 -1. + <_> + 6 5 15 1 3. + 0 + -0.0310676805675030 + 0.6427816152572632 + -0.1671900004148483 + <_> + + <_> + + + + <_> + 0 3 2 12 -1. + <_> + 0 3 1 6 2. + <_> + 1 9 1 6 2. + 0 + 3.0193419661372900e-003 + -0.2399346977472305 + 0.3676818013191223 + <_> + + <_> + + + + <_> + 7 3 11 4 -1. + <_> + 7 4 11 2 2. + 0 + 0.0315676406025887 + -0.1147691980004311 + 0.5750172734260559 + <_> + + <_> + + + + <_> + 0 0 6 6 -1. + <_> + 0 3 6 3 2. + 0 + -6.4146341755986214e-003 + 0.2154625058174133 + -0.3768770098686218 + <_> + + <_> + + + + <_> + 24 3 1 12 -1. + <_> + 24 7 1 4 3. + 0 + -5.7010860182344913e-003 + -0.4533824026584625 + 0.0946888476610184 + <_> + + <_> + + + + <_> + 0 0 24 12 -1. + <_> + 0 0 12 6 2. + <_> + 12 6 12 6 2. + 0 + 0.1890300065279007 + 0.0801155269145966 + -0.7184885144233704 + <_> + + <_> + + + + <_> + 1 1 24 14 -1. + <_> + 13 1 12 7 2. + <_> + 1 8 12 7 2. + 0 + 0.1293978989124298 + 0.1093719005584717 + -0.5197048783302307 + <_> + + <_> + + + + <_> + 5 3 8 4 -1. + <_> + 5 3 8 2 2. + 1 + -0.0657683908939362 + 0.5003104209899902 + -0.1238735020160675 + <_> + + <_> + + + + <_> + 24 9 1 4 -1. + <_> + 23 10 1 2 2. + 1 + -4.0884059853851795e-003 + -0.5118011236190796 + 0.0594223700463772 + <_> + + <_> + + + + <_> + 7 7 11 8 -1. + <_> + 7 9 11 4 2. + 0 + -0.0306642707437277 + 0.2964648902416229 + -0.1741248071193695 + <_> + + <_> + + + + <_> + 24 9 1 4 -1. + <_> + 23 10 1 2 2. + 1 + 2.7700960636138916e-003 + 0.0846907272934914 + -0.4009515047073364 + <_> + + <_> + + + + <_> + 0 6 1 9 -1. + <_> + 0 9 1 3 3. + 0 + -6.2402039766311646e-003 + -0.5560923218727112 + 0.0800850465893745 + <_> + + <_> + + + + <_> + 8 2 9 3 -1. + <_> + 8 3 9 1 3. + 0 + 0.0105152595788240 + -0.1309404969215393 + 0.3612711131572723 + <_> + + <_> + + + + <_> + 9 4 7 4 -1. + <_> + 9 5 7 2 2. + 0 + 0.0181792695075274 + -0.1245180964469910 + 0.3556562960147858 + <_> + + <_> + + + + <_> + 22 0 3 2 -1. + <_> + 22 1 3 1 2. + 0 + 5.3037698380649090e-003 + 0.0638220235705376 + -0.6178466081619263 + <_> + + <_> + + + + <_> + 0 0 13 14 -1. + <_> + 0 7 13 7 2. + 0 + -0.1947806030511856 + -0.7228901982307434 + 0.0475768186151981 + <_> + + <_> + + + + <_> + 21 9 4 4 -1. + <_> + 21 10 4 2 2. + 0 + 7.2230421938002110e-003 + 0.0453382283449173 + -0.5460836291313171 + <_> + + <_> + + + + <_> + 0 9 4 4 -1. + <_> + 0 10 4 2 2. + 0 + 5.0375838764011860e-003 + 0.0804468318820000 + -0.4817472100257874 + <_> + + <_> + + + + <_> + 22 9 1 4 -1. + <_> + 21 10 1 2 2. + 1 + -7.1934829466044903e-003 + -0.5018991827964783 + 0.0128700295463204 + <_> + + <_> + + + + <_> + 3 9 4 1 -1. + <_> + 4 10 2 1 2. + 1 + -4.4941599480807781e-003 + -0.5862709879875183 + 0.0634675025939941 + <_> + + <_> + + + + <_> + 15 3 10 12 -1. + <_> + 20 3 5 6 2. + <_> + 15 9 5 6 2. + 0 + 0.0874131396412849 + -0.0676202401518822 + 0.4797031879425049 + <_> + + <_> + + + + <_> + 0 8 14 6 -1. + <_> + 0 8 7 3 2. + <_> + 7 11 7 3 2. + 0 + -0.0377015694975853 + 0.3913342952728272 + -0.0978809297084808 + <_> + + <_> + + + + <_> + 23 10 1 4 -1. + <_> + 22 11 1 2 2. + 1 + 3.0070370994508266e-003 + 0.0484924912452698 + -0.2472224980592728 + <_> + + <_> + + + + <_> + 0 3 10 12 -1. + <_> + 0 3 5 6 2. + <_> + 5 9 5 6 2. + 0 + 0.0974098667502403 + -0.0669010728597641 + 0.5813519954681397 + <_> + + <_> + + + + <_> + 23 0 2 1 -1. + <_> + 23 0 1 1 2. + 1 + -4.0166568942368031e-003 + -0.5456554293632507 + 0.0363924615085125 + <_> + + <_> + + + + <_> + 8 3 9 3 -1. + <_> + 8 4 9 1 3. + 0 + 0.0104924896731973 + -0.1087466031312943 + 0.3253425061702728 + <_> + + <_> + + + + <_> + 7 5 11 4 -1. + <_> + 7 6 11 2 2. + 0 + 0.0249659996479750 + -0.1137896031141281 + 0.3056510984897614 + <_> + + <_> + + + + <_> + 2 7 20 8 -1. + <_> + 12 7 10 8 2. + 0 + 0.1301030069589615 + -0.1220476999878883 + 0.3035365939140320 + <_> + + <_> + + + + <_> + 12 5 9 8 -1. + <_> + 15 5 3 8 3. + 0 + -0.0843720883131027 + -0.6943122148513794 + 0.0178856607526541 + <_> + + <_> + + + + <_> + 2 0 1 2 -1. + <_> + 2 0 1 1 2. + 1 + -2.9267850331962109e-003 + -0.5401834845542908 + 0.0564073212444782 + <_> + + <_> + + + + <_> + 21 3 4 4 -1. + <_> + 22 4 2 4 2. + 1 + -0.0206745099276304 + 0.4180921018123627 + -0.0685340464115143 + <_> + + <_> + + + + <_> + 4 5 9 8 -1. + <_> + 7 5 3 8 3. + 0 + -0.0514506399631500 + -0.6289098262786865 + 0.0529876984655857 + <_> + + <_> + + + + <_> + 22 10 3 2 -1. + <_> + 22 10 3 1 2. + 1 + -8.9261196553707123e-003 + -0.4644356071949005 + 0.0236550793051720 + <_> + + <_> + + + + <_> + 0 5 24 5 -1. + <_> + 6 5 12 5 2. + 0 + -0.0830484703183174 + 0.3304196894168854 + -0.0938697606325150 + <_> + + <_> + + + + <_> + 9 7 7 3 -1. + <_> + 9 8 7 1 3. + 0 + 0.0113369999453425 + -0.0979600325226784 + 0.3484053015708923 + <_> + + <_> + + + + <_> + 2 0 20 9 -1. + <_> + 7 0 10 9 2. + 0 + 0.0827779024839401 + -0.1159391030669212 + 0.2680957913398743 + <_> + + <_> + + + + <_> + 11 2 8 9 -1. + <_> + 13 2 4 9 2. + 0 + -0.0478848814964294 + -0.6079211235046387 + 0.0222362894564867 + <_> + + <_> + + + + <_> + 1 8 4 1 -1. + <_> + 2 9 2 1 2. + 1 + -3.8582698907703161e-003 + -0.4688901007175446 + 0.0554540418088436 + <_> + + <_> + + + + <_> + 19 5 6 10 -1. + <_> + 22 5 3 5 2. + <_> + 19 10 3 5 2. + 0 + -0.0334531292319298 + 0.4192667901515961 + -0.0631088465452194 + <_> + + <_> + + + + <_> + 0 5 6 10 -1. + <_> + 0 5 3 5 2. + <_> + 3 10 3 5 2. + 0 + 0.0126036396250129 + -0.1227632984519005 + 0.2175220996141434 + <_> + + <_> + + + + <_> + 10 10 9 2 -1. + <_> + 13 10 3 2 3. + 0 + 0.0262600891292095 + 0.0162896700203419 + -0.5688759088516235 + -1.5437099933624268 + 3 + -1 + <_> + + + <_> + + <_> + + + + <_> + 5 2 15 2 -1. + <_> + 5 3 15 1 2. + 0 + -0.0197793096303940 + 0.4472095072269440 + -0.2573797106742859 + <_> + + <_> + + + + <_> + 21 4 4 3 -1. + <_> + 21 4 2 3 2. + 0 + -9.1997236013412476e-003 + 0.4397894144058228 + -0.1382309943437576 + <_> + + <_> + + + + <_> + 1 5 15 4 -1. + <_> + 1 6 15 2 2. + 0 + 0.0222425796091557 + -0.1761150062084198 + 0.3406811952590942 + <_> + + <_> + + + + <_> + 21 5 4 10 -1. + <_> + 23 5 2 5 2. + <_> + 21 10 2 5 2. + 0 + 5.3650550544261932e-003 + -0.1087490990757942 + 0.1631094068288803 + <_> + + <_> + + + + <_> + 0 0 21 8 -1. + <_> + 7 0 7 8 3. + 0 + 0.7425013780593872 + 4.6233131433837116e-004 + -1.4172740478515625e+003 + <_> + + <_> + + + + <_> + 5 0 15 6 -1. + <_> + 5 2 15 2 3. + 0 + -0.1289999037981033 + 0.4220936894416809 + -0.1264209002256393 + <_> + + <_> + + + + <_> + 2 2 21 3 -1. + <_> + 9 2 7 3 3. + 0 + 0.4214023947715759 + 3.0299068894237280e-003 + 1.2071870117187500e+003 + <_> + + <_> + + + + <_> + 6 3 15 6 -1. + <_> + 6 5 15 2 3. + 0 + -0.1431712061166763 + 0.5070012211799622 + -0.1091170981526375 + <_> + + <_> + + + + <_> + 0 5 4 10 -1. + <_> + 0 5 2 5 2. + <_> + 2 10 2 5 2. + 0 + 4.4366121292114258e-003 + -0.2218814045190811 + 0.2446105927228928 + <_> + + <_> + + + + <_> + 22 10 1 4 -1. + <_> + 21 11 1 2 2. + 1 + 3.0177310109138489e-003 + 0.1072233989834786 + -0.3470205068588257 + <_> + + <_> + + + + <_> + 0 7 3 4 -1. + <_> + 0 8 3 2 2. + 0 + -4.8220949247479439e-003 + -0.6534119248390198 + 0.0803434476256371 + <_> + + <_> + + + + <_> + 1 3 24 3 -1. + <_> + 7 3 12 3 2. + 0 + 0.0362788289785385 + -0.2207075059413910 + 0.2242490947246552 + <_> + + <_> + + + + <_> + 0 0 24 13 -1. + <_> + 6 0 12 13 2. + 0 + -0.1675994992256165 + 0.4059072136878967 + -0.1054169982671738 + <_> + + <_> + + + + <_> + 5 3 15 4 -1. + <_> + 5 4 15 2 2. + 0 + -0.0509919412434101 + 0.3452283143997192 + -0.1206474006175995 + <_> + + <_> + + + + <_> + 5 4 14 3 -1. + <_> + 5 5 14 1 3. + 0 + 0.0161635298281908 + -0.1465175002813339 + 0.3696750998497009 + <_> + + <_> + + + + <_> + 23 8 2 4 -1. + <_> + 22 9 2 2 2. + 1 + 8.3268675953149796e-003 + 0.0642398297786713 + -0.5490669012069702 + <_> + + <_> + + + + <_> + 2 8 4 2 -1. + <_> + 3 9 2 2 2. + 1 + -7.2614871896803379e-003 + -0.6105815768241882 + 0.0538330897688866 + <_> + + <_> + + + + <_> + 9 8 9 6 -1. + <_> + 9 10 9 2 3. + 0 + -0.0427855290472507 + 0.3435507118701935 + -0.1058441996574402 + <_> + + <_> + + + + <_> + 0 0 11 14 -1. + <_> + 0 7 11 7 2. + 0 + -0.0558885596692562 + -0.4213463068008423 + 0.0855342373251915 + <_> + + <_> + + + + <_> + 1 0 24 12 -1. + <_> + 13 0 12 6 2. + <_> + 1 6 12 6 2. + 0 + 0.1077039018273354 + 0.0796676799654961 + -0.5105268955230713 + <_> + + <_> + + + + <_> + 0 0 3 4 -1. + <_> + 0 2 3 2 2. + 0 + -4.8622798203723505e-005 + 0.1164970993995667 + -0.3022361099720001 + <_> + + <_> + + + + <_> + 7 2 15 4 -1. + <_> + 7 3 15 2 2. + 0 + 0.0272718109190464 + -0.0831976532936096 + 0.3410704135894775 + <_> + + <_> + + + + <_> + 2 10 4 1 -1. + <_> + 3 11 2 1 2. + 1 + 2.7942128945142031e-003 + 0.0836139172315598 + -0.4521746933460236 + <_> + + <_> + + + + <_> + 21 11 4 4 -1. + <_> + 21 12 4 2 2. + 0 + -5.9649557806551456e-003 + -0.5814967751502991 + 0.0588471181690693 + <_> + + <_> + + + + <_> + 1 7 12 8 -1. + <_> + 1 7 6 4 2. + <_> + 7 11 6 4 2. + 0 + -0.0364551208913326 + 0.2987614870071411 + -0.1163965016603470 + <_> + + <_> + + + + <_> + 7 8 11 6 -1. + <_> + 7 11 11 3 2. + 0 + 0.0560359284281731 + -0.1189749017357826 + 0.3490499854087830 + <_> + + <_> + + + + <_> + 0 13 2 2 -1. + <_> + 0 14 2 1 2. + 0 + 1.9068910041823983e-003 + 0.0623399801552296 + -0.5222734212875366 + <_> + + <_> + + + + <_> + 10 3 8 6 -1. + <_> + 12 3 4 6 2. + 0 + -0.0314803011715412 + -0.5988280177116394 + 0.0221100505441427 + <_> + + <_> + + + + <_> + 7 3 8 6 -1. + <_> + 9 3 4 6 2. + 0 + -0.0291779898107052 + -0.7628328204154968 + 0.0378519818186760 + <_> + + <_> + + + + <_> + 22 6 3 3 -1. + <_> + 22 7 3 1 3. + 0 + 9.3441819772124290e-003 + 0.0293787997215986 + -0.5464184880256653 + <_> + + <_> + + + + <_> + 0 5 5 6 -1. + <_> + 0 7 5 2 3. + 0 + 1.2941689928993583e-003 + -0.2152619063854218 + 0.1293071061372757 + <_> + + <_> + + + + <_> + 8 7 9 6 -1. + <_> + 8 9 9 2 3. + 0 + 0.0399527512490749 + -0.0815632417798042 + 0.3440327942371368 + <_> + + <_> + + + + <_> + 2 0 20 13 -1. + <_> + 12 0 10 13 2. + 0 + 0.2579689919948578 + -0.0829713121056557 + 0.2971759140491486 + <_> + + <_> + + + + <_> + 19 3 6 4 -1. + <_> + 22 3 3 2 2. + <_> + 19 5 3 2 2. + 0 + 8.3975978195667267e-003 + -0.1235759034752846 + 0.3130742907524109 + <_> + + <_> + + + + <_> + 3 8 12 3 -1. + <_> + 9 8 6 3 2. + 0 + -0.0210481006652117 + 0.2553890943527222 + -0.1077592000365257 + <_> + + <_> + + + + <_> + 22 3 2 5 -1. + <_> + 22 3 1 5 2. + 1 + 0.0184192396700382 + -0.0348858311772347 + 0.4613004922866821 + <_> + + <_> + + + + <_> + 6 7 8 8 -1. + <_> + 8 7 4 8 2. + 0 + -0.0335993207991123 + -0.6385626196861267 + 0.0432357601821423 + <_> + + <_> + + + + <_> + 20 0 3 1 -1. + <_> + 21 1 1 1 3. + 1 + -5.9369178488850594e-003 + -0.3381235003471375 + 0.0261388104408979 + <_> + + <_> + + + + <_> + 5 0 1 3 -1. + <_> + 4 1 1 1 3. + 1 + 7.4244509451091290e-003 + 0.0416494794189930 + -0.6013135910034180 + <_> + + <_> + + + + <_> + 22 11 1 3 -1. + <_> + 21 12 1 1 3. + 1 + -3.8341500330716372e-003 + -0.3147934973239899 + 0.0227260906249285 + <_> + + <_> + + + + <_> + 1 4 4 3 -1. + <_> + 3 4 2 3 2. + 0 + 5.9263929724693298e-003 + -0.0845179632306099 + 0.2986125946044922 + <_> + + <_> + + + + <_> + 19 4 6 8 -1. + <_> + 22 4 3 4 2. + <_> + 19 8 3 4 2. + 0 + -0.0194444190710783 + 0.2213757932186127 + -0.0513583682477474 + <_> + + <_> + + + + <_> + 0 4 8 8 -1. + <_> + 0 4 4 4 2. + <_> + 4 8 4 4 2. + 0 + 0.0187752693891525 + -0.1223364025354385 + 0.2647691071033478 + <_> + + <_> + + + + <_> + 22 11 1 3 -1. + <_> + 21 12 1 1 3. + 1 + 6.4857508987188339e-003 + 0.0205634497106075 + -0.5246906280517578 + <_> + + <_> + + + + <_> + 0 1 24 14 -1. + <_> + 0 1 12 7 2. + <_> + 12 8 12 7 2. + 0 + -0.2598725855350494 + -0.6570193767547607 + 0.0345496907830238 + <_> + + <_> + + + + <_> + 23 8 2 4 -1. + <_> + 23 9 2 2 2. + 0 + -5.8150831609964371e-003 + -0.6595460772514343 + 0.0302442405372858 + <_> + + <_> + + + + <_> + 5 3 15 4 -1. + <_> + 5 4 15 2 2. + 0 + -0.0261219404637814 + 0.1870407015085220 + -0.1252924054861069 + <_> + + <_> + + + + <_> + 8 1 9 3 -1. + <_> + 8 2 9 1 3. + 0 + -5.7821800000965595e-003 + 0.2328509986400604 + -0.1182496026158333 + <_> + + <_> + + + + <_> + 0 8 2 4 -1. + <_> + 0 9 2 2 2. + 0 + -2.9595640953630209e-003 + -0.4579938054084778 + 0.0564655400812626 + <_> + + <_> + + + + <_> + 18 10 7 2 -1. + <_> + 18 11 7 1 2. + 0 + -0.0120882000774145 + -0.5189349055290222 + 0.0244996603578329 + <_> + + <_> + + + + <_> + 6 11 12 4 -1. + <_> + 6 12 12 2 2. + 0 + -8.8109169155359268e-003 + 0.2570025026798248 + -0.0927671566605568 + <_> + + <_> + + + + <_> + 14 0 6 15 -1. + <_> + 16 0 2 15 3. + 0 + -0.0459428504109383 + -0.4479719102382660 + 0.0299462303519249 + <_> + + <_> + + + + <_> + 0 10 7 2 -1. + <_> + 0 11 7 1 2. + 0 + -0.0100041404366493 + -0.6149634122848511 + 0.0364212691783905 + <_> + + <_> + + + + <_> + 15 5 6 6 -1. + <_> + 18 5 3 3 2. + <_> + 15 8 3 3 2. + 0 + -0.0116753997281194 + 0.1172877028584480 + -0.0613474808633327 + <_> + + <_> + + + + <_> + 5 0 6 15 -1. + <_> + 7 0 2 15 3. + 0 + -0.0524668507277966 + -0.7613652944564819 + 0.0306894704699516 + <_> + + <_> + + + + <_> + 8 7 9 4 -1. + <_> + 8 8 9 2 2. + 0 + 0.0182263404130936 + -0.0854801833629608 + 0.2695373892784119 + <_> + + <_> + + + + <_> + 7 6 10 6 -1. + <_> + 7 8 10 2 3. + 0 + -0.0452684201300144 + 0.3264470100402832 + -0.0773756429553032 + <_> + + <_> + + + + <_> + 19 11 1 3 -1. + <_> + 18 12 1 1 3. + 1 + -8.1426883116364479e-003 + -0.4582937955856323 + 9.3973511829972267e-003 + <_> + + <_> + + + + <_> + 6 11 3 1 -1. + <_> + 7 12 1 1 3. + 1 + -5.3349281661212444e-003 + -0.5775498151779175 + 0.0352523885667324 + <_> + + <_> + + + + <_> + 16 10 4 1 -1. + <_> + 16 10 2 1 2. + 0 + -1.0754769900813699e-003 + 0.1434753984212875 + -0.1015762984752655 + <_> + + <_> + + + + <_> + 0 0 1 2 -1. + <_> + 0 1 1 1 2. + 0 + -3.5198600962758064e-003 + -0.6082041263580322 + 0.0328880697488785 + <_> + + <_> + + + + <_> + 8 1 9 3 -1. + <_> + 8 2 9 1 3. + 0 + 0.0112483501434326 + -0.0905500426888466 + 0.2323783040046692 + <_> + + <_> + + + + <_> + 0 6 5 3 -1. + <_> + 0 7 5 1 3. + 0 + -0.0119920196011662 + -0.5705332159996033 + 0.0367036312818527 + <_> + + <_> + + + + <_> + 21 8 1 4 -1. + <_> + 20 9 1 2 2. + 1 + -0.0121055301278830 + -0.7086269259452820 + 4.4598700478672981e-003 + -1.5637760162353516 + 4 + -1 + <_> + + + <_> + + <_> + + + + <_> + 5 1 15 6 -1. + <_> + 5 3 15 2 3. + 0 + -0.1112890988588333 + 0.5214446783065796 + -0.2762526869773865 + <_> + + <_> + + + + <_> + 23 0 2 2 -1. + <_> + 24 0 1 1 2. + <_> + 23 1 1 1 2. + 0 + -3.1310080084949732e-003 + -0.6073393225669861 + 0.0243980996310711 + <_> + + <_> + + + + <_> + 3 3 15 6 -1. + <_> + 3 5 15 2 3. + 0 + -0.0975013524293900 + 0.5489286780357361 + -0.1652427017688751 + <_> + + <_> + + + + <_> + 19 0 6 9 -1. + <_> + 19 3 6 3 3. + 0 + -0.0652247071266174 + 0.3402006924152374 + -0.2693930864334106 + <_> + + <_> + + + + <_> + 5 2 15 6 -1. + <_> + 5 4 15 2 3. + 0 + 0.1191802993416786 + -0.1123576015233994 + 0.6395980119705200 + <_> + + <_> + + + + <_> + 17 3 8 3 -1. + <_> + 17 4 8 1 3. + 0 + -0.0140629801899195 + 0.3342761993408203 + -0.1284538954496384 + <_> + + <_> + + + + <_> + 4 3 8 4 -1. + <_> + 4 3 8 2 2. + 1 + -0.0564025007188320 + 0.3790628910064697 + -0.1554156988859177 + <_> + + <_> + + + + <_> + 16 4 6 2 -1. + <_> + 16 5 6 1 2. + 0 + 7.1742408908903599e-003 + -0.1133088991045952 + 0.1825089007616043 + <_> + + <_> + + + + <_> + 0 0 24 12 -1. + <_> + 0 0 12 6 2. + <_> + 12 6 12 6 2. + 0 + 0.1259752959012985 + 0.0945485532283783 + -0.4853444099426270 + <_> + + <_> + + + + <_> + 22 10 3 2 -1. + <_> + 22 10 3 1 2. + 1 + 5.9177991934120655e-003 + 0.0701321363449097 + -0.5377039909362793 + <_> + + <_> + + + + <_> + 6 3 6 6 -1. + <_> + 4 5 6 2 3. + 1 + -0.0439277403056622 + 0.3950741887092590 + -0.1080185994505882 + <_> + + <_> + + + + <_> + 14 4 9 1 -1. + <_> + 17 7 3 1 3. + 1 + -9.8314704373478889e-003 + 0.0959606170654297 + -0.0468075983226299 + <_> + + <_> + + + + <_> + 3 10 2 3 -1. + <_> + 3 10 1 3 2. + 1 + 5.6353402324020863e-003 + 0.0943416282534599 + -0.5247716903686523 + <_> + + <_> + + + + <_> + 20 8 5 2 -1. + <_> + 20 8 5 1 2. + 1 + -0.0115382801741362 + -0.5154880285263062 + 0.0138055300340056 + <_> + + <_> + + + + <_> + 0 9 16 6 -1. + <_> + 0 9 8 3 2. + <_> + 8 12 8 3 2. + 0 + 0.0286462493240833 + -0.1382701992988586 + 0.2750437855720520 + <_> + + <_> + + + + <_> + 6 2 13 3 -1. + <_> + 6 3 13 1 3. + 0 + 0.0138679798692465 + -0.1203586980700493 + 0.3521435856819153 + <_> + + <_> + + + + <_> + 0 1 3 4 -1. + <_> + 0 3 3 2 2. + 0 + -4.0469371015205979e-004 + 0.1522637009620667 + -0.2590084075927734 + <_> + + <_> + + + + <_> + 8 0 9 12 -1. + <_> + 8 6 9 6 2. + 0 + -0.1594581007957459 + -0.6391854882240295 + 0.0514649897813797 + <_> + + <_> + + + + <_> + 4 0 1 2 -1. + <_> + 4 0 1 1 2. + 1 + -2.7928699273616076e-003 + -0.5840150713920593 + 0.0542793795466423 + <_> + + <_> + + + + <_> + 5 3 15 3 -1. + <_> + 5 4 15 1 3. + 0 + 0.0183532107621431 + -0.1051151007413864 + 0.3529815971851349 + <_> + + <_> + + + + <_> + 3 10 2 3 -1. + <_> + 3 10 1 3 2. + 1 + -5.1810559816658497e-003 + -0.4741767942905426 + 0.0798512324690819 + <_> + + <_> + + + + <_> + 19 4 6 4 -1. + <_> + 22 4 3 2 2. + <_> + 19 6 3 2 2. + 0 + 9.2321299016475677e-003 + -0.0759327188134193 + 0.1852813959121704 + <_> + + <_> + + + + <_> + 0 3 8 4 -1. + <_> + 0 3 4 2 2. + <_> + 4 5 4 2 2. + 0 + 0.0121171101927757 + -0.1117528975009918 + 0.2853634953498840 + <_> + + <_> + + + + <_> + 19 10 5 3 -1. + <_> + 19 11 5 1 3. + 0 + -7.2612818330526352e-003 + -0.5885108709335327 + 0.0526883192360401 + <_> + + <_> + + + + <_> + 1 10 5 3 -1. + <_> + 1 11 5 1 3. + 0 + 5.6134900078177452e-003 + 0.0474684908986092 + -0.5394589900970459 + <_> + + <_> + + + + <_> + 12 1 13 14 -1. + <_> + 12 8 13 7 2. + 0 + -0.1945167928934097 + -0.5634222030639648 + 0.0302108898758888 + <_> + + <_> + + + + <_> + 0 1 13 14 -1. + <_> + 0 8 13 7 2. + 0 + 0.3550943136215210 + 0.0630894526839256 + -0.4980587959289551 + <_> + + <_> + + + + <_> + 11 3 6 12 -1. + <_> + 14 3 3 6 2. + <_> + 11 9 3 6 2. + 0 + 0.0331119708716869 + 0.0346324704587460 + -0.5246484875679016 + <_> + + <_> + + + + <_> + 9 5 6 10 -1. + <_> + 9 5 3 5 2. + <_> + 12 10 3 5 2. + 0 + 0.0342818088829517 + 0.0431439802050591 + -0.6470713019371033 + <_> + + <_> + + + + <_> + 20 8 5 4 -1. + <_> + 20 9 5 2 2. + 0 + -7.8256614506244659e-003 + -0.4688000977039337 + 0.0402393713593483 + <_> + + <_> + + + + <_> + 0 8 5 4 -1. + <_> + 0 9 5 2 2. + 0 + 0.0111560495570302 + 0.0401505008339882 + -0.6095538735389710 + <_> + + <_> + + + + <_> + 8 9 9 3 -1. + <_> + 8 10 9 1 3. + 0 + 0.0113630602136254 + -0.0827489867806435 + 0.3811689019203186 + <_> + + <_> + + + + <_> + 7 10 6 4 -1. + <_> + 9 10 2 4 3. + 0 + 0.0204051006585360 + 0.0425756387412548 + -0.7467774152755737 + <_> + + <_> + + + + <_> + 6 6 14 4 -1. + <_> + 6 7 14 2 2. + 0 + 0.0191116295754910 + -0.1239197030663490 + 0.2226520031690598 + <_> + + <_> + + + + <_> + 9 6 5 4 -1. + <_> + 9 7 5 2 2. + 0 + -7.3364898562431335e-003 + 0.3034206926822662 + -0.0926956906914711 + <_> + + <_> + + + + <_> + 22 5 3 6 -1. + <_> + 22 7 3 2 3. + 0 + -8.6538922041654587e-003 + -0.3351745009422302 + 0.0585405789315701 + <_> + + <_> + + + + <_> + 0 5 3 6 -1. + <_> + 0 7 3 2 3. + 0 + 0.0347895994782448 + 0.0337578095495701 + -0.7483453154563904 + <_> + + <_> + + + + <_> + 17 1 5 4 -1. + <_> + 17 2 5 2 2. + 0 + -0.0174188297241926 + 0.2445363998413086 + -0.0698786973953247 + <_> + + <_> + + + + <_> + 3 1 6 4 -1. + <_> + 3 2 6 2 2. + 0 + 3.5119079984724522e-003 + -0.1277886927127838 + 0.2403315007686615 + <_> + + <_> + + + + <_> + 21 14 4 1 -1. + <_> + 21 14 2 1 2. + 0 + 5.0669797929003835e-004 + -0.1169779002666473 + 0.1439380049705505 + <_> + + <_> + + + + <_> + 4 8 3 2 -1. + <_> + 5 9 1 2 3. + 1 + -5.9512741863727570e-003 + -0.5078160762786865 + 0.0478522293269634 + <_> + + <_> + + + + <_> + 14 2 4 7 -1. + <_> + 14 2 2 7 2. + 0 + 0.0503778010606766 + 2.9282520990818739e-003 + -0.7751696109771729 + <_> + + <_> + + + + <_> + 7 2 4 7 -1. + <_> + 9 2 2 7 2. + 0 + 3.8862510118633509e-003 + -0.1550420969724655 + 0.1570920050144196 + <_> + + <_> + + + + <_> + 9 3 8 5 -1. + <_> + 11 3 4 5 2. + 0 + 0.0385116301476955 + 0.0230970401316881 + -0.6291617155075073 + <_> + + <_> + + + + <_> + 5 10 15 1 -1. + <_> + 10 10 5 1 3. + 0 + -5.5746049620211124e-003 + 0.1807070970535278 + -0.1298052966594696 + <_> + + <_> + + + + <_> + 2 6 21 9 -1. + <_> + 9 6 7 9 3. + 0 + 0.1266476064920425 + -0.0865593999624252 + 0.2957325875759125 + <_> + + <_> + + + + <_> + 0 4 6 6 -1. + <_> + 0 6 6 2 3. + 0 + 5.4126111790537834e-003 + -0.1528324931859970 + 0.1662916988134384 + <_> + + <_> + + + + <_> + 1 12 24 3 -1. + <_> + 7 12 12 3 2. + 0 + -0.0361530818045139 + 0.2797313034534454 + -0.1039886027574539 + <_> + + <_> + + + + <_> + 6 7 6 2 -1. + <_> + 6 8 6 1 2. + 0 + 7.1673998609185219e-003 + -0.0945642217993736 + 0.2778528034687042 + <_> + + <_> + + + + <_> + 13 8 2 4 -1. + <_> + 13 8 2 2 2. + 1 + -6.7790350876748562e-003 + 0.1679068058729172 + -0.0839543119072914 + <_> + + <_> + + + + <_> + 8 6 8 5 -1. + <_> + 10 6 4 5 2. + 0 + -0.0298676099628210 + -0.7236117124557495 + 0.0346310697495937 + <_> + + <_> + + + + <_> + 11 5 6 4 -1. + <_> + 11 6 6 2 2. + 0 + 6.5265512093901634e-003 + -0.1173760965466499 + 0.1346033960580826 + <_> + + <_> + + + + <_> + 0 14 4 1 -1. + <_> + 2 14 2 1 2. + 0 + 3.4080960176652297e-005 + -0.1753176003694534 + 0.1322204023599625 + <_> + + <_> + + + + <_> + 16 2 4 13 -1. + <_> + 17 2 2 13 2. + 0 + -0.0176294595003128 + -0.5160853862762451 + 0.0253861900418997 + <_> + + <_> + + + + <_> + 0 7 1 4 -1. + <_> + 0 8 1 2 2. + 0 + -1.5446309698745608e-003 + -0.4142186045646668 + 0.0513300895690918 + <_> + + <_> + + + + <_> + 24 0 1 2 -1. + <_> + 24 1 1 1 2. + 0 + 1.1520429980009794e-003 + 0.0366159491240978 + -0.3692800998687744 + <_> + + <_> + + + + <_> + 0 5 2 4 -1. + <_> + 1 5 1 4 2. + 0 + -2.9612779617309570e-003 + 0.2446188032627106 + -0.0842714235186577 + -1.5267670154571533 + 5 + -1 + <_> + + + <_> + + <_> + + + + <_> + 0 1 8 4 -1. + <_> + 0 3 8 2 2. + 0 + -0.0141031695529819 + 0.2699790894985199 + -0.3928318023681641 + <_> + + <_> + + + + <_> + 15 11 10 4 -1. + <_> + 20 11 5 2 2. + <_> + 15 13 5 2 2. + 0 + 5.4714400321245193e-003 + -0.2269169986248016 + 0.2749052047729492 + <_> + + <_> + + + + <_> + 7 5 11 3 -1. + <_> + 7 6 11 1 3. + 0 + 0.0166354794055223 + -0.1547908037900925 + 0.3224202096462250 + <_> + + <_> + + + + <_> + 21 4 4 3 -1. + <_> + 21 4 2 3 2. + 0 + -8.4477178752422333e-003 + 0.3320780992507935 + -0.1249654963612557 + <_> + + <_> + + + + <_> + 0 5 4 1 -1. + <_> + 2 5 2 1 2. + 0 + -2.4904569145292044e-003 + 0.2900204956531525 + -0.1460298001766205 + <_> + + <_> + + + + <_> + 7 3 12 4 -1. + <_> + 7 4 12 2 2. + 0 + 0.0282104406505823 + -0.0831937119364738 + 0.4805397987365723 + <_> + + <_> + + + + <_> + 8 6 7 3 -1. + <_> + 8 7 7 1 3. + 0 + 9.3179903924465179e-003 + -0.1692426949739456 + 0.3482030928134918 + <_> + + <_> + + + + <_> + 16 0 9 14 -1. + <_> + 16 7 9 7 2. + 0 + -0.0579102896153927 + -0.5040398836135864 + 0.0840934887528419 + <_> + + <_> + + + + <_> + 0 0 24 6 -1. + <_> + 0 0 12 3 2. + <_> + 12 3 12 3 2. + 0 + 0.0882126465439796 + 0.0733099877834320 + -0.4883395135402679 + <_> + + <_> + + + + <_> + 23 13 2 1 -1. + <_> + 23 13 1 1 2. + 0 + 6.0974380176048726e-005 + -0.1594507992267609 + 0.1473277956247330 + <_> + + <_> + + + + <_> + 0 13 24 2 -1. + <_> + 0 13 12 1 2. + <_> + 12 14 12 1 2. + 0 + -0.0142063600942492 + -0.6365684866905212 + 0.0507153607904911 + <_> + + <_> + + + + <_> + 19 12 5 3 -1. + <_> + 19 13 5 1 3. + 0 + -7.7181900851428509e-003 + -0.6330028772354126 + 0.0328688994050026 + <_> + + <_> + + + + <_> + 9 7 7 4 -1. + <_> + 9 8 7 2 2. + 0 + 0.0120071703568101 + -0.1254525035619736 + 0.2893699109554291 + <_> + + <_> + + + + <_> + 14 0 4 7 -1. + <_> + 14 0 2 7 2. + 1 + 0.0707826167345047 + 0.0305656604468822 + -0.5666698217391968 + <_> + + <_> + + + + <_> + 11 0 7 4 -1. + <_> + 11 0 7 2 2. + 1 + -0.0504123307764530 + -0.5089793801307678 + 0.0710048824548721 + <_> + + <_> + + + + <_> + 9 4 14 2 -1. + <_> + 9 5 14 1 2. + 0 + 0.0220727995038033 + -0.1444841027259827 + 0.2781184911727905 + <_> + + <_> + + + + <_> + 3 2 15 4 -1. + <_> + 3 3 15 2 2. + 0 + 0.0147649403661489 + -0.1283989995718002 + 0.3290185928344727 + <_> + + <_> + + + + <_> + 19 12 5 3 -1. + <_> + 19 13 5 1 3. + 0 + 6.8206568248569965e-003 + 0.0654795467853546 + -0.5463265776634216 + <_> + + <_> + + + + <_> + 0 11 8 4 -1. + <_> + 0 11 4 2 2. + <_> + 4 13 4 2 2. + 0 + 2.0179790444672108e-003 + -0.2028342932462692 + 0.1679659038782120 + <_> + + <_> + + + + <_> + 7 9 11 6 -1. + <_> + 7 11 11 2 3. + 0 + 0.0250812191516161 + -0.1104943975806236 + 0.3191860020160675 + <_> + + <_> + + + + <_> + 0 11 7 4 -1. + <_> + 0 12 7 2 2. + 0 + 8.9391358196735382e-003 + 0.0734132081270218 + -0.5538399219512940 + <_> + + <_> + + + + <_> + 20 0 5 2 -1. + <_> + 20 1 5 1 2. + 0 + -4.6396959805861115e-004 + 0.1123031005263329 + -0.1697127074003220 + <_> + + <_> + + + + <_> + 5 10 3 2 -1. + <_> + 6 11 1 2 3. + 1 + -8.5602197796106339e-003 + -0.7347347736358643 + 0.0417169481515884 + <_> + + <_> + + + + <_> + 17 4 8 10 -1. + <_> + 21 4 4 5 2. + <_> + 17 9 4 5 2. + 0 + -0.0389347188174725 + 0.2292626947164536 + -0.0792299434542656 + <_> + + <_> + + + + <_> + 5 3 15 2 -1. + <_> + 5 4 15 1 2. + 0 + -0.0215415991842747 + 0.3007172048091888 + -0.1152340024709702 + <_> + + <_> + + + + <_> + 16 4 5 2 -1. + <_> + 16 5 5 1 2. + 0 + 4.9337721429765224e-003 + -0.1002838015556335 + 0.1348572969436646 + <_> + + <_> + + + + <_> + 1 0 22 10 -1. + <_> + 1 0 11 5 2. + <_> + 12 5 11 5 2. + 0 + 0.1615066975355148 + 0.0588171891868114 + -0.5656744837760925 + <_> + + <_> + + + + <_> + 20 0 5 2 -1. + <_> + 20 1 5 1 2. + 0 + -0.0123260198161006 + -0.2823328077793121 + 0.0187596306204796 + <_> + + <_> + + + + <_> + 0 0 5 2 -1. + <_> + 0 1 5 1 2. + 0 + 5.2987951785326004e-003 + 0.0524063482880592 + -0.5719032287597656 + <_> + + <_> + + + + <_> + 10 1 6 12 -1. + <_> + 13 1 3 6 2. + <_> + 10 7 3 6 2. + 0 + 0.0289043206721544 + 0.0477108694612980 + -0.4854584038257599 + <_> + + <_> + + + + <_> + 0 0 1 8 -1. + <_> + 0 4 1 4 2. + 0 + 0.0155697297304869 + 0.0493178516626358 + -0.5100051760673523 + <_> + + <_> + + + + <_> + 6 0 13 6 -1. + <_> + 6 2 13 2 3. + 0 + -0.0938120707869530 + 0.2564809024333954 + -0.1057069003582001 + <_> + + <_> + + + + <_> + 4 3 4 4 -1. + <_> + 3 4 4 2 2. + 1 + -0.0286933295428753 + 0.5247043967247009 + -0.0509502515196800 + <_> + + <_> + + + + <_> + 20 8 5 3 -1. + <_> + 20 9 5 1 3. + 0 + 7.2301640175282955e-003 + 0.0583653002977371 + -0.4894312024116516 + <_> + + <_> + + + + <_> + 7 13 2 2 -1. + <_> + 7 13 1 1 2. + <_> + 8 14 1 1 2. + 0 + 8.2664839283097535e-005 + -0.1437218040227890 + 0.1820268929004669 + <_> + + <_> + + + + <_> + 16 13 2 2 -1. + <_> + 17 13 1 1 2. + <_> + 16 14 1 1 2. + 0 + 1.5241750515997410e-003 + 0.0201267991214991 + -0.3884589970111847 + <_> + + <_> + + + + <_> + 7 13 2 2 -1. + <_> + 7 13 1 1 2. + <_> + 8 14 1 1 2. + 0 + -6.5512307628523558e-005 + 0.2280354052782059 + -0.1581206023693085 + <_> + + <_> + + + + <_> + 19 5 6 1 -1. + <_> + 21 5 2 1 3. + 0 + 2.4175599683076143e-003 + -0.0890450775623322 + 0.2839250862598419 + <_> + + <_> + + + + <_> + 0 8 6 6 -1. + <_> + 0 10 6 2 3. + 0 + 0.0343084894120693 + 0.0391304790973663 + -0.6263393163681030 + <_> + + <_> + + + + <_> + 6 8 13 4 -1. + <_> + 6 9 13 2 2. + 0 + 0.0127667998895049 + -0.0984294191002846 + 0.2857427895069122 + <_> + + <_> + + + + <_> + 3 10 8 1 -1. + <_> + 7 10 4 1 2. + 0 + -2.7450299821794033e-003 + 0.2090786993503571 + -0.1267945021390915 + <_> + + <_> + + + + <_> + 16 11 4 4 -1. + <_> + 17 11 2 4 2. + 0 + -7.0629850961267948e-003 + -0.4784719944000244 + 0.0229746792465448 + <_> + + <_> + + + + <_> + 5 6 15 2 -1. + <_> + 5 7 15 1 2. + 0 + 0.0109674101695418 + -0.1310741007328033 + 0.1712857037782669 + <_> + + <_> + + + + <_> + 3 1 20 10 -1. + <_> + 3 1 10 10 2. + 0 + -0.1530689001083374 + 0.2361073046922684 + -0.0965401679277420 + <_> + + <_> + + + + <_> + 2 4 3 3 -1. + <_> + 2 5 3 1 3. + 0 + 2.1676090545952320e-003 + -0.1028804033994675 + 0.2537584006786346 + <_> + + <_> + + + + <_> + 16 11 4 4 -1. + <_> + 17 11 2 4 2. + 0 + 0.0107051497325301 + 0.0160892698913813 + -0.5868526101112366 + <_> + + <_> + + + + <_> + 5 11 4 4 -1. + <_> + 6 11 2 4 2. + 0 + -6.1142919585108757e-003 + -0.6146798133850098 + 0.0344046317040920 + <_> + + <_> + + + + <_> + 17 4 8 10 -1. + <_> + 21 4 4 5 2. + <_> + 17 9 4 5 2. + 0 + -0.0160057693719864 + 0.0954133197665215 + -0.0657811686396599 + <_> + + <_> + + + + <_> + 0 8 5 3 -1. + <_> + 0 9 5 1 3. + 0 + 8.5541699081659317e-003 + 0.0425793603062630 + -0.5490341186523438 + <_> + + <_> + + + + <_> + 23 13 2 1 -1. + <_> + 23 13 1 1 2. + 0 + -5.5742941185599193e-005 + 0.1505846977233887 + -0.0978325977921486 + <_> + + <_> + + + + <_> + 0 13 2 1 -1. + <_> + 1 13 1 1 2. + 0 + 4.9888480134541169e-005 + -0.1522217988967896 + 0.1464709937572479 + <_> + + <_> + + + + <_> + 10 1 7 3 -1. + <_> + 10 2 7 1 3. + 0 + 9.3986131250858307e-003 + -0.0793018564581871 + 0.2222844958305359 + <_> + + <_> + + + + <_> + 0 3 8 12 -1. + <_> + 0 3 4 6 2. + <_> + 4 9 4 6 2. + 0 + -0.0445945896208286 + 0.3217073082923889 + -0.0712599530816078 + <_> + + <_> + + + + <_> + 6 0 16 11 -1. + <_> + 6 0 8 11 2. + 0 + 0.2763071060180664 + -0.0312894396483898 + 0.4636780917644501 + <_> + + <_> + + + + <_> + 2 0 21 3 -1. + <_> + 9 0 7 3 3. + 0 + -0.0459242798388004 + 0.2685551047325134 + -0.0946981832385063 + <_> + + <_> + + + + <_> + 23 1 2 12 -1. + <_> + 23 1 2 6 2. + 1 + 0.0328284502029419 + 0.0420088581740856 + -0.1909179985523224 + <_> + + <_> + + + + <_> + 2 0 1 2 -1. + <_> + 2 0 1 1 2. + 1 + 5.8416211977601051e-003 + 0.0443820804357529 + -0.5017232894897461 + <_> + + <_> + + + + <_> + 15 0 6 3 -1. + <_> + 17 0 2 3 3. + 0 + 0.0253127701580524 + 7.6768198050558567e-003 + -0.4524691104888916 + <_> + + <_> + + + + <_> + 8 9 6 4 -1. + <_> + 10 9 2 4 3. + 0 + -0.0206803791224957 + -0.7082331180572510 + 0.0277527105063200 + <_> + + <_> + + + + <_> + 20 5 5 6 -1. + <_> + 20 7 5 2 3. + 0 + 1.9456259906291962e-003 + -0.1725641041994095 + 0.0885240733623505 + <_> + + <_> + + + + <_> + 0 4 24 8 -1. + <_> + 0 4 12 4 2. + <_> + 12 8 12 4 2. + 0 + 0.1318278014659882 + 0.0378756709396839 + -0.5236573815345764 + <_> + + <_> + + + + <_> + 22 10 1 4 -1. + <_> + 21 11 1 2 2. + 1 + -4.8449821770191193e-003 + -0.3831801116466522 + 0.0295521095395088 + <_> + + <_> + + + + <_> + 7 0 11 3 -1. + <_> + 7 1 11 1 3. + 0 + 5.3295581601560116e-003 + -0.1172816008329392 + 0.1712217032909393 + <_> + + <_> + + + + <_> + 6 0 13 4 -1. + <_> + 6 1 13 2 2. + 0 + -0.0353284589946270 + 0.3731549978256226 + -0.0650273412466049 + -1.4507639408111572 + 6 + -1 + <_> + + + <_> + + <_> + + + + <_> + 7 11 11 4 -1. + <_> + 7 13 11 2 2. + 0 + 0.0136478496715426 + -0.2802368998527527 + 0.3575335144996643 + <_> + + <_> + + + + <_> + 21 3 4 12 -1. + <_> + 23 3 2 6 2. + <_> + 21 9 2 6 2. + 0 + 0.0123078199103475 + -0.1484645009040833 + 0.2714886069297791 + <_> + + <_> + + + + <_> + 2 4 21 6 -1. + <_> + 9 6 7 2 9. + 0 + 0.4659403860569000 + -0.0705008506774902 + 0.5868018865585327 + <_> + + <_> + + + + <_> + 23 3 2 10 -1. + <_> + 24 3 1 5 2. + <_> + 23 8 1 5 2. + 0 + 1.5693339519202709e-003 + -0.1150237023830414 + 0.1375536024570465 + <_> + + <_> + + + + <_> + 0 3 2 10 -1. + <_> + 0 3 1 5 2. + <_> + 1 8 1 5 2. + 0 + 2.5176738854497671e-003 + -0.1778890937566757 + 0.2172407060861588 + <_> + + <_> + + + + <_> + 24 10 1 4 -1. + <_> + 23 11 1 2 2. + 1 + 4.5299702323973179e-003 + 0.0458603501319885 + -0.5376703143119812 + <_> + + <_> + + + + <_> + 1 10 4 1 -1. + <_> + 2 11 2 1 2. + 1 + 4.0295510552823544e-003 + 0.0599071383476257 + -0.5803095102310181 + <_> + + <_> + + + + <_> + 8 10 9 4 -1. + <_> + 8 11 9 2 2. + 0 + 9.0281656011939049e-003 + -0.0889611616730690 + 0.3474006950855255 + <_> + + <_> + + + + <_> + 5 8 13 6 -1. + <_> + 5 11 13 3 2. + 0 + -0.0710994601249695 + 0.4003205001354218 + -0.0876752585172653 + <_> + + <_> + + + + <_> + 5 0 15 4 -1. + <_> + 5 2 15 2 2. + 0 + -0.0905078798532486 + 0.3202385008335114 + -0.1107280030846596 + <_> + + <_> + + + + <_> + 1 0 22 15 -1. + <_> + 12 0 11 15 2. + 0 + 0.3949914872646332 + -0.0544822700321674 + 0.4376561045646668 + <_> + + <_> + + + + <_> + 10 14 8 1 -1. + <_> + 12 14 4 1 2. + 0 + 6.0021281242370605e-003 + 0.0412968583405018 + -0.6277515888214111 + <_> + + <_> + + + + <_> + 1 3 8 4 -1. + <_> + 1 4 8 2 2. + 0 + -0.0126753300428391 + 0.1864306032657623 + -0.1586595028638840 + <_> + + <_> + + + + <_> + 15 13 1 2 -1. + <_> + 15 14 1 1 2. + 0 + 5.2523188060149550e-004 + -0.0737809464335442 + 0.1131825000047684 + <_> + + <_> + + + + <_> + 5 2 15 6 -1. + <_> + 5 4 15 2 3. + 0 + 0.1519853025674820 + -0.0698502063751221 + 0.5526459217071533 + <_> + + <_> + + + + <_> + 23 12 2 1 -1. + <_> + 23 12 1 1 2. + 1 + -5.9174448251724243e-003 + -0.4224376976490021 + 0.0234292708337307 + <_> + + <_> + + + + <_> + 2 12 1 2 -1. + <_> + 2 12 1 1 2. + 1 + 5.1085697486996651e-004 + -0.1782114058732987 + 0.1747542023658752 + <_> + + <_> + + + + <_> + 8 13 9 2 -1. + <_> + 11 13 3 2 3. + 0 + -0.0286266505718231 + -0.7806789875030518 + 0.0430335216224194 + <_> + + <_> + + + + <_> + 8 0 8 2 -1. + <_> + 8 1 8 1 2. + 0 + 3.2388539984822273e-003 + -0.1174874976277351 + 0.2301342934370041 + <_> + + <_> + + + + <_> + 20 12 4 3 -1. + <_> + 20 13 4 1 3. + 0 + -6.8310899659991264e-003 + -0.5170273780822754 + 0.0224770605564117 + <_> + + <_> + + + + <_> + 3 0 18 10 -1. + <_> + 3 0 9 5 2. + <_> + 12 5 9 5 2. + 0 + -0.1381812989711762 + -0.6718307137489319 + 0.0339458398520947 + <_> + + <_> + + + + <_> + 10 12 6 3 -1. + <_> + 12 12 2 3 3. + 0 + 0.0129029303789139 + 0.0190411508083344 + -0.4739249050617218 + <_> + + <_> + + + + <_> + 0 0 1 8 -1. + <_> + 0 2 1 4 2. + 0 + 6.3398052006959915e-003 + 0.0412811301648617 + -0.5821130871772766 + <_> + + <_> + + + + <_> + 22 5 3 4 -1. + <_> + 22 6 3 2 2. + 0 + 8.4067512943875045e-005 + -0.2301639020442963 + 0.1240853965282440 + <_> + + <_> + + + + <_> + 0 5 4 4 -1. + <_> + 0 6 4 2 2. + 0 + 0.0172388590872288 + 0.0539665818214417 + -0.5818564891815186 + <_> + + <_> + + + + <_> + 6 0 14 10 -1. + <_> + 13 0 7 5 2. + <_> + 6 5 7 5 2. + 0 + -0.0786773264408112 + -0.4061115086078644 + 0.0569235086441040 + <_> + + <_> + + + + <_> + 1 12 4 3 -1. + <_> + 1 13 4 1 3. + 0 + 5.5859591811895370e-003 + 0.0368424393236637 + -0.5646867752075195 + <_> + + <_> + + + + <_> + 20 7 2 2 -1. + <_> + 21 7 1 1 2. + <_> + 20 8 1 1 2. + 0 + -6.1322399415075779e-004 + 0.1785047054290772 + -0.0668883100152016 + <_> + + <_> + + + + <_> + 3 7 2 2 -1. + <_> + 3 7 1 1 2. + <_> + 4 8 1 1 2. + 0 + 7.9400849062949419e-004 + -0.0783978328108788 + 0.3054557144641876 + <_> + + <_> + + + + <_> + 22 6 3 4 -1. + <_> + 22 7 3 2 2. + 0 + 0.0128271998837590 + 0.0404374599456787 + -0.6479570865631104 + <_> + + <_> + + + + <_> + 9 6 7 3 -1. + <_> + 9 7 7 1 3. + 0 + 0.0119779799133539 + -0.0993791595101357 + 0.2267276048660278 + <_> + + <_> + + + + <_> + 11 6 4 2 -1. + <_> + 11 7 4 1 2. + 0 + -4.9378769472241402e-003 + 0.2706328034400940 + -0.0839221030473709 + <_> + + <_> + + + + <_> + 0 6 5 4 -1. + <_> + 0 7 5 2 2. + 0 + 0.0203377306461334 + 0.0400571115314960 + -0.6170961260795593 + <_> + + <_> + + + + <_> + 5 3 15 6 -1. + <_> + 5 5 15 2 3. + 0 + -0.1582631021738052 + 0.3718011081218720 + -0.0776448771357536 + <_> + + <_> + + + + <_> + 4 4 5 2 -1. + <_> + 4 5 5 1 2. + 0 + 4.5150578953325748e-003 + -0.1424572020769119 + 0.1946897059679031 + <_> + + <_> + + + + <_> + 11 12 6 3 -1. + <_> + 13 12 2 3 3. + 0 + -0.0179421696811914 + -0.7258480787277222 + 0.0292347799986601 + <_> + + <_> + + + + <_> + 3 0 1 3 -1. + <_> + 2 1 1 1 3. + 1 + 5.2153151482343674e-003 + 0.0460041500627995 + -0.4536756873130798 + <_> + + <_> + + + + <_> + 7 11 12 2 -1. + <_> + 11 11 4 2 3. + 0 + -7.7863838523626328e-003 + 0.1746426969766617 + -0.1098980978131294 + <_> + + <_> + + + + <_> + 0 8 4 4 -1. + <_> + 0 9 4 2 2. + 0 + 9.4133447855710983e-003 + 0.0346476286649704 + -0.5983666181564331 + <_> + + <_> + + + + <_> + 8 7 9 3 -1. + <_> + 8 8 9 1 3. + 0 + 7.6218741014599800e-003 + -0.1057026013731957 + 0.2037336975336075 + <_> + + <_> + + + + <_> + 8 8 9 6 -1. + <_> + 8 10 9 2 3. + 0 + 0.0216018799692392 + -0.0909303426742554 + 0.2887038886547089 + <_> + + <_> + + + + <_> + 20 11 5 4 -1. + <_> + 20 12 5 2 2. + 0 + -0.0118230897933245 + -0.6303614974021912 + 0.0240826196968555 + <_> + + <_> + + + + <_> + 7 5 8 3 -1. + <_> + 9 5 4 3 2. + 0 + -0.0202329792082310 + -0.7420278787612915 + 0.0235212203115225 + <_> + + <_> + + + + <_> + 16 0 2 2 -1. + <_> + 17 0 1 1 2. + <_> + 16 1 1 1 2. + 0 + 6.4510147785767913e-004 + -0.0552557893097401 + 0.1650166064500809 + <_> + + <_> + + + + <_> + 0 11 5 4 -1. + <_> + 0 12 5 2 2. + 0 + -8.1876022741198540e-003 + -0.5770931839942932 + 0.0352346412837505 + <_> + + <_> + + + + <_> + 16 0 2 2 -1. + <_> + 17 0 1 1 2. + <_> + 16 1 1 1 2. + 0 + -4.5044958824291825e-004 + 0.1859780997037888 + -0.0824367776513100 + <_> + + <_> + + + + <_> + 5 9 6 6 -1. + <_> + 7 9 2 6 3. + 0 + -0.0273097790777683 + -0.7204548716545105 + 0.0276838503777981 + <_> + + <_> + + + + <_> + 14 10 10 4 -1. + <_> + 19 10 5 2 2. + <_> + 14 12 5 2 2. + 0 + 7.3051019571721554e-003 + -0.0758159905672073 + 0.1228180006146431 + <_> + + <_> + + + + <_> + 6 6 3 1 -1. + <_> + 7 6 1 1 3. + 0 + 7.2118180105462670e-004 + -0.0847066268324852 + 0.2212305068969727 + <_> + + <_> + + + + <_> + 16 6 3 2 -1. + <_> + 17 6 1 2 3. + 0 + -5.5794708896428347e-004 + 0.0922004431486130 + -0.0512673109769821 + <_> + + <_> + + + + <_> + 6 6 3 2 -1. + <_> + 7 6 1 2 3. + 0 + -1.2906070332974195e-003 + 0.2364850938320160 + -0.0856367424130440 + <_> + + <_> + + + + <_> + 13 3 8 4 -1. + <_> + 12 4 8 2 2. + 1 + -0.0234409496188164 + -0.3417592048645020 + 0.0303556900471449 + <_> + + <_> + + + + <_> + 2 0 1 2 -1. + <_> + 2 0 1 1 2. + 1 + 6.7003733420278877e-005 + -0.1778312027454376 + 0.1098366007208824 + <_> + + <_> + + + + <_> + 21 0 2 1 -1. + <_> + 21 0 1 1 2. + 1 + -2.0913260523229837e-003 + -0.3296548128128052 + 0.0488219298422337 + <_> + + <_> + + + + <_> + 4 0 1 2 -1. + <_> + 4 0 1 1 2. + 1 + 5.2883368916809559e-003 + 0.0476020798087120 + -0.4229690134525299 + <_> + + <_> + + + + <_> + 13 1 8 6 -1. + <_> + 11 3 8 2 3. + 1 + 0.1046722009778023 + 0.0145577099174261 + -0.5163959860801697 + <_> + + <_> + + + + <_> + 12 3 4 8 -1. + <_> + 13 4 2 8 2. + 1 + 0.0410936884582043 + 0.0255694594234228 + -0.6734575033187866 + <_> + + <_> + + + + <_> + 3 0 20 15 -1. + <_> + 3 0 10 15 2. + 0 + 0.4545299112796783 + -0.0473212711513042 + 0.4647259116172791 + <_> + + <_> + + + + <_> + 9 0 7 3 -1. + <_> + 9 1 7 1 3. + 0 + -4.4200271368026733e-003 + 0.2172905951738358 + -0.0805237367749214 + <_> + + <_> + + + + <_> + 12 1 5 2 -1. + <_> + 12 2 5 1 2. + 0 + -3.3253689762204885e-003 + 0.1196364015340805 + -0.0847371667623520 + <_> + + <_> + + + + <_> + 6 1 13 3 -1. + <_> + 6 2 13 1 3. + 0 + 0.0152236903086305 + -0.0892436280846596 + 0.2284111976623535 + <_> + + <_> + + + + <_> + 14 3 10 12 -1. + <_> + 19 3 5 6 2. + <_> + 14 9 5 6 2. + 0 + -0.0312239099293947 + 0.1464260965585709 + -0.1012998968362808 + <_> + + <_> + + + + <_> + 1 6 21 6 -1. + <_> + 8 6 7 6 3. + 0 + -0.0729675367474556 + 0.1977909952402115 + -0.0998045280575752 + <_> + + <_> + + + + <_> + 12 0 10 12 -1. + <_> + 12 0 5 12 2. + 0 + 0.0434687100350857 + -0.0738932862877846 + 0.1571179032325745 + <_> + + <_> + + + + <_> + 7 8 11 3 -1. + <_> + 7 9 11 1 3. + 0 + 7.7427257783710957e-003 + -0.0907922536134720 + 0.2449675947427750 + <_> + + <_> + + + + <_> + 2 5 22 10 -1. + <_> + 2 5 11 10 2. + 0 + -0.0834884494543076 + 0.1732859015464783 + -0.1288128942251205 + <_> + + <_> + + + + <_> + 5 4 15 4 -1. + <_> + 5 6 15 2 2. + 0 + 0.0421115085482597 + -0.1475321054458618 + 0.1373448967933655 + <_> + + <_> + + + + <_> + 7 1 15 6 -1. + <_> + 7 3 15 2 3. + 0 + 0.0966737270355225 + -0.0551961399614811 + 0.3563303947448731 + <_> + + <_> + + + + <_> + 0 8 2 6 -1. + <_> + 0 10 2 2 3. + 0 + -8.8993981480598450e-003 + -0.5261930823326111 + 0.0388906002044678 + <_> + + <_> + + + + <_> + 5 1 15 4 -1. + <_> + 5 2 15 2 2. + 0 + -0.0238508302718401 + 0.1924559026956558 + -0.1050153970718384 + <_> + + <_> + + + + <_> + 7 8 2 2 -1. + <_> + 7 8 1 1 2. + <_> + 8 9 1 1 2. + 0 + -7.4902130290865898e-004 + 0.2476740926504135 + -0.0738597288727760 + <_> + + <_> + + + + <_> + 11 9 9 2 -1. + <_> + 14 9 3 2 3. + 0 + -0.0230488497763872 + -0.5220348238945007 + 0.0295383799821138 + <_> + + <_> + + + + <_> + 7 8 2 2 -1. + <_> + 7 8 1 1 2. + <_> + 8 9 1 1 2. + 0 + 5.7920900871977210e-004 + -0.0807055011391640 + 0.2493984997272492 + <_> + + <_> + + + + <_> + 17 10 8 4 -1. + <_> + 17 11 8 2 2. + 0 + -0.0254354309290648 + -0.6520490050315857 + 0.0163280703127384 + <_> + + <_> + + + + <_> + 0 10 8 4 -1. + <_> + 0 11 8 2 2. + 0 + 0.0176391601562500 + 0.0246949195861816 + -0.6850522756576538 + <_> + + <_> + + + + <_> + 16 11 6 4 -1. + <_> + 18 11 2 4 3. + 0 + 0.0205357391387224 + 0.0165182203054428 + -0.4285225868225098 + <_> + + <_> + + + + <_> + 0 13 24 1 -1. + <_> + 6 13 12 1 2. + 0 + 0.0111132804304361 + -0.0871591791510582 + 0.2062001973390579 + -1.3936280012130737 + 7 + -1 + <_> + + + <_> + + <_> + + + + <_> + 0 9 10 6 -1. + <_> + 0 9 5 3 2. + <_> + 5 12 5 3 2. + 0 + 0.0140618495643139 + -0.2737283110618591 + 0.4017829895019531 + <_> + + <_> + + + + <_> + 13 5 10 10 -1. + <_> + 18 5 5 5 2. + <_> + 13 10 5 5 2. + 0 + -0.0334245301783085 + 0.3433864116668701 + -0.1524070948362351 + <_> + + <_> + + + + <_> + 0 4 4 2 -1. + <_> + 2 4 2 2 2. + 0 + -3.3982729073613882e-003 + 0.3046114146709442 + -0.2162856012582779 + <_> + + <_> + + + + <_> + 13 5 12 10 -1. + <_> + 19 5 6 5 2. + <_> + 13 10 6 5 2. + 0 + 0.0673939511179924 + -0.0539562106132507 + 0.3304964005947113 + <_> + + <_> + + + + <_> + 0 5 12 10 -1. + <_> + 0 5 6 5 2. + <_> + 6 10 6 5 2. + 0 + -0.0515447482466698 + 0.3804036974906921 + -0.1334261000156403 + <_> + + <_> + + + + <_> + 11 11 3 4 -1. + <_> + 11 13 3 2 2. + 0 + 3.6630779504776001e-003 + -0.1760202944278717 + 0.2139966934919357 + <_> + + <_> + + + + <_> + 5 8 2 5 -1. + <_> + 5 8 1 5 2. + 1 + 7.8836623579263687e-003 + 0.0570616200566292 + -0.5150743126869202 + <_> + + <_> + + + + <_> + 4 14 18 1 -1. + <_> + 4 14 9 1 2. + 0 + -8.9480048045516014e-003 + 0.2230996936559677 + -0.1190536990761757 + <_> + + <_> + + + + <_> + 1 0 1 6 -1. + <_> + 1 3 1 3 2. + 0 + -5.5760587565600872e-004 + 0.0999659672379494 + -0.2558285892009735 + <_> + + <_> + + + + <_> + 8 9 9 4 -1. + <_> + 8 10 9 2 2. + 0 + 9.5389392226934433e-003 + -0.0655315071344376 + 0.3246265947818756 + <_> + + <_> + + + + <_> + 0 9 5 4 -1. + <_> + 0 10 5 2 2. + 0 + 7.7904132194817066e-003 + 0.0450260303914547 + -0.6068859100341797 + <_> + + <_> + + + + <_> + 19 5 6 2 -1. + <_> + 21 5 2 2 3. + 0 + 4.0692770853638649e-003 + -0.0624743513762951 + 0.1570695042610169 + <_> + + <_> + + + + <_> + 0 5 6 2 -1. + <_> + 2 5 2 2 3. + 0 + 3.1110940035432577e-003 + -0.0744680091738701 + 0.2600801885128021 + <_> + + <_> + + + + <_> + 13 9 6 3 -1. + <_> + 15 9 2 3 3. + 0 + 0.0156514495611191 + 0.0255663506686687 + -0.5172523260116577 + <_> + + <_> + + + + <_> + 2 3 21 9 -1. + <_> + 9 3 7 9 3. + 0 + 0.2044613063335419 + -0.0763430967926979 + 0.3323906958103180 + <_> + + <_> + + + + <_> + 11 9 10 2 -1. + <_> + 11 9 5 2 2. + 0 + -0.0101691596210003 + 0.1606681048870087 + -0.1091597974300385 + <_> + + <_> + + + + <_> + 0 0 24 14 -1. + <_> + 0 0 12 7 2. + <_> + 12 7 12 7 2. + 0 + 0.1894780993461609 + 0.0538599416613579 + -0.5398759841918945 + <_> + + <_> + + + + <_> + 5 2 15 6 -1. + <_> + 5 4 15 2 3. + 0 + -0.1479240059852600 + 0.2385465949773789 + -0.1132820993661881 + <_> + + <_> + + + + <_> + 2 0 16 11 -1. + <_> + 10 0 8 11 2. + 0 + -0.1483031064271927 + 0.3646511137485504 + -0.0753156766295433 + <_> + + <_> + + + + <_> + 5 0 15 6 -1. + <_> + 5 2 15 2 3. + 0 + -0.1325532943010330 + 0.2919555902481079 + -0.0949441567063332 + <_> + + <_> + + + + <_> + 10 5 5 4 -1. + <_> + 10 6 5 2 2. + 0 + -0.0163901709020138 + 0.3920511901378632 + -0.0685021281242371 + <_> + + <_> + + + + <_> + 23 0 2 3 -1. + <_> + 23 1 2 1 3. + 0 + -6.3240979798138142e-003 + -0.6633772253990173 + 0.0337768010795116 + <_> + + <_> + + + + <_> + 0 0 6 3 -1. + <_> + 0 1 6 1 3. + 0 + 0.0147409504279494 + 0.0431423708796501 + -0.5016931891441345 + <_> + + <_> + + + + <_> + 10 5 15 2 -1. + <_> + 10 6 15 1 2. + 0 + 0.0171020403504372 + -0.1739968061447144 + 0.2036074995994568 + <_> + + <_> + + + + <_> + 0 4 6 4 -1. + <_> + 0 4 3 2 2. + <_> + 3 6 3 2 2. + 0 + -7.5232060626149178e-003 + 0.2614240050315857 + -0.0894730314612389 + <_> + + <_> + + + + <_> + 21 7 2 4 -1. + <_> + 20 8 2 2 2. + 1 + 8.0899456515908241e-003 + 0.0491316393017769 + -0.3869245946407318 + <_> + + <_> + + + + <_> + 4 7 4 2 -1. + <_> + 5 8 2 2 2. + 1 + -0.0111914901062846 + -0.7151393890380859 + 0.0292793400585651 + <_> + + <_> + + + + <_> + 24 13 1 2 -1. + <_> + 24 14 1 1 2. + 0 + -6.4855492382775992e-005 + 0.1147895976901054 + -0.1195824965834618 + <_> + + <_> + + + + <_> + 2 0 4 15 -1. + <_> + 3 0 2 15 2. + 0 + 0.0263162907212973 + 0.0260859299451113 + -0.8071029186248779 + <_> + + <_> + + + + <_> + 21 0 4 1 -1. + <_> + 22 1 2 1 2. + 1 + -0.0132494196295738 + -0.3211443126201630 + 7.5486088171601295e-003 + <_> + + <_> + + + + <_> + 4 0 1 4 -1. + <_> + 3 1 1 2 2. + 1 + 6.2180599197745323e-003 + 0.0555592402815819 + -0.4065248966217041 + <_> + + <_> + + + + <_> + 1 1 24 14 -1. + <_> + 13 1 12 7 2. + <_> + 1 8 12 7 2. + 0 + 0.1724980026483536 + 0.0407503582537174 + -0.5056337714195252 + <_> + + <_> + + + + <_> + 6 9 6 6 -1. + <_> + 8 9 2 6 3. + 0 + -0.0216798391193151 + -0.6235452890396118 + 0.0264780297875404 + <_> + + <_> + + + + <_> + 5 3 15 4 -1. + <_> + 10 3 5 4 3. + 0 + 0.0167031493037939 + -0.1379484981298447 + 0.1374935954809189 + <_> + + <_> + + + + <_> + 0 0 20 10 -1. + <_> + 5 0 10 10 2. + 0 + -0.0904578119516373 + 0.2364515066146851 + -0.0822857320308685 + <_> + + <_> + + + + <_> + 19 3 6 12 -1. + <_> + 22 3 3 6 2. + <_> + 19 9 3 6 2. + 0 + -0.0319220200181007 + 0.2578540146350861 + -0.0472433306276798 + <_> + + <_> + + + + <_> + 3 2 7 2 -1. + <_> + 3 3 7 1 2. + 0 + -0.0107858600094914 + 0.1915684044361115 + -0.1092626005411148 + <_> + + <_> + + + + <_> + 19 3 6 12 -1. + <_> + 22 3 3 6 2. + <_> + 19 9 3 6 2. + 0 + 0.0153568601235747 + -0.0915980264544487 + 0.1492947041988373 + <_> + + <_> + + + + <_> + 0 3 6 12 -1. + <_> + 0 3 3 6 2. + <_> + 3 9 3 6 2. + 0 + -0.0298386197537184 + 0.3693186044692993 + -0.0698615685105324 + <_> + + <_> + + + + <_> + 19 14 6 1 -1. + <_> + 19 14 3 1 2. + 0 + 1.5088700456544757e-003 + -0.0684053674340248 + 0.1167493984103203 + <_> + + <_> + + + + <_> + 4 2 6 13 -1. + <_> + 6 2 2 13 3. + 0 + -0.0391593612730503 + -0.5139203071594238 + 0.0376962982118130 + <_> + + <_> + + + + <_> + 17 14 8 1 -1. + <_> + 19 14 4 1 2. + 0 + 9.6957627683877945e-003 + 0.0178152993321419 + -0.4685910940170288 + <_> + + <_> + + + + <_> + 0 14 8 1 -1. + <_> + 2 14 4 1 2. + 0 + 7.2683161124587059e-004 + -0.1310783028602600 + 0.1574900001287460 + <_> + + <_> + + + + <_> + 23 11 2 2 -1. + <_> + 23 11 2 1 2. + 1 + 3.9894571527838707e-003 + 0.0452235005795956 + -0.4237715899944305 + <_> + + <_> + + + + <_> + 2 11 2 2 -1. + <_> + 2 11 1 2 2. + 1 + -5.1600970327854156e-003 + -0.5150998830795288 + 0.0348056405782700 + <_> + + <_> + + + + <_> + 8 4 9 4 -1. + <_> + 8 5 9 2 2. + 0 + -0.0237389300018549 + 0.2213699966669083 + -0.0842292308807373 + <_> + + <_> + + + + <_> + 8 4 9 3 -1. + <_> + 8 5 9 1 3. + 0 + 0.0145637700334191 + -0.0898087024688721 + 0.2186468988656998 + <_> + + <_> + + + + <_> + 22 6 2 4 -1. + <_> + 23 6 1 2 2. + <_> + 22 8 1 2 2. + 0 + 7.2849658317863941e-004 + -0.0709035396575928 + 0.1204996034502983 + <_> + + <_> + + + + <_> + 7 3 6 8 -1. + <_> + 9 3 2 8 3. + 0 + -0.0311498604714870 + -0.6067348122596741 + 0.0294798705726862 + <_> + + <_> + + + + <_> + 22 4 3 4 -1. + <_> + 22 5 3 2 2. + 0 + 0.0167685598134995 + 0.0236525908112526 + -0.4164066910743713 + <_> + + <_> + + + + <_> + 3 9 4 2 -1. + <_> + 4 10 2 2 2. + 1 + -8.9033348485827446e-003 + -0.5536022186279297 + 0.0302125699818134 + <_> + + <_> + + + + <_> + 17 7 2 2 -1. + <_> + 18 7 1 1 2. + <_> + 17 8 1 1 2. + 0 + 5.3961132653057575e-004 + -0.0588473901152611 + 0.1531303972005844 + <_> + + <_> + + + + <_> + 9 11 6 1 -1. + <_> + 11 11 2 1 3. + 0 + -8.3886012434959412e-003 + -0.7052780985832214 + 0.0250979401171207 + <_> + + <_> + + + + <_> + 17 7 2 2 -1. + <_> + 18 7 1 1 2. + <_> + 17 8 1 1 2. + 0 + -3.4085000515915453e-004 + 0.1771869063377380 + -0.1048467978835106 + <_> + + <_> + + + + <_> + 0 7 2 4 -1. + <_> + 0 8 2 2 2. + 0 + 6.1828009784221649e-003 + 0.0330388285219669 + -0.4948574900627136 + <_> + + <_> + + + + <_> + 20 5 5 6 -1. + <_> + 20 7 5 2 3. + 0 + 8.2702568033710122e-004 + -0.1844830960035324 + 0.0777885988354683 + <_> + + <_> + + + + <_> + 6 7 2 2 -1. + <_> + 6 7 1 1 2. + <_> + 7 8 1 1 2. + 0 + -6.0980831040069461e-004 + 0.1959578990936279 + -0.0837520435452461 + <_> + + <_> + + + + <_> + 17 7 2 2 -1. + <_> + 18 7 1 1 2. + <_> + 17 8 1 1 2. + 0 + 1.2273030006326735e-004 + -0.0814708098769188 + 0.1209300011396408 + <_> + + <_> + + + + <_> + 6 7 2 2 -1. + <_> + 6 7 1 1 2. + <_> + 7 8 1 1 2. + 0 + 4.6565610682591796e-004 + -0.0953319519758224 + 0.2288299947977066 + <_> + + <_> + + + + <_> + 15 0 4 9 -1. + <_> + 16 0 2 9 2. + 0 + -0.0216477997601032 + -0.6933805942535400 + 0.0170615408569574 + <_> + + <_> + + + + <_> + 5 1 14 14 -1. + <_> + 5 1 7 7 2. + <_> + 12 8 7 7 2. + 0 + 0.0595006607472897 + 0.0526031702756882 + -0.2782197892665863 + <_> + + <_> + + + + <_> + 15 0 4 9 -1. + <_> + 16 0 2 9 2. + 0 + 0.0253651998937130 + 8.9954538270831108e-003 + -0.6383489966392517 + <_> + + <_> + + + + <_> + 0 7 5 3 -1. + <_> + 0 8 5 1 3. + 0 + -3.9667091332376003e-003 + -0.3175272047519684 + 0.0470112897455692 + <_> + + <_> + + + + <_> + 21 2 3 4 -1. + <_> + 22 3 1 4 3. + 1 + 8.2784779369831085e-003 + -0.0544440597295761 + 0.2219938933849335 + <_> + + <_> + + + + <_> + 6 0 4 15 -1. + <_> + 7 0 2 15 2. + 0 + -0.0221254508942366 + -0.6738150715827942 + 0.0225456394255161 + <_> + + <_> + + + + <_> + 21 2 3 4 -1. + <_> + 22 3 1 4 3. + 1 + -0.0180159192532301 + 0.1972057968378067 + -0.0419279783964157 + <_> + + <_> + + + + <_> + 4 2 4 3 -1. + <_> + 3 3 4 1 3. + 1 + 8.4426235407590866e-003 + -0.0605471916496754 + 0.2649214863777161 + <_> + + <_> + + + + <_> + 13 5 3 7 -1. + <_> + 14 6 1 7 3. + 1 + -0.0325668416917324 + -0.7107285857200623 + 0.0118406098335981 + <_> + + <_> + + + + <_> + 4 10 15 1 -1. + <_> + 9 10 5 1 3. + 0 + -4.7655492089688778e-003 + 0.1384397000074387 + -0.1150531992316246 + <_> + + <_> + + + + <_> + 12 6 10 9 -1. + <_> + 12 6 5 9 2. + 0 + 0.0569362901151180 + -0.0613397099077702 + 0.2665694057941437 + <_> + + <_> + + + + <_> + 1 1 22 14 -1. + <_> + 12 1 11 14 2. + 0 + 0.1374146044254303 + -0.1139679029583931 + 0.1789363026618958 + <_> + + <_> + + + + <_> + 11 8 3 2 -1. + <_> + 11 9 3 1 2. + 0 + 3.4123009536415339e-003 + -0.0668940767645836 + 0.2595616877079010 + <_> + + <_> + + + + <_> + 2 5 11 2 -1. + <_> + 2 6 11 1 2. + 0 + 0.0116290198639035 + -0.1346206963062286 + 0.1518495976924896 + -1.3217060565948486 + 8 + -1 + <_> + + + <_> + + <_> + + + + <_> + 4 1 10 4 -1. + <_> + 3 2 10 2 2. + 1 + -0.0302658006548882 + 0.3809668123722076 + -0.1337769925594330 + <_> + + <_> + + + + <_> + 5 1 15 6 -1. + <_> + 5 3 15 2 3. + 0 + -0.1888993978500366 + 0.3472220003604889 + -0.1143490970134735 + <_> + + <_> + + + + <_> + 0 9 6 6 -1. + <_> + 0 9 3 3 2. + <_> + 3 12 3 3 2. + 0 + 4.4756601564586163e-003 + -0.1779001951217651 + 0.1983720064163208 + <_> + + <_> + + + + <_> + 19 3 5 2 -1. + <_> + 19 4 5 1 2. + 0 + -9.2559102922677994e-003 + 0.2553296089172363 + -0.0956856831908226 + <_> + + <_> + + + + <_> + 2 10 14 4 -1. + <_> + 2 10 7 2 2. + <_> + 9 12 7 2 2. + 0 + 0.0103751895949245 + -0.1290100961923599 + 0.2047273963689804 + <_> + + <_> + + + + <_> + 1 3 24 8 -1. + <_> + 9 3 8 8 3. + 0 + 0.2527360022068024 + -0.0779134780168533 + 0.3413710892200470 + <_> + + <_> + + + + <_> + 0 8 2 6 -1. + <_> + 0 10 2 2 3. + 0 + 7.9952310770750046e-003 + 0.1191667988896370 + -0.4138369858264923 + <_> + + <_> + + + + <_> + 23 14 2 1 -1. + <_> + 23 14 1 1 2. + 0 + 6.6510503529570997e-005 + -0.2305306047201157 + 0.1328932046890259 + <_> + + <_> + + + + <_> + 0 4 6 4 -1. + <_> + 0 4 3 2 2. + <_> + 3 6 3 2 2. + 0 + 0.0104297399520874 + -0.0622061118483543 + 0.2935121059417725 + <_> + + <_> + + + + <_> + 3 13 21 1 -1. + <_> + 10 13 7 1 3. + 0 + -9.4513092190027237e-003 + 0.1671503931283951 + -0.1161310002207756 + <_> + + <_> + + + + <_> + 0 0 24 14 -1. + <_> + 0 0 12 7 2. + <_> + 12 7 12 7 2. + 0 + -0.1386305987834930 + -0.4514685869216919 + 0.0725729763507843 + <_> + + <_> + + + + <_> + 24 0 1 10 -1. + <_> + 24 5 1 5 2. + 0 + -0.0154232997447252 + -0.4277118146419525 + 0.0248409193009138 + <_> + + <_> + + + + <_> + 4 11 2 2 -1. + <_> + 4 11 1 2 2. + 1 + -6.5782992169260979e-003 + -0.6540787816047669 + 0.0402618311345577 + <_> + + <_> + + + + <_> + 23 14 2 1 -1. + <_> + 23 14 1 1 2. + 0 + -6.8917557655368000e-005 + 0.2068260014057159 + -0.1195247992873192 + <_> + + <_> + + + + <_> + 0 14 2 1 -1. + <_> + 1 14 1 1 2. + 0 + 7.1416288847103715e-005 + -0.1625899970531464 + 0.1518989056348801 + <_> + + <_> + + + + <_> + 7 2 11 6 -1. + <_> + 7 4 11 2 3. + 0 + 0.1354866027832031 + -0.0504554286599159 + 0.4712490141391754 + <_> + + <_> + + + + <_> + 2 2 2 2 -1. + <_> + 2 2 1 2 2. + 1 + 1.1286230292171240e-003 + -0.1934940963983536 + 0.1492028981447220 + <_> + + <_> + + + + <_> + 24 0 1 10 -1. + <_> + 24 5 1 5 2. + 0 + 0.0376871302723885 + -6.5130472648888826e-004 + -0.5566216707229614 + <_> + + <_> + + + + <_> + 0 0 1 10 -1. + <_> + 0 5 1 5 2. + 0 + -0.0177724994719028 + -0.5733047127723694 + 0.0462512709200382 + <_> + + <_> + + + + <_> + 12 11 6 2 -1. + <_> + 14 11 2 2 3. + 0 + -0.0141524598002434 + -0.7905998826026917 + 0.0153570203110576 + <_> + + <_> + + + + <_> + 2 0 20 2 -1. + <_> + 7 0 10 2 2. + 0 + -0.0194474104791880 + 0.2123239040374756 + -0.1021943986415863 + <_> + + <_> + + + + <_> + 10 0 10 4 -1. + <_> + 10 0 5 4 2. + 0 + 0.0129150198772550 + -0.0788644626736641 + 0.1457864940166473 + <_> + + <_> + + + + <_> + 0 0 20 1 -1. + <_> + 10 0 10 1 2. + 0 + 7.7283121645450592e-003 + -0.1338106989860535 + 0.2055318057537079 + <_> + + <_> + + + + <_> + 8 4 10 3 -1. + <_> + 8 5 10 1 3. + 0 + -0.0264210291206837 + 0.2729040980339050 + -0.0841038301587105 + <_> + + <_> + + + + <_> + 9 6 7 6 -1. + <_> + 9 8 7 2 3. + 0 + -0.0216425806283951 + 0.2165616005659103 + -0.0997976064682007 + <_> + + <_> + + + + <_> + 8 5 9 3 -1. + <_> + 8 6 9 1 3. + 0 + -0.0186041705310345 + 0.3167817890644074 + -0.0684646219015121 + <_> + + <_> + + + + <_> + 6 0 1 3 -1. + <_> + 5 1 1 1 3. + 1 + 7.9184472560882568e-003 + 0.0389325916767120 + -0.5849621891975403 + <_> + + <_> + + + + <_> + 24 0 1 4 -1. + <_> + 24 2 1 2 2. + 0 + -9.0868779807351530e-005 + 0.1183537989854813 + -0.2693997025489807 + <_> + + <_> + + + + <_> + 9 10 2 1 -1. + <_> + 10 10 1 1 2. + 0 + -6.3271610997617245e-005 + 0.1483621001243591 + -0.1414014995098114 + <_> + + <_> + + + + <_> + 22 10 1 4 -1. + <_> + 21 11 1 2 2. + 1 + 3.0123859178274870e-003 + 0.0475597009062767 + -0.3168076872825623 + <_> + + <_> + + + + <_> + 4 0 6 5 -1. + <_> + 6 0 2 5 3. + 0 + 0.0202028602361679 + 0.0363369397819042 + -0.4958786964416504 + <_> + + <_> + + + + <_> + 17 3 8 12 -1. + <_> + 21 3 4 6 2. + <_> + 17 9 4 6 2. + 0 + 0.0681129470467567 + -0.0636018067598343 + 0.3745648860931397 + <_> + + <_> + + + + <_> + 0 3 8 12 -1. + <_> + 0 3 4 6 2. + <_> + 4 9 4 6 2. + 0 + -0.0613449215888977 + 0.3703984022140503 + -0.0626903176307678 + <_> + + <_> + + + + <_> + 10 3 6 10 -1. + <_> + 13 3 3 5 2. + <_> + 10 8 3 5 2. + 0 + -0.0239223092794418 + -0.3475331962108612 + 0.0568292401731014 + <_> + + <_> + + + + <_> + 3 10 4 1 -1. + <_> + 4 11 2 1 2. + 1 + 4.4279401190578938e-003 + 0.0318974405527115 + -0.5085908770561218 + <_> + + <_> + + + + <_> + 16 2 9 4 -1. + <_> + 16 2 9 2 2. + 1 + -0.0923664569854736 + -0.4889659881591797 + 9.9938698112964630e-003 + <_> + + <_> + + + + <_> + 9 2 4 9 -1. + <_> + 9 2 2 9 2. + 1 + -3.1878310255706310e-003 + 0.0857494324445724 + -0.2382344007492065 + <_> + + <_> + + + + <_> + 20 9 3 3 -1. + <_> + 20 10 3 1 3. + 0 + 6.2605291604995728e-003 + 0.0244128108024597 + -0.5500137209892273 + <_> + + <_> + + + + <_> + 6 1 13 4 -1. + <_> + 6 2 13 2 2. + 0 + 0.0217170491814613 + -0.0847987011075020 + 0.2182479947805405 + <_> + + <_> + + + + <_> + 10 4 5 4 -1. + <_> + 10 5 5 2 2. + 0 + 0.0102959601208568 + -0.1032914966344833 + 0.1945870965719223 + <_> + + <_> + + + + <_> + 0 5 3 3 -1. + <_> + 0 6 3 1 3. + 0 + 0.0121496301144362 + 0.0322238989174366 + -0.5932865738868713 + <_> + + <_> + + + + <_> + 21 5 4 4 -1. + <_> + 21 6 4 2 2. + 0 + 0.0191168300807476 + 0.0309407506138086 + -0.4538871943950653 + <_> + + <_> + + + + <_> + 0 5 4 4 -1. + <_> + 0 6 4 2 2. + 0 + 7.1067700628191233e-004 + -0.1545806974172592 + 0.1262297928333283 + <_> + + <_> + + + + <_> + 8 9 9 6 -1. + <_> + 8 11 9 2 3. + 0 + -0.0294274203479290 + 0.2070481926202774 + -0.0861818864941597 + <_> + + <_> + + + + <_> + 4 11 3 1 -1. + <_> + 5 12 1 1 3. + 1 + -3.7067469675093889e-003 + -0.5155926942825317 + 0.0383589081466198 + <_> + + <_> + + + + <_> + 23 14 2 1 -1. + <_> + 23 14 1 1 2. + 0 + 6.0146670875838026e-005 + -0.1023617982864380 + 0.0884054377675056 + <_> + + <_> + + + + <_> + 0 14 2 1 -1. + <_> + 1 14 1 1 2. + 0 + -6.8713612563442439e-005 + 0.1984436959028244 + -0.0994443595409393 + <_> + + <_> + + + + <_> + 11 1 4 14 -1. + <_> + 11 8 4 7 2. + 0 + -0.0848333984613419 + -0.3900933861732483 + 0.0397581607103348 + <_> + + <_> + + + + <_> + 4 0 2 3 -1. + <_> + 3 1 2 1 3. + 1 + 0.0115453395992517 + 0.0299104899168015 + -0.5021548867225647 + <_> + + <_> + + + + <_> + 24 12 1 2 -1. + <_> + 24 13 1 1 2. + 0 + 1.2721769744530320e-003 + 0.0357883498072624 + -0.3856284022331238 + <_> + + <_> + + + + <_> + 0 1 14 14 -1. + <_> + 0 8 14 7 2. + 0 + 0.3789406120777130 + 0.0429151207208633 + -0.3726823925971985 + <_> + + <_> + + + + <_> + 13 0 6 15 -1. + <_> + 15 0 2 15 3. + 0 + 0.0587286688387394 + 0.0175066608935595 + -0.7129334807395935 + <_> + + <_> + + + + <_> + 0 1 1 4 -1. + <_> + 0 3 1 2 2. + 0 + -7.2667418862693012e-005 + 0.0852374136447906 + -0.1796067953109741 + <_> + + <_> + + + + <_> + 24 13 1 2 -1. + <_> + 24 14 1 1 2. + 0 + -2.5661939289420843e-003 + -0.4941900074481964 + 0.0211067497730255 + <_> + + <_> + + + + <_> + 0 13 1 2 -1. + <_> + 0 14 1 1 2. + 0 + -6.2544771935790777e-005 + 0.1260727941989899 + -0.1358107030391693 + <_> + + <_> + + + + <_> + 23 11 2 4 -1. + <_> + 23 12 2 2 2. + 0 + -3.3382088877260685e-003 + -0.3425475955009460 + 0.0313290804624558 + <_> + + <_> + + + + <_> + 0 11 2 4 -1. + <_> + 0 12 2 2 2. + 0 + 4.0032588876783848e-003 + 0.0353341810405254 + -0.4785414040088654 + <_> + + <_> + + + + <_> + 16 10 2 2 -1. + <_> + 17 10 1 1 2. + <_> + 16 11 1 1 2. + 0 + 7.8725446655880660e-005 + -0.0865093916654587 + 0.1098069027066231 + <_> + + <_> + + + + <_> + 7 10 2 2 -1. + <_> + 7 10 1 1 2. + <_> + 8 11 1 1 2. + 0 + 3.5411381395533681e-004 + -0.0866223275661469 + 0.1815810948610306 + <_> + + <_> + + + + <_> + 1 0 24 6 -1. + <_> + 13 0 12 3 2. + <_> + 1 3 12 3 2. + 0 + -0.1003293022513390 + -0.4118100106716156 + 0.0407990105450153 + <_> + + <_> + + + + <_> + 6 1 6 12 -1. + <_> + 8 1 2 12 3. + 0 + 0.0457341782748699 + 0.0250630006194115 + -0.5801063179969788 + <_> + + <_> + + + + <_> + 19 6 6 3 -1. + <_> + 19 7 6 1 3. + 0 + 0.0143571095541120 + 0.0273739993572235 + -0.3111906945705414 + <_> + + <_> + + + + <_> + 5 6 7 2 -1. + <_> + 5 7 7 1 2. + 0 + 4.2823958210647106e-003 + -0.1212206035852432 + 0.1300680041313171 + <_> + + <_> + + + + <_> + 9 6 7 4 -1. + <_> + 9 7 7 2 2. + 0 + -0.0191692691296339 + 0.3547115027904511 + -0.0586979016661644 + <_> + + <_> + + + + <_> + 0 6 6 3 -1. + <_> + 0 7 6 1 3. + 0 + 0.0203719399869442 + 0.0270470399409533 + -0.6216102838516235 + <_> + + <_> + + + + <_> + 6 8 13 4 -1. + <_> + 6 9 13 2 2. + 0 + -0.0119816595688462 + 0.1762886941432953 + -0.0943156927824020 + <_> + + <_> + + + + <_> + 7 10 2 2 -1. + <_> + 7 10 1 1 2. + <_> + 8 11 1 1 2. + 0 + -9.4278322649188340e-005 + 0.1507049947977066 + -0.1071290969848633 + <_> + + <_> + + + + <_> + 12 11 6 2 -1. + <_> + 14 11 2 2 3. + 0 + 0.0101822800934315 + 0.0161433499306440 + -0.3503915071487427 + <_> + + <_> + + + + <_> + 6 0 12 10 -1. + <_> + 6 0 6 5 2. + <_> + 12 5 6 5 2. + 0 + -0.0520590804517269 + -0.3121460080146790 + 0.0477841906249523 + <_> + + <_> + + + + <_> + 12 11 6 2 -1. + <_> + 14 11 2 2 3. + 0 + -0.0249434690922499 + -0.7933396100997925 + -4.0430951048620045e-004 + <_> + + <_> + + + + <_> + 7 0 2 2 -1. + <_> + 7 0 1 1 2. + <_> + 8 1 1 1 2. + 0 + -6.2259827973321080e-004 + 0.2043831050395966 + -0.0712744519114494 + <_> + + <_> + + + + <_> + 16 0 2 2 -1. + <_> + 17 0 1 1 2. + <_> + 16 1 1 1 2. + 0 + -5.6859298638300970e-005 + 0.0861500576138496 + -0.0658712089061737 + <_> + + <_> + + + + <_> + 7 0 2 2 -1. + <_> + 7 0 1 1 2. + <_> + 8 1 1 1 2. + 0 + 4.0834350511431694e-004 + -0.1051706001162529 + 0.2224697023630142 + <_> + + <_> + + + + <_> + 12 11 6 2 -1. + <_> + 14 11 2 2 3. + 0 + -1.1075460352003574e-003 + 0.0464305393397808 + -0.0319086797535419 + <_> + + <_> + + + + <_> + 7 11 6 2 -1. + <_> + 9 11 2 2 3. + 0 + -0.0123662399128079 + -0.6207143068313599 + 0.0261646900326014 + <_> + + <_> + + + + <_> + 5 12 18 3 -1. + <_> + 11 12 6 3 3. + 0 + -0.0354762189090252 + 0.1230582967400551 + -0.0519298203289509 + <_> + + <_> + + + + <_> + 2 0 1 2 -1. + <_> + 2 0 1 1 2. + 1 + -2.3794448934495449e-003 + -0.3795419931411743 + 0.0417488515377045 + <_> + + <_> + + + + <_> + 21 4 4 2 -1. + <_> + 23 4 2 1 2. + <_> + 21 5 2 1 2. + 0 + 1.3966970145702362e-003 + -0.0851486772298813 + 0.1512037962675095 + <_> + + <_> + + + + <_> + 9 3 7 3 -1. + <_> + 9 4 7 1 3. + 0 + 5.1437891088426113e-003 + -0.0816644281148911 + 0.1789588034152985 + <_> + + <_> + + + + <_> + 13 2 8 5 -1. + <_> + 15 4 4 5 2. + 1 + -0.1239939033985138 + -0.6658980846405029 + 9.5204189419746399e-003 + <_> + + <_> + + + + <_> + 12 1 6 4 -1. + <_> + 11 2 6 2 2. + 1 + 0.0393908508121967 + 0.0182536505162716 + -0.7637290954589844 + <_> + + <_> + + + + <_> + 22 0 2 2 -1. + <_> + 22 1 2 1 2. + 0 + 2.9372270219027996e-003 + 0.0226261299103498 + -0.3233875036239624 + <_> + + <_> + + + + <_> + 4 1 16 12 -1. + <_> + 12 1 8 12 2. + 0 + 0.1816650927066803 + -0.0618673898279667 + 0.2298932969570160 + <_> + + <_> + + + + <_> + 3 0 20 10 -1. + <_> + 3 0 10 10 2. + 0 + 0.0892752110958099 + -0.0848015919327736 + 0.2109096944332123 + <_> + + <_> + + + + <_> + 0 4 6 6 -1. + <_> + 0 4 3 3 2. + <_> + 3 7 3 3 2. + 0 + 0.0179201308637857 + -0.0663900971412659 + 0.2243462055921555 + <_> + + <_> + + + + <_> + 22 4 3 3 -1. + <_> + 23 5 1 3 3. + 1 + 5.5024111643433571e-003 + -0.0559136196970940 + 0.1079157963395119 + <_> + + <_> + + + + <_> + 3 4 3 3 -1. + <_> + 2 5 3 1 3. + 1 + -0.0126318400725722 + 0.3352184891700745 + -0.0470694787800312 + <_> + + <_> + + + + <_> + 22 7 3 4 -1. + <_> + 22 8 3 2 2. + 0 + 8.2040186971426010e-003 + 0.0521674789488316 + -0.5830680727958679 + <_> + + <_> + + + + <_> + 3 1 4 7 -1. + <_> + 4 1 2 7 2. + 0 + 0.0215438604354858 + 0.0103719802573323 + -0.8169081807136536 + <_> + + <_> + + + + <_> + 22 7 3 4 -1. + <_> + 22 8 3 2 2. + 0 + -4.2779878713190556e-003 + -0.3437061011791229 + 0.0348356589674950 + <_> + + <_> + + + + <_> + 2 0 1 2 -1. + <_> + 2 0 1 1 2. + 1 + 9.5721762627363205e-003 + 0.0160374492406845 + -0.7592146992683411 + <_> + + <_> + + + + <_> + 18 4 6 2 -1. + <_> + 18 5 6 1 2. + 0 + 5.9499992057681084e-003 + -0.0835138633847237 + 0.0937561765313149 + <_> + + <_> + + + + <_> + 5 3 15 6 -1. + <_> + 5 5 15 2 3. + 0 + -0.0868803784251213 + 0.1977919936180115 + -0.0735685229301453 + <_> + + <_> + + + + <_> + 16 4 8 4 -1. + <_> + 16 5 8 2 2. + 0 + 5.7690730318427086e-003 + -0.0611343309283257 + 0.0826714411377907 + <_> + + <_> + + + + <_> + 0 1 24 10 -1. + <_> + 0 1 12 5 2. + <_> + 12 6 12 5 2. + 0 + 0.1480645984411240 + 0.0396532900631428 + -0.4085262119770050 + <_> + + <_> + + + + <_> + 14 0 4 7 -1. + <_> + 15 0 2 7 2. + 0 + -0.0186682697385550 + -0.6671301126480103 + 0.0156445093452930 + <_> + + <_> + + + + <_> + 0 7 3 4 -1. + <_> + 0 8 3 2 2. + 0 + 0.0101426700130105 + 0.0211487896740437 + -0.5610821843147278 + <_> + + <_> + + + + <_> + 18 5 4 4 -1. + <_> + 20 5 2 2 2. + <_> + 18 7 2 2 2. + 0 + -2.6263110339641571e-003 + 0.0881423130631447 + -0.0586008317768574 + <_> + + <_> + + + + <_> + 5 5 6 2 -1. + <_> + 5 5 3 1 2. + <_> + 8 6 3 1 2. + 0 + 3.0406240839511156e-003 + -0.0699731782078743 + 0.1942113041877747 + <_> + + <_> + + + + <_> + 21 9 2 3 -1. + <_> + 21 10 2 1 3. + 0 + -4.0523111820220947e-003 + -0.3989843130111694 + 0.0284519009292126 + <_> + + <_> + + + + <_> + 7 1 2 2 -1. + <_> + 7 1 1 1 2. + <_> + 8 2 1 1 2. + 0 + 3.3293411252088845e-004 + -0.0920187085866928 + 0.1521372944116592 + <_> + + <_> + + + + <_> + 16 1 2 2 -1. + <_> + 17 1 1 1 2. + <_> + 16 2 1 1 2. + 0 + -1.4471479516942054e-004 + 0.1328881978988648 + -0.0869787335395813 + -1.4393190145492554 + 9 + -1 + <_> + + + <_> + + <_> + + + + <_> + 9 7 7 6 -1. + <_> + 9 9 7 2 3. + 0 + -0.0305288899689913 + 0.3361127972602844 + -0.1605879068374634 + <_> + + <_> + + + + <_> + 17 2 7 2 -1. + <_> + 17 3 7 1 2. + 0 + -6.8238358944654465e-003 + 0.2510839104652405 + -0.2578383982181549 + <_> + + <_> + + + + <_> + 4 2 9 4 -1. + <_> + 3 3 9 2 2. + 1 + -0.0260700508952141 + 0.3176701068878174 + -0.1111562028527260 + <_> + + <_> + + + + <_> + 19 14 6 1 -1. + <_> + 19 14 3 1 2. + 0 + 1.6021650517359376e-003 + -0.1096177026629448 + 0.1561331003904343 + <_> + + <_> + + + + <_> + 6 9 11 6 -1. + <_> + 6 11 11 2 3. + 0 + -0.0346175394952297 + 0.2614395916461945 + -0.0955564379692078 + <_> + + <_> + + + + <_> + 17 3 8 12 -1. + <_> + 21 3 4 6 2. + <_> + 17 9 4 6 2. + 0 + 0.0825498923659325 + -0.0359772108495235 + 0.3189736902713776 + <_> + + <_> + + + + <_> + 0 7 24 8 -1. + <_> + 0 7 12 4 2. + <_> + 12 11 12 4 2. + 0 + -0.1079908013343811 + -0.4661987125873566 + 0.0965379774570465 + <_> + + <_> + + + + <_> + 5 3 16 12 -1. + <_> + 13 3 8 6 2. + <_> + 5 9 8 6 2. + 0 + -0.0710962936282158 + -0.3290941119194031 + 0.0201707594096661 + <_> + + <_> + + + + <_> + 0 3 24 6 -1. + <_> + 8 5 8 2 9. + 0 + 0.6102272272109985 + -0.0410851910710335 + 0.5919780731201172 + <_> + + <_> + + + + <_> + 1 8 24 1 -1. + <_> + 7 8 12 1 2. + 0 + -9.6180485561490059e-003 + 0.1845327019691467 + -0.1256957054138184 + <_> + + <_> + + + + <_> + 1 9 14 6 -1. + <_> + 1 9 7 3 2. + <_> + 8 12 7 3 2. + 0 + -0.0216567497700453 + 0.3558863103389740 + -0.0654195472598076 + <_> + + <_> + + + + <_> + 19 5 3 2 -1. + <_> + 19 6 3 1 2. + 0 + 3.2288730144500732e-003 + -0.1597114056348801 + 0.1442176997661591 + <_> + + <_> + + + + <_> + 0 14 10 1 -1. + <_> + 5 14 5 1 2. + 0 + 3.6023850552737713e-003 + -0.1301265954971314 + 0.1848530024290085 + <_> + + <_> + + + + <_> + 5 1 15 6 -1. + <_> + 5 3 15 2 3. + 0 + 0.1224254965782166 + -0.0509620085358620 + 0.4787274003028870 + <_> + + <_> + + + + <_> + 1 1 7 6 -1. + <_> + 1 3 7 2 3. + 0 + -0.0398168414831162 + 0.1911015063524246 + -0.1490415036678314 + <_> + + <_> + + + + <_> + 15 12 6 3 -1. + <_> + 17 13 2 1 9. + 0 + 0.0165654607117176 + 0.0250385701656342 + -0.2660810947418213 + <_> + + <_> + + + + <_> + 4 0 1 3 -1. + <_> + 3 1 1 1 3. + 1 + 6.7314971238374710e-003 + 0.0361662209033966 + -0.5751237273216248 + <_> + + <_> + + + + <_> + 1 12 24 3 -1. + <_> + 7 12 12 3 2. + 0 + -0.0238826293498278 + 0.1817242056131363 + -0.1013408973813057 + <_> + + <_> + + + + <_> + 3 12 6 3 -1. + <_> + 5 13 2 1 9. + 0 + 0.0168766304850578 + 0.0499957092106342 + -0.4964488148689270 + <_> + + <_> + + + + <_> + 1 0 24 12 -1. + <_> + 13 0 12 6 2. + <_> + 1 6 12 6 2. + 0 + 0.0814632922410965 + 0.0508196912705898 + -0.3092927038669586 + <_> + + <_> + + + + <_> + 2 0 21 15 -1. + <_> + 9 0 7 15 3. + 0 + 0.1567866057157517 + -0.0846417918801308 + 0.2097589969635010 + <_> + + <_> + + + + <_> + 17 3 6 2 -1. + <_> + 17 4 6 1 2. + 0 + 0.0107369897887111 + -0.0588766187429428 + 0.2673564851284027 + <_> + + <_> + + + + <_> + 3 3 14 2 -1. + <_> + 3 4 14 1 2. + 0 + -0.0162507798522711 + 0.2185824960470200 + -0.1275278925895691 + <_> + + <_> + + + + <_> + 4 0 21 4 -1. + <_> + 11 0 7 4 3. + 0 + -0.0513998307287693 + 0.1707165986299515 + -0.0564976185560226 + <_> + + <_> + + + + <_> + 6 13 4 1 -1. + <_> + 7 13 2 1 2. + 0 + 1.8661050125956535e-003 + 0.0403385981917381 + -0.4740450084209442 + <_> + + <_> + + + + <_> + 17 3 8 12 -1. + <_> + 21 3 4 6 2. + <_> + 17 9 4 6 2. + 0 + -0.0494354106485844 + 0.1537600010633469 + -0.0417859293520451 + <_> + + <_> + + + + <_> + 0 3 8 12 -1. + <_> + 0 3 4 6 2. + <_> + 4 9 4 6 2. + 0 + 0.0696671828627586 + -0.0588539093732834 + 0.3099964857101440 + <_> + + <_> + + + + <_> + 5 0 16 8 -1. + <_> + 13 0 8 4 2. + <_> + 5 4 8 4 2. + 0 + -0.0781185403466225 + -0.4109517037868500 + 0.0523068793118000 + <_> + + <_> + + + + <_> + 3 7 4 2 -1. + <_> + 4 8 2 2 2. + 1 + -8.6161941289901733e-003 + -0.5668942928314209 + 0.0286804605275393 + <_> + + <_> + + + + <_> + 5 11 15 4 -1. + <_> + 5 12 15 2 2. + 0 + 6.8916371092200279e-003 + -0.0957784205675125 + 0.1680631041526794 + <_> + + <_> + + + + <_> + 10 13 1 2 -1. + <_> + 10 14 1 1 2. + 0 + 8.4734419942833483e-005 + -0.1476065963506699 + 0.1278074979782105 + <_> + + <_> + + + + <_> + 12 14 6 1 -1. + <_> + 14 14 2 1 3. + 0 + -6.5460228361189365e-003 + -0.5353912711143494 + 0.0211423803120852 + <_> + + <_> + + + + <_> + 9 5 6 4 -1. + <_> + 9 6 6 2 2. + 0 + -0.0119369700551033 + 0.2489618957042694 + -0.0659059137105942 + <_> + + <_> + + + + <_> + 12 5 13 2 -1. + <_> + 12 6 13 1 2. + 0 + 0.0160134993493557 + -0.0751639306545258 + 0.0920000970363617 + <_> + + <_> + + + + <_> + 5 0 15 6 -1. + <_> + 5 2 15 2 3. + 0 + -0.1797882020473480 + 0.3122220933437347 + -0.0546800307929516 + <_> + + <_> + + + + <_> + 3 0 20 15 -1. + <_> + 3 0 10 15 2. + 0 + 0.4293603003025055 + -0.0467442497611046 + 0.4671711027622223 + <_> + + <_> + + + + <_> + 1 1 22 14 -1. + <_> + 12 1 11 14 2. + 0 + 0.1762980967760086 + -0.1196762025356293 + 0.2303612977266312 + <_> + + <_> + + + + <_> + 15 5 10 2 -1. + <_> + 15 6 10 1 2. + 0 + 0.0434980615973473 + 0.0213767793029547 + -0.3402695953845978 + <_> + + <_> + + + + <_> + 0 5 13 2 -1. + <_> + 0 6 13 1 2. + 0 + 0.0168955195695162 + -0.1305568963289261 + 0.1834042966365814 + <_> + + <_> + + + + <_> + 5 2 15 4 -1. + <_> + 5 3 15 2 2. + 0 + 0.0185353793203831 + -0.0754243135452271 + 0.2354936003684998 + <_> + + <_> + + + + <_> + 5 4 15 3 -1. + <_> + 5 5 15 1 3. + 0 + 0.0173294302076101 + -0.0853839814662933 + 0.2036404013633728 + <_> + + <_> + + + + <_> + 21 11 4 4 -1. + <_> + 21 12 4 2 2. + 0 + 8.6630741134285927e-003 + 0.0385910011827946 + -0.6201460957527161 + <_> + + <_> + + + + <_> + 5 0 1 2 -1. + <_> + 5 0 1 1 2. + 1 + 5.7052681222558022e-003 + 0.0312472805380821 + -0.4070529043674469 + <_> + + <_> + + + + <_> + 23 3 2 4 -1. + <_> + 23 3 1 4 2. + 0 + -1.8030379433184862e-003 + 0.1957851052284241 + -0.1433366984128952 + <_> + + <_> + + + + <_> + 7 1 4 6 -1. + <_> + 8 1 2 6 2. + 0 + -0.0187879204750061 + -0.8691418766975403 + 0.0169819705188274 + <_> + + <_> + + + + <_> + 8 6 11 3 -1. + <_> + 8 7 11 1 3. + 0 + 0.0186009202152491 + -0.0818153098225594 + 0.1891387999057770 + <_> + + <_> + + + + <_> + 0 13 2 1 -1. + <_> + 1 13 1 1 2. + 0 + 8.4120598330628127e-005 + -0.1289912015199661 + 0.1211050972342491 + <_> + + <_> + + + + <_> + 21 12 3 3 -1. + <_> + 21 13 3 1 3. + 0 + -5.6057129986584187e-003 + -0.4698300957679749 + 0.0159890707582235 + <_> + + <_> + + + + <_> + 1 12 3 3 -1. + <_> + 1 13 3 1 3. + 0 + 3.5192570649087429e-003 + 0.0361930206418037 + -0.4484112858772278 + <_> + + <_> + + + + <_> + 23 3 2 4 -1. + <_> + 23 3 1 4 2. + 0 + 1.7741440096870065e-003 + -0.0433034710586071 + 0.1395574957132340 + <_> + + <_> + + + + <_> + 0 3 2 4 -1. + <_> + 1 3 1 4 2. + 0 + -1.6350420191884041e-003 + 0.1395068019628525 + -0.1124152988195419 + <_> + + <_> + + + + <_> + 21 3 4 10 -1. + <_> + 23 3 2 5 2. + <_> + 21 8 2 5 2. + 0 + 6.4794770441949368e-003 + -0.0600515604019165 + 0.0728941932320595 + <_> + + <_> + + + + <_> + 0 3 4 10 -1. + <_> + 0 3 2 5 2. + <_> + 2 8 2 5 2. + 0 + -0.0203247498720884 + 0.4297815859317780 + -0.0396846085786819 + <_> + + <_> + + + + <_> + 24 1 1 4 -1. + <_> + 24 2 1 2 2. + 0 + -6.3453041948378086e-003 + -0.2533842921257019 + 0.0242939405143261 + <_> + + <_> + + + + <_> + 0 0 1 6 -1. + <_> + 0 2 1 2 3. + 0 + 9.0959975495934486e-003 + 0.0340887792408466 + -0.4518730044364929 + <_> + + <_> + + + + <_> + 16 1 4 4 -1. + <_> + 17 1 2 4 2. + 0 + 0.0161635801196098 + 6.8225921131670475e-003 + -0.7205737829208374 + <_> + + <_> + + + + <_> + 5 1 4 4 -1. + <_> + 6 1 2 4 2. + 0 + -0.0112293101847172 + -0.6191986203193665 + 0.0222914796322584 + <_> + + <_> + + + + <_> + 15 2 10 12 -1. + <_> + 15 8 10 6 2. + 0 + -0.1763328015804291 + -0.6819115877151489 + 8.8407555595040321e-003 + <_> + + <_> + + + + <_> + 8 5 9 3 -1. + <_> + 8 6 9 1 3. + 0 + 0.0192962400615215 + -0.0796290487051010 + 0.2013067007064819 + <_> + + <_> + + + + <_> + 6 7 14 2 -1. + <_> + 6 8 14 1 2. + 0 + 0.0105654401704669 + -0.0832984521985054 + 0.1872760951519013 + <_> + + <_> + + + + <_> + 10 7 5 4 -1. + <_> + 10 8 5 2 2. + 0 + -6.7616738379001617e-003 + 0.2069583982229233 + -0.0813189968466759 + <_> + + <_> + + + + <_> + 23 12 2 3 -1. + <_> + 23 13 2 1 3. + 0 + -2.3086878936737776e-003 + -0.2798121869564056 + 0.0293897707015276 + <_> + + <_> + + + + <_> + 0 7 4 4 -1. + <_> + 0 8 4 2 2. + 0 + -6.9189318455755711e-003 + -0.5095586180686951 + 0.0291001908481121 + <_> + + <_> + + + + <_> + 3 13 21 2 -1. + <_> + 10 13 7 2 3. + 0 + -0.0195926092565060 + 0.1248695999383926 + -0.0666698589920998 + <_> + + <_> + + + + <_> + 6 1 3 1 -1. + <_> + 7 1 1 1 3. + 0 + -5.6698801927268505e-004 + 0.1772525012493134 + -0.0755556300282478 + <_> + + <_> + + + + <_> + 16 0 2 2 -1. + <_> + 17 0 1 1 2. + <_> + 16 1 1 1 2. + 0 + 6.5187108702957630e-004 + -0.0468317084014416 + 0.1377387940883637 + <_> + + <_> + + + + <_> + 7 0 2 2 -1. + <_> + 7 0 1 1 2. + <_> + 8 1 1 1 2. + 0 + -4.3244438711553812e-004 + 0.1750548034906387 + -0.0822173282504082 + <_> + + <_> + + + + <_> + 23 12 2 3 -1. + <_> + 23 13 2 1 3. + 0 + 3.2091289758682251e-003 + 0.0258904304355383 + -0.3546032905578613 + <_> + + <_> + + + + <_> + 8 8 9 2 -1. + <_> + 11 8 3 2 3. + 0 + -0.0288993604481220 + -0.7315214276313782 + 0.0180548094213009 + <_> + + <_> + + + + <_> + 23 12 2 3 -1. + <_> + 23 13 2 1 3. + 0 + 9.8803699074778706e-005 + -0.0383186303079128 + 0.0343451388180256 + <_> + + <_> + + + + <_> + 0 12 2 3 -1. + <_> + 0 13 2 1 3. + 0 + -2.2848090156912804e-003 + -0.3603490889072418 + 0.0380517281591892 + <_> + + <_> + + + + <_> + 8 4 9 9 -1. + <_> + 8 7 9 3 3. + 0 + 0.2230083048343658 + -0.0353877097368240 + 0.4118692874908447 + <_> + + <_> + + + + <_> + 3 11 12 4 -1. + <_> + 3 11 6 2 2. + <_> + 9 13 6 2 2. + 0 + 3.8663020823150873e-003 + -0.1147940978407860 + 0.1196625977754593 + <_> + + <_> + + + + <_> + 10 10 5 4 -1. + <_> + 10 11 5 2 2. + 0 + 3.6781090311706066e-003 + -0.0887862071394920 + 0.2093122005462647 + <_> + + <_> + + + + <_> + 7 14 6 1 -1. + <_> + 9 14 2 1 3. + 0 + 3.6886930465698242e-003 + 0.0420652516186237 + -0.3311671912670136 + <_> + + <_> + + + + <_> + 4 0 18 15 -1. + <_> + 4 0 9 15 2. + 0 + -0.5000842809677124 + 0.4582319855690002 + -0.0300164502114058 + <_> + + <_> + + + + <_> + 0 3 4 4 -1. + <_> + 1 3 2 4 2. + 0 + 3.2457590568810701e-003 + -0.0581394806504250 + 0.2244455963373184 + <_> + + <_> + + + + <_> + 22 0 3 4 -1. + <_> + 22 2 3 2 2. + 0 + -7.2515371721237898e-004 + 0.0857456997036934 + -0.2164471000432968 + <_> + + <_> + + + + <_> + 0 0 20 8 -1. + <_> + 5 0 10 8 2. + 0 + 0.0756241232156754 + -0.0728698670864105 + 0.1809341013431549 + <_> + + <_> + + + + <_> + 1 5 24 10 -1. + <_> + 13 5 12 5 2. + <_> + 1 10 12 5 2. + 0 + -0.1401147991418839 + -0.3049497008323669 + 0.0322263389825821 + <_> + + <_> + + + + <_> + 0 5 5 6 -1. + <_> + 0 7 5 2 3. + 0 + 1.2914249673485756e-003 + -0.1651930958032608 + 0.0796989724040031 + <_> + + <_> + + + + <_> + 18 3 4 2 -1. + <_> + 18 4 4 1 2. + 0 + 4.8063062131404877e-003 + -0.0511631406843662 + 0.1528493016958237 + <_> + + <_> + + + + <_> + 2 3 4 2 -1. + <_> + 2 3 4 1 2. + 1 + 0.0197005104273558 + -0.0214679203927517 + 0.5898631215095520 + <_> + + <_> + + + + <_> + 14 1 6 6 -1. + <_> + 16 1 2 6 3. + 0 + -0.0282465498894453 + -0.3611007034778595 + 0.0215946007519960 + <_> + + <_> + + + + <_> + 5 1 6 6 -1. + <_> + 7 1 2 6 3. + 0 + 0.0318388007581234 + 0.0213881190866232 + -0.5591915845870972 + <_> + + <_> + + + + <_> + 11 10 6 1 -1. + <_> + 13 10 2 1 3. + 0 + 5.2926959469914436e-003 + 0.0171414706856012 + -0.3245368003845215 + <_> + + <_> + + + + <_> + 6 8 11 4 -1. + <_> + 6 9 11 2 2. + 0 + 9.3176206573843956e-003 + -0.0691479519009590 + 0.1877806931734085 + <_> + + <_> + + + + <_> + 23 13 2 2 -1. + <_> + 24 13 1 1 2. + <_> + 23 14 1 1 2. + 0 + 1.9812679965980351e-004 + -0.0710251703858376 + 0.1166272014379501 + <_> + + <_> + + + + <_> + 6 0 13 4 -1. + <_> + 6 1 13 2 2. + 0 + 0.0172033403068781 + -0.0834768265485764 + 0.1448491960763931 + <_> + + <_> + + + + <_> + 17 0 3 1 -1. + <_> + 18 1 1 1 3. + 1 + 8.0548562109470367e-003 + 0.0214444492012262 + -0.2763100862503052 + <_> + + <_> + + + + <_> + 8 0 1 3 -1. + <_> + 7 1 1 1 3. + 1 + 6.7419088445603848e-003 + 0.0341341383755207 + -0.3555370867252350 + <_> + + <_> + + + + <_> + 22 12 2 2 -1. + <_> + 23 12 1 1 2. + <_> + 22 13 1 1 2. + 0 + 5.7136920077027753e-005 + -0.0699329003691673 + 0.0822271332144737 + <_> + + <_> + + + + <_> + 0 13 2 1 -1. + <_> + 1 13 1 1 2. + 0 + -6.0014430346200243e-005 + 0.1533315926790237 + -0.0801942795515060 + <_> + + <_> + + + + <_> + 22 13 2 1 -1. + <_> + 22 13 1 1 2. + 0 + -6.6377622715663165e-005 + 0.0740585327148438 + -0.0435769110918045 + <_> + + <_> + + + + <_> + 1 13 2 1 -1. + <_> + 2 13 1 1 2. + 0 + 7.0605492510367185e-005 + -0.1192411035299301 + 0.1157367005944252 + <_> + + <_> + + + + <_> + 22 13 3 1 -1. + <_> + 23 13 1 1 3. + 0 + 7.2301438194699585e-005 + -0.0702318474650383 + 0.0793638303875923 + <_> + + <_> + + + + <_> + 1 2 2 12 -1. + <_> + 2 2 1 12 2. + 0 + -1.4867830323055387e-003 + 0.1245760992169380 + -0.1076287999749184 + <_> + + <_> + + + + <_> + 18 3 4 2 -1. + <_> + 18 4 4 1 2. + 0 + -5.2434820681810379e-003 + 0.1116774976253510 + -0.0614912398159504 + <_> + + <_> + + + + <_> + 3 3 4 2 -1. + <_> + 3 4 4 1 2. + 0 + 7.8055239282548428e-003 + -0.0496800504624844 + 0.3046393096446991 + <_> + + <_> + + + + <_> + 24 0 1 12 -1. + <_> + 24 3 1 6 2. + 0 + 0.0167157892137766 + 0.0242684707045555 + -0.5641499757766724 + <_> + + <_> + + + + <_> + 5 8 15 6 -1. + <_> + 5 10 15 2 3. + 0 + -0.0197794307023287 + 0.1293102055788040 + -0.1014008000493050 + <_> + + <_> + + + + <_> + 19 7 6 2 -1. + <_> + 19 7 6 1 2. + 1 + -6.7752218456007540e-005 + 0.0773630663752556 + -0.0876037329435349 + <_> + + <_> + + + + <_> + 1 10 5 3 -1. + <_> + 1 11 5 1 3. + 0 + -0.0129433302208781 + -0.8692914843559265 + 0.0158042199909687 + <_> + + <_> + + + + <_> + 24 0 1 12 -1. + <_> + 24 3 1 6 2. + 0 + -0.0125468103215098 + -0.1350758969783783 + 0.0456306189298630 + <_> + + <_> + + + + <_> + 0 0 1 12 -1. + <_> + 0 3 1 6 2. + 0 + 7.9727862030267715e-003 + 0.0405779294669628 + -0.3409133851528168 + <_> + + <_> + + + + <_> + 9 0 12 1 -1. + <_> + 13 0 4 1 3. + 0 + -6.3152899965643883e-003 + 0.1372991949319840 + -0.0561671592295170 + <_> + + <_> + + + + <_> + 4 0 12 1 -1. + <_> + 8 0 4 1 3. + 0 + -3.6897659301757813e-003 + 0.1639326065778732 + -0.0914164036512375 + <_> + + <_> + + + + <_> + 3 0 20 1 -1. + <_> + 8 0 10 1 2. + 0 + 5.0578881055116653e-003 + -0.0800797268748283 + 0.1433712989091873 + <_> + + <_> + + + + <_> + 1 0 9 2 -1. + <_> + 4 0 3 2 3. + 0 + -0.0299335699528456 + -0.5326762199401856 + 0.0227312203496695 + <_> + + <_> + + + + <_> + 11 6 8 2 -1. + <_> + 11 7 8 1 2. + 0 + 7.0810988545417786e-003 + -0.0732182189822197 + 0.1027508974075317 + <_> + + <_> + + + + <_> + 11 3 3 8 -1. + <_> + 11 7 3 4 2. + 0 + 0.0508137904107571 + 0.0516868904232979 + -0.2544622123241425 + <_> + + <_> + + + + <_> + 20 4 4 2 -1. + <_> + 21 5 2 2 2. + 1 + 4.7044758684933186e-003 + -0.0572907589375973 + 0.0760648325085640 + <_> + + <_> + + + + <_> + 6 7 2 6 -1. + <_> + 6 7 1 6 2. + 1 + 4.6408819034695625e-003 + 0.0559986904263496 + -0.2172269970178604 + <_> + + <_> + + + + <_> + 20 4 4 2 -1. + <_> + 21 5 2 2 2. + 1 + -9.5121748745441437e-003 + 0.1812860071659088 + -0.0377242304384708 + <_> + + <_> + + + + <_> + 5 4 2 4 -1. + <_> + 4 5 2 2 2. + 1 + 2.5726249441504478e-003 + -0.1238458007574081 + 0.1421934068202972 + -1.3500690460205078 + 10 + -1 + <_> + + + <_> + + <_> + + + + <_> + 7 5 11 3 -1. + <_> + 7 6 11 1 3. + 0 + 0.0184330195188522 + -0.1618741005659103 + 0.3351263999938965 + <_> + + <_> + + + + <_> + 20 1 3 4 -1. + <_> + 20 2 3 2 2. + 0 + 4.8202150501310825e-003 + -0.0972008332610130 + 0.2755692005157471 + <_> + + <_> + + + + <_> + 8 4 9 3 -1. + <_> + 8 5 9 1 3. + 0 + 0.0214508101344109 + -0.1013654991984367 + 0.3922119140625000 + <_> + + <_> + + + + <_> + 9 6 9 3 -1. + <_> + 9 7 9 1 3. + 0 + 0.0201995000243187 + -0.1041551977396011 + 0.3485709130764008 + <_> + + <_> + + + + <_> + 0 7 8 8 -1. + <_> + 0 7 4 4 2. + <_> + 4 11 4 4 2. + 0 + 0.0154604399576783 + -0.1814713031053543 + 0.2296576052904129 + <_> + + <_> + + + + <_> + 9 7 7 3 -1. + <_> + 9 8 7 1 3. + 0 + 0.0121146701276302 + -0.0955794528126717 + 0.3321264982223511 + <_> + + <_> + + + + <_> + 8 3 9 3 -1. + <_> + 8 4 9 1 3. + 0 + 0.0166161693632603 + -0.0751067474484444 + 0.3475660085678101 + <_> + + <_> + + + + <_> + 21 1 1 6 -1. + <_> + 19 3 1 2 3. + 1 + -0.0151290399953723 + 0.1396238952875137 + -0.1150512024760246 + <_> + + <_> + + + + <_> + 0 7 24 5 -1. + <_> + 6 7 12 5 2. + 0 + -0.0707296282052994 + 0.2683610916137695 + -0.1016533970832825 + <_> + + <_> + + + + <_> + 24 11 1 2 -1. + <_> + 24 11 1 1 2. + 1 + 2.2831759415566921e-003 + 0.0443518795073032 + -0.4632245898246765 + <_> + + <_> + + + + <_> + 5 2 8 5 -1. + <_> + 5 2 4 5 2. + 1 + 5.5853649973869324e-003 + 0.0919516831636429 + -0.3147256970405579 + <_> + + <_> + + + + <_> + 16 3 8 12 -1. + <_> + 20 3 4 6 2. + <_> + 16 9 4 6 2. + 0 + -0.0406785085797310 + 0.1471066027879715 + -0.0726505890488625 + <_> + + <_> + + + + <_> + 0 0 24 12 -1. + <_> + 0 0 12 6 2. + <_> + 12 6 12 6 2. + 0 + -0.1358978003263474 + -0.5053529739379883 + 0.0469954796135426 + <_> + + <_> + + + + <_> + 8 2 10 8 -1. + <_> + 13 2 5 4 2. + <_> + 8 6 5 4 2. + 0 + -0.0384974703192711 + -0.3717043101787567 + 0.0552083589136600 + <_> + + <_> + + + + <_> + 0 3 2 8 -1. + <_> + 0 3 1 4 2. + <_> + 1 7 1 4 2. + 0 + 2.7928350027650595e-003 + -0.1162076964974403 + 0.1937797069549561 + <_> + + <_> + + + + <_> + 22 11 2 4 -1. + <_> + 22 12 2 2 2. + 0 + 5.3412551060318947e-003 + 0.0129640102386475 + -0.4924449026584625 + <_> + + <_> + + + + <_> + 1 11 2 4 -1. + <_> + 1 12 2 2 2. + 0 + -2.6604509912431240e-003 + -0.4564127027988434 + 0.0437755398452282 + <_> + + <_> + + + + <_> + 12 2 13 12 -1. + <_> + 12 8 13 6 2. + 0 + 0.3209887146949768 + 0.0484563298523426 + -0.3930096924304962 + <_> + + <_> + + + + <_> + 5 8 2 4 -1. + <_> + 5 8 1 4 2. + 1 + -7.2495201602578163e-003 + -0.4188942015171051 + 0.0410884395241737 + <_> + + <_> + + + + <_> + 15 6 6 7 -1. + <_> + 17 6 2 7 3. + 0 + 0.0233532395213842 + 0.0302080996334553 + -0.3757928013801575 + <_> + + <_> + + + + <_> + 4 6 6 6 -1. + <_> + 6 6 2 6 3. + 0 + -0.0224980209022760 + -0.4524075090885162 + 0.0389229394495487 + <_> + + <_> + + + + <_> + 13 13 9 2 -1. + <_> + 16 13 3 2 3. + 0 + -0.0238666702061892 + -0.5288146734237671 + 0.0138155296444893 + <_> + + <_> + + + + <_> + 4 4 7 4 -1. + <_> + 3 5 7 2 2. + 1 + -0.0336419306695461 + 0.4436714053153992 + -0.0403416194021702 + <_> + + <_> + + + + <_> + 18 4 6 8 -1. + <_> + 21 4 3 4 2. + <_> + 18 8 3 4 2. + 0 + 0.0221408791840076 + -0.0495454296469688 + 0.2051838934421539 + <_> + + <_> + + + + <_> + 3 14 9 1 -1. + <_> + 6 14 3 1 3. + 0 + 0.0106034297496080 + 0.0319968499243259 + -0.5148760080337524 + <_> + + <_> + + + + <_> + 11 11 14 4 -1. + <_> + 18 11 7 2 2. + <_> + 11 13 7 2 2. + 0 + 9.6357148140668869e-003 + -0.1237379983067513 + 0.1527843028306961 + <_> + + <_> + + + + <_> + 1 4 6 8 -1. + <_> + 1 4 3 4 2. + <_> + 4 8 3 4 2. + 0 + 0.0297187492251396 + -0.0567854084074497 + 0.2904588878154755 + <_> + + <_> + + + + <_> + 23 0 2 2 -1. + <_> + 23 0 1 2 2. + 1 + 2.0548420434352010e-004 + -0.2718465924263001 + 0.1070784032344818 + <_> + + <_> + + + + <_> + 6 0 13 4 -1. + <_> + 6 1 13 2 2. + 0 + -0.0486726500093937 + 0.4235774874687195 + -0.0456859990954399 + <_> + + <_> + + + + <_> + 11 0 4 2 -1. + <_> + 11 1 4 1 2. + 0 + 2.5377809070050716e-003 + -0.0727348327636719 + 0.2103600949048996 + <_> + + <_> + + + + <_> + 2 0 2 2 -1. + <_> + 2 0 2 1 2. + 1 + -3.3941529691219330e-003 + -0.3815236985683441 + 0.0445483289659023 + <_> + + <_> + + + + <_> + 20 9 5 6 -1. + <_> + 20 11 5 2 3. + 0 + -0.0237451493740082 + -0.4413619935512543 + 0.0249414704740047 + <_> + + <_> + + + + <_> + 5 2 15 3 -1. + <_> + 5 3 15 1 3. + 0 + -0.0200922992080450 + 0.1694606989622116 + -0.0953345969319344 + <_> + + <_> + + + + <_> + 9 2 7 3 -1. + <_> + 9 3 7 1 3. + 0 + 0.0110265100374818 + -0.0721762925386429 + 0.2484644949436188 + <_> + + <_> + + + + <_> + 2 14 21 1 -1. + <_> + 9 14 7 1 3. + 0 + -0.0158068798482418 + 0.2241718024015427 + -0.0724460408091545 + <_> + + <_> + + + + <_> + 8 11 16 4 -1. + <_> + 8 11 8 4 2. + 0 + 0.0490073598921299 + -0.0551217384636402 + 0.2583925127983093 + <_> + + <_> + + + + <_> + 0 12 24 2 -1. + <_> + 12 12 12 2 2. + 0 + 0.0288716107606888 + -0.1153011992573738 + 0.1924846023321152 + <_> + + <_> + + + + <_> + 22 9 3 6 -1. + <_> + 22 11 3 2 3. + 0 + 7.3990179225802422e-003 + 0.0522995889186859 + -0.2191856950521469 + <_> + + <_> + + + + <_> + 0 1 12 2 -1. + <_> + 0 1 6 1 2. + <_> + 6 2 6 1 2. + 0 + -6.1737848445773125e-003 + 0.2038096934556961 + -0.0696693286299706 + <_> + + <_> + + + + <_> + 8 9 9 3 -1. + <_> + 8 10 9 1 3. + 0 + 9.4332564622163773e-003 + -0.0534071698784828 + 0.2586283981800079 + <_> + + <_> + + + + <_> + 0 9 3 6 -1. + <_> + 0 11 3 2 3. + 0 + 0.0143210804089904 + 0.0336425192654133 + -0.4679594039916992 + <_> + + <_> + + + + <_> + 11 11 14 4 -1. + <_> + 18 11 7 2 2. + <_> + 11 13 7 2 2. + 0 + 0.0224872808903456 + -0.0431007482111454 + 0.1123055964708328 + <_> + + <_> + + + + <_> + 7 9 4 6 -1. + <_> + 8 9 2 6 2. + 0 + -8.8018830865621567e-003 + -0.5997744798660278 + 0.0238500293344259 + <_> + + <_> + + + + <_> + 10 12 6 2 -1. + <_> + 12 12 2 2 3. + 0 + -9.2824921011924744e-003 + -0.3792850077152252 + 0.0247395392507315 + <_> + + <_> + + + + <_> + 0 12 1 2 -1. + <_> + 0 13 1 1 2. + 0 + -3.8288799260044470e-005 + 0.1094501987099648 + -0.1270592063665390 + <_> + + <_> + + + + <_> + 15 3 10 12 -1. + <_> + 20 3 5 6 2. + <_> + 15 9 5 6 2. + 0 + -0.1060767024755478 + 0.1223917007446289 + -0.0179706607013941 + <_> + + <_> + + + + <_> + 10 9 4 6 -1. + <_> + 10 9 2 3 2. + <_> + 12 12 2 3 2. + 0 + 0.0145011199638247 + 0.0254385806620121 + -0.5499516725540161 + <_> + + <_> + + + + <_> + 11 3 6 4 -1. + <_> + 11 3 3 4 2. + 0 + -0.0294254906475544 + -0.4407989084720612 + 0.0163295306265354 + <_> + + <_> + + + + <_> + 0 0 14 14 -1. + <_> + 0 7 14 7 2. + 0 + -0.2141247987747192 + -0.5817149281501770 + 0.0224080495536327 + <_> + + <_> + + + + <_> + 15 2 10 12 -1. + <_> + 20 2 5 6 2. + <_> + 15 8 5 6 2. + 0 + -0.0159379299730062 + 0.0447719283401966 + -0.0470217689871788 + <_> + + <_> + + + + <_> + 8 3 6 4 -1. + <_> + 11 3 3 4 2. + 0 + 0.0358322896063328 + 0.0257156305015087 + -0.5430511236190796 + <_> + + <_> + + + + <_> + 23 5 2 6 -1. + <_> + 23 7 2 2 3. + 0 + -0.0114978998899460 + -0.4132392108440399 + 0.0246592592447996 + <_> + + <_> + + + + <_> + 10 8 5 3 -1. + <_> + 10 9 5 1 3. + 0 + 7.6680490747094154e-003 + -0.0596144981682301 + 0.2419749945402145 + <_> + + <_> + + + + <_> + 20 7 5 4 -1. + <_> + 20 8 5 2 2. + 0 + 0.0123357502743602 + 0.0375008806586266 + -0.4776956140995026 + <_> + + <_> + + + + <_> + 7 10 11 4 -1. + <_> + 7 11 11 2 2. + 0 + 0.0130474697798491 + -0.0609255395829678 + 0.2419895976781845 + <_> + + <_> + + + + <_> + 16 13 1 2 -1. + <_> + 16 14 1 1 2. + 0 + 5.2074559789616615e-005 + -0.0981822684407234 + 0.0891881734132767 + <_> + + <_> + + + + <_> + 3 1 5 4 -1. + <_> + 3 2 5 2 2. + 0 + 3.2866070978343487e-003 + -0.0941056609153748 + 0.1441165059804916 + <_> + + <_> + + + + <_> + 17 3 8 2 -1. + <_> + 17 4 8 1 2. + 0 + -0.0417326614260674 + -0.6405817270278931 + 0.0221338905394077 + <_> + + <_> + + + + <_> + 0 7 5 4 -1. + <_> + 0 8 5 2 2. + 0 + 9.7638191655278206e-003 + 0.0412781611084938 + -0.3354279994964600 + <_> + + <_> + + + + <_> + 9 4 12 6 -1. + <_> + 13 4 4 6 3. + 0 + 0.1077456995844841 + 8.1762494519352913e-003 + -0.4347884058952332 + <_> + + <_> + + + + <_> + 4 4 12 6 -1. + <_> + 8 4 4 6 3. + 0 + 0.1119699031114578 + 0.0199715103954077 + -0.6503595113754273 + <_> + + <_> + + + + <_> + 11 0 12 9 -1. + <_> + 11 0 6 9 2. + 0 + 0.0680430680513382 + -0.0602735094726086 + 0.1384491026401520 + <_> + + <_> + + + + <_> + 4 5 16 8 -1. + <_> + 12 5 8 8 2. + 0 + 0.1206192970275879 + -0.0666261836886406 + 0.2128939926624298 + <_> + + <_> + + + + <_> + 16 12 2 1 -1. + <_> + 16 12 1 1 2. + 0 + -2.7089789509773254e-003 + -0.4214768111705780 + 7.0062931627035141e-003 + <_> + + <_> + + + + <_> + 7 12 2 1 -1. + <_> + 8 12 1 1 2. + 0 + -9.8798991530202329e-005 + 0.1287330985069275 + -0.1178120002150536 + <_> + + <_> + + + + <_> + 19 3 6 4 -1. + <_> + 22 3 3 2 2. + <_> + 19 5 3 2 2. + 0 + 0.0177976898849010 + -0.0398075394332409 + 0.2582241892814636 + <_> + + <_> + + + + <_> + 8 10 6 3 -1. + <_> + 10 10 2 3 3. + 0 + -0.0155267501249909 + -0.5375617146492004 + 0.0254285801202059 + <_> + + <_> + + + + <_> + 16 6 2 2 -1. + <_> + 17 6 1 1 2. + <_> + 16 7 1 1 2. + 0 + -1.1374800233170390e-003 + 0.1497129052877426 + -0.0317900516092777 + <_> + + <_> + + + + <_> + 0 0 24 2 -1. + <_> + 0 0 12 1 2. + <_> + 12 1 12 1 2. + 0 + 0.0219873897731304 + 0.0302675794810057 + -0.4156928062438965 + <_> + + <_> + + + + <_> + 16 6 2 2 -1. + <_> + 17 6 1 1 2. + <_> + 16 7 1 1 2. + 0 + 5.9880971093662083e-005 + -0.0641673132777214 + 0.0799537077546120 + <_> + + <_> + + + + <_> + 0 3 6 4 -1. + <_> + 0 3 3 2 2. + <_> + 3 5 3 2 2. + 0 + 7.6966080814599991e-003 + -0.0727465227246284 + 0.1708455979824066 + <_> + + <_> + + + + <_> + 22 0 3 4 -1. + <_> + 22 2 3 2 2. + 0 + 6.2799488659948111e-004 + 0.0341552086174488 + -0.1379152983427048 + <_> + + <_> + + + + <_> + 11 0 2 3 -1. + <_> + 11 1 2 1 3. + 0 + -1.2622140347957611e-003 + 0.1615235060453415 + -0.0755578279495239 + <_> + + <_> + + + + <_> + 21 7 2 4 -1. + <_> + 20 8 2 2 2. + 1 + -0.0110059296712279 + -0.4823004007339478 + 0.0268340297043324 + <_> + + <_> + + + + <_> + 4 9 10 1 -1. + <_> + 9 9 5 1 2. + 0 + -9.5793791115283966e-003 + 0.1946887969970703 + -0.0669640377163887 + <_> + + <_> + + + + <_> + 16 6 2 2 -1. + <_> + 17 6 1 1 2. + <_> + 16 7 1 1 2. + 0 + -9.1821959358640015e-005 + 0.0793757066130638 + -0.0674495473504066 + <_> + + <_> + + + + <_> + 7 6 2 2 -1. + <_> + 7 6 1 1 2. + <_> + 8 7 1 1 2. + 0 + 1.2134959688410163e-003 + -0.0511140711605549 + 0.2775780856609345 + <_> + + <_> + + + + <_> + 16 6 2 2 -1. + <_> + 17 6 1 1 2. + <_> + 16 7 1 1 2. + 0 + 7.9206802183762193e-004 + -0.0284809302538633 + 0.1130611971020699 + <_> + + <_> + + + + <_> + 0 0 1 4 -1. + <_> + 0 2 1 2 2. + 0 + 2.7196949813514948e-003 + 0.0362051688134670 + -0.3822895884513855 + <_> + + <_> + + + + <_> + 16 6 2 2 -1. + <_> + 17 6 1 1 2. + <_> + 16 7 1 1 2. + 0 + -7.0203691720962524e-003 + -0.7084425091743469 + 9.6215400844812393e-005 + <_> + + <_> + + + + <_> + 7 6 2 2 -1. + <_> + 7 6 1 1 2. + <_> + 8 7 1 1 2. + 0 + -7.4910762486979365e-004 + 0.1899659931659699 + -0.0707588419318199 + <_> + + <_> + + + + <_> + 8 9 9 6 -1. + <_> + 11 11 3 2 9. + 0 + -0.0300100892782211 + 0.1409595012664795 + -0.0833628922700882 + <_> + + <_> + + + + <_> + 0 5 2 6 -1. + <_> + 0 7 2 2 3. + 0 + 0.0211524497717619 + 0.0258801300078630 + -0.4697616100311279 + <_> + + <_> + + + + <_> + 14 4 4 7 -1. + <_> + 15 5 2 7 2. + 1 + -0.0319705903530121 + -0.5124071240425110 + 0.0121158296242356 + <_> + + <_> + + + + <_> + 2 13 20 2 -1. + <_> + 2 13 10 1 2. + <_> + 12 14 10 1 2. + 0 + 0.0105077195912600 + 0.0386607907712460 + -0.3098644018173218 + <_> + + <_> + + + + <_> + 23 7 2 2 -1. + <_> + 24 7 1 1 2. + <_> + 23 8 1 1 2. + 0 + 4.8152811359614134e-005 + -0.0616559796035290 + 0.0678063929080963 + <_> + + <_> + + + + <_> + 3 2 1 4 -1. + <_> + 3 3 1 2 2. + 0 + 9.6495117759332061e-004 + -0.0613585598766804 + 0.1991685926914215 + <_> + + <_> + + + + <_> + 11 2 14 4 -1. + <_> + 11 3 14 2 2. + 0 + -0.0404121391475201 + 0.1341411024332047 + -0.0717744380235672 + <_> + + <_> + + + + <_> + 5 7 4 5 -1. + <_> + 6 7 2 5 2. + 0 + 5.8856019750237465e-003 + 0.0359793491661549 + -0.3332307040691376 + <_> + + <_> + + + + <_> + 23 8 1 4 -1. + <_> + 22 9 1 2 2. + 1 + 5.3272489458322525e-003 + 0.0328989103436470 + -0.5153871178627014 + <_> + + <_> + + + + <_> + 2 0 10 8 -1. + <_> + 7 0 5 8 2. + 0 + 0.0532727986574173 + -0.0784574225544930 + 0.1582656949758530 + <_> + + <_> + + + + <_> + 1 5 24 3 -1. + <_> + 9 6 8 1 9. + 0 + 0.0174429006874561 + 0.1339583992958069 + -0.1186174973845482 + <_> + + <_> + + + + <_> + 10 0 4 10 -1. + <_> + 10 5 4 5 2. + 0 + -0.0433590598404408 + -0.2269790023565292 + 0.0467031300067902 + <_> + + <_> + + + + <_> + 5 4 15 3 -1. + <_> + 5 5 15 1 3. + 0 + -0.0231206398457289 + 0.1634031981229782 + -0.0685165524482727 + <_> + + <_> + + + + <_> + 11 6 3 6 -1. + <_> + 11 8 3 2 3. + 0 + -9.3796178698539734e-003 + 0.1582739949226379 + -0.0771108269691467 + <_> + + <_> + + + + <_> + 18 8 7 3 -1. + <_> + 18 9 7 1 3. + 0 + -0.0141222495585680 + -0.5691561102867127 + 0.0232016704976559 + <_> + + <_> + + + + <_> + 0 0 4 2 -1. + <_> + 0 1 4 1 2. + 0 + -0.0155957797542214 + -0.7199953794479370 + 0.0111829601228237 + <_> + + <_> + + + + <_> + 20 0 2 1 -1. + <_> + 20 0 1 1 2. + 1 + 7.4529898120090365e-004 + -0.0766925588250160 + 0.0582969412207603 + <_> + + <_> + + + + <_> + 0 6 1 8 -1. + <_> + 0 8 1 4 2. + 0 + -5.1220599561929703e-003 + -0.4147517085075378 + 0.0252124201506376 + <_> + + <_> + + + + <_> + 23 7 2 2 -1. + <_> + 24 7 1 1 2. + <_> + 23 8 1 1 2. + 0 + -5.7267909141955897e-005 + 0.0905847102403641 + -0.0668906867504120 + <_> + + <_> + + + + <_> + 0 7 2 2 -1. + <_> + 0 7 1 1 2. + <_> + 1 8 1 1 2. + 0 + 8.8431767653673887e-004 + -0.0570513382554054 + 0.2420555055141449 + <_> + + <_> + + + + <_> + 24 8 1 4 -1. + <_> + 23 9 1 2 2. + 1 + -6.3992529176175594e-003 + -0.4766991138458252 + 0.0172231607139111 + <_> + + <_> + + + + <_> + 1 8 3 1 -1. + <_> + 2 9 1 1 3. + 1 + 3.4215620253235102e-003 + 0.0330659411847591 + -0.3505514860153198 + <_> + + <_> + + + + <_> + 21 7 2 2 -1. + <_> + 22 7 1 1 2. + <_> + 21 8 1 1 2. + 0 + 6.0761801432818174e-004 + -0.0633307918906212 + 0.1801937073469162 + <_> + + <_> + + + + <_> + 5 8 15 6 -1. + <_> + 5 10 15 2 3. + 0 + -0.0271245595067739 + 0.1347420066595078 + -0.0843034014105797 + <_> + + <_> + + + + <_> + 6 7 14 8 -1. + <_> + 6 9 14 4 2. + 0 + 0.0320383384823799 + -0.0676692426204681 + 0.1796665936708450 + <_> + + <_> + + + + <_> + 1 4 10 2 -1. + <_> + 1 5 10 1 2. + 0 + 7.2583961300551891e-003 + -0.0986167713999748 + 0.1166217997670174 + <_> + + <_> + + + + <_> + 12 5 3 3 -1. + <_> + 13 6 1 1 9. + 0 + -3.7803640589118004e-003 + 0.1233021020889282 + -0.0477618910372257 + <_> + + <_> + + + + <_> + 0 4 7 3 -1. + <_> + 0 5 7 1 3. + 0 + 0.0392416305840015 + 0.0167705602943897 + -0.7329750061035156 + <_> + + <_> + + + + <_> + 21 7 2 2 -1. + <_> + 22 7 1 1 2. + <_> + 21 8 1 1 2. + 0 + -5.3865249356022105e-005 + 0.0850126668810844 + -0.0751027390360832 + <_> + + <_> + + + + <_> + 2 7 2 2 -1. + <_> + 2 7 1 1 2. + <_> + 3 8 1 1 2. + 0 + 8.2592968828976154e-004 + -0.0551505312323570 + 0.2059426009654999 + <_> + + <_> + + + + <_> + 22 9 1 3 -1. + <_> + 21 10 1 1 3. + 1 + -5.6403529015369713e-005 + 0.0762555226683617 + -0.0699946209788322 + <_> + + <_> + + + + <_> + 11 13 2 2 -1. + <_> + 11 13 1 1 2. + <_> + 12 14 1 1 2. + 0 + -5.6928332196548581e-004 + -0.2483194023370743 + 0.0468857996165752 + <_> + + <_> + + + + <_> + 19 3 6 12 -1. + <_> + 22 3 3 6 2. + <_> + 19 9 3 6 2. + 0 + 0.0424826890230179 + -0.0344216786324978 + 0.1484764963388443 + <_> + + <_> + + + + <_> + 0 3 6 12 -1. + <_> + 0 3 3 6 2. + <_> + 3 9 3 6 2. + 0 + -0.0339534096419811 + 0.2843470871448517 + -0.0431083589792252 + <_> + + <_> + + + + <_> + 17 1 4 11 -1. + <_> + 18 1 2 11 2. + 0 + 0.0188998207449913 + 0.0142998602241278 + -0.4192070066928864 + <_> + + <_> + + + + <_> + 0 10 6 3 -1. + <_> + 0 11 6 1 3. + 0 + 1.9765710458159447e-003 + 0.0621932409703732 + -0.1786025017499924 + <_> + + <_> + + + + <_> + 23 11 2 1 -1. + <_> + 23 11 1 1 2. + 0 + -5.0894439482362941e-005 + 0.0948854833841324 + -0.0689786225557327 + <_> + + <_> + + + + <_> + 4 1 4 11 -1. + <_> + 5 1 2 11 2. + 0 + 0.0114915501326323 + 0.0331886112689972 + -0.3628959059715271 + <_> + + <_> + + + + <_> + 21 3 4 12 -1. + <_> + 23 3 2 6 2. + <_> + 21 9 2 6 2. + 0 + -0.0215106792747974 + 0.2759737968444824 + -0.0317491404712200 + <_> + + <_> + + + + <_> + 0 3 4 12 -1. + <_> + 0 3 2 6 2. + <_> + 2 9 2 6 2. + 0 + 0.0130551997572184 + -0.0830815583467484 + 0.1449849009513855 + <_> + + <_> + + + + <_> + 11 11 6 4 -1. + <_> + 11 12 6 2 2. + 0 + 6.6747581586241722e-003 + -0.0461902506649494 + 0.1383360028266907 + <_> + + <_> + + + + <_> + 6 11 13 4 -1. + <_> + 6 12 13 2 2. + 0 + -7.0616300217807293e-003 + 0.1968749016523361 + -0.0837985798716545 + <_> + + <_> + + + + <_> + 11 10 3 1 -1. + <_> + 12 10 1 1 3. + 0 + 6.1481661396101117e-004 + 0.0542011298239231 + -0.1981233954429627 + <_> + + <_> + + + + <_> + 5 2 13 8 -1. + <_> + 5 6 13 4 2. + 0 + 0.2860183119773865 + 0.0232954602688551 + -0.4173370003700256 + <_> + + <_> + + + + <_> + 15 2 10 6 -1. + <_> + 15 4 10 2 3. + 0 + 0.0463717207312584 + -0.0290123391896486 + 0.1808013021945953 + <_> + + <_> + + + + <_> + 0 2 10 6 -1. + <_> + 0 4 10 2 3. + 0 + -0.0557247512042522 + 0.1358146965503693 + -0.1061223000288010 + <_> + + <_> + + + + <_> + 12 1 13 8 -1. + <_> + 12 3 13 4 2. + 0 + -0.2584396898746491 + -0.4910731911659241 + 0.0151501996442676 + -1.3960490226745605 + 11 + -1 + <_> + + + <_> + + <_> + + + + <_> + 5 3 15 3 -1. + <_> + 5 4 15 1 3. + 0 + -0.0417404398322105 + 0.4202992916107178 + -0.1386588066816330 + <_> + + <_> + + + + <_> + 9 3 9 3 -1. + <_> + 9 4 9 1 3. + 0 + 0.0274386107921600 + -0.0691855624318123 + 0.6378138065338135 + <_> + + <_> + + + + <_> + 3 2 7 3 -1. + <_> + 2 3 7 1 3. + 1 + -0.0319233611226082 + 0.5562999844551086 + -0.0588022507727146 + <_> + + <_> + + + + <_> + 5 2 15 3 -1. + <_> + 5 3 15 1 3. + 0 + -0.0426339097321033 + 0.3957036137580872 + -0.0923223569989204 + <_> + + <_> + + + + <_> + 5 4 15 3 -1. + <_> + 5 5 15 1 3. + 0 + -0.0453329794108868 + 0.4831672012805939 + -0.0990284606814384 + <_> + + <_> + + + + <_> + 17 6 2 2 -1. + <_> + 18 6 1 1 2. + <_> + 17 7 1 1 2. + 0 + 1.4149550115689635e-003 + -0.0383210293948650 + 0.3782787919044495 + <_> + + <_> + + + + <_> + 5 10 2 3 -1. + <_> + 5 10 1 3 2. + 1 + 3.1844570767134428e-003 + 0.0845874175429344 + -0.3629348874092102 + <_> + + <_> + + + + <_> + 23 11 2 4 -1. + <_> + 23 13 2 2 2. + 0 + 7.9865548759698868e-003 + 0.0660245269536972 + -0.4990949034690857 + <_> + + <_> + + + + <_> + 0 11 14 4 -1. + <_> + 0 11 7 2 2. + <_> + 7 13 7 2 2. + 0 + 8.3637079223990440e-003 + -0.1568834036588669 + 0.1732781976461411 + <_> + + <_> + + + + <_> + 10 4 6 3 -1. + <_> + 10 5 6 1 3. + 0 + 0.0166161693632603 + -0.1092156991362572 + 0.3208172023296356 + <_> + + <_> + + + + <_> + 0 1 24 14 -1. + <_> + 0 1 12 7 2. + <_> + 12 8 12 7 2. + 0 + -0.1083723008632660 + -0.3144314885139465 + 0.0960887372493744 + <_> + + <_> + + + + <_> + 1 5 24 8 -1. + <_> + 13 5 12 4 2. + <_> + 1 9 12 4 2. + 0 + -0.0552641600370407 + -0.3238588869571686 + 0.0760045275092125 + <_> + + <_> + + + + <_> + 0 0 24 12 -1. + <_> + 0 0 12 6 2. + <_> + 12 6 12 6 2. + 0 + 0.1263256967067719 + 0.0652572736144066 + -0.4011892974376679 + <_> + + <_> + + + + <_> + 10 0 15 14 -1. + <_> + 10 7 15 7 2. + 0 + 0.3880456089973450 + 0.0290472805500031 + -0.2850419878959656 + <_> + + <_> + + + + <_> + 1 11 2 1 -1. + <_> + 1 11 1 1 2. + 1 + 2.1647498942911625e-003 + 0.0566388815641403 + -0.4483107030391693 + <_> + + <_> + + + + <_> + 1 11 24 4 -1. + <_> + 1 11 12 4 2. + 0 + -0.0850358307361603 + 0.2374248951673508 + -0.1127642020583153 + <_> + + <_> + + + + <_> + 7 7 10 3 -1. + <_> + 7 8 10 1 3. + 0 + 0.0297137200832367 + -0.0403699316084385 + 0.4747174084186554 + <_> + + <_> + + + + <_> + 9 5 7 3 -1. + <_> + 9 6 7 1 3. + 0 + 0.0189488306641579 + -0.0794471576809883 + 0.2721098959445953 + <_> + + <_> + + + + <_> + 0 9 2 6 -1. + <_> + 0 11 2 2 3. + 0 + -5.4433820769190788e-003 + -0.4018659889698029 + 0.0573576912283897 + <_> + + <_> + + + + <_> + 22 8 3 2 -1. + <_> + 22 8 3 1 2. + 1 + -7.4416291899979115e-003 + -0.4642170965671539 + 0.0343283303081989 + <_> + + <_> + + + + <_> + 12 6 1 3 -1. + <_> + 12 7 1 1 3. + 0 + 3.1745829619467258e-003 + -0.0719946026802063 + 0.2899833023548126 + <_> + + <_> + + + + <_> + 24 6 1 6 -1. + <_> + 24 8 1 2 3. + 0 + -4.6435040421783924e-003 + -0.4219543039798737 + 0.0394870713353157 + <_> + + <_> + + + + <_> + 3 3 7 2 -1. + <_> + 3 3 7 1 2. + 1 + -0.0225970800966024 + 0.2745698094367981 + -0.0772427767515183 + <_> + + <_> + + + + <_> + 10 4 6 10 -1. + <_> + 13 4 3 5 2. + <_> + 10 9 3 5 2. + 0 + 0.0175681803375483 + 0.0604698508977890 + -0.2755838930606842 + <_> + + <_> + + + + <_> + 0 3 14 6 -1. + <_> + 0 6 14 3 2. + 0 + 0.2285360991954804 + 0.0372774116694927 + -0.5375431180000305 + <_> + + <_> + + + + <_> + 9 0 8 8 -1. + <_> + 13 0 4 4 2. + <_> + 9 4 4 4 2. + 0 + 0.0323306396603584 + 0.0458961501717567 + -0.3844825029373169 + <_> + + <_> + + + + <_> + 3 4 5 3 -1. + <_> + 2 5 5 1 3. + 1 + -0.0285396501421928 + 0.5891790986061096 + -0.0340728089213371 + <_> + + <_> + + + + <_> + 18 9 7 6 -1. + <_> + 18 11 7 2 3. + 0 + 0.0286119598895311 + 0.0241741407662630 + -0.2325512021780014 + <_> + + <_> + + + + <_> + 0 9 7 6 -1. + <_> + 0 11 7 2 3. + 0 + 0.0190214607864618 + 0.0562911406159401 + -0.3404670059680939 + <_> + + <_> + + + + <_> + 12 1 3 3 -1. + <_> + 12 2 3 1 3. + 0 + -5.7942080311477184e-003 + 0.2392093986272812 + -0.0638626366853714 + <_> + + <_> + + + + <_> + 9 2 6 8 -1. + <_> + 9 2 3 4 2. + <_> + 12 6 3 4 2. + 0 + 0.0198575407266617 + 0.0513716302812099 + -0.3405377864837647 + <_> + + <_> + + + + <_> + 1 14 24 1 -1. + <_> + 7 14 12 1 2. + 0 + -0.0227794591337442 + 0.2922581136226654 + -0.0604945607483387 + <_> + + <_> + + + + <_> + 0 3 12 12 -1. + <_> + 0 3 6 6 2. + <_> + 6 9 6 6 2. + 0 + 0.1480142027139664 + -0.0343834199011326 + 0.4667116999626160 + <_> + + <_> + + + + <_> + 11 3 9 4 -1. + <_> + 14 3 3 4 3. + 0 + -0.0337039716541767 + -0.3770483136177063 + 0.0263036508113146 + <_> + + <_> + + + + <_> + 9 4 6 6 -1. + <_> + 9 4 3 3 2. + <_> + 12 7 3 3 2. + 0 + -0.0162283908575773 + -0.3382456898689270 + 0.0570861399173737 + <_> + + <_> + + + + <_> + 20 0 4 1 -1. + <_> + 20 0 2 1 2. + 1 + -4.2941919527947903e-003 + -0.3295148909091950 + 0.0434178002178669 + <_> + + <_> + + + + <_> + 8 3 9 4 -1. + <_> + 11 3 3 4 3. + 0 + -0.0235741101205349 + -0.3945200145244598 + 0.0398236103355885 + <_> + + <_> + + + + <_> + 14 4 6 9 -1. + <_> + 16 4 2 9 3. + 0 + 0.0218487493693829 + 0.0268086697906256 + -0.2596569955348969 + <_> + + <_> + + + + <_> + 5 4 6 9 -1. + <_> + 7 4 2 9 3. + 0 + -0.0209309905767441 + -0.3641955852508545 + 0.0437827892601490 + <_> + + <_> + + + + <_> + 16 5 2 2 -1. + <_> + 17 5 1 1 2. + <_> + 16 6 1 1 2. + 0 + 1.6019339673221111e-003 + -0.0240206904709339 + 0.2182880043983460 + <_> + + <_> + + + + <_> + 0 0 15 12 -1. + <_> + 0 4 15 4 3. + 0 + -0.5489655733108521 + -0.5673372149467468 + 0.0286840796470642 + <_> + + <_> + + + + <_> + 8 1 11 3 -1. + <_> + 8 2 11 1 3. + 0 + 0.0151870902627707 + -0.0816961303353310 + 0.2107073962688446 + <_> + + <_> + + + + <_> + 0 6 1 6 -1. + <_> + 0 8 1 2 3. + 0 + -3.0653451103717089e-003 + -0.3701387047767639 + 0.0471426397562027 + <_> + + <_> + + + + <_> + 14 5 1 3 -1. + <_> + 14 6 1 1 3. + 0 + -2.2847671061754227e-003 + 0.1813296973705292 + -0.0419041812419891 + <_> + + <_> + + + + <_> + 7 2 2 2 -1. + <_> + 7 2 1 1 2. + <_> + 8 3 1 1 2. + 0 + 1.3886080123484135e-003 + -0.0477169714868069 + 0.3120515942573547 + <_> + + <_> + + + + <_> + 22 9 1 4 -1. + <_> + 21 10 1 2 2. + 1 + -4.2354268953204155e-003 + -0.3120726943016052 + 0.0365724302828312 + <_> + + <_> + + + + <_> + 10 5 5 3 -1. + <_> + 10 6 5 1 3. + 0 + 4.9234707839787006e-003 + -0.1105178967118263 + 0.1364745944738388 + <_> + + <_> + + + + <_> + 14 5 1 3 -1. + <_> + 14 6 1 1 3. + 0 + -9.7824353724718094e-004 + 0.1019112989306450 + -0.0396985597908497 + <_> + + <_> + + + + <_> + 0 0 2 2 -1. + <_> + 0 1 2 1 2. + 0 + 2.3952899500727654e-003 + 0.0345855616033077 + -0.4620797038078308 + <_> + + <_> + + + + <_> + 22 9 1 4 -1. + <_> + 21 10 1 2 2. + 1 + -2.7391599360271357e-005 + 0.0470036789774895 + -0.0576489008963108 + <_> + + <_> + + + + <_> + 3 9 4 1 -1. + <_> + 4 10 2 1 2. + 1 + -3.7895010318607092e-003 + -0.3904446959495544 + 0.0392708182334900 + <_> + + <_> + + + + <_> + 8 8 9 3 -1. + <_> + 8 9 9 1 3. + 0 + 0.0251507405191660 + -0.0313480608165264 + 0.4742729067802429 + <_> + + <_> + + + + <_> + 2 8 21 3 -1. + <_> + 9 9 7 1 9. + 0 + -0.0545641481876373 + 0.1494560986757278 + -0.0982013270258904 + <_> + + <_> + + + + <_> + 10 6 8 8 -1. + <_> + 12 6 4 8 2. + 0 + -0.0416621901094913 + -0.4245094060897827 + 0.0152987902984023 + <_> + + <_> + + + + <_> + 7 3 6 12 -1. + <_> + 9 3 2 12 3. + 0 + -0.0207394007593393 + -0.3218981921672821 + 0.0479229800403118 + <_> + + <_> + + + + <_> + 11 0 3 1 -1. + <_> + 12 0 1 1 3. + 0 + -9.7902817651629448e-004 + 0.2330693006515503 + -0.0597994215786457 + <_> + + <_> + + + + <_> + 10 10 4 4 -1. + <_> + 11 10 2 4 2. + 0 + -4.1547799482941628e-003 + -0.3040251135826111 + 0.0456931404769421 + <_> + + <_> + + + + <_> + 16 5 2 2 -1. + <_> + 17 5 1 1 2. + <_> + 16 6 1 1 2. + 0 + -2.6045470804092474e-005 + 0.0553880184888840 + -0.0540977194905281 + <_> + + <_> + + + + <_> + 7 5 2 2 -1. + <_> + 7 5 1 1 2. + <_> + 8 6 1 1 2. + 0 + 1.0567409917712212e-003 + -0.0526767596602440 + 0.2473292946815491 + <_> + + <_> + + + + <_> + 1 0 24 8 -1. + <_> + 13 0 12 4 2. + <_> + 1 4 12 4 2. + 0 + 0.1842923015356064 + 0.0165581107139587 + -0.5789644718170166 + <_> + + <_> + + + + <_> + 6 6 3 1 -1. + <_> + 7 6 1 1 3. + 0 + 1.4177090488374233e-003 + -0.0524071305990219 + 0.2524789869785309 + <_> + + <_> + + + + <_> + 21 12 4 3 -1. + <_> + 21 13 4 1 3. + 0 + -4.0882350876927376e-003 + -0.3066633939743042 + 0.0269502196460962 + <_> + + <_> + + + + <_> + 0 3 4 4 -1. + <_> + 0 3 2 2 2. + <_> + 2 5 2 2 2. + 0 + 8.5421912372112274e-003 + -0.0481166206300259 + 0.2716326117515564 + <_> + + <_> + + + + <_> + 19 0 2 3 -1. + <_> + 19 0 1 3 2. + 1 + 0.0195690393447876 + 0.0251199807971716 + -0.3371602892875671 + <_> + + <_> + + + + <_> + 2 2 15 6 -1. + <_> + 2 5 15 3 2. + 0 + 0.2677350938320160 + 0.0231193397194147 + -0.5075724124908447 + <_> + + <_> + + + + <_> + 5 0 15 2 -1. + <_> + 5 1 15 1 2. + 0 + -0.0326806083321571 + 0.2773688137531281 + -0.0481392890214920 + <_> + + <_> + + + + <_> + 0 0 2 4 -1. + <_> + 0 1 2 2 2. + 0 + -5.0574508495628834e-003 + -0.3639586865901947 + 0.0363070890307426 + <_> + + <_> + + + + <_> + 23 1 2 12 -1. + <_> + 20 4 2 6 2. + 1 + 0.0791702270507813 + -0.0295530706644058 + 0.1632819026708603 + <_> + + <_> + + + + <_> + 4 2 2 3 -1. + <_> + 4 3 2 1 3. + 0 + 2.2955629974603653e-003 + -0.0644191280007362 + 0.1921634972095490 + <_> + + <_> + + + + <_> + 20 0 2 2 -1. + <_> + 20 0 1 2 2. + 1 + 2.1744619880337268e-004 + -0.1248127967119217 + 0.0513428300619125 + <_> + + <_> + + + + <_> + 0 12 4 3 -1. + <_> + 0 13 4 1 3. + 0 + -5.9793200343847275e-003 + -0.5400406122207642 + 0.0236572697758675 + <_> + + <_> + + + + <_> + 13 1 12 8 -1. + <_> + 13 3 12 4 2. + 0 + -0.2183004021644592 + -0.3002713024616242 + 0.0188296400010586 + <_> + + <_> + + + + <_> + 5 0 2 2 -1. + <_> + 5 0 2 1 2. + 1 + -2.5782659649848938e-003 + -0.2936800122261047 + 0.0437353104352951 + <_> + + <_> + + + + <_> + 11 2 14 12 -1. + <_> + 11 8 14 6 2. + 0 + -0.1344317942857742 + -0.2982031106948853 + 0.0219516493380070 + <_> + + <_> + + + + <_> + 0 2 14 12 -1. + <_> + 0 8 14 6 2. + 0 + 0.3329834043979645 + 0.0417996607720852 + -0.3464672863483429 + <_> + + <_> + + + + <_> + 16 7 6 8 -1. + <_> + 18 7 2 8 3. + 0 + -0.0276046600192785 + -0.3169625997543335 + 0.0150398099794984 + <_> + + <_> + + + + <_> + 7 0 13 2 -1. + <_> + 7 0 13 1 2. + 1 + 0.0284599401056767 + 0.0311327595263720 + -0.4115855097770691 + <_> + + <_> + + + + <_> + 16 7 6 8 -1. + <_> + 18 7 2 8 3. + 0 + 0.0568751804530621 + 3.1998890917748213e-003 + -0.8496329784393311 + <_> + + <_> + + + + <_> + 3 7 6 8 -1. + <_> + 5 7 2 8 3. + 0 + -0.0264140591025352 + -0.4030340015888214 + 0.0285327993333340 + <_> + + <_> + + + + <_> + 17 7 2 2 -1. + <_> + 18 7 1 1 2. + <_> + 17 8 1 1 2. + 0 + 8.2670920528471470e-004 + -0.0478886701166630 + 0.2083473950624466 + <_> + + <_> + + + + <_> + 12 5 3 6 -1. + <_> + 13 6 1 6 3. + 1 + -0.0174812003970146 + -0.4784274101257324 + 0.0261973403394222 + <_> + + <_> + + + + <_> + 20 2 1 6 -1. + <_> + 20 4 1 2 3. + 0 + 0.0102093704044819 + -0.0323491990566254 + 0.3333239853382111 + <_> + + <_> + + + + <_> + 7 2 2 2 -1. + <_> + 7 2 1 1 2. + <_> + 8 3 1 1 2. + 0 + -9.0442842338234186e-004 + 0.2252988964319229 + -0.0502184815704823 + <_> + + <_> + + + + <_> + 19 10 2 1 -1. + <_> + 19 10 1 1 2. + 0 + -5.5155509471660480e-005 + 0.0854163095355034 + -0.0922556668519974 + <_> + + <_> + + + + <_> + 6 4 8 2 -1. + <_> + 8 4 4 2 2. + 0 + -7.5864349491894245e-003 + -0.2745333909988403 + 0.0428331792354584 + <_> + + <_> + + + + <_> + 9 5 16 7 -1. + <_> + 13 5 8 7 2. + 0 + 0.0689363330602646 + -0.0362212397158146 + 0.2202139943838120 + <_> + + <_> + + + + <_> + 6 7 2 2 -1. + <_> + 6 7 1 1 2. + <_> + 7 8 1 1 2. + 0 + 1.0017789900302887e-003 + -0.0464680194854736 + 0.2603206038475037 + <_> + + <_> + + + + <_> + 17 7 2 2 -1. + <_> + 18 7 1 1 2. + <_> + 17 8 1 1 2. + 0 + -1.5333900228142738e-003 + 0.2831267118453980 + -0.0321949794888496 + <_> + + <_> + + + + <_> + 11 13 2 2 -1. + <_> + 11 13 1 1 2. + <_> + 12 14 1 1 2. + 0 + 5.0275481771677732e-004 + 0.0547226108610630 + -0.2383649945259094 + <_> + + <_> + + + + <_> + 17 7 2 2 -1. + <_> + 18 7 1 1 2. + <_> + 17 8 1 1 2. + 0 + 6.7827408201992512e-005 + -0.0391390211880207 + 0.0501381084322929 + <_> + + <_> + + + + <_> + 6 7 2 2 -1. + <_> + 6 7 1 1 2. + <_> + 7 8 1 1 2. + 0 + -9.6863682847470045e-004 + 0.2108709067106247 + -0.0608406700193882 + <_> + + <_> + + + + <_> + 20 8 5 3 -1. + <_> + 20 9 5 1 3. + 0 + 0.0157267302274704 + 0.0115508204326034 + -0.8977199196815491 + <_> + + <_> + + + + <_> + 11 13 2 2 -1. + <_> + 11 13 1 1 2. + <_> + 12 14 1 1 2. + 0 + -6.1983527848497033e-004 + -0.2865422964096069 + 0.0380632318556309 + <_> + + <_> + + + + <_> + 5 11 15 4 -1. + <_> + 5 12 15 2 2. + 0 + -0.0148898903280497 + 0.2188885957002640 + -0.0534253492951393 + <_> + + <_> + + + + <_> + 0 8 6 3 -1. + <_> + 0 9 6 1 3. + 0 + 9.1423774138092995e-003 + 0.0289719104766846 + -0.4331383109092712 + <_> + + <_> + + + + <_> + 19 10 2 1 -1. + <_> + 19 10 1 1 2. + 0 + 4.4567110307980329e-005 + -0.0493506006896496 + 0.0829902365803719 + <_> + + <_> + + + + <_> + 4 10 2 1 -1. + <_> + 5 10 1 1 2. + 0 + -4.6295441279653460e-005 + 0.1145173981785774 + -0.1154157966375351 + <_> + + <_> + + + + <_> + 1 0 24 6 -1. + <_> + 13 0 12 3 2. + <_> + 1 3 12 3 2. + 0 + -0.0951543077826500 + -0.3621807992458344 + 0.0389639586210251 + <_> + + <_> + + + + <_> + 5 1 2 5 -1. + <_> + 5 1 1 5 2. + 1 + 0.0114479204639792 + -0.0633771494030952 + 0.1799890995025635 + <_> + + <_> + + + + <_> + 21 3 4 12 -1. + <_> + 23 3 2 6 2. + <_> + 21 9 2 6 2. + 0 + 0.0168469492346048 + -0.0795559063553810 + 0.2080432027578354 + <_> + + <_> + + + + <_> + 0 3 4 12 -1. + <_> + 0 3 2 6 2. + <_> + 2 9 2 6 2. + 0 + -0.0195328295230865 + 0.3306660056114197 + -0.0368879809975624 + <_> + + <_> + + + + <_> + 24 2 1 6 -1. + <_> + 24 5 1 3 2. + 0 + -9.9951513111591339e-003 + -0.2601873874664307 + 0.0200320500880480 + <_> + + <_> + + + + <_> + 5 2 9 8 -1. + <_> + 8 2 3 8 3. + 0 + 0.0559661500155926 + 0.0298731103539467 + -0.3797968029975891 + <_> + + <_> + + + + <_> + 24 2 1 6 -1. + <_> + 24 5 1 3 2. + 0 + 0.0223989300429821 + 9.4442693516612053e-003 + -0.3070712089538574 + <_> + + <_> + + + + <_> + 0 2 1 6 -1. + <_> + 0 5 1 3 2. + 0 + -0.0111306598410010 + -0.4547461867332459 + 0.0237820893526077 + <_> + + <_> + + + + <_> + 9 6 9 4 -1. + <_> + 9 7 9 2 2. + 0 + 0.0103914495557547 + -0.0801509991288185 + 0.1017400026321411 + <_> + + <_> + + + + <_> + 11 6 3 4 -1. + <_> + 11 7 3 2 2. + 0 + -9.7076389938592911e-003 + 0.3220044970512390 + -0.0475250408053398 + <_> + + <_> + + + + <_> + 20 14 2 1 -1. + <_> + 20 14 1 1 2. + 0 + 1.9170529412804171e-005 + -0.0619046017527580 + 0.0758714973926544 + <_> + + <_> + + + + <_> + 0 8 6 4 -1. + <_> + 0 9 6 2 2. + 0 + -5.7660471647977829e-003 + -0.2893261909484863 + 0.0357113592326641 + <_> + + <_> + + + + <_> + 16 0 2 2 -1. + <_> + 17 0 1 1 2. + <_> + 16 1 1 1 2. + 0 + -8.0189562868326902e-004 + 0.1487676948308945 + -0.0337995104491711 + <_> + + <_> + + + + <_> + 8 0 9 15 -1. + <_> + 11 5 3 5 9. + 0 + -0.4516898989677429 + -0.5800644755363464 + 0.0182942803949118 + <_> + + <_> + + + + <_> + 13 9 4 6 -1. + <_> + 14 9 2 6 2. + 0 + 7.1167000569403172e-003 + 0.0221952199935913 + -0.4342006146907806 + <_> + + <_> + + + + <_> + 8 2 9 3 -1. + <_> + 8 3 9 1 3. + 0 + 0.0214324798434973 + -0.0425198413431644 + 0.2711758911609650 + -1.3937480449676514 + 12 + -1 + <_> + + + <_> + + <_> + + + + <_> + 0 9 8 6 -1. + <_> + 0 9 4 3 2. + <_> + 4 12 4 3 2. + 0 + 8.8465185835957527e-003 + -0.2059727013111115 + 0.2158975005149841 + <_> + + <_> + + + + <_> + 20 1 5 4 -1. + <_> + 20 3 5 2 2. + 0 + -0.0114869000390172 + 0.1450283974409103 + -0.2512278854846954 + <_> + + <_> + + + + <_> + 4 3 16 7 -1. + <_> + 8 3 8 7 2. + 0 + 0.0613779015839100 + -0.1210888996720314 + 0.2893109023571014 + <_> + + <_> + + + + <_> + 15 0 10 8 -1. + <_> + 15 2 10 4 2. + 0 + -0.0514667406678200 + 0.0770430117845535 + -0.1447598934173584 + <_> + + <_> + + + + <_> + 0 2 24 10 -1. + <_> + 0 2 12 5 2. + <_> + 12 7 12 5 2. + 0 + 0.0990432873368263 + 0.0879464074969292 + -0.3668490052223206 + <_> + + <_> + + + + <_> + 20 9 5 4 -1. + <_> + 20 10 5 2 2. + 0 + 6.0240789316594601e-003 + 0.0559716187417507 + -0.4230535030364990 + <_> + + <_> + + + + <_> + 0 14 22 1 -1. + <_> + 11 14 11 1 2. + 0 + 9.3228947371244431e-003 + -0.1488721966743469 + 0.1423504054546356 + <_> + + <_> + + + + <_> + 22 0 3 12 -1. + <_> + 22 0 3 6 2. + 1 + -0.0837828367948532 + -0.0506230294704437 + 0.0671857669949532 + <_> + + <_> + + + + <_> + 0 4 2 2 -1. + <_> + 1 4 1 2 2. + 0 + -1.4369570417329669e-003 + 0.1669974029064179 + -0.1184794977307320 + <_> + + <_> + + + + <_> + 20 9 5 4 -1. + <_> + 20 10 5 2 2. + 0 + -8.4923747926950455e-003 + -0.5746508240699768 + 0.0469529181718826 + <_> + + <_> + + + + <_> + 0 9 5 4 -1. + <_> + 0 10 5 2 2. + 0 + 6.1581619083881378e-003 + 0.0387838594615459 + -0.4179377853870392 + <_> + + <_> + + + + <_> + 7 3 18 6 -1. + <_> + 13 5 6 2 9. + 0 + 0.3882668018341065 + -0.0341588892042637 + 0.3883490860462189 + <_> + + <_> + + + + <_> + 4 10 10 1 -1. + <_> + 9 10 5 1 2. + 0 + -6.2880381010472775e-003 + 0.1877942979335785 + -0.1096756979823113 + <_> + + <_> + + + + <_> + 21 1 4 10 -1. + <_> + 21 1 2 10 2. + 1 + -0.0886473506689072 + 0.2961074113845825 + -0.0496502704918385 + <_> + + <_> + + + + <_> + 4 1 10 4 -1. + <_> + 4 1 10 2 2. + 1 + 0.0573849491775036 + -0.0621429793536663 + 0.4039953947067261 + <_> + + <_> + + + + <_> + 16 8 4 7 -1. + <_> + 17 8 2 7 2. + 0 + 6.3049891032278538e-003 + 0.0302408598363400 + -0.2553277909755707 + <_> + + <_> + + + + <_> + 5 8 4 7 -1. + <_> + 6 8 2 7 2. + 0 + -0.0128176100552082 + -0.7491502761840820 + 0.0188356805592775 + <_> + + <_> + + + + <_> + 6 0 13 2 -1. + <_> + 6 1 13 1 2. + 0 + 6.5159690566360950e-003 + -0.0749715119600296 + 0.1975888013839722 + <_> + + <_> + + + + <_> + 0 12 8 3 -1. + <_> + 0 13 8 1 3. + 0 + 8.2992920652031898e-003 + 0.0329895503818989 + -0.4346657097339630 + <_> + + <_> + + + + <_> + 22 0 2 1 -1. + <_> + 22 0 1 1 2. + 1 + 6.3911718316376209e-003 + 0.0297571904957294 + -0.3072845935821533 + <_> + + <_> + + + + <_> + 3 0 1 2 -1. + <_> + 3 0 1 1 2. + 1 + 6.8949637352488935e-005 + -0.1729405969381332 + 0.0927027910947800 + <_> + + <_> + + + + <_> + 17 3 8 8 -1. + <_> + 21 3 4 4 2. + <_> + 17 7 4 4 2. + 0 + 0.0413548089563847 + -0.0279047600924969 + 0.1629645973443985 + <_> + + <_> + + + + <_> + 6 2 13 6 -1. + <_> + 6 4 13 2 3. + 0 + 0.1899937987327576 + -0.0312954708933830 + 0.4835174977779388 + <_> + + <_> + + + + <_> + 10 0 15 14 -1. + <_> + 10 7 15 7 2. + 0 + -0.1273290067911148 + -0.4309565126895905 + 0.0414485186338425 + <_> + + <_> + + + + <_> + 1 1 12 1 -1. + <_> + 1 1 6 1 2. + 1 + -0.0356059707701206 + -0.2009662985801697 + 0.0775555819272995 + <_> + + <_> + + + + <_> + 18 3 4 2 -1. + <_> + 18 4 4 1 2. + 0 + -7.2760661132633686e-003 + 0.1169442981481552 + -0.0564889013767242 + <_> + + <_> + + + + <_> + 7 11 6 4 -1. + <_> + 9 11 2 4 3. + 0 + -0.0167282801121473 + -0.5582438707351685 + 0.0246787108480930 + <_> + + <_> + + + + <_> + 20 4 5 6 -1. + <_> + 20 6 5 2 3. + 0 + 3.5163350403308868e-003 + -0.1312393993139267 + 0.0638676136732101 + <_> + + <_> + + + + <_> + 1 12 5 3 -1. + <_> + 1 13 5 1 3. + 0 + -3.7709469906985760e-003 + -0.3320902884006500 + 0.0413776598870754 + <_> + + <_> + + + + <_> + 1 0 24 2 -1. + <_> + 13 0 12 1 2. + <_> + 1 1 12 1 2. + 0 + -0.0138869602233171 + -0.3127424120903015 + 0.0425702482461929 + <_> + + <_> + + + + <_> + 3 3 5 3 -1. + <_> + 2 4 5 1 3. + 1 + 9.3537326902151108e-003 + -0.0667856708168983 + 0.1907455027103424 + <_> + + <_> + + + + <_> + 17 6 8 4 -1. + <_> + 19 6 4 4 2. + 0 + -0.0194346699863672 + 0.3152694106101990 + -0.0473581515252590 + <_> + + <_> + + + + <_> + 5 0 1 3 -1. + <_> + 4 1 1 1 3. + 1 + 6.2511018477380276e-003 + 0.0309588797390461 + -0.3830946981906891 + <_> + + <_> + + + + <_> + 23 0 2 4 -1. + <_> + 23 2 2 2 2. + 0 + -0.0252969004213810 + -0.2962245941162109 + 0.0151915997266769 + <_> + + <_> + + + + <_> + 0 0 3 6 -1. + <_> + 0 3 3 3 2. + 0 + -3.0754129402339458e-003 + 0.0729133188724518 + -0.1764045059680939 + <_> + + <_> + + + + <_> + 11 1 14 2 -1. + <_> + 18 1 7 1 2. + <_> + 11 2 7 1 2. + 0 + 7.8001008369028568e-003 + -0.0501575507223606 + 0.1162889003753662 + <_> + + <_> + + + + <_> + 0 1 14 2 -1. + <_> + 0 1 7 1 2. + <_> + 7 2 7 1 2. + 0 + -7.7680540271103382e-003 + 0.2415755987167358 + -0.0778944417834282 + <_> + + <_> + + + + <_> + 5 4 15 6 -1. + <_> + 5 6 15 2 3. + 0 + -0.0880923122167587 + 0.2515082955360413 + -0.0482993088662624 + <_> + + <_> + + + + <_> + 10 7 2 2 -1. + <_> + 10 8 2 1 2. + 0 + -1.7023129621520638e-003 + 0.1797576993703842 + -0.0970716699957848 + <_> + + <_> + + + + <_> + 13 2 8 5 -1. + <_> + 15 4 4 5 2. + 1 + -0.0997034236788750 + -0.4700092971324921 + 0.0155829498544335 + <_> + + <_> + + + + <_> + 2 9 2 2 -1. + <_> + 2 9 1 2 2. + 1 + 4.6657170169055462e-003 + 0.0295135807245970 + -0.4018146991729736 + <_> + + <_> + + + + <_> + 12 8 6 3 -1. + <_> + 14 8 2 3 3. + 0 + -0.0176613796502352 + -0.5449513792991638 + 0.0168585199862719 + <_> + + <_> + + + + <_> + 0 9 24 6 -1. + <_> + 8 11 8 2 9. + 0 + -0.2230933010578156 + 0.1843273043632507 + -0.0632233396172524 + <_> + + <_> + + + + <_> + 1 12 24 3 -1. + <_> + 9 13 8 1 9. + 0 + 0.0528507791459560 + -0.0734771713614464 + 0.1994421929121018 + <_> + + <_> + + + + <_> + 5 11 15 4 -1. + <_> + 5 13 15 2 2. + 0 + -0.0246656592935324 + 0.2699545025825501 + -0.0523515492677689 + <_> + + <_> + + + + <_> + 24 10 1 4 -1. + <_> + 23 11 1 2 2. + 1 + -4.9799769185483456e-003 + -0.4495851993560791 + 0.0269833803176880 + <_> + + <_> + + + + <_> + 1 10 4 1 -1. + <_> + 2 11 2 1 2. + 1 + 3.0535869300365448e-003 + 0.0375075116753578 + -0.3464896082878113 + <_> + + <_> + + + + <_> + 15 1 10 14 -1. + <_> + 15 8 10 7 2. + 0 + -0.0263100396841764 + -0.1766241043806076 + 0.0256136003881693 + <_> + + <_> + + + + <_> + 0 7 4 2 -1. + <_> + 2 7 2 2 2. + 0 + -4.8684021458029747e-003 + 0.1877097040414810 + -0.0605575516819954 + <_> + + <_> + + + + <_> + 20 4 5 6 -1. + <_> + 20 6 5 2 3. + 0 + 0.0458405800163746 + 0.0330421291291714 + -0.2026686072349548 + <_> + + <_> + + + + <_> + 0 4 7 6 -1. + <_> + 0 6 7 2 3. + 0 + 6.7487969063222408e-003 + -0.1384654939174652 + 0.1144922971725464 + <_> + + <_> + + + + <_> + 11 7 6 3 -1. + <_> + 11 8 6 1 3. + 0 + 0.0107938302680850 + -0.0550474487245083 + 0.1810662001371384 + <_> + + <_> + + + + <_> + 8 10 9 1 -1. + <_> + 11 10 3 1 3. + 0 + -0.0132016502320766 + -0.4654887914657593 + 0.0258085392415524 + <_> + + <_> + + + + <_> + 5 10 15 1 -1. + <_> + 10 10 5 1 3. + 0 + -4.9963342025876045e-003 + 0.1138966009020805 + -0.1140139997005463 + <_> + + <_> + + + + <_> + 7 8 6 3 -1. + <_> + 9 8 2 3 3. + 0 + -0.0158193595707417 + -0.4853562116622925 + 0.0220876205712557 + <_> + + <_> + + + + <_> + 23 12 2 1 -1. + <_> + 23 12 1 1 2. + 0 + 6.8264620495028794e-005 + -0.0819193720817566 + 0.0840993970632553 + <_> + + <_> + + + + <_> + 0 13 24 2 -1. + <_> + 0 13 12 1 2. + <_> + 12 14 12 1 2. + 0 + -0.0156373791396618 + -0.4515635073184967 + 0.0227358005940914 + <_> + + <_> + + + + <_> + 9 9 7 3 -1. + <_> + 9 10 7 1 3. + 0 + 8.3005577325820923e-003 + -0.0514142103493214 + 0.2212347984313965 + <_> + + <_> + + + + <_> + 0 6 2 4 -1. + <_> + 0 7 2 2 2. + 0 + 6.6999751143157482e-003 + 0.0297896005213261 + -0.3543488979339600 + <_> + + <_> + + + + <_> + 18 2 5 4 -1. + <_> + 18 3 5 2 2. + 0 + 5.1744161173701286e-003 + -0.0496886894106865 + 0.2202914059162140 + <_> + + <_> + + + + <_> + 1 4 8 2 -1. + <_> + 1 4 4 1 2. + <_> + 5 5 4 1 2. + 0 + 6.1278040520846844e-003 + -0.0630758926272392 + 0.1783366054296494 + <_> + + <_> + + + + <_> + 21 8 4 4 -1. + <_> + 21 9 4 2 2. + 0 + 6.8791587837040424e-003 + 0.0284415297210217 + -0.2993854880332947 + <_> + + <_> + + + + <_> + 4 4 8 4 -1. + <_> + 4 5 8 2 2. + 0 + -0.0217361003160477 + 0.1791318953037262 + -0.0602877512574196 + <_> + + <_> + + + + <_> + 11 4 14 4 -1. + <_> + 11 5 14 2 2. + 0 + 0.0140090202912688 + -0.1060196980834007 + 0.1548174023628235 + <_> + + <_> + + + + <_> + 3 0 18 9 -1. + <_> + 12 0 9 9 2. + 0 + 0.2186813950538635 + -0.0483517609536648 + 0.2573468983173370 + <_> + + <_> + + + + <_> + 3 0 20 15 -1. + <_> + 3 0 10 15 2. + 0 + 0.2838009893894196 + -0.0509055890142918 + 0.2936053872108460 + <_> + + <_> + + + + <_> + 12 1 6 8 -1. + <_> + 14 3 2 8 3. + 1 + 0.1209316030144692 + 0.0173095706850290 + -0.6926872134208679 + <_> + + <_> + + + + <_> + 17 4 1 9 -1. + <_> + 14 7 1 3 3. + 1 + 0.0569618307054043 + -0.0186788197606802 + 0.3227567970752716 + <_> + + <_> + + + + <_> + 6 7 4 8 -1. + <_> + 7 7 2 8 2. + 0 + -9.0500963851809502e-003 + -0.4240661859512329 + 0.0268415194004774 + <_> + + <_> + + + + <_> + 21 5 4 3 -1. + <_> + 21 6 4 1 3. + 0 + 0.0231182798743248 + 0.0105462800711393 + -0.5228689908981323 + <_> + + <_> + + + + <_> + 7 0 2 2 -1. + <_> + 7 0 1 1 2. + <_> + 8 1 1 1 2. + 0 + 1.1480690445750952e-003 + -0.0459857396781445 + 0.2319914996623993 + <_> + + <_> + + + + <_> + 21 8 4 3 -1. + <_> + 21 9 4 1 3. + 0 + -9.8909307271242142e-003 + -0.5407552123069763 + 0.0142617002129555 + <_> + + <_> + + + + <_> + 7 1 2 2 -1. + <_> + 7 1 1 1 2. + <_> + 8 2 1 1 2. + 0 + 7.0599978789687157e-004 + -0.0649549588561058 + 0.1677557975053787 + <_> + + <_> + + + + <_> + 16 1 2 2 -1. + <_> + 17 1 1 1 2. + <_> + 16 2 1 1 2. + 0 + -8.2311293226666749e-005 + 0.0727679133415222 + -0.0542482398450375 + <_> + + <_> + + + + <_> + 0 8 4 3 -1. + <_> + 0 9 4 1 3. + 0 + 5.3380471654236317e-003 + 0.0320924408733845 + -0.3186857998371124 + <_> + + <_> + + + + <_> + 20 9 2 2 -1. + <_> + 21 9 1 1 2. + <_> + 20 10 1 1 2. + 0 + 5.9835889260284603e-005 + -0.0492977797985077 + 0.0571143105626106 + <_> + + <_> + + + + <_> + 3 9 2 2 -1. + <_> + 3 9 1 1 2. + <_> + 4 10 1 1 2. + 0 + 4.0741640987107530e-005 + -0.0992263928055763 + 0.1105673015117645 + <_> + + <_> + + + + <_> + 19 3 6 12 -1. + <_> + 22 3 3 6 2. + <_> + 19 9 3 6 2. + 0 + -0.0271146595478058 + 0.2459900975227356 + -0.0621489509940147 + <_> + + <_> + + + + <_> + 7 1 2 2 -1. + <_> + 7 1 1 1 2. + <_> + 8 2 1 1 2. + 0 + -8.8477227836847305e-004 + 0.2023449987173080 + -0.0529261194169521 + <_> + + <_> + + + + <_> + 7 4 12 3 -1. + <_> + 7 5 12 1 3. + 0 + -0.0192636791616678 + 0.1516259014606476 + -0.0715369805693626 + <_> + + <_> + + + + <_> + 0 0 11 2 -1. + <_> + 0 1 11 1 2. + 0 + 9.6891522407531738e-003 + 0.0357108712196350 + -0.3255082964897156 + <_> + + <_> + + + + <_> + 13 2 6 5 -1. + <_> + 15 2 2 5 3. + 0 + -0.0228419005870819 + -0.3499914109706879 + 0.0171892996877432 + <_> + + <_> + + + + <_> + 0 0 24 10 -1. + <_> + 0 0 12 5 2. + <_> + 12 5 12 5 2. + 0 + -0.1477797031402588 + -0.4319078028202057 + 0.0216299500316381 + <_> + + <_> + + + + <_> + 20 4 2 3 -1. + <_> + 20 5 2 1 3. + 0 + 2.3399880155920982e-003 + -0.0442668199539185 + 0.0963377729058266 + <_> + + <_> + + + + <_> + 0 3 7 4 -1. + <_> + 0 4 7 2 2. + 0 + -0.0728321895003319 + -0.8186188936233521 + 0.0117990002036095 + <_> + + <_> + + + + <_> + 11 1 14 14 -1. + <_> + 11 8 14 7 2. + 0 + -0.3072721064090729 + -0.7007309198379517 + 3.5564110148698092e-003 + <_> + + <_> + + + + <_> + 6 2 6 5 -1. + <_> + 8 2 2 5 3. + 0 + -0.0207666493952274 + -0.3913905024528503 + 0.0246222894638777 + <_> + + <_> + + + + <_> + 16 0 2 2 -1. + <_> + 17 0 1 1 2. + <_> + 16 1 1 1 2. + 0 + -3.6341920495033264e-003 + -0.4501088857650757 + 5.5562350898981094e-003 + <_> + + <_> + + + + <_> + 7 0 2 2 -1. + <_> + 7 0 1 1 2. + <_> + 8 1 1 1 2. + 0 + -7.0794070779811591e-005 + 0.1087834984064102 + -0.0905004590749741 + <_> + + <_> + + + + <_> + 16 0 2 2 -1. + <_> + 17 0 1 1 2. + <_> + 16 1 1 1 2. + 0 + -8.8314860477112234e-005 + 0.0641764104366302 + -0.0494646318256855 + <_> + + <_> + + + + <_> + 2 0 20 1 -1. + <_> + 7 0 10 1 2. + 0 + -0.0110706500709057 + 0.1473083049058914 + -0.0670493170619011 + <_> + + <_> + + + + <_> + 11 0 14 1 -1. + <_> + 11 0 7 1 2. + 0 + 6.3626351766288280e-003 + -0.0400333292782307 + 0.0926633775234222 + <_> + + <_> + + + + <_> + 9 3 6 2 -1. + <_> + 9 4 6 1 2. + 0 + -7.7499519102275372e-003 + 0.1392461061477661 + -0.0774780735373497 + <_> + + <_> + + + + <_> + 11 3 3 4 -1. + <_> + 11 4 3 2 2. + 0 + 4.7532729804515839e-003 + -0.0729171708226204 + 0.1706562042236328 + <_> + + <_> + + + + <_> + 0 11 18 3 -1. + <_> + 6 12 6 1 9. + 0 + -0.0168079808354378 + 0.1308007985353470 + -0.0801806673407555 + <_> + + <_> + + + + <_> + 15 3 10 12 -1. + <_> + 20 3 5 6 2. + <_> + 15 9 5 6 2. + 0 + 0.1279494017362595 + -0.0199226494878531 + 0.3711799085140228 + <_> + + <_> + + + + <_> + 0 3 14 3 -1. + <_> + 0 4 14 1 3. + 0 + -0.0181895997375250 + 0.1235873028635979 + -0.0830406174063683 + <_> + + <_> + + + + <_> + 9 4 8 3 -1. + <_> + 11 4 4 3 2. + 0 + -0.0161725897341967 + -0.4490650892257690 + 0.0227566491812468 + <_> + + <_> + + + + <_> + 0 12 2 1 -1. + <_> + 1 12 1 1 2. + 0 + 6.8046152591705322e-005 + -0.1011824011802673 + 0.0935735777020454 + <_> + + <_> + + + + <_> + 23 13 2 2 -1. + <_> + 24 13 1 1 2. + <_> + 23 14 1 1 2. + 0 + 1.1714019638020545e-004 + -0.0810816064476967 + 0.1062628999352455 + <_> + + <_> + + + + <_> + 0 13 2 2 -1. + <_> + 0 13 1 1 2. + <_> + 1 14 1 1 2. + 0 + 5.4521678976016119e-005 + -0.0932891815900803 + 0.1159989982843399 + <_> + + <_> + + + + <_> + 9 12 8 1 -1. + <_> + 11 12 4 1 2. + 0 + -9.5095802098512650e-003 + -0.5051903724670410 + 0.0141592798754573 + <_> + + <_> + + + + <_> + 0 7 6 4 -1. + <_> + 0 8 6 2 2. + 0 + -2.8461390174925327e-003 + -0.1991575956344605 + 0.0473652109503746 + <_> + + <_> + + + + <_> + 19 3 6 12 -1. + <_> + 22 3 3 6 2. + <_> + 19 9 3 6 2. + 0 + 0.0232862401753664 + -0.0403292290866375 + 0.0805157274007797 + <_> + + <_> + + + + <_> + 0 3 6 12 -1. + <_> + 0 3 3 6 2. + <_> + 3 9 3 6 2. + 0 + -0.0426056496798992 + 0.3344807922840118 + -0.0383727103471756 + <_> + + <_> + + + + <_> + 23 7 2 4 -1. + <_> + 23 8 2 2 2. + 0 + 4.5101181603968143e-003 + 0.0263549294322729 + -0.2349215000867844 + <_> + + <_> + + + + <_> + 0 7 2 4 -1. + <_> + 0 8 2 2 2. + 0 + 6.1817811802029610e-003 + 0.0211725104600191 + -0.4420514106750488 + <_> + + <_> + + + + <_> + 13 7 8 4 -1. + <_> + 17 7 4 2 2. + <_> + 13 9 4 2 2. + 0 + -0.0106069697067142 + 0.0654574930667877 + -0.0324725992977619 + <_> + + <_> + + + + <_> + 0 1 10 14 -1. + <_> + 0 8 10 7 2. + 0 + -0.0858135819435120 + -0.3406231105327606 + 0.0301514994353056 + <_> + + <_> + + + + <_> + 9 8 7 3 -1. + <_> + 9 9 7 1 3. + 0 + 6.2758061103522778e-003 + -0.0619911886751652 + 0.1503033936023712 + <_> + + <_> + + + + <_> + 9 8 3 4 -1. + <_> + 9 9 3 2 2. + 0 + -3.0965260230004787e-003 + 0.1481299996376038 + -0.0813362672924995 + <_> + + <_> + + + + <_> + 18 10 2 3 -1. + <_> + 17 11 2 1 3. + 1 + -0.0111239803954959 + -0.4638158082962036 + 0.0152134699746966 + <_> + + <_> + + + + <_> + 7 10 3 2 -1. + <_> + 8 11 1 2 3. + 1 + -0.0111039802432060 + -0.6005380153656006 + 0.0135854296386242 + <_> + + <_> + + + + <_> + 23 0 2 1 -1. + <_> + 23 0 1 1 2. + 1 + -3.2944830600172281e-003 + -0.4641366004943848 + 0.0262269694358110 + <_> + + <_> + + + + <_> + 12 8 4 3 -1. + <_> + 12 8 2 3 2. + 1 + 0.0113766100257635 + -0.0565435998141766 + 0.1575082987546921 + <_> + + <_> + + + + <_> + 5 7 15 3 -1. + <_> + 10 8 5 1 9. + 0 + -0.0294652003794909 + 0.1486423015594482 + -0.0651882514357567 + <_> + + <_> + + + + <_> + 0 0 20 8 -1. + <_> + 10 0 10 8 2. + 0 + 0.0491673015058041 + -0.0922251716256142 + 0.1015425994992256 + <_> + + <_> + + + + <_> + 21 0 4 3 -1. + <_> + 20 1 4 1 3. + 1 + -0.0209590997546911 + 0.1749638020992279 + -0.0255501996725798 + <_> + + <_> + + + + <_> + 4 0 3 4 -1. + <_> + 5 1 1 4 3. + 1 + 5.4627470672130585e-003 + -0.0626592189073563 + 0.1695216000080109 + <_> + + <_> + + + + <_> + 18 3 5 2 -1. + <_> + 18 4 5 1 2. + 0 + -4.3515427969396114e-003 + 0.0822615697979927 + -0.0598390214145184 + <_> + + <_> + + + + <_> + 2 3 5 2 -1. + <_> + 2 4 5 1 2. + 0 + 7.4772499501705170e-003 + -0.0495455190539360 + 0.2469687014818192 + <_> + + <_> + + + + <_> + 13 0 2 5 -1. + <_> + 13 0 1 5 2. + 1 + -0.0374278612434864 + -0.9178332090377808 + 3.5620180424302816e-003 + <_> + + <_> + + + + <_> + 5 12 6 3 -1. + <_> + 7 13 2 1 9. + 0 + -0.0248439908027649 + -0.4893918037414551 + 0.0171825792640448 + <_> + + <_> + + + + <_> + 13 0 2 5 -1. + <_> + 13 0 1 5 2. + 1 + 8.0120442435145378e-003 + 0.0217423699796200 + -0.0648176670074463 + <_> + + <_> + + + + <_> + 9 6 4 2 -1. + <_> + 9 7 4 1 2. + 0 + 5.7306028902530670e-003 + -0.0707883909344673 + 0.1390995979309082 + <_> + + <_> + + + + <_> + 18 9 4 3 -1. + <_> + 18 10 4 1 3. + 0 + 0.0109893204644322 + 7.0361187681555748e-003 + -0.3556833863258362 + <_> + + <_> + + + + <_> + 3 9 4 3 -1. + <_> + 3 10 4 1 3. + 0 + -3.5342550836503506e-003 + -0.2303902953863144 + 0.0395394414663315 + <_> + + <_> + + + + <_> + 7 9 15 6 -1. + <_> + 7 12 15 3 2. + 0 + 0.0326121784746647 + -0.0834509506821632 + 0.0961622893810272 + <_> + + <_> + + + + <_> + 4 1 12 6 -1. + <_> + 4 1 6 3 2. + <_> + 10 4 6 3 2. + 0 + -0.0519190989434719 + -0.3597438931465149 + 0.0235583093017340 + <_> + + <_> + + + + <_> + 10 5 14 10 -1. + <_> + 10 10 14 5 2. + 0 + 0.2802706062793732 + 0.0191025994718075 + -0.2738722860813141 + <_> + + <_> + + + + <_> + 10 6 2 3 -1. + <_> + 10 7 2 1 3. + 0 + -1.8680640496313572e-003 + 0.1557087004184723 + -0.0592420399188995 + <_> + + <_> + + + + <_> + 13 4 4 6 -1. + <_> + 14 5 2 6 2. + 1 + 0.0412711799144745 + 9.2102894559502602e-003 + -0.6225361824035645 + <_> + + <_> + + + + <_> + 12 4 6 4 -1. + <_> + 11 5 6 2 2. + 1 + -0.0341574586927891 + -0.6910676956176758 + 0.0140588199719787 + <_> + + <_> + + + + <_> + 19 0 5 3 -1. + <_> + 19 1 5 1 3. + 0 + 0.0281112492084503 + 6.3892039470374584e-003 + -0.6016489267349243 + <_> + + <_> + + + + <_> + 6 7 3 1 -1. + <_> + 7 7 1 1 3. + 0 + -9.7675784491002560e-004 + 0.1663821935653687 + -0.0533109381794930 + <_> + + <_> + + + + <_> + 19 0 5 3 -1. + <_> + 19 1 5 1 3. + 0 + -0.0284041091799736 + -0.8431190848350525 + 4.9202498048543930e-003 + <_> + + <_> + + + + <_> + 6 7 3 1 -1. + <_> + 7 7 1 1 3. + 0 + 9.7658135928213596e-004 + -0.0524366609752178 + 0.1696853935718536 + <_> + + <_> + + + + <_> + 11 0 6 15 -1. + <_> + 13 0 2 15 3. + 0 + -0.0793864428997040 + -0.7418122291564941 + 4.5842900872230530e-003 + <_> + + <_> + + + + <_> + 0 2 2 6 -1. + <_> + 0 2 1 3 2. + <_> + 1 5 1 3 2. + 0 + 2.9205000028014183e-003 + -0.0499707907438278 + 0.1705241948366165 + <_> + + <_> + + + + <_> + 21 0 2 1 -1. + <_> + 21 0 1 1 2. + 1 + -4.9792099744081497e-003 + -0.4247047007083893 + 0.0113332699984312 + <_> + + <_> + + + + <_> + 4 0 1 2 -1. + <_> + 4 0 1 1 2. + 1 + 7.5309360399842262e-003 + 0.0200634505599737 + -0.4817556142807007 + <_> + + <_> + + + + <_> + 9 0 14 8 -1. + <_> + 9 0 7 8 2. + 0 + -0.1206317022442818 + 0.1783839017152786 + -0.0404023304581642 + <_> + + <_> + + + + <_> + 7 0 2 2 -1. + <_> + 7 0 1 1 2. + <_> + 8 1 1 1 2. + 0 + 6.4506952185183764e-005 + -0.0858542472124100 + 0.1069532036781311 + <_> + + <_> + + + + <_> + 4 6 18 4 -1. + <_> + 4 6 9 4 2. + 0 + 0.1407386958599091 + -0.0227742493152618 + 0.4258378148078919 + <_> + + <_> + + + + <_> + 0 7 2 2 -1. + <_> + 0 7 1 1 2. + <_> + 1 8 1 1 2. + 0 + 5.8708712458610535e-004 + -0.0585701502859592 + 0.1556326001882553 + <_> + + <_> + + + + <_> + 23 7 2 2 -1. + <_> + 24 7 1 1 2. + <_> + 23 8 1 1 2. + 0 + 4.2137140553677455e-005 + -0.0576708205044270 + 0.0648988783359528 + <_> + + <_> + + + + <_> + 0 7 2 2 -1. + <_> + 0 7 1 1 2. + <_> + 1 8 1 1 2. + 0 + -5.4859159718034789e-005 + 0.1383187025785446 + -0.0935516208410263 + <_> + + <_> + + + + <_> + 23 7 2 2 -1. + <_> + 24 7 1 1 2. + <_> + 23 8 1 1 2. + 0 + -8.1318263255525380e-005 + 0.0786737129092216 + -0.0584529899060726 + <_> + + <_> + + + + <_> + 0 7 2 2 -1. + <_> + 0 7 1 1 2. + <_> + 1 8 1 1 2. + 0 + 1.0710170317906886e-004 + -0.1036069020628929 + 0.1105291023850441 + <_> + + <_> + + + + <_> + 24 6 1 4 -1. + <_> + 24 7 1 2 2. + 0 + 5.9485197998583317e-003 + 0.0124739902094007 + -0.6046726703643799 + <_> + + <_> + + + + <_> + 0 6 1 4 -1. + <_> + 0 7 1 2 2. + 0 + -3.8341151084750891e-003 + -0.5651066899299622 + 0.0139579800888896 + <_> + + <_> + + + + <_> + 11 0 6 15 -1. + <_> + 13 0 2 15 3. + 0 + 0.0481832996010780 + 6.8787620402872562e-003 + -0.2265198975801468 + <_> + + <_> + + + + <_> + 0 1 2 3 -1. + <_> + 0 2 2 1 3. + 0 + 9.8468521609902382e-003 + 0.0149204200133681 + -0.5408421754837036 + <_> + + <_> + + + + <_> + 8 1 9 3 -1. + <_> + 8 2 9 1 3. + 0 + 7.0795980282127857e-003 + -0.0740584135055542 + 0.1212510019540787 + <_> + + <_> + + + + <_> + 8 1 3 3 -1. + <_> + 9 2 1 1 9. + 0 + -1.7187669873237610e-003 + 0.1150275021791458 + -0.0767944231629372 + <_> + + <_> + + + + <_> + 19 7 5 3 -1. + <_> + 18 8 5 1 3. + 1 + 0.0141321197152138 + 0.0222348105162382 + -0.3713991045951843 + <_> + + <_> + + + + <_> + 6 7 3 5 -1. + <_> + 7 8 1 5 3. + 1 + -8.0704037100076675e-003 + -0.2536310851573944 + 0.0307344105094671 + <_> + + <_> + + + + <_> + 1 0 24 14 -1. + <_> + 13 0 12 7 2. + <_> + 1 7 12 7 2. + 0 + 0.2283755987882614 + 0.0168569702655077 + -0.5456647872924805 + <_> + + <_> + + + + <_> + 8 11 9 4 -1. + <_> + 8 12 9 2 2. + 0 + -0.0106975501403213 + 0.1705504059791565 + -0.0482324399054050 + <_> + + <_> + + + + <_> + 6 11 14 4 -1. + <_> + 6 12 14 2 2. + 0 + 6.1057992279529572e-003 + -0.0747807994484901 + 0.1244964972138405 + <_> + + <_> + + + + <_> + 0 11 3 4 -1. + <_> + 0 12 3 2 2. + 0 + 3.5825320519506931e-003 + 0.0343106091022491 + -0.2529211938381195 + <_> + + <_> + + + + <_> + 17 11 8 2 -1. + <_> + 17 12 8 1 2. + 0 + 8.7969396263360977e-003 + 0.0227318406105042 + -0.2092120051383972 + <_> + + <_> + + + + <_> + 0 11 8 2 -1. + <_> + 0 12 8 1 2. + 0 + -0.0117600196972489 + -0.5789325237274170 + 0.0150208799168468 + <_> + + <_> + + + + <_> + 23 13 1 2 -1. + <_> + 23 14 1 1 2. + 0 + 1.4420140068978071e-003 + 0.0108067002147436 + -0.1743503063917160 + <_> + + <_> + + + + <_> + 1 13 1 2 -1. + <_> + 1 14 1 1 2. + 0 + -4.9062469770433381e-005 + 0.0891510024666786 + -0.0946391522884369 + <_> + + <_> + + + + <_> + 9 0 14 8 -1. + <_> + 9 0 7 8 2. + 0 + 0.0330546088516712 + -0.0502973310649395 + 0.0724259391427040 + <_> + + <_> + + + + <_> + 0 1 14 8 -1. + <_> + 0 3 14 4 2. + 0 + -0.0449321903288364 + 0.0714013203978539 + -0.1246540024876595 + <_> + + <_> + + + + <_> + 20 4 2 3 -1. + <_> + 20 5 2 1 3. + 0 + -0.0123274503275752 + 0.2216438055038452 + -0.0160399992018938 + <_> + + <_> + + + + <_> + 0 1 14 9 -1. + <_> + 0 4 14 3 3. + 0 + -0.3724926114082336 + -0.3693152964115143 + 0.0260022208094597 + <_> + + <_> + + + + <_> + 9 13 9 1 -1. + <_> + 12 13 3 1 3. + 0 + 0.0152763100340962 + 5.3399899043142796e-003 + -0.5456783771514893 + <_> + + <_> + + + + <_> + 7 13 9 1 -1. + <_> + 10 13 3 1 3. + 0 + -0.0145687395706773 + -0.5883231163024902 + 0.0139877004548907 + <_> + + <_> + + + + <_> + 20 7 2 2 -1. + <_> + 21 7 1 1 2. + <_> + 20 8 1 1 2. + 0 + 9.9890248384326696e-004 + -0.0358810797333717 + 0.1743257045745850 + -1.3605639934539795 + 13 + -1 + <_> + + + <_> + + <_> + + + + <_> + 5 9 15 6 -1. + <_> + 5 12 15 3 2. + 0 + 0.0572950802743435 + -0.1768665015697479 + 0.2448291033506393 + <_> + + <_> + + + + <_> + 21 0 2 6 -1. + <_> + 21 3 2 3 2. + 0 + -0.0100825401023030 + 0.1378919035196304 + -0.2031147032976151 + <_> + + <_> + + + + <_> + 4 4 8 10 -1. + <_> + 4 4 4 5 2. + <_> + 8 9 4 5 2. + 0 + -0.0185250397771597 + 0.1623972952365875 + -0.1676190942525864 + <_> + + <_> + + + + <_> + 16 1 8 6 -1. + <_> + 16 3 8 2 3. + 0 + -0.0527544915676117 + 0.1347105056047440 + -0.1428814977407455 + <_> + + <_> + + + + <_> + 2 1 11 2 -1. + <_> + 2 1 11 1 2. + 1 + 0.0243547502905130 + -0.0266546793282032 + 0.4326488971710205 + <_> + + <_> + + + + <_> + 20 4 5 6 -1. + <_> + 20 6 5 2 3. + 0 + 0.0634179636836052 + 0.0422610901296139 + -0.4013176858425140 + <_> + + <_> + + + + <_> + 0 4 5 6 -1. + <_> + 0 6 5 2 3. + 0 + 3.8921029772609472e-003 + -0.1906750947237015 + 0.1267316043376923 + <_> + + <_> + + + + <_> + 19 11 6 4 -1. + <_> + 22 11 3 2 2. + <_> + 19 13 3 2 2. + 0 + 1.5238909982144833e-003 + -0.1371546983718872 + 0.1246439963579178 + <_> + + <_> + + + + <_> + 10 4 5 2 -1. + <_> + 10 5 5 1 2. + 0 + -6.7657418549060822e-003 + 0.2558242976665497 + -0.0607152618467808 + <_> + + <_> + + + + <_> + 7 6 11 4 -1. + <_> + 7 7 11 2 2. + 0 + -0.0241763703525066 + 0.2859889864921570 + -0.0642128363251686 + <_> + + <_> + + + + <_> + 9 2 4 4 -1. + <_> + 9 2 2 4 2. + 1 + -9.1761918738484383e-003 + 0.1021848022937775 + -0.1999447047710419 + <_> + + <_> + + + + <_> + 1 0 24 11 -1. + <_> + 7 0 12 11 2. + 0 + -0.1578399986028671 + 0.2398308068513870 + -0.0785783529281616 + <_> + + <_> + + + + <_> + 4 0 10 10 -1. + <_> + 9 0 5 10 2. + 0 + 0.0487401895225048 + -0.1100914031267166 + 0.1558353006839752 + <_> + + <_> + + + + <_> + 23 8 2 4 -1. + <_> + 23 8 2 2 2. + 1 + 0.0191179793328047 + 0.0197066999971867 + -0.3720233142375946 + <_> + + <_> + + + + <_> + 2 8 4 2 -1. + <_> + 2 8 2 2 2. + 1 + -0.0127781601622701 + -0.4160012900829315 + 0.0353787206113338 + <_> + + <_> + + + + <_> + 23 3 2 12 -1. + <_> + 24 3 1 6 2. + <_> + 23 9 1 6 2. + 0 + 2.6996301021426916e-003 + -0.0985597372055054 + 0.1149144023656845 + <_> + + <_> + + + + <_> + 9 3 6 12 -1. + <_> + 9 3 3 6 2. + <_> + 12 9 3 6 2. + 0 + 0.0245021991431713 + 0.0430920794606209 + -0.3663294017314911 + <_> + + <_> + + + + <_> + 1 0 24 12 -1. + <_> + 13 0 12 6 2. + <_> + 1 6 12 6 2. + 0 + 0.0850031301379204 + 0.0430114008486271 + -0.2886289954185486 + <_> + + <_> + + + + <_> + 0 3 2 12 -1. + <_> + 0 3 1 6 2. + <_> + 1 9 1 6 2. + 0 + 3.1647530850023031e-003 + -0.1142930984497070 + 0.1279425024986267 + <_> + + <_> + + + + <_> + 14 8 3 4 -1. + <_> + 14 8 3 2 2. + 1 + 0.0116577902808785 + -0.0515255816280842 + 0.1422376930713654 + <_> + + <_> + + + + <_> + 0 0 6 1 -1. + <_> + 2 0 2 1 3. + 0 + -6.6801449283957481e-003 + -0.4743103981018066 + 0.0287305805832148 + <_> + + <_> + + + + <_> + 9 2 16 7 -1. + <_> + 13 2 8 7 2. + 0 + -0.0388207696378231 + 0.0953134000301361 + -0.0473909191787243 + <_> + + <_> + + + + <_> + 8 7 1 6 -1. + <_> + 8 7 1 3 2. + 1 + -0.0254217702895403 + -0.4219881892204285 + 0.0284377895295620 + <_> + + <_> + + + + <_> + 8 7 9 4 -1. + <_> + 8 8 9 2 2. + 0 + -0.0121460696682334 + 0.1830082982778549 + -0.0762820765376091 + <_> + + <_> + + + + <_> + 7 5 10 4 -1. + <_> + 7 6 10 2 2. + 0 + -0.0267872195690870 + 0.2859373092651367 + -0.0522297993302345 + <_> + + <_> + + + + <_> + 14 2 1 6 -1. + <_> + 12 4 1 2 3. + 1 + -0.0116149904206395 + 0.1138594970107079 + -0.0663506835699081 + <_> + + <_> + + + + <_> + 0 3 8 12 -1. + <_> + 0 3 4 6 2. + <_> + 4 9 4 6 2. + 0 + -0.0599568895995617 + 0.2777940034866333 + -0.0470041483640671 + <_> + + <_> + + + + <_> + 19 13 6 2 -1. + <_> + 19 13 3 2 2. + 0 + -8.6737014353275299e-003 + 0.2129196971654892 + -0.0287764091044664 + <_> + + <_> + + + + <_> + 0 13 6 2 -1. + <_> + 3 13 3 2 2. + 0 + 2.8543549124151468e-003 + -0.1221636980772018 + 0.1421594023704529 + <_> + + <_> + + + + <_> + 23 12 1 3 -1. + <_> + 23 13 1 1 3. + 0 + 2.2713060025125742e-003 + 0.0182375106960535 + -0.4104354083538055 + <_> + + <_> + + + + <_> + 1 12 1 3 -1. + <_> + 1 13 1 1 3. + 0 + -1.2334890197962523e-003 + -0.3772745132446289 + 0.0350435785949230 + <_> + + <_> + + + + <_> + 23 12 1 3 -1. + <_> + 23 13 1 1 3. + 0 + -2.6904400438070297e-003 + -0.4196098148822784 + 0.0100445803254843 + <_> + + <_> + + + + <_> + 4 10 10 1 -1. + <_> + 9 10 5 1 2. + 0 + -2.6551370974630117e-003 + 0.1150795966386795 + -0.1072231009602547 + <_> + + <_> + + + + <_> + 23 12 1 3 -1. + <_> + 23 13 1 1 3. + 0 + -5.6895318266469985e-005 + 0.0416303612291813 + -0.0317232310771942 + <_> + + <_> + + + + <_> + 1 12 1 3 -1. + <_> + 1 13 1 1 3. + 0 + 9.8731368780136108e-004 + 0.0429715514183044 + -0.2815021872520447 + <_> + + <_> + + + + <_> + 11 2 12 4 -1. + <_> + 11 3 12 2 2. + 0 + 0.0182135794311762 + -0.0451830588281155 + 0.1914888024330139 + <_> + + <_> + + + + <_> + 3 1 12 6 -1. + <_> + 3 3 12 2 3. + 0 + -0.0872772708535194 + 0.1718962937593460 + -0.1219599992036820 + <_> + + <_> + + + + <_> + 23 0 2 2 -1. + <_> + 23 0 1 2 2. + 1 + -5.3898650221526623e-003 + -0.3866654038429260 + 0.0155352503061295 + <_> + + <_> + + + + <_> + 2 0 2 2 -1. + <_> + 2 0 2 1 2. + 1 + 0.0108539797365665 + 0.0364841781556606 + -0.3959751129150391 + <_> + + <_> + + + + <_> + 14 13 4 2 -1. + <_> + 15 13 2 2 2. + 0 + -4.1801291517913342e-003 + -0.4820233881473541 + 0.0170424394309521 + <_> + + <_> + + + + <_> + 3 6 6 3 -1. + <_> + 2 7 6 1 3. + 1 + -0.0234517697244883 + 0.4986476898193359 + -0.0220960807055235 + <_> + + <_> + + + + <_> + 14 13 4 2 -1. + <_> + 15 13 2 2 2. + 0 + 2.9061511158943176e-003 + 0.0269486699253321 + -0.3256624042987824 + <_> + + <_> + + + + <_> + 0 7 24 4 -1. + <_> + 0 7 12 2 2. + <_> + 12 9 12 2 2. + 0 + 0.0463646091520786 + 0.0268820300698280 + -0.3762974143028259 + <_> + + <_> + + + + <_> + 23 0 2 2 -1. + <_> + 23 1 2 1 2. + 0 + -2.1972910326439887e-004 + 0.0705367177724838 + -0.1089593023061752 + <_> + + <_> + + + + <_> + 7 13 4 2 -1. + <_> + 8 13 2 2 2. + 0 + -3.7804399617016315e-003 + -0.4887917041778565 + 0.0199932008981705 + <_> + + <_> + + + + <_> + 16 11 2 2 -1. + <_> + 17 11 1 1 2. + <_> + 16 12 1 1 2. + 0 + 6.0642170865321532e-005 + -0.0753576681017876 + 0.0811428874731064 + <_> + + <_> + + + + <_> + 8 11 9 4 -1. + <_> + 8 12 9 2 2. + 0 + -0.0106888897716999 + 0.2206722944974899 + -0.0562041401863098 + <_> + + <_> + + + + <_> + 2 12 21 3 -1. + <_> + 9 13 7 1 9. + 0 + 0.0436831787228584 + -0.0610822103917599 + 0.1712581962347031 + <_> + + <_> + + + + <_> + 1 13 21 2 -1. + <_> + 8 13 7 2 3. + 0 + -0.0202471297234297 + 0.1565587073564529 + -0.0770068317651749 + <_> + + <_> + + + + <_> + 22 10 1 4 -1. + <_> + 21 11 1 2 2. + 1 + -5.9285280294716358e-003 + -0.4369310140609741 + 0.0202764291316271 + <_> + + <_> + + + + <_> + 3 5 6 3 -1. + <_> + 2 6 6 1 3. + 1 + 0.0113492002710700 + -0.0597750283777714 + 0.1651744991540909 + <_> + + <_> + + + + <_> + 13 2 8 5 -1. + <_> + 15 4 4 5 2. + 1 + -0.1365716010332108 + -0.8707361817359924 + 4.2868419550359249e-003 + <_> + + <_> + + + + <_> + 4 2 8 6 -1. + <_> + 4 4 8 2 3. + 0 + 0.0663046464323998 + -0.0388697795569897 + 0.2649452090263367 + <_> + + <_> + + + + <_> + 5 1 15 4 -1. + <_> + 5 2 15 2 2. + 0 + 0.0195911191403866 + -0.0803443267941475 + 0.1665123999118805 + <_> + + <_> + + + + <_> + 0 1 8 4 -1. + <_> + 0 2 8 2 2. + 0 + 0.0340932197868824 + 0.0261821094900370 + -0.4526833891868591 + <_> + + <_> + + + + <_> + 10 0 15 14 -1. + <_> + 10 7 15 7 2. + 0 + -0.2061661928892136 + -0.4254589080810547 + 0.0156788490712643 + <_> + + <_> + + + + <_> + 9 13 6 2 -1. + <_> + 11 13 2 2 3. + 0 + -7.6675140298902988e-003 + -0.3513334095478058 + 0.0274340193718672 + <_> + + <_> + + + + <_> + 8 9 11 4 -1. + <_> + 8 10 11 2 2. + 0 + -0.0129145104438066 + 0.1359857022762299 + -0.0633687376976013 + <_> + + <_> + + + + <_> + 8 6 3 3 -1. + <_> + 9 7 1 3 3. + 1 + 0.0160742308944464 + 0.0215212907642126 + -0.4643712937831879 + <_> + + <_> + + + + <_> + 21 5 4 6 -1. + <_> + 21 7 4 2 3. + 0 + 0.0369430296123028 + 0.0274755004793406 + -0.3073608875274658 + <_> + + <_> + + + + <_> + 12 3 6 6 -1. + <_> + 10 5 6 2 3. + 1 + -0.0755213573575020 + -0.4241931140422821 + 0.0237817000597715 + <_> + + <_> + + + + <_> + 12 9 10 6 -1. + <_> + 12 9 5 6 2. + 0 + 0.0243982393294573 + -0.0493879318237305 + 0.1672402024269104 + <_> + + <_> + + + + <_> + 3 9 10 6 -1. + <_> + 8 9 5 6 2. + 0 + 0.1157704964280129 + 0.0166440103203058 + -0.6928011178970337 + <_> + + <_> + + + + <_> + 12 0 4 1 -1. + <_> + 13 0 2 1 2. + 0 + 9.1529998462647200e-004 + -0.0502800084650517 + 0.1328525990247726 + <_> + + <_> + + + + <_> + 3 10 4 1 -1. + <_> + 4 11 2 1 2. + 1 + -3.6248450633138418e-003 + -0.3066833913326263 + 0.0284923594444990 + <_> + + <_> + + + + <_> + 18 12 1 2 -1. + <_> + 18 12 1 1 2. + 1 + -7.3581631295382977e-004 + 0.0559885688126087 + -0.0392797887325287 + <_> + + <_> + + + + <_> + 2 0 20 10 -1. + <_> + 12 0 10 10 2. + 0 + 0.2000436931848526 + -0.0568408109247684 + 0.1685038954019547 + <_> + + <_> + + + + <_> + 22 2 3 6 -1. + <_> + 23 3 1 6 3. + 1 + -0.0178776904940605 + 0.1931751966476440 + -0.0514639392495155 + <_> + + <_> + + + + <_> + 3 2 6 3 -1. + <_> + 2 3 6 1 3. + 1 + 0.0113503802567720 + -0.0489644110202789 + 0.2181939035654068 + <_> + + <_> + + + + <_> + 21 1 4 6 -1. + <_> + 23 1 2 3 2. + <_> + 21 4 2 3 2. + 0 + 0.0125029096379876 + -0.0419848784804344 + 0.2713862061500549 + <_> + + <_> + + + + <_> + 0 1 4 6 -1. + <_> + 0 1 2 3 2. + <_> + 2 4 2 3 2. + 0 + -9.3033276498317719e-003 + 0.1590452045202255 + -0.0626974031329155 + <_> + + <_> + + + + <_> + 24 0 1 6 -1. + <_> + 24 3 1 3 2. + 0 + 9.8205171525478363e-003 + 0.0155331101268530 + -0.3304075896739960 + <_> + + <_> + + + + <_> + 0 0 1 6 -1. + <_> + 0 3 1 3 2. + 0 + 4.4993069022893906e-003 + 0.0376702398061752 + -0.3112137019634247 + <_> + + <_> + + + + <_> + 18 0 6 6 -1. + <_> + 18 2 6 2 3. + 0 + 0.0140464501455426 + -0.0434262491762638 + 0.1032719984650612 + <_> + + <_> + + + + <_> + 5 1 15 4 -1. + <_> + 5 2 15 2 2. + 0 + -0.0411175191402435 + 0.1867991983890533 + -0.0664343684911728 + <_> + + <_> + + + + <_> + 4 8 18 1 -1. + <_> + 10 8 6 1 3. + 0 + -0.0107145197689533 + 0.1244383975863457 + -0.0663585364818573 + <_> + + <_> + + + + <_> + 8 6 6 4 -1. + <_> + 8 7 6 2 2. + 0 + 9.2895422130823135e-003 + -0.0821698531508446 + 0.1224353983998299 + <_> + + <_> + + + + <_> + 9 5 8 2 -1. + <_> + 11 5 4 2 2. + 0 + -0.0130508001893759 + -0.4003388881683350 + 0.0166369099169970 + <_> + + <_> + + + + <_> + 5 0 6 6 -1. + <_> + 7 0 2 6 3. + 0 + -0.0364681892096996 + -0.5473737716674805 + 0.0148177295923233 + <_> + + <_> + + + + <_> + 21 8 2 1 -1. + <_> + 21 8 1 1 2. + 0 + -7.5372940045781434e-005 + 0.0594716407358646 + -0.0578790009021759 + <_> + + <_> + + + + <_> + 7 1 2 2 -1. + <_> + 7 1 2 1 2. + 1 + 0.0142522901296616 + 0.0252972692251205 + -0.3336473107337952 + <_> + + <_> + + + + <_> + 17 4 8 4 -1. + <_> + 17 5 8 2 2. + 0 + 3.3469200134277344e-003 + -0.0707368031144142 + 0.0745013207197189 + <_> + + <_> + + + + <_> + 6 0 13 2 -1. + <_> + 6 1 13 1 2. + 0 + 4.4445958919823170e-003 + -0.0672459527850151 + 0.1451885998249054 + <_> + + <_> + + + + <_> + 21 5 4 6 -1. + <_> + 21 7 4 2 3. + 0 + -8.7205823510885239e-003 + -0.2021352946758270 + 0.0275202393531799 + <_> + + <_> + + + + <_> + 0 5 4 6 -1. + <_> + 0 7 4 2 3. + 0 + 0.0469216890633106 + 0.0161568503826857 + -0.5311927795410156 + <_> + + <_> + + + + <_> + 21 8 2 1 -1. + <_> + 21 8 1 1 2. + 0 + 5.8387980971019715e-005 + -0.0557161718606949 + 0.0720106214284897 + <_> + + <_> + + + + <_> + 2 8 2 1 -1. + <_> + 3 8 1 1 2. + 0 + -4.6103101340122521e-005 + 0.0959030091762543 + -0.0971473827958107 + <_> + + <_> + + + + <_> + 23 0 2 1 -1. + <_> + 23 0 1 1 2. + 1 + 6.0657761059701443e-003 + 0.0240712091326714 + -0.2376091033220291 + <_> + + <_> + + + + <_> + 4 0 15 4 -1. + <_> + 4 1 15 2 2. + 0 + -0.0555203706026077 + 0.3074511885643005 + -0.0299711804836988 + <_> + + <_> + + + + <_> + 15 1 10 8 -1. + <_> + 15 3 10 4 2. + 0 + -0.0365539006888866 + 0.0328120291233063 + -0.0570152215659618 + <_> + + <_> + + + + <_> + 0 5 4 2 -1. + <_> + 0 5 2 1 2. + <_> + 2 6 2 1 2. + 0 + 1.8784699495881796e-003 + -0.0653261989355087 + 0.1390983015298843 + <_> + + <_> + + + + <_> + 23 0 2 1 -1. + <_> + 23 0 1 1 2. + 1 + -7.4822120368480682e-003 + -0.7748216986656189 + 5.9286328032612801e-003 + <_> + + <_> + + + + <_> + 0 5 1 4 -1. + <_> + 0 6 1 2 2. + 0 + -3.3365150447934866e-003 + -0.3616085052490234 + 0.0226737502962351 + <_> + + <_> + + + + <_> + 19 13 4 2 -1. + <_> + 19 14 4 1 2. + 0 + -0.0122549999505281 + -0.6580218076705933 + 4.3241591192781925e-003 + <_> + + <_> + + + + <_> + 7 12 2 2 -1. + <_> + 7 12 1 1 2. + <_> + 8 13 1 1 2. + 0 + -2.5022740010172129e-004 + 0.1368491053581238 + -0.0613101907074451 + <_> + + <_> + + + + <_> + 1 0 24 8 -1. + <_> + 13 0 12 4 2. + <_> + 1 4 12 4 2. + 0 + 0.1189583986997604 + 0.0244670100510120 + -0.3081929087638855 + <_> + + <_> + + + + <_> + 2 4 3 3 -1. + <_> + 2 5 3 1 3. + 0 + 1.8534749979153275e-003 + -0.0657177790999413 + 0.1380506008863449 + <_> + + <_> + + + + <_> + 20 6 4 3 -1. + <_> + 19 7 4 1 3. + 1 + -0.0139663796871901 + -0.4281671941280365 + 0.0166652500629425 + <_> + + <_> + + + + <_> + 5 6 3 4 -1. + <_> + 6 7 1 4 3. + 1 + -0.0120118902996182 + -0.4546675086021423 + 0.0174813903868198 + <_> + + <_> + + + + <_> + 16 11 2 2 -1. + <_> + 17 11 1 1 2. + <_> + 16 12 1 1 2. + 0 + 8.6380320135504007e-004 + 0.0268306396901608 + -0.1949577033519745 + <_> + + <_> + + + + <_> + 7 11 2 2 -1. + <_> + 7 11 1 1 2. + <_> + 8 12 1 1 2. + 0 + -5.4863549303263426e-004 + 0.1728172004222870 + -0.0519250482320786 + <_> + + <_> + + + + <_> + 9 5 9 3 -1. + <_> + 12 5 3 3 3. + 0 + 0.0356420204043388 + 0.0119973402470350 + -0.2636224925518036 + <_> + + <_> + + + + <_> + 0 0 6 1 -1. + <_> + 2 0 2 1 3. + 0 + 9.2830741778016090e-003 + 0.0153813296929002 + -0.5276867151260376 + <_> + + <_> + + + + <_> + 17 4 8 1 -1. + <_> + 19 4 4 1 2. + 0 + 3.3444799482822418e-003 + -0.0448165088891983 + 0.1556369960308075 + <_> + + <_> + + + + <_> + 7 5 9 3 -1. + <_> + 10 5 3 3 3. + 0 + -0.0348524898290634 + -0.6144651770591736 + 0.0147144095972180 + <_> + + <_> + + + + <_> + 17 4 8 1 -1. + <_> + 19 4 4 1 2. + 0 + -3.6836538929492235e-003 + 0.0679996237158775 + -0.0403181910514832 + <_> + + <_> + + + + <_> + 0 4 8 1 -1. + <_> + 2 4 4 1 2. + 0 + 2.6370671112090349e-003 + -0.0527165904641151 + 0.1650273054838181 + <_> + + <_> + + + + <_> + 16 11 2 2 -1. + <_> + 17 11 1 1 2. + <_> + 16 12 1 1 2. + 0 + -1.1408380232751369e-003 + -0.1495666950941086 + 0.0155292097479105 + <_> + + <_> + + + + <_> + 6 11 12 2 -1. + <_> + 9 11 6 2 2. + 0 + -5.5604642257094383e-003 + 0.1015162020921707 + -0.0783084183931351 + <_> + + <_> + + + + <_> + 4 6 20 9 -1. + <_> + 9 6 10 9 2. + 0 + 0.0313040204346180 + -0.0519621782004833 + 0.1036399006843567 + <_> + + <_> + + + + <_> + 6 8 12 2 -1. + <_> + 6 9 12 1 2. + 0 + 9.2903850600123405e-003 + -0.0539887212216854 + 0.1653061956167221 + <_> + + <_> + + + + <_> + 6 8 13 4 -1. + <_> + 6 9 13 2 2. + 0 + -0.0108930300921202 + 0.1281013935804367 + -0.0734129622578621 + <_> + + <_> + + + + <_> + 2 13 4 2 -1. + <_> + 2 14 4 1 2. + 0 + -4.9190609715878963e-003 + -0.3507530987262726 + 0.0244891606271267 + <_> + + <_> + + + + <_> + 11 1 3 12 -1. + <_> + 11 4 3 6 2. + 0 + 0.0811754167079926 + 0.0209406390786171 + -0.3776533007621765 + <_> + + <_> + + + + <_> + 7 10 11 4 -1. + <_> + 7 11 11 2 2. + 0 + -7.1189319714903831e-003 + 0.1320966929197311 + -0.0743796005845070 + <_> + + <_> + + + + <_> + 5 9 15 6 -1. + <_> + 5 11 15 2 3. + 0 + 0.0290335901081562 + -0.0601534284651279 + 0.1686525046825409 + <_> + + <_> + + + + <_> + 1 5 14 10 -1. + <_> + 1 10 14 5 2. + 0 + 0.2666859030723572 + 0.0302151106297970 + -0.3336375057697296 + <_> + + <_> + + + + <_> + 13 10 2 2 -1. + <_> + 14 10 1 1 2. + <_> + 13 11 1 1 2. + 0 + 1.3437710003927350e-003 + 0.0244619604200125 + -0.3497652113437653 + <_> + + <_> + + + + <_> + 0 0 4 2 -1. + <_> + 0 1 4 1 2. + 0 + -6.4065970946103334e-005 + 0.0681859701871872 + -0.1218236982822418 + <_> + + <_> + + + + <_> + 18 3 4 2 -1. + <_> + 18 4 4 1 2. + 0 + -2.2273659706115723e-003 + 0.0591664388775826 + -0.0569609887897968 + <_> + + <_> + + + + <_> + 0 7 4 4 -1. + <_> + 0 8 4 2 2. + 0 + 1.0822839976754040e-004 + -0.1183675006031990 + 0.0699028074741364 + <_> + + <_> + + + + <_> + 12 12 6 2 -1. + <_> + 14 12 2 2 3. + 0 + 7.7762501314282417e-003 + 0.0182663407176733 + -0.3238837122917175 + <_> + + <_> + + + + <_> + 7 0 3 1 -1. + <_> + 8 0 1 1 3. + 0 + -8.5627898806706071e-004 + 0.1596496999263763 + -0.0523401089012623 + <_> + + <_> + + + + <_> + 15 0 2 1 -1. + <_> + 15 0 1 1 2. + 0 + 3.9805951528251171e-003 + 5.6993248872458935e-003 + -0.6384922862052918 + <_> + + <_> + + + + <_> + 8 0 2 1 -1. + <_> + 9 0 1 1 2. + 0 + -4.9052381655201316e-004 + 0.1629474014043808 + -0.0742301419377327 + <_> + + <_> + + + + <_> + 18 3 2 10 -1. + <_> + 18 3 1 10 2. + 0 + -0.0184035003185272 + -0.6773443222045898 + 0.0107059404253960 + <_> + + <_> + + + + <_> + 7 1 2 2 -1. + <_> + 7 1 1 1 2. + <_> + 8 2 1 1 2. + 0 + -8.9714571367949247e-004 + 0.1691973060369492 + -0.0477185398340225 + <_> + + <_> + + + + <_> + 18 0 7 3 -1. + <_> + 18 1 7 1 3. + 0 + -0.0167341101914644 + -0.3151237964630127 + 0.0124420495703816 + <_> + + <_> + + + + <_> + 7 12 6 2 -1. + <_> + 9 12 2 2 3. + 0 + -0.0119769899174571 + -0.5293223857879639 + 0.0144362701103091 + <_> + + <_> + + + + <_> + 20 7 4 3 -1. + <_> + 20 8 4 1 3. + 0 + 7.0368088781833649e-003 + 0.0264915898442268 + -0.2470992058515549 + <_> + + <_> + + + + <_> + 5 3 2 10 -1. + <_> + 6 3 1 10 2. + 0 + -0.0105798998847604 + -0.4092808067798615 + 0.0187591798603535 + <_> + + <_> + + + + <_> + 16 0 2 2 -1. + <_> + 17 0 1 1 2. + <_> + 16 1 1 1 2. + 0 + 6.0849997680634260e-004 + -0.0334094502031803 + 0.0843884497880936 + <_> + + <_> + + + + <_> + 7 0 2 2 -1. + <_> + 7 0 1 1 2. + <_> + 8 1 1 1 2. + 0 + -5.9445307124406099e-004 + 0.1412419974803925 + -0.0555582903325558 + <_> + + <_> + + + + <_> + 15 0 6 2 -1. + <_> + 17 0 2 2 3. + 0 + -0.0157594103366137 + -0.3833500146865845 + 0.0156633593142033 + <_> + + <_> + + + + <_> + 0 0 1 4 -1. + <_> + 0 2 1 2 2. + 0 + -0.0101080304011703 + -0.3391439020633698 + 0.0209970101714134 + <_> + + <_> + + + + <_> + 22 1 2 12 -1. + <_> + 18 5 2 4 3. + 1 + 8.8242385536432266e-003 + 0.0468829013407230 + -0.0345581099390984 + <_> + + <_> + + + + <_> + 4 0 12 3 -1. + <_> + 8 4 4 3 3. + 1 + 0.1695280969142914 + -0.0297883804887533 + 0.2978200018405914 + <_> + + <_> + + + + <_> + 14 13 2 2 -1. + <_> + 15 13 1 1 2. + <_> + 14 14 1 1 2. + 0 + 1.4175090473145247e-003 + 0.0145506802946329 + -0.2557711899280548 + <_> + + <_> + + + + <_> + 11 6 3 3 -1. + <_> + 12 7 1 1 9. + 0 + -6.2455357983708382e-003 + 0.1703144013881683 + -0.0457185097038746 + <_> + + <_> + + + + <_> + 15 1 10 8 -1. + <_> + 15 3 10 4 2. + 0 + 0.0829719901084900 + -0.0108856502920389 + 0.2358570992946625 + <_> + + <_> + + + + <_> + 0 1 10 8 -1. + <_> + 0 3 10 4 2. + 0 + -0.0363879613578320 + 0.0720635578036308 + -0.1351491957902908 + <_> + + <_> + + + + <_> + 11 3 14 10 -1. + <_> + 11 8 14 5 2. + 0 + 0.2605817019939423 + 0.0307604894042015 + -0.2081860005855560 + <_> + + <_> + + + + <_> + 0 0 24 12 -1. + <_> + 0 0 12 6 2. + <_> + 12 6 12 6 2. + 0 + -0.1837086975574493 + -0.4619984030723572 + 0.0176900699734688 + <_> + + <_> + + + + <_> + 20 7 4 3 -1. + <_> + 20 8 4 1 3. + 0 + -3.9726989343762398e-003 + -0.1660892963409424 + 0.0209467206150293 + <_> + + <_> + + + + <_> + 0 1 7 3 -1. + <_> + 0 2 7 1 3. + 0 + 0.0214559100568295 + 0.0231478307396173 + -0.3625465929508209 + <_> + + <_> + + + + <_> + 20 7 4 3 -1. + <_> + 20 8 4 1 3. + 0 + 0.0144318202510476 + 4.4689280912280083e-003 + -0.2445929050445557 + <_> + + <_> + + + + <_> + 0 7 1 8 -1. + <_> + 0 9 1 4 2. + 0 + -3.3524229656904936e-003 + -0.2480840981006622 + 0.0316352993249893 + <_> + + <_> + + + + <_> + 22 4 3 4 -1. + <_> + 23 5 1 4 3. + 1 + -0.0156694706529379 + 0.3172483146190643 + -0.0374899208545685 + <_> + + <_> + + + + <_> + 11 2 12 1 -1. + <_> + 15 6 4 1 3. + 1 + -0.0400774292647839 + -0.2589775919914246 + 0.0327349714934826 + <_> + + <_> + + + + <_> + 22 4 3 4 -1. + <_> + 23 5 1 4 3. + 1 + 0.0123612098395824 + -0.0450748614966869 + 0.1690649986267090 + <_> + + <_> + + + + <_> + 1 7 4 3 -1. + <_> + 1 8 4 1 3. + 0 + 0.0109678898006678 + 0.0187921095639467 + -0.4384852945804596 + <_> + + <_> + + + + <_> + 13 9 6 2 -1. + <_> + 15 9 2 2 3. + 0 + -0.0137434704229236 + -0.4609765112400055 + 0.0122369602322578 + <_> + + <_> + + + + <_> + 6 7 2 2 -1. + <_> + 6 7 1 1 2. + <_> + 7 8 1 1 2. + 0 + -1.0322439484298229e-003 + 0.1648599952459335 + -0.0516587682068348 + <_> + + <_> + + + + <_> + 13 9 6 2 -1. + <_> + 15 9 2 2 3. + 0 + 8.8313361629843712e-003 + 0.0159355308860540 + -0.2015953958034515 + <_> + + <_> + + + + <_> + 4 0 6 2 -1. + <_> + 6 0 2 2 3. + 0 + 0.0144206797704101 + 0.0160773508250713 + -0.4641633033752441 + <_> + + <_> + + + + <_> + 13 9 6 2 -1. + <_> + 15 9 2 2 3. + 0 + -1.8205989617854357e-003 + 0.0433134213089943 + -0.0280837193131447 + <_> + + <_> + + + + <_> + 7 7 2 6 -1. + <_> + 7 7 1 6 2. + 1 + 3.9304671809077263e-003 + 0.0497011989355087 + -0.1514773964881897 + <_> + + <_> + + + + <_> + 24 0 1 10 -1. + <_> + 24 5 1 5 2. + 0 + -8.3210691809654236e-003 + -0.1029928028583527 + 0.0179813895374537 + <_> + + <_> + + + + <_> + 6 7 3 1 -1. + <_> + 7 7 1 1 3. + 0 + -1.1277500307187438e-003 + 0.1659521013498306 + -0.0483443103730679 + <_> + + <_> + + + + <_> + 14 13 2 2 -1. + <_> + 15 13 1 1 2. + <_> + 14 14 1 1 2. + 0 + -7.8385067172348499e-004 + -0.1946461051702499 + 0.0250845197588205 + <_> + + <_> + + + + <_> + 8 7 4 1 -1. + <_> + 9 7 2 1 2. + 0 + -8.5464341100305319e-004 + 0.1473073959350586 + -0.0529893897473812 + <_> + + <_> + + + + <_> + 24 4 1 9 -1. + <_> + 21 7 1 3 3. + 1 + -6.1449417844414711e-003 + 0.0951583385467529 + -0.0323545187711716 + <_> + + <_> + + + + <_> + 1 4 9 1 -1. + <_> + 4 7 3 1 3. + 1 + 0.0537422299385071 + -0.0160139091312885 + 0.5178387761116028 + <_> + + <_> + + + + <_> + 11 1 6 13 -1. + <_> + 13 1 2 13 3. + 0 + -9.1773690655827522e-003 + 0.0658730715513229 + -0.0286986008286476 + <_> + + <_> + + + + <_> + 10 2 4 7 -1. + <_> + 11 2 2 7 2. + 0 + -1.6262140125036240e-003 + 0.1165013015270233 + -0.0662005692720413 + <_> + + <_> + + + + <_> + 11 1 6 13 -1. + <_> + 13 1 2 13 3. + 0 + -0.0702467709779739 + -0.5561671257019043 + 3.3650770783424377e-003 + <_> + + <_> + + + + <_> + 8 1 6 13 -1. + <_> + 10 1 2 13 3. + 0 + -0.0457130484282970 + -0.5554363131523132 + 0.0145238302648067 + <_> + + <_> + + + + <_> + 16 9 4 1 -1. + <_> + 16 9 2 1 2. + 0 + -1.6252630157396197e-003 + 0.0774459466338158 + -0.0477535910904408 + <_> + + <_> + + + + <_> + 5 9 4 1 -1. + <_> + 7 9 2 1 2. + 0 + -8.7784547358751297e-003 + -0.6660557985305786 + 0.0114997997879982 + <_> + + <_> + + + + <_> + 17 4 1 9 -1. + <_> + 14 7 1 3 3. + 1 + 0.0581780597567558 + -0.0126901902258396 + 0.2431164979934692 + <_> + + <_> + + + + <_> + 7 4 2 2 -1. + <_> + 7 4 1 1 2. + <_> + 8 5 1 1 2. + 0 + -1.0166700230911374e-003 + 0.1701835989952087 + -0.0434626787900925 + <_> + + <_> + + + + <_> + 13 9 2 2 -1. + <_> + 14 9 1 1 2. + <_> + 13 10 1 1 2. + 0 + -8.3186908159404993e-004 + -0.1554417014122009 + 0.0277679692953825 + <_> + + <_> + + + + <_> + 7 11 2 2 -1. + <_> + 7 11 1 1 2. + <_> + 8 12 1 1 2. + 0 + 1.0635660146363080e-004 + -0.0799610763788223 + 0.0975525230169296 + <_> + + <_> + + + + <_> + 13 9 2 2 -1. + <_> + 14 9 1 1 2. + <_> + 13 10 1 1 2. + 0 + 7.7358598355203867e-004 + 0.0280197393149138 + -0.1640979051589966 + <_> + + <_> + + + + <_> + 6 13 10 1 -1. + <_> + 11 13 5 1 2. + 0 + -5.1288288086652756e-003 + 0.1435500979423523 + -0.0521811507642269 + <_> + + <_> + + + + <_> + 9 8 10 7 -1. + <_> + 9 8 5 7 2. + 0 + -0.0296237897127867 + 0.1256711930036545 + -0.0727018266916275 + <_> + + <_> + + + + <_> + 4 5 15 10 -1. + <_> + 9 5 5 10 3. + 0 + 0.0479203201830387 + -0.0627507865428925 + 0.1496749967336655 + <_> + + <_> + + + + <_> + 20 6 5 4 -1. + <_> + 20 7 5 2 2. + 0 + 0.0299077890813351 + 3.3279890194535255e-003 + -0.5352283716201782 + <_> + + <_> + + + + <_> + 0 6 5 4 -1. + <_> + 0 7 5 2 2. + 0 + -3.1103161163628101e-003 + -0.1846338063478470 + 0.0402609407901764 + <_> + + <_> + + + + <_> + 11 7 3 1 -1. + <_> + 12 7 1 1 3. + 0 + 1.1777599574998021e-003 + -0.0421488806605339 + 0.1833201944828033 + <_> + + <_> + + + + <_> + 9 4 7 3 -1. + <_> + 9 5 7 1 3. + 0 + 0.0149721698835492 + -0.0501780100166798 + 0.1479559987783432 + <_> + + <_> + + + + <_> + 15 4 4 3 -1. + <_> + 15 4 2 3 2. + 0 + 0.0226974897086620 + 8.8858045637607574e-003 + -0.3510260879993439 + <_> + + <_> + + + + <_> + 6 4 4 3 -1. + <_> + 8 4 2 3 2. + 0 + 0.0128841297701001 + 0.0346549116075039 + -0.2406193017959595 + <_> + + <_> + + + + <_> + 16 6 2 2 -1. + <_> + 17 6 1 1 2. + <_> + 16 7 1 1 2. + 0 + -1.1240700259804726e-003 + 0.1314530968666077 + -0.0288430396467447 + <_> + + <_> + + + + <_> + 7 6 2 2 -1. + <_> + 7 6 1 1 2. + <_> + 8 7 1 1 2. + 0 + -1.3627869775518775e-003 + 0.2013843953609467 + -0.0379555486142635 + <_> + + <_> + + + + <_> + 14 13 2 2 -1. + <_> + 15 13 1 1 2. + <_> + 14 14 1 1 2. + 0 + 5.3557957289740443e-004 + 0.0279592797160149 + -0.1196514964103699 + <_> + + <_> + + + + <_> + 6 0 4 2 -1. + <_> + 6 0 4 1 2. + 1 + -0.0152801796793938 + -0.4851869940757752 + 0.0156223699450493 + <_> + + <_> + + + + <_> + 20 14 2 1 -1. + <_> + 20 14 1 1 2. + 0 + 4.6412500523729250e-005 + -0.0589389093220234 + 0.0601089298725128 + <_> + + <_> + + + + <_> + 1 13 6 2 -1. + <_> + 1 13 3 1 2. + <_> + 4 14 3 1 2. + 0 + 9.6553878393024206e-005 + -0.0965948700904846 + 0.0779175236821175 + <_> + + <_> + + + + <_> + 12 1 2 2 -1. + <_> + 12 2 2 1 2. + 0 + 3.8991239853203297e-003 + -0.0261822007596493 + 0.1902385950088501 + <_> + + <_> + + + + <_> + 8 0 8 8 -1. + <_> + 8 0 4 4 2. + <_> + 12 4 4 4 2. + 0 + 0.0237854700535536 + 0.0403596796095371 + -0.1793317049741745 + <_> + + <_> + + + + <_> + 16 12 2 2 -1. + <_> + 17 12 1 1 2. + <_> + 16 13 1 1 2. + 0 + 5.9117228374816477e-005 + -0.0676945373415947 + 0.0789666101336479 + <_> + + <_> + + + + <_> + 0 4 8 8 -1. + <_> + 0 4 4 4 2. + <_> + 4 8 4 4 2. + 0 + 0.0585355199873447 + -0.0279133208096027 + 0.2635962069034576 + <_> + + <_> + + + + <_> + 19 4 2 1 -1. + <_> + 19 4 1 1 2. + 0 + -6.7125670611858368e-003 + -0.8246011137962341 + 3.6960430443286896e-003 + <_> + + <_> + + + + <_> + 4 4 2 1 -1. + <_> + 5 4 1 1 2. + 0 + -4.6747662127017975e-003 + -0.7625464797019959 + 9.2743840068578720e-003 + <_> + + <_> + + + + <_> + 20 0 2 2 -1. + <_> + 21 0 1 1 2. + <_> + 20 1 1 1 2. + 0 + 5.3981528617441654e-003 + 1.9147379789501429e-003 + -0.8057739734649658 + <_> + + <_> + + + + <_> + 0 5 15 3 -1. + <_> + 0 6 15 1 3. + 0 + 7.7252141200006008e-003 + -0.0822006091475487 + 0.0925986021757126 + <_> + + <_> + + + + <_> + 13 5 1 3 -1. + <_> + 13 6 1 1 3. + 0 + -1.1672140099108219e-003 + 0.1147938966751099 + -0.0459650196135044 + <_> + + <_> + + + + <_> + 4 9 3 2 -1. + <_> + 5 10 1 2 3. + 1 + -7.4022258631885052e-003 + -0.4262216091156006 + 0.0174518898129463 + <_> + + <_> + + + + <_> + 20 0 2 2 -1. + <_> + 21 0 1 1 2. + <_> + 20 1 1 1 2. + 0 + 6.5430802351329476e-005 + -0.0445476993918419 + 0.0498182512819767 + <_> + + <_> + + + + <_> + 3 0 2 2 -1. + <_> + 3 0 1 1 2. + <_> + 4 1 1 1 2. + 0 + 4.6353430661838502e-005 + -0.0820099934935570 + 0.0922331288456917 + -1.2964390516281128 + 14 + -1 + <_> + + + <_> + + <_> + + + + <_> + 0 11 12 4 -1. + <_> + 0 11 6 2 2. + <_> + 6 13 6 2 2. + 0 + 0.0105607798323035 + -0.1728546023368835 + 0.2072951048612595 + <_> + + <_> + + + + <_> + 17 1 8 4 -1. + <_> + 17 3 8 2 2. + 0 + -0.0382373891770840 + 0.1771112978458405 + -0.1585303992033005 + <_> + + <_> + + + + <_> + 6 6 13 6 -1. + <_> + 6 8 13 2 3. + 0 + -0.0541206710040569 + 0.2564443051815033 + -0.0884335711598396 + <_> + + <_> + + + + <_> + 23 4 2 3 -1. + <_> + 23 4 1 3 2. + 0 + -2.2004460915923119e-003 + 0.2010346055030823 + -0.1101640984416008 + <_> + + <_> + + + + <_> + 2 13 10 2 -1. + <_> + 2 14 10 1 2. + 0 + 0.0654388666152954 + 7.8213139204308391e-004 + -4.3508232421875000e+003 + <_> + + <_> + + + + <_> + 23 4 2 3 -1. + <_> + 23 4 1 3 2. + 0 + -0.0135645801201463 + -0.5407810807228088 + 4.8653590492904186e-003 + <_> + + <_> + + + + <_> + 0 4 2 3 -1. + <_> + 1 4 1 3 2. + 0 + -1.8708320567384362e-003 + 0.1633561998605728 + -0.1228590980172157 + <_> + + <_> + + + + <_> + 2 7 21 3 -1. + <_> + 9 8 7 1 9. + 0 + 0.1699268966913223 + -4.5410599559545517e-003 + 0.4810850024223328 + <_> + + <_> + + + + <_> + 2 11 2 2 -1. + <_> + 2 11 1 2 2. + 1 + 3.5981500986963511e-003 + 0.0356757305562496 + -0.4236158132553101 + <_> + + <_> + + + + <_> + 2 2 21 6 -1. + <_> + 9 4 7 2 9. + 0 + 0.5448976159095764 + -0.0198735594749451 + 0.5460472106933594 + <_> + + <_> + + + + <_> + 1 1 8 6 -1. + <_> + 1 3 8 2 3. + 0 + -0.0627753064036369 + 0.1722137033939362 + -0.1143800020217896 + <_> + + <_> + + + + <_> + 6 4 15 4 -1. + <_> + 6 5 15 2 2. + 0 + -0.0459444113075733 + 0.2595784068107605 + -0.0732216089963913 + <_> + + <_> + + + + <_> + 2 10 4 1 -1. + <_> + 3 11 2 1 2. + 1 + 2.1809421014040709e-003 + 0.0495434813201427 + -0.3175086975097656 + <_> + + <_> + + + + <_> + 4 14 18 1 -1. + <_> + 4 14 9 1 2. + 0 + -9.6566081047058105e-003 + 0.1581763029098511 + -0.0890468433499336 + <_> + + <_> + + + + <_> + 0 3 24 10 -1. + <_> + 0 3 12 5 2. + <_> + 12 8 12 5 2. + 0 + 0.0808042436838150 + 0.0503276288509369 + -0.2887117862701416 + <_> + + <_> + + + + <_> + 15 3 10 12 -1. + <_> + 20 3 5 6 2. + <_> + 15 9 5 6 2. + 0 + 0.0987789332866669 + -0.0381883382797241 + 0.3119831085205078 + <_> + + <_> + + + + <_> + 9 5 6 3 -1. + <_> + 9 6 6 1 3. + 0 + 8.4114018827676773e-003 + -0.0949936509132385 + 0.1344850063323975 + <_> + + <_> + + + + <_> + 2 13 21 1 -1. + <_> + 9 13 7 1 3. + 0 + -0.0147700998932123 + 0.1715719997882843 + -0.0750405564904213 + <_> + + <_> + + + + <_> + 0 3 10 12 -1. + <_> + 0 3 5 6 2. + <_> + 5 9 5 6 2. + 0 + 0.1057564020156860 + -0.0440231785178185 + 0.3495194017887116 + <_> + + <_> + + + + <_> + 5 3 15 4 -1. + <_> + 5 4 15 2 2. + 0 + 0.0401043891906738 + -0.0572791509330273 + 0.2763915061950684 + <_> + + <_> + + + + <_> + 8 6 9 3 -1. + <_> + 8 7 9 1 3. + 0 + 0.0135993398725986 + -0.0886402428150177 + 0.1596630066633225 + <_> + + <_> + + + + <_> + 14 13 3 1 -1. + <_> + 15 13 1 1 3. + 0 + -3.3378789667040110e-003 + -0.4990870058536530 + 7.1760369464755058e-003 + <_> + + <_> + + + + <_> + 7 1 10 2 -1. + <_> + 7 2 10 1 2. + 0 + 6.5490198321640491e-003 + -0.0597806982696056 + 0.2110590040683746 + <_> + + <_> + + + + <_> + 14 13 3 1 -1. + <_> + 15 13 1 1 3. + 0 + -6.2758670537732542e-005 + 0.0655476525425911 + -0.0541992485523224 + <_> + + <_> + + + + <_> + 8 13 3 1 -1. + <_> + 9 13 1 1 3. + 0 + 9.0889551211148500e-004 + 0.0425700992345810 + -0.2828716039657593 + <_> + + <_> + + + + <_> + 1 0 24 12 -1. + <_> + 13 0 12 6 2. + <_> + 1 6 12 6 2. + 0 + 0.0881031826138496 + 0.0406627096235752 + -0.2983728945255280 + <_> + + <_> + + + + <_> + 0 0 13 14 -1. + <_> + 0 7 13 7 2. + 0 + -0.1351538002490997 + -0.4011076092720032 + 0.0259989295154810 + <_> + + <_> + + + + <_> + 21 6 3 3 -1. + <_> + 20 7 3 1 3. + 1 + 0.0105496803298593 + 0.0265602301806211 + -0.3554666042327881 + <_> + + <_> + + + + <_> + 8 9 8 4 -1. + <_> + 8 10 8 2 2. + 0 + -0.0109745198860765 + 0.1540209054946899 + -0.0715849623084068 + <_> + + <_> + + + + <_> + 13 10 6 4 -1. + <_> + 15 10 2 4 3. + 0 + -0.0128105496987700 + -0.2680475115776062 + 0.0205432493239641 + <_> + + <_> + + + + <_> + 11 3 4 4 -1. + <_> + 11 3 2 4 2. + 1 + -0.0673751235008240 + -0.5299177169799805 + 0.0192500203847885 + <_> + + <_> + + + + <_> + 13 10 6 4 -1. + <_> + 15 10 2 4 3. + 0 + 0.0133285904303193 + 0.0141924796625972 + -0.2692896127700806 + <_> + + <_> + + + + <_> + 7 10 10 4 -1. + <_> + 7 12 10 2 2. + 0 + -0.0349247902631760 + 0.2877762019634247 + -0.0366922505199909 + <_> + + <_> + + + + <_> + 13 10 6 4 -1. + <_> + 15 10 2 4 3. + 0 + -0.0259607005864382 + -0.5250588059425354 + 4.2013241909444332e-003 + <_> + + <_> + + + + <_> + 6 10 6 4 -1. + <_> + 8 10 2 4 3. + 0 + -0.0144326100125909 + -0.4404621124267578 + 0.0239412691444159 + <_> + + <_> + + + + <_> + 21 14 4 1 -1. + <_> + 21 14 2 1 2. + 0 + 1.0242980206385255e-003 + -0.0813294127583504 + 0.1090075969696045 + <_> + + <_> + + + + <_> + 0 7 4 4 -1. + <_> + 0 8 4 2 2. + 0 + -3.3913699444383383e-003 + -0.2744260132312775 + 0.0353980511426926 + <_> + + <_> + + + + <_> + 19 3 6 12 -1. + <_> + 22 3 3 6 2. + <_> + 19 9 3 6 2. + 0 + -0.0254591107368469 + 0.1884281933307648 + -0.0505212917923927 + <_> + + <_> + + + + <_> + 5 1 15 2 -1. + <_> + 5 2 15 1 2. + 0 + -0.0250639300793409 + 0.1583306044340134 + -0.0679820179939270 + <_> + + <_> + + + + <_> + 19 1 3 4 -1. + <_> + 19 2 3 2 2. + 0 + 4.5757358893752098e-003 + -0.0512838996946812 + 0.1146584972739220 + <_> + + <_> + + + + <_> + 2 5 20 4 -1. + <_> + 12 5 10 4 2. + 0 + -0.1538352966308594 + 0.4274145960807800 + -0.0233538504689932 + <_> + + <_> + + + + <_> + 21 14 4 1 -1. + <_> + 21 14 2 1 2. + 0 + 6.7441980354487896e-003 + 0.0116364201530814 + -0.1990616023540497 + <_> + + <_> + + + + <_> + 0 14 4 1 -1. + <_> + 2 14 2 1 2. + 0 + 4.9857632257044315e-004 + -0.1112217977643013 + 0.0913273170590401 + <_> + + <_> + + + + <_> + 19 3 6 12 -1. + <_> + 22 3 3 6 2. + <_> + 19 9 3 6 2. + 0 + 0.0416502095758915 + -0.0342307090759277 + 0.1340909004211426 + <_> + + <_> + + + + <_> + 0 3 6 12 -1. + <_> + 0 3 3 6 2. + <_> + 3 9 3 6 2. + 0 + -0.0486865788698196 + 0.3840608894824982 + -0.0367092713713646 + <_> + + <_> + + + + <_> + 19 1 3 4 -1. + <_> + 19 2 3 2 2. + 0 + -0.0142661100253463 + 0.1904101967811585 + -0.0373262614011765 + <_> + + <_> + + + + <_> + 3 1 3 4 -1. + <_> + 3 2 3 2 2. + 0 + 2.0738251041620970e-003 + -0.0940800234675407 + 0.1367546021938324 + <_> + + <_> + + + + <_> + 10 1 10 2 -1. + <_> + 10 1 5 2 2. + 0 + -0.0127805396914482 + 0.0790209397673607 + -0.0321417711675167 + <_> + + <_> + + + + <_> + 5 0 8 3 -1. + <_> + 9 0 4 3 2. + 0 + 8.7420884519815445e-003 + -0.0805833786725998 + 0.1433219015598297 + <_> + + <_> + + + + <_> + 21 0 2 1 -1. + <_> + 21 0 1 1 2. + 1 + 6.9780537160113454e-005 + -0.1539752036333084 + 0.0694082602858543 + <_> + + <_> + + + + <_> + 2 8 4 2 -1. + <_> + 3 9 2 2 2. + 1 + -7.9981610178947449e-003 + -0.4497911930084229 + 0.0232297703623772 + <_> + + <_> + + + + <_> + 21 0 2 1 -1. + <_> + 21 0 1 1 2. + 1 + 5.3804512135684490e-003 + 0.0246548391878605 + -0.1725358963012695 + <_> + + <_> + + + + <_> + 2 0 21 1 -1. + <_> + 9 0 7 1 3. + 0 + -0.0200069397687912 + 0.1652639061212540 + -0.0625987574458122 + <_> + + <_> + + + + <_> + 21 0 2 1 -1. + <_> + 21 0 1 1 2. + 1 + -4.4656409882009029e-003 + -0.3730463087558746 + 0.0105512700974941 + <_> + + <_> + + + + <_> + 4 0 1 2 -1. + <_> + 4 0 1 1 2. + 1 + -3.1919090542942286e-003 + -0.4411549866199493 + 0.0209588091820478 + <_> + + <_> + + + + <_> + 1 11 24 4 -1. + <_> + 13 11 12 2 2. + <_> + 1 13 12 2 2. + 0 + -0.0622704289853573 + -0.5413467884063721 + 0.0132205402478576 + <_> + + <_> + + + + <_> + 0 11 24 4 -1. + <_> + 0 11 12 2 2. + <_> + 12 13 12 2 2. + 0 + -0.0449563488364220 + -0.4331294000148773 + 0.0206683203577995 + <_> + + <_> + + + + <_> + 16 5 2 2 -1. + <_> + 17 5 1 1 2. + <_> + 16 6 1 1 2. + 0 + 1.1595709947869182e-003 + -0.0236924402415752 + 0.1087998002767563 + <_> + + <_> + + + + <_> + 7 5 2 2 -1. + <_> + 7 5 1 1 2. + <_> + 8 6 1 1 2. + 0 + -8.8405620772391558e-004 + 0.1649617999792099 + -0.0524947308003902 + <_> + + <_> + + + + <_> + 18 1 6 2 -1. + <_> + 18 1 3 2 2. + 0 + 0.0266917701810598 + 0.0148458201438189 + -0.5571644902229309 + <_> + + <_> + + + + <_> + 2 0 21 2 -1. + <_> + 9 0 7 2 3. + 0 + 0.0182767305523157 + -0.0662862136960030 + 0.1257701069116592 + <_> + + <_> + + + + <_> + 13 0 10 15 -1. + <_> + 13 0 5 15 2. + 0 + -0.0809113383293152 + 0.1131376996636391 + -0.0498078204691410 + <_> + + <_> + + + + <_> + 6 0 13 4 -1. + <_> + 6 1 13 2 2. + 0 + -0.0364037007093430 + 0.2336605936288834 + -0.0383339710533619 + <_> + + <_> + + + + <_> + 11 3 9 3 -1. + <_> + 11 4 9 1 3. + 0 + -0.0139478798955679 + 0.0991646125912666 + -0.0678260922431946 + <_> + + <_> + + + + <_> + 3 2 10 3 -1. + <_> + 2 3 10 1 3. + 1 + -0.0224205106496811 + 0.1904506981372833 + -0.0484246909618378 + <_> + + <_> + + + + <_> + 6 6 16 8 -1. + <_> + 6 6 8 8 2. + 0 + 0.0995163321495056 + -0.0482200607657433 + 0.2056124061346054 + <_> + + <_> + + + + <_> + 5 0 12 15 -1. + <_> + 8 0 6 15 2. + 0 + 0.1495629996061325 + 0.0141723398119211 + -0.6450886726379395 + <_> + + <_> + + + + <_> + 23 8 2 4 -1. + <_> + 23 8 1 4 2. + 0 + 9.6693442901596427e-004 + -0.0378436110913754 + 0.0635498985648155 + <_> + + <_> + + + + <_> + 0 5 3 3 -1. + <_> + 0 6 3 1 3. + 0 + 0.0120417503640056 + 0.0180350895971060 + -0.4774137139320374 + <_> + + <_> + + + + <_> + 21 5 4 2 -1. + <_> + 22 5 2 2 2. + 0 + 2.3097700905054808e-003 + -0.0415334291756153 + 0.1302794069051743 + <_> + + <_> + + + + <_> + 0 5 4 2 -1. + <_> + 1 5 2 2 2. + 0 + 2.2019869647920132e-003 + -0.0514689311385155 + 0.1736146062612534 + <_> + + <_> + + + + <_> + 21 2 3 4 -1. + <_> + 22 3 1 4 3. + 1 + 0.0272558908909559 + -0.0153390001505613 + 0.3625235855579376 + <_> + + <_> + + + + <_> + 4 2 4 3 -1. + <_> + 3 3 4 1 3. + 1 + 8.8747506961226463e-003 + -0.0426916293799877 + 0.2076780050992966 + <_> + + <_> + + + + <_> + 23 2 2 2 -1. + <_> + 23 2 2 1 2. + 1 + 4.7241621650755405e-003 + -0.0500567816197872 + 0.0873611792922020 + <_> + + <_> + + + + <_> + 0 5 4 4 -1. + <_> + 0 6 4 2 2. + 0 + 7.3167313530575484e-005 + -0.1244131028652191 + 0.0726777836680412 + <_> + + <_> + + + + <_> + 23 7 2 5 -1. + <_> + 23 7 1 5 2. + 0 + -1.2639940250664949e-003 + 0.0776199027895927 + -0.0404986217617989 + <_> + + <_> + + + + <_> + 0 0 1 4 -1. + <_> + 0 1 1 2 2. + 0 + 3.6909559275954962e-003 + 0.0311388503760099 + -0.3086219131946564 + <_> + + <_> + + + + <_> + 23 1 2 4 -1. + <_> + 23 3 2 2 2. + 0 + -0.0283522401005030 + -0.3550184071063995 + 0.0135328602045774 + <_> + + <_> + + + + <_> + 0 1 2 4 -1. + <_> + 0 3 2 2 2. + 0 + -9.6667202888056636e-004 + 0.0676028430461884 + -0.1432974934577942 + <_> + + <_> + + + + <_> + 19 3 5 4 -1. + <_> + 19 4 5 2 2. + 0 + -0.0587403103709221 + -0.5506312847137451 + 4.2741261422634125e-003 + <_> + + <_> + + + + <_> + 12 1 6 2 -1. + <_> + 12 1 6 1 2. + 1 + -0.0272757392376661 + -0.6493160724639893 + 0.0125345299020410 + <_> + + <_> + + + + <_> + 19 11 6 4 -1. + <_> + 19 12 6 2 2. + 0 + -0.0117558799684048 + -0.5648565292358398 + 0.0137637602165341 + <_> + + <_> + + + + <_> + 1 3 6 4 -1. + <_> + 1 4 6 2 2. + 0 + 7.5923758558928967e-003 + -0.0431140698492527 + 0.2005586028099060 + <_> + + <_> + + + + <_> + 23 0 2 1 -1. + <_> + 23 0 1 1 2. + 1 + -7.1979401400312781e-004 + -0.1374174952507019 + 0.0340671092271805 + <_> + + <_> + + + + <_> + 2 0 1 2 -1. + <_> + 2 0 1 1 2. + 1 + 4.1190441697835922e-003 + 0.0367105789482594 + -0.2477497011423111 + <_> + + <_> + + + + <_> + 19 0 4 2 -1. + <_> + 20 0 2 2 2. + 0 + 7.5443051755428314e-003 + 7.2344779036939144e-003 + -0.4473736882209778 + <_> + + <_> + + + + <_> + 0 0 2 12 -1. + <_> + 0 0 1 6 2. + <_> + 1 6 1 6 2. + 0 + -5.2358289249241352e-003 + 0.2173164039850235 + -0.0386803299188614 + <_> + + <_> + + + + <_> + 22 4 2 8 -1. + <_> + 23 4 1 4 2. + <_> + 22 8 1 4 2. + 0 + 7.4686598964035511e-004 + -0.0371707193553448 + 0.0385193713009357 + <_> + + <_> + + + + <_> + 1 4 2 8 -1. + <_> + 1 4 1 4 2. + <_> + 2 8 1 4 2. + 0 + 8.8468490866944194e-004 + -0.1020980030298233 + 0.0926149412989616 + <_> + + <_> + + + + <_> + 17 9 4 1 -1. + <_> + 17 9 2 1 2. + 0 + -1.1738609755411744e-003 + 0.1108791977167130 + -0.0856960415840149 + <_> + + <_> + + + + <_> + 12 2 5 8 -1. + <_> + 10 4 5 4 2. + 1 + -0.0989599674940109 + -0.4499149918556213 + 0.0212421305477619 + <_> + + <_> + + + + <_> + 18 13 2 2 -1. + <_> + 19 13 1 1 2. + <_> + 18 14 1 1 2. + 0 + 8.8248471729457378e-004 + 0.0228975899517536 + -0.1995048969984055 + <_> + + <_> + + + + <_> + 6 9 13 6 -1. + <_> + 6 11 13 2 3. + 0 + -0.0413776896893978 + 0.1549389958381653 + -0.0591393709182739 + <_> + + <_> + + + + <_> + 6 10 13 4 -1. + <_> + 6 11 13 2 2. + 0 + 6.7946789786219597e-003 + -0.0783610120415688 + 0.1739570051431656 + <_> + + <_> + + + + <_> + 0 8 24 4 -1. + <_> + 0 8 12 2 2. + <_> + 12 10 12 2 2. + 0 + 0.0447585098445416 + 0.0260890107601881 + -0.3311159014701843 + <_> + + <_> + + + + <_> + 17 10 8 3 -1. + <_> + 17 11 8 1 3. + 0 + 2.9978479724377394e-003 + 0.0459281504154205 + -0.1491470038890839 + <_> + + <_> + + + + <_> + 4 0 16 8 -1. + <_> + 4 0 8 4 2. + <_> + 12 4 8 4 2. + 0 + -0.0595893599092960 + -0.2485350966453552 + 0.0325236506760120 + <_> + + <_> + + + + <_> + 14 0 1 2 -1. + <_> + 14 1 1 1 2. + 0 + 9.4199320301413536e-004 + -0.0425546802580357 + 0.1344856023788452 + <_> + + <_> + + + + <_> + 3 9 6 6 -1. + <_> + 5 9 2 6 3. + 0 + -0.0239475108683109 + -0.4583190977573395 + 0.0178181305527687 + <_> + + <_> + + + + <_> + 13 10 12 3 -1. + <_> + 16 10 6 3 2. + 0 + 7.4462359771132469e-003 + -0.0423585288226604 + 0.0580310709774494 + <_> + + <_> + + + + <_> + 0 10 12 3 -1. + <_> + 3 10 6 3 2. + 0 + -0.0129095697775483 + 0.1973039060831070 + -0.0445232689380646 + <_> + + <_> + + + + <_> + 19 8 5 3 -1. + <_> + 19 9 5 1 3. + 0 + 2.8930921107530594e-003 + 0.0428810603916645 + -0.1371746063232422 + <_> + + <_> + + + + <_> + 7 1 3 1 -1. + <_> + 8 1 1 1 3. + 0 + -6.8186258431524038e-004 + 0.1337869018316269 + -0.0565496906638145 + <_> + + <_> + + + + <_> + 15 1 3 1 -1. + <_> + 16 1 1 1 3. + 0 + 9.0884382370859385e-004 + -0.0361675098538399 + 0.1220118999481201 + <_> + + <_> + + + + <_> + 7 1 3 1 -1. + <_> + 8 1 1 1 3. + 0 + 4.2305429815314710e-004 + -0.0695094764232636 + 0.1302513927221298 + <_> + + <_> + + + + <_> + 20 8 2 3 -1. + <_> + 20 9 2 1 3. + 0 + -1.6460029873996973e-003 + -0.1300535947084427 + 0.0327382087707520 + <_> + + <_> + + + + <_> + 2 0 4 2 -1. + <_> + 3 0 2 2 2. + 0 + 7.2493818588554859e-003 + 0.0122888395562768 + -0.6227869987487793 + <_> + + <_> + + + + <_> + 19 8 5 3 -1. + <_> + 19 9 5 1 3. + 0 + 7.8207803890109062e-003 + 7.4369488283991814e-003 + -0.1486981958150864 + <_> + + <_> + + + + <_> + 4 1 6 11 -1. + <_> + 6 1 2 11 3. + 0 + 0.0359272807836533 + 0.0188675802201033 + -0.3921496868133545 + <_> + + <_> + + + + <_> + 16 9 2 1 -1. + <_> + 16 9 1 1 2. + 0 + -6.1618811741936952e-005 + 0.0568877793848515 + -0.0677392184734344 + <_> + + <_> + + + + <_> + 5 2 15 4 -1. + <_> + 5 3 15 2 2. + 0 + 0.0374080687761307 + -0.0385471209883690 + 0.2218790054321289 + <_> + + <_> + + + + <_> + 11 2 3 3 -1. + <_> + 11 3 3 1 3. + 0 + -5.2155661396682262e-003 + 0.1363334953784943 + -0.0673948600888252 + <_> + + <_> + + + + <_> + 2 7 18 6 -1. + <_> + 11 7 9 6 2. + 0 + -0.0935681909322739 + 0.1743745058774948 + -0.0487747117877007 + <_> + + <_> + + + + <_> + 1 6 24 9 -1. + <_> + 7 6 12 9 2. + 0 + 0.0762281417846680 + -0.0574758499860764 + 0.1471180021762848 + <_> + + <_> + + + + <_> + 0 0 1 10 -1. + <_> + 0 5 1 5 2. + 0 + -0.0200377702713013 + -0.4157789945602417 + 0.0179230198264122 + <_> + + <_> + + + + <_> + 9 3 10 2 -1. + <_> + 9 4 10 1 2. + 0 + -0.0118243796750903 + 0.1144623011350632 + -0.0700482204556465 + <_> + + <_> + + + + <_> + 12 6 1 3 -1. + <_> + 12 7 1 1 3. + 0 + -1.6057320171967149e-003 + 0.1678820997476578 + -0.0499466583132744 + <_> + + <_> + + + + <_> + 16 9 2 1 -1. + <_> + 16 9 1 1 2. + 0 + -2.5517439935356379e-003 + -0.3828516900539398 + 0.0113612702116370 + <_> + + <_> + + + + <_> + 7 9 2 1 -1. + <_> + 8 9 1 1 2. + 0 + -9.9515629699453712e-005 + 0.0925496816635132 + -0.0903496667742729 + <_> + + <_> + + + + <_> + 16 7 6 6 -1. + <_> + 19 7 3 3 2. + <_> + 16 10 3 3 2. + 0 + -0.0167104993015528 + 0.1787143051624298 + -0.0413177497684956 + <_> + + <_> + + + + <_> + 10 10 2 2 -1. + <_> + 10 10 1 1 2. + <_> + 11 11 1 1 2. + 0 + -9.6687301993370056e-004 + -0.2522006928920746 + 0.0305528100579977 + <_> + + <_> + + + + <_> + 16 9 2 2 -1. + <_> + 17 9 1 1 2. + <_> + 16 10 1 1 2. + 0 + -6.0828930145362392e-005 + 0.0542593784630299 + -0.0474381409585476 + <_> + + <_> + + + + <_> + 7 9 2 2 -1. + <_> + 7 9 1 1 2. + <_> + 8 10 1 1 2. + 0 + -8.6335372179746628e-004 + 0.1779994070529938 + -0.0423120781779289 + <_> + + <_> + + + + <_> + 13 10 2 2 -1. + <_> + 14 10 1 1 2. + <_> + 13 11 1 1 2. + 0 + -8.9218461653217673e-004 + -0.1845878958702087 + 0.0251416098326445 + <_> + + <_> + + + + <_> + 11 7 2 3 -1. + <_> + 11 8 2 1 3. + 0 + -3.4870179370045662e-003 + 0.1677664965391159 + -0.0460440590977669 + <_> + + <_> + + + + <_> + 19 0 6 3 -1. + <_> + 19 1 6 1 3. + 0 + 0.0195988900959492 + 0.0180558506399393 + -0.3022567927837372 + <_> + + <_> + + + + <_> + 0 0 6 3 -1. + <_> + 0 1 6 1 3. + 0 + -0.0109872100874782 + -0.3727653026580811 + 0.0197681505233049 + <_> + + <_> + + + + <_> + 24 0 1 2 -1. + <_> + 24 1 1 1 2. + 0 + -6.6390639403834939e-005 + 0.0768569633364677 + -0.1268360018730164 + <_> + + <_> + + + + <_> + 0 0 16 1 -1. + <_> + 4 0 8 1 2. + 0 + -4.2606238275766373e-003 + 0.1132820025086403 + -0.0696604028344154 + <_> + + <_> + + + + <_> + 19 11 6 4 -1. + <_> + 19 12 6 2 2. + 0 + 7.3147160001099110e-003 + 0.0329976715147495 + -0.2646273076534271 + <_> + + <_> + + + + <_> + 0 11 6 4 -1. + <_> + 0 12 6 2 2. + 0 + -0.0101194800809026 + -0.4706184864044190 + 0.0138464700430632 + <_> + + <_> + + + + <_> + 5 3 15 6 -1. + <_> + 5 6 15 3 2. + 0 + 0.0921443328261375 + -0.0886306688189507 + 0.0808285027742386 + <_> + + <_> + + + + <_> + 8 3 9 3 -1. + <_> + 8 4 9 1 3. + 0 + 0.0118425898253918 + -0.0542713403701782 + 0.1590622961521149 + <_> + + <_> + + + + <_> + 12 0 1 12 -1. + <_> + 12 3 1 6 2. + 0 + 0.0260604508221149 + 0.0202190801501274 + -0.3709642887115479 + <_> + + <_> + + + + <_> + 1 3 14 8 -1. + <_> + 1 7 14 4 2. + 0 + 0.2863250076770783 + 0.0171639006584883 + -0.3946934938430786 + <_> + + <_> + + + + <_> + 15 0 6 4 -1. + <_> + 17 0 2 4 3. + 0 + -0.0193374603986740 + -0.2173891961574554 + 0.0148878796026111 + <_> + + <_> + + + + <_> + 3 7 4 2 -1. + <_> + 3 7 2 1 2. + <_> + 5 8 2 1 2. + 0 + 6.8996037589386106e-004 + -0.0642509534955025 + 0.1074123978614807 + <_> + + <_> + + + + <_> + 14 5 1 8 -1. + <_> + 14 9 1 4 2. + 0 + 0.0273154806345701 + 5.0893737934529781e-003 + -0.5541477799415588 + <_> + + <_> + + + + <_> + 0 7 3 3 -1. + <_> + 0 8 3 1 3. + 0 + -7.3149320669472218e-003 + -0.5788456201553345 + 0.0114226602017879 + <_> + + <_> + + + + <_> + 11 12 6 3 -1. + <_> + 13 12 2 3 3. + 0 + 0.0134929800406098 + 6.9531891494989395e-003 + -0.3359794020652771 + <_> + + <_> + + + + <_> + 8 12 6 3 -1. + <_> + 10 12 2 3 3. + 0 + 0.0170349292457104 + 9.6587073057889938e-003 + -0.6638085842132568 + <_> + + <_> + + + + <_> + 16 5 6 10 -1. + <_> + 19 5 3 5 2. + <_> + 16 10 3 5 2. + 0 + -0.0495363213121891 + -0.1099594011902809 + 7.1444557979702950e-003 + <_> + + <_> + + + + <_> + 3 5 6 10 -1. + <_> + 3 5 3 5 2. + <_> + 6 10 3 5 2. + 0 + -0.0326232202351093 + 0.1888170987367630 + -0.0416569598019123 + <_> + + <_> + + + + <_> + 17 8 8 1 -1. + <_> + 19 8 4 1 2. + 0 + 2.5752598885446787e-003 + -0.0510260090231895 + 0.1057118028402329 + <_> + + <_> + + + + <_> + 0 8 8 1 -1. + <_> + 2 8 4 1 2. + 0 + 2.4968909565359354e-003 + -0.0559858083724976 + 0.1347001940011978 + <_> + + <_> + + + + <_> + 9 13 14 2 -1. + <_> + 9 13 7 2 2. + 0 + -0.0116916997358203 + 0.0694792568683624 + -0.0498108491301537 + <_> + + <_> + + + + <_> + 1 14 20 1 -1. + <_> + 6 14 10 1 2. + 0 + 5.0966278649866581e-003 + -0.0719841867685318 + 0.1201341003179550 + <_> + + <_> + + + + <_> + 17 7 2 2 -1. + <_> + 18 7 1 1 2. + <_> + 17 8 1 1 2. + 0 + 8.6429098155349493e-004 + -0.0280915908515453 + 0.1105908975005150 + <_> + + <_> + + + + <_> + 0 8 2 2 -1. + <_> + 0 9 2 1 2. + 0 + -3.0658349860459566e-003 + -0.4070394039154053 + 0.0187105592340231 + <_> + + <_> + + + + <_> + 17 7 2 2 -1. + <_> + 18 7 1 1 2. + <_> + 17 8 1 1 2. + 0 + -5.5272910685744137e-005 + 0.0707912817597389 + -0.0700317397713661 + <_> + + <_> + + + + <_> + 6 7 2 2 -1. + <_> + 6 7 1 1 2. + <_> + 7 8 1 1 2. + 0 + 6.5698497928678989e-004 + -0.0492957085371017 + 0.1548248976469040 + <_> + + <_> + + + + <_> + 13 10 2 2 -1. + <_> + 14 10 1 1 2. + <_> + 13 11 1 1 2. + 0 + 5.3707341430708766e-004 + 0.0302961803972721 + -0.1238510981202126 + <_> + + <_> + + + + <_> + 4 0 6 4 -1. + <_> + 6 0 2 4 3. + 0 + -0.0272689107805490 + -0.4674024879932404 + 0.0149874398484826 + <_> + + <_> + + + + <_> + 10 0 6 2 -1. + <_> + 12 0 2 2 3. + 0 + -2.6138951070606709e-003 + 0.1166682019829750 + -0.0615368783473969 + <_> + + <_> + + + + <_> + 8 1 8 3 -1. + <_> + 10 1 4 3 2. + 0 + -0.0277075897902250 + -0.6434546709060669 + 0.0120052499696612 + <_> + + <_> + + + + <_> + 14 6 7 2 -1. + <_> + 14 6 7 1 2. + 1 + -0.0200542695820332 + -0.3493579030036926 + 0.0109763201326132 + <_> + + <_> + + + + <_> + 8 10 4 1 -1. + <_> + 9 10 2 1 2. + 0 + 6.9170317146927118e-004 + 0.0442647784948349 + -0.1491888016462326 + <_> + + <_> + + + + <_> + 16 11 2 2 -1. + <_> + 17 11 1 1 2. + <_> + 16 12 1 1 2. + 0 + 6.4560663304291666e-005 + -0.0422041602432728 + 0.0473436005413532 + <_> + + <_> + + + + <_> + 7 11 2 2 -1. + <_> + 7 11 1 1 2. + <_> + 8 12 1 1 2. + 0 + -8.8378103100694716e-005 + 0.1016054973006249 + -0.0740641728043556 + <_> + + <_> + + + + <_> + 16 11 2 2 -1. + <_> + 17 11 1 1 2. + <_> + 16 12 1 1 2. + 0 + -6.6106527810916305e-005 + 0.0759406536817551 + -0.0495208092033863 + <_> + + <_> + + + + <_> + 7 11 2 2 -1. + <_> + 7 11 1 1 2. + <_> + 8 12 1 1 2. + 0 + 4.2288508848287165e-004 + -0.0588600113987923 + 0.1385688036680222 + <_> + + <_> + + + + <_> + 17 9 4 1 -1. + <_> + 17 9 2 1 2. + 0 + 2.5251980405300856e-003 + -0.0302844792604446 + 0.1643659025430679 + <_> + + <_> + + + + <_> + 4 9 4 1 -1. + <_> + 6 9 2 1 2. + 0 + -9.0347938239574432e-003 + -0.6502289175987244 + 0.0117079298943281 + <_> + + <_> + + + + <_> + 11 8 3 4 -1. + <_> + 11 9 3 2 2. + 0 + -4.2698681354522705e-003 + 0.1213309019804001 + -0.0608336813747883 + <_> + + <_> + + + + <_> + 9 6 3 2 -1. + <_> + 10 7 1 2 3. + 1 + 0.0166539791971445 + 0.0145571101456881 + -0.5031678080558777 + <_> + + <_> + + + + <_> + 21 0 4 8 -1. + <_> + 19 2 4 4 2. + 1 + -0.1178558021783829 + -0.3486539125442505 + 5.8299610391259193e-003 + <_> + + <_> + + + + <_> + 4 0 8 4 -1. + <_> + 6 2 4 4 2. + 1 + -0.0389890410006046 + 0.1082129999995232 + -0.0824354067444801 + <_> + + <_> + + + + <_> + 20 1 5 2 -1. + <_> + 20 1 5 1 2. + 1 + -6.9744870997965336e-003 + 0.0920993909239769 + -0.0447417609393597 + <_> + + <_> + + + + <_> + 0 6 6 4 -1. + <_> + 0 7 6 2 2. + 0 + 0.0154374102130532 + 0.0294817406684160 + -0.2408691942691803 + <_> + + <_> + + + + <_> + 20 6 5 4 -1. + <_> + 20 7 5 2 2. + 0 + -5.9599988162517548e-003 + -0.2254153043031693 + 0.0256420802325010 + <_> + + <_> + + + + <_> + 6 8 3 1 -1. + <_> + 7 8 1 1 3. + 0 + -5.3358142031356692e-004 + 0.1183808967471123 + -0.0571242086589336 + <_> + + <_> + + + + <_> + 1 8 24 2 -1. + <_> + 13 8 12 1 2. + <_> + 1 9 12 1 2. + 0 + 0.0176937691867352 + 0.0266077890992165 + -0.3055857121944428 + <_> + + <_> + + + + <_> + 8 8 8 3 -1. + <_> + 8 9 8 1 3. + 0 + 5.3599448874592781e-003 + -0.0569497905671597 + 0.1210888996720314 + <_> + + <_> + + + + <_> + 17 11 6 4 -1. + <_> + 19 11 2 4 3. + 0 + 0.0158548094332218 + 0.0215572193264961 + -0.2521420121192932 + <_> + + <_> + + + + <_> + 0 0 18 1 -1. + <_> + 9 0 9 1 2. + 0 + 0.0549633502960205 + 0.0106362197548151 + -0.5730599761009216 + <_> + + <_> + + + + <_> + 14 6 3 2 -1. + <_> + 15 7 1 2 3. + 1 + -3.7383600138127804e-003 + 0.0774415433406830 + -0.0306048095226288 + <_> + + <_> + + + + <_> + 5 6 13 2 -1. + <_> + 5 7 13 1 2. + 0 + 0.0182623900473118 + -0.0549028292298317 + 0.1176588013768196 + <_> + + <_> + + + + <_> + 14 6 3 2 -1. + <_> + 15 7 1 2 3. + 1 + -0.0318278707563877 + -0.9110031723976135 + 1.3938200427219272e-003 + <_> + + <_> + + + + <_> + 10 6 2 6 -1. + <_> + 10 8 2 2 3. + 0 + -3.6466179881244898e-003 + 0.1085240989923477 + -0.0722526162862778 + <_> + + <_> + + + + <_> + 20 1 5 2 -1. + <_> + 20 1 5 1 2. + 1 + -0.0517431795597076 + -0.9186943173408508 + 1.8797840457409620e-003 + <_> + + <_> + + + + <_> + 5 1 2 5 -1. + <_> + 5 1 1 5 2. + 1 + -9.0449545532464981e-003 + 0.1787680983543396 + -0.0388442091643810 + <_> + + <_> + + + + <_> + 24 7 1 8 -1. + <_> + 24 9 1 4 2. + 0 + -4.5340228825807571e-003 + -0.2472573071718216 + 0.0297267790883780 + <_> + + <_> + + + + <_> + 7 7 11 3 -1. + <_> + 7 8 11 1 3. + 0 + 6.8734101951122284e-003 + -0.0675214827060699 + 0.1065412983298302 + <_> + + <_> + + + + <_> + 13 11 2 2 -1. + <_> + 14 11 1 1 2. + <_> + 13 12 1 1 2. + 0 + 7.7327789040282369e-004 + 0.0221925694495440 + -0.1398307979106903 + <_> + + <_> + + + + <_> + 10 11 3 1 -1. + <_> + 11 11 1 1 3. + 0 + -8.5252941062208265e-005 + 0.0903024971485138 + -0.0786189734935761 + <_> + + <_> + + + + <_> + 24 7 1 8 -1. + <_> + 24 9 1 4 2. + 0 + 4.8931739293038845e-003 + 0.0311242006719112 + -0.1617130041122437 + <_> + + <_> + + + + <_> + 10 5 2 4 -1. + <_> + 10 5 2 2 2. + 1 + -0.0357618294656277 + -0.3406237065792084 + 0.0201859101653099 + <_> + + <_> + + + + <_> + 22 1 2 3 -1. + <_> + 21 2 2 1 3. + 1 + -0.0110698901116848 + 0.1165141984820366 + -0.0340334698557854 + <_> + + <_> + + + + <_> + 3 1 3 2 -1. + <_> + 4 2 1 2 3. + 1 + 3.4201510716229677e-003 + -0.0530161187052727 + 0.1339436024427414 + <_> + + <_> + + + + <_> + 16 4 3 3 -1. + <_> + 17 5 1 1 9. + 0 + -0.0499692708253860 + -0.8493295907974243 + 2.7547380886971951e-003 + <_> + + <_> + + + + <_> + 3 0 3 2 -1. + <_> + 3 0 3 1 2. + 1 + -1.1221430031582713e-003 + -0.1629413068294525 + 0.0413381010293961 + <_> + + <_> + + + + <_> + 17 0 8 3 -1. + <_> + 17 0 4 3 2. + 0 + 0.0371481291949749 + 0.0171750299632549 + -0.2840433120727539 + <_> + + <_> + + + + <_> + 0 12 4 3 -1. + <_> + 0 13 4 1 3. + 0 + 2.3847341071814299e-003 + 0.0348382107913494 + -0.1844726949930191 + <_> + + <_> + + + + <_> + 2 3 21 3 -1. + <_> + 9 3 7 3 3. + 0 + 0.1431124955415726 + 0.0252217296510935 + -0.2543725967407227 + <_> + + <_> + + + + <_> + 8 1 2 5 -1. + <_> + 8 1 1 5 2. + 1 + -0.0119188595563173 + 0.1655784994363785 + -0.0447442717850208 + <_> + + <_> + + + + <_> + 19 7 6 4 -1. + <_> + 22 7 3 2 2. + <_> + 19 9 3 2 2. + 0 + 6.4779450185596943e-003 + -0.0250237993896008 + 0.0799132883548737 + <_> + + <_> + + + + <_> + 0 7 6 4 -1. + <_> + 0 7 3 2 2. + <_> + 3 9 3 2 2. + 0 + 1.4581739669665694e-003 + -0.0797923728823662 + 0.0829188674688339 + <_> + + <_> + + + + <_> + 24 4 1 4 -1. + <_> + 24 5 1 2 2. + 0 + 6.2418850138783455e-003 + 0.0132909296080470 + -0.2995111048221588 + <_> + + <_> + + + + <_> + 4 7 3 4 -1. + <_> + 3 8 3 2 2. + 1 + -0.0227145906537771 + 0.4398984909057617 + -0.0150371296331286 + <_> + + <_> + + + + <_> + 17 9 4 1 -1. + <_> + 18 9 2 1 2. + 0 + -4.3001482263207436e-003 + -0.3546585142612457 + 7.9521266743540764e-003 + <_> + + <_> + + + + <_> + 4 9 4 1 -1. + <_> + 5 9 2 1 2. + 0 + 1.0604769922792912e-003 + 0.0385937690734863 + -0.1762923002243042 + <_> + + <_> + + + + <_> + 23 6 2 2 -1. + <_> + 23 7 2 1 2. + 0 + 4.3205441907048225e-003 + 0.0171245392411947 + -0.1075016036629677 + <_> + + <_> + + + + <_> + 0 6 2 2 -1. + <_> + 0 7 2 1 2. + 0 + -3.8217399269342422e-003 + -0.4589209854602814 + 0.0141258295625448 + <_> + + <_> + + + + <_> + 12 0 3 1 -1. + <_> + 13 0 1 1 3. + 0 + 9.7336847102269530e-004 + -0.0361551195383072 + 0.1268056929111481 + <_> + + <_> + + + + <_> + 1 7 2 2 -1. + <_> + 1 7 1 1 2. + <_> + 2 8 1 1 2. + 0 + -7.9081847798079252e-004 + 0.1707147061824799 + -0.0376146212220192 + <_> + + <_> + + + + <_> + 22 7 2 2 -1. + <_> + 23 7 1 1 2. + <_> + 22 8 1 1 2. + 0 + -7.6159887248650193e-004 + 0.2311398983001709 + -0.0603629797697067 + <_> + + <_> + + + + <_> + 2 11 6 4 -1. + <_> + 4 11 2 4 3. + 0 + -0.0210315398871899 + -0.4918564856052399 + 0.0156012997031212 + <_> + + <_> + + + + <_> + 14 1 10 4 -1. + <_> + 19 1 5 2 2. + <_> + 14 3 5 2 2. + 0 + 0.0180973205715418 + -0.0467358492314816 + 0.1050693020224571 + <_> + + <_> + + + + <_> + 6 2 12 2 -1. + <_> + 6 3 12 1 2. + 0 + -0.0131208598613739 + 0.1018344014883041 + -0.0857265591621399 + <_> + + <_> + + + + <_> + 9 6 8 9 -1. + <_> + 9 9 8 3 3. + 0 + 0.2012819051742554 + -9.4874696806073189e-003 + 0.5418189764022827 + <_> + + <_> + + + + <_> + 3 8 3 3 -1. + <_> + 4 9 1 1 9. + 0 + 7.3326090350747108e-003 + 0.0282447207719088 + -0.2452981024980545 + <_> + + <_> + + + + <_> + 22 7 2 2 -1. + <_> + 23 7 1 1 2. + <_> + 22 8 1 1 2. + 0 + 9.0540642850100994e-004 + -0.0559650883078575 + 0.2322594970464706 + <_> + + <_> + + + + <_> + 11 10 2 2 -1. + <_> + 11 10 1 1 2. + <_> + 12 11 1 1 2. + 0 + 5.3532002493739128e-004 + 0.0432194508612156 + -0.1652047038078308 + <_> + + <_> + + + + <_> + 22 7 2 2 -1. + <_> + 23 7 1 1 2. + <_> + 22 8 1 1 2. + 0 + -8.0239711678586900e-005 + 0.0588538907468319 + -0.0475415214896202 + <_> + + <_> + + + + <_> + 4 13 10 1 -1. + <_> + 9 13 5 1 2. + 0 + 4.8403399996459484e-003 + -0.0541158504784107 + 0.1303326934576035 + <_> + + <_> + + + + <_> + 3 0 20 15 -1. + <_> + 3 0 10 15 2. + 0 + 0.6619219779968262 + -0.0147952698171139 + 0.5785722732543945 + <_> + + <_> + + + + <_> + 0 13 24 1 -1. + <_> + 6 13 12 1 2. + 0 + -8.5441237315535545e-003 + 0.1165743991732597 + -0.0628988370299339 + <_> + + <_> + + + + <_> + 22 7 2 2 -1. + <_> + 23 7 1 1 2. + <_> + 22 8 1 1 2. + 0 + 5.4021849791752174e-005 + -0.0602008998394012 + 0.0699716731905937 + -1.2540320158004761 + 15 + -1 + diff --git a/OpenCVComponent/OpenCVComponent.cpp b/OpenCVComponent/OpenCVComponent.cpp new file mode 100755 index 0000000..f062b8a --- /dev/null +++ b/OpenCVComponent/OpenCVComponent.cpp @@ -0,0 +1,291 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#include "pch.h" +#include "OpenCVComponent.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace OpenCVComponent; +using namespace Platform; +using namespace concurrency; +using namespace Windows::Foundation; +using namespace Windows::Foundation::Collections; + +// Name of the resource classifier used to detect human faces (frontal) +cv::String face_cascade_name = "haarcascade_frontalface_alt.xml"; + +// Name of the resource classifier used to detect human eyes (frontal) +cv::String eye_cascade_name = "haarcascade_eye.xml"; + +// Name of the resource classifier used to detect human mouth (frontal) +cv::String mouth_cascade_name = "haarcascade_mouth.xml"; + + +void CopyIVectorToMatrix(IVector^ input, cv::Mat& mat, int size); +void CopyMatrixToVector(const cv::Mat& mat, std::vector& vector, int size); + + +OpenCVLib::OpenCVLib() +{ + +} + +void OpenCVLib::Load() +{ + if (face_cascade.empty()) + { + if (!face_cascade.load(face_cascade_name)) + { + auto e = ref new Exception(-100, "Couldn't load face detector"); + + throw e; + //Windows::UI::Popups::MessageDialog("Couldn't load face detector \n").ShowAsync(); + } + } + + if (eye_cascade.empty()) + { + if (!eye_cascade.load(eye_cascade_name)) + { + auto e = ref new Exception(-100, "Couldn't load eye detector"); + + throw e; + //Windows::UI::Popups::MessageDialog("Couldn't load eye detector \n").ShowAsync(); + } + } + + if (mouth_cascade.empty()) + { + if (!mouth_cascade.load(mouth_cascade_name)) + { + auto e = ref new Exception(-100, "Couldn't load mouth detector"); + + throw e; + //Windows::UI::Popups::MessageDialog("Couldn't load mouth detector \n").ShowAsync(); + } + } +} + +void OutputDebugString(std::string output, LARGE_INTEGER start, LARGE_INTEGER frequency) +{ +#ifdef DEBUG + LARGE_INTEGER end; + if (::QueryPerformanceCounter(&end) == FALSE) + throw "foo"; + + double interval = static_cast(end.QuadPart - start.QuadPart) / frequency.QuadPart; + + OutputDebugStringA((output + " " + std::to_string(interval) + "\n").c_str()); +#endif +} + +IAsyncOperation^ OpenCVLib::ProcessImageAsync(String^ fileName) +{ + return concurrency::create_async([=]() -> FacesImage^ + { + LARGE_INTEGER frequency; + if (::QueryPerformanceFrequency(&frequency) == FALSE) + throw "foo"; + + LARGE_INTEGER start; + if (::QueryPerformanceCounter(&start) == FALSE) + throw "foo"; + + Load(); + + OutputDebugString("load", start, frequency); + + IVector^ fs = ref new Platform::Collections::Vector(); + + std::wstring fooW(fileName->Begin()); + std::string fooA(fooW.begin(), fooW.end()); + + cv::String fileNameCV(fooA); + cv::Mat image = cv::imread(fileNameCV.c_str()); + + OutputDebugString("cv::imread " + std::to_string(image.cols) + "x" + std::to_string(image.rows), start, frequency); + + groupFaces = cv::Mat(image.rows, image.cols, CV_8UC4); + cv::cvtColor(image, groupFaces, CV_BGR2BGRA); + + if (!groupFaces.empty()) + { + std::vector facesColl; + cv::Mat frame_gray; + + OutputDebugString("start", start, frequency); + + cvtColor(groupFaces, frame_gray, CV_BGR2GRAY); + //UpdateImage(img2, frame_gray); + + OutputDebugString("cvtColor", start, frequency); + + cv::equalizeHist(frame_gray, frame_gray); + + OutputDebugString("cv::equalizeHist", start, frequency); + + //UpdateImage(img2, frame_gray); + // Detect faces + face_cascade.detectMultiScale(frame_gray, facesColl, 1.2, 3, 0 | CV_HAAR_SCALE_IMAGE, cv::Size(30, 30)); + + OutputDebugString("face_cascade.detectMultiScale", start, frequency); + + for (unsigned int i = 0; i < facesColl.size(); i++) + { + auto face = facesColl[i]; + auto f = ref new Face(Rect(face.x, face.y, face.width, face.height)); + fs->Append(f); + + cv::rectangle(groupFaces, face, cv::Scalar(255, 0, 0), 1); + + facesColl[i].height = facesColl[i].height / 2; + cv::Mat faceROI = frame_gray(facesColl[i]); + std::vector eyesColl; + std::vector eyesCenterColl; + + int eyeWidth = face.width / 6; + eye_cascade.detectMultiScale(faceROI, eyesColl, 1.1, 3, 0 | CV_HAAR_SCALE_IMAGE, cv::Size(eyeWidth, eyeWidth)); + OutputDebugString("eye_cascade.detectMultiScale", start, frequency); + for (unsigned int j = 0; j < eyesColl.size(); j++) + { + auto eye = eyesColl[j]; + eye.x += face.x; + eye.y += face.y; + cv::rectangle(groupFaces, eye, cv::Scalar(255, 0, 0), 1); + + auto eyeRect = Rect(eye.x, eye.y, eye.width, eye.height); + f->Eye->Append(eyeRect); + + // eye center + auto eyeCenter = cv::Point(eye.x + eye.width / 2, eye.y + eye.height / 2); + eyesCenterColl.push_back(eyeCenter); + cv::circle(groupFaces, eyeCenter, 3, cv::Scalar(0, 255, 0), -1); + } + + std::vector mouthsColl; + std::vector mouthsCenterColl; + + facesColl[i].height = facesColl[i].height / 2; + facesColl[i].y += facesColl[i].height * 3; + faceROI = frame_gray(facesColl[i]); + + int mouthWidth = 30; + mouth_cascade.detectMultiScale(faceROI, mouthsColl, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, cv::Size(mouthWidth, mouthWidth)); + OutputDebugString("mouth_cascade.detectMultiScale", start, frequency); + for (unsigned int j = 0; j < mouthsColl.size() && j < 10; j++) + { + auto mouth = mouthsColl[j]; + mouth.x += facesColl[i].x; + mouth.y += facesColl[i].y; + cv::rectangle(groupFaces, mouth, cv::Scalar(255, 0, 0), 1); + + auto mouthRect = Rect(mouth.x, mouth.y, mouth.width, mouth.height); + f->Mouth->Append(mouthRect); + + auto mouthCenter = cv::Point(mouth.x + mouth.width / 2, mouth.y + mouth.height / 4); + mouthsCenterColl.push_back(mouthCenter); + cv::circle(groupFaces, mouthCenter, 3, cv::Scalar(0, 255, 0), -1); + } + + // forehead, chin + if (eyesCenterColl.size() >= 2) + { + auto eyesDistanceX = abs(eyesCenterColl[1].x - eyesCenterColl[0].x); + auto eyesDistanceY = abs(eyesCenterColl[1].y - eyesCenterColl[0].y); + auto leftEye = eyesCenterColl[0]; + if (leftEye.x > eyesCenterColl[1].x) + { + leftEye = eyesCenterColl[1]; + } + + auto eyesCenter = cv::Point(leftEye.x + eyesDistanceX / 2, leftEye.y + eyesDistanceY / 2); + cv::circle(groupFaces, eyesCenter, 3, cv::Scalar(0, 255, 0), -1); + + auto foreheadCenter = cv::Point(eyesCenter.x, eyesCenter.y - 0.7 * eyesDistanceX); + cv::circle(groupFaces, foreheadCenter, 3, cv::Scalar(0, 255, 0), -1); + + if (mouthsCenterColl.size() >= 1) + { + auto chinCenter = cv::Point(eyesCenter.x, mouthsCenterColl[0].y + 0.55 * eyesDistanceX); + cv::circle(groupFaces, chinCenter, 3, cv::Scalar(0, 255, 0), -1); + } + } + } + + //UpdateImage(img1, groupFaces); + } + + std::vector output; + CopyMatrixToVector(groupFaces, output, image.rows * image.cols); + + //Return the outputs as a VectorView + //return ref new Platform::Collections::VectorView(output); + + auto facesImage = ref new FacesImage(); + facesImage->Width = image.cols; + facesImage->Height = image.rows; + facesImage->Faces = fs; + facesImage->Image = ref new Platform::Collections::VectorView(output); + + + OutputDebugString("stop", start, frequency); + return facesImage; + }); +} + +IAsyncOperation^>^ OpenCVLib::ProcessAsync(IVector^ input, int width, int height) +{ + return create_async([=]() -> IVectorView^ + { + int size = input->Size; + cv::Mat mat(width, height, CV_8UC4); + CopyIVectorToMatrix(input, mat, size); + + // convert to grayscale + cv::Mat intermediateMat; + cv::cvtColor(mat, intermediateMat, CV_RGB2GRAY); + + // convert to BGRA + cv::cvtColor(intermediateMat, mat, CV_GRAY2BGRA); + + std::vector output; + CopyMatrixToVector(mat, output, size); + + // Return the outputs as a VectorView + return ref new Platform::Collections::VectorView(output); + }); +} + + +void CopyIVectorToMatrix(IVector^ input, cv::Mat& mat, int size) +{ + unsigned char* data = mat.data; + for (int i = 0; i < size; i++) + { + int value = input->GetAt(i); + memcpy(data, (void*) &value, 4); + data += 4; + } +} + +void CopyMatrixToVector(const cv::Mat& mat, std::vector& vector, int size) +{ + int* data = (int*) mat.data; + for (int i = 0; i < size; i++) + { + vector.push_back(data[i]); + } + +} \ No newline at end of file diff --git a/OpenCVComponent/OpenCVComponent.h b/OpenCVComponent/OpenCVComponent.h new file mode 100755 index 0000000..d8f2a26 --- /dev/null +++ b/OpenCVComponent/OpenCVComponent.h @@ -0,0 +1,60 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once + +#include +#include + +#include +#include + +namespace OpenCVComponent +{ + using namespace Windows::Foundation; + using namespace Windows::Foundation::Collections; + using namespace Platform; + + public ref class Face sealed + { + private: + public: + property IVector^ Eye; + property IVector^ Mouth; + property Rect Position; + + Face(Rect position) + { + Eye = ref new Platform::Collections::Vector(); + Mouth = ref new Platform::Collections::Vector(); + Position = position; + } + }; + + public ref class FacesImage sealed + { + public: + property int Width; + property int Height; + property IVectorView^ Image; + property IVector^ Faces; + }; + + public ref class OpenCVLib sealed + { + private: + cv::Mat groupFaces; + cv::CascadeClassifier face_cascade; + cv::CascadeClassifier eye_cascade; + cv::CascadeClassifier mouth_cascade; + void Load(); + public: + OpenCVLib(); + IAsyncOperation^ ProcessImageAsync(String^ fileName); + IAsyncOperation^>^ ProcessAsync(IVector^ input, int width, int height); + }; +} \ No newline at end of file diff --git a/OpenCVComponent/OpenCVComponent.vcxproj b/OpenCVComponent/OpenCVComponent.vcxproj new file mode 100755 index 0000000..1068d85 --- /dev/null +++ b/OpenCVComponent/OpenCVComponent.vcxproj @@ -0,0 +1,157 @@ + + + + + Debug + Win32 + + + Debug + ARM + + + Release + Win32 + + + Release + ARM + + + + {eadff7b8-e6c3-4f34-9b33-014b3035c595} + OpenCVComponent + en-US + 11.0 + true + + + + DynamicLibrary + true + v110_wp80 + + + DynamicLibrary + true + v110_wp80 + + + DynamicLibrary + false + true + v110_wp80 + + + DynamicLibrary + false + true + v110_wp80 + + + + + + + + + + + + + + + + + + + + false + false + + + + _CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_WINRT_DLL;%(PreprocessorDefinitions) + Use + pch.h + $(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories) + true + + + Console + false + ole32.lib;%(IgnoreSpecificDefaultLibraries) + true + + + + + _CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + Use + pch.h + $(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories) + true + + + Console + false + ole32.lib;%(IgnoreSpecificDefaultLibraries) + true + + + + + _CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_WINRT_DLL;%(PreprocessorDefinitions) + Use + pch.h + $(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories) + true + + + Console + false + ole32.lib;%(IgnoreSpecificDefaultLibraries) + true + + + + + _CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + Use + pch.h + $(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories) + true + + + Console + false + ole32.lib;%(IgnoreSpecificDefaultLibraries) + true + + + + + true + false + + + + + + + + + + Create + + + + + + + + + + + + \ No newline at end of file diff --git a/OpenCVComponent/OpenCVComponent.vcxproj.filters b/OpenCVComponent/OpenCVComponent.vcxproj.filters new file mode 100755 index 0000000..cf9b712 --- /dev/null +++ b/OpenCVComponent/OpenCVComponent.vcxproj.filters @@ -0,0 +1,40 @@ + + + + + 5fd0e509-b6ae-4f29-bd2a-4d2cc10f3aa0 + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {9c92a94c-8b61-4fe3-9856-7d35d5216ed6} + + + + + + + + + + + + + + + + + + + + + + Cascades + + + Cascades + + + Cascades + + + \ No newline at end of file diff --git a/OpenCVComponent/opencv.props b/OpenCVComponent/opencv.props new file mode 100755 index 0000000..7474dc0 --- /dev/null +++ b/OpenCVComponent/opencv.props @@ -0,0 +1,49 @@ + + + + + $(OPENCV_WINRT_INSTALL_DIR)\WP\8.0\$(PlatformTarget)\$(PlatformTarget)\vc11\bin\ + $(OPENCV_WINRT_INSTALL_DIR)\WP\8.0\$(PlatformTarget)\$(PlatformTarget)\vc11\lib\ + $(OPENCV_WINRT_INSTALL_DIR)\WP\8.0\$(PlatformTarget)\include\ + + d + + + + true + + + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + + + $(OpenCV_Include);%(AdditionalIncludeDirectories); + + + + opencv_core300$(DebugSuffix).lib;opencv_features2d300$(DebugSuffix).lib;opencv_flann300$(DebugSuffix).lib;opencv_imgcodecs300$(DebugSuffix).lib;opencv_imgproc300$(DebugSuffix).lib;opencv_ml300$(DebugSuffix).lib;opencv_objdetect300$(DebugSuffix).lib;WindowsPhoneCore.lib;RuntimeObject.lib;PhoneAppModelHost.lib;%(AdditionalDependencies) + $(OpenCV_Lib);%(AdditionalLibraryDirectories); + + + \ No newline at end of file diff --git a/OpenCVComponent/pch.cpp b/OpenCVComponent/pch.cpp new file mode 100755 index 0000000..ac95590 --- /dev/null +++ b/OpenCVComponent/pch.cpp @@ -0,0 +1,8 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#include "pch.h" diff --git a/OpenCVComponent/pch.h b/OpenCVComponent/pch.h new file mode 100755 index 0000000..c16b9a4 --- /dev/null +++ b/OpenCVComponent/pch.h @@ -0,0 +1,8 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once diff --git a/Telegram.Api.PCL/Hash/CRC32/CRC.WinRT.cs b/Telegram.Api.PCL/Hash/CRC32/CRC.WinRT.cs new file mode 100755 index 0000000..ff16c84 --- /dev/null +++ b/Telegram.Api.PCL/Hash/CRC32/CRC.WinRT.cs @@ -0,0 +1,266 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#if WIN_RT + + +using System; +using System.IO; + +namespace Telegram.Api +{ + /// + /// Calculates a 32bit Cyclic Redundancy Checksum (CRC) using the same polynomial + /// used by Zip. This type is used internally by DotNetZip; it is generally not used + /// directly by applications wishing to create, read, or manipulate zip archive + /// files. + /// + internal class CRC32 + { + private const int BUFFER_SIZE = 8192; + private static readonly UInt32[] crc32Table; + private UInt32 runningCrc32Result = 0xFFFFFFFF; + private Int64 totalBytesRead; + + static CRC32() + { + unchecked + { + // PKZip specifies CRC32 with a polynomial of 0xEDB88320; + // This is also the CRC-32 polynomial used bby Ethernet, FDDI, + // bzip2, gzip, and others. + // Often the polynomial is shown reversed as 0x04C11DB7. + // For more details, see http://en.wikipedia.org/wiki/Cyclic_redundancy_check + UInt32 dwPolynomial = 0xEDB88320; + UInt32 i, j; + + crc32Table = new UInt32[256]; + + UInt32 dwCrc; + for (i = 0; i < 256; i++) + { + dwCrc = i; + for (j = 8; j > 0; j--) + { + if ((dwCrc & 1) == 1) + { + dwCrc = (dwCrc >> 1) ^ dwPolynomial; + } + else + { + dwCrc >>= 1; + } + } + crc32Table[i] = dwCrc; + } + } + } + + /// + /// indicates the total number of bytes read on the CRC stream. + /// This is used when writing the ZipDirEntry when compressing files. + /// + public Int64 TotalBytesRead + { + get { return totalBytesRead; } + } + + /// + /// Indicates the current CRC for all blocks slurped in. + /// + public Int32 Crc32Result + { + get + { + // return one's complement of the running result + return unchecked((Int32)(~runningCrc32Result)); + } + } + + /// + /// Returns the CRC32 for the specified stream. + /// + /// The stream over which to calculate the CRC32 + /// the CRC32 calculation + public Int32 GetCrc32(Stream input) + { + return GetCrc32AndCopy(input, null); + } + + /// + /// Returns the CRC32 for the specified stream, and writes the input into the + /// output stream. + /// + /// The stream over which to calculate the CRC32 + /// The stream into which to deflate the input + /// the CRC32 calculation + public Int32 GetCrc32AndCopy(Stream input, Stream output) + { + if (input == null) + throw new ArgumentException("The input stream must not be null."); + + unchecked + { + //UInt32 crc32Result; + //crc32Result = 0xFFFFFFFF; + var buffer = new byte[BUFFER_SIZE]; + int readSize = BUFFER_SIZE; + + totalBytesRead = 0; + int count = input.Read(buffer, 0, readSize); + if (output != null) output.Write(buffer, 0, count); + totalBytesRead += count; + while (count > 0) + { + SlurpBlock(buffer, 0, count); + count = input.Read(buffer, 0, readSize); + if (output != null) output.Write(buffer, 0, count); + totalBytesRead += count; + } + + return (Int32)(~runningCrc32Result); + } + } + + + /// + /// Get the CRC32 for the given (word,byte) combo. This is a computation + /// defined by PKzip. + /// + /// The word to start with. + /// The byte to combine it with. + /// The CRC-ized result. + public Int32 ComputeCrc32(Int32 W, byte B) + { + return _InternalComputeCrc32((UInt32)W, B); + } + + internal Int32 _InternalComputeCrc32(UInt32 W, byte B) + { + return (Int32)(crc32Table[(W ^ B) & 0xFF] ^ (W >> 8)); + } + + /// + /// Update the value for the running CRC32 using the given block of bytes. + /// This is useful when using the CRC32() class in a Stream. + /// + /// block of bytes to slurp + /// starting point in the block + /// how many bytes within the block to slurp + public void SlurpBlock(byte[] block, int offset, int count) + { + if (block == null) + throw new ArgumentException("The data buffer must not be null."); + + for (int i = 0; i < count; i++) + { + int x = offset + i; + runningCrc32Result = ((runningCrc32Result) >> 8) ^ + crc32Table[(block[x]) ^ ((runningCrc32Result) & 0x000000FF)]; + } + totalBytesRead += count; + } + + + // pre-initialize the crc table for speed of lookup. + + + private uint gf2_matrix_times(uint[] matrix, uint vec) + { + uint sum = 0; + int i = 0; + while (vec != 0) + { + if ((vec & 0x01) == 0x01) + sum ^= matrix[i]; + vec >>= 1; + i++; + } + return sum; + } + + private void gf2_matrix_square(uint[] square, uint[] mat) + { + for (int i = 0; i < 32; i++) + square[i] = gf2_matrix_times(mat, mat[i]); + } + + + /// + /// Combines the given CRC32 value with the current running total. + /// + /// + /// This is useful when using a divide-and-conquer approach to calculating a CRC. + /// Multiple threads can each calculate a CRC32 on a segment of the data, and then + /// combine the individual CRC32 values at the end. + /// + /// the crc value to be combined with this one + /// the length of data the CRC value was calculated on + public void Combine(int crc, int length) + { + var even = new uint[32]; // even-power-of-two zeros operator + var odd = new uint[32]; // odd-power-of-two zeros operator + + if (length == 0) + return; + + uint crc1 = ~runningCrc32Result; + var crc2 = (uint)crc; + + // put operator for one zero bit in odd + odd[0] = 0xEDB88320; // the CRC-32 polynomial + uint row = 1; + for (int i = 1; i < 32; i++) + { + odd[i] = row; + row <<= 1; + } + + // put operator for two zero bits in even + gf2_matrix_square(even, odd); + + // put operator for four zero bits in odd + gf2_matrix_square(odd, even); + + var len2 = (uint)length; + + // apply len2 zeros to crc1 (first square will put the operator for one + // zero byte, eight zero bits, in even) + do + { + // apply zeros operator for this bit of len2 + gf2_matrix_square(even, odd); + + if ((len2 & 1) == 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + if (len2 == 0) + break; + + // another iteration of the loop with odd and even swapped + gf2_matrix_square(odd, even); + if ((len2 & 1) == 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + } while (len2 != 0); + + crc1 ^= crc2; + + runningCrc32Result = ~crc1; + + //return (int) crc1; + return; + } + + public byte[] ComputeHash(byte[] data) + { + return BitConverter.GetBytes(GetCrc32(new MemoryStream(data))); + } + } +} +#endif \ No newline at end of file diff --git a/Telegram.Api.PCL/Properties/AssemblyInfo.cs b/Telegram.Api.PCL/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..542fbf1 --- /dev/null +++ b/Telegram.Api.PCL/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Resources; +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("Telegram.Api.PCL")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Telegram.Api.PCL")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: NeutralResourcesLanguage("en")] + +// 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 Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Telegram.Api.PCL/Resources/AppResources.cs b/Telegram.Api.PCL/Resources/AppResources.cs new file mode 100755 index 0000000..ed21f71 --- /dev/null +++ b/Telegram.Api.PCL/Resources/AppResources.cs @@ -0,0 +1,62 @@ +using Windows.ApplicationModel.Resources; + +namespace Telegram.Api.Resources +{ + internal class AppResources + { + private static ResourceLoader resourceMan; + + //private static global::System.Globalization.CultureInfo resourceCulture; + + internal AppResources() + { + } + + internal static ResourceLoader ResourceManager + { + get + { + if (ReferenceEquals(resourceMan, null)) + { + var temp = ResourceLoader.GetForViewIndependentUse("TelegramClient.Tasks/Resources"); + resourceMan = temp; + } + + return resourceMan; + } + } + + /// + /// Looks up a localized string similar to Deleted User. + /// + internal static string DeletedUser + { + get + { + return ResourceManager.GetString("DeletedUser"); + } + } + + /// + /// Looks up a localized string similar to Empty User. + /// + internal static string EmptyUser + { + get + { + return ResourceManager.GetString("EmptyUser"); + } + } + + /// + /// Looks up a localized string similar to Saved Messages. + /// + internal static string SavedMessages + { + get + { + return ResourceManager.GetString("SavedMessages"); + } + } + } +} \ No newline at end of file diff --git a/Telegram.Api.PCL/Resources/de/Resources.resw b/Telegram.Api.PCL/Resources/de/Resources.resw new file mode 100755 index 0000000..02472e2 --- /dev/null +++ b/Telegram.Api.PCL/Resources/de/Resources.resw @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Gelöschtes Konto + + + Gelöschtes Konto + + + Saved Messages + + \ No newline at end of file diff --git a/Telegram.Api.PCL/Resources/en/Resources.resw b/Telegram.Api.PCL/Resources/en/Resources.resw new file mode 100755 index 0000000..b6cd68e --- /dev/null +++ b/Telegram.Api.PCL/Resources/en/Resources.resw @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Deleted account + + + Deleted account + + + Saved messages + + \ No newline at end of file diff --git a/Telegram.Api.PCL/Resources/es/Resources.resw b/Telegram.Api.PCL/Resources/es/Resources.resw new file mode 100755 index 0000000..a4da8e8 --- /dev/null +++ b/Telegram.Api.PCL/Resources/es/Resources.resw @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Cuenta eliminada + + + Cuenta eliminada + + + Saved Messages + + \ No newline at end of file diff --git a/Telegram.Api.PCL/Resources/it/Resources.resw b/Telegram.Api.PCL/Resources/it/Resources.resw new file mode 100755 index 0000000..6783aee --- /dev/null +++ b/Telegram.Api.PCL/Resources/it/Resources.resw @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Account eliminato + + + Account eliminato + + + Saved Messages + + \ No newline at end of file diff --git a/Telegram.Api.PCL/Resources/nl/Resources.resw b/Telegram.Api.PCL/Resources/nl/Resources.resw new file mode 100755 index 0000000..0d0dab8 --- /dev/null +++ b/Telegram.Api.PCL/Resources/nl/Resources.resw @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Verwijderd account + + + Verwijderd account + + + Saved Messages + + \ No newline at end of file diff --git a/Telegram.Api.PCL/Resources/pt/Resources.resw b/Telegram.Api.PCL/Resources/pt/Resources.resw new file mode 100755 index 0000000..8529f03 --- /dev/null +++ b/Telegram.Api.PCL/Resources/pt/Resources.resw @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Conta excluída + + + Conta excluída + + + Saved Messages + + \ No newline at end of file diff --git a/Telegram.Api.PCL/Resources/ru/Resources.resw b/Telegram.Api.PCL/Resources/ru/Resources.resw new file mode 100755 index 0000000..7d370c0 --- /dev/null +++ b/Telegram.Api.PCL/Resources/ru/Resources.resw @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Удаленный аккаунт + + + Удаленный аккаунт + + + Избранное + + \ No newline at end of file diff --git a/Telegram.Api.PCL/Telegram.Api.PCL.csproj b/Telegram.Api.PCL/Telegram.Api.PCL.csproj new file mode 100755 index 0000000..e323214 --- /dev/null +++ b/Telegram.Api.PCL/Telegram.Api.PCL.csproj @@ -0,0 +1,2058 @@ + + + + + 12.0 + Debug + AnyCPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1} + Library + Properties + Telegram.Api + Telegram.Api.PCL + en-US + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Profile32 + v4.6 + ..\..\..\ + true + + + true + full + false + bin\Debug\ + TRACE;DEBUG;WIN_RT;WP8 + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE;WIN_RT;WP8 + prompt + 4 + + + + + + + + Compression\GZipDeflateStream.cs + + + Constants.cs + + + Hash\CRC32\CRC.cs + + + Extensions\ActionExtensions.cs + + + Extensions\HttpWebRequestExtensions.cs + + + Extensions\StreamExtensions.cs + + + Extensions\TLObjectExtensions.cs + + + Helpers\Execute.cs + + + Helpers\FileUtils.cs + + + Helpers\SettingsHelper.cs + + + Helpers\Utils.cs + + + Hash\MD5\MD5.cs + + + Hash\MD5\MD5CryptoServiceProvider.cs + + + Hash\MD5\MD5Managed.cs + + + Services\Cache\Context.cs + + + Services\Cache\EventArgs\DialogAddedEventArgs.cs + + + Services\Cache\EventArgs\TopMessageUpdatedEventArgs.cs + + + Services\Cache\ICacheService.cs + + + Services\Cache\InMemoryCacheService.cs + + + Services\Cache\InMemoryDatabase.cs + + + Services\Connection\ConnectionService.cs + + + Services\DCOptionItem.cs + + + Services\DelayedItem.cs + + + Services\FileManager\AudioFileManager.cs + + + Services\FileManager\DocumentFileManager.cs + + + Services\FileManager\DownloadableItem.cs + + + Services\FileManager\DownloadablePart.cs + + + Services\FileManager\DownloadingCanceledEventArgs.cs + + + Services\FileManager\EncryptedFileManager.cs + + + Services\FileManager\FileManager.cs + + + Services\FileManager\IAudioFileManager.cs + + + Services\FileManager\IDocumentFileManager.cs + + + Services\FileManager\IEncryptedFileManager.cs + + + Services\FileManager\IFileManager.cs + + + Services\FileManager\IUploadAudioFileManager.cs + + + Services\FileManager\IUploadFileManager.cs + + + Services\FileManager\IUploadVideoFileManager.cs + + + Services\FileManager\IVideoFileManager.cs + + + Services\FileManager\ProgressChangedEventArgs.cs + + + Services\FileManager\UploadAudioFileManager.cs + + + Services\FileManager\UploadFileManager.cs + + + Services\FileManager\UploadVideoFileManager.cs + + + Services\FileManager\VideoFileManager.cs + + + Services\FileManager\Worker.cs + + + Services\HistoryItem.cs + + + Services\IMTProtoService.cs + + + Services\MTProtoService.Account.cs + + + Services\MTProtoService.Auth.cs + + + Services\MTProtoService.ByTransport.cs + + + Services\MTProtoService.Config.cs + + + Services\MTProtoService.Contacts.cs + + + Services\MTProtoService.cs + + + Services\MTProtoService.DHKeyExchange.cs + + + Services\MTProtoService.Help.cs + + + Services\MTProtoService.Helpers.cs + + + Services\MTProtoService.HttpLongPoll.cs + + + Services\MTProtoService.Messages.cs + + + Services\MTProtoService.Photos.cs + + + Services\MTProtoService.SecretChats.cs + + + Services\MTProtoService.SendingQueue.cs + + + Services\MTProtoService.Stuff.cs + + + Services\MTProtoService.Updates.cs + + + Services\MTProtoService.Upload.cs + + + Services\MTProtoService.Users.cs + + + Services\ServiceBase.cs + + + Services\Updates\IUpdatesService.cs + + + Services\Updates\ReceiveUpdatesEventArgs.cs + + + Services\Updates\UpdatesBySeqComparer.cs + + + Services\Updates\UpdatesService.cs + + + TL\Functions\Account\TLCheckUsername.cs + + + TL\Functions\Account\TLDeleteAccount.cs + + + TL\Functions\Account\TLGetAccountTTL.cs + + + TL\Functions\Account\TLGetNotifySettings.cs + + + TL\Functions\Account\TLGetPrivacy.cs + + + TL\Functions\Account\TLRegisterDevice.cs + + + TL\Functions\Account\TLResetNotifySettings.cs + + + TL\Functions\Account\TLSetPrivacy.cs + + + TL\Functions\Account\TLUnregisterDevice.cs + + + TL\Functions\Account\TLUpdateNotifySettings.cs + + + TL\Functions\Account\TLUpdateProfile.cs + + + TL\Functions\Account\TLUpdateStatus.cs + + + TL\Functions\Account\TLUpdateUserName.cs + + + TL\Functions\Auth\TLCheckPhone.cs + + + TL\Functions\Auth\TLExportAuthorization.cs + + + TL\Functions\Auth\TLImportAuthorization.cs + + + TL\Functions\Auth\TLLogOut.cs + + + TL\Functions\Auth\TLResetAuthorizations.cs + + + TL\Functions\Auth\TLSendCall.cs + + + TL\Functions\Auth\TLSendCode.cs + + + TL\Functions\Auth\TLSendInvites.cs + + + TL\Functions\Auth\TLSendSms.cs + + + TL\Functions\Auth\TLSignIn.cs + + + TL\Functions\Auth\TLSignUp.cs + + + TL\Functions\Contacts\TLBlock.cs + + + TL\Functions\Contacts\TLDeleteContact.cs + + + TL\Functions\Contacts\TLDeleteContacts.cs + + + TL\Functions\Contacts\TLGetBlocked.cs + + + TL\Functions\Contacts\TLGetContacts.cs + + + TL\Functions\Contacts\TLGetStatuses.cs + + + TL\Functions\Contacts\TLImportContacts.cs + + + TL\Functions\Contacts\TLSearch.cs + + + TL\Functions\Contacts\TLUnblock.cs + + + TL\Functions\DHKeyExchange\TLReqDHParams.cs + + + TL\Functions\DHKeyExchange\TLReqPQ.cs + + + TL\Functions\DHKeyExchange\TLSetClientDHParams.cs + + + TL\Functions\Help\TLGetConfig.cs + + + TL\Functions\Help\TLGetInviteText.cs + + + TL\Functions\Help\TLGetNearestDC.cs + + + TL\Functions\Help\TLGetSupport.cs + + + TL\Functions\Help\TLInvokeWithLayerN.cs + + + TL\Functions\Messages\TLAcceptEncryption.cs + + + TL\Functions\Messages\TLAddChatUser.cs + + + TL\Functions\Messages\TLCreateChat.cs + + + TL\Functions\Messages\TLDeleteChatUser.cs + + + TL\Functions\Messages\TLDeleteHistory.cs + + + TL\Functions\Messages\TLDeleteMessages.cs + + + TL\Functions\Messages\TLDiscardEncryption.cs + + + TL\Functions\Messages\TLEditChatPhoto.cs + + + TL\Functions\Messages\TLEditChatTitle.cs + + + TL\Functions\Messages\TLForwardMessage.cs + + + TL\Functions\Messages\TLForwardMessages.cs + + + TL\Functions\Messages\TLGetChats.cs + + + TL\Functions\Messages\TLGetDHConfig.cs + + + TL\Functions\Messages\TLGetDialogs.cs + + + TL\Functions\Messages\TLGetFullChat.cs + + + TL\Functions\Messages\TLGetHistory.cs + + + TL\Functions\Messages\TLGetMessages.cs + + + TL\Functions\Messages\TLReadEncryptedHistory.cs + + + TL\Functions\Messages\TLReadHistory.cs + + + TL\Functions\Messages\TLReadMessageContents.cs + + + TL\Functions\Messages\TLReceivedMessages.cs + + + TL\Functions\Messages\TLReceivedQueue.cs + + + TL\Functions\Messages\TLRequestEncryption.cs + + + TL\Functions\Messages\TLRestoreMessages.cs + + + TL\Functions\Messages\TLSearch.cs + + + TL\Functions\Messages\TLSendBroadcast.cs + + + TL\Functions\Messages\TLSendEncrypted.cs + + + TL\Functions\Messages\TLSendEncryptedFile.cs + + + TL\Functions\Messages\TLSendEncryptedService.cs + + + TL\Functions\Messages\TLSendMedia.cs + + + TL\Functions\Messages\TLSendMessage.cs + + + TL\Functions\Messages\TLSetEncryptedTyping.cs + + + TL\Functions\Messages\TLSetTyping.cs + + + TL\Functions\Photos\TLGetUserPhotos.cs + + + TL\Functions\Photos\TLUpdateProfilePhoto.cs + + + TL\Functions\Photos\TLUploadProfilePhoto.cs + + + TL\Functions\Stuff\TLGetFutureSalts.cs + + + TL\Functions\Stuff\TLHttpWait.cs + + + TL\Functions\Stuff\TLMessageAcknowledgments.cs + + + TL\Functions\Stuff\TLRPCDropAnswer.cs + + + TL\Functions\Updates\TLGetDifference.cs + + + TL\Functions\Updates\TLGetState.cs + + + TL\Functions\Upload\TLGetFile.cs + + + TL\Functions\Upload\TLSaveFilePart.cs + + + TL\Functions\Users\TLGetFullUser.cs + + + TL\Functions\Users\TLGetUsers.cs + + + TL\Interfaces\IBytes.cs + + + TL\Interfaces\IFullName.cs + + + TL\Interfaces\IInputPeer.cs + + + TL\Interfaces\ISelectable.cs + + + TL\Interfaces\IVIsibility.cs + + + TL\TLAffectedHistory.cs + + + TL\TLAudio.cs + + + TL\TLAuthorization.cs + + + TL\TLBadMessageNotification.cs + + + TL\TLBadServerSalt.cs + + + TL\TLBool.cs + + + TL\TLChat.cs + + + TL\TLChatFull.cs + + + TL\TLChatParticipant.cs + + + TL\TLChatParticipants.cs + + + TL\TLChats.cs + + + TL\TLCheckedPhone.cs + + + TL\TLClientDHInnerData.cs + + + TL\TLConfig.cs + + + TL\TLContact.cs + + + TL\TLContactBlocked.cs + + + TL\TLContactFound.cs + + + TL\TLContacts.cs + + + TL\TLContactsBlocked.cs + + + TL\TLContactsFound.cs + + + TL\TLContactStatus.cs + + + TL\TLContainerTransportMessage.cs + + + TL\TLDCOption.cs + + + TL\TLDecryptedMessage.cs + + + TL\TLDecryptedMessageAction.cs + + + TL\TLDecryptedMessageLayer.cs + + + TL\TLDecryptedMessageMedia.cs + + + TL\TLDHConfig.cs + + + TL\TLDHGen.cs + + + TL\TLDialog.cs + + + TL\TLDialogs.cs + + + TL\TLDifference.cs + + + TL\TLDocument.cs + + + TL\TLDouble.cs + + + TL\TLEncryptedChat.cs + + + TL\TLEncryptedFile.cs + + + TL\TLEncryptedMessage.cs + + + TL\TLExportedAuthorization.cs + + + TL\TLFile.cs + + + TL\TLFileLocation.cs + + + TL\TLFileType.cs + + + TL\TLForeignLink.cs + + + TL\TLFutureSalt.cs + + + TL\TLGeoPoint.cs + + + TL\TLGzipPacked.cs + + + TL\TLImportedContact.cs + + + TL\TLImportedContacts.cs + + + TL\TLInitConnection.cs + + + TL\TLInputAudio.cs + + + TL\TLInputChatPhoto.cs + + + TL\TLInputContact.cs + + + TL\TLInputDocument.cs + + + TL\TLInputEncryptedChat.cs + + + TL\TLInputEncryptedFile.cs + + + TL\TLInputEncryptedFileBigUploaded.cs + + + TL\TLInputEncryptedFileLocation.cs + + + TL\TLInputFile.cs + + + TL\TLInputFileBig.cs + + + TL\TLInputFileLocation.cs + + + TL\TLInputGeoPoint.cs + + + TL\TLInputMedia.cs + + + TL\TLInputMessagesFilter.cs + + + TL\TLInputNotifyPeer.cs + + + TL\TLInputPeerBase.cs + + + TL\TLInputPeerNotifyEvents.cs + + + TL\TLInputPeerNotifySettings.cs + + + TL\TLInputPhoto.cs + + + TL\TLInputPhotoCrop.cs + + + TL\TLInputUser.cs + + + TL\TLInputVideo.cs + + + TL\TLInt.cs + + + TL\TLInt128.cs + + + TL\TLInt256.cs + + + TL\TLInviteText.cs + + + TL\TLInvokeAfterMsg.cs + + + TL\TLLink.cs + + + TL\TLLong.cs + + + TL\TLMessage.cs + + + TL\TLMessage.Encrypted.cs + + + TL\TLMessageAction.cs + + + TL\TLMessageContainer.cs + + + TL\TLMessageInfo.cs + + + TL\TLMessageMedia.cs + + + TL\TLMessages.cs + + + TL\TLMessagesAcknowledgment.cs + + + TL\TLMessagesChatFull.cs + + + TL\TLMyLink.cs + + + TL\TLNearestDC.cs + + + TL\TLNewSessionCreated.cs + + + TL\TLNonEncryptedMessage.cs + + + TL\TLNotifyPeer.cs + + + TL\TLNull.cs + + + TL\TLObject.cs + + + TL\TLObjectGenerator.cs + + + TL\TLPeer.cs + + + TL\TLPeerNotifyEvents.cs + + + TL\TLPeerNotifySettings.cs + + + TL\TLPhoto.cs + + + TL\TLPhotos.cs + + + TL\TLPhotoSize.cs + + + TL\TLPhotosPhoto.cs + + + TL\TLPong.cs + + + TL\TLPQInnerData.cs + + + TL\TLResponse.cs + + + TL\TLResPQ.cs + + + TL\TLRPCDropAnswer.cs + + + TL\TLRPCError.cs + + + TL\TLRPCResult.cs + + + TL\TLSendMessageAction.cs + + + TL\TLSentCode.cs + + + TL\TLSentEncryptedFile.cs + + + TL\TLSentEncryptedMessage.cs + + + TL\TLSentMessage.cs + + + TL\TLServerDHInnerData.cs + + + TL\TLServerDHParams.cs + + + TL\TLServerFile.cs + + + TL\TLSignatures.cs + + + TL\TLState.cs + + + TL\TLStatedMessage.cs + + + TL\TLStatedMessages.cs + + + TL\TLString.cs + + + TL\TLSupport.cs + + + TL\TLUpdate.cs + + + TL\TLUpdates.cs + + + TL\TLUserBase.cs + + + TL\TLUserFull.cs + + + TL\TLUserStatus.cs + + + TL\TLUtils.cs + + + TL\TLUtils.Log.cs + + + TL\TLVector.cs + + + TL\TLVideo.cs + + + TL\TLWallpaperSolid.cs + + + Transport\DataEventArgs.cs + + + Transport\ITransport.cs + + + Transport\ITransportService.cs + + + Transport\TCPTransportBase.cs + + + Transport\TCPTransportResult.cs + + + Transport\TransportService.cs + + + Services\FileManager\IWebFileManager.cs + + + Services\FileManager\WebFileManager.cs + + + TL\Functions\Account\TLAcceptAuthorization.cs + + + TL\Functions\Account\TLDeleteSecureValue.cs + + + TL\Functions\Account\TLGetAllSecureValues.cs + + + TL\Functions\Account\TLGetAuthorizationForm.cs + + + TL\Functions\Account\TLGetSecureValue.cs + + + TL\Functions\Account\TLGetWebAuthorizations.cs + + + TL\Functions\Account\TLInitTakeoutSession.cs + + + TL\Functions\Account\TLResetWebAuthorization.cs + + + TL\Functions\Account\TLResetWebAuthorizations.cs + + + TL\Functions\Account\TLSaveSecureValue.cs + + + TL\Functions\Account\TLSendVerifyEmailCode.cs + + + TL\Functions\Account\TLSendVerifyPhoneCode.cs + + + TL\Functions\Account\TLVerifyEmail.cs + + + TL\Functions\Account\TLVerifyEmailCode.cs + + + TL\Functions\Account\TLVerifyPhone.cs + + + TL\Functions\Auth\TLBindTempAuthKey.cs + + + TL\Functions\Channels\TLChangeFeedBroadcast.cs + + + TL\Functions\Channels\TLGetFeed.cs + + + TL\Functions\Channels\TLReadFeed.cs + + + TL\Functions\Channels\TLSetFeedBroadcasts.cs + + + TL\Functions\Contacts\TLGetSaved.cs + + + TL\Functions\Help\TLGetDeepLinkInfo.cs + + + TL\Functions\Help\TLGetPassportConfig.cs + + + TL\Functions\Help\TLGetProxyData.cs + + + TL\Functions\Messages\TLClearAllDrafts.cs + + + TL\Functions\Messages\TLGetDialogUnreadMarks.cs + + + TL\Functions\Messages\TLMarkDialogUnread.cs + + + TL\Functions\Messages\TLReport.cs + + + TL\Functions\Messages\TLSearchStickerSets.cs + + + TL\Functions\Messages\TLToggleTopPeers.cs + + + TL\Functions\Upload\TLGetWebFile.cs + + + TL\Functions\Users\TLSetSecureValueErrors.cs + + + TL\TLAppUpdate.cs + + + TL\TLAuthorizationForm.cs + + + TL\TLContactsSettings.cs + + + TL\TLDeepLinkInfo.cs + + + TL\TLDialogPeer.cs + + + TL\TLFeedBroadcasts.cs + + + TL\TLFeedPosition.cs + + + TL\TLFeedSources.cs + + + TL\TLFoundStickerSets.cs + + + TL\TLInputCheckPasswordSRP.cs + + + TL\TLInputClientProxy.cs + + + TL\TLInputDialogPeer.cs + + + TL\TLInputMessage.cs + + + TL\TLInputSecureFile.cs + + + TL\TLInputSecureValue.cs + + + TL\TLInvokeWithMessageRange.cs + + + TL\TLPassportConfig.cs + + + TL\TLPasswordKdfAlgo.cs + + + TL\TLProxyData.cs + + + TL\TLSavedPhoneContact.cs + + + TL\TLSecureCredentialsEncrypted.cs + + + TL\TLSecureData.cs + + + TL\TLSecureFile.cs + + + TL\TLSecurePasswordKdfAlgo.cs + + + TL\TLSecureRequiredType.cs + + + TL\TLSecureSecretSettings.cs + + + TL\TLSecureValue.cs + + + TL\TLSecureValueError.cs + + + TL\TLSecureValueHash.cs + + + TL\TLSecureValuePlainData.cs + + + TL\TLSecureValueType.cs + + + TL\TLSentEmailCode.cs + + + TL\TLTakeout.cs + + + TL\TLTermsOfServiceUpdate.cs + + + TL\TLWebAuthorization.cs + + + TL\TLWebAuthorizations.cs + + + Transport\TCPTransportWinRT.cs + + + Aggregator\EventAggregator.cs + + + Aggregator\ExtensionMethods.cs + + + Helpers\Notifications.cs + + + Logs\Log.cs + + + Services\Connection\PublicConfigService.cs + + + Services\DeviceInfo\EmptyDeviceInfoService.cs + + + Services\DeviceInfo\IDeviceInfo.cs + + + Services\FileManager\FileManagerBase.cs + + + Services\MTProtoService.Channel.cs + + + Services\MTProtoService.Langpack.cs + + + Services\MTProtoService.Payments.cs + + + Services\MTProtoService.Phone.cs + + + TL\Functions\Account\TLChangePhone.cs + + + TL\Functions\Account\TLCheckPassword.cs + + + TL\Functions\Account\TLConfirmPhone.cs + + + TL\Functions\Account\TLGetAuthorizations.cs + + + TL\Functions\Account\TLGetPassword.cs + + + TL\Functions\Account\TLGetPasswordSettings.cs + + + TL\Functions\Account\TLGetTmpPassword.cs + + + TL\Functions\Account\TLGetWallPapers.cs + + + TL\Functions\Account\TLRecoverPassword.cs + + + TL\Functions\Account\TLReportPeer.cs + + + TL\Functions\Account\TLRequestPasswordRecovery.cs + + + TL\Functions\Account\TLResetAuthorization.cs + + + TL\Functions\Account\TLResetPassword.cs + + + TL\Functions\Account\TLSendChangePhoneCode.cs + + + TL\Functions\Account\TLSendConfirmPhoneCode.cs + + + TL\Functions\Account\TLSetPassword.cs + + + TL\Functions\Account\TLUpdateDeviceLocked.cs + + + TL\Functions\Account\TLUpdatePasswordSettings.cs + + + TL\Functions\Auth\TLCancelCode.cs + + + TL\Functions\Auth\TLResendCode.cs + + + TL\Functions\Channels\TLCheckUsername.cs + + + TL\Functions\Channels\TLCreateChannel.cs + + + TL\Functions\Channels\TLDeleteChannel.cs + + + TL\Functions\Channels\TLDeleteChannelMessages.cs + + + TL\Functions\Channels\TLDeleteHistory.cs + + + TL\Functions\Channels\TLDeleteUserHistory.cs + + + TL\Functions\Channels\TLEditAbout.cs + + + TL\Functions\Channels\TLEditAdmin.cs + + + TL\Functions\Channels\TLEditMessage.cs + + + TL\Functions\Channels\TLEditPhoto.cs + + + TL\Functions\Channels\TLEditTitle.cs + + + TL\Functions\Channels\TLExportInvite.cs + + + TL\Functions\Channels\TLExportMessageLink.cs + + + TL\Functions\Channels\TLGetAdminedPublicChannels.cs + + + TL\Functions\Channels\TLGetChannels.cs + + + TL\Functions\Channels\TLGetDialogs.cs + + + TL\Functions\Channels\TLGetFullChannel.cs + + + TL\Functions\Channels\TLGetImportantHistory.cs + + + TL\Functions\Channels\TLGetMessageEditData.cs + + + TL\Functions\Channels\TLGetMessages.cs + + + TL\Functions\Channels\TLGetParticipant.cs + + + TL\Functions\Channels\TLGetParticipants.cs + + + TL\Functions\Channels\TLInviteToChannel.cs + + + TL\Functions\Channels\TLJoinChannel.cs + + + TL\Functions\Channels\TLKickFromChannel.cs + + + TL\Functions\Channels\TLLeaveChannel.cs + + + TL\Functions\Channels\TLReadHistory.cs + + + TL\Functions\Channels\TLReadMessageContents.cs + + + TL\Functions\Channels\TLReportSpam.cs + + + TL\Functions\Channels\TLSetStickers.cs + + + TL\Functions\Channels\TLToggleComments.cs + + + TL\Functions\Channels\TLToggleInvites.cs + + + TL\Functions\Channels\TLTogglePreHistoryHidden.cs + + + TL\Functions\Channels\TLToggleSignatures.cs + + + TL\Functions\Channels\TLUpdateChannelUsername.cs + + + TL\Functions\Channels\TLUpdatePinnedMessage.cs + + + TL\Functions\Contacts\TLGetTopPeers.cs + + + TL\Functions\Contacts\TLResetSaved.cs + + + TL\Functions\Contacts\TLResetTopPeerRating.cs + + + TL\Functions\Contacts\TLResolveUsername.cs + + + TL\Functions\Help\TLGetAppChangelog.cs + + + TL\Functions\Help\TLGetCdnConfig.cs + + + TL\Functions\Help\TLGetRecentMeUrls.cs + + + TL\Functions\Help\TLGetTermsOfService.cs + + + TL\Functions\Help\TLInvokeWithoutUpdates.cs + + + TL\Functions\Langpack\TLGetDifference.cs + + + TL\Functions\Langpack\TLGetLangPack.cs + + + TL\Functions\Langpack\TLGetLanguages.cs + + + TL\Functions\Langpack\TLGetStrings.cs + + + TL\Functions\Messages\TLBotGetCallbackAnswer.cs + + + TL\Functions\Messages\TLCheckChatInvite.cs + + + TL\Functions\Messages\TLClearRecentStickers.cs + + + TL\Functions\Messages\TLDeactivateChat.cs + + + TL\Functions\Messages\TLEditChatAdmin.cs + + + TL\Functions\Messages\TLExportChatInvite.cs + + + TL\Functions\Messages\TLFaveSticker.cs + + + TL\Functions\Messages\TLGetAllDrafts.cs + + + TL\Functions\Messages\TLGetAllStickers.cs + + + TL\Functions\Messages\TLGetArchivedStickers.cs + + + TL\Functions\Messages\TLGetAttachedStickers.cs + + + TL\Functions\Messages\TLGetCommonChats.cs + + + TL\Functions\Messages\TLGetDocumentByHash.cs + + + TL\Functions\Messages\TLGetFavedStickers.cs + + + TL\Functions\Messages\TLGetFeaturedStickers.cs + + + TL\Functions\Messages\TLGetInlineBotResults.cs + + + TL\Functions\Messages\TLGetMaskStickers.cs + + + TL\Functions\Messages\TLGetPeerDialogs.cs + + + TL\Functions\Messages\TLGetPeerSettings.cs + + + TL\Functions\Messages\TLGetPinnedDialogs.cs + + + TL\Functions\Messages\TLGetRecentLocations.cs + + + TL\Functions\Messages\TLGetRecentStickers.cs + + + TL\Functions\Messages\TLGetSavedGifs.cs + + + TL\Functions\Messages\TLGetStickers.cs + + + TL\Functions\Messages\TLGetStickerSet.cs + + + TL\Functions\Messages\TLGetUnreadMentions.cs + + + TL\Functions\Messages\TLGetUnusedStickers.cs + + + TL\Functions\Messages\TLGetWebPage.cs + + + TL\Functions\Messages\TLGetWebPagePreview.cs + + + TL\Functions\Messages\TLHideReportSpam.cs + + + TL\Functions\Messages\TLImportChatInvite.cs + + + TL\Functions\Messages\TLInstallStickerSet.cs + + + TL\Functions\Messages\TLMigrateChat.cs + + + TL\Functions\Messages\TLReadFeaturedStickers.cs + + + TL\Functions\Messages\TLReadMentions.cs + + + TL\Functions\Messages\TLReorderPinnedDialogs.cs + + + TL\Functions\Messages\TLReorderStickerSets.cs + + + TL\Functions\Messages\TLReportSpam.cs + + + TL\Functions\Messages\TLSaveDraft.cs + + + TL\Functions\Messages\TLSaveGif.cs + + + TL\Functions\Messages\TLSearchGifs.cs + + + TL\Functions\Messages\TLSendInlineBotResult.cs + + + TL\Functions\Messages\TLSendMultiMedia.cs + + + TL\Functions\Messages\TLSetBotCallbackAnswer.cs + + + TL\Functions\Messages\TLSetInlineBotResults.cs + + + TL\Functions\Messages\TLStartBot.cs + + + TL\Functions\Messages\TLToggleChatAdmins.cs + + + TL\Functions\Messages\TLToggleDialogPin.cs + + + TL\Functions\Messages\TLUninstallStickerSet.cs + + + TL\Functions\Messages\TLUploadMedia.cs + + + TL\Functions\Payments\TLClearSavedInfo.cs + + + TL\Functions\Payments\TLGetPaymentForm.cs + + + TL\Functions\Payments\TLGetPaymentReceipt.cs + + + TL\Functions\Payments\TLGetSavedInfo.cs + + + TL\Functions\Payments\TLSendPaymentForm.cs + + + TL\Functions\Payments\TLValidateRequestedInfo.cs + + + TL\Functions\Phone\TLAcceptCall.cs + + + TL\Functions\Phone\TLConfirmCall.cs + + + TL\Functions\Phone\TLDiscardCall.cs + + + TL\Functions\Phone\TLGetCallConfig.cs + + + TL\Functions\Phone\TLReceivedCall.cs + + + TL\Functions\Phone\TLRequestCall.cs + + + TL\Functions\Phone\TLSaveCallDebug.cs + + + TL\Functions\Phone\TLSetCallRating.cs + + + TL\Functions\Updates\TLGetChannelDifference.cs + + + TL\Functions\Upload\TLGetCdnFile.cs + + + TL\Functions\Upload\TLReuploadCdnFile.cs + + + TL\TLAccountAuthorization.cs + + + TL\TLAccountAuthorizations.cs + + + TL\TLAccountDaysTTL.cs + + + TL\TLActionInfo.cs + + + TL\TLAdminLogResults.cs + + + TL\TLAffectedMessages.cs + + + TL\TLAllStrickers.cs + + + TL\TLAppChangelogBase.cs + + + TL\TLArchivedStickers.cs + + + TL\TLBotCallbackAnswer.cs + + + TL\TLBotCommand.cs + + + TL\TLBotInfo.cs + + + TL\TLBotInlineMessage.cs + + + TL\TLBotInlineResult.cs + + + TL\TLBotResults.cs + + + TL\TLCallsSecurity.cs + + + TL\TLCameraSettings.cs + + + TL\TLCdnConfig.cs + + + TL\TLCdnFile.cs + + + TL\TLCdnPublicKey.cs + + + TL\TLChannelAdminLogEvent.cs + + + TL\TLChannelAdminLogEventAction.cs + + + TL\TLChannelAdminLogEventsFilter.cs + + + TL\TLChannelAdminRights.cs + + + TL\TLChannelBannedRights.cs + + + TL\TLChannelDifference.cs + + + TL\TLChannelMessagesFiler.cs + + + TL\TLChannelParticipant.cs + + + TL\TLChannelParticipantRole.cs + + + TL\TLChannelParticipantsFilter.cs + + + TL\TLChatInvite.cs + + + TL\TLChatSettings.cs + + + TL\TLCodeType.cs + + + TL\TLConfigSimple.cs + + + TL\TLContactLink.cs + + + TL\TLDataJSON.cs + + + TL\TLDisabledFeature.cs + + + TL\TLDocumentAttribute.cs + + + TL\TLDraftMessage.cs + + + TL\TLExportedMessageLink.cs + + + TL\TLFavedStickers.cs + + + TL\TLFeaturedStickers.cs + + + TL\TLFoundGif.cs + + + TL\TLFoundGifs.cs + + + TL\TLGame.cs + + + TL\TLHashtagItem.cs + + + TL\TLHighScore.cs + + + TL\TLHighScores.cs + + + TL\TLInlineBotSwitchPM.cs + + + TL\TLInputBotInlineMessage.cs + + + TL\TLInputBotInlineMessageId.cs + + + TL\TLInputBotInlineResult.cs + + + TL\TLInputChatBase.cs + + + TL\TLInputGame.cs + + + TL\TLInputMessageEntityMentionName.cs + + + TL\TLInputPaymentCredentials.cs + + + TL\TLInputPhoneCall.cs + + + TL\TLInputPrivacyKey.cs + + + TL\TLInputPrivacyRule.cs + + + TL\TLInputReportReason.cs + + + TL\TLInputSingleMedia.cs + + + TL\TLInputStickeredMedia.cs + + + TL\TLInputStickerSet.cs + + + TL\TLInputWebDocument.cs + + + TL\TLInvoice.cs + + + TL\TLIpPort.cs + + + TL\TLKeyboardButton.cs + + + TL\TLKeyboardButtonRow.cs + + + TL\TLLabeledPrice.cs + + + TL\TLLangPackDifference.cs + + + TL\TLLangPackLanguage.cs + + + TL\TLLangPackString.cs + + + TL\TLMaskCoords.cs + + + TL\TLMessageEditData.cs + + + TL\TLMessageEntity.cs + + + TL\TLMessageFwdHeader.cs + + + TL\TLMessageGroup.cs + + + TL\TLMessageRange.cs + + + TL\TLMessagesChannelParticipants.cs + + + TL\TLMessagesStickerSet.cs + + + TL\TLPage.cs + + + TL\TLPageBlock.cs + + + TL\TLPasscodeParams.cs + + + TL\TLPassword.cs + + + TL\TLPasswordInputSettings.cs + + + TL\TLPasswordRecovery.cs + + + TL\TLPasswordSettings.cs + + + TL\TLPaymentCharge.cs + + + TL\TLPaymentForm.cs + + + TL\TLPaymentReceipt.cs + + + TL\TLPaymentRequestedInfo.cs + + + TL\TLPaymentResult.cs + + + TL\TLPaymentSavedCredentialsCard.cs + + + TL\TLPeerDialogs.cs + + + TL\TLPeerSettings.cs + + + TL\TLPhoneCall.cs + + + TL\TLPhoneCallDiscardReason.cs + + + TL\TLPhoneCallProtocol.cs + + + TL\TLPhoneConnection.cs + + + TL\TLPhonePhoneCall.cs + + + TL\TLPhotoPickerSettings.cs + + + TL\TLPopularContact.cs + + + TL\TLPostAddress.cs + + + TL\TLPrivacyKey.cs + + + TL\TLPrivacyRule.cs + + + TL\TLPrivacyRules.cs + + + TL\TLProxyConfig.cs + + + TL\TLReceivedNotifyMessage.cs + + + TL\TLRecentlyUsedSticker.cs + + + TL\TLRecentMeUrl.cs + + + TL\TLRecentMeUrls.cs + + + TL\TLRecentStickers.cs + + + TL\TLReplyKeyboardMarkup.cs + + + TL\TLResolvedPeer.cs + + + TL\TLResultInfo.cs + + + TL\TLRichText.cs + + + TL\TLSavedGifs.cs + + + TL\TLSavedInfo.cs + + + TL\TLSentChangePhoneCode.cs + + + TL\TLSentCodeType.cs + + + TL\TLShippingOption.cs + + + TL\TLStickerPack.cs + + + TL\TLStickers.cs + + + TL\TLStickerSet.cs + + + TL\TLStickerSetCovered.cs + + + TL\TLStickerSetInstallResult.cs + + + TL\TLTermsOfService.cs + + + TL\TLTmpPassword.cs + + + TL\TLTopPeer.cs + + + TL\TLTopPeerCategory.cs + + + TL\TLTopPeerCategoryPeers.cs + + + TL\TLTopPeers.cs + + + TL\TLValidatedRequestedInfo.cs + + + TL\TLWebDocument.cs + + + TL\TLWebFile.cs + + + TL\TLWebPage.cs + + + Transport\SocksProxy.cs + + + WindowsPhone\BigInteger.cs + + + WindowsPhone\Tuple.cs + + + + + + + + ..\packages\Portable.BouncyCastle.1.7.0.2\lib\portable-net4+sl5+wp8+win8+wpa81+MonoTouch10+MonoAndroid10+xamarinmac20+xamarinios10\crypto.dll + + + ..\packages\Rx-Core.2.2.5\lib\portable-win81+wpa81\System.Reactive.Core.dll + + + ..\packages\Rx-Interfaces.2.2.5\lib\portable-win81+wpa81\System.Reactive.Interfaces.dll + + + ..\packages\Rx-Linq.2.2.5\lib\portable-win81+wpa81\System.Reactive.Linq.dll + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/Telegram.Api.PCL/packages.config b/Telegram.Api.PCL/packages.config new file mode 100755 index 0000000..763c31d --- /dev/null +++ b/Telegram.Api.PCL/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Telegram.Api.WP8/Properties/AssemblyInfo.cs b/Telegram.Api.WP8/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..3f37542 --- /dev/null +++ b/Telegram.Api.WP8/Properties/AssemblyInfo.cs @@ -0,0 +1,44 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("Telegram.Api.WP8")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Telegram.Api.WP8")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[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("e79d5093-8038-4a5f-8a98-ca38c0d0886f")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/Telegram.Api.WP8/Resources/AppResources.Designer.cs b/Telegram.Api.WP8/Resources/AppResources.Designer.cs new file mode 100755 index 0000000..b21da73 --- /dev/null +++ b/Telegram.Api.WP8/Resources/AppResources.Designer.cs @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Telegram.Api.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class AppResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal AppResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Telegram.Api.Resources.AppResources", typeof(AppResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Deleted account. + /// + internal static string DeletedUser { + get { + return ResourceManager.GetString("DeletedUser", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Deleted account. + /// + internal static string EmptyUser { + get { + return ResourceManager.GetString("EmptyUser", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Saved messages. + /// + internal static string SavedMessages { + get { + return ResourceManager.GetString("SavedMessages", resourceCulture); + } + } + } +} diff --git a/Telegram.Api.WP8/Resources/AppResources.de.Designer.cs b/Telegram.Api.WP8/Resources/AppResources.de.Designer.cs new file mode 100755 index 0000000..e69de29 diff --git a/Telegram.Api.WP8/Resources/AppResources.de.resx b/Telegram.Api.WP8/Resources/AppResources.de.resx new file mode 100755 index 0000000..5355cd7 --- /dev/null +++ b/Telegram.Api.WP8/Resources/AppResources.de.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Gelöschtes Konto + + + Gelöschtes Konto + + + Gespeichertes + + \ No newline at end of file diff --git a/Telegram.Api.WP8/Resources/AppResources.es.Designer.cs b/Telegram.Api.WP8/Resources/AppResources.es.Designer.cs new file mode 100755 index 0000000..e69de29 diff --git a/Telegram.Api.WP8/Resources/AppResources.es.resx b/Telegram.Api.WP8/Resources/AppResources.es.resx new file mode 100755 index 0000000..efaa1da --- /dev/null +++ b/Telegram.Api.WP8/Resources/AppResources.es.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Cuenta eliminada + + + Cuenta eliminada + + + Mensajes guardados + + \ No newline at end of file diff --git a/Telegram.Api.WP8/Resources/AppResources.it.Designer.cs b/Telegram.Api.WP8/Resources/AppResources.it.Designer.cs new file mode 100755 index 0000000..e69de29 diff --git a/Telegram.Api.WP8/Resources/AppResources.it.resx b/Telegram.Api.WP8/Resources/AppResources.it.resx new file mode 100755 index 0000000..d49f70d --- /dev/null +++ b/Telegram.Api.WP8/Resources/AppResources.it.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Account eliminato + + + Account eliminato + + + Messaggi salvati + + \ No newline at end of file diff --git a/Telegram.Api.WP8/Resources/AppResources.nl.Designer.cs b/Telegram.Api.WP8/Resources/AppResources.nl.Designer.cs new file mode 100755 index 0000000..e69de29 diff --git a/Telegram.Api.WP8/Resources/AppResources.nl.resx b/Telegram.Api.WP8/Resources/AppResources.nl.resx new file mode 100755 index 0000000..cdaa9c2 --- /dev/null +++ b/Telegram.Api.WP8/Resources/AppResources.nl.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Verwijderd account + + + Verwijderd account + + + Bewaarde berichten + + \ No newline at end of file diff --git a/Telegram.Api.WP8/Resources/AppResources.pt.Designer.cs b/Telegram.Api.WP8/Resources/AppResources.pt.Designer.cs new file mode 100755 index 0000000..e69de29 diff --git a/Telegram.Api.WP8/Resources/AppResources.pt.resx b/Telegram.Api.WP8/Resources/AppResources.pt.resx new file mode 100755 index 0000000..11f89b6 --- /dev/null +++ b/Telegram.Api.WP8/Resources/AppResources.pt.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Conta excluída + + + Conta excluída + + + Saved messages + + \ No newline at end of file diff --git a/Telegram.Api.WP8/Resources/AppResources.resx b/Telegram.Api.WP8/Resources/AppResources.resx new file mode 100755 index 0000000..b6cd68e --- /dev/null +++ b/Telegram.Api.WP8/Resources/AppResources.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Deleted account + + + Deleted account + + + Saved messages + + \ No newline at end of file diff --git a/Telegram.Api.WP8/Resources/AppResources.ru.Designer.cs b/Telegram.Api.WP8/Resources/AppResources.ru.Designer.cs new file mode 100755 index 0000000..e69de29 diff --git a/Telegram.Api.WP8/Resources/AppResources.ru.resx b/Telegram.Api.WP8/Resources/AppResources.ru.resx new file mode 100755 index 0000000..7d370c0 --- /dev/null +++ b/Telegram.Api.WP8/Resources/AppResources.ru.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Удаленный аккаунт + + + Удаленный аккаунт + + + Избранное + + \ No newline at end of file diff --git a/Telegram.Api.WP8/Services/FileManager/IWebFileManager.cs b/Telegram.Api.WP8/Services/FileManager/IWebFileManager.cs new file mode 100755 index 0000000..8e84187 --- /dev/null +++ b/Telegram.Api.WP8/Services/FileManager/IWebFileManager.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public interface IWebFileManager + { + void DownloadFile(TLInt dcId, TLInputWebFileGeoPointLocation file, string fileName, TLObject owner); + void DownloadFile(TLInt dcId, TLInputWebFileGeoPointLocation file, string fileName, TLObject owner, System.Action callback); + void CancelDownloadFile(TLObject owner); + } +} diff --git a/Telegram.Api.WP8/Services/FileManager/WebFileManager.cs b/Telegram.Api.WP8/Services/FileManager/WebFileManager.cs new file mode 100755 index 0000000..6177ea2 --- /dev/null +++ b/Telegram.Api.WP8/Services/FileManager/WebFileManager.cs @@ -0,0 +1,212 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; +using System.Linq; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public class WebFileManager : FileManagerBase, IWebFileManager + { + public WebFileManager(ITelegramEventAggregator eventAggregator, IMTProtoService mtProtoService) + : base(eventAggregator, mtProtoService) + { + for (var i = 0; i < Constants.WorkersNumber; i++) + { + var worker = new Worker(OnDownloading, "webDownloader"+i); + _workers.Add(worker); + } + } + + private void OnDownloading(object state) + { + DownloadablePart part = null; + lock (_itemsSyncRoot) + { + for (var i = 0; i < _items.Count; i++) + { + var item = _items[i]; + if (item.Canceled) + { + + _items.RemoveAt(i--); + + try + { + _eventAggregator.Publish(new DownloadingCanceledEventArgs(item)); + } + catch (Exception e) + { + TLUtils.WriteException(e); + } + } + } + + foreach (var item in _items) + { + part = item.Parts.FirstOrDefault(x => x.Status == PartStatus.Ready); + if (part != null) + { + part.Status = PartStatus.Processing; + break; + } + } + } + + if (part == null) + { + var currentWorker = (Worker)state; + currentWorker.Stop(); + return; + } + + bool canceled; + ProcessFilePart(part, part.ParentItem.DCId, part.ParentItem.InputLocation, out canceled); + if (canceled) + { + lock (_itemsSyncRoot) + { + part.ParentItem.Canceled = true; + part.Status = PartStatus.Processed; + _items.Remove(part.ParentItem); + } + + return; + } + + // indicate progress + // indicate complete + bool isComplete; + bool isCanceled; + var progress = 0.0; + lock (_itemsSyncRoot) + { + part.Status = PartStatus.Processed; + + var data = part.File.Bytes.Data; + if (data.Length < part.Limit.Value && (part.Number + 1) != part.ParentItem.Parts.Count) + { + var complete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!complete) + { + var emptyBufferSize = part.Limit.Value - data.Length; + var position = data.Length; + + var missingPart = new DownloadablePart(part.ParentItem, new TLInt(position), new TLInt(emptyBufferSize), -part.Number); + + var currentItemIndex = part.ParentItem.Parts.IndexOf(part); + part.ParentItem.Parts.Insert(currentItemIndex + 1, missingPart); + } + } + + isCanceled = part.ParentItem.Canceled; + + isComplete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!isComplete) + { + var downloadedCount = part.ParentItem.Parts.Count(x => x.Status == PartStatus.Processed); + var count = part.ParentItem.Parts.Count; + progress = (double)downloadedCount / count; + } + else + { + _items.Remove(part.ParentItem); + } + } + + if (!isCanceled) + { + if (isComplete) + { + byte[] bytes = { }; + foreach (var p in part.ParentItem.Parts) + { + bytes = TLUtils.Combine(bytes, p.File.Bytes.Data); + } + //part.ParentItem.Location.Buffer = bytes; + + var fileName = part.ParentItem.FileName.ToString(); + + StringLocker.Lock(fileName, () => FileUtils.WriteBytes(fileName, bytes)); + + if (part.ParentItem.Callback != null) + { + Execute.BeginOnThreadPool(() => + { + part.ParentItem.Callback.SafeInvoke(part.ParentItem); + if (part.ParentItem.Callbacks != null) + { + foreach (var callback in part.ParentItem.Callbacks) + { + callback.SafeInvoke(part.ParentItem); + } + } + }); + } + else + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(part.ParentItem)); + } + } + else + { + //Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new ProgressChangedEventArgs(part.ParentItem, progress))); + } + } + } + + protected DownloadableItem GetDownloadableItem(TLInt dcId, TLInputWebFileGeoPointLocation location, string fileName, TLObject owner, TLInt fileSize, Action callback) + { + var item = new DownloadableItem + { + Owner = owner, + DCId = dcId, + Callback = callback, + InputLocation = location + }; + item.Parts = GetItemParts(fileSize, item); + + return item; + } + + public void DownloadFile(TLInt dcId, TLInputWebFileGeoPointLocation file, string fileName, TLObject owner) + { + DownloadFile(dcId, file, fileName, owner, null); + } + + public void DownloadFile(TLInt dcId, TLInputWebFileGeoPointLocation file, string fileName, TLObject owner, Action callback) + { + var downloadableItem = GetDownloadableItem(dcId, file, fileName, owner, new TLInt(0), callback); + downloadableItem.FileName = new TLString(fileName); + lock (_itemsSyncRoot) + { + bool addFile = true; + foreach (var item in _items) + { + if (item.InputLocation.LocationEquals(file) + && item.Owner == owner) + { + addFile = false; + break; + } + } + + if (addFile) + { + _items.Add(downloadableItem); + } + } + + StartAwaitingWorkers(); + } + } +} diff --git a/Telegram.Api.WP8/Services/Location/ILiveLocationService.cs b/Telegram.Api.WP8/Services/Location/ILiveLocationService.cs new file mode 100755 index 0000000..5f5b847 --- /dev/null +++ b/Telegram.Api.WP8/Services/Location/ILiveLocationService.cs @@ -0,0 +1,34 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Location +{ + public interface ILiveLocationService + { + void Load(); + + void UpdateAll(); + + void LoadAndUpdateAllAsync(); + + void Add(TLMessage70 messageBase); + + void UpdateAsync(TLMessage70 message, TLGeoPointBase geoPoint, Action callback, Action faultCallback = null); + + TLMessage Get(TLPeerBase peer, TLInt fromId); + + IList Get(); + + void Clear(); + + void StopAllAsync(); + } +} diff --git a/Telegram.Api.WP8/Services/Location/LiveLocationService.cs b/Telegram.Api.WP8/Services/Location/LiveLocationService.cs new file mode 100755 index 0000000..24ab226 --- /dev/null +++ b/Telegram.Api.WP8/Services/Location/LiveLocationService.cs @@ -0,0 +1,689 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Device.Location; +using System.Linq; +using System.Threading; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Location +{ + public class LiveLocationService : ILiveLocationService, IHandle, IHandle + { + private readonly TLVector _messages; + + private readonly IMTProtoService _mtProtoService; + + private readonly ITelegramEventAggregator _eventAggregator; + + private readonly object _liveLocationsSyncRoot = new object(); + + private readonly Timer _timer; + + public LiveLocationService(IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + { + _timer = new Timer(OnTick); + _timer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); + + _mtProtoService = mtProtoService; + _eventAggregator = eventAggregator; + + _eventAggregator.Subscribe(this); + + _messages = new TLVector(); + } + + private void OnTick(object state) + { + UpdateAll(); + + SetNextTimer(); + } + + public void LoadAndUpdateAllAsync() + { + Execute.BeginOnThreadPool(() => + { + Load(); + + UpdateAll(); + + SetNextTimer(); + }); + } + + public void StopAllAsync() + { + Execute.BeginOnThreadPool(() => + { + lock (_liveLocationsSyncRoot) + { + for (var i = 0; i < _messages.Count; i++) + { + var message = _messages[i] as TLMessage70; + if (message != null) + { + var mediaGeoLive = message.Media as TLMessageMediaGeoLive; + if (mediaGeoLive != null) + { + mediaGeoLive.Date = message.Date; + mediaGeoLive.EditDate = message.EditDate; + if (!mediaGeoLive.Active) + { + _messages.RemoveAt(i--); + } + } + } + } + } + + TLUtils.SaveObjectToMTProtoFile(_liveLocationsSyncRoot, Constants.LiveLocationsFileName, _messages); + + var messages = new List(); + lock (_liveLocationsSyncRoot) + { + for (var i = 0; i < _messages.Count; i++) + { + var message = _messages[i] as TLMessage70; + if (message != null) + { + messages.Add(message); + } + } + } + + if (messages.Count > 0) + { + var handles = new List(); + + foreach (var message in messages) + { + var m = message; + var waitHandle = new ManualResetEvent(false); + handles.Add(waitHandle); + UpdateAsync(m, + new TLGeoPointEmpty(), + result => + { + waitHandle.Set(); + }, + error => + { + waitHandle.Set(); + }); + } + +#if DEBUG + var timeout = Timeout.InfiniteTimeSpan; +#else + var timeout = TimeSpan.FromSeconds(30.0); +#endif + + var noTimeout = WaitHandle.WaitAll(handles.ToArray(), timeout); + + if (noTimeout) + { + lock (_liveLocationsSyncRoot) + { + _messages.Clear(); + } + + TLUtils.SaveObjectToMTProtoFile(_liveLocationsSyncRoot, Constants.LiveLocationsFileName, _messages); + + _eventAggregator.Publish(new LiveLocationClearedEventArgs()); + } + } + else + { + lock (_liveLocationsSyncRoot) + { + _messages.Clear(); + } + + TLUtils.SaveObjectToMTProtoFile(_liveLocationsSyncRoot, Constants.LiveLocationsFileName, _messages); + + _eventAggregator.Publish(new LiveLocationClearedEventArgs()); + } + }); + } + + public void UpdateAll() + { + var removedMessages = new List(); + lock (_liveLocationsSyncRoot) + { + for (var i = 0; i < _messages.Count; i++) + { + var message = _messages[i] as TLMessage70; + if (message != null) + { + var mediaGeoLive = message.Media as TLMessageMediaGeoLive; + if (mediaGeoLive != null) + { + mediaGeoLive.Date = message.Date; + mediaGeoLive.EditDate = message.EditDate; + if (!mediaGeoLive.Active) + { + removedMessages.Add(message); + _messages.RemoveAt(i--); + } + } + } + } + } + + if (removedMessages.Count > 0) + { + _eventAggregator.Publish(new LiveLocationRemovedEventArgs { Messages = removedMessages }); + } + + TLUtils.SaveObjectToMTProtoFile(_liveLocationsSyncRoot, Constants.LiveLocationsFileName, _messages); + + var messages = new List(); + lock (_liveLocationsSyncRoot) + { + for (var i = 0; i < _messages.Count; i++) + { + var message = _messages[i] as TLMessage70; + if (message != null) + { + var mediaGeoLive = message.Media as TLMessageMediaGeoLive; + if (mediaGeoLive != null && mediaGeoLive.Active) + { + var period = mediaGeoLive.Period.Value > 3600 ? 180 : 90; + + var clientDelta = _mtProtoService.ClientTicksDelta; + //var utc0SecsLong = message.EditDate.Value * 4294967296 - clientDelta; + var utc0SecsInt = message.EditDate.Value - clientDelta / 4294967296.0; + + var nextTime = Utils.UnixTimestampToDateTime(utc0SecsInt + period); + + if (nextTime <= DateTime.Now.AddSeconds(30.0)) + { + messages.Add(message); + } + } + } + } + } + + if (messages.Count > 0) + { + GeoCoordinate location; + using (var coordinateWatcher = new GeoCoordinateWatcher()) + { + coordinateWatcher.TryStart(false, TimeSpan.FromMilliseconds(1000)); + + location = coordinateWatcher.Position.Location; + + coordinateWatcher.Stop(); + } + + if (!location.IsUnknown) + { + var handles = new List(); + + foreach (var message in messages) + { + var m = message; + var waitHandle = new ManualResetEvent(false); + handles.Add(waitHandle); + UpdateAsync(m, + new TLGeoPoint + { + Lat = new TLDouble(location.Latitude), + Long = new TLDouble(location.Longitude) + }, + result => + { + waitHandle.Set(); + }, + error => + { + waitHandle.Set(); + }); + } + +#if DEBUG + var timeout = Timeout.InfiniteTimeSpan; +#else + var timeout = TimeSpan.FromSeconds(30.0); +#endif + + + var noTimeout = WaitHandle.WaitAll(handles.ToArray(), timeout); + } + } + } + + private void SetNextTimer() + { + var timeSpan = GetTimeSpan(); + _timer.Change(timeSpan, Timeout.InfiniteTimeSpan); + } + + public IList Get() + { + var list = new List(); + + lock (_liveLocationsSyncRoot) + { + for (var index = _messages.Count - 1; index >= 0; index--) + { + var messageBase = _messages[index]; + var message = messageBase as TLMessage48; + if (message != null) + { + var mediaGeoLive = message.Media as TLMessageMediaGeoLive; + if (mediaGeoLive != null) + { + mediaGeoLive.EditDate = message.EditDate; + mediaGeoLive.Date = message.Date; + if (mediaGeoLive.Active) + { + list.Add(message); + } + } + } + } + } + + return list; + } + + public TLMessage Get(TLPeerBase peer, TLInt fromId) + { + try + { + lock (_liveLocationsSyncRoot) + { + for (var index = _messages.Count - 1; index >= 0; index--) + { + var messageBase = _messages[index]; + var message = messageBase as TLMessage48; + if (message != null + && message.FromId.Value == fromId.Value) + { + var mediaGeoLive = message.Media as TLMessageMediaGeoLive; + if (mediaGeoLive != null) + { + mediaGeoLive.EditDate = message.EditDate; + mediaGeoLive.Date = message.Date; + if (mediaGeoLive.Active) + { + if (peer is TLPeerUser + && message.ToId is TLPeerUser + && !message.Out.Value + && peer.Id.Value == message.FromId.Value) + { + return message; + } + + if (peer is TLPeerUser + && message.ToId is TLPeerUser + && message.Out.Value + && peer.Id.Value == message.ToId.Id.Value) + { + return message; + } + + if (peer is TLPeerChat + && message.ToId is TLPeerChat + && peer.Id.Value == message.ToId.Id.Value) + { + return message; + } + + if (peer is TLPeerChannel + && message.ToId is TLPeerChannel + && peer.Id.Value == message.ToId.Id.Value) + { + return message; + } + } + } + } + } + } + } + catch (Exception ex) + { + + } + + return null; + } + + public void Load() + { + if (_messages == null) return; + + var messages = TLUtils.OpenObjectFromMTProtoFile>(_liveLocationsSyncRoot, Constants.LiveLocationsFileName) ?? new TLVector(); + + var m = new List(); + lock (_liveLocationsSyncRoot) + { + _messages.Clear(); + foreach (var messageBase in messages) + { + var message = messageBase as TLMessage70; + if (message != null) + { + if (message.InputPeer == null) + { + return; + } + + var mediaGeoLive = message.Media as TLMessageMediaGeoLive; + if (mediaGeoLive != null) + { + mediaGeoLive.EditDate = message.EditDate; + mediaGeoLive.Date = message.Date; + if (!mediaGeoLive.Active) + { + continue; + } + } + + _messages.Add(messageBase); + m.Add(message); + } + } + } + + _eventAggregator.Publish(new LiveLocationLoadedEventArgs { Messages = m }); + } + + public void Clear() + { + lock (_liveLocationsSyncRoot) + { + _messages.Clear(); + } + + FileUtils.Delete(_liveLocationsSyncRoot, Constants.LiveLocationsFileName); + + _eventAggregator.Publish(new LiveLocationClearedEventArgs()); + } + + private TimeSpan GetTimeSpan() + { + var timeSpan = Timeout.InfiniteTimeSpan; + lock (_liveLocationsSyncRoot) + { + for (var i = 0; i < _messages.Count; i++) + { + var message = _messages[i] as TLMessage70; + if (message != null) + { + var mediaGeoLive = message.Media as TLMessageMediaGeoLive; + if (mediaGeoLive != null && mediaGeoLive.Active) + { + var period = mediaGeoLive.Period.Value > 3600 ? 180 : 90; + + var editDate = message.EditDate != null && message.EditDate.Value > message.Date.Value + ? message.EditDate.Value + : message.Date.Value; + + // edit date + update interval + var clientDelta = _mtProtoService.ClientTicksDelta; + //var utc0SecsLong = editDate * 4294967296 - clientDelta; + var utc0SecsInt = editDate - clientDelta / 4294967296.0; + + var nextEditDate1 = Utils.UnixTimestampToDateTime(utc0SecsInt + period); + var timeSpan1 = nextEditDate1 - DateTime.Now; + if (timeSpan1.Ticks < 0) timeSpan1 = new TimeSpan(0); + + // date + period + //utc0SecsLong = message.Date.Value * 4294967296 - clientDelta; + utc0SecsInt = message.Date.Value - clientDelta / 4294967296.0; + + var nextEditDate2 = Utils.UnixTimestampToDateTime(utc0SecsInt + mediaGeoLive.Period.Value); + var timeSpan2 = nextEditDate2 - DateTime.Now; + if (timeSpan2.Ticks < 0) timeSpan2 = new TimeSpan(0); + + var currentTimeSpan = timeSpan1.Ticks < timeSpan2.Ticks ? timeSpan1 : timeSpan2; + if (currentTimeSpan < timeSpan || timeSpan == Timeout.InfiniteTimeSpan) + { + timeSpan = currentTimeSpan; + } + } + } + } + } + + return timeSpan; + } + + public void Add(TLMessage70 message) + { + message.InputPeer = _mtProtoService.PeerToInputPeer(message.ToId); + + lock (_liveLocationsSyncRoot) + { + _messages.Add(message); + } + + SetNextTimer(); + + TLUtils.SaveObjectToMTProtoFile(_liveLocationsSyncRoot, Constants.LiveLocationsFileName, _messages); + + _eventAggregator.Publish(new LiveLocationAddedEventArgs { Message = message }); + } + + public void Remove(TLMessage message) + { + lock (_liveLocationsSyncRoot) + { + _messages.Remove(message); + } + + TLUtils.SaveObjectToMTProtoFile(_liveLocationsSyncRoot, Constants.LiveLocationsFileName, _messages); + + SetNextTimer(); + + _eventAggregator.Publish(new LiveLocationRemovedEventArgs { Messages = new List { message } }); + } + + public void UpdateAsync(TLMessage70 message, TLGeoPointBase geoPointBase, Action callback, Action faultCallback = null) + { + TLMessage70 m; + lock (_liveLocationsSyncRoot) + { + m = _messages.FirstOrDefault( + x => x.Index == message.Index + && ((TLMessage)x).ToId.GetType() == message.ToId.GetType() + && ((TLMessage)x).ToId.Id.Value == message.ToId.Id.Value) as TLMessage70; + } + if (m == null || m.InputPeer == null) + { + faultCallback.SafeInvoke(null); + return; + }; + + var stopGeoLive = false; + TLInputGeoPoint inputGeoPoint = null; + var geoPoint = geoPointBase as TLGeoPoint; + if (geoPoint != null) + { + inputGeoPoint = new TLInputGeoPoint { Lat = geoPoint.Lat, Long = geoPoint.Long }; + } + else + { + stopGeoLive = true; + } + + _mtProtoService.EditMessageAsync(m.InputPeer, message.Id, null, null, null, null, false, stopGeoLive, inputGeoPoint, + result => + { + m.EditDate = TLUtils.DateToUniversalTimeTLInt(_mtProtoService.ClientTicksDelta, DateTime.Now); + var mediaGeoLive = m.Media as TLMessageMediaGeoLive; + if (mediaGeoLive != null) + { + mediaGeoLive.EditDate = m.EditDate; + } + + if (stopGeoLive) + { + Remove(m); + } + + callback.SafeInvoke(result); + }, + error => + { + // handle 400 MESSAGE_EDIT_TIME_EXPIRED, MESSAGE_ID_INVALID, ... + if (error.CodeEquals(ErrorCode.BAD_REQUEST)) + { + if (error.TypeEquals(ErrorType.MESSAGE_NOT_MODIFIED)) + { + m.EditDate = TLUtils.DateToUniversalTimeTLInt(_mtProtoService.ClientTicksDelta, DateTime.Now); + var mediaGeoLive = m.Media as TLMessageMediaGeoLive; + if (mediaGeoLive != null) + { + mediaGeoLive.EditDate = m.EditDate; + } + } + else + { + Remove(m); + } + } + + faultCallback.SafeInvoke(error); + Execute.ShowDebugMessage("messages.editMessage error " + error); + }); + } + + private void UpdateAndRemoveAt(int i, TLMessage message, TLMessage updatedMessage) + { + message.Update(updatedMessage); + + var messageMediaGeoLive = message.Media as TLMessageMediaGeoLive; + if (messageMediaGeoLive != null && !messageMediaGeoLive.Active) + { + _messages.RemoveAt(i); + + TLUtils.SaveObjectToMTProtoFile(_liveLocationsSyncRoot, Constants.LiveLocationsFileName, _messages); + + SetNextTimer(); + + _eventAggregator.Publish(new LiveLocationRemovedEventArgs { Messages = new List { message } }); + } + } + + public void Handle(TLUpdateEditMessage update) + { + var updatedMessage = update.Message as TLMessage; + if (updatedMessage != null) + { + lock (_liveLocationsSyncRoot) + { + if (_messages == null) + { + Load(); + } + + if (_messages == null) return; + + for (var i = 0; i < _messages.Count; i++) + { + var message = _messages[i] as TLMessage; + if (message != null && message.Index == updatedMessage.Index) + { + var peer = updatedMessage.ToId; + if (peer is TLPeerUser + && message.ToId is TLPeerUser + && !message.Out.Value + && peer.Id.Value == message.FromId.Value) + { + UpdateAndRemoveAt(i, message, updatedMessage); + return; + } + + if (peer is TLPeerUser + && message.ToId is TLPeerUser + && message.Out.Value + && peer.Id.Value == message.ToId.Id.Value) + { + UpdateAndRemoveAt(i, message, updatedMessage); + return; + } + + if (peer is TLPeerChat + && message.ToId is TLPeerChat + && peer.Id.Value == message.ToId.Id.Value) + { + UpdateAndRemoveAt(i, message, updatedMessage); + return; + } + } + } + } + } + } + + public void Handle(TLUpdateEditChannelMessage update) + { + var updatedMessage = update.Message as TLMessage; + if (updatedMessage != null) + { + lock (_liveLocationsSyncRoot) + { + if (_messages == null) + { + Load(); + } + + if (_messages == null) return; + + for (var i = 0; i < _messages.Count; i++) + { + var message = _messages[i] as TLMessage; + if (message != null && message.Index == updatedMessage.Index) + { + var peer = updatedMessage.ToId; + if (peer is TLPeerChannel + && message.ToId is TLPeerChannel + && peer.Id.Value == message.ToId.Id.Value) + { + UpdateAndRemoveAt(i, message, updatedMessage); + + return; + } + } + } + } + } + } + } + + public class LiveLocationAddedEventArgs + { + public TLMessage Message { get; set; } + } + + public class LiveLocationRemovedEventArgs + { + public IList Messages { get; set; } + } + + public class LiveLocationClearedEventArgs + { + + } + + public class LiveLocationLoadedEventArgs + { + public IList Messages { get; set; } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLAcceptAuthorization.cs b/Telegram.Api.WP8/TL/Functions/Account/TLAcceptAuthorization.cs new file mode 100755 index 0000000..fb4d0a1 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLAcceptAuthorization.cs @@ -0,0 +1,28 @@ +namespace Telegram.Api.TL.Functions.Account +{ + class TLAcceptAuthorization : TLObject + { + public const uint Signature = 0xe7027c94; + + public TLInt BotId { get; set; } + + public TLString Scope { get; set; } + + public TLString PublicKey { get; set; } + + public TLVector ValueHashes { get; set; } + + public TLSecureCredentialsEncrypted Credentials { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + BotId.ToBytes(), + Scope.ToBytes(), + PublicKey.ToBytes(), + ValueHashes.ToBytes(), + Credentials.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLDeleteSecureValue.cs b/Telegram.Api.WP8/TL/Functions/Account/TLDeleteSecureValue.cs new file mode 100755 index 0000000..0a2f487 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLDeleteSecureValue.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + public class TLDeleteSecureValue : TLObject + { + public const uint Signature = 0xb880bc4b; + + public TLVector Types { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Types.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLGetAllSecureValues.cs b/Telegram.Api.WP8/TL/Functions/Account/TLGetAllSecureValues.cs new file mode 100755 index 0000000..cba3763 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLGetAllSecureValues.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + public class TLGetAllSecureValues : TLObject + { + public const uint Signature = 0xb288bc7d; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLGetAuthorizationForm.cs b/Telegram.Api.WP8/TL/Functions/Account/TLGetAuthorizationForm.cs new file mode 100755 index 0000000..78f1bb8 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLGetAuthorizationForm.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLGetAuthorizationForm : TLObject + { + public const uint Signature = 0xb86ba8e1; + + public TLInt BotId { get; set; } + + public TLString Scope { get; set; } + + public TLString PublicKey { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + BotId.ToBytes(), + Scope.ToBytes(), + PublicKey.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLGetSecureValue.cs b/Telegram.Api.WP8/TL/Functions/Account/TLGetSecureValue.cs new file mode 100755 index 0000000..211bfb7 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLGetSecureValue.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + public class TLGetSecureValue : TLObject + { + public const uint Signature = 0x73665bc2; + + public TLVector Types { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Types.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLGetWebAuthorizations.cs b/Telegram.Api.WP8/TL/Functions/Account/TLGetWebAuthorizations.cs new file mode 100755 index 0000000..6074948 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLGetWebAuthorizations.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLGetWebAuthorizations : TLObject + { + public const uint Signature = 0x182e6d6f; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLInitTakeoutSession.cs b/Telegram.Api.WP8/TL/Functions/Account/TLInitTakeoutSession.cs new file mode 100755 index 0000000..bb3d943 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLInitTakeoutSession.cs @@ -0,0 +1,90 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Account +{ + [Flags] + public enum InitTakeoutSessionFlags + { + Contacts = 0x1, // 0 + MessageUsers = 0x2, // 1 + MessageChats = 0x4, // 2 + MessageMegagroups = 0x8, // 3 + MessageChannels = 0x10, // 4 + Files = 0x20, // 5 + } + + class TLInitTakeoutSession : TLObject + { + public const uint Signature = 0x768a4999; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Contacts + { + get { return IsSet(_flags, (int)InitTakeoutSessionFlags.Contacts); } + set { SetUnset(ref _flags, value, (int)InitTakeoutSessionFlags.Contacts); } + } + + public bool MessageUsers + { + get { return IsSet(_flags, (int)InitTakeoutSessionFlags.MessageUsers); } + set { SetUnset(ref _flags, value, (int)InitTakeoutSessionFlags.MessageUsers); } + } + + public bool MessageChats + { + get { return IsSet(_flags, (int)InitTakeoutSessionFlags.MessageChats); } + set { SetUnset(ref _flags, value, (int)InitTakeoutSessionFlags.MessageChats); } + } + + public bool MessageMegagroups + { + get { return IsSet(_flags, (int)InitTakeoutSessionFlags.MessageMegagroups); } + set { SetUnset(ref _flags, value, (int)InitTakeoutSessionFlags.MessageMegagroups); } + } + + public bool MessageChannels + { + get { return IsSet(_flags, (int)InitTakeoutSessionFlags.MessageChannels); } + set { SetUnset(ref _flags, value, (int)InitTakeoutSessionFlags.MessageChannels); } + } + + public bool Files + { + get { return IsSet(_flags, (int)InitTakeoutSessionFlags.Files); } + set { SetUnset(ref _flags, value, (int)InitTakeoutSessionFlags.Files); } + } + + private TLInt _fileMaxSize; + + public TLInt FileMaxSize + { + get { return _fileMaxSize; } + set { SetField(out _fileMaxSize, value, ref _flags, (int)InitTakeoutSessionFlags.Files); } + } + + public TLLong TakeoutId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(_fileMaxSize, Flags, (int)InitTakeoutSessionFlags.Files), + TakeoutId.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLResetWebAuthorization.cs b/Telegram.Api.WP8/TL/Functions/Account/TLResetWebAuthorization.cs new file mode 100755 index 0000000..e77aa70 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLResetWebAuthorization.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLResetWebAuthorization : TLObject + { + public const uint Signature = 0x2d01b9ef; + + public TLLong Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLResetWebAuthorizations.cs b/Telegram.Api.WP8/TL/Functions/Account/TLResetWebAuthorizations.cs new file mode 100755 index 0000000..64e303b --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLResetWebAuthorizations.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLResetWebAuthorizations : TLObject + { + public const uint Signature = 0x682d2594; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLSaveSecureValue.cs b/Telegram.Api.WP8/TL/Functions/Account/TLSaveSecureValue.cs new file mode 100755 index 0000000..5aa4709 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLSaveSecureValue.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLSaveSecureValue : TLObject + { + public const uint Signature = 0x899fe31d; + + public TLInputSecureValue Value { get; set; } + + public TLLong SecureSecretId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Value.ToBytes(), + SecureSecretId.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLSendVerifyEmailCode.cs b/Telegram.Api.WP8/TL/Functions/Account/TLSendVerifyEmailCode.cs new file mode 100755 index 0000000..3280f4f --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLSendVerifyEmailCode.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLSendVerifyEmailCode : TLObject + { + public const uint Signature = 0x7011509f; + + public TLString Email { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Email.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLSendVerifyPhoneCode.cs b/Telegram.Api.WP8/TL/Functions/Account/TLSendVerifyPhoneCode.cs new file mode 100755 index 0000000..3eb111b --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLSendVerifyPhoneCode.cs @@ -0,0 +1,49 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Account +{ + [Flags] + public enum SendVerifyPhoneCodeFlags + { + AllowFlashcall = 0x1, // 0 + } + + class TLSendVerifyPhoneCode : TLObject + { + public const uint Signature = 0x823380b4; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLString PhoneNumber { get; set; } + + private TLBool _currentNumber; + + public TLBool CurrentNumber + { + get { return _currentNumber; } + set { SetField(out _currentNumber, value, ref _flags, (int)SendVerifyPhoneCodeFlags.AllowFlashcall); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + PhoneNumber.ToBytes(), + ToBytes(CurrentNumber, Flags, (int)SendVerifyPhoneCodeFlags.AllowFlashcall)); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLVerifyEmail.cs b/Telegram.Api.WP8/TL/Functions/Account/TLVerifyEmail.cs new file mode 100755 index 0000000..6d9e321 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLVerifyEmail.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLVerifyEmail : TLObject + { + public const uint Signature = 0xecba39db; + + public TLString Email { get; set; } + + public TLString Code { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Email.ToBytes(), + Code.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLVerifyEmailCode.cs b/Telegram.Api.WP8/TL/Functions/Account/TLVerifyEmailCode.cs new file mode 100755 index 0000000..9b4ad6d --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLVerifyEmailCode.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Telegram.Api.TL.Functions.Account +{ + class TLVerifyEmailCode + { + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Account/TLVerifyPhone.cs b/Telegram.Api.WP8/TL/Functions/Account/TLVerifyPhone.cs new file mode 100755 index 0000000..b31e785 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Account/TLVerifyPhone.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLVerifyPhone : TLObject + { + public const uint Signature = 0x4dd3a7f6; + + public TLString PhoneNumber { get; set; } + + public TLString PhoneCodeHash { get; set; } + + public TLString PhoneCode { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumber.ToBytes(), + PhoneCodeHash.ToBytes(), + PhoneCode.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Auth/TLBindTempAuthKey.cs b/Telegram.Api.WP8/TL/Functions/Auth/TLBindTempAuthKey.cs new file mode 100755 index 0000000..faeb65f --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Auth/TLBindTempAuthKey.cs @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + class TLBindTempAuthKey : TLObject + { + public const uint Signature = 0xcdd42a05; + + public TLLong PermAuthKeyId { get; set; } + + public TLLong Nonce { get; set; } + + public TLInt ExpiresAt { get; set; } + + public TLString EncryptedMessage { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PermAuthKeyId.ToBytes(), + Nonce.ToBytes(), + ExpiresAt.ToBytes(), + EncryptedMessage.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Channels/TLChangeFeedBroadcast.cs b/Telegram.Api.WP8/TL/Functions/Channels/TLChangeFeedBroadcast.cs new file mode 100755 index 0000000..a3f3abe --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Channels/TLChangeFeedBroadcast.cs @@ -0,0 +1,49 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Channels +{ + [Flags] + public enum ChangeFeedBroadcastFlags + { + FeedId = 0x1 + } + + class TLChangeFeedBroadcast : TLObject + { + public const uint Signature = 0xffb37511; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputChannelBase Channel { get; set; } + + private TLInt _feedId; + + public TLInt FeedId + { + get { return _feedId; } + set { SetField(out _feedId, value, ref _flags, (int)ChangeFeedBroadcastFlags.FeedId); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Channel.ToBytes(), + ToBytes(FeedId, Flags, (int)ChangeFeedBroadcastFlags.FeedId)); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Channels/TLGetFeed.cs b/Telegram.Api.WP8/TL/Functions/Channels/TLGetFeed.cs new file mode 100755 index 0000000..e74d3b7 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Channels/TLGetFeed.cs @@ -0,0 +1,85 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Channels +{ + [Flags] + public enum GetFeedFlags + { + OffsetPosition = 0x1, + MaxPosition = 0x2, + MinPosition = 0x4, + OffsetToMaxRead = 0x8, + } + + class TLGetFeed : TLObject + { + public const uint Signature = 0xb90f450; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool OffsetToMaxRead + { + get { return IsSet(Flags, (int) GetFeedFlags.OffsetToMaxRead); } + set { SetUnset(ref _flags, value, (int) GetFeedFlags.OffsetToMaxRead); } + } + + public TLInt FeedId { get; set; } + + private TLFeedPosition _offsetPosition; + + public TLFeedPosition OffsetPosition + { + get { return _offsetPosition; } + set { SetField(out _offsetPosition, value, ref _flags, (int)GetFeedFlags.OffsetPosition); } + } + + public TLInt AddOffset { get; set; } + + public TLInt Limit { get; set; } + + private TLFeedPosition _maxPosition; + + public TLFeedPosition MaxPosition + { + get { return _maxPosition; } + set { SetField(out _maxPosition, value, ref _flags, (int)GetFeedFlags.MaxPosition); } + } + + private TLFeedPosition _minPosition; + + public TLFeedPosition MinPosition + { + get { return _minPosition; } + set { SetField(out _minPosition, value, ref _flags, (int)GetFeedFlags.MinPosition); } + } + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + FeedId.ToBytes(), + ToBytes(OffsetPosition, Flags, (int)GetFeedFlags.OffsetPosition), + AddOffset.ToBytes(), + Limit.ToBytes(), + ToBytes(MaxPosition, Flags, (int)GetFeedFlags.MaxPosition), + ToBytes(MinPosition, Flags, (int)GetFeedFlags.MinPosition), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Channels/TLReadFeed.cs b/Telegram.Api.WP8/TL/Functions/Channels/TLReadFeed.cs new file mode 100755 index 0000000..681659a --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Channels/TLReadFeed.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLReadFeed : TLObject + { + public const uint Signature = 0x9c3011d; + + public TLInt FeedId { get; set; } + + public TLFeedPosition MaxPosition { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + FeedId.ToBytes(), + MaxPosition.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Channels/TLSetFeedBroadcasts.cs b/Telegram.Api.WP8/TL/Functions/Channels/TLSetFeedBroadcasts.cs new file mode 100755 index 0000000..b1bfeac --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Channels/TLSetFeedBroadcasts.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLSetFeedBroadcasts : TLObject + { + public const uint Signature = 0xb5287d9a; + + public TLInt FeedId { get; set; } + + public TLVector Channels { get; set; } + + public TLBool AlsoNewlyJoined { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + FeedId.ToBytes(), + Channels.ToBytes(), + AlsoNewlyJoined.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Contacts/TLGetSaved.cs b/Telegram.Api.WP8/TL/Functions/Contacts/TLGetSaved.cs new file mode 100755 index 0000000..10bcf07 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Contacts/TLGetSaved.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + class TLGetSaved : TLObject + { + public const uint Signature = 0x82f1e39f; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Help/TLGetDeepLinkInfo.cs b/Telegram.Api.WP8/TL/Functions/Help/TLGetDeepLinkInfo.cs new file mode 100755 index 0000000..68ecb45 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Help/TLGetDeepLinkInfo.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Help +{ + public class TLGetDeepLinkInfo : TLObject + { + public const uint Signature = 0x3fedc75f; + + public TLString Path { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Path.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Help/TLGetPassportConfig.cs b/Telegram.Api.WP8/TL/Functions/Help/TLGetPassportConfig.cs new file mode 100755 index 0000000..7e54fa4 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Help/TLGetPassportConfig.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Help +{ + class TLGetPassportConfig : TLObject + { + public const uint Signature = 0xc661ad08; + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Help/TLGetProxyData.cs b/Telegram.Api.WP8/TL/Functions/Help/TLGetProxyData.cs new file mode 100755 index 0000000..a63aeba --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Help/TLGetProxyData.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Help +{ + class TLGetProxyData : TLObject + { + public const uint Signature = 0x3d7758e1; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Messages/TLClearAllDrafts.cs b/Telegram.Api.WP8/TL/Functions/Messages/TLClearAllDrafts.cs new file mode 100755 index 0000000..b25fac6 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Messages/TLClearAllDrafts.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLClearAllDrafts : TLObject + { + public const uint Signature = 0x7e58ee9c; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Messages/TLGetDialogUnreadMarks.cs b/Telegram.Api.WP8/TL/Functions/Messages/TLGetDialogUnreadMarks.cs new file mode 100755 index 0000000..cac65c5 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Messages/TLGetDialogUnreadMarks.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetDialogUnreadMarks : TLObject + { + public const uint Signature = 0x22e24e22; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Messages/TLMarkDialogUnread.cs b/Telegram.Api.WP8/TL/Functions/Messages/TLMarkDialogUnread.cs new file mode 100755 index 0000000..71d2890 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Messages/TLMarkDialogUnread.cs @@ -0,0 +1,46 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum MarkDialogUnreadFlags + { + Unread = 0x1 + } + + class TLMarkDialogUnread : TLObject + { + public const uint Signature = 0xc286d98f; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Unread + { + get { return IsSet(Flags, (int)MarkDialogUnreadFlags.Unread); } + set { SetUnset(ref _flags, value, (int)MarkDialogUnreadFlags.Unread); } + } + + public TLInputDialogPeerBase Peer { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Peer.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Messages/TLReport.cs b/Telegram.Api.WP8/TL/Functions/Messages/TLReport.cs new file mode 100755 index 0000000..f10da1c --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Messages/TLReport.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLReport : TLObject + { + public const uint Signature = 0xbd82b658; + + public TLInputPeerBase Peer { get; set; } + + public TLVector Id { get; set; } + + public TLInputReportReasonBase Reason { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Id.ToBytes(), + Reason.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Messages/TLSearchStickerSets.cs b/Telegram.Api.WP8/TL/Functions/Messages/TLSearchStickerSets.cs new file mode 100755 index 0000000..0f2d2f7 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Messages/TLSearchStickerSets.cs @@ -0,0 +1,49 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum SearchStickerSetsFlags + { + ExcludeFeatured = 0x1, + } + + class TLSearchStickerSets : TLObject + { + public const uint Signature = 0xc2b7d08b; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool ExcludeFeatured + { + get { return IsSet(Flags, (int)SearchStickerSetsFlags.ExcludeFeatured); } + set { SetUnset(ref _flags, value, (int)SearchStickerSetsFlags.ExcludeFeatured); } + } + + public TLString Q { get; set; } + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Q.ToBytes(), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Messages/TLToggleTopPeers.cs b/Telegram.Api.WP8/TL/Functions/Messages/TLToggleTopPeers.cs new file mode 100755 index 0000000..28825e0 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Messages/TLToggleTopPeers.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLToggleTopPeers : TLObject + { + public const uint Signature = 0x8514bdda; + + public TLBool Enabled { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Enabled.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Upload/TLGetWebFile.cs b/Telegram.Api.WP8/TL/Functions/Upload/TLGetWebFile.cs new file mode 100755 index 0000000..c6cdad7 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Upload/TLGetWebFile.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Upload +{ + public class TLGetWebFile : TLObject + { + public const uint Signature = 0x24e6818d; + + public TLInputFileLocationBase Location { get; set; } + + public TLInt Offset { get; set; } + + public TLInt Limit { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Location.ToBytes(), + Offset.ToBytes(), + Limit.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/Functions/Users/TLSetSecureValueErrors.cs b/Telegram.Api.WP8/TL/Functions/Users/TLSetSecureValueErrors.cs new file mode 100755 index 0000000..1fe7514 --- /dev/null +++ b/Telegram.Api.WP8/TL/Functions/Users/TLSetSecureValueErrors.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Users +{ + class TLSetSecureValueErrors : TLObject + { + public const uint Signature = 0x90c894b5; + + public TLInputUserBase Id { get; set; } + + public TLVector Errors { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Errors.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLAppUpdate.cs b/Telegram.Api.WP8/TL/TLAppUpdate.cs new file mode 100755 index 0000000..bd14c8a --- /dev/null +++ b/Telegram.Api.WP8/TL/TLAppUpdate.cs @@ -0,0 +1,91 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum AppUpdateFlags + { + Popup = 0x1, // 0 + Document = 0x2, // 1 + Url = 0x4, // 2 + } + + public abstract class TLAppUpdateBase : TLObject { } + + public class TLNoAppUpdate : TLAppUpdateBase + { + public const uint Signature = TLConstructors.TLNoAppUpdate; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLAppUpdate : TLAppUpdateBase + { + public const uint Signature = TLConstructors.TLAppUpdate; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + public bool Popup + { + get { return IsSet(_flags, (int)AppUpdateFlags.Popup); } + set { SetUnset(ref _flags, value, (int)AppUpdateFlags.Popup); } + } + + public TLInt Id { get; set; } + + public TLString Version { get; set; } + + public TLString Text { get; set; } + + public TLVector Entities { get; set; } + + protected TLDocumentBase _document; + + public TLDocumentBase Document + { + get { return _document; } + set { SetField(out _document, value, ref _flags, (int)AppUpdateFlags.Document); } + } + + protected TLString _url; + + public TLString Url + { + get { return _url; } + set { SetField(out _url, value, ref _flags, (int)AppUpdateFlags.Url); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + Text = GetObject(bytes, ref position); + Entities = GetObject>(bytes, ref position); + _document = GetObject(Flags, (int)AppUpdateFlags.Document, null, bytes, ref position); + _url = GetObject(Flags, (int)AppUpdateFlags.Url, null, bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLAuthorizationForm.cs b/Telegram.Api.WP8/TL/TLAuthorizationForm.cs new file mode 100755 index 0000000..7b953d4 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLAuthorizationForm.cs @@ -0,0 +1,99 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum AuthorizationFormFlags + { + PrivacyPolicyUrl = 0x1, // 0 + SelfieRequired = 0x2, // 1 + } + + public class TLAuthorizationForm : TLObject + { + public const uint Signature = TLConstructors.TLAuthorizationForm; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool SelfieRequired { get { return IsSet(Flags, (int) AuthorizationFormFlags.SelfieRequired); } } + + public TLVector RequiredTypes { get; set; } + + public TLVector Values { get; set; } + + public TLVector Errors { get; set; } + + public TLVector Users { get; set; } + + protected TLString _privacyPolicyUrl; + + public TLString PrivacyPolicyUrl + { + get { return _privacyPolicyUrl; } + set { SetField(out _privacyPolicyUrl, value, ref _flags, (int)AuthorizationFormFlags.PrivacyPolicyUrl); } + } + + #region Additional + + public TLInt BotId { get; set; } + + public TLString Scope { get; set; } + + public TLString PublicKey { get; set; } + + public TLString CallbackUrl { get; set; } + + public TLString Payload { get; set; } + + public TLPassportConfig Config { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + _flags = GetObject(bytes, ref position); + RequiredTypes = GetObject>(bytes, ref position); + Values = GetObject>(bytes, ref position); + Errors = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + _privacyPolicyUrl = GetObject(Flags, (int)AuthorizationFormFlags.PrivacyPolicyUrl, null, bytes, ref position); + + return this; + } + } + + public class TLAuthorizationForm85 : TLAuthorizationForm + { + public new const uint Signature = TLConstructors.TLAuthorizationForm85; + + public TLVector NewRequiredTypes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + _flags = GetObject(bytes, ref position); + NewRequiredTypes = GetObject>(bytes, ref position); + Values = GetObject>(bytes, ref position); + Errors = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + _privacyPolicyUrl = GetObject(Flags, (int)AuthorizationFormFlags.PrivacyPolicyUrl, null, bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLContactsSettings.cs b/Telegram.Api.WP8/TL/TLContactsSettings.cs new file mode 100755 index 0000000..e40d1e6 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLContactsSettings.cs @@ -0,0 +1,60 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ContactsSettingsFlags + { + SuggestFrequentContacts = 0x1, // 0 obsolete + } + + public class TLContactsSettings : TLObject + { + public const uint Signature = TLConstructors.TLContactsSettings; + + private TLLong _flags; + + public TLLong Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), Flags.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + } + } +} \ No newline at end of file diff --git a/Telegram.Api.WP8/TL/TLDeepLinkInfo.cs b/Telegram.Api.WP8/TL/TLDeepLinkInfo.cs new file mode 100755 index 0000000..9be404e --- /dev/null +++ b/Telegram.Api.WP8/TL/TLDeepLinkInfo.cs @@ -0,0 +1,68 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum DeepLinkInfoFlags + { + UpdateApp = 0x1, // 0 + Entities = 0x2, // 1 + } + + public abstract class TLDeepLinkInfoBase : TLObject { } + + public class TLDeepLinkInfoEmpty : TLDeepLinkInfoBase + { + public const uint Signature = TLConstructors.TLDeepLinkInfoEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLDeepLinkInfo : TLDeepLinkInfoBase + { + public const uint Signature = TLConstructors.TLDeepLinkInfo; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool UpdateApp { get { return IsSet(Flags, (int)DeepLinkInfoFlags.UpdateApp); } } + + public TLString Message { get; set; } + + protected TLVector _entities; + + public TLVector Entities + { + get { return _entities; } + set { SetField(out _entities, value, ref _flags, (int)DeepLinkInfoFlags.Entities); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + _flags = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + _entities = GetObject>(Flags, (int)DeepLinkInfoFlags.Entities, null, bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLDialogPeer.cs b/Telegram.Api.WP8/TL/TLDialogPeer.cs new file mode 100755 index 0000000..df7b365 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLDialogPeer.cs @@ -0,0 +1,96 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLDialogPeerBase : TLObject { } + + public class TLDialogPeerFeed : TLDialogPeerBase + { + public const uint Signature = TLConstructors.TLDialogPeerFeed; + + public TLInt FeedId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + FeedId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + FeedId.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + FeedId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(FeedId.ToBytes()); + } + + public override string ToString() + { + return "TLDialogPeer feed_id=" + FeedId; + } + } + + public class TLDialogPeer : TLDialogPeerBase + { + public const uint Signature = TLConstructors.TLDialogPeer; + + public TLPeerBase Peer { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Peer.ToBytes()); + } + + public override string ToString() + { + return "TLDialogPeer peer=" + Peer; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLFeedBroadcasts.cs b/Telegram.Api.WP8/TL/TLFeedBroadcasts.cs new file mode 100755 index 0000000..a352954 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLFeedBroadcasts.cs @@ -0,0 +1,45 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLFeedBroadcastsBase : TLObject + { + public TLVector Channels { get; set; } + } + + public class TLFeedBroadcastsUngrouped : TLFeedBroadcastsBase + { + public const uint Signature = TLConstructors.TLFeedBroadcastsUngrouped; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Channels = GetObject>(bytes, ref position); + + return this; + } + } + + public class TLFeedBroadcasts : TLFeedBroadcastsBase + { + public const uint Signature = TLConstructors.TLFeedBroadcasts; + + public TLInt FeedId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + FeedId = GetObject(bytes, ref position); + Channels = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLFeedPosition.cs b/Telegram.Api.WP8/TL/TLFeedPosition.cs new file mode 100755 index 0000000..5313f03 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLFeedPosition.cs @@ -0,0 +1,61 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLFeedPosition : TLObject + { + public const uint Signature = TLConstructors.TLFeedPosition; + + public TLInt Date { get; set; } + + public TLPeerBase Peer { get; set; } + + public TLInt Id { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + Peer = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Date.ToBytes(), + Peer.ToBytes(), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Date = GetObject(input); + Peer = GetObject(input); + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Date.ToStream(output); + Peer.ToStream(output); + Id.ToStream(output); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLFeedSources.cs b/Telegram.Api.WP8/TL/TLFeedSources.cs new file mode 100755 index 0000000..dadc190 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLFeedSources.cs @@ -0,0 +1,72 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum FeedSourcesFlags + { + NewlyJoinedFeed = 0x1 + } + + public abstract class TLFeedSourcesBase : TLObject { } + + public class TLFeedSourcesNotModified : TLFeedSourcesBase + { + public const uint Signature = TLConstructors.TLFeedSourcesNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLFeedSources : TLFeedSourcesBase + { + public const uint Signature = TLConstructors.TLFeedSources; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + protected TLInt _newlyJoinedFeed; + + public TLInt NewlyJoinedFeed + { + get { return _newlyJoinedFeed; } + set { SetField(out _newlyJoinedFeed, value, ref _flags, (int)FeedSourcesFlags.NewlyJoinedFeed); } + } + + public TLVector Feeds { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + _flags = GetObject(bytes, ref position); + _newlyJoinedFeed = GetObject(Flags, (int)FeedSourcesFlags.NewlyJoinedFeed, null, bytes, ref position); + + Feeds = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLFoundStickerSets.cs b/Telegram.Api.WP8/TL/TLFoundStickerSets.cs new file mode 100755 index 0000000..c189ee4 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLFoundStickerSets.cs @@ -0,0 +1,121 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; + +namespace Telegram.Api.TL +{ + public abstract class TLFoundStickerSetsBase : TLObject { } + + public class TLFoundStickerSetsNotModified : TLFoundStickerSetsBase + { + public const uint Signature = TLConstructors.TLFoundStickerSetsNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLFoundStickerSets : TLFoundStickerSetsBase, IStickers + { + public const uint Signature = TLConstructors.TLFoundStickerSets; + + public TLInt HashValue { get; set; } + + public TLVector SetsCovered { get; set; } + + public TLVector Sets + { + get + { + var sets = new TLVector(); + foreach (var setCovered in SetsCovered) + { + sets.Add(setCovered.StickerSet); + } + return sets; + } + set + { + Execute.ShowDebugMessage("TLFoundStickerSets.Sets set"); + } + } + + public TLVector Packs { get; set; } + + public TLVector Documents { get; set; } + + public TLVector MessagesStickerSets { get; set; } + + public TLString Hash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + HashValue = GetObject(bytes, ref position); + SetsCovered = GetObject>(bytes, ref position); + + Packs = new TLVector(); + Documents = new TLVector(); + MessagesStickerSets = new TLVector(); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + HashValue.ToBytes(), + Sets.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + HashValue = GetObject(input); + Sets = GetObject>(input); + + Packs = GetObject>(input); + Documents = GetObject>(input); + MessagesStickerSets = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + HashValue.ToStream(output); + Sets.ToStream(output); + + Packs.ToStream(output); + Documents.ToStream(output); + MessagesStickerSets.ToStream(output); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLInputCheckPasswordSRP.cs b/Telegram.Api.WP8/TL/TLInputCheckPasswordSRP.cs new file mode 100755 index 0000000..a79e451 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLInputCheckPasswordSRP.cs @@ -0,0 +1,41 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLInputCheckPasswordBase : TLObject { } + + public class TLInputCheckPasswordEmpty : TLInputCheckPasswordBase + { + public const uint Signature = TLConstructors.TLInputCheckPasswordEmpty; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputCheckPasswordSRP : TLInputCheckPasswordBase + { + public const uint Signature = TLConstructors.TLInputCheckPasswordSRP; + + public TLLong SRPId { get; set; } + + public TLString A { get; set; } + + public TLString M1 { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + SRPId.ToBytes(), + A.ToBytes(), + M1.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLInputClientProxy.cs b/Telegram.Api.WP8/TL/TLInputClientProxy.cs new file mode 100755 index 0000000..c0be64e --- /dev/null +++ b/Telegram.Api.WP8/TL/TLInputClientProxy.cs @@ -0,0 +1,49 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLInputClientProxy : TLObject + { + public const uint Signature = TLConstructors.TLInputClientProxy; + + public TLString Address { get; set; } + + public TLInt Port { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Address.ToBytes(), + Port.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Address.ToStream(output); + Port.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Address = GetObject(input); + Port = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputClientProxy address={0} port={1}", Address, Port); + } + } +} \ No newline at end of file diff --git a/Telegram.Api.WP8/TL/TLInputDialogPeer.cs b/Telegram.Api.WP8/TL/TLInputDialogPeer.cs new file mode 100755 index 0000000..9a9060d --- /dev/null +++ b/Telegram.Api.WP8/TL/TLInputDialogPeer.cs @@ -0,0 +1,98 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputDialogPeerBase : TLObject { } + + public class TLInputDialogPeerFeed : TLInputDialogPeerBase + { + public const uint Signature = TLConstructors.TLInputDialogPeerFeed; + + public TLInt FeedId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + FeedId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(TLInputPeerUser.Signature), + FeedId.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + FeedId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + FeedId = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputDialogPeerFeed feed_id={0}", FeedId); + } + } + + public class TLInputDialogPeer : TLInputDialogPeerBase + { + public const uint Signature = TLConstructors.TLInputDialogPeer; + + public TLInputPeerBase Peer { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Peer.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputDialogPeer peer={0}", Peer); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLInputMessage.cs b/Telegram.Api.WP8/TL/TLInputMessage.cs new file mode 100755 index 0000000..486eb39 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLInputMessage.cs @@ -0,0 +1,104 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputMessageBase : TLObject { } + + public class TLInputMessageId : TLInputMessageBase + { + public const uint Signature = TLConstructors.TLInputMessageId; + + public TLInt Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLInputMessageId id={0}", Id); + } + } + + public class TLInputMessageReplyTo : TLInputMessageBase + { + public const uint Signature = TLConstructors.TLInputMessageReplyTo; + + public TLInt Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLInputMessageId id={0}", Id); + } + } + + public class TLInputMessagePinned : TLInputMessageBase + { + public const uint Signature = TLConstructors.TLInputMessagePinned; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override string ToString() + { + return "TLInputMessagePinned"; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLInputSecureFile.cs b/Telegram.Api.WP8/TL/TLInputSecureFile.cs new file mode 100755 index 0000000..3e3e4f8 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLInputSecureFile.cs @@ -0,0 +1,56 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLInputSecureFileBase : TLObject { } + + public class TLInputSecureFileUploaded : TLInputSecureFileBase + { + public const uint Signature = TLConstructors.TLInputSecureFileUploaded; + + public TLLong Id { get; set; } + + public TLInt Parts { get; set; } + + public TLString MD5Checksum { get; set; } + + public TLString FileHash { get; set; } + + public TLString Secret { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Parts.ToBytes(), + MD5Checksum.ToBytes(), + FileHash.ToBytes(), + Secret.ToBytes()); + } + } + + public class TLInputSecureFile : TLInputSecureFileBase + { + public const uint Signature = TLConstructors.TLInputSecureFile; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + + + } +} diff --git a/Telegram.Api.WP8/TL/TLInputSecureValue.cs b/Telegram.Api.WP8/TL/TLInputSecureValue.cs new file mode 100755 index 0000000..c7e4a51 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLInputSecureValue.cs @@ -0,0 +1,114 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLInputSecureValue : TLObject + { + public const uint Signature = TLConstructors.TLInputSecureValue; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLSecureValueTypeBase Type { get; set; } + + protected TLSecureData _data; + + public TLSecureData Data + { + get { return _data; } + set { SetField(out _data, value, ref _flags, (int)SecureValueFlags.Data); } + } + + protected TLInputSecureFileBase _frontSide; + + public TLInputSecureFileBase FrontSide + { + get { return _frontSide; } + set { SetField(out _frontSide, value, ref _flags, (int)SecureValueFlags.FrontSide); } + } + + protected TLInputSecureFileBase _reverseSide; + + public TLInputSecureFileBase ReverseSide + { + get { return _reverseSide; } + set { SetField(out _reverseSide, value, ref _flags, (int)SecureValueFlags.ReverseSide); } + } + + protected TLInputSecureFileBase _selfie; + + public TLInputSecureFileBase Selfie + { + get { return _selfie; } + set { SetField(out _selfie, value, ref _flags, (int)SecureValueFlags.Selfie); } + } + + protected TLVector _files; + + public TLVector Files + { + get { return _files; } + set { SetField(out _files, value, ref _flags, (int)SecureValueFlags.Files); } + } + + protected TLSecurePlainDataBase _plainData; + + public TLSecurePlainDataBase PlainData + { + get { return _plainData; } + set { SetField(out _plainData, value, ref _flags, (int)SecureValueFlags.PlainData); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Type.ToBytes(), + ToBytes(Data, Flags, (int)SecureValueFlags.Data), + ToBytes(_frontSide, Flags, (int)SecureValueFlags.FrontSide), + ToBytes(_reverseSide, Flags, (int)SecureValueFlags.ReverseSide), + ToBytes(_selfie, Flags, (int)SecureValueFlags.Selfie), + ToBytes(_files, Flags, (int)SecureValueFlags.Files), + ToBytes(_plainData, Flags, (int)SecureValueFlags.PlainData)); + } + } + + public class TLInputSecureValue85 : TLInputSecureValue + { + public new const uint Signature = TLConstructors.TLInputSecureValue85; + + protected TLVector _translation; + + public TLVector Translation + { + get { return _translation; } + set { SetField(out _translation, value, ref _flags, (int)SecureValueFlags.Translation); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Type.ToBytes(), + ToBytes(Data, Flags, (int)SecureValueFlags.Data), + ToBytes(_frontSide, Flags, (int)SecureValueFlags.FrontSide), + ToBytes(_reverseSide, Flags, (int)SecureValueFlags.ReverseSide), + ToBytes(_selfie, Flags, (int)SecureValueFlags.Selfie), + ToBytes(_translation, Flags, (int)SecureValueFlags.Translation), + ToBytes(_files, Flags, (int)SecureValueFlags.Files), + ToBytes(_plainData, Flags, (int)SecureValueFlags.PlainData)); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLInvokeWithMessageRange.cs b/Telegram.Api.WP8/TL/TLInvokeWithMessageRange.cs new file mode 100755 index 0000000..1824af6 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLInvokeWithMessageRange.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + class TLInvokeWithMessageRange : TLObject + { + public const uint Signature = 0x365275f2; + + public TLMessageRange Range { get; set; } + + public TLObject Object { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Range.ToBytes(), + Object.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLInvokeWithTakeout.cs b/Telegram.Api.WP8/TL/TLInvokeWithTakeout.cs new file mode 100755 index 0000000..1b9cc0b --- /dev/null +++ b/Telegram.Api.WP8/TL/TLInvokeWithTakeout.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLInvokeWithTakeout : TLObject + { + public const uint Signature = 0xaca9fd2e; + + public TLLong TakeoutId { get; set; } + + public TLObject Object { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + TakeoutId.ToBytes(), + Object.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLPassportConfig.cs b/Telegram.Api.WP8/TL/TLPassportConfig.cs new file mode 100755 index 0000000..2c98cfb --- /dev/null +++ b/Telegram.Api.WP8/TL/TLPassportConfig.cs @@ -0,0 +1,75 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System.IO; +using Windows.Data.Json; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLPassportConfigBase : TLObject { } + + public class TLPassportConfigNotModified : TLPassportConfigBase + { + public const uint Signature = TLConstructors.TLPassportConfigNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLPassportConfig : TLPassportConfigBase + { + public const uint Signature = TLConstructors.TLPassportConfig; + + public TLInt Hash { get; set; } + + public TLDataJSON CountriesLangs { get; set; } + + public JsonObject CountriesLangsObject { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + CountriesLangs = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Hash = GetObject(input); + CountriesLangs = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Hash.ToStream(output); + CountriesLangs.ToStream(output); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLPasswordKdfAlgo.cs b/Telegram.Api.WP8/TL/TLPasswordKdfAlgo.cs new file mode 100755 index 0000000..f2adfe0 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLPasswordKdfAlgo.cs @@ -0,0 +1,63 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLPasswordKdfAlgoBase : TLObject { } + + public class TLPasswordKdfAlgoUnknown : TLPasswordKdfAlgoBase + { + public const uint Signature = TLConstructors.TLPasswordKdfAlgoUnknown; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow : TLPasswordKdfAlgoBase + { + public const uint Signature = TLConstructors.TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow; + + public TLString Salt1 { get; set; } + + public TLString Salt2 { get; set; } + + public TLInt G { get; set; } + + public TLString P { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Salt1 = GetObject(bytes, ref position); + Salt2 = GetObject(bytes, ref position); + G = GetObject(bytes, ref position); + P = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Salt1.ToBytes(), + Salt2.ToBytes(), + G.ToBytes(), + P.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLProxyData.cs b/Telegram.Api.WP8/TL/TLProxyData.cs new file mode 100755 index 0000000..852070f --- /dev/null +++ b/Telegram.Api.WP8/TL/TLProxyData.cs @@ -0,0 +1,148 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ProxyDataPromoCustomFlags + { + //Channel = 0x1, + Notified = 0x2, + } + + public abstract class TLProxyDataBase : TLObject + { + public TLInt Expires { get; set; } + + public abstract TLProxyDataBase GetEmptyObject(); + } + + public class TLProxyDataEmpty : TLProxyDataBase + { + public const uint Signature = TLConstructors.TLProxyDataEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Expires = GetObject(bytes, ref position); + + return this; + } + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Expires.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Expires.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Expires = GetObject(input); + + return this; + } + + public override TLProxyDataBase GetEmptyObject() + { + return new TLProxyDataEmpty { Expires = Expires }; + } + } + + public class TLProxyDataPromo : TLProxyDataBase + { + public const uint Signature = TLConstructors.TLProxyDataPromo; + + protected TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + public bool Notified + { + get { return IsSet(_customFlags, (int) ProxyDataPromoCustomFlags.Notified); } + set { SetUnset(ref _customFlags, value, (int) ProxyDataPromoCustomFlags.Notified); } + } + + public TLPeerBase Peer { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Expires = GetObject(bytes, ref position); + Peer = GetObject(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + CustomFlags = new TLLong(0); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Expires.ToBytes(), + Peer.ToBytes(), + Chats.ToBytes(), + Users.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Expires.ToStream(output); + Peer.ToStream(output); + Chats.ToStream(output); + Users.ToStream(output); + + CustomFlags.NullableToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Expires = GetObject(input); + Peer = GetObject(input); + Chats = GetObject>(input); + Users = GetObject>(input); + + CustomFlags = GetNullableObject(input); + + return this; + } + + public override TLProxyDataBase GetEmptyObject() + { + return new TLProxyDataPromo + { + Expires = Expires, + Peer = Peer, + Chats = new TLVector(), + Users = new TLVector(), + CustomFlags = new TLLong(0) + }; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLSavedPhoneContact.cs b/Telegram.Api.WP8/TL/TLSavedPhoneContact.cs new file mode 100755 index 0000000..d5d2d3c --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSavedPhoneContact.cs @@ -0,0 +1,34 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLSavedPhoneContact : TLObject + { + public const uint Signature = TLConstructors.TLSavedPhoneContact; + + public TLString Phone { get; set; } + + public TLString FirstName { get; set; } + + public TLString LastName { get; set; } + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Phone = GetObject(bytes, ref position); + FirstName = GetObject(bytes, ref position); + LastName = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLSecureCredentialsEncrypted.cs b/Telegram.Api.WP8/TL/TLSecureCredentialsEncrypted.cs new file mode 100755 index 0000000..d35ae7c --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSecureCredentialsEncrypted.cs @@ -0,0 +1,40 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLSecureCredentialsEncrypted : TLObject + { + public const uint Signature = TLConstructors.TLSecureCredentialsEncrypted; + + public TLString Data { get; set; } + + public TLString Secret { get; set; } + + public TLString Hash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Data = GetObject(bytes, ref position); + Hash = GetObject(bytes, ref position); + Secret = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Data.ToBytes(), + Hash.ToBytes(), + Secret.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLSecureData.cs b/Telegram.Api.WP8/TL/TLSecureData.cs new file mode 100755 index 0000000..06d22fb --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSecureData.cs @@ -0,0 +1,64 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLSecureData : TLObject + { + public const uint Signature = TLConstructors.TLSecureData; + + public TLString Data { get; set; } + + public TLString DataHash { get; set; } + + public TLString Secret { get; set; } + + #region Additional + public object DecryptedData { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Data = GetObject(bytes, ref position); + DataHash = GetObject(bytes, ref position); + Secret = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Data.ToBytes(), + DataHash.ToBytes(), + Secret.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Data = GetObject(input); + DataHash = GetObject(input); + Secret = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Data.ToStream(output); + DataHash.ToStream(output); + Secret.ToStream(output); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLSecureFile.cs b/Telegram.Api.WP8/TL/TLSecureFile.cs new file mode 100755 index 0000000..c98ee50 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSecureFile.cs @@ -0,0 +1,194 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public interface ISecureFileError + { + TLString FileHash { get; set; } + + string Error { get; set; } + } + + public abstract class TLSecureFileBase : TLObject + { + private double _uploadingProgress; + + public double UploadingProgress + { + get { return _uploadingProgress; } + set { SetField(ref _uploadingProgress, value, () => UploadingProgress); } + } + + private int _uploadingSize; + + public int UploadingSize + { + get { return _uploadingSize; } + set { SetField(ref _uploadingSize, value, () => UploadingSize); } + } + + private double _downloadingProgress; + + public double DownloadingProgress + { + get { return _downloadingProgress; } + set { SetField(ref _downloadingProgress, value, () => DownloadingProgress); } + } + + public TLSecureFileBase Self { get { return this; } } + + public abstract TLInputSecureFileBase ToInputSecureFile(); + } + + public class TLSecureFileEmpty : TLSecureFileBase + { + public const uint Signature = TLConstructors.TLSecureFileEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLInputSecureFileBase ToInputSecureFile() + { + return null; + } + } + + public class TLSecureFile : TLSecureFileBase, ISecureFileError + { + public const uint Signature = TLConstructors.TLSecureFile; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public TLInt Size { get; set; } + + public TLInt DCId { get; set; } + + public TLInt Date { get; set; } + + public TLString FileHash { get; set; } + + public TLString Secret { get; set; } + + public string Error { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + DCId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + FileHash = GetObject(bytes, ref position); + Secret = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Size = GetObject(input); + DCId = GetObject(input); + Date = GetObject(input); + FileHash = GetObject(input); + Secret = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + AccessHash.ToStream(output); + Size.ToStream(output); + DCId.ToStream(output); + Date.ToStream(output); + FileHash.ToStream(output); + Secret.ToStream(output); + } + + public override TLInputSecureFileBase ToInputSecureFile() + { + return new TLInputSecureFile { Id = Id, AccessHash = AccessHash }; + } + } + + public class TLSecureFileUploaded : TLSecureFileBase, ISecureFileError + { + public const uint Signature = TLConstructors.TLSecureFileUploaded; + + public TLLong Id { get; set; } + + public TLInt Parts { get; set; } + + public TLString MD5Checksum { get; set; } + + public TLInt Size { get; set; } + + public TLInt Date { get; set; } + + public TLString FileHash { get; set; } + + public TLString Secret { get; set; } + + public string Error { get; set; } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Parts = GetObject(input); + MD5Checksum = GetObject(input); + Size = GetObject(input); + Date = GetObject(input); + FileHash = GetObject(input); + Secret = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + Parts.ToStream(output); + MD5Checksum.ToStream(output); + Size.ToStream(output); + Date.ToStream(output); + FileHash.ToStream(output); + Secret.ToStream(output); + } + + public override TLInputSecureFileBase ToInputSecureFile() + { + return new TLInputSecureFileUploaded { Id = Id, Parts = Parts, MD5Checksum = MD5Checksum, FileHash = FileHash, Secret = Secret }; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLSecurePasswordKdfAlgo.cs b/Telegram.Api.WP8/TL/TLSecurePasswordKdfAlgo.cs new file mode 100755 index 0000000..186bb41 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSecurePasswordKdfAlgo.cs @@ -0,0 +1,74 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLSecurePasswordKdfAlgoBase : TLObject { } + + public class TLSecurePasswordKdfAlgoUnknown : TLSecurePasswordKdfAlgoBase + { + public const uint Signature = TLConstructors.TLSecurePasswordKdfAlgoUnknown; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLSecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000 : TLSecurePasswordKdfAlgoBase + { + public const uint Signature = TLConstructors.TLSecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000; + + public TLString Salt { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Salt = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Salt.ToBytes()); + } + } + + public class TLSecurePasswordKdfAlgoSHA512 : TLSecurePasswordKdfAlgoBase + { + public const uint Signature = TLConstructors.TLSecurePasswordKdfAlgoSHA512; + + public TLString Salt { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Salt = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Salt.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLSecureRequiredType.cs b/Telegram.Api.WP8/TL/TLSecureRequiredType.cs new file mode 100755 index 0000000..7d81ee0 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSecureRequiredType.cs @@ -0,0 +1,79 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum SecureRequiredTypeFlags + { + NativeNames = 0x1, // 0 + SelfieRequired = 0x2, // 1 + TranslationRequired = 0x4, // 2 + } + + public abstract class TLSecureRequiredTypeBase : TLObject { } + + public class TLSecureRequiredType : TLSecureRequiredTypeBase + { + public const uint Signature = TLConstructors.TLSecureRequiredType; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool NativeNames { get { return IsSet(Flags, (int)SecureRequiredTypeFlags.NativeNames); } } + + public bool SelfieRequired { get { return IsSet(Flags, (int)SecureRequiredTypeFlags.SelfieRequired); } } + + public bool TranslationRequired { get { return IsSet(Flags, (int)SecureRequiredTypeFlags.TranslationRequired); } } + + public TLSecureValueTypeBase Type { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + _flags = GetObject(bytes, ref position); + Type = GetObject(bytes, ref position); + + return this; + } + + public override string ToString() + { + return string.Format("TLSecureRequiredType type={0} native_names={1} selfie={2} translation={3}", Type, NativeNames, SelfieRequired, TranslationRequired); + } + } + + public class TLSecureRequiredTypeOneOf : TLSecureRequiredTypeBase + { + public const uint Signature = TLConstructors.TLSecureRequiredTypeOneOf; + + public TLVector Types { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Types = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + return string.Format("TLSecureRequiredTypeOneOf types=[{0}]", string.Join(",", Types)); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLSecureSecretSettings.cs b/Telegram.Api.WP8/TL/TLSecureSecretSettings.cs new file mode 100755 index 0000000..8a96108 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSecureSecretSettings.cs @@ -0,0 +1,40 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLSecureSecretSettings : TLObject + { + public const uint Signature = TLConstructors.TLSecureSecretSettings; + + public TLSecurePasswordKdfAlgoBase SecureAlgo { get; set; } + + public TLString SecureSecret { get; set; } + + public TLLong SecureSecretId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + SecureAlgo = GetObject(bytes, ref position); + SecureSecret = GetObject(bytes, ref position); + SecureSecretId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + SecureAlgo.ToBytes(), + SecureSecret.ToBytes(), + SecureSecretId.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLSecureValue.cs b/Telegram.Api.WP8/TL/TLSecureValue.cs new file mode 100755 index 0000000..37bdf0a --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSecureValue.cs @@ -0,0 +1,313 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum SecureValueFlags + { + Data = 0x1, // 0 + FrontSide = 0x2, // 1 + ReverseSide = 0x4, // 2 + Selfie = 0x8, // 3 + Files = 0x10, // 4 + PlainData = 0x20, // 5 + Translation = 0x40, // 6 + } + + public class TLSecureValue : TLObject + { + public const uint Signature = TLConstructors.TLSecureValue; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLSecureValueTypeBase Type { get; set; } + + protected TLSecureData _data; + + public TLSecureData Data + { + get { return _data; } + set { SetField(out _data, value, ref _flags, (int)SecureValueFlags.Data); } + } + + protected TLSecureFileBase _frontSide; + + public TLSecureFileBase FrontSide + { + get { return _frontSide; } + set { SetField(out _frontSide, value, ref _flags, (int)SecureValueFlags.FrontSide); } + } + + protected TLSecureFileBase _reverseSide; + + public TLSecureFileBase ReverseSide + { + get { return _reverseSide; } + set { SetField(out _reverseSide, value, ref _flags, (int)SecureValueFlags.ReverseSide); } + } + + protected TLSecureFileBase _selfie; + + public TLSecureFileBase Selfie + { + get { return _selfie; } + set { SetField(out _selfie, value, ref _flags, (int)SecureValueFlags.Selfie); } + } + + protected TLVector _files; + + public TLVector Files + { + get { return _files; } + set { SetField(out _files, value, ref _flags, (int)SecureValueFlags.Files); } + } + + protected TLSecurePlainDataBase _plainData; + + public TLSecurePlainDataBase PlainData + { + get { return _plainData; } + set { SetField(out _plainData, value, ref _flags, (int)SecureValueFlags.PlainData); } + } + + public TLString Hash { get; set; } + + #region Additional + public TLSecureValue Self { get { return this; } } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Type = GetObject(bytes, ref position); + _data = GetObject(Flags, (int)SecureValueFlags.Data, null, bytes, ref position); + _frontSide = GetObject(Flags, (int)SecureValueFlags.FrontSide, null, bytes, ref position); + _reverseSide = GetObject(Flags, (int)SecureValueFlags.ReverseSide, null, bytes, ref position); + _selfie = GetObject(Flags, (int)SecureValueFlags.Selfie, null, bytes, ref position); + _files = GetObject>(Flags, (int)SecureValueFlags.Files, null, bytes, ref position); + _plainData = GetObject(Flags, (int)SecureValueFlags.PlainData, null, bytes, ref position); + Hash = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Type = GetObject(input); + _data = GetObject(Flags, (int)SecureValueFlags.Data, null, input); + _frontSide = GetObject(Flags, (int)SecureValueFlags.FrontSide, null, input); + _reverseSide = GetObject(Flags, (int)SecureValueFlags.ReverseSide, null, input); + _selfie = GetObject(Flags, (int)SecureValueFlags.Selfie, null, input); + _files = GetObject>(Flags, (int)SecureValueFlags.Files, null, input); + _plainData = GetObject(Flags, (int)SecureValueFlags.PlainData, null, input); + Hash = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Type.ToStream(output); + ToStream(output, _data, Flags, (int)SecureValueFlags.Data); + ToStream(output, _frontSide, Flags, (int)SecureValueFlags.FrontSide); + ToStream(output, _reverseSide, Flags, (int)SecureValueFlags.ReverseSide); + ToStream(output, _selfie, Flags, (int)SecureValueFlags.Selfie); + ToStream(output, _files, Flags, (int)SecureValueFlags.Files); + ToStream(output, _plainData, Flags, (int)SecureValueFlags.PlainData); + Hash.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLSecureValue type={0} data={1} front_side={2} reverse_side={3} selfie={4} files={5} plain_data={6} hash={7}", + Type, + _data != null ? "[data]" : "null", + _frontSide != null ? "[front_side]" : "null", + _reverseSide != null ? "[reverse_side]" : "null", + _selfie != null ? "[selfie]" : "null", + _files != null ? _files.Count.ToString() : "null", + _plainData != null ? "[plain_data]" : "null", + Hash); + } + + public virtual TLInputSecureValue ToInputSecureValue() + { + TLVector files = null; + if (_files != null && _files.Count > 0) + { + files = new TLVector(); + foreach (var file in _files) + { + files.Add(file.ToInputSecureFile()); + } + } + + return new TLInputSecureValue + { + Flags = new TLInt(0), + Type = Type, + Data = _data, + FrontSide = _frontSide != null ? _frontSide.ToInputSecureFile() : null, + ReverseSide = _reverseSide != null ? _reverseSide.ToInputSecureFile() : null, + Selfie = _selfie != null ? _selfie.ToInputSecureFile() : null, + Files = files, + PlainData = _plainData + }; + } + + public virtual void Update(TLSecureValue result) + { + Flags = new TLInt(0); + Type = result.Type; + Data = result.Data; + FrontSide = result.FrontSide; + ReverseSide = result.ReverseSide; + Selfie = result.Selfie; + Files = result.Files; + PlainData = result.PlainData; + Hash = result.Hash; + } + } + + public class TLSecureValue85 : TLSecureValue + { + public new const uint Signature = TLConstructors.TLSecureValue85; + + protected TLVector _translation; + + public TLVector Translation + { + get { return _translation; } + set { SetField(out _translation, value, ref _flags, (int)SecureValueFlags.Translation); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Type = GetObject(bytes, ref position); + _data = GetObject(Flags, (int)SecureValueFlags.Data, null, bytes, ref position); + _frontSide = GetObject(Flags, (int)SecureValueFlags.FrontSide, null, bytes, ref position); + _reverseSide = GetObject(Flags, (int)SecureValueFlags.ReverseSide, null, bytes, ref position); + _selfie = GetObject(Flags, (int)SecureValueFlags.Selfie, null, bytes, ref position); + _translation = GetObject>(Flags, (int)SecureValueFlags.Translation, null, bytes, ref position); + _files = GetObject>(Flags, (int)SecureValueFlags.Files, null, bytes, ref position); + _plainData = GetObject(Flags, (int)SecureValueFlags.PlainData, null, bytes, ref position); + Hash = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Type = GetObject(input); + _data = GetObject(Flags, (int)SecureValueFlags.Data, null, input); + _frontSide = GetObject(Flags, (int)SecureValueFlags.FrontSide, null, input); + _reverseSide = GetObject(Flags, (int)SecureValueFlags.ReverseSide, null, input); + _selfie = GetObject(Flags, (int)SecureValueFlags.Selfie, null, input); + _translation = GetObject>(Flags, (int)SecureValueFlags.Translation, null, input); + _files = GetObject>(Flags, (int)SecureValueFlags.Files, null, input); + _plainData = GetObject(Flags, (int)SecureValueFlags.PlainData, null, input); + Hash = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Type.ToStream(output); + ToStream(output, _data, Flags, (int)SecureValueFlags.Data); + ToStream(output, _frontSide, Flags, (int)SecureValueFlags.FrontSide); + ToStream(output, _reverseSide, Flags, (int)SecureValueFlags.ReverseSide); + ToStream(output, _selfie, Flags, (int)SecureValueFlags.Selfie); + ToStream(output, _translation, Flags, (int)SecureValueFlags.Translation); + ToStream(output, _files, Flags, (int)SecureValueFlags.Files); + ToStream(output, _plainData, Flags, (int)SecureValueFlags.PlainData); + Hash.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLSecureValue85 type={0} data={1} front_side={2} reverse_side={3} selfie={4} translation{5} files={6} plain_data={7} hash={8}", + Type, + _data != null ? "[data]" : "null", + _frontSide != null ? "[front_side]" : "null", + _reverseSide != null ? "[reverse_side]" : "null", + _selfie != null ? "[selfie]" : "null", + _translation != null ? _translation.Count.ToString() : "null", + _files != null ? _files.Count.ToString() : "null", + _plainData != null ? "[plain_data]" : "null", + Hash); + } + + public override TLInputSecureValue ToInputSecureValue() + { + TLVector files = null; + if (_files != null && _files.Count > 0) + { + files = new TLVector(); + foreach (var file in _files) + { + files.Add(file.ToInputSecureFile()); + } + } + TLVector translation = null; + if (_translation != null && _translation.Count > 0) + { + translation = new TLVector(); + foreach (var file in _translation) + { + translation.Add(file.ToInputSecureFile()); + } + } + + return new TLInputSecureValue85 + { + Flags = new TLInt(0), + Type = Type, + Data = _data, + FrontSide = _frontSide != null ? _frontSide.ToInputSecureFile() : null, + ReverseSide = _reverseSide != null ? _reverseSide.ToInputSecureFile() : null, + Selfie = _selfie != null ? _selfie.ToInputSecureFile() : null, + Translation = translation, + Files = files, + PlainData = _plainData + }; + } + + public override void Update(TLSecureValue result) + { + base.Update(result); + + var result85 = result as TLSecureValue85; + if (result85 != null) + { + Translation = result85.Translation; + } + } + } +} diff --git a/Telegram.Api.WP8/TL/TLSecureValueError.cs b/Telegram.Api.WP8/TL/TLSecureValueError.cs new file mode 100755 index 0000000..57d6a7d --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSecureValueError.cs @@ -0,0 +1,262 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLSecureValueErrorBase : TLObject + { + public TLSecureValueTypeBase Type { get; set; } + + public TLString Text { get; set; } + + public abstract int Priority { get; } + } + + public class TLSecureValueError : TLSecureValueErrorBase + { + public const uint Signature = TLConstructors.TLSecureValueError; + + public TLString Hash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + Hash = GetObject(bytes, ref position); + Text = GetObject(bytes, ref position); + + return this; + } + + public override int Priority + { + get { return 1; } + } + } + + public class TLSecureValueErrorData : TLSecureValueErrorBase + { + public const uint Signature = TLConstructors.TLSecureValueErrorData; + + public TLString DataHash { get; set; } + + public TLString Field { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + DataHash = GetObject(bytes, ref position); + Field = GetObject(bytes, ref position); + Text = GetObject(bytes, ref position); + + return this; + } + + public override int Priority + { + get + { + switch (Field.ToString()) + { + case "first_name": + return 801; + case "middle_name": + return 802; + case "last_name": + return 803; + case "birth_date": + return 804; + case "gender": + return 805; + //case "country_code": + // return 806; + case "residence_country_code": + return 807; + case "document_no": + return 808; + case "expiry_date": + return 809; + + + case "street_line1": + return 851; + case "street_line2": + return 852; + case "post_code": + return 853; + case "state": + return 854; + case "city": + return 855; + case "country_code": + return 856; + } + + return 800; + } + } + } + + public abstract class TLSecureValueErrorFileBase : TLSecureValueErrorBase + { + public TLString FileHash { get; set; } + } + + public class TLSecureValueErrorFrontSide : TLSecureValueErrorFileBase + { + public const uint Signature = TLConstructors.TLSecureValueErrorFrontSide; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + FileHash = GetObject(bytes, ref position); + Text = GetObject(bytes, ref position); + + return this; + } + + public override int Priority + { + get { return 100; } + } + } + + public class TLSecureValueErrorReverseSide : TLSecureValueErrorFileBase + { + public const uint Signature = TLConstructors.TLSecureValueErrorReverseSide; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + FileHash = GetObject(bytes, ref position); + Text = GetObject(bytes, ref position); + + return this; + } + + public override int Priority + { + get { return 200; } + } + } + + public class TLSecureValueErrorSelfie : TLSecureValueErrorFileBase + { + public const uint Signature = TLConstructors.TLSecureValueErrorSelfie; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + FileHash = GetObject(bytes, ref position); + Text = GetObject(bytes, ref position); + + return this; + } + + public override int Priority + { + get { return 300; } + } + } + + public class TLSecureValueErrorFile : TLSecureValueErrorFileBase + { + public const uint Signature = TLConstructors.TLSecureValueErrorFile; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + FileHash = GetObject(bytes, ref position); + Text = GetObject(bytes, ref position); + + return this; + } + + public override int Priority + { + get { return 400; } + } + } + + public class TLSecureValueErrorFiles : TLSecureValueErrorBase + { + public const uint Signature = TLConstructors.TLSecureValueErrorFiles; + + public TLVector FileHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + FileHash = GetObject>(bytes, ref position); + Text = GetObject(bytes, ref position); + + return this; + } + + public override int Priority + { + get { return 500; } + } + } + + public class TLSecureValueErrorTranslationFile : TLSecureValueErrorFileBase + { + public const uint Signature = TLConstructors.TLSecureValueErrorTranslationFile; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + FileHash = GetObject(bytes, ref position); + Text = GetObject(bytes, ref position); + + return this; + } + + public override int Priority + { + get { return 600; } + } + } + + public class TLSecureValueErrorTranslationFiles : TLSecureValueErrorBase + { + public const uint Signature = TLConstructors.TLSecureValueErrorTranslationFiles; + + public TLVector FileHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + FileHash = GetObject>(bytes, ref position); + Text = GetObject(bytes, ref position); + + return this; + } + + public override int Priority + { + get { return 700; } + } + } +} \ No newline at end of file diff --git a/Telegram.Api.WP8/TL/TLSecureValueHash.cs b/Telegram.Api.WP8/TL/TLSecureValueHash.cs new file mode 100755 index 0000000..1785a3c --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSecureValueHash.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLSecureValueHash : TLObject + { + public const uint Signature = TLConstructors.TLSecureValueHash; + + public TLSecureValueTypeBase Type { get; set; } + + public TLString Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Type.ToBytes(), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLSecureValuePlainData.cs b/Telegram.Api.WP8/TL/TLSecureValuePlainData.cs new file mode 100755 index 0000000..1aaf387 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSecureValuePlainData.cs @@ -0,0 +1,86 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLSecurePlainDataBase : TLObject { } + + public class TLSecurePlainPhone : TLSecurePlainDataBase + { + public const uint Signature = TLConstructors.TLSecurePlainPhone; + + public TLString Phone { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Phone = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Phone.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Phone = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Phone.ToStream(output); + } + } + + public class TLSecurePlainEmail : TLSecurePlainDataBase + { + public const uint Signature = TLConstructors.TLSecurePlainEmail; + + public TLString Email { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Email = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Email.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Email = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Email.ToStream(output); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLSecureValueType.cs b/Telegram.Api.WP8/TL/TLSecureValueType.cs new file mode 100755 index 0000000..56c7279 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSecureValueType.cs @@ -0,0 +1,366 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLSecureValueTypeBase : TLObject { } + + public class TLSecureValueTypePersonalDetails : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypePersonalDetails; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSecureValueTypePassport : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypePassport; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSecureValueTypeDriverLicense : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypeDriverLicense; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSecureValueTypeIdentityCard : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypeIdentityCard; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSecureValueTypeInternalPassport : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypeInternalPassport; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSecureValueTypeAddress : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypeAddress; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSecureValueTypeUtilityBill : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypeUtilityBill; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSecureValueTypeBankStatement : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypeBankStatement; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSecureValueTypeRentalAgreement : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypeRentalAgreement; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSecureValueTypePassportRegistration : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypePassportRegistration; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSecureValueTypeTemporaryRegistration : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypeTemporaryRegistration; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSecureValueTypePhone : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypePhone; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSecureValueTypeEmail : TLSecureValueTypeBase + { + public const uint Signature = TLConstructors.TLSecureValueTypeEmail; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api.WP8/TL/TLSentEmailCode.cs b/Telegram.Api.WP8/TL/TLSentEmailCode.cs new file mode 100755 index 0000000..137c58e --- /dev/null +++ b/Telegram.Api.WP8/TL/TLSentEmailCode.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLSentEmailCode : TLObject, ILength + { + public const uint Signature = TLConstructors.TLSentEmailCode; + + public TLString EmailPattern { get; set; } + + public TLInt Length { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + EmailPattern = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLTakeout.cs b/Telegram.Api.WP8/TL/TLTakeout.cs new file mode 100755 index 0000000..488b5d6 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLTakeout.cs @@ -0,0 +1,25 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLTakeout : TLObject + { + public const uint Signature = TLConstructors.TLTakeout; + + public TLLong Id { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLTermsOfServiceUpdate.cs b/Telegram.Api.WP8/TL/TLTermsOfServiceUpdate.cs new file mode 100755 index 0000000..fb4191b --- /dev/null +++ b/Telegram.Api.WP8/TL/TLTermsOfServiceUpdate.cs @@ -0,0 +1,45 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLTermsOfServiceUpdateBase : TLObject + { + public TLInt Expires { get; set; } + } + + public class TLTermsOfServiceUpdate : TLTermsOfServiceUpdateBase + { + public const uint Signature = TLConstructors.TLTermsOfServiceUpdate; + + public TLTermsOfServiceBase TermsOfService { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Expires = GetObject(bytes, ref position); + TermsOfService = GetObject(bytes, ref position); + + return this; + } + } + + public class TLTermsOfServiceUpdateEmpty : TLTermsOfServiceUpdateBase + { + public const uint Signature = TLConstructors.TLTermsOfServiceUpdateEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Expires = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLWebAuthorization.cs b/Telegram.Api.WP8/TL/TLWebAuthorization.cs new file mode 100755 index 0000000..bb7b733 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLWebAuthorization.cs @@ -0,0 +1,120 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using System.Text; +using System.Threading; +using Telegram.Api.Services.Cache; + +namespace Telegram.Api.TL +{ + public class TLWebAuthorization : TLObject + { + public const uint Signature = TLConstructors.TLWebAuthorization; + + public TLLong Hash { get; set; } + + public TLInt BotId { get; set; } + + public TLString Domain { get; set; } + + public TLString Browser { get; set; } + + public TLString Platform { get; set; } + + public TLInt DateCreated { get; set; } + + public TLInt DateActive { get; set; } + + public TLString Ip { get; set; } + + public TLString Region { get; set; } + + public string Caption + { + get + { + var domain = + Domain.ToString() + .Replace("https://", string.Empty) + .Replace("http://", string.Empty) + .Replace("www.", string.Empty); + var index = domain.IndexOf('.'); + if (index > 0) + { + var result = domain.Substring(0, index); + if (!string.IsNullOrEmpty(result)) + { + return char.ToUpper(result[0]) + result.Substring(1); + } + } + + return Domain.ToString(); + } + } + + public string Location + { + get { return string.Format("{0} – {1}", Ip, Region); } + } + + public TLUserBase Bot + { + get + { + var cacheService = InMemoryCacheService.Instance; + + return cacheService.GetUser(BotId); + } + } + + public string ParamsString + { + get { return string.Join(", ", Params); } + } + + public IEnumerable Params + { + get + { + if (Bot != null) yield return Bot.FullName; + if (!TLString.IsNullOrEmpty(Browser)) yield return Browser.ToString(); + if (!TLString.IsNullOrEmpty(Platform)) yield return Platform.ToString(); + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + BotId = GetObject(bytes, ref position); + Domain = GetObject(bytes, ref position); + Browser = GetObject(bytes, ref position); + Platform = GetObject(bytes, ref position); + DateCreated = GetObject(bytes, ref position); + DateActive = GetObject(bytes, ref position); + Ip = GetObject(bytes, ref position); + Region = GetObject(bytes, ref position); + + return this; + } + + public void Update(TLWebAuthorization authorization) + { + Hash = authorization.Hash; + BotId = authorization.BotId; + Domain = authorization.Domain; + Browser = authorization.Browser; + Platform = authorization.Platform; + DateCreated = authorization.DateCreated; + DateActive = authorization.DateActive; + Ip = authorization.Ip; + Region = authorization.Region; + } + } +} diff --git a/Telegram.Api.WP8/TL/TLWebAuthorizations.cs b/Telegram.Api.WP8/TL/TLWebAuthorizations.cs new file mode 100755 index 0000000..0028f88 --- /dev/null +++ b/Telegram.Api.WP8/TL/TLWebAuthorizations.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLWebAuthorizations : TLObject + { + public const uint Signature = TLConstructors.TLWebAuthorizations; + + public TLVector Authorizations { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Authorizations = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api.WP8/Telegram.Api.WP8.csproj b/Telegram.Api.WP8/Telegram.Api.WP8.csproj new file mode 100755 index 0000000..0de2912 --- /dev/null +++ b/Telegram.Api.WP8/Telegram.Api.WP8.csproj @@ -0,0 +1,2035 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Telegram.Api + Telegram.Api + WindowsPhone + v8.1 + + + false + true + 12.0 + true + ..\ + true + + en-US + + + true + full + false + Bin\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;LOG_REGISTRATION;WP8 + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;LOG_REGISTRATION;WP8 + true + true + prompt + 4 + + + true + full + false + Bin\x86\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;LOG_REGISTRATION;WP8 + true + true + prompt + 4 + + + + pdbonly + true + Bin\x86\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;LOG_REGISTRATION;WP8 + true + true + prompt + 4 + + + + true + full + false + Bin\ARM\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;LOG_REGISTRATION;WP8 + true + true + prompt + 4 + + + + pdbonly + true + Bin\ARM\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;LOG_REGISTRATION;WP8 + true + true + prompt + 4 + + + + + Compression\GZipDeflateStream.cs + + + Constants.cs + + + Hash\CRC32\CRC.cs + + + Extensions\ActionExtensions.cs + + + Extensions\HttpWebRequestExtensions.cs + + + Extensions\StreamExtensions.cs + + + Extensions\TLObjectExtensions.cs + + + Helpers\Execute.cs + + + Helpers\FileUtils.cs + + + Helpers\SettingsHelper.cs + + + Helpers\Utils.cs + + + Hash\MD5\MD5.cs + + + Hash\MD5\MD5CryptoServiceProvider.cs + + + Hash\MD5\MD5Managed.cs + + + Services\Cache\Context.cs + + + Services\Cache\EventArgs\DialogAddedEventArgs.cs + + + Services\Cache\EventArgs\TopMessageUpdatedEventArgs.cs + + + Services\Cache\ICacheService.cs + + + Services\Cache\InMemoryCacheService.cs + + + Services\Cache\InMemoryDatabase.cs + + + Services\Connection\ConnectionService.cs + + + Services\DCOptionItem.cs + + + Services\DelayedItem.cs + + + Services\FileManager\AudioFileManager.cs + + + Services\FileManager\DocumentFileManager.cs + + + Services\FileManager\DownloadableItem.cs + + + Services\FileManager\DownloadablePart.cs + + + Services\FileManager\DownloadingCanceledEventArgs.cs + + + Services\FileManager\EncryptedFileManager.cs + + + Services\FileManager\FileManager.cs + + + Services\FileManager\IAudioFileManager.cs + + + Services\FileManager\IDocumentFileManager.cs + + + Services\FileManager\IEncryptedFileManager.cs + + + Services\FileManager\IFileManager.cs + + + Services\FileManager\IUploadAudioFileManager.cs + + + Services\FileManager\IUploadFileManager.cs + + + Services\FileManager\IUploadVideoFileManager.cs + + + Services\FileManager\IVideoFileManager.cs + + + Services\FileManager\ProgressChangedEventArgs.cs + + + Services\FileManager\UploadAudioFileManager.cs + + + Services\FileManager\UploadFileManager.cs + + + Services\FileManager\UploadVideoFileManager.cs + + + Services\FileManager\VideoFileManager.cs + + + Services\FileManager\Worker.cs + + + Services\HistoryItem.cs + + + Services\IMTProtoService.cs + + + Services\MTProtoService.Account.cs + + + Services\MTProtoService.Auth.cs + + + Services\MTProtoService.ByTransport.cs + + + Services\MTProtoService.Config.cs + + + Services\MTProtoService.Contacts.cs + + + Services\MTProtoService.cs + + + Services\MTProtoService.DHKeyExchange.cs + + + Services\MTProtoService.Help.cs + + + Services\MTProtoService.Helpers.cs + + + Services\MTProtoService.HttpLongPoll.cs + + + Services\MTProtoService.Messages.cs + + + Services\MTProtoService.Photos.cs + + + Services\MTProtoService.SecretChats.cs + + + Services\MTProtoService.SendingQueue.cs + + + Services\MTProtoService.Stuff.cs + + + Services\MTProtoService.Updates.cs + + + Services\MTProtoService.Upload.cs + + + Services\MTProtoService.Users.cs + + + Services\ServiceBase.cs + + + Services\Updates\IUpdatesService.cs + + + Services\Updates\ReceiveUpdatesEventArgs.cs + + + Services\Updates\UpdatesBySeqComparer.cs + + + Services\Updates\UpdatesService.cs + + + TL\Functions\Account\TLCheckUsername.cs + + + TL\Functions\Account\TLDeleteAccount.cs + + + TL\Functions\Account\TLGetAccountTTL.cs + + + TL\Functions\Account\TLGetNotifySettings.cs + + + TL\Functions\Account\TLGetPrivacy.cs + + + TL\Functions\Account\TLRegisterDevice.cs + + + TL\Functions\Account\TLResetNotifySettings.cs + + + TL\Functions\Account\TLSetPrivacy.cs + + + TL\Functions\Account\TLUnregisterDevice.cs + + + TL\Functions\Account\TLUpdateNotifySettings.cs + + + TL\Functions\Account\TLUpdateProfile.cs + + + TL\Functions\Account\TLUpdateStatus.cs + + + TL\Functions\Account\TLUpdateUserName.cs + + + TL\Functions\Auth\TLCheckPhone.cs + + + TL\Functions\Auth\TLExportAuthorization.cs + + + TL\Functions\Auth\TLImportAuthorization.cs + + + TL\Functions\Auth\TLLogOut.cs + + + TL\Functions\Auth\TLResetAuthorizations.cs + + + TL\Functions\Auth\TLSendCall.cs + + + TL\Functions\Auth\TLSendCode.cs + + + TL\Functions\Auth\TLSendInvites.cs + + + TL\Functions\Auth\TLSendSms.cs + + + TL\Functions\Auth\TLSignIn.cs + + + TL\Functions\Auth\TLSignUp.cs + + + TL\Functions\Contacts\TLBlock.cs + + + TL\Functions\Contacts\TLDeleteContact.cs + + + TL\Functions\Contacts\TLDeleteContacts.cs + + + TL\Functions\Contacts\TLGetBlocked.cs + + + TL\Functions\Contacts\TLGetContacts.cs + + + TL\Functions\Contacts\TLGetStatuses.cs + + + TL\Functions\Contacts\TLImportContacts.cs + + + TL\Functions\Contacts\TLSearch.cs + + + TL\Functions\Contacts\TLUnblock.cs + + + TL\Functions\DHKeyExchange\TLReqDHParams.cs + + + TL\Functions\DHKeyExchange\TLReqPQ.cs + + + TL\Functions\DHKeyExchange\TLSetClientDHParams.cs + + + TL\Functions\Help\TLGetConfig.cs + + + TL\Functions\Help\TLGetInviteText.cs + + + TL\Functions\Help\TLGetNearestDC.cs + + + TL\Functions\Help\TLGetSupport.cs + + + TL\Functions\Help\TLInvokeWithLayerN.cs + + + TL\Functions\Messages\TLAcceptEncryption.cs + + + TL\Functions\Messages\TLAddChatUser.cs + + + TL\Functions\Messages\TLCreateChat.cs + + + TL\Functions\Messages\TLDeleteChatUser.cs + + + TL\Functions\Messages\TLDeleteHistory.cs + + + TL\Functions\Messages\TLDeleteMessages.cs + + + TL\Functions\Messages\TLDiscardEncryption.cs + + + TL\Functions\Messages\TLEditChatPhoto.cs + + + TL\Functions\Messages\TLEditChatTitle.cs + + + TL\Functions\Messages\TLForwardMessage.cs + + + TL\Functions\Messages\TLForwardMessages.cs + + + TL\Functions\Messages\TLGetChats.cs + + + TL\Functions\Messages\TLGetDHConfig.cs + + + TL\Functions\Messages\TLGetDialogs.cs + + + TL\Functions\Messages\TLGetFullChat.cs + + + TL\Functions\Messages\TLGetHistory.cs + + + TL\Functions\Messages\TLGetMessages.cs + + + TL\Functions\Messages\TLReadEncryptedHistory.cs + + + TL\Functions\Messages\TLReadHistory.cs + + + TL\Functions\Messages\TLReadMessageContents.cs + + + TL\Functions\Messages\TLReceivedMessages.cs + + + TL\Functions\Messages\TLReceivedQueue.cs + + + TL\Functions\Messages\TLRequestEncryption.cs + + + TL\Functions\Messages\TLRestoreMessages.cs + + + TL\Functions\Messages\TLSearch.cs + + + TL\Functions\Messages\TLSendBroadcast.cs + + + TL\Functions\Messages\TLSendEncrypted.cs + + + TL\Functions\Messages\TLSendEncryptedFile.cs + + + TL\Functions\Messages\TLSendEncryptedService.cs + + + TL\Functions\Messages\TLSendMedia.cs + + + TL\Functions\Messages\TLSendMessage.cs + + + TL\Functions\Messages\TLSetEncryptedTyping.cs + + + TL\Functions\Messages\TLSetTyping.cs + + + TL\Functions\Photos\TLGetUserPhotos.cs + + + TL\Functions\Photos\TLUpdateProfilePhoto.cs + + + TL\Functions\Photos\TLUploadProfilePhoto.cs + + + TL\Functions\Stuff\TLGetFutureSalts.cs + + + TL\Functions\Stuff\TLHttpWait.cs + + + TL\Functions\Stuff\TLMessageAcknowledgments.cs + + + TL\Functions\Stuff\TLRPCDropAnswer.cs + + + TL\Functions\Updates\TLGetDifference.cs + + + TL\Functions\Updates\TLGetState.cs + + + TL\Functions\Upload\TLGetFile.cs + + + TL\Functions\Upload\TLSaveFilePart.cs + + + TL\Functions\Users\TLGetFullUser.cs + + + TL\Functions\Users\TLGetUsers.cs + + + TL\Interfaces\IBytes.cs + + + TL\Interfaces\IFullName.cs + + + TL\Interfaces\IInputPeer.cs + + + TL\Interfaces\ISelectable.cs + + + TL\Interfaces\IVIsibility.cs + + + TL\TLAffectedHistory.cs + + + TL\TLAudio.cs + + + TL\TLAuthorization.cs + + + TL\TLBadMessageNotification.cs + + + TL\TLBadServerSalt.cs + + + TL\TLBool.cs + + + TL\TLChat.cs + + + TL\TLChatFull.cs + + + TL\TLChatParticipant.cs + + + TL\TLChatParticipants.cs + + + TL\TLChats.cs + + + TL\TLCheckedPhone.cs + + + TL\TLClientDHInnerData.cs + + + TL\TLConfig.cs + + + TL\TLContact.cs + + + TL\TLContactBlocked.cs + + + TL\TLContactFound.cs + + + TL\TLContacts.cs + + + TL\TLContactsBlocked.cs + + + TL\TLContactsFound.cs + + + TL\TLContactStatus.cs + + + TL\TLContainerTransportMessage.cs + + + TL\TLDCOption.cs + + + TL\TLDecryptedMessage.cs + + + TL\TLDecryptedMessageAction.cs + + + TL\TLDecryptedMessageLayer.cs + + + TL\TLDecryptedMessageMedia.cs + + + TL\TLDHConfig.cs + + + TL\TLDHGen.cs + + + TL\TLDialog.cs + + + TL\TLDialogs.cs + + + TL\TLDifference.cs + + + TL\TLDocument.cs + + + TL\TLDouble.cs + + + TL\TLEncryptedChat.cs + + + TL\TLEncryptedFile.cs + + + TL\TLEncryptedMessage.cs + + + TL\TLExportedAuthorization.cs + + + TL\TLFile.cs + + + TL\TLFileLocation.cs + + + TL\TLFileType.cs + + + TL\TLForeignLink.cs + + + TL\TLFutureSalt.cs + + + TL\TLGeoPoint.cs + + + TL\TLGzipPacked.cs + + + TL\TLImportedContact.cs + + + TL\TLImportedContacts.cs + + + TL\TLInitConnection.cs + + + TL\TLInputAudio.cs + + + TL\TLInputChatPhoto.cs + + + TL\TLInputContact.cs + + + TL\TLInputDocument.cs + + + TL\TLInputEncryptedChat.cs + + + TL\TLInputEncryptedFile.cs + + + TL\TLInputEncryptedFileLocation.cs + + + TL\TLInputFile.cs + + + TL\TLInputFileLocation.cs + + + TL\TLInputGeoPoint.cs + + + TL\TLInputMedia.cs + + + TL\TLInputMessagesFilter.cs + + + TL\TLInputNotifyPeer.cs + + + TL\TLInputPeerBase.cs + + + TL\TLInputPeerNotifyEvents.cs + + + TL\TLInputPeerNotifySettings.cs + + + TL\TLInputPhoto.cs + + + TL\TLInputPhotoCrop.cs + + + TL\TLInputUser.cs + + + TL\TLInputVideo.cs + + + TL\TLInt.cs + + + TL\TLInt128.cs + + + TL\TLInt256.cs + + + TL\TLInviteText.cs + + + TL\TLInvokeAfterMsg.cs + + + TL\TLLink.cs + + + TL\TLLong.cs + + + TL\TLMessage.cs + + + TL\TLMessage.Encrypted.cs + + + TL\TLMessageAction.cs + + + TL\TLMessageContainer.cs + + + TL\TLMessageInfo.cs + + + TL\TLMessageMedia.cs + + + TL\TLMessages.cs + + + TL\TLMessagesAcknowledgment.cs + + + TL\TLMessagesChatFull.cs + + + TL\TLMyLink.cs + + + TL\TLNearestDC.cs + + + TL\TLNewSessionCreated.cs + + + TL\TLNonEncryptedMessage.cs + + + TL\TLNotifyPeer.cs + + + TL\TLNull.cs + + + TL\TLObject.cs + + + TL\TLObjectGenerator.cs + + + TL\TLPeer.cs + + + TL\TLPeerNotifyEvents.cs + + + TL\TLPeerNotifySettings.cs + + + TL\TLPhoto.cs + + + TL\TLPhotos.cs + + + TL\TLPhotoSize.cs + + + TL\TLPhotosPhoto.cs + + + TL\TLPong.cs + + + TL\TLPQInnerData.cs + + + TL\TLResponse.cs + + + TL\TLResPQ.cs + + + TL\TLRPCDropAnswer.cs + + + TL\TLRPCError.cs + + + TL\TLRPCResult.cs + + + TL\TLSendMessageAction.cs + + + TL\TLSentCode.cs + + + TL\TLSentEncryptedFile.cs + + + TL\TLSentEncryptedMessage.cs + + + TL\TLSentMessage.cs + + + TL\TLServerDHInnerData.cs + + + TL\TLServerDHParams.cs + + + TL\TLServerFile.cs + + + TL\TLSignatures.cs + + + TL\TLState.cs + + + TL\TLStatedMessage.cs + + + TL\TLStatedMessages.cs + + + TL\TLString.cs + + + TL\TLSupport.cs + + + TL\TLUpdate.cs + + + TL\TLUpdates.cs + + + TL\TLUserBase.cs + + + TL\TLUserFull.cs + + + TL\TLUserStatus.cs + + + TL\TLUtils.cs + + + TL\TLUtils.Log.cs + + + TL\TLVector.cs + + + TL\TLVideo.cs + + + TL\TLWallpaperSolid.cs + + + Transport\DataEventArgs.cs + + + Transport\HttpTransport.cs + + + Transport\ITransport.cs + + + Transport\ITransportService.cs + + + Transport\TCPTransport.cs + + + Transport\TCPTransportBase.cs + + + Transport\TCPTransportResult.cs + + + Transport\TransportService.cs + + + Aggregator\EventAggregator.cs + + + Aggregator\ExtensionMethods.cs + + + Helpers\Notifications.cs + + + Logs\Log.cs + + + Services\Connection\PublicConfigService.cs + + + Services\DeviceInfo\EmptyDeviceInfoService.cs + + + Services\DeviceInfo\IDeviceInfo.cs + + + Services\FileManager\FileManagerBase.cs + + + Services\MTProtoService.Channel.cs + + + Services\MTProtoService.Langpack.cs + + + Services\MTProtoService.Payments.cs + + + Services\MTProtoService.Phone.cs + + + TL\Functions\Account\TLChangePhone.cs + + + TL\Functions\Account\TLCheckPassword.cs + + + TL\Functions\Account\TLConfirmPhone.cs + + + TL\Functions\Account\TLGetAuthorizations.cs + + + TL\Functions\Account\TLGetPassword.cs + + + TL\Functions\Account\TLGetPasswordSettings.cs + + + TL\Functions\Account\TLGetTmpPassword.cs + + + TL\Functions\Account\TLGetWallPapers.cs + + + TL\Functions\Account\TLRecoverPassword.cs + + + TL\Functions\Account\TLReportPeer.cs + + + TL\Functions\Account\TLRequestPasswordRecovery.cs + + + TL\Functions\Account\TLResetAuthorization.cs + + + TL\Functions\Account\TLResetPassword.cs + + + TL\Functions\Account\TLSendChangePhoneCode.cs + + + TL\Functions\Account\TLSendConfirmPhoneCode.cs + + + TL\Functions\Account\TLSetPassword.cs + + + TL\Functions\Account\TLUpdateDeviceLocked.cs + + + TL\Functions\Account\TLUpdatePasswordSettings.cs + + + TL\Functions\Auth\TLCancelCode.cs + + + TL\Functions\Auth\TLResendCode.cs + + + TL\Functions\Channels\TLCheckUsername.cs + + + TL\Functions\Channels\TLCreateChannel.cs + + + TL\Functions\Channels\TLDeleteChannel.cs + + + TL\Functions\Channels\TLDeleteChannelMessages.cs + + + TL\Functions\Channels\TLDeleteHistory.cs + + + TL\Functions\Channels\TLDeleteUserHistory.cs + + + TL\Functions\Channels\TLEditAbout.cs + + + TL\Functions\Channels\TLEditAdmin.cs + + + TL\Functions\Channels\TLEditMessage.cs + + + TL\Functions\Channels\TLEditPhoto.cs + + + TL\Functions\Channels\TLEditTitle.cs + + + TL\Functions\Channels\TLExportInvite.cs + + + TL\Functions\Channels\TLExportMessageLink.cs + + + TL\Functions\Channels\TLGetAdminedPublicChannels.cs + + + TL\Functions\Channels\TLGetChannels.cs + + + TL\Functions\Channels\TLGetDialogs.cs + + + TL\Functions\Channels\TLGetFullChannel.cs + + + TL\Functions\Channels\TLGetImportantHistory.cs + + + TL\Functions\Channels\TLGetMessageEditData.cs + + + TL\Functions\Channels\TLGetMessages.cs + + + TL\Functions\Channels\TLGetParticipant.cs + + + TL\Functions\Channels\TLGetParticipants.cs + + + TL\Functions\Channels\TLInviteToChannel.cs + + + TL\Functions\Channels\TLJoinChannel.cs + + + TL\Functions\Channels\TLKickFromChannel.cs + + + TL\Functions\Channels\TLLeaveChannel.cs + + + TL\Functions\Channels\TLReadHistory.cs + + + TL\Functions\Channels\TLReadMessageContents.cs + + + TL\Functions\Channels\TLReportSpam.cs + + + TL\Functions\Channels\TLSetStickers.cs + + + TL\Functions\Channels\TLToggleComments.cs + + + TL\Functions\Channels\TLToggleInvites.cs + + + TL\Functions\Channels\TLTogglePreHistoryHidden.cs + + + TL\Functions\Channels\TLToggleSignatures.cs + + + TL\Functions\Channels\TLUpdateChannelUsername.cs + + + TL\Functions\Channels\TLUpdatePinnedMessage.cs + + + TL\Functions\Contacts\TLGetTopPeers.cs + + + TL\Functions\Contacts\TLResetSaved.cs + + + TL\Functions\Contacts\TLResetTopPeerRating.cs + + + TL\Functions\Contacts\TLResolveUsername.cs + + + TL\Functions\Help\TLGetAppChangelog.cs + + + TL\Functions\Help\TLGetCdnConfig.cs + + + TL\Functions\Help\TLGetRecentMeUrls.cs + + + TL\Functions\Help\TLGetTermsOfService.cs + + + TL\Functions\Help\TLInvokeWithoutUpdates.cs + + + TL\Functions\Langpack\TLGetDifference.cs + + + TL\Functions\Langpack\TLGetLangPack.cs + + + TL\Functions\Langpack\TLGetLanguages.cs + + + TL\Functions\Langpack\TLGetStrings.cs + + + TL\Functions\Messages\TLBotGetCallbackAnswer.cs + + + TL\Functions\Messages\TLCheckChatInvite.cs + + + TL\Functions\Messages\TLClearRecentStickers.cs + + + TL\Functions\Messages\TLDeactivateChat.cs + + + TL\Functions\Messages\TLEditChatAdmin.cs + + + TL\Functions\Messages\TLExportChatInvite.cs + + + TL\Functions\Messages\TLFaveSticker.cs + + + TL\Functions\Messages\TLGetAllDrafts.cs + + + TL\Functions\Messages\TLGetAllStickers.cs + + + TL\Functions\Messages\TLGetArchivedStickers.cs + + + TL\Functions\Messages\TLGetAttachedStickers.cs + + + TL\Functions\Messages\TLGetCommonChats.cs + + + TL\Functions\Messages\TLGetDocumentByHash.cs + + + TL\Functions\Messages\TLGetFavedStickers.cs + + + TL\Functions\Messages\TLGetFeaturedStickers.cs + + + TL\Functions\Messages\TLGetInlineBotResults.cs + + + TL\Functions\Messages\TLGetMaskStickers.cs + + + TL\Functions\Messages\TLGetPeerDialogs.cs + + + TL\Functions\Messages\TLGetPeerSettings.cs + + + TL\Functions\Messages\TLGetPinnedDialogs.cs + + + TL\Functions\Messages\TLGetRecentLocations.cs + + + TL\Functions\Messages\TLGetRecentStickers.cs + + + TL\Functions\Messages\TLGetSavedGifs.cs + + + TL\Functions\Messages\TLGetStickers.cs + + + TL\Functions\Messages\TLGetStickerSet.cs + + + TL\Functions\Messages\TLGetUnreadMentions.cs + + + TL\Functions\Messages\TLGetUnusedStickers.cs + + + TL\TLGetWebPage.cs + + + TL\Functions\Messages\TLGetWebPagePreview.cs + + + TL\Functions\Messages\TLHideReportSpam.cs + + + TL\Functions\Messages\TLImportChatInvite.cs + + + TL\Functions\Messages\TLInstallStickerSet.cs + + + TL\Functions\Messages\TLMigrateChat.cs + + + TL\Functions\Messages\TLReadFeaturedStickers.cs + + + TL\Functions\Messages\TLReadMentions.cs + + + TL\Functions\Messages\TLReorderPinnedDialogs.cs + + + TL\Functions\Messages\TLReorderStickerSets.cs + + + TL\Functions\Messages\TLReportSpam.cs + + + TL\Functions\Messages\TLSaveDraft.cs + + + TL\Functions\Messages\TLSaveGif.cs + + + TL\Functions\Messages\TLSearchGifs.cs + + + TL\Functions\Messages\TLSendInlineBotResult.cs + + + TL\Functions\Messages\TLSendMultiMedia.cs + + + TL\Functions\Messages\TLSetBotCallbackAnswer.cs + + + TL\Functions\Messages\TLSetInlineBotResults.cs + + + TL\Functions\Messages\TLStartBot.cs + + + TL\Functions\Messages\TLToggleChatAdmins.cs + + + TL\Functions\Messages\TLToggleDialogPin.cs + + + TL\Functions\Messages\TLUninstallStickerSet.cs + + + TL\Functions\Messages\TLUploadMedia.cs + + + TL\Functions\Payments\TLClearSavedInfo.cs + + + TL\Functions\Payments\TLGetPaymentForm.cs + + + TL\Functions\Payments\TLGetPaymentReceipt.cs + + + TL\Functions\Payments\TLGetSavedInfo.cs + + + TL\Functions\Payments\TLSendPaymentForm.cs + + + TL\Functions\Payments\TLValidateRequestedInfo.cs + + + TL\Functions\Phone\TLAcceptCall.cs + + + TL\Functions\Phone\TLConfirmCall.cs + + + TL\Functions\Phone\TLDiscardCall.cs + + + TL\Functions\Phone\TLGetCallConfig.cs + + + TL\Functions\Phone\TLReceivedCall.cs + + + TL\Functions\Phone\TLRequestCall.cs + + + TL\Functions\Phone\TLSaveCallDebug.cs + + + TL\Functions\Phone\TLSetCallRating.cs + + + TL\Functions\Updates\TLGetChannelDifference.cs + + + TL\Functions\Upload\TLGetCdnFile.cs + + + TL\Functions\Upload\TLReuploadCdnFile.cs + + + TL\TLAccountAuthorization.cs + + + TL\TLAccountAuthorizations.cs + + + TL\TLAccountDaysTTL.cs + + + TL\TLActionInfo.cs + + + TL\TLAdminLogResults.cs + + + TL\TLAffectedMessages.cs + + + TL\TLAllStrickers.cs + + + TL\TLAppChangelogBase.cs + + + TL\TLArchivedStickers.cs + + + TL\TLBotCallbackAnswer.cs + + + TL\TLBotCommand.cs + + + TL\TLBotInfo.cs + + + TL\TLBotInlineMessage.cs + + + TL\TLBotInlineResult.cs + + + TL\TLBotResults.cs + + + TL\TLCallsSecurity.cs + + + TL\TLCameraSettings.cs + + + TL\TLCdnConfig.cs + + + TL\TLCdnFile.cs + + + TL\TLCdnPublicKey.cs + + + TL\TLChannelAdminLogEvent.cs + + + TL\TLChannelAdminLogEventAction.cs + + + TL\TLChannelAdminLogEventsFilter.cs + + + TL\TLChannelAdminRights.cs + + + TL\TLChannelBannedRights.cs + + + TL\TLChannelDifference.cs + + + TL\TLChannelMessagesFiler.cs + + + TL\TLChannelParticipant.cs + + + TL\TLChannelParticipantRole.cs + + + TL\TLChannelParticipantsFilter.cs + + + TL\TLChatInvite.cs + + + TL\TLChatSettings.cs + + + TL\TLCodeType.cs + + + TL\TLConfigSimple.cs + + + TL\TLContactLink.cs + + + TL\TLDataJSON.cs + + + TL\TLDisabledFeature.cs + + + TL\TLDocumentAttribute.cs + + + TL\TLDraftMessage.cs + + + TL\TLExportedMessageLink.cs + + + TL\TLFavedStickers.cs + + + TL\TLFeaturedStickers.cs + + + TL\TLFoundGif.cs + + + TL\TLFoundGifs.cs + + + TL\TLGame.cs + + + TL\TLHashtagItem.cs + + + TL\TLHighScore.cs + + + TL\TLHighScores.cs + + + TL\TLInlineBotSwitchPM.cs + + + TL\TLInputBotInlineMessage.cs + + + TL\TLInputBotInlineMessageId.cs + + + TL\TLInputBotInlineResult.cs + + + TL\TLInputChatBase.cs + + + TL\TLInputGame.cs + + + TL\TLInputMessageEntityMentionName.cs + + + TL\TLInputPaymentCredentials.cs + + + TL\TLInputPhoneCall.cs + + + TL\TLInputPrivacyKey.cs + + + TL\TLInputPrivacyRule.cs + + + TL\TLInputReportReason.cs + + + TL\TLInputSingleMedia.cs + + + TL\TLInputStickeredMedia.cs + + + TL\TLInputStickerSet.cs + + + TL\TLInputWebDocument.cs + + + TL\TLInvoice.cs + + + TL\TLIpPort.cs + + + TL\TLKeyboardButton.cs + + + TL\TLKeyboardButtonRow.cs + + + TL\TLLabeledPrice.cs + + + TL\TLLangPackDifference.cs + + + TL\TLLangPackLanguage.cs + + + TL\TLLangPackString.cs + + + TL\TLMaskCoords.cs + + + TL\TLMessageEditData.cs + + + TL\TLMessageEntity.cs + + + TL\TLMessageFwdHeader.cs + + + TL\TLMessageGroup.cs + + + TL\TLMessageRange.cs + + + TL\TLMessagesChannelParticipants.cs + + + TL\TLMessagesStickerSet.cs + + + TL\TLPage.cs + + + TL\TLPageBlock.cs + + + TL\TLPasscodeParams.cs + + + TL\TLPassword.cs + + + TL\TLPasswordInputSettings.cs + + + TL\TLPasswordRecovery.cs + + + TL\TLPasswordSettings.cs + + + TL\TLPaymentCharge.cs + + + TL\TLPaymentForm.cs + + + TL\TLPaymentReceipt.cs + + + TL\TLPaymentRequestedInfo.cs + + + TL\TLPaymentResult.cs + + + TL\TLPaymentSavedCredentialsCard.cs + + + TL\TLPeerDialogs.cs + + + TL\TLPeerSettings.cs + + + TL\TLPhoneCall.cs + + + TL\TLPhoneCallDiscardReason.cs + + + TL\TLPhoneCallProtocol.cs + + + TL\TLPhoneConnection.cs + + + TL\TLPhonePhoneCall.cs + + + TL\TLPhotoPickerSettings.cs + + + TL\TLPopularContact.cs + + + TL\TLPostAddress.cs + + + TL\TLPrivacyKey.cs + + + TL\TLPrivacyRule.cs + + + TL\TLPrivacyRules.cs + + + TL\TLProxyConfig.cs + + + TL\TLReceivedNotifyMessage.cs + + + TL\TLRecentlyUsedSticker.cs + + + TL\TLRecentMeUrl.cs + + + TL\TLRecentMeUrls.cs + + + TL\TLRecentStickers.cs + + + TL\TLReplyKeyboardMarkup.cs + + + TL\TLResolvedPeer.cs + + + TL\TLResultInfo.cs + + + TL\TLRichText.cs + + + TL\TLSavedGifs.cs + + + TL\TLSavedInfo.cs + + + TL\TLSentChangePhoneCode.cs + + + TL\TLSentCodeType.cs + + + TL\TLShippingOption.cs + + + TL\TLStickerPack.cs + + + TL\TLStickers.cs + + + TL\TLStickerSet.cs + + + TL\TLStickerSetCovered.cs + + + TL\TLStickerSetInstallResult.cs + + + TL\TLTermsOfService.cs + + + TL\TLTmpPassword.cs + + + TL\TLTopPeer.cs + + + TL\TLTopPeerCategory.cs + + + TL\TLTopPeerCategoryPeers.cs + + + TL\TLTopPeers.cs + + + TL\TLValidatedRequestedInfo.cs + + + TL\TLWebDocument.cs + + + TL\TLWebFile.cs + + + TL\TLWebPage.cs + + + Transport\SocksProxy.cs + + + WindowsPhone\BigInteger.cs + + + WindowsPhone\Tuple.cs + + + + AppResources.ru.resx + True + True + + + AppResources.pt.resx + True + True + + + AppResources.nl.resx + True + True + + + AppResources.it.resx + True + True + + + AppResources.es.resx + True + True + + + AppResources.de.resx + True + True + + + True + True + AppResources.resx + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ..\packages\Portable.BouncyCastle.1.7.0.2\lib\portable-net4+sl5+wp8+win8+wpa81+MonoTouch10+MonoAndroid10+xamarinmac20+xamarinios10\crypto.dll + + + ..\packages\Rx-Core.2.2.2\lib\windowsphone71\System.Reactive.Core.dll + + + ..\packages\Rx-Linq.2.2.2\lib\windowsphone71\System.Reactive.Linq.dll + + + ..\packages\Rx-Interfaces.2.2.2\lib\windowsphone71\System.Reactive.Interfaces.dll + + + + + + + + ResXFileCodeGenerator + AppResources.ru.Designer.cs + + + ResXFileCodeGenerator + AppResources.pt.Designer.cs + + + ResXFileCodeGenerator + AppResources.nl.Designer.cs + + + ResXFileCodeGenerator + AppResources.it.Designer.cs + + + ResXFileCodeGenerator + AppResources.es.Designer.cs + + + ResXFileCodeGenerator + AppResources.de.Designer.cs + + + ResXFileCodeGenerator + AppResources.Designer.cs + + + + + {cc7a35bf-aabc-411d-b911-ac037a781266} + libtgnet + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/Telegram.Api.WP8/Transport/NativeTcpTransport.cs b/Telegram.Api.WP8/Transport/NativeTcpTransport.cs new file mode 100755 index 0000000..e98bea6 --- /dev/null +++ b/Telegram.Api.WP8/Transport/NativeTcpTransport.cs @@ -0,0 +1,365 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using Windows.Networking; +using libtgnet; +using Telegram.Api.Extensions; +using Telegram.Api.TL; + +namespace Telegram.Api.Transport +{ + public class NativeTcpTransport : TcpTransportBase + { + private readonly ConnectionSocketWrapper _wrapper; + + private bool _isConnected; + + private readonly List, Action>> _requests = new List, Action>>(); + + public override ulong Ping + { + get + { + ulong ping; + lock (SyncRoot) + { + ping = _wrapper != null ? _wrapper.GetPing() : 0; + } + return ping; + } + } + + private ProxySettings _proxySettings; + + public NativeTcpTransport(string host, int port, string staticHost, int staticPort, MTProtoTransportType mtProtoType, short protocolDCId, byte[] protocolSecret, TLProxyConfigBase proxyConfig) + : base(host, port, staticHost, staticPort, mtProtoType, proxyConfig) + { +// System.Diagnostics.Debug.WriteLine( +// " [NativeTcpTransport] .ctor begin host={0} port={1} static_host={2} static_port={3} type={4} protocol_dcid={5} protocol_secret={6} proxy={7}", +// host, port, staticHost, staticPort, mtProtoType, protocolDCId, protocolSecret, proxyConfig); + + ActualHost = host; + ActualPort = port; + + var ipv4 = true; + ProxySettings proxySettings = null; + if (proxyConfig != null && proxyConfig.IsEnabled.Value && !proxyConfig.IsEmpty) + { + var socks5Proxy = proxyConfig.GetProxy() as TLSocks5Proxy; + if (socks5Proxy != null) + { + try + { + ipv4 = new HostName(socks5Proxy.Server.ToString()).Type == HostNameType.Ipv4; + } + catch (Exception ex) + { + + } + proxySettings = new ProxySettings + { + Type = ProxyType.Socks5, + Host = socks5Proxy.Server.ToString(), + Port = socks5Proxy.Port.Value, + Username = socks5Proxy.Username.ToString(), + Password = socks5Proxy.Password.ToString(), + IPv4 = ipv4 + }; + + ActualHost = staticHost; + ActualPort = staticPort; + protocolSecret = null; + protocolDCId = protocolDCId; + } + var mtProtoProxy = proxyConfig.GetProxy() as TLMTProtoProxy; + if (mtProtoProxy != null) + { + try + { + ipv4 = new HostName(mtProtoProxy.Server.ToString()).Type == HostNameType.Ipv4; + } + catch (Exception ex) + { + + } + proxySettings = new ProxySettings + { + Type = ProxyType.MTProto, + Host = mtProtoProxy.Server.ToString(), + Port = mtProtoProxy.Port.Value, + Secret = TLUtils.ParseSecret(mtProtoProxy.Secret), + IPv4 = ipv4 + }; + + ActualHost = staticHost; + ActualPort = staticPort; + } + } + + try + { + ipv4 = new HostName(ActualHost).Type == HostNameType.Ipv4; + } + catch (Exception ex) + { + + } + + var connectionSettings = new ConnectionSettings + { + Host = ActualHost, + Port = ActualPort, + IPv4 = ipv4, + ProtocolDCId = protocolDCId, + ProtocolSecret = protocolSecret + }; + + _proxySettings = proxySettings; + +// var proxyString = proxySettings == null +// ? "null" +// : string.Format("[host={0} port={1} ipv4={2} type={3} secret={4} username={5} password={6}]", +// proxySettings.Host, +// proxySettings.Port, +// proxySettings.IPv4, +// proxySettings.Type, +// proxySettings.Secret, +// proxySettings.Username, +// proxySettings.Password); +// System.Diagnostics.Debug.WriteLine( +// " [NativeTcpTransport] .ctor end host={0} port={1} ipv4={2} protocol_dcid={3} protocol_secret={4} proxy={5}", +// connectionSettings.Host, connectionSettings.Port, connectionSettings.IPv4, connectionSettings.ProtocolDCId, connectionSettings.ProtocolSecret, proxyString); + + _wrapper = new ConnectionSocketWrapper(connectionSettings, proxySettings); + _wrapper.Closed += Wrapper_OnClosed; + _wrapper.PacketReceived += Wrapper_OnPacketReceived; + } + + private void Wrapper_OnPacketReceived(ConnectionSocketWrapper sender, byte[] data) + { + LastReceiveTime = DateTime.Now; + + StopCheckConfigTimer(); + RaiseConnectedAsync(); + lock (SyncRoot) + { + _isConnected = true; + } + + Helpers.Execute.BeginOnThreadPool(() => + { + RaisePacketReceived(new DataEventArgs(data)); + }); + } + + private void Wrapper_OnClosed(ConnectionSocketWrapper sender) + { + RaiseConnectionLost(); + } + + ~NativeTcpTransport() + { + + } + + private void LOG(string message) + { + System.Diagnostics.Debug.WriteLine("NativeTcpTransport " + Host + " " + message); + } + + public override void SendPacketAsync(string caption, byte[] data, Action callback, Action faultCallback = null) + { + var now = DateTime.Now; + if (!FirstSendTime.HasValue) + { + FirstSendTime = now; + } + + Helpers.Execute.BeginOnThreadPool(() => + { + var isConnected = false; + var isConnecting = false; + var result = -1; + + lock (SyncRoot) + { + isConnected = _isConnected; + if (!isConnected) + { + _requests.Add(new Tuple, Action>(data, callback, faultCallback)); + isConnecting = _requests.Count == 1; + } + } + + if (isConnected) + { + lock (SyncRoot) + { + try + { + result = _wrapper.SendPacket(data); + } + catch (Exception ex) + { + + } + } + + if (result > 0 && result < data.Length) + { + Helpers.Execute.ShowDebugMessage(string.Format("NativeTransport Send req={0} sent={1}", data.Length, result)); + callback.SafeInvoke(true); + } + else if (result > 0) + { + callback.SafeInvoke(true); + } + else + { + faultCallback.SafeInvoke(new TcpTransportResult(new Exception("NativeTCPTransport error=" + result))); + } + + return; + } + + if (isConnecting) + { + RaiseConnectingAsync(); + result = -1; + + try + { + //LOG("Connect start"); + result = _wrapper.Connect(); + //LOG("Connect end"); + } + catch (Exception ex) + { + + } + + isConnected = result > 0; + if (!isConnected) + { + List, Action>> requests; + lock (SyncRoot) + { + _isConnected = false; + requests = new List, Action>>(_requests); + _requests.Clear(); + } + + if (requests.Count > 0) + { + for (var i = 0; i < requests.Count; i++) + { + requests[i].Item3.SafeInvoke(new TcpTransportResult(new Exception("NativeTCPTransport connect error=" + result))); + } + } + } + else + { + Helpers.Execute.BeginOnThreadPool(() => + { + try + { + _wrapper.StartReceive(); + } + catch (Exception ex) + { + + } + }); + + List, Action>> requests; + lock (SyncRoot) + { + _isConnected = true; + requests = new List, Action>>(_requests); + _requests.Clear(); + } + + if (requests.Count > 0) + { + for (var i = 0; i < requests.Count; i++) + { + lock (SyncRoot) + { + try + { + result = _wrapper.SendPacket(requests[i].Item1); + } + catch (Exception ex) + { + + } + } + if (result > 0 && result < requests[i].Item1.Length) + { + Helpers.Execute.ShowDebugMessage(string.Format("NativeTransport Send req={0} sent={1}", requests[i].Item1.Length, result)); + requests[i].Item2.SafeInvoke(true); + } + else if (result > 0) + { + requests[i].Item2.SafeInvoke(true); + } + else + { + requests[i].Item3.SafeInvoke(new TcpTransportResult(new Exception("NativeTCPTransport error=" + result))); + } + } + } + } + } + }); + } + + public override void Close() + { + WRITE_LOG(string.Format("Close socket {2} {0}:{1}", Host, Port, Id)); + + List, Action>> requests; + + lock (SyncRoot) + { + if (Closed) + { + return; + } + try + { + _wrapper.Closed -= Wrapper_OnClosed; + _wrapper.PacketReceived -= Wrapper_OnPacketReceived; + _wrapper.Close(); + } + catch (Exception ex) + { + Helpers.Execute.ShowDebugMessage("NativeTCPTransport.Close ex " + ex); + } + Closed = true; + requests = new List, Action>>(_requests); + _requests.Clear(); + StopCheckConfigTimer(); + } + + if (requests.Count > 0) + { + for (var i = 0; i < requests.Count; i++) + { + requests[i].Item3.SafeInvoke(new TcpTransportResult(new Exception("NativeTCPTransport closed"))); + } + } + } + + public override string GetTransportInfo() + { + return string.Empty; + } + } +} \ No newline at end of file diff --git a/Telegram.Api.WP8/Transport/TCPTransportWinRT.cs b/Telegram.Api.WP8/Transport/TCPTransportWinRT.cs new file mode 100755 index 0000000..6cfc486 --- /dev/null +++ b/Telegram.Api.WP8/Transport/TCPTransportWinRT.cs @@ -0,0 +1,412 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define TCP_OBFUSCATED_2 +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Windows.Foundation; +using Windows.Networking; +using Windows.Networking.Sockets; +using Windows.Storage.Streams; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; + +namespace Telegram.Api.Transport +{ + public class TcpTransportWinRT : TcpTransportBase + { + private readonly StreamSocket _socket; + + private readonly object _isConnectedSyncRoot = new object(); + + private bool _isConnected; + + private readonly object _dataWriterSyncRoot = new object(); + + private readonly DataReader _dataReader; + + private readonly DataWriter _dataWriter; + + private readonly double _timeout; + + public TcpTransportWinRT(string host, int port, string staticHost, int staticPort, MTProtoTransportType mtProtoType, TLProxyConfigBase proxyConfig) + : base(host, port, staticHost, staticPort, mtProtoType, proxyConfig) + { + _timeout = 25.0; + _socket = new StreamSocket(); + var control = _socket.Control; + control.QualityOfService = SocketQualityOfService.LowLatency; + + _dataReader = new DataReader(_socket.InputStream) { InputStreamOptions = InputStreamOptions.Partial }; + _dataWriter = new DataWriter(_socket.OutputStream); + } + +#if TCP_OBFUSCATED_2 + private byte[] GetInitBufferInternal() + { + var buffer = new byte[64]; + var random = new Random(); + while (true) + { + random.NextBytes(buffer); + + var val = (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | (buffer[0]); + var val2 = (buffer[7] << 24) | (buffer[6] << 16) | (buffer[5] << 8) | (buffer[4]); + if (buffer[0] != 0xef + && val != 0x44414548 + && val != 0x54534f50 + && val != 0x20544547 + && val != 0x4954504f + && val != 0xeeeeeeee + && val2 != 0x00000000) + { + buffer[56] = buffer[57] = buffer[58] = buffer[59] = 0xef; + break; + } + } + + var keyIvEncrypt = buffer.SubArray(8, 48); + EncryptKey = keyIvEncrypt.SubArray(0, 32); + EncryptIV = keyIvEncrypt.SubArray(32, 16); + //Array.Reverse(EncryptIV); + + Array.Reverse(keyIvEncrypt); + DecryptKey = keyIvEncrypt.SubArray(0, 32); + DecryptIV = keyIvEncrypt.SubArray(32, 16); + //Array.Reverse(DecryptIV); + + //var shortStamp = BitConverter.GetBytes(0xefefefef); + //for (var i = 0; i < shortStamp.Length; i++) + //{ + // buffer[56 + i] = shortStamp[i]; + //} + + var encryptedBuffer = Encrypt(buffer); + for (var i = 56; i < encryptedBuffer.Length; i++) + { + buffer[i] = encryptedBuffer[i]; + } + + return buffer; + } + + protected override byte[] GetInitBuffer() + { + return GetInitBufferInternal(); + } +#endif + + private async Task ConnectAsync(double timeout, Action faultCallback) + { + TLSocks5Proxy socks5Proxy = ProxyConfig != null && ProxyConfig.IsEnabled.Value && !ProxyConfig.IsEmpty + ? ProxyConfig.GetProxy() as TLSocks5Proxy + : null; + + if (socks5Proxy != null) + { + try + { + ActualHost = StaticHost; + ActualPort = StaticPort; + + RaiseConnectingAsync(); + + await SocksProxy.ConnectToSocks5Proxy(timeout, _socket, _dataWriter, _dataReader, socks5Proxy.Server.ToString(), (ushort)socks5Proxy.Port.Value, StaticHost, (ushort)StaticPort, socks5Proxy.Username.ToString(), socks5Proxy.Password.ToString()); + + lock (_dataWriterSyncRoot) + { + var buffer = GetInitBufferInternal(); + _dataWriter.WriteBytes(buffer); + + var result = _dataWriter.StoreAsync().AsTask().Result; + } + + lock (_isConnectedSyncRoot) + { + _isConnecting = false; + _isConnected = true; + } + } + catch (Exception ex) + { + var status = SocketError.GetStatus(ex.HResult); + WRITE_LOG("TCPTransportWinRT.ConnectAsync " + status, ex); + + var error = SocketError.GetStatus(ex.HResult); + faultCallback.SafeInvoke(new TcpTransportResult(ex)); + return false; + } + } + else + { + try + { + ActualHost = Host; + ActualPort = Port; + + RaiseConnectingAsync(); + + //var address = IPAddress.IsValidIPv6(Host); + await _socket.ConnectAsync(new HostName(Host), Port.ToString(CultureInfo.InvariantCulture)).WithTimeout(timeout); + + lock (_dataWriterSyncRoot) + { + var buffer = GetInitBufferInternal(); + _dataWriter.WriteBytes(buffer); + } + + lock (_isConnectedSyncRoot) + { + _isConnecting = false; + _isConnected = true; + } + } + catch (Exception ex) + { + var status = SocketError.GetStatus(ex.HResult); + WRITE_LOG("TCPTransportWinRT.ConnectAsync " + status, ex); + + var error = SocketError.GetStatus(ex.HResult); + faultCallback.SafeInvoke(new TcpTransportResult(ex)); + return false; + } + } + + return true; + } + + private async Task SendAsync(double timeout, byte[] data, Action faultCallback) + { + try + { +#if TCP_OBFUSCATED_2 + lock (_dataWriterSyncRoot) + { + data = Encrypt(data); + _dataWriter.WriteBytes(data); + } + + var storeResult = await _dataWriter.StoreAsync(); +#else + lock (_dataWriterSyncRoot) + { + _dataWriter.WriteBytes(data); + } + var storeResult = await _dataWriter.StoreAsync();//.WithTimeout(timeout); +#endif + } + catch (Exception ex) + { + var status = SocketError.GetStatus(ex.HResult); + WRITE_LOG("TCPTransportWinRT.SendAsync " + status, ex); + + faultCallback.SafeInvoke(new TcpTransportResult(ex)); + return false; + } + + return true; + } + + private async void ReceiveAsync(double timeout) + { + while (true) + { + if (Closed) + { + return; + } + + int bytesTransferred = 0; + try + { + bytesTransferred = (int)await _dataReader.LoadAsync(64); //WithTimeout(timeout); + } + catch (Exception ex) + { + //Log.Write(string.Format(" TCPTransport.ReceiveAsync transport={0} LoadAsync exception={1}", Id, ex)); + var status = SocketError.GetStatus(ex.HResult); + WRITE_LOG("ReceiveAsync DataReader.LoadAsync " + status, ex); + + if (ex is ObjectDisposedException) + { + return; + } + } + + if (bytesTransferred > 0) + { + //Log.Write(string.Format(" TCPTransport.ReceiveAsync transport={0} bytes_transferred={1}", Id, bytesTransferred)); + + var now = DateTime.Now; + + if (!FirstReceiveTime.HasValue) + { + FirstReceiveTime = now; + RaiseConnectedAsync(); + } + + LastReceiveTime = now; + + var buffer = new byte[_dataReader.UnconsumedBufferLength]; + _dataReader.ReadBytes(buffer); + +#if TCP_OBFUSCATED_2 + buffer = Decrypt(buffer); +#endif + + OnBufferReceived(buffer, 0, bytesTransferred); + } + else + { + //Log.Write(string.Format(" TCPTransport.ReceiveAsync transport={0} bytes_transferred={1} closed={2}", Id, bytesTransferred, Closed)); + if (!Closed) + { + Closed = true; + RaiseConnectionLost(); + Execute.ShowDebugMessage("TCPTransportWinRT ReceiveAsync connection lost bytesTransferred=0; close transport"); + } + } + } + } + + private bool _isConnecting; + + private readonly List>> _queue = new List>>(); + + public override void SendPacketAsync(string caption, byte[] data, Action callback, Action faultCallback = null) + { + var now = DateTime.Now; + if (!FirstSendTime.HasValue) + { + FirstSendTime = now; + } + + Execute.BeginOnThreadPool(async () => + { + bool connect = false; + bool isConnected; + lock (_isConnectedSyncRoot) + { + isConnected = _isConnected; + if (!_isConnected && !_isConnecting) + { + _isConnecting = true; + connect = true; + } + + if (connect + && caption.StartsWith("msgs_ack")) + { + Execute.ShowDebugMessage("TCPTransportWinRT connect on msgs_ack"); + connect = false; + } + } + + if (!isConnected) + { + if (connect) + { + var connectResult = await ConnectAsync(_timeout, faultCallback); + if (!connectResult) return; + + //var buffer = GetInitBuffer(); + //var sendResult = await SendAsync(_timeout, buffer, faultCallback); + //if (!sendResult) return; + + ReceiveAsync(_timeout); + + SendQueue(_timeout); + } + else + { + Enqueue(caption, data, faultCallback); + return; + } + } + + var sendPacketResult = await SendAsync(_timeout, CreatePacket(data), faultCallback); + if (!sendPacketResult) return; + + callback.SafeInvoke(true); + }); + } + + private void Enqueue(string caption, byte[] data, Action faultCallback) + { + lock (_isConnectedSyncRoot) + { + _queue.Add(new Tuple>(caption, data, faultCallback)); + } + } + + private void SendQueue(double timeout) + { + var queue = new List>>(); + var info = new StringBuilder(); + info.Append("SendQueue"); + lock (_isConnectedSyncRoot) + { + foreach (var tuple in _queue) + { + queue.Add(tuple); + info.AppendLine(tuple.Item1); + } + + _queue.Clear(); + } + + //Execute.ShowDebugMessage(info.ToString()); + + foreach (var tuple in queue) + { + SendAsync(timeout, CreatePacket(tuple.Item2), tuple.Item3); + } + } + + public override void Close() + { + Closed = true; + if (_socket != null) + { + _socket.Dispose(); + } + + StopCheckConfigTimer(); + } + + public override string GetTransportInfo() + { + var info = new StringBuilder(); + info.AppendLine("TCP_WinRT transport"); + info.AppendLine(string.Format("Socket {0}:{1}, Connected={2}, HashCode={3}", Host, Port, _isConnected, _socket.GetHashCode())); + info.AppendLine(string.Format("LastReceiveTime={0}", LastReceiveTime.GetValueOrDefault().ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture))); + info.AppendLine(string.Format("FirstSendTime={0}", FirstSendTime.GetValueOrDefault().ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture))); + + return info.ToString(); + } + } + + public static class AsyncExtensions + { + public static async Task WithTimeout(this IAsyncAction task, double timeout) + { + var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeout)); + await task.AsTask(cts.Token); + } + + public static async Task WithTimeout(this IAsyncOperation task, double timeout) + { + var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeout)); + return await task.AsTask(cts.Token); + } + } +} diff --git a/Telegram.Api.WP8/packages.config b/Telegram.Api.WP8/packages.config new file mode 100755 index 0000000..fa7617b --- /dev/null +++ b/Telegram.Api.WP8/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Telegram.Api/Aggregator/EventAggregator.cs b/Telegram.Api/Aggregator/EventAggregator.cs new file mode 100755 index 0000000..a46c101 --- /dev/null +++ b/Telegram.Api/Aggregator/EventAggregator.cs @@ -0,0 +1,277 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; + +namespace Telegram.Api.Aggregator { + /// + /// A marker interface for classes that subscribe to messages. + /// + public interface IHandle { } + + /// + /// Denotes a class which can handle a particular type of message. + /// + /// The type of message to handle. + public interface IHandle : IHandle { //don't use contravariance here + /// + /// Handles the message. + /// + /// The message. + void Handle(TMessage message); + } + + /// + /// Enables loosely-coupled publication of and subscription to events. + /// + public interface ITelegramEventAggregator { + /// + /// Gets or sets the default publication thread marshaller. + /// + /// + /// The default publication thread marshaller. + /// + Action PublicationThreadMarshaller { get; set; } + + /// + /// Searches the subscribed handlers to check if we have a handler for + /// the message type supplied. + /// + /// The message type to check with + /// True if any handler is found, false if not. + bool HandlerExistsFor(Type messageType); + + /// + /// Subscribes an instance to all events declared through implementations of + /// + /// The instance to subscribe for event publication. + void Subscribe(object subscriber); + + /// + /// Unsubscribes the instance from all events. + /// + /// The instance to unsubscribe. + void Unsubscribe(object subscriber); + + /// + /// Publishes a message. + /// + /// The message instance. + /// + /// Uses the default thread marshaller during publication. + /// + void Publish(object message); + + /// + /// Publishes a message. + /// + /// The message instance. + /// Allows the publisher to provide a custom thread marshaller for the message publication. + void Publish(object message, Action marshal); + } + + /// + /// Enables loosely-coupled publication of and subscription to events. + /// + public class TelegramEventAggregator : ITelegramEventAggregator { + readonly List handlers = new List(); + + /// + /// The default thread marshaller used for publication; + /// + public static Action DefaultPublicationThreadMarshaller = action => action(); + + /// + /// Processing of handler results on publication thread. + /// + public static Action HandlerResultProcessing = (target, result) => { }; + + public static ITelegramEventAggregator Instance { get; protected set; } + + /// + /// Initializes a new instance of the class. + /// + public TelegramEventAggregator() { + PublicationThreadMarshaller = DefaultPublicationThreadMarshaller; + + Instance = this; + } + + /// + /// Gets or sets the default publication thread marshaller. + /// + /// + /// The default publication thread marshaller. + /// + public Action PublicationThreadMarshaller { get; set; } + + /// + /// Searches the subscribed handlers to check if we have a handler for + /// the message type supplied. + /// + /// The message type to check with + /// True if any handler is found, false if not. + public bool HandlerExistsFor(Type messageType) { + return handlers.Any(handler => handler.Handles(messageType) & !handler.IsDead); + } + + /// + /// Subscribes an instance to all events declared through implementations of + /// + /// The instance to subscribe for event publication. + public virtual void Subscribe(object subscriber) { + if (subscriber == null) { + throw new ArgumentNullException("subscriber"); + } + lock(handlers) { + if (handlers.Any(x => x.Matches(subscriber))) { + return; + } + + handlers.Add(new Handler(subscriber)); + } + } + + /// + /// Unsubscribes the instance from all events. + /// + /// The instance to unsubscribe. + public virtual void Unsubscribe(object subscriber) { + if (subscriber == null) { + throw new ArgumentNullException("subscriber"); + } + lock(handlers) { + var found = handlers.FirstOrDefault(x => x.Matches(subscriber)); + + if (found != null) { + handlers.Remove(found); + } + } + } + + public static bool LogPublish { get; set; } + + /// + /// Publishes a message. + /// + /// The message instance. + /// + /// Does not marshall the the publication to any special thread by default. + /// + public virtual void Publish(object message) { + if (message == null) { + throw new ArgumentNullException("message"); + } + +#if DEBUG + if (LogPublish) + { + Debug.WriteLine("Publish " + message.GetType()); + } +#endif + + Publish(message, PublicationThreadMarshaller); + } + + /// + /// Publishes a message. + /// + /// The message instance. + /// Allows the publisher to provide a custom thread marshaller for the message publication. + public virtual void Publish(object message, Action marshal) { + if (message == null){ + throw new ArgumentNullException("message"); + } + if (marshal == null) { + throw new ArgumentNullException("marshal"); + } + + Handler[] toNotify; + lock (handlers) { + toNotify = handlers.ToArray(); + } + + marshal(() => { + var messageType = message.GetType(); + + var dead = toNotify + .Where(handler => !handler.Handle(messageType, message)) + .ToList(); + + if(dead.Any()) { + lock(handlers) { + dead.Apply(x => handlers.Remove(x)); + } + } + }); + } + + class Handler { + readonly WeakReference reference; + readonly Dictionary supportedHandlers = new Dictionary(); + + public bool IsDead { + get { return reference.Target == null; } + } + + public Handler(object handler) { + reference = new WeakReference(handler); + +#if WIN_RT + var handlerInfo = typeof(IHandle).GetTypeInfo(); + var interfaces = handler.GetType().GetTypeInfo().ImplementedInterfaces + .Where(x => handlerInfo.IsAssignableFrom(x.GetTypeInfo()) && x.GetTypeInfo().IsGenericType); + + foreach (var @interface in interfaces) { + var type = @interface.GenericTypeArguments[0]; + var method = @interface.GetTypeInfo().DeclaredMethods.First(x => x.Name == "Handle"); + supportedHandlers[type] = method; + } +#else + var interfaces = handler.GetType().GetInterfaces() + .Where(x => typeof(IHandle).IsAssignableFrom(x) && x.IsGenericType); + + foreach(var @interface in interfaces) { + var type = @interface.GetGenericArguments()[0]; + var method = @interface.GetMethod("Handle"); + supportedHandlers[type] = method; + } +#endif + } + + public bool Matches(object instance) { + return reference.Target == instance; + } + + public bool Handle(Type messageType, object message) { + var target = reference.Target; + if (target == null) { + return false; + } + + foreach(var pair in supportedHandlers) { + if(pair.Key.IsAssignableFrom(messageType)) { + var result = pair.Value.Invoke(target, new[] { message }); + if (result != null) { + HandlerResultProcessing(target, result); + } + } + } + + return true; + } + + public bool Handles(Type messageType) { + return supportedHandlers.Any(pair => pair.Key.IsAssignableFrom(messageType)); + } + } + } +} diff --git a/Telegram.Api/Aggregator/ExtensionMethods.cs b/Telegram.Api/Aggregator/ExtensionMethods.cs new file mode 100755 index 0000000..18466f3 --- /dev/null +++ b/Telegram.Api/Aggregator/ExtensionMethods.cs @@ -0,0 +1,135 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace Telegram.Api.Aggregator { + /// + /// Generic extension methods used by the framework. + /// + public static class ExtensionMethods { + /// + /// Get's the name of the assembly. + /// + /// The assembly. + /// The assembly's name. + public static string GetAssemblyName(this Assembly assembly) { + return assembly.FullName.Remove(assembly.FullName.IndexOf(',')); + } + + /// + /// Gets all the attributes of a particular type. + /// + /// The type of attributes to get. + /// The member to inspect for attributes. + /// Whether or not to search for inherited attributes. + /// The list of attributes found. + public static IEnumerable GetAttributes(this MemberInfo member, bool inherit) { +#if WIN_RT + return member.GetCustomAttributes(inherit).OfType(); +#else + return Attribute.GetCustomAttributes(member, inherit).OfType(); +#endif + } + + /// + /// Applies the action to each element in the list. + /// + /// The enumerable item's type. + /// The elements to enumerate. + /// The action to apply to each item in the list. + public static void Apply(this IEnumerable enumerable, Action action) { + foreach(var item in enumerable) { + action(item); + } + } + + /// + /// Converts an expression into a . + /// + /// The expression to convert. + /// The member info. + public static MemberInfo GetMemberInfo(this Expression expression) { + var lambda = (LambdaExpression)expression; + + MemberExpression memberExpression; + if (lambda.Body is UnaryExpression) { + var unaryExpression = (UnaryExpression)lambda.Body; + memberExpression = (MemberExpression)unaryExpression.Operand; + } + else { + memberExpression = (MemberExpression)lambda.Body; + } + + return memberExpression.Member; + } + +#if WINDOWS_PHONE && !WP8 + //Method missing in WP7.1 Linq + + /// + /// Merges two sequences by using the specified predicate function. + /// + /// The type of the elements of the first input sequence. + /// The type of the elements of the second input sequence. + /// The type of the elements of the result sequence. + /// The first sequence to merge. + /// The second sequence to merge. + /// A function that specifies how to merge the elements from the two sequences. + /// An System.Collections.Generic.IEnumerable<T> that contains merged elements of two input sequences. + public static IEnumerable Zip(this IEnumerable first, IEnumerable second, Func resultSelector) { + if (first == null) { + throw new ArgumentNullException("first"); + } + + if (second == null) { + throw new ArgumentNullException("second"); + } + + if (resultSelector == null) { + throw new ArgumentNullException("resultSelector"); + } + + var enumFirst = first.GetEnumerator(); + var enumSecond = second.GetEnumerator(); + + while (enumFirst.MoveNext() && enumSecond.MoveNext()) { + yield return resultSelector(enumFirst.Current, enumSecond.Current); + } + } +#endif + +#if WIN_RT + /// + /// Gets a collection of the public types defined in this assembly that are visible outside the assembly. + /// + /// The assembly. + /// A collection of the public types defined in this assembly that are visible outside the assembly. + /// + public static IEnumerable GetExportedTypes(this Assembly assembly) { + if (assembly == null) + throw new ArgumentNullException("assembly"); + + return assembly.ExportedTypes; + } + + /// + /// Returns a value that indicates whether the specified type can be assigned to the current type. + /// + /// The target type + /// The type to check. + /// true if the specified type can be assigned to this type; otherwise, false. + public static bool IsAssignableFrom(this Type target, Type type) { + return target.GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()); + } +#endif + } +} diff --git a/Telegram.Api/Compression/GZipDeflateStream.cs b/Telegram.Api/Compression/GZipDeflateStream.cs new file mode 100755 index 0000000..47484f4 --- /dev/null +++ b/Telegram.Api/Compression/GZipDeflateStream.cs @@ -0,0 +1,299 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#if WINDOWS_PHONE +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Windows; +using System.Windows.Resources; + +namespace SharpGIS +{ + internal sealed class GZipInflateStream : Stream + { + private readonly Stream _deflatedStream; + private Stream _inflatedStream; + + public GZipInflateStream(System.IO.Stream deflatedStream) + { + _deflatedStream = deflatedStream; + ProcessStream(); + } + + private void ProcessStream() + { + int firstByte = _deflatedStream.ReadByte(); + + if (firstByte == -1) + { + _inflatedStream = new MemoryStream(); + return; + } + + if ((0x1f != firstByte) || // ID1 + (0x8b != _deflatedStream.ReadByte()) || // ID2 + (8 != _deflatedStream.ReadByte())) // CM (8 == deflate) + { + throw new NotSupportedException("Compressed data not in the expected format."); + } + + // Read flags + var flg = _deflatedStream.ReadByte(); // FLG + var fhcrc = 0 != (0x2 & flg); // CRC16 present before compressed data + var fextra = 0 != (0x4 & flg); // extra fields present + var fname = 0 != (0x8 & flg); // original file name present + var fcomment = 0 != (0x10 & flg); // file comment present + + // Skip unsupported fields + if (_deflatedStream.CanSeek) + _deflatedStream.Seek(6, SeekOrigin.Current); + else + { + _deflatedStream.ReadByte(); + _deflatedStream.ReadByte(); + _deflatedStream.ReadByte(); + _deflatedStream.ReadByte(); // MTIME + _deflatedStream.ReadByte(); // XFL + _deflatedStream.ReadByte(); // OS + } + + if (fextra) + { + // Skip XLEN bytes of data + var xlen = _deflatedStream.ReadByte() | (_deflatedStream.ReadByte() << 8); + while (0 < xlen) + { + _deflatedStream.ReadByte(); + xlen--; + } + } + if (fname) + { + // Skip 0-terminated file name + while (0 != _deflatedStream.ReadByte()) + { + } + } + if (fcomment) + { + // Skip 0-terminated file comment + while (0 != _deflatedStream.ReadByte()) + { + } + } + if (fhcrc) + { + _deflatedStream.ReadByte(); _deflatedStream.ReadByte(); // CRC16 + } + + // Read compressed data + const int zipHeaderSize = 30 + 1; // 30 bytes + 1 character for file name + const int zipFooterSize = 68 + 1; // 68 bytes + 1 character for file name + + // Download unknown amount of compressed data efficiently (note: Content-Length header is not always reliable) + var buffers = new List(); + var buffer = new byte[4096]; + var bytesInBuffer = 0; + var totalBytes = 0; + var bytesRead = 0; + do + { + if (buffer.Length == bytesInBuffer) + { + // Full, allocate another + buffers.Add(buffer); + buffer = new byte[buffer.Length]; + bytesInBuffer = 0; + } + Debug.Assert(bytesInBuffer < buffer.Length); + bytesRead = _deflatedStream.Read(buffer, bytesInBuffer, buffer.Length - bytesInBuffer); + bytesInBuffer += bytesRead; + totalBytes += bytesRead; + } while (0 < bytesRead); + buffers.Add(buffer); + + // "Trim" crc32 and isize fields off the end + var compressedSize = totalBytes - 4 - 4; + if (compressedSize < 0) + { + throw new NotSupportedException("Compressed data not in the expected format."); + } + + // Create contiguous buffer + var compressedBytes = new byte[zipHeaderSize + compressedSize + zipFooterSize]; + var offset = zipHeaderSize; + var remainingBytes = totalBytes; + foreach (var b in buffers) + { + var length = Math.Min(b.Length, remainingBytes); + Array.Copy(b, 0, compressedBytes, offset, length); + offset += length; + remainingBytes -= length; + } + Debug.Assert(0 == remainingBytes); + + // Read footer from end of compressed bytes (note: footer is within zipFooterSize; will be overwritten below) + Debug.Assert(totalBytes <= compressedSize + zipFooterSize); + offset = zipHeaderSize + compressedSize; + var crc32 = compressedBytes[offset + 0] | (compressedBytes[offset + 1] << 8) | (compressedBytes[offset + 2] << 16) | (compressedBytes[offset + 3] << 24); + var isize = compressedBytes[offset + 4] | (compressedBytes[offset + 5] << 8) | (compressedBytes[offset + 6] << 16) | (compressedBytes[offset + 7] << 24); + + if (0 == isize) // HACK to handle compressed 0-byte streams without figuring out what's really going wrong + { + _inflatedStream = new MemoryStream(); + return; + } + + // Create ZIP file stream + const string fileName = "f"; // MUST be 1 character (offsets below assume this) + Debug.Assert(1 == fileName.Length); + var zipFileMemoryStream = new MemoryStream(compressedBytes); + var writer = new BinaryWriter(zipFileMemoryStream); + + // Local file header + writer.Write((uint)0x04034b50); // local file header signature + writer.Write((ushort)20); // version needed to extract (2.0 == compressed using deflate) + writer.Write((ushort)0); // general purpose bit flag + writer.Write((ushort)8); // compression method (8: deflate) + writer.Write((ushort)0); // last mod file time + writer.Write((ushort)0); // last mod file date + writer.Write(crc32); // crc-32 + writer.Write(compressedSize); // compressed size + writer.Write(isize); // uncompressed size + writer.Write((ushort)1); // file name length + writer.Write((ushort)0); // extra field length + writer.Write((byte)fileName[0]); // file name + + // File data (already present) + zipFileMemoryStream.Seek(compressedSize, SeekOrigin.Current); + + // Central directory structure + writer.Write((uint)0x02014b50); // central file header signature + writer.Write((ushort)20); // version made by + writer.Write((ushort)20); // version needed to extract (2.0 == compressed using deflate) + writer.Write((ushort)0); // general purpose bit flag + writer.Write((ushort)8); // compression method + writer.Write((ushort)0); // last mod file time + writer.Write((ushort)0); // last mod file date + writer.Write(crc32); // crc-32 + writer.Write(compressedSize); // compressed size + writer.Write(isize); // uncompressed size + writer.Write((ushort)1); // file name length + writer.Write((ushort)0); // extra field length + writer.Write((ushort)0); // file comment length + writer.Write((ushort)0); // disk number start + writer.Write((ushort)0); // internal file attributes + writer.Write((uint)0); // external file attributes + writer.Write((uint)0); // relative offset of local header + writer.Write((byte)fileName[0]); // file name + // End of central directory record + writer.Write((uint)0x06054b50); // end of central dir signature + writer.Write((ushort)0); // number of this disk + writer.Write((ushort)0); // number of the disk with the start of the central directory + writer.Write((ushort)1); // total number of entries in the central directory on this disk + writer.Write((ushort)1); // total number of entries in the central directory + writer.Write((uint)(46 + 1)); // size of the central directory (46 bytes + 1 character for file name) + writer.Write((uint)(zipHeaderSize + compressedSize)); // offset of start of central directory with respect to the starting disk number + writer.Write((ushort)0); // .ZIP file comment length + + // Reset ZIP file stream to beginning + zipFileMemoryStream.Seek(0, SeekOrigin.Begin); + + // Return the decompressed stream + _inflatedStream = Application.GetResourceStream( + new StreamResourceInfo(zipFileMemoryStream, null), + new Uri(fileName, UriKind.Relative)) + .Stream; + } + + public override bool CanRead + { + get { return _inflatedStream.CanRead; } + } + + public override bool CanSeek + { + get { return _inflatedStream.CanSeek; } + } + + public override bool CanWrite + { + get { return _inflatedStream.CanWrite; } + } + + public override void Flush() + { + _inflatedStream.Flush(); + } + + public override long Length + { + get { return _inflatedStream.Length; } + } + + public override long Position + { + get { return _inflatedStream.Position; } + set { _inflatedStream.Position = value; } + } + + public override int Read(byte[] buffer, int offset, int count) + { + return _inflatedStream.Read(buffer, offset, count); + } + + public override long Seek(long offset, SeekOrigin origin) + { + return _inflatedStream.Seek(offset, origin); + } + + public override void SetLength(long value) + { + _inflatedStream.SetLength(value); + } + + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + + public override void Close() + { + _deflatedStream.Close(); + _inflatedStream.Close(); + } + protected override void Dispose(bool disposing) + { + _deflatedStream.Dispose(); + _inflatedStream.Dispose(); + } + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + return _inflatedStream.BeginRead(buffer, offset, count, callback, state); + } + public override int ReadByte() + { + return _inflatedStream.ReadByte(); + } + public override int EndRead(IAsyncResult asyncResult) + { + return _inflatedStream.EndRead(asyncResult); + } + public override int ReadTimeout + { + get { return _inflatedStream.ReadTimeout; } + set { _inflatedStream.ReadTimeout = value; } + } + public override bool CanTimeout + { + get { return _inflatedStream.CanTimeout; } + } + } +} +#endif \ No newline at end of file diff --git a/Telegram.Api/Compression/GZipWebClient.cs b/Telegram.Api/Compression/GZipWebClient.cs new file mode 100755 index 0000000..9bb33ed --- /dev/null +++ b/Telegram.Api/Compression/GZipWebClient.cs @@ -0,0 +1,138 @@ +// (c) Copyright Morten Nielsen. +// This source is subject to the Microsoft Public License (Ms-PL). +// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. +// All other rights reserved. +#if SILVERLIGHT +using System; +using System.Net; +using System.Security; +using System.IO; +using System.Linq; + +namespace SharpGIS +{ + /// + /// This is an explicit web client class for doing webrequests. + /// If you want to opt in for gzip support on all existing WebClients, consider + /// using the + /// + public class GZipWebClient : WebClient + { + /// + /// Initializes a new instance of the class. + /// + [SecuritySafeCritical] + public GZipWebClient() + { + } + /// + /// Returns a object for the specified resource. + /// + /// A that identifies the resource to request. + /// + /// A new object for the specified resource. + /// + protected override WebRequest GetWebRequest(Uri address) + { + var req = base.GetWebRequest(address); + req.Headers[HttpRequestHeader.AcceptEncoding] = "gzip"; //Set GZIP header + return req; + } + /// + /// Returns the for the specified using the specified . + /// + /// A that is used to obtain the response. + /// An object obtained from a previous call to . + /// + /// A containing the response for the specified . + /// + protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result) + { + try + { + WebResponse response = base.GetWebResponse(request, result); + if (!(response is GZipWebResponse) && //this would be the case if WebRequestCreator was also used + (response.Headers[HttpRequestHeader.ContentEncoding] == "gzip") && response is HttpWebResponse) + return new GZipWebResponse(response as HttpWebResponse); //If gzipped response, uncompress + else + return response; + } + catch + { + return null; + } + } + internal sealed class GZipWebResponse : HttpWebResponse + { + private readonly HttpWebResponse _response; + private readonly SharpGIS.GZipInflateStream _stream; + + internal GZipWebResponse(HttpWebResponse resp) + { + _response = resp; + _stream = new GZipInflateStream(_response.GetResponseStream()); + } + public override System.IO.Stream GetResponseStream() + { + return _stream; + } + public override void Close() + { + _response.Close(); + _stream.Close(); + } + public override long ContentLength + { + get + { + return _stream.Length; + } + } + public override string ContentType + { + get { return _response.ContentType; } + } + public override WebHeaderCollection Headers + { + get { return _response.Headers; } + } + public override Uri ResponseUri + { + get { return _response.ResponseUri; } + } + public override bool SupportsHeaders + { + get { return _response.SupportsHeaders; } + } + public override string Method + { + get + { + return _response.Method; + } + } + public override HttpStatusCode StatusCode + { + get + { + return _response.StatusCode; + } + } + public override string StatusDescription + { + get + { + return _response.StatusDescription; + } + } + public override CookieCollection Cookies + { + get + { + return _response.Cookies; + } + } + } + } +} +#endif \ No newline at end of file diff --git a/Telegram.Api/Constants.cs b/Telegram.Api/Constants.cs new file mode 100755 index 0000000..c12c0c6 --- /dev/null +++ b/Telegram.Api/Constants.cs @@ -0,0 +1,121 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +//#define TEST_SERVER + +namespace Telegram.Api +{ + public static class Constants + { + public const int ApiId = https://core.telegram.org/api/obtaining_api_id + public const string ApiHash = https://core.telegram.org/api/obtaining_api_id + +#if TEST_SERVER + public const int FirstServerDCId = 1; + public const int FirstServerPort = 443; + public const string FirstServerIpAddress = + "149.154.175.40"; // dc1 + //"149.154.167.40"; // dc2 + //"149.154.175.117"; // dc3 + public const bool IsTestServer = true; +#else + public const int FirstServerDCId = 2; // [1, 2, 3, 4, 5] + public const int FirstServerPort = 443; + public const string FirstServerIpAddress = + //"149.154.175.50"; // dc1 + "149.154.167.51"; // dc2 + //"174.140.142.6"; // dc3 + //"149.154.167.90"; // dc4 + //"149.154.171.5"; // dc5 + public const bool IsTestServer = false; +#endif + + public const int SupportedLayer = 85; + public const int MinSecretSupportedLayer = 46; + public const int SecretSupportedLayer = 73; + + public const int LongPollReattemptDelay = 5000; //ms + public const double MessageSendingInterval = +#if DEBUG + 300; //seconds (5 minutes - 30 seconds(max delay: 25)) +#else + 180; //seconds (5 minutes - 30 seconds(max delay: 25)) +#endif + public const double ResendMessageInterval = 5.0; //seconds + public const int CommitDBInterval = 3; //seconds + public const int GetConfigInterval = 60 * 60; //seconds + public const int TimeoutInterval = 25; //seconds + public const double DelayedTimeoutInterval = 45.0; //seconds + public const double NonEncryptedTimeoutInterval = 15.0; //seconds + + public const bool IsLongPollEnabled = false; + public const int CachedDialogsCount = 20; + public const int CachedMessagesCount = 25; + + public const int WorkersNumber = 4; + public static int BigFileWorkersNumber = 4; + + public const string ConfigKey = "Config"; + public const string ConfigFileName = "config.xml"; + public static double CheckSendingMesagesInterval = 5.0; //seconds + + public static double CheckGetConfigInterval = +#if DEBUG + 10.0; +#else + 1 * 60.0; //seconds (1 min) +#endif + public static double CheckPingInterval = 20.0; //seconds + public static double UpdateStatusInterval = 2.0; + public static int VideoUploadersCount = 3; + public static int DocumentUploadersCount = 3; + public static int AudioDownloadersCount = 3; + public static int MaximumChunksCount = 3000; + public static int DownloadedChunkSize = 32 * 1024; // 1MB % DownloadedChunkSize = 0 && DownloadedChunkSize % 1KB = 0 + public static int DownloadedBigChunkSize = 128 * 1024; // 1MB % DownloadedChunkSize = 0 && DownloadedChunkSize % 1KB = 0 + public static ulong MaximumUploadedFileSize = 512 * 1024 * 3000; // 1,5GB + + public static string StateFileName = "state.dat"; + public static string TempStateFileName = "temp_state.dat"; + public static string ActionQueueFileName = "action_queue.dat"; + public static string SentQueueIdFileName = "sent_queue_id.dat"; + + public const string IsAuthorizedKey = "IsAuthorized"; + public const int StickerMaxSize = 256 * 1024; // 256 KB + public const int GifMaxSize = 10 * 1014 * 1024; // 10 MB + public const int AutoDownloadGifMaxSize = 2 * 1014 * 1024; // 1 MB + public const int SmallFileMaxSize = 32 * 1024; //10 * 1024 * 1024; // 10 MB + + public const string BackgroundTaskSettingsFileName = "background_task_settings.dat"; + public const string DifferenceFileName = "difference.dat"; + public const string TempDifferenceFileName = "temp_difference.dat"; + public const string DifferenceTimeFileName = "difference_time.dat"; + + public const string TelegramMessengerMutexName = "TelegramMessenger"; + public const double DifferenceMinInterval = 10.0; //seconds + + public const string InitConnectionFileName = "init_connection.dat"; + public const string DisableNotificationsFileName = "disable_notifications.dat"; + + public const int MinRandomBytesLength = 15; + + public static int MinSecretChatWithExtendedKeyVisualizationLayer = 46; + public static int MinSecretChatWithMTProto2Layer = 46; + + public const string ProxyConfigFileName = "proxy_config.dat"; + public const string CdnConfigFileName = "cdn_config.dat"; + + public const string LiveLocationsFileName = "live_locations.dat"; + + public const int CheckConfigTimeout = +#if DEBUG + 10; +#else + 7; +#endif + } +} diff --git a/Telegram.Api/Extensions/ActionExtensions.cs b/Telegram.Api/Extensions/ActionExtensions.cs new file mode 100755 index 0000000..501f70c --- /dev/null +++ b/Telegram.Api/Extensions/ActionExtensions.cs @@ -0,0 +1,54 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.Extensions +{ + public static class ActionExtensions + { + public static void SafeInvoke(this Action action) + { + if (action != null) + { + action.Invoke(); + } + } + + public static void SafeInvoke(this Action action, T param) + { + if (action != null) + { + action.Invoke(param); + } + } + + public static void SafeInvoke(this Action action, T1 param1, T2 param2) + { + if (action != null) + { + action.Invoke(param1, param2); + } + } + + public static void SafeInvoke(this Action action, T1 param1, T2 param2, T3 param3) + { + if (action != null) + { + action.Invoke(param1, param2, param3); + } + } + + public static void SafeInvoke(this Action action, T1 param1, T2 param2, T3 param3, T4 param4) + { + if (action != null) + { + action.Invoke(param1, param2, param3, param4); + } + } + } +} diff --git a/Telegram.Api/Extensions/HttpWebRequestExtensions.cs b/Telegram.Api/Extensions/HttpWebRequestExtensions.cs new file mode 100755 index 0000000..5ef1155 --- /dev/null +++ b/Telegram.Api/Extensions/HttpWebRequestExtensions.cs @@ -0,0 +1,93 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Net; +using Telegram.Api.TL; + +namespace Telegram.Api.Extensions +{ + public static class HttpWebRequestExtensions + { + public static void BeginAsync(this HttpWebRequest request, byte[] data, Action callback, Action faultCallback) + { + request.BeginGetRequestStream(ar => GetRequestStreamCallback(data, ar, ar2 => EndAsync(ar2, callback, faultCallback)), request); + } + + public static void BeginAsync(this HttpWebRequest request, byte[] data, Action onCompleted) + { + request.BeginGetRequestStream(ar => GetRequestStreamCallback(data, ar, onCompleted), request); + } + + private static void GetRequestStreamCallback(byte[] data, IAsyncResult asynchronousResult, Action onCompleted) + { + var request = (HttpWebRequest)asynchronousResult.AsyncState; + + // End the operation + var postStream = request.EndGetRequestStream(asynchronousResult); + + // Convert the string into a byte array. + var byteArray = data; + + // Write to the request stream. + postStream.Write(byteArray, 0, data.Length); + postStream.Dispose(); + + // Start the asynchronous operation to get the response + request.BeginGetResponse(x => onCompleted(x), request); + } + + private static void EndAsync(IAsyncResult asynchronousResult, Action callback, Action faultCallback) + { + //try + { + try + { + var request = (HttpWebRequest)asynchronousResult.AsyncState; + HttpWebResponse response; + + using (response = (HttpWebResponse)request.EndGetResponse(asynchronousResult)) + { + using (var dataStream = response.GetResponseStream()) + { + + var buffer = new byte[Int32.Parse(response.Headers["Content-Length"])]; + var bytesRead = 0; + var totalBytesRead = bytesRead; + while (totalBytesRead < buffer.Length) + { + bytesRead = dataStream.Read(buffer, bytesRead, buffer.Length - bytesRead); + totalBytesRead += bytesRead; + } + + callback(buffer); + } + } + } + catch (Exception ex) + { + TLUtils.WriteException(ex); + faultCallback(); + + //response = (HttpWebResponse)ex.Response; + //if (response == null) + //{ + // if (faultCallback != null) faultCallback(); + // return; + //} + + //if (response.StatusCode == HttpStatusCode.BadGateway + // || response.StatusCode == HttpStatusCode.NotFound) + //{ + // if (faultCallback != null) faultCallback(); + // return; + //} + } + } + } + } +} diff --git a/Telegram.Api/Extensions/StreamExtensions.cs b/Telegram.Api/Extensions/StreamExtensions.cs new file mode 100755 index 0000000..bde9adc --- /dev/null +++ b/Telegram.Api/Extensions/StreamExtensions.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; + +namespace Telegram.Api.Extensions +{ + public static class StreamExtensions + { + public static void Write(this Stream output, byte[] buffer) + { + output.Write(buffer, 0, buffer.Length); + } + } +} diff --git a/Telegram.Api/Extensions/TLObjectExtensions.cs b/Telegram.Api/Extensions/TLObjectExtensions.cs new file mode 100755 index 0000000..b31781f --- /dev/null +++ b/Telegram.Api/Extensions/TLObjectExtensions.cs @@ -0,0 +1,36 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.TL; + +namespace Telegram.Api.Extensions +{ + public static class TLObjectExtensions + { + public static void NullableToStream(this TLObject obj, Stream output) + { + if (obj == null) + { + output.Write(new TLNull().ToBytes()); + } + else + { + obj.ToStream(output); + } + } + + public static T NullableFromStream(Stream input) where T : TLObject + { + var obj = TLObjectGenerator.GetNullableObject(input); + + if (obj == null) return null; + + return (T)obj.FromStream(input); + } + } +} diff --git a/Telegram.Api/Hash/CRC32/CRC.cs b/Telegram.Api/Hash/CRC32/CRC.cs new file mode 100755 index 0000000..ad1cd7e --- /dev/null +++ b/Telegram.Api/Hash/CRC32/CRC.cs @@ -0,0 +1,175 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#if WINDOWS_PHONE +using System; +using System.Security.Cryptography; + +namespace Telegram.Api +{ + /// + /// HashAlgorithm implementation for CRC-32. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", + "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "CRC", + Justification = "Matching algorithm acronym.")] + public class CRC32 : HashAlgorithm + { + // Shared, pre-computed lookup table for efficiency + private static readonly uint[] _crc32Table; + + /// + /// Initializes the shared lookup table. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", + "CA1810:InitializeReferenceTypeStaticFieldsInline", Justification = + "Table values must be computed; not possible to remove the static constructor.")] + static CRC32() + { + // Allocate table + _crc32Table = new uint[256]; + + // For each byte + for (uint n = 0; n < 256; n++) + { + // For each bit + uint c = n; + for (int k = 0; k < 8; k++) + { + // Compute value + if (0 != (c & 1)) + { + c = 0xedb88320 ^ (c >> 1); + } + else + { + c = c >> 1; + } + } + + // Store result in table + _crc32Table[n] = c; + } + } + + // Current hash value + private uint _crc32Value; + + // True if HashCore has been called + private bool _hashCoreCalled; + + // True if HashFinal has been called + private bool _hashFinalCalled; + + /// + /// Initializes a new instance. + /// + public CRC32() + { + InitializeVariables(); + } + + /// + /// Initializes internal state. + /// + public override void Initialize() + { + InitializeVariables(); + } + + /// + /// Initializes variables. + /// + private void InitializeVariables() + { + _crc32Value = uint.MaxValue; + _hashCoreCalled = false; + _hashFinalCalled = false; + } + + /// + /// Updates the hash code for the provided data. + /// + /// Data. + /// Start position. + /// Number of bytes. + protected override void HashCore(byte[] array, int ibStart, int cbSize) + { + if (null == array) + { + throw new ArgumentNullException("array"); + } + + if (_hashFinalCalled) + { + throw new CryptographicException( + "Hash not valid for use in specified state."); + } + _hashCoreCalled = true; + + for (int i = ibStart; i < ibStart + cbSize; i++) + { + byte index = (byte)(_crc32Value ^ array[i]); + _crc32Value = _crc32Table[index] ^ ((_crc32Value >> 8) & 0xffffff); + } + } + + /// + /// Finalizes the hash code and returns it. + /// + /// + protected override byte[] HashFinal() + { + _hashFinalCalled = true; + return Hash; + } + + /// + /// Returns the hash as an array of bytes. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", + "CA1065:DoNotRaiseExceptionsInUnexpectedLocations", Justification = + "Matching .NET behavior by throwing here.")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", + "CA2201:DoNotRaiseReservedExceptionTypes", Justification = + "Matching .NET behavior by throwing NullReferenceException.")] + public override byte[] Hash + { + get + { + if (!_hashCoreCalled) + { + throw new NullReferenceException(); + } + if (!_hashFinalCalled) + { + // Note: Not CryptographicUnexpectedOperationException because + // that can't be instantiated on Silverlight 4 + throw new CryptographicException( + "Hash must be finalized before the hash value is retrieved."); + } + + // Convert complement of hash code to byte array + byte[] bytes = BitConverter.GetBytes(~_crc32Value); + + // Reverse for proper endianness, and return + Array.Reverse(bytes); + return bytes; + } + } + + // Return size of hash in bits. + public override int HashSize + { + get + { + return 4 * 8; + } + } + } +} +#endif diff --git a/Telegram.Api/Hash/MD5/MD5.cs b/Telegram.Api/Hash/MD5/MD5.cs new file mode 100755 index 0000000..a7e28c1 --- /dev/null +++ b/Telegram.Api/Hash/MD5/MD5.cs @@ -0,0 +1,271 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Text; + +// Simple struct for the (a,b,c,d) which is used to compute the mesage digest. +struct ABCDStruct +{ + public uint A; + public uint B; + public uint C; + public uint D; +} + +public sealed class MD5Core +{ + //Prevent CSC from adding a default public constructor + private MD5Core() {} + + public static byte[] GetHash(string input, Encoding encoding) + { + if (null == input) + throw new System.ArgumentNullException("input", "Unable to calculate hash over null input data"); + if (null == encoding) + throw new System.ArgumentNullException("encoding", "Unable to calculate hash over a string without a default encoding. Consider using the GetHash(string) overload to use UTF8 Encoding"); + + byte[] target = encoding.GetBytes(input); + + return GetHash(target); + } + + public static byte[] GetHash(string input) + { + return GetHash(input, new UTF8Encoding()); + } + + public static string GetHashString(byte[] input) + { + if (null == input) + throw new System.ArgumentNullException("input", "Unable to calculate hash over null input data"); + + string retval = BitConverter.ToString(GetHash(input)); + retval = retval.Replace("-", ""); + + return retval; + } + + public static string GetHashString(string input, Encoding encoding) + { + if (null == input) + throw new System.ArgumentNullException("input", "Unable to calculate hash over null input data"); + if (null == encoding) + throw new System.ArgumentNullException("encoding", "Unable to calculate hash over a string without a default encoding. Consider using the GetHashString(string) overload to use UTF8 Encoding"); + + byte[] target = encoding.GetBytes(input); + + return GetHashString(target); + } + + public static string GetHashString(string input) + { + return GetHashString(input, new UTF8Encoding()); + } + + public static byte[] GetHash(byte[] input) + { + if (null == input) + throw new System.ArgumentNullException("input", "Unable to calculate hash over null input data"); + + //Intitial values defined in RFC 1321 + ABCDStruct abcd = new ABCDStruct(); + abcd.A = 0x67452301; + abcd.B = 0xefcdab89; + abcd.C = 0x98badcfe; + abcd.D = 0x10325476; + + //We pass in the input array by block, the final block of data must be handled specialy for padding & length embeding + int startIndex = 0; + while (startIndex <= input.Length - 64) + { + MD5Core.GetHashBlock(input, ref abcd, startIndex); + startIndex += 64; + } + // The final data block. + return MD5Core.GetHashFinalBlock(input, startIndex, input.Length - startIndex, abcd, (Int64)input.Length * 8); + } + + internal static byte[] GetHashFinalBlock(byte[] input, int ibStart, int cbSize, ABCDStruct ABCD, Int64 len) + { + byte[] working = new byte[64]; + byte[] length = BitConverter.GetBytes(len); + + //Padding is a single bit 1, followed by the number of 0s required to make size congruent to 448 modulo 512. Step 1 of RFC 1321 + //The CLR ensures that our buffer is 0-assigned, we don't need to explicitly set it. This is why it ends up being quicker to just + //use a temporary array rather then doing in-place assignment (5% for small inputs) + Array.Copy(input, ibStart, working, 0, cbSize); + working[cbSize] = 0x80; + + //We have enough room to store the length in this chunk + if (cbSize < 56) + { + Array.Copy(length, 0, working, 56, 8); + GetHashBlock(working, ref ABCD, 0); + } + else //We need an aditional chunk to store the length + { + GetHashBlock(working, ref ABCD, 0); + //Create an entirely new chunk due to the 0-assigned trick mentioned above, to avoid an extra function call clearing the array + working = new byte[64]; + Array.Copy(length, 0, working, 56, 8); + GetHashBlock(working, ref ABCD, 0); + } + byte[] output = new byte[16]; + Array.Copy(BitConverter.GetBytes(ABCD.A), 0, output, 0, 4); + Array.Copy(BitConverter.GetBytes(ABCD.B), 0, output, 4, 4); + Array.Copy(BitConverter.GetBytes(ABCD.C), 0, output, 8, 4); + Array.Copy(BitConverter.GetBytes(ABCD.D), 0, output, 12, 4); + return output; + } + + // Performs a single block transform of MD5 for a given set of ABCD inputs + /* If implementing your own hashing framework, be sure to set the initial ABCD correctly according to RFC 1321: + // A = 0x67452301; + // B = 0xefcdab89; + // C = 0x98badcfe; + // D = 0x10325476; + */ + internal static void GetHashBlock(byte[] input, ref ABCDStruct ABCDValue, int ibStart) + { + uint[] temp = Converter(input, ibStart); + uint a = ABCDValue.A; + uint b = ABCDValue.B; + uint c = ABCDValue.C; + uint d = ABCDValue.D; + + a = r1(a, b, c, d, temp[0 ], 7, 0xd76aa478); + d = r1(d, a, b, c, temp[1 ], 12, 0xe8c7b756); + c = r1(c, d, a, b, temp[2 ], 17, 0x242070db); + b = r1(b, c, d, a, temp[3 ], 22, 0xc1bdceee); + a = r1(a, b, c, d, temp[4 ], 7, 0xf57c0faf); + d = r1(d, a, b, c, temp[5 ], 12, 0x4787c62a); + c = r1(c, d, a, b, temp[6 ], 17, 0xa8304613); + b = r1(b, c, d, a, temp[7 ], 22, 0xfd469501); + a = r1(a, b, c, d, temp[8 ], 7, 0x698098d8); + d = r1(d, a, b, c, temp[9 ], 12, 0x8b44f7af); + c = r1(c, d, a, b, temp[10], 17, 0xffff5bb1); + b = r1(b, c, d, a, temp[11], 22, 0x895cd7be); + a = r1(a, b, c, d, temp[12], 7, 0x6b901122); + d = r1(d, a, b, c, temp[13], 12, 0xfd987193); + c = r1(c, d, a, b, temp[14], 17, 0xa679438e); + b = r1(b, c, d, a, temp[15], 22, 0x49b40821); + + a = r2(a, b, c, d, temp[1 ], 5, 0xf61e2562); + d = r2(d, a, b, c, temp[6 ], 9, 0xc040b340); + c = r2(c, d, a, b, temp[11], 14, 0x265e5a51); + b = r2(b, c, d, a, temp[0 ], 20, 0xe9b6c7aa); + a = r2(a, b, c, d, temp[5 ], 5, 0xd62f105d); + d = r2(d, a, b, c, temp[10], 9, 0x02441453); + c = r2(c, d, a, b, temp[15], 14, 0xd8a1e681); + b = r2(b, c, d, a, temp[4 ], 20, 0xe7d3fbc8); + a = r2(a, b, c, d, temp[9 ], 5, 0x21e1cde6); + d = r2(d, a, b, c, temp[14], 9, 0xc33707d6); + c = r2(c, d, a, b, temp[3 ], 14, 0xf4d50d87); + b = r2(b, c, d, a, temp[8 ], 20, 0x455a14ed); + a = r2(a, b, c, d, temp[13], 5, 0xa9e3e905); + d = r2(d, a, b, c, temp[2 ], 9, 0xfcefa3f8); + c = r2(c, d, a, b, temp[7 ], 14, 0x676f02d9); + b = r2(b, c, d, a, temp[12], 20, 0x8d2a4c8a); + + a = r3(a, b, c, d, temp[5 ], 4, 0xfffa3942); + d = r3(d, a, b, c, temp[8 ], 11, 0x8771f681); + c = r3(c, d, a, b, temp[11], 16, 0x6d9d6122); + b = r3(b, c, d, a, temp[14], 23, 0xfde5380c); + a = r3(a, b, c, d, temp[1 ], 4, 0xa4beea44); + d = r3(d, a, b, c, temp[4 ], 11, 0x4bdecfa9); + c = r3(c, d, a, b, temp[7 ], 16, 0xf6bb4b60); + b = r3(b, c, d, a, temp[10], 23, 0xbebfbc70); + a = r3(a, b, c, d, temp[13], 4, 0x289b7ec6); + d = r3(d, a, b, c, temp[0 ], 11, 0xeaa127fa); + c = r3(c, d, a, b, temp[3 ], 16, 0xd4ef3085); + b = r3(b, c, d, a, temp[6 ], 23, 0x04881d05); + a = r3(a, b, c, d, temp[9 ], 4, 0xd9d4d039); + d = r3(d, a, b, c, temp[12], 11, 0xe6db99e5); + c = r3(c, d, a, b, temp[15], 16, 0x1fa27cf8); + b = r3(b, c, d, a, temp[2 ], 23, 0xc4ac5665); + + a = r4(a, b, c, d, temp[0 ], 6, 0xf4292244); + d = r4(d, a, b, c, temp[7 ], 10, 0x432aff97); + c = r4(c, d, a, b, temp[14], 15, 0xab9423a7); + b = r4(b, c, d, a, temp[5 ], 21, 0xfc93a039); + a = r4(a, b, c, d, temp[12], 6, 0x655b59c3); + d = r4(d, a, b, c, temp[3 ], 10, 0x8f0ccc92); + c = r4(c, d, a, b, temp[10], 15, 0xffeff47d); + b = r4(b, c, d, a, temp[1 ], 21, 0x85845dd1); + a = r4(a, b, c, d, temp[8 ], 6, 0x6fa87e4f); + d = r4(d, a, b, c, temp[15], 10, 0xfe2ce6e0); + c = r4(c, d, a, b, temp[6 ], 15, 0xa3014314); + b = r4(b, c, d, a, temp[13], 21, 0x4e0811a1); + a = r4(a, b, c, d, temp[4 ], 6, 0xf7537e82); + d = r4(d, a, b, c, temp[11], 10, 0xbd3af235); + c = r4(c, d, a, b, temp[2 ], 15, 0x2ad7d2bb); + b = r4(b, c, d, a, temp[9 ], 21, 0xeb86d391); + + ABCDValue.A = unchecked(a + ABCDValue.A); + ABCDValue.B = unchecked(b + ABCDValue.B); + ABCDValue.C = unchecked(c + ABCDValue.C); + ABCDValue.D = unchecked(d + ABCDValue.D); + return; + } + + //Manually unrolling these equations nets us a 20% performance improvement + private static uint r1(uint a, uint b, uint c, uint d, uint x, int s, uint t) + { + // (b + LSR((a + F(b, c, d) + x + t), s)) + //F(x, y, z) ((x & y) | ((x ^ 0xFFFFFFFF) & z)) + return unchecked(b + LSR((a + ((b & c) | ((b ^ 0xFFFFFFFF) & d)) + x + t), s)); + } + + private static uint r2(uint a, uint b, uint c, uint d, uint x, int s, uint t) + { + // (b + LSR((a + G(b, c, d) + x + t), s)) + //G(x, y, z) ((x & z) | (y & (z ^ 0xFFFFFFFF))) + return unchecked(b + LSR((a + ((b & d) | (c & (d ^ 0xFFFFFFFF))) + x + t), s)); + } + + private static uint r3(uint a, uint b, uint c, uint d, uint x, int s, uint t) + { + // (b + LSR((a + H(b, c, d) + k + i), s)) + //H(x, y, z) (x ^ y ^ z) + return unchecked(b + LSR((a + (b ^ c ^ d) + x + t), s)); + } + + private static uint r4(uint a, uint b, uint c, uint d, uint x, int s, uint t) + { + // (b + LSR((a + I(b, c, d) + k + i), s)) + //I(x, y, z) (y ^ (x | (z ^ 0xFFFFFFFF))) + return unchecked(b + LSR((a + (c ^ (b | (d ^ 0xFFFFFFFF))) + x + t), s)); + } + + // Implementation of left rotate + // s is an int instead of a uint becuase the CLR requires the argument passed to >>/<< is of + // type int. Doing the demoting inside this function would add overhead. + private static uint LSR(uint i, int s) + { + return ((i << s) | (i >> (32-s))); + } + + //Convert input array into array of UInts + private static uint[] Converter(byte[] input, int ibStart) + { + if(null == input) + throw new System.ArgumentNullException("input", "Unable convert null array to array of uInts"); + + uint[] result = new uint[16]; + + for (int i = 0; i < 16; i++) + { + result[i] = (uint)input[ibStart + i * 4]; + result[i] += (uint)input[ibStart + i * 4 + 1] << 8; + result[i] += (uint)input[ibStart + i * 4 + 2] << 16; + result[i] += (uint)input[ibStart + i * 4 + 3] << 24; + } + + return result; + } +} \ No newline at end of file diff --git a/Telegram.Api/Hash/MD5/MD5CryptoServiceProvider.cs b/Telegram.Api/Hash/MD5/MD5CryptoServiceProvider.cs new file mode 100755 index 0000000..03139bd --- /dev/null +++ b/Telegram.Api/Hash/MD5/MD5CryptoServiceProvider.cs @@ -0,0 +1,564 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using System.Text; + +namespace Telegram.Api.MD5 +{ + public class MD5CryptoServiceProvider : MD5 + { + public MD5CryptoServiceProvider() + : base() + { + } + } + + public class MD5 : IDisposable + { + static public MD5 Create(string hashName) + { + if (hashName == "MD5") + return new MD5(); + else + throw new NotSupportedException(); + } + + static public string GetMd5String(String source) + { + MD5 md = MD5CryptoServiceProvider.Create(); + byte[] hash; + + //Create a new instance of ASCIIEncoding to + //convert the string into an array of Unicode bytes. + UTF8Encoding enc = new UTF8Encoding(); + // ASCIIEncoding enc = new ASCIIEncoding(); + + //Convert the string into an array of bytes. + byte[] buffer = enc.GetBytes(source); + + //Create the hash value from the array of bytes. + hash = md.ComputeHash(buffer); + + StringBuilder sb = new StringBuilder(); + foreach (byte b in hash) + sb.Append(b.ToString("x2")); + return sb.ToString(); + } + + static public MD5 Create() + { + return new MD5(); + } + + #region base implementation of the MD5 + #region constants + private const byte S11 = 7; + private const byte S12 = 12; + private const byte S13 = 17; + private const byte S14 = 22; + private const byte S21 = 5; + private const byte S22 = 9; + private const byte S23 = 14; + private const byte S24 = 20; + private const byte S31 = 4; + private const byte S32 = 11; + private const byte S33 = 16; + private const byte S34 = 23; + private const byte S41 = 6; + private const byte S42 = 10; + private const byte S43 = 15; + private const byte S44 = 21; + static private byte[] PADDING = new byte[] { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + #endregion + + #region F, G, H and I are basic MD5 functions. + static private uint F(uint x, uint y, uint z) + { + return (((x) & (y)) | ((~x) & (z))); + } + static private uint G(uint x, uint y, uint z) + { + return (((x) & (z)) | ((y) & (~z))); + } + static private uint H(uint x, uint y, uint z) + { + return ((x) ^ (y) ^ (z)); + } + static private uint I(uint x, uint y, uint z) + { + return ((y) ^ ((x) | (~z))); + } + #endregion + + #region rotates x left n bits. + /// + /// rotates x left n bits. + /// + /// + /// + /// + static private uint ROTATE_LEFT(uint x, byte n) + { + return (((x) << (n)) | ((x) >> (32 - (n)))); + } + #endregion + + #region FF, GG, HH, and II transformations + /// FF, GG, HH, and II transformations + /// for rounds 1, 2, 3, and 4. + /// Rotation is separate from addition to prevent recomputation. + static private void FF(ref uint a, uint b, uint c, uint d, uint x, byte s, uint ac) + { + (a) += F((b), (c), (d)) + (x) + (uint)(ac); + (a) = ROTATE_LEFT((a), (s)); + (a) += (b); + } + static private void GG(ref uint a, uint b, uint c, uint d, uint x, byte s, uint ac) + { + (a) += G((b), (c), (d)) + (x) + (uint)(ac); + (a) = ROTATE_LEFT((a), (s)); + (a) += (b); + } + static private void HH(ref uint a, uint b, uint c, uint d, uint x, byte s, uint ac) + { + (a) += H((b), (c), (d)) + (x) + (uint)(ac); + (a) = ROTATE_LEFT((a), (s)); + (a) += (b); + } + static private void II(ref uint a, uint b, uint c, uint d, uint x, byte s, uint ac) + { + (a) += I((b), (c), (d)) + (x) + (uint)(ac); + (a) = ROTATE_LEFT((a), (s)); + (a) += (b); + } + #endregion + + #region context info + /// + /// state (ABCD) + /// + uint[] state = new uint[4]; + + /// + /// number of bits, modulo 2^64 (lsb first) + /// + uint[] count = new uint[2]; + + /// + /// input buffer + /// + byte[] buffer = new byte[64]; + #endregion + + internal MD5() + { + Initialize(); + } + + /// + /// MD5 initialization. Begins an MD5 operation, writing a new context. + /// + /// + /// The RFC named it "MD5Init" + /// + public virtual void Initialize() + { + count[0] = count[1] = 0; + + // Load magic initialization constants. + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; + } + + /// + /// MD5 block update operation. Continues an MD5 message-digest + /// operation, processing another message block, and updating the + /// context. + /// + /// + /// + /// + /// The RFC Named it MD5Update + protected virtual void HashCore(byte[] input, int offset, int count) + { + int i; + int index; + int partLen; + + // Compute number of bytes mod 64 + index = (int)((this.count[0] >> 3) & 0x3F); + + // Update number of bits + if ((this.count[0] += (uint)((uint)count << 3)) < ((uint)count << 3)) + this.count[1]++; + this.count[1] += ((uint)count >> 29); + + partLen = 64 - index; + + // Transform as many times as possible. + if (count >= partLen) + { + Buffer.BlockCopy(input, offset, this.buffer, index, partLen); + Transform(this.buffer, 0); + + for (i = partLen; i + 63 < count; i += 64) + Transform(input, offset + i); + + index = 0; + } + else + i = 0; + + // Buffer remaining input + Buffer.BlockCopy(input, offset + i, this.buffer, index, count - i); + } + + /// + /// MD5 finalization. Ends an MD5 message-digest operation, writing the + /// the message digest and zeroizing the context. + /// + /// message digest + /// The RFC named it MD5Final + protected virtual byte[] HashFinal() + { + byte[] digest = new byte[16]; + byte[] bits = new byte[8]; + int index, padLen; + + // Save number of bits + Encode(bits, 0, this.count, 0, 8); + + // Pad out to 56 mod 64. + index = (int)((uint)(this.count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + HashCore(PADDING, 0, padLen); + + // Append length (before padding) + HashCore(bits, 0, 8); + + // Store state in digest + Encode(digest, 0, state, 0, 16); + + // Zeroize sensitive information. + count[0] = count[1] = 0; + state[0] = 0; + state[1] = 0; + state[2] = 0; + state[3] = 0; + + // initialize again, to be ready to use + Initialize(); + + return digest; + } + + /// + /// MD5 basic transformation. Transforms state based on 64 bytes block. + /// + /// + /// + private void Transform(byte[] block, int offset) + { + uint a = state[0], b = state[1], c = state[2], d = state[3]; + uint[] x = new uint[16]; + Decode(x, 0, block, offset, 64); + + // Round 1 + FF(ref a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ + FF(ref d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ + FF(ref c, d, a, b, x[2], S13, 0x242070db); /* 3 */ + FF(ref b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ + FF(ref a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ + FF(ref d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ + FF(ref c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ + FF(ref b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ + FF(ref a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ + FF(ref d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ + FF(ref c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF(ref b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF(ref a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF(ref d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF(ref c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF(ref b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + // Round 2 + GG(ref a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ + GG(ref d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ + GG(ref c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG(ref b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ + GG(ref a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ + GG(ref d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG(ref c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG(ref b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ + GG(ref a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ + GG(ref d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG(ref c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ + GG(ref b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ + GG(ref a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG(ref d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ + GG(ref c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ + GG(ref b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + // Round 3 + HH(ref a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ + HH(ref d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ + HH(ref c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH(ref b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH(ref a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ + HH(ref d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ + HH(ref c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ + HH(ref b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH(ref a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH(ref d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ + HH(ref c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ + HH(ref b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ + HH(ref a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ + HH(ref d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH(ref c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH(ref b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ + + // Round 4 + II(ref a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ + II(ref d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ + II(ref c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II(ref b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ + II(ref a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II(ref d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ + II(ref c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II(ref b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ + II(ref a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ + II(ref d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II(ref c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ + II(ref b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II(ref a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ + II(ref d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II(ref c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ + II(ref b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + for (int i = 0; i < x.Length; i++) + x[i] = 0; + } + + /// + /// Encodes input (uint) into output (byte). Assumes len is + /// multiple of 4. + /// + /// + /// + /// + /// + /// + private static void Encode(byte[] output, int outputOffset, uint[] input, int inputOffset, int count) + { + int i, j; + int end = outputOffset + count; + for (i = inputOffset, j = outputOffset; j < end; i++, j += 4) + { + output[j] = (byte)(input[i] & 0xff); + output[j + 1] = (byte)((input[i] >> 8) & 0xff); + output[j + 2] = (byte)((input[i] >> 16) & 0xff); + output[j + 3] = (byte)((input[i] >> 24) & 0xff); + } + } + + /// + /// Decodes input (byte) into output (uint). Assumes len is + /// a multiple of 4. + /// + /// + /// + /// + /// + /// + static private void Decode(uint[] output, int outputOffset, byte[] input, int inputOffset, int count) + { + int i, j; + int end = inputOffset + count; + for (i = outputOffset, j = inputOffset; j < end; i++, j += 4) + output[i] = ((uint)input[j]) | (((uint)input[j + 1]) << 8) | (((uint)input[j + 2]) << 16) | (((uint)input[j + 3]) << 24); + } + #endregion + + #region expose the same interface as the regular MD5 object + + protected byte[] HashValue; + protected int State; + public virtual bool CanReuseTransform + { + get + { + return true; + } + } + + public virtual bool CanTransformMultipleBlocks + { + get + { + return true; + } + } + public virtual byte[] Hash + { + get + { + if (this.State != 0) + throw new InvalidOperationException(); + return (byte[])HashValue.Clone(); + } + } + public virtual int HashSize + { + get + { + return HashSizeValue; + } + } + protected int HashSizeValue = 128; + + public virtual int InputBlockSize + { + get + { + return 1; + } + } + public virtual int OutputBlockSize + { + get + { + return 1; + } + } + + public void Clear() + { + Dispose(true); + } + + public byte[] ComputeHash(byte[] buffer) + { + return ComputeHash(buffer, 0, buffer.Length); + } + public byte[] ComputeHash(byte[] buffer, int offset, int count) + { + Initialize(); + HashCore(buffer, offset, count); + HashValue = HashFinal(); + return (byte[])HashValue.Clone(); + } + + public byte[] ComputeHash(Stream inputStream) + { + Initialize(); + int count; + byte[] buffer = new byte[4096]; + while (0 < (count = inputStream.Read(buffer, 0, 4096))) + { + HashCore(buffer, 0, count); + } + HashValue = HashFinal(); + return (byte[])HashValue.Clone(); + } + + public int TransformBlock( + byte[] inputBuffer, + int inputOffset, + int inputCount, + byte[] outputBuffer, + int outputOffset + ) + { + if (inputBuffer == null) + { + throw new ArgumentNullException("inputBuffer"); + } + if (inputOffset < 0) + { + throw new ArgumentOutOfRangeException("inputOffset"); + } + if ((inputCount < 0) || (inputCount > inputBuffer.Length)) + { + throw new ArgumentException("inputCount"); + } + if ((inputBuffer.Length - inputCount) < inputOffset) + { + throw new ArgumentOutOfRangeException("inputOffset"); + } + if (this.State == 0) + { + Initialize(); + this.State = 1; + } + + HashCore(inputBuffer, inputOffset, inputCount); + if ((inputBuffer != outputBuffer) || (inputOffset != outputOffset)) + { + Buffer.BlockCopy(inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount); + } + return inputCount; + } + public byte[] TransformFinalBlock( + byte[] inputBuffer, + int inputOffset, + int inputCount + ) + { + if (inputBuffer == null) + { + throw new ArgumentNullException("inputBuffer"); + } + if (inputOffset < 0) + { + throw new ArgumentOutOfRangeException("inputOffset"); + } + if ((inputCount < 0) || (inputCount > inputBuffer.Length)) + { + throw new ArgumentException("inputCount"); + } + if ((inputBuffer.Length - inputCount) < inputOffset) + { + throw new ArgumentOutOfRangeException("inputOffset"); + } + if (this.State == 0) + { + Initialize(); + } + HashCore(inputBuffer, inputOffset, inputCount); + HashValue = HashFinal(); + byte[] buffer = new byte[inputCount]; + Buffer.BlockCopy(inputBuffer, inputOffset, buffer, 0, inputCount); + this.State = 0; + return buffer; + } + #endregion + + protected virtual void Dispose(bool disposing) + { + if (!disposing) + Initialize(); + } + public void Dispose() + { + Dispose(true); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Hash/MD5/MD5Managed.cs b/Telegram.Api/Hash/MD5/MD5Managed.cs new file mode 100755 index 0000000..520c684 --- /dev/null +++ b/Telegram.Api/Hash/MD5/MD5Managed.cs @@ -0,0 +1,76 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#if !WIN_RT +using System; +using System.Security.Cryptography; +#if WINDOWS_PHONE +public class MD5Managed : HashAlgorithm +#else +public class MD5Managed : MD5 +#endif +{ + private byte[] _data; + private ABCDStruct _abcd; + private Int64 _totalLength; + private int _dataSize; + + public MD5Managed() + { + base.HashSizeValue = 0x80; + this.Initialize(); + } + + public override void Initialize() + { + _data = new byte[64]; + _dataSize = 0; + _totalLength = 0; + _abcd = new ABCDStruct(); + //Intitial values as defined in RFC 1321 + _abcd.A = 0x67452301; + _abcd.B = 0xefcdab89; + _abcd.C = 0x98badcfe; + _abcd.D = 0x10325476; + } + + protected override void HashCore(byte[] array, int ibStart, int cbSize) + { + int startIndex = ibStart; + int totalArrayLength = _dataSize + cbSize; + if (totalArrayLength >= 64) + { + Array.Copy(array, startIndex, _data, _dataSize, 64 - _dataSize); + // Process message of 64 bytes (512 bits) + MD5Core.GetHashBlock(_data, ref _abcd, 0); + startIndex += 64 - _dataSize; + totalArrayLength -= 64; + while (totalArrayLength >= 64) + { + Array.Copy(array, startIndex, _data, 0, 64); + MD5Core.GetHashBlock(array, ref _abcd, startIndex); + totalArrayLength -= 64; + startIndex += 64; + } + _dataSize = totalArrayLength; + Array.Copy(array, startIndex, _data, 0, totalArrayLength); + } + else + { + Array.Copy(array, startIndex, _data, _dataSize, cbSize); + _dataSize = totalArrayLength; + } + _totalLength += cbSize; + } + + protected override byte[] HashFinal() + { + base.HashValue = MD5Core.GetHashFinalBlock(_data, 0, _dataSize, _abcd, _totalLength * 8); + return base.HashValue; + } +} +#endif \ No newline at end of file diff --git a/Telegram.Api/Helpers/AuthorizationHelper.cs b/Telegram.Api/Helpers/AuthorizationHelper.cs new file mode 100755 index 0000000..2d0f266 --- /dev/null +++ b/Telegram.Api/Helpers/AuthorizationHelper.cs @@ -0,0 +1,774 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Numerics; +using System.Security.Cryptography; +using Telegram.Api.TL; +using Telegram.Api.Transport; + +namespace Telegram.Api.Helpers +{ + /*public class AuthorizationHelper : IAuthorizationHelper + { + public static byte[] AuthKey { get; set; } + public static TLLong Salt { get; set; } + public static TLLong SessionId { get; set; } + + private readonly ITransport _transport; + + public AuthorizationHelper(ITransport transport) + { + _transport = transport; + } + + public void InitAsync(Action> callback, Action faultCallback = null) + { + var authTime = Stopwatch.StartNew(); + // 1 stage + var authRequest = ComposeBeginAuthRequest(); + var message = CreatePlainMessageBody(authRequest); + var guid = 1; + _transport.SendBytesAsync("resPQ " + guid, message, + x1 => + { + var buffer = x1; + // 2 stage + var authResponse = AuthResponse.Parse(buffer); + + // 3 stage + TLUtils.WriteLine("pq: " + authResponse.pq); + var pqCalcTime = Stopwatch.StartNew(); + var tuple = Utils.GetPQPollard(authResponse.pq); + pqCalcTime.Stop(); + TLUtils.WriteLineAtBegin("pqCalc time: " + pqCalcTime.Elapsed); + var p = tuple.Item1; + var q = tuple.Item2; + TLUtils.WriteLine("p: " + tuple.Item1); + var pStr = TLString.FromUInt64(tuple.Item1); + //TLUtils.WriteLine("p bytes: " + BitConverter.ToString(pStr.ToBytes(8))); + + var qStr = TLString.FromUInt64(tuple.Item2); + TLUtils.WriteLine("q: " + tuple.Item2); + //TLUtils.WriteLine("q bytes: " + BitConverter.ToString(qStr.ToBytes(8))); + + + + + + + // 4 stage + var random1 = new Random(); + var newNonce = new byte[32]; + random1.NextBytes(newNonce); + + var data = ComposeData(authResponse, p, q, newNonce); //newNonce 32 + //TLUtils.WriteLine("-----------------------------------------"); + //TLUtils.WriteLine(string.Format("data [{1}]: {0}", BitConverter.ToString(data), data.Length)); + //TLUtils.WriteLine("-----------------------------------------"); + + + + SHA1 sha = new SHA1Managed(); + var sha1 = sha.ComputeHash(data); // data 96 + //TLUtils.WriteLine("-----------------------------------------"); + //TLUtils.WriteLine(string.Format("SHA1 data [{1}]: {0}", BitConverter.ToString(sha1), sha1.Length)); + //TLUtils.WriteLine("-----------------------------------------"); + + var dataWithHash = sha1.Concat(data).ToArray(); //116 + var data255 = new byte[255]; + var random = new Random(); + random.NextBytes(data255); + Array.Copy(dataWithHash, data255, dataWithHash.Length); + //TLUtils.WriteLine("-----------------------------------------"); + //TLUtils.WriteLine(string.Format("data with hash [{1}]: {0}", BitConverter.ToString(data255), data255.Length)); + //TLUtils.WriteLine("-----------------------------------------"); + + var rsa = GetRSABytes(data255); //data255 255 bytes + + var dhRequest = ComposeBeginDHRequest(authResponse, p, q, rsa); //rsa 256 bytes + var dhMessage = CreatePlainMessageBody(dhRequest); //dhRequest 320 bytes + guid = 2; + _transport.SendBytesAsync("req_DH_params " + guid, dhMessage, + dhResponseBuffer => + { + var dhResponse = BeginDHResponse.Parse(dhResponseBuffer); + + var aesParams = GetAesKeyIV(authResponse.ServerNonce, newNonce); + + var decryptedAnswerWithHash = Utils.AesIge(dhResponse.EncryptedAnswer, aesParams.Item1, aesParams.Item2, false); + TLUtils.WriteLine("---Decrypted answer with hash----------------"); + TLUtils.WriteLine(BitConverter.ToString(decryptedAnswerWithHash)); + //var encryptedAnswerWithHash = Utils.AesIge(dhResponse.EncryptedAnswer, aesParams.Item1, aesParams.Item2, true); + + var answer = Answer.Parse(decryptedAnswerWithHash.Skip(20).ToArray()); + var bBytes = new byte[256]; //big endian B + random.NextBytes(bBytes); + //TLUtils.WriteLine("B bytes: " + BitConverter.ToString(bBytes)); + + var g_bBytes = GetG_B(bBytes, answer.G, answer.DHPrime); // big-endian g_b + + //TLUtils.WriteLine("--G_B big endian bytes----------------------"); + //TLUtils.WriteLine(BitConverter.ToString(g_bBytes)); + + var client_DH_inner_data = ComposeClientDHInnerData(g_bBytes, authResponse); + + var client_DH_inner_dataWithHash = sha.ComputeHash(client_DH_inner_data).Concat(client_DH_inner_data).ToArray(); + var addedBytesLength = 16 - (client_DH_inner_dataWithHash.Length % 16); + if (addedBytesLength > 0 && addedBytesLength < 16) + { + var addedBytes = new byte[addedBytesLength]; + random.NextBytes(addedBytes); + client_DH_inner_dataWithHash = client_DH_inner_dataWithHash.Concat(addedBytes).ToArray(); + //TLUtils.WriteLine(string.Format("Added {0} bytes", addedBytesLength)); + } + + var aesEncryptClientDHInnerDataWithHash = Utils.AesIge(client_DH_inner_dataWithHash, aesParams.Item1, aesParams.Item2, true); + //TLUtils.WriteLine("--Last encrypted data------------------"); + //TLUtils.WriteLine(BitConverter.ToString(aesEncryptClientDHInnerDataWithHash)); + + + var requestSetClientDHParams = ComposeRequestSetClientDHParams(authResponse, aesEncryptClientDHInnerDataWithHash); + var requestSetClientDHParamsMessage = CreatePlainMessageBody(requestSetClientDHParams); + guid = 3; + _transport.SendBytesAsync("set_client_DH_params " + guid, requestSetClientDHParamsMessage, + x2 => + { + authTime.Stop(); + TLUtils.WriteLineAtBegin("pqCalc time: " + pqCalcTime.Elapsed); + TLUtils.WriteLineAtBegin("Auth time: " + authTime.Elapsed); + TLUtils.WriteLineAtBegin("Auth - pqCalc time: " + (authTime.Elapsed - pqCalcTime.Elapsed)); + buffer = x2; + var endAuthResponse = EndAuthResponse.Parse(buffer); + + var authKey = GetAuthKey(bBytes, answer.G_A, answer.DHPrime); + TLUtils.WriteLine("-Big endian auth key----------------------------------"); + TLUtils.WriteLine(BitConverter.ToString(authKey)); + TLUtils.WriteLine("-Big endian auth key----------------------------------"); + +#if !SILVERLIGHT + using (StreamWriter w = File.AppendText("log.txt")) + { + w.WriteLine(DateTime.Now); + w.WriteLine(BitConverter.ToString(authKey)); + } +#endif + //newNonce - little endian + //authResponse.ServerNonce - little endian + var salt = GetSalt(newNonce, authResponse.ServerNonce); + var sessionId = new byte[8]; + random.NextBytes(sessionId); + + AuthKey = authKey; + Salt = new TLLong(BitConverter.ToInt64(salt, 0)); + SessionId = new TLLong(BitConverter.ToInt64(sessionId, 0)); + TLUtils.WriteLine("Salt " + Salt + " (" + BitConverter.ToString(salt) + ")"); + TLUtils.WriteLine("Session id " +SessionId + " (" + BitConverter.ToString(sessionId) + ")"); + + callback(new Tuple(authKey, salt, sessionId)); + }, + () => { if (faultCallback != null) faultCallback(null); }); + }, + () => { if (faultCallback != null) faultCallback(null); }); // dhMessage340bytes 404 here + }, + () => { if (faultCallback != null) faultCallback(null); }); + } + + public Tuple Init() + { + // 1 stage + var authRequest = ComposeBeginAuthRequest(); + var message = CreatePlainMessageBody(authRequest); + var buffer = _transport.SendBytes(message); + + // 2 stage + var authResponse = AuthResponse.Parse(buffer); + + // 3 stage + TLUtils.WriteLine("pq: ", authResponse.pq); + var time = Stopwatch.StartNew(); + var tuple = Utils.GetPQ(authResponse.pq); + var p = tuple.Item1; + var q = tuple.Item2; + TLUtils.WriteLine("p: " + tuple.Item1); + var pStr = TLString.FromUInt64(tuple.Item1); + //TLUtils.WriteLine("p bytes: " + BitConverter.ToString(pStr.ToBytes(8))); + + var qStr = TLString.FromUInt64(tuple.Item2); + TLUtils.WriteLine("q: " + tuple.Item2); + //TLUtils.WriteLine("q bytes: " + BitConverter.ToString(qStr.ToBytes(8))); + TLUtils.WriteLine("Calculation time: " + time.ElapsedMilliseconds); + + // 4 stage + var random1 = new Random(); + var newNonce = new byte[32]; + random1.NextBytes(newNonce); + + var data = ComposeData(authResponse, p, q, newNonce); //newNonce 32 + //TLUtils.WriteLine("-----------------------------------------"); + //TLUtils.WriteLine(string.Format("data [{1}]: {0}", BitConverter.ToString(data), data.Length)); + //TLUtils.WriteLine("-----------------------------------------"); + + + + SHA1 sha = new SHA1Managed(); + var sha1 = sha.ComputeHash(data); // data 96 + //TLUtils.WriteLine("-----------------------------------------"); + //TLUtils.WriteLine(string.Format("SHA1 data [{1}]: {0}", BitConverter.ToString(sha1), sha1.Length)); + //TLUtils.WriteLine("-----------------------------------------"); + + var dataWithHash = sha1.Concat(data).ToArray(); //116 + var data255 = new byte[255]; + var random = new Random(); + random.NextBytes(data255); + Array.Copy(dataWithHash, data255, dataWithHash.Length); + //TLUtils.WriteLine("-----------------------------------------"); + //TLUtils.WriteLine(string.Format("data with hash [{1}]: {0}", BitConverter.ToString(data255), data255.Length)); + //TLUtils.WriteLine("-----------------------------------------"); + + var rsa = GetRSABytes(data255); //data255 255 bytes + + var dhRequest = ComposeBeginDHRequest(authResponse, p, q, rsa); //rsa 256 bytes + var dhMessage = CreatePlainMessageBody(dhRequest); //dhRequest 320 bytes + var stamp = Stopwatch.StartNew(); + var dhResponseBuffer = _transport.SendBytes(dhMessage); // dhMessage340bytes 404 here + + var dhResponse = BeginDHResponse.Parse(dhResponseBuffer); + + var aesParams = GetAesKeyIV(authResponse.ServerNonce, newNonce); + + var decryptedAnswerWithHash = Utils.AesIge(dhResponse.EncryptedAnswer, aesParams.Item1, aesParams.Item2, false); + //TLUtils.WriteLine("---Decrypted answer with hash----------------"); + //TLUtils.WriteLine(BitConverter.ToString(decryptedAnswerWithHash)); + //var encryptedAnswerWithHash = Utils.AesIge(dhResponse.EncryptedAnswer, aesParams.Item1, aesParams.Item2, true); + + var answer = Answer.Parse(decryptedAnswerWithHash.Skip(20).ToArray()); + var bBytes = new byte[256]; //big endian B + random.NextBytes(bBytes); + //TLUtils.WriteLine("B bytes: " + BitConverter.ToString(bBytes)); + + var g_bBytes = GetG_B(bBytes, answer.G, answer.DHPrime); // big-endian g_b + + //TLUtils.WriteLine("--G_B big endian bytes----------------------"); + //TLUtils.WriteLine(BitConverter.ToString(g_bBytes)); + + var client_DH_inner_data = ComposeClientDHInnerData(g_bBytes, authResponse); + + var client_DH_inner_dataWithHash = sha.ComputeHash(client_DH_inner_data).Concat(client_DH_inner_data).ToArray(); + var addedBytesLength = 16 - (client_DH_inner_dataWithHash.Length % 16); + if (addedBytesLength > 0 && addedBytesLength < 16) + { + var addedBytes = new byte[addedBytesLength]; + random.NextBytes(addedBytes); + client_DH_inner_dataWithHash = client_DH_inner_dataWithHash.Concat(addedBytes).ToArray(); + //TLUtils.WriteLine(string.Format("Added {0} bytes", addedBytesLength)); + } + + var aesEncryptClientDHInnerDataWithHash = Utils.AesIge(client_DH_inner_dataWithHash, aesParams.Item1, aesParams.Item2, true); + //TLUtils.WriteLine("--Last encrypted data------------------"); + //TLUtils.WriteLine(BitConverter.ToString(aesEncryptClientDHInnerDataWithHash)); + + + var requestSetClientDHParams = ComposeRequestSetClientDHParams(authResponse, aesEncryptClientDHInnerDataWithHash); + var requestSetClientDHParamsMessage = CreatePlainMessageBody(requestSetClientDHParams); + buffer = _transport.SendBytes(requestSetClientDHParamsMessage); + //TLUtils.WriteLine("--RESPONSE--------------"); + //TLUtils.WriteLine(BitConverter.ToString(buffer)); + var endAuthResponse = EndAuthResponse.Parse(buffer); + + var authKey = GetAuthKey(bBytes, answer.G_A, answer.DHPrime); + TLUtils.WriteLine("-Big endian auth key----------------------------------"); + TLUtils.WriteLine(BitConverter.ToString(authKey)); + TLUtils.WriteLine("-Big endian auth key----------------------------------"); + + using (StreamWriter w = File.AppendText("log.txt")) + { + w.WriteLine(DateTime.Now); + w.WriteLine(BitConverter.ToString(authKey)); + } + + // II saveDeveloperInfo + + //var saveDeveloperInfoRequest = ComposeSaveDeveloperInfoRequest(); + //newNonce - little endian + //authResponse.ServerNonce - little endian + var salt = GetSalt(newNonce, authResponse.ServerNonce); + TLUtils.WriteLine("Salt " + BitConverter.ToString(salt)); + var sessionId = new byte[8]; + random.NextBytes(sessionId); + TLUtils.WriteLine("Session id " + BitConverter.ToString(sessionId)); + + AuthKey = authKey; + Salt = new TLLong(BitConverter.ToInt64(salt, 0)); + SessionId = new TLLong(BitConverter.ToInt64(sessionId, 0)); + + return new Tuple(authKey, salt, sessionId); + } + + + public static byte[] GetSalt(byte[] newNonce, byte[] serverNonce) + { + var newNonceBytes = newNonce.Take(8).ToArray(); + var serverNonceBytes = serverNonce.Take(8).ToArray(); + + //TLUtils.WriteLine("--Generate salt--"); + //TLUtils.WriteLine("NewNonce little endian " + BitConverter.ToString(newNonce)); + //TLUtils.WriteLine("ServerNonce little endian " + BitConverter.ToString(serverNonce)); + + //TLUtils.WriteLine("Getted 8 first bytes"); + //TLUtils.WriteLine("NewNonce " + BitConverter.ToString(newNonceBytes)); + //TLUtils.WriteLine("ServerNonce " + BitConverter.ToString(serverNonceBytes)); + var returnBytes = new byte[8]; + for (int i = 0; i < returnBytes.Length; i++) + { + returnBytes[i] = (byte)(newNonceBytes[i] ^ serverNonceBytes[i]); + } + + return returnBytes; + } + + private static byte[] ComposeBeginAuthRequest() + { + byte[] res_pq = { 0x60, 0x46, 0x97, 0x78 }; + + var randomNumber = new byte[16]; + var random = new Random(); + random.NextBytes(randomNumber); + + return res_pq.Reverse() + .Concat(randomNumber).ToArray(); + } + + static byte[] CreatePlainMessageBody(byte[] data) + { + byte[] authKeyId = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + var now = DateTime.Now; + var fullTimeBytes = BitConverter.GetBytes((long)Utils.DateTimeToUnixTimestamp(now)); + var unixTime = (long)Utils.DateTimeToUnixTimestamp(now) << 32; + byte[] date = //{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + BitConverter.GetBytes(unixTime); + var messageBodyLength = BitConverter.GetBytes(data.Length); + + return authKeyId + .Concat(date) + .Concat(messageBodyLength) + .Concat(data).ToArray(); + } + + // return big-endian authKey + public static byte[] GetAuthKey(byte[] bBytes, byte[] g_aData, byte[] dhPrimeData) + { + int position = 0; + var b = new BigInteger(bBytes.Reverse().Concat(new byte[] { 0x00 }).ToArray()); + var dhPrime = TLObject.GetObject(dhPrimeData, ref position).ToBigInteger(); + position = 0; + var g_a = TLObject.GetObject(g_aData, ref position).ToBigInteger(); + + var authKey = BigInteger.ModPow(g_a, b, dhPrime).ToByteArray(); // little endian + (may be) zero last byte + + //remove last zero byte + if (authKey[authKey.Length - 1] == 0x00) + { + authKey = authKey.SubArray(0, authKey.Length - 1); + } + + return authKey.Reverse().ToArray(); + } + + // b - big endian bytes + // g - serialized data + // dhPrime - serialized data + // returns big-endian G_B + public static byte[] GetG_B(byte[] bBytes, byte[] gData, byte[] dhPrimeData) + { + //var bBytes = new byte[256]; // big endian bytes + //var random = new Random(); + //random.NextBytes(bBytes); + int position = 0; + var g = new BigInteger(gData); + var dhPrime = TLObject.GetObject(dhPrimeData, ref position).ToBigInteger(); + + var b = new BigInteger(bBytes.Reverse().Concat(new byte[] { 0x00 }).ToArray()); + + var g_b = BigInteger.ModPow(g, b, dhPrime).ToByteArray(); // little endian + (may be) zero last byte + + //remove last zero byte + if (g_b[g_b.Length - 1] == 0x00) + { + g_b = g_b.SubArray(0, g_b.Length - 1); + } + + return g_b.Reverse().ToArray(); + } + + public static Tuple GetAesKeyIV(byte[] serverNonce, byte[] newNonce) + { + SHA1 sha = new SHA1Managed(); + + var newNonceServerNonce = newNonce.Concat(serverNonce).ToArray(); + var serverNonceNewNonce = serverNonce.Concat(newNonce).ToArray(); + var key = sha.ComputeHash(newNonceServerNonce) + .Concat(sha.ComputeHash(serverNonceNewNonce).SubArray(0, 12)); + var im = sha.ComputeHash(serverNonceNewNonce).SubArray(12, 8) + .Concat(sha.ComputeHash(newNonce.Concat(newNonce).ToArray())) + .Concat(newNonce.SubArray(0, 4)); + + return new Tuple(key.ToArray(), im.ToArray()); + } + + // encryptedData - big-endian number + private static byte[] ComposeBeginDHRequest(AuthResponse response, UInt64 p, UInt64 q, byte[] encryptedData) + { + //TLUtils.WriteLine("---------------------------------"); + //TLUtils.WriteLine("Begin DH"); + //TLUtils.WriteLine("---------------------------------"); + var req_DH_params = new byte[] { 0xd7, 0x12, 0xe4, 0xbe }; + var nonce = response.Nonce; + //TLUtils.WriteLine("ServerNonce: " + BitConverter.ToString(response.Nonce)); + var serverNonce = response.ServerNonce; + //TLUtils.WriteLine("ServerNonce: " + BitConverter.ToString(response.ServerNonce)); + var pBytes = TLString.FromUInt64(p).ToBytes(); // 8 + //TLUtils.WriteLine("p: " + BitConverter.ToString(pBytes)); + var qBytes = TLString.FromUInt64(q).ToBytes(); // 8 + //TLUtils.WriteLine("q: " + BitConverter.ToString(qBytes)); + var fingerPrints = response.FingerPrints; + //TLUtils.WriteLine("FingerPrints: " + BitConverter.ToString(response.FingerPrints)); + var encryptedDataBytes = new byte[] { 0xFE, 0x00, 0x01, 0x00 }.Concat(encryptedData).ToArray(); + //TLUtils.WriteLine("encryptedDataBytes: " + BitConverter.ToString(encryptedDataBytes)); + + return req_DH_params.Reverse() + .Concat(nonce) + .Concat(serverNonce) + .Concat(pBytes) + .Concat(qBytes) + .Concat(fingerPrints) + .Concat(encryptedDataBytes).ToArray(); + } + + + + private static byte[] ComposeRequestSetClientDHParams(AuthResponse response, byte[] encryptedData) + { + //TLUtils.WriteLine("----Compose SetClientDHParams-------------"); + var set_client_DH_params = new byte[] { 0x1f, 0x5f, 0x04, 0xf5 }; + //TLUtils.WriteLine("set_client_DH_params " + BitConverter.ToString(set_client_DH_params)); + + var nonce = response.Nonce; + //TLUtils.WriteLine("Nonce " + BitConverter.ToString(nonce)); + + var serverNonce = response.ServerNonce; + //TLUtils.WriteLine("Server nonce " + BitConverter.ToString(serverNonce)); + + var encryptedDataStr = TLString.FromBigEndianData(encryptedData); + //TLUtils.WriteLine("encrypted data serialized"); + //TLUtils.WriteLine(BitConverter.ToString(encryptedDataStr.ToBytes(340))); + + return set_client_DH_params + .Concat(nonce) + .Concat(serverNonce) + .Concat(encryptedDataStr.ToBytes()) // 340 + .ToArray(); + } + + public static byte[] ComposeClientDHInnerData(byte[] g_bBigEndianBytes, AuthResponse response) + { + //TLUtils.WriteLine("----Compose ClientDHInnerData-------------"); + var client_DH_inner_data = new byte[] { 0x54, 0xb6, 0x43, 0x66 }; + //TLUtils.WriteLine("client_DH_inner_data " + BitConverter.ToString(client_DH_inner_data)); + + var nonce = response.Nonce; + //TLUtils.WriteLine("Nonce " + BitConverter.ToString(nonce)); + + var serverNonce = response.ServerNonce; + //TLUtils.WriteLine("Server nonce " + BitConverter.ToString(serverNonce)); + + Int64 retryId = 0; + var retryIdBytes = BitConverter.GetBytes(retryId); + //TLUtils.WriteLine("Retry id " + BitConverter.ToString(retryIdBytes)); + + var strG_b = TLString.FromBigEndianData(g_bBigEndianBytes); + //TLUtils.WriteLine("g_b serialized"); + //TLUtils.WriteLine(BitConverter.ToString(strG_b.ToBytes(260))); + + return client_DH_inner_data + .Concat(nonce) + .Concat(serverNonce) + .Concat(retryIdBytes) + .Concat(strG_b.ToBytes()).ToArray(); // 260 + + } + + private static byte[] GetRSABytes(byte[] bytes) + { + // big-endian exponent and modulus + const string exponentString = "010001"; + const string modulusString = "C150023E2F70DB7985DED064759CFECF" + + "0AF328E69A41DAF4D6F01B538135A6F91F8F8B2A0EC9BA9720CE352EFCF6C5680FFC424BD6348649" + + "02DE0B4BD6D49F4E580230E3AE97D95C8B19442B3C0A10D8F5633FECEDD6926A7F6DAB0DDB7D457F" + + "9EA81B8465FCD6FFFEED114011DF91C059CAEDAF97625F6C96ECC74725556934EF781D866B34F011" + + "FCE4D835A090196E9A5F0E4449AF7EB697DDB9076494CA5F81104A305B6DD27665722C46B60E5DF6" + + "80FB16B210607EF217652E60236C255F6A28315F4083A96791D7214BF64C1DF4FD0DB1944FB26A2A" + + "57031B32EEE64AD15A8BA68885CDE74A5BFC920F6ABF59BA5C75506373E7130F9042DA922179251F"; + var modulusBytes = Utils.StringToByteArray(modulusString); + var exponentBytes = Utils.StringToByteArray(exponentString); + var modulus = new BigInteger(modulusBytes.Reverse().Concat(new byte[] { 0x00 }).ToArray()); + var exponent = new BigInteger(exponentBytes.Reverse().Concat(new byte[] { 0x00 }).ToArray()); + var num = new BigInteger(bytes.Reverse().Concat(new byte[] { 0x00 }).ToArray()); + + var rsa = BigInteger.ModPow(num, exponent, modulus).ToByteArray().Reverse().ToArray(); + if (rsa.Length == 257) + { + if (rsa[0] != 0x00) throw new Exception("rsa last byte is " + rsa[0]); + + TLUtils.WriteLine("First RSA byte removes: byte value is " + rsa[0]); + rsa = rsa.SubArray(1, 256); + } + return rsa; + } + + public static byte[] ComposeData(AuthResponse response, UInt64 p, UInt64 q, byte[] newNonce) + { + var pqInnerData = new byte[] { 0x83, 0xc9, 0x5a, 0xec }; + + var pq = response.pqString.ToBytes(); //12 + var pBytes = TLString.FromUInt64(p).ToBytes(); //8 + var qBytes = TLString.FromUInt64(q).ToBytes(); //8 + + var nonce = response.Nonce; + var serverNonce = response.ServerNonce; + + return pqInnerData.Reverse().ToArray() + .Concat(pq).ToArray() + .Concat(pBytes).ToArray() + .Concat(qBytes).ToArray() + .Concat(nonce).ToArray() + .Concat(serverNonce).ToArray() + .Concat(newNonce).ToArray(); + } + } + + + + public class AuthResponse + { + public byte[] AuthKeyId { get; set; } + + public byte[] MessageId { get; set; } + + public Int32 MessageLength { get; set; } + + public byte[] Nonce { get; set; } + + public byte[] ServerNonce { get; set; } + + public byte[] FingerPrints { get; set; } + + public UInt64 pq { get; set; } + + public TLString pqString { get; set; } + + public static AuthResponse Parse(byte[] bytes) + { + var response = new AuthResponse(); + response.AuthKeyId = bytes.SubArray(0, 8); + //TLUtils.WriteLine("AuthKeyId: " + BitConverter.ToString(response.AuthKeyId)); + + response.MessageId = bytes.SubArray(8, 8); + var unixTime = BitConverter.ToInt64(response.MessageId, 0) >> 32; + //var serverDate = Utils.UnixTimestampToDateTime(unixTime); + //TLUtils.WriteLine("Server time: " + serverDate); + //TLUtils.WriteLine("MessageId: " + BitConverter.ToString(response.MessageId)); + + response.MessageLength = BitConverter.ToInt32(bytes.SubArray(16, 4), 0); + //TLUtils.WriteLine("MessageLength: " + response.MessageLength); + + response.Nonce = bytes.SubArray(24, 16); + //TLUtils.WriteLine("Nonce: " + BitConverter.ToString(response.Nonce)); + + response.ServerNonce = bytes.SubArray(40, 16); + //TLUtils.WriteLine("ServerNonce: " + BitConverter.ToString(response.ServerNonce)); + + var pqBytes = //new byte[] { 0x08, 0x17, 0xED, 0x48, 0x94, 0x1A, 0x08, 0xF9, 0x81, 0x00, 0x00, 0x00 }; + bytes.SubArray(56, 12); + //TLUtils.WriteLine("pq bytes: " + BitConverter.ToString(pqBytes)); + int position = 0; + response.pqString = TLObject.GetObject(pqBytes, ref position); + response.pq = BitConverter.ToUInt64(response.pqString.Data, 0); + //TLUtils.WriteLine("pq: " + response.pq); + + response.FingerPrints = bytes.SubArray(76, 8); + //TLUtils.WriteLine("FingerPrints: " + BitConverter.ToString(response.FingerPrints)); + + return response; + } + } + + internal class EndAuthResponse + { + public byte[] AuthKeyId { get; set; } + + public byte[] MessageId { get; set; } + + public Int32 MessageLength { get; set; } + + public byte[] Status { get; set; } + + public byte[] Nonce { get; set; } + + public byte[] ServerNonce { get; set; } + + public byte[] NewNonceSHA1 { get; set; } + + public static EndAuthResponse Parse(byte[] bytes) + { + TLUtils.WriteLine("----------------------------"); + TLUtils.WriteLine("--Parse end auth response---"); + TLUtils.WriteLine("----------------------------"); + + var response = new EndAuthResponse(); + + + response.AuthKeyId = bytes.SubArray(0, 8); + TLUtils.WriteLine("AuthKeyId: " + BitConverter.ToString(response.AuthKeyId)); + + response.MessageId = bytes.SubArray(8, 8); + var unixTime = BitConverter.ToInt64(response.MessageId, 0) >> 32; + var serverDate = Utils.UnixTimestampToDateTime(unixTime); + TLUtils.WriteLine("Server time: " + serverDate); + TLUtils.WriteLine(" MESSAGEID: " + BitConverter.ToString(response.MessageId)); + + response.MessageLength = BitConverter.ToInt32(bytes.SubArray(16, 4), 0); + TLUtils.WriteLine("MessageLength: " + response.MessageLength); + + response.Status = bytes.SubArray(20, 4); + TLUtils.WriteLine("Status " + BitConverter.ToString(response.Status)); + TLUtils.WriteLine(string.Equals(BitConverter.ToString(response.Status), "34-f7-cb-3b", + StringComparison.OrdinalIgnoreCase) + ? "Auth OK" + : "Auth Fail"); + + response.Nonce = bytes.SubArray(24, 16); + TLUtils.WriteLine("Nonce: " + BitConverter.ToString(response.Nonce)); + + response.ServerNonce = bytes.SubArray(40, 16); + TLUtils.WriteLine("ServerNonce: " + BitConverter.ToString(response.ServerNonce)); + + response.NewNonceSHA1 = bytes.SubArray(56, 16); + TLUtils.WriteLine("NewNonceSHA1: " + BitConverter.ToString(response.NewNonceSHA1)); + + return response; + } + } + + internal class Answer + { + + public byte[] Status { get; set; } + + public byte[] Nonce { get; set; } + + public byte[] ServerNonce { get; set; } + + public byte[] G { get; set; } + + public byte[] DHPrime { get; set; } + + public byte[] G_A { get; set; } + + public byte[] ServerTime { get; set; } + + public static Answer Parse(byte[] bytes) + { + //TLUtils.WriteLine("----------------------------"); + //TLUtils.WriteLine("--Server_DH_inner_dat-------"); + //TLUtils.WriteLine("----------------------------"); + + var answer = new Answer(); + + answer.Status = bytes.SubArray(0, 4); + //TLUtils.WriteLine(string.Equals(BitConverter.ToString(answer.Status), "BA-0D-89-B5", + // StringComparison.OrdinalIgnoreCase) + // ? "Server_DH_inner_dat OK" + // : "Server_DH_inner_dat Fail"); + + answer.Nonce = bytes.SubArray(4, 16); + TLUtils.WriteLine("Nonce: " + BitConverter.ToString(answer.Nonce)); + + answer.ServerNonce = bytes.SubArray(20, 16); + TLUtils.WriteLine("ServerNonce: " + BitConverter.ToString(answer.ServerNonce)); + + answer.G = bytes.SubArray(36, 4); + //TLUtils.WriteLine("G: " + BitConverter.ToString(answer.G)); + + answer.DHPrime = bytes.SubArray(40, 260); + //TLUtils.WriteLine("DHPrime: " + BitConverter.ToString(answer.DHPrime)); + //TLUtils.WriteLine(); + answer.G_A = bytes.SubArray(300, 260); + //TLUtils.WriteLine("G_A: " + BitConverter.ToString(answer.DHPrime)); + + answer.ServerTime = bytes.SubArray(560, 4); + var unixTime = BitConverter.ToInt32(answer.ServerTime, 0); + var serverDate = Utils.UnixTimestampToDateTime(unixTime); + //TLUtils.WriteLine("Server time: " + serverDate); + + + return answer; + } + } + + + internal class BeginDHResponse + { + public byte[] AuthKeyId { get; set; } + + public byte[] MessageId { get; set; } + + public Int32 MessageLength { get; set; } + + public byte[] Status { get; set; } + + public byte[] Nonce { get; set; } + + public byte[] ServerNonce { get; set; } + + public byte[] EncryptedAnswer { get; set; } + + public static BeginDHResponse Parse(byte[] bytes) + { + //TLUtils.WriteLine("----------------------------"); + //TLUtils.WriteLine("--server_DH_params----------"); + //TLUtils.WriteLine("----------------------------"); + + var response = new BeginDHResponse(); + response.AuthKeyId = bytes.SubArray(0, 8); + //TLUtils.WriteLine("AuthKeyId: " + BitConverter.ToString(response.AuthKeyId)); + + response.MessageId = bytes.SubArray(8, 8); + var unixTime = BitConverter.ToInt64(response.MessageId, 0) >> 32; + var serverDate = Utils.UnixTimestampToDateTime(unixTime); + //TLUtils.WriteLine("Server time: " + serverDate); + //TLUtils.WriteLine("MessageId: " + BitConverter.ToString(response.MessageId)); + + response.MessageLength = BitConverter.ToInt32(bytes.SubArray(16, 4), 0); + //TLUtils.WriteLine("MessageLength: " + response.MessageLength); + + response.Status = bytes.SubArray(20, 4); + //TLUtils.WriteLine(string.Equals(BitConverter.ToString(response.Status), "5c-07-e8-d0", + // StringComparison.OrdinalIgnoreCase) + // ? "DH Params OK" + // : "DH Params Fail"); + + response.Nonce = bytes.SubArray(24, 16); + //TLUtils.WriteLine("Nonce: " + BitConverter.ToString(response.Nonce)); + + response.ServerNonce = bytes.SubArray(40, 16); + //TLUtils.WriteLine("ServerNonce: " + BitConverter.ToString(response.ServerNonce)); + + response.EncryptedAnswer = bytes.SubArray(60, 592); + //TLUtils.WriteLine("EncryptedAnswer: "); + //TLUtils.WriteLine(BitConverter.ToString(response.EncryptedAnswer)); + + return response; + } + }*/ +} diff --git a/Telegram.Api/Helpers/Execute.cs b/Telegram.Api/Helpers/Execute.cs new file mode 100755 index 0000000..79cedf4 --- /dev/null +++ b/Telegram.Api/Helpers/Execute.cs @@ -0,0 +1,184 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Threading; +#if WIN_RT +using Windows.UI.Core; +using Windows.UI.Popups; +using System.Threading.Tasks; +using Windows.System.Threading; +#else +using System.Windows; +#endif +using Telegram.Api.Extensions; +using Telegram.Api.TL; + +namespace Telegram.Api.Helpers +{ + public static class Execute + { + public static void BeginOnThreadPool(TimeSpan delay, Action action) + { +#if WIN_RT + Task.Run(async () => + { + await Task.Delay(delay); + try + { + action.SafeInvoke(); + } + catch (Exception ex) + { + TLUtils.WriteException(ex); + } + }); +#else + ThreadPool.QueueUserWorkItem(state => + { + Thread.Sleep(delay); + try + { + action.SafeInvoke(); + } + catch (Exception ex) + { + TLUtils.WriteException(ex); + } + }); +#endif + } + + public static void BeginOnThreadPool(Action action) + { +#if WIN_RT + Task.Run(() => + { + try + { + action.SafeInvoke(); + } + catch (Exception ex) + { + TLUtils.WriteException(ex); + } + }); +#else + ThreadPool.QueueUserWorkItem(state => + { + try + { + action.SafeInvoke(); + } + catch (Exception ex) + { + TLUtils.WriteException(ex); + } + }); +#endif + } + + public static void BeginOnUIThread(Action action) + { +#if WIN_RT + var coreWindow = CoreWindow.GetForCurrentThread(); + if (coreWindow == null) return; + + var dispatcher = coreWindow.Dispatcher; + if (dispatcher == null) return; + + dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + try + { + action.SafeInvoke(); + } + catch (Exception ex) + { + TLUtils.WriteException(ex); + } + }); +#else + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + try + { + action.SafeInvoke(); + } + catch (Exception ex) + { + TLUtils.WriteException(ex); + } + }); +#endif + } + + public static void BeginOnUIThread(TimeSpan delay, Action action) + { + BeginOnThreadPool(delay, () => + { + BeginOnUIThread(action); + }); + } + + public static bool CheckAccess() + { +#if WIN_RT + var coreWindow = CoreWindow.GetForCurrentThread(); + if (coreWindow == null) return true; + + var dispatcher = coreWindow.Dispatcher; + if (dispatcher == null) return true; + + return dispatcher.HasThreadAccess; +#else + return Deployment.Current.Dispatcher.CheckAccess(); +#endif + } + + public static void OnUIThread(Action action) + { + if (CheckAccess()) + { + action(); + } + else + { + var waitHandle = new ManualResetEvent(false); + BeginOnUIThread((() => + { + action(); + waitHandle.Set(); + })); + waitHandle.WaitOne(); + } + } + + public static void ShowMessageBox(string message) + { +#if SILVERLIGHT + MessageBox.Show(message); +#elif WIN_RT + new MessageDialog(message).ShowAsync(); +#else + Console.WriteLine(message); +#endif + } + + public static bool IsForegroundApp { get; set; } + + public static void ShowDebugMessage(string message) + { +#if DEBUG + if (!IsForegroundApp) return; + + BeginOnUIThread(() => ShowMessageBox(message)); +#endif + } + } +} diff --git a/Telegram.Api/Helpers/FileUtils.cs b/Telegram.Api/Helpers/FileUtils.cs new file mode 100755 index 0000000..2be7e63 --- /dev/null +++ b/Telegram.Api/Helpers/FileUtils.cs @@ -0,0 +1,797 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Windows.Storage; +using Windows.Storage.Search; +using Windows.Storage.Streams; +using Telegram.Api.Aggregator; +using Telegram.Api.Services.FileManager; +#if WIN_RT +using Windows.Storage.Streams; +using Windows.Storage; +#else +using Microsoft.Phone.Shell; +using System.IO.IsolatedStorage; +using System.IO; +#endif +using Telegram.Api.TL; + +namespace Telegram.Api.Helpers +{ + public static class FileUtils + { + public static async Task MergePartsToFileAsync(Func getPartName, IEnumerable parts, string fileName) + { + using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(fileName, CreationCollisionOption.ReplaceExisting)) + { + foreach (var part in parts) + { + var partFileName = getPartName(part); + var partFile = await ApplicationData.Current.LocalFolder.GetFileAsync(partFileName); + using (var partStream = await partFile.OpenStreamForReadAsync()) + { + // append + var buffer = new byte[partStream.Length]; + stream.Seek(0, SeekOrigin.End); + await stream.WriteAsync(buffer, 0, buffer.Length); + } + await partFile.DeleteAsync(StorageDeleteOption.PermanentDelete); + } + } + } + + public static void MergePartsToFile(Func getPartName, IEnumerable parts, string fileName) + { +#if WINDOWS_PHONE + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (!store.FileExists(fileName)) + { + using (var stream = new IsolatedStorageFileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, store)) + { + foreach (var part in parts) + { + var partFileName = getPartName(part); + using (var partStream = new IsolatedStorageFileStream(partFileName, FileMode.OpenOrCreate, FileAccess.Read, store)) + { + var bytes = new byte[partStream.Length]; + partStream.Read(bytes, 0, bytes.Length); + stream.Position = stream.Length; + stream.Write(bytes, 0, bytes.Length); + } + + store.DeleteFile(partFileName); + } + } + } + else + { + foreach (var part in parts) + { + var partFileName = getPartName(part); + if (store.FileExists(partFileName)) + { + store.DeleteFile(partFileName); + } + } + } + } +#else + MergePartsToFileAsync(getPartName, parts, fileName).RunSynchronously(); +#endif + } + + public static bool Delete(object syncRoot, string fileName) + { + try + { + lock (syncRoot) + { +#if WIN_RT + var getFileOperation = ApplicationData.Current.LocalFolder.GetFileAsync(fileName); + + getFileOperation.AsTask().Wait(); + + var file = getFileOperation.GetResults(); + + Delete(file); +#elif WINDOWS_PHONE + var storage = IsolatedStorageFile.GetUserStoreForApplication(); + + if (storage.FileExists(fileName)) + { + storage.DeleteFile(fileName); + } +#endif + } + + return true; + } + catch (Exception e) + { + TLUtils.WriteLine("FILE ERROR: cannot delete " + fileName, LogSeverity.Error); + TLUtils.WriteException(e); + } + + return false; + } + + public static void Copy(object syncRoot, string fileName, string destinationFileName) + { + try + { + lock (syncRoot) + { +#if WIN_RT + var getFileOperation = ApplicationData.Current.LocalFolder.GetFileAsync(fileName); + getFileOperation.AsTask().Wait(); + var file = getFileOperation.GetResults(); + + var copyFileOperation = file.CopyAsync(ApplicationData.Current.LocalFolder, destinationFileName, NameCollisionOption.ReplaceExisting); + copyFileOperation.AsTask().Wait(); + var destinationFile = copyFileOperation.GetResults(); +#elif WINDOWS_PHONE + var file = IsolatedStorageFile.GetUserStoreForApplication(); + + file.CopyFile(fileName, destinationFileName, true); + +#endif + } + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR: cannot copy " + fileName, LogSeverity.Error); + TLUtils.WriteException(e); + } + } + + + public static void NotifyProgress(object itemsSyncRoot, IList items, UploadablePart part, ITelegramEventAggregator eventAggregator) + { + bool isComplete = false; + bool isCanceled; + var progress = 0.0; + lock (itemsSyncRoot) + { + part.Status = PartStatus.Processed; + isCanceled = part.ParentItem.Canceled; + if (!isCanceled) + { + isComplete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!isComplete) + { + double uploadedCount = part.ParentItem.Parts.Count(x => x.Status == PartStatus.Processed); + double totalCount = part.ParentItem.Parts.Count; + progress = uploadedCount / totalCount; + } + else + { + items.Remove(part.ParentItem); + } + } + } + + if (!isCanceled) + { + if (isComplete) + { + SwitchIdleDetectionMode(true); + Execute.BeginOnThreadPool(() => eventAggregator.Publish(part.ParentItem)); + } + else + { + if (part.ParentItem.FileNotFound) + { + return; + } + + var args = new UploadProgressChangedEventArgs(part.ParentItem, progress); + Execute.BeginOnThreadPool(() => eventAggregator.Publish(args)); + } + } + } + + public static void SwitchIdleDetectionMode(bool enabled) + { +#if WINDOWS_PHONE + var mode = enabled ? IdleDetectionMode.Enabled : IdleDetectionMode.Disabled; + try + { + PhoneApplicationService.Current.UserIdleDetectionMode = mode; + } + catch (Exception ex) + { + Execute.ShowDebugMessage("UploadVideoFileManager UserIdleDetectionMode=" + mode + Environment.NewLine + ex); + } +#endif + } + + public static int GetChunkSize(long totalSize) + { + int chunkSize = 32 * 1024; // 32Kb + if (totalSize > 256 * 1024 * Constants.MaximumChunksCount) + { + chunkSize = 512 * 1024; + } + else if (totalSize > 128 * 1024 * Constants.MaximumChunksCount) + { + chunkSize = 256 * 1024; + } + else if (totalSize > 64 * 1024 * Constants.MaximumChunksCount) + { + chunkSize = 128 * 1024; + } + else if (totalSize > 32 * 1024 * Constants.MaximumChunksCount) + { + chunkSize = 64 * 1024; + } + + return chunkSize; + } + + public static int GetPartsCount(long totalSize, int chunkSize) + { + return (int)(totalSize / chunkSize + (totalSize % chunkSize > 0 ? 1 : 0)); + } + + public static int GetLocalFileLength(string fileName) + { +#if WINDOWS_PHONE + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (store.FileExists(fileName)) + { + using (var file = store.OpenFile(fileName, FileMode.Open, FileAccess.Read)) + { + return (int)file.Length; + } + } + } + + return -1; +#else + var file = GetLocalFile(fileName); + + if (file != null) + { + var getBasicPropertiesOperation = file.GetBasicPropertiesAsync(); + getBasicPropertiesOperation.AsTask().Wait(); + + var basicProperties = getBasicPropertiesOperation.GetResults(); + + return (int)basicProperties.Size; + } + + return -1; +#endif + } + + public static StorageFile GetLocalFile(string fileName) + { + StorageFile file = null; + try + { + var getFileOperation = ApplicationData.Current.LocalFolder.GetFileAsync(fileName); + getFileOperation.AsTask().Wait(); + file = getFileOperation.GetResults(); + } + catch (Exception ex) + { + + } + + return file; + } + + private static StorageFile CreateLocalFile(string fileName) + { + var createFileOperation = ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); + createFileOperation.AsTask().Wait(); + var file = createFileOperation.GetResults(); + + return file; + } + + private static void Delete(StorageFile file) + { + if (file != null) + { + var deleteFileOperation = file.DeleteAsync(); + deleteFileOperation.AsTask().Wait(); + deleteFileOperation.GetResults(); + } + } + + public static void CheckMissingPart(object syncRoot, DownloadablePart part, string partName) + { +#if WINDOWS_PHONE + + if (part.Offset.Value == 0) + { + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (store.FileExists(partName)) + { + store.DeleteFile(partName); + } + } + } + + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (store.FileExists(partName)) + { + store.DeleteFile(partName); + } + + using (var stream = new IsolatedStorageFileStream(partName, FileMode.OpenOrCreate, FileAccess.Write, store)) + { + var data = part.File.Bytes.Data; + part.File.Bytes = new TLString(); + stream.Position = stream.Length; + stream.Write(data, 0, data.Length); + + if (data.Length < part.Limit.Value && (part.Number + 1) != part.ParentItem.Parts.Count) + { + lock (syncRoot) + { + var complete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!complete) + { + var emptyBufferSize = part.Limit.Value - data.Length; + var position = stream.Position; + + var missingPart = new DownloadablePart(part.ParentItem, new TLInt((int)position), + new TLInt(emptyBufferSize), -part.Number); + + var currentItemIndex = part.ParentItem.Parts.IndexOf(part); + part.ParentItem.Parts.Insert(currentItemIndex + 1, missingPart); + } + } + } + } + } +#else + CheckMissingPartAsync(syncRoot, part, partName).RunSynchronously(); +#endif + } + + private static async Task CheckMissingPartAsync(object syncRoot, DownloadablePart part, string partName) + { + try + { + var file = await ApplicationData.Current.LocalFolder.GetFileAsync(partName); + await file.DeleteAsync(StorageDeleteOption.PermanentDelete); + } + catch (Exception ex) + { + + } + + using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(partName, CreationCollisionOption.ReplaceExisting)) + { + var data = part.File.Bytes.Data; + part.File.Bytes = new TLString(); + stream.Position = stream.Length; + stream.Write(data, 0, data.Length); + + if (data.Length < part.Limit.Value && (part.Number + 1) != part.ParentItem.Parts.Count) + { + lock (syncRoot) + { + var complete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!complete) + { + var emptyBufferSize = part.Limit.Value - data.Length; + var position = stream.Position; + + var missingPart = new DownloadablePart(part.ParentItem, new TLInt((int)position), + new TLInt(emptyBufferSize), -part.Number); + + var currentItemIndex = part.ParentItem.Parts.IndexOf(part); + part.ParentItem.Parts.Insert(currentItemIndex + 1, missingPart); + } + } + } + } + } + + public static void WriteBytes(string fileName, byte[] bytes) + { +#if WINDOWS_PHONE + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + using (var fileStream = store.OpenFile(fileName, FileMode.Create, FileAccess.Write)) + { + fileStream.Write(bytes, 0, bytes.Length); + } + } +#else + var file = CreateLocalFile(fileName); + WriteBytes(file, bytes); +#endif + } + +#if WIN_RT + private static void WriteBytes(StorageFile file, byte[] data) + { + var writeBytesOperation = FileIO.WriteBytesAsync(file, data); + writeBytesOperation.AsTask().Wait(); + writeBytesOperation.GetResults(); + } +#endif + + public static byte[] ReadBytes(string fileName, long position, long length) + { +#if WINDOWS_PHONE + byte[] bytes = null; + using (var storage = IsolatedStorageFile.GetUserStoreForApplication()) + { + using (var stream = storage.OpenFile(fileName, FileMode.Open, FileAccess.Read)) + { + stream.Position = position; + bytes = new byte[length]; + stream.Read(bytes, 0, (int)length); + } + } + + return bytes; +#else + var file = GetLocalFile(fileName); + return file != null? ReadBytesAsync(file, position, length).Result : null; +#endif + } + + private static async Task ReadBytesAsync(StorageFile file, long position, long length) + { + using (var fs = await file.OpenAsync(FileAccessMode.Read)) + { + using (var inStream = fs.GetInputStreamAt((ulong)position)) + { + using (var reader = new DataReader(inStream)) + { + await reader.LoadAsync((uint)length); + var data = new byte[length]; + reader.ReadBytes(data); + reader.DetachStream(); + return data; + } + } + } + } + +#if WP8 + public static async Task> FillBuffer(IStorageFile file, UploadablePart part) + { + try + { + if (part.ParentItem.FileNotFound) + { + return new Tuple(false, null); + } + + System.Diagnostics.Debug.WriteLine("FillBuffer part=" + part.FilePart); + using (var inStream = await file.OpenSequentialReadAsync()) + { + using (var stream = inStream.AsStreamForRead()) + //using (var inStream = stream.GetInputStreamAt((ulong) part.Position)) + { + stream.Seek(part.Position, SeekOrigin.Begin); + var bytes = new byte[part.Count]; + + stream.Read(bytes, 0, bytes.Length); + //using (var reader = new DataReader(inStream)) + //{ + // await reader.LoadAsync((uint) bytes.Length); + // reader.ReadBytes(bytes); + //} + + // encrypting part + if (part.ParentItem.Key != null + && part.ParentItem.IV != null) + { + var key = part.ParentItem.Key; + var iv = part.FilePart.Value == 0 ? part.ParentItem.IV : part.IV; + + if (iv == null) + { + return new Tuple(true, null); + } + + byte[] nextIV; + + var encryptedBytes = Utils.AesIge(bytes, key.Data, iv.Data, true, out nextIV); + bytes = encryptedBytes; + + var nextPartId = part.FilePart.Value + 1; + if (part.ParentItem.Parts.Count > nextPartId) + { + part.ParentItem.Parts[nextPartId].IV = TLString.FromBigEndianData(nextIV); + } + } + + return new Tuple(true, bytes); + } + } + } + catch (FileNotFoundException ex) + { + Logs.Log.Write(string.Format("FileUtils.FillBuffer bytes=null position={0} count={1} ex={2}", part.Position, part.Count, ex)); + Execute.ShowDebugMessage("FillBuffer FileNotFoundException\n" + ex); + return new Tuple(false, null); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine("FillBuffer ex part=" + part.FilePart); + Logs.Log.Write(string.Format("FileUtils.FillBuffer bytes=null position={0} count={1} ex={2}", part.Position, part.Count, ex)); + Execute.ShowDebugMessage("FillBuffer Exception\n" + ex); + return new Tuple(true, null); + } + } + + public static UploadableItem GetUploadableItem(TLLong fileId, TLObject owner, StorageFile file) + { + return GetUploadableItem(fileId, owner, file, null, null); + } + + public static UploadableItem GetUploadableItem(TLLong fileId, TLObject owner, StorageFile file, TLString key, TLString iv) + { + var item = new UploadableItem(fileId, owner, file, key, iv); + + var task = file.GetBasicPropertiesAsync().AsTask(); + task.Wait(); + var propertie = task.Result; + var size = propertie.Size; + item.Parts = GetItemParts(item, (int)size); + return item; + } + + private static List GetItemParts(UploadableItem item, int size) + { + var chunkSize = GetChunkSize(size); + var partsCount = GetPartsCount(size, chunkSize); + var parts = new List(partsCount); + + for (var i = 0; i < partsCount; i++) + { + var part = new UploadablePart(item, new TLInt(i), i * chunkSize, Math.Min(chunkSize, (long)size - i * chunkSize)); + parts.Add(part); + } + + item.IsSmallFile = size < Constants.SmallFileMaxSize; // size < chunkSize; + + return parts; + } +#endif + + public static void Write(object syncRoot, string directoryName, string fileName, string str) + { +#if WINDOWS_PHONE + lock (syncRoot) + { + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (!store.DirectoryExists(directoryName)) + { + store.CreateDirectory(directoryName); + } + + using (var file = store.OpenFile(Path.Combine(directoryName, fileName), FileMode.Append)) + { + var bytes = Encoding.UTF8.GetBytes(str); + file.Write(bytes, 0, bytes.Length); + } + } + } +#else + lock (syncRoot) + { + var task = Task.Run(async () => await WriteAsync(directoryName, fileName, str)); + task.Wait(); + } +#endif + } + + private static async Task WriteAsync(string directoryName, string fileName, string str) + { + var logFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(directoryName, CreationCollisionOption.OpenIfExists); + + var logFile = await logFolder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists); + using (var stream = await logFile.OpenStreamForWriteAsync()) + { + // append + var buffer = Encoding.UTF8.GetBytes(str); + stream.Seek(0, SeekOrigin.End); + await stream.WriteAsync(buffer, 0, buffer.Length); + } + } + + public static void Clear(object syncRoot, string directoryName) + { +#if WINDOWS_PHONE + lock (syncRoot) + { + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + var fileNames = store.GetFileNames(Path.Combine(directoryName, "*.txt")); + foreach (var fileName in fileNames) + { + try + { + store.DeleteFile(Path.Combine(directoryName, fileName)); + } + catch (Exception ex) + { + TLUtils.WriteException(ex); + } + } + } + } +#else + lock (syncRoot) + { + ClearAsync(directoryName).RunSynchronously(); + } +#endif + } + + private static async Task ClearAsync(string directoryName) + { + var folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(directoryName, CreationCollisionOption.OpenIfExists); + + var files = await folder.GetFilesAsync(); + foreach (var file in files) + { + try + { + await file.DeleteAsync(StorageDeleteOption.PermanentDelete); + } + catch (Exception ex) + { + TLUtils.WriteException(ex); + } + } + } + + public static void CopyLog(object syncRoot, string fromDirectoryName, string fromFileName, string toFileName, bool isEnabled) + { +#if WINDOWS_PHONE + lock (syncRoot) + { + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (store.FileExists(Path.Combine(fromDirectoryName, fromFileName))) + { + store.CopyFile(Path.Combine(fromDirectoryName, fromFileName), toFileName); + } + else + { + using (var file = store.OpenFile(toFileName, FileMode.Append)) + { + var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture); + var bytes = Encoding.UTF8.GetBytes(string.Format("{0} {1}{2}", timestamp, "Log.IsEnabled=" + isEnabled, Environment.NewLine)); + file.Write(bytes, 0, bytes.Length); + } + } + } + } +#else + lock (syncRoot) + { + CopyLogAsync(syncRoot, fromDirectoryName, fromFileName, toFileName, isEnabled).RunSynchronously(); + } +#endif + } + + private static async Task CopyLogAsync(object syncRoot, string fromDirectoryName, string fromFileName, string toFileName, bool isEnabled) + { + var folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(fromDirectoryName, CreationCollisionOption.OpenIfExists); + StorageFile logFile = null; + try + { + logFile = await folder.GetFileAsync(fromFileName); + } + catch (Exception ex) + { + + } + + if (logFile != null) + { + await logFile.CopyAsync(ApplicationData.Current.LocalFolder, toFileName); + } + else + { + var logFolder = ApplicationData.Current.LocalFolder; + + logFile = await logFolder.CreateFileAsync(toFileName); + using (var stream = await logFile.OpenStreamForReadAsync()) + { + // append + var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture); + var buffer = Encoding.UTF8.GetBytes(string.Format("{0} {1}{2}", timestamp, "Log.IsEnabled=" + isEnabled, Environment.NewLine)); + stream.Seek(0, SeekOrigin.End); + await stream.WriteAsync(buffer, 0, buffer.Length); + } + } + } + + public static Stream GetLocalFileStreamForRead(string fileName) + { +#if WINDOWS_PHONE + var store = IsolatedStorageFile.GetUserStoreForApplication(); + + return new IsolatedStorageFileStream(fileName, FileMode.OpenOrCreate, store); +#else + var openFileOperation = ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists); + openFileOperation.AsTask().Wait(); + var file = openFileOperation.GetResults(); + + return file.OpenStreamForReadAsync().Result; +#endif + } + + public static Stream GetLocalFileStreamForWrite(string fileName) + { +#if WINDOWS_PHONE + var store = IsolatedStorageFile.GetUserStoreForApplication(); + + return new IsolatedStorageFileStream(fileName, FileMode.Create, store); +#else + var openFileOperation = ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists); + openFileOperation.AsTask().Wait(); + var file = openFileOperation.GetResults(); + + return file.OpenStreamForWriteAsync().Result; +#endif + } + + public static void SaveWithTempFile(string fileName, T data) where T : TLObject + { +#if WINDOWS_PHONE + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + var tempFileName = fileName + ".temp"; + using (var fileStream = new IsolatedStorageFileStream(tempFileName, FileMode.Create, store)) + { + data.ToStream(fileStream); + } + //var stopwatch = Stopwatch.StartNew(); + store.CopyFile(tempFileName, fileName, true); + //store.DeleteFile(fileName); + //store.MoveFile(tempFileName, fileName); + //store.DeleteFile(tempFileName); + //WritePerformance("MoveFile time: " + stopwatch.Elapsed); + } +#else + + + var tempFileName = fileName + ".temp"; + var openFileOperation = ApplicationData.Current.LocalFolder.CreateFileAsync(tempFileName, CreationCollisionOption.OpenIfExists); + openFileOperation.AsTask().Wait(); + var tempFile = openFileOperation.GetResults(); + + using (var fileStream = tempFile.OpenStreamForWriteAsync().Result) + { + data.ToStream(fileStream); + } + + var copyOperation = tempFile.CopyAsync(ApplicationData.Current.LocalFolder, fileName, NameCollisionOption.ReplaceExisting); + copyOperation.AsTask().Wait(); + copyOperation.GetResults(); +#endif + } + } +} diff --git a/Telegram.Api/Helpers/IAuthorizationHelper.cs b/Telegram.Api/Helpers/IAuthorizationHelper.cs new file mode 100755 index 0000000..54a5f53 --- /dev/null +++ b/Telegram.Api/Helpers/IAuthorizationHelper.cs @@ -0,0 +1,16 @@ +using System; +using Telegram.Api.TL; + +namespace Telegram.Api.Helpers +{ + //public interface IAuthorizationHelper + //{ + // /// + // /// Initializes and return authKey, salt and sessionId + // /// + // /// + // Tuple Init(); + + // void InitAsync(Action> callback, Action faultCallback = null); + //} +} diff --git a/Telegram.Api/Helpers/Notifications.cs b/Telegram.Api/Helpers/Notifications.cs new file mode 100755 index 0000000..94f90c2 --- /dev/null +++ b/Telegram.Api/Helpers/Notifications.cs @@ -0,0 +1,36 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Telegram.Api.TL; + +namespace Telegram.Api.Helpers +{ + public static class Notifications + { + private static readonly object _notificatonsSyncRoot = new object(); + + public static bool IsDisabled + { + get + { + var result = TLUtils.OpenObjectFromMTProtoFile(_notificatonsSyncRoot, Constants.DisableNotificationsFileName); + + return result != null; + } + } + + public static void Disable() + { + TLUtils.SaveObjectToMTProtoFile(_notificatonsSyncRoot, Constants.DisableNotificationsFileName, TLBool.True); + } + + public static void Enable() + { + FileUtils.Delete(_notificatonsSyncRoot, Constants.DisableNotificationsFileName); + } + } +} diff --git a/Telegram.Api/Helpers/PhoneHelper.cs b/Telegram.Api/Helpers/PhoneHelper.cs new file mode 100755 index 0000000..569f5eb --- /dev/null +++ b/Telegram.Api/Helpers/PhoneHelper.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.Xml; +#if WINDOWS_PHONE +using Microsoft.Phone.Info; +#endif + +namespace Telegram.Api.Helpers +{ + public class PhoneHelper + { + const string AppManifestName = "WMAppManifest.xml"; + const string AppNodeName = "App"; + public const string AppVersion = "Version"; + + public static bool IsLowMemoryDevice() + { +#if WINDOWS_PHONE + try + { + var result = (long)DeviceExtendedProperties.GetValue("ApplicationWorkingSetLimit"); + + if (result < 94371840L) + { + return true; + } + + return false; + } + + catch (ArgumentOutOfRangeException) + { + // The device does not support querying for this value. This occurs + // on Windows Phone OS 7.1 and older phones without OS updates. + + return true; + } +#else + return false; +#endif + } + + public static string GetOSVersion() + { +#if WINDOWS_PHONE + + return Environment.OSVersion.Version.ToString(); +#else + return "TestWinRT"; +#endif + } + + public static string GetAppVersion() + { + return GetAppAttribute(AppVersion); + } + + /// + /// Gets the value from the WMAppManifest in runtime + /// Example: PhoneHelper.GetAppAttribute("Title"); + /// + /// http://stackoverflow.com/questions/3411377/get-the-windows-phone-7-application-title-from-code + /// + /// + /// + public static string GetAppAttribute(string attributeName) + { +#if WINDOWS_PHONE + try + { + var settings = new XmlReaderSettings { XmlResolver = new XmlXapResolver() }; + + using (var rdr = XmlReader.Create(AppManifestName, settings)) + { + rdr.ReadToDescendant(AppNodeName); + if (!rdr.IsStartElement()) + { + throw new FormatException(AppManifestName + " is missing " + AppNodeName); + } + + return rdr.GetAttribute(attributeName); + } + } + catch (Exception) + { + return ""; + } +#else + return "TestWinRT"; +#endif + } + + public static string GetDeviceFullName() + { +#if WINDOWS_PHONE + return (string)DeviceExtendedProperties.GetValue("DeviceName"); +#else + return "TestWinRT"; +#endif + } + + public static bool IsWiFiEnabled() + { +#if WINDOWS_PHONE + return Microsoft.Phone.Net.NetworkInformation.DeviceNetworkInformation.IsWiFiEnabled; +#else + return true; +#endif + } + + public static bool IsCellularDataEnabled() + { +#if WINDOWS_PHONE + return Microsoft.Phone.Net.NetworkInformation.DeviceNetworkInformation.IsCellularDataEnabled; +#else + return true; +#endif + } + + public static string GetShortPhoneModel(string phoneCode) + { + var cleanCode = phoneCode.Replace("-", string.Empty).ToLowerInvariant(); + + foreach (var model in _models) + { + if (cleanCode.StartsWith(model.Key)) + { + return model.Value; + } + } + + return string.Empty; + } + + private static Dictionary _models = new Dictionary + { + {"rm923", "Lumia505"}, + {"rm898", "Lumia510"}, + {"rm889", "Lumia510"}, + {"rm915", "Lumia520"}, + {"rm917", "Lumia521"}, + {"rm998", "Lumia525"}, + {"rm997", "Lumia526"}, + {"rm1017", "Lumia530"}, + {"rm1018", "Lumia530"}, + {"rm1019", "Lumia530"}, + {"rm1020", "Lumia530"}, + {"rm1090", "Lumia535"}, + {"rm836", "Lumia610"}, + {"rm849", "Lumia610"}, + {"rm846", "Lumia620"}, + {"rm941", "Lumia625"}, + {"rm942", "Lumia625"}, + {"rm943", "Lumia625"}, + {"rm974", "Lumia630"}, + {"rm976", "Lumia630"}, + {"rm977", "Lumia630"}, + {"rm978", "Lumia630"}, + {"rm975", "Lumia635"}, + {"rm803", "Lumia710"}, + {"rm809", "Lumia710"}, + {"rm885", "Lumia720"}, + {"rm887", "Lumia720"}, + {"rm1038", "Lumia730"}, + {"rm801", "Lumia800"}, + {"rm802", "Lumia800"}, + {"rm819", "Lumia800"}, + {"rm878", "Lumia810"}, + {"rm824", "Lumia820"}, + {"rm825", "Lumia820"}, + {"rm826", "Lumia820"}, + {"rm845", "Lumia822"}, + {"rm983", "Lumia830"}, + {"rm984", "Lumia830"}, + {"rm985", "Lumia830"}, + {"rm808", "Lumia900"}, + {"rm823", "Lumia900"}, + {"rm820", "Lumia920"}, + {"rm821", "Lumia920"}, + {"rm822", "Lumia920"}, + {"rm867", "Lumia920"}, + {"rm892", "Lumia925"}, + {"rm893", "Lumia925"}, + {"rm910", "Lumia925"}, + {"rm955", "Lumia925"}, + {"rm860", "Lumia928"}, + {"rm1045", "Lumia930"}, + {"rm875", "Lumia1020"}, + {"rm876", "Lumia1020"}, + {"rm877", "Lumia1020"}, + {"rm994", "Lumia1320"}, + {"rm995", "Lumia1320"}, + {"rm996", "Lumia1320"}, + {"rm937", "Lumia1520"}, + {"rm938", "Lumia1520"}, + {"rm939", "Lumia1520"}, + {"rm940", "Lumia1520"}, + {"rm927", "LumiaIcon"}, + + }; + + } +} diff --git a/Telegram.Api/Helpers/RequestHelper.cs b/Telegram.Api/Helpers/RequestHelper.cs new file mode 100755 index 0000000..dbcbe26 --- /dev/null +++ b/Telegram.Api/Helpers/RequestHelper.cs @@ -0,0 +1,87 @@ +using System; +using System.Linq; +using System.Security.Cryptography; +using Telegram.Api.Services; +using Telegram.Api.TL; +using Telegram.Api.Transport; + +namespace Telegram.Api.Helpers +{ + class RequestHelper + { + private readonly ITransport _transport; + + public RequestHelper(ITransport transport) + { + _transport = transport; + } + + public TLResponse Send(string caption, int seqNo, Func getData) + { + var authKey = MTProtoService.AuthKey; + var salt = MTProtoService.Salt; + var sessionId = MTProtoService.SessionId; + + TLUtils.WriteLine(); + TLUtils.WriteLine("------------------------"); + TLUtils.WriteLine(String.Format("--{0}--", caption)); + TLUtils.WriteLine("------------------------"); + + SHA1 sha = new SHA1Managed(); + var random = new Random(); + var request = getData(); + + TLUtils.WriteLine("Salt: " + salt); + TLUtils.WriteLine("SessionId: " + sessionId); + var messageId = TLUtils.GenerateMessageId(); + TLUtils.WriteLine("->MESSAGEID: " + TLUtils.MessageIdString(messageId)); + TLUtils.WriteLine(" SEQUENCENUMBER: " + seqNo); + //var seqNo = BitConverter.GetBytes(3); + var data = salt.ToBytes() + .Concat(sessionId.ToBytes()) + .Concat(messageId.ToBytes()) + .Concat(BitConverter.GetBytes(seqNo)) + .Concat(BitConverter.GetBytes(request.Length)) + .Concat(request) + .ToArray(); + + var length = data.Length; + var padding = 16 - (length % 16); + byte[] paddingBytes = null; + if (padding > 0 && padding < 16) + { + paddingBytes = new byte[padding]; + random.NextBytes(paddingBytes); + } + + byte[] dataWithPadding = data; + if (paddingBytes != null) + { + dataWithPadding = data.Concat(paddingBytes).ToArray(); + } + + + var msgKey = TLUtils.GetMsgKey(data); + var keyIV = Utils.GetEncryptKeyIV(authKey, msgKey); + var encryptedData = Utils.AesIge(dataWithPadding, keyIV.Item1, keyIV.Item2, true); + + //TLUtils.WriteLine("--Compute auth key sha1--"); + var authKeyHash = sha.ComputeHash(authKey); + var authKeyId = authKeyHash.SubArray(12, 8); + //TLUtils.WriteLine("Auth key sha1: " + BitConverter.ToString(authKeyHash)); + //TLUtils.WriteLine("Auth key little 8 bytes: " + BitConverter.ToString(authKeyId)); + + //TLUtils.WriteLine("--Check phone request--"); + var reqBytes = authKeyId.Concat(msgKey).Concat(encryptedData).ToArray(); + + return null; + // var buffer = _transport.SendBytes(reqBytes); + + //TLUtils.WriteLine("Buffer:"); + //TLUtils.WriteLine(BitConverter.ToString(buffer)); + + //Console.ReadKey(); + //return TLResponse.Parse(buffer, authKey); + } + } +} diff --git a/Telegram.Api/Helpers/SettingsHelper.cs b/Telegram.Api/Helpers/SettingsHelper.cs new file mode 100755 index 0000000..d156bf5 --- /dev/null +++ b/Telegram.Api/Helpers/SettingsHelper.cs @@ -0,0 +1,351 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using System.Xml; +using Telegram.Api; +using Telegram.Api.TL; +#if WINDOWS_PHONE +using System.Windows; +using System.IO.IsolatedStorage; +#else +using System.Threading.Tasks; +using TelegramClient.ViewModels.Additional; +using Windows.UI.Xaml; +using Windows.Storage; +#endif + +namespace Telegram.Api.Helpers +{ +#if WINDOWS_PHONE + public static class SettingsHelper + { + private static readonly object SyncLock = new object(); + + public static void CrossThreadAccess(Action action) + { + lock (SyncLock) + { + try + { + action(IsolatedStorageSettings.ApplicationSettings); + } + catch (Exception e) + { + Execute.ShowDebugMessage("SettingsHelper.CrossThreadAccess" + e); + } + } + } + + public static T GetValue(string key) + { + T result; + lock (SyncLock) // critical for wp7 devices + { + try + { + if (IsolatedStorageSettings.ApplicationSettings.TryGetValue(key, out result)) + { + return result; + } + + result = default(T); + } + catch (Exception e) + { + Logs.Log.Write("SettingsHelper.GetValue " + e); + result = default(T); + } + } + return result; + } + + public static object GetValue(string key) + { + object result; + lock (SyncLock) //critical for wp7 devices + { + try + { + if (IsolatedStorageSettings.ApplicationSettings.TryGetValue(key, out result)) + { + return result; + } + + result = null; + } + catch (Exception e) + { + Logs.Log.Write("SettingsHelper.GetValue " + e); + result = null; + } + + } + return result; + } + + private static readonly object _backgroundTaskSettingsSyncRoot = new object(); + + public static void SetValue(string key, object value) + { + lock (SyncLock) + { + IsolatedStorageSettings.ApplicationSettings[key] = value; + IsolatedStorageSettings.ApplicationSettings.Save(); + + //var backgroundSettings = new Dictionary(); + //foreach (var settings in IsolatedStorageSettings.ApplicationSettings) + //{ + // if (settings.Value.GetType().Assembly.GetName().Name != "Telegram.Api") + // { + // continue; + // } + + // backgroundSettings[settings.Key] = settings.Value; + //} + //SaveBackgroundSettingsAsync(_backgroundTaskSettingsSyncRoot, Constants.BackgroundTaskSettingsFileName, backgroundSettings); + } + } + + private static void SaveBackgroundSettingsAsync(object syncRoot, string fileName, Dictionary settings) + { + Execute.BeginOnThreadPool(() => + { + TLUtils.SaveObjectToFile(syncRoot, fileName, settings); + }); + } + + public static void RemoveValue(string key) + { + lock (SyncLock) + { + IsolatedStorageSettings.ApplicationSettings.Remove(key); + } + } + } +#elif WIN_RT + public static class SettingsHelper + { + private static readonly object SyncLock = new object(); + + public static void CrossThreadAccess(Action> action) + { + lock (SyncLock) + { + try + { + action(LocalSettings); + } + catch (Exception e) + { + Execute.ShowDebugMessage("SettingsHelper.CrossThreadAccess" + e); + } + } + } + + public static T GetValue(string key) + { + object result; + lock (SyncLock) // critical for wp7 devices + { + try + { + if (LocalSettings.TryGetValue(key, out result)) + { + return (T)result; + } + + result = default(T); + } + catch (Exception e) + { + Logs.Log.Write("SettingsHelper.GetValue " + e); + result = default(T); + } + } + return (T)result; + } + + public static object GetValue(string key) + { + object result; + lock (SyncLock) //critical for wp7 devices + { + try + { + if (LocalSettings.TryGetValue(key, out result)) + { + return result; + } + + result = null; + } + catch (Exception e) + { + Logs.Log.Write("SettingsHelper.GetValue " + e); + result = null; + } + + } + return result; + } + + public static void SetValue(string key, object value) + { + lock (SyncLock) + { + LocalSettings[key] = value; + } + } + + public static void RemoveValue(string key) + { + lock (SyncLock) + { + LocalSettings.Remove(key); + } + } + + private static Dictionary _settings; + + public static Dictionary LocalSettings + { + get + { + if (_settings == null) + { + _settings = GetValuesAsync().Result; + } + + return _settings; + } + } + + public static async Task> GetValuesAsync() + { + try + { + using (var fileStream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync("__ApplicationSettings")) + { + //var stringReader = new StreamReader(fileStream); + //var str = stringReader.ReadToEnd(); + + using (var streamReader = new StreamReader(fileStream)) + { + var line = streamReader.ReadLine() ?? string.Empty; + + var knownTypes = line.Split('\0') + .Where(x => !string.IsNullOrEmpty(x)) + .Select(Type.GetType) + .ToList(); + + ReplaceNonPclTypes(knownTypes); + + fileStream.Position = line.Length + Environment.NewLine.Length; + + var serializer = new DataContractSerializer(typeof(Dictionary), knownTypes); + return (Dictionary)serializer.ReadObject(fileStream); + } + } + } + catch(Exception ex) + { + Logs.Log.Write("SettingsHelper.GetValuesAsync exception " + ex); + + return new Dictionary(); + } + } + + private static void ReplaceNonPclTypes(List knownTypes) + { + for (var i = 0; i < knownTypes.Count; i++) + { + if (knownTypes[i].Name == typeof(TLConfig82).Name) + { + knownTypes[i] = typeof(TLConfig82); + } + else if (knownTypes[i].Name == typeof(TLConfig78).Name) + { + knownTypes[i] = typeof(TLConfig78); + } + else if (knownTypes[i].Name == typeof(TLConfig76).Name) + { + knownTypes[i] = typeof(TLConfig76); + } + else if (knownTypes[i].Name == typeof(TLConfig72).Name) + { + knownTypes[i] = typeof(TLConfig72); + } + else if (knownTypes[i].Name == typeof(TLConfig71).Name) + { + knownTypes[i] = typeof(TLConfig71); + } + else if (knownTypes[i].Name == typeof(TLConfig67).Name) + { + knownTypes[i] = typeof(TLConfig67); + } + else if (knownTypes[i].Name == typeof(TLConfig63).Name) + { + knownTypes[i] = typeof(TLConfig63); + } + else if (knownTypes[i].Name == typeof(TLConfig61).Name) + { + knownTypes[i] = typeof(TLConfig61); + } + else if (knownTypes[i].Name == typeof(TLConfig60).Name) + { + knownTypes[i] = typeof(TLConfig60); + } + else if (knownTypes[i].Name == typeof(TLConfig55).Name) + { + knownTypes[i] = typeof(TLConfig55); + } + else if (knownTypes[i].Name == typeof(TLConfig54).Name) + { + knownTypes[i] = typeof(TLConfig54); + } + else if (knownTypes[i].Name == typeof(TLConfig52).Name) + { + knownTypes[i] = typeof(TLConfig52); + } + else if (knownTypes[i].Name == typeof(TLConfig48).Name) + { + knownTypes[i] = typeof(TLConfig48); + } + else if (knownTypes[i].Name == typeof(TLConfig44).Name) + { + knownTypes[i] = typeof(TLConfig44); + } + else if (knownTypes[i].Name == typeof(TLConfig41).Name) + { + knownTypes[i] = typeof(TLConfig41); + } + else if (knownTypes[i].Name == typeof(TLConfig28).Name) + { + knownTypes[i] = typeof(TLConfig28); + } + else if (knownTypes[i].Name == typeof(BackgroundItem).Name) + { + knownTypes[i] = typeof(BackgroundItem); + } + } + } + } +#endif +} + +#if WIN_RT +namespace TelegramClient.ViewModels.Additional +{ + public class BackgroundItem { } +} +#endif \ No newline at end of file diff --git a/Telegram.Api/Helpers/Utils.cs b/Telegram.Api/Helpers/Utils.cs new file mode 100755 index 0000000..2af3fb0 --- /dev/null +++ b/Telegram.Api/Helpers/Utils.cs @@ -0,0 +1,755 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Storage.Streams; +using Org.BouncyCastle.OpenSsl; +#if WINDOWS_PHONE +using System.Threading; +using System.Security.Cryptography; +using System.Windows; +#elif WIN_RT +using Windows.Security.Cryptography; +using System.Runtime.InteropServices.WindowsRuntime; +#endif +using System.Text; +using Windows.Security.Cryptography.Core; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Telegram.Api.TL; +using Buffer = System.Buffer; + +namespace Telegram.Api.Helpers +{ + public class PollardRhoLong + { + public static long Gcd(long ths, long val) + { + if (val == 0) + return Math.Abs(ths); + if (ths == 0) + return Math.Abs(val); + + long r; + long u = ths; + long v = val; + + while (v != 0) + { + r = u % v; + u = v; + v = r; + } + + return u; + } + + public static long Rho(long N) + { + var random = new Random(); + + long divisor; + var bytes = new byte[8]; + random.NextBytes(bytes); + var c = BitConverter.ToInt64(bytes, 0); + random.NextBytes(bytes); + var x = BitConverter.ToInt64(bytes, 0); + var xx = x; + + // check divisibility by 2 + if (N % 2 == 0) return 2; + + do + { + x = (x * x % N + c) % N; + xx = (xx * xx % N + c) % N; + xx = (xx * xx % N + c) % N; + divisor = Gcd(x - xx, N); + } while (divisor == 1); + + return divisor; + } + } + + public class PollardRho + { + private static readonly BigInteger ZERO = new BigInteger("0"); + private static readonly BigInteger ONE = new BigInteger("1"); + private static readonly BigInteger TWO = new BigInteger("2"); + private static readonly SecureRandom random = new SecureRandom(); + + public static BigInteger Rho(BigInteger N) + { + BigInteger divisor; + var c = new BigInteger(N.BitLength, random); + var x = new BigInteger(N.BitLength, random); + var xx = x; + + // check divisibility by 2 + if (N.Mod(TWO).CompareTo(ZERO) == 0) return TWO; + + do + { + x = x.Multiply(x).Mod(N).Add(c).Mod(N); + xx = xx.Multiply(xx).Mod(N).Add(c).Mod(N); + xx = xx.Multiply(xx).Mod(N).Add(c).Mod(N); + divisor = x.Subtract(xx).Gcd(N); + } while ((divisor.CompareTo(ONE)) == 0); + + return divisor; + } + + public static WindowsPhone.Tuple Factor(BigInteger N) + { + var divisor = Rho(N); + + var divisor2 = N.Divide(divisor); + + return divisor.CompareTo(divisor2) > 0 + ? new WindowsPhone.Tuple(divisor2, divisor) + : new WindowsPhone.Tuple(divisor, divisor2); + } + } + + public static class Utils + { +#if !WIN_RT + public static bool XapContentFileExists(string relativePath) + { + return Application.GetResourceStream(new Uri(relativePath, UriKind.Relative)) != null; + } +#endif + + public static long GetRSAFingerprint(string key) + { + using (var text = new StringReader(key)) + { + var reader = new PemReader(text); + var parameter = reader.ReadObject() as RsaKeyParameters; + if (parameter != null) + { + var modulus = parameter.Modulus.ToByteArray(); + var exponent = parameter.Exponent.ToByteArray(); + + if (modulus.Length > 256) + { + var corrected = new byte[256]; + Buffer.BlockCopy(modulus, modulus.Length - 256, corrected, 0, 256); + + modulus = corrected; + } + else if (modulus.Length < 256) + { + var corrected = new byte[256]; + Buffer.BlockCopy(modulus, 0, corrected, 256 - modulus.Length, modulus.Length); + + for (int a = 0; a < 256 - modulus.Length; a++) + { + modulus[a] = 0; + } + + modulus = corrected; + } + + using (var stream = new MemoryStream()) + { + var modulusString = TLString.FromBigEndianData(modulus); + var exponentString = TLString.FromBigEndianData(exponent); + + modulusString.ToStream(stream); + exponentString.ToStream(stream); + + var hash = ComputeSHA1(stream.ToArray()); + + var fingerprint = (((ulong)hash[19]) << 56) | + (((ulong)hash[18]) << 48) | + (((ulong)hash[17]) << 40) | + (((ulong)hash[16]) << 32) | + (((ulong)hash[15]) << 24) | + (((ulong)hash[14]) << 16) | + (((ulong)hash[13]) << 8) | + ((ulong)hash[12]); + + return (long)fingerprint; + } + } + } + + return -1; + } + + public static byte[] GetRSABytes(byte[] bytes, string key) + { + using (var text = new StringReader(key)) + { + var reader = new PemReader(text); + var parameter = reader.ReadObject() as RsaKeyParameters; + if (parameter != null) + { + var modulus = parameter.Modulus; + var exponent = parameter.Exponent; + + var num = new BigInteger(TLUtils.Combine(new byte[] { 0x00 }, bytes)); + var rsa = num.ModPow(exponent, modulus).ToByteArray(); + +#if LOG_REGISTRATION + TLUtils.WriteLog("RSA bytes length " + rsa.Length); +#endif + if (rsa.Length == 257) + { + if (rsa[0] != 0x00) throw new Exception("rsa last byte is " + rsa[0]); + +#if LOG_REGISTRATION + TLUtils.WriteLog("First RSA byte removes: byte value is " + rsa[0]); +#endif + + rsa = rsa.SubArray(1, 256); + } + else if (rsa.Length < 256) + { + var correctedRsa = new byte[256]; + Array.Copy(rsa, 0, correctedRsa, 256 - rsa.Length, rsa.Length); + for (var i = 0; i < 256 - rsa.Length; i++) + { + correctedRsa[i] = 0; +#if LOG_REGISTRATION + TLUtils.WriteLog("First RSA bytes added i=" + i + " " + correctedRsa[i]); +#endif + } + rsa = correctedRsa; + } + + return rsa; + } + } + + return null; + } + + private static UInt64 GetP(UInt64 data) + { + var sqrt = (UInt64)Math.Sqrt(data); + if (sqrt % 2 == 0) sqrt++; + + + for (UInt64 i = sqrt; i >= 1; i = i - 2) + { + if (data % i == 0) return i; + } + + return data; + } + + public static WindowsPhone.Tuple GetPQ(UInt64 pq) + { + var p = GetP(pq); + var q = pq / p; + + if (p > q) + { + var temp = p; + p = q; + q = temp; + } + + return new WindowsPhone.Tuple(p, q); + } + + public static WindowsPhone.Tuple GetPQPollard(UInt64 pq) + { + var n = new BigInteger(BitConverter.GetBytes(pq).Reverse().ToArray()); + var result = PollardRho.Factor(n); + return new WindowsPhone.Tuple((UInt64)result.Item1.LongValue, (UInt64)result.Item2.LongValue); + } + + public static WindowsPhone.Tuple GetFastPQ(UInt64 pq) + { + var first = FastFactor((long)pq); + var second = (long)pq / first; + + return first < second ? + new WindowsPhone.Tuple((UInt64)first, (UInt64)second) : + new WindowsPhone.Tuple((UInt64)second, (UInt64)first); + } + + public static long GCD(long a, long b) + { + while (a != 0 && b != 0) + { + while ((b & 1) == 0) + { + b >>= 1; + } + while ((a & 1) == 0) + { + a >>= 1; + } + if (a > b) + { + a -= b; + } + else + { + b -= a; + } + } + return b == 0 ? a : b; + } + + public static long FastFactor(long what) + { + Random r = new Random(); + long g = 0; + int it = 0; + for (int i = 0; i < 3; i++) + { + int q = (r.Next(128) & 15) + 17; + long x = r.Next(1000000000) + 1, y = x; + int lim = 1 << (i + 18); + for (int j = 1; j < lim; j++) + { + ++it; + long a = x, b = x, c = q; + while (b != 0) + { + if ((b & 1) != 0) + { + c += a; + if (c >= what) + { + c -= what; + } + } + a += a; + if (a >= what) + { + a -= what; + } + b >>= 1; + } + x = c; + long z = x < y ? y - x : x - y; + g = GCD(z, what); + if (g != 1) + { + break; + } + if ((j & (j - 1)) == 0) + { + y = x; + } + } + if (g > 1) + { + break; + } + } + + long p = what / g; + return Math.Min(p, g); + } + + + + + private static byte[] XorArrays(byte[] first, byte[] second) + { + var bytes = new byte[16]; + for (int i = 0; i < bytes.Length; i++) + { + bytes[i] = (byte)(first[i] ^ second[i]); + } + + return bytes; + } +#if WINDOWS_PHONE || WIN_RT + public static Stream AesIge(Stream data, byte[] key, byte[] iv, bool encrypt) + { + var cipher = CipherUtilities.GetCipher("AES/ECB/NOPADDING"); + var param = new KeyParameter(key); + cipher.Init(encrypt, param); + + var inData = data; + var outStream = new MemoryStream(); + var position = 0; + + byte[] xOld = new byte[16], yOld = new byte[16], x = new byte[16]; + + Array.Copy(iv, 0, encrypt ? yOld : xOld, 0, 16); + Array.Copy(iv, 16, encrypt ? xOld : yOld, 0, 16); + + while (position < inData.Length) + { + long length; + if ((position + 16) < inData.Length) + { + length = 16; + } + else + { + length = inData.Length - position; + } + + inData.Read(x, 0, (int)length); + //Array.Copy(inData, position, x, 0, length); + + + var processedBytes = cipher.ProcessBytes(XorArrays(x, yOld)); + byte[] y = XorArrays(processedBytes, xOld); + + xOld = (byte[])x.Clone(); + //xOld = new byte[x.Length]; + //Array.Copy(x, xOld, x.Length); + yOld = y; + + outStream.Write(y, 0, y.Length); + //outData = TLUtils.Combine(outData, y); + + position += 16; + } + return outStream; + //return outData; + } + + public static byte[] AesIge(byte[] data, byte[] key, byte[] iv, bool encrypt) + { + byte[] nextIV; + return AesIge(data, key, iv, encrypt, out nextIV); + } + +#if WIN_RT + public static byte[] AesIgeWinRT(byte[] data, byte[] key, byte[] iv, bool encrypt) + { + byte[] nextIV; + return AesIge2(data, key, iv, encrypt, out nextIV); + } + + public static byte[] AesIge2(byte[] data, byte[] key, byte[] iv, bool encrypt, out byte[] nextIV) + { + var cipher = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcb); + var keyMaterial = CryptographicBuffer.CreateFromByteArray(key); + var param = cipher.CreateSymmetricKey(keyMaterial); + + var inData = data; + //var outData = new byte[]{}; + var outStream = new MemoryStream(); + var position = 0; + + byte[] xOld = new byte[16], yOld = new byte[16], x = new byte[16], y = new byte[16]; + + Array.Copy(iv, 0, encrypt ? yOld : xOld, 0, 16); + Array.Copy(iv, 16, encrypt ? xOld : yOld, 0, 16); + + while (position < inData.Length) + { + int length; + if ((position + 16) < inData.Length) + { + length = 16; + } + else + { + length = inData.Length - position; + } + + Array.Copy(inData, position, x, 0, length); + + y = XorArrays(x, yOld); + var processedBytes = encrypt ? CryptographicEngine.Encrypt(param, CryptographicBuffer.CreateFromByteArray(y), null) : CryptographicEngine.Decrypt(param, CryptographicBuffer.CreateFromByteArray(y), null); + y = XorArrays(processedBytes.ToArray(), xOld); + + xOld = (byte[])x.Clone(); + //xOld = new byte[x.Length]; + //Array.Copy(x, xOld, x.Length); + yOld = y; + + outStream.Write(y, 0, y.Length); + //outData = TLUtils.Combine(outData, y); + + position += 16; + } + + nextIV = encrypt ? TLUtils.Combine(yOld, xOld) : TLUtils.Combine(xOld, yOld); + + return outStream.ToArray(); + //return outData; + } +#endif + + public static byte[] AesIge(byte[] data, byte[] key, byte[] iv, bool encrypt, out byte[] nextIV) + { + var cipher = CipherUtilities.GetCipher("AES/ECB/NOPADDING"); + var param = new KeyParameter(key); + cipher.Init(encrypt, param); + + var inData = data; + //var outData = new byte[]{}; + var outStream = new MemoryStream(); + var position = 0; + + byte[] xOld = new byte[16], yOld = new byte[16], x = new byte[16]; + + Array.Copy(iv, 0, encrypt ? yOld : xOld, 0, 16); + Array.Copy(iv, 16, encrypt ? xOld : yOld, 0, 16); + + while (position < inData.Length) + { + int length; + if ((position + 16) < inData.Length) + { + length = 16; + } + else + { + length = inData.Length - position; + } + + Array.Copy(inData, position, x, 0, length); + + + var processedBytes = cipher.ProcessBytes(XorArrays(x, yOld)); + byte[] y = XorArrays(processedBytes, xOld); + + xOld = (byte[])x.Clone(); + //xOld = new byte[x.Length]; + //Array.Copy(x, xOld, x.Length); + yOld = y; + + outStream.Write(y, 0, y.Length); + //outData = TLUtils.Combine(outData, y); + + position += 16; + } + + nextIV = encrypt ? TLUtils.Combine(yOld, xOld) : TLUtils.Combine(xOld, yOld); + + return outStream.ToArray(); + //return outData; + } + + private static System.Numerics.BigInteger MaxIvec = new System.Numerics.BigInteger(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); + + // Note: ivec - big-endian, but BigInterger.ctor and BigInteger.ToByteArray return little-endian + public static byte[] AES_ctr128_encrypt(byte[] input, byte[] key, ref byte[] ivec, ref byte[] ecount_buf, ref uint num) + { + uint n; + var output = new byte[input.Length]; + n = num; + + var cipher = CipherUtilities.GetCipher("AES/ECB/NOPADDING"); + var param = new KeyParameter(key); + cipher.Init(true, param); + + for (uint i = 0; i < input.Length; i++) + { + if (n == 0) + { + ecount_buf = cipher.DoFinal(ivec); + Array.Reverse(ivec); + var bi = new System.Numerics.BigInteger(TLUtils.Combine(ivec, new byte[] { 0x00 })); + bi = (bi + 1); + var biArray = bi.ToByteArray(); + var b = new byte[16]; + Buffer.BlockCopy(biArray, 0, b, 0, Math.Min(b.Length, biArray.Length)); + + //System.Diagnostics.Debug.WriteLine(bi); + Array.Reverse(b); + ivec = b; + } + + output[i] = (byte)(input[i] ^ ecount_buf[n]); + n = (n + 1) % 16; + } + + num = n; + return output; + } + + public static byte[] AES_ctr128_encrypt2(byte[] input, byte[] key, ref byte[] ivec, ref byte[] ecount_buf, ref uint num) + { + uint n; + var output = new byte[input.Length]; + n = num; + + var cipher = CipherUtilities.GetCipher("AES/ECB/NOPADDING"); + var param = new KeyParameter(key); + cipher.Init(true, param); + + for (uint i = 0; i < input.Length; i++) + { + if (n == 0) + { + ecount_buf = cipher.DoFinal(ivec); + Array.Reverse(ivec); + var bi = new System.Numerics.BigInteger(TLUtils.Combine(ivec, new byte[] { 0x00 })); + bi = (bi + 1); + var biArray = bi.ToByteArray(); + var b = new byte[16]; + Buffer.BlockCopy(biArray, 0, b, 0, Math.Min(b.Length, biArray.Length)); + + //System.Diagnostics.Debug.WriteLine(bi); + Array.Reverse(b); + ivec = b; + } + + output[i] = (byte)(input[i] ^ ecount_buf[n]); + n = (n + 1) % 16; + } + + num = n; + return output; + } + + //public static byte[] AesCtr(byte[] data, byte[] key, byte[] iv, bool encrypt) + //{ + // var cipher = CipherUtilities.GetCipher("AES/CTR/NOPADDING"); + // var keyIv = new ParametersWithIV(new KeyParameter(key), iv); + // cipher.Init(encrypt, keyIv); + // //cipher.Init(encrypt, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", key), iv)); + + // var outData = cipher.DoFinal(data); + // if (outData.Length != data.Length) + // { + // Execute.ShowDebugMessage(string.Format("Utils.AesCtr outData.Length!=data.Length outData={0} data={1}", outData.Length, data.Length)); + // } + + // return outData; + //} +#else + public static byte[] AesIge(byte[] data, byte[] key, byte[] iv, bool encrypt) + { + throw new NotImplementedException(); + } + + public static byte[] AesCtr(byte[] data, byte[] key, byte[] iv, bool encrypt) + { + var cipher = CipherUtilities.GetCipher("AES/CTR/NOPADDING"); + cipher.Init(encrypt, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", key), iv)); + + var outData = cipher.DoFinal(data); + if (outData.Length != data.Length) + { + Execute.ShowDebugMessage(string.Format("Utils.AesCtr outData.Length!=data.Length outData={0} data={1}", outData.Length, data.Length)); + } + + return outData; + } +#endif + + public static byte[] StringToByteArray(String hex) + { + int NumberChars = hex.Length / 2; + byte[] bytes = new byte[NumberChars]; + StringReader sr = new StringReader(hex); + for (int i = 0; i < NumberChars; i++) + bytes[i] = Convert.ToByte(new string(new char[2] { (char)sr.Read(), (char)sr.Read() }), 16); + sr.Dispose(); + return bytes; + } + + public static T[] SubArray(this T[] data, int index, int length) + { + if (index == 0 && length == data.Length) + { + return data; + } + + var result = new T[length]; + Array.Copy(data, index, result, 0, length); + return result; + } + + public static double DateTimeToUnixTimestamp(DateTime dateTime) + { + // From local DateTime to UTC0 UnixTime + + var dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0); + DateTime.SpecifyKind(dtDateTime, DateTimeKind.Utc); + + return (dateTime.ToUniversalTime() - dtDateTime).TotalSeconds; + } + + public static DateTime UnixTimestampToDateTime(double unixTimeStamp) + { + // From UTC0 UnixTime to local DateTime + + var dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0); + DateTime.SpecifyKind(dtDateTime, DateTimeKind.Utc); + + dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime(); + return dtDateTime; + } + + public static byte[] ComputeSHA1(byte[] data) + { +#if WINDOWS_PHONE + //var sha1 = new SHA1Managed(); // to avoid thread sync problems http://stackoverflow.com/questions/12644257/sha1managed-computehash-occasionally-different-on-different-servers + //return sha1.ComputeHash(data); + var sha1 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha1); + return sha1.HashData(data.AsBuffer()).ToArray(); +#elif WIN_RT + var sha1 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha1); + return sha1.HashData(data.AsBuffer()).ToArray(); +#endif + } + + public static byte[] ComputeSHA256(byte[] data) + { +#if WINDOWS_PHONE + //var sha256 = new SHA256Managed(); // to avoid thread sync problems http://stackoverflow.com/questions/12644257/sha1managed-computehash-occasionally-different-on-different-servers + //return sha256.ComputeHash(data); + var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); + return sha256.HashData(data.AsBuffer()).ToArray(); +#elif WIN_RT + var sha1 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); + return sha1.HashData(data.AsBuffer()).ToArray(); +#endif + } + + public static byte[] ComputeMD5(byte[] data) + { +#if WINDOWS_PHONE + //var md5 = new MD5Managed(); + //return md5.ComputeHash(data); + var md5 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5); + return md5.HashData(data.AsBuffer()).ToArray(); +#elif WIN_RT + var md5 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5); + return md5.HashData(data.AsBuffer()).ToArray(); +#endif + } + + public static byte[] ComputeCRC32(string data) + { + byte[] utf16Bytes = Encoding.Unicode.GetBytes(data); + byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes); + + return ComputeCRC32(utf8Bytes); + } + + public static byte[] ComputeCRC32(byte[] data) + { + var crc = new CRC32(); + var hash = crc.ComputeHash(data); + + return hash; + } + + public static string CurrentUICulture() + { +#if WIN_RT + return Windows.Globalization.Language.CurrentInputMethodLanguageTag; +#elif WINDOWS_PHONE + return Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName; +#endif + } + } +} diff --git a/Telegram.Api/Logs/Log.cs b/Telegram.Api/Logs/Log.cs new file mode 100755 index 0000000..fabbe17 --- /dev/null +++ b/Telegram.Api/Logs/Log.cs @@ -0,0 +1,128 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.IO; +using System.Text; +using System.Threading; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Execute = Telegram.Api.Helpers.Execute; + +namespace Telegram.Logs +{ + public class Log + { + public static bool IsPrivateBeta + { + get + { +#if DEBUG + return true; +#endif +#if WP81 + return Windows.ApplicationModel.Package.Current.Id.Name == "TelegramMessengerLLP.TelegramMessengerPreview"; +#endif + return true; + } + } + + public static bool WriteSync { get; set; } + + public static bool IsEnabled + { + get { return IsPrivateBeta; } + } + + public static void Write(string str, Action callback = null) + { + if (!IsEnabled) + { + return; + } + + if (WriteSync) + { + WriteInternal(str, callback); + } + else + { + Execute.BeginOnThreadPool(() => + { + WriteInternal(str, callback); + }); + } + } + + public static void SyncWrite(string str, Action callback = null) + { + if (!IsEnabled) + { + return; + } + + //if (WriteSync) + { + WriteInternal(str, callback); + } + } + + private static readonly object _fileSyncRoot = new object(); + + private static void WriteInternal(string str, Action callback = null) + { + var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture); + + str = string.Format("{0} {1}{2}", timestamp, str, Environment.NewLine); + using (var mutex = new Mutex(false, "Telegram.Log")) + { + mutex.WaitOne(); + FileUtils.Write(_fileSyncRoot, DirectoryName, FileName, str); + mutex.ReleaseMutex(); + } + callback.SafeInvoke(); + } + + private const string DirectoryName = "Logs"; + + public static string FileName + { + get { return DateTime.Now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt"; } + } + + public static void CopyTo(string fileName, Action callback) + { + Execute.BeginOnThreadPool(() => + { + using (var mutex = new Mutex(false, "Telegram.Log")) + { + mutex.WaitOne(); + FileUtils.CopyLog(_fileSyncRoot, DirectoryName, FileName, fileName, IsEnabled); + mutex.ReleaseMutex(); + } + + callback.SafeInvoke(fileName); + }); + } + + public static void Clear(Action callback) + { + Execute.BeginOnThreadPool(() => + { + using (var mutex = new Mutex(false, "Telegram.Log")) + { + mutex.WaitOne(); + FileUtils.Clear(_fileSyncRoot, DirectoryName); + mutex.ReleaseMutex(); + } + + callback.SafeInvoke(); + }); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Properties/AssemblyInfo.cs b/Telegram.Api/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..7376e96 --- /dev/null +++ b/Telegram.Api/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("Telegram.Api")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Telegram.Api")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[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("0c2f1b61-a8fe-45fb-8538-aa6925a415b6")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en")] diff --git a/Telegram.Api/Services/Cache/Context.cs b/Telegram.Api/Services/Cache/Context.cs new file mode 100755 index 0000000..867fdb5 --- /dev/null +++ b/Telegram.Api/Services/Cache/Context.cs @@ -0,0 +1,42 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; + +namespace Telegram.Api.Services.Cache +{ + public class Context : Dictionary + { + public Context() + { + + } + + public Context(IEnumerable items, Func keyFunc) + { + foreach (var item in items) + { + this[keyFunc(item)] = item; + } + } + + public new T this[long index] + { + get + { + T val; + return TryGetValue(index, out val) ? val : default(T); + } + + set + { + base[index] = value; + } + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/Cache/EventArgs/DialogAddedEventArgs.cs b/Telegram.Api/Services/Cache/EventArgs/DialogAddedEventArgs.cs new file mode 100755 index 0000000..0737778 --- /dev/null +++ b/Telegram.Api/Services/Cache/EventArgs/DialogAddedEventArgs.cs @@ -0,0 +1,72 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Cache.EventArgs +{ + public class MessagesRemovedEventArgs + { + public TLDialogBase Dialog { get; protected set; } + + public IList Messages { get; protected set; } + + public TLDecryptedMessageBase DecryptedMessage { get; protected set; } + + public MessagesRemovedEventArgs(TLDialogBase dialog, TLMessageBase message) + { + Dialog = dialog; + Messages = new List {message}; + } + + public MessagesRemovedEventArgs(TLDialogBase dialog, IList messages) + { + Dialog = dialog; + Messages = messages; + } + + public MessagesRemovedEventArgs(TLDialogBase dialog, TLDecryptedMessageBase message) + { + Dialog = dialog; + DecryptedMessage = message; + } + } + + public class DialogAddedEventArgs + { + public TLDialogBase Dialog { get; protected set; } + + public DialogAddedEventArgs(TLDialogBase dialog) + { + Dialog = dialog; + } + } + + public class DialogRemovedEventArgs + { + public TLDialogBase Dialog { get; protected set; } + + public DialogRemovedEventArgs(TLDialogBase dialog) + { + Dialog = dialog; + } + } + + public class ChannelAvailableMessagesEventArgs + { + public TLDialogBase Dialog { get; protected set; } + + public TLInt AvailableMinId { get; set; } + + public ChannelAvailableMessagesEventArgs(TLDialogBase dialog, TLInt availableMinId) + { + Dialog = dialog; + AvailableMinId = availableMinId; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/Cache/EventArgs/TopMessageUpdatedEventArgs.cs b/Telegram.Api/Services/Cache/EventArgs/TopMessageUpdatedEventArgs.cs new file mode 100755 index 0000000..d4e4e22 --- /dev/null +++ b/Telegram.Api/Services/Cache/EventArgs/TopMessageUpdatedEventArgs.cs @@ -0,0 +1,41 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Cache.EventArgs +{ + public class TopMessageUpdatedEventArgs : System.EventArgs + { + public TLPeerBase Peer { get; protected set; } + + public TLDialogBase Dialog { get; protected set; } + + public TLMessageBase Message { get; protected set; } + + public TLDecryptedMessageBase DecryptedMessage { get; protected set; } + + public bool NotifyPinned { get; set; } + + public TopMessageUpdatedEventArgs(TLPeerBase peer) + { + Peer = peer; + } + + public TopMessageUpdatedEventArgs(TLDialogBase dialog, TLMessageBase message) + { + Dialog = dialog; + Message = message; + } + + public TopMessageUpdatedEventArgs(TLDialogBase dialog, TLDecryptedMessageBase message) + { + Dialog = dialog; + DecryptedMessage = message; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/Cache/ICacheService.cs b/Telegram.Api/Services/Cache/ICacheService.cs new file mode 100755 index 0000000..453af58 --- /dev/null +++ b/Telegram.Api/Services/Cache/ICacheService.cs @@ -0,0 +1,153 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Cache +{ + public interface ICacheService + { + ExceptionInfo LastSyncMessageException { get; } + + void ClearLocalFileNames(); + void CompressAsync(Action callback); + void Commit(); + bool TryCommit(); + void SaveSnapshot(string toDirectoryName); + void SaveTempSnapshot(string toDirectoryName); + void LoadSnapshot(string fromDirectoryName); + //event EventHandler DialogAdded; + //event EventHandler TopMessageUpdated; + + TLUserBase GetUser(TLInt id); + TLUserBase GetUser(string username); + TLUserBase GetUser(TLUserProfilePhoto photo); + TLMessageBase GetMessage(TLInt id, TLInt channelId = null); + TLMessageBase GetMessage(TLLong randomId); + TLMessageBase GetMessage(TLWebPageBase webPage); + TLDecryptedMessageBase GetDecryptedMessage(TLInt chatId, TLLong randomId); + TLDialog GetDialog(TLMessageCommon message); + TLDialog GetDialog(TLPeerBase peer); + TLDialogBase GetEncryptedDialog(TLInt chatId); + + TLChat GetChat(TLChatPhoto chatPhoto); + TLChannel GetChannel(string username); + TLChannel GetChannel(TLChatPhoto channelPhoto); + TLChatBase GetChat(TLInt id); + TLBroadcastChat GetBroadcast(TLInt id); + + IList GetMessages(); + IList GetSendingMessages(); + IList GetResendingMessages(); + + void GetHistoryAsync(TLPeerBase peer, Action> callback, int limit = Constants.CachedMessagesCount); + IList GetHistory(TLPeerBase peer, int limit = Constants.CachedMessagesCount); + IList GetHistory(TLPeerBase peer, int maxId, int limit = Constants.CachedMessagesCount); + //IList GetUnreadHistory(TLInt currentUserId, TLPeerBase peer, int limit = Constants.CachedMessagesCount); + IList GetHistory(int dialogId); + IList GetDecryptedHistory(int dialogId, int limit = Constants.CachedMessagesCount); + IList GetDecryptedHistory(int dialogId, long randomId, int limit = Constants.CachedMessagesCount); + IList GetUnreadDecryptedHistory(int dialogId); + void GetDialogsAsync(Action> callback); + IList GetDialogs(); + void GetContactsAsync(Action> callback); + + List GetContacts(); + List GetUsersForSearch(IList nonCachedDialogs); + List GetUsers(); + List GetChats(); + void GetChatsAsync(Action> callback); + + + void ClearAsync(Action callback = null); + void SyncMessage(TLMessageBase message, Action callback); + void SyncMessage(TLMessageBase message, bool notifyNewDialog, bool notifyTopMessageUpdated, Action callback); + void SyncEditedMessage(TLMessageBase message, bool notifyNewDialog, bool notifyTopMessageUpdated, Action callback); + void SyncSendingMessage(TLMessageCommon message, TLMessageBase previousMessage, Action callback); + void SyncSendingMessages(IList messages, TLMessageBase previousMessage, Action> callback); + void SyncSendingMessageId(TLLong randomId, TLInt id, Action callback); + void SyncPeerMessages(TLPeerBase peer, TLMessagesBase messages, bool notifyNewDialog, bool notifyTopMessageUpdated, Action callback); + void AddMessagesToContext(TLMessagesBase messages, Action callback); + void SyncDialogs(Stopwatch stopwatch, TLDialogsBase dialogs, Action callback); + void SyncProxyData(TLProxyDataBase proxyData, Action callback); + void SyncChannelDialogs(TLDialogsBase dialogs, Action callback); + void MergeMessagesAndChannels(TLDialogsBase dialogs); + void SyncUser(TLUserBase user, Action callback); + void SyncUser(TLUserFull userFull, Action callback); + void SyncUsers(TLVector users, Action> callback); + void AddUsers(TLVector users, Action> callback); + void SyncUsersAndChats(TLVector users, TLVector chats, Action, TLVector>> callback); + void SyncUserLink(TLLinkBase link, Action callback); + void SyncContacts(TLContactsBase contacts, Action callback); + void SyncContacts(TLImportedContacts contacts, Action callback); + + void ClearDialog(TLPeerBase peer); + void DeleteDialog(TLDialogBase dialog); + void DeleteMessages(TLVector ids); + void DeleteChannelMessages(TLInt channelId, TLVector ids); + void DeleteMessages(TLPeerBase peer, TLMessageBase lastItem, TLVector messages); + void DeleteMessages(TLVector ids); + void DeleteDecryptedMessages(TLVector ids); + void ClearDecryptedHistoryAsync(TLInt chatId); + void ClearBroadcastHistoryAsync(TLInt chatId); + + void SyncStatedMessage(TLStatedMessageBase statedMessage, Action callback); + void SyncStatedMessages(TLStatedMessagesBase statedMessages, Action callback); + + void GetConfigAsync(Action config); + TLConfig GetConfig(); + void SetConfig(TLConfig config); + + void GetCdnConfigAsync(Action cdnConfig); + TLCdnConfig GetCdnConfig(); + void SetCdnCofig(TLCdnConfig cdnConfig); + + void ClearConfigImportAsync(); + void SyncChat(TLMessagesChatFull messagesChatFull, Action callback); + void AddChats(TLVector chats, Action> callback); + void SyncBroadcast(TLBroadcastChat broadcast, Action callback); + + TLEncryptedChatBase GetEncryptedChat(TLInt id); + void SyncEncryptedChat(TLEncryptedChatBase encryptedChat, Action callback); + void SyncDecryptedMessage(TLDecryptedMessageBase message, TLEncryptedChatBase peer, Action callback); + void SyncDecryptedMessages(IList> tuples, TLEncryptedChatBase peer, Action>> callback); + void SyncSendingDecryptedMessage(TLInt chatId, TLInt date, TLLong randomId, Action callback); + + void Init(); + + void SyncDifference(TLDifference difference, Action result, IList exceptions); + void SyncDifferenceWithoutUsersAndChats(TLDifference difference, Action result, IList exceptions); + void SyncStatuses(TLVector contacts, Action> callback); + void DeleteUser(TLInt id); + void DeleteChat(TLInt id); + void DeleteUserHistory(TLPeerChannel channel, TLPeerUser peer); + + void UpdateDialogPinned(TLPeerBase peer, bool pinned); + void UpdatePinnedDialogs(TLVector order); + void UpdateChannelAvailableMessages(TLInt channelId, TLInt availableMinId); + void UpdateDialogPromo(TLDialogBase dialogBase, bool promo); + TLProxyDataBase GetProxyData(); + void UpdateProxyData(TLProxyDataBase proxyData); + } + + public class ExceptionInfo + { + public Exception Exception { get; set; } + + public DateTime Timestamp { get; set; } + + public string Caption { get; set; } + + public override string ToString() + { + return string.Format("Caption={2}\nTimestamp={0}\nException={1}", Timestamp, Exception, Caption); + } + } +} diff --git a/Telegram.Api/Services/Cache/InMemoryCacheService.cs b/Telegram.Api/Services/Cache/InMemoryCacheService.cs new file mode 100755 index 0000000..6967893 --- /dev/null +++ b/Telegram.Api/Services/Cache/InMemoryCacheService.cs @@ -0,0 +1,4111 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.Services.Cache.EventArgs; +using Telegram.Api.Services.Updates; +using Telegram.Api.TL; +using Action = System.Action; + + +namespace Telegram.Api.Services.Cache +{ + public class MockupCacheService : ICacheService + { + public ExceptionInfo LastSyncMessageException { get; private set; } + + public void SyncProxyData(TLProxyDataBase proxyData, Action callback) + { + throw new NotImplementedException(); + } + + public void ClearLocalFileNames() + { + + } + + public void CompressAsync(Action callback) + { + callback.SafeInvoke(); + } + + public void Commit() + { + + } + + public bool TryCommit() + { + return true; + } + + public void SaveSnapshot(string toDirectoryName) + { + + } + + public void SaveTempSnapshot(string toDirectoryName) + { + + } + + public void LoadSnapshot(string fromDirectoryName) + { + + } + + public TLUserBase GetUser(TLInt id) + { + throw new NotImplementedException(); + } + + public TLUserBase GetUser(string username) + { + throw new NotImplementedException(); + } + + public TLUserBase GetUser(TLUserProfilePhoto photo) + { + throw new NotImplementedException(); + } + + public TLMessageBase GetMessage(TLInt id, TLInt channelId = null) + { + throw new NotImplementedException(); + } + + public TLMessageBase GetMessage(TLLong randomId) + { + throw new NotImplementedException(); + } + + public TLMessageBase GetMessage(TLWebPageBase webPage) + { + throw new NotImplementedException(); + } + + public TLDecryptedMessageBase GetDecryptedMessage(TLInt chatId, TLLong randomId) + { + throw new NotImplementedException(); + } + + public TLDialog GetDialog(TLMessageCommon message) + { + throw new NotImplementedException(); + } + + public TLDialog GetDialog(TLPeerBase peer) + { + throw new NotImplementedException(); + } + + public TLDialogBase GetEncryptedDialog(TLInt chatId) + { + throw new NotImplementedException(); + } + + public TLChat GetChat(TLChatPhoto chatPhoto) + { + throw new NotImplementedException(); + } + + public TLChannel GetChannel(string username) + { + throw new NotImplementedException(); + } + + public TLChannel GetChannel(TLChatPhoto channelPhoto) + { + throw new NotImplementedException(); + } + + public TLChatBase GetChat(TLInt id) + { + throw new NotImplementedException(); + } + + public TLBroadcastChat GetBroadcast(TLInt id) + { + throw new NotImplementedException(); + } + + public IList GetMessages() + { + throw new NotImplementedException(); + } + + public IList GetSendingMessages() + { + throw new NotImplementedException(); + } + + public IList GetResendingMessages() + { + throw new NotImplementedException(); + } + + public void GetHistoryAsync(TLPeerBase peer, Action> callback, int limit = Constants.CachedMessagesCount) + { + callback.SafeInvoke(null); + } + + public IList GetHistory(TLPeerBase peer, int limit = Constants.CachedMessagesCount) + { + throw new NotImplementedException(); + } + + public IList GetHistory(TLPeerBase peer, int maxId, int limit = Constants.CachedMessagesCount) + { + throw new NotImplementedException(); + } + + public IList GetHistory(int dialogId) + { + throw new NotImplementedException(); + } + + public IList GetDecryptedHistory(int dialogId, int limit = Constants.CachedMessagesCount) + { + throw new NotImplementedException(); + } + + public IList GetDecryptedHistory(int dialogId, long randomId, int limit = Constants.CachedMessagesCount) + { + throw new NotImplementedException(); + } + + public IList GetUnreadDecryptedHistory(int dialogId) + { + throw new NotImplementedException(); + } + + public void GetDialogsAsync(Action> callback) + { + throw new NotImplementedException(); + } + + public IList GetDialogs() + { + throw new NotImplementedException(); + } + + public void GetContactsAsync(Action> callback) + { + throw new NotImplementedException(); + } + + public List GetContacts() + { + throw new NotImplementedException(); + } + + public List GetUsersForSearch(IList nonCachedDialogs) + { + throw new NotImplementedException(); + } + + public List GetUsers() + { + throw new NotImplementedException(); + } + + public List GetChats() + { + throw new NotImplementedException(); + } + + public void GetChatsAsync(Action> callback) + { + throw new NotImplementedException(); + } + + public void ClearAsync(Action callback = null) + { + throw new NotImplementedException(); + } + + public void SyncMessage(TLMessageBase message, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncMessage(TLMessageBase message, bool notifyNewDialog, bool notifyTopMessageUpdated, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncEditedMessage(TLMessageBase message, bool notifyNewDialog, bool notifyTopMessageUpdated, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncSendingMessage(TLMessageCommon message, TLMessageBase previousMessage, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncSendingMessages(IList messages, TLMessageBase previousMessage, Action> callback) + { + throw new NotImplementedException(); + } + + public void SyncSendingMessageId(TLLong randomId, TLInt id, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncPeerMessages(TLPeerBase peer, TLMessagesBase messages, bool notifyNewDialog, bool notifyTopMessageUpdated, + Action callback) + { + throw new NotImplementedException(); + } + + public void AddMessagesToContext(TLMessagesBase messages, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncDialogs(Stopwatch stopwatch, TLDialogsBase dialogs, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncChannelDialogs(TLDialogsBase dialogs, Action callback) + { + throw new NotImplementedException(); + } + + public void MergeMessagesAndChannels(TLDialogsBase dialogs) + { + throw new NotImplementedException(); + } + + public void SyncUser(TLUserBase user, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncUser(TLUserFull userFull, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncUsers(TLVector users, Action> callback) + { + throw new NotImplementedException(); + } + + public void AddUsers(TLVector users, Action> callback) + { + throw new NotImplementedException(); + } + + public void SyncUsersAndChats(TLVector users, TLVector chats, Action, TLVector>> callback) + { + throw new NotImplementedException(); + } + + public void SyncUserLink(TLLinkBase link, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncContacts(TLContactsBase contacts, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncContacts(TLImportedContacts contacts, Action callback) + { + throw new NotImplementedException(); + } + + public void ClearDialog(TLPeerBase peer) + { + throw new NotImplementedException(); + } + + public void DeleteDialog(TLDialogBase dialog) + { + throw new NotImplementedException(); + } + + public void DeleteMessages(TLVector ids) + { + throw new NotImplementedException(); + } + + public void DeleteChannelMessages(TLInt channelId, TLVector ids) + { + throw new NotImplementedException(); + } + + public void DeleteMessages(TLPeerBase peer, TLMessageBase lastItem, TLVector messages) + { + throw new NotImplementedException(); + } + + public void DeleteMessages(TLVector ids) + { + throw new NotImplementedException(); + } + + public void DeleteDecryptedMessages(TLVector ids) + { + throw new NotImplementedException(); + } + + public void ClearDecryptedHistoryAsync(TLInt chatId) + { + throw new NotImplementedException(); + } + + public void ClearBroadcastHistoryAsync(TLInt chatId) + { + throw new NotImplementedException(); + } + + public void SyncStatedMessage(TLStatedMessageBase statedMessage, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncStatedMessages(TLStatedMessagesBase statedMessages, Action callback) + { + throw new NotImplementedException(); + } + + private TLCdnConfig _cdnConfig; + + private readonly object _cdnConfigSyncRoot = new object(); + + public void GetCdnConfigAsync(Action callback) + { + if (_cdnConfig == null) + { + _cdnConfig = TLUtils.OpenObjectFromMTProtoFile(_cdnConfigSyncRoot, Constants.CdnConfigFileName); + } + + callback.SafeInvoke(_cdnConfig); + } + + public TLCdnConfig GetCdnConfig() + { + if (_cdnConfig == null) + { + _cdnConfig = TLUtils.OpenObjectFromMTProtoFile(_cdnConfigSyncRoot, Constants.CdnConfigFileName); + } + + return _cdnConfig; + } + + public void SetCdnCofig(TLCdnConfig cdnConfig) + { + _cdnConfig = cdnConfig; + + TLUtils.SaveObjectToMTProtoFile(_cdnConfigSyncRoot, Constants.CdnConfigFileName, _cdnConfig); + } + + private TLConfig _config; + + public TLConfig GetConfig() + { +#if SILVERLIGHT || WIN_RT + if (_config == null) + { + _config = SettingsHelper.GetValue(Constants.ConfigKey) as TLConfig; + } +#endif + return _config; + } + + + public void GetConfigAsync(Action callback) + { +#if SILVERLIGHT || WIN_RT + if (_config == null) + { + _config = SettingsHelper.GetValue(Constants.ConfigKey) as TLConfig; + } +#endif + callback.SafeInvoke(_config); + } + + public void SetConfig(TLConfig config) + { + _config = config; +#if SILVERLIGHT || WIN_RT + SettingsHelper.SetValue(Constants.ConfigKey, config); +#endif + } + + public void ClearConfigImportAsync() + { + throw new NotImplementedException(); + } + + public void SyncChat(TLMessagesChatFull messagesChatFull, Action callback) + { + throw new NotImplementedException(); + } + + public void AddChats(TLVector chats, Action> callback) + { + throw new NotImplementedException(); + } + + public void SyncBroadcast(TLBroadcastChat broadcast, Action callback) + { + throw new NotImplementedException(); + } + + public TLEncryptedChatBase GetEncryptedChat(TLInt id) + { + throw new NotImplementedException(); + } + + public void SyncEncryptedChat(TLEncryptedChatBase encryptedChat, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncDecryptedMessage(TLDecryptedMessageBase message, TLEncryptedChatBase peer, Action callback) + { + throw new NotImplementedException(); + } + + public void SyncDecryptedMessages(IList> tuples, TLEncryptedChatBase peer, Action>> callback) + { + throw new NotImplementedException(); + } + + public void SyncSendingDecryptedMessage(TLInt chatId, TLInt date, TLLong randomId, Action callback) + { + throw new NotImplementedException(); + } + + public void Init() + { + throw new NotImplementedException(); + } + + public void SyncDifference(TLDifference difference, Action result, IList exceptions) + { + throw new NotImplementedException(); + } + + public void SyncDifferenceWithoutUsersAndChats(TLDifference difference, Action result, IList exceptions) + { + throw new NotImplementedException(); + } + + public void SyncStatuses(TLVector contacts, Action> callback) + { + throw new NotImplementedException(); + } + + public void DeleteUser(TLInt id) + { + throw new NotImplementedException(); + } + + public void DeleteChat(TLInt id) + { + throw new NotImplementedException(); + } + + public void DeleteUserHistory(TLPeerChannel channel, TLPeerUser peer) + { + throw new NotImplementedException(); + } + + public void UpdateDialogPinned(TLPeerBase peer, bool pinned) + { + throw new NotImplementedException(); + } + + public void UpdatePinnedDialogs(TLVector order) + { + throw new NotImplementedException(); + } + + public void UpdateChannelAvailableMessages(TLInt channelId, TLInt availableMinId) + { + throw new NotImplementedException(); + } + + public void UpdateDialogPromo(TLDialogBase dialogBase, bool promo) + { + throw new NotImplementedException(); + } + + public TLProxyDataBase GetProxyData() + { + throw new NotImplementedException(); + } + + public void UpdateProxyData(TLProxyDataBase proxyData) + { + throw new NotImplementedException(); + } + } + + public class InMemoryCacheService : ICacheService + { + private readonly object _databaseSyncRoot = new object(); + + private InMemoryDatabase _database; + + private Context UsersContext + { + get { return _database != null ? _database.UsersContext : null; } + } + + private Context ChatsContext + { + get { return _database != null ? _database.ChatsContext : null; } + } + + private Context BroadcastsContext + { + get { return _database != null ? _database.BroadcastsContext : null; } + } + + private Context EncryptedChatsContext + { + get { return _database != null ? _database.EncryptedChatsContext : null; } + } + + private Context MessagesContext + { + get { return _database != null ? _database.MessagesContext : null; } + } + + private Context> ChannelsContext + { + get { return _database != null ? _database.ChannelsContext : null; } + } + + private Context DecryptedMessagesContext + { + get { return _database != null ? _database.DecryptedMessagesContext : null; } + } + + private Context RandomMessagesContext + { + get { return _database != null ? _database.RandomMessagesContext : null; } + } + + private Context DialogsContext + { + get { return _database != null ? _database.DialogsContext : null; } + } + + public void Init() + { + var stopwatch = Stopwatch.StartNew(); + + _database = new InMemoryDatabase(_eventAggregator); + _database.Open(); + + Debug.WriteLine("{0} {1}", stopwatch.Elapsed, "open database time"); + } + + private readonly ITelegramEventAggregator _eventAggregator; + + public static ICacheService Instance { get; protected set; } + + public InMemoryCacheService(ITelegramEventAggregator eventAggregator) + { + _eventAggregator = eventAggregator; + + Instance = this; + } + + public IList GetDialogs() + { + var result = new List(); + + if (_database == null) Init(); + + if (DialogsContext == null) + { + + return result; + } + var timer = Stopwatch.StartNew(); + + IList dialogs = new List(); + + try + { + dialogs = new List(_database.Dialogs); + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteLine(e.ToString(), LogSeverity.Error); + } + + TLUtils.WritePerformance(string.Format("GetCachedDialogs time ({0} from {1}): {2}", dialogs.Count, _database.CountRecords(), timer.Elapsed)); + return dialogs.OrderByDescending(x => x.GetDateIndex()).ToList(); + } + + + public void GetDialogsAsync(Action> callback) + { + Execute.BeginOnThreadPool( + () => + { + var result = new List(); + + if (_database == null) Init(); + + if (DialogsContext == null) + { + callback(result); + return; + } + var timer = Stopwatch.StartNew(); + + IList dialogs = new List(); + + try + { + dialogs = new List(_database.Dialogs); + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteLine(e.ToString(), LogSeverity.Error); + } + + TLUtils.WritePerformance(string.Format("GetCachedDialogs time ({0} from {1}): {2}", dialogs.Count, _database.CountRecords(), timer.Elapsed)); + callback(dialogs.OrderByDescending(x => x.GetDateIndex()).ToList()); + }); + } + + public List GetUsers() + { + var result = new List(); + + if (_database == null) Init(); + + if (UsersContext == null) + { + return result; + } + var timer = Stopwatch.StartNew(); + + var contacts = new List(); + + try + { + contacts = _database.UsersContext.Values.ToList(); + + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + TLUtils.WritePerformance(string.Format("GetCachedContacts time ({0} from {1}): {2}", contacts.Count, _database.CountRecords(), timer.Elapsed)); + return contacts; + } + + public List GetContacts() + { + var result = new List(); + + if (_database == null) Init(); + + if (UsersContext == null) + { + return result; + } + var timer = Stopwatch.StartNew(); + + var contacts = new List(); + + try + { + contacts = _database.UsersContext.Values.Where(x => x != null && (x.IsContact || x.IsSelf)).ToList(); + //contacts = _database.UsersContext.Values.Where(x => x.Contact != null).ToList(); + + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + TLUtils.WritePerformance(string.Format("GetCachedContacts time ({0} from {1}): {2}", contacts.Count, _database.CountRecords(), timer.Elapsed)); + return contacts; + } + + public List GetUsersForSearch(IList nonCachedDialogs) + { + var result = new List(); + + if (_database == null) Init(); + + if (UsersContext == null) + { + return result; + } + + var contacts = new List(); + try + { + var usersCache = new Dictionary(); + + if (nonCachedDialogs != null) + { + for (var i = 0; i < nonCachedDialogs.Count; i++) + { + var dialog = nonCachedDialogs[i] as TLDialog; + if (dialog != null) + { + var user = nonCachedDialogs[i].With as TLUserBase; + if (user != null) + { + if (!usersCache.ContainsKey(user.Index)) + { + usersCache[user.Index] = user.Index; + contacts.Add(user); + } + } + } + } + } + + var dialogs = new List(_database.Dialogs); + + for (var i = 0; i < dialogs.Count; i++) + { + var dialog = dialogs[i] as TLDialog; + if (dialog != null) + { + var user = dialogs[i].With as TLUserBase; + if (user != null) + { + if (!usersCache.ContainsKey(user.Index)) + { + usersCache[user.Index] = user.Index; + contacts.Add(user); + } + } + } + } + + var unsortedContacts = _database.UsersContext.Values.Where(x => x != null && x.IsContact).ToList(); + for (var i = 0; i < unsortedContacts.Count; i++) + { + var user = unsortedContacts[i]; + if (!usersCache.ContainsKey(user.Index)) + { + usersCache[user.Index] = user.Index; + contacts.Add(user); + } + } + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + return contacts; + } + + public void GetContactsAsync(Action> callback) + { + Execute.BeginOnThreadPool( + () => + { + var result = new List(); + + if (_database == null) Init(); + + if (UsersContext == null) + { + callback(result); + return; + } + var timer = Stopwatch.StartNew(); + + IList contacts = new List(); + + try + { + contacts = _database.UsersContext.Values.Where(x => x != null && x.IsContact).ToList(); + //contacts = _database.UsersContext.Values.Where(x => x.Contact != null).ToList(); + + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + TLUtils.WritePerformance(string.Format("GetCachedContacts time ({0} from {1}): {2}", contacts.Count, _database.CountRecords(), timer.Elapsed)); + callback(contacts); + }); + } + + public List GetChats() + { + var result = new List(); + + if (_database == null) Init(); + + if (ChatsContext == null) + { + return result; + } + var timer = Stopwatch.StartNew(); + + IList chats = new List(); + + try + { + result = _database.ChatsContext.Values.ToList(); + + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + TLUtils.WritePerformance(string.Format("GetCachedChats time ({0} from {1}): {2}", chats.Count, _database.CountRecords(), timer.Elapsed)); + + return result; + } + + public void GetChatsAsync(Action> callback) + { + Execute.BeginOnThreadPool( + () => + { + var result = new List(); + + if (_database == null) Init(); + + if (ChatsContext == null) + { + callback(result); + return; + } + var timer = Stopwatch.StartNew(); + + IList chats = new List(); + + try + { + chats = _database.ChatsContext.Values.ToList(); + + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + TLUtils.WritePerformance(string.Format("GetCachedChats time ({0} from {1}): {2}", chats.Count, _database.CountRecords(), timer.Elapsed)); + callback(chats); + }); + } + + public TLChatBase GetChat(TLInt id) + { + if (_database == null) + { + Init(); + } + + return ChatsContext[id.Value]; + } + + public TLBroadcastChat GetBroadcast(TLInt id) + { + if (_database == null) + { + Init(); + } + + return BroadcastsContext[id.Value]; + } + + public TLEncryptedChatBase GetEncryptedChat(TLInt id) + { + if (_database == null) + { + Init(); + } + + return EncryptedChatsContext[id.Value]; + } + + public TLUserBase GetUser(TLInt id) + { + if (_database == null) + { + Init(); + } + + return UsersContext[id.Value]; + } + + public TLUserBase GetUser(TLUserProfilePhoto photo) + { + var usersShapshort = new List(UsersContext.Values); + + return usersShapshort.FirstOrDefault(x => x.Photo == photo); + } + + public TLUserBase GetUser(string username) + { + var usersShapshort = new List(UsersContext.Values); + + return usersShapshort.FirstOrDefault(x => x is IUserName && ((IUserName)x).UserName != null && string.Equals(((IUserName)x).UserName.ToString(), username, StringComparison.OrdinalIgnoreCase)); + } + + public TLMessageBase GetMessage(TLInt id, TLInt channelId = null) + { + if (channelId != null) + { + var channelContext = ChannelsContext[channelId.Value]; + if (channelContext != null) + { + return channelContext[id.Value]; + } + + return null; + } + + return MessagesContext[id.Value]; + } + + public TLMessageBase GetMessage(TLLong randomId) + { + return RandomMessagesContext[randomId.Value]; + } + + public TLMessageBase GetMessage(TLWebPageBase webPageBase) + { + var m = MessagesContext.Values.FirstOrDefault(x => + { + var message = x as TLMessage; + if (message != null) + { + var webPageMedia = message.Media as TLMessageMediaWebPage; + if (webPageMedia != null) + { + var currentWebPage = webPageMedia.WebPage; + if (currentWebPage != null + && currentWebPage.Id.Value == webPageBase.Id.Value) + { + return true; + } + } + } + + return false; + }); + + if (m != null) return m; + + foreach (var channelContext in ChannelsContext.Values) + { + foreach (var x in channelContext.Values) + { + var message = x as TLMessage; + if (message != null) + { + var webPageMedia = message.Media as TLMessageMediaWebPage; + if (webPageMedia != null) + { + var currentWebPage = webPageMedia.WebPage; + if (currentWebPage != null + && currentWebPage.Id.Value == webPageBase.Id.Value) + { + m = message; + break; + } + } + } + } + } + + if (m != null) return m; + + m = RandomMessagesContext.Values.FirstOrDefault(x => + { + var message = x as TLMessage; + if (message != null) + { + var webPageMedia = message.Media as TLMessageMediaWebPage; + if (webPageMedia != null) + { + var currentWebPage = webPageMedia.WebPage; + if (currentWebPage != null + && currentWebPage.Id.Value == webPageBase.Id.Value) + { + return true; + } + } + } + + return false; + }); + + return m; + } + + public TLDialog GetDialog(TLMessageCommon message) + { + TLPeerBase peer; + if (message.ToId is TLPeerChat) + { + peer = message.ToId; + } + else + { + peer = message.Out.Value ? message.ToId : new TLPeerUser { Id = message.FromId }; + } + return GetDialog(peer); + } + + public TLDialog GetDialog(TLPeerBase peer) + { + return _database.GetDialog(peer) as TLDialog; + + //return _database.Dialogs.OfType().FirstOrDefault(x => x.WithId == peer.Id.Value && x.IsChat == peer is TLPeerChat); + } + + public TLDialogBase GetEncryptedDialog(TLInt chatId) + { + return _database.Dialogs.OfType().FirstOrDefault(x => x.Index == chatId.Value); + } + + public TLChat GetChat(TLChatPhoto chatPhoto) + { + return _database.ChatsContext.Values.FirstOrDefault(x => x is TLChat && ((TLChat)x).Photo == chatPhoto) as TLChat; + } + + public TLChannel GetChannel(string username) + { + var chatsSnapshort = new List(_database.ChatsContext.Values); + + return chatsSnapshort.FirstOrDefault(x => x is TLChannel && ((TLChannel)x).UserName != null && string.Equals(((TLChannel)x).UserName.ToString(), username, StringComparison.OrdinalIgnoreCase)) as TLChannel; + } + + public TLChannel GetChannel(TLChatPhoto chatPhoto) + { + var chatsSnapshort = new List(_database.ChatsContext.Values); + + return chatsSnapshort.FirstOrDefault(x => x is TLChannel && ((TLChannel)x).Photo == chatPhoto) as TLChannel; + } + + public IList GetHistory(int dialogIndex) + { + var result = new List(); + + if (_database == null) Init(); + + if (DecryptedMessagesContext == null || DialogsContext == null) + { + return result; + } + var timer = Stopwatch.StartNew(); + + + IList msgs = new List(); + try + { + var dialog = DialogsContext[dialogIndex] as TLDialog; + + if (dialog != null) + { + msgs = dialog.Messages + .OfType() + //.Where(x => + + //x.FromId.Value == currentUserId.Value && x.ToId.Id.Value == peer.Id.Value // to peer from current + //|| x.FromId.Value == peer.Id.Value && x.ToId.Id.Value == currentUserId.Value) // from peer to current + + .Cast() + .ToList(); + } + + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + //TLUtils.WritePerformance(string.Format("GetCachedHistory time ({0}): {1}", _database.CountRecords(), timer.Elapsed)); + return msgs.Take(Constants.CachedMessagesCount).ToList(); + } + + public TLDecryptedMessageBase GetDecryptedMessage(TLInt chatId, TLLong randomId) + { + TLDecryptedMessageBase result = null; + + if (_database == null) Init(); + + if (MessagesContext == null || DialogsContext == null) + { + return result; + } + + IList msgs = new List(); + try + { + var dialog = DialogsContext[chatId.Value] as TLEncryptedDialog; + + if (dialog != null) + { + msgs = dialog.Messages.ToList(); + foreach (var message in msgs) + { + if (message.RandomIndex == randomId.Value) + { + return message; + } + } + } + + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + return result; + } + + public IList GetDecryptedHistory(int dialogIndex, int limit = Constants.CachedMessagesCount) + { + var result = new List(); + + if (_database == null) Init(); + + if (MessagesContext == null || DialogsContext == null) + { + return result; + } + + IList msgs = new List(); + try + { + var dialog = DialogsContext[dialogIndex] as TLEncryptedDialog; + + if (dialog != null) + { + msgs = dialog.Messages.ToList(); + } + + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + var returnedMessages = new List(); + var count = 0; + for (var i = 0; i < msgs.Count && count < limit; i++) + { + returnedMessages.Add(msgs[i]); + if (TLUtils.IsDisplayedDecryptedMessage(msgs[i])) + { + count++; + } + } + + return returnedMessages; + } + + public IList GetUnreadDecryptedHistory(int dialogIndex) + { + var result = new List(); + + if (_database == null) Init(); + + if (MessagesContext == null || DialogsContext == null) + { + return result; + } + + IList msgs = new List(); + try + { + var dialog = DialogsContext[dialogIndex] as TLEncryptedDialog; + + if (dialog != null) + { + msgs = dialog.Messages.ToList(); + } + + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + var returnedMessages = new List(); + for (var i = 0; i < msgs.Count; i++) + { + if (!msgs[i].Out.Value && msgs[i].Unread.Value) + { + returnedMessages.Add(msgs[i]); + } + } + + return returnedMessages; + } + + public IList GetDecryptedHistory(int dialogIndex, long randomId, int limit = Constants.CachedMessagesCount) + { + var result = new List(); + + if (_database == null) Init(); + + if (MessagesContext == null || DialogsContext == null) + { + return result; + } + + IList msgs = new List(); + try + { + var dialog = DialogsContext[dialogIndex] as TLEncryptedDialog; + + if (dialog != null) + { + msgs = dialog.Messages.ToList(); + } + + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + var skipCount = 0; + if (randomId != 0) + { + skipCount = 1; + for (var i = 0; i < msgs.Count; i++) + { + if (msgs[i].RandomIndex != randomId) + { + skipCount++; + } + else + { + break; + } + } + } + + var returnedMessages = new List(); + var count = 0; + for (var i = skipCount; i < msgs.Count && count < limit; i++) + { + returnedMessages.Add(msgs[i]); + if (TLUtils.IsDisplayedDecryptedMessage(msgs[i])) + { + count++; + } + } + + return returnedMessages; + } + + public IList GetHistory(TLPeerBase peer, int maxId, int limit = Constants.CachedMessagesCount) + { + var result = new List(); + + if (_database == null) Init(); + + if (MessagesContext == null) + { + return result; + } + + IList msgs = new List(); + try + { + var withId = peer.Id.Value; + var dialogBase = _database.Dialogs.FirstOrDefault(x => x.WithId == withId && peer.GetType() == x.Peer.GetType()); + + var dialog = dialogBase as TLDialog; + if (dialog != null) + { + msgs = dialog.Messages + .OfType() + .Cast() + .ToList(); + } + + var broadcast = dialogBase as TLBroadcastDialog; + if (broadcast != null) + { + msgs = broadcast.Messages + .OfType() + .Cast() + .ToList(); + } + + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + var count = 0; + var startPosition = -1; + var resultMsgs = new List(); + for (var i = 0; i < msgs.Count && count < limit; i++) + { + var msg = msgs[i]; + if (startPosition == -1) + { + if (msg.Index == 0 || msg.Index > maxId) + { + continue; + } + + if (msg.Index == maxId) + { + startPosition = i; + } + + if (msg.Index < maxId) + { + break; + } + } + + resultMsgs.Add(msg); + count++; + } + + return resultMsgs; + } + + public IList GetHistory(TLPeerBase peer, int limit = Constants.CachedMessagesCount) + { + var result = new List(); + + if (_database == null) Init(); + + if (MessagesContext == null) + { + return result; + } + var timer = Stopwatch.StartNew(); + + + IList msgs = new List(); + try + { + var withId = peer.Id.Value; + var dialogBase = _database.Dialogs.FirstOrDefault(x => x.WithId == withId && peer.GetType() == x.Peer.GetType()); + + var dialog = dialogBase as TLDialog; + if (dialog != null) + { + msgs = dialog.Messages + .OfType() + //.Where(x => + + //x.FromId.Value == currentUserId.Value && x.ToId.Id.Value == peer.Id.Value // to peer from current + //|| x.FromId.Value == peer.Id.Value && x.ToId.Id.Value == currentUserId.Value) // from peer to current + + .Cast() + .ToList(); + } + + var broadcast = dialogBase as TLBroadcastDialog; + if (broadcast != null) + { + msgs = broadcast.Messages + .OfType() + //.Where(x => + + //x.FromId.Value == currentUserId.Value && x.ToId.Id.Value == peer.Id.Value // to peer from current + //|| x.FromId.Value == peer.Id.Value && x.ToId.Id.Value == currentUserId.Value) // from peer to current + + .Cast() + .ToList(); + } + + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR:", LogSeverity.Error); + TLUtils.WriteException(e); + } + + // TLUtils.WritePerformance(string.Format("GetCachedHistory time ({0}): {1}", _database.CountRecords(), timer.Elapsed)); + return msgs.Take(limit).ToList(); + } + + public void GetHistoryAsync(TLPeerBase peer, Action> callback, int limit = Constants.CachedMessagesCount) + { + Execute.BeginOnThreadPool( + () => + { + var history = GetHistory(peer, limit); + callback.SafeInvoke(history); + }); + } + + public void ClearAsync(Action callback = null) + { + Execute.BeginOnThreadPool( + () => + { + lock (_databaseSyncRoot) + { + if (_database != null) _database.Clear(); + } + callback.SafeInvoke(); + }); + } + + #region Messages + + private TLMessageBase GetCachedMessage(TLMessageBase message) + { + TLPeerChannel peerChannel; + var isChannelMessage = TLUtils.IsChannelMessage(message, out peerChannel); + if (isChannelMessage) + { + if (message.Index != 0 && ChannelsContext != null && ChannelsContext.ContainsKey(peerChannel.Id.Value)) + { + var channelContext = ChannelsContext[peerChannel.Id.Value]; + if (channelContext != null) + { + return channelContext[message.Index]; + } + } + + return null; + } + + if (message.Index != 0 && MessagesContext != null && MessagesContext.ContainsKey(message.Index)) + { + return MessagesContext[message.Index]; + } + + if (message.RandomIndex != 0 && RandomMessagesContext != null && RandomMessagesContext.ContainsKey(message.RandomIndex)) + { + return RandomMessagesContext[message.RandomIndex]; + } + + return null; + } + + private TLDecryptedMessageBase GetCachedDecryptedMessage(TLLong randomId) + { + if (randomId != null && DecryptedMessagesContext != null && DecryptedMessagesContext.ContainsKey(randomId.Value)) + { + return DecryptedMessagesContext[randomId.Value]; + } + + return null; + } + + private TLDecryptedMessageBase GetCachedDecryptedMessage(TLDecryptedMessageBase message) + { + if (message.RandomId != null && DecryptedMessagesContext != null && DecryptedMessagesContext.ContainsKey(message.RandomIndex)) + { + return DecryptedMessagesContext[message.RandomIndex]; + } + + //if (message.RandomIndex != 0 && RandomMessagesContext != null && RandomMessagesContext.ContainsKey(message.RandomIndex)) + //{ + // return RandomMessagesContext[message.RandomIndex]; + //} + + + return null; + } + + public void SyncSendingMessages(IList messages, TLMessageBase previousMessage, Action> callback) + { + if (messages == null) + { + callback(null); + return; + } + + var message73 = previousMessage as TLMessage73; + if (message73 != null) + { + var mediaGroup = message73.Media as TLMessageMediaGroup; + if (mediaGroup != null) + { + previousMessage = mediaGroup.Group.LastOrDefault(); + } + } + + var timer = Stopwatch.StartNew(); + + var result = new List(); + if (_database == null) Init(); + + for (var i = 0; i < messages.Count; i++) + { + var message = messages[i]; + var cachedMessage = GetCachedMessage(message) as TLMessage; + + if (cachedMessage != null) + { + _database.UpdateSendingMessage(message, cachedMessage); + result.Add(cachedMessage); + } + else + { + var previousMsg = i == 0 ? previousMessage : messages[i - 1]; + var isLastMsg = i == messages.Count - 1; + _database.AddSendingMessage(message, previousMsg, isLastMsg, isLastMsg); + result.Add(message); + } + } + + _database.Commit(); + + TLUtils.WritePerformance("SyncSendingMessages time: " + timer.Elapsed); + callback(result); + } + + public void SyncSendingMessageId(TLLong randomId, TLInt id, Action callback) + { + var timer = Stopwatch.StartNew(); + + TLMessage result = null; + if (_database == null) Init(); + + var cachedMessage = GetMessage(randomId) as TLMessage; + if (cachedMessage != null) + { + cachedMessage.Id = id; + _database.UpdateSendingMessageContext(cachedMessage); + result = cachedMessage; + + // send at background task and GetDialogs was invoked before getDifference + // remove duplicates + var dialog = GetDialog(cachedMessage); + if (dialog != null) + { + lock (dialog.MessagesSyncRoot) + { + var count = 0; + for (int i = 0; i < dialog.Messages.Count; i++) + { + if (dialog.Messages[i].Index == id.Value) + { + count++; + + if (count > 1) + { + dialog.Messages.RemoveAt(i--); + } + } + } + } + } + } + + _database.Commit(); + + TLUtils.WritePerformance("SyncSendingMessageId time: " + timer.Elapsed); + callback(result); + } + + public void SyncSendingMessage(TLMessageCommon message, TLMessageBase previousMessage, Action callback) + { + if (message == null) + { + callback(null); + return; + } + + var message73 = previousMessage as TLMessage73; + if (message73 != null) + { + var mediaGroup = message73.Media as TLMessageMediaGroup; + if (mediaGroup != null) + { + previousMessage = mediaGroup.Group.LastOrDefault(); + } + } + + var timer = Stopwatch.StartNew(); + + var result = message; + if (_database == null) Init(); + + var cachedMessage = GetCachedMessage(message); + + if (cachedMessage != null) + { + _database.UpdateSendingMessage(message, cachedMessage); + result = (TLMessage)cachedMessage; + } + else + { + _database.AddSendingMessage(message, previousMessage); + + // forwarding + var messagesContainer = message.Reply as TLMessagesContainter; + if (messagesContainer != null) + { + var messages = messagesContainer.FwdMessages; + if (messages != null) + { + for (var i = 0; i < messages.Count; i++) + { + var fwdMessage = messages[i]; + var previousMsg = i == 0 ? message : messages[i - 1]; + var isLastMsg = i == messages.Count - 1; + _database.AddSendingMessage(fwdMessage, previousMsg, isLastMsg, isLastMsg); + } + } + } + } + + _database.Commit(); + + TLUtils.WritePerformance("SyncSendingMessage time: " + timer.Elapsed); + callback(result); + } + + public void SyncSendingDecryptedMessage(TLInt chatId, TLInt date, TLLong randomId, Action callback) + { + TLDecryptedMessageBase result = null; + if (_database == null) Init(); + + if (DecryptedMessagesContext != null) + { + result = GetCachedDecryptedMessage(randomId); + } + + if (result == null) + { + callback(null); + return; + } + + _database.UpdateSendingDecryptedMessage(chatId, date, result); + + _database.Commit(); + + callback(result); + } + + public void SyncDecryptedMessages(IList> tuples, TLEncryptedChatBase peer, Action>> callback) + { + if (tuples == null) + { + callback(null); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = tuples; + if (_database == null) Init(); + + foreach (var tuple in tuples) + { + TLDecryptedMessageBase cachedMessage = null; + + if (DecryptedMessagesContext != null) + { + cachedMessage = GetCachedDecryptedMessage(tuple.Item1); + } + + if (cachedMessage != null) + { + // update fields + if (tuple.Item1.GetType() == cachedMessage.GetType()) + { + cachedMessage.Update(tuple.Item1); + } + + tuple.Item1 = cachedMessage; + } + else + { + // add object to cache + _database.AddDecryptedMessage(tuple.Item1, peer); + } + } + + _database.Commit(); + + TLUtils.WritePerformance("Sync DecryptedMessage time: " + timer.Elapsed); + callback(result); + } + + public void SyncDecryptedMessage(TLDecryptedMessageBase message, TLEncryptedChatBase peer, Action callback) + { + if (message == null) + { + callback(null); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = message; + if (_database == null) Init(); + + TLDecryptedMessageBase cachedMessage = null; + + if (DecryptedMessagesContext != null) + { + cachedMessage = GetCachedDecryptedMessage(message); + } + + if (cachedMessage != null) + { + // update fields + if (message.GetType() == cachedMessage.GetType()) + { + cachedMessage.Update(message); + } + + result = cachedMessage; + } + else + { + // add object to cache + _database.AddDecryptedMessage(message, peer); + } + + _database.Commit(); + + TLUtils.WritePerformance("Sync DecryptedMessage time: " + timer.Elapsed); + callback(result); + } + + public ExceptionInfo LastSyncMessageException { get; set; } + + public void SyncMessage(TLMessageBase message, Action callback) + { + SyncMessage(message, true, true, callback); + } + + public void SyncEditedMessage(TLMessageBase message, bool notifyNewDialog, bool notifyTopMessageUpdated, Action callback) + { + try + { + if (message == null) + { + callback(null); + return; + } + + var result = message; + if (_database == null) Init(); + + var cachedMessage = GetCachedMessage(message); + + if (cachedMessage != null) + { + if (cachedMessage.RandomId != null) + { + _database.RemoveMessageFromContext(cachedMessage); + + if (cachedMessage.Index != 0) + { + cachedMessage.RandomId = null; + } + + _database.AddMessageToContext(cachedMessage); + } + + if (message.GetType() == cachedMessage.GetType()) + { + cachedMessage.Edit(message); + } + else + { + _database.RemoveMessageFromContext(cachedMessage); + _database.AddMessage(message, notifyNewDialog, notifyTopMessageUpdated); + } + result = cachedMessage; + } + + _database.Commit(); + callback(result); + } + catch (Exception ex) + { + LastSyncMessageException = new ExceptionInfo + { + Caption = "CacheService.SyncMessage", + Exception = ex, + Timestamp = DateTime.Now + }; + + TLUtils.WriteException("CacheService.SyncMessage", ex); + } + } + + public void SyncMessage(TLMessageBase message, bool notifyNewDialog, bool notifyTopMessageUpdated, Action callback) + { + try + { + if (message == null) + { + callback(null); + return; + } + + var result = message; + if (_database == null) Init(); + + var cachedMessage = GetCachedMessage(message); + + if (cachedMessage != null) + { + if (cachedMessage.RandomId != null) + { + _database.RemoveMessageFromContext(cachedMessage); + + if (cachedMessage.Index != 0) + { + cachedMessage.RandomId = null; + } + + _database.AddMessageToContext(cachedMessage); + } + + if (message.GetType() == cachedMessage.GetType()) + { + cachedMessage.Update(message); + } + else + { + _database.DeleteMessage(cachedMessage); + _database.AddMessage(message, notifyNewDialog, notifyTopMessageUpdated); + } + result = cachedMessage; + } + else + { + try + { + _database.AddMessage(message, notifyNewDialog, notifyTopMessageUpdated); + } + catch (Exception ex) + { + LastSyncMessageException = new ExceptionInfo { Exception = ex, Timestamp = DateTime.Now }; + Helpers.Execute.ShowDebugMessage("SyncMessage ex:\n" + ex); + } + } + + _database.Commit(); + callback(result); + } + catch (Exception ex) + { + LastSyncMessageException = new ExceptionInfo + { + Caption = "CacheService.SyncMessage", + Exception = ex, + Timestamp = DateTime.Now + }; + + TLUtils.WriteException("CacheService.SyncMessage", ex); + } + } + + public void SyncPeerMessages(TLPeerBase peer, TLMessagesBase messages, bool notifyNewDialog, bool notifyTopMessageUpdated, Action callback) + { + if (messages == null) + { + callback(new TLMessages()); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = messages.GetEmptyObject(); + if (_database == null) Init(); + + ProcessPeerReading(peer, messages); + + SyncChatsInternal(messages.Chats, result.Chats); + SyncUsersInternal(messages.Users, result.Users); + SyncMessagesInternal(peer, messages.Messages, result.Messages, notifyNewDialog, notifyTopMessageUpdated); + + _database.Commit(); + + //TLUtils.WritePerformance("SyncPeerMessages time: " + timer.Elapsed); + callback(result); + } + + private void ProcessPeerReading(TLPeerBase peer, TLMessagesBase messages) + { + IReadMaxId readMaxId = null; + if (peer is TLPeerUser) + { + readMaxId = GetUser(peer.Id) as IReadMaxId; + } + else if (peer is TLPeerChat) + { + readMaxId = GetChat(peer.Id) as IReadMaxId; + } + else if (peer is TLPeerChannel) + { + readMaxId = GetChat(peer.Id) as IReadMaxId; + } + + if (readMaxId != null) + { + foreach (var message in messages.Messages) + { + var messageCommon = message as TLMessageCommon; + if (messageCommon != null) + { + if (messageCommon.Out.Value + && readMaxId.ReadOutboxMaxId != null + && readMaxId.ReadOutboxMaxId.Value >= 0 + && readMaxId.ReadOutboxMaxId.Value < messageCommon.Index) + { + messageCommon.SetUnreadSilent(TLBool.True); + } + else if (!messageCommon.Out.Value + && readMaxId.ReadInboxMaxId != null + && readMaxId.ReadInboxMaxId.Value >= 0 + && readMaxId.ReadInboxMaxId.Value < messageCommon.Index) + { + messageCommon.SetUnreadSilent(TLBool.True); + } + } + } + } + } + + public void AddMessagesToContext(TLMessagesBase messages, Action callback) + { + if (messages == null) + { + callback(new TLMessages()); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = messages.GetEmptyObject(); + if (_database == null) Init(); + + SyncChatsInternal(messages.Chats, result.Chats); + SyncUsersInternal(messages.Users, result.Users); + foreach (var message in messages.Messages) + { + if (GetCachedMessage(message) == null) + { + _database.AddMessageToContext(message); + } + } + + _database.Commit(); + + //TLUtils.WritePerformance("SyncPeerMessages time: " + timer.Elapsed); + callback(result); + } + + public void SyncStatuses(TLVector contactStatuses, Action> callback) + { + if (contactStatuses == null) + { + callback(new TLVector()); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = contactStatuses; + if (_database == null) Init(); + + foreach (var contactStatus in contactStatuses) + { + var contactStatus19 = contactStatus as TLContactStatus19; + if (contactStatus19 != null) + { + var userId = contactStatus.UserId; + var user = GetUser(userId); + if (user != null) + { + user._status = contactStatus19.Status; + } + } + } + + _database.Commit(); + + //TLUtils.WritePerformance("SyncPeerMessages time: " + timer.Elapsed); + callback(result); + } + + public void SyncDifference(TLDifference difference, Action callback, IList exceptions) + { + if (difference == null) + { + callback(new TLDifference()); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = (TLDifference)difference.GetEmptyObject(); + if (_database == null) Init(); + + SyncChatsInternal(difference.Chats, result.Chats, exceptions); + SyncUsersInternal(difference.Users, result.Users, exceptions); + SyncMessagesInternal(null, difference.NewMessages, result.NewMessages, false, false, exceptions); + SyncEncryptedMessagesInternal(difference.State.Qts, difference.NewEncryptedMessages, result.NewEncryptedMessages, exceptions); + + _database.Commit(); + + //TLUtils.WritePerformance("Sync difference time: " + timer.Elapsed); + callback(result); + } + + public void SyncDifferenceWithoutUsersAndChats(TLDifference difference, Action callback, IList exceptions) + { + if (difference == null) + { + callback(new TLDifference()); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = (TLDifference)difference.GetEmptyObject(); + if (_database == null) Init(); + + //SyncChatsInternal(difference.Chats, result.Chats, exceptions); + //SyncUsersInternal(difference.Users, result.Users, exceptions); + + foreach (var messageBase in difference.NewMessages) + { + MTProtoService.ProcessSelfMessage(messageBase); + } + + SyncMessagesInternal(null, difference.NewMessages, result.NewMessages, false, false, exceptions); + SyncEncryptedMessagesInternal(difference.State.Qts, difference.NewEncryptedMessages, result.NewEncryptedMessages, exceptions); + + _database.Commit(); + + //TLUtils.WritePerformance("Sync difference time: " + timer.Elapsed); + callback(result); + } + + private void SyncMessageInternal(TLPeerBase peer, TLMessageBase message, out TLMessageBase result) + { + TLMessageCommon cachedMessage = null; + //if (MessagesContext != null) + { + cachedMessage = (TLMessageCommon)GetCachedMessage(message); + //cachedMessage = (TLMessageCommon)MessagesContext[message.Index]; + } + + if (cachedMessage != null) + { + if (cachedMessage.RandomId != null) + { + _database.RemoveMessageFromContext(cachedMessage); + + cachedMessage.RandomId = null; + + _database.AddMessageToContext(cachedMessage); + + } + + // update fields + if (message.GetType() == cachedMessage.GetType()) + { + cachedMessage.Update(message); + //_database.Storage.Modify(cachedMessage); + } + // or replace object + else + { + _database.DeleteMessage(cachedMessage); + _database.AddMessage(message); + } + result = cachedMessage; + } + else + { + // add object to cache + result = message; + _database.AddMessage(message); + } + } + + private void SyncMessagesInternal(TLPeerBase peer, IEnumerable messages, TLVector result, bool notifyNewDialogs, bool notifyTopMessageUpdated, IList exceptions = null) + { + TLChannel channel = null; + TLInt readInboxMaxId; + if (peer is TLPeerChannel) + { + channel = GetChat(peer.Id) as TLChannel; + } + + foreach (var message in messages) + { + try + { + // for updates we have input message only and set peer to null by default + if (peer == null) + { + peer = TLUtils.GetPeerFromMessage(message); + + if (peer is TLPeerChannel) + { + channel = GetChat(peer.Id) as TLChannel; + if (channel != null) + { + readInboxMaxId = channel.ReadInboxMaxId; + if (readInboxMaxId != null) + { + var messageCommon = message as TLMessageCommon; + if (messageCommon != null && !messageCommon.Out.Value && + messageCommon.Index > readInboxMaxId.Value) + { + messageCommon.SetUnreadSilent(TLBool.True); + } + } + } + } + } + + var cachedMessage = (TLMessageCommon)GetCachedMessage(message); + + if (cachedMessage != null) + { + if (message.GetType() == cachedMessage.GetType()) + { + cachedMessage.Update(message); + } + else + { + _database.DeleteMessage(cachedMessage); + _database.AddMessage(message); + } + result.Add(cachedMessage); + } + else + { + if (peer != null) + { + if (channel != null) + { + readInboxMaxId = channel.ReadInboxMaxId; + if (readInboxMaxId != null) + { + var messageCommon = message as TLMessageCommon; + if (messageCommon != null && !messageCommon.Out.Value && + messageCommon.Index > readInboxMaxId.Value) + { + messageCommon.SetUnreadSilent(TLBool.True); + } + } + } + } + + result.Add(message); + _database.AddMessage(message, notifyNewDialogs, notifyTopMessageUpdated); + } + } + catch (Exception ex) + { + if (exceptions != null) + { + exceptions.Add(new ExceptionInfo + { + Caption = "UpdatesService.ProcessDifference Messages", + Exception = ex, + Timestamp = DateTime.Now + }); + } + + TLUtils.WriteException("UpdatesService.ProcessDifference Messages", ex); + } + } + } + + #endregion + + #region Dialogs + + private void SyncDialogsInternal(Stopwatch stopwatch2, TLDialogsBase dialogs, TLDialogsBase result) + { + MergeMessagesAndChannels(dialogs); + + //Debug.WriteLine("messages.getDialogs sync dialogs merge messages and channels elapsed=" + stopwatch.Elapsed); + + foreach (TLDialog dialog in dialogs.Dialogs) + { + //Debug.WriteLine("messages.getDialogs sync dialogs start get cached elapsed=" + stopwatch.Elapsed); + TLDialog cachedDialog = null; + if (DialogsContext != null) + { + cachedDialog = DialogsContext[dialog.Index] as TLDialog; + } + //Debug.WriteLine("messages.getDialogs sync dialogs stop get cached elapsed=" + stopwatch.Elapsed); + + if (cachedDialog != null) + { + //Debug.WriteLine("messages.getDialogs sync dialogs start update cached elapsed=" + stopwatch.Elapsed); + var raiseTopMessageUpdated = cachedDialog.TopMessageId == null || cachedDialog.TopMessageId.Value != dialog.TopMessageId.Value; + cachedDialog.Update(dialog); + //Debug.WriteLine("messages.getDialogs sync dialogs stop update cached elapsed=" + stopwatch.Elapsed); + if (raiseTopMessageUpdated) + { + if (_eventAggregator != null) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(cachedDialog, cachedDialog.TopMessage)); + } + } + result.Dialogs.Add(cachedDialog); + } + else + { + result.Dialogs.Add(dialog); + + // skip left and not promo dialogs + var peerChannel = dialog.Peer as TLPeerChannel; + if (peerChannel != null) + { + var channel = GetChat(peerChannel.Id) as TLChannel; + var dialog71 = dialog as TLDialog71; + if (channel != null && channel.Left.Value && dialog71 != null && !dialog71.IsPromo) + { + continue; + } + } + + //Debug.WriteLine("messages.getDialogs sync dialogs start add none cached elapsed=" + stopwatch.Elapsed); + // add object to cache + _database.AddDialog(dialog); + + //Debug.WriteLine("messages.getDialogs sync dialogs stop add none cached elapsed=" + stopwatch.Elapsed); + } + } + + //Debug.WriteLine("messages.getDialogs sync dialogs foreach elapsed=" + stopwatch.Elapsed); + + + + result.Messages = dialogs.Messages; + } + + private void SyncChannelDialogsInternal(TLDialogsBase dialogs, TLDialogsBase result) + { + // set TopMessage properties + var timer = Stopwatch.StartNew(); + MergeMessagesAndChannels(dialogs); + //TLUtils.WritePerformance("Dialogs:: merge dialogs and messages " + timer.Elapsed); + + timer = Stopwatch.StartNew(); + foreach (TLDialog dialog in dialogs.Dialogs) + { + TLDialog cachedDialog = null; + if (DialogsContext != null) + { + cachedDialog = DialogsContext[dialog.Index] as TLDialog; + } + + if (cachedDialog != null) + { + var raiseTopMessageUpdated = cachedDialog.TopMessageId == null || cachedDialog.TopMessageId.Value != dialog.TopMessageId.Value; + cachedDialog.Update(dialog); + if (raiseTopMessageUpdated) + { + if (_eventAggregator != null) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(cachedDialog, cachedDialog.TopMessage)); + } + } + result.Dialogs.Add(cachedDialog); + } + else + { + // add object to cache + result.Dialogs.Add(dialog); + _database.AddDialog(dialog); + } + } + //TLUtils.WritePerformance("Dialogs:: foreach dialogs " + timer.Elapsed); + + + + result.Messages = dialogs.Messages; + } + + public void SyncDialogs(Stopwatch stopwatch, TLDialogsBase dialogs, Action callback) + { + if (dialogs == null) + { + callback(new TLDialogs()); + return; + } + + + var result = dialogs.GetEmptyObject(); + if (_database == null) Init(); + + //Debug.WriteLine("messages.getDialogs after init elapsed=" + stopwatch.Elapsed); + + MergeReadMaxIdAndNotifySettings(dialogs); + + //Debug.WriteLine("messages.getDialogs merge notify settings elapsed=" + stopwatch.Elapsed); + + SyncChatsInternal(dialogs.Chats, result.Chats); + + //Debug.WriteLine("messages.getDialogs sync chats elapsed=" + stopwatch.Elapsed); + + SyncUsersInternal(dialogs.Users, result.Users); + + //Debug.WriteLine("messages.getDialogs sync users elapsed=" + stopwatch.Elapsed); + + SyncDialogsInternal(stopwatch, dialogs, result); + + //Debug.WriteLine("messages.getDialogs end sync dialogs elapsed=" + stopwatch.Elapsed); + + _database.Commit(); + + //Debug.WriteLine("messages.getDialogs after commit elapsed=" + stopwatch.Elapsed); + + callback.SafeInvoke(result); + } + + public void SyncProxyData(TLProxyDataBase proxyData, Action callback) + { + var result = proxyData != null ? proxyData.GetEmptyObject() : null; + + var proxyDataPromo = proxyData as TLProxyDataPromo; + if (proxyDataPromo != null) + { + SyncChatsInternal(proxyDataPromo.Chats, ((TLProxyDataPromo)result).Chats); + SyncUsersInternal(proxyDataPromo.Users, ((TLProxyDataPromo)result).Users); + } + + _database.UpdateProxyData(proxyData); + + _database.Commit(); + + callback.SafeInvoke(result); + } + + public void SyncChannelDialogs(TLDialogsBase dialogs, Action callback) + { + if (dialogs == null) + { + callback(new TLDialogs()); + return; + } + + var result = dialogs.GetEmptyObject(); + if (_database == null) Init(); + + MergeReadMaxIdAndNotifySettings(dialogs); + + // add or update chats, users and messages + var timer = Stopwatch.StartNew(); + SyncChatsInternal(dialogs.Chats, result.Chats); + //TLUtils.WritePerformance("Dialogs:: sync chats " + timer.Elapsed); + + timer = Stopwatch.StartNew(); + SyncUsersInternal(dialogs.Users, result.Users); + //TLUtils.WritePerformance("Dialogs:: sync users " + timer.Elapsed); + + //SyncMessagesInternal(dialogs.Messages, result.Messages); + timer = Stopwatch.StartNew(); + SyncChannelDialogsInternal(dialogs, result); + //TLUtils.WritePerformance("Dialogs:: sync dialogs " + timer.Elapsed); + + _database.Commit(); + + TLUtils.WritePerformance("SyncDialogs time: " + timer.Elapsed); + callback.SafeInvoke(result); + } + + private void MergeReadMaxIdAndNotifySettings(TLDialogsBase dialogs) + { + var chatsIndex = new Dictionary(); + foreach (var chat in dialogs.Chats) + { + chatsIndex[chat.Index] = chat; + } + + var usersIndex = new Dictionary(); + foreach (var user in dialogs.Users) + { + usersIndex[user.Index] = user; + } + + foreach (var dialog in dialogs.Dialogs) + { + if (dialog.NotifySettings != null) + { + if (dialog.Peer is TLPeerChannel) + { + TLChatBase chat; + if (chatsIndex.TryGetValue(dialog.Index, out chat)) + { + chat.NotifySettings = dialog.NotifySettings; + } + } + else if (dialog.Peer is TLPeerChat) + { + TLChatBase chat; + if (chatsIndex.TryGetValue(dialog.Index, out chat)) + { + chat.NotifySettings = dialog.NotifySettings; + } + } + else if (dialog.Peer is TLPeerUser) + { + TLUserBase user; + if (usersIndex.TryGetValue(dialog.Index, out user)) + { + user.NotifySettings = dialog.NotifySettings; + } + } + } + + var dialog53 = dialog as IReadMaxId; + if (dialog53 != null) + { + if (dialog.Peer is TLPeerChannel) + { + TLChatBase chatBase; + if (chatsIndex.TryGetValue(dialog.Index, out chatBase)) + { + var chat = chatBase as IReadMaxId; + if (chat != null) + { + chat.ReadInboxMaxId = dialog53.ReadInboxMaxId; + chat.ReadOutboxMaxId = dialog53.ReadOutboxMaxId; + } + } + } + else if (dialog.Peer is TLPeerChat) + { + TLChatBase chatBase; + if (chatsIndex.TryGetValue(dialog.Index, out chatBase)) + { + var chat = chatBase as IReadMaxId; + if (chat != null) + { + chat.ReadInboxMaxId = dialog53.ReadInboxMaxId; + chat.ReadOutboxMaxId = dialog53.ReadOutboxMaxId; + } + } + } + else if (dialog.Peer is TLPeerUser) + { + TLUserBase userBase; + if (usersIndex.TryGetValue(dialog.Index, out userBase)) + { + var user = userBase as IReadMaxId; + if (user != null) + { + user.ReadInboxMaxId = dialog53.ReadInboxMaxId; + user.ReadOutboxMaxId = dialog53.ReadOutboxMaxId; + } + } + } + } + } + } + + public void MergeMessagesAndChannels(TLDialogsBase dialogs) + { + var dialogsCache = new Context(); + var messagesCache = new Context>(); + + try + { + foreach (var dialogBase in dialogs.Dialogs) + { + var dialog = dialogBase as TLDialog; + if (dialog != null) + { + var peerId = dialog.Peer.Id.Value; + dialogsCache[peerId] = dialog; + } + } + + foreach (var messageBase in dialogs.Messages) + { + var message = messageBase as TLMessageCommon; + if (message != null) + { + var peerId = message.ToId is TLPeerUser && !message.Out.Value ? message.FromId.Value : message.ToId.Id.Value; + if (!message.Out.Value) + { + TLDialog dialog; + if (dialogsCache.TryGetValue(peerId, out dialog)) + { + var dialogChannel = dialog as TLDialogChannel; + if (dialogChannel != null + && dialogChannel.ReadInboxMaxId.Value < message.Index) + { + message.SetUnreadSilent(TLBool.True); + } + } + } + + Context dialogContext; + if (!messagesCache.TryGetValue(peerId, out dialogContext)) + { + dialogContext = new Context(); + messagesCache[peerId] = dialogContext; + } + dialogContext[message.Index] = message; + } + } + } + catch (Exception ex) + { + + } + + try + { + + foreach (var dialogCache in messagesCache.Values) + { + + foreach (var message in dialogCache.Values) + { + TLMessageCommon cachedMessage = null; + //if (MessagesContext != null) + { + cachedMessage = (TLMessageCommon)GetCachedMessage(message); + //cachedMessage = (TLMessageCommon)MessagesContext[message.Index]; + } + + if (cachedMessage != null) + { + // update fields + if (message.GetType() == cachedMessage.GetType()) + { + cachedMessage.Update(message); + //_database.Storage.Modify(cachedMessage); + } + // or replace object + else + { + _database.AddMessageToContext(message); + } + } + else + { + // add object to cache + _database.AddMessageToContext(message); + } + } + } + } + catch (Exception ex) + { + + } + + try + { + + foreach (var dialogBase in dialogs.Dialogs) + { + var peer = dialogBase.Peer; + if (peer is TLPeerUser) + { + dialogBase._with = UsersContext[peer.Id.Value]; + } + else if (peer is TLPeerChat) + { + dialogBase._with = ChatsContext[peer.Id.Value]; + } + else if (peer is TLPeerChannel) + { + dialogBase._with = ChatsContext[peer.Id.Value]; + } + + var dialogFeed = dialogBase as TLDialogFeed; + if (dialogFeed != null) + { + var channels = new TLVector(); + foreach (var channelId in dialogFeed.FeedOtherChannels) + { + var ch = ChatsContext[channelId.Value]; + if (ch != null) + { + channels.Add(ch); + } + } + dialogFeed._with = channels; + } + + var dialog = dialogBase as TLDialog; + if (dialog != null) + { + dialog._topMessage = messagesCache[peer.Id.Value][dialogBase.TopMessageId.Value]; + dialog.Messages = new ObservableCollection { dialog.TopMessage }; + } + + //var dialogChannel = dialogBase as TLDialogChannel; + //if (dialog != null) + //{ + // dialog._topMessage = messagesCache[peer.Id.Value][dialogBase.TopMessageId.Value]; + // dialog.Messages = new ObservableCollection { dialog.TopMessage }; + //} + } + } + catch (Exception ex) + { + + } + + + + } + + #endregion + + #region Users + + public void SyncUserLink(TLLinkBase link, Action callback) + { + if (link == null) + { + callback(null); + return; + } + + var timer = Stopwatch.StartNew(); + + TLUserBase result; + if (_database == null) Init(); + + SyncUserInternal(link.User, out result); + link.User = result; + + _database.Commit(); + + TLUtils.WritePerformance("SyncUser time: " + timer.Elapsed); + callback(link); + } + + public void SyncUser(TLUserFull userFull, Action callback) + { + if (userFull == null) + { + callback(null); + return; + } + + var timer = Stopwatch.StartNew(); + + TLUserBase result; + if (_database == null) Init(); + + SyncUserInternal(userFull.ToUser(), out result); + userFull.User = result; + + var dialog = GetDialog(new TLPeerUser { Id = userFull.User.Id }); + if (dialog != null) + { + dialog.NotifySettings = userFull.NotifySettings; + } + + _database.Commit(); + + //TLUtils.WritePerformance("SyncUserFull time: " + timer.Elapsed); + + callback.SafeInvoke(userFull); + } + + + public void SyncUser(TLUserBase user, Action callback) + { + if (user == null) + { + callback(null); + return; + } + + var timer = Stopwatch.StartNew(); + + TLUserBase result; + if (_database == null) Init(); + + SyncUserInternal(user, out result); + + _database.Commit(); + + TLUtils.WritePerformance("SyncUser time: " + timer.Elapsed); + callback(result); + } + + public void SyncUsers(TLVector users, Action> callback) + { + if (users == null) + { + callback(new TLVector()); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = new TLVector(); + if (_database == null) Init(); + + SyncUsersInternal(users, result); + + _database.Commit(); + + TLUtils.WritePerformance("SyncUsers time: " + timer.Elapsed); + callback(result); + } + + public void SyncUsersAndChats(TLVector users, TLVector chats, Action, TLVector>> callback) + { + if (users == null && chats == null) + { + callback(new WindowsPhone.Tuple, TLVector>(null, null)); + return; + } + + var timer = Stopwatch.StartNew(); + + var usersResult = new TLVector(); + var chatsResult = new TLVector(); + if (_database == null) Init(); + + SyncUsersInternal(users, usersResult); + SyncChatsInternal(chats, chatsResult); + + _database.Commit(); + + TLUtils.WritePerformance("SyncUsersAndChats time: " + timer.Elapsed); + callback(new WindowsPhone.Tuple, TLVector>(usersResult, chatsResult)); + } + + private void SyncUserInternal(TLUserBase user, out TLUserBase result) + { + TLUserBase cachedUser = null; + if (UsersContext != null) + { + cachedUser = UsersContext[user.Index]; + } + + if (cachedUser != null) + { + var user45 = user as TLUser45; + var isMinUser = user45 != null && user45.Min; + + // update fields + if (user.GetType() == cachedUser.GetType()) + { + cachedUser.Update(user); + result = cachedUser; + } + else if (isMinUser) + { + result = cachedUser; + } + // or replace object + else + { + _database.ReplaceUser(user.Index, user); + result = user; + } + } + else + { + // add object to cache + result = user; + _database.AddUser(user); + } + } + + private void SyncUsersInternal(TLVector users, TLVector result, IList exceptions = null) + { + foreach (var user in users) + { + try + { + TLUserBase cachedUser = null; + if (UsersContext != null) + { + cachedUser = UsersContext[user.Index]; + } + + if (cachedUser != null) + { + var user45 = user as TLUser45; + var isMinUser = user45 != null && user45.Min; + + // update fields + if (user.GetType() == cachedUser.GetType()) + { + cachedUser.Update(user); + result.Add(cachedUser); + } + else if (isMinUser) + { + result.Add(cachedUser); + } + // or replace object + else + { + _database.ReplaceUser(user.Index, user); + result.Add(user); + } + } + else + { + // add object to cache + result.Add(user); + _database.AddUser(user); + } + } + catch (Exception ex) + { + if (exceptions != null) + { + exceptions.Add(new ExceptionInfo + { + Caption = "UpdatesService.ProcessDifference Users", + Exception = ex, + Timestamp = DateTime.Now + }); + } + + TLUtils.WriteException("UpdatesService.ProcessDifference Users", ex); + } + } + } + + #endregion + + #region SecretChats + + private void SyncEncryptedChatInternal(TLEncryptedChatBase chat, out TLEncryptedChatBase result) + { + try + { + TLEncryptedChatBase cachedChat = null; + if (EncryptedChatsContext != null) + { + cachedChat = EncryptedChatsContext[chat.Index]; + } + + if (cachedChat != null) + { + // update fields + if (chat.GetType() == cachedChat.GetType()) + { + cachedChat.Update(chat); + result = cachedChat; + } + // or replace object + else + { + var chatWaiting = cachedChat as TLEncryptedChatWaiting; + if (chatWaiting != null) + { + var encryptedChat = chat as TLEncryptedChat; + if (encryptedChat != null) + { + chat.A = cachedChat.A; + chat.P = cachedChat.P; + chat.G = cachedChat.G; + + if (!TLUtils.CheckGaAndGb(encryptedChat.GAorB.Data, chat.P.Data)) + { + result = chat; + return; + } + + var gbBytes = encryptedChat.GAorB.ToBytes(); + var authKey = MTProtoService.GetAuthKey(chat.A.Data, gbBytes, chat.P.ToBytes()); + chat.Key = TLString.FromBigEndianData(authKey); + + var authKeyFingerprint = Utils.ComputeSHA1(authKey); + chat.KeyFingerprint = new TLLong(BitConverter.ToInt64(authKeyFingerprint, 12)); + } + else + { + if (cachedChat.Key != null) chat.Key = cachedChat.Key; + if (cachedChat.KeyFingerprint != null) chat.KeyFingerprint = cachedChat.KeyFingerprint; + } + } + //chat.A = cachedChat.A; + //chat.P = cachedChat.P; + //chat.G = cachedChat.G; + + //var encryptedChat = chat as TLEncryptedChat; + //if (encryptedChat != null) + //{ + // var gbBytes = encryptedChat.GAorB.ToBytes(); + // var authKey = MTProtoService.GetAuthKey(chat.A.Data, gbBytes, chat.P.ToBytes()); + // chat.Key = TLString.FromBigEndianData(authKey); + + // var authKeyFingerprint = Utils.ComputeSHA1(authKey); + // chat.KeyFingerprint = new TLLong(BitConverter.ToInt64(authKeyFingerprint, 12)); + //} + //else + //{ + // if (cachedChat.Key != null) chat.Key = cachedChat.Key; + // if (cachedChat.KeyFingerprint != null) chat.KeyFingerprint = cachedChat.KeyFingerprint; + //} + + //Helpers.Execute.ShowDebugMessage(string.Format("InMemoryCacheService.SyncEncryptedChatInternal {0}!={1}", cachedChat.GetType(), chat.GetType())); + + _database.ReplaceEncryptedChat(chat.Index, chat); + + result = chat; + } + } + else + { + // add object to cache + result = chat; + _database.AddEncryptedChat(chat); + } + } + catch (Exception ex) + { + result = null; + } + } + + public void SyncEncryptedChat(TLEncryptedChatBase encryptedChat, Action callback) + { + if (encryptedChat == null) + { + callback(null); + return; + } + + TLEncryptedChatBase chatResult; + if (_database == null) Init(); + + SyncEncryptedChatInternal(encryptedChat, out chatResult); + + _database.Commit(); + + callback.SafeInvoke(chatResult); + } + + public void SyncEncryptedMessagesInternal(TLInt qts, TLVector messages, TLVector result, IList exceptions = null) + { + foreach (var message in messages) + { + try + { + var encryptedChatBase = GetEncryptedChat(message.ChatId); + var encryptedChat = encryptedChatBase as TLEncryptedChat; + if (encryptedChat == null) + { + result.Add(message); + Execute.ShowDebugMessage(string.Format("SyncEncryptedMessagesInternal skip decrypted message chatId={0} chat_type={1}", encryptedChatBase != null ? encryptedChatBase.Id.ToString() : "null", encryptedChatBase != null ? encryptedChatBase.GetType().ToString() : "null")); + + continue; + } + + bool commitChat; + var decryptedMessage = UpdatesService.GetDecryptedMessage(MTProtoService.Instance.CurrentUserId, encryptedChat, message, qts, out commitChat); + if (commitChat) + { + Commit(); + } + if (decryptedMessage == null) + { + continue; + } + + var seqNoMessage = decryptedMessage as ISeqNo; + var encryptedChat17 = encryptedChat as TLEncryptedChat17; + if (seqNoMessage != null + && encryptedChat17 != null) + { + var chatRawInSeqNo = encryptedChat17.RawInSeqNo.Value; + var messageRawInSeqNo = UpdatesService.GetRawInFromReceivedMessage(MTProtoService.Instance.CurrentUserId, encryptedChat17, seqNoMessage); + + if (chatRawInSeqNo <= messageRawInSeqNo) + { + if (messageRawInSeqNo > chatRawInSeqNo) + { + Execute.ShowDebugMessage(string.Format("SyncEncryptedMessagesInternal decrypted message gap chatId={0} chatRawInSeqNo={1} messageRawInSeqNo={2}", encryptedChat17.Id, chatRawInSeqNo, messageRawInSeqNo)); + } + encryptedChat17.RawInSeqNo = new TLInt(chatRawInSeqNo + 1); + SyncEncryptedChat(encryptedChat17, r => { }); + } + else + { + Execute.ShowDebugMessage(string.Format("SyncEncryptedMessagesInternal skip old decrypted message chatId={0} chatRawInSeqNo={1} messageRawInSeqNo={2}", encryptedChat17.Id, chatRawInSeqNo, messageRawInSeqNo)); + continue; + } + } + + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(decryptedMessage)); + + SyncDecryptedMessage(decryptedMessage, encryptedChat, cachedMessage => + { + var decryptedMessageService = decryptedMessage as TLDecryptedMessageService; + if (decryptedMessageService != null) + { + var readMessagesAction = decryptedMessageService.Action as TLDecryptedMessageActionReadMessages; + if (readMessagesAction != null) + { + var items = GetDecryptedHistory(encryptedChat.Id.Value, 100); + foreach (var randomId in readMessagesAction.RandomIds) + { + foreach (var item in items) + { + if (item.RandomId.Value == randomId.Value) + { + item.Status = MessageStatus.Read; + if (item.TTL != null && item.TTL.Value > 0) + { + item.DeleteDate = new TLLong(DateTime.Now.Ticks + encryptedChat.MessageTTL.Value * TimeSpan.TicksPerSecond); + } + + var m = item as TLDecryptedMessage17; + if (m != null) + { + var decryptedMediaPhoto = m.Media as TLDecryptedMessageMediaPhoto; + if (decryptedMediaPhoto != null) + { + if (decryptedMediaPhoto.TTLParams == null) + { + var ttlParams = new TTLParams(); + ttlParams.IsStarted = true; + ttlParams.Total = m.TTL.Value; + ttlParams.StartTime = DateTime.Now; + ttlParams.Out = m.Out.Value; + + decryptedMediaPhoto._ttlParams = ttlParams; + } + } + + var decryptedMediaVideo17 = m.Media as TLDecryptedMessageMediaVideo17; + if (decryptedMediaVideo17 != null) + { + if (decryptedMediaVideo17.TTLParams == null) + { + var ttlParams = new TTLParams(); + ttlParams.IsStarted = true; + ttlParams.Total = m.TTL.Value; + ttlParams.StartTime = DateTime.Now; + ttlParams.Out = m.Out.Value; + + decryptedMediaVideo17._ttlParams = ttlParams; + } + } + + var decryptedMediaAudio17 = m.Media as TLDecryptedMessageMediaAudio17; + if (decryptedMediaAudio17 != null) + { + if (decryptedMediaAudio17.TTLParams == null) + { + var ttlParams = new TTLParams(); + ttlParams.IsStarted = true; + ttlParams.Total = m.TTL.Value; + ttlParams.StartTime = DateTime.Now; + ttlParams.Out = m.Out.Value; + + decryptedMediaAudio17._ttlParams = ttlParams; + } + } + + var decryptedMediaDocument45 = m.Media as TLDecryptedMessageMediaDocument45; + if (decryptedMediaDocument45 != null && (m.IsVoice() || m.IsVideo())) + { + if (decryptedMediaDocument45.TTLParams == null) + { + var ttlParams = new TTLParams(); + ttlParams.IsStarted = true; + ttlParams.Total = m.TTL.Value; + ttlParams.StartTime = DateTime.Now; + ttlParams.Out = m.Out.Value; + + decryptedMediaDocument45._ttlParams = ttlParams; + } + + var message45 = m as TLDecryptedMessage45; + if (message45 != null) + { + message45.SetListened(); + } + decryptedMediaDocument45.NotListened = false; + } + } + break; + } + } + } + } + } + + var isDisplayedMessage = TLUtils.IsDisplayedDecryptedMessageInternal(decryptedMessage); + if (!isDisplayedMessage) + { + decryptedMessage.Unread = TLBool.False; + } + + UpdatesService.ProcessPFS(MTProtoService.Instance.SendEncryptedServiceAsync, this, _eventAggregator, encryptedChat, decryptedMessageService); + + UpdatesService.ProcessNewLayer(MTProtoService.Instance.SendEncryptedServiceAsync, this, _eventAggregator, encryptedChat, decryptedMessage); + + if (decryptedMessageService != null) + { + var resendAction = decryptedMessageService.Action as TLDecryptedMessageActionResend; + if (resendAction != null) + { + Execute.ShowDebugMessage(string.Format("SyncEncryptedMessagesInternal TLDecryptedMessageActionResend start_seq_no={0} end_seq_no={1}", resendAction.StartSeqNo, resendAction.EndSeqNo)); + } + } + }); + + result.Add(message); + } + catch (Exception ex) + { + if (exceptions != null) + { + exceptions.Add(new ExceptionInfo + { + Caption = "UpdatesService.ProcessDifference EncryptedMessages", + Exception = ex, + Timestamp = DateTime.Now + }); + } + + TLUtils.WriteException("UpdatesService.ProcessDifference EncryptedMessages", ex); + } + } + } + #endregion + + #region Chats + + public void AddChats(TLVector chats, Action> callback) + { + if (chats == null) + { + callback(null); + return; + } + + if (_database == null) Init(); + + foreach (var chat in chats) + { + TLChatBase cachedChat = null; + if (ChatsContext != null) + { + cachedChat = ChatsContext[chat.Index]; + } + + if (cachedChat == null) + { + _database.AddChat(chat); + } + } + + _database.Commit(); + + callback.SafeInvoke(chats); + } + + public void SyncChat(TLMessagesChatFull messagesChatFull, Action callback) + { + if (messagesChatFull == null) + { + callback(null); + return; + } + + var usersResult = new TLVector(messagesChatFull.Users.Count); + var chatsResult = new TLVector(messagesChatFull.Chats.Count); + var currentChat = messagesChatFull.Chats.First(x => x.Index == messagesChatFull.FullChat.Id.Value); + TLChatBase chatResult; + if (_database == null) Init(); + + SyncUsersInternal(messagesChatFull.Users, usersResult); + messagesChatFull.Users = usersResult; + + SyncChatsInternal(messagesChatFull.Chats, chatsResult); + messagesChatFull.Chats = chatsResult; + + SyncChatInternal(messagesChatFull.FullChat.ToChat(currentChat), out chatResult); + + var channel = currentChat as TLChannel; + var dialog = GetDialog(channel != null ? (TLPeerBase)new TLPeerChannel { Id = messagesChatFull.FullChat.Id } : new TLPeerChat { Id = messagesChatFull.FullChat.Id }); + if (dialog != null) + { + dialog.NotifySettings = messagesChatFull.FullChat.NotifySettings; + } + + _database.Commit(); + + //TLUtils.WritePerformance("SyncChatFull time: " + timer.Elapsed); + + callback.SafeInvoke(messagesChatFull); + } + + public void SyncChats(TLVector chats, Action> callback) + { + if (chats == null) + { + callback(new TLVector()); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = new TLVector(); + if (_database == null) Init(); + + SyncChatsInternal(chats, result); + + _database.Commit(); + + TLUtils.WritePerformance("SyncChats time: " + timer.Elapsed); + callback(result); + } + + private void SyncChatsInternal(TLVector chats, TLVector result, IList exceptions = null) + { + foreach (var chat in chats) + { + try + { + TLChatBase cachedChat = null; + if (ChatsContext != null) + { + cachedChat = ChatsContext[chat.Index]; + } + + if (cachedChat != null) + { + var channel49 = chat as TLChannel49; + var isMinChannel = channel49 != null && channel49.Min; + + // update fields + if (chat.GetType() == cachedChat.GetType()) + { + cachedChat.Update(chat); + } + else if (isMinChannel) + { + + } + // or replace object + else + { + _database.ReplaceChat(chat.Index, chat); + } + result.Add(cachedChat); + } + else + { + // add object to cache + result.Add(chat); + _database.AddChat(chat); + } + } + catch (Exception ex) + { + if (exceptions != null) + { + exceptions.Add(new ExceptionInfo + { + Caption = "UpdatesService.ProcessDifference Chats", + Exception = ex, + Timestamp = DateTime.Now + }); + } + + TLUtils.WriteException("UpdatesService.ProcessDifference Chats", ex); + } + } + } + + private void SyncChatInternal(TLChatBase chat, out TLChatBase result) + { + TLChatBase cachedChat = null; + if (ChatsContext != null) + { + cachedChat = ChatsContext[chat.Index]; + } + + if (cachedChat != null) + { + var channel49 = chat as TLChannel49; + var isMinChannel = channel49 != null && channel49.Min; + + // update fields + if (chat.GetType() == cachedChat.GetType()) + { + cachedChat.Update(chat); + } + else if (isMinChannel) + { + + } + // or replace object + else + { + _database.ReplaceChat(chat.Index, chat); + } + result = cachedChat; + } + else + { + // add object to cache + result = chat; + _database.AddChat(chat); + } + } + #endregion + + #region Broadcasts + + public void SyncBroadcast(TLBroadcastChat broadcast, Action callback) + { + if (broadcast == null) + { + callback(null); + return; + } + + var timer = Stopwatch.StartNew(); + + TLBroadcastChat result; + if (_database == null) Init(); + + SyncBroadcastInternal(broadcast, out result); + + _database.Commit(); + + TLUtils.WritePerformance("SyncBroadcast time: " + timer.Elapsed); + callback(result); + } + + private void SyncBroadcastInternal(TLBroadcastChat chat, out TLBroadcastChat result) + { + TLBroadcastChat cachedBroadcast = null; + if (BroadcastsContext != null) + { + cachedBroadcast = BroadcastsContext[chat.Index]; + } + + if (cachedBroadcast != null) + { + // update fields + if (chat.GetType() == cachedBroadcast.GetType()) + { + cachedBroadcast.Update(chat); + } + // or replace object + else + { + _database.ReplaceBroadcast(chat.Index, chat); + } + result = cachedBroadcast; + } + else + { + // add object to cache + result = chat; + _database.AddBroadcast(chat); + } + } + #endregion + + #region Contacts + + public void AddUsers(TLVector users, Action> callback) + { + if (users == null) + { + callback(null); + return; + } + + if (_database == null) Init(); + + foreach (var user in users) + { + TLUserBase cachedUser = null; + if (UsersContext != null) + { + cachedUser = UsersContext[user.Index]; + } + + if (cachedUser == null) + { + _database.AddUser(user); + } + } + + _database.Commit(); + + callback.SafeInvoke(users); + } + + public void SyncContacts(TLImportedContacts contacts, Action callback) + { + if (contacts == null) + { + callback(new TLImportedContacts69()); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = contacts.GetEmptyObject(); + if (_database == null) Init(); + + SyncContactsInternal(contacts, result); + + _database.Commit(); + + TLUtils.WritePerformance("SyncImportedContacts time: " + timer.Elapsed); + callback(result); + } + + public void SyncStatedMessage(TLStatedMessageBase statedMessage, Action callback) + { + if (statedMessage == null) + { + callback(null); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = statedMessage.GetEmptyObject(); + if (_database == null) Init(); + + SyncChatsInternal(statedMessage.Chats, result.Chats); + SyncUsersInternal(statedMessage.Users, result.Users); + TLMessageBase message; + SyncMessageInternal(TLUtils.GetPeerFromMessage(statedMessage.Message), statedMessage.Message, out message); + result.Message = message; + + var messageCommon = message as TLMessageCommon; + if (messageCommon != null) + { + var dialog = GetDialog(messageCommon); + if (dialog != null) + { + var oldMessage = dialog.Messages.FirstOrDefault(x => x.Index == message.Index); + if (oldMessage != null) + { + dialog.Messages.Remove(oldMessage); + dialog.Messages.Insert(0, message); + dialog._topMessage = message; + dialog.TopMessageId = message.Id; + dialog.TopMessageRandomId = message.RandomId; + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialog, message)); + } + } + } + + _database.Commit(); + + + TLUtils.WritePerformance("SyncStatedMessage time: " + timer.Elapsed); + callback(result); + } + + public void SyncStatedMessages(TLStatedMessagesBase statedMessages, Action callback) + { + if (statedMessages == null) + { + callback(null); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = statedMessages.GetEmptyObject(); + if (_database == null) Init(); + + SyncChatsInternal(statedMessages.Chats, result.Chats); + SyncUsersInternal(statedMessages.Users, result.Users); + + foreach (var m in statedMessages.Messages) + { + TLMessageBase message; + SyncMessageInternal(TLUtils.GetPeerFromMessage(m), m, out message); + result.Messages.Add(message); + } + + + _database.Commit(); + + + TLUtils.WritePerformance("SyncStatedMessages time: " + timer.Elapsed); + callback(result); + } + + public void UpdateDialogPinned(TLPeerBase peer, bool pinned) + { + if (_database == null) Init(); + + _database.UpdateDialogPinned(peer, pinned); + _database.Commit(); + } + + public void UpdatePinnedDialogs(TLVector order) + { + if (_database == null) Init(); + + + _database.Commit(); + } + + public TLProxyDataBase GetProxyData() + { + if (_database == null) Init(); + + return _database.ProxyData; + } + + public void UpdateProxyData(TLProxyDataBase proxyData) + { + if (_database == null) Init(); + + _database.UpdateProxyData(proxyData); + _database.Commit(); + } + + public void UpdateChannelAvailableMessages(TLInt channelId, TLInt availableMinId) + { + if (_database == null) Init(); + + _database.UpdateChannelAvailableMessages(new TLPeerChannel { Id = channelId }, availableMinId); + + _database.Commit(); + } + + public void UpdateDialogPromo(TLDialogBase dialogBase, bool promo) + { + if (_database == null) Init(); + + _database.UpdateDialogPromo(dialogBase, promo); + _database.Commit(); + } + + public void DeleteDialog(TLDialogBase dialog) + { + if (dialog != null) + { + _database.DeleteDialog(dialog); + + _database.Commit(); + } + } + + public void ClearDialog(TLPeerBase peer) + { + if (peer != null) + { + _database.ClearDialog(peer); + + _database.Commit(); + } + } + + public void DeleteUser(TLInt id) + { + _database.DeleteUser(id); + _database.Commit(); + } + + public void DeleteChat(TLInt id) + { + _database.DeleteChat(id); + _database.Commit(); + } + + public void DeleteMessages(TLVector randomIds) + { + if (randomIds == null || randomIds.Count == 0) return; + + foreach (var id in randomIds) + { + var message = _database.RandomMessagesContext[id.Value]; + if (message != null) + { + var peer = TLUtils.GetPeerFromMessage(message); + + if (peer != null) + { + _database.DeleteMessage(message); + } + } + } + + _database.Commit(); + } + + public void DeleteDecryptedMessages(TLVector randomIds) + { + foreach (var id in randomIds) + { + var message = _database.DecryptedMessagesContext[id.Value]; + if (message != null) + { + var peer = TLUtils.GetPeerFromMessage(message); + + if (peer != null) + { + _database.DeleteDecryptedMessage(message, peer); + } + } + } + + _database.Commit(); + } + + public void ClearDecryptedHistoryAsync(TLInt chatId) + { + _database.ClearDecryptedHistory(chatId); + + _database.Commit(); + } + + public void ClearBroadcastHistoryAsync(TLInt chatId) + { + _database.ClearBroadcastHistory(chatId); + + _database.Commit(); + } + + public void DeleteMessages(TLPeerBase peer, TLMessageBase lastItem, TLVector messages) + { + if (messages == null || messages.Count == 0) return; + + _database.DeleteMessages(peer, lastItem, messages); + + _database.Commit(); + } + + public void DeleteMessages(TLVector ids) + { + if (ids == null || ids.Count == 0) return; + + foreach (var id in ids) + { + var message = _database.MessagesContext[id.Value]; + if (message != null) + { + _database.DeleteMessage(message); + } + } + + _database.Commit(); + } + + public void DeleteUserHistory(TLPeerChannel channel, TLPeerUser user) + { + if (channel == null || user == null) return; + + _database.DeleteUserHistory(channel, user); + + _database.Commit(); + } + + public void DeleteChannelMessages(TLInt channelId, TLVector ids) + { + if (ids == null || ids.Count == 0) return; + + var channelContext = _database.ChannelsContext[channelId.Value]; + if (channelContext != null) + { + var peer = new TLPeerChannel { Id = channelId }; + + var messages = new List(); + foreach (var id in ids) + { + var message = channelContext[id.Value]; + if (message != null) + { + messages.Add(message); + } + } + + _database.DeleteMessages(messages, peer); + } + + _database.Commit(); + } + + private void SyncContactsInternal(TLImportedContacts contacts, TLImportedContacts result) + { + var cache = contacts.Users.ToDictionary(x => x.Index); + foreach (var importedContact in contacts.Imported) + { + if (cache.ContainsKey(importedContact.UserId.Value)) + { + cache[importedContact.UserId.Value].ClientId = importedContact.ClientId; + } + } + + + foreach (var user in contacts.Users) + { + TLUserBase cachedUser = null; + if (UsersContext != null) + { + cachedUser = UsersContext[user.Index]; + } + + if (cachedUser != null) + { + var user45 = user as TLUser45; + var isMinUser = user45 != null && user45.Min; + + // update fields + if (user.GetType() == cachedUser.GetType()) + { + cachedUser.Update(user); + result.Users.Add(cachedUser); + } + else if (isMinUser) + { + result.Users.Add(cachedUser); + } + // or replace object + else + { + _database.ReplaceUser(user.Index, user); + result.Users.Add(user); + } + } + else + { + // add object to cache + result.Users.Add(user); + _database.AddUser(user); + } + + } + + result.Imported = contacts.Imported; + } + + public void SyncContacts(TLContactsBase contacts, Action callback) + { + if (contacts == null) + { + callback(new TLContacts()); + return; + } + + if (contacts is TLContactsNotModified) + { + callback(contacts); + return; + } + + var timer = Stopwatch.StartNew(); + + var result = contacts.GetEmptyObject(); + if (_database == null) Init(); + + SyncContactsInternal((TLContacts)contacts, (TLContacts)result); + + _database.Commit(); + + TLUtils.WritePerformance("SyncContacts time: " + timer.Elapsed); + callback(result); + } + + private void SyncContactsInternal(TLContacts contacts, TLContacts result) + { + var contactsCache = new Dictionary(); + foreach (var contact in contacts.Contacts) + { + contactsCache[contact.UserId.Value] = contact; + } + + foreach (var user in contacts.Users) + { + user.Contact = contactsCache[user.Index]; + + TLUserBase cachedUser = null; + if (UsersContext != null) + { + cachedUser = UsersContext[user.Index]; + } + + if (cachedUser != null) + { + var user45 = user as TLUser45; + var isMinUser = user45 != null && user45.Min; + + // update fields + if (user.GetType() == cachedUser.GetType()) + { + cachedUser.Update(user); + result.Users.Add(cachedUser); + } + else if (isMinUser) + { + result.Users.Add(cachedUser); + } + // or replace object + else + { + _database.ReplaceUser(user.Index, user); + result.Users.Add(user); + } + } + else + { + // add object to cache + result.Users.Add(user); + _database.AddUser(user); + } + + } + + result.Contacts = contacts.Contacts; + } + + #endregion + + #region Config + + private TLCdnConfig _cdnConfig; + + private readonly object _cdnConfigSyncRoot = new object(); + + public void GetCdnConfigAsync(Action callback) + { + if (_cdnConfig == null) + { + _cdnConfig = TLUtils.OpenObjectFromMTProtoFile(_cdnConfigSyncRoot, Constants.CdnConfigFileName); + } + + callback.SafeInvoke(_cdnConfig); + } + + public TLCdnConfig GetCdnConfig() + { + if (_cdnConfig == null) + { + _cdnConfig = TLUtils.OpenObjectFromMTProtoFile(_cdnConfigSyncRoot, Constants.CdnConfigFileName); + } + + return _cdnConfig; + } + + public void SetCdnCofig(TLCdnConfig cdnConfig) + { + _cdnConfig = cdnConfig; + + TLUtils.SaveObjectToMTProtoFile(_cdnConfigSyncRoot, Constants.CdnConfigFileName, _cdnConfig); + } + + private TLConfig _config; + + public TLConfig GetConfig() + { +#if SILVERLIGHT || WIN_RT + if (_config == null) + { + _config = SettingsHelper.GetValue(Constants.ConfigKey) as TLConfig; + } +#endif + return _config; + } + + + public void GetConfigAsync(Action callback) + { + GetConfig(); + + callback.SafeInvoke(_config); + } + + public void SetConfig(TLConfig config) + { + _config = config; +#if SILVERLIGHT || WIN_RT + SettingsHelper.SetValue(Constants.ConfigKey, config); +#endif + } + + public void ClearConfigImportAsync() + { + GetConfigAsync(config => + { + foreach (var option in config.DCOptions) + { + option.IsAuthorized = false; + //if (config.ThisDC.Value != option.Id.Value) + //{ + // option.IsAuthorized = false; + //} + //else + //{ + // option.IsAuthorized = true; + //} + } + + SetConfig(config); + }); + } + + #endregion + + public IList GetSendingMessages() + { + return RandomMessagesContext.Values.ToList(); + } + + public IList GetResendingMessages() + { + return _database.ResendingMessages; + } + + public IList GetMessages() + { + var result = new List(); + foreach (var d in _database.Dialogs) + { + var dialog = d as TLDialog; + if (dialog != null) + { + foreach (var message in dialog.Messages) + { + result.Add(message); + } + } + else + { + + //var encryptedDialog = d as TLEncryptedDialog; + //if (encryptedDialog != null) + //{ + // foreach (var message in encryptedDialog.Messages) + // { + // result.Add(message); + // } + //} + } + } + + return result; + } + + public void Commit() + { + if (_database != null) + { + _database.Commit(); + } + } + + public void CompressAsync(Action callback) + { + if (_database != null) + { + Execute.BeginOnThreadPool(() => + { + _database.Compress(); + + callback.SafeInvoke(); + }); + } + } + + public void ClearLocalFileNames() + { + if (_database != null) + { + _database.ClearLocalFileNames(); + } + } + + public bool TryCommit() + { + if (_database != null && _database.HasChanges) + { + _database.CommitInternal(); + //Helpers.Execute.ShowDebugMessage("TryCommit result=true"); + return true; + } + + return false; + } + + public void SaveSnapshot(string toDirectoryName) + { + if (_database != null) + { + _database.SaveSnapshot(toDirectoryName); + } + } + + public void SaveTempSnapshot(string toDirectoryName) + { + if (_database != null) + { + _database.SaveTempSnapshot(toDirectoryName); + } + } + + public void LoadSnapshot(string fromDirectoryName) + { + if (_database != null) + { + _database.LoadSnapshot(fromDirectoryName); + _database.Open(); + } + } + } +} diff --git a/Telegram.Api/Services/Cache/InMemoryDatabase.cs b/Telegram.Api/Services/Cache/InMemoryDatabase.cs new file mode 100755 index 0000000..5af3eae --- /dev/null +++ b/Telegram.Api/Services/Cache/InMemoryDatabase.cs @@ -0,0 +1,2776 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reactive.Linq; +using System.Threading; +using System.Threading.Tasks; +using Org.BouncyCastle.Security; +using Telegram.Api.Aggregator; +using Telegram.Api.Helpers; +using Telegram.Api.Services.Cache.EventArgs; +using Telegram.Api.TL; + + +namespace Telegram.Api.Services.Cache +{ + public class InMemoryDatabase : IDisposable + { + private volatile bool _isOpened; + + public const string ProxyDataMTProtoFileName = "proxy_data.dat"; + + public const string DialogsMTProtoFileName = "dialogs.dat"; + + public const string UsersMTProtoFileName = "users.dat"; + + public const string ChatsMTProtoFileName = "chats.dat"; + + public const string BroadcastsMTProtoFileName = "broadcasts.dat"; + + public const string EncryptedChatsMTProtoFileName = "encryptedChats.dat"; + + public const string TempProxyDataMTProtoFileName = "temp_proxy_data.dat"; + + public const string TempDialogsMTProtoFileName = "temp_dialogs.dat"; + + public const string TempUsersMTProtoFileName = "temp_users.dat"; + + public const string TempChatsMTProtoFileName = "temp_chats.dat"; + + public const string TempBroadcastsMTProtoFileName = "temp_broadcasts.dat"; + + public const string TempEncryptedChatsMTProtoFileName = "temp_encryptedChats.dat"; + + private readonly object _proxyDataSyncRoot = new object(); + + private readonly object _dialogsFileSyncRoot = new object(); + + private readonly object _usersSyncRoot = new object(); + + private readonly object _chatsSyncRoot = new object(); + + private readonly object _broadcastsSyncRoot = new object(); + + private readonly object _encryptedChatsSyncRoot = new object(); + + public Context MessagesContext = new Context(); + + public Context> ChannelsContext = new Context>(); + + public Context DecryptedMessagesContext = new Context(); + + public Context RandomMessagesContext = new Context(); + + public Context DialogsContext = new Context(); + + public Context UsersContext = new Context(); + + public Context ChatsContext = new Context(); + + public Context BroadcastsContext = new Context(); + + public Context EncryptedChatsContext = new Context(); + + public TLProxyDataBase ProxyData { get; set; } + + private readonly object _dialogsSyncRoot = new object(); + + public ObservableCollection Dialogs { get; set; } + + private readonly ITelegramEventAggregator _eventAggregator; + + private readonly IDisposable _commitSubscription; + + public volatile bool HasChanges; + + public InMemoryDatabase(ITelegramEventAggregator eventAggregator) + { + var commitEvents = Observable.FromEventPattern( + keh => { CommitInvoked += keh; }, + keh => { CommitInvoked -= keh; }); + + _commitSubscription = commitEvents + .Throttle(TimeSpan.FromSeconds(Constants.CommitDBInterval)) + .Subscribe(e => CommitInternal()); + + //commitEvents.Publish() + + Dialogs = new ObservableCollection(); + _eventAggregator = eventAggregator; + } + + public void AddDialog(TLDialog dialog) + { + if (dialog != null) + { + DialogsContext[dialog.Index] = dialog; + + var topMessage = (TLMessageCommon)dialog.TopMessage; + + // add in desc order by Date + var isAdded = false; + + lock (_dialogsSyncRoot) + { + for (var i = 0; i < Dialogs.Count; i++) + { + var d = Dialogs[i] as TLDialog; + var ed = Dialogs[i] as TLEncryptedDialog; + if (d != null) + { + var currentDateIndex = d.GetDateIndex(); + + if (currentDateIndex != 0 + && currentDateIndex < dialog.GetDateIndex()) + { + isAdded = true; + Dialogs.Insert(i, dialog); + break; + } + } + else if (ed != null) + { + var currentDateIndex = ed.GetDateIndex(); + if (currentDateIndex != 0 + && currentDateIndex < dialog.GetDateIndex()) + { + isAdded = true; + Dialogs.Insert(i, dialog); + break; + } + } + } + if (!isAdded) + { + Dialogs.Add(dialog); + } + } + + //sync topMessage + AddMessageToContext(topMessage); + //MessagesContext[topMessage.Index] = topMessage; + + } + } + + //private TLMessageBase GetMessageFromContext(long commonId) + //{ + // if (RandomMessagesContext.ContainsKey(commonId)) + // { + // return RandomMessagesContext[commonId]; + // } + + // if (MessagesContext.ContainsKey(commonId)) + // { + // return MessagesContext[commonId]; + // } + + // return null; + //} + + public void RemoveMessageFromContext(TLMessageBase message) + { + if (message.Index != 0) + { + TLPeerChannel peerChannel; + if (TLUtils.IsChannelMessage(message, out peerChannel)) + { + var channelContext = ChannelsContext[peerChannel.Id.Value]; + if (channelContext != null) + { + channelContext.Remove(message.Index); + } + } + else + { + MessagesContext.Remove(message.Index); + } + } + if (message.RandomIndex != 0) + { + RandomMessagesContext.Remove(message.RandomIndex); + } + } + + public void RemoveDecryptedMessageFromContext(TLDecryptedMessageBase message) + { + if (message.RandomIndex != 0) + { + DecryptedMessagesContext.Remove(message.RandomIndex); + } + //if (message.RandomIndex != 0) + //{ + // RandomMessagesContext.Remove(message.RandomIndex); + //} + } + + public void AddMessageToContext(TLMessageBase message) + { + if (message.Index != 0) + { + TLPeerChannel peerChannel; + if (TLUtils.IsChannelMessage(message, out peerChannel)) + { + var channelContext = ChannelsContext[peerChannel.Id.Value]; + if (channelContext == null) + { + channelContext = new Context(); + ChannelsContext[peerChannel.Id.Value] = channelContext; + } + + channelContext[message.Index] = message; + } + else + { + MessagesContext[message.Index] = message; + } + } + else if (message.RandomIndex != 0) + { + RandomMessagesContext[message.RandomIndex] = message; + } + else + { + Execute.ShowDebugMessage("MsgId and RandomMsgId are zero"); + //throw new Exception("MsgId and RandomMsgId are zero"); + } + } + + public void AddDecryptedMessageToContext(TLDecryptedMessageBase message) + { + if (message.RandomIndex != 0) + { + DecryptedMessagesContext[message.RandomIndex] = message; + } + else + { + throw new Exception("RandomId is zero for DecryptedMessage"); + } + } + + public void AddUser(TLUserBase user) + { + if (user != null) + { + UsersContext[user.Index] = user; + } + } + + public void AddChat(TLChatBase chat) + { + if (chat != null) + { + ChatsContext[chat.Index] = chat; + } + } + + public void AddEncryptedChat(TLEncryptedChatBase chat) + { + if (chat != null) + { + EncryptedChatsContext[chat.Index] = chat; + } + } + + public void AddBroadcast(TLBroadcastChat broadcast) + { + if (broadcast != null) + { + BroadcastsContext[broadcast.Index] = broadcast; + } + } + + public void SaveSnapshot(string toDirectoryName) + { + var timer = Stopwatch.StartNew(); + + CopyInternal(_usersSyncRoot, UsersMTProtoFileName, Path.Combine(toDirectoryName, UsersMTProtoFileName)); + CopyInternal(_chatsSyncRoot, ChatsMTProtoFileName, Path.Combine(toDirectoryName, ChatsMTProtoFileName)); + CopyInternal(_broadcastsSyncRoot, BroadcastsMTProtoFileName, Path.Combine(toDirectoryName, BroadcastsMTProtoFileName)); + CopyInternal(_encryptedChatsSyncRoot, EncryptedChatsMTProtoFileName, Path.Combine(toDirectoryName, EncryptedChatsMTProtoFileName)); + CopyInternal(_dialogsFileSyncRoot, DialogsMTProtoFileName, Path.Combine(toDirectoryName, DialogsMTProtoFileName)); + CopyInternal(_proxyDataSyncRoot, ProxyDataMTProtoFileName, Path.Combine(toDirectoryName, ProxyDataMTProtoFileName)); + + TLUtils.WritePerformance("Save DB snapshot time: " + timer.Elapsed); + } + + public void SaveTempSnapshot(string toDirectoryName) + { + var timer = Stopwatch.StartNew(); + + CopyInternal(_usersSyncRoot, TempUsersMTProtoFileName, Path.Combine(toDirectoryName, UsersMTProtoFileName)); + CopyInternal(_chatsSyncRoot, TempChatsMTProtoFileName, Path.Combine(toDirectoryName, ChatsMTProtoFileName)); + CopyInternal(_broadcastsSyncRoot, TempBroadcastsMTProtoFileName, Path.Combine(toDirectoryName, BroadcastsMTProtoFileName)); + CopyInternal(_encryptedChatsSyncRoot, TempEncryptedChatsMTProtoFileName, Path.Combine(toDirectoryName, EncryptedChatsMTProtoFileName)); + CopyInternal(_dialogsFileSyncRoot, TempDialogsMTProtoFileName, Path.Combine(toDirectoryName, DialogsMTProtoFileName)); + CopyInternal(_proxyDataSyncRoot, TempProxyDataMTProtoFileName, Path.Combine(toDirectoryName, ProxyDataMTProtoFileName)); + + TLUtils.WritePerformance("Save DB snapshot time: " + timer.Elapsed); + } + + private void CopyInternal(object syncRoot, string fileName, string destinationFileName) + { + FileUtils.Copy(syncRoot, fileName, destinationFileName); + } + + public void LoadSnapshot(string fromDirectoryName) + { + var timer = Stopwatch.StartNew(); + + CopyInternal(_usersSyncRoot, Path.Combine(fromDirectoryName, UsersMTProtoFileName), UsersMTProtoFileName); + CopyInternal(_chatsSyncRoot, Path.Combine(fromDirectoryName, ChatsMTProtoFileName), ChatsMTProtoFileName); + CopyInternal(_broadcastsSyncRoot, Path.Combine(fromDirectoryName, BroadcastsMTProtoFileName), BroadcastsMTProtoFileName); + CopyInternal(_encryptedChatsSyncRoot, Path.Combine(fromDirectoryName, EncryptedChatsMTProtoFileName), EncryptedChatsMTProtoFileName); + CopyInternal(_dialogsFileSyncRoot, Path.Combine(fromDirectoryName, DialogsMTProtoFileName), DialogsMTProtoFileName); + CopyInternal(_proxyDataSyncRoot, Path.Combine(fromDirectoryName, ProxyDataMTProtoFileName), ProxyDataMTProtoFileName); + + TLUtils.WritePerformance("Load DB snapshot time: " + timer.Elapsed); + } + + public void Clear() + { + var timer = Stopwatch.StartNew(); + + Dialogs.Clear(); + UsersContext.Clear(); + ChatsContext.Clear(); + BroadcastsContext.Clear(); + EncryptedChatsContext.Clear(); + DialogsContext.Clear(); + ProxyData = null; + + ClearInternal(_usersSyncRoot, UsersMTProtoFileName); + ClearInternal(_chatsSyncRoot, ChatsMTProtoFileName); + ClearInternal(_broadcastsSyncRoot, BroadcastsMTProtoFileName); + ClearInternal(_encryptedChatsSyncRoot, EncryptedChatsMTProtoFileName); + ClearInternal(_dialogsFileSyncRoot, DialogsMTProtoFileName); + ClearInternal(_proxyDataSyncRoot, ProxyDataMTProtoFileName); + + TLUtils.WritePerformance("Clear DB time: " + timer.Elapsed); + } + + private void ClearInternal(object syncRoot, string fileName) + { + FileUtils.Delete(syncRoot, fileName); + } + + private void AddDecryptedMessageCommon(TLDecryptedMessageBase message, TLEncryptedChatBase p, bool notifyNewDialogs, Func, bool> insertAction) + { + if (message != null) + { + AddDecryptedMessageToContext(message); + + var isUnread = !message.Out.Value && message.Unread.Value; + + var dialog = GetEncryptedDialog(message); + + if (dialog != null) + { + if (dialog.Messages.Count > 0) + { + var isAdded = insertAction(dialog.Messages); + + if (!isAdded) + { + dialog.Messages.Add(message); + } + } + else + { + dialog.Messages.Add(message); + } + + if (isUnread) + { + var isDisplayedMessage = TLUtils.IsDisplayedDecryptedMessage(message); + + if (isDisplayedMessage) + { + dialog.UnreadCount = new TLInt(dialog.UnreadCount.Value + 1); + } + } + + CorrectDialogOrder(dialog, dialog.GetDateIndex(), 0); + + if (dialog.Messages[0] == message) + { + dialog.TopMessage = message; + dialog.TopDecryptedMessageRandomId = message.RandomId; + if (_eventAggregator != null) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialog, message)); + } + } + } + else + { + var currentUserId = MTProtoService.Instance.CurrentUserId; + TLInt withId; + TLObject with = null; + + var encryptedChatCommmon = p as TLEncryptedChatCommon; + if (encryptedChatCommmon != null) + { + withId = encryptedChatCommmon.AdminId.Value == currentUserId.Value + ? encryptedChatCommmon.ParticipantId + : encryptedChatCommmon.AdminId; + + with = UsersContext[withId.Value]; + } + + + TLPeerBase peer = new TLPeerEncryptedChat { Id = message.ChatId }; + int index = 0; + + var addingDialog = new TLEncryptedDialog + { + Peer = peer, + With = with, + Messages = new ObservableCollection { message }, + TopDecryptedMessageRandomId = message.RandomId, + TopMessage = message, + UnreadCount = isUnread ? new TLInt(1) : new TLInt(0) + }; + + lock (_dialogsSyncRoot) + { + for (var i = 0; i < Dialogs.Count; i++) + { + if (Dialogs[i].GetDateIndex() < message.DateIndex) + { + index = i; + break; + } + } + + Dialogs.Insert(index, addingDialog); + DialogsContext[addingDialog.Index] = addingDialog; + } + if (_eventAggregator != null && notifyNewDialogs) + { + _eventAggregator.Publish(new DialogAddedEventArgs(addingDialog)); + } + } + } + else + { + throw new NotImplementedException(); + } + } + + private void CorrectDialogOrder(TLDialogBase dialog, int dateIndex, int messageId) + { + var isInserted = false; + lock (_dialogsSyncRoot) + { + Dialogs.Remove(dialog); + for (var i = 0; i < Dialogs.Count; i++) + { + if (Dialogs[i].GetDateIndex() < dateIndex) + { + Dialogs.Insert(i, dialog); + isInserted = true; + break; + } + + // в бродкастах дата у всех сообщений совпадает: правильный порядок можно определить по индексу сообщения + if (Dialogs[i].GetDateIndex() == dateIndex) + { + var currentMessageId = Dialogs[i].TopMessageId != null ? Dialogs[i].TopMessageId.Value : 0; + + if (currentMessageId != 0 && messageId != 0) + { + if (currentMessageId < messageId) + { + Dialogs.Insert(i, dialog); + isInserted = true; + break; + } + + Dialogs.Insert(i + 1, dialog); + isInserted = true; + break; + } + } + } + + if (!isInserted) + { + Dialogs.Add(dialog); + } + } + } + + private void AddMessageCommon(TLMessageBase message, bool notifyNewDialogs, bool notifyTopMessageUpdated, Func, bool> insertAction) + { + if (message != null) + { + AddMessageToContext(message); + + var commonMessage = message as TLMessageCommon; + if (commonMessage != null) + { + var message70 = commonMessage as TLMessage70; + var isUnread = !commonMessage.Out.Value && commonMessage.Unread.Value; + var isUnreadMention = isUnread && message70 != null && message70.IsMention && message70.FwdHeader == null; + + var dialogBase = GetDialog(commonMessage); + if (dialogBase != null) + { + var dialog = dialogBase as TLDialog; + if (dialog != null) + { + if (dialog.Messages.Count > 0) + { + var isAdded = insertAction(dialog.Messages); + + if (!isAdded) + { + dialog.Messages.Add(commonMessage); + } + } + else + { + dialog.Messages.Add(commonMessage); + } + + if (isUnread && dialog.TopMessage != null && dialog.TopMessage.Index < commonMessage.Index) + { + dialogBase.UnreadCount = new TLInt(dialogBase.UnreadCount.Value + 1); + if (isUnreadMention) + { + var dialog71 = dialogBase as TLDialog71; + if (dialog71 != null) + { + dialog71.UnreadMentionsCount = new TLInt(dialog71.UnreadMentionsCount.Value + 1); + } + } + } + + if (dialog.TopMessage != null) + { + CorrectDialogOrder(dialogBase, dialog.GetDateIndex(), dialog.TopMessage.Index); + } + + if (dialog.Messages[0] == commonMessage) + { + if (notifyTopMessageUpdated) + { + dialog._topMessage = commonMessage; + Helpers.Execute.BeginOnUIThread(() => dialog.NotifyOfPropertyChange(() => dialog.TopMessage)); + } + else + { + dialog._topMessage = commonMessage; + } + dialog.TopMessageId = commonMessage.Id; + dialog.TopMessageRandomId = commonMessage.RandomId; + if (_eventAggregator != null && notifyTopMessageUpdated) + { + Helpers.Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialogBase, commonMessage))); + } + } + } + + var broadcast = dialogBase as TLBroadcastDialog; + if (broadcast != null) + { + if (broadcast.Messages.Count > 0) + { + var isAdded = insertAction(broadcast.Messages); + + if (!isAdded) + { + broadcast.Messages.Add(commonMessage); + } + } + else + { + broadcast.Messages.Add(commonMessage); + } + + if (isUnread && broadcast.TopMessage != null && broadcast.TopMessage.Index < commonMessage.Index) + { + dialogBase.UnreadCount = new TLInt(dialogBase.UnreadCount.Value + 1); + } + + if (broadcast.TopMessage != null) + { + CorrectDialogOrder(dialogBase, broadcast.GetDateIndex(), broadcast.TopMessage.Index); + } + + if (broadcast.Messages[0] == commonMessage) + { + if (notifyTopMessageUpdated) + { + broadcast._topMessage = commonMessage; + Helpers.Execute.BeginOnUIThread(() => broadcast.NotifyOfPropertyChange(() => broadcast.TopMessage)); + } + else + { + broadcast._topMessage = commonMessage; + } + broadcast.TopMessageId = commonMessage.Id; + broadcast.TopMessageRandomId = commonMessage.RandomId; + if (_eventAggregator != null && notifyTopMessageUpdated) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialogBase, commonMessage)); + } + } + } + } + else + { + TLObject with; + + TLPeerBase peer; + + if (commonMessage.ToId is TLPeerChannel) + { + peer = commonMessage.ToId; + } + else if (commonMessage.ToId is TLPeerBroadcast) + { + peer = commonMessage.ToId; + } + else if (commonMessage.ToId is TLPeerChat) + { + peer = commonMessage.ToId; + } + else + { + if (commonMessage.Out.Value) + { + peer = commonMessage.ToId; + } + else + { + peer = new TLPeerUser { Id = commonMessage.FromId }; + } + } + + if (peer is TLPeerChannel) + { + with = ChatsContext[peer.Id.Value]; + } + else if (peer is TLPeerBroadcast) + { + with = BroadcastsContext[peer.Id.Value]; + } + else if (peer is TLPeerChat) + { + with = ChatsContext[peer.Id.Value]; + } + else + { + with = UsersContext[peer.Id.Value]; + } + int index = 0; + + + TLDialogBase addingDialog; + + if (peer is TLPeerBroadcast) + { + addingDialog = new TLBroadcastDialog + { + Peer = peer, + With = with, + Messages = new ObservableCollection { commonMessage }, + TopMessageId = commonMessage.Id, + TopMessageRandomId = commonMessage.RandomId, + TopMessage = commonMessage, + UnreadCount = isUnread ? new TLInt(1) : new TLInt(0) + }; + } + else if (peer is TLPeerChannel) + { + addingDialog = new TLDialog71 + { + Flags = new TLInt(0), + Peer = peer, + With = with, + Messages = new ObservableCollection { commonMessage }, + TopMessageId = commonMessage.Id, + TopMessageRandomId = commonMessage.RandomId, + TopMessage = commonMessage, + UnreadCount = isUnread ? new TLInt(1) : new TLInt(0), + UnreadMentionsCount = isUnreadMention ? new TLInt(1) : new TLInt(0), + ReadInboxMaxId = new TLInt(0), + ReadOutboxMaxId = new TLInt(0), + + Pts = new TLInt(0) + }; + } + else + { + addingDialog = new TLDialog71 + { + Flags = new TLInt(0), + Peer = peer, + With = with, + Messages = new ObservableCollection { commonMessage }, + TopMessageId = commonMessage.Id, + TopMessageRandomId = commonMessage.RandomId, + TopMessage = commonMessage, + UnreadCount = isUnread ? new TLInt(1) : new TLInt(0), + UnreadMentionsCount = isUnreadMention ? new TLInt(1) : new TLInt(0), + ReadInboxMaxId = new TLInt(0), + ReadOutboxMaxId = new TLInt(0) + }; + } + + + lock (_dialogsSyncRoot) + { + for (var i = 0; i < Dialogs.Count; i++) + { + if (Dialogs[i].GetDateIndex() < message.DateIndex) + { + index = i; + break; + } + } + + Dialogs.Insert(index, addingDialog); + DialogsContext[addingDialog.Index] = addingDialog; + } + if (_eventAggregator != null && notifyNewDialogs) + { + _eventAggregator.Publish(new DialogAddedEventArgs(addingDialog)); + } + } + } + } + else + { + + } + } + + private TLEncryptedDialog GetEncryptedDialog(TLInt id) + { + lock (_dialogsSyncRoot) + { + foreach (var d in Dialogs) + { + if (d.Peer is TLPeerEncryptedChat + && d.Peer.Id.Value == id.Value) + { + return d as TLEncryptedDialog; + } + } + } + return null; + } + + private TLEncryptedDialog GetEncryptedDialog(TLEncryptedChatBase peer) + { + lock (_dialogsSyncRoot) + { + foreach (var d in Dialogs) + { + if (d.Peer is TLPeerEncryptedChat + && d.Peer.Id.Value == peer.Id.Value) + { + return d as TLEncryptedDialog; + } + } + } + return null; + } + + private TLEncryptedDialog GetEncryptedDialog(TLDecryptedMessageBase commonMessage) + { + lock (_dialogsSyncRoot) + { + foreach (var d in Dialogs) + { + if (d.Peer is TLPeerEncryptedChat + //&& message.ToId is TLPeerChat + && d.Peer.Id.Value == commonMessage.ChatId.Value) + { + return d as TLEncryptedDialog; + } + } + + //dialog = Dialogs.FirstOrDefault(x => x.WithId == peer.Id.Value && x.IsChat == peer is TLPeerChat); + } + return null; + } + + public TLDialogBase GetDialog(TLPeerBase peer) + { + TLDialogBase result = null; + + lock (_dialogsSyncRoot) + { + foreach (var d in Dialogs) + { + if (d.Peer.Id.Value == peer.Id.Value) + { + if (d.Peer is TLPeerChannel + && peer is TLPeerChannel) + { + result = d as TLDialog; + if (result != null) break; + } + + if (d.Peer is TLPeerChat + && peer is TLPeerChat) + { + result = d as TLDialog; + if (result != null) break; + } + + if (d.Peer is TLPeerUser + && peer is TLPeerUser) + { + result = d as TLDialog; + if (result != null) break; + } + + if (d.Peer is TLPeerBroadcast + && peer is TLPeerBroadcast) + { + result = d as TLBroadcastDialog; + if (result != null) break; + } + } + } + } + + return result; + } + + private TLDialogBase GetDialog(TLMessageCommon commonMessage) + { + lock (_dialogsSyncRoot) + { + foreach (var d in Dialogs) + { + if (d.Peer is TLPeerChat + && commonMessage.ToId is TLPeerChat + && d.Peer.Id.Value == commonMessage.ToId.Id.Value) + { + return d as TLDialog; + } + + if (d.Peer is TLPeerUser + && commonMessage.ToId is TLPeerUser + && commonMessage.Out.Value + && d.Peer.Id.Value == commonMessage.ToId.Id.Value) + { + return d as TLDialog; + } + + if (d.Peer is TLPeerUser + && commonMessage.ToId is TLPeerUser + && !commonMessage.Out.Value + && d.Peer.Id.Value == commonMessage.FromId.Value) + { + return d as TLDialog; + } + + if (d.Peer is TLPeerBroadcast + && commonMessage.ToId is TLPeerBroadcast + && d.Peer.Id.Value == commonMessage.ToId.Id.Value) + { + return d as TLBroadcastDialog; + } + + if (d.Peer is TLPeerChannel + && commonMessage.ToId is TLPeerChannel + && d.Peer.Id.Value == commonMessage.ToId.Id.Value) + { + return d as TLDialogBase; + } + } + + //dialog = Dialogs.FirstOrDefault(x => x.WithId == peer.Id.Value && x.IsChat == peer is TLPeerChat); + } + return null; + } + + public void UpdateSendingMessageContext(TLMessageBase message) + { + RemoveMessageFromContext(message); + + message.RandomId = null; + + AddMessageToContext(message); + } + + public void UpdateSendingMessage(TLMessageBase message, TLMessageBase cachedMessage) + { + RemoveMessageFromContext(cachedMessage); + + cachedMessage.Update(message); + cachedMessage.RandomId = null; + + AddMessageToContext(cachedMessage); + + var commonMessage = message as TLMessageCommon; + if (commonMessage == null) + { + return; + } + var dialog = GetDialog(commonMessage) as TLDialog; + + if (dialog != null) + { + bool notify = false; + lock (dialog.MessagesSyncRoot) + { + var oldMessage = dialog.Messages.FirstOrDefault(x => x.Index == cachedMessage.Index); + if (oldMessage != null) + { + dialog.Messages.Remove(oldMessage); + TLDialog.InsertMessageInOrder(dialog.Messages, cachedMessage); + if (dialog.TopMessageId == null || dialog.TopMessageId.Value < cachedMessage.Index) + { + dialog._topMessage = cachedMessage; + dialog.TopMessageId = cachedMessage.Id; + dialog.TopMessageRandomId = cachedMessage.RandomId; + notify = true; + } + } + } + if (notify) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialog, cachedMessage)); + } + } + } + + public void UpdateSendingDecryptedMessage(TLInt chatId, TLInt date, TLDecryptedMessageBase cachedMessage) + { + RemoveDecryptedMessageFromContext(cachedMessage); + + cachedMessage.Date = date; + + AddDecryptedMessageToContext(cachedMessage); + + var dialog = GetEncryptedDialog(chatId); + + if (dialog != null) + { + var oldMessage = dialog.Messages.FirstOrDefault(x => x.RandomIndex == cachedMessage.RandomIndex); + if (oldMessage != null) + { + dialog.Messages.Remove(oldMessage); + TLEncryptedDialog.InsertMessageInOrder(dialog.Messages, cachedMessage); + if (dialog.TopDecryptedMessageRandomId == null || dialog.TopDecryptedMessageRandomId.Value != cachedMessage.RandomIndex) + { + dialog._topMessage = cachedMessage; + dialog.TopDecryptedMessageRandomId = cachedMessage.RandomId; + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialog, cachedMessage)); + } + } + } + } + + public void AddSendingMessage(TLMessageBase message, TLMessageBase previousMessage) + { + AddMessageCommon( + message, true, true, + messages => + { + if (previousMessage == null) + { + messages.Insert(0, message); + return true; + } + + for (var i = 0; i < messages.Count; i++) + { + if (messages[i] == previousMessage) + { + messages.Insert(i, message); + return true; + } + } + + if (previousMessage.Index > 0) + { + for (var i = 0; i < messages.Count; i++) + { + if (messages[i].Index > 0 && previousMessage.Index > messages[i].Index) + { + messages.Insert(i, message); + return true; + } + } + } + else + { + for (var i = 0; i < messages.Count; i++) + { + if (messages[i].DateIndex > 0 && previousMessage.DateIndex > messages[i].DateIndex) + { + messages.Insert(i, message); + return true; + } + } + } + + return false; + }); + } + + public void AddSendingMessage(TLMessageBase message, TLMessageBase previousMessage, bool notifyNewDialog, bool notifyTopMessageUpdated) + { + AddMessageCommon( + message, notifyNewDialog, notifyTopMessageUpdated, + messages => + { + if (previousMessage == null) + { + messages.Insert(0, message); + return true; + } + + for (var i = 0; i < messages.Count; i++) + { + if (messages[i] == previousMessage) + { + messages.Insert(i, message); + return true; + } + } + + return false; + }); + } + + + public void AddDecryptedMessage(TLDecryptedMessageBase message, TLEncryptedChatBase peer, bool notifyNewDialogs = true) + { + AddDecryptedMessageCommon( + message, peer, notifyNewDialogs, + messages => + { + for (var i = 0; i < messages.Count; i++) + { + if (messages[i].DateIndex < message.DateIndex) + { + messages.Insert(i, message); + return true; + } + + if (messages[i].DateIndex == message.DateIndex) + { + // TODO: fix for randomId and id (messages[i] has only randomId) + //if (messages[i].RandomIndex == 0) + //{ + // messages.Insert(i, message); + // return true; + //} + + //if (messages[i].RandomIndex < message.RandomIndex) + //{ + // messages.Insert(i, message); + // return true; + //} + + if (messages[i].RandomIndex == message.RandomIndex) + { + return true; + } + + messages.Insert(i, message); + + return true; + } + } + + return false; + }); + } + + public void AddMessage(TLMessageBase message, bool notifyNewDialogs = true, bool notifyNewMessageUpdated = true) + { + AddMessageCommon( + message, notifyNewDialogs, notifyNewMessageUpdated, + messages => + { + for (var i = 0; i < messages.Count; i++) + { + if (messages[i].DateIndex < message.DateIndex) + { + messages.Insert(i, message); + return true; + } + + if (messages[i].DateIndex == message.DateIndex) + { + // TODO: fix for randomId and id (messages[i] can has only randomId) + if (messages[i].Index == 0) + { + messages.Insert(i, message); + return true; + } + + if (messages[i].Index < message.Index) + { + messages.Insert(i, message); + return true; + } + + if (messages[i].Index == message.Index) + { + if (messages[i].GetType() != message.GetType()) + { + messages[i] = message; + } + + return true; + } + } + } + + return false; + }); + } + + public void ClearDecryptedHistory(TLInt chatId) + { + var dialog = DialogsContext[chatId.Value] as TLEncryptedDialog; + if (dialog != null) + { + + lock (_dialogsSyncRoot) + { + foreach (var message in dialog.Messages) + { + RemoveDecryptedMessageFromContext(message); + } + + dialog.Messages.Clear(); + + var chat = (TLEncryptedChatCommon)InMemoryCacheService.Instance.GetEncryptedChat(chatId); + var lastMessage = new TLDecryptedMessageService + { + RandomId = TLLong.Random(), + RandomBytes = TLString.Random(Constants.MinRandomBytesLength), + ChatId = chat.Id, + Action = new TLDecryptedMessageActionEmpty(), + FromId = MTProtoService.Instance.CurrentUserId, + Date = chat.Date, + Out = new TLBool(false), + Unread = new TLBool(false), + Status = MessageStatus.Read + }; + + dialog.UnreadCount = new TLInt(0); + dialog.Messages.Add(lastMessage); + AddDecryptedMessageToContext(lastMessage); + + dialog.TopMessage = lastMessage; + dialog.TopDecryptedMessageRandomId = lastMessage.RandomId; + + CorrectDialogOrder(dialog, dialog.GetDateIndex(), 0); + } + + if (_eventAggregator != null) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialog, dialog.TopMessage)); + } + } + } + + public void ClearBroadcastHistory(TLInt chatId) + { + var dialog = DialogsContext[chatId.Value] as TLBroadcastDialog; + if (dialog != null) + { + + lock (_dialogsSyncRoot) + { + foreach (var message in dialog.Messages) + { + RemoveMessageFromContext(message); + } + + dialog.Messages.Clear(); + + var topMessage = dialog.TopMessage as TLMessageCommon; + if (topMessage == null) return; + + var broadcastChat = InMemoryCacheService.Instance.GetBroadcast(chatId); + if (broadcastChat == null) return; + + var serviceMessage = new TLMessageService17 + { + FromId = topMessage.FromId, + ToId = topMessage.ToId, + Status = MessageStatus.Confirmed, + Out = new TLBool { Value = true }, + Date = topMessage.Date, + //IsAnimated = true, + RandomId = TLLong.Random(), + Action = new TLMessageActionChatCreate + { + Title = broadcastChat.Title, + Users = broadcastChat.ParticipantIds + } + }; + serviceMessage.SetUnread(new TLBool(false)); + + dialog.Messages.Add(serviceMessage); + AddMessageToContext(serviceMessage); + + dialog.TopMessage = serviceMessage; + dialog.TopMessageRandomId = serviceMessage.RandomId; + + CorrectDialogOrder(dialog, dialog.GetDateIndex(), dialog.TopMessage.Index); + } + + if (_eventAggregator != null) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialog, dialog.TopMessage)); + } + } + } + + public void DeleteDecryptedMessage(TLDecryptedMessageBase message, TLPeerBase peer) + { + if (message != null) + { + RemoveDecryptedMessageFromContext(message); + //MessagesContext.Remove(message.Index); + + var commonMessage = message; + if (commonMessage != null) + { + //TLDialog dialog; + var isMessageRemoved = false; + var isDialogRemoved = false; + var isTopMessageUpdated = false; + + var dialog = DialogsContext[peer.Id.Value] as TLEncryptedDialog; + if (dialog != null) + { + lock (_dialogsSyncRoot) + { + dialog.Messages.Remove(commonMessage); + isMessageRemoved = true; + + if (dialog.Messages.Count == 0) + { + DialogsContext.Remove(dialog.Index); + Dialogs.Remove(dialog); + isDialogRemoved = true; + } + else + { + dialog.TopMessage = dialog.Messages[0]; + dialog.TopDecryptedMessageRandomId = dialog.Messages[0].RandomId; + isTopMessageUpdated = true; + } + + CorrectDialogOrder(dialog, dialog.GetDateIndex(), 0); + } + } + + + if (isDialogRemoved && _eventAggregator != null) + { + _eventAggregator.Publish(new DialogRemovedEventArgs(dialog)); + } + if (isTopMessageUpdated && _eventAggregator != null) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialog, dialog.TopMessage)); + } + if (isMessageRemoved && _eventAggregator != null) + { + _eventAggregator.Publish(new MessagesRemovedEventArgs(dialog, commonMessage)); + } + } + } + else + { + throw new NotImplementedException(); + } + } + + public TLMessageBase GetMessage(TLPeerBase peer, TLInt messageId) + { + if (peer is TLPeerChannel) + { + var channelContext = ChannelsContext[peer.Id.Value]; + if (channelContext != null) + { + return channelContext[messageId.Value]; + } + + return null; + } + + return MessagesContext[messageId.Value]; + } + + public void DeleteMessages(TLPeerBase peer, TLMessageBase lastMessage, IList messageIds) + { + if (messageIds != null) + { + var messages = new List(); + for (var i = 0; i < messageIds.Count; i++) + { + var message = GetMessage(peer, messageIds[i]); + if (message != null) + { + RemoveMessageFromContext(message); + messages.Add(message); + } + } + + var isDialogRemoved = false; + var isTopMessageUpdated = false; + + var dialogBase = GetDialog(peer); + TLMessageBase topMessage = null; + lock (_dialogsSyncRoot) + { + var broadcast = dialogBase as TLBroadcastDialog; + if (broadcast != null) + { + for (var i = 0; i < messageIds.Count; i++) + { + for (var j = 0; j < broadcast.Messages.Count; j++) + { + if (messageIds[i].Value == broadcast.Messages[j].Index) + { + broadcast.Messages.RemoveAt(j); + break; + } + } + } + + if (broadcast.Messages.Count == 0) + { + if (lastMessage == null) + { + DialogsContext.Remove(dialogBase.Index); + Dialogs.Remove(dialogBase); + isDialogRemoved = true; + } + else + { + broadcast.Messages.Add(lastMessage); + broadcast._topMessage = broadcast.Messages[0]; + broadcast.TopMessageId = broadcast.Messages[0].Id; + broadcast.TopMessageRandomId = broadcast.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = broadcast.TopMessage; + } + } + else + { + broadcast._topMessage = broadcast.Messages[0]; + broadcast.TopMessageId = broadcast.Messages[0].Id; + broadcast.TopMessageRandomId = broadcast.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = broadcast.TopMessage; + } + + CorrectDialogOrder(broadcast, broadcast.GetDateIndex(), broadcast.TopMessage.Index); + } + + var dialog = dialogBase as TLDialog; + if (dialog != null) + { + for (var i = 0; i < messageIds.Count; i++) + { + for (var j = 0; j < dialog.Messages.Count; j++) + { + if (messageIds[i].Value == dialog.Messages[j].Index) + { + dialog.Messages.RemoveAt(j); + break; + } + } + } + + if (dialog.Messages.Count == 0) + { + if (lastMessage == null) + { + DialogsContext.Remove(dialogBase.Index); + Dialogs.Remove(dialogBase); + isDialogRemoved = true; + } + else + { + dialog.Messages.Add(lastMessage); + dialog._topMessage = dialog.Messages[0]; + dialog.TopMessageId = dialog.Messages[0].Id; + dialog.TopMessageRandomId = dialog.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = dialog.TopMessage; + } + } + else + { + dialog._topMessage = dialog.Messages[0]; + dialog.TopMessageId = dialog.Messages[0].Id; + dialog.TopMessageRandomId = dialog.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = dialog.TopMessage; + } + + CorrectDialogOrder(dialog, dialog.GetDateIndex(), dialog.TopMessage.Index); + } + } + + if (isDialogRemoved && _eventAggregator != null) + { + _eventAggregator.Publish(new DialogRemovedEventArgs(dialogBase)); + } + if (isTopMessageUpdated && _eventAggregator != null) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialogBase, topMessage)); + } + if (_eventAggregator != null) + { + _eventAggregator.Publish(new MessagesRemovedEventArgs(dialogBase, messages)); + } + } + else + { + throw new NotImplementedException(); + } + } + + public void DeleteUserHistory(TLPeerBase channel, TLPeerBase user) + { + var isMessageRemoved = false; + var isDialogRemoved = false; + var isTopMessageUpdated = false; + TLMessageBase topMessage = null; + + var dialogBase = GetDialog(channel); + + var messages = new List(); + + lock (_dialogsSyncRoot) + { + var broadcast = dialogBase as TLBroadcastDialog; + if (broadcast != null) + { + for (var j = 0; j < broadcast.Messages.Count; j++) + { + var messageCommon = broadcast.Messages[j] as TLMessageCommon; + if (messageCommon != null + && messageCommon.FromId.Value == user.Id.Value) + { + messages.Add(messageCommon); + broadcast.Messages.RemoveAt(j--); + } + } + + isMessageRemoved = true; + + if (broadcast.Messages.Count == 0) + { + DialogsContext.Remove(dialogBase.Index); + Dialogs.Remove(dialogBase); + isDialogRemoved = true; + } + else + { + broadcast._topMessage = broadcast.Messages[0]; + broadcast.TopMessageId = broadcast.Messages[0].Id; + broadcast.TopMessageRandomId = broadcast.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = broadcast.TopMessage; + } + } + + var dialog = dialogBase as TLDialog; + if (dialog != null) + { + for (var j = 0; j < dialog.Messages.Count; j++) + { + var messageCommon = dialog.Messages[j] as TLMessageCommon; + if (messageCommon != null + && messageCommon.FromId.Value == user.Id.Value) + { + if (messageCommon.Index == 1) + { + var message = messageCommon as TLMessageService; + if (message != null) + { + var channelMigrateFrom = message.Action as TLMessageActionChannelMigrateFrom; + if (channelMigrateFrom != null) + { + continue; + } + } + } + + messages.Add(messageCommon); + dialog.Messages.RemoveAt(j--); + } + } + + isMessageRemoved = true; + + if (dialog.Messages.Count == 0) + { + DialogsContext.Remove(dialogBase.Index); + Dialogs.Remove(dialogBase); + isDialogRemoved = true; + } + else + { + var dialog71 = dialog as TLDialog71; + for (var i = 0; i < messages.Count; i++) + { + var commonMessage = messages[i] as TLMessageCommon; + var message70 = messages[i] as TLMessage70; + if (commonMessage != null && !commonMessage.Out.Value && commonMessage.Unread.Value) + { + dialog.UnreadCount = new TLInt(Math.Max(0, dialog.UnreadCount.Value - 1)); + + if (dialog71 != null && message70 != null && message70.FwdHeader == null && message70.IsMention) + { + dialog71.UnreadMentionsCount = new TLInt(Math.Max(0, dialog71.UnreadMentionsCount.Value - 1)); + } + } + } + + dialog._topMessage = dialog.Messages[0]; + dialog.TopMessageId = dialog.Messages[0].Id; + dialog.TopMessageRandomId = dialog.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = dialog.TopMessage; + } + } + } + + for (var i = 0; i < messages.Count; i++) + { + var message = messages[i]; + if (message != null) + { + RemoveMessageFromContext(message); + } + } + + if (topMessage != null) + { + CorrectDialogOrder(dialogBase, dialogBase.GetDateIndex(), topMessage.Index); + } + + if (isDialogRemoved && _eventAggregator != null) + { + _eventAggregator.Publish(new DialogRemovedEventArgs(dialogBase)); + } + if (isTopMessageUpdated && _eventAggregator != null) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialogBase, topMessage)); + } + if (isMessageRemoved && _eventAggregator != null) + { + _eventAggregator.Publish(new MessagesRemovedEventArgs(dialogBase, messages)); + } + } + + public void DeleteMessages(IList messages, TLPeerBase peer) + { + var isMessageRemoved = false; + var isDialogRemoved = false; + var isTopMessageUpdated = false; + TLMessageBase topMessage = null; + + var dialogBase = GetDialog(peer); + + for (var i = 0; i < messages.Count; i++) + { + var message = messages[i]; + if (message != null) + { + RemoveMessageFromContext(message); + } + } + + lock (_dialogsSyncRoot) + { + var broadcast = dialogBase as TLBroadcastDialog; + if (broadcast != null) + { + for (var i = 0; i < messages.Count; i++) + { + for (var j = 0; j < broadcast.Messages.Count; j++) + { + if (messages[i].Id.Value == broadcast.Messages[j].Index) + { + broadcast.Messages.RemoveAt(j); + break; + } + } + } + + isMessageRemoved = true; + + if (broadcast.Messages.Count == 0) + { + DialogsContext.Remove(dialogBase.Index); + Dialogs.Remove(dialogBase); + isDialogRemoved = true; + } + else + { + broadcast._topMessage = broadcast.Messages[0]; + broadcast.TopMessageId = broadcast.Messages[0].Id; + broadcast.TopMessageRandomId = broadcast.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = broadcast.TopMessage; + } + } + + var dialog = dialogBase as TLDialog; + if (dialog != null) + { + for (var i = 0; i < messages.Count; i++) + { + for (var j = 0; j < dialog.Messages.Count; j++) + { + if (messages[i].Id.Value == dialog.Messages[j].Index) + { + dialog.Messages.RemoveAt(j); + break; + } + } + } + + isMessageRemoved = true; + + if (dialog.Messages.Count == 0) + { + DialogsContext.Remove(dialogBase.Index); + Dialogs.Remove(dialogBase); + isDialogRemoved = true; + } + else + { + var dialog71 = dialog as TLDialog71; + for (var i = 0; i < messages.Count; i++) + { + var commonMessage = messages[i] as TLMessageCommon; + var message70 = messages[i] as TLMessage70; + if (commonMessage != null && !commonMessage.Out.Value && commonMessage.Unread.Value) + { + dialog.UnreadCount = new TLInt(Math.Max(0, dialog.UnreadCount.Value - 1)); + + if (dialog71 != null && message70 != null && message70.FwdHeader == null && message70.IsMention) + { + dialog71.UnreadMentionsCount = new TLInt(Math.Max(0, dialog71.UnreadMentionsCount.Value - 1)); + } + } + } + + dialog._topMessage = dialog.Messages[0]; + dialog.TopMessageId = dialog.Messages[0].Id; + dialog.TopMessageRandomId = dialog.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = dialog.TopMessage; + } + } + } + + if (topMessage != null) + { + CorrectDialogOrder(dialogBase, dialogBase.GetDateIndex(), topMessage.Index); + } + + if (isDialogRemoved && _eventAggregator != null) + { + _eventAggregator.Publish(new DialogRemovedEventArgs(dialogBase)); + } + if (isTopMessageUpdated && _eventAggregator != null) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialogBase, topMessage)); + } + if (isMessageRemoved && _eventAggregator != null) + { + _eventAggregator.Publish(new MessagesRemovedEventArgs(dialogBase, messages)); + } + } + + public void DeleteMessage(TLMessageBase message) + { + if (message != null) + { + RemoveMessageFromContext(message); + //MessagesContext.Remove(message.Index); + + var commonMessage = message as TLMessageCommon; + var message70 = message as TLMessage70; + if (commonMessage != null) + { + //TLDialog dialog; + var isMessageRemoved = false; + var isDialogRemoved = false; + var isTopMessageUpdated = false; + + var dialogBase = GetDialog(commonMessage); + TLMessageBase topMessage = null; + lock (_dialogsSyncRoot) + { + //dialog = Dialogs.FirstOrDefault(x => x.WithId == peer.Id.Value && x.IsChat == peer is TLPeerChat); + var broadcast = dialogBase as TLBroadcastDialog; + if (broadcast != null) + { + broadcast.Messages.Remove(commonMessage); + isMessageRemoved = true; + + if (broadcast.Messages.Count == 0) + { + DialogsContext.Remove(dialogBase.Index); + Dialogs.Remove(dialogBase); + isDialogRemoved = true; + } + else + { + broadcast.TopMessage = broadcast.Messages[0]; + broadcast.TopMessageId = broadcast.Messages[0].Id; + broadcast.TopMessageRandomId = broadcast.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = broadcast.TopMessage; + } + + CorrectDialogOrder(broadcast, broadcast.GetDateIndex(), broadcast.TopMessage.Index); + } + + var dialog = dialogBase as TLDialog; + if (dialog != null) + { + dialog.Messages.Remove(commonMessage); + isMessageRemoved = true; + + if (dialog.Messages.Count == 0) + { + DialogsContext.Remove(dialogBase.Index); + Dialogs.Remove(dialogBase); + isDialogRemoved = true; + } + else + { + var dialog71 = dialog as TLDialog71; + if (!commonMessage.Out.Value && commonMessage.Unread.Value) + { + dialog.UnreadCount = new TLInt(Math.Max(0, dialog.UnreadCount.Value - 1)); + if (dialog71 != null && message70 != null && message70.FwdHeader == null && message70.IsMention) + { + dialog71.UnreadMentionsCount = new TLInt(Math.Max(0, dialog71.UnreadMentionsCount.Value - 1)); + } + } + dialog.TopMessage = dialog.Messages[0]; + dialog.TopMessageId = dialog.Messages[0].Id; + dialog.TopMessageRandomId = dialog.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = dialog.TopMessage; + } + + CorrectDialogOrder(dialog, dialog.GetDateIndex(), dialog.TopMessage.Index); + } + } + + if (isDialogRemoved && _eventAggregator != null) + { + _eventAggregator.Publish(new DialogRemovedEventArgs(dialogBase)); + } + if (isTopMessageUpdated && _eventAggregator != null) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialogBase, topMessage)); + } + if (isMessageRemoved && _eventAggregator != null) + { + _eventAggregator.Publish(new MessagesRemovedEventArgs(dialogBase, commonMessage)); + } + } + } + else + { + throw new NotImplementedException(); + } + } + + public void ReplaceUser(int index, TLUserBase user) + { + var cachedUser = UsersContext[index]; + if (cachedUser == null) + { + UsersContext[index] = user; + } + else + { + UsersContext[index] = user; + + lock (_dialogsSyncRoot) + { + foreach (var dialog in Dialogs) + { + if (!dialog.IsChat + && dialog.WithId == index) + { + dialog.With = user; + } + } + } + } + } + + public void DeleteUser(TLInt id) + { + UsersContext.Remove(id.Value); + } + + public void DeleteUser(TLUserBase user) + { + UsersContext.Remove(user.Index); + } + + public void ReplaceChat(int index, TLChatBase chat) + { + var cachedChat = ChatsContext[index]; + if (cachedChat == null) + { + ChatsContext[index] = chat; + } + else + { + ChatsContext[index] = chat; + + lock (_dialogsSyncRoot) + { + foreach (var dialog in Dialogs) + { + if (dialog.IsChat + && dialog.WithId == index) + { + dialog.With = chat; + } + } + } + } + } + + public void ReplaceBroadcast(int index, TLBroadcastChat chat) + { + var cachedChat = BroadcastsContext[index]; + if (cachedChat == null) + { + BroadcastsContext[index] = chat; + } + else + { + BroadcastsContext[index] = chat; + + lock (_dialogsSyncRoot) + { + foreach (var dialog in Dialogs) + { + if (dialog.IsChat + && dialog.WithId == index) + { + dialog._with = chat; + } + } + } + } + } + + public void ReplaceEncryptedChat(int index, TLEncryptedChatBase chat) + { + var cachedChat = EncryptedChatsContext[index]; + if (cachedChat == null) + { + EncryptedChatsContext[index] = chat; + } + else + { + EncryptedChatsContext[index] = chat; + + //lock (_encryptedDialogsSyncRoot) + //{ + // foreach (var dialog in EncryptedDialogs) + // { + // if (dialog.IsChat + // && dialog.WithId == index) + // { + // dialog.With = chat; + // } + // } + //} + } + } + + public void DeleteChat(TLInt id) + { + ChatsContext.Remove(id.Value); + } + + public void DeleteChat(TLChatBase chat) + { + ChatsContext.Remove(chat.Index); + } + + public void DeleteDialog(TLDialogBase dialogBase) + { + lock (_dialogsSyncRoot) + { + var dialog = Dialogs.FirstOrDefault(x => x.Index == dialogBase.Index); + + if (dialog != null) + { + Dialogs.Remove(dialog); + DialogsContext.Remove(dialog.Index); + } + } + } + + public void UpdatePinnedDialogs(TLPeerDialogs peerDialogs) + { + + } + + public void UpdateProxyData(TLProxyDataBase proxyDaya) + { + lock (_dialogsSyncRoot) + { + ProxyData = proxyDaya; + } + } + + public void UpdateDialogPinned(TLPeerBase peer, bool pinned) + { + var dialog = GetDialog(peer) as TLDialog53; + if (dialog != null) + { + lock (_dialogsSyncRoot) + { + if (pinned) + { + dialog.IsPinned = true; + Dialogs.Remove(dialog); + Dialogs.Insert(0, dialog); + + } + else + { + dialog.IsPinned = false; + CorrectDialogOrder(dialog, dialog.GetDateIndex(), 0); + } + + var pinnedId = 0; + foreach (var d in Dialogs) + { + var d53 = d as TLDialog53; + if (d53 != null) + { + if (d53.IsPinned) + { + d53.PinnedId = new TLInt(pinnedId++); + } + else + { + d.PinnedId = null; + } + } + } + } + } + } + + public void UpdateDialogPromo(TLDialogBase dialogBase, bool promo) + { + var dialog = dialogBase as TLDialog71; + if (dialog != null) + { + lock (_dialogsSyncRoot) + { + if (promo) + { + dialog.IsPromo = true; + if (dialogBase.Peer is TLPeerChannel) + { + var channel = ChatsContext[dialogBase.Peer.Id.Value] as TLChannel73; + if (channel != null && !channel.Left.Value) + { + CorrectDialogOrder(dialog, dialog.GetDateIndex(), 0); + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialog, dialog.TopMessage)); + } + else + { + Dialogs.Remove(dialog); + Dialogs.Insert(0, dialog); + _eventAggregator.Publish(new DialogAddedEventArgs(dialog)); + } + } + else + { + Dialogs.Remove(dialog); + Dialogs.Insert(0, dialog); + _eventAggregator.Publish(new DialogAddedEventArgs(dialog)); + } + + } + else + { + dialog.IsPromo = false; + if (dialogBase.Peer is TLPeerChannel) + { + var channel = ChatsContext[dialogBase.Peer.Id.Value] as TLChannel73; + if (channel != null && !channel.Left.Value) + { + CorrectDialogOrder(dialog, dialog.GetDateIndex(), 0); + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialog, dialog.TopMessage)); + } + else + { + Dialogs.Remove(dialog); + _eventAggregator.Publish(new DialogRemovedEventArgs(dialog)); + } + } + else + { + Dialogs.Remove(dialog); + _eventAggregator.Publish(new DialogRemovedEventArgs(dialog)); + } + } + + var pinnedId = 0; + foreach (var d in Dialogs) + { + var d53 = d as TLDialog53; + if (d53 != null) + { + if (d53.IsPinned) + { + d53.PinnedId = new TLInt(pinnedId++); + } + else + { + d.PinnedId = null; + } + } + } + } + } + } + + public void UpdateChannelAvailableMessages(TLPeerBase peer, TLInt availableMinId) + { + var channel = ChatsContext[peer.Id.Value] as TLChannel68; + if (channel != null) + { + channel.AvailableMinId = availableMinId; + } + + var messages = new List(); + + var isDialogRemoved = false; + var isTopMessageUpdated = false; + + var dialogBase = GetDialog(peer); + TLMessageBase topMessage = null; + lock (_dialogsSyncRoot) + { + var dialog = dialogBase as TLDialog; + if (dialog != null) + { + var updatedIndex = -1; + for (var i = 0; i < dialog.Messages.Count; i++) + { + if (dialog.Messages[i].Index > 0 && dialog.Messages[i].Index <= availableMinId.Value) + { + if (updatedIndex == -1) + { + updatedIndex = i; + } + else + { + messages.Add(dialog.Messages[i]); + dialog.Messages.RemoveAt(i--); + } + } + } + + if (updatedIndex >= 0 && updatedIndex < dialog.Messages.Count) + { + var messageCommon = dialog.Messages[updatedIndex] as TLMessageCommon; + if (messageCommon != null) + { + var clearHistoryMessage = new TLMessageService49(); + clearHistoryMessage.Flags = new TLInt(0); + clearHistoryMessage.Id = messageCommon.Id; + clearHistoryMessage.FromId = messageCommon.FromId ?? new TLInt(-1); + clearHistoryMessage.ToId = messageCommon.ToId; + clearHistoryMessage.Date = messageCommon.Date; + clearHistoryMessage.Out = messageCommon.Out; + clearHistoryMessage.Action = new TLMessageActionClearHistory(); + + dialog.Messages[updatedIndex] = clearHistoryMessage; + } + } + + dialog.UnreadCount = new TLInt(0); + var dialog71 = dialog as TLDialog71; + if (dialog71 != null) + { + dialog71.UnreadMentionsCount = new TLInt(0); + } + + if (dialog.Messages.Count == 0) + { + DialogsContext.Remove(dialogBase.Index); + Dialogs.Remove(dialogBase); + isDialogRemoved = true; + } + else + { + dialog._topMessage = dialog.Messages[0]; + dialog.TopMessageId = dialog.Messages[0].Id; + dialog.TopMessageRandomId = dialog.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = dialog.TopMessage; + } + } + } + + for (var i = 0; i < messages.Count; i++) + { + RemoveMessageFromContext(messages[i]); + } + + if (isDialogRemoved && _eventAggregator != null) + { + _eventAggregator.Publish(new DialogRemovedEventArgs(dialogBase)); + } + if (isTopMessageUpdated && _eventAggregator != null) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialogBase, topMessage)); + } + if (_eventAggregator != null) + { + _eventAggregator.Publish(new ChannelAvailableMessagesEventArgs(dialogBase, availableMinId)); + } + } + + public void ClearDialog(TLPeerBase peer) + { + var messages = new List(); + + var isDialogRemoved = false; + var isTopMessageUpdated = false; + + var dialogBase = GetDialog(peer); + TLMessageBase topMessage = null; + lock (_dialogsSyncRoot) + { + var broadcast = dialogBase as TLBroadcastDialog; + if (broadcast != null) + { + for (var i = 1; i < broadcast.Messages.Count; i++) + { + broadcast.Messages.RemoveAt(i--); + } + + if (broadcast.Messages.Count == 0) + { + DialogsContext.Remove(dialogBase.Index); + Dialogs.Remove(dialogBase); + isDialogRemoved = true; + } + else + { + broadcast._topMessage = broadcast.Messages[0]; + broadcast.TopMessageId = broadcast.Messages[0].Id; + broadcast.TopMessageRandomId = broadcast.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = broadcast.TopMessage; + } + + //CorrectDialogOrder(broadcast, broadcast.TopMessage.DateIndex, broadcast.TopMessage.Index); + } + + var dialog = dialogBase as TLDialog; + if (dialog != null) + { + var updatedIndex = -1; + for (var i = 0; i < dialog.Messages.Count; i++) + { + if (dialog.Messages[i].Index > 0) + { + if (updatedIndex == -1) + { + updatedIndex = i; + } + else + { + messages.Add(dialog.Messages[i]); + dialog.Messages.RemoveAt(i--); + } + } + } + + if (updatedIndex >= 0 && updatedIndex < dialog.Messages.Count) + { + var messageCommon = dialog.Messages[updatedIndex] as TLMessageCommon; + if (messageCommon != null) + { + var clearHistoryMessage = new TLMessageService49(); + clearHistoryMessage.Flags = new TLInt(0); + clearHistoryMessage.Id = messageCommon.Id; + clearHistoryMessage.FromId = messageCommon.FromId ?? new TLInt(-1); + clearHistoryMessage.ToId = messageCommon.ToId; + clearHistoryMessage.Date = messageCommon.Date; + clearHistoryMessage.Out = messageCommon.Out; + clearHistoryMessage.Action = new TLMessageActionClearHistory(); + + dialog.Messages[updatedIndex] = clearHistoryMessage; + + RemoveMessageFromContext(messageCommon); + AddMessageToContext(clearHistoryMessage); + } + } + + dialog.UnreadCount = new TLInt(0); + var dialog71 = dialog as TLDialog71; + if (dialog71 != null) + { + dialog71.UnreadMentionsCount = new TLInt(0); + } + + if (dialog.Messages.Count == 0) + { + DialogsContext.Remove(dialogBase.Index); + Dialogs.Remove(dialogBase); + isDialogRemoved = true; + } + else + { + dialog._topMessage = dialog.Messages[0]; + dialog.TopMessageId = dialog.Messages[0].Id; + dialog.TopMessageRandomId = dialog.Messages[0].RandomId; + isTopMessageUpdated = true; + topMessage = dialog.TopMessage; + } + + //CorrectDialogOrder(dialog, dialog.TopMessage.DateIndex, dialog.TopMessage.Index); + } + } + + for (var i = 0; i < messages.Count; i++) + { + RemoveMessageFromContext(messages[i]); + } + + if (isDialogRemoved && _eventAggregator != null) + { + _eventAggregator.Publish(new DialogRemovedEventArgs(dialogBase)); + } + if (isTopMessageUpdated && _eventAggregator != null) + { + _eventAggregator.Publish(new TopMessageUpdatedEventArgs(dialogBase, topMessage)); + } + if (_eventAggregator != null) + { + _eventAggregator.Publish(new MessagesRemovedEventArgs(dialogBase, messages)); + } + } + + private static bool _logEnabled = true; + + private static void Log(string str) + { + if (!_logEnabled) return; + + Debug.WriteLine(str); + } + + public void Open() + { + try + { + + Log("InMemoryDatabase.Open"); + //TLObject.LogNotify = true; + var timer = Stopwatch.StartNew(); + + var t1 = Task.Factory.StartNew(() => + { + var usersTimer = Stopwatch.StartNew(); + var users = TLUtils.OpenObjectFromMTProtoFile>(_usersSyncRoot, UsersMTProtoFileName) ?? new TLVector(); + Log(string.Format("Open users time ({0}) : {1}", users.Count, usersTimer.Elapsed)); + + foreach (var user in users) + { + UsersContext[user.Index] = user; + } + }); + + var t2 = Task.Factory.StartNew(() => + { + var chatsTimer = Stopwatch.StartNew(); + var chats = TLUtils.OpenObjectFromMTProtoFile>(_chatsSyncRoot, ChatsMTProtoFileName) ?? new TLVector(); + Log(string.Format("Open chats time ({0}) : {1}", chats.Count, chatsTimer.Elapsed)); + + foreach (var chat in chats) + { + ChatsContext[chat.Index] = chat; + } + }); + + var t3 = Task.Factory.StartNew(() => + { + var broadcastsTimer = Stopwatch.StartNew(); + var broadcasts = TLUtils.OpenObjectFromMTProtoFile>(_broadcastsSyncRoot, BroadcastsMTProtoFileName) ?? new TLVector(); + Log(string.Format("Open broadcasts time ({0}) : {1}", broadcasts.Count, broadcastsTimer.Elapsed)); + + foreach (var broadcast in broadcasts) + { + BroadcastsContext[broadcast.Index] = broadcast; + } + }); + + var t4 = Task.Factory.StartNew(() => + { + var encryptedChatsTimer = Stopwatch.StartNew(); + var encryptedChats = TLUtils.OpenObjectFromMTProtoFile>(_encryptedChatsSyncRoot, EncryptedChatsMTProtoFileName) ?? new TLVector(); + Log(string.Format("Open encrypted chats time ({0}) : {1}", encryptedChats.Count, encryptedChatsTimer.Elapsed)); + + foreach (var encryptedChat in encryptedChats) + { + EncryptedChatsContext[encryptedChat.Index] = encryptedChat; + } + }); + + var t5 = Task.Factory.StartNew(() => + { + var dialogsTimer = Stopwatch.StartNew(); + var dialogs = TLUtils.OpenObjectFromMTProtoFile>(_dialogsFileSyncRoot, DialogsMTProtoFileName) ?? new TLVector(); + Dialogs = new ObservableCollection(dialogs.Items); + Log(string.Format("Open dialogs time ({0}) : {1}", dialogs.Count, dialogsTimer.Elapsed)); + + foreach (var dialog in dialogs) + { + DialogsContext[dialog.Index] = dialog; + } + }); + + var t6 = Task.Factory.StartNew(() => + { + var proxyDataTimer = Stopwatch.StartNew(); + var proxyData = TLUtils.OpenObjectFromMTProtoFile(_proxyDataSyncRoot, ProxyDataMTProtoFileName); + ProxyData = proxyData; + Log(string.Format("Open proxy data time : {0}", proxyDataTimer.Elapsed)); + }); + + Task.WaitAll(t1, t2, t3, t4, t5, t6); + //TelegramPropertyChangedBase.IsNotifyingGlobal = true; + //WaitHandle.WaitAll(handles.ToArray()); + + Log("Open DB files time: " + timer.Elapsed); + MessagesContext.Clear(); + ChannelsContext.Clear(); + lock (_dialogsSyncRoot) + { + ResendingMessages = new List(); + ResendingDecryptedMessages = new List(); + foreach (var d in Dialogs) + { + var encryptedDialog = d as TLEncryptedDialog; + var broadcastDialog = d as TLBroadcastDialog; + if (encryptedDialog != null) + { + //var peer = encryptedDialog.Peer; + //if (peer is TLPeerEncryptedChat) + //{ + // var encryptedChat = EncryptedChatsContext[peer.Id.Value] as TLEncryptedChatCommon; + // if (encryptedChat != null) + // { + // encryptedDialog._with = UsersContext[encryptedChat.ParticipantId.Value]; + // } + //} + + encryptedDialog._topMessage = encryptedDialog.Messages.FirstOrDefault(); + encryptedDialog.TopDecryptedMessageRandomId = encryptedDialog.TopMessage != null ? encryptedDialog.TopMessage.RandomId : null; + if (encryptedDialog.TopMessageId == null) + { + encryptedDialog.TopMessageRandomId = encryptedDialog.TopMessage != null ? encryptedDialog.TopMessage.RandomId : null; + } + foreach (var message in encryptedDialog.Messages) + { + if (message.Status == MessageStatus.Sending + || message.Status == MessageStatus.Compressing) + { + message.Status = MessageStatus.Failed; + ResendingDecryptedMessages.Add(message); + } + + if (message.RandomIndex != 0) + { + DecryptedMessagesContext[message.RandomIndex] = message; + } + } + } + else if (broadcastDialog != null) + { + var dialog = broadcastDialog; + var peer = dialog.Peer; + var broadcastChat = ChatsContext[peer.Id.Value]; + if (broadcastChat != null) + { + dialog._with = broadcastChat; + } + else + { + broadcastChat = dialog.With as TLBroadcastChat; + if (broadcastChat != null) + { + ChatsContext[broadcastChat.Index] = broadcastChat; + } + } + + dialog._topMessage = dialog.Messages.FirstOrDefault(); + dialog.TopMessageId = dialog.TopMessage != null ? dialog.TopMessage.Id : null; + if (dialog.TopMessageId == null) + { + dialog.TopMessageRandomId = dialog.TopMessage != null ? dialog.TopMessage.RandomId : null; + } + foreach (var message in dialog.Messages) + { + if (message.Status == MessageStatus.Sending + || message.Status == MessageStatus.Compressing) + { + message._status = message.Index != 0 ? MessageStatus.Confirmed : MessageStatus.Failed; + ResendingMessages.Add(message); + } + + AddMessageToContext(message); + if (message.RandomIndex != 0) + { + RandomMessagesContext[message.RandomIndex] = message; + } + } + } + else + { + var dialog = (TLDialog)d; + var peer = dialog.Peer; + if (peer is TLPeerUser) + { + var user = UsersContext[peer.Id.Value]; + if (user != null) + { + dialog._with = user; + } + else + { + var userBase = dialog.With as TLUserBase; + if (userBase != null) + { + UsersContext[userBase.Index] = userBase; + } + } + } + else if (peer is TLPeerChat) + { + var chat = ChatsContext[peer.Id.Value]; + if (chat != null) + { + dialog._with = chat; + } + else + { + var chatBase = dialog.With as TLChatBase; + if (chatBase != null) + { + ChatsContext[chatBase.Index] = chatBase; + } + } + } + else if (peer is TLPeerBroadcast) + { + var broadcastChat = ChatsContext[peer.Id.Value]; + if (broadcastChat != null) + { + dialog._with = broadcastChat; + } + else + { + broadcastChat = dialog.With as TLBroadcastChat; + if (broadcastChat != null) + { + ChatsContext[broadcastChat.Index] = broadcastChat; + } + } + } + else if (peer is TLPeerChannel) + { + var channel = ChatsContext[peer.Id.Value]; + if (channel != null) + { + dialog._with = channel; + } + else + { + channel = dialog.With as TLChannel; + if (channel != null) + { + ChatsContext[channel.Index] = channel; + } + } + + var dialogFeed = dialog as TLDialogFeed; + if (dialogFeed != null) + { + var channels = new TLVector(); + foreach (var channelId in dialogFeed.FeedOtherChannels) + { + var ch = ChatsContext[channelId.Value]; + if (ch != null) + { + channels.Add(ch); + } + } + dialogFeed._with = channels; + } + } + + dialog._topMessage = dialog.Messages.FirstOrDefault(); + dialog.TopMessageId = dialog.TopMessage != null ? dialog.TopMessage.Id : null; + if (dialog.TopMessageId == null) + { + dialog.TopMessageRandomId = dialog.TopMessage != null ? dialog.TopMessage.RandomId : null; + } + foreach (var message in dialog.Messages) + { + if (message.Status == MessageStatus.Sending + || message.Status == MessageStatus.Compressing) + { + message._status = message.Index != 0 ? MessageStatus.Confirmed : MessageStatus.Failed; + ResendingMessages.Add(message); + } + + AddMessageToContext(message); + if (message.RandomIndex != 0) + { + RandomMessagesContext[message.RandomIndex] = message; + } + } + } + + } + } + _isOpened = true; + + //#if DEBUG + Execute.BeginOnThreadPool(() => + { + FileUtils.Copy(_usersSyncRoot, UsersMTProtoFileName, TempUsersMTProtoFileName); + FileUtils.Copy(_chatsSyncRoot, ChatsMTProtoFileName, TempChatsMTProtoFileName); + FileUtils.Copy(_broadcastsSyncRoot, BroadcastsMTProtoFileName, TempBroadcastsMTProtoFileName); + FileUtils.Copy(_encryptedChatsSyncRoot, EncryptedChatsMTProtoFileName, TempEncryptedChatsMTProtoFileName); + FileUtils.Copy(_dialogsSyncRoot, DialogsMTProtoFileName, TempDialogsMTProtoFileName); + }); + //#endif + + //TLObject.LogNotify = false; + Log("Open DB time: " + timer.Elapsed); + //TLUtils.WritePerformance("Open DB time: " + timer.Elapsed); + } + catch (Exception e) + { + TLUtils.WriteLine("DB ERROR: open DB error", LogSeverity.Error); + TLUtils.WriteException(e); + } + } + + public IList ResendingMessages { get; protected set; } + public IList ResendingDecryptedMessages { get; protected set; } + + public event EventHandler CommitInvoked; + + protected virtual void RaiseCommitInvoked() + { + var handler = CommitInvoked; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public void Commit() + { + RaiseCommitInvoked(); + HasChanges = true; + } + + public void CommitInternal() + { + //return; + //return; + if (!_isOpened) return; + + var timer = Stopwatch.StartNew(); + + //truncate commiting DB + var dialogs = new List(); + var messagesCount = 0; + lock (_dialogsSyncRoot) + { + var importantCount = 0; + for (var i = 0; i < Dialogs.Count && importantCount < Constants.CachedDialogsCount; i++) + { + dialogs.Add(Dialogs[i]); + + var chat = Dialogs[i].With as TLChat41; + if (chat == null || !chat.IsMigrated) + { + importantCount++; + } + } + foreach (var d in dialogs) + { + var dialog = d as TLDialog; + if (dialog != null) + { + var chat = dialog.With as TLChat41; + if (chat != null && chat.IsMigrated) + { + //dialog.Messages = new ObservableCollection(dialog.Messages.Take(Constants.CachedMessagesCount)); + dialog.CommitMessages = dialog.Messages.Take(Constants.CachedMessagesCount).ToList(); + } + else + { + //dialog.Messages = new ObservableCollection(dialog.Messages.Take(Constants.CachedMessagesCount)); + dialog.CommitMessages = dialog.Messages.Take(Constants.CachedMessagesCount).ToList(); + } + messagesCount += dialog.Messages.Count; + } + } + } + + var mtProtoDialogs = new TLVector { Items = dialogs }; + if (ProxyData != null) { TLUtils.SaveObjectToMTProtoFile(_proxyDataSyncRoot, ProxyDataMTProtoFileName, ProxyData); } + else { FileUtils.Delete(_proxyDataSyncRoot, ProxyDataMTProtoFileName); } + TLUtils.SaveObjectToMTProtoFile(_dialogsFileSyncRoot, DialogsMTProtoFileName, mtProtoDialogs); + TLUtils.SaveObjectToMTProtoFile(_usersSyncRoot, UsersMTProtoFileName, new TLVector { Items = UsersContext.Values.ToList() }); + TLUtils.SaveObjectToMTProtoFile(_chatsSyncRoot, ChatsMTProtoFileName, new TLVector { Items = ChatsContext.Values.ToList() }); + TLUtils.SaveObjectToMTProtoFile(_broadcastsSyncRoot, BroadcastsMTProtoFileName, new TLVector { Items = BroadcastsContext.Values.ToList() }); + TLUtils.SaveObjectToMTProtoFile(_encryptedChatsSyncRoot, EncryptedChatsMTProtoFileName, new TLVector { Items = EncryptedChatsContext.Values.ToList() }); + + HasChanges = false; + + TLUtils.WritePerformance(string.Format("Commit DB time ({0}d, {1}u, {2}c, {6}b, {5}ec, {4}m): {3}", dialogs.Count, UsersContext.Count, ChatsContext.Count, timer.Elapsed, messagesCount, EncryptedChatsContext.Count, BroadcastsContext.Count)); + } + + public int CountRecords() where T : TLObject + { + var result = 0; + if (typeof(T) == typeof(TLMessageBase)) + { + lock (_dialogsSyncRoot) + { + foreach (var dialog in Dialogs) + { + result += dialog.CountMessages(); + } + } + + } + else if (typeof(T) == typeof(TLDialog)) + { + result += Dialogs.Count; + } + else if (typeof(T) == typeof(TLUserBase)) + { + result += UsersContext.Count; + } + else if (typeof(T) == typeof(TLBroadcastChat)) + { + result += BroadcastsContext.Count; + } + else if (typeof(T) == typeof(TLChatBase)) + { + result += ChatsContext.Count; + } + else + { + throw new NotImplementedException(); + } + + return result; + } + + public void Dispose() + { + _commitSubscription.Dispose(); + } + + public void Compress() + { + lock (_dialogsSyncRoot) + { + MessagesContext.Clear(); + for (var i = 0; i < Dialogs.Count; i++) + { + var dialog = Dialogs[i] as TLDialog; + if (dialog != null) + { + dialog.Messages = new ObservableCollection(dialog.Messages.Take(1)); + + var message = dialog.Messages.FirstOrDefault(); + if (message != null) + { + AddMessageToContext(message); + } + } + } + } + + CommitInternal(); + } + + public void ClearLocalFileNames() + { + lock (_dialogsSyncRoot) + { + MessagesContext.Clear(); + for (var i = 0; i < Dialogs.Count; i++) + { + var dialog = Dialogs[i] as TLDialog; + if (dialog != null) + { + for (var j = 0; j < dialog.Messages.Count; j++) + { + var message = dialog.Messages[j] as TLMessage; + if (message != null) + { + var media = message.Media as TLMessageMediaDocument; + if (media != null) + { + media.IsoFileName = null; + } + } + } + } + } + } + + CommitInternal(); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/Connection/ConnectionService.cs b/Telegram.Api/Services/Connection/ConnectionService.cs new file mode 100755 index 0000000..8e425e5 --- /dev/null +++ b/Telegram.Api/Services/Connection/ConnectionService.cs @@ -0,0 +1,366 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using System.Globalization; +using System.Text; +using System.Threading; +using Telegram.Api.Services.DeviceInfo; +#if WP8 || WIN_RT +using Windows.Networking.Connectivity; +#endif +#if WINDOWS_PHONE +using Microsoft.Phone.Net.NetworkInformation; +#endif +using Telegram.Api.Helpers; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Connection +{ + public interface IConnectionService + { + void Initialize(IMTProtoService mtProtoService); + event EventHandler ConnectionLost; + } + + public class ConnectionService : IConnectionService + { + public event EventHandler ConnectionLost; + + protected virtual void RaiseConnectionFailed() + { + var handler = ConnectionLost; + if (handler != null) handler(this, EventArgs.Empty); + } + + private IMTProtoService _mtProtoService; + + public void Initialize(IMTProtoService mtProtoService) + { + _mtProtoService = mtProtoService; + } + + private Timer _connectionScheduler; + + private bool _isNetworkAwailable; + +#if WP8 || WIN_RT + private ConnectionProfile _profile; + private NetworkConnectivityLevel? _connectivityLevel; +#endif + + public ConnectionService(IDeviceInfoService deviceInfoService) + { + if (deviceInfoService != null && deviceInfoService.IsBackground) + { + return; + } + + _connectionScheduler = new Timer(CheckConnectionState, this, TimeSpan.FromSeconds(0.0), TimeSpan.FromSeconds(5.0)); + +#if WINDOWS_PHONE + _isNetworkAwailable = DeviceNetworkInformation.IsNetworkAvailable; +#endif + +#if WP8 || WIN_RT + _profile = NetworkInformation.GetInternetConnectionProfile(); + _connectivityLevel = _profile != null ? _profile.GetNetworkConnectivityLevel() : (NetworkConnectivityLevel?)null; + + //var connectivityLevel = _profile.GetNetworkConnectivityLevel(); + //_profile.NetworkAdapter.IanaInterfaceType != 71 // mobile data + //_profile.GetConnectionCost().Roaming; + + //Helpers.Execute.ShowDebugMessage(string.Format("InternetConnectionProfile={0}", _profile != null ? _profile.GetNetworkConnectivityLevel().ToString() : "null")); + + // new solution + NetworkInformation.NetworkStatusChanged += sender => + { + var previousProfile = _profile; + var previousConnectivityLevel = _connectivityLevel; + + _profile = NetworkInformation.GetInternetConnectionProfile(); + _connectivityLevel = _profile != null ? _profile.GetNetworkConnectivityLevel() : (NetworkConnectivityLevel?)null; + + if (_profile != null) + { + if (_mtProtoService == null) return; + + var activeTransport = _mtProtoService.GetActiveTransport(); + if (activeTransport == null) return; + if (activeTransport.AuthKey == null) return; + + var transportId = activeTransport.Id; + + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (!isAuthorized) + { + return; + } + + var errorDebugString = string.Format("{0} internet connected", DateTime.Now.ToString("HH:mm:ss.fff")); + TLUtils.WriteLine(errorDebugString, LogSeverity.Error); + + var reconnect = _connectivityLevel == NetworkConnectivityLevel.InternetAccess && previousConnectivityLevel != NetworkConnectivityLevel.InternetAccess; + if (reconnect) + { + TLUtils.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + " reconnect t" + transportId, LogSeverity.Error); + + Logs.Log.Write(string.Format(" Reconnect reason=NetworkStatusChanged profile={0} internet_access={1} previous_profile={2} previous_internet_access={3}", + _profile != null ? _profile.ProfileName : "none", + _profile != null ? _connectivityLevel.ToString() : "none", + previousProfile != null ? previousProfile.ProfileName : "none", + previousProfile != null ? previousConnectivityLevel.ToString() : "none")); + + RaiseConnectionFailed(); + + return; + } + } + else + { + var errorDebugString = string.Format("{0} internet disconnected", DateTime.Now.ToString("HH:mm:ss.fff")); + TLUtils.WriteLine(errorDebugString, LogSeverity.Error); + + _mtProtoService.SetMessageOnTime(60.0 * 60, "Waiting for network..."); + //Helpers.Execute.ShowDebugMessage(string.Format("NetworkStatusChanged Internet disconnected Profile={0}", _profile)); + } + }; +#endif + +#if WINDOWS_PHONE + // old solution + DeviceNetworkInformation.NetworkAvailabilityChanged += (sender, args) => + { + return; + + var isNetworkAvailable = _isNetworkAwailable; + + _isNetworkAwailable = DeviceNetworkInformation.IsNetworkAvailable; + //if (isNetworkAvailable != _isNetworkAwailable) + { + var info = new StringBuilder(); + info.AppendLine(); + foreach (var networkInterface in new NetworkInterfaceList()) + { + info.AppendLine(string.Format(" {0} {1} {2}", + networkInterface.InterfaceName, + networkInterface.InterfaceState, + networkInterface.InterfaceType)); + } + + var current = new NetworkInterfaceList(); + var ni = NetworkInterface.NetworkInterfaceType; + Helpers.Execute.ShowDebugMessage(string.Format("NetworkAwailabilityChanged Interface={0}\n{1}", ni, info.ToString())); + } + + var networkString = string.Format("{0}, {1}, ", args.NotificationType, + args.NetworkInterface != null ? args.NetworkInterface.InterfaceState.ToString() : "none"); + + var mtProtoService = MTProtoService.Instance; + if (mtProtoService != null) + { + if (args.NotificationType == NetworkNotificationType.InterfaceDisconnected) + { +#if DEBUG + var interfaceSubtype = args.NetworkInterface != null + ? args.NetworkInterface.InterfaceSubtype.ToString() + : "Interface"; + mtProtoService.SetMessageOnTime(2.0, DateTime.Now.ToString("HH:mm:ss.fff ", CultureInfo.InvariantCulture) + interfaceSubtype + " disconnected..."); + TLUtils.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff ", CultureInfo.InvariantCulture) + interfaceSubtype + " disconnected", LogSeverity.Error); +#else + //mtProtoService.SetMessageOnTime(2.0, "No Internet connection"); +#endif + } + else if (args.NotificationType == NetworkNotificationType.InterfaceConnected) + { +#if DEBUG + var interfaceSubtype = args.NetworkInterface != null + ? args.NetworkInterface.InterfaceSubtype.ToString() + : "Interface"; + mtProtoService.SetMessageOnTime(2.0, DateTime.Now.ToString("HH:mm:ss.fff ", CultureInfo.InvariantCulture) + interfaceSubtype + " connected..."); + TLUtils.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff ", CultureInfo.InvariantCulture) + interfaceSubtype + " connected", LogSeverity.Error); +#else + mtProtoService.SetMessageOnTime(0.0, string.Empty); +#endif + } + else if (args.NotificationType == NetworkNotificationType.CharacteristicUpdate) + { + //#if DEBUG + + // mtProtoService.SetMessageOnTime(2.0, "Characteristic update..."); + // var networkInterface = args.NetworkInterface; + // if (networkInterface != null) + // { + // var characteristics = new StringBuilder(); + // characteristics.AppendLine(); + // //characteristics.AppendLine("Description=" + networkInterface.Description); + // characteristics.AppendLine("InterfaceName=" + networkInterface.InterfaceName); + // characteristics.AppendLine("InterfaceState=" + networkInterface.InterfaceState); + // characteristics.AppendLine("InterfaceType=" + networkInterface.InterfaceType); + // characteristics.AppendLine("InterfaceSubtype=" + networkInterface.InterfaceSubtype); + // characteristics.AppendLine("Bandwidth=" + networkInterface.Bandwidth); + // //characteristics.AppendLine("Characteristics=" + networkInterface.Characteristics); + // TLUtils.WriteLine(characteristics.ToString(), LogSeverity.Error); + // } + //#endif + } + } + + }; +#endif + + + } + + private void CheckConnectionState(object state) + { +//#if !WIN_RT && DEBUG +// Microsoft.Devices.VibrateController.Default.Start(TimeSpan.FromMilliseconds(50)); +//#endif + + if (Debugger.IsAttached) return; +//#if DEBUG +// return; +//#endif + + if (_mtProtoService == null) return; + + var activeTransport = _mtProtoService.GetActiveTransport(); + if (activeTransport == null) return; + if (activeTransport.AuthKey == null) return; + + var transportId = activeTransport.Id; + + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (!isAuthorized) + { + return; + } + + var connectionFailed = false; + var now = DateTime.Now; + if (activeTransport.LastReceiveTime.HasValue) + { + connectionFailed = Math.Abs((now - activeTransport.LastReceiveTime.Value).TotalSeconds) > Constants.TimeoutInterval; + if (connectionFailed) + { + Logs.Log.Write(string.Format(" Reconnect reason=ConnectionFailed transport={3} now={0} - last_receive_time={1} > timeout={2}", now.ToString("dd-MM-yyyy HH:mm:ss.fff"), activeTransport.LastReceiveTime.Value.ToString("dd-MM-yyyy HH:mm:ss.fff"), Constants.TimeoutInterval, activeTransport.Id)); + } + } + else + { + if (activeTransport.FirstSendTime.HasValue) + { + connectionFailed = Math.Abs((now - activeTransport.FirstSendTime.Value).TotalSeconds) > Constants.TimeoutInterval; + if (connectionFailed) + { + Logs.Log.Write(string.Format(" Reconnect reason=ConnectionFailed transport={3} now={0} - first_send_time={1} > timeout={2}", now.ToString("dd-MM-yyyy HH:mm:ss.fff"), activeTransport.FirstSendTime.Value.ToString("dd-MM-yyyy HH:mm:ss.fff"), Constants.TimeoutInterval, activeTransport.Id)); + } + } + } + + if (connectionFailed) + { + RaiseConnectionFailed(); + TLUtils.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + " reconnect t" + transportId, LogSeverity.Error); + return; + } + + var pingRequired = false; + var timeFromLastReceive = 0.0; + var timeFromFirstSend = 0.0; + var pingTimeout = Math.Max(Constants.TimeoutInterval - 10.0, 10.0); + if (activeTransport.LastReceiveTime.HasValue) + { + // что-то уже получали по соединению + var lastReceiveTime = activeTransport.LastReceiveTime.Value; + timeFromLastReceive = Math.Abs((now - lastReceiveTime).TotalSeconds); + + pingRequired = timeFromLastReceive > pingTimeout; + if (pingRequired) + { + Logs.Log.Write(string.Format(" CheckReconnect reason=PingRequired transport={3} now={0} - last_receive_time={1} > ping_timeout={2}", now.ToString("HH:mm:ss.fff"), lastReceiveTime.ToString("HH:mm:ss.fff"), pingTimeout, activeTransport.Id)); + } + } + else + { + // ничего не получали, но что-то отправляли + if (activeTransport.FirstSendTime.HasValue) + { + var firstSendTime = activeTransport.FirstSendTime.Value; + timeFromFirstSend = Math.Abs((now - firstSendTime).TotalSeconds); + + pingRequired = timeFromFirstSend > pingTimeout; + if (pingRequired) + { + Logs.Log.Write(string.Format(" CheckReconnect reason=PingRequired transport={3} now={0} - first_send_time={1} > ping_timeout={2}", now.ToString("HH:mm:ss.fff"), firstSendTime.ToString("HH:mm:ss.fff"), pingTimeout, activeTransport.Id)); + } + } + // хотя бы пинганем для начала + else + { + pingRequired = true; + } + } + + if (pingRequired) + { + var pingId = TLLong.Random(); + var pingIdHash = pingId.Value % 1000; + + var debugString = string.Format("{0} ping t{1} ({2}, {3}) [{4}]", + DateTime.Now.ToString("HH:mm:ss.fff"), + transportId, + timeFromFirstSend.ToString("N"), + timeFromLastReceive.ToString("N"), + pingIdHash); + + TLUtils.WriteLine(debugString, LogSeverity.Error); + _mtProtoService.PingAsync(pingId, //new TLInt(35), + result => + { + var resultDebugString = string.Format("{0} pong t{1} ({2}, {3}) [{4}]", + DateTime.Now.ToString("HH:mm:ss.fff"), + transportId, + timeFromFirstSend.ToString("N"), + timeFromLastReceive.ToString("N"), + pingIdHash); + + TLUtils.WriteLine(resultDebugString, LogSeverity.Error); + }, + error => + { + var errorDebugString = string.Format("{0} pong error t{1} ({2}, {3}) [{4}] \nSocketError={5}", + DateTime.Now.ToString("HH:mm:ss.fff"), + transportId, + timeFromFirstSend.ToString("N"), + timeFromLastReceive.ToString("N"), + pingIdHash, +#if WINDOWS_PHONE + error.SocketError +#else + string.Empty +#endif + ); + + TLUtils.WriteLine(errorDebugString, LogSeverity.Error); + }); + } + else + { + var checkDebugString = string.Format("{0} check t{1} ({2}, {3})", + DateTime.Now.ToString("HH:mm:ss.fff"), + transportId, + timeFromFirstSend.ToString("N"), + timeFromLastReceive.ToString("N")); + + //TLUtils.WriteLine(checkDebugString, LogSeverity.Error); + } + } + } +} diff --git a/Telegram.Api/Services/Connection/PublicConfigService.cs b/Telegram.Api/Services/Connection/PublicConfigService.cs new file mode 100755 index 0000000..c3e9aaf --- /dev/null +++ b/Telegram.Api/Services/Connection/PublicConfigService.cs @@ -0,0 +1,413 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Numerics; +using System.Runtime.Serialization.Json; +#if !WIN_RT +using System.Security.Cryptography; +#endif +using System.Text; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Connection +{ + public class MockupPublicConfigService : IPublicConfigService + { + public void GetAsync(Action callback, Action faultCallback = null) + { + + } + } + + public class PublicConfigService : IPublicConfigService + { + private static void Log(string str) + { + Logs.Log.Write(string.Format(" PublicConfigService {0}", str)); + } + + public bool Test { get; set; } + + private int _counter; + + private void PerformAppRequestAsync(Action callback, Action faultCallback) + { + Execute.ShowDebugMessage("GetPublicConfig start counter=" + _counter); + + var counter = _counter; + + WebRequest request; + if (_counter == 0) + { + request = Test + ? WebRequest.Create("https://www.google.pt/resolve?name=tap.stel.com&type=16") + : WebRequest.Create("https://www.google.pt/resolve?name=ap.stel.com&type=16"); + request.Headers["Host"] = "dns.google.com"; + + _counter = 1; + } + else if (_counter == 1) + { + request = Test + ? WebRequest.Create("https://www.google.com/resolve?name=tap.stel.com&type=16") + : WebRequest.Create("https://www.google.com/resolve?name=ap.stel.com&type=16"); + request.Headers["Host"] = "dns.google.com"; + + _counter = 2; + } + else if (_counter == 2) + { + request = Test + ? WebRequest.Create("https://google.pt/resolve?name=tap.stel.com&type=16") + : WebRequest.Create("https://google.pt/resolve?name=ap.stel.com&type=16"); + request.Headers["Host"] = "dns.google.com"; + + _counter = 3; + } + else + { + request = Test + ? WebRequest.Create("https://google.com/resolve?name=tap.stel.com&type=16") + : WebRequest.Create("https://google.com/resolve?name=ap.stel.com&type=16"); + request.Headers["Host"] = "dns.google.com"; + + _counter = 0; + } + + /*else if (_counter == 1) + { + request = Test + ? WebRequest.Create("https://google.com/test/") + : WebRequest.Create("https://google.com/"); + request.Headers["Host"] = "dns-telegram.appspot.com"; + + _counter = 2; + } + else + { + request = Test + ? WebRequest.Create("https://software-download.microsoft.com/test/config.txt") + : WebRequest.Create("https://software-download.microsoft.com/prod/config.txt"); + request.Headers["Host"] = "tcdnb.azureedge.net"; + + _counter = 0; + }*/ + + + Log("Start app request"); + + request.BeginGetResponse( + result => + { + Log("Stop app request"); + try + { + var response = request.EndGetResponse(result); + + string dataString; + using (var s = response.GetResponseStream()) + { + using (var readStream = new StreamReader(s)) + { + dataString = readStream.ReadToEnd(); + } + } + + //if (counter == 0) + { + dataString = ParseDataString(dataString); + } + + var configSimple = DecryptSimpleConfig(dataString); + + callback.SafeInvoke(configSimple); + } + catch (Exception ex) + { + Log("App request exception\n" + ex); + + faultCallback.SafeInvoke(counter, ex); + } + }, + request); + } + + private void PerformDnsRequestAsync(Action callback, Action faultCallback) + { + var request = Test + ? WebRequest.Create("https://google.com/resolve?name=tap.stel.com&type=16") + : WebRequest.Create("https://google.com/resolve?name=ap.stel.com&type=16"); + request.Headers["Host"] = "dns.google.com"; + + Log("Start dns request"); + + request.BeginGetResponse( + result => + { + Log("Stop dns request"); + try + { + var response = request.EndGetResponse(result); + + string dataString; + using (var s = response.GetResponseStream()) + { + using (var readStream = new StreamReader(s)) + { + dataString = readStream.ReadToEnd(); + } + } + + dataString = ParseDataString(dataString); + + var configSimple = DecryptSimpleConfig(dataString); + + callback.SafeInvoke(configSimple); + } + catch (Exception ex) + { + Log("Dns request exception\n" + ex); + + faultCallback.SafeInvoke(ex); + } + }, + request); + } + + private static TLConfigSimple DecryptSimpleConfig(string dataString) + { + TLConfigSimple result = null; + +#if !WIN_RT + var base64Chars = dataString.Where(ch => + { + var isGoodBase64 = + (ch == '+') || (ch == '=') || (ch == '/') + || (ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') + || (ch >= '0' && ch <= '9'); + + return isGoodBase64; + }).ToArray(); + + var cleanDataString = new string(base64Chars); + const int kGoodSizeBase64 = 344; + if (cleanDataString.Length != kGoodSizeBase64) + { + Log(string.Format("Bad base64 size {0} required {1}", cleanDataString.Length, kGoodSizeBase64)); + return null; + } + byte[] data = null; + try + { + data = Convert.FromBase64String(cleanDataString); + } + catch (Exception ex) + { + Log("Bad base64 bytes"); + + return null; + } + const int kGoodSizeData = 256; + if (data.Length != kGoodSizeData) + { + Log(string.Format("Bad data size {0} required {1}", data.Length, kGoodSizeData)); + + return null; + } + + var xml = "yr+18Rex2ohtVy8sroGPBwXD3DOoKCSpjDqYoXgCqB7ioln4eDCFfOBUlfXUEvM/fnKCpF46VkAftlb4VuPDeQSS/ZxZYEGqHaywlroVnXHIjgqoxiAd192xRGreuXIaUKmkwlM9JID9WS2jUsTpzQ91L8MEPLJ/4zrBwZua8W5fECwCCh2c9G5IzzBm+otMS/YKwmR1olzRCyEkyAEjXWqBI9Ftv5eG8m0VkBzOG655WIYdyV0HfDK/NWcvGqa0w/nriMD6mDjKOryamw0OP9QuYgMN0C9xMW9y8SmP4h92OAWodTYgY1hZCxdv6cs5UnW9+PWvS+WIbkh+GaWYxw==AQAB"; + + var provider = new RSACryptoServiceProvider(); + provider.FromXmlString(xml); + var parameters = provider.ExportParameters(false); + var modulus = parameters.Modulus; + var exponent = parameters.Exponent; + + var dataBI = new BigInteger(data.Reverse().Concat(new byte[] { 0x00 }).ToArray()); + var exponentBI = new BigInteger(exponent.Reverse().Concat(new byte[] { 0x00 }).ToArray()); + var modulusBI = new BigInteger(modulus.Reverse().Concat(new byte[] { 0x00 }).ToArray()); + + var authKey = BigInteger.ModPow(dataBI, exponentBI, modulusBI).ToByteArray(); + if (authKey[authKey.Length - 1] == 0x00) + { + authKey = authKey.SubArray(0, authKey.Length - 1); + } + + authKey = authKey.Reverse().ToArray(); + if (authKey.Length > 256) + { + var correctedAuth = new byte[256]; + Array.Copy(authKey, authKey.Length - 256, correctedAuth, 0, 256); + authKey = correctedAuth; + } + else if (authKey.Length < 256) + { + var correctedAuth = new byte[256]; + Array.Copy(authKey, 0, correctedAuth, 256 - authKey.Length, authKey.Length); + for (var i = 0; i < 256 - authKey.Length; i++) + { + authKey[i] = 0; + } + authKey = correctedAuth; + } + + var key = authKey.SubArray(0, 32); + var iv = authKey.SubArray(16, 16); + var encryptedData = authKey.SubArray(32, authKey.Length - 32); + + var cipher = CipherUtilities.GetCipher("AES/CBC/NOPADDING"); + var param = new KeyParameter(key); + cipher.Init(false, new ParametersWithIV(param, iv)); + var decryptedData = cipher.DoFinal(encryptedData); + + const int kDigestSize = 16; + var hash = Utils.ComputeSHA256(decryptedData.SubArray(0, 208)); + for (var i = 0; i < kDigestSize; i++) + { + if (hash[i] != decryptedData[208 + i]) + { + Log("Bad digest"); + return null; + } + } + + var position = 4; + var length = BitConverter.ToInt32(decryptedData, 0); + if (length <= 0 || length > 208 || length % 4 != 0) + { + Log(string.Format("Bad length {0}", length)); + return null; + } + try + { + result = TLObject.GetObject(decryptedData, ref position); + } + catch (Exception ex) + { + Log("Could not read configSimple"); + return null; + } + + if (position != length) + { + Log(string.Format("Bad read length {0} shoud be {1}", position, length)); + return null; + } +#endif + + return result; + } + + public void GetAsync(Action callback, Action faultCallback = null) + { +//#if DEBUG +// return; +//#endif + + if (Debugger.IsAttached) + { + return; + } + +#if !WIN_RT + PerformAppRequestAsync( + result => + { + Execute.ShowDebugMessage(result != null ? result.ToString() : "null"); + + callback.SafeInvoke(result); + }, + (counter, error) => + { + Execute.ShowDebugMessage(string.Format("GetPublicConfig counter={0} error={1}", counter, error)); + + faultCallback.SafeInvoke(error); + }); +#endif + } + + private static string ParseDataString(string dataString) + { + var serializer = new DataContractJsonSerializer(typeof(RootObject)); + RootObject rootObject; + try + { + using (var stream = new MemoryStream(Encoding.Unicode.GetBytes(dataString))) + { + rootObject = serializer.ReadObject(stream) as RootObject; + } + } + catch (Exception ex) + { + Log("Failed to parse dns response JSON, ex\n" + ex); + return null; + } + + if (rootObject == null) + { + Log("Not an object received in dns response JSON"); + return null; + } + + if (rootObject.Answer == null) + { + Log("Could not find Answer in dns response JSON"); + return null; + } + + var result = new StringBuilder(); + for (int i = rootObject.Answer.Count - 1; i >= 0; i--) + { + result.Append(rootObject.Answer[i].data); + } + + return result.ToString(); + } + } + + public interface IPublicConfigService + { + void GetAsync(Action callback, Action faultCallback = null); + } + + public class Question + { + public string name { get; set; } + public int type { get; set; } + } + + public class Answer + { + public string name { get; set; } + public int type { get; set; } + public int TTL { get; set; } + public string data { get; set; } + } + + public class RootObject + { + public int Status { get; set; } + public bool TC { get; set; } + public bool RD { get; set; } + public bool RA { get; set; } + public bool AD { get; set; } + public bool CD { get; set; } + public List Question { get; set; } + public List Answer { get; set; } + } +} diff --git a/Telegram.Api/Services/DCOptionItem.cs b/Telegram.Api/Services/DCOptionItem.cs new file mode 100755 index 0000000..3480b11 --- /dev/null +++ b/Telegram.Api/Services/DCOptionItem.cs @@ -0,0 +1,31 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.Services +{ + public class ConnectionParams + { + public byte[] Salt { get; set; } + + public byte[] SessionId { get; set; } + + public byte[] AuthKey { get; set; } + } + + public class DCOptionItem + { + public ConnectionParams Params { get; set; } + + public int Id { get; set; } + + public string Hostname { get; set; } + + public string IpAddress { get; set; } + + public int Port { get; set; } + } +} diff --git a/Telegram.Api/Services/DelayedItem.cs b/Telegram.Api/Services/DelayedItem.cs new file mode 100755 index 0000000..df28214 --- /dev/null +++ b/Telegram.Api/Services/DelayedItem.cs @@ -0,0 +1,38 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Text; +using Telegram.Api.TL; + +namespace Telegram.Api.Services +{ + class DelayedItem + { + public string Caption { get; set; } + public DateTime SendTime { get; set; } + //public DateTime? SendBeforeTime { get; set; } + public TLObject Object { get; set; } + public Action Callback { get; set; } + public Action FaultCallback { get; set; } + public Action AttemptFailed { get; set; } + public int? MaxAttempt { get; set; } + public int CurrentAttempt { get; set; } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine("DelayedItem"); + sb.AppendLine("Caption " + Caption); + sb.AppendLine("MaxAttempt " + MaxAttempt); + sb.AppendLine("CurrentAttempt " + CurrentAttempt); + + return sb.ToString(); + } + } +} diff --git a/Telegram.Api/Services/DeviceInfo/EmptyDeviceInfoService.cs b/Telegram.Api/Services/DeviceInfo/EmptyDeviceInfoService.cs new file mode 100755 index 0000000..0387cd1 --- /dev/null +++ b/Telegram.Api/Services/DeviceInfo/EmptyDeviceInfoService.cs @@ -0,0 +1,41 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Telegram.Api.TL; + +namespace Telegram.Api.Services.DeviceInfo +{ + public class DeviceInfoService : IDeviceInfoService + { + public string Model { get; protected set; } + public string AppVersion { get; protected set; } + public string SystemVersion { get; protected set; } + public bool IsBackground { get; protected set; } + public string BackgroundTaskName { get; protected set; } + public int BackgroundTaskId { get; protected set; } + + public DeviceInfoService(string model, string appVersion, string systemVersion, bool isBackground, string backgroundTaskName, int backgroundTaskId) + { + Model = model; + AppVersion = appVersion; + SystemVersion = systemVersion; + IsBackground = isBackground; + BackgroundTaskName = backgroundTaskName; + BackgroundTaskId = backgroundTaskId; + } + + public DeviceInfoService(TLInitConnection initConnection, bool isBackground, string backgroundTaskName, int backgroundTaskId) + { + Model = initConnection.DeviceModel.ToString(); + AppVersion = initConnection.AppVersion.ToString(); + SystemVersion = initConnection.SystemVersion.ToString(); + IsBackground = isBackground; + BackgroundTaskName = backgroundTaskName; + BackgroundTaskId = backgroundTaskId; + } + } +} diff --git a/Telegram.Api/Services/DeviceInfo/IDeviceInfo.cs b/Telegram.Api/Services/DeviceInfo/IDeviceInfo.cs new file mode 100755 index 0000000..cf5cfcb --- /dev/null +++ b/Telegram.Api/Services/DeviceInfo/IDeviceInfo.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.Services.DeviceInfo +{ + public interface IDeviceInfoService + { + string Model { get; } + string AppVersion { get; } + string SystemVersion { get; } + bool IsBackground { get; } + string BackgroundTaskName { get; } + int BackgroundTaskId { get; } + } +} diff --git a/Telegram.Api/Services/FileManager/AudioFileManager.cs b/Telegram.Api/Services/FileManager/AudioFileManager.cs new file mode 100755 index 0000000..3ca1fac --- /dev/null +++ b/Telegram.Api/Services/FileManager/AudioFileManager.cs @@ -0,0 +1,205 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Linq; +using Telegram.Api.Aggregator; +using Telegram.Api.Helpers; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public class AudioFileManager : FileManagerBase, IAudioFileManager + { + public AudioFileManager(ITelegramEventAggregator eventAggregator, IMTProtoService mtProtoService) : base(eventAggregator, mtProtoService) + { + for (var i = 0; i < Constants.AudioDownloadersCount; i++) + { + var worker = new Worker(OnDownloading, "audioDownloader" + i); + _workers.Add(worker); + } + } + + private void OnDownloading(object state) + { + DownloadablePart part = null; + lock (_itemsSyncRoot) + { + for (var i = 0; i < _items.Count; i++) + { + var item = _items[i]; + if (item.Canceled) + { + _items.RemoveAt(i--); + try + { + //_eventAggregator.Publish(new UploadingCanceledEventArgs(item)); + } + catch (Exception e) + { + TLUtils.WriteException(e); + } + } + } + + foreach (var item in _items) + { + part = item.Parts.FirstOrDefault(x => x.Status == PartStatus.Ready); + if (part != null) + { + part.Status = PartStatus.Processing; + break; + } + } + } + + if (part == null) + { + var currentWorker = (Worker)state; + currentWorker.Stop(); + return; + } + + var partName = part.ParentItem.InputLocation.GetPartFileName(part.Number, "audio"); + var isLastPart = part.Number + 1 == part.ParentItem.Parts.Count; + var partLength = FileUtils.GetLocalFileLength(partName); + var partExists = partLength > 0; + var isCorrectPartLength = isLastPart || partLength == part.Limit.Value; + + if (!partExists || !isCorrectPartLength) + { + bool canceled; + ProcessFilePart(part, part.ParentItem.DCId, part.ParentItem.InputLocation, out canceled); + if (canceled) + { + lock (_itemsSyncRoot) + { + part.ParentItem.Canceled = true; + part.Status = PartStatus.Processed; + _items.Remove(part.ParentItem); + } + + return; + } + + //part.File = GetFile(part.ParentItem.DCId, (TLInputFileLocationBase) part.ParentItem.InputAudioLocation, part.Offset, part.Limit, out error, out canceled); + //while (part.File == null) + //{ + // part.File = GetFile(part.ParentItem.DCId, (TLInputFileLocationBase) part.ParentItem.InputAudioLocation, part.Offset, part.Limit, out error, out canceled); + //} + } + + // indicate progress + // indicate complete + bool isComplete; + bool isCanceled; + var progress = 0.0; + lock (_itemsSyncRoot) + { + part.Status = PartStatus.Processed; + + FileUtils.CheckMissingPart(_itemsSyncRoot, part, partName); + + isCanceled = part.ParentItem.Canceled; + + isComplete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!isComplete) + { + var downloadedCount = part.ParentItem.Parts.Count(x => x.Status == PartStatus.Processed); + var count = part.ParentItem.Parts.Count; + progress = downloadedCount / (double)count; + } + else + { + _items.Remove(part.ParentItem); + } + } + + if (!isCanceled) + { + if (isComplete) + { + var fileName = part.ParentItem.InputLocation.GetFileName("audio", ".mp3"); + var getPartName = new Func(x => x.ParentItem.InputLocation.GetPartFileName(x.Number, "audio")); + + FileUtils.MergePartsToFile(getPartName, part.ParentItem.Parts, fileName); + + part.ParentItem.IsoFileName = fileName; + if (part.ParentItem.Callback != null) + { + Execute.BeginOnThreadPool(() => part.ParentItem.Callback(part.ParentItem)); + } + else + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(part.ParentItem)); + } + } + else + { + //Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new ProgressChangedEventArgs(part.ParentItem, progress))); + } + } + } + + public void DownloadFile(TLInt dcId, TLInputFileLocationBase fileLocation, TLObject owner, TLInt fileSize, Action callback) + { + var downloadableItem = GetDownloadableItem(dcId, fileLocation, owner, fileSize, callback); + + var downloadedCount = downloadableItem.Parts.Count(x => x.Status == PartStatus.Processed); + var count = downloadableItem.Parts.Count; + var isComplete = downloadedCount == count; + + if (isComplete) + { + var fileName = downloadableItem.InputLocation.GetFileName("audio", ".mp3"); + var getPartName = new Func(x => x.ParentItem.InputLocation.GetPartFileName(x.Number, "audio")); + + FileUtils.MergePartsToFile(getPartName, downloadableItem.Parts, fileName); + + downloadableItem.IsoFileName = fileName; + _eventAggregator.Publish(downloadableItem); + } + else + { + lock (_itemsSyncRoot) + { + bool addFile = true; + foreach (var item in _items) + { + if (item.InputLocation.LocationEquals(fileLocation) + && item.Owner == owner) + { + addFile = false; + break; + } + } + + if (addFile) + { + _items.Add(downloadableItem); + } + } + + StartAwaitingWorkers(); + } + } + + private DownloadableItem GetDownloadableItem(TLInt dcId, TLInputFileLocationBase location, TLObject owner, TLInt fileSize, Action callback) + { + var item = new DownloadableItem + { + Owner = owner, + DCId = dcId, + InputLocation = location, + Callback = callback, + }; + item.Parts = GetItemParts(fileSize, item); + + return item; + } + } +} diff --git a/Telegram.Api/Services/FileManager/DocumentFileManager.cs b/Telegram.Api/Services/FileManager/DocumentFileManager.cs new file mode 100755 index 0000000..3917152 --- /dev/null +++ b/Telegram.Api/Services/FileManager/DocumentFileManager.cs @@ -0,0 +1,284 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public class DocumentFileManager : FileManagerBase, IDocumentFileManager + { + public DocumentFileManager(ITelegramEventAggregator eventAggregator, IMTProtoService mtProtoService) : base(eventAggregator, mtProtoService) + { + for (var i = 0; i < Constants.BigFileWorkersNumber; i++) + { + var worker = new Worker(OnDownloading, "documentDownloader" + i); + _workers.Add(worker); + } + } + + private void OnDownloading(object state) + { + DownloadablePart part = null; + lock (_itemsSyncRoot) + { + for (var i = 0; i < _items.Count; i++) + { + var item = _items[i]; + if (item.Canceled) + { + _items.RemoveAt(i--); + try + { + //_eventAggregator.Publish(new UploadingCanceledEventArgs(item)); + } + catch (Exception e) + { + TLUtils.WriteException(e); + } + } + } + + foreach (var item in _items) + { + part = item.Parts.FirstOrDefault(x => x.Status == PartStatus.Ready); + if (part != null) + { + part.Status = PartStatus.Processing; + break; + } + } + } + + if (part == null) + { + var currentWorker = (Worker)state; + currentWorker.Stop(); + return; + } + + var partName = part.ParentItem.InputLocation.GetPartFileName(part.Number, "document"); + bool canceled; + ProcessFilePart(part, part.ParentItem.DCId, part.ParentItem.InputLocation, out canceled); + if (canceled) + { + lock (_itemsSyncRoot) + { + part.ParentItem.Canceled = true; + part.Status = PartStatus.Processed; + _items.Remove(part.ParentItem); + } + + return; + } + //part.File = GetFile(part.ParentItem.DCId, part.ParentItem.InputDocumentLocation, part.Offset, part.Limit); + //while (part.File == null) + //{ + // part.File = GetFile(part.ParentItem.DCId, part.ParentItem.InputDocumentLocation, part.Offset, part.Limit); + //} + + // indicate progress + // indicate complete + bool isComplete; + bool isCanceled; + var progress = 0.0; + lock (_itemsSyncRoot) + { + part.Status = PartStatus.Processed; + + if (!part.ParentItem.SuppressMerge) + { + FileUtils.CheckMissingPart(_itemsSyncRoot, part, partName); + } + + isCanceled = part.ParentItem.Canceled; + + isComplete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!isComplete) + { + var downloadedCount = part.ParentItem.Parts.Count(x => x.Status == PartStatus.Processed); + var count = part.ParentItem.Parts.Count; + progress = downloadedCount / (double)count; + } + else + { + //var id = part.ParentItem.InputDocumentLocation.Id; + //var accessHash = part.ParentItem.InputDocumentLocation.AccessHash; + //var fileExtension = Path.GetExtension(part.ParentItem.FileName.ToString()); + //var fileName = string.Format("document{0}_{1}{2}", id, accessHash, fileExtension); + + //if (fileName.EndsWith(".mp4")) + //{ + // Logs.Log.SyncWrite("FileManager.IsComplete " + fileName + " hash=" + part.ParentItem.GetHashCode()); + //} + + _items.Remove(part.ParentItem); + } + } + + if (!isCanceled) + { + if (isComplete) + { + //var id = part.ParentItem.InputDocumentLocation.Id; + //var accessHash = part.ParentItem.InputDocumentLocation.AccessHash; + //var version = part.ParentItem.InputDocumentLocation.Version; + var fileExtension = Path.GetExtension(part.ParentItem.FileName.ToString()); + var fileName = part.ParentItem.InputLocation.GetFileName("document", fileExtension); + Func getPartName = x => part.ParentItem.InputLocation.GetPartFileName(x.Number, "document"); + + if (!part.ParentItem.SuppressMerge) + { + FileUtils.MergePartsToFile(getPartName, part.ParentItem.Parts, fileName); + } + + part.ParentItem.IsoFileName = fileName; + if (part.ParentItem.Callback != null) + { + Execute.BeginOnThreadPool(() => + { + part.ParentItem.Callback(part.ParentItem); + if (part.ParentItem.Callbacks != null) + { + foreach (var callback in part.ParentItem.Callbacks) + { + callback.SafeInvoke(part.ParentItem); + } + } + }); + } + else + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(part.ParentItem)); + } + } + else + { + if (part.NotifyProgress) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new ProgressChangedEventArgs(part.ParentItem, progress))); + } + } + } + } + + public void DownloadFileAsync(TLString originalFileName, TLInt dcId, TLInputFileLocationBase fileLocation, TLObject owner, TLInt fileSize, Action startCallback, Action callback = null) + { + Execute.BeginOnThreadPool(() => + { + var downloadableItem = GetDownloadableItem(originalFileName, dcId, fileLocation, owner, fileSize, callback); + + var downloadedCount = downloadableItem.Parts.Count(x => x.Status == PartStatus.Processed); + var count = downloadableItem.Parts.Count; + var isComplete = downloadedCount == count; + + if (isComplete) + { + var fileExtension = Path.GetExtension(downloadableItem.FileName.ToString()); + var fileName = downloadableItem.InputLocation.GetFileName("document", fileExtension); + Func getPartName = x => downloadableItem.InputLocation.GetPartFileName(x.Number, "document"); + + FileUtils.MergePartsToFile(getPartName, downloadableItem.Parts, fileName); + + downloadableItem.IsoFileName = fileName; + _eventAggregator.Publish(downloadableItem); + } + else + { + var progress = downloadedCount/(double) count; + startCallback.SafeInvoke(progress); + + lock (_itemsSyncRoot) + { + bool addFile = true; + foreach (var item in _items) + { + if (item.InputLocation.LocationEquals(fileLocation)) + { + + //item.SuppressMerge = true; + + if (callback != null) + { + if (item.Callbacks == null) + { + item.Callbacks = new List>(); + } + item.Callbacks.Add(callback); + addFile = false; + break; + } + //item. + if (item.Owner == owner) + { + addFile = false; + break; + } + } + } + + if (addFile) + { + _items.Add(downloadableItem); + } + } + + StartAwaitingWorkers(); + } + }); + } + + private DownloadableItem GetDownloadableItem(TLString fileName, TLInt dcId, TLInputFileLocationBase location, TLObject owner, TLInt fileSize, Action callback) + { + var item = new DownloadableItem + { + DCId = dcId, + FileName = fileName, + Owner = owner, + InputLocation = location, + Callback = callback + }; + item.Parts = GetItemParts(fileSize, item); + + return item; + } + + protected override List GetItemParts(TLInt size, DownloadableItem item) + { + var chunkSize = size.Value > 1024*1024 ? Constants.DownloadedBigChunkSize : Constants.DownloadedChunkSize; + var parts = new List(); + var partsCount = size.Value / chunkSize + (size.Value % chunkSize > 0 ? 1 : 0); + + var step = partsCount / 25; + + for (var i = 0; i < partsCount; i++) + { + var part = new DownloadablePart(item, new TLInt(i * chunkSize), size.Value == 0 ? new TLInt(1024 * 1024) : new TLInt(chunkSize), i); + var partName = item.InputLocation.GetPartFileName(part.Number, "document"); + var partLength = FileUtils.GetLocalFileLength(partName); + + if (partLength >= 0) + { + var isCompletePart = (part.Number + 1 == partsCount) || partLength == part.Limit.Value; + part.Status = isCompletePart ? PartStatus.Processed : PartStatus.Ready; + } + + part.NotifyProgress = part.Status == PartStatus.Ready && (step == 0 || i % step == 0); + + parts.Add(part); + } + + return parts; + } + } +} diff --git a/Telegram.Api/Services/FileManager/DownloadableItem.cs b/Telegram.Api/Services/FileManager/DownloadableItem.cs new file mode 100755 index 0000000..6b877cb --- /dev/null +++ b/Telegram.Api/Services/FileManager/DownloadableItem.cs @@ -0,0 +1,63 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public class DownloadableItem + { + public TLInt DCId { get; set; } + + public TLString FileName { get; set; } + + public TLObject Owner { get; set; } + + public System.Action Callback { get; set; } + + public IList> Callbacks { get; set; } + + public TLInputFileLocationBase InputLocation { get; set; } + + public List Parts { get; set; } + + public string IsoFileName { get; set; } + + public bool Canceled { get; set; } + + public bool SuppressMerge { get; set; } + + public TLFileCdnRedirect CdnRedirect { get; set; } + + #region Http + + public string SourceUri { get; set; } + + public string DestFileName { get; set; } + + public System.Action FaultCallback { get; set; } + + public IList> FaultCallbacks { get; set; } + + public double Timeout { get; set; } + + public void IncreaseTimeout() + { + Timeout = Timeout * 2.0; + if (Timeout == 0.0) + { + Timeout = 4.0; + } + if (Timeout >= 32.0) + { + Timeout = 4.0; + } + } + #endregion + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/FileManager/DownloadablePart.cs b/Telegram.Api/Services/FileManager/DownloadablePart.cs new file mode 100755 index 0000000..9b4a3f6 --- /dev/null +++ b/Telegram.Api/Services/FileManager/DownloadablePart.cs @@ -0,0 +1,51 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public enum PartStatus + { + Ready, + Processing, + Processed, + } + + public class DownloadablePart + { + public int Number { get; protected set; } + + public DownloadableItem ParentItem { get; protected set; } + + public TLInt Offset { get; protected set; } + + public TLInt Limit { get; protected set; } + + public PartStatus Status { get; set; } + + public TLFile File { get; set; } + + public int HttpErrorsCount { get; set; } + + public bool NotifyProgress { get; set; } + + public DownloadablePart(DownloadableItem item, TLInt offset, TLInt limit, int number) + { + ParentItem = item; + Offset = offset; + Limit = limit; + Number = number; + NotifyProgress = true; + } + + public override string ToString() + { + return string.Format("{0} {1} {2}", Number, Offset, Limit); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/FileManager/DownloadingCanceledEventArgs.cs b/Telegram.Api/Services/FileManager/DownloadingCanceledEventArgs.cs new file mode 100755 index 0000000..8dbd2d2 --- /dev/null +++ b/Telegram.Api/Services/FileManager/DownloadingCanceledEventArgs.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.Services.FileManager +{ + public class DownloadingCanceledEventArgs + { + public DownloadableItem Item { get; protected set; } + + public DownloadingCanceledEventArgs(DownloadableItem item) + { + Item = item; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/FileManager/EncryptedFileManager.cs b/Telegram.Api/Services/FileManager/EncryptedFileManager.cs new file mode 100755 index 0000000..3fb222a --- /dev/null +++ b/Telegram.Api/Services/FileManager/EncryptedFileManager.cs @@ -0,0 +1,223 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using Telegram.Api.Aggregator; +using Telegram.Api.Helpers; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public class EncryptedFileManager : FileManagerBase, IEncryptedFileManager + { + public EncryptedFileManager(ITelegramEventAggregator eventAggregator, IMTProtoService mtProtoService) : base(eventAggregator, mtProtoService) + { + for (var i = 0; i < Constants.BigFileWorkersNumber; i++) + { + var worker = new Worker(OnDownloading, "encryptedDownloader"+i); + _workers.Add(worker); + } + } + + private void OnDownloading(object state) + { + DownloadablePart part = null; + lock (_itemsSyncRoot) + { + for (var i = 0; i < _items.Count; i++) + { + var item = _items[i]; + if (item.Canceled) + { + _items.RemoveAt(i--); + try + { + //_eventAggregator.Publish(new UploadingCanceledEventArgs(item)); + } + catch (Exception e) + { + TLUtils.WriteException(e); + } + } + } + + foreach (var item in _items) + { + part = item.Parts.FirstOrDefault(x => x.Status == PartStatus.Ready); + if (part != null) + { + part.Status = PartStatus.Processing; + break; + } + } + } + + if (part == null) + { + var currentWorker = (Worker)state; + currentWorker.Stop(); + return; + } + + var partName = part.ParentItem.InputLocation.GetPartFileName(part.Number, "encrypted"); + bool canceled; + ProcessFilePart(part, part.ParentItem.DCId, part.ParentItem.InputLocation, out canceled); + if (canceled) + { + lock (_itemsSyncRoot) + { + part.ParentItem.Canceled = true; + part.Status = PartStatus.Processed; + _items.Remove(part.ParentItem); + } + + return; + } + + // indicate progress + // indicate complete + bool isComplete; + bool isCanceled; + var progress = 0.0; + lock (_itemsSyncRoot) + { + part.Status = PartStatus.Processed; + + FileUtils.CheckMissingPart(_itemsSyncRoot, part, partName); + + isCanceled = part.ParentItem.Canceled; + + isComplete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!isComplete) + { + var downloadedCount = part.ParentItem.Parts.Count(x => x.Status == PartStatus.Processed); + var count = part.ParentItem.Parts.Count; + progress = downloadedCount / (double)count; + } + else + { + _items.Remove(part.ParentItem); + } + } + + if (!isCanceled) + { + if (isComplete) + { + var fileName = part.ParentItem.InputLocation.GetFileName("encrypted"); + var getPartFileName = new Func(p => p.ParentItem.InputLocation.GetPartFileName(p.Number, "encrypted")); + + FileUtils.MergePartsToFile(getPartFileName, part.ParentItem.Parts, fileName); + + part.ParentItem.IsoFileName = fileName; + if (part.ParentItem.Callback != null) + { + part.ParentItem.Callback(part.ParentItem); + } + else + { + _eventAggregator.Publish(part.ParentItem); + } + } + else + { + _eventAggregator.Publish(new ProgressChangedEventArgs(part.ParentItem, progress)); + } + } + } + + public void DownloadFile(TLEncryptedFile file, TLObject owner, Action callback) + { + var inputFile = new TLInputEncryptedFileLocation { Id = file.Id, AccessHash = file.AccessHash }; + var downloadableItem = GetDownloadableItem(file.DCId, inputFile, owner, file.Size, callback); + + var downloadedCount = downloadableItem.Parts.Count(x => x.Status == PartStatus.Processed); + var count = downloadableItem.Parts.Count; + var isComplete = downloadedCount == count; + + if (isComplete) + { + var fileName = downloadableItem.InputLocation.GetFileName("encrypted"); + Func getPartName = x => downloadableItem.InputLocation.GetPartFileName(x.Number, "encrypted"); + + FileUtils.MergePartsToFile(getPartName, downloadableItem.Parts, fileName); + + downloadableItem.IsoFileName = fileName; + if (downloadableItem.Callback != null) + { + downloadableItem.Callback(downloadableItem); + } + else + { + _eventAggregator.Publish(downloadableItem); + } + } + else + { + lock (_itemsSyncRoot) + { + bool addFile = true; + foreach (var item in _items) + { + if (item.InputLocation.LocationEquals(inputFile)) + { + addFile = false; + break; + } + } + + if (addFile) + { + _items.Add(downloadableItem); + } + } + + StartAwaitingWorkers(); + } + } + + private DownloadableItem GetDownloadableItem(TLInt dcId, TLInputFileLocationBase location, TLObject owner, TLInt fileSize, Action callback) + { + var item = new DownloadableItem + { + Owner = owner, + DCId = dcId, + InputLocation = location, + Callback = callback + }; + item.Parts = GetItemParts(fileSize, item); + + return item; + } + + protected override List GetItemParts(TLInt size, DownloadableItem item) + { + var chunkSize = size.Value > 1024 * 1024 ? Constants.DownloadedBigChunkSize : Constants.DownloadedChunkSize; + var parts = new List(); + var partsCount = size.Value / chunkSize + (size.Value % chunkSize > 0 ? 1 : 0); + + for (var i = 0; i < partsCount; i++) + { + var part = new DownloadablePart(item, new TLInt(i * chunkSize), size.Value == 0 ? new TLInt(1024 * 1024) : new TLInt(chunkSize), i); + var partName = item.InputLocation.GetPartFileName(part.Number, "encrypted"); + var partLength = FileUtils.GetLocalFileLength(partName); + + if (partLength >= 0) + { + var isCompletePart = (part.Number + 1 == partsCount) || partLength == part.Limit.Value; + part.Status = isCompletePart ? PartStatus.Processed : PartStatus.Ready; + } + + parts.Add(part); + } + + return parts; + } + } +} diff --git a/Telegram.Api/Services/FileManager/FileManager.cs b/Telegram.Api/Services/FileManager/FileManager.cs new file mode 100755 index 0000000..e2c0b9b --- /dev/null +++ b/Telegram.Api/Services/FileManager/FileManager.cs @@ -0,0 +1,274 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public class FileManager : FileManagerBase, IFileManager + { + public FileManager(ITelegramEventAggregator eventAggregator, IMTProtoService mtProtoService) : base(eventAggregator, mtProtoService) + { + for (var i = 0; i < Constants.WorkersNumber; i++) + { + var worker = new Worker(OnDownloading, "downloader"+i); + _workers.Add(worker); + } + } + + private void OnDownloading(object state) + { + DownloadablePart part = null; + lock (_itemsSyncRoot) + { + for (var i = 0; i < _items.Count; i++) + { + var item = _items[i]; + if (item.Canceled) + { + + _items.RemoveAt(i--); + + try + { + _eventAggregator.Publish(new DownloadingCanceledEventArgs(item)); + } + catch (Exception e) + { + TLUtils.WriteException(e); + } + } + } + + foreach (var item in _items) + { + part = item.Parts.FirstOrDefault(x => x.Status == PartStatus.Ready); + if (part != null) + { + part.Status = PartStatus.Processing; + break; + } + } + } + + if (part == null) + { + var currentWorker = (Worker)state; + currentWorker.Stop(); + return; + } + + bool canceled; + ProcessFilePart(part, part.ParentItem.DCId, part.ParentItem.InputLocation, out canceled); + if (canceled) + { + lock (_itemsSyncRoot) + { + part.ParentItem.Canceled = true; + part.Status = PartStatus.Processed; + _items.Remove(part.ParentItem); + } + + return; + } + + // indicate progress + // indicate complete + bool isComplete; + bool isCanceled; + var progress = 0.0; + lock (_itemsSyncRoot) + { + part.Status = PartStatus.Processed; + + var data = part.File.Bytes.Data; + if (data.Length < part.Limit.Value && (part.Number + 1) != part.ParentItem.Parts.Count) + { + var complete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!complete) + { + var emptyBufferSize = part.Limit.Value - data.Length; + var position = data.Length; + + var missingPart = new DownloadablePart(part.ParentItem, new TLInt(position), new TLInt(emptyBufferSize), -part.Number); + + var currentItemIndex = part.ParentItem.Parts.IndexOf(part); + part.ParentItem.Parts.Insert(currentItemIndex + 1, missingPart); + } + } + + isCanceled = part.ParentItem.Canceled; + + isComplete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!isComplete) + { + var downloadedCount = part.ParentItem.Parts.Count(x => x.Status == PartStatus.Processed); + var count = part.ParentItem.Parts.Count; + progress = (double)downloadedCount / count; + } + else + { + _items.Remove(part.ParentItem); + } + } + + if (!isCanceled) + { + if (isComplete) + { + byte[] bytes = { }; + foreach (var p in part.ParentItem.Parts) + { + bytes = TLUtils.Combine(bytes, p.File.Bytes.Data); + } + //part.ParentItem.Location.Buffer = bytes; + + var fileName = part.ParentItem.InputLocation.GetFileName("", ".jpg"); + + StringLocker.Lock(fileName, () => FileUtils.WriteBytes(fileName, bytes)); + + if (part.ParentItem.Callback != null) + { + Execute.BeginOnThreadPool(() => + { + part.ParentItem.Callback.SafeInvoke(part.ParentItem); + if (part.ParentItem.Callbacks != null) + { + foreach (var callback in part.ParentItem.Callbacks) + { + callback.SafeInvoke(part.ParentItem); + } + } + }); + } + else + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(part.ParentItem)); + } + } + else + { + //Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new ProgressChangedEventArgs(part.ParentItem, progress))); + } + } + } + + public void DownloadFile(TLFileLocation file, TLObject owner, TLInt fileSize) + { + var downloadableItem = GetDownloadableItem(file, owner, fileSize, null); + + lock (_itemsSyncRoot) + { + bool addFile = true; + var inputFileLocation = file.ToInputFileLocation(); + foreach (var item in _items) + { + if (item.InputLocation.LocationEquals(inputFileLocation) + && item.Owner == owner) + { + addFile = false; + break; + } + } + + if (addFile) + { + _items.Add(downloadableItem); + } + } + + StartAwaitingWorkers(); + } + + public void DownloadFile(TLFileLocation file, TLObject owner, TLInt fileSize, Action callback) + { + var downloadableItem = GetDownloadableItem(file, owner, fileSize, callback); + + lock (_itemsSyncRoot) + { + bool addFile = true; + var inputFileLocation = file.ToInputFileLocation(); + foreach (var item in _items) + { + if (item.InputLocation.LocationEquals(inputFileLocation)) + { + if (callback != null) + { + if (item.Callbacks == null) + { + item.Callbacks = new List>(); + } + item.Callbacks.Add(callback); + + addFile = false; + break; + } + + if (item.Owner == owner) + { + addFile = false; + break; + } + } + } + + if (addFile) + { + _items.Add(downloadableItem); + } + } + + StartAwaitingWorkers(); + } + + protected DownloadableItem GetDownloadableItem(TLFileLocation location, TLObject owner, TLInt fileSize, Action callback) + { + var item = new DownloadableItem + { + Owner = owner, + DCId = location.DCId, + Callback = callback, + InputLocation = location.ToInputFileLocation() + }; + item.Parts = GetItemParts(fileSize, item); + + return item; + } + } + + public class StringLocker + { + private static readonly object _syncRoot = new Object(); + + private static readonly Dictionary _syncRoots = new Dictionary(); + + public static void Lock(string key, Action action) + { + object keySyncRoot; + lock (_syncRoot) + { + + if (!_syncRoots.TryGetValue(key, out keySyncRoot)) + { + keySyncRoot = new object(); + _syncRoots[key] = keySyncRoot; + } + } + + lock (keySyncRoot) + { + action(); + } + } + } +} diff --git a/Telegram.Api/Services/FileManager/FileManagerBase.cs b/Telegram.Api/Services/FileManager/FileManagerBase.cs new file mode 100755 index 0000000..e537712 --- /dev/null +++ b/Telegram.Api/Services/FileManager/FileManagerBase.cs @@ -0,0 +1,321 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using Telegram.Api.Aggregator; +using Telegram.Api.Helpers; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public abstract class FileManagerBase + { + private readonly object _randomRoot = new object(); + + private readonly Random _random = new Random(); + + protected readonly object _itemsSyncRoot = new object(); + + protected readonly List _workers = new List(Constants.WorkersNumber); + + protected readonly List _items = new List(); + + protected readonly IMTProtoService _mtProtoService; + + protected readonly ITelegramEventAggregator _eventAggregator; + + protected FileManagerBase(ITelegramEventAggregator eventAggregator, IMTProtoService mtProtoService) + { + _mtProtoService = mtProtoService; + _eventAggregator = eventAggregator; + } + + protected void ProcessFilePart(DownloadablePart part, TLInt dcId, TLInputFileLocationBase location, out bool canceled) + { + do + { + TLRPCError error; + + TLFileBase result; + if (part.ParentItem.CdnRedirect != null) + { + TLCdnFileReuploadNeeded cdnFileReuploadNeeded; + bool tokenInvalid; + result = GetCdnFile(part.ParentItem.CdnRedirect, part.Offset, part.Limit, out cdnFileReuploadNeeded, out error, out canceled, out tokenInvalid); + if (cdnFileReuploadNeeded != null) + { + ReuploadFile(part.ParentItem.CdnRedirect, dcId, cdnFileReuploadNeeded.RequestToken, out error, out canceled, out tokenInvalid); + } + + if (tokenInvalid) + { + lock (_itemsSyncRoot) + { + part.ParentItem.CdnRedirect = null; + } + continue; + } + } + else + { + result = GetFile(dcId, location, part.Offset, part.Limit, out error, out canceled); + var fileCdnRedirect = result as TLFileCdnRedirect; + if (fileCdnRedirect != null) + { + lock (_itemsSyncRoot) + { + part.ParentItem.CdnRedirect = fileCdnRedirect; + } + continue; + } + } + + part.File = result as TLFile; + + if (canceled) + { + return; + } + } while (part.File == null); + } + + protected TLFileBase GetFile(TLInt dcId, TLInputFileLocationBase location, TLInt offset, TLInt limit, out TLRPCError er, out bool isCanceled) + { + var manualResetEvent = new ManualResetEvent(false); + TLFileBase result = null; + TLRPCError outError = null; + var outIsCanceled = false; + _mtProtoService.GetFileAsync(dcId, location, offset, limit, + file => + { + result = file; + manualResetEvent.Set(); + }, + error => + { + outError = error; + + if (error.CodeEquals(ErrorCode.INTERNAL) + || (error.CodeEquals(ErrorCode.BAD_REQUEST) && (error.TypeEquals(ErrorType.LOCATION_INVALID) || error.TypeEquals(ErrorType.VOLUME_LOC_NOT_FOUND))) + || (error.CodeEquals(ErrorCode.NOT_FOUND) && error.Message != null && error.Message.ToString().StartsWith("Incorrect dhGen"))) + { + outIsCanceled = true; + + manualResetEvent.Set(); + return; + } + + int delay; + lock (_randomRoot) + { + delay = _random.Next(1000, 3000); + } + + Execute.BeginOnThreadPool(TimeSpan.FromMilliseconds(delay), () => manualResetEvent.Set()); + }); + + manualResetEvent.WaitOne(); + er = outError; + isCanceled = outIsCanceled; + + return result; + } + + protected TLVector ReuploadFile(TLFileCdnRedirect redirect, TLInt dcId, TLString requestToken, out TLRPCError er, out bool isCanceled, out bool isTokenInvalid) + { + var manualResetEvent = new ManualResetEvent(false); + TLVector result = null; + TLRPCError outError = null; + var outIsCanceled = false; + var outIsTokenInvalid = false; + + _mtProtoService.ReuploadCdnFileAsync(dcId, redirect.FileToken, requestToken, + callback => + { + result = callback; + + manualResetEvent.Set(); + }, + error => + { + outError = error; + + if (error.CodeEquals(ErrorCode.INTERNAL) + || (error.CodeEquals(ErrorCode.BAD_REQUEST) && (error.TypeEquals(ErrorType.LOCATION_INVALID) || error.TypeEquals(ErrorType.VOLUME_LOC_NOT_FOUND))) + || (error.CodeEquals(ErrorCode.NOT_FOUND) && error.Message != null && error.Message.ToString().StartsWith("Incorrect dhGen"))) + { + outIsCanceled = true; + + manualResetEvent.Set(); + return; + } + if (error.CodeEquals(ErrorCode.BAD_REQUEST) && (error.TypeEquals(ErrorType.FILE_TOKEN_INVALID) || error.TypeEquals(ErrorType.REQUEST_TOKEN_INVALID))) + { + outIsTokenInvalid = true; + + manualResetEvent.Set(); + return; + } + + int delay; + lock (_randomRoot) + { + delay = _random.Next(1000, 3000); + } + + Execute.BeginOnThreadPool(TimeSpan.FromMilliseconds(delay), () => manualResetEvent.Set()); + }); + + manualResetEvent.WaitOne(); + er = outError; + isCanceled = outIsCanceled; + isTokenInvalid = outIsTokenInvalid; + + return result; + } + + protected byte[] GetIV(byte[] ivec, TLInt offset) + { + var iv = new byte[ivec.Length]; + Buffer.BlockCopy(ivec, 0, iv, 0, ivec.Length); + + Array.Reverse(iv); + var bi = new System.Numerics.BigInteger(TLUtils.Combine(iv, new byte[] { 0x00 })); + bi = (bi + offset.Value/16); + var biArray = bi.ToByteArray(); + var b = new byte[16]; + Buffer.BlockCopy(biArray, 0, b, 0, Math.Min(b.Length, biArray.Length)); + + Array.Reverse(b); + + return b; + } + + protected TLFileBase GetCdnFile(TLFileCdnRedirect redirect, TLInt offset, TLInt limit, out TLCdnFileReuploadNeeded reuploadNeeded, out TLRPCError er, out bool isCanceled, out bool isTokenInvalid) + { + var manualResetEvent = new ManualResetEvent(false); + TLFileBase result = null; + TLCdnFileReuploadNeeded outReuploadNeeded = null; + TLRPCError outError = null; + var outIsCanceled = false; + var outIsTokenInvalid = false; + + _mtProtoService.GetCdnFileAsync(redirect.DCId, redirect.FileToken, offset, limit, + cdnFileBase => + { + var cdnFile = cdnFileBase as TLCdnFile; + if (cdnFile != null) + { + var iv = GetIV(redirect.EncryptionIV.Data, offset); + var counter = offset.Value / 16; + iv[15] = (byte)(counter & 0xFF); + iv[14] = (byte)((counter >> 8) & 0xFF); + iv[13] = (byte)((counter >> 16) & 0xFF); + iv[12] = (byte)((counter >> 24) & 0xFF); + + var key = redirect.EncryptionKey.Data; + + var ecount_buf = new byte[0]; + var num = 0u; + var bytes = Utils.AES_ctr128_encrypt(cdnFile.Bytes.Data, key, ref iv, ref ecount_buf, ref num); + + result = new TLFile { Bytes = TLString.FromBigEndianData(bytes) }; + } + + var cdnFileReuploadNeeded = cdnFileBase as TLCdnFileReuploadNeeded; + if (cdnFileReuploadNeeded != null) + { + outReuploadNeeded = cdnFileReuploadNeeded; + } + + manualResetEvent.Set(); + }, + error => + { + outError = error; + + if (error.CodeEquals(ErrorCode.INTERNAL) + || (error.CodeEquals(ErrorCode.BAD_REQUEST) && (error.TypeEquals(ErrorType.LOCATION_INVALID) || error.TypeEquals(ErrorType.VOLUME_LOC_NOT_FOUND))) + || (error.CodeEquals(ErrorCode.NOT_FOUND) && error.Message != null && error.Message.ToString().StartsWith("Incorrect dhGen"))) + { + outIsCanceled = true; + + manualResetEvent.Set(); + return; + } + if (error.CodeEquals(ErrorCode.BAD_REQUEST) && error.TypeEquals(ErrorType.FILE_TOKEN_INVALID)) + { + outIsTokenInvalid = true; + + manualResetEvent.Set(); + return; + } + + int delay; + lock (_randomRoot) + { + delay = _random.Next(1000, 3000); + } + + Execute.BeginOnThreadPool(TimeSpan.FromMilliseconds(delay), () => manualResetEvent.Set()); + }); + + manualResetEvent.WaitOne(); + reuploadNeeded = outReuploadNeeded; + er = outError; + isCanceled = outIsCanceled; + isTokenInvalid = outIsTokenInvalid; + + return result; + } + + protected virtual List GetItemParts(TLInt size, DownloadableItem item) + { + var chunkSize = size.Value > 1024 * 1024? Constants.DownloadedBigChunkSize : Constants.DownloadedChunkSize; + var parts = new List(); + var partsCount = size.Value / chunkSize + ((size.Value % chunkSize > 0 || size.Value == 0) ? 1 : 0); + for (var i = 0; i < partsCount; i++) + { + var part = new DownloadablePart(item, new TLInt(i * chunkSize), size.Value == 0 ? new TLInt(1024 * 1024) : new TLInt(chunkSize), i); + parts.Add(part); + } + + return parts; + } + + public void CancelDownloadFile(TLObject owner) + { + lock (_itemsSyncRoot) + { + var items = _items.Where(x => x.Owner == owner); + + foreach (var item in items) + { + item.Canceled = true; + } + } + } + + public void CancelDownloadFileAsync(TLObject owner) + { + Execute.BeginOnThreadPool(() => CancelDownloadFile(owner)); + } + + protected void StartAwaitingWorkers() + { + var awaitingWorkers = _workers.Where(x => x.IsWaiting); + + foreach (var awaitingWorker in awaitingWorkers) + { + awaitingWorker.Start(); + } + } + } +} diff --git a/Telegram.Api/Services/FileManager/IAudioFileManager.cs b/Telegram.Api/Services/FileManager/IAudioFileManager.cs new file mode 100755 index 0000000..ec08768 --- /dev/null +++ b/Telegram.Api/Services/FileManager/IAudioFileManager.cs @@ -0,0 +1,17 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public interface IAudioFileManager + { + void DownloadFile(TLInt dcId, TLInputFileLocationBase file, TLObject owner, TLInt fileSize, System.Action callback = null); + void CancelDownloadFile(TLObject owner); + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/FileManager/IDocumentFileManager.cs b/Telegram.Api/Services/FileManager/IDocumentFileManager.cs new file mode 100755 index 0000000..f04fa35 --- /dev/null +++ b/Telegram.Api/Services/FileManager/IDocumentFileManager.cs @@ -0,0 +1,18 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public interface IDocumentFileManager + { + void DownloadFileAsync(TLString fileName, TLInt dcId, TLInputFileLocationBase file, TLObject owner, TLInt fileSize, Action startCallback, Action callback = null); + void CancelDownloadFileAsync(TLObject owner); + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/FileManager/IEncryptedFileManager.cs b/Telegram.Api/Services/FileManager/IEncryptedFileManager.cs new file mode 100755 index 0000000..a2bd5d6 --- /dev/null +++ b/Telegram.Api/Services/FileManager/IEncryptedFileManager.cs @@ -0,0 +1,18 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public interface IEncryptedFileManager + { + void DownloadFile(TLEncryptedFile file, TLObject owner, Action callback = null); + void CancelDownloadFile(TLObject owner); + } +} diff --git a/Telegram.Api/Services/FileManager/IFileManager.cs b/Telegram.Api/Services/FileManager/IFileManager.cs new file mode 100755 index 0000000..6212db3 --- /dev/null +++ b/Telegram.Api/Services/FileManager/IFileManager.cs @@ -0,0 +1,18 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public interface IFileManager + { + void DownloadFile(TLFileLocation file, TLObject owner, TLInt fileSize); + void DownloadFile(TLFileLocation file, TLObject owner, TLInt fileSize, System.Action callback); + void CancelDownloadFile(TLObject owner); + } +} diff --git a/Telegram.Api/Services/FileManager/IUploadAudioFileManager.cs b/Telegram.Api/Services/FileManager/IUploadAudioFileManager.cs new file mode 100755 index 0000000..86934aa --- /dev/null +++ b/Telegram.Api/Services/FileManager/IUploadAudioFileManager.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public interface IUploadAudioFileManager + { + void UploadFile(TLLong fileId, TLObject owner, string fileName); + void UploadFile(TLLong fileId, TLObject owner, string fileName, IList parts); + void CancelUploadFile(TLLong fileId); + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/FileManager/IUploadFileManager.cs b/Telegram.Api/Services/FileManager/IUploadFileManager.cs new file mode 100755 index 0000000..e9155f7 --- /dev/null +++ b/Telegram.Api/Services/FileManager/IUploadFileManager.cs @@ -0,0 +1,33 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#if WP8 +using Windows.Storage; +#endif +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public interface IUploadFileManager + { + void UploadFile(TLLong fileId, TLObject owner, byte[] bytes); +#if WP8 + void UploadFile(TLLong fileId, TLObject owner, StorageFile file); +#endif + void CancelUploadFile(TLLong fileId); + } + + public interface IUploadDocumentFileManager + { + void UploadFile(TLLong fileId, TLObject owner, byte[] bytes); +#if WP8 + void UploadFile(TLLong fileId, TLObject owner, StorageFile file); + void UploadFile(TLLong fileId, TLObject owner, StorageFile file, TLString key, TLString iv); +#endif + void CancelUploadFile(TLLong fileId); + } +} diff --git a/Telegram.Api/Services/FileManager/IUploadVideoFileManager.cs b/Telegram.Api/Services/FileManager/IUploadVideoFileManager.cs new file mode 100755 index 0000000..9cd1f8e --- /dev/null +++ b/Telegram.Api/Services/FileManager/IUploadVideoFileManager.cs @@ -0,0 +1,27 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +#if WP8 +using Windows.Storage; +#endif +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public interface IUploadVideoFileManager + { + void UploadFile(TLLong fileId, TLObject owner, string fileName); + void UploadFile(TLLong fileId, TLObject owner, string fileName, IList parts); + +#if WP8 + void UploadFile(TLLong fileId, bool isGif, TLObject owner, StorageFile file); +#endif + + void CancelUploadFile(TLLong fileId); + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/FileManager/IVideoFileManager.cs b/Telegram.Api/Services/FileManager/IVideoFileManager.cs new file mode 100755 index 0000000..630c05e --- /dev/null +++ b/Telegram.Api/Services/FileManager/IVideoFileManager.cs @@ -0,0 +1,18 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public interface IVideoFileManager + { + void DownloadFileAsync(TLInt dcId, TLInputFileLocationBase file, TLObject owner, TLInt fileSize, Action callback); + void CancelDownloadFileAsync(TLObject owner); + } +} diff --git a/Telegram.Api/Services/FileManager/ProgressChangedEventArgs.cs b/Telegram.Api/Services/FileManager/ProgressChangedEventArgs.cs new file mode 100755 index 0000000..7e26e95 --- /dev/null +++ b/Telegram.Api/Services/FileManager/ProgressChangedEventArgs.cs @@ -0,0 +1,22 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.Services.FileManager +{ + public class ProgressChangedEventArgs + { + public double Progress { get; protected set; } + + public DownloadableItem Item { get; protected set; } + + public ProgressChangedEventArgs(DownloadableItem item, double progress) + { + Item = item; + Progress = progress; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/FileManager/UploadAudioFileManager.cs b/Telegram.Api/Services/FileManager/UploadAudioFileManager.cs new file mode 100755 index 0000000..4a7a3d9 --- /dev/null +++ b/Telegram.Api/Services/FileManager/UploadAudioFileManager.cs @@ -0,0 +1,296 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using Telegram.Api.Aggregator; +using Telegram.Api.Helpers; +using Telegram.Api.TL; + + +namespace Telegram.Api.Services.FileManager +{ + public class UploadAudioFileManager : IUploadAudioFileManager + { + private readonly object _itemsSyncRoot = new object(); + + private readonly List _items = new List(); + + private readonly List _workers = new List(Constants.WorkersNumber); + + private readonly ITelegramEventAggregator _eventAggregator; + + private readonly IMTProtoService _mtProtoService; + + public UploadAudioFileManager(ITelegramEventAggregator eventAggregator, IMTProtoService mtProtoService) + { + _eventAggregator = eventAggregator; + _mtProtoService = mtProtoService; + + + var timer = Stopwatch.StartNew(); + for (int i = 0; i < Constants.VideoUploadersCount; i++) + { + var worker = new Worker(OnUploading, "audioUploader" + i); + _workers.Add(worker); + } + + TLUtils.WritePerformance("Start workers timer: " + timer.Elapsed); + + } + + private void OnUploading(object state) + { + UploadablePart part = null; + lock (_itemsSyncRoot) + { + for (var i = 0; i < _items.Count; i++) + { + var item = _items[i]; + if (item.Canceled) + { + _items.RemoveAt(i--); + try + { + _eventAggregator.Publish(new UploadingCanceledEventArgs(item)); + } + catch (Exception e) + { + TLUtils.WriteException(e); + } + } + } + + foreach (var item in _items) + { + part = item.Parts.FirstOrDefault(x => x.Status == PartStatus.Ready); + if (part != null) + { + part.Status = PartStatus.Processing; + break; + } + } + } + + if (part != null) + { + var bytes = FileUtils.ReadBytes(part.ParentItem.IsoFileName, part.Position, part.Count); + part.SetBuffer(bytes); + + bool result = PutFile(part.ParentItem.FileId, part.FilePart, part.Bytes); + while (!result) + { + if (part.ParentItem.Canceled) + { + return; + } + result = PutFile(part.ParentItem.FileId, part.FilePart, part.Bytes); + } + + part.ClearBuffer(); + + + // indicate progress + // indicate complete + bool isComplete = false; + bool isCanceled; + var progress = 0.0; + lock (_itemsSyncRoot) + { + part.Status = PartStatus.Processed; + isCanceled = part.ParentItem.Canceled; + if (!isCanceled) + { + isComplete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!isComplete) + { + double uploadedCount = part.ParentItem.Parts.Count(x => x.Status == PartStatus.Processed); + double totalCount = part.ParentItem.Parts.Count; + progress = uploadedCount / totalCount; + } + else + { + _items.Remove(part.ParentItem); + } + } + } + + if (!isCanceled) + { + if (isComplete) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(part.ParentItem)); + } + else + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new UploadProgressChangedEventArgs(part.ParentItem, progress))); + } + } + } + else + { + var currentWorker = (Worker)state; + currentWorker.Stop(); + } + } + + private bool PutFile(TLLong fileId, TLInt filePart, byte[] bytes) + { + var manualResetEvent = new ManualResetEvent(false); + var result = false; + + _mtProtoService.SaveFilePartAsync(fileId, filePart, TLString.FromBigEndianData(bytes), + savingResult => + { + result = true; + manualResetEvent.Set(); + }, + error => + { + + Execute.BeginOnThreadPool(TimeSpan.FromMilliseconds(1000), () => manualResetEvent.Set()); + }); + + manualResetEvent.WaitOne(); + return result; + } + + public void UploadFile(TLLong fileId, TLObject owner, string fileName) + { + long fileLength = FileUtils.GetLocalFileLength(fileName); + if (fileLength <= 0) return; + + var item = GetUploadableItem(fileId, owner, fileName, fileLength); + + var uploadedCount = item.Parts.Count(x => x.Status == PartStatus.Processed); + var count = item.Parts.Count; + var isComplete = uploadedCount == count; + + if (isComplete) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(item)); + } + else + { + lock (_itemsSyncRoot) + { + _items.Add(item); + } + + StartAwaitingWorkers(); + } + } + + public void UploadFile(TLLong fileId, TLObject owner, string fileName, IList parts) + { + long fileLength = FileUtils.GetLocalFileLength(fileName); + if (fileLength <= 0) return; + + var item = GetUploadableItem(fileId, owner, fileName, fileLength, parts); + + var uploadedCount = item.Parts.Count(x => x.Status == PartStatus.Processed); + var count = item.Parts.Count; + var isComplete = uploadedCount == count; + + //if (isComplete) + //{ + // Execute.BeginOnThreadPool(() => _eventAggregator.Publish(item)); + //} + //else + { + lock (_itemsSyncRoot) + { + _items.Add(item); + } + + StartAwaitingWorkers(); + } + } + + private UploadableItem GetUploadableItem(TLLong fileId, TLObject owner, string isoFileName, long isoFileLength, IList parts) + { + var item = new UploadableItem(fileId, owner, isoFileName, isoFileLength); + item.Parts = GetItemParts(item, isoFileLength, parts); + return item; + } + + private UploadableItem GetUploadableItem(TLLong fileId, TLObject owner, string isoFileName, long isoFileLength) + { + var item = new UploadableItem(fileId, owner, isoFileName, isoFileLength); + item.Parts = GetItemParts(item, isoFileLength); + return item; + } + + private List GetItemParts(UploadableItem item, long isoFileLength) + { + const int partSize = 32 * 1024; // 32 Kb: 1 Kb 1024 Kb + var parts = new List(); + var partsCount = item.IsoFileLength / partSize + (item.IsoFileLength % partSize > 0 ? 1 : 0); + for (var i = 0; i < partsCount; i++) + { + var part = new UploadablePart(item, new TLInt(i), i * partSize, Math.Min(partSize, isoFileLength - i * partSize)); + parts.Add(part); + } + + return parts; + } + + private List GetItemParts(UploadableItem item, long isoFileLength, IList uploadedParts) + { + const int partSize = 32 * 1024; + foreach (var uploadedPart in uploadedParts) + { + uploadedPart.SetParentItem(item); + } + var parts = new List(uploadedParts); + + var uploadedLength = uploadedParts.Sum(x => x.Count); + + var uploadingLength = item.IsoFileLength - uploadedLength; + if (uploadingLength == 0) + { + return parts; + } + var partsCount = uploadingLength / partSize + 1; + for (var i = 0; i < partsCount; i++) + { + var partId = i + uploadedParts.Count; + var part = new UploadablePart(item, new TLInt(partId), uploadedLength + i * partSize, Math.Min(partSize, isoFileLength - (uploadedLength + i * partSize))); + parts.Add(part); + } + + return parts; + } + + private void StartAwaitingWorkers() + { + var awaitingWorkers = _workers.Where(x => x.IsWaiting); + + foreach (var awaitingWorker in awaitingWorkers) + { + awaitingWorker.Start(); + } + } + + public void CancelUploadFile(TLLong fileId) + { + lock (_itemsSyncRoot) + { + var item = _items.FirstOrDefault(x => x.FileId.Value == fileId.Value); + + if (item != null) + { + item.Canceled = true; + //_items.Remove(item); + } + } + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/FileManager/UploadFileManager.cs b/Telegram.Api/Services/FileManager/UploadFileManager.cs new file mode 100755 index 0000000..909fa55 --- /dev/null +++ b/Telegram.Api/Services/FileManager/UploadFileManager.cs @@ -0,0 +1,726 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading; +using System.Windows.Input; +#if WINDOWS_PHONE +using Microsoft.Phone.Shell; +#endif +#if WP8 +using System.Threading.Tasks; +using Windows.Storage; +using Windows.Storage.Streams; +#endif +using Telegram.Api.Aggregator; +using Telegram.Api.Helpers; +using Telegram.Api.TL; +using Execute = Telegram.Api.Helpers.Execute; + + +namespace Telegram.Api.Services.FileManager +{ + public class UploadProgressChangedEventArgs + { + public double Progress { get; protected set; } + + public UploadableItem Item { get; protected set; } + + public UploadProgressChangedEventArgs(UploadableItem item, double progress) + { + Item = item; + Progress = progress; + } + } + + public class UploadablePart + { + public UploadableItem ParentItem { get; protected set; } + + public TLInt FilePart { get; protected set; } + + public PartStatus Status { get; set; } + + public byte[] Bytes { get; protected set; } + + public long Position { get; protected set; } + + public long Count { get; protected set; } + + public TLString IV { get; set; } + + public void ClearBuffer() + { + Bytes = null; + } + + public UploadablePart(UploadableItem item, TLInt filePart, byte[] bytes) + { + ParentItem = item; + FilePart = filePart; + Bytes = bytes; + } + + public UploadablePart(UploadableItem item, TLInt filePart, long position, long count) + { + ParentItem = item; + FilePart = filePart; + Position = position; + Count = count; + } + + public UploadablePart(UploadableItem item, TLInt filePart, byte[] bytes, long position, long count) + { + ParentItem = item; + FilePart = filePart; + Bytes = bytes; + Position = position; + Count = count; + } + + public override string ToString() + { + return string.Format("Part={0}, Status={1}, Position={2}, Count={3}", FilePart, Status, Position, Count); + } + + public void SetBuffer(byte[] bytes) + { + Bytes = bytes; + } + + public void SetParentItem(UploadableItem item) + { + ParentItem = item; + } + } + + public class UploadableItem + { + public bool FileNotFound { get; set; } + + public bool IsSmallFile { get; set; } + + public TLLong FileId { get; protected set; } + + public string IsoFileName { get; protected set; } + + public long IsoFileLength { get; protected set; } + + public TLObject Owner { get; protected set; } + +#if WP8 + public StorageFile File { get; protected set; } + + public TLString Key { get; protected set; } + + public TLString IV { get; protected set; } +#endif + + public byte[] Bytes { get; protected set; } + + public List Parts { get; set; } + + public bool Canceled { get; set; } + + public UploadableItem(TLLong fileId, TLObject owner, byte[] bytes) + { + FileId = fileId; + Owner = owner; + Bytes = bytes; + } + +#if WP8 + public UploadableItem(TLLong fileId, TLObject owner, StorageFile file) + { + FileId = fileId; + Owner = owner; + File = file; + } + + public UploadableItem(TLLong fileId, TLObject owner, StorageFile file, TLString key, TLString iv) + { + FileId = fileId; + Owner = owner; + File = file; + + Key = key; + IV = iv; + } +#endif + + public UploadableItem(TLLong fileId, TLObject owner, string isoFileName, long isoFileLength) + { + FileId = fileId; + Owner = owner; + IsoFileName = isoFileName; + IsoFileLength = isoFileLength; + } + } + + public class UploadFileManager : IUploadFileManager + { + private readonly object _itemsSyncRoot = new object(); + + private readonly List _items = new List(); + + private readonly List _workers = new List(Constants.WorkersNumber); + + private readonly ITelegramEventAggregator _eventAggregator; + + private readonly IMTProtoService _mtProtoService; + + public UploadFileManager(ITelegramEventAggregator eventAggregator, IMTProtoService mtProtoService) + { + _eventAggregator = eventAggregator; + _mtProtoService = mtProtoService; + + + var timer = Stopwatch.StartNew(); + for (int i = 0; i < Constants.WorkersNumber; i++) + { + var worker = new Worker(OnUploading, "uploader"+i); + _workers.Add(worker); + } + + TLUtils.WritePerformance("Start workers timer: " + timer.Elapsed); + + } + + private void OnUploading(object state) + { + UploadablePart part = null; + lock (_itemsSyncRoot) + { + for (var i = 0; i < _items.Count; i++) + { + var item = _items[i]; + if (item.Canceled) + { + _items.RemoveAt(i--); + try + { + _eventAggregator.Publish(new UploadingCanceledEventArgs(item)); + } + catch (Exception e) + { + TLUtils.WriteException(e); + } + } + } + + + foreach (var item in _items) + { + part = item.Parts.FirstOrDefault(x => x.Status == PartStatus.Ready); + if (part != null) + { + part.Status = PartStatus.Processing; + break; + } + } + } + + if (part != null) + { + var bytes = part.Bytes; +#if WP8 + if (bytes == null) + { + var file = part.ParentItem.File; + if (file != null) + { + var task = FileUtils.FillBuffer(file, part); + task.Wait(); + + bytes = task.Result.Item2; + } + + if (bytes == null) + { + part.Status = PartStatus.Ready; + return; + } + } +#endif + + var result = PutFile(part.ParentItem.FileId, part.FilePart, new TLInt(part.ParentItem.Parts.Count), bytes); + while (!result) + { + if (part.ParentItem.Canceled) + { + return; + } + result = PutFile(part.ParentItem.FileId, part.FilePart, new TLInt(part.ParentItem.Parts.Count), bytes); + } + + // indicate progress + // indicate complete + bool isComplete = false; + bool isCanceled; + var progress = 0.0; + lock (_itemsSyncRoot) + { + part.Status = PartStatus.Processed; + isCanceled = part.ParentItem.Canceled; + if (!isCanceled) + { + isComplete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!isComplete) + { + double uploadedCount = part.ParentItem.Parts.Count(x => x.Status == PartStatus.Processed); + double totalCount = part.ParentItem.Parts.Count; + progress = uploadedCount / totalCount; + } + else + { + _items.Remove(part.ParentItem); + } + } + } + + if (!isCanceled) + { + if (isComplete) + { + try + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(part.ParentItem)); + } + catch (Exception e) + { + TLUtils.WriteLine(e.ToString(), LogSeverity.Error); + } + } + else + { + try + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new UploadProgressChangedEventArgs(part.ParentItem, progress))); + } + catch (Exception e) + { + TLUtils.WriteLine(e.ToString(), LogSeverity.Error); + } + } + } + } + else + { + + var currentWorker = (Worker)state; + currentWorker.Stop(); + } + } + + private bool PutFile(TLLong fileId, TLInt filePart, TLInt fileTotalPars, byte[] bytes) + { + var manualResetEvent = new ManualResetEvent(false); + var result = false; + + _mtProtoService.SaveFilePartAsync(fileId, filePart, TLString.FromBigEndianData(bytes), + savingResult => + { + result = true; + manualResetEvent.Set(); + }, + error => Execute.BeginOnThreadPool(TimeSpan.FromSeconds(1.0), () => + { + Execute.ShowDebugMessage(string.Format("upload.saveFilePart part={0}, bytesCount={1} error\n", filePart.Value, bytes.Length) + error); + + manualResetEvent.Set(); + })); + + manualResetEvent.WaitOne(); + return result; + } + + public void UploadFile(TLLong fileId, TLObject owner, byte[] bytes) + { + var item = GetUploadableItem(fileId, owner, bytes); + + lock (_itemsSyncRoot) + { + _items.Add(item); + } + + StartAwaitingWorkers(); + } + +#if WP8 + public void UploadFile(TLLong fileId, TLObject owner, StorageFile file) + { + var item = GetUploadableItem(fileId, owner, file); + + lock (_itemsSyncRoot) + { + _items.Add(item); + } + + StartAwaitingWorkers(); + } + + private UploadableItem GetUploadableItem(TLLong fileId, TLObject owner, StorageFile file) + { + var item = new UploadableItem(fileId, owner, file); + + var task = file.GetBasicPropertiesAsync().AsTask(); + task.Wait(); + var propertie = task.Result; + var size = propertie.Size; + item.Parts = GetItemParts(item, (int)size); + return item; + } + + private static List GetItemParts(UploadableItem item, int size) + { + var chunkSize = FileUtils.GetChunkSize(size); + var partsCount = FileUtils.GetPartsCount(size, chunkSize); + var parts = new List(partsCount); + + for (var i = 0; i < partsCount; i++) + { + var part = new UploadablePart(item, new TLInt(i), i * chunkSize, Math.Min(chunkSize, (long)size - i * chunkSize)); + parts.Add(part); + } + + return parts; + } +#endif + + private UploadableItem GetUploadableItem(TLLong fileId, TLObject owner, byte[] bytes) + { + var item = new UploadableItem(fileId, owner, bytes); + item.Parts = GetItemParts(item); + return item; + } + + private static List GetItemParts(UploadableItem item) + { + var size = item.Bytes.Length; + var chunkSize = FileUtils.GetChunkSize(size); + var partsCount = FileUtils.GetPartsCount(size, chunkSize); + var parts = new List(partsCount); + + for (var i = 0; i < partsCount; i++) + { + var part = new UploadablePart(item, new TLInt(i), item.Bytes.SubArray(i * chunkSize, Math.Min(chunkSize, item.Bytes.Length - i * chunkSize))); + parts.Add(part); + } + + return parts; + } + + private void StartAwaitingWorkers() + { + var awaitingWorkers = _workers.Where(x => x.IsWaiting); + + foreach (var awaitingWorker in awaitingWorkers) + { + awaitingWorker.Start(); + } + } + + public void CancelUploadFile(TLLong fileId) + { + lock (_itemsSyncRoot) + { + var item = _items.FirstOrDefault(x => x.FileId.Value == fileId.Value); + + if (item != null) + { + item.Canceled = true; + //_items.Remove(item); + } + } + } + } + + public class UploadingCanceledEventArgs + { + public UploadableItem Item { get; protected set; } + + public UploadingCanceledEventArgs(UploadableItem item) + { + Item = item; + } + } + + public class UploadDocumentFileManager : IUploadDocumentFileManager + { + private readonly object _itemsSyncRoot = new object(); + + private readonly List _items = new List(); + + private readonly List _workers = new List(Constants.WorkersNumber); + + private readonly ITelegramEventAggregator _eventAggregator; + + private readonly IMTProtoService _mtProtoService; + + public UploadDocumentFileManager(ITelegramEventAggregator eventAggregator, IMTProtoService mtProtoService) + { + _eventAggregator = eventAggregator; + _mtProtoService = mtProtoService; + + + var timer = Stopwatch.StartNew(); + for (var i = 0; i < Constants.DocumentUploadersCount; i++) + { + var worker = new Worker(OnUploading, "documentUploader" + i); + _workers.Add(worker); + } + + TLUtils.WritePerformance("Start workers timer: " + timer.Elapsed); + + } + + private void OnUploading(object state) + { + UploadablePart part = null; + lock (_itemsSyncRoot) + { + for (var i = 0; i < _items.Count; i++) + { + var item = _items[i]; + if (item.Canceled) + { + _items.RemoveAt(i--); + try + { + _eventAggregator.Publish(new UploadingCanceledEventArgs(item)); + } + catch (Exception e) + { + TLUtils.WriteException(e); + } + } + } + + foreach (var item in _items) + { + part = item.Parts.FirstOrDefault(x => x.Status == PartStatus.Ready); + if (part != null) + { + part.Status = PartStatus.Processing; + break; + } + } + } + + if (part != null) + { + var bytes = part.Bytes; +#if WP8 + if (bytes == null) + { + var file = part.ParentItem.File; + Tuple result = null; + if (file != null) + { + var task = FileUtils.FillBuffer(file, part); + task.Wait(); + result = task.Result; + } + + if (result == null) + { + part.Status = PartStatus.Ready; + return; + } + + if (result.Item1 && result.Item2 == null) + { + part.Status = PartStatus.Ready; + return; + } + + if (!result.Item1) + { + part.ParentItem.FileNotFound = true; + part.Status = PartStatus.Processed; + FileUtils.NotifyProgress(_itemsSyncRoot, _items, part, _eventAggregator); + return; + } + + bytes = result.Item2; + + if (bytes == null) + { + part.Status = PartStatus.Ready; + return; + } + } +#endif + if (part.ParentItem.IsSmallFile) + { + bool result = PutFile(part.ParentItem.FileId, part.FilePart, bytes); + while (!result) + { + if (part.ParentItem.Canceled) + { + return; + } + result = PutFile(part.ParentItem.FileId, part.FilePart, bytes); + } + } + else + { + bool result = PutBigFile(part.ParentItem.FileId, part.FilePart, new TLInt(part.ParentItem.Parts.Count), bytes); + while (!result) + { + if (part.ParentItem.Canceled) + { + return; + } + result = PutBigFile(part.ParentItem.FileId, part.FilePart, new TLInt(part.ParentItem.Parts.Count), bytes); + } + } + + FileUtils.NotifyProgress(_itemsSyncRoot, _items, part, _eventAggregator); + } + else + { + + var currentWorker = (Worker)state; + currentWorker.Stop(); + } + } + + + private bool PutBigFile(TLLong fileId, TLInt filePart, TLInt fileTotalPars, byte[] bytes) + { + var manualResetEvent = new ManualResetEvent(false); + var result = false; + + _mtProtoService.SaveBigFilePartAsync(fileId, filePart, fileTotalPars, TLString.FromBigEndianData(bytes), + savingResult => + { + result = true; + manualResetEvent.Set(); + }, + error => Execute.BeginOnThreadPool(TimeSpan.FromSeconds(1.0), () => + { + Execute.ShowDebugMessage(string.Format("upload.saveBigFilePart part={0}, count={1} error\n", filePart.Value, bytes.Length) + error); + + manualResetEvent.Set(); + })); + + manualResetEvent.WaitOne(); + return result; + } + + private bool PutFile(TLLong fileId, TLInt filePart, byte[] bytes) + { + var manualResetEvent = new ManualResetEvent(false); + var result = false; + + _mtProtoService.SaveFilePartAsync(fileId, filePart, TLString.FromBigEndianData(bytes), + savingResult => + { + result = true; + manualResetEvent.Set(); + }, + error => Execute.BeginOnThreadPool(TimeSpan.FromSeconds(1.0), () => + { + Execute.ShowDebugMessage(string.Format("upload.saveBigFilePart part={0}, count={1} error\n", filePart.Value, bytes.Length) + error); + + manualResetEvent.Set(); + })); + + manualResetEvent.WaitOne(); + return result; + } + + public void UploadFile(TLLong fileId, TLObject owner, byte[] bytes) + { + FileUtils.SwitchIdleDetectionMode(false); + var item = GetUploadableItem(fileId, owner, bytes); + lock (_itemsSyncRoot) + { + _items.Add(item); + } + + StartAwaitingWorkers(); + } + +#if WP8 + public void UploadFile(TLLong fileId, TLObject owner, StorageFile file) + { + UploadFile(fileId, owner, file, null, null); + } + + public void UploadFile(TLLong fileId, TLObject owner, StorageFile file, TLString key, TLString iv) + { + FileUtils.SwitchIdleDetectionMode(false); + var item = FileUtils.GetUploadableItem(fileId, owner, file, key, iv); + //if (item) + //{ + // item.IsSmallFile = false; // to void auto convert small video documents to videos on server side + //} + lock (_itemsSyncRoot) + { + _items.Add(item); + } + + StartAwaitingWorkers(); + } +#endif + + private UploadableItem GetUploadableItem(TLLong fileId, TLObject owner, byte[] bytes) + { + var item = new UploadableItem(fileId, owner, bytes); + item.Parts = GetItemParts(item); + return item; + } + + private static List GetItemParts(UploadableItem item) + { + var size = item.Bytes.Length; + var chunkSize = FileUtils.GetChunkSize(size); + var partsCount = FileUtils.GetPartsCount(size, chunkSize); + var parts = new List(partsCount); + + for (var i = 0; i < partsCount; i++) + { + var part = new UploadablePart(item, new TLInt(i), item.Bytes.SubArray(i * chunkSize, Math.Min(chunkSize, item.Bytes.Length - i * chunkSize))); + parts.Add(part); + } + + item.IsSmallFile = size < Constants.SmallFileMaxSize;// size < chunkSize; + + return parts; + } + + private void StartAwaitingWorkers() + { + var awaitingWorkers = _workers.Where(x => x.IsWaiting); + + foreach (var awaitingWorker in awaitingWorkers) + { + awaitingWorker.Start(); + } + } + + public void CancelUploadFile(TLLong fileId) + { + lock (_itemsSyncRoot) + { + var item = _items.FirstOrDefault(x => x.FileId.Value == fileId.Value); + + if (item != null) + { + item.Canceled = true; + //_items.Remove(item); + } + } + } + } +} diff --git a/Telegram.Api/Services/FileManager/UploadVideoFileManager.cs b/Telegram.Api/Services/FileManager/UploadVideoFileManager.cs new file mode 100755 index 0000000..b938735 --- /dev/null +++ b/Telegram.Api/Services/FileManager/UploadVideoFileManager.cs @@ -0,0 +1,359 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using Telegram.Api.Helpers; +#if WP8 +using Windows.Storage; +#endif +using Telegram.Api.Aggregator; +using Telegram.Api.TL; + + +namespace Telegram.Api.Services.FileManager +{ + public class UploadVideoFileManager : IUploadVideoFileManager + { + private readonly object _itemsSyncRoot = new object(); + + private readonly List _items = new List(); + + private readonly List _workers = new List(Constants.WorkersNumber); + + private readonly ITelegramEventAggregator _eventAggregator; + + private readonly IMTProtoService _mtProtoService; + + public UploadVideoFileManager(ITelegramEventAggregator eventAggregator, IMTProtoService mtProtoService) + { + _eventAggregator = eventAggregator; + _mtProtoService = mtProtoService; + + + var timer = Stopwatch.StartNew(); + for (int i = 0; i < Constants.VideoUploadersCount; i++) + { + var worker = new Worker(OnUploading, "videoUploader"+i); + _workers.Add(worker); + } + + TLUtils.WritePerformance("Start workers timer: " + timer.Elapsed); + + } + + private void OnUploading(object state) + { + UploadablePart part = null; + lock (_itemsSyncRoot) + { + for (var i = 0; i < _items.Count; i++) + { + var item = _items[i]; + if (item.Canceled) + { + _items.RemoveAt(i--); + try + { + _eventAggregator.Publish(new UploadingCanceledEventArgs(item)); + } + catch (Exception e) + { + TLUtils.WriteException(e); + } + } + } + + foreach (var item in _items) + { + part = item.Parts.FirstOrDefault(x => x.Status == PartStatus.Ready); + if (part != null) + { + part.Status = PartStatus.Processing; + break; + } + } + } + + if (part != null) + { + var bytes = part.Bytes; + + var fileName = part.ParentItem.IsoFileName; + if (!string.IsNullOrEmpty(fileName)) + { + bytes = FileUtils.ReadBytes(fileName, part.Position, part.Count); + } +#if WP8 + if (bytes == null) + { + var file = part.ParentItem.File; + Tuple result = null; + if (file != null) + { + var task = FileUtils.FillBuffer(file, part); + task.Wait(); + result = task.Result; + } + + if (result == null) + { + part.Status = PartStatus.Ready; + return; + } + + if (!result.Item1) + { + part.ParentItem.FileNotFound = true; + part.Status = PartStatus.Processed; + FileUtils.NotifyProgress(_itemsSyncRoot, _items, part, _eventAggregator); + return; + } + + bytes = result.Item2; + + if (bytes == null) + { + part.Status = PartStatus.Ready; + return; + } + } +#endif + if (bytes == null) + { + Logs.Log.Write(string.Format("UploadVideoFileManager.OnUploading bytes=null position={0} count={1} fileName={2}", part.Position, part.Count, fileName)); + //Execute.ShowDebugMessage(string.Format("UploadVideoFileManager.OnUploading bytes=null position={0} count={1} fileName={2}", part.Position, part.Count, fileName)); + } + + if (part.ParentItem.IsSmallFile) + { + var result = PutFile(part.ParentItem.FileId, part.FilePart, bytes); + while (!result) + { + if (part.ParentItem.Canceled) + { + return; + } + result = PutFile(part.ParentItem.FileId, part.FilePart, bytes); + } + } + else + { + var result = PutBigFile(part.ParentItem.FileId, part.FilePart, new TLInt(part.ParentItem.Parts.Count), bytes); + while (!result) + { + if (part.ParentItem.Canceled) + { + return; + } + result = PutBigFile(part.ParentItem.FileId, part.FilePart, new TLInt(part.ParentItem.Parts.Count), bytes); + } + } + part.ClearBuffer(); + + FileUtils.NotifyProgress(_itemsSyncRoot, _items, part, _eventAggregator); + } + else + { + var currentWorker = (Worker)state; + currentWorker.Stop(); + } + } + + private bool PutFile(TLLong fileId, TLInt filePart, byte[] bytes) + { + var manualResetEvent = new ManualResetEvent(false); + var result = false; + + _mtProtoService.SaveFilePartAsync(fileId, filePart, TLString.FromBigEndianData(bytes), + savingResult => + { + result = true; + manualResetEvent.Set(); + }, + error => + { + Execute.BeginOnThreadPool(TimeSpan.FromMilliseconds(1000), () => manualResetEvent.Set()); + }); + + manualResetEvent.WaitOne(); + return result; + } + + private bool PutBigFile(TLLong fileId, TLInt filePart, TLInt fileTotalParts, byte[] bytes) + { + var manualResetEvent = new ManualResetEvent(false); + var result = false; + + _mtProtoService.SaveBigFilePartAsync(fileId, filePart, fileTotalParts, TLString.FromBigEndianData(bytes), + savingResult => + { + result = true; + manualResetEvent.Set(); + }, + error => + { + Execute.BeginOnThreadPool(TimeSpan.FromMilliseconds(1000), () => manualResetEvent.Set()); + }); + + manualResetEvent.WaitOne(); + return result; + } + + public void UploadFile(TLLong fileId, TLObject owner, string fileName) + { + var fileLength = FileUtils.GetLocalFileLength(fileName); + if (fileLength <= 0) return; + + var item = GetUploadableItem(fileId, owner, fileName, fileLength); + + var uploadedCount = item.Parts.Count(x => x.Status == PartStatus.Processed); + var count = item.Parts.Count; + var isComplete = uploadedCount == count; + + if (isComplete) + { + Helpers.Execute.BeginOnThreadPool(() => _eventAggregator.Publish(item)); + } + else + { + lock (_itemsSyncRoot) + { + _items.Add(item); + } + + StartAwaitingWorkers(); + } + } + +#if WP8 + public void UploadFile(TLLong fileId, bool isGif, TLObject owner, StorageFile file) + { + FileUtils.SwitchIdleDetectionMode(false); + + var item = FileUtils.GetUploadableItem(fileId, owner, file); + item.IsSmallFile = isGif && item.Parts.Sum(part => part.Count) < Constants.GifMaxSize; + lock (_itemsSyncRoot) + { + _items.Add(item); + } + + StartAwaitingWorkers(); + } +#endif + + public void UploadFile(TLLong fileId, TLObject owner, string fileName, IList parts) + { + FileUtils.SwitchIdleDetectionMode(false); + + long fileLength = FileUtils.GetLocalFileLength(fileName); + if (fileLength <= 0) return; + + var item = GetUploadableItem(fileId, owner, fileName, fileLength, parts); + + var uploadedCount = item.Parts.Count(x => x.Status == PartStatus.Processed); + var count = item.Parts.Count; + var isComplete = uploadedCount == count; + + if (isComplete) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(item)); + } + else + { + lock (_itemsSyncRoot) + { + _items.Add(item); + } + + StartAwaitingWorkers(); + } + } + + private UploadableItem GetUploadableItem(TLLong fileId, TLObject owner, string fileName, long fileLength) + { + FileUtils.SwitchIdleDetectionMode(false); + + var item = new UploadableItem(fileId, owner, fileName, fileLength); + item.Parts = GetItemParts(item, fileLength); + return item; + } + + private UploadableItem GetUploadableItem(TLLong fileId, TLObject owner, string fileName, long fileLength, IList parts) + { + var item = new UploadableItem(fileId, owner, fileName, fileLength); + item.Parts = GetItemParts(item, fileLength, parts); + return item; + } + + private List GetItemParts(UploadableItem item, long fileLength) + { + var chunkSize = FileUtils.GetChunkSize(fileLength); + var partsCount = FileUtils.GetPartsCount(fileLength, chunkSize); + var parts = new List(); + for (var i = 0; i < partsCount; i++) + { + var part = new UploadablePart(item, new TLInt(i), i * chunkSize, Math.Min(chunkSize, fileLength - i * chunkSize)); + parts.Add(part); + } + + item.IsSmallFile = fileLength < chunkSize; + + return parts; + } + + private List GetItemParts(UploadableItem item, long fileLength, IList uploadedParts) + { + var chunkSize = FileUtils.GetChunkSize(fileLength); + var parts = new List(uploadedParts); + foreach (var uploadedPart in uploadedParts) + { + uploadedPart.SetParentItem(item); + } + var uploadedLength = uploadedParts.Sum(x => x.Count); + + var partsCount = FileUtils.GetPartsCount(item.IsoFileLength - uploadedLength, chunkSize); + for (var i = 0; i < partsCount; i++) + { + var partId = i + uploadedParts.Count; + var part = new UploadablePart(item, new TLInt(partId), uploadedLength + i * chunkSize, Math.Min(chunkSize, fileLength - (uploadedLength + i * chunkSize))); + parts.Add(part); + } + + item.IsSmallFile = fileLength < chunkSize; + + return parts; + } + + private void StartAwaitingWorkers() + { + var awaitingWorkers = _workers.Where(x => x.IsWaiting); + + foreach (var awaitingWorker in awaitingWorkers) + { + awaitingWorker.Start(); + } + } + + public void CancelUploadFile(TLLong fileId) + { + lock (_itemsSyncRoot) + { + var item = _items.FirstOrDefault(x => x.FileId.Value == fileId.Value); + + if (item != null) + { + item.Canceled = true; + //_items.Remove(item); + } + } + } + } +} diff --git a/Telegram.Api/Services/FileManager/VideoFileManager.cs b/Telegram.Api/Services/FileManager/VideoFileManager.cs new file mode 100755 index 0000000..6413a79 --- /dev/null +++ b/Telegram.Api/Services/FileManager/VideoFileManager.cs @@ -0,0 +1,219 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ + public class VideoFileManager : FileManagerBase, IVideoFileManager + { + public VideoFileManager(ITelegramEventAggregator eventAggregator, IMTProtoService mtProtoService) : base(eventAggregator, mtProtoService) + { + for (var i = 0; i < Constants.BigFileWorkersNumber; i++) + { + var worker = new Worker(OnDownloading, "videoDownloader"+i); + _workers.Add(worker); + } + } + + private void OnDownloading(object state) + { + DownloadablePart part = null; + lock (_itemsSyncRoot) + { + for (var i = 0; i < _items.Count; i++) + { + var item = _items[i]; + if (item.Canceled) + { + _items.RemoveAt(i--); + try + { + //_eventAggregator.Publish(new UploadingCanceledEventArgs(item)); + } + catch (Exception e) + { + TLUtils.WriteException(e); + } + } + } + + foreach (var item in _items) + { + part = item.Parts.FirstOrDefault(x => x.Status == PartStatus.Ready); + if (part != null) + { + part.Status = PartStatus.Processing; + break; + } + } + } + + if (part == null) + { + var currentWorker = (Worker)state; + currentWorker.Stop(); + return; + } + + var partName = part.ParentItem.InputLocation.GetPartFileName(part.Number, "video"); + bool canceled; + ProcessFilePart(part, part.ParentItem.DCId, part.ParentItem.InputLocation, out canceled); + if (canceled) + { + lock (_itemsSyncRoot) + { + part.ParentItem.Canceled = true; + part.Status = PartStatus.Processed; + _items.Remove(part.ParentItem); + } + + return; + } + //part.File = GetFile(part.ParentItem.DCId, (TLInputFileLocationBase)part.ParentItem.InputVideoLocation, part.Offset, part.Limit); + //while (part.File == null) + //{ + // part.File = GetFile(part.ParentItem.DCId, (TLInputFileLocationBase)part.ParentItem.InputVideoLocation, part.Offset, part.Limit); + //} + + // indicate progress + // indicate complete + bool isComplete; + bool isCanceled; + var progress = 0.0; + lock (_itemsSyncRoot) + { + part.Status = PartStatus.Processed; + + FileUtils.CheckMissingPart(_itemsSyncRoot, part, partName); + + isCanceled = part.ParentItem.Canceled; + + isComplete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); + if (!isComplete) + { + var downloadedCount = part.ParentItem.Parts.Count(x => x.Status == PartStatus.Processed); + var count = part.ParentItem.Parts.Count; + progress = downloadedCount / (double)count; + } + else + { + _items.Remove(part.ParentItem); + } + } + + if (!isCanceled) + { + if (isComplete) + { + var fileName = part.ParentItem.InputLocation.GetFileName("video", ".mp4"); + var getPartName = new Func(x => x.ParentItem.InputLocation.GetPartFileName(x.Number, "video")); + + FileUtils.MergePartsToFile(getPartName, part.ParentItem.Parts, fileName); + + part.ParentItem.IsoFileName = fileName; + _eventAggregator.Publish(part.ParentItem); + } + else + { + _eventAggregator.Publish(new ProgressChangedEventArgs(part.ParentItem, progress)); + } + } + } + + public void DownloadFileAsync(TLInt dcId, TLInputFileLocationBase fileLocation, TLObject owner, TLInt fileSize, Action callback) + { + Execute.BeginOnThreadPool(() => + { + var downloadableItem = GetDownloadableItem(dcId, fileLocation, owner, fileSize); + + var downloadedCount = downloadableItem.Parts.Count(x => x.Status == PartStatus.Processed); + var count = downloadableItem.Parts.Count; + var isComplete = downloadedCount == count; + + if (isComplete) + { + var fileName = downloadableItem.InputLocation.GetFileName("video", ".mp4"); + var getPartName = new Func(x => x.ParentItem.InputLocation.GetPartFileName(x.Number, "video")); + FileUtils.MergePartsToFile(getPartName, downloadableItem.Parts, fileName); + + downloadableItem.IsoFileName = fileName; + _eventAggregator.Publish(downloadableItem); + } + else + { + var progress = downloadedCount / (double)count; + callback.SafeInvoke(progress); + + lock (_itemsSyncRoot) + { + bool addFile = true; + foreach (var item in _items) + { + if (item.InputLocation.LocationEquals(fileLocation) + && item.Owner == owner) + { + addFile = false; + break; + } + } + + if (addFile) + { + _items.Add(downloadableItem); + } + } + + StartAwaitingWorkers(); + } + }); + } + + private DownloadableItem GetDownloadableItem(TLInt dcId, TLInputFileLocationBase location, TLObject owner, TLInt fileSize) + { + var item = new DownloadableItem + { + Owner = owner, + DCId = dcId, + InputLocation = location + }; + item.Parts = GetItemParts(fileSize, item); + + return item; + } + + protected override List GetItemParts(TLInt size, DownloadableItem item) + { + var chunkSize = size.Value > 1024 * 1024 ? Constants.DownloadedBigChunkSize : Constants.DownloadedChunkSize; + var parts = new List(); + var partsCount = size.Value/chunkSize + (size.Value % chunkSize > 0 ? 1 : 0); + + for (var i = 0; i < partsCount; i++) + { + var part = new DownloadablePart(item, new TLInt(i * chunkSize), size.Value == 0 ? new TLInt(1024 * 1024) : new TLInt(chunkSize), i); + var partName = item.InputLocation.GetPartFileName(part.Number, "video"); + + var partLength = FileUtils.GetLocalFileLength(partName); + if (partLength >= 0) + { + var isCompletePart = (part.Number + 1 == partsCount) || partLength == part.Limit.Value; + part.Status = isCompletePart ? PartStatus.Processed : PartStatus.Ready; + } + + parts.Add(part); + } + + return parts; + } + } +} diff --git a/Telegram.Api/Services/FileManager/Worker.cs b/Telegram.Api/Services/FileManager/Worker.cs new file mode 100755 index 0000000..9657de8 --- /dev/null +++ b/Telegram.Api/Services/FileManager/Worker.cs @@ -0,0 +1,131 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Threading; +#if !WINDOWS_PHONE +using System.Threading.Tasks; +#endif +using Telegram.Api.TL; + +namespace Telegram.Api.Services.FileManager +{ +#if WINDOWS_PHONE + public class Worker + { + private readonly Thread _thread; + + private readonly ManualResetEvent _resetEvent = new ManualResetEvent(true); + + public ThreadState ThreadState + { + get { return _thread.ThreadState; } + } + + public string Name { get { return _thread.Name; } } + + public Worker(ParameterizedThreadStart start, string name) + { + _thread = new Thread(state => OnThreadStartInternal(start)); + _thread.Name = name; + //_thread.IsBackground = true; + _thread.Start(this); + } + + private void OnThreadStartInternal(ParameterizedThreadStart start) + { + while (true) + { + + try + { + start(this); + } + catch (Exception e) + { + TLUtils.WriteException(e); + } + + _resetEvent.WaitOne(); + } + } + + public bool IsWaiting + { + get{ return ThreadState == ThreadState.WaitSleepJoin; } + } + + public void Start() + { + _resetEvent.Set(); + } + + public void Stop() + { + _resetEvent.Reset(); + } + } +#else + public class Worker + { + private readonly Task _thread; + + private readonly ManualResetEvent _resetEvent = new ManualResetEvent(true); + + public TaskStatus ThreadState + { + get { return _thread.Status; } + } + + public Worker(Action start, string name) + { + _thread = new Task(state => OnThreadStartInternal(start, state), this, TaskCreationOptions.LongRunning); + //_thread.Name = name; + //_thread.IsBackground = true; + _thread.Start(); + } + + private bool _isWorking; + + private void OnThreadStartInternal(Action start, object state) + { + while (true) + { + try + { + start(state); + } + catch (Exception e) + { + TLUtils.WriteException(e); + } + _isWorking = false; + _isWorking = _resetEvent.WaitOne(); + } + } + + public bool IsWaiting + { + get + { + return true; + return !_isWorking; + } + } + + public void Start() + { + _resetEvent.Set(); + } + + public void Stop() + { + _resetEvent.Reset(); + } + } +#endif +} \ No newline at end of file diff --git a/Telegram.Api/Services/HistoryItem.cs b/Telegram.Api/Services/HistoryItem.cs new file mode 100755 index 0000000..c7f7274 --- /dev/null +++ b/Telegram.Api/Services/HistoryItem.cs @@ -0,0 +1,50 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.TL; + +namespace Telegram.Api.Services +{ + public enum RequestStatus + { + Sent, + Confirmed, + Failed, + ReadyToSend + } + + public class HistoryItem + { + public long Hash { get { return Message != null ? Message.MessageId.Value : 0; } } + public TLTransportMessageWithIdBase Message { get; set; } + public TLObject Object { get; set; } + public string Caption { get; set; } + public DateTime SendTime { get; set; } + public int TimeToResend { get; set; } + public DateTime? SendBeforeTime { get; set; } + public RequestStatus Status { get; set; } + public Action Callback { get; set; } + public Action FastCallback { get; set; } + public Action AttemptFailed { get; set; } + public Action FaultCallback { get; set; } + public Action FaultQueueCallback { get; set; } + public long ClientTicksDelta { get; set; } + public HistoryItem InvokeAfter { get; set; } + public TLRPCError LastError { get; set; } + + public int DCId { get; set; } + + //public volatile bool IsSending; + + public override string ToString() + { + + return string.Format("{0:HH:mm:ss.fff} dc_id={1} {2} hash={3}", SendTime, DCId, Caption, GetHashCode()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/IMTProtoService.cs b/Telegram.Api/Services/IMTProtoService.cs new file mode 100755 index 0000000..916aa35 --- /dev/null +++ b/Telegram.Api/Services/IMTProtoService.cs @@ -0,0 +1,378 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Contacts; +using Telegram.Api.Transport; + +namespace Telegram.Api.Services +{ + public interface IMTProtoService + { + TLEncryptedTransportMessage GetEncryptedTransportMessage(byte[] authKey, TLLong salt, TLObject obj); + +#if DEBUG + void CheckPublicConfig(); +#endif + + TLInputPeerBase PeerToInputPeer(TLPeerBase peer); + + void Stop(); + + void StartInitialize(); + + void RemoveFromQueue(TLLong id); + + event EventHandler TransportChecked; + + string Message { get; } + void SetMessageOnTime(double seconds, string message); + + ITransport GetActiveTransport(); + WindowsPhone.Tuple GetCurrentPacketInfo(); + string GetTransportInfo(); + + string Country { get; } + event EventHandler GotUserCountry; + + // To remove multiple UpdateStatusAsync calls, it's prefer to invoke this method instead + void RaiseSendStatus(SendStatusEventArgs e); + + TLInt CurrentUserId { get; set; } + + IList History { get; } + + void ClearHistory(string caption, bool createNewSession, bool syncFaultCallbacks = false, Exception e = null); + + long ClientTicksDelta { get; } + + /// + /// Indicates that service has authKey + /// + //bool IsInitialized { get; } + event EventHandler Initialized; + event EventHandler AuthorizationRequired; + event EventHandler CheckDeviceLocked; + event EventHandler ProxyDisabled; + + void SaveConfig(); + TLConfig LoadConfig(); + + void GetStateAsync(Action callback, Action faultCallback = null); + void GetDifferenceAsync(TLInt pts, TLInt date, TLInt qts, Action callback, Action faultCallback = null); + void GetDifferenceWithoutUpdatesAsync(TLInt pts, TLInt date, TLInt qts, Action callback, Action faultCallback = null); + + void RegisterDeviceAsync(TLInt tokenType, TLString token, Action callback, Action faultCallback = null); + void UnregisterDeviceAsync(TLInt tokenType, TLString token, Action callback, Action faultCallback = null); + + + void MessageAcknowledgments(TLVector ids); + + // auth + void BindTempAuthKeyAsync(TLLong permAuthKeyId, TLLong nonce, TLInt expiresAt, TLString encryptedMessage, Action callback, Action faultCallback = null); + void SendCodeAsync(TLString phoneNumber, TLString currentNumber, Action callback, Action attemptFailed = null, Action faultCallback = null); + void ResendCodeAsync(TLString phoneNumber, TLString phoneCodeHash, Action callback, Action faultCallback = null); + void CancelCodeAsync(TLString phoneNumber, TLString phoneCodeHash, Action callback, Action faultCallback = null); + void SignInAsync(TLString phoneNumber, TLString phoneCodeHash, TLString phoneCode, Action callback, Action faultCallback = null); + void CancelSignInAsync(); + void LogOutAsync(Action callback); + void LogOutAsync(Action callback, Action faultCallback = null); + void LogOutTransportsAsync(Action callback, Action> faultCallback = null); + void SignUpAsync(TLString phoneNumber, TLString phoneCodeHash, TLString phoneCode, TLString firstName, TLString lastName, Action callback, Action faultCallback = null); + void SendCallAsync(TLString phoneNumber, TLString phoneCodeHash, Action callback, Action faultCallback = null); + + void SearchAsync(TLInputPeerBase peer, TLString query, TLInputUserBase fromId, TLInputMessagesFilterBase filter, TLInt minDate, TLInt maxDate, TLInt addOffset, TLInt offsetId, TLInt limit, TLInt hash, Action callback, Action faultCallback = null); + void GetDialogsAsync(Stopwatch timer, TLInt offsetDate, TLInt offsetId, TLInputPeerBase offsetPeer, TLInt limit, TLInt hash, Action callback, Action faultCallback = null); + void GetHistoryAsync(Stopwatch timer, TLInputPeerBase inputPeer, TLPeerBase peer, bool sync, TLInt offsetDate, TLInt offset, TLInt maxId, TLInt limit, Action callback, Action faultCallback = null); + void DeleteMessagesAsync(bool revoke, TLVector id, Action callback, Action faultCallback = null); + void DeleteHistoryAsync(bool justClear, TLInputPeerBase peer, TLInt offset, Action callback, Action faultCallback = null); + void ReadHistoryAsync(TLInputPeerBase peer, TLInt maxId, TLInt offset, Action callback, Action faultCallback = null); + void ReadMentionsAsync(TLInputPeerBase peer, Action callback, Action faultCallback = null); + void ReadMessageContentsAsync(TLVector id, Action callback, Action faultCallback = null); + void GetFullChatAsync(TLInt chatId, Action callback, Action faultCallback = null); + + void SetTypingAsync(TLInputPeerBase peer, TLBool typing, Action callback, Action faultCallback = null); + void SetTypingAsync(TLInputPeerBase peer, TLSendMessageActionBase action, Action callback, Action faultCallback = null); + + void GetContactsAsync(TLInt hash, Action callback, Action faultCallback = null); + void ImportContactsAsync(TLVector contacts, Action callback, Action faultCallback = null); + + void BlockAsync(TLInputUserBase id, Action callback, Action faultCallback = null); + void UnblockAsync(TLInputUserBase id, Action callback, Action faultCallback = null); + void GetBlockedAsync(TLInt offset, TLInt limit, Action callback, Action faultCallback = null); + + void UpdateProfileAsync(TLString firstName, TLString lastName, TLString about, Action callback, Action faultCallback = null); + void UpdateStatusAsync(TLBool offline, Action callback, Action faultCallback = null); + + void GetFileAsync(TLInt dcId, TLInputFileLocationBase location, TLInt offset, TLInt limit, Action callback, Action faultCallback = null); + void GetFileAsync(TLInputFileLocationBase location, TLInt offset, TLInt limit, Action callback, Action faultCallback = null); + void SaveFilePartAsync(TLLong fileId, TLInt filePart, TLString bytes, Action callback, Action faultCallback = null); + void SaveBigFilePartAsync(TLLong fileId, TLInt filePart, TLInt fileTotalParts, TLString bytes, Action callback, Action faultCallback = null); + + void GetNotifySettingsAsync(TLInputNotifyPeerBase peer, Action settings, Action faultCallback = null); + void UpdateNotifySettingsAsync(TLInputNotifyPeerBase peer, TLInputPeerNotifySettings settings, Action callback, Action faultCallback = null); + void ResetNotifySettingsAsync(Action callback, Action faultCallback = null); + + void UploadProfilePhotoAsync(TLInputFile file, Action callback, Action faultCallback = null); + void UpdateProfilePhotoAsync(TLInputPhotoBase id, Action callback, Action faultCallback = null); + + void GetDHConfigAsync(TLInt version, TLInt randomLength, Action result, Action faultCallback = null); + void RequestEncryptionAsync(TLInputUserBase userId, TLInt randomId, TLString g_a, Action callback, Action faultCallback = null); + void AcceptEncryptionAsync(TLInputEncryptedChat peer, TLString gb, TLLong keyFingerprint, Action callback, Action faultCallback = null); + void SendEncryptedAsync(TLInputEncryptedChat peer, TLLong randomId, TLString data, Action callback, Action fastCallback, Action faultCallback = null); + void SendEncryptedFileAsync(TLInputEncryptedChat peer, TLLong randomId, TLString data, TLInputEncryptedFileBase file, Action callback, Action fastCallback, Action faultCallback = null); + void SendEncryptedMultiMediaAsync(TLInputEncryptedChat peer, TLVector randomId, TLVector data, TLVector file, Action> callback, Action fastCallback, Action faultCallback = null); + void ReadEncryptedHistoryAsync(TLInputEncryptedChat peer, TLInt maxDate, Action callback, Action faultCallback = null); + void SendEncryptedServiceAsync(TLInputEncryptedChat peer, TLLong randomId, TLString data, Action callback, Action faultCallback = null); + void DiscardEncryptionAsync(TLInt chatId, Action callback, Action faultCallback = null); + void SetEncryptedTypingAsync(TLInputEncryptedChat peer, TLBool typing, Action callback, Action faultCallback = null); + + void GetConfigInformationAsync(Action callback); + void GetTransportInformationAsync(Action callback); + void GetUserPhotosAsync(TLInputUserBase userId, TLInt offset, TLLong maxId, TLInt limit, Action callback, Action faultCallback = null); + void GetNearestDCAsync(Action callback, Action faultCallback = null); + void GetSupportAsync(Action callback, Action faultCallback = null); + + void ResetAuthorizationsAsync(Action callback, Action faultCallback = null); + void SetInitState(); + + void PingAsync(TLLong pingId, Action callback, Action faultCallback = null); + void PingDelayDisconnectAsync(TLLong pingId, TLInt disconnectDelay, Action callback, Action faultCallback = null); + + void SearchAsync(TLString q, TLInt limit, Action callback, Action faultCallback = null); + void CheckUsernameAsync(TLString username, Action callback, Action faultCallback = null); + void UpdateUsernameAsync(TLString username, Action callback, Action faultCallback = null); + void GetAccountTTLAsync(Action callback, Action faultCallback = null); + void SetAccountTTLAsync(TLAccountDaysTTL ttl, Action callback, Action faultCallback = null); + void DeleteAccountTTLAsync(TLString reason, Action callback, Action faultCallback = null); + void GetPrivacyAsync(TLInputPrivacyKeyBase key, Action callback, Action faultCallback = null); + void SetPrivacyAsync(TLInputPrivacyKeyBase key, TLVector rules, Action callback, Action faultCallback = null); + void GetStatusesAsync(Action> callback, Action faultCallback = null); + void UpdateTransportInfoAsync(TLDCOption78 dcOption, TLString ipAddress, TLInt port, Action callback); + void CheckAndUpdateTransportInfoAsync(TLInt dcId, TLString host, TLInt port, Action callback, Action faultCallback = null); + + void ResolveUsernameAsync(TLString username, Action callback, Action faultCallback = null); + void SendChangePhoneCodeAsync(TLString phoneNumber, TLString currentNumber, Action callback, Action faultCallback = null); + void ChangePhoneAsync(TLString phoneNumber, TLString phoneCodeHash, TLString phoneCode, Action callback, Action faultCallback = null); + void GetWallpapersAsync(Action> callback, Action faultCallback = null); + void GetAllStickersAsync(TLString hash, Action callback, Action faultCallback = null); + void GetMaskStickersAsync(TLString hash, Action callback, Action faultCallback = null); + + void UpdateDeviceLockedAsync(TLInt period, Action callback, Action faultCallback = null); + + void GetSendingQueueInfoAsync(Action callback); + void GetSyncErrorsAsync(Action> callback); + void GetMessagesAsync(TLVector id, Action callback, Action faultCallback = null); + // users + void GetFullUserAsync(TLInputUserBase id, Action callback, Action faultCallback = null); + void GetUsersAsync(TLVector id, Action> callback, Action faultCallback = null); + void SetSecureValueErrorsAsync(TLInputUserBase id, TLVector errors, Action callback, Action faultCallback = null); + + // messages + void GetRecentLocationsAsync(TLInputPeerBase peer, TLInt limit, TLInt hash, Action callback, Action faultCallback = null); + void GetFeaturedStickersAsync(bool full, TLInt hash, Action callback, Action faultCallback = null); + void GetArchivedStickersAsync(bool full, TLLong offsetId, TLInt limit, Action callback, Action faultCallback = null); + void ReadFeaturedStickersAsync(TLVector id, Action callback, Action faultCallback = null); + void GetAllDraftsAsync(Action callback, Action faultCallback = null); + void SaveDraftAsync(TLInputPeerBase peer, TLDraftMessageBase draft, Action callback, Action faultCallback = null); + void GetInlineBotResultsAsync(TLInputUserBase bot, TLInputPeerBase peer, TLInputGeoPointBase geoPoint, TLString query, TLString offset, Action callback, Action faultCallback = null); + void SetInlineBotResultsAsync(TLBool gallery, TLBool pr, TLLong queryId, TLVector results, TLInt cacheTime, TLString nextOffset, TLInlineBotSwitchPM switchPM, Action callback, Action faultCallback = null); + void SendInlineBotResultAsync(TLMessage45 message, Action callback, Action fastCallback, Action faultCallback = null); + void GetDocumentByHashAsync(TLString sha256, TLInt size, TLString mimeType, Action callback, Action faultCallback = null); + void SearchGifsAsync(TLString q, TLInt offset, Action callback, Action faultCallback = null); + void GetSavedGifsAsync(TLInt hash, Action callback, Action faultCallback = null); + void SaveGifAsync(TLInputDocumentBase id, TLBool unsave, Action callback, Action faultCallback = null); + void ReorderStickerSetsAsync(bool masks, TLVector order, Action callback, Action faultCallback = null); + void SearchGlobalAsync(TLString query, TLInt offsetDate, TLInputPeerBase offsetPeer, TLInt offsetId, TLInt limit, Action callback, Action faultCallback = null); + void ReportSpamAsync(TLInputPeerBase peer, Action callback, Action faultCallback = null); + void SendMessageAsync(TLMessage36 message, Action callback, Action fastCallback, Action faultCallback = null); + void SendMediaAsync(TLInputPeerBase inputPeer, TLInputMediaBase inputMedia, TLMessage34 message, Action callback, Action faultCallback = null); + void StartBotAsync(TLInputUserBase bot, TLString startParam, TLMessage25 message, Action callback, Action faultCallback = null); + void SendBroadcastAsync(TLVector contacts, TLInputMediaBase inputMedia, TLMessage25 message, Action callback, Action fastCallback, Action faultCallback = null); + void ForwardMessageAsync(TLInputPeerBase peer, TLInt fwdMessageId, TLMessage25 message, Action callback, Action faultCallback = null); + void ForwardMessagesAsync(TLInputPeerBase toPeer, TLVector id, IList messages, bool withMyScore, Action callback, Action faultCallback = null); + void ForwardMessagesAsync(TLMessage25 commentMessage, TLInputPeerBase toPeer, TLVector id, IList messages, bool withMyScore, Action callback, Action faultCallback = null); + void CreateChatAsync(TLVector users, TLString title, Action callback, Action faultCallback = null); + void EditChatTitleAsync(TLInt chatId, TLString title, Action callback, Action faultCallback = null); + void EditChatPhotoAsync(TLInt chatId, TLInputChatPhotoBase photo, Action callback, Action faultCallback = null); + void AddChatUserAsync(TLInt chatId, TLInputUserBase userId, TLInt fwdLimit, Action callback, Action faultCallback = null); + void DeleteChatUserAsync(TLInt chatId, TLInputUserBase userId, Action callback, Action faultCallback = null); + void GetWebPagePreviewAsync(TLString message, Action callback, Action faultCallback = null); + void ExportChatInviteAsync(TLInt chatId, Action callback, Action faultCallback = null); + void CheckChatInviteAsync(TLString hash, Action callback, Action faultCallback = null); + void ImportChatInviteAsync(TLString hash, Action callback, Action faultCallback = null); + void GetStickerSetAsync(TLInputStickerSetBase stickerset, Action callback, Action faultCallback = null); + void InstallStickerSetAsync(TLInputStickerSetBase stickerset, TLBool archived, Action callback, Action faultCallback = null); + void UninstallStickerSetAsync(TLInputStickerSetBase stickerset, Action callback, Action faultCallback = null); + void HideReportSpamAsync(TLInputPeerBase peer, Action callback, Action faultCallback = null); + void GetPeerSettingsAsync(TLInputPeerBase peer, Action callback, Action faultCallback = null); + void GetBotCallbackAnswerAsync(TLInputPeerBase peer, TLInt messageId, TLString data, TLBool game, Action callback, Action faultCallback = null); + void GetPromoDialogAsync(TLInputPeerBase peer, Action callback, Action faultCallback = null); + void GetRecentStickersAsync(bool attached, TLInt hash, Action callback, Action faultCallback = null); + void ClearRecentStickersAsync(bool attached, Action callback, Action faultCallback = null); + void GetUnusedStickersAsync(TLInt limit, Action> callback, Action faultCallback = null); + void GetAttachedStickersAsync(bool full, TLInputStickeredMediaBase media, Action callback, Action faultCallback = null); + void GetCommonChatsAsync(TLInputUserBase user, TLInt maxId, TLInt limit, Action callback, Action faultCallback = null); + void GetWebPageAsync(TLString url, TLInt hash, Action callback, Action faultCallback = null); + void GetPinnedDialogsAsync(Action callback, Action faultCallback = null); + void ReorderPinnedDialogsAsync(bool force, TLVector order, Action callback, Action faultCallback = null); + void ToggleDialogPinAsync(bool pinned, TLPeerBase peer, Action callback, Action faultCallback = null); + void GetFavedStickersAsync(TLInt hash, Action callback, Action faultCallback = null); + void FaveStickerAsync(TLInputDocumentBase id, TLBool unfave, Action callback, Action faultCallback = null); + void GetUnreadMentionsAsync(TLInputPeerBase peer, TLInt offsetId, TLInt addOffset, TLInt limit, TLInt maxId, TLInt minId, Action callback, Action faultCallback = null); + void UploadMediaAsync(TLInputPeerBase inputPeer, TLInputMediaBase inputMedia, Action callback, Action faultCallback = null); + void SendMultiMediaAsync(TLInputPeerBase inputPeer, TLVector inputMedia, TLMessage25 message, Action callback, Action faultCallback = null); + void GetStickersAsync(TLString emoticon, TLInt hash, Action callback, Action faultCallback = null); + void ReportAsync(TLInputPeerBase peer, TLVector id, TLInputReportReasonBase reason, Action callback, Action faultCallback = null); + void SearchStickerSetsAsync(bool full, bool excludeFeatured, TLString q, TLInt hash, Action callback, Action faultCallback = null); + void GetPeerDialogsAsync(TLInputPeerBase peer, Action callback, Action faultCallback = null); + void MarkDialogUnreadAsync(bool unread, TLInputDialogPeer peer, Action callback, Action faultCallback = null); + void GetDialogUnreadMarksAsync(Action> callback, Action faultCallback = null); + void ToggleTopPeersAsync(TLBool enabled, Action callback, Action faultCallback = null); + void ClearAllDraftsAsync(Action callback, Action faultCallback = null); + + // contacts + void DeleteContactAsync(TLInputUserBase id, Action callback, Action faultCallback = null); + void DeleteContactsAsync(TLVector id, Action callback, Action faultCallback = null); + void GetTopPeersAsync(GetTopPeersFlags flags, TLInt offset, TLInt limit, TLInt hash, Action callback, Action faultCallback = null); + void ResetTopPeerRatingAsync(TLTopPeerCategoryBase category, TLInputPeerBase peer, Action callback, Action faultCallback = null); + void ResetSavedAsync(Action callback, Action faultCallback = null); + void GetSavedAsync(Action> callback, Action faultCallback = null); + + // channels + void GetChannelHistoryAsync(string debugInfo, TLInputPeerBase inputPeer, TLPeerBase peer, bool sync, TLInt offset, TLInt maxId, TLInt limit, Action callback, Action faultCallback = null); + void GetMessagesAsync(TLInputChannelBase inputChannel, TLVector id, Action callback, Action faultCallback = null); + void UpdateChannelAsync(TLInt channelId, Action callback, Action faultCallback = null); + void EditAdminAsync(TLChannel channel, TLInputUserBase userId, TLChannelAdminRights adminRights, Action callback, Action faultCallback = null); + void KickFromChannelAsync(TLChannel channel, TLInputUserBase userId, TLBool kicked, Action callback, Action faultCallback = null); + void GetParticipantAsync(TLInputChannelBase inputChannel, TLInputUserBase userId, Action callback, Action faultCallback = null); + void GetParticipantsAsync(TLInputChannelBase inputChannel, TLChannelParticipantsFilterBase filter, TLInt offset, TLInt limit, TLInt hash, Action callback, Action faultCallback = null); + void EditTitleAsync(TLChannel channel, TLString title, Action callback, Action faultCallback = null); + void EditAboutAsync(TLChannel channel, TLString about, Action callback, Action faultCallback = null); + void EditPhotoAsync(TLChannel channel, TLInputChatPhotoBase photo, Action callback, Action faultCallback = null); + void JoinChannelAsync(TLChannel channel, Action callback, Action faultCallback = null); + void LeaveChannelAsync(TLChannel channel, Action callback, Action faultCallback = null); + void DeleteChannelAsync(TLChannel channel, Action callback, Action faultCallback = null); + void InviteToChannelAsync(TLInputChannelBase channel, TLVector users, Action callback, Action faultCallback = null); + void GetFullChannelAsync(TLInputChannelBase channel, Action callback, Action faultCallback = null); + void CreateChannelAsync(TLInt flags, TLString title, TLString about, Action callback, Action faultCallback = null); + void ExportInviteAsync(TLInputChannelBase channel, Action callback, Action faultCallback = null); + void CheckUsernameAsync(TLInputChannelBase channel, TLString username, Action callback, Action faultCallback = null); + void UpdateUsernameAsync(TLInputChannelBase channel, TLString username, Action callback, Action faultCallback = null); + void GetChannelDialogsAsync(TLInt offset, TLInt limit, Action callback, Action faultCallback = null); + void GetImportantHistoryAsync(TLInputChannelBase channel, TLPeerBase peer, bool sync, TLInt offsetId, TLInt addOffset, TLInt limit, TLInt maxId, TLInt minId, Action callback, Action faultCallback = null); + void ReadHistoryAsync(TLChannel channel, TLInt maxId, Action callback, Action faultCallback = null); + void DeleteMessagesAsync(TLInputChannelBase channel, TLVector id, Action callback, Action faultCallback = null); + void ToggleInvitesAsync(TLInputChannelBase channel, TLBool enabled, Action callback, Action faultCallback = null); + void ExportMessageLinkAsync(TLInputChannelBase channel, TLInt id, Action callback, Action faultCallback = null); + void ToggleSignaturesAsync(TLInputChannelBase channel, TLBool enabled, Action callback, Action faultCallback = null); + void GetMessageEditDataAsync(TLInputPeerBase peer, TLInt id, Action callback, Action faultCallback = null); + void EditMessageAsync(TLInputPeerBase peer, TLInt id, TLString message, TLVector entities, TLInputMediaBase media, TLReplyKeyboardBase replyMarkup, bool noWebPage, bool stopGeoLive, TLInputGeoPointBase geoPoint, Action callback, Action faultCallback = null); + void UpdatePinnedMessageAsync(bool silent, TLInputChannelBase channel, TLInt id, Action callback, Action faultCallback = null); + void ReportSpamAsync(TLInputChannelBase channel, TLInt userId, TLVector id, Action callback, Action faultCallback = null); + void DeleteUserHistoryAsync(TLChannel channel, TLInputUserBase userId, Action callback, Action faultCallback = null); + void GetAdminedPublicChannelsAsync(Action callback, Action faultCallback = null); + void ReadMessageContentsAsync(TLInputChannelBase channel, TLVector id, Action callback, Action faultCallback = null); + void SetStickersAsync(TLInputChannelBase channel, TLInputStickerSetBase stickerset, Action callback, Action faultCallback = null); + void TogglePreHistoryHiddenAsync(TLInputChannelBase channel, TLBool enabled, Action callback, Action faultCallback = null); + void DeleteHistoryAsync(TLInputChannelBase channel, Action callback, Action faultCallback = null); + void SetFeedBroadcastsAsync(TLInt feedId, TLVector channels, TLBool alsoNewlyJoined, Action callback, Action faultCallback = null); + void ChangeFeedBroadcastAsync(TLInputChannelBase channel, TLInt feedId, Action callback, Action faultCallback = null); + void GetFeedAsync(bool offsetToMaxReed, TLInt feedId, TLFeedPosition offsetPosition, TLInt addOffset, TLInt limit, TLFeedPosition maxPosition, TLFeedPosition minPosition, TLInt hash, Action callback, Action faultCallback = null); + void ReadFeedAsync(TLInt feedId, TLFeedPosition maxPosition, Action callback, Action faultCallback = null); + + // updates + void GetChannelDifferenceAsync(bool force, TLInputChannelBase inputChannel, TLChannelMessagesFilerBase filter, TLInt pts, TLInt limit, Action callback, Action faultCallback = null); + + // admins + void ToggleChatAdminsAsync(TLInt chatId, TLBool enabled, Action callback, Action faultCallback = null); + void EditChatAdminAsync(TLInt chatId, TLInputUserBase userId, TLBool isAdmin, Action callback, Action faultCallback = null); + void DeactivateChatAsync(TLInt chatId, TLBool enabled, Action callback, Action faultCallback = null); + void MigrateChatAsync(TLInt chatId, Action callback, Action faultCallback = null); + + // account + void ReportPeerAsync(TLInputPeerBase peer, TLInputReportReasonBase reason, Action callback, Action faultCallback = null); + void DeleteAccountAsync(TLString reason, Action callback, Action faultCallback = null); + void GetAuthorizationsAsync(Action callback, Action faultCallback = null); + void ResetAuthorizationAsync(TLLong hash, Action callback, Action faultCallback = null); + void GetPasswordAsync(Action callback, Action faultCallback = null); + void GetPasswordSettingsAsync(TLInputCheckPasswordBase password, Action callback, Action faultCallback = null); + void UpdatePasswordSettingsAsync(TLInputCheckPasswordBase password, TLPasswordInputSettings newSettings, Action callback, Action faultCallback = null); + void CheckPasswordAsync(TLInputCheckPasswordBase password, Action callback, Action faultCallback = null); + void RequestPasswordRecoveryAsync(Action callback, Action faultCallback = null); + void RecoverPasswordAsync(TLString code, Action callback, Action faultCallback = null); + void ConfirmPhoneAsync(TLString phoneCodeHash, TLString phoneCode, Action callback, Action faultCallback = null); + void SendConfirmPhoneCodeAsync(TLString hash, TLBool currentNumber, Action callback, Action faultCallback = null); + void GetTmpPasswordAsync(TLInputCheckPasswordBase password, TLInt period, Action callback, Action faultCallback = null); + void GetWebAuthorizationsAsync(Action callback, Action faultCallback = null); + void ResetWebAuthorizationAsync(TLLong hash, Action callback, Action faultCallback = null); + void ResetWebAuthorizationsAsync(Action callback, Action faultCallback = null); + void GetAllSecureValuesAsync(Action> callback, Action faultCallback = null); + void GetSecureValueAsync(TLVector types, Action> callback, Action faultCallback = null); + void SaveSecureValueAsync(TLInputSecureValue value, TLLong secureSecretId, Action callback, Action faultCallback = null); + void DeleteSecureValueAsync(TLVector types, Action callback, Action faultCallback = null); + void GetAuthorizationFormAsync(TLInt botId, TLString scope, TLString publicKey, Action callback, Action faultCallback = null); + void GetAuthorizationFormAndPassportConfigAsync(TLInt botId, TLString scope, TLString publicKey, TLInt passportSettingsHash, Action callback, Action faultCallback = null); + void AcceptAuthorizationAsync(TLInt botId, TLString scope, TLString publicKey, TLVector valueHashes, TLSecureCredentialsEncrypted credentials, Action callback, Action faultCallback = null); + void SendVerifyPhoneCodeAsync(TLString phoneNumber, TLBool currentNumber, Action callback, Action faultCallback = null); + void VerifyPhoneAsync(TLString phoneNumber, TLString phoneCodeHash, TLString phoneCode, Action callback, Action faultCallback = null); + void SendVerifyEmailCodeAsync(TLString email, Action callback, Action faultCallback = null); + void VerifyEmailAsync(TLString email, TLString code, Action callback, Action faultCallback = null); + void InitTakeoutSessionAsync(bool contacts, bool messageUsers, bool messageChats, bool messageMegagroups, bool messageChannels, bool files, TLInt fileMaxSize, TLLong takeoutId, Action callback, Action faultCallback = null); + void GetPassportDataAsync(Action> callback, Action faultCallback = null); + + // help + void GetAppChangelogAsync(TLString deviceModel, TLString systemVersion, TLString appVersion, TLString langCode, Action callback, Action faultCallback = null); + void GetTermsOfServiceAsync(TLString countryISO2, Action callback, Action faultCallback = null); + void GetCdnConfigAsync(Action callback, Action faultCallback = null); + void GetProxyDataAsync(Action callback, Action faultCallback = null); + void GetDeepLinkInfoAsync(TLString path, Action callback, Action faultCallback = null); + void GetPassportConfigAsync(TLInt hash, Action callback, Action faultCallback = null); + + // upload + void GetCdnFileAsync(TLInt dcId, TLString fileToken, TLInt offset, TLInt limit, Action callback, Action faultCallback = null); + void ReuploadCdnFileAsync(TLInt dcId, TLString fileToken, TLString requestToken, Action> callback, Action faultCallback = null); + + // encrypted chats + void RekeyAsync(TLEncryptedChatBase chat, Action callback); + + // phone + void GetCallConfigAsync(Action callback, Action faultCallback = null); + void RequestCallAsync(TLInputUserBase userId, TLInt randomId, TLString gaHash, TLPhoneCallProtocol protocol, Action callback, Action faultCallback = null); + void AcceptCallAsync(TLInputPhoneCall peer, TLString gb, TLPhoneCallProtocol protocol, Action callback, Action faultCallback = null); + void ConfirmCallAsync(TLInputPhoneCall peer, TLString ga, TLLong keyFingerprint, TLPhoneCallProtocol protocol, Action callback, Action faultCallback = null); + void ReceivedCallAsync(TLInputPhoneCall peer, Action callback, Action faultCallback = null); + void DiscardCallAsync(TLInputPhoneCall peer, TLInt duration, TLPhoneCallDiscardReasonBase reason, TLLong connectionId, Action callback, Action faultCallback = null); + void SetCallRatingAsync(TLInputPhoneCall peer, TLInt rating, TLString comment, Action callback, Action faultCallback = null); + void SaveCallDebugAsync(TLInputPhoneCall peer, TLDataJSON debug, Action callback, Action faultCallback = null); + + // payments + void GetPaymentReceiptAsync(TLInt msgId, Action callback, Action faultCallback = null); + void GetPaymentFormAsync(TLInt msgId, Action callback, Action faultCallback = null); + void SendPaymentFormAsync(TLInt msgId, TLString requestedInfoId, TLString shippingOptionId, TLInputPaymentCredentialsBase credentials, Action callback, Action faultCallback = null); + void ValidateRequestedInfoAsync(bool save, TLInt msgId, TLPaymentRequestedInfo info, Action callback, Action faultCallback = null); + void GetSavedInfoAsync(Action callback, Action faultCallback = null); + void ClearSavedInfoAsync(bool credentials, bool info, Action callback, Action faultCallback = null); + + // langpack + void GetLangPackAsync(TLString langCode, Action callback, Action faultCallback = null); + void GetStringsAsync(TLString langCode, TLVector keys, Action> callback, Action faultCallback = null); + void GetDifferenceAsync(TLInt fromVersion, Action callback, Action faultCallback = null); + void GetLanguagesAsync(Action> callback, Action faultCallback = null); + + // proxy + void PingProxyAsync(TLProxyBase proxy, Action callback, Action faultCallback = null); + + // background task + void SendActionsAsync(List actions, Action callback, Action faultCallback = null); + void ClearQueue(); + } +} diff --git a/Telegram.Api/Services/MTProtoService.Account.cs b/Telegram.Api/Services/MTProtoService.Account.cs new file mode 100755 index 0000000..d5cfc80 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Account.cs @@ -0,0 +1,626 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Threading; +#if WIN_RT +using Windows.Data.Xml.Dom; +#if WNS_PUSH_SERVICE +using Windows.UI.Notifications; +#endif +#endif +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; +using Telegram.Api.TL.Account; +using Telegram.Api.TL.Functions.Account; +using Telegram.Api.TL.Functions.Help; +using TLUpdateUserName = Telegram.Api.TL.Account.TLUpdateUserName; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public event EventHandler CheckDeviceLocked; + + protected virtual void RaiseCheckDeviceLocked() + { + var handler = CheckDeviceLocked; + if (handler != null) handler(this, EventArgs.Empty); + } + + private void CheckDeviceLockedInternal(object state) + { + RaiseCheckDeviceLocked(); + } + + public void ReportPeerAsync(TLInputPeerBase peer, TLInputReportReasonBase reason, Action callback, Action faultCallback = null) + { + var obj = new TLReportPeer { Peer = peer, Reason = reason }; + + SendInformativeMessage("account.reportPeer", obj, callback, faultCallback); + } + + public void DeleteAccountAsync(TLString reason, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteAccount { Reason = reason }; + + SendInformativeMessage("account.deleteAccount", obj, callback, faultCallback); + } + + public void UpdateDeviceLockedAsync(TLInt period, Action callback, Action faultCallback = null) + { + var obj = new TLUpdateDeviceLocked{ Period = period }; + + SendInformativeMessage("account.updateDeviceLocked", obj, callback, faultCallback); + } + + public void GetWallpapersAsync(Action> callback, Action faultCallback = null) + { + var obj = new TLGetWallPapers(); + + SendInformativeMessage("account.getWallpapers", obj, callback, faultCallback); + } + + public void SendChangePhoneCodeAsync(TLString phoneNumber, TLString currentNumber, Action callback, Action faultCallback = null) + { + var obj = new TLSendChangePhoneCode { Flags = new TLInt(0), PhoneNumber = phoneNumber, CurrentNumber = currentNumber }; + + SendInformativeMessage("account.sendChangePhoneCode", obj, callback, faultCallback); + } + + public void ChangePhoneAsync(TLString phoneNumber, TLString phoneCodeHash, TLString phoneCode, Action callback, Action faultCallback = null) + { + var obj = new TLChangePhone { PhoneNumber = phoneNumber, PhoneCodeHash = phoneCodeHash, PhoneCode = phoneCode }; + + SendInformativeMessage("account.changePhone", obj, user => _cacheService.SyncUser(user, callback.SafeInvoke), faultCallback); + } + + public void RegisterDeviceAsync(TLInt tokenType, TLString token, Action callback, Action faultCallback = null) + { + if (_activeTransport.AuthKey == null) + { + faultCallback.SafeInvoke(new TLRPCError + { + Code = new TLInt(404), + Message = new TLString("Service is not initialized to register device") + }); + + return; + } + + var obj = new TLRegisterDevice + { + //TokenType = new TLInt(3), // MPNS + //TokenType = new TLInt(8), // WNS + //TokenType = new TLInt(11), // MPNS raw + TokenType = tokenType, + Token = token, + AppSandbox = TLBool.False, + Secret = TLString.Empty, + OtherUids = new TLVector() + }; + + const string methodName = "account.registerDevice"; + Logs.Log.Write(string.Format("{0} {1}", methodName, obj)); + SendInformativeMessage(methodName, obj, + result => + { + Logs.Log.Write(string.Format("{0} result={1}", methodName, result)); + + callback.SafeInvoke(result); + }, + error => + { + Logs.Log.Write(string.Format("{0} error={1}", methodName, error)); + + faultCallback.SafeInvoke(error); + }); + } + + public void UnregisterDeviceAsync(TLInt tokenType, TLString token, Action callback, Action faultCallback = null) + { + var obj = new TLUnregisterDevice + { + //TokenType = new TLInt(3), // MPNS + //TokenType = new TLInt(8), // WNS + TokenType = tokenType, + Token = token + }; + + const string methodName = "account.unregisterDevice"; + Logs.Log.Write(string.Format("{0} {1}", methodName, obj)); + SendInformativeMessage("account.unregisterDevice", obj, + result => + { + Logs.Log.Write(string.Format("{0} result={1}", methodName, result)); + + callback.SafeInvoke(result); + }, + error => + { + Logs.Log.Write(string.Format("{0} error={1}", methodName, error)); + + faultCallback.SafeInvoke(error); + }); + } + + public void GetNotifySettingsAsync(TLInputNotifyPeerBase peer, Action callback, Action faultCallback = null) + { + var obj = new TLGetNotifySettings{ Peer = peer }; + + SendInformativeMessage("account.getNotifySettings", obj, callback, faultCallback); + } + + public void ResetNotifySettingsAsync(Action callback, Action faultCallback = null) + { + Execute.ShowDebugMessage(string.Format("account.resetNotifySettings")); + + var obj = new TLResetNotifySettings(); + + SendInformativeMessage("account.resetNotifySettings", obj, callback, faultCallback); + } + + public void UpdateNotifySettingsAsync(TLInputNotifyPeerBase peer, TLInputPeerNotifySettings settings, Action callback, Action faultCallback = null) + { + //Execute.ShowDebugMessage(string.Format("account.updateNotifySettings peer=[{0}] settings=[{1}]", peer, settings)); + + var obj = new TL.Functions.Account.TLUpdateNotifySettings { Peer = peer, Settings = settings }; + + SendInformativeMessage("account.updateNotifySettings", obj, callback, faultCallback); + } + + public void UpdateProfileAsync(TLString firstName, TLString lastName, TLString about, Action callback, Action faultCallback = null) + { + var obj = new TLUpdateProfile { FirstName = firstName, LastName = lastName, About = about }; + + SendInformativeMessage("account.updateProfile", obj, result => _cacheService.SyncUser(result, callback), faultCallback); + } + + public void UpdateStatusAsync(TLBool offline, Action callback, Action faultCallback = null) + { + if (_activeTransport.AuthKey == null) return; + +#if WIN_RT + if (_deviceInfo != null && _deviceInfo.IsBackground) + { + var message = string.Format("::{0} {1} account.updateStatus {2}", _deviceInfo.BackgroundTaskName, _deviceInfo.BackgroundTaskId, offline); + Logs.Log.Write(message); +#if DEBUG && WNS_PUSH_SERVICE + AddToast("task", message); +#endif + } +#endif + + TLObject obj = null; + if (_deviceInfo != null && _deviceInfo.IsBackground) + { + obj = new TLInvokeWithoutUpdates {Object = new TLUpdateStatus {Offline = offline}}; + } + else + { + obj = new TLUpdateStatus { Offline = offline }; + } + + System.Diagnostics.Debug.WriteLine("account.updateStatus offline=" + offline.Value); + SendInformativeMessage("account.updateStatus", obj, callback, faultCallback); + } +#if WIN_RT && WNS_PUSH_SERVICE + public static void AddToast(string caption, string message) + { + var toastNotifier = ToastNotificationManager.CreateToastNotifier(); + + var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); + SetText(toastXml, caption, message); + + try + { + var toast = new ToastNotification(toastXml); + //RemoveToastGroup(group); + toastNotifier.Show(toast); + } + catch (Exception ex) + { + Logs.Log.Write(ex.ToString()); + } + } + + private static void SetText(XmlDocument document, string caption, string message) + { + var toastTextElements = document.GetElementsByTagName("text"); + toastTextElements[0].InnerText = caption ?? string.Empty; + toastTextElements[1].InnerText = message ?? string.Empty; + } +#endif + + public void CheckUsernameAsync(TLString username, Action callback, Action faultCallback = null) + { + var obj = new TLCheckUsername { Username = username }; + + SendInformativeMessage("account.checkUsername", obj, callback, faultCallback); + } + + public void UpdateUsernameAsync(TLString username, Action callback, Action faultCallback = null) + { + var obj = new TLUpdateUserName { Username = username }; + + SendInformativeMessage("account.updateUsername", obj, callback, faultCallback); + } + + public void GetAccountTTLAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetAccountTTL(); + + SendInformativeMessage("account.getAccountTTL", obj, callback, faultCallback); + } + + public void SetAccountTTLAsync(TLAccountDaysTTL ttl, Action callback, Action faultCallback = null) + { + var obj = new TLSetAccountTTL{TTL = ttl}; + + SendInformativeMessage("account.setAccountTTL", obj, callback, faultCallback); + } + + public void DeleteAccountTTLAsync(TLString reason, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteAccount { Reason = reason }; + + SendInformativeMessage("account.deleteAccount", obj, callback, faultCallback); + } + + public void GetPrivacyAsync(TLInputPrivacyKeyBase key, Action callback, Action faultCallback = null) + { + var obj = new TLGetPrivacy { Key = key }; + + SendInformativeMessage("account.getPrivacy", obj, callback, faultCallback); + } + + public void SetPrivacyAsync(TLInputPrivacyKeyBase key, TLVector rules, Action callback, Action faultCallback = null) + { + var obj = new TLSetPrivacy { Key = key, Rules = rules }; + + SendInformativeMessage("account.setPrivacy", obj, callback, faultCallback); + } + + public void GetAuthorizationsAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetAuthorizations(); + + SendInformativeMessage("account.getAuthorizations", obj, callback, faultCallback); + } + + public void ResetAuthorizationAsync(TLLong hash, Action callback, Action faultCallback = null) + { + var obj = new TLResetAuthorization { Hash = hash }; + + SendInformativeMessage("account.resetAuthorization", obj, callback, faultCallback); + } + + public void GetPasswordAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetPassword(); + + SendInformativeMessage("account.getPassword", obj, callback, faultCallback); + } + + public void GetTmpPasswordAsync(TLInputCheckPasswordBase password, TLInt period, Action callback, Action faultCallback = null) + { + var obj = new TLGetTmpPassword{ Password = password, Period = period }; + + SendInformativeMessage("account.getTmpPassword", obj, callback, faultCallback); + } + + public void GetPasswordSettingsAsync(TLInputCheckPasswordBase password, Action callback, Action faultCallback = null) + { + var obj = new TLGetPasswordSettings { Password = password }; + + SendInformativeMessage("account.getPasswordSettings", obj, callback, faultCallback); + } + + public void UpdatePasswordSettingsAsync(TLInputCheckPasswordBase password, TLPasswordInputSettings newSettings, Action callback, Action faultCallback = null) + { + var obj = new TLUpdatePasswordSettings { Password = password, NewSettings = newSettings }; + + SendInformativeMessage("account.updatePasswordSettings", obj, callback, faultCallback); + } + + public void CheckPasswordAsync(TLInputCheckPasswordBase password, Action callback, Action faultCallback = null) + { + var obj = new TLCheckPassword { Password = password }; + + SendInformativeMessage("account.checkPassword", obj, callback, faultCallback); + } + + public void RequestPasswordRecoveryAsync(Action callback, Action faultCallback = null) + { + var obj = new TLRequestPasswordRecovery(); + + SendInformativeMessage("account.requestPasswordRecovery", obj, callback, faultCallback); + } + + public void RecoverPasswordAsync(TLString code, Action callback, Action faultCallback = null) + { + var obj = new TLRecoverPassword {Code = code}; + + SendInformativeMessage("account.recoverPassword", obj, callback, faultCallback); + } + + public void ConfirmPhoneAsync(TLString phoneCodeHash, TLString phoneCode, Action callback, Action faultCallback = null) + { + var obj = new TLConfirmPhone { PhoneCodeHash = phoneCodeHash, PhoneCode = phoneCode }; + + SendInformativeMessage("account.confirmPhone", obj, callback, faultCallback); + } + + public void SendConfirmPhoneCodeAsync(TLString hash, TLBool currentNumber, Action callback, Action faultCallback = null) + { + var obj = new TLSendConfirmPhoneCode { Flags = new TLInt(0), Hash = hash, CurrentNumber = currentNumber }; + + SendInformativeMessage("account.sendConfirmPhoneCode", obj, callback, faultCallback); + } + + public void GetWebAuthorizationsAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetWebAuthorizations(); + + SendInformativeMessage("account.getWebAuthorizations", obj, callback, faultCallback); + } + + public void ResetWebAuthorizationAsync(TLLong hash, Action callback, Action faultCallback = null) + { + var obj = new TLResetWebAuthorization { Hash = hash }; + + SendInformativeMessage("account.resetWebAuthorization", obj, callback, faultCallback); + } + + public void ResetWebAuthorizationsAsync(Action callback, Action faultCallback = null) + { + var obj = new TLResetWebAuthorizations(); + + SendInformativeMessage("account.resetWebAuthorizations", obj, callback, faultCallback); + } + + public void GetAllSecureValuesAsync(Action> callback, Action faultCallback = null) + { + var obj = new TLGetAllSecureValues(); + + SendInformativeMessage("account.getAllSecureValues", obj, + result => + { + var vector = result as TLVector; + if (vector != null) + { + callback.SafeInvoke(vector); + } + else + { + callback.SafeInvoke(new TLVector()); + } + }, + faultCallback); + } + + public void GetPassportDataAsync(Action> callback, Action faultCallback = null) + { + var requests = new TLObject[] + { + new TLGetPassword(), + new TLGetAllSecureValues() + }; + var returnValue = new TLObject[2]; + GetPassportRequestsInternal( + requests, + result => + { + bool completed; + lock (returnValue) + { + if (result is TLPasswordBase) returnValue[0] = result; + if (result is IList) returnValue[1] = result; + else if (result is IList) returnValue[1] = new TLVector(); + completed = returnValue[0] != null && returnValue[1] != null; + } + + if (completed) + { + callback.SafeInvoke(returnValue[0] as TLPasswordBase, returnValue[1] as IList); + } + }, + faultCallback.SafeInvoke); + } + + private void GetPassportRequestsInternal(TLObject[] requests, Action getResultCallback, Action faultCallback = null) + { + var container = new TLContainer { Messages = new List() }; + var historyItems = new List(); + + for (var i = 0; i < requests.Length; i++) + { + var obj = requests[i]; + int sequenceNumber; + TLLong messageId; + lock (_activeTransportRoot) + { + sequenceNumber = _activeTransport.SequenceNumber * 2 + 1; + _activeTransport.SequenceNumber++; + messageId = _activeTransport.GenerateMessageId(true); + } + + var data = i > 0 ? new TLInvokeAfterMsg { MsgId = container.Messages[i - 1].MessageId, Object = obj } : obj; + + var transportMessage = new TLContainerTransportMessage + { + MessageId = messageId, + SeqNo = new TLInt(sequenceNumber), + MessageData = data + }; + + var historyItem = new HistoryItem + { + SendTime = DateTime.Now, + Caption = "passport.item" + i, + Object = obj, + Message = transportMessage, + Callback = getResultCallback, + AttemptFailed = null, + FaultCallback = faultCallback, + ClientTicksDelta = ClientTicksDelta, + Status = RequestStatus.Sent, + }; + historyItems.Add(historyItem); + + container.Messages.Add(transportMessage); + } + + lock (_historyRoot) + { + foreach (var item in historyItems) + { + _history[item.Hash] = item; + } + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + + SendNonInformativeMessage("passport.container", container, + result => + { + + }, + faultCallback); + } + + public void GetSecureValueAsync(TLVector types, Action> callback, Action faultCallback = null) + { + var obj = new TLGetSecureValue { Types = types }; + + SendInformativeMessage("account.getSecureValue", obj, callback, faultCallback); + } + + public void SaveSecureValueAsync(TLInputSecureValue value, TLLong secureSecretHash, Action callback, Action faultCallback = null) + { + var obj = new TLSaveSecureValue { Value = value, SecureSecretId = secureSecretHash }; + + SendInformativeMessage("account.saveSecureValue", obj, callback, faultCallback); + } + + public void DeleteSecureValueAsync(TLVector types, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteSecureValue { Types = types }; + + SendInformativeMessage("account.deleteSecureValue", obj, callback, faultCallback); + } + + public void GetAuthorizationFormAsync(TLInt botId, TLString scope, TLString publicKey, Action callback, Action faultCallback = null) + { + var obj = new TLGetAuthorizationForm { BotId = botId, Scope = scope, PublicKey = publicKey }; + + SendInformativeMessage("account.getAuthorizationForm", obj, + result => + { + _cacheService.SyncUsers(result.Users, users => + { + result.Users = users; + callback.SafeInvoke(result); + }); + }, + faultCallback); + } + + public void GetAuthorizationFormAndPassportConfigAsync(TLInt botId, TLString scope, TLString publicKey, TLInt passportConfigHash, Action callback, Action faultCallback = null) + { + var requests = new TLObject[] + { + new TLGetAuthorizationForm + { + BotId = botId, + Scope = scope, + PublicKey = publicKey + }, + new TLGetPassportConfig + { + Hash = passportConfigHash + } + }; + + var returnValue = new TLObject[2]; + GetPassportRequestsInternal( + requests, + result => + { + bool completed; + lock (returnValue) + { + if (result is TLAuthorizationForm) returnValue[0] = result; + if (result is TLPassportConfigBase) returnValue[1] = result; + completed = returnValue[0] != null && returnValue[1] != null; + } + + if (completed) + { + callback.SafeInvoke(returnValue[0] as TLAuthorizationForm, returnValue[1] as TLPassportConfigBase); + } + }, + faultCallback.SafeInvoke); + } + + public void AcceptAuthorizationAsync(TLInt botId, TLString scope, TLString publicKey, TLVector valueHashes, TLSecureCredentialsEncrypted credentials, Action callback, Action faultCallback = null) + { + var obj = new TLAcceptAuthorization { BotId = botId, Scope = scope, PublicKey = publicKey, ValueHashes = valueHashes, Credentials = credentials }; + + SendInformativeMessage("account.acceptAuthorization", obj, callback, faultCallback); + } + + public void SendVerifyPhoneCodeAsync(TLString phoneNumber, TLBool currentNumber, Action callback, Action faultCallback = null) + { + var obj = new TLSendVerifyPhoneCode { Flags = new TLInt(0), PhoneNumber = phoneNumber, CurrentNumber = currentNumber }; + + SendInformativeMessage("account.sendVerifyPhoneCode", obj, callback, faultCallback); + } + + public void VerifyPhoneAsync(TLString phoneNumber, TLString phoneCodeHash, TLString phoneCode, Action callback, Action faultCallback = null) + { + var obj = new TLVerifyPhone { PhoneNumber = phoneNumber, PhoneCodeHash = phoneCodeHash, PhoneCode = phoneCode }; + + SendInformativeMessage("account.verifyPhone", obj, callback, faultCallback); + } + + public void SendVerifyEmailCodeAsync(TLString email, Action callback, Action faultCallback = null) + { + var obj = new TLSendVerifyEmailCode { Email = email }; + + SendInformativeMessage("account.sendVerifyEmailCode", obj, callback, faultCallback); + } + + public void VerifyEmailAsync(TLString email, TLString code, Action callback, Action faultCallback = null) + { + var obj = new TLVerifyEmail { Email = email, Code = code }; + + SendInformativeMessage("account.verifyEmail", obj, callback, faultCallback); + } + + public void InitTakeoutSessionAsync(bool contacts, bool messageUsers, bool messageChats, bool messageMegagroups, bool messageChannels, bool files, TLInt fileMaxSize, TLLong takeoutId, Action callback, Action faultCallback = null) + { + var obj = new TLInitTakeoutSession + { + Flags = new TLInt(0), + Contacts = contacts, + MessageUsers = messageUsers, + MessageChats = messageChats, + MessageMegagroups = messageMegagroups, + MessageChannels = messageChannels, + Files = files, + FileMaxSize = fileMaxSize, + TakeoutId = takeoutId + }; + + SendInformativeMessage("account.initTakeoutSession", obj, callback, faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Auth.cs b/Telegram.Api/Services/MTProtoService.Auth.cs new file mode 100755 index 0000000..d149351 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Auth.cs @@ -0,0 +1,160 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.Extensions; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Auth; +using Telegram.Api.Transport; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void BindTempAuthKeyAsync(TLLong permAuthKeyId, TLLong nonce, TLInt expiresAt, TLString encryptedMessage, Action callback, Action faultCallback = null) + { + var obj = new TLBindTempAuthKey { PermAuthKeyId = permAuthKeyId, Nonce = nonce, ExpiresAt = expiresAt, EncryptedMessage = encryptedMessage }; + + SendInformativeMessage("auth.bindTempAuthKey", obj, callback, faultCallback); + } + + public void LogOutAsync(Action callback) + { + _cacheService.ClearAsync(callback); + + //try to close session + LogOutAsync(null, null); + } + + public void CheckPhoneAsync(TLString phoneNumber, Action callback, Action faultCallback = null) + { + var obj = new TLCheckPhone { PhoneNumber = phoneNumber }; + + SendInformativeMessage("auth.checkPhone", obj, callback, faultCallback); + } + + public void SendCodeAsync(TLString phoneNumber, TLString currentNumber, Action callback, Action attemptFailed = null, Action faultCallback = null) + { + var obj = new TLSendCode + { + Flags = new TLInt(0), + PhoneNumber = phoneNumber, + CurrentNumber = currentNumber, + ApiId = new TLInt(Constants.ApiId), + ApiHash = new TLString(Constants.ApiHash) + }; + + SendInformativeMessage("auth.sendCode", obj, callback, faultCallback, 3); + } + + public void ResendCodeAsync(TLString phoneNumber, TLString phoneCodeHash, Action callback, Action faultCallback = null) + { + var obj = new TLResendCode { PhoneNumber = phoneNumber, PhoneCodeHash = phoneCodeHash }; + + SendInformativeMessage("auth.resendCode", obj, callback, faultCallback); + } + + public void CancelCodeAsync(TLString phoneNumber, TLString phoneCodeHash, Action callback, Action faultCallback = null) + { + var obj = new TLCancelCode { PhoneNumber = phoneNumber, PhoneCodeHash = phoneCodeHash }; + + SendInformativeMessage("auth.cancelCode", obj, callback, faultCallback); + } + + public void SendCallAsync(TLString phoneNumber, TLString phoneCodeHash, Action callback, Action faultCallback = null) + { + var obj = new TLSendCall { PhoneNumber = phoneNumber, PhoneCodeHash = phoneCodeHash }; + + SendInformativeMessage("auth.sendCall", obj, callback, faultCallback); + } + + public void SignUpAsync(TLString phoneNumber, TLString phoneCodeHash, TLString phoneCode, TLString firstName, TLString lastName, Action callback, Action faultCallback = null) + { + var obj = new TLSignUp { PhoneNumber = phoneNumber, PhoneCodeHash = phoneCodeHash, PhoneCode = phoneCode, FirstName = firstName, LastName = lastName }; + + SendInformativeMessage("auth.signUp", obj, + auth => + { + _cacheService.SyncUser(auth.User, result => { }); + callback(auth); + }, + faultCallback); + } + + public void SignInAsync(TLString phoneNumber, TLString phoneCodeHash, TLString phoneCode, Action callback, Action faultCallback = null) + { + var obj = new TLSignIn{ PhoneNumber = phoneNumber, PhoneCodeHash = phoneCodeHash, PhoneCode = phoneCode}; + + SendInformativeMessage("auth.signIn", obj, + auth => + { + _cacheService.SyncUser(auth.User, result => { }); + callback(auth); + }, + faultCallback); + } + + public void CancelSignInAsync() + { + CancelDelayedItemsAsync(true); + } + + public void LogOutAsync(Action callback, Action faultCallback = null) + { + var obj = new TLLogOut(); + + const string methodName = "auth.logOut"; + Logs.Log.Write(methodName); + SendInformativeMessage(methodName, obj, + result => + { + Logs.Log.Write(string.Format("{0} result={1}", methodName, result)); + callback.SafeInvoke(result); + }, + error => + { + Logs.Log.Write(string.Format("{0} error={1}", methodName, error)); + faultCallback.SafeInvoke(error); + }); + } + + public void SendInvitesAsync(TLVector phoneNumbers, TLString message, Action callback, Action faultCallback = null) + { + var obj = new TLSendInvites{ PhoneNumbers = phoneNumbers, Message = message }; + + SendInformativeMessage("auth.sendInvites", obj, callback, faultCallback); + } + + public void ExportAuthorizationAsync(TLInt dcId, Action callback, Action faultCallback = null) + { + var obj = new TLExportAuthorization { DCId = dcId }; + + SendInformativeMessage("auth.exportAuthorization dc_id=" + dcId, obj, callback, faultCallback); + } + + public void ImportAuthorizationAsync(TLInt id, TLString bytes, Action callback, Action faultCallback = null) + { + var obj = new TLImportAuthorization { Id = id, Bytes = bytes }; + + SendInformativeMessage("auth.importAuthorization id=" + id, obj, callback, faultCallback); + } + + public void ImportAuthorizationByTransportAsync(ITransport transport, TLInt id, TLString bytes, Action callback, Action faultCallback = null) + { + var obj = new TLImportAuthorization { Id = id, Bytes = bytes }; + + SendInformativeMessageByTransport(transport, "auth.importAuthorization dc_id=" + transport.DCId, obj, callback, faultCallback); + } + + public void ResetAuthorizationsAsync(Action callback, Action faultCallback = null) + { + var obj = new TLResetAuthorizations(); + + SendInformativeMessage("auth.resetAuthorizations", obj, callback, faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.ByTransport.cs b/Telegram.Api/Services/MTProtoService.ByTransport.cs new file mode 100755 index 0000000..1af0d87 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.ByTransport.cs @@ -0,0 +1,2320 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define MTPROTO +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using Org.BouncyCastle.Security; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Auth; +using Telegram.Api.TL.Functions.Channels; +using Telegram.Api.TL.Functions.DHKeyExchange; +using Telegram.Api.TL.Functions.Help; +using Telegram.Api.TL.Functions.Messages; +using Telegram.Api.TL.Functions.Stuff; +using Telegram.Api.TL.Functions.Upload; +using Telegram.Api.Transport; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void PingByTransportAsync(ITransport transport, TLLong pingId, Action callback, Action faultCallback = null) + { + var obj = new TLPing { PingId = pingId }; + + SendNonInformativeMessageByTransport(transport, "ping", obj, + result => + { + callback.SafeInvoke(result); + }, + faultCallback.SafeInvoke); + } + + public void GetConfigByTransportAsync(ITransport transport, Action callback, Action faultCallback = null) + { + var obj = new TLGetConfig(); + + Logs.Log.Write("help.getConfig"); + + SendInformativeMessageByTransport(transport, "help.getConfig", obj, + result => + { + callback(result); + }, + faultCallback); + } + + private void ReqPQByTransportAsync(ITransport transport, TLInt128 nonce, Action callback, Action faultCallback = null) + { + var obj = new TLReqPQ { Nonce = nonce }; + + SendNonEncryptedMessageByTransport(transport, "req_pq", obj, callback, faultCallback); + } + + private void ReqDHParamsByTransportAsync(ITransport transport, TLInt128 nonce, TLInt128 serverNonce, TLString p, TLString q, TLLong publicKeyFingerprint, TLString encryptedData, Action callback, Action faultCallback = null) + { + var obj = new TLReqDHParams { Nonce = nonce, ServerNonce = serverNonce, P = p, Q = q, PublicKeyFingerprint = publicKeyFingerprint, EncryptedData = encryptedData }; + + SendNonEncryptedMessageByTransport(transport, "req_DH_params", obj, callback, faultCallback); + } + + public void SetClientDHParamsByTransportAsync(ITransport transport, TLInt128 nonce, TLInt128 serverNonce, TLString encryptedData, Action callback, Action faultCallback = null) + { + var obj = new TLSetClientDHParams { Nonce = nonce, ServerNonce = serverNonce, EncryptedData = encryptedData }; + + SendNonEncryptedMessageByTransport(transport, "set_client_DH_params", obj, callback, faultCallback); + } + + private static Dictionary _serverPublicKeys = new Dictionary(); + + public void GetServerPublicKeyAsync(int dcId, TLVector fingerprints, Action callback, Action faultCallback = null) + { + if (_serverPublicKeys.Count == 0) + { + _serverPublicKeys[unchecked((long)0xc3b42b026ce86b21L)] = + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6\n" + + "lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS\n" + + "an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw\n" + + "Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+\n" + + "8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n\n" + + "Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB\n" + + "-----END RSA PUBLIC KEY-----"; + + _serverPublicKeys[unchecked((long)0x9a996a1db11c729bL)] = + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIIBCgKCAQEAxq7aeLAqJR20tkQQMfRn+ocfrtMlJsQ2Uksfs7Xcoo77jAid0bRt\n" + + "ksiVmT2HEIJUlRxfABoPBV8wY9zRTUMaMA654pUX41mhyVN+XoerGxFvrs9dF1Ru\n" + + "vCHbI02dM2ppPvyytvvMoefRoL5BTcpAihFgm5xCaakgsJ/tH5oVl74CdhQw8J5L\n" + + "xI/K++KJBUyZ26Uba1632cOiq05JBUW0Z2vWIOk4BLysk7+U9z+SxynKiZR3/xdi\n" + + "XvFKk01R3BHV+GUKM2RYazpS/P8v7eyKhAbKxOdRcFpHLlVwfjyM1VlDQrEZxsMp\n" + + "NTLYXb6Sce1Uov0YtNx5wEowlREH1WOTlwIDAQAB\n" + + "-----END RSA PUBLIC KEY-----"; + + _serverPublicKeys[unchecked((long)0xb05b2a6f70cdea78L)] = + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIIBCgKCAQEAsQZnSWVZNfClk29RcDTJQ76n8zZaiTGuUsi8sUhW8AS4PSbPKDm+\n" + + "DyJgdHDWdIF3HBzl7DHeFrILuqTs0vfS7Pa2NW8nUBwiaYQmPtwEa4n7bTmBVGsB\n" + + "1700/tz8wQWOLUlL2nMv+BPlDhxq4kmJCyJfgrIrHlX8sGPcPA4Y6Rwo0MSqYn3s\n" + + "g1Pu5gOKlaT9HKmE6wn5Sut6IiBjWozrRQ6n5h2RXNtO7O2qCDqjgB2vBxhV7B+z\n" + + "hRbLbCmW0tYMDsvPpX5M8fsO05svN+lKtCAuz1leFns8piZpptpSCFn7bWxiA9/f\n" + + "x5x17D7pfah3Sy2pA+NDXyzSlGcKdaUmwQIDAQAB\n" + + "-----END RSA PUBLIC KEY-----"; + + _serverPublicKeys[unchecked((long)0x71e025b6c76033e3L)] = + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIIBCgKCAQEAwqjFW0pi4reKGbkc9pK83Eunwj/k0G8ZTioMMPbZmW99GivMibwa\n" + + "xDM9RDWabEMyUtGoQC2ZcDeLWRK3W8jMP6dnEKAlvLkDLfC4fXYHzFO5KHEqF06i\n" + + "qAqBdmI1iBGdQv/OQCBcbXIWCGDY2AsiqLhlGQfPOI7/vvKc188rTriocgUtoTUc\n" + + "/n/sIUzkgwTqRyvWYynWARWzQg0I9olLBBC2q5RQJJlnYXZwyTL3y9tdb7zOHkks\n" + + "WV9IMQmZmyZh/N7sMbGWQpt4NMchGpPGeJ2e5gHBjDnlIf2p1yZOYeUYrdbwcS0t\n" + + "UiggS4UeE8TzIuXFQxw7fzEIlmhIaq3FnwIDAQAB\n" + + "-----END RSA PUBLIC KEY-----"; + + _serverPublicKeys[unchecked((long)0xbc35f3509f7b7a5L)] = + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIIBCgKCAQEAruw2yP/BCcsJliRoW5eBVBVle9dtjJw+OYED160Wybum9SXtBBLX\n" + + "riwt4rROd9csv0t0OHCaTmRqBcQ0J8fxhN6/cpR1GWgOZRUAiQxoMnlt0R93LCX/\n" + + "j1dnVa/gVbCjdSxpbrfY2g2L4frzjJvdl84Kd9ORYjDEAyFnEA7dD556OptgLQQ2\n" + + "e2iVNq8NZLYTzLp5YpOdO1doK+ttrltggTCy5SrKeLoCPPbOgGsdxJxyz5KKcZnS\n" + + "Lj16yE5HvJQn0CNpRdENvRUXe6tBP78O39oJ8BTHp9oIjd6XWXAsp2CvK45Ol8wF\n" + + "XGF710w9lwCGNbmNxNYhtIkdqfsEcwR5JwIDAQAB\n" + + "-----END RSA PUBLIC KEY-----"; + + _serverPublicKeys[unchecked((long)0x15ae5fa8b5529542L)] = + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIIBCgKCAQEAvfLHfYH2r9R70w8prHblWt/nDkh+XkgpflqQVcnAfSuTtO05lNPs\n" + + "pQmL8Y2XjVT4t8cT6xAkdgfmmvnvRPOOKPi0OfJXoRVylFzAQG/j83u5K3kRLbae\n" + + "7fLccVhKZhY46lvsueI1hQdLgNV9n1cQ3TDS2pQOCtovG4eDl9wacrXOJTG2990V\n" + + "jgnIKNA0UMoP+KF03qzryqIt3oTvZq03DyWdGK+AZjgBLaDKSnC6qD2cFY81UryR\n" + + "WOab8zKkWAnhw2kFpcqhI0jdV5QaSCExvnsjVaX0Y1N0870931/5Jb9ICe4nweZ9\n" + + "kSDF/gip3kWLG0o8XQpChDfyvsqB9OLV/wIDAQAB\n" + + "-----END RSA PUBLIC KEY-----"; + + _serverPublicKeys[unchecked((long)0xaeae98e13cd7f94fL)] = + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIIBCgKCAQEAs/ditzm+mPND6xkhzwFIz6J/968CtkcSE/7Z2qAJiXbmZ3UDJPGr\n" + + "zqTDHkO30R8VeRM/Kz2f4nR05GIFiITl4bEjvpy7xqRDspJcCFIOcyXm8abVDhF+\n" + + "th6knSU0yLtNKuQVP6voMrnt9MV1X92LGZQLgdHZbPQz0Z5qIpaKhdyA8DEvWWvS\n" + + "Uwwc+yi1/gGaybwlzZwqXYoPOhwMebzKUk0xW14htcJrRrq+PXXQbRzTMynseCoP\n" + + "Ioke0dtCodbA3qQxQovE16q9zz4Otv2k4j63cz53J+mhkVWAeWxVGI0lltJmWtEY\n" + + "K6er8VqqWot3nqmWMXogrgRLggv/NbbooQIDAQAB\n" + + "-----END RSA PUBLIC KEY-----"; + + _serverPublicKeys[unchecked((long)0x5a181b2235057d98L)] = + "-----BEGIN RSA PUBLIC KEY-----\n" + + "MIIBCgKCAQEAvmpxVY7ld/8DAjz6F6q05shjg8/4p6047bn6/m8yPy1RBsvIyvuD\n" + + "uGnP/RzPEhzXQ9UJ5Ynmh2XJZgHoE9xbnfxL5BXHplJhMtADXKM9bWB11PU1Eioc\n" + + "3+AXBB8QiNFBn2XI5UkO5hPhbb9mJpjA9Uhw8EdfqJP8QetVsI/xrCEbwEXe0xvi\n" + + "fRLJbY08/Gp66KpQvy7g8w7VB8wlgePexW3pT13Ap6vuC+mQuJPyiHvSxjEKHgqe\n" + + "Pji9NP3tJUFQjcECqcm0yV7/2d0t/pbCm+ZH1sadZspQCEPPrtbkQBlvHb4OLiIW\n" + + "PGHKSMeRFvp3IWcmdJqXahxLCUS1Eh6MAQIDAQAB\n" + + "-----END RSA PUBLIC KEY-----"; + } + + var dcOption = _config != null ? _config.DCOptions.FirstOrDefault(x => x.Id.Value == dcId) : null; + if (dcOption == null || !dcOption.CDN.Value) + { + for (var i = 0; i < fingerprints.Count; i++) + { + string key; + if (_serverPublicKeys.TryGetValue(fingerprints[i].Value, out key)) + { + callback.SafeInvoke(i, key); + return; + } + } + + callback.SafeInvoke(-1, null); + return; + } + + var cdnConfig = _cacheService.GetCdnConfig(); + if (cdnConfig != null) + { + var pairs = cdnConfig.PublicKeys.Where(x => x.DCId.Value == dcId).ToDictionary(x => x.PublicKeyFingerprint.Value); + for (var i = 0; i < fingerprints.Count; i++) + { + if (pairs.ContainsKey(fingerprints[i].Value)) + { + callback.SafeInvoke(i, pairs[fingerprints[i].Value].PublicKey.ToString()); + return; + } + } + } + + GetCdnConfigAsync( + result => + { + cdnConfig = result; + + _cacheService.SetCdnCofig(cdnConfig); + + GetServerPublicKeyAsync(dcId, fingerprints, callback, faultCallback); + }, + error => + { + faultCallback.SafeInvoke(error); + }); + } + + public void InitTransportAsync(ITransport transport, Action> callback, Action faultCallback = null) + { + var authTime = Stopwatch.StartNew(); + var newNonce = TLInt256.Random(); + +#if LOG_REGISTRATION + TLUtils.WriteLog("Start ReqPQ"); +#endif + var nonce = TLInt128.Random(); + ReqPQByTransportAsync( + transport, + nonce, + resPQ => + { + GetServerPublicKeyAsync(transport.DCId, resPQ.ServerPublicKeyFingerprints, + (index, publicKey) => + { + if (index < 0 || string.IsNullOrEmpty(publicKey)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("unknown public key") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqPQ with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + + var serverNonce = resPQ.ServerNonce; + if (!TLUtils.ByteArraysEqual(nonce.Value, resPQ.Nonce.Value)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect nonce") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqPQ with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqPQ"); +#endif + TimeSpan calcTime; + WindowsPhone.Tuple pqPair; + var innerData = GetInnerData(new TLInt(TLUtils.GetProtocolDCId(transport.DCId, false, Constants.IsTestServer)), resPQ, newNonce, out calcTime, out pqPair); + var encryptedInnerData = GetEncryptedInnerData(innerData, publicKey); + +#if LOG_REGISTRATION + TLUtils.WriteLog("Start ReqDHParams"); +#endif + ReqDHParamsByTransportAsync( + transport, + resPQ.Nonce, + resPQ.ServerNonce, + innerData.P, + innerData.Q, + resPQ.ServerPublicKeyFingerprints[index], + encryptedInnerData, + serverDHParams => + { + if (!TLUtils.ByteArraysEqual(nonce.Value, serverDHParams.Nonce.Value)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect nonce") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + if (!TLUtils.ByteArraysEqual(serverNonce.Value, serverDHParams.ServerNonce.Value)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect server_nonce") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams"); +#endif + var random = new SecureRandom(); + + var serverDHParamsOk = serverDHParams as TLServerDHParamsOk; + if (serverDHParamsOk == null) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("Incorrect serverDHParams") }; + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); +#if LOG_REGISTRATION + + TLUtils.WriteLog("ServerDHParams " + serverDHParams); +#endif + return; + } + + var aesParams = GetAesKeyIV(resPQ.ServerNonce.ToBytes(), newNonce.ToBytes()); + + var decryptedAnswerWithHash = Utils.AesIge(serverDHParamsOk.EncryptedAnswer.Data, aesParams.Item1, aesParams.Item2, false); //NOTE: Remove reverse here + + var position = 0; + var serverDHInnerData = (TLServerDHInnerData)new TLServerDHInnerData().FromBytes(decryptedAnswerWithHash.Skip(20).ToArray(), ref position); + + var sha1 = Utils.ComputeSHA1(serverDHInnerData.ToBytes()); + if (!TLUtils.ByteArraysEqual(sha1, decryptedAnswerWithHash.Take(20).ToArray())) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect sha1 TLServerDHInnerData") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + + if (!TLUtils.CheckPrime(serverDHInnerData.DHPrime.Data, serverDHInnerData.G.Value)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect (p, q) pair") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + + if (!TLUtils.CheckGaAndGb(serverDHInnerData.GA.Data, serverDHInnerData.DHPrime.Data)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect g_a") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + + var bBytes = new byte[256]; //big endian B + random.NextBytes(bBytes); + + var gbBytes = GetGB(bBytes, serverDHInnerData.G, serverDHInnerData.DHPrime); + + var clientDHInnerData = new TLClientDHInnerData + { + Nonce = resPQ.Nonce, + ServerNonce = resPQ.ServerNonce, + RetryId = new TLLong(0), + GB = TLString.FromBigEndianData(gbBytes) + }; + + var encryptedClientDHInnerData = GetEncryptedClientDHInnerData(clientDHInnerData, aesParams); +#if LOG_REGISTRATION + TLUtils.WriteLog("Start SetClientDHParams"); +#endif + SetClientDHParamsByTransportAsync( + transport, + resPQ.Nonce, + resPQ.ServerNonce, + encryptedClientDHInnerData, + dhGen => + { + if (!TLUtils.ByteArraysEqual(nonce.Value, dhGen.Nonce.Value)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect nonce") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop SetClientDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + if (!TLUtils.ByteArraysEqual(serverNonce.Value, dhGen.ServerNonce.Value)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect server_nonce") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop SetClientDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + + var dhGenOk = dhGen as TLDHGenOk; + if (dhGenOk == null) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("Incorrect dhGen " + dhGen.GetType()) }; + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); +#if LOG_REGISTRATION + TLUtils.WriteLog("DHGen result " + serverDHParams); +#endif + return; + } + +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop SetClientDHParams"); +#endif + var getKeyTimer = Stopwatch.StartNew(); + var authKey = GetAuthKey(bBytes, serverDHInnerData.GA.ToBytes(), serverDHInnerData.DHPrime.ToBytes()); + +#if LOG_REGISTRATION + var logCountersString = new StringBuilder(); + + logCountersString.AppendLine("Auth Counters"); + logCountersString.AppendLine(); + logCountersString.AppendLine("pq factorization time: " + calcTime); + logCountersString.AppendLine("calc auth key time: " + getKeyTimer.Elapsed); + logCountersString.AppendLine("auth time: " + authTime.Elapsed); + + TLUtils.WriteLog(logCountersString.ToString()); +#endif + //newNonce - little endian + //authResponse.ServerNonce - little endian + var salt = GetSalt(newNonce.ToBytes(), resPQ.ServerNonce.ToBytes()); + var sessionId = new byte[8]; + random.NextBytes(sessionId); + + // authKey, salt, sessionId + callback(new WindowsPhone.Tuple(authKey, new TLLong(BitConverter.ToInt64(salt, 0)), new TLLong(BitConverter.ToInt64(sessionId, 0)))); + }, + error => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop SetClientDHParams with error " + error.ToString()); +#endif + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + }); + }, + error => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams with error " + error.ToString()); +#endif + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + }); + }, + error => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ServerPublicKey with error " + error.ToString()); +#endif + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + }); + }, + error => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqPQ with error " + error.ToString()); +#endif + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + }); + } + + public void LogOutTransportsAsync(Action callback, Action> faultCallback = null) + { + Execute.BeginOnThreadPool(() => + { + var dcOptions = _config.DCOptions; + var activeDCOptionIndex = _config.ActiveDCOptionIndex; + + if (dcOptions.Count > 1) + { + var waitHandles = new List(); + var errors = new List(); + for (var i = 0; i < dcOptions.Count; i++) + { + if (activeDCOptionIndex == i) + { + continue; + } + + var local = i; + var handle = new ManualResetEvent(false); + waitHandles.Add(handle); + Execute.BeginOnThreadPool(() => + { + var dcOption = dcOptions[local]; + LogOutAsync(dcOption.Id, + result => + { + handle.Set(); + }, + error => + { + errors.Add(error); + handle.Set(); + }); + }); + } + + var waitingResult = WaitHandle.WaitAll(waitHandles.ToArray(), TimeSpan.FromSeconds(25.0)); + if (waitingResult) + { + if (errors.Count > 0) + { + faultCallback.SafeInvoke(errors); + } + else + { + callback.SafeInvoke(); + } + } + else + { + faultCallback.SafeInvoke(errors); + } + } + else + { + callback.SafeInvoke(); + } + }); + } + + public void LogOutAsync(TLInt dcId, Action callback, Action faultCallback = null) + { + lock (_activeTransportRoot) + { + if (_activeTransport.DCId == dcId.Value) + { + if (_activeTransport.DCId == 0) + { + TLUtils.WriteException(new Exception("_activeTransport.DCId==0")); + } + + LogOutAsync(callback, faultCallback); + return; + } + } + + var transport = GetMediaTransportByDCId(dcId); + + if (transport == null) + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("LogOutAsync: Empty transport for dc id " + dcId) }); + + return; + } + + if (transport.AuthKey == null) + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("LogOutAsync: Empty authKey for dc id " + dcId) }); + + return; + } + + var obj = new TLLogOut(); + + SendInformativeMessageByTransport(transport, "auth.logOut", obj, + result => + { + lock (transport.SyncRoot) + { + transport.IsInitializing = false; + transport.IsAuthorizing = false; + transport.IsAuthorized = false; + } + }, + faultCallback); + } + + public void ReuploadCdnFileAsync(TLInt dcId, TLString fileToken, TLString requestToken, Action> callback, Action faultCallback = null) + { + var obj = new TLReuploadCdnFile { FileToken = fileToken, RequestToken = requestToken }; + + var transport = GetMediaTransportByDCId(dcId); + if (transport == null) + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("ReuploadCdnFileAsync: Empty transport for dc id " + dcId) }); + } + else + { + SendInformativeMessageByTransport(transport, string.Format("upload.reuploadCdnFile dc_id={0} file_token={1} request_token={2}", dcId, fileToken, requestToken), obj, callback, faultCallback); + } + } + + public void GetCdnFileAsync(TLInt dcId, TLString fileToken, TLInt offset, TLInt limit, Action callback, Action faultCallback = null) + { + var obj = new TLGetCdnFile { FileToken = fileToken, Offset = offset, Limit = limit }; + + var transport = GetMediaTransportByDCId(dcId); + if (transport == null) + { + GetConfigAsync( + result => + { + _config = TLConfig.Merge(_config, result); + _cacheService.SetConfig(_config); + + GetCdnFileAsync(dcId, fileToken, offset, limit, callback, faultCallback); + }, + error => + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("GetCdnFileAsync: Empty transport for dc id " + dcId) }); + }); + + return; + } + + if (transport.AuthKey == null) + { + var cancelInitializing = false; + lock (transport.SyncRoot) + { + if (transport.IsInitializing) + { + cancelInitializing = true; + } + else + { + transport.IsInitializing = true; + } + } + + if (cancelInitializing) + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("DC " + dcId + " is already initializing") }); + return; + } + + InitTransportAsync( + transport, + tuple => + { + lock (transport.SyncRoot) + { + transport.AuthKey = tuple.Item1; + transport.Salt = tuple.Item2; + transport.SessionId = tuple.Item3; + + transport.IsInitializing = false; + } + var authKeyId = TLUtils.GenerateLongAuthKeyId(tuple.Item1); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = tuple.Item1, AutkKeyId = authKeyId }); + } + } + + foreach (var dcOption in _config.DCOptions) + { + if (dcOption.Id.Value == transport.DCId) + { + dcOption.AuthKey = tuple.Item1; + dcOption.Salt = tuple.Item2; + dcOption.SessionId = tuple.Item3; + } + } + + _cacheService.SetConfig(_config); + + SendInformativeMessageByTransport(transport, string.Format("upload.getCdnFile dc_id={0} file_token={3} o={1} l={2}", dcId, offset, limit, fileToken), obj, callback, faultCallback); + }, + error => + { + lock (transport.SyncRoot) + { + transport.IsInitializing = false; + } + + faultCallback.SafeInvoke(error); + }); + } + else + { + SendInformativeMessageByTransport(transport, string.Format("upload.getCdnFile dc_id={0} file_token={3} o={1} l={2}", dcId, offset, limit, fileToken), obj, callback, faultCallback); + } + } + + private void GetFileAsyncInternal(TLObject obj, TLInt dcId, TLInputFileLocationBase location, TLInt offset, TLInt limit, Action callback, Action faultCallback = null) where T : TLObject + { + var transport = GetMediaTransportByDCId(dcId); + + lock (_activeTransportRoot) + { + if (_activeTransport.DCId == dcId.Value) + { + if (_activeTransport.DCId == 0) + { + TLUtils.WriteException(new Exception("_activeTransport.DCId==0")); + } + + SendInformativeMessageByTransport(transport, string.Format("upload.getFile main dc_id={0} loc=[{5}] o={1} l={2}\ntransport_id={3} session_id={4}", dcId, offset, limit, transport.Id, transport.SessionId, location.GetLocationString()), obj, callback, faultCallback); + return; + } + } + + if (transport == null) + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("GetFileAsync: Empty transport for dc id " + dcId) }); + + return; + } + + if (transport.AuthKey == null) + { + var cancelInitializing = false; + lock (transport.SyncRoot) + { + if (transport.IsInitializing) + { + cancelInitializing = true; + } + else + { + transport.IsInitializing = true; + } + } + + if (cancelInitializing) + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("DC " + dcId + " is already initializing") }); + return; + } + + InitTransportAsync( + transport, + tuple => + { + lock (transport.SyncRoot) + { + transport.AuthKey = tuple.Item1; + transport.Salt = tuple.Item2; + transport.SessionId = tuple.Item3; + + transport.IsInitializing = false; + } + var authKeyId = TLUtils.GenerateLongAuthKeyId(tuple.Item1); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = tuple.Item1, AutkKeyId = authKeyId }); + } + } + + ExportImportAuthorizationAsync( + transport, + () => + { + foreach (var dcOption in _config.DCOptions) + { + if (dcOption.Id.Value == transport.DCId) + { + dcOption.AuthKey = tuple.Item1; + dcOption.Salt = tuple.Item2; + dcOption.SessionId = tuple.Item3; + } + } + + _cacheService.SetConfig(_config); + + SendInformativeMessageByTransport(transport, string.Format("upload.getFile dc_id={0} loc=[{3}] o={1} l={2}", dcId, offset, limit, location.GetLocationString()), obj, callback, faultCallback); + }, + error => + { + if (!error.CodeEquals(ErrorCode.NOT_FOUND) && + !error.Message.ToString().Contains("is already authorizing")) + { + Execute.ShowDebugMessage("ExportImportAuthorization error " + error); + } + + faultCallback.SafeInvoke(error); + }); + }, + error => + { + lock (transport.SyncRoot) + { + transport.IsInitializing = false; + } + + faultCallback.SafeInvoke(error); + }); + } + else + { + ExportImportAuthorizationAsync( + transport, + () => + { + SendInformativeMessageByTransport(transport, string.Format("upload.getFile dc_id={0} loc=[{3}] o={1} l={2}", dcId, offset, limit, location.GetLocationString()), obj, callback, faultCallback); + }, + error => + { + if (!error.CodeEquals(ErrorCode.NOT_FOUND) + && !error.Message.ToString().Contains("is already authorizing")) + { + Execute.ShowDebugMessage("ExportImportAuthorization error " + error); + } + + faultCallback.SafeInvoke(error); + }); + } + } + + public void GetFileAsync(TLInt dcId, TLInputFileLocationBase location, TLInt offset, TLInt limit, Action callback, Action faultCallback = null) + { + var obj = location is TLInputWebFileLocationBase + ? (TLObject)new TLGetWebFile { Location = location, Offset = offset, Limit = limit } + : new TLGetFile { Location = location, Offset = offset, Limit = limit }; + + GetFileAsyncInternal(obj, dcId, location, offset, limit, callback, faultCallback); + } + + private void ExportImportAuthorizationAsync(ITransport toTransport, Action callback, Action faultCallback = null) + { + if (!toTransport.IsAuthorized) + { + bool authorizing = false; + lock (toTransport.SyncRoot) + { + if (toTransport.IsAuthorizing) + { + authorizing = true; + } + + toTransport.IsAuthorizing = true; + } + + if (authorizing) + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("DC " + toTransport.DCId + " is already authorizing") }); + return; + } + + ExportAuthorizationAsync( + new TLInt(toTransport.DCId), + exportedAuthorization => + { + ImportAuthorizationByTransportAsync( + toTransport, + exportedAuthorization.Id, + exportedAuthorization.Bytes, + authorization => + { + lock (toTransport.SyncRoot) + { + toTransport.IsAuthorized = true; + toTransport.IsAuthorizing = false; + } + + foreach (var dcOption in _config.DCOptions) + { + if (dcOption.Id.Value == toTransport.DCId) + { + dcOption.IsAuthorized = true; + } + } + + _cacheService.SetConfig(_config); + + callback.SafeInvoke(); + }, + error => + { + lock (toTransport.SyncRoot) + { + toTransport.IsAuthorizing = false; + } + faultCallback.SafeInvoke(error); + }); + ; + }, + error => + { + lock (toTransport.SyncRoot) + { + toTransport.IsAuthorizing = false; + } + faultCallback.SafeInvoke(error); + }); + } + else + { + callback.SafeInvoke(); + } + } + + private ITransport GetMediaTransportByDCId(TLInt dcId) + { + ITransport transport; + lock (_activeTransportRoot) + { + var dcOption = TLUtils.GetDCOption(_config, dcId);// && x.Media.Value); + + if (dcOption == null) return null; + + transport = GetFileTransport(dcOption.IpAddress.Value, dcOption.Port.Value, Type, + new TransportSettings + { + DcId = dcOption.Id.Value, + Secret = TLUtils.ParseSecret(dcOption), + AuthKey = dcOption.AuthKey, + Salt = dcOption.Salt, + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = dcOption.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }); + } + + return transport; + } + + + private void SendNonInformativeMessageByTransport(ITransport transport, string caption, TLObject obj, Action callback, Action faultCallback = null) where T : TLObject + { + bool isInitialized; + lock (transport.SyncRoot) + { + isInitialized = transport.AuthKey != null; + } + + if (!isInitialized) + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("transport " + transport.DCId + " " + caption + " delayed send is not supported") }); + + return; + } + + int sequenceNumber; + TLLong messageId; + lock (transport.SyncRoot) + { + sequenceNumber = transport.SequenceNumber * 2; + messageId = transport.GenerateMessageId(true); + } + var authKey = transport.AuthKey; + var salt = transport.Salt; + var sessionId = transport.SessionId; + var clientsTicksDelta = transport.ClientTicksDelta; + var transportMessage = CreateTLTransportMessage(salt, sessionId, new TLInt(sequenceNumber), messageId, obj); + var encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + + lock (transport.SyncRoot) + { + if (transport.Closed) + { + var transportSettings = new TransportSettings + { + DcId = transport.DCId, + Secret = transport.Secret, + AuthKey = transport.AuthKey, + Salt = transport.Salt, + SessionId = transport.SessionId, + MessageIdDict = transport.MessageIdDict, + SequenceNumber = transport.SequenceNumber, + ClientTicksDelta = transport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }; + + transport = transport.MTProtoType == MTProtoTransportType.Special + ? GetSpecialTransport(transport.Host, transport.Port, Type, transportSettings) + : GetFileTransport(transport.Host, transport.Port, Type, transportSettings); + } + } + + PrintCaption(caption); + + HistoryItem historyItem = null; + if (string.Equals(caption, "ping", StringComparison.OrdinalIgnoreCase) + || string.Equals(caption, "ping_delay_disconnect", StringComparison.OrdinalIgnoreCase) + || string.Equals(caption, "messages.container", StringComparison.OrdinalIgnoreCase)) + { + //save items to history + historyItem = new HistoryItem + { + SendTime = DateTime.Now, + //SendBeforeTime = sendBeforeTime, + Caption = caption, + Object = obj, + Message = transportMessage, + Callback = t => callback((T)t), + AttemptFailed = null, + FaultCallback = faultCallback, + ClientTicksDelta = clientsTicksDelta, + Status = RequestStatus.Sent, + }; + + lock (_historyRoot) + { + _history[historyItem.Hash] = historyItem; + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + } + + //Debug.WriteLine(">>{0, -30} MsgId {1} SeqNo {2, -4} SessionId {3}", caption, transportMessage.MessageId.Value, transportMessage.SeqNo.Value, transportMessage.SessionId.Value); + + var captionString = string.Format("{0} {1}", caption, transportMessage.MessageId); + + SendPacketAsync(transport, captionString, encryptedMessage, + result => + { + if (!result) + { + if (historyItem != null) + { + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + } + faultCallback.SafeInvoke(new TLRPCError(404) { Message = new TLString("FastCallback SocketError=" + result) }); + } + }, + error => + { + if (historyItem != null) + { + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + } + faultCallback.SafeInvoke(new TLRPCError(404) + { +#if WINDOWS_PHONE + SocketError = error.Error, +#endif + Exception = error.Exception + }); + }); + } + + private readonly object _initConnectionSyncRoot = new object(); + + private void SendInformativeMessageByTransport(ITransport transport, string caption, TLObject obj, Action callback, Action faultCallback = null, + int? maxAttempt = null, // to send delayed items + Action attemptFailed = null) // to send delayed items + where T : TLObject + { + bool isInitialized; + lock (transport.SyncRoot) + { + isInitialized = transport.AuthKey != null; + } + + if (!isInitialized) + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("transport " + transport.DCId + " " + caption + " delayed send is not supported") }); + + // var delayedItem = new DelayedItem + // { + // SendTime = DateTime.Now, + // Caption = caption, + // Object = obj, + // Callback = t => callback((T)t), + // AttemptFailed = attemptFailed, + // FaultCallback = faultCallback, + // MaxAttempt = maxAttempt + // }; + //#if LOG_REGISTRATION + // TLUtils.WriteLog(DateTime.Now.ToLocalTime() + ": Enqueue delayed item\n " + delayedItem); + //#endif + // lock (_delayedItemsRoot) + // { + // _delayedItems.Add(delayedItem); + // } + + return; + } + + lock (transport.SyncRoot) + { + if (transport.Closed) + { + var transportSettings = new TransportSettings + { + DcId = transport.DCId, + Secret = transport.Secret, + AuthKey = transport.AuthKey, + Salt = transport.Salt, + SessionId = transport.SessionId, + MessageIdDict = transport.MessageIdDict, + SequenceNumber = transport.SequenceNumber, + ClientTicksDelta = transport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }; + + transport = transport.MTProtoType == MTProtoTransportType.Special + ? GetSpecialTransport(transport.Host, transport.Port, Type, transportSettings) + : GetFileTransport(transport.Host, transport.Port, Type, transportSettings); + } + } + + PrintCaption(caption); + + TLObject data; + int sequenceNumber; + TLLong messageId; + lock (transport.SyncRoot) + { + if (!transport.Initiated || caption == "auth.sendCode") + { + var initConnection = new TLInitConnection78 + { + Flags = new TLInt(0), + AppId = new TLInt(Constants.ApiId), + AppVersion = new TLString(_deviceInfo.AppVersion), + Data = obj, + DeviceModel = new TLString(_deviceInfo.Model), + SystemLangCode = new TLString(Utils.CurrentUICulture()), + LangPack = TLString.Empty, + LangCode = new TLString(Utils.CurrentUICulture()), + SystemVersion = new TLString(_deviceInfo.SystemVersion), + Proxy = TLUtils.GetInputProxy(_transportService.GetProxyConfig()) + }; + + var withLayerN = new TLInvokeWithLayerN { Data = initConnection }; + data = withLayerN; + transport.Initiated = true; + } + else + { + data = obj; + } + + sequenceNumber = transport.SequenceNumber * 2 + 1; + transport.SequenceNumber++; + messageId = transport.GenerateMessageId(true); + } + + var authKey = transport.AuthKey; + var salt = transport.Salt; + var sessionId = transport.SessionId; + var clientsTicksDelta = transport.ClientTicksDelta; + var dcId = transport.DCId; + var transportMessage = CreateTLTransportMessage(salt, sessionId, new TLInt(sequenceNumber), messageId, data); + var encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + + var historyItem = new HistoryItem + { + SendTime = DateTime.Now, + Caption = caption, + Object = obj, + Message = transportMessage, + Callback = t => callback((T)t), + FaultCallback = faultCallback, + ClientTicksDelta = clientsTicksDelta, + Status = RequestStatus.Sent, + + DCId = dcId + }; + + lock (_historyRoot) + { + _history[historyItem.Hash] = historyItem; + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + + //Debug.WriteLine(">> {4} {0, -30} MsgId {1} SeqNo {2, -4} SessionId {3}", caption, transportMessage.MessageId, transportMessage.SeqNo, transportMessage.SessionId, historyItem.DCId); + var captionString = string.Format("{0} {1} {2}", caption, transportMessage.SessionId, transportMessage.MessageId); + SendPacketAsync(transport, captionString, + encryptedMessage, + result => + { + if (!result) + { + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("FastCallback SocketError=" + result) }); + } + }, + error => + { + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404) }); + }); + } + + private void SaveInitConnectionAsync(TLInitConnection initConnection) + { + Execute.BeginOnThreadPool(() => TLUtils.SaveObjectToMTProtoFile(_initConnectionSyncRoot, Constants.InitConnectionFileName, initConnection)); + } + + private void SendNonEncryptedMessageByTransport(ITransport transport, string caption, TLObject obj, Action callback, Action faultCallback = null) where T : TLObject + { + PrintCaption(caption); + + TLLong messageId; + lock (transport.SyncRoot) + { + messageId = transport.GenerateMessageId(); + } + var message = CreateTLNonEncryptedMessage(messageId, obj); + + var historyItem = new HistoryItem + { + Caption = caption, + Message = message, + Callback = t => callback((T)t), + FaultCallback = faultCallback, + SendTime = DateTime.Now, + Status = RequestStatus.Sent + }; + + var guid = message.MessageId; + lock (transport.SyncRoot) + { + if (transport.Closed) + { + var transportSettings = new TransportSettings + { + DcId = transport.DCId, + Secret = transport.Secret, + AuthKey = transport.AuthKey, + Salt = transport.Salt, + SessionId = transport.SessionId, + MessageIdDict = transport.MessageIdDict, + SequenceNumber = transport.SequenceNumber, + ClientTicksDelta = transport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }; + + transport = transport.MTProtoType == MTProtoTransportType.Special + ? GetSpecialTransport(transport.Host, transport.Port, Type, transportSettings) + : GetFileTransport(transport.Host, transport.Port, Type, transportSettings); + } + } + + transport.EnqueueNonEncryptedItem(historyItem); + + var captionString = string.Format("{0} {1}", caption, guid); + SendPacketAsync(transport, captionString, message, + socketError => + { +#if LOG_REGISTRATION + TLUtils.WriteLog(caption + " SocketError=" + socketError); +#endif + if (!socketError) + { + transport.RemoveNonEncryptedItem(historyItem); + + // connection is unsuccessfully + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("FastCallback SocketError=" + socketError) }); + } + }, + error => + { + transport.RemoveNonEncryptedItem(historyItem); + + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404) }); + }); + } + + public void MessageAcknowledgmentsByTransport(ITransport transport, TLVector ids) + { + PrintCaption("msgs_ack"); + TLUtils.WriteLine("ids"); + foreach (var id in ids) + { + TLUtils.WriteLine(TLUtils.MessageIdString(id)); + } + var obj = new TLMessageAcknowledgments { MsgIds = ids }; + + var authKey = transport.AuthKey; + var sesseionId = transport.SessionId; + var salt = transport.Salt; + + int sequenceNumber; + TLLong messageId; + lock (transport.SyncRoot) + { + sequenceNumber = transport.SequenceNumber * 2; + messageId = transport.GenerateMessageId(true); + } + var transportMessage = CreateTLTransportMessage(salt, sesseionId, new TLInt(sequenceNumber), messageId, obj); + var encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + + lock (transport.SyncRoot) + { + if (transport.Closed) + { + transport = GetTransport(transport.Host, transport.Port, Type, + new TransportSettings + { + DcId = transport.DCId, + Secret = transport.Secret, + AuthKey = transport.AuthKey, + Salt = transport.Salt, + SessionId = transport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = transport.SequenceNumber, + ClientTicksDelta = transport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }); + } + } + + lock (_debugRoot) + { + //Debug.WriteLine(">>{0, -30} MsgId {1} SeqNo {2, -4} SessionId {3}\nids:", "msgs_ack", transportMessage.MessageId.Value, transportMessage.SeqNo.Value, transportMessage.SessionId.Value); + foreach (var id in ids) + { + Debug.WriteLine(id.Value); + } + } + + var captionString = string.Format("msgs_ack {0}", transportMessage.MessageId); + SendPacketAsync(transport, captionString, encryptedMessage, + result => + { + //Debug.WriteLine("@msgs_ack {0} result {1}", transportMessage.MessageId, result); + //ReceiveBytesAsync(result, authKey); + }, + error => + { + //Debug.WriteLine("< History); +#endif + + var saveConfig = false; + lock (transport.SyncRoot) + { + var serverTime = message.MessageId.Value; + var clientTime = transport.GenerateMessageId().Value; + + var serverDateTime = Utils.UnixTimestampToDateTime(serverTime >> 32); + var clientDateTime = Utils.UnixTimestampToDateTime(clientTime >> 32); + + errorInfo.AppendLine("Server time: " + serverDateTime); + errorInfo.AppendLine("Client time: " + clientDateTime); + + if (historyItem.ClientTicksDelta == transport.ClientTicksDelta) + { + transport.ClientTicksDelta += serverTime - clientTime; + saveConfig = true; + errorInfo.AppendLine("Set ticks delta: " + transport.ClientTicksDelta + "(" + (serverDateTime - clientDateTime).TotalSeconds + " seconds)"); + } + } + + if (saveConfig && _config != null) + { + var dcOption = _config.DCOptions.FirstOrDefault(x => string.Equals(x.IpAddress.ToString(), transport.Host, StringComparison.OrdinalIgnoreCase)); + if (dcOption != null) + { + dcOption.ClientTicksDelta = transport.ClientTicksDelta; + _cacheService.SetConfig(_config); + } + } + + TLUtils.WriteLine(errorInfo.ToString(), LogSeverity.Error); + + + // TODO: replace with SendInformativeMessage + var transportMessage = (TLContainerTransportMessage)historyItem.Message; + int sequenceNumber; + lock (transport.SyncRoot) + { + if (transportMessage.SeqNo.Value % 2 == 0) + { + sequenceNumber = 2 * transport.SequenceNumber; + } + else + { + sequenceNumber = 2 * transport.SequenceNumber + 1; + transport.SequenceNumber++; + } + + transportMessage.SeqNo = new TLInt(sequenceNumber); + transportMessage.MessageId = transport.GenerateMessageId(true); + } + TLUtils.WriteLine("Corrected client time: " + TLUtils.MessageIdString(transportMessage.MessageId)); + var authKey = transport.AuthKey; + var encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + + lock (_historyRoot) + { + _history[historyItem.Hash] = historyItem; + } + + var faultCallback = historyItem.FaultCallback; + + lock (transport.SyncRoot) + { + if (transport.Closed) + { + var transportSettings = new TransportSettings + { + DcId = transport.DCId, + Secret = transport.Secret, + AuthKey = transport.AuthKey, + Salt = transport.Salt, + SessionId = transport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = transport.SequenceNumber, + ClientTicksDelta = transport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }; + + transport = transport.MTProtoType == MTProtoTransportType.Special + ? GetSpecialTransport(transport.Host, transport.Port, Type, transportSettings) + : GetFileTransport(transport.Host, transport.Port, Type, transportSettings); + } + } + //Debug.WriteLine(">>{0, -30} MsgId {1} SeqNo {2,-4} SessionId {3} BadMsgId {4}", string.Format("{0}: {1}", historyItem.Caption, "time"), transportMessage.MessageId.Value, transportMessage.SeqNo.Value, message.SessionId.Value, badMessage.BadMessageId.Value); + var captionString = string.Format("{0} {1} {2}", historyItem.Caption, message.SessionId, transportMessage.MessageId); + SendPacketAsync(transport, captionString, + encryptedMessage, + result => + { + Debug.WriteLine("@{0} {1} result {2}", string.Format("{0}: {1}", historyItem.Caption, "time"), transportMessage.MessageId.Value, result); + + },//ReceiveBytesAsync(result, authKey), + error => + { + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404) }); + }); + + //_activeTransport.SendPacketAsync(historyItem.Caption + " " + transportMessage.MessageId, + // encryptedMessage.ToBytes(), result => ReceiveBytesAsync(result, authKey), + // () => { if (faultCallback != null) faultCallback(null); }); + + break; + + case 32: + case 33: + TLUtils.WriteLine(string.Format("ErrorCode={0} INCORRECT MSGSEQNO BY TRANSPORT TO DCID={2}, CREATE NEW SESSION {1}", badMessage.ErrorCode.Value, historyItem.Caption, transport.DCId), LogSeverity.Error); + Execute.ShowDebugMessage(string.Format("ErrorCode={0} INCORRECT MSGSEQNO BY TRANSPORT TO DCID={2}, CREATE NEW SESSION {1}", badMessage.ErrorCode.Value, historyItem.Caption, transport.DCId)); + + var previousMessageId = historyItem.Hash; + + // fix seqNo with creating new Session + lock (transport.SyncRoot) + { + transport.SessionId = TLLong.Random(); + transport.SequenceNumber = 0; + transportMessage = (TLTransportMessage)historyItem.Message; + if (transportMessage.SeqNo.Value % 2 == 0) + { + sequenceNumber = 2 * transport.SequenceNumber; + } + else + { + sequenceNumber = 2 * transport.SequenceNumber + 1; + transport.SequenceNumber++; + } + + transportMessage.SeqNo = new TLInt(sequenceNumber); + transportMessage.MessageId = transport.GenerateMessageId(true); + } + ((TLTransportMessage)transportMessage).SessionId = transport.SessionId; + + + // TODO: replace with SendInformativeMessage + TLUtils.WriteLine("Corrected client time: " + TLUtils.MessageIdString(transportMessage.MessageId)); + authKey = transport.AuthKey; + encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + + lock (_historyRoot) + { + _history.Remove(previousMessageId); + _history[historyItem.Hash] = historyItem; + } + + faultCallback = historyItem.FaultCallback; + + lock (transport.SyncRoot) + { + if (transport.Closed) + { + var transportSettings = new TransportSettings + { + DcId = transport.DCId, + Secret = transport.Secret, + AuthKey = transport.AuthKey, + Salt = transport.Salt, + SessionId = transport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = transport.SequenceNumber, + ClientTicksDelta = transport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }; + + transport = transport.MTProtoType == MTProtoTransportType.Special + ? GetSpecialTransport(transport.Host, transport.Port, Type, transportSettings) + : GetFileTransport(transport.Host, transport.Port, Type, transportSettings); + } + } + //Debug.WriteLine(">>{0, -30} MsgId {1} SeqNo {2,-4} SessionId {3} BadMsgId {4}", string.Format("{0}: {1}", historyItem.Caption, "seqNo"), transportMessage.MessageId.Value, transportMessage.SeqNo.Value, message.SessionId.Value, badMessage.BadMessageId.Value); + captionString = string.Format("{0} {1} {2}", historyItem.Caption, message.SessionId, transportMessage.MessageId); + SendPacketAsync(transport, captionString, + encryptedMessage, + result => + { + Debug.WriteLine("@{0} {1} result {2}", string.Format("{0}: {1}", historyItem.Caption, "seqNo"), transportMessage.MessageId.Value, result); + + },//ReceiveBytesAsync(result, authKey)}, + error => { if (faultCallback != null) faultCallback(null); }); + + break; + } + } + + private void ProcessBadServerSaltByTransport(ITransport transport, TLTransportMessage message, TLBadServerSalt badServerSalt, HistoryItem historyItem) + { + if (historyItem == null) + { + return; + } + + var transportMessage = (TLContainerTransportMessage)historyItem.Message; + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + + TLUtils.WriteLine("CORRECT SERVER SALT:"); + ((TLTransportMessage)transportMessage).Salt = badServerSalt.NewServerSalt; + //Salt = badServerSalt.NewServerSalt; + TLUtils.WriteLine("New salt: " + transport.Salt); + + switch (badServerSalt.ErrorCode.Value) + { + case 16: + case 17: + TLUtils.WriteLine("1. CORRECT TIME DELTA with salt by transport " + transport.DCId); + + var saveConfig = false; + long serverTime; + long clientTime; + lock (transport.SyncRoot) + { + serverTime = message.MessageId.Value; + clientTime = transport.GenerateMessageId().Value; + + TLUtils.WriteLine("Server time: " + TLUtils.MessageIdString(BitConverter.GetBytes(serverTime))); + TLUtils.WriteLine("Client time: " + TLUtils.MessageIdString(BitConverter.GetBytes(clientTime))); + + if (historyItem.ClientTicksDelta == transport.ClientTicksDelta) + { + saveConfig = true; + transport.ClientTicksDelta += serverTime - clientTime; + } + + transportMessage.MessageId = transport.GenerateMessageId(true); + TLUtils.WriteLine("Corrected client time: " + TLUtils.MessageIdString(transportMessage.MessageId)); + } + + if (saveConfig && _config != null) + { + var dcOption = _config.DCOptions.FirstOrDefault(x => string.Equals(x.IpAddress.ToString(), transport.Host, StringComparison.OrdinalIgnoreCase)); + if (dcOption != null) + { + dcOption.ClientTicksDelta += serverTime - clientTime; + _cacheService.SetConfig(_config); + } + } + + break; + case 48: + break; + } + + if (transportMessage == null) return; + + var authKey = transport.AuthKey; + var encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + lock (_historyRoot) + { + _history[historyItem.Hash] = historyItem; + } + var faultCallback = historyItem.FaultCallback; + + lock (transport.SyncRoot) + { + if (transport.Closed) + { + transport = GetTransport(transport.Host, transport.Port, Type, + new TransportSettings + { + DcId = transport.DCId, + Secret = transport.Secret, + AuthKey = transport.AuthKey, + Salt = transport.Salt, + SessionId = transport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = transport.SequenceNumber, + ClientTicksDelta = transport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }); + } + } + + var captionString = string.Format("{0} {1}", historyItem.Caption, transportMessage.MessageId); + SendPacketAsync(transport, captionString, + encryptedMessage, + result => + { + Debug.WriteLine("@{0} {1} result {2}", historyItem.Caption, transportMessage.MessageId.Value, result); + + },//ReceiveBytesAsync(result, authKey)}, + error => { if (faultCallback != null) faultCallback(new TLRPCError { Code = new TLInt(404), Message = new TLString("TCPTransport error") }); }); + } + + private void ProcessRPCErrorByTransport(ITransport transport, TLRPCError error, HistoryItem historyItem, long keyId) + { + if (error.CodeEquals(ErrorCode.UNAUTHORIZED)) + { + Execute.ShowDebugMessage(string.Format("RPCError ByTransport {2} {0} {1}", historyItem.Caption, error, transport.DCId)); + + if (historyItem != null + && historyItem.Caption != "account.updateStatus" + && historyItem.Caption != "account.registerDevice" + && historyItem.Caption != "auth.signIn") + { + if (error.TypeEquals(ErrorType.SESSION_REVOKED)) + { + + } + else + { + // Note! no reauthorization by transport to additional dc + //RaiseAuthorizationRequired(new AuthorizationRequiredEventArgs{MethodName = "ByTransport " + transport.DCId + " " + historyItem.Caption, Error = error, AuthKeyId = keyId}); + historyItem.FaultCallback.SafeInvoke(error); + } + } + else if (historyItem != null && historyItem.FaultCallback != null) + { + historyItem.FaultCallback(error); + } + } + else if (error.CodeEquals(ErrorCode.ERROR_SEE_OTHER) + && (error.TypeStarsWith(ErrorType.NETWORK_MIGRATE) + || error.TypeStarsWith(ErrorType.PHONE_MIGRATE) + //|| error.TypeStarsWith(ErrorType.FILE_MIGRATE) + )) + { + var serverNumber = Convert.ToInt32( + error.GetErrorTypeString() + .Replace(ErrorType.NETWORK_MIGRATE.ToString(), string.Empty) + .Replace(ErrorType.PHONE_MIGRATE.ToString(), string.Empty) + //.Replace(ErrorType.FILE_MIGRATE.ToString(), string.Empty) + .Replace("_", string.Empty)); + + if (_config == null + || TLUtils.GetDCOption(_config, new TLInt(serverNumber)) == null) + { + GetConfigAsync(config => + { + _config = TLConfig.Merge(_config, config); + SaveConfig(); + if (historyItem.Object.GetType() == typeof(TLSendCode)) + { + var dcOption = TLUtils.GetDCOption(_config, new TLInt(serverNumber)); + + lock (transport.SyncRoot) + { + transport = GetTransport(dcOption.IpAddress.ToString(), dcOption.Port.Value, Type, + new TransportSettings + { + DcId = dcOption.Id.Value, + AuthKey = dcOption.AuthKey, + Secret = TLUtils.ParseSecret(dcOption), + Salt = dcOption.Salt, + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = dcOption.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }); + } + lock (transport.SyncRoot) + { + transport.Initialized = false; + } + InitTransportAsync(transport, tuple => + { + lock (transport.SyncRoot) + { + transport.DCId = serverNumber; + transport.AuthKey = tuple.Item1; + transport.Salt = tuple.Item2; + transport.SessionId = tuple.Item3; + } + var authKeyId = TLUtils.GenerateLongAuthKeyId(tuple.Item1); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = tuple.Item1, AutkKeyId = authKeyId }); + } + } + + dcOption.AuthKey = tuple.Item1; + dcOption.Salt = tuple.Item2; + dcOption.SessionId = tuple.Item3; + + _config.ActiveDCOptionIndex = _config.DCOptions.IndexOf(dcOption); + _cacheService.SetConfig(_config); + + lock (transport.SyncRoot) + { + transport.Initialized = true; + } + RaiseInitialized(); + + SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback); + }, + er => + { + lock (transport.SyncRoot) + { + transport.Initialized = false; + } + historyItem.FaultCallback.SafeInvoke(er); + }); + } + else + { + MigrateAsync(serverNumber, auth => SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback)); + } + }); + + } + else + { + if (historyItem.Object.GetType() == typeof(TLSendCode) + || historyItem.Object.GetType() == typeof(TLGetFile)) + { + var activeDCOption = TLUtils.GetDCOption(_config, new TLInt(serverNumber)); + + lock (transport.SyncRoot) + { + transport = GetTransport(activeDCOption.IpAddress.ToString(), activeDCOption.Port.Value, Type, + new TransportSettings + { + DcId = activeDCOption.Id.Value, + Secret = TLUtils.ParseSecret(activeDCOption), + AuthKey = activeDCOption.AuthKey, + Salt = activeDCOption.Salt, + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = activeDCOption.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }); + } + + if (activeDCOption.AuthKey == null) + { + lock (transport.SyncRoot) + { + transport.Initialized = false; + } + InitTransportAsync(transport, tuple => + { + lock (transport.SyncRoot) + { + transport.DCId = serverNumber; + transport.AuthKey = tuple.Item1; + transport.Salt = tuple.Item2; + transport.SessionId = tuple.Item3; + } + + var authKeyId = TLUtils.GenerateLongAuthKeyId(tuple.Item1); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = tuple.Item1, AutkKeyId = authKeyId }); + } + } + + activeDCOption.AuthKey = tuple.Item1; + activeDCOption.Salt = tuple.Item2; + activeDCOption.SessionId = tuple.Item3; + + _config.ActiveDCOptionIndex = _config.DCOptions.IndexOf(activeDCOption); + _cacheService.SetConfig(_config); + + lock (transport.SyncRoot) + { + transport.Initialized = true; + } + + RaiseInitialized(); + SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback); + }, + er => + { + lock (transport.SyncRoot) + { + transport.Initialized = false; + } + historyItem.FaultCallback.SafeInvoke(er); + }); + } + else + { + lock (transport.SyncRoot) + { + transport.AuthKey = activeDCOption.AuthKey; + transport.Salt = activeDCOption.Salt; + transport.SessionId = TLLong.Random(); + } + var authKeyId = TLUtils.GenerateLongAuthKeyId(activeDCOption.AuthKey); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = activeDCOption.AuthKey, AutkKeyId = authKeyId }); + } + } + + + _config.ActiveDCOptionIndex = _config.DCOptions.IndexOf(activeDCOption); + _cacheService.SetConfig(_config); + + lock (transport.SyncRoot) + { + transport.Initialized = true; + } + RaiseInitialized(); + + SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback); + } + } + else + { + MigrateAsync(serverNumber, auth => SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback)); + } + } + } + else if (historyItem.FaultCallback != null) + { + historyItem.FaultCallback(error); + } + } + + private void OnPacketReceivedByTransport(object sender, DataEventArgs e) + { + var transport = (ITransport)sender; + bool isInitialized; + lock (transport.SyncRoot) + { + isInitialized = transport.AuthKey != null; + } + + var position = 0; + var handled = false; + + if (!isInitialized) + { + try + { + var message = TLObject.GetObject(e.Data, ref position); + + var item = transport.DequeueFirstNonEncryptedItem(); + if (item != null) + { +#if LOG_REGISTRATION + TLUtils.WriteLog("OnReceivedBytes !IsInitialized try historyItem " + item.Caption); +#endif + item.Callback.SafeInvoke(message.Data); + } + else + { +#if LOG_REGISTRATION + TLUtils.WriteLog("OnReceivedBytes !IsInitialized cannot try historyItem "); +#endif + } + + handled = true; + } + catch (Exception ex) + { +#if LOG_REGISTRATION + + var sb = new StringBuilder(); + sb.AppendLine("OnPacketReceived !IsInitialized catch Exception: \n" + ex); + sb.AppendLine(transport.PrintNonEncryptedHistory()); + TLUtils.WriteLog(sb.ToString()); +#endif + } + + if (!handled) + { +#if LOG_REGISTRATION + TLUtils.WriteLog("OnPacketReceived !IsInitialized !handled invoke ReceiveBytesAsync"); +#endif + ReceiveBytesByTransportAsync(transport, e.Data); + } + } + else + { +#if LOG_REGISTRATION + TLUtils.WriteLog("OnPacketReceived IsInitialized invoke ReceiveBytesAsync"); +#endif + ReceiveBytesByTransportAsync(transport, e.Data); + } + } + + private void DisableMTProtoProxy() + { + var proxyConfig = _transportService.GetProxyConfig(); + if (proxyConfig != null && !proxyConfig.IsEmpty && !proxyConfig.IsEnabled.Value) + { + var mtProtoProxy = proxyConfig.GetProxy() as TLMTProtoProxy; + if (mtProtoProxy != null) + { + proxyConfig.IsEnabled = TLBool.False; + _transportService.SetProxyConfig(proxyConfig); + + var instance = TelegramEventAggregator.Instance; + if (instance != null) + { + instance.Publish(new MTProtoProxyDisabledEventArgs()); + } + } + } + } + + private void ReceiveBytesByTransportAsync(ITransport transport, byte[] bytes) + { + try + { + if (bytes.Length == 4) + { + var error = BitConverter.ToInt32(bytes, 0); + if (error == -404 || error == -444) + { + if (error == -444) + { + DisableMTProtoProxy(); + + RaiseProxyDisabled(); + } + + var message = string.Format("ByTransport dc_id={0} error={1}", transport.DCId, error); + TLUtils.WriteException(new Exception(message)); + + ResetConnectionByTransport(transport, new Exception(message)); + return; + } + } + + var position = 0; + var encryptedMessage = (TLEncryptedTransportMessage)new TLEncryptedTransportMessage().FromBytes(bytes, ref position); + + encryptedMessage.Decrypt(transport.AuthKey); + + if (encryptedMessage.Data == null) + { + var message = string.Format("ByTransport msgKey mismatch transport_dc_id={0}", transport.DCId); + + TLUtils.WriteException(new Exception(message)); + } + + if (encryptedMessage.Data.Length < 32) + { + var message = string.Format("ByTransport padding extension data={0} < 32 transport_dc_id={1}", encryptedMessage.Data.Length, transport.DCId); + + TLUtils.WriteException(new Exception(message)); + } + var messageDataLength = BitConverter.ToInt32(encryptedMessage.Data, 28); + if (messageDataLength < 0 || messageDataLength % 4 != 0) + { + var message = string.Format("ByTransport incorrect length data={0} length={1} transport_dc_id={2}", encryptedMessage.Data.Length, messageDataLength, transport.DCId); + + TLUtils.WriteException(new Exception(message)); + } + + if (32 + messageDataLength > encryptedMessage.Data.Length) + { + var message = string.Format("ByTransport padding extension data={0} length={1} transport_dc_id={2}", encryptedMessage.Data.Length, messageDataLength, transport.DCId); + + TLUtils.WriteException(new Exception(message)); + } + + position = 0; + var transportMessage = TLObject.GetObject(encryptedMessage.Data, ref position); + +#if MTPROTO + if (encryptedMessage.Data.Length - position < 12 + || encryptedMessage.Data.Length - position > 1024) + { + var message = string.Format("ByTransport padding extension data={0} position={1} object={2} transport_dc_id={3}", encryptedMessage.Data.Length, position, transportMessage.MessageData, transport.DCId); + TLUtils.WriteException(new Exception(message)); + } +#else + if ((encryptedMessage.Data.Length - position) > 15) + { + var message = string.Format("ByTransport padding extension data={0} position={1} object={2}", encryptedMessage.Data.Length, position, transportMessage.MessageData, transport.DCId); + TLUtils.WriteException(new Exception(message)); + } +#endif + + if (transportMessage.SessionId.Value != transport.SessionId.Value) + { + var message = string.Format("ByTransport session_id={0} is not equal to transport.session_id={1} transport_dc_id={2}", transportMessage.SessionId, transport.SessionId, transport.DCId); + TLUtils.WriteException(new Exception(message)); + } + + if (transport.MinMessageId != 0) + { + if (transport.MinMessageId > transportMessage.MessageId.Value) + { + var message = string.Format("ByTransport message_id={0} seq_no={1} is higher than transport.min_message_id={2} transport_dc_id={3}", transportMessage.MessageId, transportMessage.SeqNo, transport.MinMessageId, transport.DCId); + TLUtils.WriteException(new Exception(message)); + } + } + + if (transport.MessageIdDict.ContainsKey(transportMessage.MessageId.Value)) + { + var message = string.Format("ByTransport message_id={0} seq_no={1} already exists transport_dc_id={2}", transportMessage.MessageId, transportMessage.SeqNo, transport.MinMessageId); + TLUtils.WriteException(new Exception(message)); + } + + lock (transport.SyncRoot) + { + transport.MessageIdDict[transportMessage.MessageId.Value] = transportMessage.MessageId.Value; + } + + if ((transportMessage.MessageId.Value % 2) == 0) + { + TLUtils.WriteException(new Exception(string.Format("ByTransport incorrect message_id transport_dc_id={0}", transport.MinMessageId))); + } + + // get acknowledgments + foreach (var acknowledgment in TLUtils.FindInnerObjects(transportMessage)) + { + var ids = acknowledgment.MessageIds.Items; + lock (_historyRoot) + { + foreach (var id in ids) + { + if (_history.ContainsKey(id.Value)) + { + _history[id.Value].Status = RequestStatus.Confirmed; + } + } + } + + } + + // send acknowledgments + SendAcknowledgmentsByTransport(transport, transportMessage); + + // updates + _updatesService.ProcessTransportMessage(transportMessage); + + // bad messages + foreach (var badMessage in TLUtils.FindInnerObjects(transportMessage)) + { + + HistoryItem item = null; + lock (_historyRoot) + { + if (_history.ContainsKey(badMessage.BadMessageId.Value)) + { + item = _history[badMessage.BadMessageId.Value]; + } + } + Logs.Log.Write(string.Format("{0} {1} transport={2}", badMessage, item, transport.DCId)); + + ProcessBadMessageByTransport(transport, transportMessage, badMessage, item); + } + + // bad server salts + foreach (var badServerSalt in TLUtils.FindInnerObjects(transportMessage)) + { + + lock (transport.SyncRoot) + { + transport.Salt = badServerSalt.NewServerSalt; + } + HistoryItem item = null; + lock (_historyRoot) + { + if (_history.ContainsKey(badServerSalt.BadMessageId.Value)) + { + item = _history[badServerSalt.BadMessageId.Value]; + } + } + Logs.Log.Write(string.Format("{0} {1} transport={2}", badServerSalt, item, transport.DCId)); + + ProcessBadServerSaltByTransport(transport, transportMessage, badServerSalt, item); + } + + // new session created + foreach (var newSessionCreated in TLUtils.FindInnerObjects(transportMessage)) + { + TLUtils.WritePerformance(string.Format("NEW SESSION CREATED: {0} (old {1})", transportMessage.SessionId, _activeTransport.SessionId)); + lock (transport.SyncRoot) + { + transport.SessionId = transportMessage.SessionId; + transport.Salt = newSessionCreated.ServerSalt; + } + } + + foreach (var pong in TLUtils.FindInnerObjects(transportMessage)) + { + HistoryItem item; + lock (_historyRoot) + { + if (_history.ContainsKey(pong.MessageId.Value)) + { + item = _history[pong.MessageId.Value]; + _history.Remove(pong.MessageId.Value); + } + else + { + //Execute.ShowDebugMessage("TLPong lost item id=" + pong.MessageId); + continue; + } + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + + if (item != null) + { + item.Callback.SafeInvoke(pong); + } + } + + // rpcresults + foreach (var result in TLUtils.FindInnerObjects(transportMessage)) + { + HistoryItem historyItem = null; + + lock (_historyRoot) + { + if (_history.ContainsKey(result.RequestMessageId.Value)) + { + historyItem = _history[result.RequestMessageId.Value]; + _history.Remove(result.RequestMessageId.Value); + } + else + { + continue; + } + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + + //RemoveItemFromSendingQueue(result.RequestMessageId.Value); + + var error = result.Object as TLRPCError; + if (error != null) + { + Debug.WriteLine("RPCError: " + error.Code + " " + error.Message + " MsgId " + result.RequestMessageId.Value); + TLUtils.WriteLine("RPCError: " + error.Code + " " + error.Message); + + string errorString; + var reqError = error as TLRPCReqError; + if (reqError != null) + { + errorString = string.Format("RPCReqError {1} {2} (query_id={0}) transport=[dc_id={3}]", reqError.QueryId, reqError.Code, reqError.Message, transport.DCId); + } + else + { + errorString = string.Format("RPCError {0} {1} transport=[dc_id={2}]", error.Code, error.Message, transport.DCId); + } + + Execute.ShowDebugMessage(historyItem + Environment.NewLine + errorString); + ProcessRPCErrorByTransport(transport, error, historyItem, encryptedMessage.AuthKeyId.Value); + Debug.WriteLine(errorString + " msg_id=" + result.RequestMessageId.Value); + TLUtils.WriteLine(errorString); + } + else + { + var messageData = result.Object; + if (messageData is TLGzipPacked) + { + messageData = ((TLGzipPacked)messageData).Data; + } + + if (messageData is TLSentMessageBase + || messageData is TLStatedMessageBase + || messageData is TLUpdatesBase + || messageData is TLSentEncryptedMessage + || messageData is TLSentEncryptedFile + || messageData is TLAffectedHistory + || messageData is TLAffectedMessages + || historyItem.Object is TLReadChannelHistory + || historyItem.Object is TLReadEncryptedHistory) + { + RemoveFromQueue(historyItem); + } + + try + { + historyItem.Callback(messageData); + } + catch (Exception e) + { +#if LOG_REGISTRATION + TLUtils.WriteLog(e.ToString()); +#endif + TLUtils.WriteException(e); + } + } + } + } + catch (Exception e) + { + TLUtils.WriteException("ReceiveBytesByTransportAsync", e); + + ResetConnectionByTransport(transport, e); + } + } + + public void ClearHistoryByTransport(ITransport transport) + { + _transportService.CloseTransport(transport); + + lock (_historyRoot) + { + var keysToRemove = new List(); + foreach (var keyValue in _history) + { + if (keyValue.Value.Caption.StartsWith("msgs_ack")) + { + TLUtils.WriteLine("!!!!!!MSGS_ACK FAULT!!!!!!!", LogSeverity.Error); + Debug.WriteLine("!!!!!!MSGS_ACK FAULT!!!!!!!"); + } + if (transport.DCId == keyValue.Value.DCId) + { + keyValue.Value.FaultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("Clear History") }); + keysToRemove.Add(keyValue.Key); + } + } + foreach (var key in keysToRemove) + { + _history.Remove(key); + } + } + + transport.ClearNonEncryptedHistory(); + } + } + + public class MTProtoProxyDisabledEventArgs + { + + } +} diff --git a/Telegram.Api/Services/MTProtoService.Channel.cs b/Telegram.Api/Services/MTProtoService.Channel.cs new file mode 100755 index 0000000..dcb8716 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Channel.cs @@ -0,0 +1,680 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Channels; +using Telegram.Api.TL.Functions.Updates; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void ReadFeedAsync(TLInt feedId, TLFeedPosition maxPosition, Action callback, Action faultCallback = null) + { + var obj = new TLReadFeed { FeedId = feedId, MaxPosition = maxPosition }; + + const string caption = "channels.readFeed"; + SendInformativeMessage(caption, obj, + result => + { + callback(result); + }, + faultCallback); + } + + public void GetFeedAsync(bool offsetToMaxReed, TLInt feedId, TLFeedPosition offsetPosition, TLInt addOffset, TLInt limit, TLFeedPosition maxPosition, TLFeedPosition minPosition, TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetFeed { Flags = new TLInt(0), OffsetToMaxRead = offsetToMaxReed, FeedId = feedId, OffsetPosition = offsetPosition, AddOffset = addOffset, Limit = limit, MaxPosition = maxPosition, MinPosition = minPosition, Hash = hash }; + + const string caption = "channels.getFeed"; + SendInformativeMessage(caption, obj, + result => + { + callback(result); + }, + faultCallback); + } + + public void SetFeedBroadcastsAsync(TLInt feedId, TLVector channels, TLBool alsoNewlyJoined, Action callback, Action faultCallback = null) + { + var obj = new TLSetFeedBroadcasts { FeedId = feedId, Channels = channels, AlsoNewlyJoined = alsoNewlyJoined }; + + const string caption = "channels.setFeedBroadcasts"; + SendInformativeMessage(caption, obj, + result => + { + callback(result); + }, + faultCallback); + } + + public void ChangeFeedBroadcastAsync(TLInputChannelBase channel, TLInt feedId, Action callback, Action faultCallback = null) + { + var obj = new TLChangeFeedBroadcast { Flags = new TLInt(0), Channel = channel, FeedId = feedId }; + + const string caption = "channels.changeFeedBroadcast"; + SendInformativeMessage(caption, obj, + result => + { + callback(result); + }, + faultCallback); + } + + public void DeleteHistoryAsync(TLInputChannelBase channel, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteHistory { Channel = channel, MaxId = new TLInt(int.MaxValue) }; + + const string caption = "channels.deleteHistory"; + SendInformativeMessage(caption, obj, + result => + { + callback(result); + }, + faultCallback); + } + + public void TogglePreHistoryHiddenAsync(TLInputChannelBase channel, TLBool enabled, Action callback, Action faultCallback = null) + { + var obj = new TLTogglePreHistoryHidden { Channel = channel, Enabled = enabled }; + + const string caption = "channels.togglePreHistoryHidden"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void SetStickersAsync(TLInputChannelBase channel, TLInputStickerSetBase stickerset, Action callback, Action faultCallback = null) + { + var obj = new TLSetStickers { Channel = channel, StickerSet = stickerset }; + + SendInformativeMessage("channels.setStickers", obj, callback.SafeInvoke, faultCallback); + } + + public void ReadMessageContentsAsync(TLInputChannelBase channel, TLVector id, Action callback, Action faultCallback = null) + { + var obj = new TLReadMessageContents { Channel = channel, Id = id }; + + const string caption = "channels.readMessageContents"; + ReadMessageContentsAsyncInternal(obj, + result => + { + callback.SafeInvoke(result); + }, + () => { }, + faultCallback.SafeInvoke); + } + + public void GetAdminedPublicChannelsAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetAdminedPublicChannels(); + + SendInformativeMessage("updates.getAdminedPublicChannels", obj, + result => + { + var chats = result as TLChats24; + if (chats != null) + { + _cacheService.SyncUsersAndChats(new TLVector(), chats.Chats, tuple => callback.SafeInvoke(result)); + } + }, + faultCallback); + } + + public void GetChannelDifferenceAsync(bool force, TLInputChannelBase inputChannel, TLChannelMessagesFilerBase filter, TLInt pts, TLInt limit, Action callback, Action faultCallback = null) + { + var obj = new TLGetChannelDifference { Flags = new TLInt(0), Channel = inputChannel, Filter = filter, Pts = pts, Limit = limit }; + + if (force) + { + obj.SetForce(); + } + + SendInformativeMessage("updates.getChannelDifference", obj, callback, faultCallback); + } + + public void GetMessagesAsync(TLInputChannelBase inputChannel, TLVector id, Action callback, Action faultCallback = null) + { + var obj = new TLGetMessages { Channel = inputChannel, Id = id }; + + SendInformativeMessage("channels.getMessages", obj, callback, faultCallback); + } + + public void EditAdminAsync(TLChannel channel, TLInputUserBase userId, TLChannelAdminRights adminRights, Action callback, Action faultCallback = null) + { + var obj = new TLEditAdmin { Channel = channel.ToInputChannel(), UserId = userId, AdminRights = adminRights }; + + const string caption = "channels.editAdmin"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + GetFullChannelAsync(channel.ToInputChannel(), + messagesChatFull => callback.SafeInvoke(result), + faultCallback.SafeInvoke); + }, + faultCallback); + } + + + public void GetParticipantAsync(TLInputChannelBase inputChannel, TLInputUserBase userId, Action callback, Action faultCallback = null) + { + var obj = new TLGetParticipant { Channel = inputChannel, UserId = userId }; + + const string caption = "channels.getParticipant"; + SendInformativeMessage(caption, obj, result => + { + _cacheService.SyncUsers(result.Users, r => { }); + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void GetParticipantsAsync(TLInputChannelBase inputChannel, TLChannelParticipantsFilterBase filter, TLInt offset, TLInt limit, TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetParticipants { Channel = inputChannel, Filter = filter, Offset = offset, Limit = limit, Hash = hash }; + + const string caption = "channels.getParticipants"; + SendInformativeMessage(caption, obj, + result => + { + var channelParticipants = result as TLChannelParticipants; + if (channelParticipants != null) + { + for (var i = 0; i < channelParticipants.Users.Count; i++) + { + var cachedUser = _cacheService.GetUser(channelParticipants.Users[i].Id); + if (cachedUser != null) + { + cachedUser._status = channelParticipants.Users[i].Status; + channelParticipants.Users[i] = cachedUser; + } + } + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void EditTitleAsync(TLChannel channel, TLString title, Action callback, Action faultCallback = null) + { + var obj = new TLEditTitle { Channel = channel.ToInputChannel(), Title = title }; + + const string caption = "channels.editTitle"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void EditAboutAsync(TLChannel channel, TLString about, Action callback, Action faultCallback = null) + { + var obj = new TLEditAbout { Channel = channel.ToInputChannel(), About = about }; + + const string caption = "channels.editAbout"; + SendInformativeMessage(caption, obj, callback.SafeInvoke, faultCallback); + } + + public void JoinChannelAsync(TLChannel channel, Action callback, Action faultCallback = null) + { + var obj = new TLJoinChannel { Channel = channel.ToInputChannel() }; + + const string caption = "channels.joinChannel"; + SendInformativeMessage(caption, obj, + result => + { + channel.Left = TLBool.False; + if (channel.ParticipantsCount != null) + { + channel.ParticipantsCount = new TLInt(channel.ParticipantsCount.Value + 1); + } + _cacheService.Commit(); + + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void LeaveChannelAsync(TLChannel channel, Action callback, Action faultCallback = null) + { + var obj = new TLLeaveChannel { Channel = channel.ToInputChannel() }; + + const string caption = "channels.leaveChannel"; + SendInformativeMessage(caption, obj, + result => + { + channel.Left = TLBool.True; + if (channel.ParticipantsCount != null) + { + channel.ParticipantsCount = new TLInt(channel.ParticipantsCount.Value - 1); + } + _cacheService.Commit(); + + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void KickFromChannelAsync(TLChannel channel, TLInputUserBase userId, TLBool kicked, Action callback, Action faultCallback = null) + { + var obj = new TLKickFromChannel { Channel = channel.ToInputChannel(), UserId = userId, Kicked = kicked }; + + const string caption = "channels.kickFromChannel"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + GetFullChannelAsync(channel.ToInputChannel(), + messagesChatFull => callback.SafeInvoke(result), + faultCallback.SafeInvoke); + }, + faultCallback); + } + + public void DeleteChannelAsync(TLChannel channel, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteChannel { Channel = channel.ToInputChannel() }; + + const string caption = "channels.deleteChannel"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void InviteToChannelAsync(TLInputChannelBase channel, TLVector users, Action callback, Action faultCallback = null) + { + var obj = new TLInviteToChannel { Channel = channel, Users = users }; + + const string caption = "channels.inviteToChannel"; + SendInformativeMessage(caption, obj, + result => + { + + + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void DeleteMessagesAsync(TLInputChannelBase channel, TLVector id, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteChannelMessages { Channel = channel, Id = id }; + + const string caption = "channels.deleteMessages"; + SendInformativeMessage(caption, obj, + result => + { + //var multiPts = result as IMultiPts; + //if (multiPts != null) + //{ + // _updatesService.SetState(multiPts, caption); + //} + //else + //{ + // _updatesService.SetState(null, result.Pts, null, null, null, caption); + //} + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void UpdateChannelAsync(TLInt channelId, Action callback, Action faultCallback = null) + { + var channel = _cacheService.GetChat(channelId) as TL.Interfaces.IInputChannel; + if (channel != null) + { + GetFullChannelAsync(channel.ToInputChannel(), callback, faultCallback); + return; + } + } + + public void GetFullChannelAsync(TLInputChannelBase channel, Action callback, Action faultCallback = null) + { + var obj = new TLGetFullChannel { Channel = channel }; + + SendInformativeMessage( + "cnannels.getFullChannel", obj, + messagesChatFull => + { + _cacheService.SyncChat(messagesChatFull, result => callback.SafeInvoke(messagesChatFull)); + }, + faultCallback); + } + + public void GetImportantHistoryAsync(TLInputChannelBase channel, TLPeerBase peer, bool sync, TLInt offsetId, TLInt addOffset, TLInt limit, TLInt maxId, TLInt minId, Action callback, Action faultCallback = null) + { + var obj = new TLGetImportantHistory { Channel = channel, OffsetId = offsetId, OffsetDate = new TLInt(0), AddOffset = addOffset, Limit = limit, MaxId = maxId, MinId = minId }; + + SendInformativeMessage("channels.getImportantHistory", obj, callback, faultCallback); + } + + public void ReadHistoryAsync(TLChannel channel, TLInt maxId, Action callback, Action faultCallback = null) + { + var obj = new TLReadChannelHistory { Channel = channel.ToInputChannel(), MaxId = maxId }; + + ReadChannelHistoryAsyncInternal(obj, + result => + { + channel.ReadInboxMaxId = maxId; + + _cacheService.Commit(); + + callback.SafeInvoke(result); + }, + () => { }, + faultCallback.SafeInvoke); + } + + public void CreateChannelAsync(TLInt flags, TLString title, TLString about, Action callback, Action faultCallback = null) + { + var obj = new TLCreateChannel { Flags = flags, Title = title, About = about }; + + var caption = "channels.createChannel"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void ExportInviteAsync(TLInputChannelBase channel, Action callback, Action faultCallback = null) + { + var obj = new TLExportInvite { Channel = channel }; + + SendInformativeMessage("channels.exportInvite", obj, callback, faultCallback); + } + + public void CheckUsernameAsync(TLInputChannelBase channel, TLString username, Action callback, Action faultCallback = null) + { + var obj = new TLCheckUsername { Channel = channel, Username = username }; + + SendInformativeMessage("channels.checkUsername", obj, callback, faultCallback); + } + + public void UpdateUsernameAsync(TLInputChannelBase channel, TLString username, Action callback, Action faultCallback = null) + { + var obj = new TLUpdateUsername { Channel = channel, Username = username }; + + SendInformativeMessage("channels.updateUsername", obj, callback, faultCallback); + } + + public void EditPhotoAsync(TLChannel channel, TLInputChatPhotoBase photo, Action callback, Action faultCallback = null) + { + var obj = new TLEditPhoto { Channel = channel.ToInputChannel(), Photo = photo }; + + const string caption = "channels.editPhoto"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null, true); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void DeleteChannelMessagesAsync(TLInputChannelBase channel, TLVector id, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteChannelMessages { Channel = channel, Id = id }; + + SendInformativeMessage("channels.deleteMessages", obj, callback, faultCallback); + } + + public void ToggleInvitesAsync(TLInputChannelBase channel, TLBool enabled, Action callback, Action faultCallback = null) + { + var obj = new TLToggleInvites { Channel = channel, Enabled = enabled }; + + const string caption = "channels.toggleInvites"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void ExportMessageLinkAsync(TLInputChannelBase channel, TLInt id, Action callback, Action faultCallback = null) + { + var obj = new TLExportMessageLink { Channel = channel, Id = id }; + + SendInformativeMessage("channels.exportMessageLink", obj, callback, faultCallback); + } + + public void UpdatePinnedMessageAsync(bool silent, TLInputChannelBase channel, TLInt id, Action callback, Action faultCallback = null) + { + var obj = new TLUpdatePinnedMessage { Flags = new TLInt(0), Channel = channel, Id = id }; + if (silent) + { + obj.SetSilent(); + } + + const string caption = "channels.updatePinnedMessage"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void ToggleSignaturesAsync(TLInputChannelBase channel, TLBool enabled, Action callback, Action faultCallback = null) + { + var obj = new TLToggleSignatures { Channel = channel, Enabled = enabled }; + + const string caption = "channels.toggleSignatures"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void GetMessageEditDataAsync(TLInputPeerBase peer, TLInt id, Action callback, Action faultCallback = null) + { + var obj = new TLGetMessageEditData { Peer = peer, Id = id }; + + SendInformativeMessage("messages.getMessageEditData", obj, callback, faultCallback); + } + + public void EditMessageAsync(TLInputPeerBase peer, TLInt id, TLString message, TLVector entities, TLInputMediaBase media, TLReplyKeyboardBase replyMarkup, bool noWebPage, bool stopGeoLive, TLInputGeoPointBase geoPoint, Action callback, Action faultCallback = null) + { + var obj = new TLEditMessage { Flags = new TLInt(0), Peer = peer, Id = id, Message = message, NoWebPage = noWebPage, Entities = entities, Media = media, ReplyMarkup = replyMarkup, StopGeoLive = stopGeoLive, GeoPoint = geoPoint }; + + const string caption = "messages.editMessage"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null, true); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void ReportSpamAsync(TLInputChannelBase channel, TLInt userId, TLVector id, Action callback, Action faultCallback = null) + { + var obj = new TLReportSpam { Channel = channel, UserId = userId, Id = id }; + + const string caption = "channels.reportSpam"; + SendInformativeMessage(caption, obj, callback.SafeInvoke, faultCallback); + } + + public void DeleteUserHistoryAsync(TLChannel channel, TLInputUserBase userId, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteUserHistory { Channel = channel.ToInputChannel(), UserId = userId }; + + const string caption = "channels.deleteUserHistory"; + SendInformativeMessage(caption, obj, + result => + { + var multiChannelPts = result as IMultiChannelPts; + if (multiChannelPts != null) + { + if (channel.Pts == null + || channel.Pts.Value + multiChannelPts.ChannelPtsCount.Value != multiChannelPts.ChannelPts.Value) + { + Execute.ShowDebugMessage(string.Format("channel_id={0} channel_pts={1} affectedHistory24[channel_pts={2} channel_pts_count={3}]", channel.Id, channel.Pts, multiChannelPts.ChannelPts, multiChannelPts.ChannelPtsCount)); + } + channel.Pts = new TLInt(multiChannelPts.ChannelPts.Value); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Config.cs b/Telegram.Api/Services/MTProtoService.Config.cs new file mode 100755 index 0000000..f52b865 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Config.cs @@ -0,0 +1,346 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Telegram.Api.Extensions; +using Telegram.Api.Services.Connection; +using Telegram.Api.TL; +using Telegram.Api.Transport; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void SaveConfig() + { + _cacheService.SetConfig(_config); + } + + public TLConfig LoadConfig() + { + throw new NotImplementedException(); + } + +#if DEBUG + public void CheckPublicConfig() + { + OnCheckConfig(null, null); + } +#endif + + public void PingProxyAsync(TLProxyBase proxy, Action callback, Action faultCallback = null) + { + if (_activeTransport == null) + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("ActiveTransport is null") }); + return; + } + + var transport = GetSpecialTransportWithProxy(_activeTransport.Host, _activeTransport.Port, _activeTransport.Type, proxy, new TransportSettings + { + DcId = _activeTransport.DCId, + Secret = _activeTransport.Secret, + AuthKey = _activeTransport.AuthKey, + Salt = TLLong.Random(), + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = _activeTransport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }); + + if (transport.AuthKey == null) + { + InitTransportAsync(transport, + tuple => + { + lock (transport.SyncRoot) + { + transport.AuthKey = tuple.Item1; + transport.Salt = tuple.Item2; + transport.SessionId = tuple.Item3; + + transport.IsInitializing = false; + } + var authKeyId = TLUtils.GenerateLongAuthKeyId(tuple.Item1); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = tuple.Item1, AutkKeyId = authKeyId }); + } + } + + PingSpecialTransportAsync(transport, callback, faultCallback); + }, + error => + { + faultCallback.SafeInvoke(error); + }); + } + else + { + PingSpecialTransportAsync(transport, callback, faultCallback); + } + } + + private void PingSpecialTransportAsync(ITransport transport, Action callback, Action faultCallback = null) + { + // connect and ping + var stopwatch = Stopwatch.StartNew(); + PingByTransportAsync(transport, TLLong.Random(), + pong => + { + // ping and measure + var ping = transport.Ping > 0 ? transport.Ping : stopwatch.Elapsed.TotalMilliseconds; + _transportService.CloseSpecialTransport(transport); + callback.SafeInvoke(new TLInt((int)ping)); + }, + error => + { + _transportService.CloseSpecialTransport(transport); + faultCallback.SafeInvoke(error); + }); + } + + private readonly IPublicConfigService _publicConfigService; + + private static void LogPublicConfig(string str) + { + Logs.Log.Write(string.Format(" MTProtoService.CheckConfig {0}", str)); + Debug.WriteLine(" MTProtoService.CheckConfig {0}", str); + } + + private void PingAndUpdateTransportInfoAsync(TLDCOption78 dcOption, ITransport transport, Action callback, Action faultCallback = null) + { + LogPublicConfig(string.Format("Ping id={0} dc_id={1} ip={2} port={3} secret={4} proxy=[{5}]", transport.Id, transport.DCId, transport.Host, transport.Port, transport.Secret != null, transport.ProxyConfig)); + + PingByTransportAsync(transport, TLLong.Random(), + pong => + { + LogPublicConfig(string.Format("Ping completed id={0}", transport.Id)); + + LogPublicConfig("Close transport id=" + transport.Id); + _transportService.CloseSpecialTransport(transport); + + LogPublicConfig(string.Format("Update info dc_id={0} ip={1} port={2} secret={3}", transport.DCId, transport.Host, transport.Port, transport.Secret != null)); + UpdateTransportInfoAsync(dcOption, new TLString(transport.Host), new TLInt(transport.Port), + result => + { + LogPublicConfig("Update info completed"); + callback.SafeInvoke(); + }); + }, + error => + { + LogPublicConfig(string.Format("Ping error id={0} error={1}", transport.Id, error)); + _transportService.CloseSpecialTransport(transport); + faultCallback.SafeInvoke(error); + }); + } + + private void CheckAndUpdateTransportInfoInternalAsync(TLDCOption78 dcOption, ITransport transport, Action callback, Action faultCallback = null) + { + if (transport.AuthKey == null) + { + InitTransportAsync(transport, + tuple => + { + LogPublicConfig(string.Format("Init transport completed id={0}", transport.Id)); + lock (transport.SyncRoot) + { + transport.AuthKey = tuple.Item1; + transport.Salt = tuple.Item2; + transport.SessionId = tuple.Item3; + + transport.IsInitializing = false; + } + var authKeyId = TLUtils.GenerateLongAuthKeyId(tuple.Item1); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = tuple.Item1, AutkKeyId = authKeyId }); + } + } + + PingAndUpdateTransportInfoAsync(dcOption, transport, callback, faultCallback); + }, + error => + { + LogPublicConfig(string.Format("Init transport error id={0} error={1}", transport.Id, error)); + }); + } + else + { + PingAndUpdateTransportInfoAsync(dcOption, transport, callback, faultCallback); + } + } + + public void CheckAndUpdateTransportInfoAsync(TLInt dcId, TLString host, TLInt port, Action callback, Action faultCallback = null) + { + LogPublicConfig(string.Format("CheckTransport dc_id={0} host={1} port={2}", dcId, host, port)); + + if (dcId == null) return; + if (TLString.IsNullOrEmpty(host)) return; + if (port == null) return; + + var dcOption = TLUtils.GetDCOption(_config, dcId); + + var transport = GetSpecialTransport(host.ToString(), port.Value, Type, new TransportSettings + { + DcId = dcId.Value, + Secret = TLUtils.ParseSecret(dcOption), + AuthKey = dcOption != null ? dcOption.AuthKey : null, + Salt = dcOption != null ? dcOption.Salt : TLLong.Random(), + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = dcOption != null ? dcOption.ClientTicksDelta : 0, + PacketReceivedHandler = OnPacketReceivedByTransport + }); + + CheckAndUpdateTransportInfoInternalAsync(dcOption as TLDCOption78, transport, callback, faultCallback); + } + + private void OnCheckConfig(object sender, EventArgs e) + { + _publicConfigService.GetAsync( + configSimple => + { + if (configSimple != null) + { + var now = TLUtils.DateToUniversalTimeTLInt(ClientTicksDelta, DateTime.Now); + if (configSimple.Expires.Value < now.Value || now.Value < configSimple.Date.Value) + { + LogPublicConfig(string.Format("Config expired date={0} expires={1} now={2}", configSimple.Date, configSimple.Expires, now)); + return; + } + + var dcId = configSimple.DCId; + var ipPort = configSimple.IpPortList.FirstOrDefault(); + if (ipPort == null) + { + LogPublicConfig("ipPort is null"); + return; + } + + var dcOption = TLUtils.GetDCOption(_config, dcId); + + var transport = GetSpecialTransport(ipPort.GetIpString(), ipPort.Port.Value, Type, new TransportSettings + { + DcId = dcId.Value, + Secret = null, //ipPort.Secret + AuthKey = dcOption != null ? dcOption.AuthKey : null, + Salt = dcOption != null ? dcOption.Salt : TLLong.Random(), + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = dcOption != null ? dcOption.ClientTicksDelta : 0, + PacketReceivedHandler = OnPacketReceivedByTransport + }); + + if (transport.AuthKey == null) + { + LogPublicConfig(string.Format("Init transport id={0} dc_id={1} ip={2} port={3} proxy=[{4}]", transport.Id, transport.DCId, transport.Host, transport.Port, transport.ProxyConfig)); + InitTransportAsync(transport, + tuple => + { + LogPublicConfig(string.Format("Init transport completed id={0}", transport.Id)); + lock (transport.SyncRoot) + { + transport.AuthKey = tuple.Item1; + transport.Salt = tuple.Item2; + transport.SessionId = tuple.Item3; + + transport.IsInitializing = false; + } + var authKeyId = TLUtils.GenerateLongAuthKeyId(tuple.Item1); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = tuple.Item1, AutkKeyId = authKeyId }); + } + } + + CheckAndUpdateMainTransportAsync(transport); + }, + error => + { + LogPublicConfig(string.Format("Init transport error id={0} error={1}", transport.Id, error)); + }); + } + else + { + CheckAndUpdateMainTransportAsync(transport); + } + } + } + , + error => + { + LogPublicConfig(string.Format("PublicConfigService.GetAsync error {0}", error)); + }); + } + + private void CheckAndUpdateMainTransportAsync(ITransport transport) + { + LogPublicConfig(string.Format("Get config from id={0} dc_id={1} ip={2} port={3} proxy=[{4}]", transport.Id, transport.DCId, transport.Host, transport.Port, transport.ProxyConfig)); + GetConfigByTransportAsync(transport, + config => + { + LogPublicConfig(string.Format("Get config completed id={0}", transport.Id)); + + var dcId = new TLInt(_activeTransport.DCId); + var dcOption = TLUtils.GetDCOption(config, dcId) as TLDCOption78; + if (dcOption == null) + { + LogPublicConfig(string.Format("dcOption is null id={0}", transport.Id)); + return; + } + if (string.Equals(_activeTransport.Host, dcOption.IpAddress.ToString(), StringComparison.OrdinalIgnoreCase)) + { + LogPublicConfig(string.Format("dcOption ip equals ip={0}", dcOption.IpAddress.ToString())); + return; + } + LogPublicConfig("Close transport id=" + transport.Id); + _transportService.CloseSpecialTransport(transport); + + // replace main dc ip and port + transport = GetSpecialTransport(dcOption.IpAddress.ToString(), dcOption.Port.Value, Type, new TransportSettings + { + DcId = dcOption.Id.Value, + Secret = TLUtils.ParseSecret(dcOption), + AuthKey = _activeTransport.AuthKey, + Salt = _activeTransport.Salt, + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = _activeTransport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }); + + CheckAndUpdateTransportInfoInternalAsync(dcOption, transport, null); + // reconnect + }, + error2 => + { + LogPublicConfig(string.Format("Get config error id={0} error={1}", transport.Id, error2)); + + LogPublicConfig("Close transport id=" + transport.Id); + _transportService.CloseSpecialTransport(transport); + }); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Contacts.cs b/Telegram.Api/Services/MTProtoService.Contacts.cs new file mode 100755 index 0000000..634740f --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Contacts.cs @@ -0,0 +1,166 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Linq; +using Telegram.Api.Extensions; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Contacts; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void ResetSavedAsync(Action callback, Action faultCallback = null) + { + var obj = new TLResetSaved(); + + SendInformativeMessage("contacts.resetSaved", obj, callback.SafeInvoke, faultCallback); + } + + public void ResetTopPeerRatingAsync(TLTopPeerCategoryBase category, TLInputPeerBase peer, Action callback, Action faultCallback = null) + { + var obj = new TLResetTopPeerRating { Category = category, Peer = peer }; + + SendInformativeMessage("contacts.resetTopPeerRating", obj, callback.SafeInvoke, faultCallback); + } + + public void GetTopPeersAsync(GetTopPeersFlags flags, TLInt offset, TLInt limit, TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetTopPeers { Flags = new TLInt((int) flags), Offset = offset, Limit = limit, Hash = hash }; + + SendInformativeMessage("contacts.getTopPeers", obj, result => + { + var topPeers = result as TLTopPeers; + if (topPeers != null) + { + _cacheService.SyncUsersAndChats(topPeers.Users, topPeers.Chats, + tuple => + { + topPeers.Users = tuple.Item1; + topPeers.Chats = tuple.Item2; + callback.SafeInvoke(result); + }); + } + else + { + callback.SafeInvoke(result); + } + }, faultCallback); + } + + public void ResolveUsernameAsync(TLString username, Action callback, Action faultCallback = null) + { + var obj = new TLResolveUsername{ Username = username }; + + SendInformativeMessage("contacts.resolveUsername", obj, + result => + { + _cacheService.SyncUsersAndChats(result.Users, result.Chats, + tuple => + { + result.Users = tuple.Item1; + result.Chats = tuple.Item2; + callback.SafeInvoke(result); + }); + }, + faultCallback); + } + + public void GetStatusesAsync(Action> callback, Action faultCallback = null) + { + var obj = new TLGetStatuses(); + + SendInformativeMessage>("contacts.getStatuses", obj, + contacts => + { + _cacheService.SyncStatuses(contacts, callback); + }, + faultCallback); + } + + public void GetContactsAsync(TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetContacts { Hash = hash }; + + SendInformativeMessage("contacts.getContacts", obj, result => _cacheService.SyncContacts(result, callback), faultCallback); + } + + public void ImportContactsAsync(TLVector contacts, Action callback, Action faultCallback = null) + { + var obj = new TLImportContacts { Contacts = contacts }; + + SendInformativeMessage("contacts.importContacts", obj, result => _cacheService.SyncContacts(result, callback), faultCallback); + } + + public void DeleteContactAsync(TLInputUserBase id, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteContact { Id = id }; + + SendInformativeMessage("contacts.deleteContact", obj, result => _cacheService.SyncUserLink(result, callback), faultCallback); + } + + public void DeleteContactsAsync(TLVector id, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteContacts { Id = id }; + + SendInformativeMessage("contacts.deleteContacts", obj, + result => + { + foreach (var inputUser in id.OfType()) + { + var user = _cacheService.GetUser(inputUser.UserId); + if (user != null && user.IsContact) + { + user.IsContact = false; + user.IsContactMutual = false; + } + } + + _cacheService.Commit(); + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void BlockAsync(TLInputUserBase id, Action callback, Action faultCallback = null) + { + var obj = new TLBlock { Id = id }; + + SendInformativeMessage("contacts.block", obj, callback, faultCallback); + } + + public void UnblockAsync(TLInputUserBase id, Action callback, Action faultCallback = null) + { + var obj = new TLUnblock { Id = id }; + + SendInformativeMessage("contacts.unblock", obj, callback, faultCallback); + } + + public void GetBlockedAsync(TLInt offset, TLInt limit, Action callback, Action faultCallback = null) + { + var obj = new TLGetBlocked { Offset = offset, Limit = limit }; + + SendInformativeMessage("contacts.getBlocked", obj, callback, faultCallback); + } + + public void SearchAsync(TLString q, TLInt limit, Action callback, Action faultCallback = null) + { + var obj = new TLSearch { Q = q, Limit = limit }; + + SendInformativeMessage("contacts.search", obj, callback, faultCallback); + } + + public void GetSavedAsync(Action> callback, Action faultCallback = null) + { + var obj = new TLGetSaved(); + + SendInformativeMessage("contacts.getSaved", obj, callback, faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.DHKeyExchange.cs b/Telegram.Api/Services/MTProtoService.DHKeyExchange.cs new file mode 100755 index 0000000..edabace --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.DHKeyExchange.cs @@ -0,0 +1,547 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Numerics; +using System.Text; +using Org.BouncyCastle.Security; +using Telegram.Api.Helpers; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.DHKeyExchange; + +namespace Telegram.Api.Services +{ + public class AuthKeyItem + { + public long AutkKeyId { get; set; } + public byte[] AuthKey { get; set; } + } + + public partial class MTProtoService + { + /// + /// Список имеющихся ключей авторизации + /// + private static readonly Dictionary _authKeys = new Dictionary(); + + private static readonly object _authKeysRoot = new object(); + + private void ReqPQAsync(TLInt128 nonce, Action callback, Action faultCallback = null) + { + var obj = new TLReqPQ { Nonce = nonce }; + + SendNonEncryptedMessage("req_pq", obj, callback, faultCallback); + } + + private void ReqDHParamsAsync(TLInt128 nonce, TLInt128 serverNonce, TLString p, TLString q, TLLong publicKeyFingerprint, TLString encryptedData, Action callback, Action faultCallback = null) + { + var obj = new TLReqDHParams { Nonce = nonce, ServerNonce = serverNonce, P = p, Q = q, PublicKeyFingerprint = publicKeyFingerprint, EncryptedData = encryptedData }; + + SendNonEncryptedMessage("req_DH_params", obj, callback, faultCallback); + } + + public void SetClientDHParamsAsync(TLInt128 nonce, TLInt128 serverNonce, TLString encryptedData, Action callback, Action faultCallback = null) + { + var obj = new TLSetClientDHParams { Nonce = nonce, ServerNonce = serverNonce, EncryptedData = encryptedData }; + + SendNonEncryptedMessage("set_client_DH_params", obj, callback, faultCallback); + } + + private TimeSpan _authTimeElapsed; + + public void InitAsync(Action> callback, Action faultCallback = null) + { + var authTime = Stopwatch.StartNew(); + var newNonce = TLInt256.Random(); + +#if LOG_REGISTRATION + TLUtils.WriteLog("Start ReqPQ"); +#endif + var nonce = TLInt128.Random(); + ReqPQAsync(nonce, + resPQ => + { + GetServerPublicKeyAsync(_activeTransport.DCId, resPQ.ServerPublicKeyFingerprints, + (index, publicKey) => + { + if (index < 0 || string.IsNullOrEmpty(publicKey)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("unknown public key") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqPQ with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + + var serverNonce = resPQ.ServerNonce; + if (!TLUtils.ByteArraysEqual(nonce.Value, resPQ.Nonce.Value)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect nonce") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqPQ with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqPQ"); +#endif + TimeSpan calcTime; + WindowsPhone.Tuple pqPair; + var innerData = GetInnerData(new TLInt(TLUtils.GetProtocolDCId(_activeTransport.DCId, false, Constants.IsTestServer)), resPQ, newNonce, out calcTime, out pqPair); + var encryptedInnerData = GetEncryptedInnerData(innerData, publicKey); + +#if LOG_REGISTRATION + var pq = BitConverter.ToUInt64(resPQ.PQ.Data.Reverse().ToArray(), 0); + var logPQString = new StringBuilder(); + logPQString.AppendLine("PQ Counters"); + logPQString.AppendLine(); + logPQString.AppendLine("pq: " + pq); + logPQString.AppendLine("p: " + pqPair.Item1); + logPQString.AppendLine("q: " + pqPair.Item2); + logPQString.AppendLine("encrypted_data length: " + encryptedInnerData.Data.Length); + TLUtils.WriteLog(logPQString.ToString()); + TLUtils.WriteLog("Start ReqDHParams"); +#endif + ReqDHParamsAsync( + resPQ.Nonce, + resPQ.ServerNonce, + innerData.P, + innerData.Q, + resPQ.ServerPublicKeyFingerprints[0], + encryptedInnerData, + serverDHParams => + { + if (!TLUtils.ByteArraysEqual(nonce.Value, serverDHParams.Nonce.Value)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect nonce") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + if (!TLUtils.ByteArraysEqual(serverNonce.Value, serverDHParams.ServerNonce.Value)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect server_nonce") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams"); +#endif + var random = new SecureRandom(); + + var serverDHParamsOk = serverDHParams as TLServerDHParamsOk; + if (serverDHParamsOk == null) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("Incorrect serverDHParams " + serverDHParams.GetType()) }; + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); +#if LOG_REGISTRATION + TLUtils.WriteLog("ServerDHParams " + serverDHParams); +#endif + return; + } + + var aesParams = GetAesKeyIV(resPQ.ServerNonce.ToBytes(), newNonce.ToBytes()); + + var decryptedAnswerWithHash = Utils.AesIge(serverDHParamsOk.EncryptedAnswer.Data, aesParams.Item1, aesParams.Item2, false); + + var position = 0; + var serverDHInnerData = (TLServerDHInnerData)new TLServerDHInnerData().FromBytes(decryptedAnswerWithHash.Skip(20).ToArray(), ref position); + + var sha1 = Utils.ComputeSHA1(serverDHInnerData.ToBytes()); + if (!TLUtils.ByteArraysEqual(sha1, decryptedAnswerWithHash.Take(20).ToArray())) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect sha1 TLServerDHInnerData") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + + if (!TLUtils.CheckPrime(serverDHInnerData.DHPrime.Data, serverDHInnerData.G.Value)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect (p, q) pair") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + + if (!TLUtils.CheckGaAndGb(serverDHInnerData.GA.Data, serverDHInnerData.DHPrime.Data)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect g_a") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + + var bBytes = new byte[256]; //big endian B + random.NextBytes(bBytes); + + var gbBytes = GetGB(bBytes, serverDHInnerData.G, serverDHInnerData.DHPrime); + + var clientDHInnerData = new TLClientDHInnerData + { + Nonce = resPQ.Nonce, + ServerNonce = resPQ.ServerNonce, + RetryId = new TLLong(0), + GB = TLString.FromBigEndianData(gbBytes) + }; + + var encryptedClientDHInnerData = GetEncryptedClientDHInnerData(clientDHInnerData, aesParams); +#if LOG_REGISTRATION + TLUtils.WriteLog("Start SetClientDHParams"); +#endif + SetClientDHParamsAsync(resPQ.Nonce, resPQ.ServerNonce, encryptedClientDHInnerData, + dhGen => + { + if (!TLUtils.ByteArraysEqual(nonce.Value, dhGen.Nonce.Value)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect nonce") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop SetClientDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + if (!TLUtils.ByteArraysEqual(serverNonce.Value, dhGen.ServerNonce.Value)) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("incorrect server_nonce") }; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop SetClientDHParams with error " + error); +#endif + + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + } + + var dhGenOk = dhGen as TLDHGenOk; + if (dhGenOk == null) + { + var error = new TLRPCError { Code = new TLInt(404), Message = new TLString("Incorrect dhGen " + dhGen.GetType()) }; + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); +#if LOG_REGISTRATION + TLUtils.WriteLog("DHGen result " + serverDHParams); +#endif + return; + } + + + _authTimeElapsed = authTime.Elapsed; +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop SetClientDHParams"); +#endif + var getKeyTimer = Stopwatch.StartNew(); + var authKey = GetAuthKey(bBytes, serverDHInnerData.GA.ToBytes(), serverDHInnerData.DHPrime.ToBytes()); + + var logCountersString = new StringBuilder(); + + logCountersString.AppendLine("Auth Counters"); + logCountersString.AppendLine(); + logCountersString.AppendLine("pq factorization time: " + calcTime); + logCountersString.AppendLine("calc auth key time: " + getKeyTimer.Elapsed); + logCountersString.AppendLine("auth time: " + _authTimeElapsed); +#if LOG_REGISTRATION + TLUtils.WriteLog(logCountersString.ToString()); +#endif + //newNonce - little endian + //authResponse.ServerNonce - little endian + var salt = GetSalt(newNonce.ToBytes(), resPQ.ServerNonce.ToBytes()); + var sessionId = new byte[8]; + random.NextBytes(sessionId); + + TLUtils.WriteLine("Salt " + BitConverter.ToInt64(salt, 0) + " (" + BitConverter.ToString(salt) + ")"); + TLUtils.WriteLine("Session id " + BitConverter.ToInt64(sessionId, 0) + " (" + BitConverter.ToString(sessionId) + ")"); + + callback(new WindowsPhone.Tuple(authKey, new TLLong(BitConverter.ToInt64(salt, 0)), new TLLong(BitConverter.ToInt64(sessionId, 0)))); + }, + error => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop SetClientDHParams with error " + error.ToString()); +#endif + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + }); + }, + error => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqDHParams with error " + error.ToString()); +#endif + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + }); + }); + }, + error => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop ReqPQ with error " + error.ToString()); +#endif + if (faultCallback != null) faultCallback(error); + TLUtils.WriteLine(error.ToString()); + }); + } + + private static TLPQInnerData GetInnerData(TLInt dcId, TLResPQ resPQ, TLInt256 newNonce, out TimeSpan calcTime, out WindowsPhone.Tuple pqPair) + { + var pq = BitConverter.ToUInt64(resPQ.PQ.Data.Reverse().ToArray(), 0); + TLUtils.WriteLine("pq: " + pq); + + var pqCalcTime = Stopwatch.StartNew(); + try + { + pqPair = Utils.GetFastPQ(pq); + pqCalcTime.Stop(); + calcTime = pqCalcTime.Elapsed; + TLUtils.WriteLineAtBegin("Pq Fast calculation time: " + pqCalcTime.Elapsed); + TLUtils.WriteLine("p: " + pqPair.Item1); + TLUtils.WriteLine("q: " + pqPair.Item2); + } + catch (Exception e) + { + pqCalcTime = Stopwatch.StartNew(); + pqPair = Utils.GetPQPollard(pq); + pqCalcTime.Stop(); + calcTime = pqCalcTime.Elapsed; + TLUtils.WriteLineAtBegin("Pq Pollard calculation time: " + pqCalcTime.Elapsed); + TLUtils.WriteLine("p: " + pqPair.Item1); + TLUtils.WriteLine("q: " + pqPair.Item2); + } + + var p = TLString.FromUInt64(pqPair.Item1); + var q = TLString.FromUInt64(pqPair.Item2); + + var innerData1 = new TLPQInnerDataDC + { + NewNonce = newNonce, + Nonce = resPQ.Nonce, + P = p, + Q = q, + PQ = resPQ.PQ, + ServerNonce = resPQ.ServerNonce, + DCId = dcId + }; + + return innerData1; + } + + private static TLString GetEncryptedClientDHInnerData(TLClientDHInnerData clientDHInnerData, WindowsPhone.Tuple aesParams) + { + var random = new Random(); + var client_DH_inner_data = clientDHInnerData.ToBytes(); + + var client_DH_inner_dataWithHash = TLUtils.Combine(Utils.ComputeSHA1(client_DH_inner_data), client_DH_inner_data); + var addedBytesLength = 16 - (client_DH_inner_dataWithHash.Length % 16); + if (addedBytesLength > 0 && addedBytesLength < 16) + { + var addedBytes = new byte[addedBytesLength]; + random.NextBytes(addedBytes); + client_DH_inner_dataWithHash = TLUtils.Combine(client_DH_inner_dataWithHash, addedBytes); + //TLUtils.WriteLine(string.Format("Added {0} bytes", addedBytesLength)); + } + + var aesEncryptClientDHInnerDataWithHash = Utils.AesIge(client_DH_inner_dataWithHash, aesParams.Item1, aesParams.Item2, true); + + return TLString.FromBigEndianData(aesEncryptClientDHInnerDataWithHash); + } + + public static TLString GetEncryptedInnerData(TLPQInnerData innerData, string publicKey) + { + var innerDataBytes = innerData.ToBytes(); +#if LOG_REGISTRATION + var sb = new StringBuilder(); + sb.AppendLine(); + sb.AppendLine("pq " + innerData.PQ.ToBytes().Length); + sb.AppendLine("p " + innerData.P.ToBytes().Length); + sb.AppendLine("q " + innerData.Q.ToBytes().Length); + sb.AppendLine("nonce " + innerData.Nonce.ToBytes().Length); + sb.AppendLine("serverNonce " + innerData.ServerNonce.ToBytes().Length); + sb.AppendLine("newNonce " + innerData.NewNonce.ToBytes().Length); + sb.AppendLine("innerData length " + innerDataBytes.Length); + + TLUtils.WriteLog(sb.ToString()); +#endif + + var sha1 = Utils.ComputeSHA1(innerDataBytes); + var dataWithHash = TLUtils.Combine(sha1, innerDataBytes); //116 + +#if LOG_REGISTRATION + TLUtils.WriteLog("innerData+hash length " + dataWithHash.Length); +#endif + + var data255 = new byte[255]; + var random = new Random(); + random.NextBytes(data255); + Array.Copy(dataWithHash, data255, dataWithHash.Length); + + + var reverseRSABytes = Utils.GetRSABytes(data255, publicKey); // NOTE: remove Reverse here + + var encryptedData = new TLString { Data = reverseRSABytes }; + + return encryptedData; + } + + public static byte[] GetSalt(byte[] newNonce, byte[] serverNonce) + { + var newNonceBytes = newNonce.Take(8).ToArray(); + var serverNonceBytes = serverNonce.Take(8).ToArray(); + + var returnBytes = new byte[8]; + for (int i = 0; i < returnBytes.Length; i++) + { + returnBytes[i] = (byte)(newNonceBytes[i] ^ serverNonceBytes[i]); + } + + return returnBytes; + } + + + // return big-endian authKey + public static byte[] GetAuthKey(byte[] bBytes, byte[] g_aData, byte[] dhPrimeData) + { + int position = 0; + var b = new BigInteger(bBytes.Reverse().Concat(new byte[] { 0x00 }).ToArray()); + var dhPrime = TLObject.GetObject(dhPrimeData, ref position).ToBigInteger(); + position = 0; + var g_a = TLObject.GetObject(g_aData, ref position).ToBigInteger(); + + var authKey = BigInteger.ModPow(g_a, b, dhPrime).ToByteArray(); // little endian + (may be) zero last byte + + //remove last zero byte + if (authKey[authKey.Length - 1] == 0x00) + { + authKey = authKey.SubArray(0, authKey.Length - 1); + } + + authKey = authKey.Reverse().ToArray(); + + if (authKey.Length > 256) + { +#if DEBUG + var authKeyInfo = new StringBuilder(); + authKeyInfo.AppendLine("auth_key length > 256: " + authKey.Length); + authKeyInfo.AppendLine("g_a=" + g_a); + authKeyInfo.AppendLine("b=" + b); + authKeyInfo.AppendLine("dhPrime=" + dhPrime); + Execute.ShowDebugMessage(authKeyInfo.ToString()); +#endif + + var correctedAuth = new byte[256]; + Array.Copy(authKey, authKey.Length - 256, correctedAuth, 0, 256); + authKey = correctedAuth; + } + else if (authKey.Length < 256) + { +#if DEBUG + var authKeyInfo = new StringBuilder(); + authKeyInfo.AppendLine("auth_key length < 256: " + authKey.Length); + authKeyInfo.AppendLine("g_a=" + g_a); + authKeyInfo.AppendLine("b=" + b); + authKeyInfo.AppendLine("dhPrime=" + dhPrime); + Execute.ShowDebugMessage(authKeyInfo.ToString()); +#endif + + var correctedAuth = new byte[256]; + Array.Copy(authKey, 0, correctedAuth, 256 - authKey.Length, authKey.Length); + for (var i = 0; i < 256 - authKey.Length; i++) + { + authKey[i] = 0; + } + authKey = correctedAuth; + } + + return authKey; + } + + // b - big endian bytes + // g - serialized data + // dhPrime - serialized data + // returns big-endian G_B + public static byte[] GetGB(byte[] bData, TLInt gData, TLString pString) + { + //var bBytes = new byte[256]; // big endian bytes + //var random = new Random(); + //random.NextBytes(bBytes); + + var g = new BigInteger(gData.Value); + var p = pString.ToBigInteger(); + var b = new BigInteger(bData.Reverse().Concat(new byte[] { 0x00 }).ToArray()); + + var gb = BigInteger.ModPow(g, b, p).ToByteArray(); // little endian + (may be) zero last byte + //remove last zero byte + if (gb[gb.Length - 1] == 0x00) + { + gb = gb.SubArray(0, gb.Length - 1); + } + + var length = gb.Length; + var result = new byte[length]; + for (int i = 0; i < length; i++) + { + result[length - i - 1] = gb[i]; + } + + return result; + } + + //public BigInteger ToBigInteger() + //{ + // var data = new List(Data); + // while (data[0] == 0x00) + // { + // data.RemoveAt(0); + // } + + // return new BigInteger(Data.Reverse().Concat(new byte[] { 0x00 }).ToArray()); //NOTE: add reverse here + //} + + public static WindowsPhone.Tuple GetAesKeyIV(byte[] serverNonce, byte[] newNonce) + { + var newNonceServerNonce = TLUtils.Combine(newNonce, serverNonce); + var serverNonceNewNonce = TLUtils.Combine(serverNonce, newNonce); + + var key = TLUtils.Combine( + Utils.ComputeSHA1(newNonceServerNonce), + Utils.ComputeSHA1(serverNonceNewNonce).SubArray(0, 12)); + + var iv = TLUtils.Combine( + Utils.ComputeSHA1(serverNonceNewNonce).SubArray(12, 8), + Utils.ComputeSHA1(TLUtils.Combine(newNonce, newNonce)), + newNonce.SubArray(0, 4)); + + return new WindowsPhone.Tuple(key, iv); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Help.cs b/Telegram.Api/Services/MTProtoService.Help.cs new file mode 100755 index 0000000..7c4a7a9 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Help.cs @@ -0,0 +1,188 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Threading; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Help; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + private TLConfig __config = new TLConfig + { + DCOptions = new TLVector + { + new TLDCOption + { + Id = new TLInt(Constants.FirstServerDCId), + IpAddress = new TLString(Constants.FirstServerIpAddress), + Port = new TLInt(Constants.FirstServerPort) + } + } + }; + + private TLConfig _config + { + get { return __config; } + set + { + __config = value; + } + } + + public void GetConfigAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetConfig(); + + Logs.Log.Write("help.getConfig"); + + SendInformativeMessage("help.getConfig", obj, + result => + { + callback(result); + }, + faultCallback); + } + + private Timer _getConfigTimer; + + private volatile bool _isGettingConfig; + + private void CheckGetConfig(object state) + { + //TLUtils.WriteLine(DateTime.Now.ToLongTimeString() + ": Check Config on Thread " + Thread.CurrentThread.ManagedThreadId, LogSeverity.Error); + + if (_deviceInfo != null && _deviceInfo.IsBackground) + { + return; + } + + if (_isGettingConfig) + { + return; + } + + if (_activeTransport == null) + { + return; + } + + if (_activeTransport.AuthKey == null) + { + return; + } + + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (!isAuthorized) + { + return; + } + + var currentTime = TLUtils.DateToUniversalTimeTLInt(ClientTicksDelta, DateTime.Now); + + + var config23 = _config as TLConfig23; + if (config23 != null && config23.Expires != null && (config23.Expires.Value > currentTime.Value)) + { + return; + } + + //if (_config != null && _config.Date != null && Math.Abs(_config.Date.Value - currentTime.Value) < Constants.GetConfigInterval) + //{ + // return; + //} + + //Execute.ShowDebugMessage("MTProtoService.CheckGetConfig GetConfig"); + + _isGettingConfig = true; + GetConfigAsync( + result => + { + //TLUtils.WriteLine(DateTime.Now.ToLongTimeString() + ": help.getConfig", LogSeverity.Error); + _config = TLConfig.Merge(_config, result); + SaveConfig(); + _isGettingConfig = false; + }, + error => + { + _isGettingConfig = false; + //Execute.ShowDebugMessage("help.getConfig error: " + error); + }); + } + + public void GetPassportConfigAsync(TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetPassportConfig { Hash = hash }; + + SendInformativeMessage("help.getPassportConfig", obj, callback, faultCallback); + } + + public void GetTermsOfServiceAsync(TLString countryISO2, Action callback, Action faultCallback = null) + { + var obj = new TLGetTermsOfService { CountryISO2 = countryISO2 }; + + SendInformativeMessage("help.getTermsOfService", obj, callback, faultCallback); + } + + public void GetNearestDCAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetNearestDC(); + + SendInformativeMessage("help.getNearestDc", obj, callback, faultCallback); + } + + public void GetInviteTextAsync(TLString langCode, Action callback, Action faultCallback = null) + { + var obj = new TLGetInviteText(); + + SendInformativeMessage("help.getInviteText", obj, callback, faultCallback); + } + + public void GetSupportAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetSupport(); + + SendInformativeMessage("help.getSupport", obj, callback, faultCallback); + } + + public void GetAppChangelogAsync(TLString deviceModel, TLString systemVersion, TLString appVersion, TLString langCode, Action callback, Action faultCallback = null) + { + var obj = new TLGetAppChangelog(); + + SendInformativeMessage("help.getAppChangelog", obj, callback, faultCallback); + } + + public void GetCdnConfigAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetCdnConfig(); + + SendInformativeMessage("help.getCdnConfig", obj, + result => + { + foreach (var publicKey in result.PublicKeys) + { + var fingerprint = Utils.GetRSAFingerprint(publicKey.PublicKey.ToString()); + publicKey.PublicKeyFingerprint = new TLLong(fingerprint); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void GetDeepLinkInfoAsync(TLString path, Action callback, Action faultCallback = null) + { + var obj = new TLGetDeepLinkInfo{ Path = path }; + + SendInformativeMessage("help.getDeepLinkInfo", obj, callback, faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Helpers.cs b/Telegram.Api/Services/MTProtoService.Helpers.cs new file mode 100755 index 0000000..cb36879 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Helpers.cs @@ -0,0 +1,553 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using Telegram.Logs; +#if WINDOWS_PHONE +using System.Globalization; +#endif +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Help; +using Telegram.Api.Transport; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + private void PrintCaption(string caption) + { + TLUtils.WriteLine(" "); + //TLUtils.WriteLine("------------------------"); + TLUtils.WriteLine(String.Format("-->>{0}", caption)); + TLUtils.WriteLine("------------------------"); + } + + public TLEncryptedTransportMessage GetEncryptedTransportMessage(byte[] authKey, TLLong salt, TLObject obj) + { + int sequenceNumber; + TLLong messageId; + lock (_activeTransportRoot) + { + sequenceNumber = 0; + messageId = _activeTransport.GenerateMessageId(true); + } + var sessionId = TLLong.Random(); + var transportMessage = CreateTLTransportMessage(salt, sessionId, new TLInt(sequenceNumber), messageId, obj); + var encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + + return encryptedMessage; + } + + private readonly object _delayedNonInformativeItemsRoot = new object(); + + private readonly List _delayedNonInformativeItems = new List(); + + private void SendNonInformativeMessage(string caption, TLObject obj, Action callback, Action faultCallback = null) where T : TLObject + { + PrintCaption(caption); + + if (_activeTransport.AuthKey == null) + { + var delayedItem = new DelayedItem + { + SendTime = DateTime.Now, + //SendBeforeTime = sendBeforeTime, + Caption = caption, + Object = obj, + Callback = t => callback((T)t), + AttemptFailed = null, + FaultCallback = faultCallback, + }; + lock (_delayedNonInformativeItemsRoot) + { + _delayedNonInformativeItems.Add(delayedItem); + } +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("Add delayed item {0} sendTime={1}", delayedItem.Caption, delayedItem.SendTime.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture))); +#endif + + return; + } + + int sequenceNumber; + TLLong messageId; + lock (_activeTransportRoot) + { + sequenceNumber = _activeTransport.SequenceNumber * 2; + messageId = _activeTransport.GenerateMessageId(true); + } + var authKey = _activeTransport.AuthKey; + var salt = _activeTransport.Salt; + var sessionId = _activeTransport.SessionId; + var clientsTicksDelta = _activeTransport.ClientTicksDelta; + var transportMessage = CreateTLTransportMessage(salt, sessionId, new TLInt(sequenceNumber), messageId, obj); + var encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + + lock (_activeTransportRoot) + { + if (_activeTransport.Closed) + { + _activeTransport = GetTransport(_activeTransport.Host, _activeTransport.Port, Type, + new TransportSettings + { + DcId = _activeTransport.DCId, + Secret = _activeTransport.Secret, + AuthKey = _activeTransport.AuthKey, + Salt = _activeTransport.Salt, + SessionId = _activeTransport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = _activeTransport.SequenceNumber, + ClientTicksDelta = _activeTransport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); + } + } + + HistoryItem historyItem = null; + if (string.Equals(caption, "ping", StringComparison.OrdinalIgnoreCase) + || string.Equals(caption, "ping_delay_disconnect", StringComparison.OrdinalIgnoreCase) + || string.Equals(caption, "messages.container", StringComparison.OrdinalIgnoreCase)) + { + //save items to history + historyItem = new HistoryItem + { + SendTime = DateTime.Now, + //SendBeforeTime = sendBeforeTime, + Caption = caption, + Object = obj, + Message = transportMessage, + Callback = t => callback((T)t), + AttemptFailed = null, + FaultCallback = faultCallback, + ClientTicksDelta = clientsTicksDelta, + Status = RequestStatus.Sent, + }; + + lock (_historyRoot) + { + _history[historyItem.Hash] = historyItem; + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + } + + //Debug.WriteLine(">>{0, -30} MsgId {1} SeqNo {2, -4} SessionId {3}", caption, transportMessage.MessageId.Value, transportMessage.SeqNo.Value, transportMessage.SessionId.Value); + + var captionString = string.Format("{0} {1}", caption, transportMessage.MessageId); + + SendPacketAsync(_activeTransport, captionString, encryptedMessage, + result => + { + if (!result) + { + if (historyItem != null) + { + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + } + faultCallback.SafeInvoke(new TLRPCError(404) { Message = new TLString("FastCallback SocketError=" + result) }); + } + }, + error => + { + if (historyItem != null) + { + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + } + faultCallback.SafeInvoke(new TLRPCError(404) + { +#if WINDOWS_PHONE + SocketError = error.Error, +#endif + Exception = error.Exception + }); + }); + } + + private void SendPacketAsync(ITransport transport, string caption, TLObject data, Action callback, Action faultCallback = null) + { + if (_deviceInfo != null && _deviceInfo.IsBackground) + { + if (caption.Contains("account.updateStatus")) + { + + } + Log.SyncWrite("Background MTProto send " + caption); + } + + transport.SendPacketAsync( + caption, + data.ToBytes(), + callback, + faultCallback); + } + + private readonly object _historyRoot = new object(); + + public void SendInformativeMessageInternal(string caption, TLObject obj, Action callback, Action faultCallback = null, + int? maxAttempt = null, // to send delayed items + Action attemptFailed = null, + Action fastCallback = null) // to send delayed items + where T : TLObject + { + if (_activeTransport.AuthKey == null) + { + var delayedItem = new DelayedItem + { + SendTime = DateTime.Now, + //SendBeforeTime = sendBeforeTime, + Caption = caption, + Object = obj, + Callback = t => callback((T)t), + AttemptFailed = attemptFailed, + FaultCallback = faultCallback, + MaxAttempt = maxAttempt + }; + lock (_delayedItemsRoot) + { + _delayedItems.Add(delayedItem); + } +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("Add delayed item {0} sendTime={1}", delayedItem.Caption, delayedItem.SendTime.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture))); +#endif + + return; + } + + lock (_activeTransportRoot) + { + if (_activeTransport.Closed) + { + _activeTransport = GetTransport(_activeTransport.Host, _activeTransport.Port, Type, + new TransportSettings + { + DcId = _activeTransport.DCId, + Secret = _activeTransport.Secret, + AuthKey = _activeTransport.AuthKey, + Salt = _activeTransport.Salt, + SessionId = _activeTransport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = _activeTransport.SequenceNumber, + ClientTicksDelta = _activeTransport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); + } + } + + PrintCaption(caption); + + TLObject data; + lock (_activeTransportRoot) + { + if (!_activeTransport.Initiated || caption == "auth.sendCode") + { + var initConnection = new TLInitConnection78 + { + Flags = new TLInt(0), + AppId = new TLInt(Constants.ApiId), + AppVersion = new TLString(_deviceInfo.AppVersion), + Data = obj, + DeviceModel = new TLString(_deviceInfo.Model), + LangCode = new TLString(Utils.CurrentUICulture()), + SystemLangCode = new TLString(Utils.CurrentUICulture()), + LangPack = TLString.Empty, + SystemVersion = new TLString(_deviceInfo.SystemVersion), + Proxy = TLUtils.GetInputProxy(_transportService.GetProxyConfig()) + }; + + //Execute.ShowDebugMessage("initConnection dc_id=" + _activeTransport.DCId); + + SaveInitConnectionAsync(initConnection); + + var withLayerN = new TLInvokeWithLayerN { Data = initConnection }; + data = withLayerN; + _activeTransport.Initiated = true; + } + else + { + data = obj; + } + } + + int sequenceNumber; + TLLong messageId; + lock (_activeTransportRoot) + { + sequenceNumber = _activeTransport.SequenceNumber * 2 + 1; + _activeTransport.SequenceNumber++; + messageId = _activeTransport.GenerateMessageId(true); + } + var authKey = _activeTransport.AuthKey; + var salt = _activeTransport.Salt; + var sessionId = _activeTransport.SessionId; + var clientsTicksDelta = _activeTransport.ClientTicksDelta; + var transportMessage = CreateTLTransportMessage(salt, sessionId, new TLInt(sequenceNumber), messageId, data); + var encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + + //save items to history + var historyItem = new HistoryItem + { + SendTime = DateTime.Now, + //SendBeforeTime = sendBeforeTime, + Caption = caption, + Object = obj, + Message = transportMessage, + Callback = t => callback((T)t), + AttemptFailed = attemptFailed, + FaultCallback = faultCallback, + ClientTicksDelta = clientsTicksDelta, + Status = RequestStatus.Sent, + }; + + lock (_historyRoot) + { +#if DEBUG + HistoryItem existingItem; + if (_history.TryGetValue(historyItem.Hash, out existingItem)) + { + Execute.ShowDebugMessage(string.Format("Duplicated history item hash={0} existing={1} new={2}", historyItem.Hash, existingItem.Caption, historyItem.Caption)); + } + _history[historyItem.Hash] = historyItem; +#else + _history[historyItem.Hash] = historyItem; +#endif + } + +#if DEBUG + ITransport transport; + lock (_activeTransportRoot) + { + transport = _activeTransport; + } + var transportId = transport.Id; + var lastReceiveTime = transport.LastReceiveTime; + int historyCount; + string historyDescription; + lock (_historyRoot) + { + historyCount = _history.Count; + historyDescription = string.Join("\n", _history.Values.Select(x => x.Caption + " " + x.Hash)); + } + var currentPacketLength = transport.PacketLength; + var lastPacketLength = transport.LastPacketLength; + + RaiseTransportChecked(new TransportCheckedEventArgs + { + TransportId = transportId, + SessionId = sessionId, + AuthKey = authKey, + LastReceiveTime = lastReceiveTime, + HistoryCount = historyCount, + HistoryDescription = historyDescription, + NextPacketLength = currentPacketLength, + LastPacketLength = lastPacketLength + }); +#endif + +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("Add history item {0} sendTime={1}", historyItem.Caption, historyItem.SendTime.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture))); +#endif +#if DEBUG + if (historyItem.Caption != "account.updateStatus") // to avoid deadlock on deactivation + { + NotifyOfPropertyChange(() => History); + } +#endif + + //Debug.WriteLine(">>{0, -30} MsgId {1} SeqNo {2, -4} SessionId {3} ClientTicksDelta {4}", caption, transportMessage.MessageId.Value, transportMessage.SeqNo.Value, transportMessage.SessionId.Value, clientsTicksDelta); + + + var captionString = string.Format("{0} {1} {2}", caption, transportMessage.SessionId, transportMessage.MessageId); + SendPacketAsync(_activeTransport, captionString, encryptedMessage, + result => + { + if (!result) + { + if (historyItem != null) + { + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + if (historyItem.Caption != "account.updateStatus") // to avoid deadlock on deactivation + { + NotifyOfPropertyChange(() => History); + } +#endif + } + faultCallback.SafeInvoke(new TLRPCError(404) { Message = new TLString("FastCallback SocketError=" + result) }); + } + }, + error => + { + if (historyItem != null) + { + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + if (historyItem.Caption != "account.updateStatus") // to avoid deadlock on deactivation + { + NotifyOfPropertyChange(() => History); + } +#endif + } + faultCallback.SafeInvoke(new TLRPCError(404) + { +#if WINDOWS_PHONE + SocketError = error.Error, +#endif + Exception = error.Exception + }); + }); + } + + private void SendInformativeMessage(string caption, TLObject obj, Action callback, Action faultCallback = null, + int? maxAttempt = null, // to send delayed items + Action attemptFailed = null) // to send delayed items + where T : TLObject + { + Execute.BeginOnThreadPool(() => + { + SendInformativeMessageInternal(caption, obj, callback, faultCallback, maxAttempt, attemptFailed); + }); + } + + private void SendNonEncryptedMessage(string caption, TLObject obj, Action callback, Action faultCallback = null) + where T : TLObject + { + PrintCaption(caption); + TLLong messageId; + lock (_activeTransportRoot) + { + messageId = _activeTransport.GenerateMessageId(); + } + var message = CreateTLNonEncryptedMessage(messageId, obj); + + var historyItem = new HistoryItem + { + Caption = caption, + Message = message, + Callback = t => callback((T)t), + FaultCallback = faultCallback, + SendTime = DateTime.Now, + Status = RequestStatus.Sent + }; + + var guid = message.MessageId; + lock (_activeTransportRoot) + { + if (_activeTransport.Closed) + { + _activeTransport = GetTransport(_activeTransport.Host, _activeTransport.Port, Type, + new TransportSettings + { + DcId = _activeTransport.DCId, + Secret = _activeTransport.Secret, + AuthKey = _activeTransport.AuthKey, + Salt = _activeTransport.Salt, + SessionId = _activeTransport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = _activeTransport.SequenceNumber, + ClientTicksDelta = _activeTransport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); + } + } + + var activeTransport = _activeTransport; // до вызова callback _activeTransport может уже поменяться + + // Сначала создаем или получаем транспорт, а потом добавляем в его историю. + // Если сначала добавить в историю транспорта, то потом можем получить новый и не найдем запрос + _activeTransport.EnqueueNonEncryptedItem(historyItem); + + var bytes = message.ToBytes(); +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("SendPacketAsync {0} [{1}](data length={2})", _activeTransport.Id, caption, bytes.Length)); +#endif + var captionString = string.Format("{0} {1}", caption, guid); + SendPacketAsync(_activeTransport, captionString, message, + socketError => + { +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("SendPacketAsync fastCallback {0} [{1}] socketError={2}", activeTransport.Id, caption, socketError)); +#endif + if (!socketError) + { + var result = activeTransport.RemoveNonEncryptedItem(historyItem); + + if (result) + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("FastCallback SocketError=" + socketError) }); + } + } + }, + error => + { +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("SendPacketAsync error {0} [{1}] error={2}", activeTransport.Id, caption, error)); +#endif + var result = activeTransport.RemoveNonEncryptedItem(historyItem); + + // чтобы callback не вызвался два раза из CheckTimeouts и отсюда + if (result) + { + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("FaltCallback") }); + } + }); + } + + private static TLEncryptedTransportMessage CreateTLEncryptedMessage(byte[] authKey, TLContainerTransportMessage containerTransportMessage) + { + var message = new TLEncryptedTransportMessage { Data = containerTransportMessage.ToBytes() }; + + return message.Encrypt(authKey); + } + + private TLTransportMessage CreateTLTransportMessage(TLLong salt, TLLong sessionId, TLInt seqNo, TLLong messageId, TLObject obj) + { + var message = new TLTransportMessage(); + message.Salt = salt; + message.SessionId = sessionId; + message.MessageId = messageId; + message.SeqNo = seqNo; + message.MessageData = obj; + + return message; + } + + public static TLNonEncryptedMessage CreateTLNonEncryptedMessage(TLLong messageId, TLObject obj) + { + var message = new TLNonEncryptedMessage(); + message.AuthKeyId = new TLLong(0); + message.MessageId = messageId; + message.Data = obj; + + return message; + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.HttpLongPoll.cs b/Telegram.Api/Services/MTProtoService.HttpLongPoll.cs new file mode 100755 index 0000000..acd2eab --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.HttpLongPoll.cs @@ -0,0 +1,65 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Threading; +using Telegram.Api.Helpers; +using Telegram.Api.TL; + +namespace Telegram.Api.Services +{ + public enum TransportType + { + Http, + Tcp + } + + public partial class MTProtoService + { + private volatile bool _isLongPollStopped; + + private const int ReattemptDelay = Constants.LongPollReattemptDelay; + + public void StartLongPollRequestAsync() + { + if (_isLongPollStopped || _type != TransportType.Http) return; + TLUtils.WriteLongPoll("Send " + DateTime.Now); + try + { + HttpWaitAsync(new TLInt(0), new TLInt(0), new TLInt(25000), + () => + { + TLUtils.WriteLongPoll("Receive " + DateTime.Now); + StartLongPollRequestAsync(); + }, + () => + { + TLUtils.WriteLongPoll("Receive failed " + DateTime.Now); + StartLongPollRequestAsync(); + }); + } + catch (Exception) + { + TLUtils.WriteLongPoll("Receive failed " + DateTime.Now); + Execute.BeginOnThreadPool(TimeSpan.FromSeconds(5.0), StartLongPollRequestAsync); + } + } + + public void StartLongPoll() + { + TLUtils.WriteLongPoll("Start long poll " + DateTime.Now); + _isLongPollStopped = false; + StartLongPollRequestAsync(); + } + + public void StopLongPoll() + { + TLUtils.WriteLongPoll("Stop long poll " + DateTime.Now); + _isLongPollStopped = true; + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Langpack.cs b/Telegram.Api/Services/MTProtoService.Langpack.cs new file mode 100755 index 0000000..3c4c8e0 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Langpack.cs @@ -0,0 +1,44 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Langpack; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void GetLangPackAsync(TLString langCode, Action callback, Action faultCallback = null) + { + var obj = new TLGetLangPack { LangCode = langCode }; + + SendInformativeMessage("langpack.getLangPack", obj, callback, faultCallback); + } + + public void GetStringsAsync(TLString langCode, TLVector keys, Action> callback, Action faultCallback = null) + { + var obj = new TLGetStrings { LangCode = langCode, Keys = keys }; + + SendInformativeMessage("langpack.getStrings", obj, callback, faultCallback); + } + + public void GetDifferenceAsync(TLInt fromVersion, Action callback, Action faultCallback = null) + { + var obj = new TLGetDifference { FromVersion = fromVersion }; + + SendInformativeMessage("langpack.getDifference", obj, callback, faultCallback); + } + + public void GetLanguagesAsync(Action> callback, Action faultCallback = null) + { + var obj = new TLGetLanguages(); + + SendInformativeMessage("langpack.getLanguages", obj, callback, faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Messages.cs b/Telegram.Api/Services/MTProtoService.Messages.cs new file mode 100755 index 0000000..c04fe14 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Messages.cs @@ -0,0 +1,2980 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Text; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Help; +using Telegram.Api.TL.Functions.Messages; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void ToggleTopPeersAsync(TLBool enabled, Action callback, Action faultCallback = null) + { + var obj = new TLToggleTopPeers{ Enabled = enabled }; + + const string caption = "messages.toggleTopPeers"; + SendInformativeMessage(caption, obj, + callback.SafeInvoke, + faultCallback); + } + + public void ClearAllDraftsAsync(Action callback, Action faultCallback = null) + { + var obj = new TLClearAllDrafts(); + + const string caption = "messages.clearAllDrafts"; + SendInformativeMessage(caption, obj, + callback.SafeInvoke, + faultCallback); + } + + public void MarkDialogUnreadAsync(bool unread, TLInputDialogPeer peer, Action callback, Action faultCallback = null) + { + var obj = new TLMarkDialogUnread{ Flags = new TLInt(0), Unread = unread, Peer = peer }; + + const string caption = "messages.markDialogUnread"; + SendInformativeMessage(caption, obj, + callback.SafeInvoke, + faultCallback); + } + + public void GetDialogUnreadMarksAsync(Action> callback, Action faultCallback = null) + { + var obj = new TLGetDialogUnreadMarks(); + + const string caption = "messages.getDialogUnreadMarks"; + SendInformativeMessage>(caption, obj, + callback.SafeInvoke, + faultCallback); + } + + public void GetProxyDataAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetProxyData(); + + const string caption = "messages.getProxyData"; + SendInformativeMessage(caption, obj, + result => + { + _cacheService.SyncProxyData(result, callback.SafeInvoke); + }, + faultCallback); + } + + public void SearchStickerSetsAsync(bool full, bool excludeFeatured, TLString q, TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLSearchStickerSets { Flags = new TLInt(0), ExcludeFeatured = excludeFeatured, Q = q, Hash = hash }; + + var results = new List(); + var resultsSyncRoot = new object(); + + const string caption = "messages.searchStickerSets"; + SendInformativeMessage(caption, obj, + result => + { + var foundStickerSets = result as TLFoundStickerSets; + if (foundStickerSets != null && full) + { + GetStickerSetsAsync(foundStickerSets, r => callback(r as TLFoundStickerSetsBase), + stickerSetResult => + { + var messagesStickerSet = stickerSetResult as TLMessagesStickerSet; + if (messagesStickerSet != null) + { + bool processStickerSets; + lock (resultsSyncRoot) + { + results.Add(messagesStickerSet); + processStickerSets = results.Count == foundStickerSets.Sets.Count; + } + + if (processStickerSets) + { + ProcessStickerSets(foundStickerSets, results); + foundStickerSets.MessagesStickerSets = new TLVector(results); + callback.SafeInvoke(foundStickerSets); + } + } + }, + faultCallback); + } + else + { + callback.SafeInvoke(result); + } + }, + faultCallback.SafeInvoke); + } + + public void ReportAsync(TLInputPeerBase peer, TLVector id, TLInputReportReasonBase reason, Action callback, Action faultCallback = null) + { + var obj = new TLReport { Peer = peer, Id = id, Reason = reason }; + + const string caption = "messages.report"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void GetStickersAsync(TLString emoticon, TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetStickers { Emoticon = emoticon, Hash = hash }; + + const string caption = "messages.getStickers"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void GetRecentLocationsAsync(TLInputPeerBase peer, TLInt limit, TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetRecentLocations { Peer = peer, Limit = limit, Hash = hash }; + + const string caption = "messages.getRecentLocations"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void GetFavedStickersAsync(TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetFavedStickers { Hash = hash }; + + const string caption = "messages.getFavedStickers"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void FaveStickerAsync(TLInputDocumentBase id, TLBool unfave, Action callback, Action faultCallback = null) + { + var obj = new TLFaveSticker { Id = id, Unfave = unfave }; + + const string caption = "messages.faveSticker"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void GetUnreadMentionsAsync(TLInputPeerBase peer, TLInt offsetId, TLInt addOffset, TLInt limit, TLInt maxId, TLInt minId, Action callback, Action faultCallback = null) + { + var obj = new TLGetUnreadMentions { Peer = peer, OffsetId = offsetId, AddOffset = addOffset, Limit = limit, MinId = minId, MaxId = maxId }; + + SendInformativeMessage("messages.getUnreadMentions", obj, callback.SafeInvoke, faultCallback); + } + + public void ToggleDialogPinAsync(bool pinned, TLPeerBase peer, Action callback, Action faultCallback = null) + { + var obj = new TLToggleDialogPin { Flags = new TLInt(0), Peer = PeerToInputPeer(peer), Pinned = pinned }; + + const string caption = "messages.toggleDialogPin"; + SendInformativeMessage(caption, obj, + result => + { + _cacheService.UpdateDialogPinned(peer, pinned); + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void ReorderPinnedDialogsAsync(bool force, TLVector order, Action callback, Action faultCallback = null) + { + var obj = new TLReorderPinnedDialogs { Flags = new TLInt(0), Order = order }; + if (force) + { + obj.SetForce(); + } + + const string caption = "messages.reorderPinnedDialogs"; + SendInformativeMessage(caption, obj, callback.SafeInvoke, faultCallback); + } + + public void GetWebPageAsync(TLString url, TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetWebPage { Url = url, Hash = hash }; + + const string caption = "messages.getWebPage"; + SendInformativeMessage(caption, obj, callback.SafeInvoke, faultCallback); + } + + public void GetCommonChatsAsync(TLInputUserBase user, TLInt maxId, TLInt limit, Action callback, Action faultCallback = null) + { + var obj = new TLGetCommonChats { User = user, MaxId = maxId, Limit = limit }; + + const string caption = "messages.getCommonChats"; + SendInformativeMessage(caption, obj, + result => + { + var chats = result as TLChats24; + if (chats != null) + { + _cacheService.SyncUsersAndChats(new TLVector(), chats.Chats, tuple => callback.SafeInvoke(result)); + } + }, + faultCallback); + } + + private readonly Dictionary _cachedArchivedStickers = new Dictionary(); + + public void GetAttachedStickersAsync(bool full, TLInputStickeredMediaBase media, Action callback, Action faultCallback = null) + { + TLArchivedStickers cachedArchivedStickers; + var key = string.Format("{0} {1}", media, full); + if (_cachedArchivedStickers.TryGetValue(key, out cachedArchivedStickers)) + { + callback.SafeInvoke(cachedArchivedStickers); + return; + } + + + var obj = new TLGetAttachedStickers { Media = media }; + + const string caption = "messages.getAttachedStickers"; + //SendInformativeMessage(caption, obj, callback, faultCallback); + var results = new List(); + var resultsSyncRoot = new object(); + SendInformativeMessage>(caption, obj, + result => + { + var archivedStickers = new TLArchivedStickers(); + archivedStickers.Count = new TLInt(result.Count); + archivedStickers.SetsCovered = result; + + archivedStickers.Packs = new TLVector(); + archivedStickers.Documents = new TLVector(); + archivedStickers.MessagesStickerSets = new TLVector(); + + if (full) + { + GetStickerSetsAsync(archivedStickers, r => callback(r as TLArchivedStickers), + stickerSetResult => + { + var messagesStickerSet = stickerSetResult as TLMessagesStickerSet; + if (messagesStickerSet != null) + { + bool processStickerSets; + lock (resultsSyncRoot) + { + results.Add(messagesStickerSet); + processStickerSets = results.Count == archivedStickers.Sets.Count; + } + + if (processStickerSets) + { + ProcessStickerSets(archivedStickers, results); + archivedStickers.MessagesStickerSets = new TLVector(results); + _cachedArchivedStickers[key] = archivedStickers; + callback.SafeInvoke(archivedStickers); + } + } + }, + faultCallback); + } + else + { + _cachedArchivedStickers[key] = archivedStickers; + callback.SafeInvoke(archivedStickers); + } + }); + } + + public void GetRecentStickersAsync(bool attached, TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetRecentStickers { Flags = new TLInt(0), Hash = hash }; + if (attached) + { + obj.SetAttached(); + } + + const string caption = "messages.getRecentStickers"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void ClearRecentStickersAsync(bool attached, Action callback, Action faultCallback = null) + { + var obj = new TLClearRecentStickers { Flags = new TLInt(0) }; + if (attached) + { + obj.SetAttached(); + } + + const string caption = "messages.clearRecentStickers"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void GetUnusedStickersAsync(TLInt limit, Action> callback, Action faultCallback = null) + { + var obj = new TLGetUnusedStickers { Limit = limit }; + + const string caption = "messages.getUnusedStickers"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void ReadFeaturedStickersAsync(TLVector id, Action callback, Action faultCallback = null) + { +#if DEBUG + callback.SafeInvoke(TLBool.True); + return; +#endif + + var obj = new TLReadFeaturedStickers { Id = id }; + + const string caption = "messages.readFeaturedStickers"; + SendInformativeMessage(caption, obj, callback.SafeInvoke, faultCallback.SafeInvoke); + } + + public void GetAllDraftsAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetAllDrafts(); + + const string caption = "messages.getAllDrafts"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + _updatesService.ProcessUpdates(result, true); + } + + callback.SafeInvoke(result); + }, + faultCallback.SafeInvoke); + } + + public void SaveDraftAsync(TLInputPeerBase peer, TLDraftMessageBase draft, Action callback, Action faultCallback = null) + { + var obj = draft.ToSaveDraftObject(peer); + + const string caption = "messages.saveDraft"; + SendInformativeMessage(caption, obj, + result => + { + callback.SafeInvoke(result); + }, + faultCallback.SafeInvoke); + } + + public void GetInlineBotResultsAsync(TLInputUserBase bot, TLInputPeerBase peer, TLInputGeoPointBase geoPoint, TLString query, TLString offset, Action callback, Action faultCallback = null) + { + var key = string.Format("{0}_{1}_{2}_{3}_{4}", bot, peer, geoPoint, query, offset); + + TLBotResults botResults; + if (TryGetCachedValue(_cache, key, out botResults, IsCacheTimeValid)) + { + callback.SafeInvoke(botResults); + return; + } + + var obj = new TLGetInlineBotResults { Flags = new TLInt(0), Bot = bot, Peer = peer, GeoPoint = geoPoint, Query = query, Offset = offset }; + + const string caption = "messages.getInlineBotResults"; + SendInformativeMessage(caption, obj, + result => + { + SetCachedValue(ref _cache, key, result as ICachedObject, IsCacheTimeValid); + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void SetInlineBotResultsAsync(TLBool gallery, TLBool pr, TLLong queryId, TLVector results, TLInt cacheTime, TLString nextOffset, TLInlineBotSwitchPM switchPM, Action callback, Action faultCallback = null) + { + var obj = new TLSetInlineBotResults { Flags = new TLInt(0), Gallery = gallery, Private = pr, QueryId = queryId, Results = results, CacheTime = cacheTime, NextOffset = nextOffset, SwitchPM = switchPM }; + + const string caption = "messages.setInlineBotResults"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void SendInlineBotResultAsync(TLMessage45 message, Action callback, Action fastCallback, Action faultCallback = null) + { + var inputPeer = PeerToInputPeer(message.ToId); + var obj = new TLSendInlineBotResult { Flags = new TLInt(0), Peer = inputPeer, ReplyToMsgId = message.ReplyToMsgId, RandomId = message.RandomId, QueryId = message.InlineBotResultQueryId, Id = message.InlineBotResultId }; + + if (message.IsChannelMessage) + { + obj.SetChannelMessage(); + } + + var message48 = message as TLMessage48; + if (message48 != null && message48.Silent) + { + obj.SetSilent(); + } + + const string caption = "messages.sendInlineBotResult"; + SendInlineBotResultAsyncInternal(obj, + result => + { + var multiPts = result as IMultiPts; + var shortSentMessage = result as TLUpdatesShortSentMessage; + if (shortSentMessage != null) + { + message.Flags = shortSentMessage.Flags; + if (shortSentMessage.HasMedia) + { + message._media = shortSentMessage.Media; + } + if (shortSentMessage.HasEntities) + { + message.Entities = shortSentMessage.Entities; + } + + Execute.BeginOnUIThread(() => + { + message.Status = GetMessageStatus(_cacheService, message.ToId); + message.Date = shortSentMessage.Date; + if (shortSentMessage.Media is TLMessageMediaWebPage) + { + message.NotifyOfPropertyChange(() => message.Media); + } + +#if DEBUG + message.Id = shortSentMessage.Id; + message.NotifyOfPropertyChange(() => message.Id); + message.NotifyOfPropertyChange(() => message.Date); +#endif + }); + + _updatesService.SetState(multiPts, caption); + + message.Id = shortSentMessage.Id; + _cacheService.SyncSendingMessage(message, null, callback); + return; + } + + var updates = result as TLUpdates; + if (updates != null) + { + foreach (var update in updates.Updates) + { + var updateNewMessage = update as TLUpdateNewMessage24; + if (updateNewMessage != null) + { + Execute.BeginOnUIThread(() => + { + // faster update web page with inline bots @imdb, @vid, @wiki + var newMessage = updateNewMessage.Message as TLMessage45; + if (newMessage != null) + { + var mediaWebPage = newMessage.Media as TLMessageMediaWebPage; + if (mediaWebPage != null) + { + message.Media = newMessage.Media; + } + + if (mediaWebPage == null) + { + //Execute.ShowDebugMessage(newMessage.Media.GetType().ToString()); + } + } + }); + + var messageCommon = updateNewMessage.Message as TLMessageCommon; + if (messageCommon != null) + { + messageCommon.RandomId = message.RandomId; + message.Id = messageCommon.Id; + message.Date = messageCommon.Date; + } + } + } + + Execute.BeginOnUIThread(() => + { + message.Status = GetMessageStatus(_cacheService, message.ToId); + }); + + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + _updatesService.ProcessUpdates(updates); + } + + callback.SafeInvoke(message); + } + }, + fastCallback, + faultCallback.SafeInvoke); + } + + public void GetDocumentByHashAsync(TLString sha256, TLInt size, TLString mimeType, Action callback, Action faultCallback = null) + { + var obj = new TLGetDocumentByHash { Sha256 = sha256, Size = size, MimeType = mimeType }; + + const string caption = "messages.getDocumentByHash"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void SearchGifsAsync(TLString q, TLInt offset, Action callback, Action faultCallback = null) + { + var obj = new TLSearchGifs { Q = q, Offset = offset }; + + const string caption = "messages.searchGifs"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void GetSavedGifsAsync(TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetSavedGifs { Hash = hash }; + + const string caption = "messages.getSavedGifs"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void SaveGifAsync(TLInputDocumentBase id, TLBool unsave, Action callback, Action faultCallback = null) + { + var obj = new TLSaveGif { Id = id, Unsave = unsave }; + + const string caption = "messages.saveGif"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void ReorderStickerSetsAsync(bool masks, TLVector order, Action callback, Action faultCallback = null) + { + var obj = new TLReorderStickerSets { Flags = new TLInt(0), Order = order }; + if (masks) + { + obj.SetMasks(); + } + + const string caption = "messages.reorderStickerSets"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void ReportSpamAsync(TLInputPeerBase peer, Action callback, Action faultCallback = null) + { +#if DEBUG + Execute.BeginOnThreadPool(() => callback.SafeInvoke(TLBool.True)); + return; +#endif + + var obj = new TLReportSpam { Peer = peer }; + + const string caption = "messages.reportSpam"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void GetWebPagePreviewAsync(TLString message, Action callback, Action faultCallback = null) + { + var obj = new TLGetWebPagePreview { Flags = new TLInt(0), Message = message, Entities = null }; + + const string caption = "messages.getWebPagePreview"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void GetFeaturedStickersAsync(bool full, TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetFeaturedStickers { Hash = hash }; + + const string caption = "messages.getFeaturedStickers"; + + var results = new List(); + var resultsSyncRoot = new object(); + SendInformativeMessage(caption, obj, + result => + { + var featuredStickers = result as TLFeaturedStickers; + if (featuredStickers != null && full) + { + GetStickerSetsAsync(featuredStickers, r => callback(r as TLFeaturedStickersBase), + stickerSetResult => + { + var messagesStickerSet = stickerSetResult as TLMessagesStickerSet; + if (messagesStickerSet != null) + { + bool processStickerSets; + lock (resultsSyncRoot) + { + results.Add(messagesStickerSet); + processStickerSets = results.Count == featuredStickers.Sets.Count; + } + + if (processStickerSets) + { + ProcessStickerSets(featuredStickers, results); + featuredStickers.MessagesStickerSets = new TLVector(results); + //Execute.ShowDebugMessage(caption + " elapsed=" + stopwatch.Elapsed); + callback.SafeInvoke(featuredStickers); + } + } + }, + faultCallback); + } + else + { + callback.SafeInvoke(result); + } + }, + faultCallback.SafeInvoke); + } + + public void GetArchivedStickersAsync(bool full, TLLong offsetId, TLInt limit, Action callback, Action faultCallback = null) + { + var obj = new TLGetArchivedStickers { Flags = new TLInt(0), OffsetId = offsetId, Limit = limit }; + //obj.SetMasks(); + + const string caption = "messages.getArchivedStickers"; + + var results = new List(); + var resultsSyncRoot = new object(); + SendInformativeMessage(caption, obj, + result => + { + if (full) + { + GetStickerSetsAsync(result, r => callback(r as TLArchivedStickers), + stickerSetResult => + { + var messagesStickerSet = stickerSetResult as TLMessagesStickerSet; + if (messagesStickerSet != null) + { + bool processStickerSets; + lock (resultsSyncRoot) + { + results.Add(messagesStickerSet); + processStickerSets = results.Count == result.Sets.Count; + } + + if (processStickerSets) + { + ProcessStickerSets(result, results); + result.MessagesStickerSets = new TLVector(results); + callback.SafeInvoke(result); + } + } + }, + faultCallback); + } + else + { + callback.SafeInvoke(result); + } + }); + } + + public void GetMaskStickersAsync(TLString hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetMaskStickers { Hash = TLUtils.ToTLInt(hash) ?? new TLInt(0) }; + + const string caption = "messages.getMaskStickers"; + + var results = new List(); + var resultsSyncRoot = new object(); + SendInformativeMessage(caption, obj, + result => + { + var allStickers32 = result as TLAllStickers43; + if (allStickers32 != null) + { + GetStickerSetsAsync(allStickers32, r => callback(r as TLAllStickersBase), + stickerSetResult => + { + var messagesStickerSet = stickerSetResult as TLMessagesStickerSet; + if (messagesStickerSet != null) + { + bool processStickerSets; + lock (resultsSyncRoot) + { + results.Add(messagesStickerSet); + processStickerSets = results.Count == allStickers32.Sets.Count; + } + + if (processStickerSets) + { + ProcessStickerSets(allStickers32, results); + + callback.SafeInvoke(allStickers32); + } + } + }, + faultCallback); + } + else + { + callback.SafeInvoke(result); + } + }); + } + + public void GetAllStickersAsync(TLString hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetAllStickers { Hash = TLUtils.ToTLInt(hash) ?? new TLInt(0) }; + + const string caption = "messages.getAllStickers"; + + var results = new List(); + var resultsSyncRoot = new object(); + SendInformativeMessage(caption, obj, + result => + { + var allStickers32 = result as TLAllStickers43; + if (allStickers32 != null) + { + GetStickerSetsAsync(allStickers32, r => callback(r as TLAllStickersBase), + stickerSetResult => + { + var messagesStickerSet = stickerSetResult as TLMessagesStickerSet; + if (messagesStickerSet != null) + { + bool processStickerSets; + lock (resultsSyncRoot) + { + results.Add(messagesStickerSet); + processStickerSets = results.Count == allStickers32.Sets.Count; + } + + if (processStickerSets) + { + ProcessStickerSets(allStickers32, results); + + callback.SafeInvoke(allStickers32); + } + } + }, + faultCallback); + } + else + { + callback.SafeInvoke(result); + } + }); + } + + private static void ProcessStickerSets(IStickers stickers, List results) + { + var documentsDict = new Dictionary(); + var packsDict = new Dictionary(); + foreach (var result in results) + { + foreach (var pack in result.Packs) + { + var emoticon = pack.Emoticon.ToString(); + TLStickerPack currentPack; + if (packsDict.TryGetValue(emoticon, out currentPack)) + { + var docDict = new Dictionary(); + foreach (var document in currentPack.Documents) + { + docDict[document.Value] = document.Value; + } + foreach (var document in pack.Documents) + { + if (!docDict.ContainsKey(document.Value)) + { + docDict[document.Value] = document.Value; + currentPack.Documents.Add(document); + } + } + } + else + { + packsDict[emoticon] = pack; + } + } + + foreach (var document in result.Documents) + { + documentsDict[document.Id.Value] = document; + } + } + stickers.Packs = new TLVector(); + foreach (var pack in packsDict.Values) + { + stickers.Packs.Add(pack); + } + stickers.Documents = new TLVector(); + foreach (var document in documentsDict.Values) + { + stickers.Documents.Add(document); + } + } + + private void GetStickerSetsAsync(IStickers stickers, Action callback, Action getStickerSetCallback, Action faultCallback) + { + var sets = stickers.Sets; + if (sets.Count == 0) + { + callback.SafeInvoke(stickers); + return; + } + + var container = new TLContainer { Messages = new List() }; + var historyItems = new List(); + for (var i = 0; i < sets.Count; i++) + { + var set = sets[i]; + var obj = new TLGetStickerSet { Stickerset = new TLInputStickerSetId { Id = set.Id, AccessHash = set.AccessHash } }; + int sequenceNumber; + TLLong messageId; + lock (_activeTransportRoot) + { + sequenceNumber = _activeTransport.SequenceNumber * 2 + 1; + _activeTransport.SequenceNumber++; + messageId = _activeTransport.GenerateMessageId(true); + } + + var data = i > 0 ? (TLObject)new TLInvokeAfterMsg { MsgId = container.Messages[i - 1].MessageId, Object = obj } : obj; + + var transportMessage = new TLContainerTransportMessage + { + MessageId = messageId, + SeqNo = new TLInt(sequenceNumber), + MessageData = data + }; + + var historyItem = new HistoryItem + { + SendTime = DateTime.Now, + Caption = "stickers.containerGetStickerSetPart" + i, + Object = obj, + Message = transportMessage, + Callback = getStickerSetCallback, + AttemptFailed = null, + FaultCallback = faultCallback, + ClientTicksDelta = ClientTicksDelta, + Status = RequestStatus.Sent, + }; + historyItems.Add(historyItem); + + container.Messages.Add(transportMessage); + } + + + lock (_historyRoot) + { + foreach (var historyItem in historyItems) + { + _history[historyItem.Hash] = historyItem; + } + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + + SendNonInformativeMessage("stickers.container", container, result => callback(null), faultCallback); + } + + private Dictionary _stickerSetCache; + + public void GetStickerSetAsync(TLInputStickerSetBase stickerset, Action callback, Action faultCallback = null) + { + var obj = new TLGetStickerSet { Stickerset = stickerset }; + + var inputStickerSetShortName = stickerset as TLInputStickerSetShortName; + TLMessagesStickerSet cachedValue; + if (inputStickerSetShortName != null && _stickerSetCache != null && _stickerSetCache.TryGetValue(inputStickerSetShortName.ShortName.ToString(), out cachedValue)) + { + callback.SafeInvoke(cachedValue); + return; + } + + const string caption = "messages.getStickerSet"; + SendInformativeMessage(caption, obj, + result => + { + _stickerSetCache = _stickerSetCache ?? new Dictionary(); + _stickerSetCache[result.Set.ShortName.ToString()] = result; + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void InstallStickerSetAsync(TLInputStickerSetBase stickerset, TLBool archived, Action callback, Action faultCallback = null) + { + var obj = new TLInstallStickerSet { Stickerset = stickerset, Archived = archived }; + + const string caption = "messages.installStickerSet"; + + var results = new List(); + var resultsSyncRoot = new object(); + SendInformativeMessage(caption, obj, + result => + { + var resultArchive = result as TLStickerSetInstallResultArchive; + if (resultArchive != null) + { + GetStickerSetsAsync(resultArchive, r => callback(r as TLStickerSetInstallResultArchive), + stickerSetResult => + { + var messagesStickerSet = stickerSetResult as TLMessagesStickerSet; + if (messagesStickerSet != null) + { + var set32 = messagesStickerSet.Set as TLStickerSet32; + if (set32 != null) + { + set32.Installed = true; + set32.Archived = true; + } + + var set76 = messagesStickerSet.Set as TLStickerSet76; + if (set76 != null) + { + set76.InstalledDate = TLUtils.DateToUniversalTimeTLInt(ClientTicksDelta, DateTime.Now); + } + + bool processStickerSets; + lock (resultsSyncRoot) + { + results.Add(messagesStickerSet); + processStickerSets = results.Count == resultArchive.Sets.Count; + } + + if (processStickerSets) + { + ProcessStickerSets(resultArchive, results); + resultArchive.MessagesStickerSets = new TLVector(results); + callback.SafeInvoke(result); + } + } + }, + faultCallback); + } + else + { + callback.SafeInvoke(result); + } + }, + faultCallback); + } + + public void UninstallStickerSetAsync(TLInputStickerSetBase stickerset, Action callback, Action faultCallback = null) + { + var obj = new TLUninstallStickerSet { Stickerset = stickerset }; + + const string caption = "messages.uninstallStickerSet"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + private static MessageStatus GetMessageStatus(ICacheService cacheService, TLPeerBase peer) + { + var status = MessageStatus.Confirmed; + if (peer is TLPeerUser) + { + var user = cacheService.GetUser(peer.Id); + if (user != null) + { + var botInfo = user.BotInfo as TLBotInfo; + if (botInfo != null) + { + status = MessageStatus.Read; + } + else if (user.IsSelf) + { + status = MessageStatus.Read; + } + } + } + + //if (peer is TLPeerChannel) + //{ + // status = MessageStatus.Read; + //} + + return status; + } + + public TLInputPeerBase PeerToInputPeer(TLPeerBase peer) + { + if (peer is TLPeerUser) + { + var cachedUser = _cacheService.GetUser(peer.Id); + if (cachedUser != null) + { + var userForeign = cachedUser as TLUserForeign; + var userRequest = cachedUser as TLUserRequest; + var user = cachedUser as TLUser; + + if (userForeign != null) + { + return new TLInputPeerUser { UserId = userForeign.Id, AccessHash = userForeign.AccessHash }; + } + + if (userRequest != null) + { + return new TLInputPeerUser { UserId = userRequest.Id, AccessHash = userRequest.AccessHash }; + } + + if (user != null) + { + return user.ToInputPeer(); + } + + return new TLInputPeerUser { UserId = peer.Id, AccessHash = new TLLong(0) }; + } + + return new TLInputPeerUser { UserId = peer.Id, AccessHash = new TLLong(0) }; + } + + if (peer is TLPeerChannel) + { + var channel = _cacheService.GetChat(peer.Id) as TLChannel; + if (channel != null) + { + return new TLInputPeerChannel { ChatId = peer.Id, AccessHash = channel.AccessHash }; + } + } + + if (peer is TLPeerChat) + { + return new TLInputPeerChat { ChatId = peer.Id }; + } + + return new TLInputPeerBroadcast { ChatId = peer.Id }; + } + + public void SendMessageAsync(TLMessage36 message, Action callback, Action fastCallback, Action faultCallback = null) + { + var inputPeer = PeerToInputPeer(message.ToId); + var obj = new TLSendMessage { Peer = inputPeer, ReplyToMsgId = message.ReplyToMsgId, Message = message.Message, RandomId = message.RandomId }; + + if (message.Entities != null) + { + obj.Entities = message.Entities; + } + + if (message.NoWebpage) + { + obj.NoWebpage(); + } + + if (message.IsChannelMessage) + { + obj.SetChannelMessage(); + } + + var message48 = message as TLMessage48; + if (message48 != null && message48.Silent) + { + obj.SetSilent(); + } + + obj.ClearDraft(); + + const string caption = "messages.sendMessage"; + SendMessageAsyncInternal(obj, + result => + { +#if DEBUG + var builder = new StringBuilder(); + builder.Append(result.GetType()); + var updates = result as TLUpdates; + var updatesShort = result as TLUpdatesShort; + if (updates != null) + { + foreach (var update in updates.Updates) + { + builder.Append(update); + } + } + else if (updatesShort != null) + { + builder.Append(updatesShort.Update); + } + + Logs.Log.Write(string.Format("{0} result={1}", caption, builder.ToString())); +#endif + + var multiPts = result as IMultiPts; + + var shortSentMessage = result as TLUpdatesShortSentMessage; + if (shortSentMessage != null) + { + message.Flags = shortSentMessage.Flags; + if (shortSentMessage.HasMedia) + { + message._media = shortSentMessage.Media; + } + if (shortSentMessage.HasEntities) + { + message.Entities = shortSentMessage.Entities; + } + + Execute.BeginOnUIThread(() => + { + message.Status = GetMessageStatus(_cacheService, message.ToId); + message.Date = shortSentMessage.Date; + if (shortSentMessage.Media is TLMessageMediaWebPage) + { + message.NotifyOfPropertyChange(() => message.Media); + } + +#if DEBUG + message.Id = shortSentMessage.Id; + message.NotifyOfPropertyChange(() => message.Id); + message.NotifyOfPropertyChange(() => message.Date); +#endif + }); + + _updatesService.SetState(multiPts, caption); + + message.Id = shortSentMessage.Id; + _cacheService.SyncSendingMessage(message, null, callback); + return; + } + + Execute.BeginOnUIThread(() => + { + message.Status = GetMessageStatus(_cacheService, message.ToId); + }); + + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, new List { message }); + } + + callback.SafeInvoke(message); + }, + fastCallback, + faultCallback.SafeInvoke); + } + + private void ProcessUpdates(TLUpdatesBase updatesBase, IList messages, bool notifyNewMessage = false) + { + var updates = updatesBase as TLUpdates; + if (updates != null) + { + var messagesRandomIndex = new Dictionary(); + if (messages != null) + { + for (var i = 0; i < messages.Count; i++) + { + if (messages[i].RandomIndex != 0) + { + messagesRandomIndex[messages[i].RandomIndex] = messages[i]; + } + } + } + + var updateNewMessageIndex = new Dictionary(); + var updateNewChannelMessageIndex = new Dictionary(); + var updateMessageIdList = new List(); + for (var i = 0; i < updates.Updates.Count; i++) + { + var updateNewMessage = updates.Updates[i] as TLUpdateNewMessage; + if (updateNewMessage != null) + { + ProcessSelfMessage(updateNewMessage.Message); + + updateNewMessageIndex[updateNewMessage.Message.Index] = updateNewMessage; + continue; + } + + var updateNewChannelMessage = updates.Updates[i] as TLUpdateNewChannelMessage; + if (updateNewChannelMessage != null) + { + //ProcessSelfMessage(updateNewChannelMessage.Message); // no need to channel messages + + updateNewChannelMessageIndex[updateNewChannelMessage.Message.Index] = updateNewChannelMessage; + continue; + } + + var updateMessageId = updates.Updates[i] as TLUpdateMessageId; + if (updateMessageId != null) + { + updateMessageIdList.Add(updateMessageId); + continue; + } + } + + foreach (var updateMessageId in updateMessageIdList) + { + TLUpdateNewMessage updateNewMessage; + if (updateNewMessageIndex.TryGetValue(updateMessageId.Id.Value, out updateNewMessage)) + { + var cachedSendingMessage = _cacheService.GetMessage(updateMessageId.RandomId); + if (cachedSendingMessage != null) + { + updateNewMessage.Message.RandomId = updateMessageId.RandomId; + } + } + + TLUpdateNewChannelMessage updateNewChannelMessage; + if (updateNewChannelMessageIndex.TryGetValue(updateMessageId.Id.Value, out updateNewChannelMessage)) + { + var cachedSendingMessage = _cacheService.GetMessage(updateMessageId.RandomId); + if (cachedSendingMessage != null) + { + updateNewChannelMessage.Message.RandomId = updateMessageId.RandomId; + } + } + + TLMessage25 message; + if (messagesRandomIndex.TryGetValue(updateMessageId.RandomId.Value, out message)) + { + message.Id = updateMessageId.Id; + if (updateNewMessage != null) + { + var messageCommon = updateNewMessage.Message as TLMessageCommon; + if (messageCommon != null) + { + message.Date = messageCommon.Date; + } + } + else if (updateNewChannelMessage != null) + { + var messageCommon = updateNewChannelMessage.Message as TLMessageCommon; + if (messageCommon != null) + { + message.Date = messageCommon.Date; + } + } + } + } + } + + _updatesService.ProcessUpdates(updates, notifyNewMessage); + } + + public static void ProcessSelfMessage(TLMessageBase messageBase) + { + var messageCommon = messageBase as TLMessageCommon; + if (messageCommon != null + && messageCommon.ToId is TLPeerUser + && messageCommon.FromId != null + && messageCommon.FromId.Value == messageCommon.ToId.Id.Value) + { + messageCommon.Out = TLBool.True; + messageCommon.SetUnreadSilent(TLBool.False); + } + } + + public void GetBotCallbackAnswerAsync(TLInputPeerBase peer, TLInt messageId, TLString data, TLBool game, Action callback, Action faultCallback = null) + { + var key = string.Format("{0}_{1}_{2}_{3}", peer, messageId, data, game); + + TLBotCallbackAnswer58 botCallbackAnswer; + if (TryGetCachedValue(_cache, key, out botCallbackAnswer, IsCacheTimeValid)) + { + callback.SafeInvoke(botCallbackAnswer); + return; + } + + var obj = new TLGetBotCallbackAnswer { Peer = peer, MessageId = messageId, Data = data }; + if (game != null && game.Value) + { + obj.SetGame(); + } + + const string caption = "messages.getBotCallbackAnswer"; + SendInformativeMessage(caption, obj, + result => + { + SetCachedValue(ref _cache, key, result as ICachedObject, IsCacheTimeValid); + + callback.SafeInvoke(result); + }, + faultCallback); + } + + private Dictionary>> _cache; + + private static bool IsCacheTimeValid(DateTime cachedDate, ICachedObject cachedObject) + { + if (cachedObject != null && cachedDate.AddSeconds(cachedObject.CacheTime.Value) > DateTime.Now) + { + return true; + } + + return false; + } + + private static void SetCachedValue(ref Dictionary>> dict, string key, T result, Func predicate) + where T : class + { + var now = DateTime.Now; + if (!predicate(now, result)) return; + + dict = dict ?? new Dictionary>>(); + + dict[key] = new Tuple>(now, new WeakReference(result)); + } + + private static bool TryGetCachedValue(Dictionary>> dict, string key, out T1 cachedValue, Func predicate) + where T : class + where T1 : class + { + Tuple> tuple; + cachedValue = null; + + T target; + if (dict != null + && dict.TryGetValue(key, out tuple) + && tuple.Item2.TryGetTarget(out target) + && predicate(tuple.Item1, target)) + { + if (target is T1) + { + cachedValue = target as T1; + return true; + } + } + + return false; + } + + public void StartBotAsync(TLInputUserBase bot, TLString startParam, TLMessage25 message, Action callback, Action faultCallback = null) + { + var obj = new TLStartBot { Bot = bot, Peer = PeerToInputPeer(message.ToId), RandomId = message.RandomId, StartParam = startParam }; + + const string caption = "messages.startBot"; + StartBotAsyncInternal(obj, + result => + { + Execute.BeginOnUIThread(() => + { + message.Status = GetMessageStatus(_cacheService, message.ToId); + message.Media.LastProgress = 0.0; + message.Media.DownloadingProgress = 0.0; + }); + + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, new List { message }); + } + + callback.SafeInvoke(result); + }, + () => + { + //TLUtils.WriteLine(caption + " fast result " + message.RandomIndex, LogSeverity.Error); + //fastCallback(); + }, + faultCallback.SafeInvoke); + } + + public void UploadMediaAsync(TLInputPeerBase inputPeer, TLInputMediaBase inputMedia, Action callback, Action faultCallback = null) + { + var obj = new TLUploadMedia { Peer = inputPeer, Media = inputMedia }; + + const string caption = "messages.uploadMedia"; + SendInformativeMessage(caption, obj, callback, faultCallback); + } + + public void SendMultiMediaAsync(TLInputPeerBase inputPeer, TLVector inputMedia, TLMessage25 message, Action callback, Action faultCallback = null) + { + var obj = new TLSendMultiMedia { Flags = new TLInt(0), Peer = inputPeer, ReplyToMsgId = message.ReplyToMsgId, MultiMedia = inputMedia }; + + var message48 = message as TLMessage48; + if (message48 != null && message48.Silent) + { + obj.SetSilent(); + } + + const string caption = "messages.sendMultiMedia"; + SendMultiMediaAsyncInternal(obj, + result => + { + Execute.BeginOnUIThread(() => + { + message.Status = GetMessageStatus(_cacheService, message.ToId); + message.Media.LastProgress = 0.0; + message.Media.DownloadingProgress = 1.0; + + var mediaGroup = message.Media as TLMessageMediaGroup; + if (mediaGroup != null) + { + foreach (var m in mediaGroup.Group.OfType()) + { + m.Status = GetMessageStatus(_cacheService, message.ToId); + m.Media.LastProgress = 0.0; + m.Media.DownloadingProgress = 1.0; + } + } + }); + + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + var handled = false; + var message73 = message as TLMessage73; + if (message73 != null) + { + var mediaGroup = message73.Media as TLMessageMediaGroup; + if (mediaGroup != null) + { + var messages = new List(); + foreach (var item in mediaGroup.Group) + { + messages.Add((TLMessage25)item); + } + + if (messages.Count > 0) + { + handled = true; + ProcessUpdates(result, messages); + message.Id = messages[messages.Count - 1].Id; + message.Date = messages[messages.Count - 1].Date; + message.RandomId = new TLLong(0); + } + } + } + + if (!handled) + { + ProcessUpdates(result, new List { message }); + } + } + + callback.SafeInvoke(result); + }, + () => + { + + }, + faultCallback.SafeInvoke); + } + + public void SendMediaAsync(TLInputPeerBase inputPeer, TLInputMediaBase inputMedia, TLMessage34 message, Action callback, Action faultCallback = null) + { + var obj = new TLSendMedia { Flags = new TLInt(0), Peer = inputPeer, ReplyToMsgId = message.ReplyToMsgId, Media = inputMedia, Message = message.Message, RandomId = message.RandomId, ReplyMarkup = null, Entities = message.Entities }; + + if (message.IsChannelMessage) + { + obj.SetChannelMessage(); + } + + var message48 = message as TLMessage48; + if (message48 != null && message48.Silent) + { + obj.SetSilent(); + } + + const string caption = "messages.sendMedia"; + SendMediaAsyncInternal(obj, + result => + { + Execute.BeginOnUIThread(() => + { + message.Status = GetMessageStatus(_cacheService, message.ToId); + message.Media.LastProgress = 0.0; + message.Media.DownloadingProgress = 1.0; + }); + + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, new List { message }); + } + + callback.SafeInvoke(result); + }, + () => + { + + }, + faultCallback.SafeInvoke); + } + + public void SendBroadcastAsync(TLVector contacts, TLInputMediaBase inputMedia, TLMessage25 message, Action callback, Action fastCallback, Action faultCallback = null) + { + var randomId = new TLVector(); + for (var i = 0; i < contacts.Count; i++) + { + randomId.Add(TLLong.Random()); + } + + var obj = new TLSendBroadcast { Contacts = contacts, RandomId = randomId, Message = message.Message, Media = inputMedia }; + + + + const string caption = "messages.sendBroadcast"; + SendInformativeMessage(caption, + obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, new List { message }); + } + + var updates = result as TLUpdates; + if (updates != null) + { + var updateNewMessage = updates.Updates.FirstOrDefault(x => x is TLUpdateNewMessage) as TLUpdateNewMessage; + if (updateNewMessage != null) + { + var messageCommon = updateNewMessage.Message as TLMessageCommon; + if (messageCommon != null) + { + message.Date = new TLInt(messageCommon.DateIndex - 1); // Делаем бродкаст после всех чатов, в которые отправили, в списке диалогов + } + } + } + + //message.Id = result.Id; + message.Status = MessageStatus.Confirmed; + + callback.SafeInvoke(result); + }, + faultCallback); + } + + + + public void SendEncryptedAsync(TLInputEncryptedChat peer, TLLong randomId, TLString data, Action callback, Action fastCallback, Action faultCallback = null) + { + var obj = new TLSendEncrypted { Peer = peer, RandomId = randomId, Data = data }; + + SendEncryptedAsyncInternal( + obj, + result => + { + callback(result); + }, + () => + { + + }, + faultCallback); + } + + private object _sendEncryptedFileSyncRoot; + + public void SendEncryptedMultiMediaAsync(TLInputEncryptedChat peer, TLVector randomId, TLVector data, TLVector file, Action> callback, Action fastCallback, Action faultCallback = null) + { + var obj = new TLVector(); + for (var i = 0; i < randomId.Count; i++) + { + obj.Add(new TLSendEncryptedFile { Peer = peer, RandomId = randomId[i], Data = data[i], File = file[i] }); + } + + _sendEncryptedFileSyncRoot = _sendEncryptedFileSyncRoot ?? new object(); + var results = new TLVector(); + + SendEncryptedFileAsyncInternal( + obj, + result => + { + lock (_sendEncryptedFileSyncRoot) + { + results.Add(result); + } + + if (results.Count == randomId.Count) + { + callback.SafeInvoke(results); + } + }, + () => + { + + }, + faultCallback); + } + + public void SendEncryptedFileAsync(TLInputEncryptedChat peer, TLLong randomId, TLString data, TLInputEncryptedFileBase file, Action callback, Action fastCallback, Action faultCallback = null) + { + var obj = new TLSendEncryptedFile { Peer = peer, RandomId = randomId, Data = data, File = file }; + + SendEncryptedFileAsyncInternal( + obj, + callback, + () => + { + + }, + faultCallback); + } + + public void SendEncryptedServiceAsync(TLInputEncryptedChat peer, TLLong randomId, TLString data, Action callback, Action faultCallback = null) + { + var obj = new TLSendEncryptedService { Peer = peer, RandomId = randomId, Data = data }; + + SendEncryptedServiceAsyncInternal( + obj, + callback, + () => + { + + }, + faultCallback); + } + + public void ReadEncryptedHistoryAsync(TLInputEncryptedChat peer, TLInt maxDate, Action callback, + Action faultCallback = null) + { + var obj = new TLReadEncryptedHistory { Peer = peer, MaxDate = maxDate }; + + ReadEncryptedHistoryAsyncInternal(obj, callback, () => { }, faultCallback); + } + + public void SetEncryptedTypingAsync(TLInputEncryptedChat peer, TLBool typing, Action callback, Action faultCallback = null) + { + var obj = new TLSetEncryptedTyping { Peer = peer, Typing = typing }; + + SendInformativeMessage("messages.setEncryptedTyping", obj, callback, faultCallback); + } + + public void SetTypingAsync(TLInputPeerBase peer, TLBool typing, Action callback, Action faultCallback = null) + { + var action = typing.Value ? (TLSendMessageActionBase)new TLSendMessageTypingAction() : new TLSendMessageCancelAction(); + var obj = new TLSetTyping { Peer = peer, Action = action }; + + SendInformativeMessage("messages.setTyping", obj, callback, faultCallback); + } + + public void SetTypingAsync(TLInputPeerBase peer, TLSendMessageActionBase action, Action callback, Action faultCallback = null) + { + var obj = new TLSetTyping { Peer = peer, Action = action ?? new TLSendMessageTypingAction() }; + + SendInformativeMessage("messages.setTyping", obj, callback, faultCallback); + } + + public void GetMessagesAsync(TLVector id, Action callback, Action faultCallback = null) + { + var obj = new TLGetMessages { Id = id }; + + SendInformativeMessage("messages.getMessages", obj, callback, faultCallback); + } + + private static void ProcessPinnedId(IList result) + { + var pinnedIndex = 0; + foreach (var dialog in result) + { + var dialog53 = dialog as TLDialog53; + if (dialog53 != null && dialog53.IsPinned) + { + dialog53.PinnedId = new TLInt(pinnedIndex++); + } + } + } + + private static void ProcessUnread(TLDialogsBase result) + { + var dialogsCache = new Dictionary>(); + foreach (var dialogBase in result.Dialogs) + { + List dialogs; + if (dialogsCache.TryGetValue(dialogBase.TopMessageId.Value, out dialogs)) + { + dialogs.Add(dialogBase); + } + else + { + dialogsCache[dialogBase.TopMessageId.Value] = new List { dialogBase }; + } + } + + foreach (var messageBase in result.Messages) + { + ProcessSelfMessage(messageBase); + + var messageCommon = messageBase as TLMessageCommon; + if (messageCommon != null) + { + List dialogs; + if (dialogsCache.TryGetValue(messageBase.Index, out dialogs)) + { + TLDialog53 dialog53 = null; + if (messageCommon.ToId is TLPeerChannel) + { + dialog53 = + dialogs.FirstOrDefault( + x => x.Peer is TLPeerChannel && x.Peer.Id.Value == messageCommon.ToId.Id.Value) as + TLDialog53; + } + else if (messageCommon.ToId is TLPeerChat) + { + dialog53 = + dialogs.FirstOrDefault( + x => x.Peer is TLPeerChat && x.Peer.Id.Value == messageCommon.ToId.Id.Value) as TLDialog53; + } + else if (messageCommon.ToId is TLPeerUser) + { + var peer = messageCommon.Out.Value ? messageCommon.ToId : new TLPeerUser { Id = messageCommon.FromId }; + dialog53 = + dialogs.FirstOrDefault(x => x.Peer is TLPeerUser && x.Peer.Id.Value == peer.Id.Value) as + TLDialog53; + } + if (dialog53 != null) + { + if (messageCommon.Out.Value) + { + if (messageCommon.Index > dialog53.ReadOutboxMaxId.Value) + { + messageCommon.SetUnreadSilent(TLBool.True); + } + } + else + { + if (messageCommon.Index > dialog53.ReadInboxMaxId.Value) + { + messageCommon.SetUnreadSilent(TLBool.True); + } + } + } + } + } + } + } + + public void GetPeerDialogsAsync(TLInputPeerBase peer, Action callback, Action faultCallback = null) + { + var obj = new TLGetPeerDialogs { Peers = new TLVector { peer } }; + + SendInformativeMessage("messages.getPeerDialogs", obj, + result => + { + ProcessUnread(result.ToDialogs()); + + _cacheService.SyncDialogs(Stopwatch.StartNew(), + result.ToDialogs(), + r => + { + callback.SafeInvoke(r.ToPeerDialogs(result.State)); + }); + }, + faultCallback); + } + + public void GetPromoDialogAsync(TLInputPeerBase peer, Action callback, Action faultCallback = null) + { + var obj = new TLGetPeerDialogs { Peers = new TLVector { peer } }; + + SendInformativeMessage("messages.getPeerDialogs", obj, + result => + { + var oldDialogs = _cacheService.GetDialogs(); + var oldPromoDialogs = new List(); + foreach (var dialogBase in oldDialogs) + { + var dialog = dialogBase as TLDialog71; + if (dialog != null && dialog.IsPromo) + { + oldPromoDialogs.Add(dialog); + } + } + + ProcessUnread(result.ToDialogs()); + + foreach (var dialogBase in oldPromoDialogs) + { + _cacheService.UpdateDialogPromo(dialogBase, false); + } + + foreach (var dialogBase in result.Dialogs) + { + var channel = _cacheService.GetChat(dialogBase.Peer.Id) as TLChannel; + if (channel != null && channel.Left.Value) + { + _cacheService.UpdateDialogPromo(dialogBase, true); + } + } + + _cacheService.SyncDialogs(Stopwatch.StartNew(), + result.ToDialogs(), + r => + { + callback.SafeInvoke(r.ToPeerDialogs(result.State)); + }); + }, + faultCallback); + } + + public void GetPinnedDialogsAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetPinnedDialogs(); + + const string caption = "messages.getPinnedDialogs"; + SendInformativeMessage(caption, obj, + result => + { + var oldDialogs = _cacheService.GetDialogs(); + var oldPinnedDialogs = new List(); + foreach (var dialogBase in oldDialogs) + { + var dialog = dialogBase as TLDialog53; + if (dialog != null + && dialog.IsPinned + && result.Dialogs.FirstOrDefault(x => x.Index == dialog.Index) == null) + { + oldPinnedDialogs.Add(dialog); + } + } + + ProcessPinnedId(result.Dialogs); + + ProcessUnread(result.ToDialogs()); + + foreach (var dialogBase in oldPinnedDialogs) + { + _cacheService.UpdateDialogPinned(dialogBase.Peer, false); + } + + _cacheService.SyncDialogs(Stopwatch.StartNew(), + result.ToDialogs(), r => + { + callback.SafeInvoke(r.ToPeerDialogs(result.State)); + }); + }, + faultCallback); + } + + public void GetDialogsAsync(Stopwatch stopwatch, TLInt offsetDate, TLInt offsetId, TLInputPeerBase offsetPeer, TLInt limit, TLInt hash, Action callback, Action faultCallback = null) + { + var obj = new TLGetDialogs { Flags = new TLInt(0), /*FeedId = null,*/ OffsetDate = offsetDate, OffsetId = offsetId, OffsetPeer = offsetPeer, Limit = limit, Hash = hash }; + + if (offsetDate.Value != 0 + || offsetId.Value != 0 + || !(offsetPeer is TLInputPeerEmpty)) + { + obj.ExcludePinned = true; + } + + SendInformativeMessage("messages.getDialogs", obj, + result => + { + if (offsetDate.Value == 0 && !obj.ExcludePinned) + { + ProcessPinnedId(result.Dialogs); + } + + ProcessUnread(result); + + _cacheService.SyncDialogs(stopwatch, result, callback); + }, + faultCallback); + } + + public void GetChannelDialogsAsync(TLInt offset, TLInt limit, Action callback, Action faultCallback = null) + { + var obj = new TL.Functions.Channels.TLGetDialogs { Offset = offset, Limit = limit }; + + SendInformativeMessage("channels.getDialogs", obj, result => + { + //return; + var channelsCache = new Context(); + foreach (var chatBase in result.Chats) + { + var channel = chatBase as TLChannel; + if (channel != null) + { + channelsCache[channel.Index] = channel; + } + } + + var dialogsCache = new Context(); + foreach (var dialogBase in result.Dialogs) + { + var dialogChannel = dialogBase as TLDialogChannel; + if (dialogChannel != null) + { + var channelId = dialogChannel.Peer.Id.Value; + dialogsCache[channelId] = dialogChannel; + TLChannel channel; + if (channelsCache.TryGetValue(channelId, out channel)) + { + channel.ReadInboxMaxId = dialogChannel.ReadInboxMaxId; + //channel.UnreadCount = dialogChannel.UnreadCount; + //channel.UnreadImportantCount = dialogChannel.UnreadImportantCount; + channel.NotifySettings = dialogChannel.NotifySettings; + //channel.Pts = dialogChannel.Pts; + } + } + } + + //_cacheService.SyncChannelDialogs(result, callback); + _cacheService.SyncUsersAndChats(result.Users, result.Chats, x => + { + _cacheService.MergeMessagesAndChannels(result); + + callback.SafeInvoke(result); + }); + }, faultCallback); + } + + private void GetChannelHistoryAsyncInternal(bool sync, TLPeerBase peer, TLMessagesBase result, Action callback) + { + if (sync) + { + _cacheService.SyncPeerMessages(peer, result, false, false, callback); + } + else + { + _cacheService.AddChats(result.Chats, results => { }); + _cacheService.AddUsers(result.Users, results => { }); + callback(result); + } + } + + private void GetHistoryAsyncInternal(bool sync, TLPeerBase peer, TLMessagesBase result, Action callback) + { + if (sync) + { + _cacheService.SyncPeerMessages(peer, result, false, true, callback); + } + else + { + _cacheService.AddChats(result.Chats, results => { }); + _cacheService.AddUsers(result.Users, results => { }); + callback(result); + } + } + + public void GetHistoryAsync(Stopwatch timer, TLInputPeerBase inputPeer, TLPeerBase peer, bool sync, TLInt offsetDate, TLInt offset, TLInt maxId, TLInt limit, Action callback, Action faultCallback = null) + { + var obj = new TLGetHistory { Peer = inputPeer, AddOffset = offset, OffsetId = maxId, OffsetDate = offsetDate, Limit = limit, MaxId = new TLInt(int.MaxValue), MinId = new TLInt(0), Hash = new TLInt(0) }; + + //Telegram.Api.Helpers.Execute.ShowDebugMessage(string.Format("messages.getHistory offset_date=[{0} {1}], offset={2} max_id={3} limit={4}", offsetDate, TLUtils.ToDateTime(offsetDate).ToString("dd-MM-yyyy HH:mm:ss.f"), offset, maxId, limit)); + //Debug.WriteLine("UpdateItems start request elapsed=" + (timer != null? timer.Elapsed.ToString() : null)); + + SendInformativeMessage("messages.getHistory", obj, + result => + { + var peerChannel = inputPeer as TLInputPeerChannel; + if (peerChannel != null) + { + var channel = result.Chats.FirstOrDefault(x => x.Index == peerChannel.ChatId.Value) as TLChannel; + if (channel != null && channel.Left.Value) + { + sync = false; + } + } + //Debug.WriteLine("UpdateItems stop request elapsed=" + (timer != null ? timer.Elapsed.ToString() : null)); + + foreach (var message in result.Messages) + { + ProcessSelfMessage(message); + } + var replyId = new TLVector(); + var waitingList = new List(); + //for (var i = 0; i < result.Messages.Count; i++) + //{ + // var message25 = result.Messages[i] as TLMessage25; + // if (message25 != null + // && message25.ReplyToMsgId != null + // && message25.ReplyToMsgId.Value > 0) + // { + // var cachedReply = _cacheService.GetMessage(message25.ReplyToMsgId); + // if (cachedReply != null) + // { + // message25.Reply = cachedReply; + // } + // else + // { + // replyId.Add(message25.ReplyToMsgId); + // waitingList.Add(message25); + // } + // } + //} + + if (replyId.Count > 0) + { + //Debug.WriteLine("UpdateItems start GetMessages elapsed=" + (timer != null ? timer.Elapsed.ToString() : null)); + + GetMessagesAsync( + replyId, + messagesResult => + { + //Debug.WriteLine("UpdateItems stop GetMessages elapsed=" + (timer != null ? timer.Elapsed.ToString() : null)); + + _cacheService.AddChats(result.Chats, results => { }); + _cacheService.AddUsers(result.Users, results => { }); + + for (var i = 0; i < messagesResult.Messages.Count; i++) + { + for (var j = 0; j < waitingList.Count; j++) + { + var messageToReply = messagesResult.Messages[i] as TLMessageCommon; + if (messageToReply != null + && messageToReply.Index == waitingList[j].Index) + { + waitingList[j].Reply = messageToReply; + } + } + } + + var inputChannelPeer = inputPeer as TLInputPeerChannel; + if (inputChannelPeer != null) + { + var channel = _cacheService.GetChat(inputChannelPeer.ChatId) as TLChannel; + if (channel != null) + { + var maxIndex = channel.ReadInboxMaxId != null ? channel.ReadInboxMaxId.Value : 0; + foreach (var messageBase in messagesResult.Messages) + { + var messageCommon = messageBase as TLMessageCommon; + if (messageCommon != null + && !messageCommon.Out.Value + && messageCommon.Index > maxIndex) + { + messageCommon.SetUnread(TLBool.True); + } + } + } + } + + //Debug.WriteLine("UpdateItems stop GetMessages GetHistoryAsyncInternal elapsed=" + (timer != null ? timer.Elapsed.ToString() : null)); + + GetHistoryAsyncInternal(sync, peer, result, callback); + }, + faultCallback); + } + else + { + //Debug.WriteLine("UpdateItems GetHistoryAsyncInternal elapsed=" + (timer != null ? timer.Elapsed.ToString() : null)); + + GetHistoryAsyncInternal(sync, peer, result, callback); + } + }, + faultCallback); + } + + + public void GetChannelHistoryAsync(string debugInfo, TLInputPeerBase inputPeer, TLPeerBase peer, bool sync, TLInt offset, TLInt maxId, TLInt limit, Action callback, Action faultCallback = null) + { + var obj = new TLGetHistory { Peer = inputPeer, AddOffset = offset, OffsetId = maxId, OffsetDate = new TLInt(0), Limit = limit, MaxId = new TLInt(int.MaxValue), MinId = new TLInt(0), Hash = new TLInt(0) }; + + TLUtils.WriteLine(string.Format("{0} {1} messages.getHistory peer={2} offset={3} max_id={4} limit={5}", string.Empty, debugInfo, inputPeer, offset, maxId, limit), LogSeverity.Error); + SendInformativeMessage("messages.getHistory", obj, + result => + { + var peerChannel = inputPeer as TLInputPeerChannel; + if (peerChannel != null) + { + var channel = result.Chats.FirstOrDefault(x => x.Index == peerChannel.ChatId.Value) as TLChannel; + if (channel != null && channel.Left.Value) + { + sync = false; + } + } + + var replyId = new TLVector(); + var waitingList = new List(); + //for (var i = 0; i < result.Messages.Count; i++) + //{ + // var message25 = result.Messages[i] as TLMessage25; + // if (message25 != null + // && message25.ReplyToMsgId != null + // && message25.ReplyToMsgId.Value > 0) + // { + // var cachedReply = _cacheService.GetMessage(message25.ReplyToMsgId); + // if (cachedReply != null) + // { + // message25.Reply = cachedReply; + // } + // else + // { + // replyId.Add(message25.ReplyToMsgId); + // waitingList.Add(message25); + // } + // } + //} + + if (replyId.Count > 0) + { + GetMessagesAsync( + replyId, + messagesResult => + { + _cacheService.AddChats(result.Chats, results => { }); + _cacheService.AddUsers(result.Users, results => { }); + + for (var i = 0; i < messagesResult.Messages.Count; i++) + { + for (var j = 0; j < waitingList.Count; j++) + { + var messageToReply = messagesResult.Messages[i] as TLMessageCommon; + if (messageToReply != null + && messageToReply.Index == waitingList[j].Index) + { + waitingList[j].Reply = messageToReply; + } + } + } + + var inputChannelPeer = inputPeer as TLInputPeerChannel; + if (inputChannelPeer != null) + { + var channel = _cacheService.GetChat(inputChannelPeer.ChatId) as TLChannel; + if (channel != null) + { + var maxIndex = channel.ReadInboxMaxId != null ? channel.ReadInboxMaxId.Value : 0; + foreach (var messageBase in messagesResult.Messages) + { + var messageCommon = messageBase as TLMessageCommon; + if (messageCommon != null + && !messageCommon.Out.Value + && messageCommon.Index > maxIndex) + { + messageCommon.SetUnread(TLBool.True); + } + } + } + } + + GetChannelHistoryAsyncInternal(sync, peer, result, callback); + }, + faultCallback); + } + else + { + GetChannelHistoryAsyncInternal(sync, peer, result, callback); + } + }, + faultCallback); + } + + public void SearchAsync(TLInputPeerBase peer, TLString query, TLInputUserBase fromId, TLInputMessagesFilterBase filter, TLInt minDate, TLInt maxDate, TLInt addOffset, TLInt offsetId, TLInt limit, TLInt hash, Action callback, Action faultCallback = null) + { + Debug.WriteLine("messages.search query={0} from_id={7} filter={1} minDate={2} maxDate={3} offset={4} maxId={5} limit={6}", query, filter, maxDate, maxDate, addOffset, offsetId, limit, fromId); + + var obj = new TLSearch { Flags = new TLInt(0), Peer = peer, Query = query, FromId = fromId, Filter = filter, MinDate = minDate, MaxDate = maxDate, AddOffset = addOffset, OffsetId = offsetId, Limit = limit, MinId = new TLInt(0), MaxId = new TLInt(0), Hash = hash }; + + SendInformativeMessage("messages.search", obj, result => + { + callback.SafeInvoke(result); + }, faultCallback); + } + + public void SearchGlobalAsync(TLString query, TLInt offsetDate, TLInputPeerBase offsetPeer, TLInt offsetId, TLInt limit, Action callback, Action faultCallback = null) + { + TLUtils.WriteLine(string.Format("{0} messages.searchGlobal query={1} offset_date={2} offset_peer={3} offset_id={4} limit={5}", DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture), query, offsetDate, offsetPeer, offsetId, limit), LogSeverity.Error); + + var obj = new TLSearchGlobal { Query = query, OffsetDate = offsetDate, OffsetPeer = offsetPeer, OffsetId = offsetId, Limit = limit }; + + SendInformativeMessage("messages.searchGlobal", obj, result => + { + TLUtils.WriteLine(string.Format("{0} messages.searchGlobal result={1}", DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture), result.Messages.Count), LogSeverity.Error); + callback.SafeInvoke(result); + }, faultCallback); + } + + public void ReadHistoryAsync(TLInputPeerBase peer, TLInt maxId, TLInt offset, Action callback, Action faultCallback = null) + { + var obj = new TLReadHistory { Peer = peer, MaxId = maxId }; + + const string caption = "messages.readHistory"; + ReadHistoryAsyncInternal(obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + _updatesService.SetState(null, result.Pts, null, null, null, caption); + } + + callback.SafeInvoke(result); + }, + () => { }, + faultCallback.SafeInvoke); + } + + public void ReadMentionsAsync(TLInputPeerBase peer, Action callback, Action faultCallback = null) + { + var obj = new TLReadMentions { Peer = peer }; + + const string caption = "messages.readMentions"; + ReadMentionsAsyncInternal(obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + _updatesService.SetState(null, result.Pts, null, null, null, caption); + } + + callback.SafeInvoke(result); + }, + () => { }, + faultCallback.SafeInvoke); + } + + public void ReadMessageContentsAsync(TLVector id, Action callback, Action faultCallback = null) + { + var obj = new TLReadMessageContents { Id = id }; + + const string caption = "messages.readMessageContents"; + ReadMessageContentsAsyncInternal(obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + _updatesService.SetState(null, result.Pts, null, null, null, caption); + } + + callback.SafeInvoke(result); + }, + () => { }, + faultCallback.SafeInvoke); + } + + public void DeleteHistoryAsync(bool justClear, TLInputPeerBase peer, TLInt offset, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteHistory { Flags = new TLInt(0), Peer = peer, MaxId = new TLInt(int.MaxValue) }; + + if (justClear) + { + obj.SetJustClear(); + } + + const string caption = "messages.deleteHistory"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + _updatesService.SetState(result.Seq, result.Pts, null, null, null, caption); + } + + callback(result); + }, + faultCallback); + } + + public void DeleteMessagesAsync(bool revoke, TLVector id, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteMessages { Id = id, Revoke = revoke }; + + const string caption = "messages.deleteMessages"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + _updatesService.SetState(null, result.Pts, null, null, null, caption); + } + + callback(result); + }, + faultCallback); + } + + public void RestoreMessagesAsync(TLVector id, Action> callback, Action faultCallback = null) + { + var obj = new TLRestoreMessages { Id = id }; + + SendInformativeMessage("messages.restoreMessages", obj, callback, faultCallback); + } + + public void ReceivedMessagesAsync(TLInt maxId, Action> callback, Action faultCallback = null) + { + var obj = new TLReceivedMessages { MaxId = maxId }; + + SendInformativeMessage("messages.receivedMessages", obj, callback, faultCallback); + } + + public void ForwardMessageAsync(TLInputPeerBase peer, TLInt fwdMessageId, TLMessage25 message, Action callback, Action faultCallback = null) + { + var obj = new TLForwardMessage { Peer = peer, Id = fwdMessageId, RandomId = message.RandomId }; + + const string caption = "messages.forwardMessage"; + ForwardMessageAsyncInternal(obj, + result => + { + Execute.BeginOnUIThread(() => + { + message.Status = MessageStatus.Confirmed; + message.Media.LastProgress = 0.0; + message.Media.DownloadingProgress = 0.0; + }); + + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, new List { message }); + } + + callback.SafeInvoke(result); + }, + () => + { + + }, + faultCallback); + } + + private readonly object _forwardMessagesWithCommentSyncRoot = new object(); + + public void ForwardMessagesAsync(TLMessage25 commentMessage, TLInputPeerBase toPeer, TLVector id, IList messages, bool withMyScore, Action callback, Action faultCallback = null) + { + var randomId = new TLVector(); + foreach (var message in messages) + { + randomId.Add(message.RandomId); + } + + TLInputPeerBase fromPeer = null; + var message48 = messages.FirstOrDefault() as TLMessage48; + if (message48 != null) + { + fromPeer = message48.FwdFromChannelPeer; + } + + if (fromPeer == null) + { + var message40 = messages.FirstOrDefault() as TLMessage40; + if (message40 != null) + { + fromPeer = message40.FwdFromChannelPeer ?? PeerToInputPeer(message40.FwdFromPeer); + } + } + + var obj1 = commentMessage != null && !TLString.IsNullOrEmpty(commentMessage.Message) ? new TLSendMessage { Flags = new TLInt(0), Peer = toPeer, Message = commentMessage.Message, RandomId = commentMessage.RandomId } : null; + var obj2 = new TLForwardMessages { ToPeer = toPeer, Id = id, RandomIds = randomId, FromPeer = fromPeer, Flags = new TLInt(0) }; + + if (message48 != null && message48.IsChannelMessage) + { + obj2.SetChannelMessage(); + } + + if (message48 != null && message48.Silent) + { + obj2.SetSilent(); + } + + if (withMyScore) + { + obj2.SetWithMyScore(); + } + + var grouped = messages.OfType().FirstOrDefault(x => x.GroupedId != null) != null; + if (grouped) + { + obj2.SetGrouped(); + } + + const string caption1 = "messages.sendMessage"; + const string caption2 = "messages.forwardMessages"; + + var results = new TLUpdatesBase[2]; + + ForwardMessagesWithCommentAsyncInternal(obj1, obj2, + result => + { + bool invokeCallback; + + var multiPts = result as IMultiPts; + var shortSentMessage = result as TLUpdatesShortSentMessage; + if (shortSentMessage != null) + { + commentMessage.Flags = shortSentMessage.Flags; + if (shortSentMessage.HasMedia) + { + commentMessage._media = shortSentMessage.Media; + } + if (shortSentMessage.HasEntities) + { + var commentMessage70 = commentMessage as TLMessage70; + if (commentMessage70 != null) + { + commentMessage70.Entities = shortSentMessage.Entities; + } + } + + Execute.BeginOnUIThread(() => + { + commentMessage.Status = GetMessageStatus(_cacheService, commentMessage.ToId); + commentMessage.Date = shortSentMessage.Date; + if (shortSentMessage.Media is TLMessageMediaWebPage) + { + commentMessage.NotifyOfPropertyChange(() => commentMessage.Media); + } + +#if DEBUG + commentMessage.Id = shortSentMessage.Id; + commentMessage.NotifyOfPropertyChange(() => commentMessage.Id); + commentMessage.NotifyOfPropertyChange(() => commentMessage.Date); +#endif + }); + + _updatesService.SetState(multiPts, caption1); + + commentMessage.Id = shortSentMessage.Id; + _cacheService.SyncSendingMessage(commentMessage, null, + cachedMessage => + { + lock (_forwardMessagesWithCommentSyncRoot) + { + results[0] = result; + invokeCallback = obj1 == null || (results[0] != null && results[1] != null); + } + + if (invokeCallback) + { + callback.SafeInvoke(results); + } + }); + return; + } + + Execute.BeginOnUIThread(() => + { + commentMessage.Status = GetMessageStatus(_cacheService, commentMessage.ToId); + }); + + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption1); + } + else + { + ProcessUpdates(result, new List { commentMessage }); + } + + lock (_forwardMessagesWithCommentSyncRoot) + { + results[0] = result; + invokeCallback = obj1 == null || (results[0] != null && results[1] != null); + } + + if (invokeCallback) + { + callback.SafeInvoke(results); + } + }, + result => + { + Execute.BeginOnUIThread(() => + { + for (var i = 0; i < messages.Count; i++) + { + messages[i].Status = MessageStatus.Confirmed; + messages[i].Media.LastProgress = 0.0; + messages[i].Media.DownloadingProgress = 0.0; + } + }); + + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption2); + } + else + { + ProcessUpdates(result, messages); + } + + bool invokeCallback; + lock (_forwardMessagesWithCommentSyncRoot) + { + results[1] = result; + invokeCallback = obj1 == null || (results[0] != null && results[1] != null); + } + + if (invokeCallback) + { + callback.SafeInvoke(results); + } + }, + () => + { + + }, + faultCallback.SafeInvoke); + } + + public void ForwardMessagesAsync(TLInputPeerBase toPeer, TLVector id, IList messages, bool withMyScore, Action callback, Action faultCallback = null) + { + var randomId = new TLVector(); + foreach (var message in messages) + { + randomId.Add(message.RandomId); + } + + TLInputPeerBase fromPeer = null; + var message48 = messages.FirstOrDefault() as TLMessage48; + if (message48 != null) + { + fromPeer = message48.FwdFromChannelPeer; + } + + if (fromPeer == null) + { + var message40 = messages.FirstOrDefault() as TLMessage40; + if (message40 != null) + { + fromPeer = message40.FwdFromChannelPeer ?? PeerToInputPeer(message40.FwdFromPeer); + } + } + + var obj = new TLForwardMessages { ToPeer = toPeer, Id = id, RandomIds = randomId, FromPeer = fromPeer, Flags = new TLInt(0) }; + + if (message48 != null && message48.IsChannelMessage) + { + obj.SetChannelMessage(); + } + + if (message48 != null && message48.Silent) + { + obj.SetSilent(); + } + + if (withMyScore) + { + obj.SetWithMyScore(); + } + + const string caption = "messages.forwardMessages"; + + //Execute.ShowDebugMessage(string.Format(caption + " to_peer={0} from_peer={1} id={2} flags={3}", toPeer, fromPeer, string.Join(",", id), TLForwardMessages.ForwardMessagesFlagsString(obj.Flags))); + //Execute.ShowDebugMessage(caption + string.Format("id={0} random_id={1} from_peer={2} to_peer={3}", obj.Id.FirstOrDefault(), obj.RandomIds.FirstOrDefault(), obj.FromPeer, obj.ToPeer)); + + ForwardMessagesAsyncInternal(obj, + result => + { + Execute.BeginOnUIThread(() => + { + for (var i = 0; i < messages.Count; i++) + { + messages[i].Status = MessageStatus.Confirmed; + messages[i].Media.LastProgress = 0.0; + messages[i].Media.DownloadingProgress = 0.0; + } + }); + + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, messages); + } + + callback.SafeInvoke(result); + }, + () => + { + + }, + faultCallback.SafeInvoke); + } + + public void GetChatsAsync(TLVector id, Action callback, Action faultCallback = null) + { + var obj = new TLGetChats { Id = id }; + + SendInformativeMessage("messages.getChats", obj, callback, faultCallback); + } + + public void GetFullChatAsync(TLInt chatId, Action callback, Action faultCallback = null) + { + var obj = new TLGetFullChat { ChatId = chatId }; + + SendInformativeMessage( + "messages.getFullChat", obj, + messagesChatFull => + { + _cacheService.SyncChat(messagesChatFull, result => callback.SafeInvoke(messagesChatFull)); + }, + faultCallback); + } + + public void EditChatTitleAsync(TLInt chatId, TLString title, Action callback, Action faultCallback = null) + { + var obj = new TLEditChatTitle { ChatId = chatId, Title = title }; + + const string caption = "messages.editChatTitle"; + SendInformativeMessage(caption, + obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void EditChatPhotoAsync(TLInt chatId, TLInputChatPhotoBase photo, Action callback, Action faultCallback = null) + { + var obj = new TLEditChatPhoto { ChatId = chatId, Photo = photo }; + + const string caption = "messages.editChatPhoto"; + SendInformativeMessage(caption, + obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null, true); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void AddChatUserAsync(TLInt chatId, TLInputUserBase userId, TLInt fwdLimit, Action callback, Action faultCallback = null) + { + var obj = new TLAddChatUser { ChatId = chatId, UserId = userId, FwdLimit = fwdLimit }; + + const string caption = "messages.addChatUser"; + SendInformativeMessage(caption, + obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void DeleteChatUserAsync(TLInt chatId, TLInputUserBase userId, Action callback, Action faultCallback = null) + { + var obj = new TLDeleteChatUser { ChatId = chatId, UserId = userId }; + + const string caption = "messages.deleteChatUser"; + SendInformativeMessage(caption, + obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void CreateChatAsync(TLVector users, TLString title, Action callback, Action faultCallback = null) + { + var obj = new TLCreateChat { Users = users, Title = title }; + + const string caption = "messages.createChat"; + SendInformativeMessage(caption, + obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void ExportChatInviteAsync(TLInt chatId, Action callback, Action faultCallback = null) + { + var obj = new TLExportChatInvite { ChatId = chatId }; + + SendInformativeMessage("messages.exportChatInvite", obj, callback, faultCallback); + } + + public void CheckChatInviteAsync(TLString hash, Action callback, Action faultCallback = null) + { + var obj = new TLCheckChatInvite { Hash = hash }; + + SendInformativeMessage("messages.checkChatInvite", obj, + result => + { + var chatInvite = result as TLChatInvite54; + if (chatInvite != null) + { + _cacheService.SyncUsers(chatInvite.Participants, participants => + { + chatInvite.Participants = participants; + callback.SafeInvoke(result); + }); + } + else + { + callback.SafeInvoke(result); + } + } + , faultCallback); + } + + public void ImportChatInviteAsync(TLString hash, Action callback, Action faultCallback = null) + { + var obj = new TLImportChatInvite { Hash = hash }; + + const string caption = "messages.importChatInvite"; + SendInformativeMessage(caption, + obj, + result => + { + var updates = result as TLUpdates; + if (updates != null) + { + _cacheService.SyncUsersAndChats(updates.Users, updates.Chats, tuple => { }); + } + + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void SendActionsAsync(List actions, Action callback, Action faultCallback = null) + { + var container = new TLContainer { Messages = new List() }; + var historyItems = new List(); + for (var i = 0; i < actions.Count; i++) + { + var obj = actions[i]; + int sequenceNumber; + TLLong messageId; + lock (_activeTransportRoot) + { + sequenceNumber = _activeTransport.SequenceNumber * 2 + 1; + _activeTransport.SequenceNumber++; + messageId = _activeTransport.GenerateMessageId(true); + } + + var data = i > 0 ? new TLInvokeAfterMsg { MsgId = container.Messages[i - 1].MessageId, Object = obj } : obj; + var invokeWithoutUpdates = new TLInvokeWithoutUpdates { Object = data }; + + var transportMessage = new TLContainerTransportMessage + { + MessageId = messageId, + SeqNo = new TLInt(sequenceNumber), + MessageData = invokeWithoutUpdates + }; + + var historyItem = new HistoryItem + { + SendTime = DateTime.Now, + Caption = "messages.containerPart" + i, + Object = obj, + Message = transportMessage, + Callback = result => callback(obj, result), + AttemptFailed = null, + FaultCallback = faultCallback, + ClientTicksDelta = ClientTicksDelta, + Status = RequestStatus.Sent, + }; + historyItems.Add(historyItem); + + container.Messages.Add(transportMessage); + } + + + lock (_historyRoot) + { + foreach (var historyItem in historyItems) + { + _history[historyItem.Hash] = historyItem; + } + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + + SendNonInformativeMessage("messages.container", container, result => callback(null, result), faultCallback); + } + + public void ToggleChatAdminsAsync(TLInt chatId, TLBool enabled, Action callback, Action faultCallback = null) + { + var obj = new TLToggleChatAdmins { ChatId = chatId, Enabled = enabled }; + + const string caption = "messages.toggleChatAdmins"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void EditChatAdminAsync(TLInt chatId, TLInputUserBase userId, TLBool isAdmin, Action callback, Action faultCallback = null) + { + var obj = new TLEditChatAdmin { ChatId = chatId, UserId = userId, IsAdmin = isAdmin }; + + SendInformativeMessage("messages.editChatAdmin", obj, callback, faultCallback); + } + + public void DeactivateChatAsync(TLInt chatId, TLBool enabled, Action callback, Action faultCallback = null) + { + var obj = new TLDeactivateChat { ChatId = chatId, Enabled = enabled }; + + const string caption = "messages.deactivateChat"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void HideReportSpamAsync(TLInputPeerBase peer, Action callback, Action faultCallback = null) + { + var obj = new TLHideReportSpam { Peer = peer }; + + const string caption = "messages.hideReportSpam"; + SendInformativeMessage(caption, obj, callback.SafeInvoke, faultCallback); + } + + public void GetPeerSettingsAsync(TLInputPeerBase peer, Action callback, Action faultCallback = null) + { + var obj = new TLGetPeerSettings { Peer = peer }; + + const string caption = "messages.getPeerSettings"; + SendInformativeMessage(caption, obj, callback.SafeInvoke, faultCallback); + } + + public void MigrateChatAsync(TLInt chatId, Action callback, Action faultCallback = null) + { + var obj = new TLMigrateChat { ChatId = chatId }; + + const string caption = "messages.migrateChat"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public int SendingMessages + { + get + { + var result = 0; + lock (_historyRoot) + { + foreach (var historyItem in _history.Values) + { + if (historyItem.Caption.StartsWith("messages.containerPart")) + { + result++; + break; + } + } + } + + return result; + } + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Payments.cs b/Telegram.Api/Services/MTProtoService.Payments.cs new file mode 100755 index 0000000..5422f7b --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Payments.cs @@ -0,0 +1,109 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.Extensions; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Payments; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void GetPaymentFormAsync(TLInt msgId, Action callback, Action faultCallback = null) + { + var obj = new TLGetPaymentForm { MsgId = msgId }; + + const string caption = "payments.getPaymentForm"; + SendInformativeMessage(caption, obj, + result => _cacheService.SyncUsers(result.Users, users => + { + result.Users = users; + callback.SafeInvoke(result); + }), + faultCallback); + } + + public void SendPaymentFormAsync(TLInt msgId, TLString requestedInfoId, TLString shippingOptionId, TLInputPaymentCredentialsBase credentials, Action callback, Action faultCallback = null) + { + var obj = new TLSendPaymentForm + { + Flags = new TLInt(0), + MsgId = msgId, + RequestedInfoId = requestedInfoId, + ShippingOptionId = shippingOptionId, + Credentials = credentials + }; + + const string caption = "payments.savePaymentForm"; + SendInformativeMessage(caption, obj, + result => + { + var paymentResult = result as TLPaymentResult; + if (paymentResult != null) + { + var multiPts = paymentResult.Updates as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(paymentResult.Updates, null, true); + } + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void ValidateRequestedInfoAsync(bool save, TLInt msgId, TLPaymentRequestedInfo info, Action callback, Action faultCallback = null) + { + var obj = new TLValidateRequestedInfo + { + Flags = new TLInt(0), + Save = save, + MsgId = msgId, + Info = info + }; + + const string caption = "payments.validateRequestedInfo"; + SendInformativeMessage(caption, obj, callback.SafeInvoke, faultCallback); + } + + public void GetSavedInfoAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetSavedInfo(); + + const string caption = "payments.getSavedInfo"; + SendInformativeMessage(caption, obj, callback.SafeInvoke, faultCallback); + } + + public void ClearSavedInfoAsync(bool credentials, bool info, Action callback, Action faultCallback = null) + { + var obj = new TLClearSavedInfo{ Flags = new TLInt(0), Credentials = credentials, Info = info }; + + const string caption = "payments.clearSavedInfo"; + SendInformativeMessage(caption, obj, callback.SafeInvoke, faultCallback); + } + + public void GetPaymentReceiptAsync(TLInt msgId, Action callback, Action faultCallback = null) + { + var obj = new TLGetPaymentReceipt{ MsgId = msgId }; + + const string caption = "payments.getGetReceipt"; + SendInformativeMessage(caption, obj, + result => _cacheService.SyncUsers(result.Users, users => + { + result.Users = users; + callback.SafeInvoke(result); + }), + faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Phone.cs b/Telegram.Api/Services/MTProtoService.Phone.cs new file mode 100755 index 0000000..6f87cd0 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Phone.cs @@ -0,0 +1,105 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.Extensions; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Phone; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void GetCallConfigAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetCallConfig(); + + SendInformativeMessage("phone.requestCall", obj, callback, faultCallback); + } + + public void RequestCallAsync(TLInputUserBase userId, TLInt randomId, TLString gaHash, TLPhoneCallProtocol protocol, Action callback, Action faultCallback = null) + { + var obj = new TLRequestCall { UserId = userId, RandomId = randomId, GAHash = gaHash, Protocol = protocol }; + + SendInformativeMessage("phone.requestCall", obj, callback, faultCallback); + } + + public void AcceptCallAsync(TLInputPhoneCall peer, TLString gb, TLPhoneCallProtocol protocol, Action callback, Action faultCallback = null) + { + var obj = new TLAcceptCall { Peer = peer, GB = gb, Protocol = protocol }; + + SendInformativeMessage("phone.acceptCall", obj, callback, faultCallback); + } + + public void ConfirmCallAsync(TLInputPhoneCall peer, TLString ga, TLLong keyFingerprint, TLPhoneCallProtocol protocol, Action callback, Action faultCallback = null) + { + var obj = new TLConfirmCall { Peer = peer, GA = ga, KeyFingerprint = keyFingerprint, Protocol = protocol }; + + SendInformativeMessage("phone.confirmCall", obj, callback, faultCallback); + } + + public void ReceivedCallAsync(TLInputPhoneCall peer, Action callback, Action faultCallback = null) + { + var obj = new TLReceivedCall { Peer = peer }; + + SendInformativeMessage("phone.receivedCall", obj, callback, faultCallback); + } + + public void DiscardCallAsync(TLInputPhoneCall peer, TLInt duration, TLPhoneCallDiscardReasonBase reason, TLLong connectionId, Action callback, Action faultCallback = null) + { + var obj = new TLDiscardCall { Peer = peer, Duration = duration, Reason = reason, ConnectionId = connectionId }; + + const string caption = "phone.discardCall"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null, true); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void SetCallRatingAsync(TLInputPhoneCall peer, TLInt rating, TLString comment, Action callback, Action faultCallback = null) + { + var obj = new TLSetCallRating { Peer = peer, Rating = rating, Comment = comment }; + + const string caption = "phone.setCallRating"; + SendInformativeMessage(caption, obj, + result => + { + var multiPts = result as IMultiPts; + if (multiPts != null) + { + _updatesService.SetState(multiPts, caption); + } + else + { + ProcessUpdates(result, null, true); + } + + callback.SafeInvoke(result); + }, + faultCallback); + } + + public void SaveCallDebugAsync(TLInputPhoneCall peer, TLDataJSON debug, Action callback, Action faultCallback = null) + { + var obj = new TLSaveCallDebug { Peer = peer, Debug = debug }; + + SendInformativeMessage("phone.saveCallDebug", obj, callback, faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Photos.cs b/Telegram.Api/Services/MTProtoService.Photos.cs new file mode 100755 index 0000000..42257cb --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Photos.cs @@ -0,0 +1,37 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Photos; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void UploadProfilePhotoAsync(TLInputFile file, Action callback, Action faultCallback = null) + { + var obj = new TLUploadProfilePhoto { File = file }; + + SendInformativeMessage("photos.uploadProfilePhoto", obj, callback, faultCallback); + } + + public void UpdateProfilePhotoAsync(TLInputPhotoBase id, Action callback, Action faultCallback = null) + { + var obj = new TLUpdateProfilePhoto{ Id = id }; + + SendInformativeMessage("photos.updateProfilePhoto", obj, callback, faultCallback); + } + + public void GetUserPhotosAsync(TLInputUserBase userId, TLInt offset, TLLong maxId, TLInt limit, Action callback, Action faultCallback = null) + { + var obj = new TLGetUserPhotos { UserId = userId, Offset = offset, MaxId = maxId, Limit = limit }; + + SendInformativeMessage("photos.getUserPhotos", obj, callback, faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.SecretChats.cs b/Telegram.Api/Services/MTProtoService.SecretChats.cs new file mode 100755 index 0000000..1244f47 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.SecretChats.cs @@ -0,0 +1,60 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.Extensions; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Messages; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void RekeyAsync(TLEncryptedChatBase chat, Action callback) + { + //GetGA() + } + + public void GetDHConfigAsync(TLInt version, TLInt randomLength, Action callback, Action faultCallback = null) + { + var obj = new TLGetDHConfig { Version = version, RandomLength = randomLength }; + + SendInformativeMessage("messages.getDhConfig", obj, callback, faultCallback); + } + + public void RequestEncryptionAsync(TLInputUserBase userId, TLInt randomId, TLString ga, Action callback, Action faultCallback = null) + { + var obj = new TLRequestEncryption { UserId = userId, RandomId = randomId, G_A = ga }; + + SendInformativeMessage("messages.requestEncryption", obj, + encryptedChat => + { + _cacheService.SyncEncryptedChat(encryptedChat, callback.SafeInvoke); + }, + faultCallback); + } + + public void AcceptEncryptionAsync(TLInputEncryptedChat peer, TLString gb, TLLong keyFingerprint, Action callback, Action faultCallback = null) + { + var obj = new TLAcceptEncryption { Peer = peer, GB = gb, KeyFingerprint = keyFingerprint }; + + SendInformativeMessage("messages.acceptEncryption", obj, + encryptedChat => + { + _cacheService.SyncEncryptedChat(encryptedChat, callback.SafeInvoke); + }, + faultCallback); + } + + public void DiscardEncryptionAsync(TLInt chatId, Action callback, Action faultCallback = null) + { + var obj = new TLDiscardEncryption { ChatId = chatId }; + + SendInformativeMessage("messages.discardEncryption", obj, callback, faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.SendingQueue.cs b/Telegram.Api/Services/MTProtoService.SendingQueue.cs new file mode 100755 index 0000000..8fa7fab --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.SendingQueue.cs @@ -0,0 +1,651 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using Telegram.Api.Extensions; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Channels; +using Telegram.Api.TL.Functions.Messages; +using Action = System.Action; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + private readonly object _sendingQueueSyncRoot = new object(); + + private readonly List _sendingQueue = new List(); + + private static Timer _sendingTimer; + + private static void StartSendingTimer() + { + //Helpers.Execute.ShowDebugMessage("MTProtoService.StartSendingTimer"); + _sendingTimer.Change(TimeSpan.FromSeconds(Constants.ResendMessageInterval), TimeSpan.FromSeconds(Constants.ResendMessageInterval)); + } + + private static void StopSendingTimer() + { + //Helpers.Execute.ShowDebugMessage("MTProtoService.StoptSendingTimer"); + _sendingTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + + private static void CheckSendingMessages(object state) + { +#if DEBUG + if (Debugger.IsAttached) return; +#endif + + var service = (MTProtoService)state; + + service.ProcessQueue(); + } + + private void ReadEncryptedHistoryAsyncInternal(TLReadEncryptedHistory message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.readEncryptedHistory", int.MaxValue, message, callback, fastCallback, faultCallback); + } + + private void ReadChannelHistoryAsyncInternal(TLReadChannelHistory message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("channels.readHistory", int.MaxValue, message, callback, fastCallback, faultCallback); + } + + private void ReadMessageContentsAsyncInternal(TL.Functions.Channels.TLReadMessageContents message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("channels.readMessageContents", int.MaxValue, message, callback, fastCallback, faultCallback); + } + + private void ReadHistoryAsyncInternal(TLReadHistory message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.readHistory", int.MaxValue, message, callback, fastCallback, faultCallback); + } + + private void ReadMentionsAsyncInternal(TLReadMentions message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.readMentions", int.MaxValue, message, callback, fastCallback, faultCallback); + } + + private void ReadMessageContentsAsyncInternal(TL.Functions.Messages.TLReadMessageContents message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.readMessageContents", int.MaxValue, message, callback, fastCallback, faultCallback); + } + + private void SendEncryptedAsyncInternal(TLSendEncrypted message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.sendEncrypted", Constants.MessageSendingInterval, message, callback, fastCallback, faultCallback); + } + + private void SendEncryptedFileAsyncInternal(TLSendEncryptedFile message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.sendEncryptedFile", Constants.MessageSendingInterval, message, callback, fastCallback, faultCallback); + } + + private void SendEncryptedFileAsyncInternal(TLVector messages, Action callback, Action fastCallback, Action faultCallback) + { + for (var i = 0; i < messages.Count - 1; i++) + { + AddAsyncInternal("messages.sendEncryptedFile", Constants.MessageSendingInterval, messages[i], callback, fastCallback, faultCallback, 10); + } + + SendAsyncInternal("messages.sendEncryptedFile", Constants.MessageSendingInterval, messages[messages.Count - 1], callback, fastCallback, faultCallback, 10); + } + + private void SendEncryptedServiceAsyncInternal(TLSendEncryptedService message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.sendEncryptedService", Constants.MessageSendingInterval, message, callback, fastCallback, faultCallback); + } + + private void SendMessageAsyncInternal(TLSendMessage message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.sendMessage", Constants.MessageSendingInterval, message, callback, fastCallback, faultCallback); + } + + private void SendInlineBotResultAsyncInternal(TLSendInlineBotResult message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.sendInlineBotResult", Constants.MessageSendingInterval, message, callback, fastCallback, faultCallback); + } + + private void SendMediaAsyncInternal(TLSendMedia message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.sendMedia", Constants.MessageSendingInterval, message, callback, fastCallback, faultCallback); + } + + private void SendMultiMediaAsyncInternal(TLSendMultiMedia message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.sendMultiMedia", Constants.MessageSendingInterval, message, callback, fastCallback, faultCallback); + } + + private void StartBotAsyncInternal(TLStartBot message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.startBot", Constants.MessageSendingInterval, message, callback, fastCallback, faultCallback); + } + + private void ForwardMessageAsyncInternal(TLForwardMessage message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.forwardMessage", Constants.MessageSendingInterval, message, callback, fastCallback, faultCallback); + } + + private void ForwardMessagesAsyncInternal(TLForwardMessages message, Action callback, Action fastCallback, Action faultCallback) + { + SendAsyncInternal("messages.forwardMessages", Constants.MessageSendingInterval, message, callback, fastCallback, faultCallback); + } + + private void ForwardMessagesWithCommentAsyncInternal(TLSendMessage message1, TLForwardMessages message2, Action callback1, Action callback2, Action fastCallback, Action faultCallback) + { + if (message1 != null) AddAsyncInternal("messages.sendMessages", Constants.MessageSendingInterval, message1, callback1, fastCallback, faultCallback, 10); + SendAsyncInternal("messages.forwardMessages", Constants.MessageSendingInterval, message2, callback2, fastCallback, faultCallback, 10); + } + + private HistoryItem AddAsyncInternal(string caption, double timeout, TLObject obj, Action callback, Action fastCallback, Action faultCallback, int timeoutToResend = 0) where T : TLObject + { + int sequenceNumber; + TLLong messageId; + lock (_activeTransportRoot) + { + sequenceNumber = _activeTransport.SequenceNumber * 2 + 1; + _activeTransport.SequenceNumber++; + messageId = _activeTransport.GenerateMessageId(true); + } + + Debug.WriteLine("AddAsyncInternal msg_id={0} caption={1}", messageId, caption); + + var transportMessage = new TLContainerTransportMessage + { + MessageId = messageId, + SeqNo = new TLInt(sequenceNumber), + MessageData = obj + }; + + var now = DateTime.Now; + var sendBeforeTime = now.AddSeconds(timeout); + var sendingItem = new HistoryItem + { + SendTime = DateTime.MinValue, + TimeToResend = timeoutToResend, + SendBeforeTime = sendBeforeTime, + Caption = caption, + Object = obj, + Message = transportMessage, + Callback = result => callback((T)result), + FastCallback = fastCallback, + FaultCallback = null, // чтобы не вылететь по таймауту не сохраняем сюда faultCallback, а просто запоминаем последнюю ошибку, + FaultQueueCallback = faultCallback, // для MTProto.CleanupQueue + InvokeAfter = null, // устанвливаем в момент создания контейнера historyItems.LastOrDefault(), + Status = RequestStatus.ReadyToSend, + }; + + //обрабатываем ошибки + sendingItem.FaultCallback = error => ProcessFault(sendingItem, error); + + AddActionInfoToFile(TLUtils.DateToUniversalTimeTLInt(ClientTicksDelta, sendBeforeTime), obj); + + lock (_sendingQueueSyncRoot) + { + _sendingQueue.Add(sendingItem); + } + return sendingItem; + } + + private void SendAsyncInternal(string caption, double timeout, TLObject obj, Action callback, Action fastCallback, Action faultCallback, int timeoutToResend = 0) where T : TLObject + { + var sendingItem = AddAsyncInternal(caption, timeout, obj, callback, fastCallback, faultCallback, timeoutToResend); + + lock (_sendingQueueSyncRoot) + { + StartSendingTimer(); + } + + ProcessQueue(); + } + + private void ProcessFault(HistoryItem item, TLRPCError error) + { + item.LastError = error; + if (error != null + && (error.CodeEquals(ErrorCode.BAD_REQUEST) + || error.CodeEquals(ErrorCode.FLOOD) + || error.CodeEquals(ErrorCode.UNAUTHORIZED) + || error.CodeEquals(ErrorCode.INTERNAL))) + { + RemoveFromQueue(item); + item.FaultQueueCallback.SafeInvoke(error); + } + } + + private void ProcessQueue() + { + CleanupQueue(); + + SendQueue(); + } + + private void SendQueue() + { + List itemsSnapshort; + lock (_sendingQueueSyncRoot) + { + var now = DateTime.Now; + itemsSnapshort = _sendingQueue.Where(x => x.SendTime.AddSeconds(x.TimeToResend) < now).ToList(); + } + if (itemsSnapshort.Count == 0) return; + + var historyItems = new List(); + for (var i = 0; i < itemsSnapshort.Count; i++) + { + itemsSnapshort[i].SendTime = DateTime.Now; + itemsSnapshort[i].InvokeAfter = historyItems.LastOrDefault(); + historyItems.Add(itemsSnapshort[i]); + } + +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + + lock (_historyRoot) + { + for (var i = 0; i < historyItems.Count; i++) + { + _history[historyItems[i].Hash] = historyItems[i]; + } + } + + var container = CreateContainer(historyItems); + + Debug.WriteLine("send container msg_count=" + container.Messages.Count); + + SendNonInformativeMessage( + "container.sendMessages", + container, + result => + { + // переотправка сейчас по таймеру раз в 5 сек + // этот метод никогда не вызывается, т.к. не используется в SendNonInformativeMessage для container.sendMessages + //lock (_queueSyncRoot) + //{ + // // fast aknowledgments + // _sendingQueue.Remove(item); + //} + + + //item.FastCallback.SafeInvoke(); + }, + error => + { + // переотправка сейчас по таймеру раз в 5 сек + //FaultSending(error, item); + }); + } + + private void CleanupQueue() + { + var itemsToRemove = new List(); + + lock (_sendingQueueSyncRoot) + { + var now = DateTime.Now; + for (var i = 0; i < _sendingQueue.Count; i++) + { + var historyItem = _sendingQueue[i]; + if (historyItem.SendBeforeTime > now) continue; + + itemsToRemove.Add(historyItem); + _sendingQueue.RemoveAt(i--); + } + + if (_sendingQueue.Count == 0) + { + StopSendingTimer(); + } + } + + lock (_historyRoot) + { + for (var i = 0; i < itemsToRemove.Count; i++) + { + _history.Remove(itemsToRemove[i].Hash); + } + } + + var actions = new TLVector(); + for (var i = 0; i < itemsToRemove.Count; i++) + { + actions.Add(itemsToRemove[i].Object); + } + RemoveActionInfoFromFile(actions); + + Helpers.Execute.BeginOnThreadPool(() => + { + foreach (var item in itemsToRemove) + { + item.FaultQueueCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("MTProtoService.CleanupQueue") }); + } + }); + } + + public void ClearQueue() + { + var itemsToRemove = new List(); + + lock (_sendingQueueSyncRoot) + { + var now = DateTime.Now; + for (var i = 0; i < _sendingQueue.Count; i++) + { + var historyItem = _sendingQueue[i]; + + itemsToRemove.Add(historyItem); + _sendingQueue.RemoveAt(i--); + } + + if (_sendingQueue.Count == 0) + { + StopSendingTimer(); + } + } + + lock (_historyRoot) + { + for (var i = 0; i < itemsToRemove.Count; i++) + { + _history.Remove(itemsToRemove[i].Hash); + } + } + + var actions = new TLVector(); + for (var i = 0; i < itemsToRemove.Count; i++) + { + actions.Add(itemsToRemove[i].Object); + } + + ClearActionInfoFile(); + + Helpers.Execute.BeginOnThreadPool(() => + { + foreach (var item in itemsToRemove) + { + item.FaultQueueCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("MTProtoService.CleanupQueue") }); + } + }); + } + + private void RemoveFromQueue(HistoryItem item) + { + if (item == null) + { + Helpers.Execute.ShowDebugMessage("MTProtoService.RemoveFromQueue item=null"); + return; + } + + lock (_sendingQueueSyncRoot) + { + _sendingQueue.Remove(item); + } + + RemoveActionInfoFromFile(item.Object); + } + + public void RemoveFromQueue(TLLong id) + { + HistoryItem item = null; + lock (_sendingQueueSyncRoot) + { + foreach (var historyItem in _sendingQueue) + { + var randomId = historyItem.Object as IRandomId; + if (randomId != null && randomId.RandomId.Value == id.Value) + { + item = historyItem; + break; + } + } + if (item != null) + { + _sendingQueue.Remove(item); + } + } + + RemoveActionInfoFromFile(id); + } + + private readonly object _actionsSyncRoot = new object(); + + private readonly object _actionInfoSyncRoot = new object(); + + private TLVector _actionInfo; + + public TLVector GetActionInfoFromFile() + { + if (_actionInfo != null) + { + return _actionInfo; + } + + _actionInfo = TLUtils.OpenObjectFromMTProtoFile>(_actionsSyncRoot, Constants.ActionQueueFileName) ?? new TLVector(); + + return _actionInfo; + } + + private void SaveActionInfoToFile(TLVector data) + { + TLUtils.SaveObjectToMTProtoFile(_actionsSyncRoot, Constants.ActionQueueFileName, data); + } + + private void AddActionInfoToFile(TLInt sendBefore, TLObject obj) + { + if (!TLUtils.IsValidAction(obj)) + { + return; + } + + lock (_actionInfoSyncRoot) + { + var actions = GetActionInfoFromFile(); + + var actionInfo = new TLActionInfo + { + Action = obj, + SendBefore = sendBefore + }; + actions.Add(actionInfo); + + SaveActionInfoToFile(actions); + } + } + + private void RemoveActionInfoFromFile(TLVector objects) + { + lock (_actionInfoSyncRoot) + { + var actions = GetActionInfoFromFile(); + + foreach (var obj in objects) + { + RemoveActionInfoCommon(actions, obj); + } + + SaveActionInfoToFile(actions); + } + } + + public static void RemoveActionInfoCommon(TLVector actions, TLObject obj) + { + for (var i = 0; i < actions.Count; i++) + { + if (actions[i].Action.GetType() == obj.GetType()) + { + if (actions[i].Action == obj) + { + actions.RemoveAt(i--); + continue; + } + + var randomId1 = actions[i].Action as IRandomId; + var randomId2 = obj as IRandomId; + if (randomId1 != null + && randomId2 != null + && randomId1.RandomId.Value == randomId2.RandomId.Value) + { + actions.RemoveAt(i--); + continue; + } + } + } + } + + private void RemoveActionInfoFromFile(TLLong id) + { + lock (_actionInfoSyncRoot) + { + var actions = GetActionInfoFromFile(); + + for (var i = 0; i < actions.Count; i++) + { + var randomId = actions[i].Action as IRandomId; + if (randomId != null + && randomId.RandomId.Value == id.Value) + { + actions.RemoveAt(i--); + } + } + + SaveActionInfoToFile(actions); + } + } + + private void RemoveActionInfoFromFile(TLObject obj) + { + lock (_actionInfoSyncRoot) + { + var actions = GetActionInfoFromFile(); + + RemoveActionInfoCommon(actions, obj); + + SaveActionInfoToFile(actions); + } + } + + public void RemoveActionInfoFromFile(IEnumerable obj) + { + lock (_actionInfoSyncRoot) + { + var actions = GetActionInfoFromFile(); + + foreach (var o in obj) + { + RemoveActionInfoCommon(actions, o); + } + + SaveActionInfoToFile(actions); + } + } + + public void ClearActionInfoFile() + { + lock (_actionInfoSyncRoot) + { + var actions = new TLVector(); + SaveActionInfoToFile(actions); + } + } + + private static TLContainer CreateContainer(IList items) + { + var messages = new List(); + + for (var i = 0; i < items.Count; i++) + { + var item = items[i]; + + var transportMessage = (TLContainerTransportMessage)item.Message; + if (item.InvokeAfter != null) + { + transportMessage.MessageData = new TLInvokeAfterMsg + { + MsgId = item.InvokeAfter.Message.MessageId, + Object = item.Object + }; + } + + item.Status = RequestStatus.Sent; + + messages.Add(transportMessage); + } + + var container = new TLContainer + { + Messages = new List(messages) + }; + + return container; + } + + + public void GetSyncErrorsAsync(Action> callback) + { + Helpers.Execute.BeginOnThreadPool(() => callback.SafeInvoke(_cacheService.LastSyncMessageException, _updatesService.SyncDifferenceExceptions)); + } + + public void GetSendingQueueInfoAsync(Action callback) + { + Helpers.Execute.BeginOnThreadPool(() => + { + var info = new StringBuilder(); + lock (_sendingQueueSyncRoot) + { + var count = 0; + foreach (var item in _sendingQueue) + { + var sendBeforeTimeString = item.SendBeforeTime.HasValue + ? item.SendBeforeTime.Value.ToString("H:mm:ss.fff") + : null; + + var message = string.Empty; + try + { + var transportMessage = item.Message as TLContainerTransportMessage; + if (transportMessage != null) + { + var sendMessage = transportMessage.MessageData as TLSendMessage; + if (sendMessage != null) + { + message = string.Format("{0} {1}", sendMessage.Message, sendMessage.RandomId); + } + else + { + var invokeAfterMsg = transportMessage.MessageData as TLInvokeAfterMsg; + if (invokeAfterMsg != null) + { + sendMessage = invokeAfterMsg.Object as TLSendMessage; + if (sendMessage != null) + { + message = string.Format("{0} {1}", sendMessage.Message, sendMessage.RandomId); + } + } + } + } + } + catch (Exception ex) + { + + } + info.AppendLine(string.Format("{0} send={1} before={2} msg=[{3}] error=[{4}]", count++, item.SendTime.ToString("H:mm:ss.fff"), sendBeforeTimeString, message, item.LastError)); + } + } + + callback.SafeInvoke(info.ToString()); + }); + } + + } +} diff --git a/Telegram.Api/Services/MTProtoService.Stuff.cs b/Telegram.Api/Services/MTProtoService.Stuff.cs new file mode 100755 index 0000000..e1293a7 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Stuff.cs @@ -0,0 +1,169 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using Telegram.Api.Extensions; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Stuff; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + private object _debugRoot = new object(); + + public void MessageAcknowledgments(TLVector ids) + { + PrintCaption("msgs_ack"); + TLUtils.WriteLine("ids"); + foreach (var id in ids) + { + TLUtils.WriteLine(TLUtils.MessageIdString(id)); + } + var obj = new TLMessageAcknowledgments { MsgIds = ids }; + + var authKey = _activeTransport.AuthKey; + var sesseionId = _activeTransport.SessionId; + var salt = _activeTransport.Salt; + + int sequenceNumber; + TLLong messageId; + lock (_activeTransportRoot) + { + sequenceNumber = _activeTransport.SequenceNumber * 2; + messageId = _activeTransport.GenerateMessageId(true); + } + var transportMessage = CreateTLTransportMessage(salt, sesseionId, new TLInt(sequenceNumber), messageId, obj); + var encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + + lock (_activeTransportRoot) + { + if (_activeTransport.Closed) + { + _activeTransport = GetTransport(_activeTransport.Host, _activeTransport.Port, Type, + new TransportSettings + { + DcId = _activeTransport.DCId, + Secret = _activeTransport.Secret, + AuthKey = _activeTransport.AuthKey, + Salt = _activeTransport.Salt, + SessionId = _activeTransport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = _activeTransport.SequenceNumber, + ClientTicksDelta = _activeTransport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); + } + } + + lock (_debugRoot) + { + //Debug.WriteLine(">>{0, -30} MsgId {1} SeqNo {2, -4} SessionId {3}\nids:", "msgs_ack", transportMessage.MessageId.Value, transportMessage.SeqNo.Value, transportMessage.SessionId.Value); + foreach (var id in ids) + { + //Debug.WriteLine(id.Value); + } + } + + var captionString = string.Format("msgs_ack {0}", transportMessage.MessageId); + SendPacketAsync(_activeTransport, captionString, encryptedMessage, + result => + { + //Debug.WriteLine("@msgs_ack {0} result {1}", transportMessage.MessageId, result); + }, + error => + { + //Debug.WriteLine("< callback, Action faultCallback = null) + { + var obj = new TLPing { PingId = pingId }; + + SendNonInformativeMessage("ping", obj, + result => + { + callback.SafeInvoke(result); + }, + faultCallback.SafeInvoke); + } + + public void PingDelayDisconnectAsync(TLLong pingId, TLInt disconnectDelay, Action callback, Action faultCallback = null) + { + var obj = new TLPingDelayDisconnect { PingId = pingId, DisconnectDelay = disconnectDelay }; + + SendNonInformativeMessage("ping_delay_disconnect", obj, + result => + { + callback.SafeInvoke(result); + }, + faultCallback.SafeInvoke); + } + + public void HttpWaitAsync(TLInt maxDelay, TLInt waitAfter, TLInt maxWait, Action callback, Action faultCallback) + { + PrintCaption("http_wait"); + + var obj = new TLHttpWait { MaxDelay = maxDelay, WaitAfter = waitAfter, MaxWait = maxWait }; + + var authKey = _activeTransport.AuthKey; + var salt = _activeTransport.Salt; + var sessionId = _activeTransport.SessionId; + + int sequenceNumber; + TLLong messageId; + lock (_activeTransportRoot) + { + sequenceNumber = _activeTransport.SequenceNumber * 2; + messageId = _activeTransport.GenerateMessageId(true); + } + var transportMessage = CreateTLTransportMessage(salt, sessionId, new TLInt(sequenceNumber), messageId, obj); + var encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + + lock (_activeTransportRoot) + { + if (_activeTransport.Closed) + { + _activeTransport = GetTransport(_activeTransport.Host, _activeTransport.Port, Type, + new TransportSettings + { + DcId = _activeTransport.DCId, + Secret = _activeTransport.Secret, + AuthKey = _activeTransport.AuthKey, + Salt = _activeTransport.Salt, + SessionId = _activeTransport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = _activeTransport.SequenceNumber, + ClientTicksDelta = _activeTransport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); + } + } + + SendPacketAsync(_activeTransport, "http_wait " + transportMessage.MessageId, encryptedMessage, + result => + { + //try + //{ + // ReceiveBytesAsync(result, authKey); + //} + //catch (Exception e) + //{ + // TLUtils.WriteException(e); + //} + //finally + //{ + // callback(); + //} + }, + error => faultCallback.SafeInvoke()); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Updates.cs b/Telegram.Api/Services/MTProtoService.Updates.cs new file mode 100755 index 0000000..3062855 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Updates.cs @@ -0,0 +1,45 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Help; +using Telegram.Api.TL.Functions.Updates; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void GetStateAsync(Action callback, Action faultCallback = null) + { + var obj = new TLGetState(); + + SendInformativeMessage("updates.getState", obj, callback, faultCallback); + } + + public void GetStateWithoutUpdatesAsync(Action callback, Action faultCallback = null) + { + var obj = new TLInvokeWithoutUpdates {Object = new TLGetState()}; + + SendInformativeMessage("updates.getState", obj, callback, faultCallback); + } + + public void GetDifferenceAsync(TLInt pts, TLInt date, TLInt qts, Action callback, Action faultCallback = null) + { + var obj = new TLGetDifference { Flags = new TLInt(0), Pts = pts, Date = date, Qts = qts }; + + SendInformativeMessage("updates.getDifference", obj, callback, faultCallback); + } + + public void GetDifferenceWithoutUpdatesAsync(TLInt pts, TLInt date, TLInt qts, Action callback, Action faultCallback = null) + { + var obj = new TLGetDifference { Flags = new TLInt(0), Pts = pts, Date = date, Qts = qts }; + + SendInformativeMessage("updates.getDifference", new TLInvokeWithoutUpdates{Object = obj}, callback, faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Upload.cs b/Telegram.Api/Services/MTProtoService.Upload.cs new file mode 100755 index 0000000..23a4f9e --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Upload.cs @@ -0,0 +1,41 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Upload; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void SaveFilePartAsync(TLLong fileId, TLInt filePart, TLString bytes, Action callback, Action faultCallback = null) + { + var filePartValue = filePart.Value; + var bytesLength = bytes.Data.Length; + + var obj = new TLSaveFilePart{ FileId = fileId, FilePart = filePart, Bytes = bytes }; + + SendInformativeMessage("upload.saveFilePart" + " " + filePart.Value, obj, callback, faultCallback); + } + + public void SaveBigFilePartAsync(TLLong fileId, TLInt filePart, TLInt fileTotalParts, TLString bytes, Action callback, Action faultCallback = null) + { + var obj = new TLSaveBigFilePart { FileId = fileId, FilePart = filePart, FileTotalParts = fileTotalParts, Bytes = bytes }; + Debug.WriteLine(string.Format("upload.saveBigFilePart file_id={0} file_part={1} file_total_parts={2} bytes={3}", fileId, filePart, fileTotalParts, bytes.Data.Length)); + SendInformativeMessage("upload.saveBigFilePart " + filePart + " " + fileTotalParts, obj, callback, faultCallback); + } + + public void GetFileAsync(TLInputFileLocationBase location, TLInt offset, TLInt limit, Action callback, Action faultCallback = null) + { + var obj = new TLGetFile { Location = location, Offset = offset, Limit = limit }; + + SendInformativeMessage("upload.getFile", obj, callback, faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.Users.cs b/Telegram.Api/Services/MTProtoService.Users.cs new file mode 100755 index 0000000..780b26d --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.Users.cs @@ -0,0 +1,42 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.Extensions; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Users; + +namespace Telegram.Api.Services +{ + public partial class MTProtoService + { + public void GetUsersAsync(TLVector id, Action> callback, Action faultCallback = null) + { + var obj = new TLGetUsers { Id = id }; + + SendInformativeMessage>("users.getUsers", obj, result => + { + _cacheService.SyncUsers(result, callback); + }, + faultCallback); + } + + public void GetFullUserAsync(TLInputUserBase id, Action callback, Action faultCallback = null) + { + var obj = new TLGetFullUser { Id = id }; + + SendInformativeMessage("users.getFullUser", obj, userFull => _cacheService.SyncUser(userFull, callback.SafeInvoke), faultCallback); + } + + public void SetSecureValueErrorsAsync(TLInputUserBase id, TLVector errors, Action callback, Action faultCallback = null) + { + var obj = new TLSetSecureValueErrors { Id = id, Errors = errors }; + + SendInformativeMessage("users.setSecureValueErrors", obj, callback, faultCallback); + } + } +} diff --git a/Telegram.Api/Services/MTProtoService.cs b/Telegram.Api/Services/MTProtoService.cs new file mode 100755 index 0000000..0b700f9 --- /dev/null +++ b/Telegram.Api/Services/MTProtoService.cs @@ -0,0 +1,2674 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define MTPROTO +//#define DEBUG_UPDATEDCOPTIONS +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reactive.Linq; +using System.Text; +using System.Threading; +using Org.BouncyCastle.Bcpg; +using Telegram.Api.Services.DeviceInfo; +using Telegram.Api.TL.Functions.Channels; +using Telegram.Api.TL.Functions.Messages; +#if WIN_RT +using Windows.UI.Xaml; +#elif WINDOWS_PHONE +using System.Windows.Threading; +using Microsoft.Devices; +#endif +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.Connection; +using Telegram.Api.Services.Updates; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Auth; +using Telegram.Api.TL.Functions.Upload; +using Telegram.Api.Transport; +using Telegram.Logs; +using Environment = System.Environment; + +namespace Telegram.Api.Services +{ + public class CountryEventArgs : EventArgs + { + public string Country { get; set; } + } + + public partial class MTProtoService : ServiceBase, IMTProtoService, IDisposable + { + public event EventHandler ProxyDisabled; + + protected void RaiseProxyDisabled() + { + var handler = ProxyDisabled; + if (handler != null) + { + handler(this, EventArgs.Empty); + } + } + + public event EventHandler GotUserCountry; + + protected void RaiseGotUserCountry(string country) + { + var handler = GotUserCountry; + if (handler != null) + { + handler(this, new CountryEventArgs { Country = country }); + } + } + + public void SetInitState() + { + _updatesService.SetInitState(); + } + + public ITransport GetActiveTransport() + { + return _activeTransport; + } + + public WindowsPhone.Tuple GetCurrentPacketInfo() + { + return _activeTransport != null ? _activeTransport.GetCurrentPacketInfo() : null; + } + + public string GetTransportInfo() + { + return _activeTransport != null ? _activeTransport.GetTransportInfo() : null; + } + + public string Country + { + get { return _config != null ? _config.Country : null; } + } + + private TLInt _currentUserId; + + public TLInt CurrentUserId + { + get + { + return _currentUserId; + } + set + { + _currentUserId = value; + + } + } + + public long ClientTicksDelta { get { return _activeTransport.ClientTicksDelta; } } + + //private bool _isInitialized; + + /// + /// Получен ли ключ авторизации + /// + //public bool IsInitialized + //{ + // get { return _isInitialized; } + // protected set + // { + // if (_isInitialized != value) + // { + // _isInitialized = value; + // NotifyOfPropertyChange(() => IsInitialized); + // } + // } + //} + + public event EventHandler Initialized; + + protected virtual void RaiseInitialized() + { + var handler = Initialized; + if (handler != null) handler(this, EventArgs.Empty); + } + + public event EventHandler InitializationFailed; + + protected virtual void RaiseInitializationFailed() + { + var handler = InitializationFailed; + if (handler != null) handler(this, EventArgs.Empty); + } + + private readonly object _fileTransportRoot = new object(); + + private readonly object _activeTransportRoot = new object(); + + private ITransport _activeTransport; + + private readonly ITransportService _transportService; + + private readonly ICacheService _cacheService; + + private readonly IUpdatesService _updatesService; + + private readonly IConnectionService _connectionService; + + private readonly IDeviceInfoService _deviceInfo; + + private readonly Dictionary _history = new Dictionary(); + +#if DEBUG + private readonly Dictionary _removedHistory = new Dictionary(); +#endif + + public IList History + { + get { return _history.Values.ToList(); } + } + + private TransportType _type = TransportType.Tcp; + + public TransportType Type + { + get { return _type; } + set { _type = value; } + } + + private readonly object _delayedItemsRoot = new object(); + + private readonly List _delayedItems = new List(); + + private Timer _timeoutsTimer; + + private Timer _deviceLockedTimer; + + private Timer _checkTransportTimer; + + public MTProtoService(IDeviceInfoService deviceInfo, IUpdatesService updatesService, ICacheService cacheService, ITransportService transportService, IConnectionService connectionService, IPublicConfigService publicConfigService) + { + var isBackground = deviceInfo != null && deviceInfo.IsBackground; + + _deviceInfo = deviceInfo; + + _sendingTimer = new Timer(CheckSendingMessages, this, Timeout.Infinite, Timeout.Infinite); + _getConfigTimer = new Timer(CheckGetConfig, this, TimeSpan.FromSeconds(10.0), TimeSpan.FromSeconds(Constants.CheckGetConfigInterval)); + _timeoutsTimer = new Timer(CheckTimeouts, this, TimeSpan.FromSeconds(10.0), TimeSpan.FromSeconds(10.0)); + _deviceLockedTimer = new Timer(CheckDeviceLockedInternal, this, TimeSpan.FromSeconds(60.0), TimeSpan.FromSeconds(60.0)); + + _publicConfigService = publicConfigService; + + _connectionService = connectionService; + _connectionService.Initialize(this); + _connectionService.ConnectionLost += OnConnectionLost; + + var sendStatusEvents = Observable.FromEventPattern, SendStatusEventArgs>( + keh => { SendStatus += keh; }, + keh => { SendStatus -= keh; }); + + _statusSubscription = sendStatusEvents + .Throttle(TimeSpan.FromSeconds(Constants.UpdateStatusInterval)) + .Subscribe(e => UpdateStatusAsync(e.EventArgs.Offline, result => { })); + + _updatesService = updatesService; + _updatesService.DCOptionsUpdated += OnDCOptionsUpdated; + + _cacheService = cacheService; + + if (_updatesService != null) + { + _updatesService.GetDifferenceAsync = GetDifferenceAsync; + _updatesService.GetStateAsync = GetStateAsync; + _updatesService.GetCurrentUserId = GetCurrentUserId; + _updatesService.GetDHConfigAsync = GetDHConfigAsync; + _updatesService.AcceptEncryptionAsync = AcceptEncryptionAsync; + _updatesService.SendEncryptedServiceAsync = SendEncryptedServiceAsync; + _updatesService.SetMessageOnTimeAsync = SetMessageOnTime; + _updatesService.RemoveFromQueue = RemoveFromQueue; + _updatesService.UpdateChannelAsync = UpdateChannelAsync; + _updatesService.GetFullChatAsync = GetFullChatAsync; + _updatesService.GetFullUserAsync = GetFullUserAsync; + _updatesService.GetChannelMessagesAsync = GetMessagesAsync; + _updatesService.GetPinnedDialogsAsync = GetPinnedDialogsAsync; + _updatesService.GetMessagesAsync = GetMessagesAsync; + _updatesService.GetPeerDialogsAsync = GetPeerDialogsAsync; + _updatesService.GetPromoDialogAsync = GetPromoDialogAsync; + } + + _transportService = transportService; + _transportService.ConnectionLost += OnConnectionLost; + _transportService.FileConnectionLost += OnFileConnectionLost; + _transportService.SpecialConnectionLost += OnSpecialConnectionLost; + _transportService.CheckConfig += OnCheckConfig; + + _activeTransport = GetTransport(Constants.FirstServerIpAddress, Constants.FirstServerPort, Type, + new TransportSettings + { + DcId = _activeTransport != null ? _activeTransport.DCId : Constants.FirstServerDCId, + Secret = _activeTransport != null ? _activeTransport.Secret : null, + AuthKey = _activeTransport != null ? _activeTransport.AuthKey : null, + Salt = _activeTransport != null ? _activeTransport.Salt : null, + SessionId = _activeTransport != null ? _activeTransport.SessionId : null, + MessageIdDict = _activeTransport != null ? _activeTransport.MessageIdDict : new Dictionary(), + SequenceNumber = _activeTransport != null ? _activeTransport.SequenceNumber : 0, + ClientTicksDelta = _activeTransport != null ? _activeTransport.ClientTicksDelta : 0, + PacketReceivedHandler = OnPacketReceived + }); + +#if DEBUG + _checkTransportTimer = new Timer(CheckTransport, this, TimeSpan.FromSeconds(1.0), Timeout.InfiniteTimeSpan); +#endif + + Initialized += OnServiceInitialized; + InitializationFailed += OnServiceInitializationFailed; + + //IsInitialized = true; + if (!isBackground) + { + //Initialize(); + } + + Instance = this; + } + + public event EventHandler TransportChecked; + + protected virtual void RaiseTransportChecked(TransportCheckedEventArgs e) + { + var handler = TransportChecked; + if (handler != null) handler(this, e); + } + + private void CheckTransport(object state) + { + //return; + ITransport transport = null; + + lock (_activeTransportRoot) + { + transport = _activeTransport; + } + var transportId = transport.Id; + var sessionId = transport.SessionId; + var authKey = transport.AuthKey; + var lastReceiveTime = transport.LastReceiveTime; + int historyCount; + string historyDescription; + lock (_historyRoot) + { + historyCount = _history.Count; + historyDescription = string.Join("\n", _history.Values.Select(x => x.Caption + " " + x.Hash)); + } + var currentPacketLength = transport.PacketLength; + var lastPacketLength = transport.LastPacketLength; + + RaiseTransportChecked(new TransportCheckedEventArgs + { + TransportId = transportId, + SessionId = sessionId, + AuthKey = authKey, + LastReceiveTime = lastReceiveTime, + HistoryCount = historyCount, + HistoryDescription = historyDescription, + NextPacketLength = currentPacketLength, + LastPacketLength = lastPacketLength + }); + + _checkTransportTimer.Change(TimeSpan.FromSeconds(1.0), Timeout.InfiniteTimeSpan); + } + + public static IMTProtoService Instance { get; protected set; } + + private void CheckTimeouts(object state) + { +#if DEBUG + if (Debugger.IsAttached) + { + return; + } +#endif + + const double timeout = Constants.TimeoutInterval; + const double delayedTimeout = Constants.DelayedTimeoutInterval; + const double nonEncryptedTimeout = Constants.NonEncryptedTimeoutInterval; + + var timedOutKeys = new List(); + var timedOutValues = new List(); + var now = DateTime.Now; + + // history + lock (_historyRoot) + { + foreach (var historyKeyValue in _history) + { + var historyValue = historyKeyValue.Value; + if (historyValue.SendTime != default(DateTime) + && historyValue.SendTime.AddSeconds(timeout) < now) + { + timedOutKeys.Add(historyKeyValue.Key); + timedOutValues.Add(historyKeyValue.Value); + } + } + + foreach (var key in timedOutKeys) + { + _history.Remove(key); + } + } + + if (timedOutValues.Count > 0) + { + Execute.BeginOnThreadPool(() => + { + foreach (var item in timedOutValues) + { + try + { + item.FaultCallback.SafeInvoke( + new TLRPCError + { + Code = new TLInt((int)ErrorCode.TIMEOUT), + Message = new TLString("MTProtoService: operation timed out (" + timeout + "s)") + }); +#if DEBUG + TLUtils.WriteLine(item.Caption + " time out", LogSeverity.Error); +#endif + } + catch (Exception ex) + { + TLUtils.WriteException("Timeout exception", ex); + } + } + }); + } + + // delayed history + var timedOutItems = new List(); + lock (_delayedItemsRoot) + { + foreach (var item in _delayedItems) + { + if (item.SendTime != default(DateTime) + && item.SendTime.AddSeconds(delayedTimeout) < now) + { + timedOutItems.Add(item); + } + } + + foreach (var item in timedOutItems) + { + _delayedItems.Remove(item); + } + } + + if (timedOutItems.Count > 0) + { + Execute.BeginOnThreadPool(() => + { + foreach (var item in timedOutItems) + { + try + { + item.FaultCallback.SafeInvoke( + new TLRPCError + { + Code = new TLInt((int)ErrorCode.TIMEOUT), + Message = new TLString("MTProtoService: operation timed out (" + delayedTimeout + "s)") + }); +#if DEBUG + TLUtils.WriteLine(item.Caption + " time out", LogSeverity.Error); +#endif + } + catch (Exception ex) + { + TLUtils.WriteException("Timeout exception", ex); + } + } + }); + } + + // generating key + if (_activeTransport != null) + { + var requests = _activeTransport.RemoveTimeOutRequests(nonEncryptedTimeout); + + if (requests.Count > 0) + { +#if LOG_REGISTRATION + TLUtils.WriteLog("MTProtoService.CheckTimeouts clear history and replace transport"); +#endif + ClearHistory("CheckTimeouts", false); + + Execute.BeginOnThreadPool(() => + { + foreach (var item in requests) + { + try + { + item.FaultCallback.SafeInvoke( + new TLRPCError + { + Code = new TLInt((int)ErrorCode.TIMEOUT), + Message = new TLString("MTProtoService: operation timed out (" + timeout + "s)") + }); +#if DEBUG + TLUtils.WriteLine(item.Caption + " time out", LogSeverity.Error); +#endif + } + catch (Exception ex) + { + TLUtils.WriteException("Timeout exception", ex); + } + } + }); + } + } + } + + private void OnConnectionLost(object sender, EventArgs e) + { + ResetConnection(null); + } + + private void OnFileConnectionLost(object sender, EventArgs e) + { + ResetConnection(null); + } + + private void OnSpecialConnectionLost(object sender, TransportEventArgs e) + { + var transport = e.Transport; + if (transport != null) + { + var str = string.Format("Connection lost id={0} dc_id={1} ip={2} port={3}", transport.Id, transport.DCId, transport.Host, transport.Port); + LogPublicConfig(str); + Execute.ShowDebugMessage(str); + } + } + + public void GetConfigInformationAsync(Action callback) + { + Execute.BeginOnThreadPool(() => + { + var now = DateTime.Now; + var currentTime = TLUtils.DateToUniversalTimeTLInt(ClientTicksDelta, now); + + var activeTransportString = _activeTransport != null ? _activeTransport.ToString() : null; + + var sb = new StringBuilder(); + sb.AppendLine("current_time utc0:"); + sb.AppendLine(string.Format("{0} {1}", currentTime, TLUtils.ToDateTime(currentTime).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine("config:"); + sb.AppendLine(_config.ToString()); + sb.AppendLine("active transport:"); + sb.AppendLine(activeTransportString); + sb.AppendLine("dc_options:"); + foreach (var option in _config.DCOptions) + { + sb.AppendLine(option.ToString()); + } + + callback(sb.ToString()); + }); + } + + public void GetTransportInformationAsync(Action callback) + { + Execute.BeginOnThreadPool(() => + { + var activeTransportString = _activeTransport != null ? _activeTransport.ToString() : null; + + var sb = new StringBuilder(); + sb.AppendLine("active transport:"); + sb.AppendLine(activeTransportString); + sb.AppendLine("Date: " + TLUtils.ToDateTime(_config.Date)); + callback(sb.ToString()); + }); + } + + public void UpdateTransportInfoAsync(TLDCOption78 dcOption, TLString ipAddress, TLInt port, Action callback) + { + var args = new DCOptionsUpdatedEventArgs + { + Update = new TLUpdateDCOptions { DCOptions = new TLVector { dcOption } } + }; + + OnDCOptionsUpdated(this, args); + + ClearHistory("UpdateTransportInfoAsync", false); + + // continue listening on fault + _activeTransport = GetTransport(ipAddress.ToString(), port.Value, Type, + new TransportSettings + { + DcId = dcOption.Id.Value, + Secret = TLUtils.ParseSecret(dcOption), + AuthKey = _activeTransport != null ? _activeTransport.AuthKey : null, + Salt = _activeTransport != null ? _activeTransport.Salt : null, + SessionId = _activeTransport != null ? _activeTransport.SessionId : null, + MessageIdDict = _activeTransport != null ? _activeTransport.MessageIdDict : new Dictionary(), + SequenceNumber = _activeTransport != null ? _activeTransport.SequenceNumber : 0, + ClientTicksDelta = _activeTransport != null ? _activeTransport.ClientTicksDelta : 0, + PacketReceivedHandler = OnPacketReceived + }); + + callback.SafeInvoke(true); + } + + + private void OnDCOptionsUpdated(object sender, DCOptionsUpdatedEventArgs e) + { + var newOptions = e.Update.DCOptions; + + var dcOptionsInfo = new StringBuilder(); + dcOptionsInfo.AppendLine("TLUpdateDCOptions"); + foreach (var option in newOptions) + { + dcOptionsInfo.AppendLine(string.Format("DCId={0} {1}:{2}", option.Id, option.IpAddress, option.Port)); + } + Execute.ShowDebugMessage(dcOptionsInfo.ToString()); + + if (_config != null && _config.DCOptions != null) + { + var activeDCId = _config.DCOptions[_config.ActiveDCOptionIndex].Id.Value; + + foreach (var newOption in newOptions) + { + var updated = false; + // 1) update ip address, port, hostname + foreach (var oldOption in _config.DCOptions) + { + if (newOption.Id.Value == oldOption.Id.Value + && newOption.IPv6.Value == oldOption.IPv6.Value + && newOption.Media.Value == oldOption.Media.Value + && newOption.TCPO.Value == oldOption.TCPO.Value + && newOption.Static.Value == oldOption.Static.Value) + { + // keep AuthKey, SessionId and Salt + var oldOption78 = oldOption as TLDCOption78; + var newOption78 = newOption as TLDCOption78; + if (oldOption78 != null + && newOption78 != null) + { + if (oldOption78.Secret != null && newOption78.Secret != null + || oldOption78.Secret == null && newOption78.Secret == null) + { + oldOption.Hostname = newOption.Hostname; + oldOption.IpAddress = newOption.IpAddress; + oldOption.Port = newOption.Port; + oldOption78.Secret = newOption78.Secret; + updated = true; + + if (!newOption.Media.Value && activeDCId == newOption78.Id.Value) + { + _config.ActiveDCOptionIndex = _config.DCOptions.IndexOf(oldOption); + } + break; + } + } + else + { + oldOption.Hostname = newOption.Hostname; + oldOption.IpAddress = newOption.IpAddress; + oldOption.Port = newOption.Port; + updated = true; + + if (!newOption.Media.Value && activeDCId == newOption.Id.Value) + { + _config.ActiveDCOptionIndex = _config.DCOptions.IndexOf(oldOption); + } + break; + } + } + } + + // 2) append new DCOption + if (!updated) + { + // fix readonly array of dcOption + var list = _config.DCOptions.ToList(); + list.Add(newOption); + _config.DCOptions.Items = list; + + if (!newOption.Media.Value && activeDCId == newOption.Id.Value) + { + _config.ActiveDCOptionIndex = _config.DCOptions.IndexOf(newOption); + } + } + } + SaveConfig(); + } + } + + private TLInt GetCurrentUserId() + { + return CurrentUserId; + } + + private void OnPacketReceived(object sender, DataEventArgs e) + { + var transport = (ITransport)sender; +#if DEBUG + bool byActiveTransport; + lock (_activeTransportRoot) + { + byActiveTransport = transport == _activeTransport; + } + if (byActiveTransport) + { + var transportId = transport.Id; + var sessionId = transport.SessionId; + var authKey = transport.AuthKey; + int historyCount; + string historyDescription; + lock (_historyRoot) + { + historyCount = _history.Count; + historyDescription = string.Join("\n", _history.Values.Select(x => x.Caption + " " + x.Hash)); + } + + RaiseTransportChecked(new TransportCheckedEventArgs + { + HistoryCount = historyCount, + HistoryDescription = historyDescription, + + TransportId = transportId, + SessionId = sessionId, + AuthKey = authKey, + LastReceiveTime = e.LastReceiveTime, + NextPacketLength = e.NextPacketLength, + LastPacketLength = e.Data.Length + }); + } +#endif + + var position = 0; + var handled = false; + + if (transport.AuthKey == null) + { + try + { + + var message = TLObject.GetObject(e.Data, ref position); + var historyItem = transport.DequeueFirstNonEncryptedItem(); + if (historyItem != null) + { +#if LOG_REGISTRATION + TLUtils.WriteLog( + string.Format("OnReceivedBytes by {0} AuthKey==null: invoke historyItem {1} with result {2} (data length={3})", + transport.Id, historyItem.Caption, message.Data.GetType(), e.Data.Length)); +#endif + historyItem.Callback.SafeInvoke(message.Data); + } + else + { +#if LOG_REGISTRATION + TLUtils.WriteLog( + string.Format("OnReceivedBytes by {0} AuthKey==null: cannot find historyItem {1} with result {2} (data length={3})", + transport.Id, string.Empty, message.Data.GetType(), e.Data.Length)); +#endif + } + + handled = true; + } + catch (Exception ex) + { +#if LOG_REGISTRATION + + TLUtils.WriteLog( + string.Format("OnReceivedBytes by {0} AuthKey==null exception: cannot parse TLNonEncryptedMessage with History\n {1} \nand exception\n{2} (data length={3})", + transport.Id, transport.PrintNonEncryptedHistory(), ex, e.Data.Length)); +#endif + } + + if (!handled) + { +#if LOG_REGISTRATION + TLUtils.WriteLog( + string.Format("OnReceivedBytes by {0} AuthKey==null !handled: invoke ReceiveBytesAsync with data length {1}", + transport.Id, e.Data.Length)); +#endif + ReceiveBytesAsync(transport, e.Data); + } + } + else + { +#if LOG_REGISTRATION + TLUtils.WriteLog( + string.Format("OnReceivedBytes by {0} AuthKey!=null: invoke ReceiveBytesAsync with data length {1}", + transport.Id, e.Data.Length)); +#endif + ReceiveBytesAsync(transport, e.Data); + } + } + + private void OnServiceInitializationFailed(object sender, EventArgs e) + { + Execute.BeginOnThreadPool(TimeSpan.FromSeconds(1.0), () => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Service initialization failed"); +#endif + CancelDelayedItemsAsync(); + + // если генерация ключа прошла успешно, но предыдущая попытка завершилась неудачно на методах help.getNearestDc, help.getConfig + // обнуляем ключ, т.к. в противном случае resPQ будем пытаться расшифровать ключем + + lock (_activeTransportRoot) + { + _activeTransport.AuthKey = null; + } + + Initialize(); + }); + } + + private void CancelDelayedItemsAsync(bool force = false) + { + Execute.BeginOnThreadPool(() => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Cancel delayed items"); +#endif + lock (_delayedItemsRoot) + { + var canceledItems = new List(); + foreach (var item in _delayedItems) + { + if (force + || (item.MaxAttempt.HasValue + && item.MaxAttempt <= item.CurrentAttempt)) + { + item.AttemptFailed.SafeInvoke(item.CurrentAttempt); + canceledItems.Add(item); + } + item.CurrentAttempt++; + } + + foreach (var canceledItem in canceledItems) + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Cancel delayed item\n " + canceledItem); +#endif + _delayedItems.Remove(canceledItem); + + if (canceledItem.FaultCallback != null) + { + canceledItem.FaultCallback(new TLRPCError { Code = new TLInt(404) }); + } + } + } + }); + } + + private void OnServiceInitialized(object sender, EventArgs e) + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Service initialized"); +#endif + if (Constants.IsLongPollEnabled) + { + StartLongPoll(); + } + + SendDelayedItemsAsync(); + } + + private void SendDelayedItemsAsync() + { + Execute.BeginOnThreadPool(() => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Send delayed items (count=" + _delayedItems.Count + ")"); +#endif + lock (_delayedItemsRoot) + { + if (_delayedItems.Count > 0) + { + foreach (var item in _delayedItems) + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Dequeue and send delayed item \n" + item); +#endif + SendInformativeMessage(item.Caption, item.Object, item.Callback, item.FaultCallback, item.MaxAttempt, item.AttemptFailed); + } + + _delayedItems.Clear(); + } + } + + lock (_delayedNonInformativeItemsRoot) + { + if (_delayedNonInformativeItems.Count > 0) + { + foreach (var item in _delayedNonInformativeItems) + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Dequeue and send delayed item \n" + item); +#endif + SendNonInformativeMessage(item.Caption, item.Object, item.Callback, item.FaultCallback); + } + + _delayedNonInformativeItems.Clear(); + } + } + }); + } + + private bool _initializeInvoked; + + public void StartInitialize() + { + if (_initializeInvoked) return; + + _initializeInvoked = true; + + Initialize(); + } + + public void Initialize() + { + Execute.BeginOnThreadPool(() => + { + try + { + TryReadConfig( + result => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Read config with result: " + result); +#endif + if (!result) + { +#if LOG_REGISTRATION + TLUtils.WriteLog("TLUtils.LogRegistration=true"); + TLUtils.IsLogEnabled = true; +#endif + + var host = _activeTransport != null ? _activeTransport.Host : Constants.FirstServerIpAddress; // !IMPORTANT host can be obtained through publig config + var port = _activeTransport != null ? _activeTransport.Port : Constants.FirstServerPort; // !IMPORTANT port can be obtained through publig config + var dcId = _activeTransport != null ? _activeTransport.DCId : Constants.FirstServerDCId; // !IMPORTANT dcId can be obtained through publig config + _activeTransport = GetTransport(host, port, Type, + new TransportSettings + { + DcId = dcId, + Secret = _activeTransport != null ? _activeTransport.Secret : null, + AuthKey = _activeTransport != null ? _activeTransport.AuthKey : null, + Salt = _activeTransport != null ? _activeTransport.Salt : null, + SessionId = _activeTransport != null ? _activeTransport.SessionId : null, + MessageIdDict = _activeTransport != null ? _activeTransport.MessageIdDict : new Dictionary(), + SequenceNumber = _activeTransport != null ? _activeTransport.SequenceNumber : 0, + ClientTicksDelta = _activeTransport != null ? _activeTransport.ClientTicksDelta : 0, + PacketReceivedHandler = OnPacketReceived + }); +#if LOG_REGISTRATION + TLUtils.WriteLog("Start generating auth key"); +#endif + InitAsync(tuple => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop generating auth key"); + TLUtils.WriteLog("Start help.getNearestDc"); +#endif + lock (_activeTransportRoot) + { + _activeTransport.DCId = Constants.FirstServerDCId; + _activeTransport.AuthKey = tuple.Item1; + _activeTransport.Salt = tuple.Item2; + _activeTransport.SessionId = tuple.Item3; + } + var authKeyId = TLUtils.GenerateLongAuthKeyId(tuple.Item1); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = tuple.Item1, AutkKeyId = authKeyId }); + } + } + //IsInitialized = true; // Важно, используется тут, чтобы OnPacketReceived не пытался рассматривать ответ как NonEncryptedMessage + + + var timer = Stopwatch.StartNew(); + GetNearestDCAsync(nearestDC => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop help.getNearestDc"); + TLUtils.WriteLog("Start help.getConfig"); +#endif + lock (_activeTransportRoot) + { + _activeTransport.DCId = nearestDC.ThisDC.Value; + } + var elapsed = timer.Elapsed; + var timer2 = Stopwatch.StartNew(); + GetConfigAsync( + config => + { + var elapsed2 = timer2.Elapsed; + var sb = new StringBuilder(); + sb.AppendLine("help.getNearestDc " + elapsed.ToString("g")); + sb.AppendLine("help.getConfig " + elapsed2.ToString("g")); + sb.AppendLine("auth time " + _authTimeElapsed.ToString("g")); + Execute.ShowDebugMessage(sb.ToString()); +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop help.getConfig"); +#endif + config.Country = nearestDC.Country.ToString(); + + Execute.BeginOnThreadPool(() => RaiseGotUserCountry(config.Country)); + + _config = TLConfig.Merge(_config, config); + var dcOption = TLUtils.GetDCOption(config, new TLInt(_activeTransport.DCId)); + + dcOption.AuthKey = _activeTransport.AuthKey; + dcOption.Salt = _activeTransport.Salt; + dcOption.SessionId = _activeTransport.SessionId; + + config.ActiveDCOptionIndex = config.DCOptions.IndexOf(dcOption); + + _cacheService.SetConfig(config); + RaiseInitialized(); + }, + error => RaiseInitializationFailed()); + }, + error => RaiseInitializationFailed()); + }, + error => RaiseInitializationFailed()); + } + else + { + var configQ = _config; + var activeDCOPtionIndex = _config.ActiveDCOptionIndex; + + + var activeDCOption = configQ.DCOptions[activeDCOPtionIndex]; + var getConfigRequired = activeDCOption.Id == null; + // fix to update from 0.1.2.1 to 0.1.2.4 + // previously Id is not saved for first DC + _activeTransport = GetTransport(activeDCOption.IpAddress.ToString(), activeDCOption.Port.Value, Type, + new TransportSettings + { + DcId = getConfigRequired ? 0 : activeDCOption.Id.Value, + Secret = TLUtils.ParseSecret(activeDCOption), + AuthKey = activeDCOption.AuthKey, + Salt = activeDCOption.Salt, + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = activeDCOption.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); + + lock (_activeTransportRoot) + { + _activeTransport.DCId = getConfigRequired ? 0 : activeDCOption.Id.Value; + _activeTransport.AuthKey = activeDCOption.AuthKey; + _activeTransport.Salt = activeDCOption.Salt; + _activeTransport.SessionId = TLLong.Random(); + _activeTransport.ClientTicksDelta = activeDCOption.ClientTicksDelta; + } + + //fix for version 0.1.3.12 + if (activeDCOption.AuthKey == null) + { + //clear config and try again + RaiseAuthorizationRequired(new AuthorizationRequiredEventArgs { MethodName = "Initialize activeDCOption.AuthKey==null", Error = null, AuthKeyId = 0 }); + _config = null; + _cacheService.SetConfig(_config); + + RaiseInitializationFailed(); + + return; + } + + var authKeyId = TLUtils.GenerateLongAuthKeyId(activeDCOption.AuthKey); + //Log.Write("Use authKey=" + authKeyId); + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = activeDCOption.AuthKey, AutkKeyId = authKeyId }); + } + } + + if (getConfigRequired) + { + var timer = Stopwatch.StartNew(); + GetNearestDCAsync(nearestDC => + { +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop help.getNearestDc"); + TLUtils.WriteLog("Start help.getConfig"); +#endif + lock (_activeTransportRoot) + { + _activeTransport.DCId = nearestDC.ThisDC.Value; + } + var elapsed = timer.Elapsed; + var timer2 = Stopwatch.StartNew(); + GetConfigAsync( + config => + { + var elapsed2 = timer2.Elapsed; + var sb = new StringBuilder(); + sb.AppendLine("help.getNearestDc: " + elapsed); + sb.AppendLine("help.getConfig: " + elapsed2); + + Execute.ShowDebugMessage(sb.ToString()); +#if LOG_REGISTRATION + TLUtils.WriteLog("Stop help.getConfig"); +#endif + config.Country = nearestDC.Country.ToString(); + _config = TLConfig.Merge(_config, config); + var dcOption = TLUtils.GetDCOption(config, new TLInt(_activeTransport.DCId)); + + dcOption.AuthKey = _activeTransport.AuthKey; + dcOption.Salt = _activeTransport.Salt; + dcOption.SessionId = _activeTransport.SessionId; + + config.ActiveDCOptionIndex = config.DCOptions.IndexOf(dcOption); + _cacheService.SetConfig(config); + RaiseInitialized(); + }, + error => RaiseInitializationFailed()); + }, + error => RaiseInitializationFailed()); + } + else + { + RaiseInitialized(); + } + + } + }); + } + catch (Exception e) + { + TLUtils.WriteException(e); + RaiseInitializationFailed(); + } + }); + } + + private void TryReadConfig(Action callback) + { + _cacheService.GetConfigAsync( + config => + { + _config = config; + if (_config == null) + { + callback(false); + return; + } + + callback(true); + }); + } + + private void SendAcknowledgments(TLTransportMessage response) + { + var ids = new TLVector(); + + if (response.SeqNo.Value % 2 == 1) + { + ids.Items.Add(response.MessageId); + } + if (response.MessageData is TLContainer) + { + var container = (TLContainer)response.MessageData; + foreach (var message in container.Messages) + { + if (message.SeqNo.Value % 2 == 1) + { + ids.Items.Add(message.MessageId); + } + } + } + + if (ids.Items.Count > 0) + { + MessageAcknowledgments(ids); + } + } + + private void SendAcknowledgmentsByTransport(ITransport transport, TLTransportMessage response) + { + var ids = new TLVector(); + + if (response.SeqNo.Value % 2 == 1) + { + ids.Items.Add(response.MessageId); + } + if (response.MessageData is TLContainer) + { + var container = (TLContainer)response.MessageData; + foreach (var message in container.Messages) + { + if (message.SeqNo.Value % 2 == 1) + { + ids.Items.Add(message.MessageId); + } + } + } + + if (ids.Items.Count > 0) + { + MessageAcknowledgmentsByTransport(transport, ids); + } + } + + public event EventHandler AuthorizationRequired; + + public void RaiseAuthorizationRequired(AuthorizationRequiredEventArgs args) + { + var handler = AuthorizationRequired; + if (handler != null) + { + handler(this, args); + } + } + + private void ReceiveBytesAsync(ITransport transport, byte[] bytes) + { + try + { + if (bytes.Length == 4) + { + var error = BitConverter.ToInt32(bytes, 0); + if (error == -404 || error == -444) + { + if (error == -444) + { + DisableMTProtoProxy(); + + RaiseProxyDisabled(); + } + + var message = string.Format("dc_id={0} error={1}", transport.DCId, error); + TLUtils.WriteException(new Exception(message)); + + ResetConnection(new Exception(message)); + return; + } + } + + var position = 0; + var encryptedMessage = (TLEncryptedTransportMessage)new TLEncryptedTransportMessage().FromBytes(bytes, ref position); + + byte[] authKey2 = null; + lock (_authKeysRoot) + { + try + { + authKey2 = _authKeys[encryptedMessage.AuthKeyId.Value].AuthKey; + } + catch (Exception e) + { + var error = new StringBuilder(); + error.AppendLine("bytes_length=" + bytes.Length); + error.AppendLine("authKey=" + encryptedMessage.AuthKeyId); + error.AppendLine("authKeys"); + foreach (var authKey in _authKeys) + { + error.AppendLine(string.Format("{0} {1}", authKey.Key, authKey.Value.AutkKeyId)); + } + + TLUtils.WriteException(error.ToString(), e); + } + } + + encryptedMessage.Decrypt(authKey2); + + #region Security checks + + if (encryptedMessage.Data == null) + { + var message = "msgKey mismatch"; + + TLUtils.WriteException(new Exception(message)); + } + + if (encryptedMessage.Data.Length < 32) + { + var message = string.Format("padding extension data={0} < 32", encryptedMessage.Data.Length); + + TLUtils.WriteException(new Exception(message)); + } + var messageDataLength = BitConverter.ToInt32(encryptedMessage.Data, 28); + if (messageDataLength < 0 || messageDataLength % 4 != 0) + { + var message = string.Format("incorrect length data={0} length={1}", encryptedMessage.Data.Length, messageDataLength); + + TLUtils.WriteException(new Exception(message)); + } + + if (32 + messageDataLength > encryptedMessage.Data.Length) + { + var message = string.Format("padding extension data={0} length={1}", encryptedMessage.Data.Length, messageDataLength); + + TLUtils.WriteException(new Exception(message)); + } + + position = 0; + var transportMessage = TLObject.GetObject(encryptedMessage.Data, ref position); +#if MTPROTO + if (encryptedMessage.Data.Length - position < 12 + || encryptedMessage.Data.Length - position > 1024) + { + var message = string.Format("padding extension data={0} position={1} object={2}", encryptedMessage.Data.Length, position, transportMessage.MessageData); + TLUtils.WriteException(new Exception(message)); + } +#else + if ((encryptedMessage.Data.Length - position) > 15) + { + var message = string.Format("padding extension data={0} position={1} object={2}", encryptedMessage.Data.Length, position, transportMessage.MessageData); + TLUtils.WriteException(new Exception(message)); + } +#endif + if (transportMessage.SessionId.Value != transport.SessionId.Value) + { + var message = string.Format("Transport Session_id={0} is not equal to transport.session_id={1} transport_dc_id={2}", transportMessage.SessionId, transport.SessionId, transport.DCId); + TLUtils.WriteException(new Exception(message)); + } + + if (transport.MinMessageId != 0) + { + if (transport.MinMessageId > transportMessage.MessageId.Value) + { + var message = string.Format("Message_id={0} seq_no={1} is higher than transport.min_message_id={2}", transportMessage.MessageId, transportMessage.SeqNo, transport.MinMessageId); + TLUtils.WriteException(new Exception(message)); + } + } + + if (transport.MessageIdDict.ContainsKey(transportMessage.MessageId.Value)) + { + var message = string.Format("Message_id={0} already exists", transportMessage.MessageId.Value); + TLUtils.WriteException(new Exception(message)); + } + + lock (transport.SyncRoot) + { + transport.MessageIdDict[transportMessage.MessageId.Value] = transportMessage.MessageId.Value; + } + + if ((transportMessage.MessageId.Value % 2) == 0) + { + TLUtils.WriteException(new Exception("Incorrect message_id")); + } + + #endregion + + // get acknowledgments + foreach (var acknowledgment in TLUtils.FindInnerObjects(transportMessage)) + { + var ids = acknowledgment.MessageIds.Items; + lock (_historyRoot) + { + foreach (var id in ids) + { + if (_history.ContainsKey(id.Value)) + { + _history[id.Value].Status = RequestStatus.Confirmed; + } + } + } + } + // send acknowledgments + SendAcknowledgments(transportMessage); + + // set client ticks delta + bool updated = false; + lock (_activeTransportRoot) + { + if (transport.ClientTicksDelta == 0) + { + var serverTime = transportMessage.MessageId.Value; + var clientTime = transport.GenerateMessageId().Value; + + var serverDateTime = Utils.UnixTimestampToDateTime(serverTime >> 32); + var clientDateTime = Utils.UnixTimestampToDateTime(clientTime >> 32); + + var errorInfo = new StringBuilder(); + + errorInfo.AppendLine("Server time: " + serverDateTime); + errorInfo.AppendLine("Client time: " + clientDateTime); + + transport.ClientTicksDelta = serverTime - clientTime; + + if (transport.ClientTicksDelta == 0) transport.ClientTicksDelta = 1; + updated = true; + } + } + + if (updated && _config != null) + { + var dcOption = _config.DCOptions.FirstOrDefault(x => string.Equals(x.IpAddress.ToString(), transport.Host, StringComparison.OrdinalIgnoreCase)); + if (dcOption != null) + { + dcOption.ClientTicksDelta = transport.ClientTicksDelta; + _cacheService.SetConfig(_config); + } + } + + // updates + _updatesService.ProcessTransportMessage(transportMessage); + + // bad messages + foreach (var badMessage in TLUtils.FindInnerObjects(transportMessage)) + { + + HistoryItem item = null; + lock (_historyRoot) + { + if (_history.ContainsKey(badMessage.BadMessageId.Value)) + { + item = _history[badMessage.BadMessageId.Value]; + } + else + { + Execute.ShowDebugMessage("TLBadMessageNotificaiton lost item id=" + badMessage.BadMessageId); + } + } + + Logs.Log.Write(string.Format("{0} {1}", badMessage, item)); + + ProcessBadMessage(transportMessage, badMessage, item); + } + + // bad server salts + foreach (var badServerSalt in TLUtils.FindInnerObjects(transportMessage)) + { + + lock (_activeTransportRoot) + { + _activeTransport.Salt = badServerSalt.NewServerSalt; + } + + // save config + if (_config != null && _config.DCOptions != null) + { + var activeDCOption = _config.DCOptions[_config.ActiveDCOptionIndex]; + activeDCOption.Salt = badServerSalt.NewServerSalt; + + SaveConfig(); + } + + HistoryItem item = null; + lock (_historyRoot) + { + if (_history.ContainsKey(badServerSalt.BadMessageId.Value)) + { + item = _history[badServerSalt.BadMessageId.Value]; + } + else + { + Execute.ShowDebugMessage("TLBadServerSalt lost item id=" + badServerSalt.BadMessageId); + } + } + + Logs.Log.Write(string.Format("{0} {1}", badServerSalt, item)); + + ProcessBadServerSalt(transportMessage, badServerSalt, item); + } + + // new session created + foreach (var newSessionCreated in TLUtils.FindInnerObjects(transportMessage)) + { + TLUtils.WritePerformance(string.Format("NEW SESSION CREATED: {0} (old {1})", transportMessage.SessionId, _activeTransport.SessionId)); + lock (_activeTransportRoot) + { + _activeTransport.SessionId = transportMessage.SessionId; + _activeTransport.Salt = newSessionCreated.ServerSalt; + } + } + + foreach (var pong in TLUtils.FindInnerObjects(transportMessage)) + { + HistoryItem item; + lock (_historyRoot) + { + if (_history.ContainsKey(pong.MessageId.Value)) + { + item = _history[pong.MessageId.Value]; + _history.Remove(pong.MessageId.Value); + } + else + { + //Execute.ShowDebugMessage("TLPong lost item id=" + pong.MessageId); + continue; + } + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + + if (item != null) + { + item.Callback.SafeInvoke(pong); + } + } + + // rpcresults + foreach (var result in TLUtils.FindInnerObjects(transportMessage)) + { + HistoryItem historyItem = null; + + lock (_historyRoot) + { + if (_history.ContainsKey(result.RequestMessageId.Value)) + { + historyItem = _history[result.RequestMessageId.Value]; + //#if !DEBUG + _history.Remove(result.RequestMessageId.Value); + //Debug.WriteLine("History remove msg_id={0} obj={1}", result.RequestMessageId, result.Object); +#if DEBUG + _removedHistory[result.RequestMessageId.Value] = new HistoryItem { Caption = historyItem.Caption }; +#endif + //#endif + } + else + { +#if DEBUG + //Debug.WriteLine("History missing msg_id={0} obj={1}", result.RequestMessageId, result.Object); + if (_removedHistory.ContainsKey(result.RequestMessageId.Value)) + { + var removedHistoryItem = _removedHistory[result.RequestMessageId.Value]; + + Execute.ShowDebugMessage(string.Format("TLRPCResult LostItem msg_id={0} caption={1} result={2}", result.RequestMessageId, removedHistoryItem != null ? removedHistoryItem.Caption : "null", result.Object)); + } + else + { + HistoryItem removedHistoryItem = null; + + Execute.ShowDebugMessage(string.Format("TLRPCResult LostItem msg_id={0} caption={1} result={2}", result.RequestMessageId, removedHistoryItem != null ? removedHistoryItem.Caption : "null", result.Object)); + } +#endif + continue; + } + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + + var error = result.Object as TLRPCError; + if (error != null) + { + string errorString; + var reqError = error as TLRPCReqError; + if (reqError != null) + { + errorString = string.Format("RPCReqError {1} {2} (query_id={0})", reqError.QueryId, reqError.Code, reqError.Message); + } + else + { + errorString = string.Format("RPCError {0} {1}", error.Code, error.Message); + } + + Execute.ShowDebugMessage(historyItem + Environment.NewLine + errorString); + ProcessRPCError(error, historyItem, encryptedMessage.AuthKeyId.Value); + Debug.WriteLine(errorString + " msg_id=" + result.RequestMessageId.Value); + TLUtils.WriteLine(errorString); + } + else + { + var messageData = result.Object; + if (messageData is TLGzipPacked) + { + messageData = ((TLGzipPacked)messageData).Data; + } + + if (messageData is TLSentMessageBase + || messageData is TLStatedMessageBase + || messageData is TLUpdatesBase + || messageData is TLSentEncryptedMessage + || messageData is TLSentEncryptedFile + || messageData is TLAffectedHistory + || messageData is TLAffectedMessages + || historyItem.Object is TLReadChannelHistory + || historyItem.Object is TLReadEncryptedHistory) + { + RemoveFromQueue(historyItem); + } + + if (historyItem.Caption == "messages.getDialogs") + { +#if DEBUG_UPDATEDCOPTIONS + var dcOption = new TLDCOption + { + Hostname = new TLString(""), + Id = new TLInt(2), + IpAddress = new TLString("109.239.131.193"), + Port = new TLInt(80) + }; + var dcOptions = new TLVector {dcOption}; + var update = new TLUpdateDCOptions {DCOptions = dcOptions}; + var updateShort = new TLUpdatesShort {Date = new TLInt(0), Update = update}; + + _updatesService.ProcessTransportMessage(new TLTransportMessage{MessageData = updateShort}); +#endif + } + try + { + historyItem.Callback(messageData); + } + catch (Exception e) + { +#if LOG_REGISTRATION + TLUtils.WriteLog(e.ToString()); +#endif + TLUtils.WriteException(e); + } + } + } + } + catch (Exception e) + { + TLUtils.WriteException("ReceiveBytesAsync", e); + + ResetConnection(e); + } + } + + private void ResetConnectionByTransport(ITransport transport, Exception ex) + { + ClearHistoryByTransport(transport); + + lock (transport.SyncRoot) + { + // continue listening on fault + transport = GetTransport(transport.Host, transport.Port, Type, + new TransportSettings + { + DcId = transport.DCId, + Secret = transport.Secret, + AuthKey = transport.AuthKey, + Salt = transport.Salt, + SessionId = transport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = transport.SequenceNumber, + ClientTicksDelta = transport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceivedByTransport + }); + } + // to bind authKey to current TCPTransport + PingByTransportAsync(transport, TLLong.Random(), result => { }); + } + + private void ResetConnection(Exception ex) + { + ClearHistory("ResetConnection", false, false, ex); + + // continue listening on fault + _activeTransport = GetTransport(_activeTransport.Host, _activeTransport.Port, Type, + new TransportSettings + { + DcId = _activeTransport != null ? _activeTransport.DCId : 0, + Secret = _activeTransport != null ? _activeTransport.Secret : null, + AuthKey = _activeTransport != null ? _activeTransport.AuthKey : null, + Salt = _activeTransport != null ? _activeTransport.Salt : null, + SessionId = _activeTransport != null ? _activeTransport.SessionId : null, + MessageIdDict = _activeTransport != null ? _activeTransport.MessageIdDict : new Dictionary(), + SequenceNumber = _activeTransport != null ? _activeTransport.SequenceNumber : 0, + ClientTicksDelta = _activeTransport != null ? _activeTransport.ClientTicksDelta : 0, + PacketReceivedHandler = OnPacketReceived + }); + + // to bind authKey to current TCPTransport, get changes, etc... + PingAsync(TLLong.Random(), pong => { }); + } + + public void Stop() + { + _transportService.CheckConfig -= OnCheckConfig; + _transportService.ConnectionLost -= OnConnectionLost; + _transportService.FileConnectionLost -= OnFileConnectionLost; + _transportService.SpecialConnectionLost -= OnSpecialConnectionLost; + _transportService.Close(); + + var history = new List(); + lock (_historyRoot) + { + foreach (var keyValue in _history) + { + history.Add(keyValue.Value); + } + _history.Clear(); + } + + foreach (var keyValue in history) + { + keyValue.FaultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("MTProtoService.Stop") }); + } + } + + public void ClearHistory(string caption, bool createNewSession, bool syncFaultCallbacks = false, Exception e = null) + { + var errorDebugString = string.Format("{0} clear history start {1}", DateTime.Now.ToString("HH:mm:ss.fff"), _history.Count); + TLUtils.WriteLine(errorDebugString, LogSeverity.Error); + + _transportService.Close(); + if (createNewSession) + { + _activeTransport.SessionId = TLLong.Random(); + _activeTransport.MessageIdDict = new Dictionary(); + } + // сначала очищаем reqPQ, reqDHParams и setClientDHParams + _activeTransport.ClearNonEncryptedHistory(); + + //затем очищаем help.getNearestDc, help.getConfig и любые другие методы + //иначе при вызове faultCallback для help.getNearestDc, help.getConfig и reqPQ снова бы завершился с ошибкой + // при вызове ClearNonEncryptedHistory + var history = new List(); + lock (_historyRoot) + { + foreach (var keyValue in _history) + { + history.Add(keyValue.Value); + } + _history.Clear(); + } + + if (syncFaultCallbacks) + { + foreach (var keyValue in history) + { + keyValue.FaultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("MTProtoService.ClearHistory " + caption), Exception = e }); + } + } + else + { + Execute.BeginOnThreadPool(() => + { + foreach (var keyValue in history) + { + keyValue.FaultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("MTProtoService.ClearHistory " + caption), Exception = e }); + } + }); + } + } + + private void ResetConnection(ITransport transport, Exception ex) + { + Execute.ShowDebugMessage("ResetConnection dc_id=" + transport.DCId); + + ClearHistory("ResetConnection dc_id=" + transport.DCId, false, false, ex); + } + + public void ClearHistory(string caption, ITransport transport, Exception e = null) + { + var errorDebugString = string.Format("{0} clear history start {1}", DateTime.Now.ToString("HH:mm:ss.fff"), _history.Count); + TLUtils.WriteLine(errorDebugString, LogSeverity.Error); + + _transportService.CloseTransport(transport); + // сначала очищаем reqPQ, reqDHParams и setClientDHParams + transport.ClearNonEncryptedHistory(); + + //затем очищаем help.getNearestDc, help.getConfig и любые другие методы + //иначе при вызове faultCallback для help.getNearestDc, help.getConfig и reqPQ снова бы завершился с ошибкой + // при вызове ClearNonEncryptedHistory + var history = new List(); + lock (_historyRoot) + { + foreach (var keyValue in _history) + { + if (keyValue.Value.DCId == transport.DCId) + { + history.Add(keyValue.Value); + } + } + foreach (var historyItem in history) + { + _history.Remove(historyItem.Hash); + } + } + + Execute.BeginOnThreadPool(() => + { + foreach (var keyValue in history) + { + keyValue.FaultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString("MTProtoService.ClearHistory " + caption), Exception = e }); + } + }); + } + + private void ProcessRPCError(TLRPCError error, HistoryItem historyItem, long keyId) + { + Log.Write(string.Format("RPCError {0} {1}", historyItem.Caption, error)); + +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("RPCError {0} {1}", historyItem.Caption, error)); +#endif + + if (error.CodeEquals(ErrorCode.UNAUTHORIZED)) + { + Execute.ShowDebugMessage(string.Format("RPCError {0} {1}", historyItem.Caption, error)); + + if (historyItem != null + && historyItem.Caption != "account.updateStatus" + && historyItem.Caption != "account.registerDevice" + && historyItem.Caption != "auth.signIn") + { + //Execute.ShowDebugMessage(string.Format("RPCError {0} {1} (auth required)", historyItem.Caption, error)); + RaiseAuthorizationRequired(new AuthorizationRequiredEventArgs { Error = error, MethodName = historyItem.Caption, AuthKeyId = keyId }); + } + else if (historyItem != null && historyItem.FaultCallback != null) + { + historyItem.FaultCallback(error); + } + } + else if (error.CodeEquals(ErrorCode.ERROR_SEE_OTHER) + && (error.TypeStarsWith(ErrorType.NETWORK_MIGRATE) + || error.TypeStarsWith(ErrorType.PHONE_MIGRATE) + //|| error.TypeStarsWith(ErrorType.FILE_MIGRATE) + )) + { + + var serverNumber = Convert.ToInt32( + error.GetErrorTypeString() + .Replace(ErrorType.NETWORK_MIGRATE.ToString(), string.Empty) + .Replace(ErrorType.PHONE_MIGRATE.ToString(), string.Empty) + //.Replace(ErrorType.FILE_MIGRATE.ToString(), string.Empty) + .Replace("_", string.Empty)); + + if (_config == null + || TLUtils.GetDCOption(_config, new TLInt(serverNumber)) == null) + { + GetConfigAsync(config => + { + // параметры предыдущего подключения не сохраняются, поэтому когда ответ приходит после + // подключения к следующему серверу, то не удается расшифровать старые сообщения, пришедшие с + // задержкой с новой солью и authKey + _config = TLConfig.Merge(_config, config); + SaveConfig(); + if (historyItem.Object.GetType() == typeof(TLSendCode)) + { + var dcOption = TLUtils.GetDCOption(_config, new TLInt(serverNumber)); + + _activeTransport = GetTransport(dcOption.IpAddress.ToString(), dcOption.Port.Value, Type, + new TransportSettings + { + DcId = dcOption.Id.Value, + Secret = TLUtils.ParseSecret(dcOption), + AuthKey = dcOption.AuthKey, + Salt = dcOption.Salt, + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = dcOption.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); + + //IsInitialized = false; + InitAsync(tuple => + { + lock (_activeTransportRoot) + { + _activeTransport.DCId = serverNumber; + _activeTransport.AuthKey = tuple.Item1; + _activeTransport.Salt = tuple.Item2; + _activeTransport.SessionId = tuple.Item3; + } + var authKeyId = TLUtils.GenerateLongAuthKeyId(tuple.Item1); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = tuple.Item1, AutkKeyId = authKeyId }); + } + } + + dcOption.AuthKey = tuple.Item1; + dcOption.Salt = tuple.Item2; + dcOption.SessionId = tuple.Item3; + + _config.ActiveDCOptionIndex = _config.DCOptions.IndexOf(dcOption); + _cacheService.SetConfig(_config); + + //IsInitialized = true; + RaiseInitialized(); + + SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback); + }, + er => + { + //restore previous transport + var activeDCOption = _config.DCOptions[_config.ActiveDCOptionIndex]; + _activeTransport = GetTransport(activeDCOption.IpAddress.ToString(), activeDCOption.Port.Value, Type, + new TransportSettings + { + DcId = activeDCOption.Id.Value, + Secret = TLUtils.ParseSecret(activeDCOption), + AuthKey = activeDCOption.AuthKey, + Salt = activeDCOption.Salt, + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = activeDCOption.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("RPCError restore transport {0} {1}:{2} item {3}", _activeTransport.Id, _activeTransport.Host, _activeTransport.Port, historyItem.Caption)); +#endif + + historyItem.FaultCallback.SafeInvoke(er); + }); + } + else + { + MigrateAsync(serverNumber, auth => SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback)); + } + }); + } + else + { + if (historyItem.Object.GetType() == typeof(TLSendCode) + || historyItem.Object.GetType() == typeof(TLGetFile)) + { + var activeDCOption = TLUtils.GetDCOption(_config, new TLInt(serverNumber)); + + _activeTransport = GetTransport(activeDCOption.IpAddress.ToString(), activeDCOption.Port.Value, Type, + new TransportSettings + { + DcId = activeDCOption.Id.Value, + Secret = TLUtils.ParseSecret(activeDCOption), + AuthKey = activeDCOption.AuthKey, + Salt = activeDCOption.Salt, + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = activeDCOption.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); + + if (activeDCOption.AuthKey == null) + { + //IsInitialized = false; + InitAsync(tuple => + { + lock (_activeTransportRoot) + { + _activeTransport.DCId = serverNumber; + _activeTransport.AuthKey = tuple.Item1; + _activeTransport.Salt = tuple.Item2; + _activeTransport.SessionId = tuple.Item3; + } + + var authKeyId = TLUtils.GenerateLongAuthKeyId(tuple.Item1); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = tuple.Item1, AutkKeyId = authKeyId }); + } + } + + activeDCOption.AuthKey = tuple.Item1; + activeDCOption.Salt = tuple.Item2; + activeDCOption.SessionId = tuple.Item3; + + _config.ActiveDCOptionIndex = _config.DCOptions.IndexOf(activeDCOption); + _cacheService.SetConfig(_config); + + //IsInitialized = true; + RaiseInitialized(); + + SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback); + }, + er => + { + //restore previous transport + var activeDCOption2 = _config.DCOptions[_config.ActiveDCOptionIndex]; + _activeTransport = GetTransport(activeDCOption2.IpAddress.ToString(), activeDCOption2.Port.Value, Type, + new TransportSettings + { + DcId = activeDCOption2.Id.Value, + Secret = TLUtils.ParseSecret(activeDCOption2), + AuthKey = activeDCOption2.AuthKey, + Salt = activeDCOption2.Salt, + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = activeDCOption2.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("RPCError restore transport {0} {1}:{2} item {3}", _activeTransport.Id, _activeTransport.Host, _activeTransport.Port, historyItem.Caption)); +#endif + + historyItem.FaultCallback.SafeInvoke(er); + }); + } + else + { + lock (_activeTransportRoot) + { + _activeTransport.AuthKey = activeDCOption.AuthKey; + _activeTransport.Salt = activeDCOption.Salt; + _activeTransport.SessionId = TLLong.Random(); + } + var authKeyId = TLUtils.GenerateLongAuthKeyId(activeDCOption.AuthKey); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = activeDCOption.AuthKey, AutkKeyId = authKeyId }); + } + } + + _config.ActiveDCOptionIndex = _config.DCOptions.IndexOf(activeDCOption); + _cacheService.SetConfig(_config); + + //IsInitialized = true; + RaiseInitialized(); + + SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback); + } + } + else + { + MigrateAsync(serverNumber, auth => SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback)); + } + } + } + else if (error.CodeEquals(ErrorCode.ERROR_SEE_OTHER) + && error.TypeStarsWith(ErrorType.USER_MIGRATE)) + { + //return; + + var serverNumber = Convert.ToInt32( + error.GetErrorTypeString() + .Replace(ErrorType.USER_MIGRATE.ToString(), string.Empty) + .Replace("_", string.Empty)); + + // фикс версии 0.1.3.13 когда первый конфиг для dc2 отличался от стартового dc2 + // можно убрать после + if (_config.ActiveDCOptionIndex == 0 && serverNumber == 2) + { + var activeDCOption = TLUtils.GetDCOption(_config, new TLInt(serverNumber)); + + _activeTransport = GetTransport(activeDCOption.IpAddress.ToString(), activeDCOption.Port.Value, Type, + new TransportSettings + { + DcId = activeDCOption.Id.Value, + Secret = TLUtils.ParseSecret(activeDCOption), + AuthKey = activeDCOption.AuthKey, + Salt = activeDCOption.Salt, + SessionId = TLLong.Random(), + MessageIdDict = new Dictionary(), + SequenceNumber = 0, + ClientTicksDelta = activeDCOption.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); + + var authKeyId = TLUtils.GenerateLongAuthKeyId(activeDCOption.AuthKey); + + lock (_authKeysRoot) + { + if (!_authKeys.ContainsKey(authKeyId)) + { + _authKeys.Add(authKeyId, new AuthKeyItem { AuthKey = activeDCOption.AuthKey, AutkKeyId = authKeyId }); + } + } + + _config.ActiveDCOptionIndex = _config.DCOptions.IndexOf(activeDCOption); + _cacheService.SetConfig(_config); + + SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback); + } + // конец фикса + + //ITransport newTransport; + //TLDCOption newActiveDCOption; + //lock (_activeTransportRoot) + //{ + // newActiveDCOption = _config.DCOptions.First(x => x.IsValidIPv4Option(new TLInt(serverNumber))); + + // var transportClientsTicksDelta = newActiveDCOption.ClientTicksDelta; + // bool isCreated; + // newTransport = _transportService.GetTransport(newActiveDCOption.IpAddress.ToString(), newActiveDCOption.Port.Value, Type, out isCreated); + // newTransport.ClientTicksDelta = transportClientsTicksDelta; + // newTransport.PacketReceived += OnPacketReceived; + //} + + //if (newTransport.AuthKey == null) + //{ + // InitTransportAsync(newTransport, + // tuple => + // { + // lock (newTransport.SyncRoot) + // { + // newTransport.AuthKey = tuple.Item1; + // newTransport.Salt = tuple.Item2; + // newTransport.SessionId = tuple.Item3; + + // newTransport.IsInitializing = false; + // } + // var authKeyId = TLUtils.GenerateLongAuthKeyId(tuple.Item1); + + // lock (_authKeysRoot) + // { + // if (!_authKeys.ContainsKey(authKeyId)) + // { + // _authKeys.Add(authKeyId, new AuthKeyItem {AuthKey = tuple.Item1, AutkKeyId = authKeyId}); + // } + // } + + // foreach (var dcOption in _config.DCOptions) + // { + // if (dcOption.Id.Value == newTransport.Id) + // { + // dcOption.AuthKey = tuple.Item1; + // dcOption.Salt = tuple.Item2; + // dcOption.SessionId = tuple.Item3; + // } + // } + + // _cacheService.SetConfig(_config); + + // ExportImportAuthorizationAsync( + // newTransport, + // () => + // { + // lock (_activeTransportRoot) + // { + // _activeTransport = newTransport; + // } + + // _config.ActiveDCOptionIndex = _config.DCOptions.IndexOf(newActiveDCOption); + // SaveConfig(); + + // SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback); + // }, + // err => + // { + + // }); + // }, + // er => + // { + + // }); + //} + //else + //{ + // ExportImportAuthorizationAsync( + // newTransport, + // () => + // { + // lock (_activeTransportRoot) + // { + // _activeTransport = newTransport; + // } + + // _config.ActiveDCOptionIndex = _config.DCOptions.IndexOf(newActiveDCOption); + // SaveConfig(); + + // SendInformativeMessage(historyItem.Caption, historyItem.Object, historyItem.Callback, historyItem.FaultCallback); + // }, + // err => + // { + + // }); + //} + + } + else if (historyItem.FaultCallback != null) + { + historyItem.FaultCallback(error); + } + } + + private void MigrateAsync(int serverNumber, Action callback) + { + throw new NotImplementedException(); + + //ExportAuthorizationAsync(new TLInt(serverNumber), + // exportedAuthorization => + // { + // var dcOption = _config.DCOptions.First(x => x.IsValidIPv4Option(new TLInt(serverNumber))); + // _activeTransport.SetAddress(dcOption.IpAddress.ToString(), dcOption.Port.Value); + + // _isInitialized = false; + // NotifyOfPropertyChange(() => IsInitialized); + + // _authHelper.InitAsync(tuple => + // { + // ImportAuthorizationAsync(exportedAuthorization.Id, exportedAuthorization.Bytes, callback); + // _isInitialized = true; + // NotifyOfPropertyChange(() => IsInitialized); + // RaiseInitialized(); + // }); + // }); + } + + private void ProcessBadMessage(TLTransportMessage message, TLBadMessageNotification badMessage, HistoryItem historyItem) + { + if (historyItem == null) return; + + switch (badMessage.ErrorCode.Value) + { + case 16: // слишком маленький msg_id + case 17: // слишком большой msg_id + var errorInfo = new StringBuilder(); + errorInfo.AppendLine("2. CORRECT TIME DELTA for active transport " + _activeTransport.DCId); + errorInfo.AppendLine(historyItem.Caption); + + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + + var saveConfig = false; + lock (_activeTransportRoot) + { + var serverTime = message.MessageId.Value; + var clientTime = _activeTransport.GenerateMessageId().Value; + + var serverDateTime = Utils.UnixTimestampToDateTime(serverTime >> 32); + var clientDateTime = Utils.UnixTimestampToDateTime(clientTime >> 32); + + errorInfo.AppendLine("Server time: " + serverDateTime); + errorInfo.AppendLine("Client time: " + clientDateTime); + + if (historyItem.ClientTicksDelta == _activeTransport.ClientTicksDelta) + { + saveConfig = true; + _activeTransport.ClientTicksDelta += serverTime - clientTime; + errorInfo.AppendLine("Set ticks delta: " + _activeTransport.ClientTicksDelta + "(" + (serverDateTime - clientDateTime).TotalSeconds + " seconds)"); + } + } + + TLUtils.WriteLine(errorInfo.ToString(), LogSeverity.Error); + + if (saveConfig && _config != null) + { + var dcOption = _config.DCOptions.FirstOrDefault(x => string.Equals(x.IpAddress.ToString(), _activeTransport.Host, StringComparison.OrdinalIgnoreCase)); + if (dcOption != null) + { + dcOption.ClientTicksDelta = _activeTransport.ClientTicksDelta; + _cacheService.SetConfig(_config); + } + } + + // TODO: replace with SendInformativeMessage + + + var transportMessage = (TLContainerTransportMessage)historyItem.Message; + int sequenceNumber; + lock (_activeTransportRoot) + { + if (transportMessage.SeqNo.Value % 2 == 0) + { + sequenceNumber = 2 * _activeTransport.SequenceNumber; + } + else + { + sequenceNumber = 2 * _activeTransport.SequenceNumber + 1; + _activeTransport.SequenceNumber++; + } + + transportMessage.SeqNo = new TLInt(sequenceNumber); + transportMessage.MessageId = _activeTransport.GenerateMessageId(false); + } + + TLUtils.WriteLine("Corrected client time: " + TLUtils.MessageIdString(transportMessage.MessageId)); + var authKey = _activeTransport.AuthKey; + var encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + + lock (_historyRoot) + { + _history[historyItem.Hash] = historyItem; + } + var faultCallback = historyItem.FaultCallback; + lock (_activeTransportRoot) + { + if (_activeTransport.Closed) + { + _activeTransport = GetTransport(_activeTransport.Host, _activeTransport.Port, Type, + new TransportSettings + { + DcId = _activeTransport.DCId, + Secret = _activeTransport.Secret, + AuthKey = _activeTransport.AuthKey, + Salt = _activeTransport.Salt, + SessionId = _activeTransport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = _activeTransport.SequenceNumber, + ClientTicksDelta = _activeTransport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); + } + } + //Debug.WriteLine(">>{0, -30} MsgId {1} SeqNo {2,-4} SessionId {3} BadMsgId {4}", string.Format("{0}: {1}", historyItem.Caption, "time"), transportMessage.MessageId.Value, transportMessage.SeqNo.Value, message.SessionId.Value, badMessage.BadMessageId.Value); + + var captionString = string.Format("{0} {1} {2}", historyItem.Caption, message.SessionId, transportMessage.MessageId); + SendPacketAsync(_activeTransport, captionString, encryptedMessage, + result => + { + Debug.WriteLine("@{0} {1} result {2}", string.Format("{0}: {1}", historyItem.Caption, "time"), transportMessage.MessageId.Value, result); + + },//ReceiveBytesAsync(result, authKey), + error => + { + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + faultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404) }); + }); + + break; + + case 32: + case 33: + TLUtils.WriteLine(string.Format("ErrorCode={0} INCORRECT MSGSEQNO, CREATE NEW SESSION {1}", badMessage.ErrorCode.Value, historyItem.Caption), LogSeverity.Error); + Execute.ShowDebugMessage(string.Format("ErrorCode={0} INCORRECT MSGSEQNO, CREATE NEW SESSION {1}", badMessage.ErrorCode.Value, historyItem.Caption)); + + var previousMessageId = historyItem.Hash; + + // fix seqNo with creating new Session + lock (_activeTransportRoot) + { + _activeTransport.SessionId = TLLong.Random(); + _activeTransport.SequenceNumber = 0; + transportMessage = (TLTransportMessage)historyItem.Message; + if (transportMessage.SeqNo.Value % 2 == 0) + { + sequenceNumber = 2 * _activeTransport.SequenceNumber; + } + else + { + sequenceNumber = 2 * _activeTransport.SequenceNumber + 1; + _activeTransport.SequenceNumber++; + } + + transportMessage.SeqNo = new TLInt(sequenceNumber); + transportMessage.MessageId = _activeTransport.GenerateMessageId(true); + } + ((TLTransportMessage)transportMessage).SessionId = _activeTransport.SessionId; + + + // TODO: replace with SendInformativeMessage + TLUtils.WriteLine("Corrected client time: " + TLUtils.MessageIdString(transportMessage.MessageId)); + authKey = _activeTransport.AuthKey; + encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + + lock (_historyRoot) + { + _history.Remove(previousMessageId); + _history[historyItem.Hash] = historyItem; + } + faultCallback = historyItem.FaultCallback; + lock (_activeTransportRoot) + { + if (_activeTransport.Closed) + { + _activeTransport = GetTransport(_activeTransport.Host, _activeTransport.Port, Type, + new TransportSettings + { + DcId = _activeTransport.DCId, + Secret = _activeTransport.Secret, + AuthKey = _activeTransport.AuthKey, + Salt = _activeTransport.Salt, + SessionId = _activeTransport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = _activeTransport.SequenceNumber, + ClientTicksDelta = _activeTransport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); + } + } + //Debug.WriteLine(">>{0, -30} MsgId {1} SeqNo {2,-4} SessionId {3} BadMsgId {4}", string.Format("{0}: {1}", historyItem.Caption, "seqNo"), transportMessage.MessageId.Value, transportMessage.SeqNo.Value, message.SessionId.Value, badMessage.BadMessageId.Value); + + captionString = string.Format("{0} {1} {2}", historyItem.Caption, message.SessionId, transportMessage.MessageId); + SendPacketAsync(_activeTransport, captionString, encryptedMessage, + result => + { + Debug.WriteLine("@{0} {1} result {2}", string.Format("{0}: {1}", historyItem.Caption, "seqNo"), transportMessage.MessageId.Value, result); + + },//ReceiveBytesAsync(result, authKey)}, + error => { if (faultCallback != null) faultCallback(null); }); + + break; + } + } + + + + private void ProcessBadServerSalt(TLTransportMessage message, TLBadServerSalt badServerSalt, HistoryItem historyItem) + { + if (historyItem == null) + { + return; + } + + var transportMessage = (TLContainerTransportMessage)historyItem.Message; + lock (_historyRoot) + { + _history.Remove(historyItem.Hash); + } +#if DEBUG + NotifyOfPropertyChange(() => History); +#endif + + TLUtils.WriteLine("CORRECT SERVER SALT:"); + ((TLTransportMessage)transportMessage).Salt = badServerSalt.NewServerSalt; + //Salt = badServerSalt.NewServerSalt; + TLUtils.WriteLine("New salt: " + _activeTransport.Salt); + + switch (badServerSalt.ErrorCode.Value) + { + case 16: + case 17: + TLUtils.WriteLine("3. CORRECT TIME DELTA with Salt by activeTransport " + _activeTransport.DCId); + + var saveConfig = false; + lock (_activeTransportRoot) + { + var serverTime = message.MessageId.Value; + TLUtils.WriteLine("Server time: " + TLUtils.MessageIdString(BitConverter.GetBytes(serverTime))); + var clientTime = _activeTransport.GenerateMessageId().Value; + TLUtils.WriteLine("Client time: " + TLUtils.MessageIdString(BitConverter.GetBytes(clientTime))); + + if (historyItem.ClientTicksDelta == _activeTransport.ClientTicksDelta) + { + saveConfig = true; + _activeTransport.ClientTicksDelta += serverTime - clientTime; + } + + transportMessage.MessageId = _activeTransport.GenerateMessageId(true); + TLUtils.WriteLine("Corrected client time: " + TLUtils.MessageIdString(transportMessage.MessageId)); + } + + if (saveConfig && _config != null) + { + var dcOption = _config.DCOptions.FirstOrDefault(x => string.Equals(x.IpAddress.ToString(), _activeTransport.Host, StringComparison.OrdinalIgnoreCase)); + if (dcOption != null) + { + dcOption.ClientTicksDelta = _activeTransport.ClientTicksDelta; + _cacheService.SetConfig(_config); + } + } + + break; + case 48: + break; + } + + if (transportMessage == null) return; + + var authKey = _activeTransport.AuthKey; + var encryptedMessage = CreateTLEncryptedMessage(authKey, transportMessage); + lock (_historyRoot) + { + _history[historyItem.Hash] = historyItem; + } + var faultCallback = historyItem.FaultCallback; + lock (_activeTransportRoot) + { + if (_activeTransport.Closed) + { + _activeTransport = GetTransport(_activeTransport.Host, _activeTransport.Port, Type, + new TransportSettings + { + DcId = _activeTransport.DCId, + Secret = _activeTransport.Secret, + AuthKey = _activeTransport.AuthKey, + Salt = _activeTransport.Salt, + SessionId = _activeTransport.SessionId, + MessageIdDict = _activeTransport.MessageIdDict, + SequenceNumber = _activeTransport.SequenceNumber, + ClientTicksDelta = _activeTransport.ClientTicksDelta, + PacketReceivedHandler = OnPacketReceived + }); + } + } + + var captionString = string.Format("{0} {1} {2}", historyItem.Caption, message.SessionId, transportMessage.MessageId); + SendPacketAsync(_activeTransport, captionString, encryptedMessage, + result => + { + Debug.WriteLine("@{0} {1} result {2}", historyItem.Caption, transportMessage.MessageId.Value, result); + + },//ReceiveBytesAsync(result, authKey)}, + error => { if (faultCallback != null) faultCallback(new TLRPCError { Code = new TLInt(404), Message = new TLString("TCPTransport error") }); }); + } + + + private readonly IDisposable _statusSubscription; + + public event EventHandler SendStatus; + + public void RaiseSendStatus(SendStatusEventArgs e) + { + var handler = SendStatus; + if (handler != null) handler(this, e); + } + + public void Dispose() + { + _statusSubscription.Dispose(); + } + + private string _message; + + public string Message + { + get { return _message; } + set + { + if (_message != value) + { + _message = value; + NotifyOfPropertyChange(() => Message); + } + } + } + + private DispatcherTimer _messageScheduler; + + public void SetMessageOnTime(double seconds, string message) + { + //Logs.Log.Write(string.Format("MTProtoService.SetMessageOnTime sec={0}, message={1}", seconds, message)); + + Execute.BeginOnUIThread(() => + { + if (_messageScheduler == null) + { + _messageScheduler = new DispatcherTimer(); + _messageScheduler.Tick += MessageScheduler_Tick; + } + + _messageScheduler.Stop(); + Message = message; + _messageScheduler.Interval = TimeSpan.FromSeconds(seconds); + _messageScheduler.Start(); + }); + } + +#if WINDOWS_PHONE + private void MessageScheduler_Tick(object sender, EventArgs e) +#elif WIN_RT + private void MessageScheduler_Tick(object sender, object args) +#endif + { + Message = string.Empty; + _messageScheduler.Stop(); + } + + private ITransport GetTransportWithProxyInternal(GetTransportWithProxyFunc getTransportAction, string host, int port, TransportType type, bool checkStatic, TransportSettings settings, TLProxyBase proxy) + { + bool isCreated; + var staticHost = host; + var staticPort = port; + + // looking for static dcOption with none empty config + if (checkStatic) + { + var staticOption = GetStaticDCOption(settings.DcId); + if (staticOption != null) + { + staticHost = staticOption.IpAddress.ToString(); + staticPort = staticOption.Port.Value; + } + } + + ITransport transport; + lock (_activeTransportRoot) + { + transport = getTransportAction(host, port, staticHost, staticPort, type, TLUtils.GetProtocolDCId(settings.DcId, false, Constants.IsTestServer), settings.Secret, proxy, out isCreated); + } + if (isCreated) + { + transport.DCId = settings.DcId; + transport.Secret = settings.Secret; + transport.AuthKey = settings.AuthKey; + transport.Salt = settings.Salt; + transport.SessionId = settings.SessionId; + transport.MessageIdDict = settings.MessageIdDict; + transport.SequenceNumber = settings.SequenceNumber; + transport.ClientTicksDelta = settings.ClientTicksDelta; + transport.PacketReceived += settings.PacketReceivedHandler; + } + + return transport; + } + + private TLDCOption GetStaticDCOption(int dcId) + { + if (_config == null) return null; + + foreach (var item in _config.DCOptions.Items.Where(x => x.Static.Value)) + { + if (item.Id.Value == dcId) + { + return item; + } + } + + return null; + } + + private ITransport GetTransportInternal(GetTransportFunc getTransportAction, string host, int port, TransportType type, bool checkStatic, TransportSettings settings) + { + bool isCreated; + var staticHost = host; + var staticPort = port; + + // looking for static dcOption with none empty config + if (checkStatic) + { + var staticOption = GetStaticDCOption(settings.DcId); + if (staticOption != null) + { + staticHost = staticOption.IpAddress.ToString(); + staticPort = staticOption.Port.Value; + } + } + + ITransport transport; + lock (_activeTransportRoot) + { + transport = getTransportAction(host, port, staticHost, staticPort, type, TLUtils.GetProtocolDCId(settings.DcId, false, Constants.IsTestServer), settings.Secret, out isCreated); + } + if (isCreated) + { + transport.DCId = settings.DcId; + transport.Secret = settings.Secret; + transport.AuthKey = settings.AuthKey; + transport.Salt = settings.Salt; + transport.SessionId = settings.SessionId; + transport.MessageIdDict = settings.MessageIdDict; + transport.SequenceNumber = settings.SequenceNumber; + transport.ClientTicksDelta = settings.ClientTicksDelta; + transport.PacketReceived += settings.PacketReceivedHandler; + } + + return transport; + } + + private ITransport GetTransport(string host, int port, TransportType type, TransportSettings settings) + { + return GetTransportInternal(_transportService.GetTransport, host, port, type, true, settings); + } + + private ITransport GetFileTransport(string host, int port, TransportType type, TransportSettings settings) + { + return GetTransportInternal(_transportService.GetFileTransport, host, port, type, true, settings); + } + + private ITransport GetFileTransport2(string host, int port, int dcId, TransportType type, TransportSettings settings) + { + return GetTransportInternal(_transportService.GetFileTransport2, host, port, type, true, settings); + } + + private ITransport GetSpecialTransport(string host, int port, TransportType type, TransportSettings settings) + { + return GetTransportInternal(_transportService.GetSpecialTransport, host, port, type, false, settings); + } + + private ITransport GetSpecialTransportWithProxy(string host, int port, TransportType type, TLProxyBase proxy, TransportSettings settings) + { + return GetTransportWithProxyInternal(_transportService.GetSpecialTransport, host, port, type, true, settings, proxy); + } + } + + public class TransportSettings + { + public int DcId { get; set; } + public byte[] Secret { get; set; } + public byte[] AuthKey { get; set; } + public TLLong Salt { get; set; } + public TLLong SessionId { get; set; } + public Dictionary MessageIdDict { get; set; } + public int SequenceNumber { get; set; } + public long ClientTicksDelta { get; set; } + public EventHandler PacketReceivedHandler { get; set; } + } + + public class AuthorizationRequiredEventArgs : EventArgs + { + public string MethodName { get; set; } + + public long AuthKeyId { get; set; } + + public TLRPCError Error { get; set; } + } + + public class SendStatusEventArgs : EventArgs + { + public TLBool Offline { get; set; } + + public SendStatusEventArgs(TLBool offline) + { + Offline = offline; + } + } + + public class TransportCheckedEventArgs : EventArgs + { + public int TransportId { get; set; } + public TLLong SessionId { get; set; } + public byte[] AuthKey { get; set; } + public DateTime? LastReceiveTime { get; set; } + public int HistoryCount { get; set; } + public int NextPacketLength { get; set; } + public int LastPacketLength { get; set; } + public string HistoryDescription { get; set; } + } +} diff --git a/Telegram.Api/Services/Messages/ISenderService.cs b/Telegram.Api/Services/Messages/ISenderService.cs new file mode 100755 index 0000000..702a14f --- /dev/null +++ b/Telegram.Api/Services/Messages/ISenderService.cs @@ -0,0 +1,13 @@ +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Messages +{ + public interface ISenderService + { + void Send(TLMessageBase message); + void ResendAll(); + + void Open(); + void Close(); + } +} diff --git a/Telegram.Api/Services/Messages/SenderService.cs b/Telegram.Api/Services/Messages/SenderService.cs new file mode 100755 index 0000000..638da6b --- /dev/null +++ b/Telegram.Api/Services/Messages/SenderService.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Messages +{ + public class SenderService : ISenderService + { + private Queue _sendingQueue = new Queue(); + + private IMTProtoService _mtProtoService; + + public SenderService(IMTProtoService mtProtoService) + { + _mtProtoService = mtProtoService; + } + + public void Send(TLMessageBase message) + { + _sendingQueue.Enqueue(message); + } + + public void ResendAll() + { + + } + + public void Open() + { + + } + + public void Close() + { + + } + } +} diff --git a/Telegram.Api/Services/ServiceBase.cs b/Telegram.Api/Services/ServiceBase.cs new file mode 100755 index 0000000..6c11745 --- /dev/null +++ b/Telegram.Api/Services/ServiceBase.cs @@ -0,0 +1,152 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq.Expressions; +using System.Reflection; +using System.Runtime.Serialization; +using Telegram.Api.Helpers; + +namespace Telegram.Api.Services +{ + [DataContract] + public abstract class TelegramPropertyChangedBase : INotifyPropertyChanged + { + /// + /// Enables/Disables property change notification. + /// + /// + public bool IsNotifying { get; set; } + + private static bool _isNotifyingGlobal = true; + + public static bool IsNotifyingGlobal + { + get { return _isNotifyingGlobal; } + set { _isNotifyingGlobal = false; } + } + + private static bool _logNotify = false; + + public static bool LogNotify + { + get { return _logNotify; } + set { _logNotify = value; } + } + + /// + /// Occurs when a property value changes. + /// + /// + public event PropertyChangedEventHandler PropertyChanged = (param0, param1) => { }; + + + public TelegramPropertyChangedBase() + { + IsNotifying = true; + } + + /// + /// Raises a change notification indicating that all bindings should be refreshed. + /// + /// + public void Refresh() + { + NotifyOfPropertyChange(String.Empty); + } + + /// + /// Notifies subscribers of the property change. + /// + /// + /// Name of the property. + public virtual void NotifyOfPropertyChange(string propertyName) + { + if (!IsNotifyingGlobal) + return; + + if (!IsNotifying) + return; + +#if DEBUG + if (LogNotify) + { + Debug.WriteLine("Notify " + propertyName + " " + GetType()); + } +#endif + if (Execute.CheckAccess()) + { + OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); + } + else + { + Execute.BeginOnUIThread(() => OnPropertyChanged(new PropertyChangedEventArgs(propertyName))); + } + //Execute.OnUIThread(() => OnPropertyChanged(new PropertyChangedEventArgs(propertyName))); + } + + /// + /// Notifies subscribers of the property change. + /// + /// + /// The type of the property.The property expression. + public void NotifyOfPropertyChange(Expression> property) + { + this.NotifyOfPropertyChange(GetMemberInfo(property).Name); + } + + public static MemberInfo GetMemberInfo(Expression expression) + { + var lambdaExpression = (LambdaExpression)expression; + return (!(lambdaExpression.Body is UnaryExpression) ? (MemberExpression)lambdaExpression.Body : (MemberExpression)((UnaryExpression)lambdaExpression.Body).Operand).Member; + } + + /// + /// Raises the event directly. + /// + /// + /// The instance containing the event data. + [EditorBrowsable(EditorBrowsableState.Never)] + protected void OnPropertyChanged(PropertyChangedEventArgs e) + { + PropertyChangedEventHandler changedEventHandler = PropertyChanged; + if (changedEventHandler == null) + return; + changedEventHandler(this, e); + } + + /// + /// Called when the object is deserialized. + /// + /// + /// The streaming context. + [OnDeserialized] + public void OnDeserialized(StreamingContext c) + { + IsNotifying = true; + } + + /// + /// Used to indicate whether or not the IsNotifying property is serialized to Xml. + /// + /// + /// + /// + /// Whether or not to serialize the IsNotifying property. The default is false. + /// + public virtual bool ShouldSerializeIsNotifying() + { + return false; + } + } + + public abstract class ServiceBase : TelegramPropertyChangedBase + { + } +} diff --git a/Telegram.Api/Services/Updates/IUpdatesService.cs b/Telegram.Api/Services/Updates/IUpdatesService.cs new file mode 100755 index 0000000..5b4408d --- /dev/null +++ b/Telegram.Api/Services/Updates/IUpdatesService.cs @@ -0,0 +1,75 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Updates +{ + public delegate void GetDifferenceAction(TLInt pts, TLInt date, TLInt qts, Action callback, Action faultCallback); + public delegate void GetDHConfigAction(TLInt version, TLInt randomLength, Action callback, Action faultCallback); + public delegate void AcceptEncryptionAction(TLInputEncryptedChat peer, TLString gb, TLLong keyFingerprint, Action callback, Action faultCallback); + public delegate void SendEncryptedServiceAction(TLInputEncryptedChat peer, TLLong randomkId, TLString data, Action callback, Action faultCallback); + public delegate void UpdateChannelAction(TLInt channelId, Action callback, Action faultCallback); + public delegate void GetFullChatAction(TLInt chatId, Action callback, Action faultCallback); + public delegate void GetFullUserAction(TLInputUserBase userId, Action callback, Action faultCallback); + public delegate void GetPinnedDialogsAction(Action callback, Action faultCallback = null); + public delegate void GetChannelMessagesAction(TLInputChannelBase channelId, TLVector id, Action callback, Action faultCallback); + public delegate void GetMessagesAction(TLVector id, Action callback, Action faultCallback = null); + public delegate void GetPeerDialogsAction(TLInputPeerBase peer, Action callback, Action faultCallback = null); + public delegate void GetPromoDialogAction(TLInputPeerBase peer, Action callback, Action faultCallback = null); + + public delegate void SetMessageOnTimeAtion(double seconds, string message); + + public interface IUpdatesService + { + bool ProcessUpdateInternal(TLUpdateBase update, bool notifyNewMessage = true); + + void CancelUpdating(); + + IList SyncDifferenceExceptions { get; } + //void IncrementClientSeq(); + + Func GetCurrentUserId { get; set; } + + Action, Action> GetStateAsync { get; set; } + GetDHConfigAction GetDHConfigAsync { get; set; } + GetDifferenceAction GetDifferenceAsync { get; set; } + AcceptEncryptionAction AcceptEncryptionAsync { get; set; } + SendEncryptedServiceAction SendEncryptedServiceAsync { get; set; } + SetMessageOnTimeAtion SetMessageOnTimeAsync { get; set; } + Action RemoveFromQueue { get; set; } + UpdateChannelAction UpdateChannelAsync { get; set; } + GetFullChatAction GetFullChatAsync { get; set; } + GetFullUserAction GetFullUserAsync { get; set; } + GetChannelMessagesAction GetChannelMessagesAsync { get; set; } + GetPinnedDialogsAction GetPinnedDialogsAsync { get; set; } + GetMessagesAction GetMessagesAsync { get; set; } + GetPeerDialogsAction GetPeerDialogsAsync { get; set; } + GetPromoDialogAction GetPromoDialogAsync { get; set; } + + void SetInitState(); + + TLInt ClientSeq { get; } + void SetState(TLInt seq, TLInt pts, TLInt qts, TLInt date, TLInt unreadCount, string caption, bool cleanupMissingCounts = false); + void SetState(IMultiPts multiPts, string caption); + void ProcessTransportMessage(TLTransportMessage transportMessage); + void ProcessUpdates(TLUpdatesBase updates, bool notifyNewMessages = false); + + void LoadStateAndUpdate(long acceptedCallId, Action callback); + void SaveState(); + TLState GetState(); + void ClearState(); + + void SaveStateSnapshot(string toDirectoryName); + void LoadStateSnapshot(string fromDirectoryName); + + event EventHandler DCOptionsUpdated; + } +} diff --git a/Telegram.Api/Services/Updates/ReceiveUpdatesEventArgs.cs b/Telegram.Api/Services/Updates/ReceiveUpdatesEventArgs.cs new file mode 100755 index 0000000..409789a --- /dev/null +++ b/Telegram.Api/Services/Updates/ReceiveUpdatesEventArgs.cs @@ -0,0 +1,22 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Updates +{ + public class ReceiveUpdatesEventArgs : EventArgs + { + public TLUpdates Updates { get; protected set; } + + public ReceiveUpdatesEventArgs(TLUpdates updates) + { + Updates = updates; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Services/Updates/UpdatesBySeqComparer.cs b/Telegram.Api/Services/Updates/UpdatesBySeqComparer.cs new file mode 100755 index 0000000..12ecebc --- /dev/null +++ b/Telegram.Api/Services/Updates/UpdatesBySeqComparer.cs @@ -0,0 +1,42 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Updates +{ + //public class UpdatesBySeqComparer : IComparer + //{ + // private const int XIsLessThanY = -1; + // private const int XEqualsY = 0; + // private const int XIsGreaterThanY = 1; + + // public int Compare(TLUpdatesBase x, TLUpdatesBase y) + // { + // var xSeq = x.GetSeq(); + // var ySeq = y.GetSeq(); + + // if (xSeq == null && ySeq == null) + // { + // return x is TLUpdatesShort ? XIsLessThanY : XIsGreaterThanY; + // } + + // if (xSeq == null) + // { + // return XIsGreaterThanY; + // } + + // if (ySeq == null) + // { + // return XIsLessThanY; + // } + + // return xSeq.Value < ySeq.Value ? XIsLessThanY : (xSeq == ySeq ? XEqualsY : XIsGreaterThanY); + // } + //} +} \ No newline at end of file diff --git a/Telegram.Api/Services/Updates/UpdatesService.cs b/Telegram.Api/Services/Updates/UpdatesService.cs new file mode 100755 index 0000000..a29a8ae --- /dev/null +++ b/Telegram.Api/Services/Updates/UpdatesService.cs @@ -0,0 +1,4184 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define LOG_CLIENTSEQ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using Org.BouncyCastle.Bcpg; +using Org.BouncyCastle.Security; +using Telegram.Api.Helpers; +using Telegram.Logs; +#if DEBUG +using System.Windows; +#endif +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.Cache.EventArgs; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.Updates +{ + public class MockupUpdatesService : IUpdatesService + { + public void CancelUpdating() + { + + } + + public IList SyncDifferenceExceptions { get; private set; } + public Func GetCurrentUserId { get; set; } + public Action, Action> GetStateAsync { get; set; } + public GetDHConfigAction GetDHConfigAsync { get; set; } + public GetDifferenceAction GetDifferenceAsync { get; set; } + public AcceptEncryptionAction AcceptEncryptionAsync { get; set; } + public SendEncryptedServiceAction SendEncryptedServiceAsync { get; set; } + public SetMessageOnTimeAtion SetMessageOnTimeAsync { get; set; } + public Action RemoveFromQueue { get; set; } + public UpdateChannelAction UpdateChannelAsync { get; set; } + public GetFullChatAction GetFullChatAsync { get; set; } + public GetFullUserAction GetFullUserAsync { get; set; } + public GetChannelMessagesAction GetChannelMessagesAsync { get; set; } + public GetPinnedDialogsAction GetPinnedDialogsAsync { get; set; } + public GetMessagesAction GetMessagesAsync { get; set; } + public GetPeerDialogsAction GetPeerDialogsAsync { get; set; } + public GetPromoDialogAction GetPromoDialogAsync { get; set; } + + public void SetInitState() + { + + } + + public TLInt ClientSeq { get; private set; } + + public void SetState(TLInt seq, TLInt pts, TLInt qts, TLInt date, TLInt unreadCount, string caption, bool cleanupMissingCounts = false) + { + + } + + public void SetState(IMultiPts multiPts, string caption) + { + + } + + public void ProcessTransportMessage(TLTransportMessage transportMessage) + { + + } + + public void ProcessUpdates(TLUpdatesBase updates, bool notifyNewMessages = false) + { + + } + + public void LoadStateAndUpdate(long acceptedCallId, Action callback) + { + + } + + public void SaveState() + { + + } + + public TLState GetState() + { + throw new NotImplementedException(); + } + + public void ClearState() + { + + } + + public void SaveStateSnapshot(string toDirectoryName) + { + + } + + public void LoadStateSnapshot(string fromDirectoryName) + { + + } + + public event EventHandler DCOptionsUpdated; + + public bool ProcessUpdateInternal(TLUpdateBase update, bool notifyNewMessage = true) + { + throw new NotImplementedException(); + } + } + + public class UpdatesService : IUpdatesService + { + public TLUserBase CurrentUser { get; set; } + + private readonly ICacheService _cacheService; + + private readonly ITelegramEventAggregator _eventAggregator; + + public Func GetCurrentUserId { get; set; } + + public Action, Action> GetStateAsync { get; set; } + public GetDHConfigAction GetDHConfigAsync { get; set; } + public GetDifferenceAction GetDifferenceAsync { get; set; } + public AcceptEncryptionAction AcceptEncryptionAsync { get; set; } + public SendEncryptedServiceAction SendEncryptedServiceAsync { get; set; } + public SetMessageOnTimeAtion SetMessageOnTimeAsync { get; set; } + public Action RemoveFromQueue { get; set; } + public UpdateChannelAction UpdateChannelAsync { get; set; } + public GetFullChatAction GetFullChatAsync { get; set; } + public GetFullUserAction GetFullUserAsync { get; set; } + public GetChannelMessagesAction GetChannelMessagesAsync { get; set; } + public GetPinnedDialogsAction GetPinnedDialogsAsync { get; set; } + public GetMessagesAction GetMessagesAsync { get; set; } + public GetPeerDialogsAction GetPeerDialogsAsync { get; set; } + public GetPromoDialogAction GetPromoDialogAsync { get; set; } + + private readonly Timer _lostSeqTimer; + + private readonly Timer _lostPtsTimer; + + public UpdatesService(ICacheService cacheService, ITelegramEventAggregator eventAggregator) + { + _lostSeqTimer = new Timer(OnCheckLostSeq, this, Timeout.Infinite, Timeout.Infinite); + _lostPtsTimer = new Timer(OnCheckLostPts, this, Timeout.Infinite, Timeout.Infinite); + + _cacheService = cacheService; + _eventAggregator = eventAggregator; + } + + private void StartLostSeqTimer() + { + _lostSeqTimer.Change(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)); + TLUtils.WriteLine(DateTime.Now.ToString(" HH:mm:ss.fff", CultureInfo.InvariantCulture) + " Start lostSeqTimer", LogSeverity.Error); + + } + + private void StopLostSeqTimer() + { + _lostSeqTimer.Change(Timeout.Infinite, Timeout.Infinite); + TLUtils.WriteLine(DateTime.Now.ToString(" HH:mm:ss.fff", CultureInfo.InvariantCulture) + " Stop lostSeqTimer", LogSeverity.Error); + } + + private void StartLostPtsTimer() + { + _lostPtsTimer.Change(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)); + TLUtils.WriteLine(DateTime.Now.ToString(" HH:mm:ss.fff", CultureInfo.InvariantCulture) + " Start lostPtsTimer", LogSeverity.Error); + + } + + private void StopLostPtsTimer() + { + _lostPtsTimer.Change(Timeout.Infinite, Timeout.Infinite); + TLUtils.WriteLine(DateTime.Now.ToString(" HH:mm:ss.fff", CultureInfo.InvariantCulture) + " Stop lostPtsTimer", LogSeverity.Error); + } + + private void OnCheckLostSeq(object state) + { + TLUtils.WriteLine(DateTime.Now.ToString(" HH:mm:ss.fff", CultureInfo.InvariantCulture) + " OnCheck lostSeqTimer", LogSeverity.Error); + var getDifference = false; + var isLostSeqEmpty = true; + var keyValuePair = default(KeyValuePair>); + lock (_clientSeqLock) + { + foreach (var keyValue in _lostSeq.OrderBy(x => x.Key)) + { + isLostSeqEmpty = false; + if (DateTime.Now > keyValue.Value.Item1.AddSeconds(3.0)) + { + getDifference = true; + keyValuePair = keyValue; + break; + } + } + } + + if (isLostSeqEmpty) + { + StopLostSeqTimer(); + } + + if (getDifference) + { + var seq = keyValuePair.Key; + var pts = keyValuePair.Value.Item2.Pts; + var date = keyValuePair.Value.Item2.Date; + var qts = keyValuePair.Value.Item2.Qts; + + Helpers.Execute.ShowDebugMessage(string.Format("stub lostSeqTimer.getDifference(seq={0}, pts={1}, date={2}, qts={3}) localState=[seq={4}, pts={5}, date={6}, qts={7}]", seq, pts, date, qts, ClientSeq, _pts, _date, _qts)); + StopLostSeqTimer(); + + lock (_clientSeqLock) + { + _lostSeq.Clear(); + } + //GetDifference(() => + //{ + + //}); + } + } + + private void OnCheckLostPts(object state) + { + TLUtils.WriteLine(DateTime.Now.ToString(" HH:mm:ss.fff", CultureInfo.InvariantCulture) + " OnCheck lostPtsTimer", LogSeverity.Error); + var getDifference = false; + var isLostPtsEmpty = true; + var keyValuePair = default(KeyValuePair>); + lock (_clientPtsLock) + { + foreach (var keyValue in _lostPts.OrderBy(x => x.Key)) + { + isLostPtsEmpty = false; + if (DateTime.Now > keyValue.Value.Item1.AddSeconds(3.0)) + { + getDifference = true; + keyValuePair = keyValue; + break; + } + } + } + + if (isLostPtsEmpty) + { + StopLostPtsTimer(); + } + + if (getDifference) + { + var seq = keyValuePair.Value.Item2.Seq; + var pts = keyValuePair.Key; + var date = keyValuePair.Value.Item2.Date; + var qts = keyValuePair.Value.Item2.Qts; + + Helpers.Execute.ShowDebugMessage(string.Format("stub lostSeqTimer.getDifference(seq={0}, pts={1}, date={2}, qts={3}) localState=[seq={4}, pts={5}, date={6}, qts={7}]", seq, pts, date, qts, ClientSeq, _pts, _date, _qts)); + StopLostPtsTimer(); + + lock (_clientPtsLock) + { + _lostPts.Clear(); + } + //GetDifference(() => + //{ + + //}); + } + } + + public void SetState(IMultiPts multiPts, string caption) + { + var ptsList = TLUtils.GetPtsRange(multiPts); + + if (ptsList.Count == 0) + { + ptsList.Add(multiPts.Pts); + } +#if LOG_CLIENTSEQ + TLUtils.WriteLine(string.Format("{0} {1}\nclientSeq={2} newSeq={3}\npts={4} ptsList={5}\n", DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture), caption, ClientSeq != null ? ClientSeq.ToString() : "null", "null", _pts != null ? _pts.ToString() : "null", ptsList.Count > 0 ? string.Join(", ", ptsList) : "null"), LogSeverity.Error); +#endif + UpdateLostPts(ptsList); + } + + public TLInt ClientSeq { get; protected set; } + + private TLInt _dateInternal; + + private TLInt _date + { + get { return _dateInternal; } + set + { + _dateInternal = value; + } + } + + private TLInt _pts; + + private TLInt _qts = new TLInt(1); + + private TLInt _unreadCount; + + public void SetState(TLInt seq, TLInt pts, TLInt qts, TLInt date, TLInt unreadCount, string caption, bool cleanupMissingCounts = false) + { +#if LOG_CLIENTSEQ + TLUtils.WriteLine(string.Format("{0} {1}\nclientSeq={2} newSeq={3}\npts={4} newPts={5}\n", DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture), caption, ClientSeq != null ? ClientSeq.ToString() : "null", seq, _pts != null ? _pts.ToString() : "null", pts), LogSeverity.Error); + //TLUtils.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + " " + caption + " clientSeq=" + ClientSeq + " newSeq=" + seq + " pts=" + pts, LogSeverity.Error); +#endif + if (seq != null) + { + UpdateLostSeq(new List { seq }, cleanupMissingCounts); + } + + _date = date ?? _date; + + if (pts != null) + { + UpdateLostPts(new List { pts }, cleanupMissingCounts); + } + + _qts = qts ?? _qts; + _unreadCount = unreadCount ?? _unreadCount; + } + + public void SetState(TLState state, string caption) + { + if (state == null) return; + + Debug.WriteLine("SetState state={0}", state); + SetState(state.Seq, state.Pts, state.Qts, state.Date, state.UnreadCount, caption, true); + } + + public void SetInitState() + { + GetStateAsync.SafeInvoke( + result => SetState(result, "setInitState"), + error => Execute.BeginOnThreadPool(TimeSpan.FromSeconds(5.0), SetInitState)); + } + + private readonly object _getDifferenceRequestRoot = new object(); + + private readonly IList _getDifferenceRequests = new List(); + + private bool RequestExists(int id) + { + var result = false; + lock (_getDifferenceRequestRoot) + { + foreach (var differenceRequest in _getDifferenceRequests) + { + if (differenceRequest == id) + { + result = true; + break; + } + } + } + + return result; + } + + private void AddRequest(int id) + { + lock (_getDifferenceRequestRoot) + { + _getDifferenceRequests.Add(id); + } + } + + private void RemoveRequest(int id) + { + lock (_getDifferenceRequestRoot) + { + _getDifferenceRequests.Remove(id); + } + } + + public void CancelUpdating() + { + lock (_getDifferenceRequestRoot) + { + _getDifferenceRequests.Clear(); + } + } + + private void GetDifference(int id, Action callback) + { + if (_pts != null && _date != null && _qts != null) + { + GetDifference(id, _pts, _date, _qts, callback); + } + else + { + SetInitState(); + callback(); + } + } + + private void GetDifference(int id, TLInt pts, TLInt date, TLInt qts, Action callback) + { + Logs.Log.Write(string.Format("UpdatesService.GetDifference {0} state=[p={1} d={2} q={3}]", id, _pts, _date, _qts)); + TLUtils.WritePerformance(string.Format("UpdatesService.GetDifference pts={0} date={1} qts={2}", _pts, _date, _qts)); + + GetDifferenceAsync(pts, date, qts, + diff => + { + //#if DEBUG + // Execute.BeginOnThreadPool(TimeSpan.FromSeconds(5.0), () => + // { + //#endif + + var processDiffStopwatch = Stopwatch.StartNew(); + + var differenceEmpty = diff as TLDifferenceEmpty; + if (differenceEmpty != null) + { +#if LOG_CLIENTSEQ + TLUtils.WriteLine( + string.Format("{0} {1} clientSeq={2} newSeq={3} pts={4}", + DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture), + "processDiff empty", ClientSeq, differenceEmpty.Seq, _pts), LogSeverity.Error); +#endif + _date = differenceEmpty.Date; + lock (_clientSeqLock) + { + ClientSeq = differenceEmpty.Seq; + } + + Logs.Log.Write(string.Format("UpdatesService.GetDifference {0} result {1} elapsed={2}", id, + diff, processDiffStopwatch.Elapsed)); + + TLUtils.WritePerformance("UpdateService.GetDifference empty result=" + differenceEmpty.Seq); + + Execute.BeginOnThreadPool(() => + { + var updateChannelTooLongList = new List(); + + lock (_updateChannelTooLongSyncRoot) + { + foreach (var keyValue in _updateChannelTooLongList) + { + updateChannelTooLongList.Add(keyValue.Value); + } + _updateChannelTooLongList.Clear(); + } + + _eventAggregator.Publish(new UpdateChannelsEventArgs + { + UpdateChannelTooLongList = updateChannelTooLongList + }); + }); + + callback(); + return; + } + + var difference = diff as TLDifference; + if (difference != null) + { + //Logs.Log.Write("UpdatesService.Publish UpdatingEventArgs"); + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new UpdatingEventArgs())); + + var resetEvent = new ManualResetEvent(false); + + TLUtils.WritePerformance( + string.Format("UpdateService.GetDifference result=[Pts={0} Date={1} Qts={2}]", + difference.State.Pts, difference.State.Date, difference.State.Qts)); + lock (_clientSeqLock) + { + SetState(difference.State, "processDiff"); + } + ProcessDifference(difference, () => resetEvent.Set()); + +#if DEBUG + resetEvent.WaitOne(); +#else + resetEvent.WaitOne(10000); +#endif + } + + var otherInfo = new StringBuilder(); + if (difference != null && difference.OtherUpdates.Count > 0) + { + otherInfo.AppendLine(); + for (var i = 0; i < difference.OtherUpdates.Count; i++) + { + otherInfo.AppendLine(difference.OtherUpdates[i].ToString()); + } + } + Logs.Log.Write(string.Format("UpdatesService.GetDifference {0} result {1} elapsed={2}{3}", id, + diff, processDiffStopwatch.Elapsed, otherInfo)); + + var differenceSlice = diff as TLDifferenceSlice; + if (differenceSlice != null) + { + GetDifference(id, callback); + //GetDifference(differenceSlice.State.Pts, differenceSlice.State.Date, differenceSlice.State.Qts, callback); + } + else + { + Logs.Log.Write( + string.Format("UpdatesService.GetDifference {0} publish UpdateCompletedEventArgs", id)); + + Execute.BeginOnThreadPool(() => + { + var updateChannelTooLongList = new List(); + + lock (_updateChannelTooLongSyncRoot) + { + foreach (var keyValue in _updateChannelTooLongList) + { + updateChannelTooLongList.Add(keyValue.Value); + } + _updateChannelTooLongList.Clear(); + } + + _eventAggregator.Publish(new UpdateCompletedEventArgs + { + UpdateChannelTooLongList = updateChannelTooLongList + }); + }); + callback(); + } + //#if DEBUG + // }); + //#endif + }, + error => + { + Execute.BeginOnThreadPool(TimeSpan.FromSeconds(5.0), () => + { + if (!RequestExists(id)) + { + Logs.Log.Write(string.Format("UpdatesService.LoadStateAndUpdate {0} CancelGetDifference", id)); + return; + } + + GetDifference(id, callback); + }); + }); + } + + public bool IsCanceled { get; set; } + + private readonly List _syncDifferenceExceptions = new List(); + + public IList SyncDifferenceExceptions + { + get { return _syncDifferenceExceptions; } + } + + private void ProcessDifference(TLDifference difference, System.Action callback) + { + // в первую очередь синхронизируем пользователей и чаты (секретный чат может создать пользователь, которого у нас нет на клиенте) + _cacheService.SyncUsersAndChats(difference.Users, difference.Chats, + result => + { + + // сначала получаем апдейты, а только потом синхронизируем новые сообщения + // т.к. апдейт о создании секретного чата нада обрабатывать раньше, чем новые сообщения в нем + foreach (var update in difference.OtherUpdates) + { + try + { + ProcessUpdateInternal(update, false); + } + catch (Exception ex) + { + _syncDifferenceExceptions.Add(new ExceptionInfo + { + Caption = "UpdatesService.ProcessDifference OtherUpdates", + Exception = ex, + Timestamp = DateTime.Now + }); + + TLUtils.WriteException("UpdatesService.ProcessDifference OtherUpdates ex ", ex); + } + } + + _cacheService.SyncDifferenceWithoutUsersAndChats(difference, + result2 => + { + callback.SafeInvoke(); + }, + _syncDifferenceExceptions); + }); + } + + private bool ProcessUpdatesInternal(TLUpdatesBase updatesBase, bool notifyNewMessage = true) + { + //ClientSeq = updates.GetSeq() ?? ClientSeq; + + var updatesShortSentMessage = updatesBase as TLUpdatesShortSentMessage; + if (updatesShortSentMessage != null) + { + //if (updatesShortSentMessage.Date.Value > 0) + //{ + // _date = updatesShortSentMessage.Date; + //} + + Execute.ShowDebugMessage(string.Format("ProcessUpdatesInternal.UpdatesShortSentMessage: id={0}", updatesShortSentMessage.Id)); + + return true; + } + + // chat message + var updatesShortChatMessage = updatesBase as TLUpdatesShortChatMessage; + if (updatesShortChatMessage != null) + { + var user = _cacheService.GetUser(updatesShortChatMessage.UserId); + if (user == null) + { + var logString = string.Format("ProcessUpdatesInternal.UpdatesShortChatMessage: user is missing (userId={0}, msgId={1})", updatesShortChatMessage.UserId, updatesShortChatMessage.Id); + Logs.Log.Write(logString); + Helpers.Execute.ShowDebugMessage(logString); + return false; + } + var chat = _cacheService.GetChat(updatesShortChatMessage.ChatId); + if (chat == null) + { + var logString = string.Format("ProcessUpdatesInternal.UpdatesShortChatMessage: chat is missing (chatId={0}, msgId={1})", updatesShortChatMessage.ChatId, updatesShortChatMessage.Id); + Logs.Log.Write(logString); + Helpers.Execute.ShowDebugMessage(logString); + return false; + } + + if (updatesShortChatMessage.Date.Value > 0 && (_date == null || _date.Value < updatesShortChatMessage.Date.Value)) + { + _date = updatesShortChatMessage.Date; + } + + ContinueShortChatMessage(updatesShortChatMessage, notifyNewMessage); + + return true; + } + + // user message + var updatesShortMessage = updatesBase as TLUpdatesShortMessage; + if (updatesShortMessage != null) + { + if (_cacheService.GetUser(updatesShortMessage.UserId) == null) + { + var logString = string.Format("ProcessUpdatesInternal.UpdatesShortMessage: user is missing (userId={0}, msgId={1})", updatesShortMessage.UserId, updatesShortMessage.Id); + Logs.Log.Write(logString); + Helpers.Execute.ShowDebugMessage(logString); + return false; + } + + if (updatesShortMessage.Date.Value > 0 && (_date == null || _date.Value < updatesShortMessage.Date.Value)) + { + _date = updatesShortMessage.Date; + } + + ContinueShortMessage(updatesShortMessage, notifyNewMessage); + + return true; + } + + var updatesShort = updatesBase as TLUpdatesShort; + if (updatesShort != null) + { + if (updatesShort.Date.Value > 0 && (_date == null || _date.Value < updatesShort.Date.Value)) + { + _date = updatesShort.Date; + } + return ProcessUpdateInternal(updatesShort.Update, notifyNewMessage); + } + + var updatesCombined = updatesBase as TLUpdatesCombined; + if (updatesCombined != null) + { + var resetEvent = new ManualResetEvent(false); + var returnValue = true; + + _cacheService.SyncUsersAndChats(updatesCombined.Users, updatesCombined.Chats, + result => + { + if (updatesCombined.Date.Value > 0 && (_date == null || _date.Value < updatesCombined.Date.Value)) + { + _date = updatesCombined.Date; + } + //ClientSeq = combined.Seq; + foreach (var update in updatesCombined.Updates) + { + if (!ProcessUpdateInternal(update, notifyNewMessage)) + { + returnValue = false; + } + } + + resetEvent.Set(); + }); + + resetEvent.WaitOne(10000); + + return returnValue; + } + + var updates = updatesBase as TLUpdates; + if (updates != null) + { + var resetEvent = new ManualResetEvent(false); + var returnValue = true; + + _cacheService.SyncUsersAndChats(updates.Users, updates.Chats, + result => + { + if (updates.Date.Value > 0 && (_date == null || _date.Value < updates.Date.Value)) + { + _date = updates.Date; + } + //ClientSeq = updatesFull.Seq; + foreach (var update in updates.Updates) + { + if (!ProcessUpdateInternal(update, notifyNewMessage)) + { + returnValue = false; + } + } + + resetEvent.Set(); + }); + + resetEvent.WaitOne(10000); + return returnValue; + } + + return false; + } + + private void ContinueShortMessage(TLUpdatesShortMessage updatesShortMessage, bool notifyNewMessage) + { + var message = TLUtils.GetShortMessage( + updatesShortMessage.Id, + updatesShortMessage.UserId, + new TLPeerUser { Id = GetCurrentUserId() }, + updatesShortMessage.Date, + updatesShortMessage.Message); + + var shortMessage40 = updatesShortMessage as TLUpdatesShortMessage40; + if (shortMessage40 != null) + { + message.Flags = shortMessage40.Flags; + message.FwdFromPeer = shortMessage40.FwdFrom; + //message.FwdFromId = shortMessage25.FwdFromId; + message.FwdDate = shortMessage40.FwdDate; + message.ReplyToMsgId = shortMessage40.ReplyToMsgId; + } + + var shortMessage48 = updatesShortMessage as TLUpdatesShortMessage48; + if (shortMessage48 != null) + { + message.FwdHeader = shortMessage48.FwdHeader; + } + + var shortMessage45 = updatesShortMessage as TLUpdatesShortMessage45; + if (shortMessage45 != null) + { + message.ViaBotId = shortMessage45.ViaBotId; + } + + var shortMessage34 = updatesShortMessage as TLUpdatesShortMessage34; + if (shortMessage34 != null) + { + message.Entities = shortMessage34.Entities; + } + + if (message.Out.Value) + { + message.ToId = new TLPeerUser { Id = updatesShortMessage.UserId }; + message.FromId = GetCurrentUserId(); + } + + // set as read + var readMaxId = _cacheService.GetUser(message.Out.Value ? message.ToId.Id : message.FromId) as IReadMaxId; + if (readMaxId != null) + { + var maxId = message.Out.Value ? readMaxId.ReadOutboxMaxId : readMaxId.ReadInboxMaxId; + if (maxId != null) + { + if (maxId.Value >= message.Index) + { + message.SetUnreadSilent(TLBool.False); + } + } + } + + MTProtoService.ProcessSelfMessage(message); + + _cacheService.SyncMessage(message, + cachedMessage => + { + if (notifyNewMessage) + { + _eventAggregator.Publish(cachedMessage); + } + }); + } + + private void ContinueShortChatMessage(TLUpdatesShortChatMessage updatesShortChatMessage, bool notifyNewMessage) + { + var message = TLUtils.GetShortMessage( + updatesShortChatMessage.Id, + updatesShortChatMessage.UserId, + new TLPeerChat { Id = updatesShortChatMessage.ChatId }, + updatesShortChatMessage.Date, + updatesShortChatMessage.Message); + + var shortChatMessage40 = updatesShortChatMessage as TLUpdatesShortChatMessage40; + if (shortChatMessage40 != null) + { + message.Flags = shortChatMessage40.Flags; + message.FwdFromPeer = shortChatMessage40.FwdFrom; + //message.FwdFromId = shortChatMessage25.FwdFromId; + message.FwdDate = shortChatMessage40.FwdDate; + message.ReplyToMsgId = shortChatMessage40.ReplyToMsgId; + } + + var shortMessage48 = updatesShortChatMessage as TLUpdatesShortChatMessage48; + if (shortMessage48 != null) + { + message.FwdHeader = shortMessage48.FwdHeader; + } + + var shortChatMessage45 = updatesShortChatMessage as TLUpdatesShortChatMessage45; + if (shortChatMessage45 != null) + { + message.ViaBotId = shortChatMessage45.ViaBotId; + } + + var shortChatMessage34 = updatesShortChatMessage as TLUpdatesShortChatMessage34; + if (shortChatMessage34 != null) + { + message.Entities = shortChatMessage34.Entities; + } + + // set as read + var readMaxId = _cacheService.GetChat(message.ToId.Id) as IReadMaxId; + if (readMaxId != null) + { + var maxId = message.Out.Value ? readMaxId.ReadOutboxMaxId : readMaxId.ReadInboxMaxId; + if (maxId != null) + { + if (maxId.Value >= message.Index) + { + message.SetUnreadSilent(TLBool.False); + } + } + } + + _cacheService.SyncMessage(message, + cachedMessage => + { + if (notifyNewMessage) + { + _eventAggregator.Publish(cachedMessage); + } + }); + } + + public event EventHandler DCOptionsUpdated; + + protected virtual void RaiseDCOptionsUpdated(DCOptionsUpdatedEventArgs e) + { + var handler = DCOptionsUpdated; + if (handler != null) handler(this, e); + } + + public static TLDecryptedMessageBase GetDecryptedMessage(TLInt currentUserId, TLEncryptedChat cachedChat, TLEncryptedMessageBase encryptedMessageBase, TLInt qts, out bool commitChat) + { + commitChat = false; + + if (cachedChat == null) return null; + if (cachedChat.Key == null) return null; + + TLDecryptedMessageBase decryptedMessage = null; + try + { + decryptedMessage = TLUtils.DecryptMessage(encryptedMessageBase.Bytes, currentUserId, cachedChat, out commitChat); + } + catch (Exception e) + { +#if DEBUG + TLUtils.WriteException(e); +#endif + } + + if (decryptedMessage == null) return null; + + var participantId = currentUserId.Value == cachedChat.ParticipantId.Value + ? cachedChat.AdminId + : cachedChat.ParticipantId; + var cachedUser = InMemoryCacheService.Instance.GetUser(participantId); + if (cachedUser == null) return null; + + decryptedMessage.FromId = cachedUser.Id; + decryptedMessage.Out = new TLBool(false); + decryptedMessage.Unread = new TLBool(true); + decryptedMessage.RandomId = encryptedMessageBase.RandomId; + decryptedMessage.ChatId = encryptedMessageBase.ChatId; + decryptedMessage.Date = encryptedMessageBase.Date; + decryptedMessage.Qts = qts; + + var message = decryptedMessage as TLDecryptedMessage; + if (message != null) + { + var encryptedMessage = encryptedMessageBase as TLEncryptedMessage; + if (encryptedMessage != null) + { + message.Media.File = encryptedMessage.File; + var document = message.Media as TLDecryptedMessageMediaDocument; + if (document != null) + { + var file = document.File as TLEncryptedFile; + if (file != null) + { + file.FileName = document.FileName; + } + } + + var video = message.Media as TLDecryptedMessageMediaVideo; + if (video != null) + { + var file = video.File as TLEncryptedFile; + if (file != null) + { + file.Duration = video.Duration; + } + } + + var audio = message.Media as TLDecryptedMessageMediaAudio; + if (audio != null) + { + audio.UserId = decryptedMessage.FromId; + } + } + } + + return decryptedMessage; + } + + private Dictionary _contactRegisteredList = new Dictionary(); + + private static readonly object _updateChannelTooLongSyncRoot = new object(); + + private Dictionary _updateChannelTooLongList = new Dictionary(); + + public bool ProcessUpdateInternal(TLUpdateBase update, bool notifyNewMessage = true) + { + var userStatus = update as TLUpdateUserStatus; + if (userStatus != null) + { + var user = _cacheService.GetUser(userStatus.UserId); + if (user == null) + { + return false; + } + + user._status = userStatus.Status; // not UI Thread + + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(userStatus)); + } + //Execute.BeginOnThreadPool(() => _eventAggregator.Publish(user)); + + return true; + } + + var userTyping = update as TLUpdateUserTyping; + if (userTyping != null) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(userTyping)); + + return true; + } + + var chatUserTyping = update as TLUpdateChatUserTyping; + if (chatUserTyping != null) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(chatUserTyping)); + + return true; + } + + System.Diagnostics.Debug.WriteLine(update); + + var updateServiceNotification = update as TLUpdateServiceNotification; + if (updateServiceNotification != null) + { + Helpers.Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateServiceNotification)); + + return true; + } + + var updatePrivacy = update as TLUpdatePrivacy; + if (updatePrivacy != null) + { + Helpers.Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updatePrivacy)); + + return true; + } + + var updateUserBlocked = update as TLUpdateUserBlocked; + if (updateUserBlocked != null) + { + var user = _cacheService.GetUser(updateUserBlocked.UserId); + if (user != null) + { + user.Blocked = updateUserBlocked.Blocked; + _cacheService.Commit(); + } + Helpers.Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateUserBlocked)); + + return true; + } + + var processed = ProcessEncryptedChatUpdate(update); + if (processed != null) + { + return processed.Value; + } + + var updateDCOptions = update as TLUpdateDCOptions; + if (updateDCOptions != null) + { + RaiseDCOptionsUpdated(new DCOptionsUpdatedEventArgs { Update = updateDCOptions }); + + return true; + } + + var updateChannelTooLong = update as TLUpdateChannelTooLong; + if (updateChannelTooLong != null) + { + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChannelTooLong)); + } + else + { + lock (_updateChannelTooLongSyncRoot) + { + _updateChannelTooLongList[updateChannelTooLong.ChannelId.Value] = updateChannelTooLong; + } + } + + //var updateChannelTooLong49 = update as TLUpdateChannelTooLong49; + //if (updateChannelTooLong49 != null) + //{ + // Execute.ShowDebugMessage(string.Format("updateChannelTooLong channel_id={0} channel_pts={1}", updateChannelTooLong49.ChannelId, updateChannelTooLong49.ChannelPts)); + //} + //else + //{ + // Execute.ShowDebugMessage(string.Format("updateChannelTooLong channel_id={0}", updateChannelTooLong.ChannelId)); + //} + //#if DEBUG + // Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChannelTooLong)); + // Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChannelTooLong)); + // Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChannelTooLong)); + //#endif + + //UpdateChannelAsync(updateChannelTooLong.ChannelId, + // result => + // { + // var channel = result.Chats.FirstOrDefault(); + // if (channel != null) + // { + // // replace with channels.getDifference and handling channelDifferenceTooLong + // GetHistoryAsync(channel.ToInputPeer(), new TLInt(0), new TLInt(0), + // new TLInt(Constants.CachedMessagesCount), new TLInt(0), new TLInt(0), + // result2 => + // { + + // }, + // error2 => + // { + + // }); + // } + // else + // { + + // } + // }, + // error => + // { + // Execute.ShowDebugMessage("updateChannel getFullChannel error " + error); + // }); + + + return true; + } + + var updateChannel = update as TLUpdateChannel; + if (updateChannel != null) + { + UpdateChannelAsync(updateChannel.ChannelId, + result => + { + var channel = result.Chats.FirstOrDefault() as TLChannel; + if (channel != null) + { + var dialogBase = _cacheService.GetDialog(new TLPeerChannel { Id = channel.Id }); + if (channel.Left.Value) + { + var promo = _cacheService.GetProxyData() as TLProxyDataPromo; + if (promo != null && promo.Peer.Id.Value == updateChannel.ChannelId.Value) + { + if (dialogBase == null) + { + GetPromoDialogAsync(channel.ToInputPeer(), + result3 => + { + + }); + } + else + { + var oldDialogs = _cacheService.GetDialogs().OfType().Where(x => x.IsPromo).ToList(); + foreach (var oldDialogBase in oldDialogs) + { + _cacheService.UpdateDialogPromo(oldDialogBase, false); + } + + _cacheService.UpdateDialogPromo(dialogBase, true); + } + } + else + { + if (dialogBase != null) + { + _cacheService.DeleteDialog(dialogBase); + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new DialogRemovedEventArgs(dialogBase))); + } + } + } + } + else + { + var promo = _cacheService.GetProxyData() as TLProxyDataPromo; + if (promo != null && promo.Peer.Id.Value == updateChannel.ChannelId.Value) + { + if (dialogBase != null) + { + _cacheService.UpdateDialogPromo(dialogBase, false); + } + } + else + { + if (dialogBase == null) + { + GetPeerDialogsAsync(channel.ToInputPeer(), + result3 => + { + dialogBase = result3.Dialogs.FirstOrDefault() as TLDialog; + if (dialogBase != null) + { + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new DialogAddedEventArgs(dialogBase))); + } + } + }); + } + } + } + + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChannel)); + } + } + else + { + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChannel)); + } + + Execute.ShowDebugMessage("updateChannel empty"); + } + }, + error => + { + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChannel)); + } + + Execute.ShowDebugMessage("updateChannel getFullChannel error " + error); + }); + + return true; + } + + var updateChannelGroup = update as TLUpdateChannelGroup; + if (updateChannelGroup != null) + { + Execute.ShowDebugMessage(string.Format("updateChannelGroup channel_id={0} min_id={1} max_id={2} count={3} date={4}", updateChannelGroup.ChannelId, updateChannelGroup.Group.MinId, updateChannelGroup.Group.MaxId, updateChannelGroup.Group.Count, updateChannelGroup.Group.Date)); + + return true; + } + + var updateChannelPinnedMessage = update as TLUpdateChannelPinnedMessage; + if (updateChannelPinnedMessage != null) + { + var channel = _cacheService.GetChat(updateChannelPinnedMessage.ChannelId) as TLChannel49; + if (channel != null) + { + channel.PinnedMsgId = updateChannelPinnedMessage.Id; + channel.HiddenPinnedMsgId = null; + _cacheService.Commit(); + + var message = _cacheService.GetMessage(updateChannelPinnedMessage.Id, updateChannelPinnedMessage.ChannelId); + if (message == null) + { + GetChannelMessagesAsync(channel.ToInputChannel(), new TLVector { new TLInputMessageId { Id = updateChannelPinnedMessage.Id } }, + messagesBase => + { + _cacheService.AddMessagesToContext(messagesBase, result => + { + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChannelPinnedMessage)); + } + }); + }, + error => + { + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChannelPinnedMessage)); + } + }); + } + else + { + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChannelPinnedMessage)); + } + } + } + + return true; + } + + var updateEditMessage = update as TLUpdateEditMessage; + if (updateEditMessage != null) + { + //uExecute.ShowDebugMessage(string.Format("updateEditMessage pts={0} pts_count={1} message={2}", updateEditMessage.Pts, updateEditMessage.PtsCount, updateEditMessage.Message)); + + _cacheService.SyncEditedMessage(updateEditMessage.Message, notifyNewMessage, notifyNewMessage, + cachedMessage => + { + var geoLive = false; + var message = cachedMessage as TLMessage; + if (message != null) + { + var mediaGeoLive = message.Media as TLMessageMediaGeoLive; + if (mediaGeoLive != null) + { + geoLive = true; + } + } + + if (notifyNewMessage || geoLive) // to avoid handle live locations on UpdateCompletedEventArgs + { + updateEditMessage.Message = cachedMessage; + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateEditMessage)); + } + }); + + return true; + } + + var updateEditChannelMessage = update as TLUpdateEditChannelMessage; + if (updateEditChannelMessage != null) + { + //Execute.ShowDebugMessage(string.Format("updateEditChannelMessage channel_pts={0} channel_ptscount={1} message={2}", updateEditChannelMessage.ChannelPts, updateEditChannelMessage.ChannelPtsCount, updateEditChannelMessage.Message)); + + var commonMessage = updateEditChannelMessage.Message as TLMessageCommon; + if (commonMessage != null) + { + var peer = commonMessage.ToId; + + var channel = _cacheService.GetChat(commonMessage.ToId.Id) as TLChannel; + if (channel != null) + { + if (channel.Pts == null + || (channel.Pts.Value < updateEditChannelMessage.ChannelPts.Value + && channel.Pts.Value + updateEditChannelMessage.ChannelPtsCount.Value != updateEditChannelMessage.ChannelPts.Value)) + { + Execute.ShowDebugMessage(string.Format("channel_id={0} channel_pts={1} updateEditChannelMessage[channel_pts={2} channel_pts_count={3}]", peer.Id, channel.Pts, updateEditChannelMessage.ChannelPts, updateEditChannelMessage.ChannelPtsCount)); + } + channel.Pts = new TLInt(updateEditChannelMessage.ChannelPts.Value); + } + + _cacheService.SyncEditedMessage(updateEditChannelMessage.Message, notifyNewMessage, notifyNewMessage, + cachedMessage => + { + var geoLive = false; + var message = cachedMessage as TLMessage; + if (message != null) + { + var mediaGeoLive = message.Media as TLMessageMediaGeoLive; + if (mediaGeoLive != null) + { + geoLive = true; + } + } + + if (notifyNewMessage || geoLive) // to avoid handle live locations on UpdateCompletedEventArgs + { + updateEditChannelMessage.Message = cachedMessage; + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateEditChannelMessage)); + } + }); + } + + return true; + } + + var updateNewChannelMessage = update as TLUpdateNewChannelMessage; + if (updateNewChannelMessage != null) + { + var commonMessage = updateNewChannelMessage.Message as TLMessageCommon; + if (commonMessage != null) + { + var peer = commonMessage.ToId; + + var channel = _cacheService.GetChat(commonMessage.ToId.Id) as TLChannel; + if (channel != null) + { + if (channel.Pts == null + || (channel.Pts.Value < updateNewChannelMessage.ChannelPts.Value + && channel.Pts.Value + updateNewChannelMessage.ChannelPtsCount.Value != updateNewChannelMessage.ChannelPts.Value)) + { + //Execute.ShowDebugMessage(string.Format("channel_id={0} channel_pts={1} updateNewChannelMessage[channel_pts={2} channel_pts_count={3}]", peer.Id, channel.Pts, updateNewChannelMessage.ChannelPts, updateNewChannelMessage.ChannelPtsCount)); + } + channel.Pts = new TLInt(updateNewChannelMessage.ChannelPts.Value); + + if (!commonMessage.Out.Value) + { + var readInboxMaxId = channel.ReadInboxMaxId != null ? channel.ReadInboxMaxId.Value : 0; + + if (commonMessage.Index <= readInboxMaxId) + { + commonMessage.SetUnreadSilent(TLBool.False); + } + } + else + { + var channel49 = channel as TLChannel49; + if (channel49 != null) + { + var readOutboxMaxId = channel49.ReadOutboxMaxId != null ? channel49.ReadOutboxMaxId.Value : 0; + + if (commonMessage.Index <= readOutboxMaxId) + { + commonMessage.SetUnreadSilent(TLBool.False); + } + } + } + } + + if (commonMessage.RandomIndex != 0) + { + _cacheService.SyncSendingMessage(commonMessage, null, + cachedMessage => + { + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(cachedMessage)); + } + }); + } + else + { + _cacheService.SyncMessage(updateNewChannelMessage.Message, notifyNewMessage, notifyNewMessage, + cachedMessage => + { + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(cachedMessage)); + } + }); + } + } + + return true; + } + + var updateNewMessage = update as TLUpdateNewMessage; + if (updateNewMessage != null) + { + var commonMessage = updateNewMessage.Message as TLMessageCommon; + if (commonMessage != null) + { + MTProtoService.ProcessSelfMessage(commonMessage); + + TLPeerBase peer; + if (commonMessage.ToId is TLPeerChat) + { + peer = commonMessage.ToId; + } + else + { + peer = commonMessage.Out.Value ? commonMessage.ToId : new TLPeerUser { Id = commonMessage.FromId }; + } + + if (commonMessage.RandomIndex != 0) + { +#if DEBUG + Log.Write("TLUpdateNewMessage " + updateNewMessage.Message); +#endif + _cacheService.SyncSendingMessage(commonMessage, null, + cachedMessage => + { + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(cachedMessage)); + } + }); + } + else + { +#if DEBUG + Log.Write("TLUpdateNewMessage " + updateNewMessage.Message); +#endif + + _cacheService.SyncMessage(updateNewMessage.Message, + cachedMessage => + { + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(cachedMessage)); + } + }); + } + } + + return true; + } + + var updateMessageId = update as TLUpdateMessageId; + if (updateMessageId != null) + { + _cacheService.SyncSendingMessageId(updateMessageId.RandomId, updateMessageId.Id, m => { }); + RemoveFromQueue(updateMessageId.RandomId); + + return true; + } + + var updateChannelReadMessagesContents = update as TLUpdateChannelReadMessagesContents; + if (updateChannelReadMessagesContents != null) + { + var localMessages = new List(); + var remoteMessages = new TLVector(); + foreach (var readMessageId in updateChannelReadMessagesContents.Messages) + { + var message = _cacheService.GetMessage(readMessageId, updateChannelReadMessagesContents.ChannelId) as TLMessage25; + if (message != null) + { + localMessages.Add(message); + } + else + { + remoteMessages.Add(new TLInputMessageId { Id = readMessageId }); + } + } + + TLDialog71 dialog = null; + var localMentionsCount = localMessages.OfType().Count(x => x.IsMention); + if (localMentionsCount > 0 || remoteMessages.Count > 0) + { + dialog = _cacheService.GetDialog(new TLPeerChannel { Id = updateChannelReadMessagesContents.ChannelId }) as TLDialog71; + if (dialog != null) + { + if (remoteMessages.Count > 0) + { + var channel = _cacheService.GetChat(updateChannelReadMessagesContents.ChannelId) as TLChannel; + if (channel != null) + { + GetChannelMessagesAsync(channel.ToInputChannel(), + remoteMessages, + messagesBase => + { + var remoteMentionsCount = messagesBase.Messages.OfType().Count(x => x.IsMention); + if (remoteMentionsCount > 0) + { + Execute.BeginOnUIThread(() => + { + dialog.UnreadMentionsCount = new TLInt(Math.Max(0, dialog.UnreadMentionsCount.Value - remoteMentionsCount)); + dialog.NotifyOfPropertyChange(() => dialog.UnreadMentionsCount); + }); + } + }, + error => + { + + }); + } + } + } + } + + Execute.BeginOnUIThread(() => + { + foreach (var message in localMessages) + { + message.SetListened(); + if (message.Media != null) + { + message.Media.NotListened = false; + message.Media.NotifyOfPropertyChange(() => message.Media.NotListened); + } + + var message70 = message as TLMessage70; + if (message70 != null && message70.HasTTL()) + { + var mediaPhoto70 = message.Media as TLMessageMediaPhoto70; + if (mediaPhoto70 != null && mediaPhoto70.Photo != null) + { + mediaPhoto70.Photo = null; + message70.NotifyOfPropertyChange(() => message70.TTLMediaExpired); + } + + var mediaDocument70 = message.Media as TLMessageMediaDocument70; + if (mediaDocument70 != null && mediaDocument70.Document != null) + { + mediaDocument70.Document = null; + message70.NotifyOfPropertyChange(() => message70.TTLMediaExpired); + } + } + } + + if (dialog != null && localMentionsCount > 0) + { + dialog.UnreadMentionsCount = new TLInt(Math.Max(0, dialog.UnreadMentionsCount.Value - localMentionsCount)); + dialog.NotifyOfPropertyChange(() => dialog.UnreadMentionsCount); + } + + if (notifyNewMessage) + { + _eventAggregator.Publish(updateChannelReadMessagesContents); + } + }); + + return true; + } + + var updateReadMessagesContents = update as TLUpdateReadMessagesContents; + if (updateReadMessagesContents != null) + { + var localMessages = new List(); + var remoteMessages = new TLVector(); + foreach (var readMessageId in updateReadMessagesContents.Messages) + { + var message = _cacheService.GetMessage(readMessageId) as TLMessage25; + if (message != null) + { + localMessages.Add(message); + } + else + { + remoteMessages.Add(new TLInputMessageId { Id = readMessageId }); + } + } + + var dialogs = new List(); + if (localMessages.Count > 0) + { + foreach (var localMessage in localMessages) + { + if (localMessage.IsMention) + { + var dialog = _cacheService.GetDialog(localMessage) as TLDialog71; + if (dialog != null && dialog.UnreadMentionsCount.Value > 0) + { + dialog.UnreadMentionsCount = new TLInt(Math.Max(0, dialog.UnreadMentionsCount.Value - 1)); + dialogs.Add(dialog); + } + } + } + } + if (remoteMessages.Count > 0) + { + GetMessagesAsync(remoteMessages, + messagesBase => + { + var dialogs2 = new List(); + foreach (var messageBase in messagesBase.Messages) + { + var message = messageBase as TLMessage17; + if (message != null && message.IsMention) + { + var dialog = _cacheService.GetDialog(message) as TLDialog71; + if (dialog != null && dialog.UnreadMentionsCount.Value > 0) + { + dialog.UnreadMentionsCount = new TLInt(Math.Max(0, dialog.UnreadMentionsCount.Value - 1)); + dialogs2.Add(dialog); + } + } + } + + Execute.BeginOnUIThread(() => + { + foreach (var dialog in dialogs2) + { + dialog.NotifyOfPropertyChange(() => dialog.UnreadMentionsCount); + } + }); + }, + error => + { + + }); + } + + Execute.BeginOnUIThread(() => + { + foreach (var message in localMessages) + { + message.SetListened(); + if (message.Media != null) + { + message.Media.NotListened = false; + message.Media.NotifyOfPropertyChange(() => message.Media.NotListened); + } + + var message70 = message as TLMessage70; + if (message70 != null && message70.HasTTL()) + { + var mediaPhoto70 = message.Media as TLMessageMediaPhoto70; + if (mediaPhoto70 != null && mediaPhoto70.Photo != null) + { + mediaPhoto70.Photo = null; + message70.NotifyOfPropertyChange(() => message70.TTLMediaExpired); + } + + var mediaDocument70 = message.Media as TLMessageMediaDocument70; + if (mediaDocument70 != null && mediaDocument70.Document != null) + { + mediaDocument70.Document = null; + message70.NotifyOfPropertyChange(() => message70.TTLMediaExpired); + } + } + } + + foreach (var dialog in dialogs) + { + dialog.NotifyOfPropertyChange(() => dialog.UnreadMentionsCount); + } + + if (notifyNewMessage) + { + _eventAggregator.Publish(updateReadMessagesContents); + } + }); + + return true; + } + + var updateChannelMessageViews = update as TLUpdateChannelMessageViews; + if (updateChannelMessageViews != null) + { + //Execute.ShowDebugMessage(string.Format("updateChannelMessageViews channel_id={0} id={1} views={2}", updateChannelMessageViews.ChannelId, updateChannelMessageViews.Id, updateChannelMessageViews.Views)); + + var message = _cacheService.GetMessage(updateChannelMessageViews.Id, updateChannelMessageViews.ChannelId) as TLMessage36; + if (message != null) + { + if (message.Views == null || message.Views.Value < updateChannelMessageViews.Views.Value) + { + message.Views = updateChannelMessageViews.Views; + + Execute.BeginOnUIThread(() => + { + message.NotifyOfPropertyChange(() => message.Views); + }); + } + } + + return true; + } + + + var updateReadHistory = update as TLUpdateReadHistory; + if (updateReadHistory != null) + { + var outbox = update is TLUpdateReadHistoryOutbox; + + IReadMaxId readMaxId = null; + if (updateReadHistory.Peer is TLPeerUser) + { + readMaxId = _cacheService.GetUser(updateReadHistory.Peer.Id) as IReadMaxId; + } + else if (updateReadHistory.Peer is TLPeerChat) + { + readMaxId = _cacheService.GetChat(updateReadHistory.Peer.Id) as IReadMaxId; + } + SetReadMaxId(readMaxId, updateReadHistory.MaxId, outbox); + + var dialog = _cacheService.GetDialog(updateReadHistory.Peer); + if (dialog != null) + { + var dialog53 = dialog as TLDialog53; + if (dialog53 != null) + { + SetReadMaxId(dialog53, updateReadHistory.MaxId, outbox); + SetReadMaxId(dialog53.With as IReadMaxId, updateReadHistory.MaxId, outbox); + } + + var notifyMessages = new List(); + var maxId = updateReadHistory.MaxId; + for (int i = 0; i < dialog.Messages.Count; i++) + { + var message = dialog.Messages[i] as TLMessageCommon; + if (message != null) + { + if (message.Index != 0 + && message.Index <= maxId.Value + && message.Out.Value == outbox) + { + if (message.Unread.Value) + { + message.SetUnread(TLBool.False); + notifyMessages.Add(message); + //message.NotifyOfPropertyChange(() => message.Unread); + } + else + { + break; + } + } + } + } + + var topMessage = dialog.TopMessage as TLMessageCommon; + if (topMessage != null) + { + if (topMessage.Index <= maxId.Value) + { + if (topMessage.Index != 0 + && topMessage.Unread.Value + && topMessage.Out.Value == outbox) + { + topMessage.SetUnread(TLBool.False); + notifyMessages.Add(topMessage); + //topMessage.NotifyOfPropertyChange(() => topMessage.Unread); + } + } + } + + var unreadCount = 0; + if (dialog.TopMessageId != null && dialog.TopMessageId.Value > updateReadHistory.MaxId.Value) + { + unreadCount = dialog.UnreadCount.Value; + } + if (outbox) + { + unreadCount = dialog.UnreadCount.Value; + } + dialog.UnreadCount = new TLInt(unreadCount); + + if (notifyNewMessage) + { + Execute.BeginOnUIThread(() => + { + foreach (var message in notifyMessages) + { + message.NotifyOfPropertyChange(() => message.Unread); + } + dialog.NotifyOfPropertyChange(() => dialog.TopMessage); + dialog.NotifyOfPropertyChange(() => dialog.Self); + dialog.NotifyOfPropertyChange(() => dialog.UnreadCount); + }); + } + } + + return true; + } + + var updateReadChannelOutbox = update as TLUpdateReadChannelOutbox; + if (updateReadChannelOutbox != null) + { + //Execute.ShowDebugMessage(string.Format("TLUpdateReadChannelOutbox channel_id={0} max_id={1}", updateReadChannelOutbox.ChannelId, updateReadChannelOutbox.MaxId)); + + var readMaxId = _cacheService.GetChat(updateReadChannelOutbox.ChannelId) as IReadMaxId; + if (readMaxId != null) + { + SetReadMaxId(readMaxId, updateReadChannelOutbox.MaxId, true); + } + + var dialog = _cacheService.GetDialog(new TLPeerChannel { Id = updateReadChannelOutbox.ChannelId }); + if (dialog != null) + { + var dialog53 = dialog as TLDialog53; + if (dialog53 != null) + { + SetReadMaxId(dialog53, updateReadChannelOutbox.MaxId, true); + SetReadMaxId(dialog53.With as IReadMaxId, updateReadChannelOutbox.MaxId, true); + } + + var messages = new List(); + + var topMessage = dialog.TopMessage as TLMessageCommon; + if (topMessage != null + && topMessage.Out.Value + && topMessage.Index <= updateReadChannelOutbox.MaxId.Value) + { + //dialog.UnreadCount = new TLInt(0); + topMessage.SetUnread(TLBool.False); + messages.Add(topMessage); + } + + foreach (var messageBase in dialog.Messages) + { + var message = messageBase as TLMessageCommon; + if (message != null && message.Unread.Value && message.Out.Value) + { + if (message.Index != 0 && message.Index < updateReadChannelOutbox.MaxId.Value) + { + message.SetUnread(TLBool.False); + messages.Add(message); + } + } + } + + if (notifyNewMessage) + { + Execute.BeginOnUIThread(() => + { + foreach (var message in messages) + { + message.NotifyOfPropertyChange(() => message.Unread); + } + + dialog.NotifyOfPropertyChange(() => dialog.TopMessage); + dialog.NotifyOfPropertyChange(() => dialog.Self); + dialog.NotifyOfPropertyChange(() => dialog.UnreadCount); + }); + } + } + + _cacheService.Commit(); + + return true; + } + + var updateReadChannelInbox = update as TLUpdateReadChannelInbox; + if (updateReadChannelInbox != null) + { + //Execute.ShowDebugMessage(string.Format("TLUpdateReadChannelInbox channel_id={0} max_id={1}", updateReadChannelInbox.ChannelId, updateReadChannelInbox.MaxId)); + + var messages = new List(); + + var readMaxId = _cacheService.GetChat(updateReadChannelInbox.ChannelId) as IReadMaxId; + if (readMaxId != null) + { + SetReadMaxId(readMaxId, updateReadChannelInbox.MaxId, false); + } + + var dialog = _cacheService.GetDialog(new TLPeerChannel { Id = updateReadChannelInbox.ChannelId }); + if (dialog != null) + { + var dialog53 = dialog as TLDialog53; + if (dialog53 != null) + { + SetReadMaxId(dialog53, updateReadChannelInbox.MaxId, false); + SetReadMaxId(dialog53.With as IReadMaxId, updateReadChannelInbox.MaxId, false); + } + + var topMessage = dialog.TopMessage as TLMessageCommon; + if (topMessage != null + && !topMessage.Out.Value + && topMessage.Index <= updateReadChannelInbox.MaxId.Value) + { + dialog.UnreadCount = new TLInt(0); + topMessage.SetUnread(TLBool.False); + messages.Add(topMessage); + } + + foreach (var messageBase in dialog.Messages) + { + var message = messageBase as TLMessageCommon; + if (message != null && message.Unread.Value && !message.Out.Value) + { + if (message.Index != 0 && message.Index < updateReadChannelInbox.MaxId.Value) + { + message.SetUnread(TLBool.False); + messages.Add(message); + } + } + } + + if (notifyNewMessage) + { + Execute.BeginOnUIThread(() => + { + foreach (var message in messages) + { + message.NotifyOfPropertyChange(() => message.Unread); + } + + dialog.NotifyOfPropertyChange(() => dialog.TopMessage); + dialog.NotifyOfPropertyChange(() => dialog.Self); + dialog.NotifyOfPropertyChange(() => dialog.UnreadCount); + }); + } + } + + _cacheService.Commit(); + + return true; + } + + var updateReadMessages = update as TLUpdateReadMessages; + if (updateReadMessages != null) + { + var dialogs = new Dictionary(); + var messages = new List(updateReadMessages.Messages.Count); + foreach (var readMessageId in updateReadMessages.Messages) + { + var message = _cacheService.GetMessage(readMessageId) as TLMessageCommon; + if (message != null) + { + messages.Add(message); + + var dialog = _cacheService.GetDialog(message); + if (dialog != null && dialog.UnreadCount.Value > 0) + { + dialog.UnreadCount = new TLInt(Math.Max(0, dialog.UnreadCount.Value - 1)); + var topMessage = dialog.TopMessage; + if (topMessage != null + && topMessage.Index == readMessageId.Value) + { + dialogs[dialog.Index] = dialog; + } + } + } + } + + Execute.BeginOnUIThread(() => + { + foreach (var message in messages) + { + message.SetUnread(new TLBool(false)); + message.NotifyOfPropertyChange(() => message.Unread); + } + + foreach (var dialogBase in dialogs.Values) + { + var dialog = dialogBase as TLDialog; + if (dialog == null) continue; + + dialog.NotifyOfPropertyChange(() => dialog.TopMessage); + dialog.NotifyOfPropertyChange(() => dialog.Self); + dialog.NotifyOfPropertyChange(() => dialog.UnreadCount); + } + }); + + return true; + } + + var deleteMessages = update as TLUpdateDeleteMessages; + if (deleteMessages != null) + { + _cacheService.DeleteMessages(deleteMessages.Messages); + + return true; + } + + var updateDeleteChannelMessages = update as TLUpdateDeleteChannelMessages; + if (updateDeleteChannelMessages != null) + { + Execute.ShowDebugMessage(string.Format("updateDeleteChannelMessages channel_id={0} msgs=[{1}] channel_pts={2} channel_pts_count={3}", updateDeleteChannelMessages.ChannelId, string.Join(", ", updateDeleteChannelMessages.Messages), updateDeleteChannelMessages.ChannelPts, updateDeleteChannelMessages.ChannelPtsCount)); + + var channel = _cacheService.GetChat(updateDeleteChannelMessages.ChannelId) as TLChannel; + if (channel != null) + { + if (channel.Pts == null + || channel.Pts.Value + updateDeleteChannelMessages.ChannelPtsCount.Value != updateDeleteChannelMessages.ChannelPts.Value) + { + Execute.ShowDebugMessage(string.Format("channel_id={0} channel_pts={1} updateDeleteChannelMessages[channel_pts={2} channel_pts_count={3}]", channel.Id, channel.Pts, updateDeleteChannelMessages.ChannelPts, updateDeleteChannelMessages.ChannelPtsCount)); + } + channel.Pts = new TLInt(updateDeleteChannelMessages.ChannelPts.Value); + } + + _cacheService.DeleteChannelMessages(updateDeleteChannelMessages.ChannelId, updateDeleteChannelMessages.Messages); + + return true; + } + + var restoreMessages = update as TLUpdateRestoreMessages; + if (restoreMessages != null) + { + return true; + } + + var updateChatAdmins = update as TLUpdateChatAdmins; + if (updateChatAdmins != null) + { + var chat = _cacheService.GetChat(updateChatAdmins.ChatId) as TLChat40; + if (chat != null) + { + chat.AdminsEnabled = updateChatAdmins.Enabled; + chat.Version = updateChatAdmins.Version; + + _cacheService.Commit(); + } + + Execute.ShowDebugMessage(string.Format("TLUpdateChatAdmins chat_id={0} enabled={1} version={2}", updateChatAdmins.ChatId, updateChatAdmins.Enabled, updateChatAdmins.Version)); + + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChatAdmins)); + + return true; + } + + var updateChatParticipantAdmin = update as TLUpdateChatParticipantAdmin; + if (updateChatParticipantAdmin != null) + { + var chat = _cacheService.GetChat(updateChatParticipantAdmin.ChatId) as TLChat40; + if (chat != null) + { + var userId = GetCurrentUserId(); + if (updateChatParticipantAdmin.UserId.Value == userId.Value) + { + chat.Admin = updateChatParticipantAdmin.IsAdmin; + chat.Version = updateChatParticipantAdmin.Version; + + _cacheService.Commit(); + } + } + + Execute.ShowDebugMessage(string.Format("TLUpdateChatParticipantAdmin chat_id={0} user_id={1} is_admin={2} version={3}", updateChatParticipantAdmin.ChatId, updateChatParticipantAdmin.UserId, updateChatParticipantAdmin.IsAdmin, updateChatParticipantAdmin.Version)); + + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChatParticipantAdmin)); + + return true; + } + + var updateChatParticipants = update as TLUpdateChatParticipants; + if (updateChatParticipants != null) + { + var chat = _cacheService.GetChat(updateChatParticipants.Participants.ChatId) as TLChat40; + if (chat != null) + { + chat.Participants = updateChatParticipants.Participants; + var participants = chat.Participants as IChatParticipants; + if (participants != null) + { + chat.Version = participants.Version; + } + + _cacheService.Commit(); + } + + Execute.ShowDebugMessage(string.Format("TLUpdateChatParticipants participants={0}", updateChatParticipants.Participants.GetType().Name)); + + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChatParticipants)); + + return true; + } + + var userName = update as TLUpdateUserName; + if (userName != null) + { + var user = _cacheService.GetUser(userName.UserId); + if (user == null) + { + return false; + } + + user.FirstName = userName.FirstName; + user.LastName = userName.LastName; + + var userWithUserName = user as IUserName; + if (userWithUserName != null) + { + userWithUserName.UserName = userName.UserName; + } + + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(userName)); + + return true; + } + + var userPhoto = update as TLUpdateUserPhoto; + if (userPhoto != null) + { + if (userPhoto.Date.Value > 0 && (_date == null || _date.Value < userPhoto.Date.Value)) + { + _date = userPhoto.Date; + } + + var user = _cacheService.GetUser(userPhoto.UserId); + if (user == null) + { + return false; + } + + user.Photo = userPhoto.Photo; + Helpers.Execute.BeginOnThreadPool(() => _eventAggregator.Publish(userPhoto)); + //_cacheService.SyncUser(user, result => _eventAggregator.Publish(result)); + + return true; + } + + var userPhone = update as TLUpdateUserPhone; + if (userPhone != null) + { + var user = _cacheService.GetUser(userPhone.UserId); + if (user == null) + { + return false; + } + + user.Phone = userPhone.Phone; + Helpers.Execute.BeginOnThreadPool(() => user.NotifyOfPropertyChange(() => user.Phone)); + + return true; + } + + var contactRegistered = update as TLUpdateContactRegistered; + if (contactRegistered != null) + { + if (contactRegistered.Date.Value > 0 && (_date == null || _date.Value < contactRegistered.Date.Value)) + { + _date = contactRegistered.Date; + } + + if (_contactRegisteredList.ContainsKey(contactRegistered.UserId.Value)) + { + return true; + } + + _contactRegisteredList[contactRegistered.UserId.Value] = contactRegistered.UserId.Value; + + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(contactRegistered)); + } + + return true; + } + + var updateNewAuthorization = update as TLUpdateNewAuthorization; + if (updateNewAuthorization != null) + { + if (updateNewAuthorization.Date.Value > 0 && (_date == null || _date.Value < updateNewAuthorization.Date.Value)) + { + _date = updateNewAuthorization.Date; + } + + Helpers.Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateNewAuthorization)); + + return true; + } + + var updateContactLink = update as TLUpdateContactLinkBase; + if (updateContactLink != null) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateContactLink)); + + return true; + } + + var updateChatParticipantAdd = update as TLUpdateChatParticipantAdd; + if (updateChatParticipantAdd != null) + { + return true; + } + + var updateChatParticipantDelete = update as TLUpdateChatParticipantDelete; + if (updateChatParticipantDelete != null) + { + return true; + } + + var updateNotifySettings = update as TLUpdateNotifySettings; + if (updateNotifySettings != null) + { + var notifyPeer = updateNotifySettings.Peer as TLNotifyPeer; + + if (notifyPeer != null) + { + + var dialog = _cacheService.GetDialog(notifyPeer.Peer); + if (dialog != null) + { + dialog.NotifySettings = updateNotifySettings.NotifySettings; + + var peerUser = dialog.Peer as TLPeerUser; + if (peerUser != null) + { + var user = _cacheService.GetUser(peerUser.Id); + if (user != null) + { + user.NotifySettings = updateNotifySettings.NotifySettings; + if (dialog.With != null) + { + var dialogUser = dialog.With as TLUserBase; + if (dialogUser != null) + { + dialogUser.NotifySettings = updateNotifySettings.NotifySettings; + } + } + } + } + + var peerChat = dialog.Peer as TLPeerChat; + if (peerChat != null) + { + var chat = _cacheService.GetChat(peerChat.Id); + if (chat != null) + { + chat.NotifySettings = updateNotifySettings.NotifySettings; + if (dialog.With != null) + { + var dialogChat = dialog.With as TLChatBase; + if (dialogChat != null) + { + dialogChat.NotifySettings = updateNotifySettings.NotifySettings; + } + } + } + } + + if (peerChat != null || peerUser != null) + { + _cacheService.Commit(); + } + + Helpers.Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateNotifySettings)); + } + } + + return true; + } + + var updateWebPage = update as TLUpdateWebPage; + if (updateWebPage != null) + { + var message = _cacheService.GetMessage(updateWebPage.WebPage) as TLMessage; + if (message != null) + { + message._media = new TLMessageMediaWebPage { WebPage = updateWebPage.WebPage }; + + _cacheService.SyncMessage(message, + m => + { + Helpers.Execute.BeginOnUIThread(() => message.NotifyOfPropertyChange(() => message.Media)); + }); + } + + Helpers.Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateWebPage)); + + return true; + } + + var updateNewStickerSet = update as TLUpdateNewStickerSet; + if (updateNewStickerSet != null) + { + Execute.ShowDebugMessage("TLUpdateNewStickeSet"); + + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateNewStickerSet)); + + return true; + } + + var updateStickerSetsOrder = update as TLUpdateStickerSetsOrder; + if (updateStickerSetsOrder != null) + { + Execute.ShowDebugMessage("TLUpdateStickerSetsOrder56"); + + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateStickerSetsOrder)); + + return true; + } + + var updateStickerSets = update as TLUpdateStickerSets; + if (updateStickerSets != null) + { + Execute.ShowDebugMessage("TLUpdateStickerSets"); + + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateStickerSets)); + + return true; + } + + var updateReadFeaturedStickers = update as TLUpdateReadFeaturedStickers; + if (updateReadFeaturedStickers != null) + { + Execute.ShowDebugMessage("TLUpdateReadFeaturedStickers"); + + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateReadFeaturedStickers)); + + return true; + } + + var updateRecentStickers = update as TLUpdateRecentStickers; + if (updateRecentStickers != null) + { + Execute.ShowDebugMessage("TLUpdateRecentStickers"); + + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateRecentStickers)); + + return true; + } + + var updateFavedStickers = update as TLUpdateFavedStickers; + if (updateFavedStickers != null) + { + //Execute.ShowDebugMessage("TLUpdateFavedStickers"); + + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateFavedStickers)); + + return true; + } + + var updateSavedGifs = update as TLUpdateSavedGifs; + if (updateSavedGifs != null) + { + Execute.ShowDebugMessage("TLUpdateSavedGifs"); + + //Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateSavedGifs)); + + return true; + } + + var updateBotInlineQuery = update as TLUpdateBotInlineQuery; + if (updateBotInlineQuery != null) + { + Execute.ShowDebugMessage("TLUpdateBotInlineQuery"); + + //Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateSavedGifs)); + + return true; + } + + var updateBotCallbackQuery = update as TLUpdateBotCallbackQuery; + if (updateBotCallbackQuery != null) + { + Execute.ShowDebugMessage("TLUpdateBotCallbackQuery"); + + //Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateSavedGifs)); + + return true; + } + + var updateBotInlineSend = update as TLUpdateBotInlineSend; + if (updateBotInlineSend != null) + { + Execute.ShowDebugMessage("TLUpdateBotInlineSend"); + + //Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateSavedGifs)); + + return true; + } + + var updateInlineBotCallbackQuery = update as TLUpdateInlineBotCallbackQuery; + if (updateInlineBotCallbackQuery != null) + { + Execute.ShowDebugMessage("TLUpdateInlineBotCallbackQuery"); + + //Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateSavedGifs)); + + return true; + } + + var updateDraftMessage = update as TLUpdateDraftMessage; + if (updateDraftMessage != null) + { + //Execute.ShowDebugMessage("TLUpdateDraftMessage draft=" + updateDraftMessage.Draft); + + var dialog = _cacheService.GetDialog(updateDraftMessage.Peer) as TLDialog53; + if (dialog != null) + { + dialog.Draft = updateDraftMessage.Draft; + + _cacheService.Commit(); + } + + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateDraftMessage)); + } + + return true; + } + + var updatePinnedDialogs = update as TLUpdatePinnedDialogs; + if (updatePinnedDialogs != null) + { +#if DEBUG + var order = new List(); + if (updatePinnedDialogs.Order != null) + { + foreach (var peer in updatePinnedDialogs.Order) + { + order.Add(peer.ToString()); + } + } + + Execute.ShowDebugMessage(string.Format("TLUpdatePinnedDialogs order=[{0}]", string.Join(", ", order))); +#endif + + //if (updatePinnedDialogs.Order == null) + //{ + GetPinnedDialogsAsync(result => + { + // important: must be true in all cases. UpdateCompletedEventArgs will be invoke before getting new pinned chats + //if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updatePinnedDialogs)); + } + }); + //} + //else + //{ + // _cacheService.UpdatePinnedDialogs(updatePinnedDialogs.Order); + + // if (notifyNewMessage) + // { + // Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updatePinnedDialogs)); + // } + //} + + return true; + } + + var updateDialogPinned = update as TLUpdateDialogPinned76; + if (updateDialogPinned != null) + { + var dialogPeer = updateDialogPinned.Peer as TLDialogPeer; + if (dialogPeer != null) + { + _cacheService.UpdateDialogPinned(dialogPeer.Peer, updateDialogPinned.Pinned); + } + + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateDialogPinned)); + } + + return true; + } + + var updateChannelAvailableMessages = update as TLUpdateChannelAvailableMessages; + if (updateChannelAvailableMessages != null) + { + _cacheService.UpdateChannelAvailableMessages(updateChannelAvailableMessages.ChannelId, updateChannelAvailableMessages.AvailableMinId); + + if (notifyNewMessage) + { + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(updateChannelAvailableMessages)); + } + + return true; + } + + var updateDialogUnreadMark = update as TLUpdateDialogUnreadMark; + if (updateDialogUnreadMark != null) + { + var dialogPeer = updateDialogUnreadMark.Peer as TLDialogPeer; + if (dialogPeer != null) + { + var dialog = _cacheService.GetDialog(dialogPeer.Peer); + if (dialog != null) + { + var dialog71 = dialog as TLDialog71; + if (dialog71 != null) + { + dialog71.UnreadMark = updateDialogUnreadMark.Unread; + } + + if (notifyNewMessage) + { + Execute.BeginOnUIThread(() => + { + if (dialog71 != null) + { + dialog71.NotifyOfPropertyChange(() => dialog71.UnreadMark); + } + }); + } + } + + return true; + } + } + + return false; + } + + private static void SetReadMaxId(IReadMaxId readMaxId, TLInt maxId, bool outbox) + { + if (readMaxId == null) return; + + if (outbox) + { + if (readMaxId.ReadOutboxMaxId == null || readMaxId.ReadOutboxMaxId.Value < maxId.Value) + { + readMaxId.ReadOutboxMaxId = maxId; + } + } + else + { + if (readMaxId.ReadInboxMaxId == null || readMaxId.ReadInboxMaxId.Value < maxId.Value) + { + readMaxId.ReadInboxMaxId = maxId; + } + } + } + + private object _waitingEncryptedMessagesSyncRoot = new object(); + + private List _waitingEncryptedMessages = new List(); + + + private bool? ProcessEncryptedChatUpdate(TLUpdateBase update) + { + // typing + var updateEncryptedChatTyping = update as TLUpdateEncryptedChatTyping; + if (updateEncryptedChatTyping != null) + { + _eventAggregator.Publish(updateEncryptedChatTyping); + + return true; + } + + // reading + var updateEncryptedMessagesRead = update as TLUpdateEncryptedMessagesRead; + if (updateEncryptedMessagesRead != null) + { + //Helpers.Execute.ShowDebugMessage(updateEncryptedMessagesRead.ToString()); + + var encryptedChat = _cacheService.GetEncryptedChat(updateEncryptedMessagesRead.ChatId) as TLEncryptedChat; + + if (encryptedChat != null) + { + var items = _cacheService.GetDecryptedHistory(encryptedChat.Id.Value, 100); + Execute.BeginOnUIThread(() => + { + for (var i = 0; i < items.Count; i++) + { + if (items[i].Out.Value) + { + if (items[i].Status == MessageStatus.Confirmed) + //&& Items[i].Date.Value <= update.MaxDate.Value) // здесь надо учитывать смещение по времени + { + items[i].Status = MessageStatus.Read; + items[i].NotifyOfPropertyChange(() => items[i].Status); + + if (items[i].TTL != null && items[i].TTL.Value > 0) + { + var decryptedMessage = items[i] as TLDecryptedMessage17; + if (decryptedMessage != null) + { + var decryptedPhoto = decryptedMessage.Media as TLDecryptedMessageMediaPhoto; + if (decryptedPhoto != null && items[i].TTL.Value <= 60.0) + { + continue; + } + + var decryptedVideo17 = decryptedMessage.Media as TLDecryptedMessageMediaVideo17; + if (decryptedVideo17 != null && items[i].TTL.Value <= 60.0) + { + continue; + } + + var decryptedAudio17 = decryptedMessage.Media as TLDecryptedMessageMediaAudio17; + if (decryptedAudio17 != null && items[i].TTL.Value <= 60.0) + { + continue; + } + + var decryptedDocument45 = decryptedMessage.Media as TLDecryptedMessageMediaDocument45; + if (decryptedDocument45 != null && (items[i].IsVoice() || items[i].IsVideo()) && items[i].TTL.Value <= 60.0) + { + continue; + } + } + + items[i].DeleteDate = new TLLong(DateTime.Now.Ticks + encryptedChat.MessageTTL.Value * TimeSpan.TicksPerSecond); + } + } + else if (items[i].Status == MessageStatus.Read) + { + var message = items[i] as TLDecryptedMessage; + if (message != null) + { + break; + } + } + } + } + + var dialog = _cacheService.GetEncryptedDialog(encryptedChat.Id) as TLEncryptedDialog; + if (dialog != null) + { + //dialog.UnreadCount = new TLInt(dialog.UnreadCount.Value - 1); + var topMessage = dialog.TopMessage; + if (topMessage != null) + { + dialog.NotifyOfPropertyChange(() => dialog.TopMessage); + } + } + }); + } + + //_eventAggregator.Publish(updateEncryptedMessagesRead); + + return true; + } + + // message + var updateNewEncryptedMessage = update as TLUpdateNewEncryptedMessage; + if (updateNewEncryptedMessage != null) + { + var encryptedMessageBase = updateNewEncryptedMessage.Message; + if (encryptedMessageBase != null) + { + var encryptedChat = _cacheService.GetEncryptedChat(encryptedMessageBase.ChatId) as TLEncryptedChat; + if (encryptedChat == null) + { + var chat = _cacheService.GetEncryptedChat(encryptedMessageBase.ChatId); + if (chat is TLEncryptedChatWaiting) + { + Debug.WriteLine(" >>ProcessEncryptedChatUpdate await TLUpdateNewEncryptedMessage chat_id=" + chat.Id); + lock (_waitingEncryptedMessagesSyncRoot) + { + _waitingEncryptedMessages.Add(updateNewEncryptedMessage); + } + } + else + { + Execute.ShowDebugMessage(string.Format("ProcessEncryptedChatUpdate chat_id={0} is not TLEncryptedChat ({1})", encryptedMessageBase.ChatId, chat != null ? chat.GetType() : null)); + } + + return true; + } + + TLDecryptedMessageBase decryptedMessage = null; + try + { + bool commitChat; + decryptedMessage = GetDecryptedMessage(MTProtoService.Instance.CurrentUserId, encryptedChat, encryptedMessageBase, updateNewEncryptedMessage.Qts, out commitChat); + if (commitChat) + { + _cacheService.Commit(); + } + } + catch (Exception ex) + { + Execute.ShowDebugMessage("ProcessEncryptedChatUpdate ex " + ex); + } + + if (decryptedMessage == null) + { + return true; + } + + var seqNoDecryptedMessage = decryptedMessage as ISeqNo; + var encryptedChat17 = encryptedChat as TLEncryptedChat17; + if (seqNoDecryptedMessage != null + && encryptedChat17 != null) + { + var chatRawInSeqNo = encryptedChat17.RawInSeqNo.Value; + var messageRawInSeqNo = GetRawInFromReceivedMessage(MTProtoService.Instance.CurrentUserId, encryptedChat17, seqNoDecryptedMessage); + + if (chatRawInSeqNo <= messageRawInSeqNo) + { + if (messageRawInSeqNo > chatRawInSeqNo) + { + Execute.ShowDebugMessage(string.Format("ProcessEncryptedChatUpdate decrypted message gap chatId={0} chatRawInSeqNo={1} messageRawInSeqNo={2}", encryptedChat17.Id, chatRawInSeqNo, messageRawInSeqNo)); + } + + encryptedChat17.RawInSeqNo = new TLInt(chatRawInSeqNo + 1); + _cacheService.SyncEncryptedChat(encryptedChat17, r => { }); + } + else + { + Execute.ShowDebugMessage(string.Format("ProcessEncryptedChatUpdate skip old decrypted message chatId={0} chatRawInSeqNo={1} messageRawInSeqNo={2}", encryptedChat17.Id, chatRawInSeqNo, messageRawInSeqNo)); + return true; + } + } + + var decryptedMessageService = decryptedMessage as TLDecryptedMessageService; + if (decryptedMessageService != null) + { + var readMessagesAction = decryptedMessageService.Action as TLDecryptedMessageActionReadMessages; + if (readMessagesAction != null) + { + var items = _cacheService.GetDecryptedHistory(encryptedChat.Id.Value, 100); + Execute.BeginOnUIThread(() => + { + foreach (var randomId in readMessagesAction.RandomIds) + { + foreach (var item in items) + { + if (item.RandomId.Value == randomId.Value) + { + item.Status = MessageStatus.Read; + if (item.TTL != null && item.TTL.Value > 0) + { + item.DeleteDate = new TLLong(DateTime.Now.Ticks + encryptedChat.MessageTTL.Value * TimeSpan.TicksPerSecond); + } + + var message = item as TLDecryptedMessage17; + if (message != null) + { + var decryptedMediaPhoto = message.Media as TLDecryptedMessageMediaPhoto; + if (decryptedMediaPhoto != null) + { + if (decryptedMediaPhoto.TTLParams == null) + { + var ttlParams = new TTLParams(); + ttlParams.IsStarted = true; + ttlParams.Total = message.TTL.Value; + ttlParams.StartTime = DateTime.Now; + ttlParams.Out = message.Out.Value; + + decryptedMediaPhoto.TTLParams = ttlParams; + } + } + + var decryptedMediaVideo17 = message.Media as TLDecryptedMessageMediaVideo17; + if (decryptedMediaVideo17 != null) + { + if (decryptedMediaVideo17.TTLParams == null) + { + var ttlParams = new TTLParams(); + ttlParams.IsStarted = true; + ttlParams.Total = message.TTL.Value; + ttlParams.StartTime = DateTime.Now; + ttlParams.Out = message.Out.Value; + + decryptedMediaVideo17.TTLParams = ttlParams; + } + } + + var decryptedMediaAudio17 = message.Media as TLDecryptedMessageMediaAudio17; + if (decryptedMediaAudio17 != null) + { + if (decryptedMediaAudio17.TTLParams == null) + { + var ttlParams = new TTLParams(); + ttlParams.IsStarted = true; + ttlParams.Total = message.TTL.Value; + ttlParams.StartTime = DateTime.Now; + ttlParams.Out = message.Out.Value; + + decryptedMediaAudio17.TTLParams = ttlParams; + } + } + + var decryptedMediaDocument45 = message.Media as TLDecryptedMessageMediaDocument45; + if (decryptedMediaDocument45 != null && (message.IsVoice() || message.IsVideo())) + { + if (decryptedMediaDocument45.TTLParams == null) + { + var ttlParams = new TTLParams(); + ttlParams.IsStarted = true; + ttlParams.Total = message.TTL.Value; + ttlParams.StartTime = DateTime.Now; + ttlParams.Out = message.Out.Value; + + decryptedMediaDocument45.TTLParams = ttlParams; + } + + var message45 = message as TLDecryptedMessage45; + if (message45 != null) + { + message45.SetListened(); + } + decryptedMediaDocument45.NotListened = false; + decryptedMediaDocument45.NotifyOfPropertyChange(() => decryptedMediaDocument45.NotListened); + } + } + break; + } + } + } + }); + + } + } + + var isDisplayedMessage = TLUtils.IsDisplayedDecryptedMessageInternal(decryptedMessage); + if (!isDisplayedMessage) + { + decryptedMessage.Unread = TLBool.False; + } + + ProcessPFS(SendEncryptedServiceAsync, _cacheService, _eventAggregator, encryptedChat, decryptedMessageService); + + ProcessNewLayer(SendEncryptedServiceAsync, _cacheService, _eventAggregator, encryptedChat, decryptedMessage); + + _eventAggregator.Publish(decryptedMessage); + + _cacheService.SyncDecryptedMessage(decryptedMessage, encryptedChat, cachedMessage => + { + SetState(null, null, updateNewEncryptedMessage.Qts, null, null, "ProcessEncryptedChatUpdate"); + }); + + if (decryptedMessageService != null) + { + var resendAction = decryptedMessageService.Action as TLDecryptedMessageActionResend; + if (resendAction != null) + { + Execute.ShowDebugMessage(string.Format("ProcessEncryptedChatUpdate TLDecryptedMessageActionResend start_seq_no={0} end_seq_no={1}", resendAction.StartSeqNo, resendAction.EndSeqNo)); + } + } + + return true; + } + } + + var updatePhoneCall = update as TLUpdatePhoneCall; + if (updatePhoneCall != null) + { + try + { + _eventAggregator.Publish(updatePhoneCall); + } + catch (Exception ex) + { + TLUtils.WriteException("ProcessUpdateInternal", ex); + } + } + + // creating, new layer + var updateEncryption = update as TLUpdateEncryption; + if (updateEncryption != null) + { + var chatRequested = updateEncryption.Chat as TLEncryptedChatRequested; + + if (chatRequested != null) + { + _cacheService.SyncEncryptedChat(updateEncryption.Chat, result => _eventAggregator.Publish(result)); + + var message = new TLDecryptedMessageService17 + { + RandomId = TLLong.Random(), + //RandomBytes = TLString.Random(Constants.MinRandomBytesLength), + ChatId = chatRequested.Id, + Action = new TLDecryptedMessageActionEmpty(), + FromId = MTProtoService.Instance.CurrentUserId, + Date = chatRequested.Date, + Out = new TLBool(false), + Unread = new TLBool(false), + Status = MessageStatus.Read + }; + + _cacheService.SyncDecryptedMessage(message, chatRequested, result => { }); + + GetDHConfigAsync(new TLInt(0), new TLInt(0), + result => + { + var dhConfig = (TLDHConfig)result; + if (!TLUtils.CheckPrime(dhConfig.P.Data, dhConfig.G.Value)) + { + return; + } + if (!TLUtils.CheckGaAndGb(chatRequested.GA.Data, dhConfig.P.Data)) + { + return; + } + + //TODO: precalculate gb to improve speed + var bBytes = new byte[256]; + var random = new SecureRandom(); + random.NextBytes(bBytes); + //var b = TLString.FromBigEndianData(bBytes); + var p = dhConfig.P; + var g = dhConfig.G; + + updateEncryption.Chat.P = p; + updateEncryption.Chat.G = g; + + var gbBytes = MTProtoService.GetGB(bBytes, dhConfig.G, dhConfig.P); + var gb = TLString.FromBigEndianData(gbBytes); + + var key = MTProtoService.GetAuthKey(bBytes, chatRequested.GA.ToBytes(), dhConfig.P.ToBytes()); + var keyHash = Utils.ComputeSHA1(key); + var keyFingerprint = new TLLong(BitConverter.ToInt64(keyHash, 12)); + + AcceptEncryptionAsync( + new TLInputEncryptedChat + { + AccessHash = chatRequested.AccessHash, + ChatId = chatRequested.Id + }, + gb, + keyFingerprint, + chat => + { + chat.P = p; + chat.G = g; + chat.Key = TLString.FromBigEndianData(key); + chat.KeyFingerprint = keyFingerprint; + + _cacheService.SyncEncryptedChat(chat, r2 => _eventAggregator.Publish(r2)); + }, + er => + { + Helpers.Execute.ShowDebugMessage("messages.acceptEncryption " + er); + }); + + }, + error => + { + Helpers.Execute.ShowDebugMessage("messages.getDhConfig error " + error); + }); + } + + var encryptedChat = updateEncryption.Chat as TLEncryptedChat; + if (encryptedChat != null) + { + var waitingChat = _cacheService.GetEncryptedChat(encryptedChat.Id) as TLEncryptedChatWaiting; + + if (waitingChat != null) + { + _cacheService.SyncEncryptedChat(encryptedChat, + syncedChat => + { + // to avoid raise conditions for TLUpdateEncryption and TLUpdateNewEncryptedMessage with layer notificaiton + var updates = new List(); + lock (_waitingEncryptedMessagesSyncRoot) + { + for (var i = 0; i < _waitingEncryptedMessages.Count; i++) + { + if (_waitingEncryptedMessages[i].Message.ChatId.Value == syncedChat.Index) + { + updates.Add(_waitingEncryptedMessages[i]); + _waitingEncryptedMessages.RemoveAt(i--); + } + } + } + foreach (var u in updates) + { + Debug.WriteLine(" >>ProcessEncryptedChatUpdate process awaited TLUpdateNewEncryptedMessage chat_id=" + syncedChat.Id); + ProcessEncryptedChatUpdate(u); + } + + var syncedChat17 = _cacheService.GetEncryptedChat(encryptedChat.Id) as TLEncryptedChat17; + if (syncedChat17 == null + || syncedChat17.Layer.Value <= Constants.MinSecretSupportedLayer) + { + var layer = new TLInt(Constants.MinSecretSupportedLayer); + var rawInSeqNo = new TLInt(0); + var rawOutSeqNo = new TLInt(0); + UpgradeSecretChatLayerAndSendNotification(SendEncryptedServiceAsync, _cacheService, _eventAggregator, encryptedChat, layer, rawInSeqNo, rawOutSeqNo); + } + }); + } + + var encryptedChat17 = _cacheService.GetEncryptedChat(encryptedChat.Id) as TLEncryptedChat17; + if (encryptedChat17 != null) + { + updateEncryption.Chat = encryptedChat17; + } + + _cacheService.SyncEncryptedChat(updateEncryption.Chat, + r => + { + _eventAggregator.Publish(r); + }); + } + else + { + _cacheService.SyncEncryptedChat(updateEncryption.Chat, + r => + { + _eventAggregator.Publish(r); + }); + } + + return true; + } + + return null; + } + + public static void ProcessNewLayer(SendEncryptedServiceAction sendEncryptedServiceActionAsync, ICacheService cacheService, ITelegramEventAggregator eventAggregator, TLEncryptedChatBase encryptedChatBase, TLDecryptedMessageBase decryptedMessageBase) + { + var seqNoMessage = decryptedMessageBase as ISeqNo; + var encryptedChat8 = encryptedChatBase as TLEncryptedChat; + var encryptedChat17 = encryptedChatBase as TLEncryptedChat17; + var decryptedMessageService = decryptedMessageBase as TLDecryptedMessageService; + + if (seqNoMessage != null) + { + if (encryptedChat17 != null) + { + if (decryptedMessageService != null) + { + var notifyLayerAction = decryptedMessageService.Action as TLDecryptedMessageActionNotifyLayer; + if (notifyLayerAction != null) + { + if (encryptedChat17.Layer.Value < notifyLayerAction.Layer.Value + && notifyLayerAction.Layer.Value <= Constants.SecretSupportedLayer) + { + var layer = notifyLayerAction.Layer; + var rawInSeqNo = encryptedChat17.RawInSeqNo; + var rawOutSeqNo = encryptedChat17.RawOutSeqNo; + UpgradeSecretChatLayerAndSendNotification(sendEncryptedServiceActionAsync, cacheService, eventAggregator, encryptedChat17, layer, rawInSeqNo, rawOutSeqNo); + } + } + } + } + else if (encryptedChat8 != null) + { + var newLayer = Constants.SecretSupportedLayer; + if (decryptedMessageService != null) + { + var actionNotifyLayer = decryptedMessageService.Action as TLDecryptedMessageActionNotifyLayer; + if (actionNotifyLayer != null) + { + if (actionNotifyLayer.Layer.Value <= Constants.SecretSupportedLayer) + { + newLayer = actionNotifyLayer.Layer.Value; + } + } + } + + var layer = new TLInt(newLayer); + var rawInSeqNo = new TLInt(1); // one message was received + var rawOutSeqNo = new TLInt(0); + UpgradeSecretChatLayerAndSendNotification(sendEncryptedServiceActionAsync, cacheService, eventAggregator, encryptedChat8, layer, rawInSeqNo, rawOutSeqNo); + } + } + else if (decryptedMessageService != null) + { + var notifyLayerAction = decryptedMessageService.Action as TLDecryptedMessageActionNotifyLayer; + if (notifyLayerAction != null) + { + if (encryptedChat17 != null) + { + var newLayer = Constants.SecretSupportedLayer; + if (notifyLayerAction.Layer.Value <= Constants.SecretSupportedLayer) + { + newLayer = notifyLayerAction.Layer.Value; + } + + var layer = new TLInt(newLayer); + var rawInSeqNo = new TLInt(0); + var rawOutSeqNo = new TLInt(0); + UpgradeSecretChatLayerAndSendNotification(sendEncryptedServiceActionAsync, cacheService, eventAggregator, encryptedChat17, layer, rawInSeqNo, rawOutSeqNo); + } + else if (encryptedChat8 != null) + { + var newLayer = Constants.SecretSupportedLayer; + if (notifyLayerAction.Layer.Value <= Constants.SecretSupportedLayer) + { + newLayer = notifyLayerAction.Layer.Value; + } + + var layer = new TLInt(newLayer); + var rawInSeqNo = new TLInt(1); // one message was received + var rawOutSeqNo = new TLInt(0); + UpgradeSecretChatLayerAndSendNotification(sendEncryptedServiceActionAsync, cacheService, eventAggregator, encryptedChat8, layer, rawInSeqNo, rawOutSeqNo); + } + } + } + } + + public static void ProcessPFS(SendEncryptedServiceAction sendEncryptedServiceActionAsync, ICacheService cacheService, ITelegramEventAggregator eventAggregator, TLEncryptedChatBase encryptedChatBase, TLDecryptedMessageService decryptedMessageService) + { + var encryptedChat = encryptedChatBase as TLEncryptedChat20; + if (encryptedChat == null) return; + if (decryptedMessageService == null) return; + + var abortKey = decryptedMessageService.Action as TLDecryptedMessageActionAbortKey; + if (abortKey != null) + { + encryptedChat.PFS_A = null; + encryptedChat.PFS_ExchangeId = null; + cacheService.SyncEncryptedChat(encryptedChat, cachedChat => + { + + }); + + return; + } + + var noop = decryptedMessageService.Action as TLDecryptedMessageActionNoop; + if (noop != null) + { + return; + } + + var commitKey = decryptedMessageService.Action as TLDecryptedMessageActionCommitKey; + if (commitKey != null) + { + encryptedChat.PFS_A = null; + encryptedChat.PFS_ExchangeId = null; + encryptedChat.Key = encryptedChat.PFS_Key; + encryptedChat.PFS_Key = null; + cacheService.SyncEncryptedChat(encryptedChat, cachedChat => + { + eventAggregator.Publish(encryptedChat); + + var actionNoop = new TLDecryptedMessageActionNoop(); + + SendEncryptedServiceActionAsync(sendEncryptedServiceActionAsync, cacheService, eventAggregator, encryptedChat, actionNoop, + (message, result) => + { + + }); + }); + + return; + } + + var requestKey = decryptedMessageService.Action as TLDecryptedMessageActionRequestKey; + if (requestKey != null) + { + var bBytes = new byte[256]; + var random = new Random(); + random.NextBytes(bBytes); + var p = encryptedChat.P; + var g = encryptedChat.G; + + var gbBytes = MTProtoService.GetGB(bBytes, g, p); + var gb = TLString.FromBigEndianData(gbBytes); + + encryptedChat.PFS_A = TLString.FromBigEndianData(bBytes); + encryptedChat.PFS_ExchangeId = requestKey.ExchangeId; + + if (!TLUtils.CheckGaAndGb(requestKey.GA.Data, encryptedChat.P.Data)) + { + return; + } + + var key = MTProtoService.GetAuthKey(encryptedChat.PFS_A.Data, requestKey.GA.ToBytes(), encryptedChat.P.ToBytes()); + var keyHash = Utils.ComputeSHA1(key); + var keyFingerprint = new TLLong(BitConverter.ToInt64(keyHash, 12)); + + encryptedChat.PFS_Key = TLString.FromBigEndianData(key); + encryptedChat.PFS_KeyFingerprint = keyFingerprint; + cacheService.SyncEncryptedChat(encryptedChat, cachedChat => + { + var actionAcceptKey = new TLDecryptedMessageActionAcceptKey + { + ExchangeId = encryptedChat.PFS_ExchangeId, + KeyFingerprint = keyFingerprint, + GB = gb + }; + + SendEncryptedServiceActionAsync(sendEncryptedServiceActionAsync, cacheService, eventAggregator, encryptedChat, actionAcceptKey, + (message, result) => + { + + }); + }); + + return; + } + + var acceptKey = decryptedMessageService.Action as TLDecryptedMessageActionAcceptKey; + if (acceptKey != null) + { + if (!TLUtils.CheckGaAndGb(acceptKey.GB.Data, encryptedChat.P.Data)) + { + return; + } + + var key = MTProtoService.GetAuthKey(encryptedChat.PFS_A.Data, acceptKey.GB.ToBytes(), encryptedChat.P.ToBytes()); + var keyHash = Utils.ComputeSHA1(key); + var keyFingerprint = new TLLong(BitConverter.ToInt64(keyHash, 12)); + + // abort for keyfingerprint != acceptKey.keyFingerprint + if (keyFingerprint.Value != acceptKey.KeyFingerprint.Value) + { + var actionAbortKey = new TLDecryptedMessageActionAbortKey + { + ExchangeId = encryptedChat.PFS_ExchangeId + }; + + SendEncryptedServiceActionAsync(sendEncryptedServiceActionAsync, cacheService, eventAggregator, encryptedChat, actionAbortKey, + (message, result) => + { + encryptedChat.PFS_A = null; + encryptedChat.PFS_ExchangeId = null; + + eventAggregator.Publish(encryptedChat); + cacheService.Commit(); + }); + + return; + } + + encryptedChat.PFS_Key = TLString.FromBigEndianData(key); + encryptedChat.PFS_KeyFingerprint = keyFingerprint; + cacheService.SyncEncryptedChat(encryptedChat, cachedChat => + { + var actionCommitKey = new TLDecryptedMessageActionCommitKey + { + ExchangeId = encryptedChat.PFS_ExchangeId, + KeyFingerprint = keyFingerprint + }; + + SendEncryptedServiceActionAsync(sendEncryptedServiceActionAsync, cacheService, eventAggregator, encryptedChat, actionCommitKey, + (message, result) => + { + encryptedChat.PFS_ExchangeId = null; + if (encryptedChat.PFS_Key != null) + { + encryptedChat.Key = encryptedChat.PFS_Key; + } + encryptedChat.PFS_A = null; + encryptedChat.PFS_KeyFingerprint = null; + cacheService.SyncEncryptedChat(encryptedChat, cachedChat2 => + { + eventAggregator.Publish(encryptedChat); + }); + }); + }); + + return; + } + } + + private static void SendEncryptedServiceActionAsync(SendEncryptedServiceAction sendEncryptedServiceAsync, ICacheService cacheService, ITelegramEventAggregator eventAggregator, TLEncryptedChat20 encryptedChat, TLDecryptedMessageActionBase action, Action callback) + { + if (encryptedChat == null) return; + + var randomId = TLLong.Random(); + + var currentUserId = MTProtoService.Instance.CurrentUserId; + var clientTicksDelta = MTProtoService.Instance.ClientTicksDelta; + + var inSeqNo = TLUtils.GetInSeqNo(currentUserId, encryptedChat); + var outSeqNo = TLUtils.GetOutSeqNo(currentUserId, encryptedChat); + + encryptedChat.RawOutSeqNo = new TLInt(encryptedChat.RawOutSeqNo.Value + 1); + + var message = new TLDecryptedMessageService17 + { + Action = action, + RandomId = randomId, + //RandomBytes = TLString.Random(Constants.MinRandomBytesLength), + ChatId = encryptedChat.Id, + FromId = currentUserId, + Out = TLBool.True, + Unread = TLBool.False, + Date = TLUtils.DateToUniversalTimeTLInt(clientTicksDelta, DateTime.Now), + Status = MessageStatus.Sending, + TTL = new TLInt(0), + InSeqNo = inSeqNo, + OutSeqNo = outSeqNo + }; + + var decryptedMessageLayer17 = TLUtils.GetDecryptedMessageLayer(encryptedChat.Layer, inSeqNo, outSeqNo, message); + + cacheService.SyncDecryptedMessage( + message, + encryptedChat, + messageResult => + { + sendEncryptedServiceAsync( + new TLInputEncryptedChat + { + AccessHash = encryptedChat.AccessHash, + ChatId = encryptedChat.Id + }, + randomId, + TLUtils.EncryptMessage(decryptedMessageLayer17, MTProtoService.Instance.CurrentUserId, encryptedChat), + result => + { + message.Status = MessageStatus.Confirmed; + cacheService.SyncSendingDecryptedMessage(encryptedChat.Id, result.Date, message.RandomId, + m => + { +#if DEBUG + eventAggregator.Publish(message); +#endif + callback.SafeInvoke(message, result); + }); + }, + error => { Helpers.Execute.ShowDebugMessage("messages.sendEncryptedService error " + error); }); + }); + } + + public static void UpgradeSecretChatLayerAndSendNotification(SendEncryptedServiceAction sendEncryptedServiceAsync, ICacheService cacheService, ITelegramEventAggregator eventAggregator, TLEncryptedChat encryptedChat, TLInt layer, TLInt rawInSeqNo, TLInt rawOutSeqNo) + { + var newEncryptedChat = new TLEncryptedChat20(); + newEncryptedChat.Layer = layer; + + newEncryptedChat.RawInSeqNo = rawInSeqNo; + newEncryptedChat.RawOutSeqNo = rawOutSeqNo; + + //SetInitRawSeqNo(newEncryptedChat, MTProtoService.Instance.CurrentUserId); + + newEncryptedChat.Id = encryptedChat.Id; + newEncryptedChat.AccessHash = encryptedChat.AccessHash; + newEncryptedChat.Date = encryptedChat.Date; + newEncryptedChat.AdminId = encryptedChat.AdminId; + newEncryptedChat.ParticipantId = encryptedChat.ParticipantId; + newEncryptedChat.GAorB = encryptedChat.GAorB; + + newEncryptedChat.CustomFlags = encryptedChat.CustomFlags; + if (encryptedChat.OriginalKey != null) newEncryptedChat.OriginalKey = encryptedChat.OriginalKey; + if (encryptedChat.ExtendedKey != null) newEncryptedChat.ExtendedKey = encryptedChat.ExtendedKey; + newEncryptedChat.Key = encryptedChat.Key; + newEncryptedChat.KeyFingerprint = encryptedChat.KeyFingerprint; + newEncryptedChat.P = encryptedChat.P; + newEncryptedChat.G = encryptedChat.G; + newEncryptedChat.A = encryptedChat.A; + newEncryptedChat.MessageTTL = encryptedChat.MessageTTL; + + cacheService.SyncEncryptedChat(newEncryptedChat, + result => + { + eventAggregator.Publish(newEncryptedChat); + + var currentUserId = MTProtoService.Instance.CurrentUserId; + var clientTicksDelta = MTProtoService.Instance.ClientTicksDelta; + + var randomId = TLLong.Random(); + + var notifyLayerAction = new TLDecryptedMessageActionNotifyLayer(); + notifyLayerAction.Layer = new TLInt(Constants.SecretSupportedLayer); + + var inSeqNo = TLUtils.GetInSeqNo(currentUserId, newEncryptedChat); + var outSeqNo = TLUtils.GetOutSeqNo(currentUserId, newEncryptedChat); + + var encryptedChat17 = result as TLEncryptedChat17; + if (encryptedChat17 != null) + { + encryptedChat17.RawOutSeqNo = new TLInt(encryptedChat17.RawOutSeqNo.Value + 1); + } + + var decryptedMessageService17 = new TLDecryptedMessageService17 + { + Action = notifyLayerAction, + RandomId = randomId, + //RandomBytes = TLString.Random(Constants.MinRandomBytesLength), + + ChatId = encryptedChat.Id, + FromId = currentUserId, + Out = TLBool.True, + Unread = TLBool.False, + Date = TLUtils.DateToUniversalTimeTLInt(clientTicksDelta, DateTime.Now), + Status = MessageStatus.Sending, + + TTL = new TLInt(0), + InSeqNo = inSeqNo, + OutSeqNo = outSeqNo + }; + + var decryptedMessageLayer17 = TLUtils.GetDecryptedMessageLayer(newEncryptedChat.Layer, inSeqNo, outSeqNo, decryptedMessageService17); + + cacheService.SyncDecryptedMessage( + decryptedMessageService17, + encryptedChat, + messageResult => + { + sendEncryptedServiceAsync( + new TLInputEncryptedChat + { + AccessHash = encryptedChat.AccessHash, + ChatId = encryptedChat.Id + }, + randomId, + TLUtils.EncryptMessage(decryptedMessageLayer17, MTProtoService.Instance.CurrentUserId, newEncryptedChat), + sentEncryptedMessage => + { + decryptedMessageService17.Status = MessageStatus.Confirmed; + cacheService.SyncSendingDecryptedMessage(encryptedChat.Id, sentEncryptedMessage.Date, decryptedMessageService17.RandomId, + m => + { +#if DEBUG + eventAggregator.Publish(decryptedMessageService17); +#endif + }); + }, + error => + { + Helpers.Execute.ShowDebugMessage("messages.sendEncryptedService error " + error); + }); + }); + }); + } + + public static int GetRawInFromReceivedMessage(TLInt currentUserId, TLEncryptedChat17 chat, ISeqNo message) + { + var isAdmin = chat.AdminId.Value == currentUserId.Value; + var x = isAdmin ? 0 : 1; + return (message.OutSeqNo.Value - x) / 2; + } + + private readonly object _clientSeqLock = new object(); + + private readonly Dictionary> _lostSeq = new Dictionary>(); + + private void UpdateLostSeq(IList seqList, bool cleanupMissingSeq = false) + { + lock (_clientSeqLock) + { + if (ClientSeq != null) + { + if (seqList.Count > 0) + { + // add missing items + if (seqList[0].Value > ClientSeq.Value + 1) + { + for (var i = ClientSeq.Value + 1; i < seqList[0].Value; i++) + { + _lostSeq[i] = new WindowsPhone.Tuple(DateTime.Now, new TLState { Seq = ClientSeq, Pts = _pts, Date = _date, Qts = _qts }); + } + } + + // remove received items + for (var i = 0; i < seqList.Count; i++) + { + if (_lostSeq.ContainsKey(seqList[i].Value)) + { + TLUtils.WriteLine( + DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + " remove from Missing Seq List seq=" + + seqList[i].Value + " time=" + (DateTime.Now - _lostSeq[seqList[i].Value].Item1), LogSeverity.Error); + _lostSeq.Remove(seqList[i].Value); + } + } + } + } + + // cleanup (updates.getDifference, set initState, etc) + if (cleanupMissingSeq) + { + _lostSeq.Clear(); + } + + if (seqList.Count > 0) + { + var lastSeqValue = seqList.Last().Value; + var maxSeqValue = Math.Max(lastSeqValue, ClientSeq != null ? ClientSeq.Value : -1); + ClientSeq = new TLInt(maxSeqValue); + } + + if (_lostSeq.Count > 0) + { + var missingSeqInfo = new StringBuilder(); + foreach (var keyValue in _lostSeq) + { + missingSeqInfo.AppendLine(string.Format("seq={0}, date={1}", keyValue.Key, + keyValue.Value.Item1.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture))); + } + + StartLostSeqTimer(); + + TLUtils.WriteLine( + DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + " Missing Seq List\n" + + missingSeqInfo, LogSeverity.Error); + } + } + } + + private readonly object _clientPtsLock = new object(); + + private readonly Dictionary> _lostPts = new Dictionary>(); + + private void UpdateLostPts(IList ptsList, bool cleanupMissingPts = false) + { + lock (_clientPtsLock) + { + if (_pts != null) + { + if (ptsList.Count > 0) + { + // add missing items + if (ptsList[0].Value > _pts.Value + 1) + { + for (var i = _pts.Value + 1; i < ptsList[0].Value; i++) + { + _lostPts[i] = new WindowsPhone.Tuple(DateTime.Now, new TLState { Seq = ClientSeq, Pts = _pts, Date = _date, Qts = _qts }); + } + } + + // remove received items + for (var i = 0; i < ptsList.Count; i++) + { + if (_lostPts.ContainsKey(ptsList[i].Value)) + { + TLUtils.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + " remove from Missing Pts List pts=" + ptsList[i].Value + " time=" + (DateTime.Now - _lostPts[ptsList[i].Value].Item1), LogSeverity.Error); + _lostPts.Remove(ptsList[i].Value); + } + } + } + } + + // cleanup (updates.getDifference, set initState, etc) + if (cleanupMissingPts) + { + _lostPts.Clear(); + } + + if (ptsList.Count > 0) + { + var lastPtsValue = ptsList.Last().Value; + var maxPtsValue = Math.Max(lastPtsValue, _pts != null ? _pts.Value : -1); + _pts = new TLInt(maxPtsValue); + } + + if (_lostPts.Count > 0) + { + var missingPtsInfo = new StringBuilder(); + foreach (var keyValue in _lostPts) + { + missingPtsInfo.AppendLine(string.Format("pts={0}, date={1}", keyValue.Key, + keyValue.Value.Item1.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture))); + } + + StartLostPtsTimer(); + + TLUtils.WriteLine( + DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + " Missing Pts List\n" + + missingPtsInfo, LogSeverity.Error); + } + } + } + + private void ProcessUpdates(IList updatesList, IList updatesTooLong = null, bool notifyNewMessage = true) + { + try + { +#if DEBUG + if (updatesTooLong != null && updatesTooLong.Count > 0) + { + //NOTE to get AUTH_KEY_UNREGISTERED + GetStateAsync.SafeInvoke( + result => + { + + }, + error => + { + Helpers.Execute.ShowDebugMessage("account.updateStatus error " + error); + }); +#if LOG_CLIENTSEQ + Helpers.Execute.ShowDebugMessage(string.Format("{0} updatesTooLong clientSeq={1} pts={2}", DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture), ClientSeq, _pts)); + TLUtils.WriteLine(string.Format("{0} updatesTooLong seq={1} pts={2}", DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture), ClientSeq, _pts), LogSeverity.Error); + //TLUtils.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + " updatesTooLong clientSeq=" + ClientSeq, LogSeverity.Error); +#endif + } +#endif + + var seqList = updatesList.SelectMany(updates => updates.GetSeq()).OrderBy(x => x.Value).ToList(); + var ptsList = updatesList.SelectMany(updates => updates.GetPts()).OrderBy(x => x.Value).ToList(); + + /*#if DEBUG + if (seqList.Count > 0) + { + var showDebugInfo = false; + for (var i = 0; i < seqList.Count; i++) + { + if (seqList[i].Value == 0) + { + showDebugInfo = true; + break; + } + } + + // only TLUpdateUserStatus here + if (showDebugInfo) + { + var updateListInfo = new StringBuilder(); + foreach (var updatesBase in updateList) + { + updateListInfo.AppendLine(updatesBase.ToString()); + } + Helpers.Execute.ShowDebugMessage("ProcessTransportMessage seqs=0 " + updateListInfo); + } + } + #endif*/ + +#if LOG_CLIENTSEQ + if (ptsList.Count > 0 || seqList.Count > 0) + { + var builder = new StringBuilder(); + builder.AppendLine(string.Format("{0} ProcessTransportMessage", DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture))); + builder.AppendLine(string.Format("clientSeq={0} seqList={1}", ClientSeq, seqList.Count == 0 ? "null" : string.Join(", ", seqList))); + builder.AppendLine(string.Format("pts={0} ptsList={1}", _pts, ptsList.Count == 0 ? "null" : string.Join(", ", ptsList))); + TLUtils.WriteLine(builder.ToString(), LogSeverity.Error); + } +#endif + if (GetDifferenceRequired(updatesList)) + { + var stopwatch = Stopwatch.StartNew(); + Logs.Log.Write("UpdatesService.ProcessUpdates StartGetDifference"); + GetDifference(1000, () => + { + var elapsed = stopwatch.Elapsed; + Logs.Log.Write("UpdatesService.ProcessUpdates StopGetDifference time=" + elapsed); + }); + return; + } + + var processUpdates = false; + if (updatesList.Count > 0) + { + if (seqList.Count > 0) + { + UpdateLostSeq(seqList); + } + + if (ptsList.Count > 0) + { + UpdateLostPts(ptsList); + } + + processUpdates = true; + } + + if (processUpdates) + { + ProcessReading(updatesList); + foreach (var updatesItem in updatesList) + { + ProcessUpdatesInternal(updatesItem, notifyNewMessage); + } + } + + return; + } + catch (Exception e) + { + TLUtils.WriteLine("Error during processing update: ", LogSeverity.Error); + TLUtils.WriteException(e); + } + } + + private bool GetDifferenceRequired(IList updatesList) + { + var getDifferenceRequired = false; + for (int i = 0; i < updatesList.Count; i++) + { + var updatesShortChatMessage = updatesList[i] as TLUpdatesShortChatMessage; + if (updatesShortChatMessage != null) + { + var user = _cacheService.GetUser(updatesShortChatMessage.UserId); + if (user == null) + { + var logString = + string.Format("ProcessUpdates.UpdatesShortChatMessage: user is missing (userId={0}, msgId={1})", + updatesShortChatMessage.UserId, updatesShortChatMessage.Id); + Logs.Log.Write(logString); + getDifferenceRequired = true; + break; + } + var chat = _cacheService.GetChat(updatesShortChatMessage.ChatId); + if (chat == null) + { + var logString = + string.Format("ProcessUpdates.UpdatesShortChatMessage: chat is missing (chatId={0}, msgId={1})", + updatesShortChatMessage.ChatId, updatesShortChatMessage.Id); + Logs.Log.Write(logString); + getDifferenceRequired = true; + break; + } + } + + var updatesShortMessage = updatesList[i] as TLUpdatesShortMessage; + if (updatesShortMessage != null) + { + var user = _cacheService.GetUser(updatesShortMessage.UserId); + if (user == null) + { + var logString = + string.Format("ProcessUpdates.UpdatesShortMessage: user is missing (userId={0}, msgId={1})", + updatesShortMessage.UserId, updatesShortMessage.Id); + Logs.Log.Write(logString); + getDifferenceRequired = true; + break; + } + } + } + return getDifferenceRequired; + } + + private void ProcessReading(IList updatesList) + { + var readHistoryInboxList = new List(); + var readHistoryOutboxList = new List(); + + var newChatMessageList = new List(); + var newMessageList = new List(); + var shortChatMessageList = new List(); + var shortMessageList = new List(); + + foreach (var updatesBase in updatesList) + { + var updatesShort = updatesBase as TLUpdatesShort; + if (updatesShort != null) + { + GetReadingUpdates(updatesShort.Update, readHistoryInboxList, readHistoryOutboxList, newChatMessageList, newMessageList); + + continue; + } + + var updates = updatesBase as TLUpdates; + if (updates != null) + { + foreach (var updateBase in updates.Updates) + { + GetReadingUpdates(updateBase, readHistoryInboxList, readHistoryOutboxList, newChatMessageList, newMessageList); + } + + continue; + } + + var shortChatMessage = updatesBase as TLUpdatesShortChatMessage34; + if (shortChatMessage != null + && shortChatMessage.Unread.Value) + { + shortChatMessageList.Add(shortChatMessage); + continue; + } + + var shortMessage = updatesBase as TLUpdatesShortMessage34; + if (shortMessage != null + && shortMessage.Unread.Value) + { + shortMessageList.Add(shortMessage); + continue; + } + } + + ProcessReadingUpdates(false, readHistoryInboxList, shortChatMessageList, newChatMessageList, shortMessageList, newMessageList); + ProcessReadingUpdates(true, readHistoryOutboxList, shortChatMessageList, newChatMessageList, shortMessageList, newMessageList); + } + + private static void ProcessReadingUpdates( + bool outbox, IList readHistoryList, + IList shortChatMessageList, + IList newChatMessageList, + IList shortMessageList, + IList newMessageList) + { + if (readHistoryList.Count == 0) return; + + foreach (var readHistory in readHistoryList) + { + var peerChat = readHistory.Peer as TLPeerChat; + if (peerChat != null) + { + for (var i = 0; i < shortChatMessageList.Count; i++) + { + if (shortChatMessageList[i].Out.Value == outbox + && peerChat.Id.Value == shortChatMessageList[i].ChatId.Value + && readHistory.MaxId.Value >= shortChatMessageList[i].Id.Value) + { + shortChatMessageList[i].Unread = TLBool.False; + shortChatMessageList.RemoveAt(i--); + } + } + + for (var i = 0; i < newChatMessageList.Count; i++) + { + var message = newChatMessageList[i].Message as TLMessageCommon; + if (message != null && message.Out.Value == outbox) + { + if (message.Out.Value == outbox + && peerChat.Id.Value == message.ToId.Id.Value + && readHistory.MaxId.Value >= message.Id.Value) + { + message.SetUnreadSilent(TLBool.False); + newChatMessageList.RemoveAt(i--); + } + } + } + continue; + } + + var peerUser = readHistory.Peer as TLPeerUser; + if (peerUser != null) + { + for (var i = 0; i < shortMessageList.Count; i++) + { + if (shortMessageList[i].Out.Value == outbox + && peerUser.Id.Value == shortMessageList[i].UserId.Value + && readHistory.MaxId.Value >= shortMessageList[i].Id.Value) + { + shortMessageList[i].Unread = TLBool.False; + shortMessageList.RemoveAt(i--); + } + } + + for (var i = 0; i < newMessageList.Count; i++) + { + var message = newMessageList[i].Message as TLMessageCommon; + if (message != null) + { + if (message.Out.Value == outbox + && peerUser.Id.Value == message.FromId.Value + && readHistory.MaxId.Value >= message.Id.Value) + { + message.SetUnreadSilent(TLBool.False); + newMessageList.RemoveAt(i--); + } + } + } + continue; + } + } + } + + private static void GetReadingUpdates(TLUpdateBase updateBase, + IList readHistoryInboxList, + IList readHistoryOutboxList, + IList newChatMessageList, + IList newMessageList) + { + var readHistoryInbox = updateBase as TLUpdateReadHistoryInbox; + if (readHistoryInbox != null) + { + readHistoryInboxList.Add(readHistoryInbox); + return; + } + + var readHistoryOutbox = updateBase as TLUpdateReadHistoryOutbox; + if (readHistoryOutbox != null) + { + readHistoryOutboxList.Add(readHistoryOutbox); + return; + } + + var newMessage = updateBase as TLUpdateNewMessage; + if (newMessage != null) + { + var message = newMessage.Message as TLMessageCommon; + if (message != null + && message.Unread.Value) + { + var peerChat = message.ToId as TLPeerChat; + if (peerChat != null) + { + newChatMessageList.Add(newMessage); + return; + } + + var peerUser = message.ToId as TLPeerUser; + if (peerUser != null) + { + newMessageList.Add(newMessage); + return; + } + } + } + } + + public void ProcessUpdates(TLUpdatesBase updates, bool notifyNewMessages = false) + { + var updatesList = new List { updates }; + + var updatesTooLongList = new List(); + var updatesTooLong = updates as TLUpdatesTooLong; + if (updatesTooLong != null) + { + updatesTooLongList.Add(updatesTooLong); + } + + ProcessUpdates(updatesList, updatesTooLongList, notifyNewMessages); + } + + public void ProcessTransportMessage(TLTransportMessage transportMessage) + { + try + { + var isUpdating = false; + lock (_getDifferenceRequestRoot) + { + if (_getDifferenceRequests.Count > 0) + { + isUpdating = true; + } + } + + if (isUpdating) + { + //Execute.ShowDebugMessage("UpdatesService.ProcessTransportMessage Skip"); + return; + } + + var updatesList = TLUtils.FindInnerObjects(transportMessage).ToList(); + var updatesTooLong = TLUtils.FindInnerObjects(transportMessage).ToList(); + + ProcessUpdates(updatesList, updatesTooLong); + } + catch (Exception e) + { + TLUtils.WriteLine("Error during processing update: ", LogSeverity.Error); + TLUtils.WriteException(e); + } + } + + private readonly object _stateRoot = new object(); + + public void LoadStateAndUpdate(long acceptedCallId, Action callback) + { + var id = new Random().Next(999); + TLUtils.WritePerformance(">>Loading current state and updating"); + + if (_pts == null || _date == null || _qts == null) + { + var state = TLUtils.OpenObjectFromMTProtoFile(_stateRoot, Constants.StateFileName); +#if DEBUG_UPDATES + state.Pts = new TLInt(140000); +#endif + + SetState(state, "setFileState"); + TLUtils.WritePerformance("Current state: " + state); + + FileUtils.Copy(_stateRoot, Constants.StateFileName, Constants.TempStateFileName); + } + + Logs.Log.Write(string.Format("UpdatesService.LoadStateAndUpdate {0} client_state=[p={1} d={2} q={3}]", id, _pts, _date, _qts)); + + LoadFileState(); + + var stopwatch = Stopwatch.StartNew(); + Logs.Log.Write(string.Format("UpdatesService.LoadStateAndUpdate {0} start GetDifference", id)); + AddRequest(id); + //TLObject.LogNotify = true; + //TelegramEventAggregator.LogPublish = true; + + GetDifference(id, () => + { + var elapsed = stopwatch.Elapsed; + Logs.Log.Write(string.Format("UpdatesService.LoadStateAndUpdate {0} stop GetDifference elapsed={1}", id, elapsed)); + + + //TLObject.LogNotify = false; + //TelegramEventAggregator.LogPublish = false; + RemoveRequest(id); + callback.SafeInvoke(); + }); + } + + private readonly object _differenceSyncRoot = new object(); + + private readonly object _differenceTimeSyncRoot = new object(); + + private void LoadFileState() + { + var stopwatch = Stopwatch.StartNew(); + var difference = TLUtils.OpenObjectFromMTProtoFile>(_differenceSyncRoot, Constants.DifferenceFileName); + + Logs.Log.Write("UpdatesService.LoadStateAndUpdate start LoadFileState"); + + if (difference != null && difference.Count > 0) + { + CleanupDifference(difference); + + var ptsList = string.Join(", ", difference.OfType().Select(x => x.State.Pts)); + Logs.Log.Write(string.Format("UpdatesService.LoadStateAndUpdate ptsList=[{0}]", ptsList)); + + foreach (var differenceBase in difference) + { + var stopwatchProcessDiff = Stopwatch.StartNew(); + var diff = differenceBase as TLDifference; + if (diff != null) + { + var resetEvent = new ManualResetEvent(false); + + lock (_clientSeqLock) + { + SetState(diff.State, "loadFileState"); + } + ProcessDifference(diff, () => resetEvent.Set()); +#if DEBUG + resetEvent.WaitOne(); +#else + resetEvent.WaitOne(10000); +#endif + + var otherInfo = new StringBuilder(); + if (diff.OtherUpdates.Count > 0) + { + otherInfo.AppendLine(); + for (var i = 0; i < diff.OtherUpdates.Count; i++) + { + otherInfo.AppendLine(diff.OtherUpdates[i].ToString()); + } + } + + Logs.Log.Write(string.Format("UpdatesService.LoadFileState processDiff state=[{0}] messages={1} other={2} elapsed={3}{4}", diff.State, diff.NewMessages.Count, diff.OtherUpdates.Count, stopwatchProcessDiff.Elapsed, otherInfo)); + } + } + + Logs.Log.Write("UpdatesService.LoadStateAndUpdate LoadFileState publish UpdateCompletedEventArgs"); + + Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new UpdateCompletedEventArgs())); + } + + Logs.Log.Write("UpdatesService.LoadStateAndUpdate stop LoadFileState elapsed=" + stopwatch.Elapsed); + + FileUtils.Copy(_differenceSyncRoot, Constants.DifferenceFileName, Constants.TempDifferenceFileName); + FileUtils.Delete(_differenceSyncRoot, Constants.DifferenceFileName); + FileUtils.Delete(_differenceTimeSyncRoot, Constants.DifferenceTimeFileName); + } + + private void CleanupDifference(TLVector list) + { + var updateChannelTooLongCache = new Dictionary(); + var updateChannelCache = new Dictionary(); + var hasUpdateDialogPinned = false; + var updatePhoneCallDiscardedCache = new Dictionary(); + + foreach (var differenceBase in list) + { + var differenceSlice = differenceBase as TLDifference; + if (differenceSlice != null) + { + var updates = differenceSlice.OtherUpdates; + for (var i = 0; i < updates.Count; i++) + { + var updateChannelTooLong = updates[i] as TLUpdateChannelTooLong; + if (updateChannelTooLong != null) + { + if (updateChannelTooLongCache.ContainsKey(updateChannelTooLong.ChannelId.Value)) + { + updates.RemoveAt(i--); + } + else + { + updateChannelTooLongCache[updateChannelTooLong.ChannelId.Value] = updateChannelTooLong.ChannelId.Value; + } + } + + var updatePhoneCall = updates[i] as TLUpdatePhoneCall; + if (updatePhoneCall != null) + { + var phoneCallDiscarded = updatePhoneCall.PhoneCall as TLPhoneCallDiscarded61; + if (phoneCallDiscarded != null) + { + updatePhoneCallDiscardedCache[phoneCallDiscarded.Id.Value] = phoneCallDiscarded.Id.Value; + } + } + } + } + } + + foreach (var differenceBase in list) + { + var differenceSlice = differenceBase as TLDifference; + if (differenceSlice != null) + { + var updates = differenceSlice.OtherUpdates; + for (var i = 0; i < updates.Count; i++) + { + var updateChannel = updates[i] as TLUpdateChannel; + if (updateChannel != null) + { + if (updateChannelTooLongCache.ContainsKey(updateChannel.ChannelId.Value)) + { + updates.RemoveAt(i--); + } + else if (updateChannelCache.ContainsKey(updateChannel.ChannelId.Value)) + { + updates.RemoveAt(i--); + } + else + { + updateChannelCache[updateChannel.ChannelId.Value] = updateChannel.ChannelId.Value; + } + } + + var updatePinnedDialogs = updates[i] as TLUpdatePinnedDialogs; + if (updatePinnedDialogs != null) + { + if (hasUpdateDialogPinned) + { + updates.RemoveAt(i--); + } + else + { + hasUpdateDialogPinned = true; + updatePinnedDialogs.Order = null; + } + } + + var updatePhoneCall = updates[i] as TLUpdatePhoneCall; + if (updatePhoneCall != null) + { + var phoneCallDiscarded = updatePhoneCall.PhoneCall as TLPhoneCallDiscarded61; + if (phoneCallDiscarded == null) + { + if (updatePhoneCallDiscardedCache.ContainsKey(updatePhoneCall.PhoneCall.Id.Value)) + { + updates.RemoveAt(i--); + } + } + } + } + } + } + } + + public void SaveState() + { + var state = new TLState { Date = _date, Pts = _pts, Qts = _qts, Seq = ClientSeq, UnreadCount = _unreadCount }; + TLUtils.WritePerformance("<(_stateRoot, Path.Combine(fromDirectoryName, Constants.StateFileName)); + if (state != null) + { + lock (_clientSeqLock) + { + ClientSeq = state.Seq; + } + _date = state.Date ?? _date; + _pts = state.Pts ?? _pts; + _qts = state.Qts ?? _qts; + _unreadCount = state.UnreadCount ?? _unreadCount; + SaveState(); + } + + FileUtils.Copy(_differenceSyncRoot, Path.Combine(fromDirectoryName, Constants.DifferenceFileName), Constants.DifferenceFileName); + } + + public void ClearState() + { + _date = null; + _pts = null; + _qts = null; + ClientSeq = null; + _unreadCount = null; + FileUtils.Delete(_stateRoot, Constants.StateFileName); + } + } + + public class DCOptionsUpdatedEventArgs : EventArgs + { + public TLUpdateDCOptions Update { get; set; } + } + + public class UpdatingEventArgs : EventArgs { } + + public class UpdateCompletedEventArgs : EventArgs + { + public IList UpdateChannelTooLongList { get; set; } + } + + public class UpdateChannelsEventArgs : EventArgs + { + public IList UpdateChannelTooLongList { get; set; } + } + + public class ChannelUpdateCompletedEventArgs + { + public TLInt ChannelId { get; set; } + } +} diff --git a/Telegram.Api/Services/VoIP/IVoIPService.cs b/Telegram.Api/Services/VoIP/IVoIPService.cs new file mode 100755 index 0000000..fef7a6a --- /dev/null +++ b/Telegram.Api/Services/VoIP/IVoIPService.cs @@ -0,0 +1,9 @@ +using Telegram.Api.TL; + +namespace Telegram.Api.Services.VoIP +{ + public interface IVoIPService + { + void StartOutgoingCall(TLInputUserBase userId); + } +} diff --git a/Telegram.Api/Services/VoIP/VoIPService.cs b/Telegram.Api/Services/VoIP/VoIPService.cs new file mode 100755 index 0000000..a4006a7 --- /dev/null +++ b/Telegram.Api/Services/VoIP/VoIPService.cs @@ -0,0 +1,344 @@ +using System; +using System.Text; +using Windows.Storage; +#if WINDOWS_PHONE +using libtgvoip; +#endif +using Org.BouncyCastle.Security; +using Telegram.Api.Aggregator; +using Telegram.Api.Helpers; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; + +namespace Telegram.Api.Services.VoIP +{ + public class VoIPService : IVoIPService, IHandle +#if WINDOWS_PHONE + , IStateCallback +#endif + { + private const int CALL_MIN_LAYER = 65; + private const int CALL_MAX_LAYER = 65; + + private readonly IMTProtoService _mtProtoService; + + private readonly ITelegramEventAggregator _eventAggregator; + + private readonly ICacheService _cacheService; + + public VoIPService(IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator, ICacheService cacheService) + { + _mtProtoService = mtProtoService; + _eventAggregator = eventAggregator; + _cacheService = cacheService; + + _eventAggregator.Subscribe(this); + +#if WINDOWS_PHONE + MicrosoftCryptoImpl.Init(); + + var input = Encoding.UTF8.GetBytes("test"); + var result1 = MicrosoftCryptoImpl.SHA1_test(input, (uint) input.Length); + var result2 = Utils.ComputeSHA1(input); + for (int i = 0; i < result1.Length; i++) + { + if (result1[i] != result2[i]) + { + throw new Exception("sha1 i=" + i); + } + } + var result3 = MicrosoftCryptoImpl.SHA256_test(input, (uint)input.Length); + var result4 = Utils.ComputeSHA256(input); + for (int i = 0; i < result1.Length; i++) + { + if (result3[i] != result4[i]) + { + throw new Exception("sha1 i=" + i); + } + } + var keyString = "01234567890123456789012345678901"; + var ivString = "01234567890123456789012345678901"; + var key = Encoding.UTF8.GetBytes(keyString); + var iv = Encoding.UTF8.GetBytes(ivString); + var result5 = MicrosoftCryptoImpl.AesIgeEncrypt_test(input, (uint)input.Length, key, iv); + key = Encoding.UTF8.GetBytes(keyString); + iv = Encoding.UTF8.GetBytes(ivString); + var result6 = MicrosoftCryptoImpl.AesIgeDecrypt_test(result5, (uint)input.Length, key, iv); + key = Encoding.UTF8.GetBytes(keyString); + iv = Encoding.UTF8.GetBytes(ivString); + var result7 = Utils.AesIge(input, key, iv, true); + var result8 = Utils.AesIge(result7, key, iv, false); +#endif + } + + private TLString _secretP; + + private TLString _secretRandom; + + private TLInt _secretG; + + private TLInt _lastVersion; + + private byte[] _ga; + + private TLPhonePhoneCall _call; + private byte[] _aOrB; + private byte[] _authKey; + private bool _outgoing = true; +#if WINDOWS_PHONE + private VoIPControllerWrapper _controller; +#endif + + public void StartOutgoingCall(TLInputUserBase userId) + { + var salt = new Byte[256]; + var random = new SecureRandom(); + random.NextBytes(salt); + + var version = _lastVersion ?? new TLInt(0); + var randomLength = new TLInt(256); + + _mtProtoService.GetDHConfigAsync(version, randomLength, + result => + { + ConfigureDeviceForCall(); + ShowNotifications(); + StartConnectionSound(); + DispatchStateChanged(PhoneCallState.STATE_REQUESTING); + + _eventAggregator.Publish(new PhoneCallEventArgs("NotificationCenter.didStartedCall")); + + var dhConfig = result as TLDHConfig; + if (dhConfig != null) + { + if (!TLUtils.CheckPrime(dhConfig.P.Data, dhConfig.G.Value)) + { + CallFailed(); + return; + } + + _secretP = dhConfig.P; + _secretG = dhConfig.G; + _secretRandom = dhConfig.Random; + } + + for (var i = 0; i < 256; i++) + { + salt[i] = (byte) (salt[i] ^ _secretRandom.Data[i]); + } + + var gaBytes = MTProtoService.GetGB(salt, _secretG, _secretP); + + var protocol = new TLPhoneCallProtocol + { + Flags = new TLInt(0), + UdpP2P = true, + UdpReflector = true, + MinLayer = new TLInt(CALL_MIN_LAYER), + MaxLayer = new TLInt(CALL_MAX_LAYER) + }; + _ga = gaBytes; + var gaHash = Utils.ComputeSHA256(_ga); + + _mtProtoService.RequestCallAsync(userId, TLInt.Random(), TLString.FromBigEndianData(gaHash), protocol, + result2 => + { + _call = result2; + _aOrB = salt; + DispatchStateChanged(PhoneCallState.STATE_WAITING); + //if (_endCallAfterRequest) + //{ + // Hangup(); + // return; + //} + }, + error2 => + { + + }); + }, + error => + { + Helpers.Execute.ShowDebugMessage("messages.getDHConfig error " + error); + CallFailed(); + }); + + } + + private void DispatchStateChanged(PhoneCallState phoneCallState) + { + + } + + private void StartConnectionSound() + { + + } + + private void ShowNotifications() + { + + + } + + private void ConfigureDeviceForCall() + { + + } + + private void CallFailed() + { + + } + + public void Handle(TLUpdatePhoneCall updatePhoneCall) + { + var phoneCall = updatePhoneCall.PhoneCall; + var phoneCallAccepted = phoneCall as TLPhoneCallAccepted; + if (phoneCallAccepted != null) + { + if (_authKey == null) + { + ProcessAcceptedCall(phoneCallAccepted); + } + + return; + } + + } + + private void ProcessAcceptedCall(TLPhoneCallAccepted phoneCallAccepted) + { + DispatchStateChanged(PhoneCallState.STATE_EXCHANGING_KEYS); + + if (!TLUtils.CheckGaAndGb(phoneCallAccepted.GB.Data, _secretP.Data)) + { + CallFailed(); + return; + } + + + _authKey = MTProtoService.GetAuthKey(_aOrB, phoneCallAccepted.GB.ToBytes(), _secretP.ToBytes()); + var keyHash = Utils.ComputeSHA1(_authKey); + var keyFingerprint = new TLLong(BitConverter.ToInt64(keyHash, 12)); + + var peer = new TLInputPhoneCall + { + Id = phoneCallAccepted.Id, + AccessHash = phoneCallAccepted.AccessHash + }; + + var protocol = new TLPhoneCallProtocol + { + Flags = new TLInt(0), + UdpP2P = true, + UdpReflector = true, + MinLayer = new TLInt(CALL_MIN_LAYER), + MaxLayer = new TLInt(CALL_MAX_LAYER) + }; + + _mtProtoService.ConfirmCallAsync(peer, TLString.FromBigEndianData(_ga), keyFingerprint, protocol, + result => + { + _call = result; + InitiateActualEncryptedCall(); + }, + error => + { + CallFailed(); + }); + + } + + private void InitiateActualEncryptedCall() + { +#if WINDOWS_PHONE + + _mtProtoService.GetCallConfigAsync(result => + { + VoIPControllerWrapper.UpdateServerConfig(result.Data.ToString()); + + var logFile = ApplicationData.Current.LocalFolder.Path + "\\tgvoip.logFile.txt"; + var statsDumpFile = ApplicationData.Current.LocalFolder.Path + "\\tgvoip.statsDump.txt"; + + + if (_controller != null) + { + //_controller.Dispose(); + _controller = null; + } + + _cacheService.GetConfigAsync(config => + { + var config60 = config as TLConfig60; + if (config60 != null) + { + _controller = new VoIPControllerWrapper(); + _controller.SetConfig(config60.CallPacketTimeoutMs.Value / 1000.0, config60.CallConnectTimeoutMs.Value / 1000.0, DataSavingMode.Never, false, false, true, logFile, statsDumpFile); + + _controller.SetStateCallback(this); + _controller.SetEncryptionKey(_authKey, _outgoing); + + var phoneCall = _call.PhoneCall as TLPhoneCall; + if (phoneCall != null) + { + var connection = phoneCall.Connection; + var endpoints = new Endpoint[phoneCall.AlternativeConnections.Count + 1]; + endpoints[0] = connection.ToEndpoint(); + + for (int i = 0; i < phoneCall.AlternativeConnections.Count; i++) + { + connection = phoneCall.AlternativeConnections[i]; + endpoints[i + 1] = connection.ToEndpoint(); + } + + _controller.SetPublicEndpoints(endpoints, phoneCall.Protocol.UdpP2P); + _controller.Start(); + _controller.Connect(); + } + } + }); + + }, + error => + { + + }); + +#endif + } + +#if WINDOWS_PHONE + public void OnCallStateChanged(CallState newState) + { + Execute.ShowDebugMessage("OnCallStateChanged state=" + newState); + } +#endif + } + + public class PhoneCallEventArgs + { + public string Param { get; set; } + + public PhoneCallEventArgs(string param) + { + Param = param; + } + } + + public enum PhoneCallState + { + STATE_WAIT_INIT = 1, + STATE_WAIT_INIT_ACK = 2, + STATE_ESTABLISHED = 3, + STATE_FAILED = 4, + STATE_HANGING_UP = 5, + STATE_ENDED = 6, + STATE_EXCHANGING_KEYS = 7, + STATE_WAITING = 8, + STATE_REQUESTING = 9, + STATE_WAITING_INCOMING = 10, + STATE_RINGING = 11, + STATE_BUSY = 12, + } +} diff --git a/Telegram.Api/TL/Account/TLChangePhone.cs b/Telegram.Api/TL/Account/TLChangePhone.cs new file mode 100755 index 0000000..a452e09 --- /dev/null +++ b/Telegram.Api/TL/Account/TLChangePhone.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLChangePhone : TLObject + { + public const string Signature = "#70c32edb"; + + public TLString PhoneNumber { get; set; } + + public TLString PhoneCodeHash { get; set; } + + public TLString PhoneCode { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumber.ToBytes(), + PhoneCodeHash.ToBytes(), + PhoneCode.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Account/TLCheckPassword.cs b/Telegram.Api/TL/Account/TLCheckPassword.cs new file mode 100755 index 0000000..8e3090c --- /dev/null +++ b/Telegram.Api/TL/Account/TLCheckPassword.cs @@ -0,0 +1,37 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLCheckPassword : TLObject + { + public const uint Signature = 0xd18b4d16; + + public TLInputCheckPasswordBase Password { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Password.ToBytes()); + } + } + + class TLCheckPasswordOld : TLObject + { + public const string Signature = "#a63011e"; + + public TLString PasswordHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PasswordHash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Account/TLConfirmPhone.cs b/Telegram.Api/TL/Account/TLConfirmPhone.cs new file mode 100755 index 0000000..93a6abb --- /dev/null +++ b/Telegram.Api/TL/Account/TLConfirmPhone.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLConfirmPhone : TLObject + { + public const uint Signature = 0x5f2178c3; + + public TLString PhoneCodeHash { get; set; } + + public TLString PhoneCode { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneCodeHash.ToBytes(), + PhoneCode.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Account/TLGetAuthorizations.cs b/Telegram.Api/TL/Account/TLGetAuthorizations.cs new file mode 100755 index 0000000..21ce303 --- /dev/null +++ b/Telegram.Api/TL/Account/TLGetAuthorizations.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + class TLGetAuthorizations : TLObject + { + public const uint Signature = 0xe320c158; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Account/TLGetPassword.cs b/Telegram.Api/TL/Account/TLGetPassword.cs new file mode 100755 index 0000000..5674cd6 --- /dev/null +++ b/Telegram.Api/TL/Account/TLGetPassword.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLGetPassword : TLObject + { + public const string Signature = "#548a30f5"; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Account/TLGetPasswordSettings.cs b/Telegram.Api/TL/Account/TLGetPasswordSettings.cs new file mode 100755 index 0000000..9548f9f --- /dev/null +++ b/Telegram.Api/TL/Account/TLGetPasswordSettings.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + class TLGetPasswordSettings : TLObject + { + public const uint Signature = 0x9cd4eaf9; + + public TLInputCheckPasswordBase Password { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Password.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Account/TLGetTmpPassword.cs b/Telegram.Api/TL/Account/TLGetTmpPassword.cs new file mode 100755 index 0000000..7007000 --- /dev/null +++ b/Telegram.Api/TL/Account/TLGetTmpPassword.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLGetTmpPassword : TLObject + { + public const uint Signature = 0x449e0b51; + + public TLInputCheckPasswordBase Password { get; set; } + + public TLInt Period { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Password.ToBytes(), + Period.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Account/TLGetWallPapers.cs b/Telegram.Api/TL/Account/TLGetWallPapers.cs new file mode 100755 index 0000000..7423fbc --- /dev/null +++ b/Telegram.Api/TL/Account/TLGetWallPapers.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + class TLGetWallPapers : TLObject + { + public const string Signature = "#c04cfac2"; + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Account/TLRecoverPassword.cs b/Telegram.Api/TL/Account/TLRecoverPassword.cs new file mode 100755 index 0000000..0e00fe6 --- /dev/null +++ b/Telegram.Api/TL/Account/TLRecoverPassword.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + class TLRecoverPassword : TLObject + { + public const string Signature = "#4ea56e92"; + + public TLString Code { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Code.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Account/TLReportPeer.cs b/Telegram.Api/TL/Account/TLReportPeer.cs new file mode 100755 index 0000000..a80c035 --- /dev/null +++ b/Telegram.Api/TL/Account/TLReportPeer.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + class TLReportPeer : TLObject + { + public const uint Signature = 0xae189d5f; + + public TLInputPeerBase Peer { get; set; } + + public TLInputReportReasonBase Reason { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Reason.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Account/TLRequestPasswordRecovery.cs b/Telegram.Api/TL/Account/TLRequestPasswordRecovery.cs new file mode 100755 index 0000000..4d023de --- /dev/null +++ b/Telegram.Api/TL/Account/TLRequestPasswordRecovery.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + class TLRequestPasswordRecovery : TLObject + { + public const string Signature = "#d897bc66"; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Account/TLResetAuthorization.cs b/Telegram.Api/TL/Account/TLResetAuthorization.cs new file mode 100755 index 0000000..08a8070 --- /dev/null +++ b/Telegram.Api/TL/Account/TLResetAuthorization.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + class TLResetAuthorization : TLObject + { + public const uint Signature = 0xdf77f3bc; + + public TLLong Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Account/TLResetPassword.cs b/Telegram.Api/TL/Account/TLResetPassword.cs new file mode 100755 index 0000000..91ff5ca --- /dev/null +++ b/Telegram.Api/TL/Account/TLResetPassword.cs @@ -0,0 +1,18 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Telegram.Api.TL.Account +{ + class TLResetPassword + { + } +} diff --git a/Telegram.Api/TL/Account/TLSendChangePhoneCode.cs b/Telegram.Api/TL/Account/TLSendChangePhoneCode.cs new file mode 100755 index 0000000..f09ffc3 --- /dev/null +++ b/Telegram.Api/TL/Account/TLSendChangePhoneCode.cs @@ -0,0 +1,49 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Account +{ + [Flags] + public enum SendChangePhoneCode + { + AllowFlashcall = 0x1, // 0 + } + + class TLSendChangePhoneCode : TLObject + { + public const uint Signature = 0x8e57deb; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLString PhoneNumber { get; set; } + + private TLString _currentNumber; + + public TLString CurrentNumber + { + get { return _currentNumber; } + set { SetField(out _currentNumber, value, ref _flags, (int)SendChangePhoneCode.AllowFlashcall); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + PhoneNumber.ToBytes(), + ToBytes(CurrentNumber, Flags, (int)SendChangePhoneCode.AllowFlashcall)); + } + } +} diff --git a/Telegram.Api/TL/Account/TLSendConfirmPhoneCode.cs b/Telegram.Api/TL/Account/TLSendConfirmPhoneCode.cs new file mode 100755 index 0000000..5c91ab5 --- /dev/null +++ b/Telegram.Api/TL/Account/TLSendConfirmPhoneCode.cs @@ -0,0 +1,49 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Account +{ + [Flags] + public enum SendConfirmPhoneCodeFlags + { + AllowFlashcall = 0x1, // 0 + } + + class TLSendConfirmPhoneCode : TLObject + { + public const uint Signature = 0x1516d7bd; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLString Hash { get; set; } + + private TLBool _currentNumber; + + public TLBool CurrentNumber + { + get { return _currentNumber; } + set { SetField(out _currentNumber, value, ref _flags, (int)SendConfirmPhoneCodeFlags.AllowFlashcall); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Hash.ToBytes(), + ToBytes(CurrentNumber, Flags, (int)SendConfirmPhoneCodeFlags.AllowFlashcall)); + } + } +} diff --git a/Telegram.Api/TL/Account/TLSetPassword.cs b/Telegram.Api/TL/Account/TLSetPassword.cs new file mode 100755 index 0000000..0348fbd --- /dev/null +++ b/Telegram.Api/TL/Account/TLSetPassword.cs @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + class TLSetPassword : TLObject + { + public const string Signature = "#dd2a4d8f"; + + public TLString CurrentPasswordHash { get; set; } + + public TLString NewSalt { get; set; } + + public TLString NewPasswordHash { get; set; } + + public TLString Hint { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + CurrentPasswordHash.ToBytes(), + NewSalt.ToBytes(), + NewPasswordHash.ToBytes(), + Hint.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Account/TLUpdateDeviceLocked.cs b/Telegram.Api/TL/Account/TLUpdateDeviceLocked.cs new file mode 100755 index 0000000..f45852a --- /dev/null +++ b/Telegram.Api/TL/Account/TLUpdateDeviceLocked.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + class TLUpdateDeviceLocked : TLObject + { + public const string Signature = "#38df3532"; + + public TLInt Period { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Period.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Account/TLUpdatePasswordSettings.cs b/Telegram.Api/TL/Account/TLUpdatePasswordSettings.cs new file mode 100755 index 0000000..1d5cab5 --- /dev/null +++ b/Telegram.Api/TL/Account/TLUpdatePasswordSettings.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + class TLUpdatePasswordSettings : TLObject + { + public const uint Signature = 0xa59b102f; + + public TLInputCheckPasswordBase Password { get; set; } + + public TLPasswordInputSettings NewSettings { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Password.ToBytes(), + NewSettings.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Enums.cs b/Telegram.Api/TL/Enums.cs new file mode 100755 index 0000000..694c2a4 --- /dev/null +++ b/Telegram.Api/TL/Enums.cs @@ -0,0 +1,4 @@ +namespace Telegram.Api.TL +{ + +} diff --git a/Telegram.Api/TL/Functions/Account/TLCheckUsername.cs b/Telegram.Api/TL/Functions/Account/TLCheckUsername.cs new file mode 100755 index 0000000..455c51e --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLCheckUsername.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + public class TLCheckUsername : TLObject + { + public const string Signature = "#2714d86c"; + + public TLString Username { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Username.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Account/TLDeleteAccount.cs b/Telegram.Api/TL/Functions/Account/TLDeleteAccount.cs new file mode 100755 index 0000000..a09c21f --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLDeleteAccount.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + public class TLDeleteAccount : TLObject + { + public const string Signature = "#418d4e0b"; + + public TLString Reason { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Reason.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Account/TLGetAccountTTL.cs b/Telegram.Api/TL/Functions/Account/TLGetAccountTTL.cs new file mode 100755 index 0000000..fde96db --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLGetAccountTTL.cs @@ -0,0 +1,34 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + public class TLGetAccountTTL : TLObject + { + public const string Signature = "#8fc711d"; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSetAccountTTL : TLObject + { + public const string Signature = "#2442485e"; + + public TLAccountDaysTTL TTL { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + TTL.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Account/TLGetNotifySettings.cs b/Telegram.Api/TL/Functions/Account/TLGetNotifySettings.cs new file mode 100755 index 0000000..f16bc44 --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLGetNotifySettings.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + public class TLGetNotifySettings : TLObject + { + public const string Signature = "#12b3ad31"; + + public TLInputNotifyPeerBase Peer { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Account/TLGetPrivacy.cs b/Telegram.Api/TL/Functions/Account/TLGetPrivacy.cs new file mode 100755 index 0000000..077b6b3 --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLGetPrivacy.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + public class TLGetPrivacy : TLObject + { + public const string Signature = "#dadbc950"; + + public TLInputPrivacyKeyBase Key { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Key.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Account/TLRegisterDevice.cs b/Telegram.Api/TL/Functions/Account/TLRegisterDevice.cs new file mode 100755 index 0000000..a047a64 --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLRegisterDevice.cs @@ -0,0 +1,40 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + public class TLRegisterDevice : TLObject + { + public const uint Signature = 0x5cbea590; + + public TLInt TokenType { get; set; } + + public TLString Token { get; set; } + + public TLBool AppSandbox { get; set; } + + public TLString Secret { get; set; } + + public TLVector OtherUids { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + TokenType.ToBytes(), + Token.ToBytes(), + AppSandbox.ToBytes(), + Secret.ToBytes(), + OtherUids.ToBytes()); + } + + public override string ToString() + { + return string.Format("token_type={0}\ntoken={1}", TokenType, Token); + } + } +} diff --git a/Telegram.Api/TL/Functions/Account/TLResetNotifySettings.cs b/Telegram.Api/TL/Functions/Account/TLResetNotifySettings.cs new file mode 100755 index 0000000..f99a5fd --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLResetNotifySettings.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + public class TLResetNotifySettings : TLObject + { + public const string Signature = "#db7e1747"; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Account/TLSetPrivacy.cs b/Telegram.Api/TL/Functions/Account/TLSetPrivacy.cs new file mode 100755 index 0000000..d346a18 --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLSetPrivacy.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + public class TLSetPrivacy : TLObject + { + public const string Signature = "#c9f81ce8"; + + public TLInputPrivacyKeyBase Key { get; set; } + + public TLVector Rules { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Key.ToBytes(), + Rules.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Account/TLUnregisterDevice.cs b/Telegram.Api/TL/Functions/Account/TLUnregisterDevice.cs new file mode 100755 index 0000000..95acb30 --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLUnregisterDevice.cs @@ -0,0 +1,31 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + public class TLUnregisterDevice : TLObject + { + public const string Signature = "#65c55b40"; + + public TLInt TokenType { get; set; } + + public TLString Token { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + TokenType.ToBytes(), + Token.ToBytes()); + } + + public override string ToString() + { + return string.Format("token_type={0}\ntoken={1}", TokenType, Token); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Account/TLUpdateNotifySettings.cs b/Telegram.Api/TL/Functions/Account/TLUpdateNotifySettings.cs new file mode 100755 index 0000000..e9c8ba4 --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLUpdateNotifySettings.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + public class TLUpdateNotifySettings : TLObject + { + public const string Signature = "#84be5b93"; + + public TLInputNotifyPeerBase Peer { get; set; } + + public TLInputPeerNotifySettings Settings { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Settings.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Account/TLUpdateProfile.cs b/Telegram.Api/TL/Functions/Account/TLUpdateProfile.cs new file mode 100755 index 0000000..0d46392 --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLUpdateProfile.cs @@ -0,0 +1,66 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Account +{ + [Flags] + public enum UpdateProfileFlags + { + FirstName = 0x1, // 0 + LastName = 0x2, // 1 + About = 0x4, // 2 + } + + public class TLUpdateProfile : TLObject + { + public const uint Signature = 0x78515775; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLString _firstName; + + public TLString FirstName + { + get { return _firstName; } + set { SetField(out _firstName, value, ref _flags, (int)UpdateProfileFlags.FirstName); } + } + + private TLString _lastName; + + public TLString LastName + { + get { return _lastName; } + set { SetField(out _lastName, value, ref _flags, (int)UpdateProfileFlags.LastName); } + } + + private TLString _about; + + public TLString About + { + get { return _about; } + set { SetField(out _about, value, ref _flags, (int)UpdateProfileFlags.About); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(FirstName, Flags, (int)UpdateProfileFlags.FirstName), + ToBytes(LastName, Flags, (int)UpdateProfileFlags.LastName), + ToBytes(About, Flags, (int)UpdateProfileFlags.About)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Account/TLUpdateStatus.cs b/Telegram.Api/TL/Functions/Account/TLUpdateStatus.cs new file mode 100755 index 0000000..9fc93ea --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLUpdateStatus.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Account +{ + public class TLUpdateStatus : TLObject + { + public const string Signature = "#6628562c"; + + public TLBool Offline { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offline.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Account/TLUpdateUserName.cs b/Telegram.Api/TL/Functions/Account/TLUpdateUserName.cs new file mode 100755 index 0000000..63c6b8e --- /dev/null +++ b/Telegram.Api/TL/Functions/Account/TLUpdateUserName.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Account +{ + public class TLUpdateUserName : TLObject + { + public const string Signature = "#3e0bdd7c"; + + public TLString Username { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Username.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLCancelCode.cs b/Telegram.Api/TL/Functions/Auth/TLCancelCode.cs new file mode 100755 index 0000000..d6e30f1 --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLCancelCode.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + public class TLCancelCode : TLObject + { + public const uint Signature = 0x1f040578; + + public TLString PhoneNumber { get; set; } + + public TLString PhoneCodeHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumber.ToBytes(), + PhoneCodeHash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLCheckPhone.cs b/Telegram.Api/TL/Functions/Auth/TLCheckPhone.cs new file mode 100755 index 0000000..9b8a2f5 --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLCheckPhone.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + public class TLCheckPhone : TLObject + { + public const string Signature = "#6fe51dfb"; + + public TLString PhoneNumber { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumber.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLExportAuthorization.cs b/Telegram.Api/TL/Functions/Auth/TLExportAuthorization.cs new file mode 100755 index 0000000..e759ea8 --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLExportAuthorization.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + public class TLExportAuthorization : TLObject + { + public const string Signature = "#e5bfffcd"; + + public TLInt DCId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + DCId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLImportAuthorization.cs b/Telegram.Api/TL/Functions/Auth/TLImportAuthorization.cs new file mode 100755 index 0000000..ec8fcf6 --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLImportAuthorization.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + public class TLImportAuthorization : TLObject + { + public const string Signature = "#e3ef9613"; + + public TLInt Id { get; set; } + + public TLString Bytes { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Bytes.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLLogOut.cs b/Telegram.Api/TL/Functions/Auth/TLLogOut.cs new file mode 100755 index 0000000..046096c --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLLogOut.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + public class TLLogOut : TLObject + { + public const string Signature = "#5717da40"; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLResendCode.cs b/Telegram.Api/TL/Functions/Auth/TLResendCode.cs new file mode 100755 index 0000000..c391f64 --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLResendCode.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + public class TLResendCode : TLObject + { + public const uint Signature = 0x3ef1a9bf; + + public TLString PhoneNumber { get; set; } + + public TLString PhoneCodeHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumber.ToBytes(), + PhoneCodeHash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLResetAuthorizations.cs b/Telegram.Api/TL/Functions/Auth/TLResetAuthorizations.cs new file mode 100755 index 0000000..1a1f123 --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLResetAuthorizations.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + public class TLResetAuthorizations : TLObject + { + public const string Signature = "#9fab0d1a"; + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLSendCall.cs b/Telegram.Api/TL/Functions/Auth/TLSendCall.cs new file mode 100755 index 0000000..d8615d7 --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLSendCall.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + public class TLSendCall : TLObject + { + public const string Signature = "#3c51564"; + + public TLString PhoneNumber { get; set; } + + public TLString PhoneCodeHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumber.ToBytes(), + PhoneCodeHash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLSendCode.cs b/Telegram.Api/TL/Functions/Auth/TLSendCode.cs new file mode 100755 index 0000000..efa463a --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLSendCode.cs @@ -0,0 +1,55 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Auth +{ + [Flags] + public enum SendCode + { + AllowFlashcall = 0x1, // 0 + } + + class TLSendCode : TLObject + { + public const uint Signature = 0x86aef0ec; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLString PhoneNumber { get; set; } + + private TLString _currentNumber; + + public TLString CurrentNumber + { + get { return _currentNumber; } + set { SetField(out _currentNumber, value, ref _flags, (int)SendCode.AllowFlashcall); } + } + + public TLInt ApiId { get; set; } + + public TLString ApiHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + PhoneNumber.ToBytes(), + ToBytes(CurrentNumber, Flags, (int)SendCode.AllowFlashcall), + ApiId.ToBytes(), + ApiHash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLSendInvites.cs b/Telegram.Api/TL/Functions/Auth/TLSendInvites.cs new file mode 100755 index 0000000..8e6b3a9 --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLSendInvites.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + public class TLSendInvites : TLObject + { + public const string Signature = "#771c1d97"; + + public TLVector PhoneNumbers { get; set; } + + public TLString Message { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumbers.ToBytes(), + Message.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLSendSms.cs b/Telegram.Api/TL/Functions/Auth/TLSendSms.cs new file mode 100755 index 0000000..4de42a8 --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLSendSms.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + public class TLSendSms : TLObject + { + public const string Signature = "#da9f3e8"; + + public TLString PhoneNumber { get; set; } + + public TLString PhoneCodeHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumber.ToBytes(), + PhoneCodeHash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLSignIn.cs b/Telegram.Api/TL/Functions/Auth/TLSignIn.cs new file mode 100755 index 0000000..fa5856c --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLSignIn.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + class TLSignIn : TLObject + { + public const string Signature = "#bcd51581"; + + public TLString PhoneNumber { get; set; } + + public TLString PhoneCodeHash { get; set; } + + public TLString PhoneCode { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumber.ToBytes(), + PhoneCodeHash.ToBytes(), + PhoneCode.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Auth/TLSignUp.cs b/Telegram.Api/TL/Functions/Auth/TLSignUp.cs new file mode 100755 index 0000000..0ca4cf4 --- /dev/null +++ b/Telegram.Api/TL/Functions/Auth/TLSignUp.cs @@ -0,0 +1,35 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Auth +{ + public class TLSignUp : TLObject + { + public const string Signature = "#1b067634"; + + public TLString PhoneNumber { get; set; } + + public TLString PhoneCodeHash { get; set; } + + public TLString PhoneCode { get; set; } + + public TLString FirstName { get; set; } + + public TLString LastName { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumber.ToBytes(), + PhoneCodeHash.ToBytes(), + PhoneCode.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLCheckUsername.cs b/Telegram.Api/TL/Functions/Channels/TLCheckUsername.cs new file mode 100755 index 0000000..d8678b7 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLCheckUsername.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLCheckUsername : TLObject + { + public const uint Signature = 0x10e6bd2c; + + public TLInputChannelBase Channel { get; set; } + + public TLString Username { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Username.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLCreateChannel.cs b/Telegram.Api/TL/Functions/Channels/TLCreateChannel.cs new file mode 100755 index 0000000..1383e28 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLCreateChannel.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLCreateChannel : TLObject + { + public const uint Signature = 0xf4893d7f; + + public TLInt Flags { get; set; } + + public TLString Title { get; set; } + + public TLString About { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Title.ToBytes(), + About.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLDeleteChannel.cs b/Telegram.Api/TL/Functions/Channels/TLDeleteChannel.cs new file mode 100755 index 0000000..45a9b17 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLDeleteChannel.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLDeleteChannel : TLObject + { + public const uint Signature = 0xc0111fe3; + + public TLInputChannelBase Channel { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Channels/TLDeleteChannelMessages.cs b/Telegram.Api/TL/Functions/Channels/TLDeleteChannelMessages.cs new file mode 100755 index 0000000..4ac37e4 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLDeleteChannelMessages.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLDeleteChannelMessages : TLObject + { + public const uint Signature = 0x84c1fd4e; + + public TLInputChannelBase Channel { get; set; } + + public TLVector Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLDeleteHistory.cs b/Telegram.Api/TL/Functions/Channels/TLDeleteHistory.cs new file mode 100755 index 0000000..fab2ad4 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLDeleteHistory.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLDeleteHistory : TLObject + { + public const uint Signature = 0xaf369d42; + + public TLInputChannelBase Channel { get; set; } + + public TLInt MaxId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + MaxId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLDeleteUserHistory.cs b/Telegram.Api/TL/Functions/Channels/TLDeleteUserHistory.cs new file mode 100755 index 0000000..35918b3 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLDeleteUserHistory.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLDeleteUserHistory : TLObject + { + public const uint Signature = 0xd10dd71b; + + public TLInputChannelBase Channel { get; set; } + + public TLInputUserBase UserId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + UserId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLEditAbout.cs b/Telegram.Api/TL/Functions/Channels/TLEditAbout.cs new file mode 100755 index 0000000..7fd213b --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLEditAbout.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLEditAbout : TLObject + { + public const uint Signature = 0x13e27f1e; + + public TLInputChannelBase Channel { get; set; } + + public TLString About { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + About.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLEditAdmin.cs b/Telegram.Api/TL/Functions/Channels/TLEditAdmin.cs new file mode 100755 index 0000000..6dace84 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLEditAdmin.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLEditAdmin : TLObject + { + public const uint Signature = 0x20b88214; + + public TLInputChannelBase Channel { get; set; } + + public TLInputUserBase UserId { get; set; } + + public TLChannelAdminRights AdminRights { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + UserId.ToBytes(), + AdminRights.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLEditMessage.cs b/Telegram.Api/TL/Functions/Channels/TLEditMessage.cs new file mode 100755 index 0000000..e3ed097 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLEditMessage.cs @@ -0,0 +1,108 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Channels +{ + [Flags] + public enum EditMessageFlags + { + // 0 + NoWebPage = 0x2, // 1 + ReplyMarkup = 0x4, // 2 + Entities = 0x8, // 3 + + Message = 0x800, // 11 + StopGeoLive = 0x1000, // 12 + GeoPoint = 0x2000, // 13 + Media = 0x4000, // 14 + } + + class TLEditMessage : TLObject + { + public const uint Signature = 0xc000e4c8; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputPeerBase Peer { get; set; } + + public TLInt Id { get; set; } + + private TLString _message; + + public TLString Message + { + get { return _message; } + set { SetField(out _message, value, ref _flags, (int)EditMessageFlags.Message); } + } + + private TLVector _entities; + + public TLVector Entities + { + get { return _entities; } + set { SetField(out _entities, value, ref _flags, (int)EditMessageFlags.Entities); } + } + + private TLInputMediaBase _media; + + public TLInputMediaBase Media + { + get { return _media; } + set { SetField(out _media, value, ref _flags, (int)EditMessageFlags.Media); } + } + + private TLReplyKeyboardBase _replyMarkup; + + public TLReplyKeyboardBase ReplyMarkup + { + get { return _replyMarkup; } + set { SetField(out _replyMarkup, value, ref _flags, (int)EditMessageFlags.ReplyMarkup); } + } + + public bool NoWebPage + { + get { return IsSet(Flags, (int)EditMessageFlags.NoWebPage); } + set { SetUnset(ref _flags, value, (int)EditMessageFlags.NoWebPage); } + } + + private TLInputGeoPointBase _geoPoint; + + public TLInputGeoPointBase GeoPoint + { + get { return _geoPoint; } + set { SetField(out _geoPoint, value, ref _flags, (int)EditMessageFlags.GeoPoint); } + } + + public bool StopGeoLive + { + get { return IsSet(Flags, (int)EditMessageFlags.StopGeoLive); } + set { SetUnset(ref _flags, value, (int)EditMessageFlags.StopGeoLive); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Peer.ToBytes(), + Id.ToBytes(), + ToBytes(Message, Flags, (int)EditMessageFlags.Message), + ToBytes(Media, Flags, (int)EditMessageFlags.Media), + ToBytes(ReplyMarkup, Flags, (int)EditMessageFlags.ReplyMarkup), + ToBytes(Entities, Flags, (int)EditMessageFlags.Entities), + ToBytes(GeoPoint, Flags, (int)EditMessageFlags.GeoPoint)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLEditPhoto.cs b/Telegram.Api/TL/Functions/Channels/TLEditPhoto.cs new file mode 100755 index 0000000..1206332 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLEditPhoto.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + public class TLEditPhoto : TLObject + { + public const uint Signature = 0xf12e57c9; + + public TLInputChannelBase Channel { get; set; } + + public TLInputChatPhotoBase Photo { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Photo.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLEditTitle.cs b/Telegram.Api/TL/Functions/Channels/TLEditTitle.cs new file mode 100755 index 0000000..2e940ab --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLEditTitle.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLEditTitle : TLObject + { + public const uint Signature = 0x566decd0; + + public TLInputChannelBase Channel { get; set; } + + public TLString Title { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Title.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLExportInvite.cs b/Telegram.Api/TL/Functions/Channels/TLExportInvite.cs new file mode 100755 index 0000000..90f4d4e --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLExportInvite.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLExportInvite : TLObject + { + public const uint Signature = 0xc7560885; + + public TLInputChannelBase Channel { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Channels/TLExportMessageLink.cs b/Telegram.Api/TL/Functions/Channels/TLExportMessageLink.cs new file mode 100755 index 0000000..d84a689 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLExportMessageLink.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLExportMessageLink : TLObject + { + public const uint Signature = 0xc846d22d; + + public TLInputChannelBase Channel { get; set; } + + public TLInt Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLGetAdminedPublicChannels.cs b/Telegram.Api/TL/Functions/Channels/TLGetAdminedPublicChannels.cs new file mode 100755 index 0000000..f9b05bc --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLGetAdminedPublicChannels.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLGetAdminedPublicChannels : TLObject + { + public const uint Signature = 0x8d8d82d7; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLGetChannels.cs b/Telegram.Api/TL/Functions/Channels/TLGetChannels.cs new file mode 100755 index 0000000..1f62ac7 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLGetChannels.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLGetChannels : TLObject + { + public const uint Signature = 0xa7f6bbb; + + public TLVector Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLGetDialogs.cs b/Telegram.Api/TL/Functions/Channels/TLGetDialogs.cs new file mode 100755 index 0000000..9883f8e --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLGetDialogs.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLGetDialogs : TLObject + { + public const uint Signature = 0xa9d3d249; + + public TLInt Offset { get; set; } + + public TLInt Limit { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Limit.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLGetFullChannel.cs b/Telegram.Api/TL/Functions/Channels/TLGetFullChannel.cs new file mode 100755 index 0000000..afc9854 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLGetFullChannel.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLGetFullChannel : TLObject + { + public const uint Signature = 0x08736a09; + + public TLInputChannelBase Channel { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLGetImportantHistory.cs b/Telegram.Api/TL/Functions/Channels/TLGetImportantHistory.cs new file mode 100755 index 0000000..f056834 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLGetImportantHistory.cs @@ -0,0 +1,41 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLGetImportantHistory : TLObject + { + public const uint Signature = 0x8f494bb2; + + public TLInputChannelBase Channel { get; set; } + + public TLInt OffsetId { get; set; } + + public TLInt OffsetDate { get; set; } + + public TLInt AddOffset { get; set; } + + public TLInt Limit { get; set; } + + public TLInt MaxId { get; set; } + + public TLInt MinId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + OffsetId.ToBytes(), + OffsetDate.ToBytes(), + AddOffset.ToBytes(), + Limit.ToBytes(), + MaxId.ToBytes(), + MinId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLGetMessageEditData.cs b/Telegram.Api/TL/Functions/Channels/TLGetMessageEditData.cs new file mode 100755 index 0000000..e164018 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLGetMessageEditData.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLGetMessageEditData : TLObject + { + public const uint Signature = 0xfda68d36; + + public TLInputPeerBase Peer { get; set; } + + public TLInt Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLGetMessages.cs b/Telegram.Api/TL/Functions/Channels/TLGetMessages.cs new file mode 100755 index 0000000..90e0800 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLGetMessages.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLGetMessages : TLObject + { + public const uint Signature = 0xad8c9a23; + + public TLInputChannelBase Channel { get; set; } + + public TLVector Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLGetParticipant.cs b/Telegram.Api/TL/Functions/Channels/TLGetParticipant.cs new file mode 100755 index 0000000..493e7a3 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLGetParticipant.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLGetParticipant : TLObject + { + public const uint Signature = 0x546dd7a6; + + public TLInputChannelBase Channel { get; set; } + + public TLInputUserBase UserId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + UserId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLGetParticipants.cs b/Telegram.Api/TL/Functions/Channels/TLGetParticipants.cs new file mode 100755 index 0000000..237cc60 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLGetParticipants.cs @@ -0,0 +1,35 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLGetParticipants : TLObject + { + public const uint Signature = 0x123e05e9; + + public TLInputChannelBase Channel { get; set; } + + public TLChannelParticipantsFilterBase Filter { get; set; } + + public TLInt Offset { get; set; } + + public TLInt Limit { get; set; } + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Filter.ToBytes(), + Offset.ToBytes(), + Limit.ToBytes(), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLInviteToChannel.cs b/Telegram.Api/TL/Functions/Channels/TLInviteToChannel.cs new file mode 100755 index 0000000..4a43095 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLInviteToChannel.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLInviteToChannel : TLObject + { + public const uint Signature = 0x199f3a6c; + + public TLInputChannelBase Channel { get; set; } + + public TLVector Users { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Users.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Channels/TLJoinChannel.cs b/Telegram.Api/TL/Functions/Channels/TLJoinChannel.cs new file mode 100755 index 0000000..b496096 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLJoinChannel.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLJoinChannel : TLObject + { + public const uint Signature = 0x24b524c5; + + public TLInputChannelBase Channel { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLKickFromChannel.cs b/Telegram.Api/TL/Functions/Channels/TLKickFromChannel.cs new file mode 100755 index 0000000..948ddc1 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLKickFromChannel.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLKickFromChannel : TLObject + { + public const uint Signature = 0xa672de14; + + public TLInputChannelBase Channel { get; set; } + + public TLInputUserBase UserId { get; set; } + + public TLBool Kicked { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + UserId.ToBytes(), + Kicked.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Channels/TLLeaveChannel.cs b/Telegram.Api/TL/Functions/Channels/TLLeaveChannel.cs new file mode 100755 index 0000000..770ba46 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLLeaveChannel.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLLeaveChannel : TLObject + { + public const uint Signature = 0xf836aa95; + + public TLInputChannelBase Channel { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Channels/TLReadHistory.cs b/Telegram.Api/TL/Functions/Channels/TLReadHistory.cs new file mode 100755 index 0000000..699c709 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLReadHistory.cs @@ -0,0 +1,58 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; +using Telegram.Api.TL.Functions.Messages; + +namespace Telegram.Api.TL.Functions.Channels +{ + public class TLReadChannelHistory : TLObject, IRandomId + { + public const uint Signature = 0xcc104937; + + public TLInputChannelBase Channel { get; set; } + + public TLInt MaxId { get; set; } + + public TLLong RandomId { get; set; } + + public TLReadChannelHistory() + { + RandomId = TLLong.Random(); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + MaxId.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Channel.ToStream(output); + MaxId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Channel = GetObject(input); + MaxId = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLReadChannelHistory max_id={0} peer=[{1}]", MaxId, Channel); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLReadMessageContents.cs b/Telegram.Api/TL/Functions/Channels/TLReadMessageContents.cs new file mode 100755 index 0000000..74c609e --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLReadMessageContents.cs @@ -0,0 +1,53 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; +using Telegram.Api.TL.Functions.Messages; + +namespace Telegram.Api.TL.Functions.Channels +{ + class TLReadMessageContents : TLObject, IRandomId + { + public const uint Signature = 0xeab5dc38; + + public TLInputChannelBase Channel { get; set; } + + public TLVector Id { get; set; } + + public TLLong RandomId { get; set; } + + public TLReadMessageContents() + { + RandomId = TLLong.Random(); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Id.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Channel.ToStream(output); + Id.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Channel = GetObject(input); + Id = GetObject>(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLReportSpam.cs b/Telegram.Api/TL/Functions/Channels/TLReportSpam.cs new file mode 100755 index 0000000..36e39d5 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLReportSpam.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLReportSpam : TLObject + { + public const uint Signature = 0xfe087810; + + public TLInputChannelBase Channel { get; set; } + + public TLInt UserId { get; set; } + + public TLVector Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + UserId.ToBytes(), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLSetStickers.cs b/Telegram.Api/TL/Functions/Channels/TLSetStickers.cs new file mode 100755 index 0000000..06c5c0b --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLSetStickers.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLSetStickers : TLObject + { + public const uint Signature = 0xea8ca4f9; + + public TLInputChannelBase Channel { get; set; } + + public TLInputStickerSetBase StickerSet { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + StickerSet.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLToggleComments.cs b/Telegram.Api/TL/Functions/Channels/TLToggleComments.cs new file mode 100755 index 0000000..7a3ace0 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLToggleComments.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLToggleComments : TLObject + { + public const uint Signature = 0xaaa29e88; + + public TLInputChannelBase Channel { get; set; } + + public TLBool Enabled { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Enabled.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLToggleInvites.cs b/Telegram.Api/TL/Functions/Channels/TLToggleInvites.cs new file mode 100755 index 0000000..d8f8b6e --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLToggleInvites.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLToggleInvites : TLObject + { + public const uint Signature = 0x49609307; + + public TLInputChannelBase Channel { get; set; } + + public TLBool Enabled { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Enabled.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLTogglePreHistoryHidden.cs b/Telegram.Api/TL/Functions/Channels/TLTogglePreHistoryHidden.cs new file mode 100755 index 0000000..be3902c --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLTogglePreHistoryHidden.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLTogglePreHistoryHidden : TLObject + { + public const uint Signature = 0xeabbb94c; + + public TLInputChannelBase Channel { get; set; } + + public TLBool Enabled { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Enabled.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLToggleSignatures.cs b/Telegram.Api/TL/Functions/Channels/TLToggleSignatures.cs new file mode 100755 index 0000000..751b688 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLToggleSignatures.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLToggleSignatures : TLObject + { + public const uint Signature = 0x1f69b606; + + public TLInputChannelBase Channel { get; set; } + + public TLBool Enabled { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Enabled.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLUpdateChannelUsername.cs b/Telegram.Api/TL/Functions/Channels/TLUpdateChannelUsername.cs new file mode 100755 index 0000000..595d369 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLUpdateChannelUsername.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Channels +{ + class TLUpdateUsername : TLObject + { + public const uint Signature = 0x3514b3de; + + public TLInputChannelBase Channel { get; set; } + + public TLString Username { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Username.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Channels/TLUpdatePinnedMessage.cs b/Telegram.Api/TL/Functions/Channels/TLUpdatePinnedMessage.cs new file mode 100755 index 0000000..ec5dad9 --- /dev/null +++ b/Telegram.Api/TL/Functions/Channels/TLUpdatePinnedMessage.cs @@ -0,0 +1,70 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; +using Telegram.Api.TL.Functions.Messages; + +namespace Telegram.Api.TL.Functions.Channels +{ + [Flags] + public enum UpdatePinnedMessageFlags + { + Silent = 0x1, + } + + class TLUpdatePinnedMessage : TLObject + { + public const uint Signature = 0xa72ded52; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputChannelBase Channel { get; set; } + + public TLInt Id { get; set; } + + public void SetSilent() + { + Set(ref _flags, (int)UpdatePinnedMessageFlags.Silent); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Channel.ToBytes(), + Id.ToBytes() + ); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Channel.ToStream(output); + Id.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Channel = GetObject(input); + Id = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Contacts/TLBlock.cs b/Telegram.Api/TL/Functions/Contacts/TLBlock.cs new file mode 100755 index 0000000..63dae45 --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLBlock.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + public class TLBlock : TLObject + { + public const string Signature = "#332b49fc"; + + public TLInputUserBase Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Contacts/TLDeleteContact.cs b/Telegram.Api/TL/Functions/Contacts/TLDeleteContact.cs new file mode 100755 index 0000000..d605092 --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLDeleteContact.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + public class TLDeleteContact : TLObject + { + public const string Signature = "#8e953744"; + + public TLInputUserBase Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Contacts/TLDeleteContacts.cs b/Telegram.Api/TL/Functions/Contacts/TLDeleteContacts.cs new file mode 100755 index 0000000..d9d22f6 --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLDeleteContacts.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + public class TLDeleteContacts : TLObject + { + public const uint Signature = 0x59ab389e; + + public TLVector Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Contacts/TLGetBlocked.cs b/Telegram.Api/TL/Functions/Contacts/TLGetBlocked.cs new file mode 100755 index 0000000..bbde525 --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLGetBlocked.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + public class TLGetBlocked : TLObject + { + public const string Signature = "#f57c350f"; + + public TLInt Offset { get; set; } + + public TLInt Limit { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Limit.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Contacts/TLGetContacts.cs b/Telegram.Api/TL/Functions/Contacts/TLGetContacts.cs new file mode 100755 index 0000000..0b7d9f2 --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLGetContacts.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + public class TLGetContacts : TLObject + { + public const uint Signature = 0xc023849f; + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Contacts/TLGetStatuses.cs b/Telegram.Api/TL/Functions/Contacts/TLGetStatuses.cs new file mode 100755 index 0000000..37d8af8 --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLGetStatuses.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + public class TLGetStatuses : TLObject + { + public const uint Signature = 0xc4a353ee; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } +} diff --git a/Telegram.Api/TL/Functions/Contacts/TLGetTopPeers.cs b/Telegram.Api/TL/Functions/Contacts/TLGetTopPeers.cs new file mode 100755 index 0000000..83363b0 --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLGetTopPeers.cs @@ -0,0 +1,44 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Contacts +{ + [Flags] + public enum GetTopPeersFlags + { + Correspondents = 0x1, + BotsPM = 0x2, + BotsInline = 0x4, + Groups = 0x400, + Channels = 0x8000, + } + + class TLGetTopPeers : TLObject + { + public const uint Signature = 0xd4982db5; + + public TLInt Flags { get; set; } + + public TLInt Offset { get; set; } + + public TLInt Limit { get; set; } + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Offset.ToBytes(), + Limit.ToBytes(), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Contacts/TLImportContacts.cs b/Telegram.Api/TL/Functions/Contacts/TLImportContacts.cs new file mode 100755 index 0000000..12f0bff --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLImportContacts.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + public class TLImportContacts : TLObject + { + public const uint Signature = 0x2c800be5; + + public TLVector Contacts { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Contacts.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Contacts/TLResetSaved.cs b/Telegram.Api/TL/Functions/Contacts/TLResetSaved.cs new file mode 100755 index 0000000..6368778 --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLResetSaved.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + class TLResetSaved : TLObject + { + public const uint Signature = 0x879537f1; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Contacts/TLResetTopPeerRating.cs b/Telegram.Api/TL/Functions/Contacts/TLResetTopPeerRating.cs new file mode 100755 index 0000000..6d8ddfa --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLResetTopPeerRating.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + class TLResetTopPeerRating : TLObject + { + public const uint Signature = 0x1ae373ac; + + public TLTopPeerCategoryBase Category { get; set; } + + public TLInputPeerBase Peer { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Category.ToBytes(), + Peer.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Contacts/TLResolveUsername.cs b/Telegram.Api/TL/Functions/Contacts/TLResolveUsername.cs new file mode 100755 index 0000000..4eb6bc5 --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLResolveUsername.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + class TLResolveUsername : TLObject + { + public const uint Signature = 0xf93ccba3; + + public TLString Username { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Username.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Contacts/TLSearch.cs b/Telegram.Api/TL/Functions/Contacts/TLSearch.cs new file mode 100755 index 0000000..dfc498a --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLSearch.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + public class TLSearch : TLObject + { + public const string Signature = "#11f812d8"; + + public TLString Q { get; set; } + + public TLInt Limit { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Q.ToBytes(), + Limit.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Contacts/TLUnblock.cs b/Telegram.Api/TL/Functions/Contacts/TLUnblock.cs new file mode 100755 index 0000000..aafdefd --- /dev/null +++ b/Telegram.Api/TL/Functions/Contacts/TLUnblock.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Contacts +{ + public class TLUnblock : TLObject + { + public const string Signature = "#e54100bd"; + + public TLInputUserBase Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/DHKeyExchange/TLReqDHParams.cs b/Telegram.Api/TL/Functions/DHKeyExchange/TLReqDHParams.cs new file mode 100755 index 0000000..d5df91b --- /dev/null +++ b/Telegram.Api/TL/Functions/DHKeyExchange/TLReqDHParams.cs @@ -0,0 +1,38 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.DHKeyExchange +{ + public class TLReqDHParams : TLObject + { + public const string Signature = "#d712e4be"; + + public TLInt128 Nonce { get; set; } + + public TLInt128 ServerNonce { get; set; } + + public TLString P { get; set; } + + public TLString Q { get; set; } + + public TLLong PublicKeyFingerprint { get; set; } + + public TLString EncryptedData { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Nonce.ToBytes(), + ServerNonce.ToBytes(), + P.ToBytes(), + Q.ToBytes(), + PublicKeyFingerprint.ToBytes(), + EncryptedData.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/DHKeyExchange/TLReqPQ.cs b/Telegram.Api/TL/Functions/DHKeyExchange/TLReqPQ.cs new file mode 100755 index 0000000..a770d53 --- /dev/null +++ b/Telegram.Api/TL/Functions/DHKeyExchange/TLReqPQ.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.DHKeyExchange +{ + public class TLReqPQ : TLObject + { + public const string Signature = "#60469778"; + + public TLInt128 Nonce { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Nonce.Value); + } + } +} diff --git a/Telegram.Api/TL/Functions/DHKeyExchange/TLSetClientDHParams.cs b/Telegram.Api/TL/Functions/DHKeyExchange/TLSetClientDHParams.cs new file mode 100755 index 0000000..83b5bb5 --- /dev/null +++ b/Telegram.Api/TL/Functions/DHKeyExchange/TLSetClientDHParams.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.DHKeyExchange +{ + public class TLSetClientDHParams : TLObject + { + public const string Signature = "#f5045f1f"; + + public TLInt128 Nonce { get; set; } + + public TLInt128 ServerNonce { get; set; } + + public TLString EncryptedData { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Nonce.ToBytes(), + ServerNonce.ToBytes(), + EncryptedData.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Help/TLGetAppChangelog.cs b/Telegram.Api/TL/Functions/Help/TLGetAppChangelog.cs new file mode 100755 index 0000000..8136c9f --- /dev/null +++ b/Telegram.Api/TL/Functions/Help/TLGetAppChangelog.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Help +{ + public class TLGetAppChangelog : TLObject + { + public const uint Signature = 0xb921197a; + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Help/TLGetCdnConfig.cs b/Telegram.Api/TL/Functions/Help/TLGetCdnConfig.cs new file mode 100755 index 0000000..83b7e88 --- /dev/null +++ b/Telegram.Api/TL/Functions/Help/TLGetCdnConfig.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Help +{ + public class TLGetCdnConfig : TLObject + { + public const uint Signature = 0x52029342; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } +} diff --git a/Telegram.Api/TL/Functions/Help/TLGetConfig.cs b/Telegram.Api/TL/Functions/Help/TLGetConfig.cs new file mode 100755 index 0000000..6029c43 --- /dev/null +++ b/Telegram.Api/TL/Functions/Help/TLGetConfig.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Help +{ + public class TLGetConfig : TLObject + { + public const uint Signature = 0xc4f9186b; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } +} diff --git a/Telegram.Api/TL/Functions/Help/TLGetInviteText.cs b/Telegram.Api/TL/Functions/Help/TLGetInviteText.cs new file mode 100755 index 0000000..3756086 --- /dev/null +++ b/Telegram.Api/TL/Functions/Help/TLGetInviteText.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Help +{ + public class TLGetInviteText : TLObject + { + public const uint Signature = 0x4d392343; + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Help/TLGetNearestDC.cs b/Telegram.Api/TL/Functions/Help/TLGetNearestDC.cs new file mode 100755 index 0000000..133fb90 --- /dev/null +++ b/Telegram.Api/TL/Functions/Help/TLGetNearestDC.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Help +{ + public class TLGetNearestDC : TLObject + { + public const string Signature = "#1fb33026"; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } +} diff --git a/Telegram.Api/TL/Functions/Help/TLGetRecentMeUrls.cs b/Telegram.Api/TL/Functions/Help/TLGetRecentMeUrls.cs new file mode 100755 index 0000000..2ab49f9 --- /dev/null +++ b/Telegram.Api/TL/Functions/Help/TLGetRecentMeUrls.cs @@ -0,0 +1,18 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Telegram.Api.TL.Functions.Help +{ + class TLGetRecentMeUrls + { + } +} diff --git a/Telegram.Api/TL/Functions/Help/TLGetSupport.cs b/Telegram.Api/TL/Functions/Help/TLGetSupport.cs new file mode 100755 index 0000000..ef3a65d --- /dev/null +++ b/Telegram.Api/TL/Functions/Help/TLGetSupport.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Help +{ + public class TLGetSupport : TLObject + { + public const string Signature = "#9cdf08cd"; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } +} diff --git a/Telegram.Api/TL/Functions/Help/TLGetTermsOfService.cs b/Telegram.Api/TL/Functions/Help/TLGetTermsOfService.cs new file mode 100755 index 0000000..9046554 --- /dev/null +++ b/Telegram.Api/TL/Functions/Help/TLGetTermsOfService.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Help +{ + public class TLGetTermsOfService : TLObject + { + public const uint Signature = 0x8e59b7e7; + + public TLString CountryISO2 { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + CountryISO2.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Help/TLInvokeWithLayerN.cs b/Telegram.Api/TL/Functions/Help/TLInvokeWithLayerN.cs new file mode 100755 index 0000000..f3a90cd --- /dev/null +++ b/Telegram.Api/TL/Functions/Help/TLInvokeWithLayerN.cs @@ -0,0 +1,485 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Help +{ + public class TLInvokeWithLayer : TLObject + { + public const string Signature = "#da9b0d0d"; + + public TLInt Layer { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Layer.ToBytes()); + } + } + + public class TLInvokeWithLayerN : TLObject + { + public const string Signature2 = "#289dd1f6"; + + public const string Signature3 = "#b7475268"; + + public const string Signature4 = "#dea0d430"; + + public const string Signature5 = "#417a57ae"; + + public const string Signature6 = "#3a64d54d"; + + public const string Signature7 = "#a5be56d3"; + + public const string Signature8 = "#e9abd9fd"; + + public const string Signature9 = "#76715a63"; + + public const string Signature10 = "#39620c41"; + + public const string Signature11 = "#a6b88fdf"; + + public const string Signature12 = "#dda60d3c"; + + public const string Signature13 = "#427c8ea2"; + + public const string Signature14 = "#2b9b08fa"; + + public const string Signature15 = "#b4418b64"; + + public const string Signature16 = "#cf5f0987"; + + public const string Signature17 = "#50858a19"; + + public const string Signature18 = "#1c900537"; + + //public const string Signature19 = "#da9b0d0d"; + + public TLObject Data { get; set; } + + public override byte[] ToBytes() + { + byte[] signature; + + if (Constants.SupportedLayer == 85) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 84) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 83) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 82) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 81) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 80) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 79) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 78) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 76) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 75) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 74) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 73) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 72) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 71) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 70) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 69) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 68) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 67) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 66) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 65) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 64) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 63) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 62) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 61) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 60) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 59) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 58) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 57) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 56) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 55) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 54) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 53) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 52) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 51) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 50) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 49) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 48) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 47) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 46) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 45) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 44) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 43) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(Constants.SupportedLayer) }.ToBytes(); + } + + if (Constants.SupportedLayer == 42) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(42) }.ToBytes(); + } + + if (Constants.SupportedLayer == 41) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(41) }.ToBytes(); + } + + if (Constants.SupportedLayer == 40) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(40) }.ToBytes(); + } + + if (Constants.SupportedLayer == 39) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(39) }.ToBytes(); + } + + if (Constants.SupportedLayer == 38) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(38) }.ToBytes(); + } + + if (Constants.SupportedLayer == 37) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(37) }.ToBytes(); + } + + if (Constants.SupportedLayer == 36) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(36) }.ToBytes(); + } + + if (Constants.SupportedLayer == 35) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(35) }.ToBytes(); + } + + if (Constants.SupportedLayer == 34) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(34) }.ToBytes(); + } + + if (Constants.SupportedLayer == 33) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(33) }.ToBytes(); + } + + if (Constants.SupportedLayer == 32) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(32) }.ToBytes(); + } + + if (Constants.SupportedLayer == 31) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(31) }.ToBytes(); + } + + + if (Constants.SupportedLayer == 30) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(30) }.ToBytes(); + } + + if (Constants.SupportedLayer == 29) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(29) }.ToBytes(); + } + + if (Constants.SupportedLayer == 28) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(28) }.ToBytes(); + } + + if (Constants.SupportedLayer == 27) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(27) }.ToBytes(); + } + + if (Constants.SupportedLayer == 26) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(26) }.ToBytes(); + } + + if (Constants.SupportedLayer == 25) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(25) }.ToBytes(); + } + + if (Constants.SupportedLayer == 24) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(24) }.ToBytes(); + } + + if (Constants.SupportedLayer == 23) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(23) }.ToBytes(); + } + + if (Constants.SupportedLayer == 22) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(22) }.ToBytes(); + } + + if (Constants.SupportedLayer == 21) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(21) }.ToBytes(); + } + + if (Constants.SupportedLayer == 20) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(20) }.ToBytes(); + } + + if (Constants.SupportedLayer == 19) + { + signature = new TLInvokeWithLayer { Layer = new TLInt(19) }.ToBytes(); + } + + if (Constants.SupportedLayer == 18) + { + signature = TLUtils.SignatureToBytes(Signature18); + } + + if (Constants.SupportedLayer == 17) + { + signature = TLUtils.SignatureToBytes(Signature17); + } + + if (Constants.SupportedLayer == 16) + { + signature = TLUtils.SignatureToBytes(Signature16); + } + + if (Constants.SupportedLayer == 15) + { + signature = TLUtils.SignatureToBytes(Signature15); + } + + if (Constants.SupportedLayer == 14) + { + signature = TLUtils.SignatureToBytes(Signature14); + } + + if (Constants.SupportedLayer == 13) + { + signature = TLUtils.SignatureToBytes(Signature13); + } + + if (Constants.SupportedLayer == 12) + { + signature = TLUtils.SignatureToBytes(Signature12); + } + + if (Constants.SupportedLayer == 11) + { + signature = TLUtils.SignatureToBytes(Signature11); + } + + if (Constants.SupportedLayer == 1) + { + signature = new byte[] { }; + } + if (Constants.SupportedLayer == 2) + { + signature = TLUtils.SignatureToBytes(Signature2); + } + if (Constants.SupportedLayer == 3) + { + signature = TLUtils.SignatureToBytes(Signature3); + } + if (Constants.SupportedLayer == 4) + { + signature = TLUtils.SignatureToBytes(Signature4); + } + if (Constants.SupportedLayer == 5) + { + signature = TLUtils.SignatureToBytes(Signature5); + } + if (Constants.SupportedLayer == 6) + { + signature = TLUtils.SignatureToBytes(Signature6); + } + if (Constants.SupportedLayer == 7) + { + signature = TLUtils.SignatureToBytes(Signature7); + } + if (Constants.SupportedLayer == 8) + { + signature = TLUtils.SignatureToBytes(Signature8); + } + if (Constants.SupportedLayer == 9) + { + signature = TLUtils.SignatureToBytes(Signature9); + } + if (Constants.SupportedLayer == 10) + { + signature = TLUtils.SignatureToBytes(Signature10); + } + + + + return TLUtils.Combine(signature, Data.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Help/TLInvokeWithoutUpdates.cs b/Telegram.Api/TL/Functions/Help/TLInvokeWithoutUpdates.cs new file mode 100755 index 0000000..364a2e1 --- /dev/null +++ b/Telegram.Api/TL/Functions/Help/TLInvokeWithoutUpdates.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Help +{ + public class TLInvokeWithoutUpdates : TLObject + { + public const uint Signature = 0xbf9459b7; + + public TLObject Object { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Object.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Langpack/TLGetDifference.cs b/Telegram.Api/TL/Functions/Langpack/TLGetDifference.cs new file mode 100755 index 0000000..4d8b25a --- /dev/null +++ b/Telegram.Api/TL/Functions/Langpack/TLGetDifference.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Langpack +{ + class TLGetDifference : TLObject + { + public const uint Signature = 0xb2e4d7d; + + public TLInt FromVersion { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + FromVersion.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Langpack/TLGetLangPack.cs b/Telegram.Api/TL/Functions/Langpack/TLGetLangPack.cs new file mode 100755 index 0000000..1d8c4fe --- /dev/null +++ b/Telegram.Api/TL/Functions/Langpack/TLGetLangPack.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Langpack +{ + class TLGetLangPack : TLObject + { + public const uint Signature = 0x9ab5c58e; + + public TLString LangCode { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + LangCode.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Langpack/TLGetLanguages.cs b/Telegram.Api/TL/Functions/Langpack/TLGetLanguages.cs new file mode 100755 index 0000000..46186a9 --- /dev/null +++ b/Telegram.Api/TL/Functions/Langpack/TLGetLanguages.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Langpack +{ + class TLGetLanguages : TLObject + { + public const uint Signature = 0x800fd57d; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Langpack/TLGetStrings.cs b/Telegram.Api/TL/Functions/Langpack/TLGetStrings.cs new file mode 100755 index 0000000..528c59f --- /dev/null +++ b/Telegram.Api/TL/Functions/Langpack/TLGetStrings.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Langpack +{ + class TLGetStrings : TLObject + { + public const uint Signature = 0x2e1ee318; + + public TLString LangCode { get; set; } + + public TLVector Keys { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + LangCode.ToBytes(), + Keys.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLAcceptEncryption.cs b/Telegram.Api/TL/Functions/Messages/TLAcceptEncryption.cs new file mode 100755 index 0000000..12b8eb2 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLAcceptEncryption.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLAcceptEncryption : TLObject + { + public const string Signature = "#3dbc0415"; + + public TLInputEncryptedChat Peer { get; set; } + + public TLString GB { get; set; } + + public TLLong KeyFingerprint { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + GB.ToBytes(), + KeyFingerprint.ToBytes()); + } + } + } \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Messages/TLAddChatUser.cs b/Telegram.Api/TL/Functions/Messages/TLAddChatUser.cs new file mode 100755 index 0000000..9b79d94 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLAddChatUser.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLAddChatUser : TLObject + { + public const string Signature = "#f9a0aa09"; + + public TLInt ChatId { get; set; } + + public TLInputUserBase UserId { get; set; } + + public TLInt FwdLimit { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes(), + UserId.ToBytes(), + FwdLimit.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLBotGetCallbackAnswer.cs b/Telegram.Api/TL/Functions/Messages/TLBotGetCallbackAnswer.cs new file mode 100755 index 0000000..6cf3f64 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLBotGetCallbackAnswer.cs @@ -0,0 +1,58 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum GetBotCallbackAnswerFlags + { + Data = 0x1, + Game = 0x2, + } + + class TLGetBotCallbackAnswer : TLObject + { + public const uint Signature = 0x810a9fec; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputPeerBase Peer { get; set; } + + public TLInt MessageId { get; set; } + + private TLString _data; + + public TLString Data + { + get { return _data; } + set { SetField(out _data, value, ref _flags, (int) GetBotCallbackAnswerFlags.Data); } + } + + public void SetGame() + { + Set(ref _flags, (int) GetBotCallbackAnswerFlags.Game); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Peer.ToBytes(), + MessageId.ToBytes(), + ToBytes(Data, Flags, (int) GetBotCallbackAnswerFlags.Data)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLCheckChatInvite.cs b/Telegram.Api/TL/Functions/Messages/TLCheckChatInvite.cs new file mode 100755 index 0000000..09a181e --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLCheckChatInvite.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLCheckChatInvite : TLObject + { + public const uint Signature = 0x3eadb1bb; + + public TLString Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLClearRecentStickers.cs b/Telegram.Api/TL/Functions/Messages/TLClearRecentStickers.cs new file mode 100755 index 0000000..2884058 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLClearRecentStickers.cs @@ -0,0 +1,41 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum ClearRecentStickersFlags + { + Attached = 0x1 + } + + class TLClearRecentStickers : TLObject + { + public const uint Signature = 0x8999602d; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public void SetAttached() + { + Set(ref _flags, (int) ClearRecentStickersFlags.Attached); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + Flags.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLCreateChat.cs b/Telegram.Api/TL/Functions/Messages/TLCreateChat.cs new file mode 100755 index 0000000..234b8fe --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLCreateChat.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLCreateChat : TLObject + { + public const string Signature = "#419d9aee"; + + public TLVector Users { get; set; } + + public TLString Title { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Users.ToBytes(), + Title.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLDeactivateChat.cs b/Telegram.Api/TL/Functions/Messages/TLDeactivateChat.cs new file mode 100755 index 0000000..05e2fc1 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLDeactivateChat.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLDeactivateChat : TLObject + { + public const uint Signature = 0x626f0b41; + + public TLInt ChatId { get; set; } + + public TLBool Enabled { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes(), + Enabled.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Messages/TLDeleteChatUser.cs b/Telegram.Api/TL/Functions/Messages/TLDeleteChatUser.cs new file mode 100755 index 0000000..2a9df21 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLDeleteChatUser.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLDeleteChatUser : TLObject + { + public const string Signature = "#e0611f16"; + + public TLInt ChatId { get; set; } + + public TLInputUserBase UserId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes(), + UserId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLDeleteHistory.cs b/Telegram.Api/TL/Functions/Messages/TLDeleteHistory.cs new file mode 100755 index 0000000..9b0a804 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLDeleteHistory.cs @@ -0,0 +1,48 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum DeleteHistoryFlags + { + JustClear = 0x1, + } + + class TLDeleteHistory : TLObject + { + public const uint Signature = 0x1c015b09; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputPeerBase Peer { get; set; } + + public TLInt MaxId { get; set; } + + public void SetJustClear() + { + Set(ref _flags, (int) DeleteHistoryFlags.JustClear); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Peer.ToBytes(), + MaxId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLDeleteMessages.cs b/Telegram.Api/TL/Functions/Messages/TLDeleteMessages.cs new file mode 100755 index 0000000..6ed3b78 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLDeleteMessages.cs @@ -0,0 +1,46 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum DeleteMessagesFlags + { + Revoke = 0x1, // 0 + } + + class TLDeleteMessages : TLObject + { + public const uint Signature = 0xe58e95d2; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLVector Id { get; set; } + + public bool Revoke + { + get { return IsSet(Flags, (int) DeleteMessagesFlags.Revoke); } + set { SetUnset(ref _flags, value, (int) DeleteMessagesFlags.Revoke); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLDiscardEncryption.cs b/Telegram.Api/TL/Functions/Messages/TLDiscardEncryption.cs new file mode 100755 index 0000000..d491ad4 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLDiscardEncryption.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLDiscardEncryption : TLObject + { + public const string Signature = "#edd923c5"; + + public TLInt ChatId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Messages/TLEditChatAdmin.cs b/Telegram.Api/TL/Functions/Messages/TLEditChatAdmin.cs new file mode 100755 index 0000000..9195ed3 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLEditChatAdmin.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLEditChatAdmin : TLObject + { + public const uint Signature = 0xa9e69f2e; + + public TLInt ChatId { get; set; } + + public TLInputUserBase UserId { get; set; } + + public TLBool IsAdmin { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes(), + UserId.ToBytes(), + IsAdmin.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLEditChatPhoto.cs b/Telegram.Api/TL/Functions/Messages/TLEditChatPhoto.cs new file mode 100755 index 0000000..38d719d --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLEditChatPhoto.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLEditChatPhoto : TLObject + { + public const string Signature = "#ca4c79d8"; + + public TLInt ChatId { get; set; } + + public TLInputChatPhotoBase Photo { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes(), + Photo.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLEditChatTitle.cs b/Telegram.Api/TL/Functions/Messages/TLEditChatTitle.cs new file mode 100755 index 0000000..1d38d8e --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLEditChatTitle.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLEditChatTitle : TLObject + { + public const string Signature = "#dc452855"; + + public TLInt ChatId { get; set; } + + public TLString Title { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes(), + Title.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLEditGeoLive.cs b/Telegram.Api/TL/Functions/Messages/TLEditGeoLive.cs new file mode 100755 index 0000000..fd642d5 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLEditGeoLive.cs @@ -0,0 +1,52 @@ +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum EditGeoLiveFlags + { + Stop = 0x1, + GeoPoint = 0x2 + } + + public class TLEditGeoLive : TLObject + { + public const uint Signature = 0x9a92304e; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Stop + { + get { return IsSet(_flags, (int) EditGeoLiveFlags.Stop); } + set { SetUnset(ref _flags, value, (int) EditGeoLiveFlags.Stop); } + } + + public TLInputPeerBase Peer { get; set; } + + public TLInt Id { get; set; } + + private TLInputGeoPointBase _geoPoint; + + public TLInputGeoPointBase GeoPoint + { + get { return _geoPoint; } + set { SetField(out _geoPoint, value, ref _flags, (int) EditGeoLiveFlags.GeoPoint); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Peer.ToBytes(), + Id.ToBytes(), + ToBytes(GeoPoint, _flags, (int) EditGeoLiveFlags.GeoPoint)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLExportChatInvite.cs b/Telegram.Api/TL/Functions/Messages/TLExportChatInvite.cs new file mode 100755 index 0000000..da51acb --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLExportChatInvite.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLExportChatInvite : TLObject + { + public const string Signature = "#7d885289"; + + public TLInt ChatId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLFaveSticker.cs b/Telegram.Api/TL/Functions/Messages/TLFaveSticker.cs new file mode 100755 index 0000000..f260d0b --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLFaveSticker.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLFaveSticker : TLObject + { + public const uint Signature = 0xb9ffc55b; + + public TLInputDocumentBase Id { get; set; } + + public TLBool Unfave { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Unfave.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLForwardMessage.cs b/Telegram.Api/TL/Functions/Messages/TLForwardMessage.cs new file mode 100755 index 0000000..c021b70 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLForwardMessage.cs @@ -0,0 +1,50 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLForwardMessage : TLObject, IRandomId + { + public const uint Signature = 0x3f3f4f2; + + public TLInputPeerBase Peer { get; set; } + + public TLInt Id { get; set; } + + public TLLong RandomId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Id.ToBytes(), + RandomId.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Peer.ToStream(output); + Id.ToStream(output); + RandomId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + Id = GetObject(input); + RandomId = GetObject(input); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Messages/TLForwardMessages.cs b/Telegram.Api/TL/Functions/Messages/TLForwardMessages.cs new file mode 100755 index 0000000..ea201f2 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLForwardMessages.cs @@ -0,0 +1,109 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLForwardMessages : TLObject, IRandomId + { + public const uint Signature = 0x708e0195; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputPeerBase FromPeer { get; set; } + + public TLInputPeerBase ToPeer { get; set; } + + public TLVector Id { get; set; } + + public TLVector RandomIds { get; set; } + + public TLLong RandomId + { + get + { + if (RandomIds != null && RandomIds.Count > 0) + { + return RandomIds[0]; + } + + return new TLLong(0); + } + } + + public void SetChannelMessage() + { + Set(ref _flags, (int) SendFlags.Channel); + } + + public void SetSilent() + { + Set(ref _flags, (int) SendFlags.Silent); + } + + public void SetWithMyScore() + { + Set(ref _flags, (int) SendFlags.WithMyScore); + } + + public void SetGrouped() + { + Set(ref _flags, (int)SendFlags.Grouped); + } + + public static string ForwardMessagesFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (SendFlags) flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + FromPeer.ToBytes(), + Id.ToBytes(), + RandomIds.ToBytes(), + ToPeer.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + FromPeer.ToStream(output); + Id.ToStream(output); + RandomIds.ToStream(output); + ToPeer.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + + Flags = GetObject(input); + FromPeer = GetObject(input); + Id = GetObject>(input); + RandomIds = GetObject>(input); + ToPeer = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetAllDrafts.cs b/Telegram.Api/TL/Functions/Messages/TLGetAllDrafts.cs new file mode 100755 index 0000000..7d6b80f --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetAllDrafts.cs @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetAllDrafts : TLObject + { + public const uint Signature = 0x6a3f8d65; + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetAllStickers.cs b/Telegram.Api/TL/Functions/Messages/TLGetAllStickers.cs new file mode 100755 index 0000000..2c71148 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetAllStickers.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetAllStickers : TLObject + { + public const uint Signature = 0x1c9618b1; + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetArchivedStickers.cs b/Telegram.Api/TL/Functions/Messages/TLGetArchivedStickers.cs new file mode 100755 index 0000000..da4d282 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetArchivedStickers.cs @@ -0,0 +1,48 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum GetArchivedStickersFlags + { + Masks = 0x1, + } + + class TLGetArchivedStickers : TLObject + { + public const uint Signature = 0x57f17692; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLLong OffsetId { get; set; } + + public TLInt Limit { get; set; } + + public void SetMasks() + { + Set(ref _flags, (int) GetArchivedStickersFlags.Masks); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + OffsetId.ToBytes(), + Limit.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetAttachedStickers.cs b/Telegram.Api/TL/Functions/Messages/TLGetAttachedStickers.cs new file mode 100755 index 0000000..d482f3e --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetAttachedStickers.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLGetAttachedStickers : TLObject + { + public const uint Signature = 0xcc5b67cc; + + public TLInputStickeredMediaBase Media { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Media.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetChats.cs b/Telegram.Api/TL/Functions/Messages/TLGetChats.cs new file mode 100755 index 0000000..83839d5 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetChats.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLGetChats : TLObject + { + public const string Signature = "#3c6aa187"; + + public TLVector Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetCommonChats.cs b/Telegram.Api/TL/Functions/Messages/TLGetCommonChats.cs new file mode 100755 index 0000000..676d4c7 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetCommonChats.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetCommonChats : TLObject + { + public const uint Signature = 0xd0a48c4; + + public TLInputUserBase User { get; set; } + + public TLInt MaxId { get; set; } + + public TLInt Limit { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + User.ToBytes(), + MaxId.ToBytes(), + Limit.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetDHConfig.cs b/Telegram.Api/TL/Functions/Messages/TLGetDHConfig.cs new file mode 100755 index 0000000..3994f49 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetDHConfig.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLGetDHConfig : TLObject + { + public const string Signature = "#26cf8950"; + + public TLInt Version { get; set; } + + public TLInt RandomLength { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Version.ToBytes(), + RandomLength.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetDialogs.cs b/Telegram.Api/TL/Functions/Messages/TLGetDialogs.cs new file mode 100755 index 0000000..a689eb2 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetDialogs.cs @@ -0,0 +1,68 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum GetDialogsFlags + { + ExcludePinned = 0x1, + FeedId = 0x2, + } + + class TLGetDialogs : TLObject + { + public const uint Signature = 0xb098aee6; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool ExcludePinned + { + get { return IsSet(Flags, (int) GetDialogsFlags.ExcludePinned); } + set { SetUnset(ref _flags, value, (int) GetDialogsFlags.ExcludePinned); } + } + + //private TLInt _feedId; + + //public TLInt FeedId + //{ + // get { return _feedId; } + // set { SetField(out _feedId, value, ref _flags, (int)GetDialogsFlags.FeedId); } + //} + + public TLInt OffsetDate { get; set; } + + public TLInt OffsetId { get; set; } + + public TLInputPeerBase OffsetPeer { get; set; } + + public TLInt Limit { get; set; } + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + //ToBytes(FeedId, Flags, (int)GetDialogsFlags.FeedId), + OffsetDate.ToBytes(), + OffsetId.ToBytes(), + OffsetPeer.ToBytes(), + Limit.ToBytes(), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetDocumentByHash.cs b/Telegram.Api/TL/Functions/Messages/TLGetDocumentByHash.cs new file mode 100755 index 0000000..d77f992 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetDocumentByHash.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetDocumentByHash : TLObject + { + public const uint Signature = 0x338e2464; + + public TLString Sha256 { get; set; } + + public TLInt Size { get; set; } + + public TLString MimeType { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Sha256.ToBytes(), + Size.ToBytes(), + MimeType.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetFavedStickers.cs b/Telegram.Api/TL/Functions/Messages/TLGetFavedStickers.cs new file mode 100755 index 0000000..bfc48fb --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetFavedStickers.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetFavedStickers : TLObject + { + public const uint Signature = 0x21ce0b0e; + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetFeaturedStickers.cs b/Telegram.Api/TL/Functions/Messages/TLGetFeaturedStickers.cs new file mode 100755 index 0000000..bfb99e9 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetFeaturedStickers.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetFeaturedStickers : TLObject + { + public const uint Signature = 0x2dacca4f; + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetFullChat.cs b/Telegram.Api/TL/Functions/Messages/TLGetFullChat.cs new file mode 100755 index 0000000..0befa03 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetFullChat.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetFullChat : TLObject + { + public const string Signature = "#3b831c66"; + + public TLInt ChatId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetHistory.cs b/Telegram.Api/TL/Functions/Messages/TLGetHistory.cs new file mode 100755 index 0000000..8839895 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetHistory.cs @@ -0,0 +1,44 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLGetHistory : TLObject + { + public const uint Signature = 0xdcbb8260; + + public TLInputPeerBase Peer { get; set; } + + public TLInt OffsetId { get; set; } + + public TLInt OffsetDate { get; set; } + + public TLInt AddOffset { get; set; } + + public TLInt Limit { get; set; } + + public TLInt MaxId { get; set; } + + public TLInt MinId { get; set; } + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + OffsetId.ToBytes(), + OffsetDate.ToBytes(), + AddOffset.ToBytes(), + Limit.ToBytes(), + MaxId.ToBytes(), + MinId.ToBytes(), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetInlineBotResults.cs b/Telegram.Api/TL/Functions/Messages/TLGetInlineBotResults.cs new file mode 100755 index 0000000..3f3c6dd --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetInlineBotResults.cs @@ -0,0 +1,58 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum GetInlineBotResultsFlags + { + GeoPoint = 0x1 + } + + class TLGetInlineBotResults : TLObject + { + public const uint Signature = 0x514e999d; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputUserBase Bot { get; set; } + + public TLInputPeerBase Peer { get; set; } + + private TLInputGeoPointBase _geoPoint; + + public TLInputGeoPointBase GeoPoint + { + get { return _geoPoint; } + set { SetField(out _geoPoint, value, ref _flags, (int) GetInlineBotResultsFlags.GeoPoint); } + } + + public TLString Query { get; set; } + + public TLString Offset { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Bot.ToBytes(), + Peer.ToBytes(), + ToBytes(GeoPoint, Flags, (int) GetInlineBotResultsFlags.GeoPoint), + Query.ToBytes(), + Offset.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetMaskStickers.cs b/Telegram.Api/TL/Functions/Messages/TLGetMaskStickers.cs new file mode 100755 index 0000000..d2f2e31 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetMaskStickers.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetMaskStickers : TLObject + { + public const uint Signature = 0x65b8c79f; + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetMessages.cs b/Telegram.Api/TL/Functions/Messages/TLGetMessages.cs new file mode 100755 index 0000000..0a05ac8 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetMessages.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLGetMessages : TLObject + { + public const uint Signature = 0x63c66506; + + public TLVector Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetPeerDialogs.cs b/Telegram.Api/TL/Functions/Messages/TLGetPeerDialogs.cs new file mode 100755 index 0000000..f25bf5f --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetPeerDialogs.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetPeerDialogs : TLObject + { + public const uint Signature = 0x2d9776b9; + + public TLVector Peers { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peers.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetPeerSettings.cs b/Telegram.Api/TL/Functions/Messages/TLGetPeerSettings.cs new file mode 100755 index 0000000..b4ba75e --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetPeerSettings.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetPeerSettings : TLObject + { + public const uint Signature = 0x3672e09c; + + public TLInputPeerBase Peer { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetPinnedDialogs.cs b/Telegram.Api/TL/Functions/Messages/TLGetPinnedDialogs.cs new file mode 100755 index 0000000..56c06f8 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetPinnedDialogs.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLGetPinnedDialogs : TLObject + { + public const uint Signature = 0xe254d64e; + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetRecentLocations.cs b/Telegram.Api/TL/Functions/Messages/TLGetRecentLocations.cs new file mode 100755 index 0000000..96a5a55 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetRecentLocations.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetRecentLocations : TLObject + { + public const uint Signature = 0xbbc45b09; + + public TLInputPeerBase Peer { get; set; } + + public TLInt Limit { get; set; } + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Limit.ToBytes(), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetRecentStickers.cs b/Telegram.Api/TL/Functions/Messages/TLGetRecentStickers.cs new file mode 100755 index 0000000..7afafc8 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetRecentStickers.cs @@ -0,0 +1,45 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum GetRecentStickersFlags + { + Attached = 0x1 + } + + class TLGetRecentStickers : TLObject + { + public const uint Signature = 0x5ea192c9; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt Hash { get; set; } + + public void SetAttached() + { + Set(ref _flags, (int) GetRecentStickersFlags.Attached); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetSavedGifs.cs b/Telegram.Api/TL/Functions/Messages/TLGetSavedGifs.cs new file mode 100755 index 0000000..f4b3c18 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetSavedGifs.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetSavedGifs : TLObject + { + public const uint Signature = 0x83bf3d52; + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetStickerSet.cs b/Telegram.Api/TL/Functions/Messages/TLGetStickerSet.cs new file mode 100755 index 0000000..f261c13 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetStickerSet.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetStickerSet : TLObject + { + public const string Signature = "#2619a90e"; + + public TLInputStickerSetBase Stickerset { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Stickerset.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetStickers.cs b/Telegram.Api/TL/Functions/Messages/TLGetStickers.cs new file mode 100755 index 0000000..f65e340 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetStickers.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetStickers : TLObject + { + public const uint Signature = 0x43d4f2c; + + public TLString Emoticon { get; set; } + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Emoticon.ToBytes(), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetUnreadMentions.cs b/Telegram.Api/TL/Functions/Messages/TLGetUnreadMentions.cs new file mode 100755 index 0000000..d190b6b --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetUnreadMentions.cs @@ -0,0 +1,38 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetUnreadMentions : TLObject + { + public const uint Signature = 0x46578472; + + public TLInputPeerBase Peer { get; set; } + + public TLInt OffsetId { get; set; } + + public TLInt AddOffset { get; set; } + + public TLInt Limit { get; set; } + + public TLInt MaxId { get; set; } + + public TLInt MinId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + OffsetId.ToBytes(), + AddOffset.ToBytes(), + Limit.ToBytes(), + MaxId.ToBytes(), + MinId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetUnusedStickers.cs b/Telegram.Api/TL/Functions/Messages/TLGetUnusedStickers.cs new file mode 100755 index 0000000..251d669 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetUnusedStickers.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLGetUnusedStickers : TLObject + { + public const uint Signature = 0xa978d356; + + public TLInt Limit { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Limit.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetWebPage.cs b/Telegram.Api/TL/Functions/Messages/TLGetWebPage.cs new file mode 100755 index 0000000..7f14bba --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetWebPage.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLGetWebPage : TLObject + { + public const uint Signature = 0x32ca8f91; + + public TLString Url { get; set; } + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Url.ToBytes(), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLGetWebPagePreview.cs b/Telegram.Api/TL/Functions/Messages/TLGetWebPagePreview.cs new file mode 100755 index 0000000..e1649b0 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLGetWebPagePreview.cs @@ -0,0 +1,41 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLGetWebPagePreview : TLObject + { + public const uint Signature = 0x8b68b0cc; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLString Message { get; set; } + + private TLVector _entities; + + public TLVector Entities + { + get { return _entities; } + set { SetField(out _entities, value, ref _flags, (int)SendFlags.Entities); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Message.ToBytes(), + ToBytes(Entities, Flags, (int)SendFlags.Entities)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLHideReportSpam.cs b/Telegram.Api/TL/Functions/Messages/TLHideReportSpam.cs new file mode 100755 index 0000000..4167a35 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLHideReportSpam.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLHideReportSpam : TLObject + { + public const uint Signature = 0xa8f1709b; + + public TLInputPeerBase Peer { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLImportChatInvite.cs b/Telegram.Api/TL/Functions/Messages/TLImportChatInvite.cs new file mode 100755 index 0000000..378c654 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLImportChatInvite.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLImportChatInvite : TLObject + { + public const string Signature = "#6c50051c"; + + public TLString Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLInstallStickerSet.cs b/Telegram.Api/TL/Functions/Messages/TLInstallStickerSet.cs new file mode 100755 index 0000000..56d0215 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLInstallStickerSet.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLInstallStickerSet : TLObject + { + public const uint Signature = 0xc78fe460; + + public TLInputStickerSetBase Stickerset { get; set; } + + public TLBool Archived { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Stickerset.ToBytes(), + Archived.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLMigrateChat.cs b/Telegram.Api/TL/Functions/Messages/TLMigrateChat.cs new file mode 100755 index 0000000..7cd8779 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLMigrateChat.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLMigrateChat : TLObject + { + public const uint Signature = 0x15a3b8e3; + + public TLInt ChatId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLReadEncryptedHistory.cs b/Telegram.Api/TL/Functions/Messages/TLReadEncryptedHistory.cs new file mode 100755 index 0000000..2aa2f06 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLReadEncryptedHistory.cs @@ -0,0 +1,52 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLReadEncryptedHistory : TLObject, IRandomId + { + public const uint Signature = 0x7f4b690a; + + public TLInputEncryptedChat Peer { get; set; } + + public TLInt MaxDate { get; set; } + + public TLLong RandomId { get; set; } + + public TLReadEncryptedHistory() + { + RandomId = TLLong.Random(); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + MaxDate.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Peer.ToStream(output); + MaxDate.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + MaxDate = GetObject(input); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Messages/TLReadFeaturedStickers.cs b/Telegram.Api/TL/Functions/Messages/TLReadFeaturedStickers.cs new file mode 100755 index 0000000..da7b77a --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLReadFeaturedStickers.cs @@ -0,0 +1,39 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + class TLReadFeaturedStickers : TLObject + { + public const uint Signature = 0x5b118126; + + public TLVector Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject>(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLReadHistory.cs b/Telegram.Api/TL/Functions/Messages/TLReadHistory.cs new file mode 100755 index 0000000..ac772a7 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLReadHistory.cs @@ -0,0 +1,57 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLReadHistory : TLObject, IRandomId + { + public const uint Signature = 0xe306d3a; + + public TLInputPeerBase Peer { get; set; } + + public TLInt MaxId { get; set; } + + public TLLong RandomId { get; set; } + + public TLReadHistory() + { + RandomId = TLLong.Random(); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + MaxId.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Peer.ToStream(output); + MaxId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + MaxId = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLReadHistory max_id={0} peer=[{1}]", MaxId, Peer); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLReadMentions.cs b/Telegram.Api/TL/Functions/Messages/TLReadMentions.cs new file mode 100755 index 0000000..10c07ca --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLReadMentions.cs @@ -0,0 +1,52 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + class TLReadMentions : TLObject, IRandomId + { + public const uint Signature = 0xf0189d3; + + public TLInputPeerBase Peer { get; set; } + + public TLLong RandomId { get; set; } + + public TLReadMentions() + { + RandomId = TLLong.Random(); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Peer.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLReadMentions peer=[{0}]", Peer); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLReadMessageContents.cs b/Telegram.Api/TL/Functions/Messages/TLReadMessageContents.cs new file mode 100755 index 0000000..ad6efb1 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLReadMessageContents.cs @@ -0,0 +1,47 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + class TLReadMessageContents : TLObject, IRandomId + { + public const uint Signature = 0x36a73f77; + + public TLVector Id { get; set; } + + public TLLong RandomId { get; set; } + + public TLReadMessageContents() + { + RandomId = TLLong.Random(); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject>(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLReceivedMessages.cs b/Telegram.Api/TL/Functions/Messages/TLReceivedMessages.cs new file mode 100755 index 0000000..5bdc37f --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLReceivedMessages.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLReceivedMessages : TLObject + { + public const string Signature = "#5a954c0"; + + public TLInt MaxId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + MaxId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLReceivedQueue.cs b/Telegram.Api/TL/Functions/Messages/TLReceivedQueue.cs new file mode 100755 index 0000000..025ea8a --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLReceivedQueue.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLReceivedQueue : TLObject + { + public const string Signature = "#55a5bb66"; + + public TLLong MaxQts { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + MaxQts.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Messages/TLReorderPinnedDialogs.cs b/Telegram.Api/TL/Functions/Messages/TLReorderPinnedDialogs.cs new file mode 100755 index 0000000..2972fe5 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLReorderPinnedDialogs.cs @@ -0,0 +1,45 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum ReorderPinnedDialogsFlags + { + Force = 0x1, + } + + class TLReorderPinnedDialogs : TLObject + { + public const uint Signature = 0x5b51d63f; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLVector Order { get; set; } + + public void SetForce() + { + Set(ref _flags, (int) ReorderPinnedDialogsFlags.Force); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Order.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLReorderStickerSets.cs b/Telegram.Api/TL/Functions/Messages/TLReorderStickerSets.cs new file mode 100755 index 0000000..7e625de --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLReorderStickerSets.cs @@ -0,0 +1,45 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum ReorderStickerSetsFlags + { + Masks = 0x1, + } + + class TLReorderStickerSets : TLObject + { + public const uint Signature = 0x78337739; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLVector Order { get; set; } + + public void SetMasks() + { + Set(ref _flags, (int) ReorderStickerSetsFlags.Masks); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Order.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLReportSpam.cs b/Telegram.Api/TL/Functions/Messages/TLReportSpam.cs new file mode 100755 index 0000000..39e7f69 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLReportSpam.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLReportSpam : TLObject + { + public const uint Signature = 0xcf1592db; + + public TLInputPeerBase Peer { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLRequestEncryption.cs b/Telegram.Api/TL/Functions/Messages/TLRequestEncryption.cs new file mode 100755 index 0000000..cc1e9b4 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLRequestEncryption.cs @@ -0,0 +1,47 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.Helpers; +using Telegram.Logs; + +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLRequestEncryption : TLObject + { + public const string Signature = "#f64daf43"; + + public TLInputUserBase UserId { get; set; } + + public TLInt RandomId { get; set; } + + public TLString G_A { get; set; } + + public override byte[] ToBytes() + { + byte[] bytes = null; + try + { + bytes = TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + UserId.ToBytes(), + RandomId.ToBytes(), + G_A.ToBytes()); + } + catch (Exception ex) + { + var str = "TLRequestEncryption.ToBytes error user_id=" + UserId + " random_id=" + RandomId + " g_a=" + G_A; + + Log.Write(str); + + Execute.ShowDebugMessage(ex.ToString()); + } + + return bytes; + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLRestoreMessages.cs b/Telegram.Api/TL/Functions/Messages/TLRestoreMessages.cs new file mode 100755 index 0000000..1f09566 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLRestoreMessages.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLRestoreMessages : TLObject + { + public const string Signature = "#395f9d7e"; + + public TLVector Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLSaveDraft.cs b/Telegram.Api/TL/Functions/Messages/TLSaveDraft.cs new file mode 100755 index 0000000..303e208 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSaveDraft.cs @@ -0,0 +1,83 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLSaveDraft : TLObject + { + public const uint Signature = 0xbc39e14b; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLInt _replyToMsgId; + + public TLInt ReplyToMsgId + { + get { return _replyToMsgId; } + set { SetField(out _replyToMsgId, value, ref _flags, (int) SendFlags.ReplyToMsgId); } + } + + public TLInputPeerBase Peer { get; set; } + + public TLString Message { get; set; } + + private TLVector _entities; + + public TLVector Entities + { + get { return _entities; } + set { SetField(out _entities, value, ref _flags, (int) SendFlags.Entities); } + } + + public void DisableWebPagePreview() + { + Set(ref _flags, (int)SendFlags.NoWebpage); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(ReplyToMsgId, Flags, (int)SendFlags.ReplyToMsgId), + Peer.ToBytes(), + Message.ToBytes(), + ToBytes(Entities, Flags, (int) SendFlags.Entities)); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + ToStream(output, ReplyToMsgId, Flags, (int) SendFlags.ReplyToMsgId); + Peer.ToStream(output); + Message.ToStream(output); + ToStream(output, Entities, Flags, (int) SendFlags.Entities); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + ReplyToMsgId = GetObject(Flags, (int) SendFlags.ReplyToMsgId, null, input); + Peer = GetObject(input); + Message = GetObject(input); + Entities = GetObject>(Flags, (int) SendFlags.Entities, null, input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLSaveGif.cs b/Telegram.Api/TL/Functions/Messages/TLSaveGif.cs new file mode 100755 index 0000000..9f4f63b --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSaveGif.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLSaveGif : TLObject + { + public const uint Signature = 0x327a30cb; + + public TLInputDocumentBase Id { get; set; } + + public TLBool Unsave { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Unsave.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLSearch.cs b/Telegram.Api/TL/Functions/Messages/TLSearch.cs new file mode 100755 index 0000000..200a00d --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSearch.cs @@ -0,0 +1,105 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum SearchFlags + { + FromId = 0x1, + } + + public class TLSearch : TLObject + { + public const uint Signature = 0x8614ef68; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputPeerBase Peer { get; set; } + + public TLString Query { get; set; } + + private TLInputUserBase _fromId; + + public TLInputUserBase FromId + { + get { return _fromId; } + set { SetField(out _fromId, value, ref _flags, (int) SearchFlags.FromId); } + } + + public TLInputMessagesFilterBase Filter { get; set; } + + public TLInt MinDate { get; set; } + + public TLInt MaxDate { get; set; } + + public TLInt OffsetId { get; set; } + + public TLInt AddOffset { get; set; } + + public TLInt Limit { get; set; } + + public TLInt MaxId { get; set; } + + public TLInt MinId { get; set; } + + public TLInt Hash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Peer.ToBytes(), + Query.ToBytes(), + ToBytes(FromId, Flags, (int)SearchFlags.FromId), + Filter.ToBytes(), + MinDate.ToBytes(), + MaxDate.ToBytes(), + OffsetId.ToBytes(), + AddOffset.ToBytes(), + Limit.ToBytes(), + MaxId.ToBytes(), + MinId.ToBytes(), + Hash.ToBytes()); + } + } + + public class TLSearchGlobal : TLObject + { + public const uint Signature = 0x9e3cacb0; + + public TLString Query { get; set; } + + public TLInt OffsetDate { get; set; } + + public TLInputPeerBase OffsetPeer { get; set; } + + public TLInt OffsetId { get; set; } + + public TLInt Limit { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Query.ToBytes(), + OffsetDate.ToBytes(), + OffsetPeer.ToBytes(), + OffsetId.ToBytes(), + Limit.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLSearchGifs.cs b/Telegram.Api/TL/Functions/Messages/TLSearchGifs.cs new file mode 100755 index 0000000..e305f5d --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSearchGifs.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLSearchGifs : TLObject + { + public const uint Signature = 0xbf9a776b; + + public TLString Q { get; set; } + + public TLInt Offset { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Q.ToBytes(), + Offset.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLSendBroadcast.cs b/Telegram.Api/TL/Functions/Messages/TLSendBroadcast.cs new file mode 100755 index 0000000..d718939 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSendBroadcast.cs @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLSendBroadcast : TLObject + { + public const string Signature = "#bf73f4da"; + + public TLVector Contacts { get; set; } + + public TLVector RandomId { get; set; } + + public TLString Message { get; set; } + + public TLInputMediaBase Media { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Contacts.ToBytes(), + RandomId.ToBytes(), + Message.ToBytes(), + Media.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLSendEncrypted.cs b/Telegram.Api/TL/Functions/Messages/TLSendEncrypted.cs new file mode 100755 index 0000000..9d63c12 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSendEncrypted.cs @@ -0,0 +1,50 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLSendEncrypted : TLObject, IRandomId + { + public const uint Signature = 0xa9776773; + + public TLInputEncryptedChat Peer { get; set; } + + public TLLong RandomId { get; set; } + + public TLString Data { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + RandomId.ToBytes(), + Data.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Peer.ToStream(output); + RandomId.ToStream(output); + Data.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + RandomId = GetObject(input); + Data = GetObject(input); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Messages/TLSendEncryptedFile.cs b/Telegram.Api/TL/Functions/Messages/TLSendEncryptedFile.cs new file mode 100755 index 0000000..b60725d --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSendEncryptedFile.cs @@ -0,0 +1,55 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLSendEncryptedFile : TLObject, IRandomId + { + public const uint Signature = 0x9a901b66; + + public TLInputEncryptedChat Peer { get; set; } + + public TLLong RandomId { get; set; } + + public TLString Data { get; set; } + + public TLInputEncryptedFileBase File { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + RandomId.ToBytes(), + Data.ToBytes(), + File.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Peer.ToStream(output); + RandomId.ToStream(output); + Data.ToStream(output); + File.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + RandomId = GetObject(input); + Data = GetObject(input); + File = GetObject(input); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Messages/TLSendEncryptedService.cs b/Telegram.Api/TL/Functions/Messages/TLSendEncryptedService.cs new file mode 100755 index 0000000..800d1bf --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSendEncryptedService.cs @@ -0,0 +1,50 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLSendEncryptedService : TLObject, IRandomId + { + public const uint Signature = 0x32d439a4; + + public TLInputEncryptedChat Peer { get; set; } + + public TLLong RandomId { get; set; } + + public TLString Data { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + RandomId.ToBytes(), + Data.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Peer.ToStream(output); + RandomId.ToStream(output); + Data.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + RandomId = GetObject(input); + Data = GetObject(input); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Messages/TLSendInlineBotResult.cs b/Telegram.Api/TL/Functions/Messages/TLSendInlineBotResult.cs new file mode 100755 index 0000000..3b5026f --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSendInlineBotResult.cs @@ -0,0 +1,106 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + class TLSendInlineBotResult : TLObject, IRandomId + { + public const uint Signature = 0xb16e06fe; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputPeerBase Peer { get; set; } + + private TLInt _replyToMsgId; + + public TLInt ReplyToMsgId + { + get { return _replyToMsgId; } + set + { + if (value != null && value.Value > 0) + { + Set(ref _flags, (int)SendFlags.ReplyToMsgId); + _replyToMsgId = value; + } + else + { + Unset(ref _flags, (int)SendFlags.ReplyToMsgId); + } + } + } + + public TLLong RandomId { get; set; } + + public TLLong QueryId { get; set; } + + public TLString Id { get; set; } + + public void SetChannelMessage() + { + Set(ref _flags, (int)SendFlags.Channel); + } + + public void SetSilent() + { + Set(ref _flags, (int)SendFlags.Silent); + } + + public void SetClearDraft() + { + Set(ref _flags, (int)SendFlags.ClearDraft); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Peer.ToBytes(), + ToBytes(ReplyToMsgId, Flags, (int)SendFlags.ReplyToMsgId), + RandomId.ToBytes(), + QueryId.ToBytes(), + Id.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Peer.ToStream(output); + ToStream(output, ReplyToMsgId, Flags, (int)SendFlags.ReplyToMsgId); + RandomId.ToStream(output); + QueryId.ToStream(output); + Id.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Peer = GetObject(input); + if (IsSet(Flags, (int)SendFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(input); + } + RandomId = GetObject(input); + QueryId = GetObject(input); + Id = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLSendMedia.cs b/Telegram.Api/TL/Functions/Messages/TLSendMedia.cs new file mode 100755 index 0000000..335d9c9 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSendMedia.cs @@ -0,0 +1,120 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLSendMedia : TLObject, IRandomId + { + public const uint Signature = 0xb8d1262b; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputPeerBase Peer { get; set; } + + private TLInt _replyToMsgId; + + public TLInt ReplyToMsgId + { + get { return _replyToMsgId; } + set + { + var replyToMsgId = value != null && value.Value > 0 ? value : null; + + SetField(out _replyToMsgId, replyToMsgId, ref _flags, (int)SendFlags.ReplyToMsgId); + } + } + + public TLInputMediaBase Media { get; set; } + + public TLString Message { get; set; } + + public TLLong RandomId { get; set; } + + private TLReplyKeyboardBase _replyMarkup; + + public TLReplyKeyboardBase ReplyMarkup + { + get { return _replyMarkup; } + set { SetField(out _replyMarkup, value, ref _flags, (int)SendFlags.ReplyMarkup); } + } + + protected TLVector _entities; + + public TLVector Entities + { + get { return _entities; } + set { SetField(out _entities, value, ref _flags, (int)SendFlags.Entities); } + } + + public void SetChannelMessage() + { + Set(ref _flags, (int)SendFlags.Channel); + } + + public void SetSilent() + { + Set(ref _flags, (int)SendFlags.Silent); + } + + public void SetClearDraft() + { + Set(ref _flags, (int)SendFlags.ClearDraft); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Peer.ToBytes(), + ToBytes(ReplyToMsgId, Flags, (int)SendFlags.ReplyToMsgId), + Media.ToBytes(), + Message.ToBytes(), + RandomId.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)SendFlags.ReplyMarkup), + ToBytes(Entities, Flags, (int)SendFlags.Entities) + ); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Peer.ToStream(output); + ToStream(output, ReplyToMsgId, Flags, (int)SendFlags.ReplyToMsgId); + Media.ToStream(output); + Message.ToStream(output); + RandomId.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)SendFlags.ReplyMarkup); + ToStream(output, Entities, Flags, (int)SendFlags.Entities); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Peer = GetObject(input); + ReplyToMsgId = GetObject(Flags, (int)SendFlags.ReplyToMsgId, null, input); + Media = GetObject(input); + Message = GetObject(input); + RandomId = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)SendFlags.ReplyMarkup, null, input); + Entities = GetObject>(Flags, (int)SendFlags.Entities, null, input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLSendMessage.cs b/Telegram.Api/TL/Functions/Messages/TLSendMessage.cs new file mode 100755 index 0000000..28934a8 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSendMessage.cs @@ -0,0 +1,136 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum SendFlags + { + ReplyToMsgId = 0x1, + NoWebpage = 0x2, + ReplyMarkup = 0x4, + Entities = 0x8, + Channel = 0x10, + Silent = 0x20, + Background = 0x40, + ClearDraft = 0x80, + WithMyScore = 0x100, + Grouped = 0x200 + } + + public interface IRandomId + { + TLLong RandomId { get; } + } + + public class TLSendMessage : TLObject, IRandomId + { + public const uint Signature = 0xfa88427a; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputPeerBase Peer { get; set; } + + private TLInt _replyToMsgId; + + public TLInt ReplyToMsgId + { + get { return _replyToMsgId; } + set { SetField(out _replyToMsgId, value, ref _flags, (int) SendFlags.ReplyToMsgId); } + } + + public TLString Message { get; set; } + + public TLLong RandomId { get; set; } + + private TLReplyKeyboardBase _replyMarkup; + + public TLReplyKeyboardBase ReplyMarkup + { + get { return _replyMarkup; } + set { SetField(out _replyMarkup, value, ref _flags, (int) SendFlags.ReplyMarkup); } + } + + private TLVector _entities; + + public TLVector Entities + { + get { return _entities; } + set { SetField(out _entities, value, ref _flags, (int) SendFlags.Entities); } + } + + public void NoWebpage() + { + Set(ref _flags, (int) SendFlags.NoWebpage); + } + + public void SetChannelMessage() + { + Set(ref _flags, (int) SendFlags.Channel); + } + + public void SetSilent() + { + Set(ref _flags, (int) SendFlags.Silent); + } + + public void ClearDraft() + { + Set(ref _flags, (int) SendFlags.ClearDraft); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Peer.ToBytes(), + ToBytes(ReplyToMsgId, Flags, (int) SendFlags.ReplyToMsgId), + Message.ToBytes(), + RandomId.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int) SendFlags.ReplyMarkup), + ToBytes(Entities, Flags, (int) SendFlags.Entities) + ); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Peer.ToStream(output); + ToStream(output, ReplyToMsgId, Flags, (int) SendFlags.ReplyToMsgId); + Message.ToStream(output); + RandomId.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int) SendFlags.ReplyMarkup); + ToStream(output, Entities, Flags, (int) SendFlags.Entities); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Peer = GetObject(input); + ReplyToMsgId = GetObject(Flags, (int) SendFlags.ReplyToMsgId, null, input); + Message = GetObject(input); + RandomId = GetObject(input); + ReplyMarkup = GetObject(Flags, (int) SendFlags.ReplyMarkup, null, input); + Entities = GetObject>(Flags, (int) SendFlags.Entities, null, input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLSendMultiMedia.cs b/Telegram.Api/TL/Functions/Messages/TLSendMultiMedia.cs new file mode 100755 index 0000000..2636f8a --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSendMultiMedia.cs @@ -0,0 +1,111 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLSendMultiMedia : TLObject, IRandomId + { + public const uint Signature = 0x2095512f; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputPeerBase Peer { get; set; } + + private TLInt _replyToMsgId; + + public TLInt ReplyToMsgId + { + get { return _replyToMsgId; } + set + { + if (value != null && value.Value > 0) + { + SetField(out _replyToMsgId, value, ref _flags, (int) SendFlags.ReplyToMsgId); + } + } + } + + public TLVector MultiMedia { get; set; } + + public TLLong RandomId + { + get + { + long hash = 19; + + unchecked + { + if (MultiMedia != null) + { + for (var i = 0; i < MultiMedia.Count; i++) + { + hash = hash * 31 + MultiMedia[i].RandomId.Value; + } + } + } + + return new TLLong(hash); + } + set { } + } + + public void SetSilent() + { + Set(ref _flags, (int)SendFlags.Silent); + } + + public void SetBackground() + { + Set(ref _flags, (int)SendFlags.Background); + } + + public void SetClearDraft() + { + Set(ref _flags, (int)SendFlags.ClearDraft); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Peer.ToBytes(), + ToBytes(ReplyToMsgId, Flags, (int)SendFlags.ReplyToMsgId), + MultiMedia.ToBytes() + ); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Peer.ToStream(output); + ToStream(output, ReplyToMsgId, Flags, (int)SendFlags.ReplyToMsgId); + MultiMedia.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Peer = GetObject(input); + ReplyToMsgId = GetObject(Flags, (int) SendFlags.ReplyToMsgId, null, input); + MultiMedia = GetObject>(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLSetBotCallbackAnswer.cs b/Telegram.Api/TL/Functions/Messages/TLSetBotCallbackAnswer.cs new file mode 100755 index 0000000..3d2e751 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSetBotCallbackAnswer.cs @@ -0,0 +1,55 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum SetBotCallbackAnswerFlags + { + Message = 0x1, // 0 + Alert = 0x2, // 1 + } + + class TLSetBotCallbackAnswer : TLObject + { + public const uint Signature = 0xa6e94f04; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt QueryId { get; set; } + + private TLString _message; + + public TLString Message + { + get { return _message; } + set { SetField(out _message, value, ref _flags, (int) SetBotCallbackAnswerFlags.Message); } + } + + public void SetAlert() + { + Set(ref _flags, (int) SetBotCallbackAnswerFlags.Alert); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + QueryId.ToBytes(), + Message.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLSetEncryptedTyping.cs b/Telegram.Api/TL/Functions/Messages/TLSetEncryptedTyping.cs new file mode 100755 index 0000000..ecea560 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSetEncryptedTyping.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLSetEncryptedTyping : TLObject + { + public const string Signature = "#791451ed"; + + public TLInputEncryptedChat Peer { get; set; } + + public TLBool Typing { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Typing.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/Functions/Messages/TLSetInlineBotResults.cs b/Telegram.Api/TL/Functions/Messages/TLSetInlineBotResults.cs new file mode 100755 index 0000000..01743fd --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSetInlineBotResults.cs @@ -0,0 +1,83 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum SetInlineBotResultsFlags + { + Gallery = 0x1, // 0 + Private = 0x2, // 1 + NextOffset = 0x4, // 2 + SwitchPM = 0x8, // 3 + } + + class TLSetInlineBotResults : TLObject + { + public const uint Signature = 0xeb5ea206; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLBool _gallery; + + public TLBool Gallery + { + get { return _gallery; } + set { SetField(out _gallery, value, ref _flags, (int) SetInlineBotResultsFlags.Gallery); } + } + + private TLBool _private; + + public TLBool Private + { + get { return _private; } + set { SetField(out _private, value, ref _flags, (int) SetInlineBotResultsFlags.Private); } + } + + public TLLong QueryId { get; set; } + + public TLVector Results { get; set; } + + public TLInt CacheTime { get; set; } + + private TLString _nextOffset; + + public TLString NextOffset + { + get { return _nextOffset; } + set { SetField(out _nextOffset, value, ref _flags, (int)SetInlineBotResultsFlags.NextOffset); } + } + + private TLInlineBotSwitchPM _switchPM; + + public TLInlineBotSwitchPM SwitchPM + { + get { return _switchPM; } + set { SetField(out _switchPM, value, ref _flags, (int)SetInlineBotResultsFlags.NextOffset); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + QueryId.ToBytes(), + Results.ToBytes(), + CacheTime.ToBytes(), + ToBytes(NextOffset, Flags, (int) SetInlineBotResultsFlags.NextOffset), + ToBytes(SwitchPM, Flags, (int) SetInlineBotResultsFlags.SwitchPM)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLSetTyping.cs b/Telegram.Api/TL/Functions/Messages/TLSetTyping.cs new file mode 100755 index 0000000..a6be74b --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLSetTyping.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLSetTyping : TLObject + { + public const string Signature = "#a3825e50"; + + public TLInputPeerBase Peer { get; set; } + + public TLSendMessageActionBase Action { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Action.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLStartBot.cs b/Telegram.Api/TL/Functions/Messages/TLStartBot.cs new file mode 100755 index 0000000..e6f4444 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLStartBot.cs @@ -0,0 +1,56 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + public class TLStartBot : TLObject, IRandomId + { + public const uint Signature = 0xe6df7378; + + public TLInputUserBase Bot { get; set; } + + public TLInputPeerBase Peer { get; set; } + + public TLLong RandomId { get; set; } + + public TLString StartParam { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Bot.ToBytes(), + Peer.ToBytes(), + RandomId.ToBytes(), + StartParam.ToBytes() + ); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Bot.ToStream(output); + Peer.ToStream(output); + RandomId.ToStream(output); + StartParam.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Bot = GetObject(input); + Peer = GetObject(input); + RandomId = GetObject(input); + StartParam = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLToggleChatAdmins.cs b/Telegram.Api/TL/Functions/Messages/TLToggleChatAdmins.cs new file mode 100755 index 0000000..007956f --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLToggleChatAdmins.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLToggleChatAdmins : TLObject + { + public const uint Signature = 0xec8bd9e1; + + public TLInt ChatId { get; set; } + + public TLBool Enabled { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes(), + Enabled.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLToggleDialogPin.cs b/Telegram.Api/TL/Functions/Messages/TLToggleDialogPin.cs new file mode 100755 index 0000000..2fb8b93 --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLToggleDialogPin.cs @@ -0,0 +1,46 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Messages +{ + [Flags] + public enum ToggleDialogPinFlags + { + Pinned = 0x1, + } + + class TLToggleDialogPin : TLObject + { + public const uint Signature = 0x3289be6a; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Pinned + { + get { return IsSet(Flags, (int)ToggleDialogPinFlags.Pinned); } + set { SetUnset(ref _flags, value, (int)ToggleDialogPinFlags.Pinned); } + } + + public TLInputPeerBase Peer { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Peer.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLUninstallStickerSet.cs b/Telegram.Api/TL/Functions/Messages/TLUninstallStickerSet.cs new file mode 100755 index 0000000..9223e8b --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLUninstallStickerSet.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Messages +{ + class TLUninstallStickerSet : TLObject + { + public const uint Signature = 0xf96e55de; + + public TLInputStickerSetBase Stickerset { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Stickerset.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Messages/TLUploadMedia.cs b/Telegram.Api/TL/Functions/Messages/TLUploadMedia.cs new file mode 100755 index 0000000..6779bdb --- /dev/null +++ b/Telegram.Api/TL/Functions/Messages/TLUploadMedia.cs @@ -0,0 +1,46 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL.Functions.Messages +{ + class TLUploadMedia : TLObject + { + public const uint Signature = 0x519bc2b1; + + public TLInputPeerBase Peer { get; set; } + + public TLInputMediaBase Media { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Media.ToBytes() + ); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Peer.ToStream(output); + Media.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + Media = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/Functions/Payments/TLClearSavedInfo.cs b/Telegram.Api/TL/Functions/Payments/TLClearSavedInfo.cs new file mode 100755 index 0000000..4ab3f24 --- /dev/null +++ b/Telegram.Api/TL/Functions/Payments/TLClearSavedInfo.cs @@ -0,0 +1,50 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Payments +{ + [Flags] + public enum ClearSavedInfoFlags + { + Credentials = 0x1, + Info = 0x2 + } + + class TLClearSavedInfo : TLObject + { + public const uint Signature = 0xd83d70c1; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Credentials + { + get { return IsSet(Flags, (int) ClearSavedInfoFlags.Credentials); } + set { SetUnset(ref _flags, value, (int) ClearSavedInfoFlags.Credentials); } + } + + public bool Info + { + get { return IsSet(Flags, (int) ClearSavedInfoFlags.Info); } + set { SetUnset(ref _flags, value, (int) ClearSavedInfoFlags.Info); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Payments/TLGetPaymentForm.cs b/Telegram.Api/TL/Functions/Payments/TLGetPaymentForm.cs new file mode 100755 index 0000000..aaf0b24 --- /dev/null +++ b/Telegram.Api/TL/Functions/Payments/TLGetPaymentForm.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Payments +{ + class TLGetPaymentForm : TLObject + { + public const uint Signature = 0x99f09745; + + public TLInt MsgId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + MsgId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Payments/TLGetPaymentReceipt.cs b/Telegram.Api/TL/Functions/Payments/TLGetPaymentReceipt.cs new file mode 100755 index 0000000..66ea8d2 --- /dev/null +++ b/Telegram.Api/TL/Functions/Payments/TLGetPaymentReceipt.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Payments +{ + class TLGetPaymentReceipt : TLObject + { + public const uint Signature = 0xa092a980; + + public TLInt MsgId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + MsgId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Payments/TLGetSavedInfo.cs b/Telegram.Api/TL/Functions/Payments/TLGetSavedInfo.cs new file mode 100755 index 0000000..71cee8b --- /dev/null +++ b/Telegram.Api/TL/Functions/Payments/TLGetSavedInfo.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Payments +{ + class TLGetSavedInfo : TLObject + { + public const uint Signature = 0x227d824b; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } +} diff --git a/Telegram.Api/TL/Functions/Payments/TLSendPaymentForm.cs b/Telegram.Api/TL/Functions/Payments/TLSendPaymentForm.cs new file mode 100755 index 0000000..d5a3025 --- /dev/null +++ b/Telegram.Api/TL/Functions/Payments/TLSendPaymentForm.cs @@ -0,0 +1,62 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Payments +{ + [Flags] + public enum SendPaymentFormFlags + { + RequestedInfoId = 0x1, + ShippingOptionId = 0x2 + } + + class TLSendPaymentForm : TLObject + { + public const uint Signature = 0x2b8879b3; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt MsgId { get; set; } + + private TLString _requestedInfoId; + + public TLString RequestedInfoId + { + get { return _requestedInfoId; } + set { SetField(out _requestedInfoId, value, ref _flags, (int) SendPaymentFormFlags.RequestedInfoId); } + } + + private TLString _shippingOptionId; + + public TLString ShippingOptionId + { + get { return _shippingOptionId; } + set { SetField(out _shippingOptionId, value, ref _flags, (int)SendPaymentFormFlags.ShippingOptionId); } + } + + public TLInputPaymentCredentialsBase Credentials { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + MsgId.ToBytes(), + ToBytes(RequestedInfoId, Flags, (int) SendPaymentFormFlags.RequestedInfoId), + ToBytes(ShippingOptionId, Flags, (int) SendPaymentFormFlags.ShippingOptionId), + Credentials.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Payments/TLValidateRequestedInfo.cs b/Telegram.Api/TL/Functions/Payments/TLValidateRequestedInfo.cs new file mode 100755 index 0000000..dda01af --- /dev/null +++ b/Telegram.Api/TL/Functions/Payments/TLValidateRequestedInfo.cs @@ -0,0 +1,60 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL.Functions.Payments +{ + [Flags] + public enum ValidateRequestedInfoFlags + { + Save = 0x1 + } + + class TLValidateRequestedInfo : TLObject + { + public const uint Signature = 0x770a8e74; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Save + { + get { return IsSet(Flags, (int) ValidateRequestedInfoFlags.Save); } + set { SetUnset(ref _flags, value, (int) ValidateRequestedInfoFlags.Save); } + } + + public TLInt MsgId { get; set; } + + public TLPaymentRequestedInfo Info { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + MsgId = GetObject(bytes, ref position); + Info = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + MsgId.ToBytes(), + Info.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Phone/TLAcceptCall.cs b/Telegram.Api/TL/Functions/Phone/TLAcceptCall.cs new file mode 100755 index 0000000..2d30478 --- /dev/null +++ b/Telegram.Api/TL/Functions/Phone/TLAcceptCall.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Phone +{ + class TLAcceptCall : TLObject + { + public const uint Signature = 0x3bd2b4a0; + + public TLInputPhoneCall Peer { get; set; } + + public TLString GB { get; set; } + + public TLPhoneCallProtocol Protocol { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + GB.ToBytes(), + Protocol.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Phone/TLConfirmCall.cs b/Telegram.Api/TL/Functions/Phone/TLConfirmCall.cs new file mode 100755 index 0000000..91ed6a9 --- /dev/null +++ b/Telegram.Api/TL/Functions/Phone/TLConfirmCall.cs @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Phone +{ + class TLConfirmCall : TLObject + { + public const uint Signature = 0x2efe1722; + + public TLInputPhoneCall Peer { get; set; } + + public TLString GA { get; set; } + + public TLLong KeyFingerprint { get; set; } + + public TLPhoneCallProtocol Protocol { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + GA.ToBytes(), + KeyFingerprint.ToBytes(), + Protocol.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Phone/TLDiscardCall.cs b/Telegram.Api/TL/Functions/Phone/TLDiscardCall.cs new file mode 100755 index 0000000..843c0fd --- /dev/null +++ b/Telegram.Api/TL/Functions/Phone/TLDiscardCall.cs @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Phone +{ + public class TLDiscardCall : TLObject + { + public const uint Signature = 0x78d413a6; + + public TLInputPhoneCall Peer { get; set; } + + public TLInt Duration { get; set; } + + public TLPhoneCallDiscardReasonBase Reason { get; set; } + + public TLLong ConnectionId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Duration.ToBytes(), + Reason.ToBytes(), + ConnectionId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Phone/TLGetCallConfig.cs b/Telegram.Api/TL/Functions/Phone/TLGetCallConfig.cs new file mode 100755 index 0000000..7b7438b --- /dev/null +++ b/Telegram.Api/TL/Functions/Phone/TLGetCallConfig.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Phone +{ + class TLGetCallConfig : TLObject + { + public const uint Signature = 0x55451fa9; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/Functions/Phone/TLReceivedCall.cs b/Telegram.Api/TL/Functions/Phone/TLReceivedCall.cs new file mode 100755 index 0000000..707d248 --- /dev/null +++ b/Telegram.Api/TL/Functions/Phone/TLReceivedCall.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Phone +{ + public class TLReceivedCall : TLObject + { + public const uint Signature = 0x17d54f61; + + public TLInputPhoneCall Peer { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Phone/TLRequestCall.cs b/Telegram.Api/TL/Functions/Phone/TLRequestCall.cs new file mode 100755 index 0000000..ca08e01 --- /dev/null +++ b/Telegram.Api/TL/Functions/Phone/TLRequestCall.cs @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Phone +{ + class TLRequestCall : TLObject + { + public const uint Signature = 0x5b95b3d4; + + public TLInputUserBase UserId { get; set; } + + public TLInt RandomId { get; set; } + + public TLString GAHash { get; set; } + + public TLPhoneCallProtocol Protocol { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + UserId.ToBytes(), + RandomId.ToBytes(), + GAHash.ToBytes(), + Protocol.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Phone/TLSaveCallDebug.cs b/Telegram.Api/TL/Functions/Phone/TLSaveCallDebug.cs new file mode 100755 index 0000000..a753956 --- /dev/null +++ b/Telegram.Api/TL/Functions/Phone/TLSaveCallDebug.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Phone +{ + class TLSaveCallDebug : TLObject + { + public const uint Signature = 0x277add7e; + + public TLInputPhoneCall Peer { get; set; } + + public TLDataJSON Debug { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Debug.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Phone/TLSetCallRating.cs b/Telegram.Api/TL/Functions/Phone/TLSetCallRating.cs new file mode 100755 index 0000000..8657579 --- /dev/null +++ b/Telegram.Api/TL/Functions/Phone/TLSetCallRating.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Phone +{ + class TLSetCallRating : TLObject + { + public const uint Signature = 0x1c536a34; + + public TLInputPhoneCall Peer { get; set; } + + public TLInt Rating { get; set; } + + public TLString Comment { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Rating.ToBytes(), + Comment.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Photos/TLGetUserPhotos.cs b/Telegram.Api/TL/Functions/Photos/TLGetUserPhotos.cs new file mode 100755 index 0000000..ae8b19d --- /dev/null +++ b/Telegram.Api/TL/Functions/Photos/TLGetUserPhotos.cs @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Photos +{ + class TLGetUserPhotos : TLObject + { + public const string Signature = "#91cd32a8"; + + public TLInputUserBase UserId { get; set; } + + public TLInt Offset { get; set; } + + public TLLong MaxId { get; set; } + + public TLInt Limit { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + UserId.ToBytes(), + Offset.ToBytes(), + MaxId.ToBytes(), + Limit.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Photos/TLUpdateProfilePhoto.cs b/Telegram.Api/TL/Functions/Photos/TLUpdateProfilePhoto.cs new file mode 100755 index 0000000..cf8690c --- /dev/null +++ b/Telegram.Api/TL/Functions/Photos/TLUpdateProfilePhoto.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Photos +{ + public class TLUpdateProfilePhoto : TLObject + { + public const uint Signature = 0xf0bb5152; + + public TLInputPhotoBase Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Photos/TLUploadProfilePhoto.cs b/Telegram.Api/TL/Functions/Photos/TLUploadProfilePhoto.cs new file mode 100755 index 0000000..7ac4519 --- /dev/null +++ b/Telegram.Api/TL/Functions/Photos/TLUploadProfilePhoto.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Photos +{ + public class TLUploadProfilePhoto : TLObject + { + public const uint Signature = 0x4f32c098; + + public TLInputFile File { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Stuff/TLGetFutureSalts.cs b/Telegram.Api/TL/Functions/Stuff/TLGetFutureSalts.cs new file mode 100755 index 0000000..33baa9e --- /dev/null +++ b/Telegram.Api/TL/Functions/Stuff/TLGetFutureSalts.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Stuff +{ + public class TLGetFutureSalts : TLObject + { + public const string Signature = "#b921bd04"; + + public TLInt Num { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Num.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Stuff/TLHttpWait.cs b/Telegram.Api/TL/Functions/Stuff/TLHttpWait.cs new file mode 100755 index 0000000..a4fd3f3 --- /dev/null +++ b/Telegram.Api/TL/Functions/Stuff/TLHttpWait.cs @@ -0,0 +1,44 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Stuff +{ + public class TLHttpWait : TLObject + { + public const string Signature = "#9299359f"; + + /// + /// Сервер ждет max_delay миллисекунд, после чего отправляет все сообщения, что у него накопились для клиента. + /// По умолчанию 0. Второй по приоритету. + /// + public TLInt MaxDelay { get; set; } + + /// + /// После получения последнего сообщения для данной сессии сервер ждет еще wait_after миллисекунд, на тот случай, если появятся еще сообщения. + /// Если ни одного дополнительного сообщения не появляется, отправляется результат (контейнер со всеми сообщениями); + /// если же появляются еще сообщения, отсчет wait_after начинается заново. + /// По умолчанию 0. Последний по приоритету. + /// + public TLInt WaitAfter { get; set; } + + /// + /// Сервер ждет не более max_wait миллисекунд, пока такое сообщение не появится. + /// Если сообщений так и не появилось, отправляется пустой контейнер. + /// По умолчанию 25000. Главный по приоритету. + /// + public TLInt MaxWait { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + MaxDelay.ToBytes(), + WaitAfter.ToBytes(), + MaxWait.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Stuff/TLMessageAcknowledgments.cs b/Telegram.Api/TL/Functions/Stuff/TLMessageAcknowledgments.cs new file mode 100755 index 0000000..db7fe77 --- /dev/null +++ b/Telegram.Api/TL/Functions/Stuff/TLMessageAcknowledgments.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Stuff +{ + class TLMessageAcknowledgments : TLObject + { + public const string Signature = "#62d6b459"; + + public TLVector MsgIds { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + MsgIds.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Stuff/TLRPCDropAnswer.cs b/Telegram.Api/TL/Functions/Stuff/TLRPCDropAnswer.cs new file mode 100755 index 0000000..580316b --- /dev/null +++ b/Telegram.Api/TL/Functions/Stuff/TLRPCDropAnswer.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Stuff +{ + public class TLRPCDropAnswer : TLObject + { + public const string Signature = "#5e2ad36e"; + + public TLLong ReqMsgId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ReqMsgId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Updates/TLGetChannelDifference.cs b/Telegram.Api/TL/Functions/Updates/TLGetChannelDifference.cs new file mode 100755 index 0000000..402dfe1 --- /dev/null +++ b/Telegram.Api/TL/Functions/Updates/TLGetChannelDifference.cs @@ -0,0 +1,50 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Updates +{ + enum GetChannelDifferenceFlags + { + Force = 0x1 + } + + class TLGetChannelDifference : TLObject + { + public const uint Signature = 0xbb32d7c0; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInputChannelBase Channel { get; set; } + + public TLChannelMessagesFilerBase Filter { get; set; } + + public TLInt Pts { get; set; } + + public TLInt Limit { get; set; } + + public void SetForce() + { + Set(ref _flags, (int) GetChannelDifferenceFlags.Force); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes(), + Filter.ToBytes(), + Pts.ToBytes(), + Limit.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Updates/TLGetDifference.cs b/Telegram.Api/TL/Functions/Updates/TLGetDifference.cs new file mode 100755 index 0000000..039c78a --- /dev/null +++ b/Telegram.Api/TL/Functions/Updates/TLGetDifference.cs @@ -0,0 +1,52 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Updates +{ + enum GetDifferenceFlags + { + PtsTotalLimit = 0x1 + } + + class TLGetDifference : TLObject + { + public const uint Signature = 0x25939651; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt Pts { get; set; } + + private TLInt _ptsTotalLimit; + + public TLInt PtsTotalLimit + { + get { return _ptsTotalLimit; } + set { SetField(out _ptsTotalLimit, value, ref _flags, (int) GetDifferenceFlags.PtsTotalLimit); } + } + + public TLInt Date { get; set; } + + public TLInt Qts { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Pts.ToBytes(), + ToBytes(PtsTotalLimit, Flags, (int)GetDifferenceFlags.PtsTotalLimit), + Date.ToBytes(), + Qts.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Updates/TLGetState.cs b/Telegram.Api/TL/Functions/Updates/TLGetState.cs new file mode 100755 index 0000000..c04f651 --- /dev/null +++ b/Telegram.Api/TL/Functions/Updates/TLGetState.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Updates +{ + public class TLGetState : TLObject + { + public const string Signature = "#edd4882a"; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } +} diff --git a/Telegram.Api/TL/Functions/Upload/TLGetCdnFile.cs b/Telegram.Api/TL/Functions/Upload/TLGetCdnFile.cs new file mode 100755 index 0000000..a4d1cf8 --- /dev/null +++ b/Telegram.Api/TL/Functions/Upload/TLGetCdnFile.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Upload +{ + public class TLGetCdnFile : TLObject + { + public const uint Signature = 0x2000bcc3; + + public TLString FileToken { get; set; } + + public TLInt Offset { get; set; } + + public TLInt Limit { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + FileToken.ToBytes(), + Offset.ToBytes(), + Limit.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Upload/TLGetFile.cs b/Telegram.Api/TL/Functions/Upload/TLGetFile.cs new file mode 100755 index 0000000..b1c69d3 --- /dev/null +++ b/Telegram.Api/TL/Functions/Upload/TLGetFile.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Upload +{ + class TLGetFile : TLObject + { + public const uint Signature = 0xe3a6cfb5; + + public TLInputFileLocationBase Location { get; set; } + + public TLInt Offset { get; set; } + + public TLInt Limit { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Location.ToBytes(), + Offset.ToBytes(), + Limit.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Upload/TLReuploadCdnFile.cs b/Telegram.Api/TL/Functions/Upload/TLReuploadCdnFile.cs new file mode 100755 index 0000000..9b2d3d1 --- /dev/null +++ b/Telegram.Api/TL/Functions/Upload/TLReuploadCdnFile.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Upload +{ + public class TLReuploadCdnFile : TLObject + { + public const uint Signature = 0x9b2754a8; + + public TLString FileToken { get; set; } + + public TLString RequestToken { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + FileToken.ToBytes(), + RequestToken.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Upload/TLSaveFilePart.cs b/Telegram.Api/TL/Functions/Upload/TLSaveFilePart.cs new file mode 100755 index 0000000..052f4f1 --- /dev/null +++ b/Telegram.Api/TL/Functions/Upload/TLSaveFilePart.cs @@ -0,0 +1,52 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Upload +{ + public class TLSaveFilePart : TLObject + { + public const string Signature = "#b304a621"; + + public TLLong FileId { get; set; } + + public TLInt FilePart { get; set; } + + public TLString Bytes { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + FileId.ToBytes(), + FilePart.ToBytes(), + Bytes.ToBytes()); + } + } + + public class TLSaveBigFilePart : TLObject + { + public const string Signature = "#de7b673d"; + + public TLLong FileId { get; set; } + + public TLInt FilePart { get; set; } + + public TLInt FileTotalParts { get; set; } + + public TLString Bytes { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + FileId.ToBytes(), + FilePart.ToBytes(), + FileTotalParts.ToBytes(), + Bytes.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Users/TLGetFullUser.cs b/Telegram.Api/TL/Functions/Users/TLGetFullUser.cs new file mode 100755 index 0000000..60e57cd --- /dev/null +++ b/Telegram.Api/TL/Functions/Users/TLGetFullUser.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Users +{ + public class TLGetFullUser : TLObject + { + public const string Signature = "#ca30a5b1"; + + public TLInputUserBase Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Functions/Users/TLGetUsers.cs b/Telegram.Api/TL/Functions/Users/TLGetUsers.cs new file mode 100755 index 0000000..a338b21 --- /dev/null +++ b/Telegram.Api/TL/Functions/Users/TLGetUsers.cs @@ -0,0 +1,23 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Functions.Users +{ + public class TLGetUsers : TLObject + { + public const string Signature = "#d91a548"; + + public TLVector Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/Interfaces/IBytes.cs b/Telegram.Api/TL/Interfaces/IBytes.cs new file mode 100755 index 0000000..bd858c7 --- /dev/null +++ b/Telegram.Api/TL/Interfaces/IBytes.cs @@ -0,0 +1,14 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Interfaces +{ + public interface IFileData + { + byte[] Buffer { get; set; } + } +} diff --git a/Telegram.Api/TL/Interfaces/IFullName.cs b/Telegram.Api/TL/Interfaces/IFullName.cs new file mode 100755 index 0000000..18a1ecf --- /dev/null +++ b/Telegram.Api/TL/Interfaces/IFullName.cs @@ -0,0 +1,14 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Interfaces +{ + public interface IFullName + { + string FullName { get; } + } +} diff --git a/Telegram.Api/TL/Interfaces/IInputPeer.cs b/Telegram.Api/TL/Interfaces/IInputPeer.cs new file mode 100755 index 0000000..0406ce3 --- /dev/null +++ b/Telegram.Api/TL/Interfaces/IInputPeer.cs @@ -0,0 +1,21 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Interfaces +{ + public interface IInputPeer + { + TLInputPeerBase ToInputPeer(); + + string GetUnsendedTextFileName(); + } + + public interface IInputChannel + { + TLInputChannelBase ToInputChannel(); + } +} diff --git a/Telegram.Api/TL/Interfaces/ISelectable.cs b/Telegram.Api/TL/Interfaces/ISelectable.cs new file mode 100755 index 0000000..344ff00 --- /dev/null +++ b/Telegram.Api/TL/Interfaces/ISelectable.cs @@ -0,0 +1,14 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Interfaces +{ + public interface ISelectable + { + bool IsSelected { get; set; } + } +} diff --git a/Telegram.Api/TL/Interfaces/IVIsibility.cs b/Telegram.Api/TL/Interfaces/IVIsibility.cs new file mode 100755 index 0000000..8aa53c6 --- /dev/null +++ b/Telegram.Api/TL/Interfaces/IVIsibility.cs @@ -0,0 +1,14 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL.Interfaces +{ + public interface IVIsibility + { + bool IsVisible { get; set; } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/SignatureAttribute.cs b/Telegram.Api/TL/SignatureAttribute.cs new file mode 100755 index 0000000..ecfac24 --- /dev/null +++ b/Telegram.Api/TL/SignatureAttribute.cs @@ -0,0 +1,14 @@ +using System; + +namespace Telegram.Api.TL +{ + class SignatureAttribute : Attribute + { + public string Value { get; set; } + + public SignatureAttribute(string signature) + { + Value = signature; + } + } +} diff --git a/Telegram.Api/TL/TLAccountAuthorization.cs b/Telegram.Api/TL/TLAccountAuthorization.cs new file mode 100755 index 0000000..34c9f46 --- /dev/null +++ b/Telegram.Api/TL/TLAccountAuthorization.cs @@ -0,0 +1,126 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Text; + +namespace Telegram.Api.TL +{ + public class TLAccountAuthorization : TLObject + { + public const uint Signature = TLConstructors.TLAccountAuthorization; + + public TLLong Hash { get; set; } + + public TLInt Flags { get; set; } + + public TLString DeviceModel { get; set; } + + public TLString Platform { get; set; } + + public TLString SystemVersion { get; set; } + + public TLInt ApiId { get; set; } + + public TLString AppName { get; set; } + + public TLString AppVersion { get; set; } + + public TLInt DateCreated { get; set; } + + public TLInt DateActive { get; set; } + + public TLString Ip { get; set; } + + public TLString Country { get; set; } + + public TLString Region { get; set; } + + public string Location + { + get { return string.Format("{0} – {1}", Ip, Country); } + } + + public string AppFullName + { + get { return string.Format("{0} {1}", AppName, AppVersion); } + } + + public string DeviceFullName + { + get + { + var name = new StringBuilder(); + name.Append(DeviceModel); + if (!TLString.IsNullOrEmpty(Platform)) + { + name.Append(string.Format(", {0}", Platform)); + } + if (!TLString.IsNullOrEmpty(SystemVersion)) + { + name.Append(string.Format(" {0}", SystemVersion)); + } + + return name.ToString(); + } + } + + public bool IsCurrent + { + get { return IsSet(Flags, 1); } + } + + public bool IsOfficialApp + { + get { return IsSet(Flags, 2); } + } + + public string Description { get; set; } + + public override string ToString() + { + return string.Format("TLAccountAuthorization hash={0} date_active={1}", Hash, TLUtils.ToDateTime(DateActive)); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + Flags = GetObject(bytes, ref position); + DeviceModel = GetObject(bytes, ref position); + Platform = GetObject(bytes, ref position); + SystemVersion = GetObject(bytes, ref position); + ApiId = GetObject(bytes, ref position); + AppName = GetObject(bytes, ref position); + AppVersion = GetObject(bytes, ref position); + DateCreated = GetObject(bytes, ref position); + DateActive = GetObject(bytes, ref position); + Ip = GetObject(bytes, ref position); + Country = GetObject(bytes, ref position); + Region = GetObject(bytes, ref position); + + return this; + } + + public void Update(TLAccountAuthorization authorization) + { + Hash = authorization.Hash; + Flags = authorization.Flags; + DeviceModel = authorization.DeviceModel; + Platform = authorization.Platform; + SystemVersion = authorization.SystemVersion; + ApiId = authorization.ApiId; + AppName = authorization.AppName; + AppVersion = authorization.AppVersion; + DateCreated = authorization.DateCreated; + DateActive = authorization.DateActive; + Ip = authorization.Ip; + Country = authorization.Country; + Region = authorization.Region; + } + } +} diff --git a/Telegram.Api/TL/TLAccountAuthorizations.cs b/Telegram.Api/TL/TLAccountAuthorizations.cs new file mode 100755 index 0000000..5c69deb --- /dev/null +++ b/Telegram.Api/TL/TLAccountAuthorizations.cs @@ -0,0 +1,25 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLAccountAuthorizations : TLObject + { + public const uint Signature = TLConstructors.TLAccountAuthorizations; + + public TLVector Authorizations { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Authorizations = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLAccountDaysTTL.cs b/Telegram.Api/TL/TLAccountDaysTTL.cs new file mode 100755 index 0000000..9396b19 --- /dev/null +++ b/Telegram.Api/TL/TLAccountDaysTTL.cs @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLAccountDaysTTL : TLObject + { + public const uint Signature = TLConstructors.TLAccountDaysTTL; + + public TLInt Days { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Days = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Days.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLActionInfo.cs b/Telegram.Api/TL/TLActionInfo.cs new file mode 100755 index 0000000..e827c05 --- /dev/null +++ b/Telegram.Api/TL/TLActionInfo.cs @@ -0,0 +1,48 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLActionInfo : TLObject + { + public const uint Signature = TLConstructors.TLActionInfo; + + public TLInt SendBefore { get; set; } + + public TLObject Action { get; set; } + + public override string ToString() + { + return string.Format("send_before={0} action={1}", SendBefore, Action); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + SendBefore = GetObject(input); + Action = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + SendBefore.ToStream(output); + Action.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLAdminLogResults.cs b/Telegram.Api/TL/TLAdminLogResults.cs new file mode 100755 index 0000000..31b7854 --- /dev/null +++ b/Telegram.Api/TL/TLAdminLogResults.cs @@ -0,0 +1,51 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLAdminLogResults : TLObject + { + public const uint Signature = TLConstructors.TLAdminLogResults; + + public TLVector Events { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Events = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Events = GetObject>(input); + Chats = GetObject>(input); + Users = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Events.ToStream(output); + Chats.ToStream(output); + Users.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLAffectedHistory.cs b/Telegram.Api/TL/TLAffectedHistory.cs new file mode 100755 index 0000000..2dd01c4 --- /dev/null +++ b/Telegram.Api/TL/TLAffectedHistory.cs @@ -0,0 +1,61 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLAffectedHistory : TLObject + { + public const uint Signature = TLConstructors.TLAffectedHistory; + + public TLInt Pts { get; set; } + + public TLInt Seq { get; set; } + + public TLInt Offset { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Pts = GetObject(bytes, ref position); + Seq = GetObject(bytes, ref position); + Offset = GetObject(bytes, ref position); + + return this; + } + } + + public class TLAffectedHistory24 : TLAffectedHistory, IMultiPts, IMultiChannelPts + { + public new const uint Signature = TLConstructors.TLAffectedHistory24; + + public TLInt PtsCount { get; set; } + + public TLInt ChannelPts + { + get { return Pts; } + set { Pts = value; } + } + + public TLInt ChannelPtsCount + { + get { return PtsCount; } + set { PtsCount = value; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Offset = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLAffectedMessages.cs b/Telegram.Api/TL/TLAffectedMessages.cs new file mode 100755 index 0000000..2dad7e9 --- /dev/null +++ b/Telegram.Api/TL/TLAffectedMessages.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLAffectedMessages : TLObject, IMultiPts + { + public const uint Signature = TLConstructors.TLAffectedMessages; + + public TLInt Pts { get; set; } + + public TLInt PtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLAllStrickers.cs b/Telegram.Api/TL/TLAllStrickers.cs new file mode 100755 index 0000000..93f85aa --- /dev/null +++ b/Telegram.Api/TL/TLAllStrickers.cs @@ -0,0 +1,381 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum AllStickersCustomFlags + { + RecentStickers = 0x1, + FavedStickers = 0x2, + ShowStickersByEmoji = 0x4, + } + + public interface IStickers + { + TLString Hash { get; set; } + + TLVector Sets { get; set; } + + TLVector Packs { get; set; } + + TLVector Documents { get; set; } + } + + public abstract class TLAllStickersBase : TLObject { } + + public class TLAllStickersNotModified : TLAllStickersBase + { + public const uint Signature = TLConstructors.TLAllStickersNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLAllStickers : TLAllStickersBase + { + public const uint Signature = TLConstructors.TLAllStickers; + + public virtual TLString Hash { get; set; } + + public TLVector Packs { get; set; } + + public TLVector Documents { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + Packs = GetObject>(bytes, ref position); + Documents = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes(), + Packs.ToBytes(), + Documents.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Hash = GetObject(input); + Packs = GetObject>(input); + Documents = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Hash.ToStream(output); + Packs.ToStream(output); + Documents.ToStream(output); + } + } + + public class TLAllStickers29 : TLAllStickers + { + public new const uint Signature = TLConstructors.TLAllStickers29; + + public TLVector Sets { get; set; } + + #region Additional + public TLInt Date { get; set; } + + public TLBool ShowStickersTab { get; set; } + + public TLVector RecentlyUsed { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + Packs = GetObject>(bytes, ref position); + Sets = GetObject>(bytes, ref position); + Documents = GetObject>(bytes, ref position); + + ShowStickersTab = new TLBool(true); + RecentlyUsed = new TLVector(); + Date = TLUtils.DateToUniversalTimeTLInt(0, DateTime.Now); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes(), + Packs.ToBytes(), + Sets.ToBytes(), + Documents.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Hash = GetObject(input); + Packs = GetObject>(input); + Sets = GetObject>(input); + Documents = GetObject>(input); + + ShowStickersTab = GetNullableObject(input); + RecentlyUsed = GetNullableObject>(input); + Date = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Hash.ToStream(output); + Packs.ToStream(output); + Sets.ToStream(output); + Documents.ToStream(output); + + ShowStickersTab.NullableToStream(output); + RecentlyUsed.NullableToStream(output); + Date.NullableToStream(output); + } + } + + public class TLAllStickers32 : TLAllStickers29 + { + public new const uint Signature = TLConstructors.TLAllStickers32; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + Sets = GetObject>(bytes, ref position); + + Packs = new TLVector(); + Documents = new TLVector(); + ShowStickersTab = TLBool.True; + RecentlyUsed = new TLVector(); + Date = TLUtils.DateToUniversalTimeTLInt(0, DateTime.Now); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes(), + Sets.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Hash = GetObject(input); + Packs = GetObject>(input); + Sets = GetObject>(input); + Documents = GetObject>(input); + + ShowStickersTab = GetNullableObject(input); + RecentlyUsed = GetNullableObject>(input); + Date = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Hash.ToStream(output); + Packs.ToStream(output); + Sets.ToStream(output); + Documents.ToStream(output); + + ShowStickersTab.NullableToStream(output); + RecentlyUsed.NullableToStream(output); + Date.NullableToStream(output); + } + } + + public class TLAllStickers43 : TLAllStickers32, IStickers + { + public new const uint Signature = TLConstructors.TLAllStickers43; + + public TLInt HashValue { get; set; } + + public override TLString Hash + { + get { return TLUtils.ToTLString(HashValue) ?? TLString.Empty; } + set { HashValue = TLUtils.ToTLInt(value) ?? new TLInt(0); } + } + + private TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + private TLRecentStickers _recentStickers; + + public TLRecentStickers RecentStickers + { + get { return _recentStickers; } + set { SetField(out _recentStickers, value, ref _customFlags, (int) AllStickersCustomFlags.RecentStickers); } + } + + private TLFavedStickers _favedStickers; + + public TLFavedStickers FavedStickers + { + get { return _favedStickers; } + set { SetField(out _favedStickers, value, ref _customFlags, (int)AllStickersCustomFlags.FavedStickers); } + } + + protected TLInt _showStickersByEmoji; + + // null - all sets + // 1 - my sets + // 0 - none + public ShowStickersByEmoji ShowStickersByEmoji + { + get + { + if (_showStickersByEmoji == null) + { + return ShowStickersByEmoji.AllSets; + } + if (_showStickersByEmoji.Value == 1) + { + return ShowStickersByEmoji.MySets; + } + + return ShowStickersByEmoji.None; + } + set + { + switch (value) + { + case ShowStickersByEmoji.AllSets: + SetField(out _showStickersByEmoji, null, ref _customFlags, (int)AllStickersCustomFlags.ShowStickersByEmoji); + break; + case ShowStickersByEmoji.MySets: + SetField(out _showStickersByEmoji, new TLInt(1), ref _customFlags, (int)AllStickersCustomFlags.ShowStickersByEmoji); + break; + default: + SetField(out _showStickersByEmoji, new TLInt(0), ref _customFlags, (int)AllStickersCustomFlags.ShowStickersByEmoji); + break; + } + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + HashValue = GetObject(bytes, ref position); + Sets = GetObject>(bytes, ref position); + + Packs = new TLVector(); + Documents = new TLVector(); + ShowStickersTab = TLBool.True; + RecentlyUsed = new TLVector(); + Date = TLUtils.DateToUniversalTimeTLInt(0, DateTime.Now); + CustomFlags = new TLLong(0); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + HashValue.ToBytes(), + Sets.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + HashValue = GetObject(input); + Packs = GetObject>(input); + + Sets = GetObject>(input); + Documents = GetObject>(input); + ShowStickersTab = GetNullableObject(input); + RecentlyUsed = GetNullableObject>(input); + Date = GetNullableObject(input); + CustomFlags = GetNullableObject(input); + RecentStickers = GetObject(CustomFlags, (int)AllStickersCustomFlags.RecentStickers, null, input); + FavedStickers = GetObject(CustomFlags, (int)AllStickersCustomFlags.FavedStickers, null, input); + _showStickersByEmoji = GetObject(CustomFlags, (int)AllStickersCustomFlags.ShowStickersByEmoji, null, input); + + // move showStickersTab flag to ShowStickersByEmoji flag + if (ShowStickersTab != null && !ShowStickersTab.Value) + { + ShowStickersByEmoji = ShowStickersByEmoji.MySets; + ShowStickersTab = TLBool.True; + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + HashValue.ToStream(output); + Packs.ToStream(output); + + Sets.ToStream(output); + Documents.ToStream(output); + ShowStickersTab.NullableToStream(output); + RecentlyUsed.NullableToStream(output); + Date.NullableToStream(output); + CustomFlags.ToStream(output); + ToStream(output, RecentStickers, CustomFlags, (int)AllStickersCustomFlags.RecentStickers); + ToStream(output, FavedStickers, CustomFlags, (int)AllStickersCustomFlags.FavedStickers); + ToStream(output, _showStickersByEmoji, CustomFlags, (int)AllStickersCustomFlags.ShowStickersByEmoji); + } + } + + public enum ShowStickersByEmoji + { + AllSets, + MySets, + None + } +} diff --git a/Telegram.Api/TL/TLAppChangelogBase.cs b/Telegram.Api/TL/TLAppChangelogBase.cs new file mode 100755 index 0000000..9bcb188 --- /dev/null +++ b/Telegram.Api/TL/TLAppChangelogBase.cs @@ -0,0 +1,61 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLAppChangelogBase : TLObject { } + + public class TLAppChangelogEmpty : TLAppChangelogBase + { + public const uint Signature = TLConstructors.TLAppChangelogEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLAppChangelog : TLAppChangelogBase + { + public const uint Signature = TLConstructors.TLAppChangelog; + + public TLString Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + } + + public class TLAppChangelog59 : TLAppChangelogBase + { + public const uint Signature = TLConstructors.TLAppChangelog59; + + public TLString Message { get; set; } + + public TLMessageMediaBase Media { get; set; } + + public TLVector Entities { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + Media = GetObject(bytes, ref position); + Entities = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLArchivedStickers.cs b/Telegram.Api/TL/TLArchivedStickers.cs new file mode 100755 index 0000000..5b28cef --- /dev/null +++ b/Telegram.Api/TL/TLArchivedStickers.cs @@ -0,0 +1,92 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; + +namespace Telegram.Api.TL +{ + public class TLArchivedStickers : TLObject, IStickers + { + public const uint Signature = TLConstructors.TLArchivedStickers; + + public TLInt Count { get; set; } + + public TLVector SetsCovered { get; set; } + + public TLVector Sets + { + get + { + var sets = new TLVector(); + foreach (var setCovered in SetsCovered) + { + sets.Add(setCovered.StickerSet); + } + return sets; + } + set + { + Execute.ShowDebugMessage("TLArchivedStickers.Sets set"); + } + } + + public TLVector Packs { get; set; } + + public TLVector Documents { get; set; } + + public TLString Hash { get; set; } + + public TLVector MessagesStickerSets { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Count = GetObject(bytes, ref position); + SetsCovered = GetObject>(bytes, ref position); + + Packs = new TLVector(); + Documents = new TLVector(); + MessagesStickerSets = new TLVector(); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Count.ToBytes(), + SetsCovered.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Count = GetObject(input); + SetsCovered = GetObject>(input); + + Packs = GetObject>(input); + Documents = GetObject>(input); + MessagesStickerSets = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Count.ToStream(output); + SetsCovered.ToStream(output); + + Packs.ToStream(output); + Documents.ToStream(output); + MessagesStickerSets.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLAudio.cs b/Telegram.Api/TL/TLAudio.cs new file mode 100755 index 0000000..28d17b3 --- /dev/null +++ b/Telegram.Api/TL/TLAudio.cs @@ -0,0 +1,240 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Services.Cache; + +namespace Telegram.Api.TL +{ + public abstract class TLAudioBase : TLObject + { + public TLLong Id { get; set; } + + public virtual int AudioSize{get { return 0; }} + } + + public class TLAudioEmpty : TLAudioBase + { + public const uint Signature = TLConstructors.TLAudioEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + } + } + + public class TLAudio33 : TLAudio + { + public new const uint Signature = TLConstructors.TLAudio33; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + //UserId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Duration = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + DCId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + //UserId.ToBytes(), + Date.ToBytes(), + Duration.ToBytes(), + MimeType.ToBytes(), + Size.ToBytes(), + DCId.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + //UserId = GetObject(input); + Date = GetObject(input); + Duration = GetObject(input); + MimeType = GetObject(input); + Size = GetObject(input); + DCId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + AccessHash.ToStream(output); + //UserId.ToStream(output); + Date.ToStream(output); + Duration.ToStream(output); + MimeType.ToStream(output); + Size.ToStream(output); + DCId.ToStream(output); + } + } + + public class TLAudio : TLAudioBase + { + public const uint Signature = TLConstructors.TLAudio; + + public TLLong AccessHash { get; set; } + + public TLInt UserId { get; set; } + + public TLInt Date { get; set; } + + public TLInt Duration { get; set; } + + public TLString MimeType { get; set; } + + public TLInt Size { get; set; } + + public TLInt DCId { get; set; } + + public string GetFileName() + { + return string.Format("audio{0}_{1}.mp3", Id, AccessHash); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Duration = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + DCId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + UserId.ToBytes(), + Date.ToBytes(), + Duration.ToBytes(), + MimeType.ToBytes(), + Size.ToBytes(), + DCId.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + UserId = GetObject(input); + Date = GetObject(input); + Duration = GetObject(input); + MimeType = GetObject(input); + Size = GetObject(input); + DCId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + AccessHash.ToStream(output); + UserId.ToStream(output); + Date.ToStream(output); + Duration.ToStream(output); + MimeType.ToStream(output); + Size.ToStream(output); + DCId.ToStream(output); + } + + #region Additional + + public override int AudioSize + { + get + { + return Size != null ? Size.Value : 0; + } + } + + public string DurationString + { + get + { + var timeSpan = TimeSpan.FromSeconds(Duration.Value); + + if (timeSpan.Hours > 0) + { + return timeSpan.ToString(@"h\:mm\:ss"); + } + + return timeSpan.ToString(@"m\:ss"); + } + } + + public TLUserBase User + { + get + { + var cacheService = InMemoryCacheService.Instance; + return cacheService.GetUser(UserId); + } + } + #endregion + + public TLInputAudioFileLocation ToInputFileLocation() + { + return new TLInputAudioFileLocation { AccessHash = AccessHash, Id = Id }; + } + } +} diff --git a/Telegram.Api/TL/TLAuthorization.cs b/Telegram.Api/TL/TLAuthorization.cs new file mode 100755 index 0000000..11d44b4 --- /dev/null +++ b/Telegram.Api/TL/TLAuthorization.cs @@ -0,0 +1,70 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum AuthorizationFlags + { + TmpSessions = 0x1, // 0 + } + + public class TLAuthorization : TLObject + { + public const uint Signature = TLConstructors.TLAuthorization; + + public TLInt Expires { get; set; } + + public TLUserBase User { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Expires = GetObject(bytes, ref position); + User = GetObject(bytes, ref position); + + return this; + } + } + + public class TLAuthorization31 : TLAuthorization + { + public new const uint Signature = TLConstructors.TLAuthorization31; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + User = GetObject(bytes, ref position); + + return this; + } + } + + public class TLAuthorization55 : TLAuthorization + { + public new const uint Signature = TLConstructors.TLAuthorization55; + + public TLInt Flags { get; set; } + + public TLInt TempSessions { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + User = GetObject(bytes, ref position); + TempSessions = GetObject(Flags, (int) AuthorizationFlags.TmpSessions, null, bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLBadMessageNotification.cs b/Telegram.Api/TL/TLBadMessageNotification.cs new file mode 100755 index 0000000..d1975dd --- /dev/null +++ b/Telegram.Api/TL/TLBadMessageNotification.cs @@ -0,0 +1,38 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; + +namespace Telegram.Api.TL +{ + public class TLBadMessageNotification : TLObject + { + public const uint Signature = TLConstructors.TLBadMessageNotification; + + public TLLong BadMessageId { get; set; } + + public TLInt BadMessageSequenceNumber { get; set; } + + public TLInt ErrorCode { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + BadMessageId = GetObject(bytes, ref position); + BadMessageSequenceNumber = GetObject(bytes, ref position); + ErrorCode = GetObject(bytes, ref position); + + return this; + } + + public override string ToString() + { + return string.Format("TLBadMessageNotification msg_id={0} msg_seq_no={1} error_code={2}", BadMessageId, BadMessageSequenceNumber, ErrorCode); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLBadServerSalt.cs b/Telegram.Api/TL/TLBadServerSalt.cs new file mode 100755 index 0000000..b1040c0 --- /dev/null +++ b/Telegram.Api/TL/TLBadServerSalt.cs @@ -0,0 +1,39 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLBadServerSalt : TLObject + { + public const uint Signature = TLConstructors.TLBadServerSalt; + + public TLLong BadMessageId { get; set; } + + public TLInt BadMessageSeqNo { get; set; } + + public TLInt ErrorCode { get; set; } + + public TLLong NewServerSalt { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + BadMessageId = GetObject(bytes, ref position); + BadMessageSeqNo = GetObject(bytes, ref position); + ErrorCode = GetObject(bytes, ref position); + NewServerSalt = GetObject(bytes, ref position); + + return this; + } + + public override string ToString() + { + return string.Format("TLBadServerSalt msg_id={0} msg_seq_no={1} error_code={2} new_salt={3}", BadMessageId, BadMessageSeqNo, ErrorCode, NewServerSalt); + } + } +} diff --git a/Telegram.Api/TL/TLBool.cs b/Telegram.Api/TL/TLBool.cs new file mode 100755 index 0000000..e04595a --- /dev/null +++ b/Telegram.Api/TL/TLBool.cs @@ -0,0 +1,119 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.IO; +using System.Runtime.Serialization; + +namespace Telegram.Api.TL +{ + [DataContract] + public class TLBool : TLObject + { + public const uint BoolTrue = 0x997275b5; + public const uint BoolFalse = 0xbc799737; + + [DataMember] + public bool Value { get; set; } + + public TLBool() + { + + } + + public TLBool(bool value) + { + Value = value; + } + + public static TLBool True + { + get { return new TLBool(true); } + } + + public static TLBool False + { + get { return new TLBool(false); } + } + + public static TLBool Parse(byte[] bytes, out int bytesRead) + { + bytesRead = 4; + if (bytes.StartsWith(BoolTrue)) + { + return new TLBool{ Value = true }; + } + if (bytes.StartsWith(BoolFalse)) + { + return new TLBool { Value = false }; + } + + bytesRead = 0; + bytes.ThrowNotSupportedException("TLBool"); + return null; + } + + public override byte[] ToBytes() + { + return Value ? TLUtils.SignatureToBytes(BoolTrue) : TLUtils.SignatureToBytes(BoolFalse); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + if (bytes.StartsWith(position, BoolTrue)) + { + Value = true; + } + else if (bytes.StartsWith(position, BoolFalse)) + { + Value = false; + } + else + { + bytes.ThrowNotSupportedException("TLBool"); + } + position += 4; + + return this; + } + + public override TLObject FromStream(Stream input) + { + var buffer = new byte[4]; + input.Read(buffer, 0, 4); + if (buffer.StartsWith(0, BoolTrue)) + { + Value = true; + } + else if (buffer.StartsWith(0, BoolFalse)) + { + Value = false; + } + else + { + buffer.ThrowNotSupportedException("TLBool"); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(Value ? BitConverter.GetBytes(BoolTrue) : BitConverter.GetBytes(BoolFalse), 0, 4); + } + + public override string ToString() + { +#if WIN_RT + return Value.ToString(); +#else + return Value.ToString(CultureInfo.InvariantCulture); +#endif + } + } +} diff --git a/Telegram.Api/TL/TLBotCallbackAnswer.cs b/Telegram.Api/TL/TLBotCallbackAnswer.cs new file mode 100755 index 0000000..e13f758 --- /dev/null +++ b/Telegram.Api/TL/TLBotCallbackAnswer.cs @@ -0,0 +1,163 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum BotCallbackAnswer + { + Message = 0x1, // 0 + Alert = 0x2, // 1 + Url = 0x4, // 2 + HasUrl = 0x8, // 3 + } + + public class TLBotCallbackAnswer : TLObject + { + public const uint Signature = TLConstructors.TLBotCallbackAnswer; + + public TLInt Flags { get; set; } + + public TLString Message { get; set; } + + public bool Alert { get { return IsSet(Flags, (int) BotCallbackAnswer.Alert); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Message = GetObject(Flags, (int)BotCallbackAnswer.Message, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Message.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Message = GetObject(Flags, (int)BotCallbackAnswer.Message, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + ToBytes(Message, Flags, (int) BotCallbackAnswer.Message); + } + } + + public class TLBotCallbackAnswer54 : TLBotCallbackAnswer + { + public new const uint Signature = TLConstructors.TLBotCallbackAnswer54; + + public TLString Url { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Message = GetObject(Flags, (int) BotCallbackAnswer.Message, null, bytes, ref position); + Url = GetObject(Flags, (int) BotCallbackAnswer.Url, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Message.ToBytes(), + Url.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Message = GetObject(Flags, (int) BotCallbackAnswer.Message, null, input); + Url = GetObject(Flags, (int) BotCallbackAnswer.Url, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + ToBytes(Message, Flags, (int) BotCallbackAnswer.Message); + ToBytes(Url, Flags, (int) BotCallbackAnswer.Url); + } + } + + public class TLBotCallbackAnswer58 : TLBotCallbackAnswer54, ICachedObject + { + public new const uint Signature = TLConstructors.TLBotCallbackAnswer58; + + public TLInt CacheTime { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Message = GetObject(Flags, (int)BotCallbackAnswer.Message, null, bytes, ref position); + Url = GetObject(Flags, (int)BotCallbackAnswer.Url, null, bytes, ref position); + CacheTime = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(Message, Flags, (int)BotCallbackAnswer.Message), + ToBytes(Url, Flags, (int)BotCallbackAnswer.Url), + CacheTime.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Message = GetObject(Flags, (int)BotCallbackAnswer.Message, null, input); + Url = GetObject(Flags, (int)BotCallbackAnswer.Url, null, input); + CacheTime = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + ToStream(output, Message, Flags, (int) BotCallbackAnswer.Message); + ToStream(output, Url, Flags, (int) BotCallbackAnswer.Url); + output.Write(CacheTime.ToBytes()); + } + } + + public interface ICachedObject + { + TLInt CacheTime { get; set; } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLBotCommand.cs b/Telegram.Api/TL/TLBotCommand.cs new file mode 100755 index 0000000..ea599fa --- /dev/null +++ b/Telegram.Api/TL/TLBotCommand.cs @@ -0,0 +1,57 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLBotCommand : TLObject + { + public const uint Signature = TLConstructors.TLBotCommand; + + public TLString Command { get; set; } + + public TLString Description { get; set; } + + + public TLUserBase Bot { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Command = GetObject(bytes, ref position); + Description = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Command.ToBytes(), + Description.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Command = GetObject(input); + Description = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Command.ToBytes()); + output.Write(Description.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLBotInfo.cs b/Telegram.Api/TL/TLBotInfo.cs new file mode 100755 index 0000000..87af8eb --- /dev/null +++ b/Telegram.Api/TL/TLBotInfo.cs @@ -0,0 +1,156 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLBotInfoBase : TLObject { } + + public class TLBotInfoEmpty : TLBotInfoBase + { + public const uint Signature = TLConstructors.TLBotInfoEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLBotInfo49 : TLBotInfo + { + public new const uint Signature = TLConstructors.TLBotInfo49; + + public override TLInt Version + { + get { return new TLInt(0); } + set { } + } + + public override TLString ShareText + { + get { return TLString.Empty; } + set { } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + Description = GetObject(bytes, ref position); + Commands = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + UserId.ToBytes(), + Description.ToBytes(), + Commands.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + Description = GetObject(input); + Commands = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(UserId.ToBytes()); + output.Write(Description.ToBytes()); + output.Write(Commands.ToBytes()); + } + } + + public class TLBotInfo : TLBotInfoBase + { + public const uint Signature = TLConstructors.TLBotInfo; + + public TLInt UserId { get; set; } + + public virtual TLInt Version { get; set; } + + public virtual TLString ShareText { get; set; } + + public TLString Description { get; set; } + + public TLVector Commands { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + ShareText = GetObject(bytes, ref position); + Description = GetObject(bytes, ref position); + Commands = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + UserId.ToBytes(), + Version.ToBytes(), + ShareText.ToBytes(), + Description.ToBytes(), + Commands.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + Version = GetObject(input); + ShareText = GetObject(input); + Description = GetObject(input); + Commands = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(UserId.ToBytes()); + output.Write(Version.ToBytes()); + output.Write(ShareText.ToBytes()); + output.Write(Description.ToBytes()); + output.Write(Commands.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLBotInlineMessage.cs b/Telegram.Api/TL/TLBotInlineMessage.cs new file mode 100755 index 0000000..5c1adb9 --- /dev/null +++ b/Telegram.Api/TL/TLBotInlineMessage.cs @@ -0,0 +1,613 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum BotInlineMessageFlags + { + NoWebpage = 0x1, // 0 + Entities = 0x2, // 1 + ReplyMarkup = 0x4, // 2 + } + + public abstract class TLBotInlineMessageBase : TLObject + { + public TLReplyKeyboardBase ReplyMarkup { get; set; } + + public static string BotInlineMessageFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (BotInlineMessageFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + } + + public class TLBotInlineMessageMediaAuto75 : TLBotInlineMessageMediaAuto51 + { + public new const uint Signature = TLConstructors.TLBotInlineMessageMediaAuto75; + + protected TLVector _entities; + + public TLVector Entities + { + get { return _entities; } + set { SetField(out _entities, value, ref _flags, (int)InputBotInlineMessageFlags.Entities); } + } + + public override string ToString() + { + return string.Format("TLBotInlineMessageMediaAuto75 flags={0} caption={1} reply_markup={2}", BotInlineMessageFlagsString(Flags), Caption, ReplyMarkup); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + Entities = GetObject>(Flags, (int)BotInlineMessageFlags.Entities, null, bytes, ref position); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Caption.ToBytes(), + ToBytes(Entities, Flags, (int)InputBotInlineMessageFlags.Entities), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Caption = GetObject(input); + Entities = GetObject>(Flags, (int)BotInlineMessageFlags.Entities, null, input); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Caption.ToStream(output); + ToStream(output, Entities, Flags, (int)BotInlineMessageFlags.Entities); + ToStream(output, ReplyMarkup, Flags, (int)BotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLBotInlineMessageMediaAuto51 : TLBotInlineMessageMediaAuto + { + public new const uint Signature = TLConstructors.TLBotInlineMessageMediaAuto51; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override string ToString() + { + return string.Format("TLBotInlineMessageMediaAuto51 flags={0} caption={1} reply_markup={2}", BotInlineMessageFlagsString(Flags), Caption, ReplyMarkup); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Caption.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Caption = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Caption.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)BotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLBotInlineMessageMediaAuto : TLBotInlineMessageBase + { + public const uint Signature = TLConstructors.TLBotInlineMessageMediaAuto; + + public TLString Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Caption = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Caption.ToStream(output); + } + } + + public class TLBotInlineMessageText51 : TLBotInlineMessageText + { + public new const uint Signature = TLConstructors.TLBotInlineMessageText51; + + public override string ToString() + { + return string.Format("TLBotInlineMessageText51 flags={0} message={1} entities={2} reply_markup={3}", BotInlineMessageFlagsString(Flags), Message, Entities, ReplyMarkup); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Entities = GetObject>(Flags, (int)BotInlineMessageFlags.Entities, null, bytes, ref position); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Message.ToBytes(), + ToBytes(Entities, Flags, (int)InputBotInlineMessageFlags.Entities), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Message = GetObject(input); + Entities = GetObject>(Flags, (int)BotInlineMessageFlags.Entities, null, input); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Message.ToStream(output); + ToStream(output, Entities, Flags, (int)InputBotInlineMessageFlags.Entities); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLBotInlineMessageText : TLBotInlineMessageBase + { + public const uint Signature = TLConstructors.TLBotInlineMessageText; + + public TLInt Flags { get; set; } + + public bool NoWebpage { get { return IsSet(Flags, (int)BotInlineMessageFlags.NoWebpage); } } + + public TLString Message { get; set; } + + public TLVector Entities { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)BotInlineMessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Message.ToBytes(), + ToBytes(Entities, Flags, (int)InputBotInlineMessageFlags.Entities)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Message = GetObject(input); + if (IsSet(Flags, (int)InputBotInlineMessageFlags.Entities)) + { + Entities = GetObject>(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Message.ToStream(output); + ToStream(output, Entities, Flags, (int)InputBotInlineMessageFlags.Entities); + } + } + + public class TLBotInlineMessageMediaGeo : TLBotInlineMessageBase + { + public const uint Signature = TLConstructors.TLBotInlineMessageMediaGeo; + + public TLInt Flags { get; set; } + + public TLGeoPointBase Geo { get; set; } + + public override string ToString() + { + return string.Format("TLBotInlineMessageMediaGeo flags={0} geo={1} reply_markup={2}", BotInlineMessageFlagsString(Flags), Geo, ReplyMarkup); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Geo = GetObject(bytes, ref position); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Geo.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Geo = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Geo.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLBotInlineMessageMediaVenue78 : TLBotInlineMessageMediaVenue + { + public new const uint Signature = TLConstructors.TLBotInlineMessageMediaVenue78; + + public TLString VenueType { get; set; } + + public override string ToString() + { + return string.Format("TLBotInlineMessageMediaVenue flags={0} geo={1} title={2} address={3} provider={4} venue_id={5} venue_type={6} reply_markup={7}", BotInlineMessageFlagsString(Flags), Geo, Title, Address, Provider, VenueId, VenueType, ReplyMarkup); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Geo = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + Address = GetObject(bytes, ref position); + Provider = GetObject(bytes, ref position); + VenueId = GetObject(bytes, ref position); + VenueType = GetObject(bytes, ref position); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Geo.ToBytes(), + Title.ToBytes(), + Address.ToBytes(), + Provider.ToBytes(), + VenueId.ToBytes(), + VenueType.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Geo = GetObject(input); + Title = GetObject(input); + Address = GetObject(input); + Provider = GetObject(input); + VenueId = GetObject(input); + VenueType = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Geo.ToStream(output); + Title.ToStream(output); + Address.ToStream(output); + Provider.ToStream(output); + VenueId.ToStream(output); + VenueType.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLBotInlineMessageMediaVenue : TLBotInlineMessageMediaGeo + { + public new const uint Signature = TLConstructors.TLBotInlineMessageMediaVenue; + + public TLString Title { get; set; } + + public TLString Address { get; set; } + + public TLString Provider { get; set; } + + public TLString VenueId { get; set; } + + public override string ToString() + { + return string.Format("TLBotInlineMessageMediaVenue flags={0} geo={1} title={2} address={3} provider={4} venue_id={5} reply_markup={6}", BotInlineMessageFlagsString(Flags), Geo, Title, Address, Provider, VenueId, ReplyMarkup); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Geo = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + Address = GetObject(bytes, ref position); + Provider = GetObject(bytes, ref position); + VenueId = GetObject(bytes, ref position); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Geo.ToBytes(), + Title.ToBytes(), + Address.ToBytes(), + Provider.ToBytes(), + VenueId.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Geo = GetObject(input); + Title = GetObject(input); + Address = GetObject(input); + Provider = GetObject(input); + VenueId = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Geo.ToStream(output); + Title.ToStream(output); + Address.ToStream(output); + Provider.ToStream(output); + VenueId.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLBotInlineMessageMediaContact82 : TLBotInlineMessageMediaContact + { + public new const uint Signature = TLConstructors.TLBotInlineMessageMediaContact82; + + public TLString VCard { get; set; } + + public override string ToString() + { + return string.Format("TLBotInlineMessageMediaContact82 flags={0} phone_number={1} first_name={2} last_name={3} vcard={4} reply_markup={5}", BotInlineMessageFlagsString(Flags), PhoneNumber, FirstName, LastName, VCard, ReplyMarkup); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + PhoneNumber = GetObject(bytes, ref position); + FirstName = GetObject(bytes, ref position); + LastName = GetObject(bytes, ref position); + VCard = GetObject(bytes, ref position); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + PhoneNumber.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + VCard.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + PhoneNumber = GetObject(input); + FirstName = GetObject(input); + LastName = GetObject(input); + VCard = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + PhoneNumber.ToStream(output); + FirstName.ToStream(output); + LastName.ToStream(output); + VCard.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLBotInlineMessageMediaContact : TLBotInlineMessageBase + { + public const uint Signature = TLConstructors.TLBotInlineMessageMediaContact; + + public TLInt Flags { get; set; } + + public TLString PhoneNumber { get; set; } + + public TLString FirstName { get; set; } + + public TLString LastName { get; set; } + + public TLUserBase User + { + get { return new TLUser { Id = new TLInt(0), Photo = new TLPhotoEmpty { Id = new TLLong(0) }, FirstName = FirstName, LastName = LastName, Phone = PhoneNumber }; } + } + + public override string ToString() + { + return string.Format("TLBotInlineMessageMediaContact flags={0} phone_number={1} first_name={2} last_name={3} reply_markup={4}", BotInlineMessageFlagsString(Flags), PhoneNumber, FirstName, LastName, ReplyMarkup); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + PhoneNumber = GetObject(bytes, ref position); + FirstName = GetObject(bytes, ref position); + LastName = GetObject(bytes, ref position); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + PhoneNumber.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + PhoneNumber = GetObject(input); + FirstName = GetObject(input); + LastName = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)BotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + PhoneNumber.ToStream(output); + FirstName.ToStream(output); + LastName.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } +} diff --git a/Telegram.Api/TL/TLBotInlineResult.cs b/Telegram.Api/TL/TLBotInlineResult.cs new file mode 100755 index 0000000..03b88e1 --- /dev/null +++ b/Telegram.Api/TL/TLBotInlineResult.cs @@ -0,0 +1,611 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum BotInlineResultFlags + { + //Unread = 0x1, // 0 + Title = 0x2, // 1 + Description = 0x4, // 2 + Url = 0x8, // 3 + Thumb = 0x10, // 4 + Content = 0x20, // 5 + Size = 0x40, // 6 + Duration = 0x80, // 7 + } + + [Flags] + public enum BotInlineMediaResultFlags + { + Photo = 0x1, // 0 + Document = 0x2, // 1 + Title = 0x4, // 2 + Description = 0x8, // 3 + } + + public abstract class TLBotInlineResultBase : TLObject + { + public TLBotInlineResultBase Self { get { return this; } } + + public TLString Id { get; set; } + + public TLString Type { get; set; } + + public TLBotInlineMessageBase SendMessage { get; set; } + + public TLLong QueryId { get; set; } + } + + public class TLBotInlineMediaResult : TLBotInlineResultBase, IMediaGif + { + public const uint Signature = TLConstructors.TLBotInlineMediaResult; + + public TLInt Flags { get; set; } + + public TLPhotoBase Photo { get; set; } + + public TLDocumentBase Document { get; set; } + + public TLString Title { get; set; } + + public TLString Description { get; set; } + + public TLBotInlineMediaResult ThumbSelf { get { return this; } } + + private double _downloadingProgress; + + public double DownloadingProgress + { + get { return _downloadingProgress; } + set { SetField(ref _downloadingProgress, value, () => DownloadingProgress); } + } + + public double LastProgress { get; set; } + public bool IsCanceled { get; set; } + public string IsoFileName { get; set; } + public bool? AutoPlayGif { get; set; } + public bool Forbidden { get; set; } + + public static string BotInlineMediaResultFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (BotInlineMediaResultFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public override string ToString() + { + return string.Format("TLBotInlineMediaResult flags={0} type={2} id={1} photo={3} document={4} title={5} description={6} send_message=[{7}]", BotInlineMediaResultFlagsString(Flags), Id, Type, Photo != null, Document != null, Title, Description, SendMessage); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + Type = GetObject(bytes, ref position); + Photo = GetObject(Flags, (int)BotInlineMediaResultFlags.Photo, null, bytes, ref position); + Document = GetObject(Flags, (int)BotInlineMediaResultFlags.Document, null, bytes, ref position); + Title = GetObject(Flags, (int)BotInlineMediaResultFlags.Title, null, bytes, ref position); + Description = GetObject(Flags, (int)BotInlineMediaResultFlags.Description, null, bytes, ref position); + SendMessage = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + Type.ToBytes(), + ToBytes(Photo, Flags, (int)BotInlineMediaResultFlags.Photo), + ToBytes(Document, Flags, (int)BotInlineMediaResultFlags.Document), + ToBytes(Title, Flags, (int)BotInlineMediaResultFlags.Title), + ToBytes(Description, Flags, (int)BotInlineMediaResultFlags.Description), + SendMessage.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Type = GetObject(input); + Photo = GetObject(Flags, (int)BotInlineMediaResultFlags.Photo, null, input); + Document = GetObject(Flags, (int)BotInlineMediaResultFlags.Document, null, input); + Title = GetObject(Flags, (int)BotInlineMediaResultFlags.Title, null, input); + Description = GetObject(Flags, (int)BotInlineMediaResultFlags.Description, null, input); + SendMessage = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + Type.ToStream(output); + ToStream(output, Photo, Flags, (int)BotInlineMediaResultFlags.Photo); + ToStream(output, Document, Flags, (int)BotInlineMediaResultFlags.Document); + ToStream(output, Title, Flags, (int)BotInlineMediaResultFlags.Title); + ToStream(output, Description, Flags, (int)BotInlineMediaResultFlags.Description); + SendMessage.ToStream(output); + } + } + + //public class TLBotInlineMediaResultDocument : TLBotInlineResultBase, IMediaGif + //{ + // public const uint Signature = TLConstructors.TLBotInlineMediaResultDocument; + + // public TLDocumentBase Document { get; set; } + + // public TLBotInlineMediaResultDocument ThumbSelf { get { return this; } } + + // private double _downloadingProgress; + + // public double DownloadingProgress + // { + // get { return _downloadingProgress; } + // set { SetField(ref _downloadingProgress, value, () => DownloadingProgress); } + // } + + // public double LastProgress { get; set; } + // public bool IsCanceled { get; set; } + // public string IsoFileName { get; set; } + // public bool? AutoPlayGif { get; set; } + // public bool Forbidden { get; set; } + + // public override string ToString() + // { + // return string.Format("TLBotInlineMediaResultDocument id={0} type={1} document={2} send_message={3}", Id, Type, Document, SendMessage); + // } + + // public override TLObject FromBytes(byte[] bytes, ref int position) + // { + // bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + // Id = GetObject(bytes, ref position); + // Type = GetObject(bytes, ref position); + // Document = GetObject(bytes, ref position); + // SendMessage = GetObject(bytes, ref position); + + // return this; + // } + + // public override byte[] ToBytes() + // { + // return TLUtils.Combine( + // TLUtils.SignatureToBytes(Signature), + // Id.ToBytes(), + // Type.ToBytes(), + // Document.ToBytes(), + // SendMessage.ToBytes()); + // } + + // public override TLObject FromStream(Stream input) + // { + // Id = GetObject(input); + // Type = GetObject(input); + // Document = GetObject(input); + // SendMessage = GetObject(input); + + // return this; + // } + + // public override void ToStream(Stream output) + // { + // output.Write(TLUtils.SignatureToBytes(Signature)); + // Id.ToStream(output); + // Type.ToStream(output); + // Document.ToStream(output); + // SendMessage.ToStream(output); + // } + //} + + public class TLBotInlineMediaResultPhoto : TLBotInlineResultBase + { + public const uint Signature = TLConstructors.TLBotInlineMediaResultPhoto; + + public TLPhotoBase Photo { get; set; } + + public override string ToString() + { + return string.Format("TLBotInlineMediaResultPhoto id={0} type={1} photo={2} send_message={3}", Id, Type, Photo, SendMessage); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Type = GetObject(bytes, ref position); + Photo = GetObject(bytes, ref position); + SendMessage = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Type.ToBytes(), + Photo.ToBytes(), + SendMessage.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Type = GetObject(input); + Photo = GetObject(input); + SendMessage = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + Type.ToStream(output); + Photo.ToStream(output); + SendMessage.ToStream(output); + } + } + + public class TLBotInlineResult : TLBotInlineResultBase, IMediaGif + { + public const uint Signature = TLConstructors.TLBotInlineResult; + + public TLInt Flags { get; set; } + + public TLString Title { get; set; } + + public TLString Description { get; set; } + + public TLString Url { get; set; } + + public virtual TLString ThumbUrl { get; protected set; } + + public string ThumbUrlString { get { return ThumbUrl != null ? ThumbUrl.ToString() : string.Empty; } } + + public virtual TLString ContentUrl { get; protected set; } + + public string ContentUrlString { get { return ContentUrl != null ? ContentUrl.ToString() : string.Empty; } } + + public virtual TLString ContentType { get; protected set; } + + public virtual TLInt W { get; protected set; } + + public virtual TLInt H { get; protected set; } + + public virtual TLInt Duration { get; protected set; } + + public static string BotInlineResultFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (BotInlineResultFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public override string ToString() + { + return string.Format("TLBotInlineResult flags={0} type={2} id={1} title={3} description={4} url={5} thumb_url={6} content_url={7} content_type={8} w={9} h={10} duration={11} send_message=[{12}]", + BotInlineResultFlagsString(Flags), Id, Type, Title, Description, Url, ThumbUrl, ContentUrl, ContentType, W, H, Duration, SendMessage); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + Type = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)BotInlineResultFlags.Title)) + { + Title = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)BotInlineResultFlags.Description)) + { + Description = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)BotInlineResultFlags.Url)) + { + Url = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)BotInlineResultFlags.Thumb)) + { + ThumbUrl = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)BotInlineResultFlags.Content)) + { + ContentUrl = GetObject(bytes, ref position); + ContentType = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)BotInlineResultFlags.Size)) + { + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)BotInlineResultFlags.Duration)) + { + Duration = GetObject(bytes, ref position); + } + + SendMessage = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + Type.ToBytes(), + ToBytes(Title, Flags, (int)InputBotInlineResultFlags.Title), + ToBytes(Description, Flags, (int)InputBotInlineResultFlags.Description), + ToBytes(Url, Flags, (int)InputBotInlineResultFlags.Url), + ToBytes(ThumbUrl, Flags, (int)InputBotInlineResultFlags.Thumb), + ToBytes(ContentUrl, Flags, (int)InputBotInlineResultFlags.Content), + ToBytes(ContentType, Flags, (int)InputBotInlineResultFlags.Content), + ToBytes(W, Flags, (int)InputBotInlineResultFlags.Size), + ToBytes(H, Flags, (int)InputBotInlineResultFlags.Size), + ToBytes(Duration, Flags, (int)InputBotInlineResultFlags.Duration), + SendMessage.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Type = GetObject(input); + if (IsSet(Flags, (int)InputBotInlineResultFlags.Title)) + { + Title = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Description)) + { + Description = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Url)) + { + Url = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Thumb)) + { + ThumbUrl = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Content)) + { + ContentUrl = GetObject(input); + ContentType = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Size)) + { + W = GetObject(input); + H = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Duration)) + { + Duration = GetObject(input); + } + SendMessage = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + Type.ToStream(output); + ToStream(output, Title, Flags, (int)InputBotInlineResultFlags.Title); + ToStream(output, Description, Flags, (int)InputBotInlineResultFlags.Description); + ToStream(output, Url, Flags, (int)InputBotInlineResultFlags.Url); + ToStream(output, ThumbUrl, Flags, (int)InputBotInlineResultFlags.Thumb); + ToStream(output, ContentUrl, Flags, (int)InputBotInlineResultFlags.Content); + ToStream(output, ContentType, Flags, (int)InputBotInlineResultFlags.Content); + ToStream(output, W, Flags, (int)InputBotInlineResultFlags.Size); + ToStream(output, H, Flags, (int)InputBotInlineResultFlags.Size); + ToStream(output, Duration, Flags, (int)InputBotInlineResultFlags.Duration); + SendMessage.ToStream(output); + } + + public TLBotInlineResult ThumbSelf { get { return this; } } + + #region IGifMedia + + private TLDocumentBase _document; + + public TLDocumentBase Document + { + get + { + if (_document != null) return _document; + + if (TLString.Equals(Type, new TLString("gif"), StringComparison.OrdinalIgnoreCase)) + { + var document = new TLDocumentExternal(); + document.Id = TLLong.Random(); + document.ResultId = Id; + document.Type = Type; + document.Url = Url ?? TLString.Empty; + document.ThumbUrl = ThumbUrl ?? TLString.Empty; + document.ContentUrl = ContentUrl ?? TLString.Empty; + document.ContentType = ContentType ?? TLString.Empty; + document.Attributes = new TLVector{ new TLDocumentAttributeAnimated() }; + if (W != null && H != null && W.Value > 0 && H.Value > 0) + { + var duration = Duration ?? new TLInt(0); + + var videoAttribute = new TLDocumentAttributeVideo66 { Flags = new TLInt(0), W = W, H = H, Duration = duration }; + document.Attributes.Add(videoAttribute); + } + + _document = document; + } + else if (TLString.Equals(Type, new TLString("photo"), StringComparison.OrdinalIgnoreCase)) + { + + } + + return _document; + } + } + + private double _downloadingProgress; + + public double DownloadingProgress + { + get { return _downloadingProgress; } + set { SetField(ref _downloadingProgress, value, () => DownloadingProgress); } + } + + public double LastProgress { get; set; } + + public bool IsCanceled { get; set; } + + public string IsoFileName { get; set; } + + public bool? AutoPlayGif { get; set; } + + public bool Forbidden { get; set; } + #endregion + } + + + public class TLBotInlineResult76 : TLBotInlineResult + { + public new const uint Signature = TLConstructors.TLBotInlineResult76; + + public TLWebDocumentBase Thumb { get; set; } + + public override TLString ThumbUrl + { + get { return Thumb != null ? Thumb.Url : null; } + } + + public TLWebDocumentBase Content { get; set; } + + public override TLString ContentUrl + { + get { return Content != null ? Content.Url : null; } + } + + public override TLString ContentType + { + get { return Content != null ? Content.MimeType : null; } + } + + public override TLInt W + { + get { return Content != null ? Content.W : null; } + } + + public override TLInt H + { + get { return Content != null ? Content.H : null; } + } + + public override TLInt Duration + { + get { return Content != null ? Content.Duration : null; } + } + + public override string ToString() + { + return string.Format("TLBotInlineResult76 flags={0} type={2} id={1} title={3} description={4} url={5} thumb_url={6} content_url={7} content_type={8} w={9} h={10} duration={11} send_message=[{12}]", + BotInlineResultFlagsString(Flags), Id, Type, Title, Description, Url, ThumbUrl, ContentUrl, ContentType, W, H, Duration, SendMessage); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + Type = GetObject(bytes, ref position); + Title = GetObject(Flags, (int)BotInlineResultFlags.Title, null, bytes, ref position); + Description = GetObject(Flags, (int)BotInlineResultFlags.Description, null, bytes, ref position); + Url = GetObject(Flags, (int)BotInlineResultFlags.Url, null, bytes, ref position); + Thumb = GetObject(Flags, (int)BotInlineResultFlags.Thumb, null, bytes, ref position); + Content = GetObject(Flags, (int)BotInlineResultFlags.Content, null, bytes, ref position); + SendMessage = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + Type.ToBytes(), + ToBytes(Title, Flags, (int)BotInlineResultFlags.Title), + ToBytes(Description, Flags, (int)BotInlineResultFlags.Description), + ToBytes(Url, Flags, (int)BotInlineResultFlags.Url), + ToBytes(Thumb, Flags, (int)BotInlineResultFlags.Thumb), + ToBytes(Content, Flags, (int)BotInlineResultFlags.Content), + SendMessage.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Type = GetObject(input); + Title = GetObject(Flags, (int)BotInlineResultFlags.Title, null, input); + Description = GetObject(Flags, (int)BotInlineResultFlags.Description, null, input); + Url = GetObject(Flags, (int)BotInlineResultFlags.Url, null, input); + Thumb = GetObject(Flags, (int)BotInlineResultFlags.Thumb, null, input); + Content = GetObject(Flags, (int)BotInlineResultFlags.Content, null, input); + SendMessage = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + Type.ToStream(output); + ToStream(output, Title, Flags, (int)BotInlineResultFlags.Title); + ToStream(output, Description, Flags, (int)BotInlineResultFlags.Description); + ToStream(output, Url, Flags, (int)BotInlineResultFlags.Url); + ToStream(output, Thumb, Flags, (int)BotInlineResultFlags.Thumb); + ToStream(output, Content, Flags, (int)BotInlineResultFlags.Content); + SendMessage.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLBotResults.cs b/Telegram.Api/TL/TLBotResults.cs new file mode 100755 index 0000000..f8c3098 --- /dev/null +++ b/Telegram.Api/TL/TLBotResults.cs @@ -0,0 +1,243 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum BotResultsFlags + { + Gallery = 0x1, // 0 + NextOffset = 0x2, // 1 + SwitchPM = 0x4, // 2 + } + + public class TLBotResults72 : TLBotResults58 + { + public new const uint Signature = TLConstructors.TLBotResults72; + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + QueryId = GetObject(bytes, ref position); + NextOffset = GetObject(Flags, (int)BotResultsFlags.NextOffset, null, bytes, ref position); + SwitchPM = GetObject(Flags, (int)BotResultsFlags.SwitchPM, null, bytes, ref position); + Results = GetObject>(bytes, ref position); + CacheTime = GetObject(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + QueryId.ToBytes(), + ToBytes(NextOffset, Flags, (int)BotResultsFlags.NextOffset), + ToBytes(SwitchPM, Flags, (int)BotResultsFlags.SwitchPM), + Results.ToBytes(), + CacheTime.ToBytes(), + Users.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + QueryId = GetObject(input); + NextOffset = GetObject(Flags, (int)BotResultsFlags.NextOffset, null, input); + SwitchPM = GetObject(Flags, (int)BotResultsFlags.SwitchPM, null, input); + Results = GetObject>(input); + CacheTime = GetObject(input); + Users = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + QueryId.ToStream(output); + ToStream(output, NextOffset, Flags, (int)BotResultsFlags.NextOffset); + ToStream(output, SwitchPM, Flags, (int)BotResultsFlags.SwitchPM); + Results.ToStream(output); + CacheTime.ToStream(output); + Users.ToStream(output); + } + } + + public class TLBotResults58 : TLBotResults51, ICachedObject + { + public new const uint Signature = TLConstructors.TLBotResults58; + + public TLInt CacheTime { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + QueryId = GetObject(bytes, ref position); + NextOffset = GetObject(Flags, (int)BotResultsFlags.NextOffset, null, bytes, ref position); + SwitchPM = GetObject(Flags, (int)BotResultsFlags.SwitchPM, null, bytes, ref position); + Results = GetObject>(bytes, ref position); + CacheTime = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + QueryId.ToBytes(), + ToBytes(NextOffset, Flags, (int)BotResultsFlags.NextOffset), + ToBytes(SwitchPM, Flags, (int)BotResultsFlags.SwitchPM), + Results.ToBytes(), + CacheTime.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + QueryId = GetObject(input); + NextOffset = GetObject(Flags, (int)BotResultsFlags.NextOffset, null, input); + SwitchPM = GetObject(Flags, (int)BotResultsFlags.SwitchPM, null, input); + Results = GetObject>(input); + CacheTime = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + QueryId.ToStream(output); + ToStream(output, NextOffset, Flags, (int)BotResultsFlags.NextOffset); + ToStream(output, SwitchPM, Flags, (int)BotResultsFlags.SwitchPM); + Results.ToStream(output); + CacheTime.ToStream(output); + } + } + + public class TLBotResults51 : TLBotResults + { + public new const uint Signature = TLConstructors.TLBotResults51; + + public TLInlineBotSwitchPM SwitchPM { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + QueryId = GetObject(bytes, ref position); + NextOffset = GetObject(Flags, (int)BotResultsFlags.NextOffset, null, bytes, ref position); + SwitchPM = GetObject(Flags, (int)BotResultsFlags.SwitchPM, null, bytes, ref position); + Results = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + QueryId.ToBytes(), + ToBytes(NextOffset, Flags, (int)BotResultsFlags.NextOffset), + ToBytes(SwitchPM, Flags, (int)BotResultsFlags.SwitchPM), + Results.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + QueryId = GetObject(input); + NextOffset = GetObject(Flags, (int)BotResultsFlags.NextOffset, null, input); + SwitchPM = GetObject(Flags, (int)BotResultsFlags.SwitchPM, null, input); + Results = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + QueryId.ToStream(output); + ToStream(output, NextOffset, Flags, (int)BotResultsFlags.NextOffset); + ToStream(output, SwitchPM, Flags, (int)BotResultsFlags.SwitchPM); + Results.ToStream(output); + } + } + + public class TLBotResults : TLBotInlineResultBase + { + public const uint Signature = TLConstructors.TLBotResults; + + public TLInt Flags { get; set; } + + public bool Gallery { get { return IsSet(Flags, (int)BotResultsFlags.Gallery); } } + + public TLString NextOffset { get; set; } + + public TLVector Results { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + QueryId = GetObject(bytes, ref position); + NextOffset = GetObject(Flags, (int) BotResultsFlags.NextOffset, null, bytes, ref position); + Results = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + QueryId.ToBytes(), + ToBytes(NextOffset, Flags, (int)BotResultsFlags.NextOffset), + Results.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + QueryId = GetObject(input); + NextOffset = GetObject(Flags, (int)BotResultsFlags.NextOffset, null, input); + Results = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + QueryId.ToStream(output); + ToStream(output, NextOffset, Flags, (int)BotResultsFlags.NextOffset); + Results.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLCallsSecurity.cs b/Telegram.Api/TL/TLCallsSecurity.cs new file mode 100755 index 0000000..2944cd9 --- /dev/null +++ b/Telegram.Api/TL/TLCallsSecurity.cs @@ -0,0 +1,94 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum CallsSecurityFlags + { + PeerToPeer = 0x1, + + PeerToPeerEverybody = 0x4, + PeerToPeerContacts = 0x8, + PeetToPeerNobody = 0x10 + } + + public class TLCallsSecurity : TLObject + { + public const uint Signature = TLConstructors.TLCallsSecurity; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool PeerToPeer + { + get { return IsSet(Flags, (int) CallsSecurityFlags.PeerToPeer); } + set { SetUnset(ref _flags, value, (int) CallsSecurityFlags.PeerToPeer); } + } + + public bool PeerToPeerEverybody + { + get { return IsSet(Flags, (int)CallsSecurityFlags.PeerToPeerEverybody); } + set { SetUnset(ref _flags, value, (int)CallsSecurityFlags.PeerToPeerEverybody); } + } + + public bool PeerToPeerContacts + { + get { return IsSet(Flags, (int)CallsSecurityFlags.PeerToPeerContacts); } + set { SetUnset(ref _flags, value, (int)CallsSecurityFlags.PeerToPeerContacts); } + } + + public bool PeerToPeerNobody + { + get { return IsSet(Flags, (int)CallsSecurityFlags.PeetToPeerNobody); } + set { SetUnset(ref _flags, value, (int)CallsSecurityFlags.PeetToPeerNobody); } + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + } + + public void Update(bool defaultP2PContacts) + { + var updated = PeerToPeerEverybody || PeerToPeerContacts || PeerToPeerNobody; + + if (!updated) + { + if (PeerToPeer) + { + PeerToPeerEverybody = false; + PeerToPeerContacts = defaultP2PContacts; + PeerToPeerNobody = !defaultP2PContacts; + } + else + { + PeerToPeerEverybody = false; + PeerToPeerContacts = false; + PeerToPeerNobody = true; + } + } + } + } +} diff --git a/Telegram.Api/TL/TLCameraSettings.cs b/Telegram.Api/TL/TLCameraSettings.cs new file mode 100755 index 0000000..0514350 --- /dev/null +++ b/Telegram.Api/TL/TLCameraSettings.cs @@ -0,0 +1,68 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum CameraSettingsFlags + { + External = 0x1, // 0 + } + + public class TLCameraSettings : TLObject + { + public const uint Signature = TLConstructors.TLCameraSettings; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool External + { + get { return IsSet(Flags, (int) CameraSettingsFlags.External); } + set { SetUnset(ref _flags, value, (int) CameraSettingsFlags.External); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLCdnConfig.cs b/Telegram.Api/TL/TLCdnConfig.cs new file mode 100755 index 0000000..4ebaa17 --- /dev/null +++ b/Telegram.Api/TL/TLCdnConfig.cs @@ -0,0 +1,41 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLCdnConfig : TLObject + { + public const uint Signature = TLConstructors.TLCdnConfig; + + public TLVector PublicKeys { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PublicKeys = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PublicKeys = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PublicKeys.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLCdnFile.cs b/Telegram.Api/TL/TLCdnFile.cs new file mode 100755 index 0000000..19398b2 --- /dev/null +++ b/Telegram.Api/TL/TLCdnFile.cs @@ -0,0 +1,43 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLCdnFileBase : TLObject { } + + public class TLCdnFile : TLCdnFileBase + { + public const uint Signature = TLConstructors.TLCdnFile; + + public TLString Bytes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Bytes = GetObject(bytes, ref position); + + return this; + } + } + + public class TLCdnFileReuploadNeeded : TLCdnFileBase + { + public const uint Signature = TLConstructors.TLCdnFileReuploadNeeded; + + public TLString RequestToken { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + RequestToken = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLCdnPublicKey.cs b/Telegram.Api/TL/TLCdnPublicKey.cs new file mode 100755 index 0000000..b48171a --- /dev/null +++ b/Telegram.Api/TL/TLCdnPublicKey.cs @@ -0,0 +1,78 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public enum CdnPublicKeyCustomFlags + { + PublicKeyFingerprint = 0x1 + } + + public class TLCdnPublicKey : TLObject + { + public const uint Signature = TLConstructors.TLCdnPublicKey; + + public TLInt DCId { get; set; } + + public TLString PublicKey { get; set; } + + #region Additional + + private TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + private TLLong _publicKeyFingerprint; + + public TLLong PublicKeyFingerprint + { + get { return _publicKeyFingerprint; } + set { SetField(out _publicKeyFingerprint, value, ref _customFlags, (int) CdnPublicKeyCustomFlags.PublicKeyFingerprint); } + } + + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + DCId = GetObject(bytes, ref position); + PublicKey = GetObject(bytes, ref position); + + CustomFlags = new TLLong(0); + + return this; + } + + public override TLObject FromStream(Stream input) + { + DCId = GetObject(input); + PublicKey = GetObject(input); + CustomFlags = GetObject(input); + _publicKeyFingerprint = GetObject(CustomFlags, (int) CdnPublicKeyCustomFlags.PublicKeyFingerprint, null, input); + + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + DCId.ToStream(output); + PublicKey.ToStream(output); + CustomFlags.ToStream(output); + ToStream(output, _publicKeyFingerprint, CustomFlags, (int)CdnPublicKeyCustomFlags.PublicKeyFingerprint); + } + } +} diff --git a/Telegram.Api/TL/TLChannelAdminLogEvent.cs b/Telegram.Api/TL/TLChannelAdminLogEvent.cs new file mode 100755 index 0000000..4139a78 --- /dev/null +++ b/Telegram.Api/TL/TLChannelAdminLogEvent.cs @@ -0,0 +1,56 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLChannelAdminLogEvent : TLObject + { + public const uint Signature = TLConstructors.TLChannelAdminLogEvent; + + public TLLong Id { get; set; } + + public TLInt Date { get; set; } + + public TLInt UserId { get; set; } + + public TLChannelAdminLogEventActionBase Action { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Action = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Date = GetObject(input); + UserId = GetObject(input); + Action = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + Date.ToStream(output); + UserId.ToStream(output); + Action.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLChannelAdminLogEventAction.cs b/Telegram.Api/TL/TLChannelAdminLogEventAction.cs new file mode 100755 index 0000000..cfa5a56 --- /dev/null +++ b/Telegram.Api/TL/TLChannelAdminLogEventAction.cs @@ -0,0 +1,504 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLChannelAdminLogEventActionBase : TLObject { } + + public class TLChannelAdminLogEventActionChangeTitle : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionChangeTitle; + + public TLString PrevValue { get; set; } + + public TLString NewValue { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PrevValue = GetObject(bytes, ref position); + NewValue = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PrevValue = GetObject(input); + NewValue = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PrevValue.ToStream(output); + NewValue.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionChangeAbout : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionChangeAbout; + + public TLString PrevValue { get; set; } + + public TLString NewValue { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PrevValue = GetObject(bytes, ref position); + NewValue = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PrevValue = GetObject(input); + NewValue = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PrevValue.ToStream(output); + NewValue.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionChangeUsername : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionChangeUsername; + + public TLString PrevValue { get; set; } + + public TLString NewValue { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PrevValue = GetObject(bytes, ref position); + NewValue = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PrevValue = GetObject(input); + NewValue = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PrevValue.ToStream(output); + NewValue.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionChangePhoto : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionChangePhoto; + + public TLPhotoBase PrevPhoto { get; set; } + + public TLPhotoBase NewPhoto { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PrevPhoto = GetObject(bytes, ref position); + NewPhoto = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PrevPhoto = GetObject(input); + NewPhoto = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PrevPhoto.ToStream(output); + NewPhoto.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionToggleInvites : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionToggleInvites; + + public TLBool NewValue { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + NewValue = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + NewValue = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + NewValue.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionToggleSignatures : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionToggleSignatures; + + public TLBool NewValue { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + NewValue = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + NewValue = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + NewValue.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionUpdatePinned : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionUpdatePinned; + + public TLMessageBase Message { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Message = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Message.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionEditMessage : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionEditMessage; + + public TLMessageBase PrevMessage { get; set; } + + public TLMessageBase NewMessage { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PrevMessage = GetObject(bytes, ref position); + NewMessage = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PrevMessage = GetObject(input); + NewMessage = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PrevMessage.ToStream(output); + NewMessage.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionDeleteMessage : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionDeleteMessage; + + public TLMessageBase Message { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Message = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Message.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionParticipantJoin : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionParticipantJoin; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLChannelAdminLogEventActionParticipantLeave : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionParticipantLeave; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLChannelAdminLogEventActionParticipantInvite : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionParticipantInvite; + + public TLChannelParticipantBase Participant { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Participant = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Participant = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Participant.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionParticipantToggleBan : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionParticipantToggleBan; + + public TLChannelParticipantBase PrevParticipant { get; set; } + + public TLChannelParticipantBase NewParticipant { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PrevParticipant = GetObject(bytes, ref position); + NewParticipant = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PrevParticipant = GetObject(input); + NewParticipant = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PrevParticipant.ToStream(output); + NewParticipant.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionParticipantToggleAdmin : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionParticipantToggleAdmin; + + public TLChannelParticipantBase PrevParticipant { get; set; } + + public TLChannelParticipantBase NewParticipant { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PrevParticipant = GetObject(bytes, ref position); + NewParticipant = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PrevParticipant = GetObject(input); + NewParticipant = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PrevParticipant.ToStream(output); + NewParticipant.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionChangeStickerSet : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionChangeStickerSet; + + public TLInputStickerSetBase PrevStickerSet { get; set; } + + public TLInputStickerSetBase NewStickerSet { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PrevStickerSet = GetObject(bytes, ref position); + NewStickerSet = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PrevStickerSet = GetObject(input); + NewStickerSet = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PrevStickerSet.ToStream(output); + NewStickerSet.ToStream(output); + } + } + + public class TLChannelAdminLogEventActionTogglePreHistoryHidden : TLChannelAdminLogEventActionBase + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventActionTogglePreHistoryHidden; + + public TLBool NewValue { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + NewValue = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + NewValue = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + NewValue.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLChannelAdminLogEventsFilter.cs b/Telegram.Api/TL/TLChannelAdminLogEventsFilter.cs new file mode 100755 index 0000000..b58b816 --- /dev/null +++ b/Telegram.Api/TL/TLChannelAdminLogEventsFilter.cs @@ -0,0 +1,158 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ChannelAdminLogEventsFilterFlags + { + Join = 0x1, + Leave = 0x2, + Invite = 0x4, + Ban = 0x8, + Unban = 0x10, + Kick = 0x20, + Unkick = 0x40, + Promote = 0x80, + Demote = 0x100, + Info = 0x200, + Settings = 0x400, + Pinned = 0x800, + Edit = 0x1000, + Delete = 0x2000, + } + + public class TLChannelAdminLogEventsFilter : TLObject + { + public const uint Signature = TLConstructors.TLChannelAdminLogEventsFilter; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Join + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Join); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Join); } + } + + public bool Leave + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Leave); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Leave); } + } + + public bool Invite + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Invite); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Invite); } + } + + public bool Ban + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Ban); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Ban); } + } + + public bool Unban + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Unban); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Unban); } + } + + public bool Kick + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Kick); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Kick); } + } + + public bool Unkick + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Unkick); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Unkick); } + } + + public bool Promote + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Promote); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Promote); } + } + + public bool Demote + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Demote); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Demote); } + } + + public bool Info + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Info); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Info); } + } + + public bool Settings + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Settings); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Settings); } + } + + public bool Pinned + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Pinned); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Pinned); } + } + + public bool Edit + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Edit); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Edit); } + } + + public bool Delete + { + get { return IsSet(_flags, (int)ChannelAdminLogEventsFilterFlags.Delete); } + set { SetUnset(ref _flags, value, (int)ChannelAdminLogEventsFilterFlags.Delete); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLChannelAdminRights.cs b/Telegram.Api/TL/TLChannelAdminRights.cs new file mode 100755 index 0000000..025fa49 --- /dev/null +++ b/Telegram.Api/TL/TLChannelAdminRights.cs @@ -0,0 +1,124 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ChannelAdminRightsFlags + { + ChannelInfo = 0x1, + PostMessages = 0x2, + EditMessages = 0x4, + DeleteMessages = 0x8, + BanUsers = 0x10, + InviteUsers = 0x20, + InviteLinks = 0x40, + PinMessages = 0x80, + + AddAdmins = 0x200, + } + + public class TLChannelAdminRights : TLObject + { + public const uint Signature = TLConstructors.TLChannelAdminRights; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool ChannelInfo + { + get { return IsSet(_flags, (int)ChannelAdminRightsFlags.ChannelInfo); } + set { SetUnset(ref _flags, value, (int)ChannelAdminRightsFlags.ChannelInfo); } + } + + public bool PostMessages + { + get { return IsSet(_flags, (int)ChannelAdminRightsFlags.PostMessages); } + set { SetUnset(ref _flags, value, (int)ChannelAdminRightsFlags.PostMessages); } + } + + public bool EditMessages + { + get { return IsSet(_flags, (int)ChannelAdminRightsFlags.EditMessages); } + set { SetUnset(ref _flags, value, (int)ChannelAdminRightsFlags.EditMessages); } + } + + public bool DeleteMessages + { + get { return IsSet(_flags, (int)ChannelAdminRightsFlags.DeleteMessages); } + set { SetUnset(ref _flags, value, (int)ChannelAdminRightsFlags.DeleteMessages); } + } + + public bool BanUsers + { + get { return IsSet(_flags, (int)ChannelAdminRightsFlags.BanUsers); } + set { SetUnset(ref _flags, value, (int)ChannelAdminRightsFlags.BanUsers); } + } + + public bool InviteUsers + { + get { return IsSet(_flags, (int)ChannelAdminRightsFlags.InviteUsers); } + set { SetUnset(ref _flags, value, (int)ChannelAdminRightsFlags.InviteUsers); } + } + + public bool InviteLinks + { + get { return IsSet(_flags, (int)ChannelAdminRightsFlags.InviteLinks); } + set { SetUnset(ref _flags, value, (int)ChannelAdminRightsFlags.InviteLinks); } + } + + public bool PinMessages + { + get { return IsSet(_flags, (int)ChannelAdminRightsFlags.PinMessages); } + set { SetUnset(ref _flags, value, (int)ChannelAdminRightsFlags.PinMessages); } + } + + public bool AddAdmins + { + get { return IsSet(_flags, (int)ChannelAdminRightsFlags.AddAdmins); } + set { SetUnset(ref _flags, value, (int)ChannelAdminRightsFlags.AddAdmins); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLChannelBannedRights.cs b/Telegram.Api/TL/TLChannelBannedRights.cs new file mode 100755 index 0000000..fd20dfd --- /dev/null +++ b/Telegram.Api/TL/TLChannelBannedRights.cs @@ -0,0 +1,114 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ChannelBannedRightsFlags + { + ViewMessages = 0x1, + SendMessages = 0x2, + SendMedia = 0x4, + SendStickers = 0x8, + SendGifs = 0x10, + SendGames = 0x20, + SendInline = 0x40, + EmbedLinks = 0x80, + } + + public class TLChannelBannedRights : TLObject + { + public const uint Signature = TLConstructors.TLChannelBannedRights; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt UntilDate { get; set; } + + public bool ViewMessages + { + get { return IsSet(_flags, (int)ChannelBannedRightsFlags.ViewMessages); } + set { SetUnset(ref _flags, value, (int)ChannelBannedRightsFlags.ViewMessages); } + } + + public bool SendMessages + { + get { return IsSet(_flags, (int)ChannelBannedRightsFlags.SendMessages); } + set { SetUnset(ref _flags, value, (int)ChannelBannedRightsFlags.SendMessages); } + } + + public bool SendMedia + { + get { return IsSet(_flags, (int)ChannelBannedRightsFlags.SendMedia); } + set { SetUnset(ref _flags, value, (int)ChannelBannedRightsFlags.SendMedia); } + } + + public bool SendStickers + { + get { return IsSet(_flags, (int)ChannelBannedRightsFlags.SendStickers); } + set { SetUnset(ref _flags, value, (int)ChannelBannedRightsFlags.SendStickers); } + } + + public bool SendGifs + { + get { return IsSet(_flags, (int)ChannelBannedRightsFlags.SendGifs); } + set { SetUnset(ref _flags, value, (int)ChannelBannedRightsFlags.SendGifs); } + } + + public bool SendGames + { + get { return IsSet(_flags, (int)ChannelBannedRightsFlags.SendGames); } + set { SetUnset(ref _flags, value, (int)ChannelBannedRightsFlags.SendGames); } + } + + public bool SendInline + { + get { return IsSet(_flags, (int)ChannelBannedRightsFlags.SendInline); } + set { SetUnset(ref _flags, value, (int)ChannelBannedRightsFlags.SendInline); } + } + + public bool EmbedLinks + { + get { return IsSet(_flags, (int)ChannelBannedRightsFlags.EmbedLinks); } + set { SetUnset(ref _flags, value, (int)ChannelBannedRightsFlags.EmbedLinks); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + UntilDate = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + UntilDate = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + UntilDate.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLChannelDifference.cs b/Telegram.Api/TL/TLChannelDifference.cs new file mode 100755 index 0000000..dfe59dc --- /dev/null +++ b/Telegram.Api/TL/TLChannelDifference.cs @@ -0,0 +1,344 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ChannelDifferenceFlags + { + Final = 0x1, + Timeout = 0x2 + } + + public abstract class TLChannelDifferenceBase : TLObject + { + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt Pts { get; set; } + + protected TLInt _timeout; + + public TLInt Timeout + { + get { return _timeout; } + set { SetField(out _timeout, value, ref _flags, (int) ChannelDifferenceFlags.Timeout); } + } + } + + public class TLChannelDifferenceEmpty : TLChannelDifferenceBase + { + public const uint Signature = TLConstructors.TLChannelDifferenceEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + _timeout = GetObject(Flags, (int) ChannelDifferenceFlags.Timeout, null, bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Pts.ToStream(output); + ToStream(output, Timeout, Flags, (int) ChannelDifferenceFlags.Timeout); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Pts = GetObject(input); + _timeout = GetObject(Flags, (int)ChannelDifferenceFlags.Timeout, null, input); + + return this; + } + + public override string ToString() + { + return string.Format("TLChannelDifferenceEmpty flags={0} pts={1} timeout={2}", Flags, Pts, Timeout); + } + } + + public class TLChannelDifferenceTooLong : TLChannelDifferenceBase + { + public const uint Signature = TLConstructors.TLChannelDifferenceTooLong; + + public TLInt TopMessage { get; set; } + + public TLInt TopImportantMessage { get; set; } + + public TLInt ReadInboxMaxId { get; set; } + + public TLInt UnreadCount { get; set; } + + public TLInt UnreadMentionsCount { get; set; } + + public TLVector Messages { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + _timeout = GetObject(Flags, (int)ChannelDifferenceFlags.Timeout, null, bytes, ref position); + TopMessage = GetObject(bytes, ref position); + TopImportantMessage = GetObject(bytes, ref position); + ReadInboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadMentionsCount = GetObject(bytes, ref position); + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Pts.ToStream(output); + ToStream(output, Timeout, Flags, (int)ChannelDifferenceFlags.Timeout); + TopMessage.ToStream(output); + TopImportantMessage.ToStream(output); + ReadInboxMaxId.ToStream(output); + UnreadCount.ToStream(output); + UnreadMentionsCount.ToStream(output); + Messages.ToStream(output); + Chats.ToStream(output); + Users.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Pts = GetObject(input); + _timeout = GetObject(Flags, (int)ChannelDifferenceFlags.Timeout, null, input); + TopMessage = GetObject(input); + TopImportantMessage = GetObject(input); + ReadInboxMaxId = GetObject(input); + UnreadCount = GetObject(input); + UnreadMentionsCount = GetObject(input); + Messages = GetObject>(input); + Chats = GetObject>(input); + Users = GetObject>(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLChannelDifferenceTooLong flags={0} pts={1} timeout={2} new_messages={3}", Flags, Pts, Timeout, Messages.Count); + } + } + + public class TLChannelDifferenceTooLong53 : TLChannelDifferenceTooLong + { + public new const uint Signature = TLConstructors.TLChannelDifferenceTooLong53; + + public TLInt ReadOutboxMaxId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + _timeout = GetObject(Flags, (int)ChannelDifferenceFlags.Timeout, null, bytes, ref position); + TopMessage = GetObject(bytes, ref position); + TopImportantMessage = new TLInt(0); + ReadInboxMaxId = GetObject(bytes, ref position); + ReadOutboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadMentionsCount = new TLInt(0); + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Pts.ToStream(output); + ToStream(output, Timeout, Flags, (int)ChannelDifferenceFlags.Timeout); + TopMessage.ToStream(output); + ReadInboxMaxId.ToStream(output); + ReadOutboxMaxId.ToStream(output); + UnreadCount.ToStream(output); + Messages.ToStream(output); + Chats.ToStream(output); + Users.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Pts = GetObject(input); + _timeout = GetObject(Flags, (int)ChannelDifferenceFlags.Timeout, null, input); + TopMessage = GetObject(input); + TopImportantMessage = new TLInt(0); + ReadInboxMaxId = GetObject(input); + ReadOutboxMaxId = GetObject(input); + UnreadCount = GetObject(input); + UnreadMentionsCount = new TLInt(0); + Messages = GetObject>(input); + Chats = GetObject>(input); + Users = GetObject>(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLChannelDifferenceTooLong53 flags={0} pts={1} timeout={2} new_messages={3}", Flags, Pts, Timeout, Messages.Count); + } + } + + public class TLChannelDifferenceTooLong71 : TLChannelDifferenceTooLong53 + { + public new const uint Signature = TLConstructors.TLChannelDifferenceTooLong71; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + _timeout = GetObject(Flags, (int)ChannelDifferenceFlags.Timeout, null, bytes, ref position); + TopMessage = GetObject(bytes, ref position); + TopImportantMessage = new TLInt(0); + ReadInboxMaxId = GetObject(bytes, ref position); + ReadOutboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadMentionsCount = GetObject(bytes, ref position); + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Pts.ToStream(output); + ToStream(output, Timeout, Flags, (int)ChannelDifferenceFlags.Timeout); + TopMessage.ToStream(output); + ReadInboxMaxId.ToStream(output); + ReadOutboxMaxId.ToStream(output); + UnreadCount.ToStream(output); + UnreadMentionsCount.ToStream(output); + Messages.ToStream(output); + Chats.ToStream(output); + Users.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Pts = GetObject(input); + _timeout = GetObject(Flags, (int)ChannelDifferenceFlags.Timeout, null, input); + TopMessage = GetObject(input); + TopImportantMessage = new TLInt(0); + ReadInboxMaxId = GetObject(input); + ReadOutboxMaxId = GetObject(input); + UnreadCount = GetObject(input); + UnreadMentionsCount = GetObject(input); + Messages = GetObject>(input); + Chats = GetObject>(input); + Users = GetObject>(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLChannelDifferenceTooLong71 flags={0} pts={1} timeout={2} new_messages={3}", Flags, Pts, Timeout, Messages.Count); + } + } + + public class TLChannelDifference : TLChannelDifferenceBase + { + public const uint Signature = TLConstructors.TLChannelDifference; + + public TLVector NewMessages { get; set; } + + public TLVector OtherUpdates { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + _timeout = GetObject(Flags, (int)ChannelDifferenceFlags.Timeout, null, bytes, ref position); + NewMessages = GetObject>(bytes, ref position); + OtherUpdates = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Pts.ToStream(output); + ToStream(output, Timeout, Flags, (int)ChannelDifferenceFlags.Timeout); + NewMessages.ToStream(output); + OtherUpdates.ToStream(output); + Chats.ToStream(output); + Users.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Pts = GetObject(input); + _timeout = GetObject(Flags, (int)ChannelDifferenceFlags.Timeout, null, input); + NewMessages = GetObject>(input); + OtherUpdates = GetObject>(input); + Chats = GetObject>(input); + Users = GetObject>(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLChannelDifference flags={0} pts={1} timeout={2} new_messages={3} other_updates={4}", Flags, Pts, Timeout, NewMessages.Count, OtherUpdates.Count); + } + } +} diff --git a/Telegram.Api/TL/TLChannelMessagesFiler.cs b/Telegram.Api/TL/TLChannelMessagesFiler.cs new file mode 100755 index 0000000..83b9223 --- /dev/null +++ b/Telegram.Api/TL/TLChannelMessagesFiler.cs @@ -0,0 +1,88 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLChannelMessagesFilerBase : TLObject { } + + public class TLChannelMessagesFilterEmpty : TLChannelMessagesFilerBase + { + public const uint Signature = TLConstructors.TLChannelMessagesFilterEmpty; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLChannelMessagesFilter : TLChannelMessagesFilerBase + { + public const uint Signature = TLConstructors.TLChannelMessagesFilter; + + public TLInt Flags { get; set; } + + public TLVector Ranges { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Ranges.ToBytes() + ); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Ranges.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Ranges = GetObject>(input); + + return this; + } + } + + public class TLChannelMessagesFilterCollapsed : TLChannelMessagesFilerBase + { + public const uint Signature = TLConstructors.TLChannelMessagesFilterCollapsed; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } +} diff --git a/Telegram.Api/TL/TLChannelParticipant.cs b/Telegram.Api/TL/TLChannelParticipant.cs new file mode 100755 index 0000000..6f5582a --- /dev/null +++ b/Telegram.Api/TL/TLChannelParticipant.cs @@ -0,0 +1,354 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public enum ChannelParticipantBannedFlags + { + Left = 0x1 + } + + public enum ChannelParticipantAdminFlags + { + CanEdit = 0x1 + } + + public interface IChannelInviter + { + TLInt InviterId { get; set; } + + TLInt Date { get; set; } + } + + public abstract class TLChannelParticipantBase : TLObject + { + public TLInt UserId { get; set; } + } + + public class TLChannelParticipant : TLChannelParticipantBase + { + public const uint Signature = TLConstructors.TLChannelParticipant; + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + Date = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(UserId.ToBytes()); + output.Write(Date.ToBytes()); + } + } + + public class TLChannelParticipantSelf : TLChannelParticipantBase, IChannelInviter + { + public const uint Signature = TLConstructors.TLChannelParticipantSelf; + + public TLInt InviterId { get; set; } + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + InviterId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + InviterId = GetObject(input); + Date = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(UserId.ToBytes()); + output.Write(InviterId.ToBytes()); + output.Write(Date.ToBytes()); + } + } + + [Obsolete] + public class TLChannelParticipantModerator : TLChannelParticipantBase, IChannelInviter + { + public const uint Signature = TLConstructors.TLChannelParticipantModerator; + + public TLInt InviterId { get; set; } + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + InviterId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + InviterId = GetObject(input); + Date = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(UserId.ToBytes()); + output.Write(InviterId.ToBytes()); + output.Write(Date.ToBytes()); + } + } + + [Obsolete] + public class TLChannelParticipantEditor : TLChannelParticipantBase, IChannelInviter + { + public const uint Signature = TLConstructors.TLChannelParticipantEditor; + + public TLInt InviterId { get; set; } + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + InviterId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + InviterId = GetObject(input); + Date = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(UserId.ToBytes()); + output.Write(InviterId.ToBytes()); + output.Write(Date.ToBytes()); + } + } + + [Obsolete] + public class TLChannelParticipantKicked : TLChannelParticipantBase + { + public const uint Signature = TLConstructors.TLChannelParticipantKicked; + + public TLInt KickedBy { get; set; } + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + KickedBy = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + KickedBy = GetObject(input); + Date = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(UserId.ToBytes()); + output.Write(KickedBy.ToBytes()); + output.Write(Date.ToBytes()); + } + } + + public class TLChannelParticipantCreator : TLChannelParticipantBase + { + public const uint Signature = TLConstructors.TLChannelParticipantCreator; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(UserId.ToBytes()); + } + } + + public class TLChannelParticipantAdmin : TLChannelParticipantBase + { + public const uint Signature = TLConstructors.TLChannelParticipantAdmin; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool CanEdit + { + get { return IsSet(Flags, (int)ChannelParticipantAdminFlags.CanEdit); } + set { SetUnset(ref _flags, value, (int)ChannelParticipantAdminFlags.CanEdit); } + } + + public TLInt InviterId { get; set; } + + public TLInt PromotedById { get; set; } + + public TLInt Date { get; set; } + + public TLChannelAdminRights AdminRights { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + InviterId = GetObject(bytes, ref position); + PromotedById = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + AdminRights = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + UserId = GetObject(input); + InviterId = GetObject(input); + PromotedById = GetObject(input); + Date = GetObject(input); + AdminRights = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + UserId.ToStream(output); + InviterId.ToStream(output); + PromotedById.ToStream(output); + Date.ToStream(output); + AdminRights.ToStream(output); + } + } + + public class TLChannelParticipantBanned : TLChannelParticipantKicked + { + public new const uint Signature = TLConstructors.TLChannelParticipantBanned; + + public TLInt Flags { get; set; } + + public bool Left { get { return IsSet(Flags, (int) ChannelParticipantBannedFlags.Left); } } + + public TLChannelBannedRights BannedRights { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + KickedBy = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + BannedRights = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + UserId = GetObject(input); + KickedBy = GetObject(input); + Date = GetObject(input); + BannedRights = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + UserId.ToStream(output); + KickedBy.ToStream(output); + Date.ToStream(output); + BannedRights.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLChannelParticipantRole.cs b/Telegram.Api/TL/TLChannelParticipantRole.cs new file mode 100755 index 0000000..9dee0e6 --- /dev/null +++ b/Telegram.Api/TL/TLChannelParticipantRole.cs @@ -0,0 +1,99 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLChannelParticipantRoleBase : TLObject { } + + [Obsolete] + public class TLChannelRoleEmpty : TLChannelParticipantRoleBase + { + public const uint Signature = TLConstructors.TLChannelRoleEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + [Obsolete] + public class TLChannelRoleModerator : TLChannelParticipantRoleBase + { + public const uint Signature = TLConstructors.TLChannelRoleModerator; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + [Obsolete] + public class TLChannelRoleEditor : TLChannelParticipantRoleBase + { + public const uint Signature = TLConstructors.TLChannelRoleEditor; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLChannelParticipantsFilter.cs b/Telegram.Api/TL/TLChannelParticipantsFilter.cs new file mode 100755 index 0000000..f81b849 --- /dev/null +++ b/Telegram.Api/TL/TLChannelParticipantsFilter.cs @@ -0,0 +1,175 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLChannelParticipantsFilterBase : TLObject { } + + public class TLChannelParticipantsRecent : TLChannelParticipantsFilterBase + { + public const uint Signature = TLConstructors.TLChannelParticipantsRecent; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLChannelParticipantsAdmins : TLChannelParticipantsFilterBase + { + public const uint Signature = TLConstructors.TLChannelParticipantsAdmins; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLChannelParticipantsKicked68 : TLChannelParticipantsFilterBase + { + public const uint Signature = TLConstructors.TLChannelParticipantsKicked68; + + public TLString Q { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Q.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Q.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Q = GetObject(input); + + return this; + } + } + + public class TLChannelParticipantsKicked : TLChannelParticipantsFilterBase + { + public const uint Signature = TLConstructors.TLChannelParticipantsKicked; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLChannelParticipantsBots : TLChannelParticipantsFilterBase + { + public const uint Signature = TLConstructors.TLChannelParticipantsBots; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLChannelParticipantsBanned : TLChannelParticipantsFilterBase + { + public const uint Signature = TLConstructors.TLChannelParticipantsBanned; + + public TLString Q { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Q.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Q.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Q = GetObject(input); + + return this; + } + } + + public class TLChannelParticipantsSearch : TLChannelParticipantsFilterBase + { + public const uint Signature = TLConstructors.TLChannelParticipantsSearch; + + public TLString Q { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Q.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Q.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Q = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLChat.cs b/Telegram.Api/TL/TLChat.cs new file mode 100755 index 0000000..96487d7 --- /dev/null +++ b/Telegram.Api/TL/TLChat.cs @@ -0,0 +1,2245 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.IO; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL.Interfaces; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ChatFlags + { + Creator = 0x1, + Kicked = 0x2, + Left = 0x4, + AdminsEnabled = 0x8, + Admin = 0x10, + Deactivated = 0x20, + MigratedTo = 0x40 + } + + [Flags] + public enum ChatCustomFlags + { + ReadInboxMaxId = 0x1, + ReadOutboxMaxId = 0x2, + } + + [Flags] + public enum ChannelFlags + { + Creator = 0x1, + Kicked = 0x2, + Left = 0x4, + Editor = 0x8, + Moderator = 0x10, + Broadcast = 0x20, + Public = 0x40, + Verified = 0x80, + MegaGroup = 0x100, + Restricted = 0x200, + Democracy = 0x400, + Signatures = 0x800, + Min = 0x1000, + AccessHash = 0x2000, + AdminRights = 0x4000, + BannedRights = 0x8000, + UntilDate = 0x10000, + ParticipantsCount = 0x20000, + FeedId = 0x40000, + } + + [Flags] + public enum ChannelCustomFlags + { + MigratedFromChatId = 0x1, + MigratedFromMaxId = 0x2, + Silent = 0x4, + PinnedMsgId = 0x8, + HiddenPinnedMsgId = 0x10, + ReadOutboxMaxId = 0x20, + ReadInboxMaxId = 0x40, + CanSetStickers = 0x80, + StickerSet = 0x100, + AvailableMinId = 0x200, + HiddenPrehistory = 0x400 + } + + public abstract class TLChatBase : TLObject, IInputPeer, IFullName, INotifySettings + { + + public static string ChatFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (ChatFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public static string ChannelFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (ChannelFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public static string ChannelCustomFlagsString(TLLong flags) + { + if (flags == null) return string.Empty; + + var list = (ChannelCustomFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public int Index + { + get { return Id.Value; } + set { Id = new TLInt(value); } + } + + public TLInt Id { get; set; } + + public virtual void Update(TLChatBase chat) + { + Id = chat.Id; + + if (chat.Participants != null) + { + Participants = chat.Participants; + } + + if (chat.ChatPhoto != null) + { + ChatPhoto = chat.ChatPhoto; + } + + if (chat.NotifySettings != null) + { + NotifySettings = chat.NotifySettings; + } + } + + public abstract TLInputPeerBase ToInputPeer(); + + public abstract string GetUnsendedTextFileName(); + + #region Full chat information + + public TLChatParticipantsBase Participants { get; set; } + + public TLPhotoBase ChatPhoto { get; set; } + + public TLPeerNotifySettingsBase NotifySettings { get; set; } + + public int UsersOnline { get; set; } + + public TLExportedChatInvite ExportedInvite { get; set; } + #endregion + + public TLInputNotifyPeerBase ToInputNotifyPeer() + { + return new TLInputNotifyPeer { Peer = ToInputPeer() }; + } + + public abstract string FullName { get; } + + public virtual string FullName2 { get { return FullName; } } + + public virtual string ShortName { get { return FullName; } } + + public abstract bool IsForbidden { get; } + + #region Additional + public IList FullNameWords { get; set; } + public TLVector BotInfo { get; set; } + + #endregion + } + + public class TLChatEmpty : TLChatBase + { + public const uint Signature = TLConstructors.TLChatEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + } + + public override string FullName + { + get { return string.Empty; } + } + + public override TLInputPeerBase ToInputPeer() + { + return new TLInputPeerChat { ChatId = Id }; + } + + public override string GetUnsendedTextFileName() + { + return "c" + Id + ".dat"; + } + + public override bool IsForbidden + { + get { return true; } + } + } + + public class TLChat : TLChatBase + { + public const uint Signature = TLConstructors.TLChat; + + protected TLString _title; + + public TLString Title + { + get { return _title; } + set + { + SetField(ref _title, value, () => Title); + NotifyOfPropertyChange(() => FullName); + } + } + + protected TLPhotoBase _photo; + + public TLPhotoBase Photo + { + get { return _photo; } + set { SetField(ref _photo, value, () => Photo); } + } + + public TLInt ParticipantsCount { get; set; } + + public TLInt Date { get; set; } + + public virtual TLBool Left { get; set; } + + public TLInt Version { get; set; } + + public override string ToString() + { + return Title.ToString(); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + _title = GetObject(bytes, ref position); + _photo = GetObject(bytes, ref position); + ParticipantsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Left = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _title = GetObject(input); + _photo = GetObject(input); + ParticipantsCount = GetObject(input); + Date = GetObject(input); + Left = GetObject(input); + Version = GetObject(input); + + Participants = GetObject(input) as TLChatParticipantsBase; + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(Title.ToBytes()); + Photo.ToStream(output); + output.Write(ParticipantsCount.ToBytes()); + output.Write(Date.ToBytes()); + output.Write(Left.ToBytes()); + output.Write(Version.ToBytes()); + + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + } + + public override string FullName + { + get { return Title != null ? Title.ToString() : string.Empty; } + } + + public override void Update(TLChatBase chat) + { + base.Update(chat); + var c = chat as TLChat; + if (c != null) + { + _title = c.Title; + if (Photo.GetType() != c.Photo.GetType()) + { + _photo = c.Photo; // при удалении фото чата не обновляется UI при _photo = c.Photo + } + else + { + Photo.Update(c.Photo); + } + ParticipantsCount = c.ParticipantsCount; + Date = c.Date; + Left = c.Left; + Version = c.Version; + } + } + + public override TLInputPeerBase ToInputPeer() + { + return new TLInputPeerChat { ChatId = Id }; + } + + public override string GetUnsendedTextFileName() + { + return "c" + Id + ".dat"; + } + + public override bool IsForbidden + { + get { return Left.Value; } + } + } + + public class TLChat40 : TLChat + { + public new const uint Signature = TLConstructors.TLChat40; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override TLBool Left + { + get { return new TLBool(IsSet(_flags, (int)ChatFlags.Left)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)ChatFlags.Left); + } + } + } + + public bool Creator + { + get { return IsSet(_flags, (int)ChatFlags.Creator); } + } + + public TLBool Admin + { + get { return new TLBool(IsSet(_flags, (int)ChatFlags.Admin)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)ChatFlags.Admin); + } + } + } + + public TLBool AdminsEnabled + { + get { return new TLBool(IsSet(_flags, (int)ChatFlags.AdminsEnabled)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)ChatFlags.AdminsEnabled); + } + } + } + + public bool Deactivated + { + get { return IsSet(_flags, (int)ChatFlags.Deactivated); } + } + + protected TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + _title = GetObject(bytes, ref position); + _photo = GetObject(bytes, ref position); + ParticipantsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + //Left = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _title = GetObject(input); + _photo = GetObject(input); + ParticipantsCount = GetObject(input); + Date = GetObject(input); + //Left = GetObject(input); + Version = GetObject(input); + + Participants = GetObject(input) as TLChatParticipantsBase; + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + + CustomFlags = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(Title.ToBytes()); + Photo.ToStream(output); + output.Write(ParticipantsCount.ToBytes()); + output.Write(Date.ToBytes()); + //output.Write(Left.ToBytes()); + output.Write(Version.ToBytes()); + + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + + CustomFlags.NullableToStream(output); + } + + public override void Update(TLChatBase chat) + { + base.Update(chat); + var c = chat as TLChat40; + if (c != null) + { + Flags = c.Flags; + if (c.CustomFlags != null) + { + CustomFlags = c.CustomFlags; + } + } + } + + public override string ToString() + { + return base.ToString() + " flags=" + ChatFlagsString(Flags); + } + } + + public class TLChat41 : TLChat40, IReadMaxId + { + public new const uint Signature = TLConstructors.TLChat41; + + public bool IsMigrated { get { return IsSet(Flags, (int)ChatFlags.MigratedTo); } } + + private TLInputChannelBase _migratedTo; + + public TLInputChannelBase MigratedTo + { + get { return _migratedTo; } + set { SetField(out _migratedTo, value, ref _flags, (int)ChatFlags.MigratedTo); } + } + + private TLInt _readInboxMaxId; + + public TLInt ReadInboxMaxId + { + get { return _readInboxMaxId; } + set { SetField(out _readInboxMaxId, value, ref _customFlags, (int)ChatCustomFlags.ReadInboxMaxId); } + } + + private TLInt _readOutboxMaxId; + + public TLInt ReadOutboxMaxId + { + get { return _readOutboxMaxId; } + set { SetField(out _readOutboxMaxId, value, ref _customFlags, (int)ChatCustomFlags.ReadOutboxMaxId); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + _title = GetObject(bytes, ref position); + _photo = GetObject(bytes, ref position); + ParticipantsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + //Left = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + _migratedTo = GetObject(Flags, (int)ChatFlags.MigratedTo, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + _title = GetObject(input); + _photo = GetObject(input); + ParticipantsCount = GetObject(input); + Date = GetObject(input); + //Left = GetObject(input); + Version = GetObject(input); + _migratedTo = GetObject(Flags, (int)ChatFlags.MigratedTo, null, input); + + Participants = GetObject(input) as TLChatParticipantsBase; + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + + CustomFlags = GetNullableObject(input); + + _readInboxMaxId = GetObject(CustomFlags, (int)ChatCustomFlags.ReadInboxMaxId, null, input); + _readOutboxMaxId = GetObject(CustomFlags, (int)ChatCustomFlags.ReadOutboxMaxId, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + output.Write(Id.ToBytes()); + output.Write(Title.ToBytes()); + Photo.ToStream(output); + output.Write(ParticipantsCount.ToBytes()); + output.Write(Date.ToBytes()); + //output.Write(Left.ToBytes()); + output.Write(Version.ToBytes()); + ToStream(output, MigratedTo, Flags, (int)ChatFlags.MigratedTo); + + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + + CustomFlags.NullableToStream(output); + + ToStream(output, ReadInboxMaxId, CustomFlags, (int)ChatCustomFlags.ReadInboxMaxId); + ToStream(output, ReadOutboxMaxId, CustomFlags, (int)ChatCustomFlags.ReadOutboxMaxId); + } + + public override void Update(TLChatBase chat) + { + base.Update(chat); + + var chat41 = chat as TLChat41; + if (chat41 != null) + { + if (chat41.MigratedTo != null) + { + MigratedTo = chat41.MigratedTo; + } + + if (chat41.ReadInboxMaxId != null + && (ReadInboxMaxId == null || ReadInboxMaxId.Value < chat41.ReadInboxMaxId.Value)) + { + ReadInboxMaxId = chat41.ReadInboxMaxId; + } + + if (chat41.ReadOutboxMaxId != null + && (ReadOutboxMaxId == null || ReadOutboxMaxId.Value < chat41.ReadOutboxMaxId.Value)) + { + ReadOutboxMaxId = chat41.ReadOutboxMaxId; + } + } + } + } + + public class TLChatForbidden : TLChatBase + { + public const uint Signature = TLConstructors.TLChatForbidden; + + public TLString Title { get; set; } + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Title = GetObject(input); + Date = GetObject(input); + + Participants = GetObject(input) as TLChatParticipantsBase; + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(Title.ToBytes()); + output.Write(Date.ToBytes()); + + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + } + + public override void Update(TLChatBase chat) + { + base.Update(chat); + var c = (TLChatForbidden)chat; + Title = c.Title; + Date = c.Date; + } + + public override string FullName + { + get + { + return Title != null ? Title.ToString() : string.Empty; + } + } + + public override TLInputPeerBase ToInputPeer() + { + return new TLInputPeerChat { ChatId = Id }; + } + + public override string GetUnsendedTextFileName() + { + return "c" + Id + ".dat"; + } + + public override bool IsForbidden + { + get { return true; } + } + } + + public class TLChatForbidden40 : TLChatForbidden, IReadMaxId + { + public new const uint Signature = TLConstructors.TLChatForbidden40; + + protected TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + private TLInt _readInboxMaxId; + + public TLInt ReadInboxMaxId + { + get { return _readInboxMaxId; } + set { SetField(out _readInboxMaxId, value, ref _customFlags, (int)ChatCustomFlags.ReadInboxMaxId); } + } + + private TLInt _readOutboxMaxId; + + public TLInt ReadOutboxMaxId + { + get { return _readOutboxMaxId; } + set { SetField(out _readOutboxMaxId, value, ref _customFlags, (int)ChatCustomFlags.ReadOutboxMaxId); } + } + + #region Additional + public TLPhotoBase Photo { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + //Date = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Title = GetObject(input); + //Date = GetObject(input); + + Participants = GetObject(input) as TLChatParticipantsBase; + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + + CustomFlags = GetNullableObject(input); + + _readInboxMaxId = GetObject(CustomFlags, (int)ChatCustomFlags.ReadInboxMaxId, null, input); + _readOutboxMaxId = GetObject(CustomFlags, (int)ChatCustomFlags.ReadOutboxMaxId, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(Title.ToBytes()); + //output.Write(Date.ToBytes()); + + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + + CustomFlags.NullableToStream(output); + + ToStream(output, ReadInboxMaxId, CustomFlags, (int)ChatCustomFlags.ReadInboxMaxId); + ToStream(output, ReadOutboxMaxId, CustomFlags, (int)ChatCustomFlags.ReadOutboxMaxId); + } + + public override void Update(TLChatBase chat) + { + base.Update(chat); + var c = chat as TLChatForbidden40; + if (c != null) + { + if (c.ReadInboxMaxId != null + && (ReadInboxMaxId == null || ReadInboxMaxId.Value < c.ReadInboxMaxId.Value)) + { + ReadInboxMaxId = c.ReadInboxMaxId; + } + + if (c.ReadOutboxMaxId != null + && (ReadOutboxMaxId == null || ReadOutboxMaxId.Value < c.ReadOutboxMaxId.Value)) + { + ReadOutboxMaxId = c.ReadOutboxMaxId; + } + } + } + } + + public class TLBroadcastChat : TLChatBase + { + public const uint Signature = TLConstructors.TLBroadcastChat; + + public TLVector ParticipantIds { get; set; } + + protected TLString _title; + + public TLString Title + { + get { return _title; } + set + { + SetField(ref _title, value, () => Title); + NotifyOfPropertyChange(() => FullName); + } + } + + public TLPhotoBase _photo; + + public TLPhotoBase Photo + { + get { return _photo; } + set { SetField(ref _photo, value, () => Photo); } + } + + public override string FullName + { + get { return Title != null ? Title.ToString() : string.Empty; } + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _title = GetObject(input); + _photo = GetObject(input); + ParticipantIds = GetObject>(input); + + Participants = GetObject(input) as TLChatParticipantsBase; + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(Title.ToBytes()); + Photo.ToStream(output); + ParticipantIds.ToStream(output); + + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + } + + public override void Update(TLChatBase chat) + { + base.Update(chat); + var c = chat as TLBroadcastChat; + if (c != null) + { + _title = c.Title; + if (Photo.GetType() != c.Photo.GetType()) + { + _photo = c.Photo; + } + else + { + Photo.Update(c.Photo); + } + ParticipantIds = c.ParticipantIds; + } + } + + public override TLInputPeerBase ToInputPeer() + { + return new TLInputPeerBroadcast { ChatId = Id }; + } + + public override string GetUnsendedTextFileName() + { + return "b" + Id + ".dat"; + } + + public override bool IsForbidden + { + get { return false; } + } + } + + public class TLChannel76 : TLChannel73 + { + public new const uint Signature = TLConstructors.TLChannel76; + + protected TLInt _feedId; + + public TLInt FeedId + { + get { return _feedId; } + set { SetField(out _feedId, value, ref _flags, (int)ChannelFlags.FeedId); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(Flags, (int)ChannelFlags.AccessHash, new TLLong(0), bytes, ref position); + _title = GetObject(bytes, ref position); + UserName = GetObject(Flags, (int)ChannelFlags.Public, TLString.Empty, bytes, ref position); + _photo = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + RestrictionReason = GetObject(Flags, (int)ChannelFlags.Restricted, TLString.Empty, bytes, ref position); + _adminRights = GetObject(Flags, (int)ChannelFlags.AdminRights, null, bytes, ref position); + _bannedRights = GetObject(Flags, (int)ChannelFlags.BannedRights, null, bytes, ref position); + _participantsCount = GetObject(Flags, (int)ChannelFlags.ParticipantsCount, null, bytes, ref position); + _feedId = GetObject(Flags, (int)ChannelFlags.FeedId, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(Flags, (int)ChannelFlags.AccessHash, new TLLong(0), input); + _title = GetObject(input); + _userName = GetObject(Flags, (int)ChannelFlags.Public, TLString.Empty, input); + _photo = GetObject(input); + Date = GetObject(input); + Version = GetObject(input); + RestrictionReason = GetObject(Flags, (int)ChannelFlags.Restricted, TLString.Empty, input); + _adminRights = GetObject(Flags, (int)ChannelFlags.AdminRights, null, input); + _bannedRights = GetObject(Flags, (int)ChannelFlags.BannedRights, null, input); + _participantsCount = GetObject(Flags, (int)ChannelFlags.ParticipantsCount, null, input); + _feedId = GetObject(Flags, (int)ChannelFlags.FeedId, null, input); + + CustomFlags = GetNullableObject(input); + + ParticipantIds = GetNullableObject>(input); + About = GetNullableObject(input); + AdminsCount = GetNullableObject(input); + KickedCount = GetNullableObject(input); + ReadInboxMaxId = GetNullableObject(input); + Pts = GetNullableObject(input); + Participants = GetNullableObject(input); + NotifySettings = GetNullableObject(input); + + _migratedFromChatId = GetObject(CustomFlags, (int)ChannelCustomFlags.MigratedFromChatId, null, input); + _migratedFromMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.MigratedFromMaxId, null, input); + _pinnedMsgId = GetObject(CustomFlags, (int)ChannelCustomFlags.PinnedMsgId, null, input); + _hiddenPinnedMsgId = GetObject(CustomFlags, (int)ChannelCustomFlags.HiddenPinnedMsgId, null, input); + _readOutboxMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.ReadOutboxMaxId, null, input); + _stickerSet = GetObject(CustomFlags, (int)ChannelCustomFlags.StickerSet, null, input); + _availableMinId = GetObject(CustomFlags, (int)ChannelCustomFlags.AvailableMinId, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + try + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + output.Write(Flags.ToBytes()); + output.Write(Id.ToBytes()); + ToStream(output, AccessHash, Flags, (int)ChannelFlags.AccessHash); + output.Write(Title.ToBytes()); + ToStream(output, UserName, Flags, (int)ChannelFlags.Public); + Photo.ToStream(output); + Date.ToStream(output); + Version.ToStream(output); + ToStream(output, RestrictionReason, Flags, (int)ChannelFlags.Restricted); + ToStream(output, AdminRights, Flags, (int)ChannelFlags.AdminRights); + ToStream(output, BannedRights, Flags, (int)ChannelFlags.BannedRights); + ToStream(output, ParticipantsCount, Flags, (int)ChannelFlags.ParticipantsCount); + ToStream(output, FeedId, Flags, (int)ChannelFlags.FeedId); + + CustomFlags.NullableToStream(output); + + ParticipantIds.NullableToStream(output); + About.NullableToStream(output); + AdminsCount.NullableToStream(output); + KickedCount.NullableToStream(output); + ReadInboxMaxId.NullableToStream(output); + Pts.NullableToStream(output); + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + + ToStream(output, _migratedFromChatId, CustomFlags, (int)ChannelCustomFlags.MigratedFromChatId); + ToStream(output, _migratedFromMaxId, CustomFlags, (int)ChannelCustomFlags.MigratedFromMaxId); + ToStream(output, PinnedMsgId, CustomFlags, (int)ChannelCustomFlags.PinnedMsgId); + ToStream(output, HiddenPinnedMsgId, CustomFlags, (int)ChannelCustomFlags.HiddenPinnedMsgId); + ToStream(output, ReadOutboxMaxId, CustomFlags, (int)ChannelCustomFlags.ReadOutboxMaxId); + ToStream(output, _stickerSet, CustomFlags, (int)ChannelCustomFlags.StickerSet); + ToStream(output, _availableMinId, CustomFlags, (int)ChannelCustomFlags.AvailableMinId); + } + catch (Exception ex) + { + Execute.ShowDebugMessage( + string.Format( + "TLChannel76.ToStream access_hash={0} user_name={1} restriction_reason={2} migrated_from_chat_id={3} migrated_from_max_id={4} pinned_msg_id={5} hidden_pinned_msg_id={9} flags={6} custom_flags={7} ex {8}", + AccessHash, UserName, RestrictionReason, MigratedFromChatId, MigratedFromMaxId, PinnedMsgId, + ChannelFlagsString(Flags), ChannelCustomFlagsString(CustomFlags), HiddenPinnedMsgId, ex)); + } + + } + + public override void Update(TLChatBase chat) + { + var c = chat as TLChannel76; + if (c != null) + { + FeedId = c.FeedId; + } + + base.Update(chat); + } + } + + public class TLChannel73 : TLChannel68 + { + public new const uint Signature = TLConstructors.TLChannel73; + + protected TLInt _participantsCount; + + public override TLInt ParticipantsCount + { + get { return _participantsCount; } + set { SetField(out _participantsCount, value, ref _flags, (int)ChannelFlags.ParticipantsCount); } + } + + public override bool CanPinMessages + { + get + { + if (IsMegaGroup) + { + return Creator || (AdminRights != null && AdminRights.PinMessages); + } + + return Creator || (AdminRights != null && AdminRights.EditMessages); + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(Flags, (int)ChannelFlags.AccessHash, new TLLong(0), bytes, ref position); + _title = GetObject(bytes, ref position); + UserName = GetObject(Flags, (int)ChannelFlags.Public, TLString.Empty, bytes, ref position); + _photo = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + RestrictionReason = GetObject(Flags, (int)ChannelFlags.Restricted, TLString.Empty, bytes, ref position); + _adminRights = GetObject(Flags, (int)ChannelFlags.AdminRights, null, bytes, ref position); + _bannedRights = GetObject(Flags, (int)ChannelFlags.BannedRights, null, bytes, ref position); + _participantsCount = GetObject(Flags, (int)ChannelFlags.ParticipantsCount, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(Flags, (int)ChannelFlags.AccessHash, new TLLong(0), input); + _title = GetObject(input); + _userName = GetObject(Flags, (int)ChannelFlags.Public, TLString.Empty, input); + _photo = GetObject(input); + Date = GetObject(input); + Version = GetObject(input); + RestrictionReason = GetObject(Flags, (int)ChannelFlags.Restricted, TLString.Empty, input); + _adminRights = GetObject(Flags, (int)ChannelFlags.AdminRights, null, input); + _bannedRights = GetObject(Flags, (int)ChannelFlags.BannedRights, null, input); + _participantsCount = GetObject(Flags, (int)ChannelFlags.ParticipantsCount, null, input); + + CustomFlags = GetNullableObject(input); + + ParticipantIds = GetNullableObject>(input); + About = GetNullableObject(input); + AdminsCount = GetNullableObject(input); + KickedCount = GetNullableObject(input); + ReadInboxMaxId = GetNullableObject(input); + Pts = GetNullableObject(input); + Participants = GetNullableObject(input); + NotifySettings = GetNullableObject(input); + + _migratedFromChatId = GetObject(CustomFlags, (int)ChannelCustomFlags.MigratedFromChatId, null, input); + _migratedFromMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.MigratedFromMaxId, null, input); + _pinnedMsgId = GetObject(CustomFlags, (int)ChannelCustomFlags.PinnedMsgId, null, input); + _hiddenPinnedMsgId = GetObject(CustomFlags, (int)ChannelCustomFlags.HiddenPinnedMsgId, null, input); + _readOutboxMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.ReadOutboxMaxId, null, input); + _stickerSet = GetObject(CustomFlags, (int)ChannelCustomFlags.StickerSet, null, input); + _availableMinId = GetObject(CustomFlags, (int)ChannelCustomFlags.AvailableMinId, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + try + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + output.Write(Flags.ToBytes()); + output.Write(Id.ToBytes()); + ToStream(output, AccessHash, Flags, (int)ChannelFlags.AccessHash); + output.Write(Title.ToBytes()); + ToStream(output, UserName, Flags, (int)ChannelFlags.Public); + Photo.ToStream(output); + Date.ToStream(output); + Version.ToStream(output); + ToStream(output, RestrictionReason, Flags, (int)ChannelFlags.Restricted); + ToStream(output, AdminRights, Flags, (int)ChannelFlags.AdminRights); + ToStream(output, BannedRights, Flags, (int)ChannelFlags.BannedRights); + ToStream(output, ParticipantsCount, Flags, (int)ChannelFlags.ParticipantsCount); + + CustomFlags.NullableToStream(output); + + ParticipantIds.NullableToStream(output); + About.NullableToStream(output); + AdminsCount.NullableToStream(output); + KickedCount.NullableToStream(output); + ReadInboxMaxId.NullableToStream(output); + Pts.NullableToStream(output); + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + + ToStream(output, _migratedFromChatId, CustomFlags, (int)ChannelCustomFlags.MigratedFromChatId); + ToStream(output, _migratedFromMaxId, CustomFlags, (int)ChannelCustomFlags.MigratedFromMaxId); + ToStream(output, PinnedMsgId, CustomFlags, (int)ChannelCustomFlags.PinnedMsgId); + ToStream(output, HiddenPinnedMsgId, CustomFlags, (int)ChannelCustomFlags.HiddenPinnedMsgId); + ToStream(output, ReadOutboxMaxId, CustomFlags, (int)ChannelCustomFlags.ReadOutboxMaxId); + ToStream(output, _stickerSet, CustomFlags, (int)ChannelCustomFlags.StickerSet); + ToStream(output, _availableMinId, CustomFlags, (int)ChannelCustomFlags.AvailableMinId); + } + catch (Exception ex) + { + Execute.ShowDebugMessage( + string.Format( + "TLChannel68.ToStream access_hash={0} user_name={1} restriction_reason={2} migrated_from_chat_id={3} migrated_from_max_id={4} pinned_msg_id={5} hidden_pinned_msg_id={9} flags={6} custom_flags={7} ex {8}", + AccessHash, UserName, RestrictionReason, MigratedFromChatId, MigratedFromMaxId, PinnedMsgId, + ChannelFlagsString(Flags), ChannelCustomFlagsString(CustomFlags), HiddenPinnedMsgId, ex)); + } + + } + + public override void Update(TLChatBase chat) + { + var c = chat as TLChannel73; + if (c != null) + { + if (c.ParticipantsCount != null) + { + ParticipantsCount = c.ParticipantsCount; + } + } + + base.Update(chat); + } + } + + public class TLChannel68 : TLChannel49 + { + public new const uint Signature = TLConstructors.TLChannel68; + + protected TLChannelAdminRights _adminRights; + + public TLChannelAdminRights AdminRights + { + get { return _adminRights; } + set { SetField(out _adminRights, value, ref _flags, (int)ChannelFlags.AdminRights); } + } + + protected TLChannelBannedRights _bannedRights; + + public TLChannelBannedRights BannedRights + { + get { return _bannedRights; } + set { SetField(out _bannedRights, value, ref _flags, (int)ChannelFlags.BannedRights); } + } + + public bool CanSetStickers + { + get { return IsSet(CustomFlags, (int)ChannelCustomFlags.CanSetStickers); } + set { SetUnset(ref _customFlags, value, (int)ChannelCustomFlags.CanSetStickers); } + } + + protected TLStickerSetBase _stickerSet; + + public TLStickerSetBase StickerSet + { + get { return _stickerSet; } + set { SetField(out _stickerSet, value, ref _customFlags, (int)ChannelCustomFlags.StickerSet); } + } + + public bool HiddenPrehistory + { + get { return IsSet(CustomFlags, (int)ChannelCustomFlags.HiddenPrehistory); } + set { SetUnset(ref _customFlags, value, (int)ChannelCustomFlags.HiddenPrehistory); } + } + + protected TLInt _availableMinId; + + public TLInt AvailableMinId + { + get { return _availableMinId; } + set { SetField(out _availableMinId, value, ref _customFlags, (int)ChannelCustomFlags.AvailableMinId); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(Flags, (int)ChannelFlags.AccessHash, new TLLong(0), bytes, ref position); + _title = GetObject(bytes, ref position); + UserName = GetObject(Flags, (int)ChannelFlags.Public, TLString.Empty, bytes, ref position); + _photo = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + RestrictionReason = GetObject(Flags, (int)ChannelFlags.Restricted, TLString.Empty, bytes, ref position); + _adminRights = GetObject(Flags, (int)ChannelFlags.AdminRights, null, bytes, ref position); + _bannedRights = GetObject(Flags, (int)ChannelFlags.BannedRights, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(Flags, (int)ChannelFlags.AccessHash, new TLLong(0), input); + _title = GetObject(input); + _userName = GetObject(Flags, (int)ChannelFlags.Public, TLString.Empty, input); + _photo = GetObject(input); + Date = GetObject(input); + Version = GetObject(input); + RestrictionReason = GetObject(Flags, (int)ChannelFlags.Restricted, TLString.Empty, input); + _adminRights = GetObject(Flags, (int)ChannelFlags.AdminRights, null, input); + _bannedRights = GetObject(Flags, (int)ChannelFlags.BannedRights, null, input); + + CustomFlags = GetNullableObject(input); + + ParticipantIds = GetNullableObject>(input); + About = GetNullableObject(input); + ParticipantsCount = GetNullableObject(input); + AdminsCount = GetNullableObject(input); + KickedCount = GetNullableObject(input); + ReadInboxMaxId = GetNullableObject(input); + Pts = GetNullableObject(input); + Participants = GetNullableObject(input); + NotifySettings = GetNullableObject(input); + + _migratedFromChatId = GetObject(CustomFlags, (int)ChannelCustomFlags.MigratedFromChatId, null, input); + _migratedFromMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.MigratedFromMaxId, null, input); + _pinnedMsgId = GetObject(CustomFlags, (int)ChannelCustomFlags.PinnedMsgId, null, input); + _hiddenPinnedMsgId = GetObject(CustomFlags, (int)ChannelCustomFlags.HiddenPinnedMsgId, null, input); + _readOutboxMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.ReadOutboxMaxId, null, input); + _stickerSet = GetObject(CustomFlags, (int)ChannelCustomFlags.StickerSet, null, input); + _availableMinId = GetObject(CustomFlags, (int)ChannelCustomFlags.AvailableMinId, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + try + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + output.Write(Flags.ToBytes()); + output.Write(Id.ToBytes()); + ToStream(output, AccessHash, Flags, (int)ChannelFlags.AccessHash); + output.Write(Title.ToBytes()); + ToStream(output, UserName, Flags, (int)ChannelFlags.Public); + Photo.ToStream(output); + Date.ToStream(output); + Version.ToStream(output); + ToStream(output, RestrictionReason, Flags, (int)ChannelFlags.Restricted); + ToStream(output, AdminRights, Flags, (int)ChannelFlags.AdminRights); + ToStream(output, BannedRights, Flags, (int)ChannelFlags.BannedRights); + + CustomFlags.NullableToStream(output); + + ParticipantIds.NullableToStream(output); + About.NullableToStream(output); + ParticipantsCount.NullableToStream(output); + AdminsCount.NullableToStream(output); + KickedCount.NullableToStream(output); + ReadInboxMaxId.NullableToStream(output); + Pts.NullableToStream(output); + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + + ToStream(output, _migratedFromChatId, CustomFlags, (int)ChannelCustomFlags.MigratedFromChatId); + ToStream(output, _migratedFromMaxId, CustomFlags, (int)ChannelCustomFlags.MigratedFromMaxId); + ToStream(output, PinnedMsgId, CustomFlags, (int)ChannelCustomFlags.PinnedMsgId); + ToStream(output, HiddenPinnedMsgId, CustomFlags, (int)ChannelCustomFlags.HiddenPinnedMsgId); + ToStream(output, ReadOutboxMaxId, CustomFlags, (int)ChannelCustomFlags.ReadOutboxMaxId); + ToStream(output, _stickerSet, CustomFlags, (int)ChannelCustomFlags.StickerSet); + ToStream(output, _availableMinId, CustomFlags, (int)ChannelCustomFlags.AvailableMinId); + } + catch (Exception ex) + { + Execute.ShowDebugMessage( + string.Format( + "TLChannel68.ToStream access_hash={0} user_name={1} restriction_reason={2} migrated_from_chat_id={3} migrated_from_max_id={4} pinned_msg_id={5} hidden_pinned_msg_id={9} flags={6} custom_flags={7} ex {8}", + AccessHash, UserName, RestrictionReason, MigratedFromChatId, MigratedFromMaxId, PinnedMsgId, + ChannelFlagsString(Flags), ChannelCustomFlagsString(CustomFlags), HiddenPinnedMsgId, ex)); + } + + } + + public override void Update(TLChatBase chat) + { + var c = chat as TLChannel68; + if (c != null) + { + AdminRights = c.AdminRights; + BannedRights = c.BannedRights; + + if (c.Full) + { + CanSetStickers = c.CanSetStickers; + if (c.StickerSet != null) + { + if (c.StickerSet is TLStickerSetEmpty) + { + StickerSet = null; + } + else + { + StickerSet = c.StickerSet; + } + } + HiddenPrehistory = c.HiddenPrehistory; + AvailableMinId = c.AvailableMinId; + } + } + + base.Update(chat); + } + } + + public class TLChannel49 : TLChannel44, IReadMaxId + { + public new const uint Signature = TLConstructors.TLChannel49; + + public bool Min + { + get { return IsSet(Flags, (int)ChannelFlags.Min); } + } + + protected TLInt _pinnedMsgId; + + public TLInt PinnedMsgId + { + get { return _pinnedMsgId; } + set { SetField(out _pinnedMsgId, value, ref _customFlags, (int)ChannelCustomFlags.PinnedMsgId); } + } + + protected TLInt _hiddenPinnedMsgId; + + public TLInt HiddenPinnedMsgId + { + get { return _hiddenPinnedMsgId; } + set { SetField(out _hiddenPinnedMsgId, value, ref _customFlags, (int)ChannelCustomFlags.HiddenPinnedMsgId); } + } + + protected TLInt _readOutboxMaxId; + + public TLInt ReadOutboxMaxId + { + get { return _readOutboxMaxId; } + set { SetField(out _readOutboxMaxId, value, ref _customFlags, (int)ChannelCustomFlags.ReadOutboxMaxId); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(Flags, (int)ChannelFlags.AccessHash, new TLLong(0), bytes, ref position); + _title = GetObject(bytes, ref position); + UserName = GetObject(Flags, (int)ChannelFlags.Public, TLString.Empty, bytes, ref position); + _photo = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + RestrictionReason = GetObject(Flags, (int)ChannelFlags.Restricted, TLString.Empty, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + //try + ////{ + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(Flags, (int)ChannelFlags.AccessHash, new TLLong(0), input); + _title = GetObject(input); + _userName = GetObject(Flags, (int)ChannelFlags.Public, TLString.Empty, input); + _photo = GetObject(input); + Date = GetObject(input); + Version = GetObject(input); + RestrictionReason = GetObject(Flags, (int)ChannelFlags.Restricted, TLString.Empty, input); + + CustomFlags = GetNullableObject(input); + + ParticipantIds = GetNullableObject>(input); + About = GetNullableObject(input); + ParticipantsCount = GetNullableObject(input); + AdminsCount = GetNullableObject(input); + KickedCount = GetNullableObject(input); + ReadInboxMaxId = GetNullableObject(input); + Pts = GetNullableObject(input); + Participants = GetNullableObject(input); + NotifySettings = GetNullableObject(input); + + _migratedFromChatId = GetObject(CustomFlags, (int)ChannelCustomFlags.MigratedFromChatId, null, input); + _migratedFromMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.MigratedFromMaxId, null, input); + _pinnedMsgId = GetObject(CustomFlags, (int)ChannelCustomFlags.PinnedMsgId, null, input); + _hiddenPinnedMsgId = GetObject(CustomFlags, (int)ChannelCustomFlags.HiddenPinnedMsgId, null, input); + _readOutboxMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.ReadOutboxMaxId, null, input); + //} + //catch (Exception ex) + //{ + // Execute.ShowDebugMessage("TLChannel44.FromStream ex " + ex); + //} + + return this; + } + + public override void ToStream(Stream output) + { + try + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + output.Write(Flags.ToBytes()); + output.Write(Id.ToBytes()); + ToStream(output, AccessHash, Flags, (int)ChannelFlags.AccessHash); + output.Write(Title.ToBytes()); + ToStream(output, UserName, Flags, (int)ChannelFlags.Public); + Photo.ToStream(output); + Date.ToStream(output); + Version.ToStream(output); + ToStream(output, RestrictionReason, Flags, (int)ChannelFlags.Restricted); + + CustomFlags.NullableToStream(output); + + ParticipantIds.NullableToStream(output); + About.NullableToStream(output); + ParticipantsCount.NullableToStream(output); + AdminsCount.NullableToStream(output); + KickedCount.NullableToStream(output); + ReadInboxMaxId.NullableToStream(output); + Pts.NullableToStream(output); + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + + ToStream(output, _migratedFromChatId, CustomFlags, (int)ChannelCustomFlags.MigratedFromChatId); + ToStream(output, _migratedFromMaxId, CustomFlags, (int)ChannelCustomFlags.MigratedFromMaxId); + ToStream(output, PinnedMsgId, CustomFlags, (int)ChannelCustomFlags.PinnedMsgId); + ToStream(output, HiddenPinnedMsgId, CustomFlags, (int)ChannelCustomFlags.HiddenPinnedMsgId); + ToStream(output, ReadOutboxMaxId, CustomFlags, (int)ChannelCustomFlags.ReadOutboxMaxId); + } + catch (Exception ex) + { + Execute.ShowDebugMessage( + string.Format( + "TLChannel49.ToStream access_hash={0} user_name={1} restriction_reason={2} migrated_from_chat_id={3} migrated_from_max_id={4} pinned_msg_id={5} hidden_pinned_msg_id={9} flags={6} custom_flags={7} ex {8}", + AccessHash, UserName, RestrictionReason, MigratedFromChatId, MigratedFromMaxId, PinnedMsgId, + ChannelFlagsString(Flags), ChannelCustomFlagsString(CustomFlags), HiddenPinnedMsgId, ex)); + } + + } + + public override void Update(TLChatBase chat) + { + var c = chat as TLChannel49; + if (c != null) + { + if (c.Min) + { + // copy flags: broadcast, verified, megagroup, democracy + IsBroadcast = c.IsBroadcast; + IsVerified = c.IsVerified; + if (IsMegaGroup && !c.IsMegaGroup) + { + + } + IsMegaGroup = c.IsMegaGroup; + IsDemocracy = c.IsDemocracy; + + Id = c.Id; + _title = c.Title; + UserName = c.UserName; + _photo = c.Photo; + + return; + } + + if (c.PinnedMsgId != null) + { + PinnedMsgId = c.PinnedMsgId; + } + if (c.HiddenPinnedMsgId != null) + { + HiddenPinnedMsgId = c.HiddenPinnedMsgId; + } + if (c.ReadOutboxMaxId != null && (ReadOutboxMaxId == null || ReadOutboxMaxId.Value < c.ReadOutboxMaxId.Value)) + { + ReadOutboxMaxId = c.ReadOutboxMaxId; + } + } + + base.Update(chat); + } + } + + public class TLChannel44 : TLChannel + { + public new const uint Signature = TLConstructors.TLChannel44; + + protected TLString _restrictionReason; + + public TLString RestrictionReason + { + get { return _restrictionReason; } + set { SetField(out _restrictionReason, value, ref _flags, (int)ChannelFlags.Restricted); } + } + + public bool IsRestricted + { + get { return IsSet(Flags, (int)ChannelFlags.Restricted); } + } + + public bool Silent + { + get { return IsSet(CustomFlags, (int)ChannelCustomFlags.Silent); } + set { SetUnset(ref _customFlags, value, (int)ChannelCustomFlags.Silent); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + _title = GetObject(bytes, ref position); + if (IsSet(Flags, (int)ChannelFlags.Public)) + { + UserName = GetObject(bytes, ref position); + } + _photo = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + if (IsSet(Flags, (int)ChannelFlags.Restricted)) + { + RestrictionReason = GetObject(bytes, ref position); + } + + return this; + } + + public override TLObject FromStream(Stream input) + { + //try + ////{ + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(input); + _title = GetObject(input); + if (IsSet(Flags, (int)ChannelFlags.Public)) + { + UserName = GetObject(input); + } + _photo = GetObject(input); + Date = GetObject(input); + Version = GetObject(input); + if (IsSet(Flags, (int)ChannelFlags.Restricted)) + { + RestrictionReason = GetObject(input); + } + + CustomFlags = GetNullableObject(input); + + ParticipantIds = GetNullableObject>(input); + About = GetNullableObject(input); + ParticipantsCount = GetNullableObject(input); + AdminsCount = GetNullableObject(input); + KickedCount = GetNullableObject(input); + ReadInboxMaxId = GetNullableObject(input); + Pts = GetNullableObject(input); + Participants = GetNullableObject(input); + NotifySettings = GetNullableObject(input); + + if (IsSet(CustomFlags, (int)ChannelCustomFlags.MigratedFromChatId)) + { + _migratedFromChatId = GetObject(input); + } + if (IsSet(CustomFlags, (int)ChannelCustomFlags.MigratedFromMaxId)) + { + _migratedFromMaxId = GetObject(input); + } + //} + //catch (Exception ex) + //{ + // Execute.ShowDebugMessage("TLChannel44.FromStream ex " + ex); + //} + + return this; + } + + public override void ToStream(Stream output) + { + try + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + output.Write(Flags.ToBytes()); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Title.ToBytes()); + if (IsSet(Flags, (int)ChannelFlags.Public)) + { + UserName.ToStream(output); + } + Photo.ToStream(output); + Date.ToStream(output); + Version.ToStream(output); + if (IsSet(Flags, (int)ChannelFlags.Restricted)) + { + RestrictionReason.ToStream(output); + } + + CustomFlags.NullableToStream(output); + + ParticipantIds.NullableToStream(output); + About.NullableToStream(output); + ParticipantsCount.NullableToStream(output); + AdminsCount.NullableToStream(output); + KickedCount.NullableToStream(output); + ReadInboxMaxId.NullableToStream(output); + Pts.NullableToStream(output); + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + + if (IsSet(CustomFlags, (int)ChannelCustomFlags.MigratedFromChatId)) + { + _migratedFromChatId.ToStream(output); + } + if (IsSet(CustomFlags, (int)ChannelCustomFlags.MigratedFromMaxId)) + { + _migratedFromMaxId.ToStream(output); + } + } + catch (Exception ex) + { + Execute.ShowDebugMessage("TLChannel44.ToStream ex " + ex); + } + + } + + public override void Update(TLChatBase chat) + { + base.Update(chat); + var c = chat as TLChannel44; + if (c != null) + { + RestrictionReason = c.RestrictionReason ?? TLString.Empty; + } + } + } + + public class TLChannel : TLBroadcastChat, IUserName, IInputChannel + { + public new const uint Signature = TLConstructors.TLChannel; + + public bool Full { get; set; } + + protected TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public virtual TLBool Left + { + get { return new TLBool(IsSet(_flags, (int)ChatFlags.Left)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)ChatFlags.Left); + } + } + } + + public TLLong AccessHash { get; set; } + + protected TLString _userName; + + public TLString UserName + { + get { return _userName; } + set { SetField(out _userName, value, ref _flags, (int)ChannelFlags.Public); } + } + + public TLInt Date { get; set; } + + public TLInt Version { get; set; } + + public TLString About { get; set; } + + public virtual TLInt ParticipantsCount { get; set; } + + public TLInt AdminsCount { get; set; } + + public TLInt KickedCount { get; set; } + + public TLInt ReadInboxMaxId { get; set; } + + private TLInt _pts; + + public TLInt Pts + { + get { return _pts; } + set { _pts = value; } + } + + public override string FullName + { + get { return Title != null ? Title.ToString() : string.Empty; } + } + + public bool Creator + { + get { return IsSet(Flags, (int)ChannelFlags.Creator); } + set { SetUnset(ref _flags, value, (int)ChannelFlags.Creator); } + } + + public bool IsEditor + { + get { return IsSet(Flags, (int)ChannelFlags.Editor); } + set { SetUnset(ref _flags, value, (int)ChannelFlags.Editor); } + } + + public bool IsModerator + { + get { return IsSet(Flags, (int)ChannelFlags.Moderator); } + set { SetUnset(ref _flags, value, (int)ChannelFlags.Moderator); } + } + + public bool IsBroadcast + { + get { return IsSet(Flags, (int)ChannelFlags.Broadcast); } + set { SetUnset(ref _flags, value, (int)ChannelFlags.Broadcast); } + } + + public bool IsPublic { get { return IsSet(Flags, (int)ChannelFlags.Public); } } + + public bool IsKicked { get { return IsSet(Flags, (int)ChannelFlags.Kicked); } } + + public bool IsVerified + { + get { return IsSet(Flags, (int)ChannelFlags.Verified); } + set { SetUnset(ref _flags, value, (int)ChannelFlags.Verified); } + } + + public bool IsMegaGroup + { + get { return IsSet(Flags, (int)ChannelFlags.MegaGroup); } + set { SetUnset(ref _flags, value, (int)ChannelFlags.MegaGroup); } + } + + public bool IsDemocracy + { + get { return IsSet(Flags, (int)ChannelFlags.Democracy); } + set { SetUnset(ref _flags, value, (int)ChannelFlags.Democracy); } + } + + public bool Signatures + { + get { return IsSet(Flags, (int)ChannelFlags.Signatures); } + set { SetUnset(ref _flags, value, (int)ChannelFlags.Signatures); } + } + + #region Additional + + public virtual bool CanPinMessages + { + get + { + return Creator; + } + } + + public string ChannelParticipantsFileName + { + get { return string.Format("{0}_participants.dat", Id); } + } + + public TLChannelParticipants ChannelParticipants { get; set; } + + protected TLInt _migratedFromChatId; + + public TLInt MigratedFromChatId + { + get { return _migratedFromChatId; } + set { SetField(out _migratedFromChatId, value, ref _customFlags, (int)ChannelCustomFlags.MigratedFromChatId); } + } + + protected TLInt _migratedFromMaxId; + + public TLInt MigratedFromMaxId + { + get { return _migratedFromMaxId; } + set { SetField(out _migratedFromMaxId, value, ref _customFlags, (int)ChannelCustomFlags.MigratedFromMaxId); } + } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + _title = GetObject(bytes, ref position); + if (IsSet(Flags, (int)ChannelFlags.Public)) + { + UserName = GetObject(bytes, ref position); + } + _photo = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(input); + _title = GetObject(input); + if (IsSet(Flags, (int)ChannelFlags.Public)) + { + UserName = GetObject(input); + } + _photo = GetObject(input); + Date = GetObject(input); + Version = GetObject(input); + + CustomFlags = GetNullableObject(input); + + ParticipantIds = GetNullableObject>(input); + About = GetNullableObject(input); + ParticipantsCount = GetNullableObject(input); + AdminsCount = GetNullableObject(input); + KickedCount = GetNullableObject(input); + ReadInboxMaxId = GetNullableObject(input); + Pts = GetNullableObject(input); + Participants = GetNullableObject(input); + NotifySettings = GetNullableObject(input); + + _migratedFromChatId = GetObject(CustomFlags, (int)ChannelCustomFlags.MigratedFromChatId, null, input); + _migratedFromMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.MigratedFromMaxId, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + try + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + output.Write(Flags.ToBytes()); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Title.ToBytes()); + if (IsSet(Flags, (int)ChannelFlags.Public)) + { + UserName.ToStream(output); + } + Photo.ToStream(output); + Date.ToStream(output); + Version.ToStream(output); + + CustomFlags.NullableToStream(output); + + ParticipantIds.NullableToStream(output); + About.NullableToStream(output); + ParticipantsCount.NullableToStream(output); + AdminsCount.NullableToStream(output); + KickedCount.NullableToStream(output); + ReadInboxMaxId.NullableToStream(output); + Pts.NullableToStream(output); + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + + ToStream(output, _migratedFromChatId, CustomFlags, (int)ChannelCustomFlags.MigratedFromChatId); + ToStream(output, _migratedFromMaxId, CustomFlags, (int)ChannelCustomFlags.MigratedFromMaxId); + } + catch (Exception ex) + { + + } + + } + + public override void Update(TLChatBase chat) + { + base.Update(chat); + + var c = chat as TLChannel; + if (c != null) + { + //if (c.Flags != null) Flags = c.Flags; + Creator = c.Creator; + Left = c.Left; + IsEditor = c.IsEditor; + IsBroadcast = c.IsBroadcast; + IsVerified = c.IsVerified; + IsMegaGroup = c.IsMegaGroup; + IsDemocracy = c.IsDemocracy; + Signatures = c.Signatures; + + AccessHash = c.AccessHash ?? new TLLong(0); + UserName = c.UserName ?? TLString.Empty; + + //if (c.CustomFlags != null) CustomFlags = c.CustomFlags; + if (c.MigratedFromChatId != null) MigratedFromChatId = c.MigratedFromChatId; + if (c.MigratedFromMaxId != null) MigratedFromMaxId = c.MigratedFromMaxId; + + if (c.ParticipantIds != null) ParticipantIds = c.ParticipantIds; + if (c.About != null) About = c.About; + if (c.ParticipantsCount != null) ParticipantsCount = c.ParticipantsCount; + if (c.AdminsCount != null) AdminsCount = c.AdminsCount; + if (c.KickedCount != null) KickedCount = c.KickedCount; + if (c.ReadInboxMaxId != null) ReadInboxMaxId = c.ReadInboxMaxId; + if (c.Participants != null) Participants = c.Participants; + if (c.NotifySettings != null) NotifySettings = c.NotifySettings; + } + } + + public override string ToString() + { + return Title + " flags=" + ChannelFlagsString(Flags) + " custom_flags=" + ChannelCustomFlagsString(CustomFlags); ; + } + + public override TLInputPeerBase ToInputPeer() + { + return new TLInputPeerChannel { ChatId = Id, AccessHash = AccessHash }; + } + + public TLInputChannelBase ToInputChannel() + { + return new TLInputChannel { ChannelId = Id, AccessHash = AccessHash }; + } + + public override string GetUnsendedTextFileName() + { + return "ch" + Id + ".dat"; + } + + public override bool IsForbidden + { + get { return Left.Value; } + } + } + + public class TLChannelForbidden : TLChatBase, IInputChannel + { + public const uint Signature = TLConstructors.TLChannelForbidden; + + public TLLong AccessHash { get; set; } + + public TLString Title { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Title = GetObject(input); + + Participants = GetObject(input) as TLChatParticipantsBase; + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Title.ToBytes()); + + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + } + + public override void Update(TLChatBase chat) + { + base.Update(chat); + var c = chat as TLChannelForbidden; + if (c != null) + { + Id = c.Id; + AccessHash = c.AccessHash; + Title = c.Title; + } + } + + public override string FullName + { + get { return Title != null ? Title.ToString() : string.Empty; } + } + + public override TLInputPeerBase ToInputPeer() + { + return new TLInputPeerChannel { ChatId = Id, AccessHash = AccessHash }; + } + + public TLInputChannelBase ToInputChannel() + { + return new TLInputChannel { ChannelId = Id, AccessHash = AccessHash }; + } + + public override string GetUnsendedTextFileName() + { + return "ch" + Id + ".dat"; + } + + public override bool IsForbidden + { + get { return true; } + } + } + + public class TLChannelForbidden53 : TLChannelForbidden, IReadMaxId + { + public new const uint Signature = TLConstructors.TLChannelForbidden53; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + public bool IsBroadcast + { + get { return IsSet(Flags, (int)ChannelFlags.Broadcast); } + set { SetUnset(ref _flags, value, (int)ChannelFlags.Broadcast); } + } + + public bool IsMegaGroup + { + get { return IsSet(Flags, (int)ChannelFlags.MegaGroup); } + set { SetUnset(ref _flags, value, (int)ChannelFlags.MegaGroup); } + } + + protected TLInt _readInboxMaxId; + + public TLInt ReadInboxMaxId + { + get { return _readInboxMaxId; } + set { SetField(out _readInboxMaxId, value, ref _customFlags, (int)ChatCustomFlags.ReadInboxMaxId); } + } + + protected TLInt _readOutboxMaxId; + + public TLInt ReadOutboxMaxId + { + get { return _readOutboxMaxId; } + set { SetField(out _readOutboxMaxId, value, ref _customFlags, (int)ChatCustomFlags.ReadOutboxMaxId); } + } + + #region Additional + public TLPhotoBase Photo { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(input); + Title = GetObject(input); + + Participants = GetObject(input) as TLChatParticipantsBase; + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + + CustomFlags = GetNullableObject(input); + + _readInboxMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.ReadInboxMaxId, null, input); + _readOutboxMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.ReadOutboxMaxId, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Title.ToBytes()); + + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + + CustomFlags.NullableToStream(output); + + ToStream(output, ReadInboxMaxId, CustomFlags, (int)ChannelCustomFlags.ReadInboxMaxId); + ToStream(output, ReadOutboxMaxId, CustomFlags, (int)ChannelCustomFlags.ReadOutboxMaxId); + } + + public override void Update(TLChatBase chat) + { + base.Update(chat); + + var c = chat as TLChannelForbidden53; + if (c != null) + { + IsBroadcast = c.IsBroadcast; + IsMegaGroup = c.IsMegaGroup; + + if (c.ReadInboxMaxId != null + && (ReadInboxMaxId == null || ReadInboxMaxId.Value < c.ReadInboxMaxId.Value)) + { + ReadInboxMaxId = c.ReadInboxMaxId; + } + + if (c.ReadOutboxMaxId != null + && (ReadOutboxMaxId == null || ReadOutboxMaxId.Value < c.ReadOutboxMaxId.Value)) + { + ReadOutboxMaxId = c.ReadOutboxMaxId; + } + } + } + } + + public class TLChannelForbidden68 : TLChannelForbidden53 + { + public new const uint Signature = TLConstructors.TLChannelForbidden68; + + protected TLInt _untilDate; + + public TLInt UntilDate + { + get { return _untilDate; } + set { SetField(out _untilDate, value, ref _flags, (int)ChannelFlags.UntilDate); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + _untilDate = GetObject(Flags, (int)ChannelFlags.UntilDate, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(input); + Title = GetObject(input); + _untilDate = GetObject(Flags, (int)ChannelFlags.UntilDate, null, input); + + Participants = GetObject(input) as TLChatParticipantsBase; + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + + CustomFlags = GetNullableObject(input); + + _readInboxMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.ReadInboxMaxId, null, input); + _readOutboxMaxId = GetObject(CustomFlags, (int)ChannelCustomFlags.ReadOutboxMaxId, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Title.ToBytes()); + ToStream(output, UntilDate, Flags, (int)ChannelFlags.UntilDate); + + Participants.NullableToStream(output); + NotifySettings.NullableToStream(output); + + CustomFlags.NullableToStream(output); + + ToStream(output, ReadInboxMaxId, CustomFlags, (int)ChannelCustomFlags.ReadInboxMaxId); + ToStream(output, ReadOutboxMaxId, CustomFlags, (int)ChannelCustomFlags.ReadOutboxMaxId); + } + + public override void Update(TLChatBase chat) + { + base.Update(chat); + + var c = chat as TLChannelForbidden68; + if (c != null) + { + UntilDate = c.UntilDate; + } + } + } +} diff --git a/Telegram.Api/TL/TLChatFull.cs b/Telegram.Api/TL/TLChatFull.cs new file mode 100755 index 0000000..cb7005a --- /dev/null +++ b/Telegram.Api/TL/TLChatFull.cs @@ -0,0 +1,660 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ChannelFullFlags + { + ParticipantsCount = 0x1, + AdminsCount = 0x2, + KickedCount = 0x4, + CanViewParticipants = 0x8, + Migrated = 0x10, + PinnedMsgId = 0x20, + CanSetUsername = 0x40, + CanSetStickers = 0x80, + StickerSet = 0x100, + AvailableMinId = 0x200, + HiddenPrehistory = 0x400 + } + + public class TLChatFull : TLObject + { + public const uint Signature = TLConstructors.TLChatFull; + + public TLInt Id { get; set; } + + public TLChatParticipantsBase Participants { get; set; } + + public TLPhotoBase ChatPhoto { get; set; } + + public TLPeerNotifySettingsBase NotifySettings { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Participants = GetObject(bytes, ref position); + ChatPhoto = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + + return this; + } + + public virtual TLChatBase ToChat(TLChatBase chat) + { + chat.NotifySettings = NotifySettings; + chat.Participants = Participants; + chat.ChatPhoto = ChatPhoto; + + return chat; + } + } + + public class TLChatFull28 : TLChatFull + { + public new const uint Signature = TLConstructors.TLChatFull28; + + public TLExportedChatInvite ExportedInvite { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Participants = GetObject(bytes, ref position); + ChatPhoto = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + ExportedInvite = GetObject(bytes, ref position); + + return this; + } + } + + public class TLChatFull31 : TLChatFull28 + { + public new const uint Signature = TLConstructors.TLChatFull31; + + public TLVector BotInfo { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Participants = GetObject(bytes, ref position); + ChatPhoto = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + ExportedInvite = GetObject(bytes, ref position); + BotInfo = GetObject>(bytes, ref position); + + return this; + } + } + + public class TLChannelFull : TLChatFull + { + public new const uint Signature = TLConstructors.TLChannelFull; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLString About { get; set; } + + protected TLInt _participantsCount; + + public TLInt ParticipantsCount + { + get { return _participantsCount; } + set { SetField(out _participantsCount, value, ref _flags, (int)ChannelFullFlags.ParticipantsCount); } + } + + protected TLInt _adminsCount; + + public TLInt AdminsCount + { + get { return _adminsCount; } + set { SetField(out _adminsCount, value, ref _flags, (int)ChannelFullFlags.AdminsCount); } + } + + protected TLInt _kickedCount; + + public TLInt KickedCount + { + get { return _kickedCount; } + set { SetField(out _kickedCount, value, ref _flags, (int)ChannelFullFlags.KickedCount); } + } + + public TLInt ReadInboxMaxId { get; set; } + + public TLInt UnreadCount { get; set; } + + public TLInt UnreadImportantCount { get; set; } + + public TLExportedChatInvite ExportedInvite { get; set; } + + public bool CanViewParticipants { get { return IsSet(Flags, (int) ChannelFullFlags.CanViewParticipants); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + //Participants = GetObject(bytes, ref position); + About = GetObject(bytes, ref position); + if (IsSet(Flags, (int)ChannelFullFlags.ParticipantsCount)) + { + ParticipantsCount = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int) ChannelFullFlags.AdminsCount)) + { + AdminsCount = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)ChannelFullFlags.KickedCount)) + { + KickedCount = GetObject(bytes, ref position); + } + ReadInboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadImportantCount = GetObject(bytes, ref position); + ChatPhoto = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + ExportedInvite = GetObject(bytes, ref position); + + return this; + } + + public override TLChatBase ToChat(TLChatBase chat) + { + chat.NotifySettings = NotifySettings; + chat.Participants = Participants; + chat.ChatPhoto = ChatPhoto; + + var channel = chat as TLChannel; + if (channel != null) + { + channel.ExportedInvite = ExportedInvite; + channel.About = About; + channel.ParticipantsCount = ParticipantsCount; + channel.AdminsCount = AdminsCount; + channel.KickedCount = KickedCount; + channel.ReadInboxMaxId = ReadInboxMaxId; + } + + return chat; + } + } + + public class TLChannelFull41 : TLChannelFull + { + public new const uint Signature = TLConstructors.TLChannelFull41; + + public TLVector BotInfo { get; set; } + + protected TLInt _migratedFromChatId; + + public TLInt MigratedFromChatId + { + get { return _migratedFromChatId; } + set { SetField(out _migratedFromChatId, value, ref _flags, (int)ChannelFullFlags.Migrated); } + } + + protected TLInt _migratedFromMaxId; + + public TLInt MigratedFromMaxId + { + get { return _migratedFromMaxId; } + set { SetField(out _migratedFromMaxId, value, ref _flags, (int)ChannelFullFlags.Migrated); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + //Participants = GetObject(bytes, ref position); + About = GetObject(bytes, ref position); + if (IsSet(Flags, (int)ChannelFullFlags.ParticipantsCount)) + { + ParticipantsCount = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)ChannelFullFlags.AdminsCount)) + { + AdminsCount = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)ChannelFullFlags.KickedCount)) + { + KickedCount = GetObject(bytes, ref position); + } + ReadInboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadImportantCount = GetObject(bytes, ref position); + ChatPhoto = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + ExportedInvite = GetObject(bytes, ref position); + BotInfo = GetObject>(bytes, ref position); + if (IsSet(Flags, (int)ChannelFullFlags.Migrated)) + { + MigratedFromChatId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)ChannelFullFlags.Migrated)) + { + MigratedFromMaxId = GetObject(bytes, ref position); + } + + return this; + } + + public override TLChatBase ToChat(TLChatBase chat) + { + chat.NotifySettings = NotifySettings; + chat.Participants = Participants; + chat.ChatPhoto = ChatPhoto; + + var channel = chat as TLChannel; + if (channel != null) + { + channel.ExportedInvite = ExportedInvite; + channel.About = About; + channel.ParticipantsCount = ParticipantsCount; + channel.AdminsCount = AdminsCount; + channel.KickedCount = KickedCount; + channel.ReadInboxMaxId = ReadInboxMaxId; + } + + return chat; + } + } + + public class TLChannelFull49 : TLChannelFull41 + { + public new const uint Signature = TLConstructors.TLChannelFull49; + + protected TLInt _pinnedMsgId; + + public TLInt PinnedMsgId + { + get { return _pinnedMsgId; } + set { SetField(out _pinnedMsgId, value, ref _flags, (int)ChannelFullFlags.PinnedMsgId); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + //Participants = GetObject(bytes, ref position); + About = GetObject(bytes, ref position); + ParticipantsCount = GetObject(Flags, (int)ChannelFullFlags.ParticipantsCount, null, bytes, ref position); + AdminsCount = GetObject(Flags, (int)ChannelFullFlags.AdminsCount, null, bytes, ref position); + KickedCount = GetObject(Flags, (int)ChannelFullFlags.KickedCount, null, bytes, ref position); + ReadInboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadImportantCount = GetObject(bytes, ref position); + ChatPhoto = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + ExportedInvite = GetObject(bytes, ref position); + BotInfo = GetObject>(bytes, ref position); + MigratedFromChatId = GetObject(Flags, (int)ChannelFullFlags.Migrated, null, bytes, ref position); + MigratedFromMaxId = GetObject(Flags, (int)ChannelFullFlags.Migrated, null, bytes, ref position); + PinnedMsgId = GetObject(Flags, (int)ChannelFullFlags.PinnedMsgId, null, bytes, ref position); + + return this; + } + + public override TLChatBase ToChat(TLChatBase chat) + { + chat.NotifySettings = NotifySettings; + chat.Participants = Participants; + chat.ChatPhoto = ChatPhoto; + + var channel = chat as TLChannel; + if (channel != null) + { + channel.About = About; + channel.ParticipantsCount = ParticipantsCount; + channel.AdminsCount = AdminsCount; + channel.KickedCount = KickedCount; + channel.ReadInboxMaxId = ReadInboxMaxId; + channel.ExportedInvite = ExportedInvite; + channel.BotInfo = BotInfo; + channel.MigratedFromChatId = MigratedFromChatId; + channel.MigratedFromMaxId = MigratedFromMaxId; + } + + var channel49 = chat as TLChannel49; + if (channel49 != null) + { + channel49.PinnedMsgId = PinnedMsgId; + } + + return chat; + } + } + + public class TLChannelFull53 : TLChannelFull49 + { + public new const uint Signature = TLConstructors.TLChannelFull53; + + public TLInt ReadOutboxMaxId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + //Participants = GetObject(bytes, ref position); + About = GetObject(bytes, ref position); + ParticipantsCount = GetObject(Flags, (int)ChannelFullFlags.ParticipantsCount, null, bytes, ref position); + AdminsCount = GetObject(Flags, (int)ChannelFullFlags.AdminsCount, null, bytes, ref position); + KickedCount = GetObject(Flags, (int)ChannelFullFlags.KickedCount, null, bytes, ref position); + ReadInboxMaxId = GetObject(bytes, ref position); + ReadOutboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadImportantCount = new TLInt(0); + ChatPhoto = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + ExportedInvite = GetObject(bytes, ref position); + BotInfo = GetObject>(bytes, ref position); + MigratedFromChatId = GetObject(Flags, (int)ChannelFullFlags.Migrated, null, bytes, ref position); + MigratedFromMaxId = GetObject(Flags, (int)ChannelFullFlags.Migrated, null, bytes, ref position); + PinnedMsgId = GetObject(Flags, (int)ChannelFullFlags.PinnedMsgId, null, bytes, ref position); + + return this; + } + + public override TLChatBase ToChat(TLChatBase chat) + { + chat.NotifySettings = NotifySettings; + chat.Participants = Participants; + chat.ChatPhoto = ChatPhoto; + + var channel = chat as TLChannel; + if (channel != null) + { + channel.About = About; + channel.ParticipantsCount = ParticipantsCount; + channel.AdminsCount = AdminsCount; + channel.KickedCount = KickedCount; + channel.ReadInboxMaxId = ReadInboxMaxId; + channel.ExportedInvite = ExportedInvite; + channel.BotInfo = BotInfo; + channel.MigratedFromChatId = MigratedFromChatId; + channel.MigratedFromMaxId = MigratedFromMaxId; + } + + var channel49 = chat as TLChannel49; + if (channel49 != null) + { + channel49.ReadOutboxMaxId = ReadOutboxMaxId; + channel49.PinnedMsgId = PinnedMsgId; + } + + return chat; + } + } + + public class TLChannelFull68 : TLChannelFull53 + { + public new const uint Signature = TLConstructors.TLChannelFull68; + + protected TLInt _bannedCount; + + public TLInt BannedCount + { + get { return _bannedCount; } + set { SetField(out _bannedCount, value, ref _flags, (int)ChannelFullFlags.KickedCount); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + About = GetObject(bytes, ref position); + ParticipantsCount = GetObject(Flags, (int)ChannelFullFlags.ParticipantsCount, null, bytes, ref position); + _adminsCount = GetObject(Flags, (int)ChannelFullFlags.AdminsCount, null, bytes, ref position); + _kickedCount = GetObject(Flags, (int)ChannelFullFlags.KickedCount, null, bytes, ref position); + _bannedCount = GetObject(Flags, (int)ChannelFullFlags.KickedCount, null, bytes, ref position); + ReadInboxMaxId = GetObject(bytes, ref position); + ReadOutboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadImportantCount = new TLInt(0); + ChatPhoto = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + ExportedInvite = GetObject(bytes, ref position); + BotInfo = GetObject>(bytes, ref position); + _migratedFromChatId = GetObject(Flags, (int)ChannelFullFlags.Migrated, null, bytes, ref position); + _migratedFromMaxId = GetObject(Flags, (int)ChannelFullFlags.Migrated, null, bytes, ref position); + _pinnedMsgId = GetObject(Flags, (int)ChannelFullFlags.PinnedMsgId, null, bytes, ref position); + + return this; + } + + public override TLChatBase ToChat(TLChatBase chat) + { + chat.NotifySettings = NotifySettings; + chat.Participants = Participants; + chat.ChatPhoto = ChatPhoto; + + var channel = chat as TLChannel; + if (channel != null) + { + channel.About = About; + channel.ParticipantsCount = ParticipantsCount; + channel.AdminsCount = AdminsCount; + channel.KickedCount = KickedCount; + channel.ReadInboxMaxId = ReadInboxMaxId; + channel.ExportedInvite = ExportedInvite; + channel.BotInfo = BotInfo; + channel.MigratedFromChatId = MigratedFromChatId; + channel.MigratedFromMaxId = MigratedFromMaxId; + } + + var channel49 = chat as TLChannel49; + if (channel49 != null) + { + channel49.ReadOutboxMaxId = ReadOutboxMaxId; + channel49.PinnedMsgId = PinnedMsgId; + } + + var channel68 = chat as TLChannel68; + if (channel68 != null) + { + + } + + return chat; + } + } + + public class TLChannelFull71 : TLChannelFull68 + { + public new const uint Signature = TLConstructors.TLChannelFull71; + + public bool CanSetStickers + { + get { return IsSet(Flags, (int) ChannelFullFlags.CanSetStickers); } + } + + protected TLStickerSetBase _stickerSet; + + public TLStickerSetBase StickerSet + { + get { return _stickerSet; } + set { SetField(out _stickerSet, value, ref _flags, (int)ChannelFullFlags.StickerSet); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + About = GetObject(bytes, ref position); + ParticipantsCount = GetObject(Flags, (int)ChannelFullFlags.ParticipantsCount, null, bytes, ref position); + _adminsCount = GetObject(Flags, (int)ChannelFullFlags.AdminsCount, null, bytes, ref position); + _kickedCount = GetObject(Flags, (int)ChannelFullFlags.KickedCount, null, bytes, ref position); + _bannedCount = GetObject(Flags, (int)ChannelFullFlags.KickedCount, null, bytes, ref position); + ReadInboxMaxId = GetObject(bytes, ref position); + ReadOutboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadImportantCount = new TLInt(0); + ChatPhoto = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + ExportedInvite = GetObject(bytes, ref position); + BotInfo = GetObject>(bytes, ref position); + _migratedFromChatId = GetObject(Flags, (int)ChannelFullFlags.Migrated, null, bytes, ref position); + _migratedFromMaxId = GetObject(Flags, (int)ChannelFullFlags.Migrated, null, bytes, ref position); + _pinnedMsgId = GetObject(Flags, (int)ChannelFullFlags.PinnedMsgId, null, bytes, ref position); + _stickerSet = GetObject(Flags, (int)ChannelFullFlags.StickerSet, null, bytes, ref position); + + return this; + } + + public override TLChatBase ToChat(TLChatBase chat) + { + chat.NotifySettings = NotifySettings; + chat.Participants = Participants; + chat.ChatPhoto = ChatPhoto; + + var channel = chat as TLChannel; + if (channel != null) + { + channel.Full = true; + + channel.About = About; + channel.ParticipantsCount = ParticipantsCount; + channel.AdminsCount = AdminsCount; + channel.KickedCount = KickedCount; + channel.ReadInboxMaxId = ReadInboxMaxId; + channel.ExportedInvite = ExportedInvite; + channel.BotInfo = BotInfo; + channel.MigratedFromChatId = MigratedFromChatId; + channel.MigratedFromMaxId = MigratedFromMaxId; + } + + var channel49 = chat as TLChannel49; + if (channel49 != null) + { + channel49.ReadOutboxMaxId = ReadOutboxMaxId; + channel49.PinnedMsgId = PinnedMsgId; + } + + var channel68 = chat as TLChannel68; + if (channel68 != null) + { + channel68.CanSetStickers = CanSetStickers; + channel68.StickerSet = StickerSet ?? new TLStickerSetEmpty(); + } + + return chat; + } + } + + public class TLChannelFull72 : TLChannelFull71 + { + public new const uint Signature = TLConstructors.TLChannelFull72; + + public bool HiddenPrehistory + { + get { return IsSet(Flags, (int)ChannelFullFlags.HiddenPrehistory); } + } + + protected TLInt _availableMinId; + + public TLInt AvailableMinId + { + get { return _availableMinId; } + set { SetField(out _availableMinId, value, ref _flags, (int)ChannelFullFlags.AvailableMinId); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + About = GetObject(bytes, ref position); + ParticipantsCount = GetObject(Flags, (int)ChannelFullFlags.ParticipantsCount, null, bytes, ref position); + _adminsCount = GetObject(Flags, (int)ChannelFullFlags.AdminsCount, null, bytes, ref position); + _kickedCount = GetObject(Flags, (int)ChannelFullFlags.KickedCount, null, bytes, ref position); + _bannedCount = GetObject(Flags, (int)ChannelFullFlags.KickedCount, null, bytes, ref position); + ReadInboxMaxId = GetObject(bytes, ref position); + ReadOutboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadImportantCount = new TLInt(0); + ChatPhoto = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + ExportedInvite = GetObject(bytes, ref position); + BotInfo = GetObject>(bytes, ref position); + _migratedFromChatId = GetObject(Flags, (int)ChannelFullFlags.Migrated, null, bytes, ref position); + _migratedFromMaxId = GetObject(Flags, (int)ChannelFullFlags.Migrated, null, bytes, ref position); + _pinnedMsgId = GetObject(Flags, (int)ChannelFullFlags.PinnedMsgId, null, bytes, ref position); + _stickerSet = GetObject(Flags, (int)ChannelFullFlags.StickerSet, null, bytes, ref position); + _availableMinId = GetObject(Flags, (int)ChannelFullFlags.AvailableMinId, null, bytes, ref position); + + return this; + } + + public override TLChatBase ToChat(TLChatBase chat) + { + chat.NotifySettings = NotifySettings; + chat.Participants = Participants; + chat.ChatPhoto = ChatPhoto; + + var channel = chat as TLChannel; + if (channel != null) + { + channel.Full = true; + + channel.About = About; + channel.ParticipantsCount = ParticipantsCount; + channel.AdminsCount = AdminsCount; + channel.KickedCount = KickedCount; + channel.ReadInboxMaxId = ReadInboxMaxId; + channel.ExportedInvite = ExportedInvite; + channel.BotInfo = BotInfo; + channel.MigratedFromChatId = MigratedFromChatId; + channel.MigratedFromMaxId = MigratedFromMaxId; + } + + var channel49 = chat as TLChannel49; + if (channel49 != null) + { + channel49.ReadOutboxMaxId = ReadOutboxMaxId; + channel49.PinnedMsgId = PinnedMsgId; + } + + var channel68 = chat as TLChannel68; + if (channel68 != null) + { + channel68.CanSetStickers = CanSetStickers; + channel68.StickerSet = StickerSet ?? new TLStickerSetEmpty(); + + channel68.HiddenPrehistory = HiddenPrehistory; + channel68.AvailableMinId = AvailableMinId; + } + + return chat; + } + } +} diff --git a/Telegram.Api/TL/TLChatInvite.cs b/Telegram.Api/TL/TLChatInvite.cs new file mode 100755 index 0000000..6793a11 --- /dev/null +++ b/Telegram.Api/TL/TLChatInvite.cs @@ -0,0 +1,285 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ChatInviteFlags + { + Channel = 0x1, + Broadcast = 0x2, + Public = 0x4, + MegaGroup = 0x8, + Participants = 0x10, + } + + public abstract class TLChatInviteBase : TLObject { } + + public abstract class TLExportedChatInvite : TLChatInviteBase { } + + public class TLChatInviteEmpty : TLExportedChatInvite + { + public const uint Signature = TLConstructors.TLChatInviteEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLChatInviteExported : TLExportedChatInvite + { + public const uint Signature = TLConstructors.TLChatInviteExported; + + public TLString Link { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Link = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Link.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Link = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Link.ToBytes()); + } + } + + public class TLChatInviteAlready : TLChatInviteBase + { + public const uint Signature = TLConstructors.TLChatInviteAlready; + + public TLChatBase Chat { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Chat = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Chat.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Chat = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Chat.ToBytes()); + } + } + + public class TLChatInvite : TLChatInviteBase + { + public const uint Signature = TLConstructors.TLChatInvite; + + public TLString Title { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Title = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Title.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Title = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Title.ToBytes()); + } + } + + public class TLChatInvite40 : TLChatInvite + { + public new const uint Signature = TLConstructors.TLChatInvite40; + + public TLInt Flags { get; set; } + + public bool IsChannel { get { return IsSet(Flags, (int) ChatInviteFlags.Channel); } } + + public bool IsBroadcast { get { return IsSet(Flags, (int)ChatInviteFlags.Broadcast); } } + + public bool IsPublic { get { return IsSet(Flags, (int)ChatInviteFlags.Public); } } + + public bool IsMegaGroup { get { return IsSet(Flags, (int)ChatInviteFlags.MegaGroup); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Title.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Title = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + output.Write(Title.ToBytes()); + } + } + + public class TLChatInvite54 : TLChatInvite40 + { + public new const uint Signature = TLConstructors.TLChatInvite54; + + public TLPhotoBase Photo { get; set; } + + public TLInt ParticipantsCount { get; set; } + + public TLVector Participants { get; set; } + + public static string ChatInviteFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (ChatInviteFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public override string ToString() + { + return "TLChatInvite54 flags=" + ChatInviteFlagsString(Flags); + } + + #region Additional + public TLChatBase Chat { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + Photo = GetObject(bytes, ref position); + ParticipantsCount = GetObject(bytes, ref position); + Participants = GetObject>(Flags, (int) ChatInviteFlags.Participants, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Title.ToBytes(), + Photo.ToBytes(), + ParticipantsCount.ToBytes(), + ToBytes(Participants, Flags, (int) ChatInviteFlags.Participants)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Title = GetObject(input); + Photo = GetObject(input); + ParticipantsCount = GetObject(input); + Participants = GetObject>(Flags, (int) ChatInviteFlags.Participants, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + output.Write(Title.ToBytes()); + output.Write(Photo.ToBytes()); + output.Write(ParticipantsCount.ToBytes()); + ToStream(output, Participants, Flags, (int) ChatInviteFlags.Participants); + } + } +} diff --git a/Telegram.Api/TL/TLChatParticipant.cs b/Telegram.Api/TL/TLChatParticipant.cs new file mode 100755 index 0000000..6e3c86f --- /dev/null +++ b/Telegram.Api/TL/TLChatParticipant.cs @@ -0,0 +1,125 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public interface IInviter + { + TLInt InviterId { get; set; } + + TLInt Date { get; set; } + } + + public abstract class TLChatParticipantBase : TLObject + { + public TLInt UserId { get; set; } + } + + public class TLChatParticipant : TLChatParticipantBase, IInviter + { + public const uint Signature = TLConstructors.TLChatParticipant; + + public TLInt InviterId { get; set; } + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + InviterId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + InviterId = GetObject(input); + Date = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(UserId.ToBytes()); + output.Write(InviterId.ToBytes()); + output.Write(Date.ToBytes()); + } + } + + public class TLChatParticipantCreator : TLChatParticipantBase + { + public const uint Signature = TLConstructors.TLChatParticipantCreator; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(UserId.ToBytes()); + } + } + + public class TLChatParticipantAdmin : TLChatParticipantBase, IInviter + { + public const uint Signature = TLConstructors.TLChatParticipantAdmin; + + public TLInt InviterId { get; set; } + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + InviterId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + InviterId = GetObject(input); + Date = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(UserId.ToBytes()); + output.Write(InviterId.ToBytes()); + output.Write(Date.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLChatParticipants.cs b/Telegram.Api/TL/TLChatParticipants.cs new file mode 100755 index 0000000..c5b53ec --- /dev/null +++ b/Telegram.Api/TL/TLChatParticipants.cs @@ -0,0 +1,228 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public enum ChatParticipantsFlags + { + Self = 0x1, + } + + public abstract class TLChatParticipantsBase : TLObject + { + public TLInt ChatId { get; set; } + } + + public class TLChatParticipantsForbidden37 : TLChatParticipantsForbidden + { + public new const uint Signature = TLConstructors.TLChatParticipantsForbidden37; + + public TLInt Flags { get; set; } + + public TLChatParticipantBase SelfParticipant { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + ChatId = GetObject(bytes, ref position); + if (IsSet(Flags, (int) ChatParticipantsFlags.Self)) + { + SelfParticipant = GetObject(bytes, ref position); + } + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + ChatId = GetObject(input); + if (IsSet(Flags, (int)ChatParticipantsFlags.Self)) + { + SelfParticipant = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + output.Write(ChatId.ToBytes()); + if (IsSet(Flags, (int)ChatParticipantsFlags.Self)) + { + SelfParticipant.ToStream(output); + } + } + } + + public class TLChatParticipantsForbidden : TLChatParticipantsBase + { + public const uint Signature = TLConstructors.TLChatParticipantsForbidden; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(ChatId.ToBytes()); + } + } + + public interface IChatParticipants + { + TLInt ChatId { get; set; } + + TLVector Participants { get; set; } + + TLInt Version { get; set; } + } + + public class TLChatParticipants : TLChatParticipantsBase, IChatParticipants + { + public const uint Signature = TLConstructors.TLChatParticipants; + + public TLInt AdminId { get; set; } + + public TLVector Participants { get; set; } + + public TLInt Version { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + AdminId = GetObject(bytes, ref position); + Participants = GetObject>(bytes, ref position); + Version = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + AdminId = GetObject(input); + Participants = GetObject>(input); + Version = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(ChatId.ToBytes()); + output.Write(AdminId.ToBytes()); + Participants.ToStream(output); + output.Write(Version.ToBytes()); + } + } + + public class TLChatParticipants40 : TLChatParticipantsBase, IChatParticipants + { + public const uint Signature = TLConstructors.TLChatParticipants40; + + public TLVector Participants { get; set; } + + public TLInt Version { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + Participants = GetObject>(bytes, ref position); + Version = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + Participants = GetObject>(input); + Version = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(ChatId.ToBytes()); + Participants.ToStream(output); + output.Write(Version.ToBytes()); + } + } + + public class TLChannelParticipants40 : TLChatParticipantsBase + { + public const uint Signature = TLConstructors.TLChannelParticipants40; + + public TLInt Flags { get; set; } + + public TLChatParticipantBase SelfParticipant { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + ChatId = GetObject(bytes, ref position); + if (IsSet(Flags, (int)ChatParticipantsFlags.Self)) + { + SelfParticipant = GetObject(bytes, ref position); + } + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + ChatId = GetObject(input); + if (IsSet(Flags, (int)ChatParticipantsFlags.Self)) + { + SelfParticipant = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(ChatId.ToBytes()); + if (IsSet(Flags, (int)ChatParticipantsFlags.Self)) + { + SelfParticipant.ToStream(output); + } + } + } +} diff --git a/Telegram.Api/TL/TLChatSettings.cs b/Telegram.Api/TL/TLChatSettings.cs new file mode 100755 index 0000000..4885b70 --- /dev/null +++ b/Telegram.Api/TL/TLChatSettings.cs @@ -0,0 +1,108 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ChatSettingsFlags + { + AutoDownloadPhotoPrivateChats = 0x1, // 0 + AutoDownloadPhotoGroups = 0x2, // 1 + AutoDownloadAudioPrivateChats = 0x4, // 2 + AutoDownloadAudioGroups = 0x8, // 3 + AutoDownloadGifPrivateChats = 0x10, + AutoDownloadGifGroups = 0x20, + AutoPlayGif = 0x40 + } + + public class TLChatSettings : TLObject + { + public const uint Signature = TLConstructors.TLChatSettings; + + private TLLong _flags; + + public TLLong Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool AutoDownloadPhotoPrivateChats + { + get { return IsSet(Flags, (int) ChatSettingsFlags.AutoDownloadPhotoPrivateChats); } + set { SetUnset(ref _flags, value, (int)ChatSettingsFlags.AutoDownloadPhotoPrivateChats); } + } + + public bool AutoDownloadPhotoGroups + { + get { return IsSet(Flags, (int)ChatSettingsFlags.AutoDownloadPhotoGroups); } + set { SetUnset(ref _flags, value, (int)ChatSettingsFlags.AutoDownloadPhotoGroups); } + } + + public bool AutoDownloadAudioPrivateChats + { + get { return IsSet(Flags, (int)ChatSettingsFlags.AutoDownloadAudioPrivateChats); } + set { SetUnset(ref _flags, value, (int)ChatSettingsFlags.AutoDownloadAudioPrivateChats); } + } + + public bool AutoDownloadAudioGroups + { + get { return IsSet(Flags, (int)ChatSettingsFlags.AutoDownloadAudioGroups); } + set { SetUnset(ref _flags, value, (int)ChatSettingsFlags.AutoDownloadAudioGroups); } + } + + public bool AutoDownloadGifPrivateChats + { + get { return IsSet(Flags, (int)ChatSettingsFlags.AutoDownloadGifPrivateChats); } + set { SetUnset(ref _flags, value, (int)ChatSettingsFlags.AutoDownloadGifPrivateChats); } + } + + public bool AutoDownloadGifGroups + { + get { return IsSet(Flags, (int)ChatSettingsFlags.AutoDownloadGifGroups); } + set { SetUnset(ref _flags, value, (int)ChatSettingsFlags.AutoDownloadGifGroups); } + } + + public bool AutoPlayGif + { + get { return IsSet(Flags, (int)ChatSettingsFlags.AutoPlayGif); } + set { SetUnset(ref _flags, value, (int)ChatSettingsFlags.AutoPlayGif); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), Flags.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLChats.cs b/Telegram.Api/TL/TLChats.cs new file mode 100755 index 0000000..511d257 --- /dev/null +++ b/Telegram.Api/TL/TLChats.cs @@ -0,0 +1,82 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLChatsBase : TLObject + { + public TLVector Chats { get; set; } + } + + public class TLChats : TLChatsBase + { + public const uint Signature = TLConstructors.TLChats; + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } + + public class TLChats24 : TLChatsBase + { + public const uint Signature = TLConstructors.TLChats24; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Chats = GetObject>(bytes, ref position); + + return this; + } + } + + public class TLChatsSlice : TLChatsBase + { + public const uint Signature = TLConstructors.TLChatsSlice; + + public TLInt Count { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Count = GetObject(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } + + public class TLChatsSlice59 : TLChatsBase + { + public const uint Signature = TLConstructors.TLChatsSlice59; + + public TLInt Count { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Count = GetObject(bytes, ref position); + Chats = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLChatsSlice.cs b/Telegram.Api/TL/TLChatsSlice.cs new file mode 100755 index 0000000..8535af8 --- /dev/null +++ b/Telegram.Api/TL/TLChatsSlice.cs @@ -0,0 +1,24 @@ +namespace Telegram.Api.TL +{ + public class TLChatsSlice : TLObject + { + public const uint Signature = TLConstructors.TLChatsSlice; + + public TLInt Count { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Count = GetObject(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLCheckedPhone.cs b/Telegram.Api/TL/TLCheckedPhone.cs new file mode 100755 index 0000000..1b94a99 --- /dev/null +++ b/Telegram.Api/TL/TLCheckedPhone.cs @@ -0,0 +1,45 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLCheckedPhoneBase : TLObject + { + public TLBool PhoneRegistered { get; set; } + } + + public class TLCheckedPhone : TLCheckedPhoneBase + { + public const uint Signature = TLConstructors.TLCheckedPhone; + + public TLBool PhoneInvited { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhoneRegistered = GetObject(bytes, ref position); + PhoneInvited = GetObject(bytes, ref position); + + return this; + } + } + + public class TLCheckedPhone24 : TLCheckedPhoneBase + { + public const uint Signature = TLConstructors.TLCheckedPhone24; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhoneRegistered = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLClientDHInnerData.cs b/Telegram.Api/TL/TLClientDHInnerData.cs new file mode 100755 index 0000000..0fd1c7f --- /dev/null +++ b/Telegram.Api/TL/TLClientDHInnerData.cs @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLClientDHInnerData : TLObject + { + public const string Signature = "#6643b654"; + + public TLInt128 Nonce { get; set; } + + public TLInt128 ServerNonce { get; set; } + + public TLLong RetryId { get; set; } + + public TLString GB { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Nonce.ToBytes(), + ServerNonce.ToBytes(), + RetryId.ToBytes(), + GB.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLCodeType.cs b/Telegram.Api/TL/TLCodeType.cs new file mode 100755 index 0000000..1f7885e --- /dev/null +++ b/Telegram.Api/TL/TLCodeType.cs @@ -0,0 +1,64 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLCodeTypeBase : TLObject + { + } + + public class TLCodeTypeSms : TLCodeTypeBase + { + public const uint Signature = TLConstructors.TLCodeTypeSms; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLCodeTypeCall : TLCodeTypeBase + { + public const uint Signature = TLConstructors.TLCodeTypeCall; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLCodeTypeFlashCall : TLCodeTypeBase + { + public const uint Signature = TLConstructors.TLCodeTypeFlashCall; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLConfig.cs b/Telegram.Api/TL/TLConfig.cs new file mode 100755 index 0000000..982f19b --- /dev/null +++ b/Telegram.Api/TL/TLConfig.cs @@ -0,0 +1,1719 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ConfigFlags + { + TmpSessions = 0x1, // 0 + PhoneCallsEnabled = 0x2, // 1 + Lang = 0x4, // 2 + DefaultP2PContacts = 0x8, // 3 + PreloadFeaturedStickers = 0x10, // 4 + IgnorePhoneEntities = 0x20, // 5 + RevokePmInbox = 0x40, // 6 + AutoupdateUrlPrefix = 0x80, // 7 + BlockedMode = 0x100, // 8 + GifSearchUsername = 0x200, // 9 + VenueSearchUsername = 0x400, // 10 + ImgSearchUsername = 0x800, // 11 + StaticMapsProvider = 0x1000, // 12 + } + + [DataContract] + public class TLConfig : TLObject + { + public const uint Signature = TLConstructors.TLConfig; + + [DataMember] + public TLInt Date { get; set; } + + [DataMember] + public TLBool TestMode { get; set; } + + /// + /// Номер датацентра, ему может соответствовать несколько записей в DCOptions + /// + [DataMember] + public TLInt ThisDC { get; set; } + + [DataMember] + public TLVector DCOptions { get; set; } + + [DataMember] + public TLInt ChatSizeMax { get; set; } + + [DataMember] + public TLInt BroadcastSizeMax { get; set; } + + #region Additional + /// + /// Время последней загрузки config + /// + [DataMember] + public DateTime LastUpdate { get; set; } + + /// + /// Номер конкретного датацентра внутри списка DCOptions, однозначно определяет текущий датацентр + /// + [DataMember] + public int ActiveDCOptionIndex { get; set; } + + [DataMember] + public string Country { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); + + return this; + } + + public static TLConfig Merge(TLConfig oldConfig, TLConfig newConfig) + { + if (oldConfig == null) + return newConfig; + + if (newConfig == null) + return oldConfig; + + foreach (var dcOption in oldConfig.DCOptions) + { + if (dcOption.AuthKey != null) + { + var option = dcOption; + foreach (var newDCOption in newConfig.DCOptions.Where(x => x.AreEquals(option))) + { + newDCOption.AuthKey = dcOption.AuthKey; + newDCOption.Salt = dcOption.Salt; + newDCOption.SessionId = dcOption.SessionId; + newDCOption.ClientTicksDelta = dcOption.ClientTicksDelta; + } + } + } + if (!string.IsNullOrEmpty(oldConfig.Country)) + { + newConfig.Country = oldConfig.Country; + } + if (oldConfig.ActiveDCOptionIndex != default(int)) + { + var oldActiveDCOption = oldConfig.DCOptions[oldConfig.ActiveDCOptionIndex]; + var dcId = oldConfig.DCOptions[oldConfig.ActiveDCOptionIndex].Id.Value; + var ipv6 = oldActiveDCOption.IPv6.Value; + var media = oldActiveDCOption.Media.Value; + + TLDCOption newActiveDCOption = null; + int newActiveDCOptionIndex = 0; + for (var i = 0; i < newConfig.DCOptions.Count; i++) + { + if (newConfig.DCOptions[i].Id.Value == dcId + && newConfig.DCOptions[i].IPv6.Value == ipv6 + && newConfig.DCOptions[i].Media.Value == media) + { + newActiveDCOption = newConfig.DCOptions[i]; + newActiveDCOptionIndex = i; + break; + } + } + + if (newActiveDCOption == null) + { + for (var i = 0; i < newConfig.DCOptions.Count; i++) + { + if (newConfig.DCOptions[i].Id.Value == dcId) + { + newActiveDCOption = newConfig.DCOptions[i]; + newActiveDCOptionIndex = i; + break; + } + } + } + + newConfig.ActiveDCOptionIndex = newActiveDCOptionIndex; + } + if (oldConfig.LastUpdate != default(DateTime)) + { + newConfig.LastUpdate = oldConfig.LastUpdate; + } + + return newConfig; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("BroadcastSizeMax {0}", BroadcastSizeMax)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig23 : TLConfig + { + public new const uint Signature = TLConstructors.TLConfig23; + + [DataMember] + public TLInt Expires { get; set; } + + [DataMember] + public TLInt ChatBigSize { get; set; } + + [DataMember] + public TLVector DisabledFeatures { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("BroadcastSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig24 : TLConfig23 + { + public new const uint Signature = TLConstructors.TLConfig24; + + [DataMember] + public TLInt OnlineUpdatePeriodMs { get; set; } + + [DataMember] + public TLInt OfflineBlurTimeoutMs { get; set; } + + [DataMember] + public TLInt OfflineIdleTimeoutMs { get; set; } + + [DataMember] + public TLInt OnlineCloudTimeoutMs { get; set; } + + [DataMember] + public TLInt NotifyCloudDelayMs { get; set; } + + [DataMember] + public TLInt NotifyDefaultDelayMs { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("BroadcastSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig26 : TLConfig24 + { + public new const uint Signature = TLConstructors.TLConfig26; + + [DataMember] + public TLInt ForwardedCountMax { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("BroadcastSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig28 : TLConfig26 + { + public new const uint Signature = TLConstructors.TLConfig28; + + [DataMember] + public TLInt PushChatPeriodMs { get; set; } + + [DataMember] + public TLInt PushChatLimit { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("BroadcastSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig41 : TLConfig28 + { + public new const uint Signature = TLConstructors.TLConfig41; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig44 : TLConfig41 + { + public new const uint Signature = TLConstructors.TLConfig44; + + [DataMember] + public TLInt SavedGifsLimit { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig48 : TLConfig44 + { + public new const uint Signature = TLConstructors.TLConfig48; + + [DataMember] + public TLInt EditTimeLimit { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig52 : TLConfig48 + { + public new const uint Signature = TLConstructors.TLConfig52; + + [DataMember] + public TLInt RatingEDecay { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + RatingEDecay = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("RatingEDecay {0}", RatingEDecay)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig54 : TLConfig52 + { + public new const uint Signature = TLConstructors.TLConfig54; + + [DataMember] + public TLInt StickersRecentLimit { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + RatingEDecay = GetObject(bytes, ref position); + StickersRecentLimit = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("RatingEDecay {0}", RatingEDecay)); + sb.AppendLine(string.Format("StickersRecentLimit {0}", StickersRecentLimit)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig55 : TLConfig54 + { + public new const uint Signature = TLConstructors.TLConfig55; + + protected TLInt _flags; + + [DataMember] + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + [DataMember] + public TLInt TmpSessions { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + RatingEDecay = GetObject(bytes, ref position); + StickersRecentLimit = GetObject(bytes, ref position); + TmpSessions = GetObject(Flags, (int)ConfigFlags.TmpSessions, null, bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public static string ConfigFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (ConfigFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Flags {0}", ConfigFlagsString(Flags))); + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("RatingEDecay {0}", RatingEDecay)); + sb.AppendLine(string.Format("StickersRecentLimit {0}", StickersRecentLimit)); + sb.AppendLine(string.Format("TmpSessions {0}", TmpSessions)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig60 : TLConfig55 + { + public new const uint Signature = TLConstructors.TLConfig60; + + public bool PhoneCallsEnabled { get { return IsSet(Flags, (int)ConfigFlags.PhoneCallsEnabled); } } + + [DataMember] + public TLInt CallReceiveTimeoutMs { get; set; } + + [DataMember] + public TLInt CallRingTimeoutMs { get; set; } + + [DataMember] + public TLInt CallConnectTimeoutMs { get; set; } + + [DataMember] + public TLInt CallPacketTimeoutMs { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + RatingEDecay = GetObject(bytes, ref position); + StickersRecentLimit = GetObject(bytes, ref position); + TmpSessions = GetObject(Flags, (int)ConfigFlags.TmpSessions, null, bytes, ref position); + CallReceiveTimeoutMs = GetObject(bytes, ref position); + CallRingTimeoutMs = GetObject(bytes, ref position); + CallConnectTimeoutMs = GetObject(bytes, ref position); + CallPacketTimeoutMs = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Flags {0}", ConfigFlagsString(Flags))); + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("RatingEDecay {0}", RatingEDecay)); + sb.AppendLine(string.Format("StickersRecentLimit {0}", StickersRecentLimit)); + sb.AppendLine(string.Format("TmpSessions {0}", TmpSessions)); + sb.AppendLine(string.Format("CallReceiveTimeoutMs {0}", CallReceiveTimeoutMs)); + sb.AppendLine(string.Format("CallRingTimeoutMs {0}", CallRingTimeoutMs)); + sb.AppendLine(string.Format("CallConnectTimeoutMs {0}", CallConnectTimeoutMs)); + sb.AppendLine(string.Format("CallPacketTimeoutMs {0}", CallPacketTimeoutMs)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig61 : TLConfig60 + { + public new const uint Signature = TLConstructors.TLConfig61; + + [DataMember] + public TLInt PinnedDialogsCountMax { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + RatingEDecay = GetObject(bytes, ref position); + StickersRecentLimit = GetObject(bytes, ref position); + TmpSessions = GetObject(Flags, (int)ConfigFlags.TmpSessions, null, bytes, ref position); + PinnedDialogsCountMax = GetObject(bytes, ref position); + CallReceiveTimeoutMs = GetObject(bytes, ref position); + CallRingTimeoutMs = GetObject(bytes, ref position); + CallConnectTimeoutMs = GetObject(bytes, ref position); + CallPacketTimeoutMs = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Flags {0}", ConfigFlagsString(Flags))); + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("RatingEDecay {0}", RatingEDecay)); + sb.AppendLine(string.Format("StickersRecentLimit {0}", StickersRecentLimit)); + sb.AppendLine(string.Format("TmpSessions {0}", TmpSessions)); + sb.AppendLine(string.Format("PinnedDialogsCountMax {0}", PinnedDialogsCountMax)); + sb.AppendLine(string.Format("CallReceiveTimeoutMs {0}", CallReceiveTimeoutMs)); + sb.AppendLine(string.Format("CallRingTimeoutMs {0}", CallRingTimeoutMs)); + sb.AppendLine(string.Format("CallConnectTimeoutMs {0}", CallConnectTimeoutMs)); + sb.AppendLine(string.Format("CallPacketTimeoutMs {0}", CallPacketTimeoutMs)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig63 : TLConfig61 + { + public new const uint Signature = TLConstructors.TLConfig63; + + [DataMember] + public TLString MeUrlPrefix { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + RatingEDecay = GetObject(bytes, ref position); + StickersRecentLimit = GetObject(bytes, ref position); + TmpSessions = GetObject(Flags, (int)ConfigFlags.TmpSessions, null, bytes, ref position); + PinnedDialogsCountMax = GetObject(bytes, ref position); + CallReceiveTimeoutMs = GetObject(bytes, ref position); + CallRingTimeoutMs = GetObject(bytes, ref position); + CallConnectTimeoutMs = GetObject(bytes, ref position); + CallPacketTimeoutMs = GetObject(bytes, ref position); + MeUrlPrefix = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Flags {0}", ConfigFlagsString(Flags))); + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("RatingEDecay {0}", RatingEDecay)); + sb.AppendLine(string.Format("StickersRecentLimit {0}", StickersRecentLimit)); + sb.AppendLine(string.Format("TmpSessions {0}", TmpSessions)); + sb.AppendLine(string.Format("PinnedDialogsCountMax {0}", PinnedDialogsCountMax)); + sb.AppendLine(string.Format("CallReceiveTimeoutMs {0}", CallReceiveTimeoutMs)); + sb.AppendLine(string.Format("CallRingTimeoutMs {0}", CallRingTimeoutMs)); + sb.AppendLine(string.Format("CallConnectTimeoutMs {0}", CallConnectTimeoutMs)); + sb.AppendLine(string.Format("CallPacketTimeoutMs {0}", CallPacketTimeoutMs)); + sb.AppendLine(string.Format("MeUrlPrefix {0}", MeUrlPrefix)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig67 : TLConfig63 + { + public new const uint Signature = TLConstructors.TLConfig67; + + protected TLString _suggestedLangCode; + + [DataMember] + public TLString SuggestedLangCode + { + get { return _suggestedLangCode; } + set { SetField(out _suggestedLangCode, value, ref _flags, (int)ConfigFlags.Lang); } + } + + protected TLInt _langPackVersion; + + [DataMember] + public TLInt LangPackVersion + { + get { return _langPackVersion; } + set { SetField(out _langPackVersion, value, ref _flags, (int)ConfigFlags.Lang); } + } + + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + RatingEDecay = GetObject(bytes, ref position); + StickersRecentLimit = GetObject(bytes, ref position); + TmpSessions = GetObject(Flags, (int)ConfigFlags.TmpSessions, null, bytes, ref position); + PinnedDialogsCountMax = GetObject(bytes, ref position); + CallReceiveTimeoutMs = GetObject(bytes, ref position); + CallRingTimeoutMs = GetObject(bytes, ref position); + CallConnectTimeoutMs = GetObject(bytes, ref position); + CallPacketTimeoutMs = GetObject(bytes, ref position); + MeUrlPrefix = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + _suggestedLangCode = GetObject(Flags, (int)ConfigFlags.Lang, null, bytes, ref position); + _langPackVersion = GetObject(Flags, (int)ConfigFlags.Lang, null, bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Flags {0}", ConfigFlagsString(Flags))); + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("RatingEDecay {0}", RatingEDecay)); + sb.AppendLine(string.Format("StickersRecentLimit {0}", StickersRecentLimit)); + sb.AppendLine(string.Format("TmpSessions {0}", TmpSessions)); + sb.AppendLine(string.Format("PinnedDialogsCountMax {0}", PinnedDialogsCountMax)); + sb.AppendLine(string.Format("CallReceiveTimeoutMs {0}", CallReceiveTimeoutMs)); + sb.AppendLine(string.Format("CallRingTimeoutMs {0}", CallRingTimeoutMs)); + sb.AppendLine(string.Format("CallConnectTimeoutMs {0}", CallConnectTimeoutMs)); + sb.AppendLine(string.Format("CallPacketTimeoutMs {0}", CallPacketTimeoutMs)); + sb.AppendLine(string.Format("MeUrlPrefix {0}", MeUrlPrefix)); + sb.AppendLine(string.Format("SuggestedLangCode {0}", SuggestedLangCode)); + sb.AppendLine(string.Format("LangPackVersion {0}", LangPackVersion)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig71 : TLConfig67 + { + public new const uint Signature = TLConstructors.TLConfig71; + + [DataMember] + public TLInt StickersFavedLimit { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + RatingEDecay = GetObject(bytes, ref position); + StickersRecentLimit = GetObject(bytes, ref position); + StickersFavedLimit = GetObject(bytes, ref position); + TmpSessions = GetObject(Flags, (int)ConfigFlags.TmpSessions, null, bytes, ref position); + PinnedDialogsCountMax = GetObject(bytes, ref position); + CallReceiveTimeoutMs = GetObject(bytes, ref position); + CallRingTimeoutMs = GetObject(bytes, ref position); + CallConnectTimeoutMs = GetObject(bytes, ref position); + CallPacketTimeoutMs = GetObject(bytes, ref position); + MeUrlPrefix = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + _suggestedLangCode = GetObject(Flags, (int)ConfigFlags.Lang, null, bytes, ref position); + _langPackVersion = GetObject(Flags, (int)ConfigFlags.Lang, null, bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Flags {0}", ConfigFlagsString(Flags))); + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("RatingEDecay {0}", RatingEDecay)); + sb.AppendLine(string.Format("StickersRecentLimit {0}", StickersRecentLimit)); + sb.AppendLine(string.Format("StickersFavedLimit {0}", StickersFavedLimit)); + sb.AppendLine(string.Format("TmpSessions {0}", TmpSessions)); + sb.AppendLine(string.Format("PinnedDialogsCountMax {0}", PinnedDialogsCountMax)); + sb.AppendLine(string.Format("CallReceiveTimeoutMs {0}", CallReceiveTimeoutMs)); + sb.AppendLine(string.Format("CallRingTimeoutMs {0}", CallRingTimeoutMs)); + sb.AppendLine(string.Format("CallConnectTimeoutMs {0}", CallConnectTimeoutMs)); + sb.AppendLine(string.Format("CallPacketTimeoutMs {0}", CallPacketTimeoutMs)); + sb.AppendLine(string.Format("MeUrlPrefix {0}", MeUrlPrefix)); + sb.AppendLine(string.Format("SuggestedLangCode {0}", SuggestedLangCode)); + sb.AppendLine(string.Format("LangPackVersion {0}", LangPackVersion)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig72 : TLConfig71 + { + public new const uint Signature = TLConstructors.TLConfig72; + + [DataMember] + public TLInt ChannelsReadMediaPeriod { get; set; } + + public bool PreloadFeaturedStickers { get { return IsSet(Flags, (int)ConfigFlags.PreloadFeaturedStickers); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = GetObject(bytes, ref position); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + RatingEDecay = GetObject(bytes, ref position); + StickersRecentLimit = GetObject(bytes, ref position); + StickersFavedLimit = GetObject(bytes, ref position); + ChannelsReadMediaPeriod = GetObject(bytes, ref position); + TmpSessions = GetObject(Flags, (int)ConfigFlags.TmpSessions, null, bytes, ref position); + PinnedDialogsCountMax = GetObject(bytes, ref position); + CallReceiveTimeoutMs = GetObject(bytes, ref position); + CallRingTimeoutMs = GetObject(bytes, ref position); + CallConnectTimeoutMs = GetObject(bytes, ref position); + CallPacketTimeoutMs = GetObject(bytes, ref position); + MeUrlPrefix = GetObject(bytes, ref position); + DisabledFeatures = GetObject>(bytes, ref position); + _suggestedLangCode = GetObject(Flags, (int)ConfigFlags.Lang, null, bytes, ref position); + _langPackVersion = GetObject(Flags, (int)ConfigFlags.Lang, null, bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Flags {0}", ConfigFlagsString(Flags))); + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("ChatBigSize {0}", ChatBigSize)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("RatingEDecay {0}", RatingEDecay)); + sb.AppendLine(string.Format("StickersRecentLimit {0}", StickersRecentLimit)); + sb.AppendLine(string.Format("StickersFavedLimit {0}", StickersFavedLimit)); + sb.AppendLine(string.Format("ChannelsReadMediaPeriod {0}", ChannelsReadMediaPeriod)); + sb.AppendLine(string.Format("TmpSessions {0}", TmpSessions)); + sb.AppendLine(string.Format("PinnedDialogsCountMax {0}", PinnedDialogsCountMax)); + sb.AppendLine(string.Format("CallReceiveTimeoutMs {0}", CallReceiveTimeoutMs)); + sb.AppendLine(string.Format("CallRingTimeoutMs {0}", CallRingTimeoutMs)); + sb.AppendLine(string.Format("CallConnectTimeoutMs {0}", CallConnectTimeoutMs)); + sb.AppendLine(string.Format("CallPacketTimeoutMs {0}", CallPacketTimeoutMs)); + sb.AppendLine(string.Format("MeUrlPrefix {0}", MeUrlPrefix)); + sb.AppendLine(string.Format("SuggestedLangCode {0}", SuggestedLangCode)); + sb.AppendLine(string.Format("LangPackVersion {0}", LangPackVersion)); + sb.AppendLine(string.Format("DisabledFeatures {0}", DisabledFeatures.Count)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig76 : TLConfig72 + { + public new const uint Signature = TLConstructors.TLConfig76; + + [DataMember] + public TLInt RevokeTimeLimit { get; set; } + + [DataMember] + public TLInt RevokePmTimeLimit { get; set; } + + public bool IgnorePhoneEntities { get { return IsSet(Flags, (int)ConfigFlags.IgnorePhoneEntities); } } + + public bool RevokePmInbox { get { return IsSet(Flags, (int)ConfigFlags.RevokePmInbox); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = new TLInt(int.MaxValue); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + RevokeTimeLimit = GetObject(bytes, ref position); + RevokePmTimeLimit = GetObject(bytes, ref position); + RatingEDecay = GetObject(bytes, ref position); + StickersRecentLimit = GetObject(bytes, ref position); + StickersFavedLimit = GetObject(bytes, ref position); + ChannelsReadMediaPeriod = GetObject(bytes, ref position); + TmpSessions = GetObject(Flags, (int)ConfigFlags.TmpSessions, null, bytes, ref position); + PinnedDialogsCountMax = GetObject(bytes, ref position); + CallReceiveTimeoutMs = GetObject(bytes, ref position); + CallRingTimeoutMs = GetObject(bytes, ref position); + CallConnectTimeoutMs = GetObject(bytes, ref position); + CallPacketTimeoutMs = GetObject(bytes, ref position); + MeUrlPrefix = GetObject(bytes, ref position); + DisabledFeatures = new TLVector(); + _suggestedLangCode = GetObject(Flags, (int)ConfigFlags.Lang, null, bytes, ref position); + _langPackVersion = GetObject(Flags, (int)ConfigFlags.Lang, null, bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Flags {0}", ConfigFlagsString(Flags))); + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("RevokeTimeLimit {0}", RevokeTimeLimit)); + sb.AppendLine(string.Format("RevokePmTimeLimit {0}", RevokePmTimeLimit)); + sb.AppendLine(string.Format("RatingEDecay {0}", RatingEDecay)); + sb.AppendLine(string.Format("StickersRecentLimit {0}", StickersRecentLimit)); + sb.AppendLine(string.Format("StickersFavedLimit {0}", StickersFavedLimit)); + sb.AppendLine(string.Format("ChannelsReadMediaPeriod {0}", ChannelsReadMediaPeriod)); + sb.AppendLine(string.Format("TmpSessions {0}", TmpSessions)); + sb.AppendLine(string.Format("PinnedDialogsCountMax {0}", PinnedDialogsCountMax)); + sb.AppendLine(string.Format("CallReceiveTimeoutMs {0}", CallReceiveTimeoutMs)); + sb.AppendLine(string.Format("CallRingTimeoutMs {0}", CallRingTimeoutMs)); + sb.AppendLine(string.Format("CallConnectTimeoutMs {0}", CallConnectTimeoutMs)); + sb.AppendLine(string.Format("CallPacketTimeoutMs {0}", CallPacketTimeoutMs)); + sb.AppendLine(string.Format("MeUrlPrefix {0}", MeUrlPrefix)); + sb.AppendLine(string.Format("SuggestedLangCode {0}", SuggestedLangCode)); + sb.AppendLine(string.Format("LangPackVersion {0}", LangPackVersion)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig78 : TLConfig76 + { + public new const uint Signature = TLConstructors.TLConfig78; + + protected TLString _autoupdateUrlPrefix; + + [DataMember] + public TLString AutoupdateUrlPrefix + { + get { return _autoupdateUrlPrefix; } + set { SetField(out _autoupdateUrlPrefix, value, ref _flags, (int)ConfigFlags.AutoupdateUrlPrefix); } + } + + public bool BlockedMode { get { return IsSet(Flags, (int)ConfigFlags.BlockedMode); } } + + public bool DefaultP2PContacts { get { return IsSet(Flags, (int)ConfigFlags.DefaultP2PContacts); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = new TLInt(int.MaxValue); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + RevokeTimeLimit = GetObject(bytes, ref position); + RevokePmTimeLimit = GetObject(bytes, ref position); + RatingEDecay = GetObject(bytes, ref position); + StickersRecentLimit = GetObject(bytes, ref position); + StickersFavedLimit = GetObject(bytes, ref position); + ChannelsReadMediaPeriod = GetObject(bytes, ref position); + TmpSessions = GetObject(Flags, (int)ConfigFlags.TmpSessions, null, bytes, ref position); + PinnedDialogsCountMax = GetObject(bytes, ref position); + CallReceiveTimeoutMs = GetObject(bytes, ref position); + CallRingTimeoutMs = GetObject(bytes, ref position); + CallConnectTimeoutMs = GetObject(bytes, ref position); + CallPacketTimeoutMs = GetObject(bytes, ref position); + MeUrlPrefix = GetObject(bytes, ref position); + _autoupdateUrlPrefix = GetObject(_flags, (int)ConfigFlags.AutoupdateUrlPrefix, null, bytes, ref position); + DisabledFeatures = new TLVector(); + _suggestedLangCode = GetObject(Flags, (int)ConfigFlags.Lang, null, bytes, ref position); + _langPackVersion = GetObject(Flags, (int)ConfigFlags.Lang, null, bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Flags {0}", ConfigFlagsString(Flags))); + sb.AppendLine(string.Format("PhoneCallsEnabled {0}", PhoneCallsEnabled)); + sb.AppendLine(string.Format("DefaultP2PContacts {0}", DefaultP2PContacts)); + sb.AppendLine(string.Format("PreloadFeaturedStickers {0}", PreloadFeaturedStickers)); + sb.AppendLine(string.Format("IgnorePhoneEntities {0}", IgnorePhoneEntities)); + sb.AppendLine(string.Format("RevokePmInbox {0}", RevokePmInbox)); + sb.AppendLine(string.Format("BlockedMode {0}", BlockedMode)); + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ThisDC {0}", ThisDC)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("RevokeTimeLimit {0}", RevokeTimeLimit)); + sb.AppendLine(string.Format("RevokePmTimeLimit {0}", RevokePmTimeLimit)); + sb.AppendLine(string.Format("RatingEDecay {0}", RatingEDecay)); + sb.AppendLine(string.Format("StickersRecentLimit {0}", StickersRecentLimit)); + sb.AppendLine(string.Format("StickersFavedLimit {0}", StickersFavedLimit)); + sb.AppendLine(string.Format("ChannelsReadMediaPeriod {0}", ChannelsReadMediaPeriod)); + sb.AppendLine(string.Format("TmpSessions {0}", TmpSessions)); + sb.AppendLine(string.Format("PinnedDialogsCountMax {0}", PinnedDialogsCountMax)); + sb.AppendLine(string.Format("CallReceiveTimeoutMs {0}", CallReceiveTimeoutMs)); + sb.AppendLine(string.Format("CallRingTimeoutMs {0}", CallRingTimeoutMs)); + sb.AppendLine(string.Format("CallConnectTimeoutMs {0}", CallConnectTimeoutMs)); + sb.AppendLine(string.Format("CallPacketTimeoutMs {0}", CallPacketTimeoutMs)); + sb.AppendLine(string.Format("MeUrlPrefix {0}", MeUrlPrefix)); + sb.AppendLine(string.Format("AutoupdateUrlPrefix {0}", AutoupdateUrlPrefix)); + sb.AppendLine(string.Format("SuggestedLangCode {0}", SuggestedLangCode)); + sb.AppendLine(string.Format("LangPackVersion {0}", LangPackVersion)); + + return sb.ToString(); + } + } + + [DataContract] + public class TLConfig82 : TLConfig78 + { + public new const uint Signature = TLConstructors.TLConfig82; + + [DataMember] + public TLString DCTxtDomainName { get; set; } + + protected TLString _gifSearchUsername; + + [DataMember] + public TLString GifSearchUsername + { + get { return _gifSearchUsername; } + set { SetField(out _gifSearchUsername, value, ref _flags, (int)ConfigFlags.GifSearchUsername); } + } + + protected TLString _venueSearchUsername; + + [DataMember] + public TLString VenueSearchUsername + { + get { return _venueSearchUsername; } + set { SetField(out _venueSearchUsername, value, ref _flags, (int)ConfigFlags.VenueSearchUsername); } + } + + protected TLString _imgSearchUsername; + + [DataMember] + public TLString ImgSearchUsername + { + get { return _imgSearchUsername; } + set { SetField(out _imgSearchUsername, value, ref _flags, (int)ConfigFlags.ImgSearchUsername); } + } + + protected TLString _staticMapsProvider; + + [DataMember] + public TLString StaticMapsProvider + { + get { return _staticMapsProvider; } + set { SetField(out _staticMapsProvider, value, ref _flags, (int)ConfigFlags.StaticMapsProvider); } + } + + [DataMember] + public TLInt CaptionLengthMax { get; set; } + + [DataMember] + public TLInt MessageLengthMax { get; set; } + + [DataMember] + public TLInt WebfileDCId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + TestMode = GetObject(bytes, ref position); + ThisDC = GetObject(bytes, ref position); + DCOptions = GetObject>(bytes, ref position); + DCTxtDomainName = GetObject(bytes, ref position); + ChatSizeMax = GetObject(bytes, ref position); + BroadcastSizeMax = GetObject(bytes, ref position); // MegagroupSizeMax + ForwardedCountMax = GetObject(bytes, ref position); + OnlineUpdatePeriodMs = GetObject(bytes, ref position); + OfflineBlurTimeoutMs = GetObject(bytes, ref position); + OfflineIdleTimeoutMs = GetObject(bytes, ref position); + OnlineCloudTimeoutMs = GetObject(bytes, ref position); + NotifyCloudDelayMs = GetObject(bytes, ref position); + NotifyDefaultDelayMs = GetObject(bytes, ref position); + ChatBigSize = new TLInt(int.MaxValue); + PushChatPeriodMs = GetObject(bytes, ref position); + PushChatLimit = GetObject(bytes, ref position); + SavedGifsLimit = GetObject(bytes, ref position); + EditTimeLimit = GetObject(bytes, ref position); + RevokeTimeLimit = GetObject(bytes, ref position); + RevokePmTimeLimit = GetObject(bytes, ref position); + RatingEDecay = GetObject(bytes, ref position); + StickersRecentLimit = GetObject(bytes, ref position); + StickersFavedLimit = GetObject(bytes, ref position); + ChannelsReadMediaPeriod = GetObject(bytes, ref position); + TmpSessions = GetObject(Flags, (int)ConfigFlags.TmpSessions, null, bytes, ref position); + PinnedDialogsCountMax = GetObject(bytes, ref position); + CallReceiveTimeoutMs = GetObject(bytes, ref position); + CallRingTimeoutMs = GetObject(bytes, ref position); + CallConnectTimeoutMs = GetObject(bytes, ref position); + CallPacketTimeoutMs = GetObject(bytes, ref position); + MeUrlPrefix = GetObject(bytes, ref position); + _autoupdateUrlPrefix = GetObject(_flags, (int)ConfigFlags.AutoupdateUrlPrefix, null, bytes, ref position); + _gifSearchUsername = GetObject(_flags, (int)ConfigFlags.GifSearchUsername, null, bytes, ref position); + _venueSearchUsername = GetObject(_flags, (int)ConfigFlags.VenueSearchUsername, null, bytes, ref position); + _imgSearchUsername = GetObject(_flags, (int)ConfigFlags.ImgSearchUsername, null, bytes, ref position); + _staticMapsProvider = GetObject(_flags, (int)ConfigFlags.StaticMapsProvider, null, bytes, ref position); + CaptionLengthMax = GetObject(bytes, ref position); + MessageLengthMax = GetObject(bytes, ref position); + WebfileDCId = GetObject(bytes, ref position); + DisabledFeatures = new TLVector(); + _suggestedLangCode = GetObject(Flags, (int)ConfigFlags.Lang, null, bytes, ref position); + _langPackVersion = GetObject(Flags, (int)ConfigFlags.Lang, null, bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine(string.Format("Flags {0}", ConfigFlagsString(Flags))); + sb.AppendLine(string.Format("PhoneCallsEnabled {0}", PhoneCallsEnabled)); + sb.AppendLine(string.Format("DefaultP2PContacts {0}", DefaultP2PContacts)); + sb.AppendLine(string.Format("PreloadFeaturedStickers {0}", PreloadFeaturedStickers)); + sb.AppendLine(string.Format("IgnorePhoneEntities {0}", IgnorePhoneEntities)); + sb.AppendLine(string.Format("RevokePmInbox {0}", RevokePmInbox)); + sb.AppendLine(string.Format("BlockedMode {0}", BlockedMode)); + sb.AppendLine(string.Format("Date utc0 {0} {1}", Date.Value, TLUtils.ToDateTime(Date).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("Expires utc0 {0} {1}", Expires.Value, TLUtils.ToDateTime(Expires).ToUniversalTime().ToString("HH:mm:ss.fff dd-MM-yyyy"))); + sb.AppendLine(string.Format("TestMode {0}", TestMode)); + sb.AppendLine(string.Format("ThisDC {0}", ThisDC)); + sb.AppendLine(string.Format("DCTxtDomainName {0}", DCTxtDomainName)); + sb.AppendLine(string.Format("ChatSizeMax {0}", ChatSizeMax)); + sb.AppendLine(string.Format("MegagroupSizeMax {0}", BroadcastSizeMax)); + sb.AppendLine(string.Format("ForwardedCountMax {0}", ForwardedCountMax)); + sb.AppendLine(string.Format("OnlineUpdatePeriodMs {0}", OnlineUpdatePeriodMs)); + sb.AppendLine(string.Format("OfflineBlurTimeoutMs {0}", OfflineBlurTimeoutMs)); + sb.AppendLine(string.Format("OfflineIdleTimeoutMs {0}", OfflineIdleTimeoutMs)); + sb.AppendLine(string.Format("OnlineCloudTimeoutMs {0}", OnlineCloudTimeoutMs)); + sb.AppendLine(string.Format("NotifyCloudDelayMs {0}", NotifyCloudDelayMs)); + sb.AppendLine(string.Format("NotifyDefaultDelayMs {0}", NotifyDefaultDelayMs)); + sb.AppendLine(string.Format("PushChatPeriodMs {0}", PushChatPeriodMs)); + sb.AppendLine(string.Format("PushChatLimit {0}", PushChatLimit)); + sb.AppendLine(string.Format("SavedGifsLimit {0}", SavedGifsLimit)); + sb.AppendLine(string.Format("EditTimeLimit {0}", EditTimeLimit)); + sb.AppendLine(string.Format("RevokeTimeLimit {0}", RevokeTimeLimit)); + sb.AppendLine(string.Format("RevokePmTimeLimit {0}", RevokePmTimeLimit)); + sb.AppendLine(string.Format("RatingEDecay {0}", RatingEDecay)); + sb.AppendLine(string.Format("StickersRecentLimit {0}", StickersRecentLimit)); + sb.AppendLine(string.Format("StickersFavedLimit {0}", StickersFavedLimit)); + sb.AppendLine(string.Format("ChannelsReadMediaPeriod {0}", ChannelsReadMediaPeriod)); + sb.AppendLine(string.Format("TmpSessions {0}", TmpSessions)); + sb.AppendLine(string.Format("PinnedDialogsCountMax {0}", PinnedDialogsCountMax)); + sb.AppendLine(string.Format("CallReceiveTimeoutMs {0}", CallReceiveTimeoutMs)); + sb.AppendLine(string.Format("CallRingTimeoutMs {0}", CallRingTimeoutMs)); + sb.AppendLine(string.Format("CallConnectTimeoutMs {0}", CallConnectTimeoutMs)); + sb.AppendLine(string.Format("CallPacketTimeoutMs {0}", CallPacketTimeoutMs)); + sb.AppendLine(string.Format("MeUrlPrefix {0}", MeUrlPrefix)); + sb.AppendLine(string.Format("AutoupdateUrlPrefix {0}", AutoupdateUrlPrefix)); + sb.AppendLine(string.Format("GifSearchUsername {0}", GifSearchUsername)); + sb.AppendLine(string.Format("VenueSearchUsername {0}", VenueSearchUsername)); + sb.AppendLine(string.Format("ImgSearchUsername {0}", ImgSearchUsername)); + sb.AppendLine(string.Format("StaticMapsProvider {0}", StaticMapsProvider)); + sb.AppendLine(string.Format("CaptionLengthMax {0}", CaptionLengthMax)); + sb.AppendLine(string.Format("MessageLengthMax {0}", MessageLengthMax)); + sb.AppendLine(string.Format("WebfileDCId {0}", WebfileDCId)); + sb.AppendLine(string.Format("SuggestedLangCode {0}", SuggestedLangCode)); + sb.AppendLine(string.Format("LangPackVersion {0}", LangPackVersion)); + + return sb.ToString(); + } + } +} diff --git a/Telegram.Api/TL/TLConfigSimple.cs b/Telegram.Api/TL/TLConfigSimple.cs new file mode 100755 index 0000000..60381e5 --- /dev/null +++ b/Telegram.Api/TL/TLConfigSimple.cs @@ -0,0 +1,61 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLConfigSimple : TLObject + { + public const uint Signature = TLConstructors.TLConfigSimple; + + public TLInt Date { get; set; } + + public TLInt Expires { get; set; } + + public TLInt DCId { get; set; } + + public TLVector IpPortList { get; set; } + + public override string ToString() + { + return string.Format("TLConfigSimple date={0} expires={1} dc_id={2} ip_port_list=[{3}]", Date, Expires, DCId, string.Join(", ", IpPortList)); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + DCId = GetObject(bytes, ref position); + IpPortList = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Date = GetObject(input); + Expires = GetObject(input); + DCId = GetObject(input); + IpPortList = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Date.ToStream(output); + Expires.ToStream(output); + DCId.ToStream(output); + IpPortList.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLContact.cs b/Telegram.Api/TL/TLContact.cs new file mode 100755 index 0000000..c01e99e --- /dev/null +++ b/Telegram.Api/TL/TLContact.cs @@ -0,0 +1,50 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using System.Runtime.Serialization; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [DataContract] + public class TLContact : TLObject + { + public const uint Signature = TLConstructors.TLContact; + + [DataMember] + public TLInt UserId { get; set; } + + [DataMember] + public TLBool Mutual { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + Mutual = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + Mutual = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(UserId.ToBytes()); + output.Write(Mutual.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLContactBlocked.cs b/Telegram.Api/TL/TLContactBlocked.cs new file mode 100755 index 0000000..890caf4 --- /dev/null +++ b/Telegram.Api/TL/TLContactBlocked.cs @@ -0,0 +1,33 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLContactBlocked : TLObject + { + public const uint Signature = TLConstructors.TLContactBlocked; + + public TLInt UserId { get; set; } + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLContactBlocked--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + + Date = GetObject(bytes, ref position); + + TLUtils.WriteLine("UserId: " + UserId); + TLUtils.WriteLine("Date: " + TLUtils.MessageIdString(Date)); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLContactFound.cs b/Telegram.Api/TL/TLContactFound.cs new file mode 100755 index 0000000..e9b6c9e --- /dev/null +++ b/Telegram.Api/TL/TLContactFound.cs @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLContactFound : TLObject + { + public const uint Signature = TLConstructors.TLContactFound; + + public TLInt UserId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + UserId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLContactLink.cs b/Telegram.Api/TL/TLContactLink.cs new file mode 100755 index 0000000..f26c230 --- /dev/null +++ b/Telegram.Api/TL/TLContactLink.cs @@ -0,0 +1,102 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLContactLinkBase : TLObject { } + + public class TLContactLinkUnknown : TLContactLinkBase + { + public const uint Signature = TLConstructors.TLContactLinkUnknown; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLContactLinkNone : TLContactLinkBase + { + public const uint Signature = TLConstructors.TLContactLinkNone; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLContactLinkHasPhone : TLContactLinkBase + { + public const uint Signature = TLConstructors.TLContactLinkHasPhone; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLContactLink : TLContactLinkBase + { + public const uint Signature = TLConstructors.TLContactLink; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLContactStatus.cs b/Telegram.Api/TL/TLContactStatus.cs new file mode 100755 index 0000000..93ffb3f --- /dev/null +++ b/Telegram.Api/TL/TLContactStatus.cs @@ -0,0 +1,48 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLContactStatusBase : TLObject + { + public TLInt UserId { get; set; } + } + + public class TLContactStatus : TLContactStatusBase + { + public const uint Signature = TLConstructors.TLContactStatus; + + public TLInt Expires { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + Expires = GetObject(bytes, ref position); + + return this; + } + } + + public class TLContactStatus19 : TLContactStatusBase + { + public const uint Signature = TLConstructors.TLContactStatus19; + + public TLUserStatus Status { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + Status = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLContacts.cs b/Telegram.Api/TL/TLContacts.cs new file mode 100755 index 0000000..ef98dbf --- /dev/null +++ b/Telegram.Api/TL/TLContacts.cs @@ -0,0 +1,92 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLContactsBase : TLObject + { + public abstract TLContactsBase GetEmptyObject(); + } + + public class TLContacts71 : TLContacts + { + public new const uint Signature = TLConstructors.TLContacts71; + + public TLInt SavedCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Contacts = GetObject>(bytes, ref position); + SavedCount = GetObject(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLContactsBase GetEmptyObject() + { + return new TLContacts71 + { + Contacts = new TLVector(Contacts.Count), + SavedCount = SavedCount, + Users = new TLVector(Users.Count) + }; + } + + public override string ToString() + { + return string.Format("TLContacts contacts={0} saved_count={1} users={2}", Contacts.Count, SavedCount, Users.Count); + } + } + + public class TLContacts : TLContactsBase + { + public const uint Signature = TLConstructors.TLContacts; + + public TLVector Users { get; set; } + + public TLVector Contacts { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Contacts = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLContactsBase GetEmptyObject() + { + return new TLContacts + { + Contacts = new TLVector(Contacts.Count), + Users = new TLVector(Users.Count) + }; + } + } + + public class TLContactsNotModified : TLContactsBase + { + public const uint Signature = TLConstructors.TLContactsNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLContactsBase GetEmptyObject() + { + return new TLContactsNotModified(); + } + } +} diff --git a/Telegram.Api/TL/TLContactsBlocked.cs b/Telegram.Api/TL/TLContactsBlocked.cs new file mode 100755 index 0000000..80d93a0 --- /dev/null +++ b/Telegram.Api/TL/TLContactsBlocked.cs @@ -0,0 +1,50 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLContactsBlockedBase : TLObject { } + + public class TLContactsBlocked : TLContactsBlockedBase + { + public const uint Signature = TLConstructors.TLContactsBlocked; + + public TLVector Blocked { get; set; } + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLContactsBlocked--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Blocked = GetObject>(bytes, ref position); + + Users = GetObject>(bytes, ref position); + + return this; + } + } + + public class TLContactsBlockedSlice : TLContactsBlocked + { + public new const uint Signature = TLConstructors.TLContactsBlockedSlice; + + public TLInt Count { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLContactsBlocked--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Count = GetObject(bytes, ref position); + Blocked = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLContactsFound.cs b/Telegram.Api/TL/TLContactsFound.cs new file mode 100755 index 0000000..e5045d7 --- /dev/null +++ b/Telegram.Api/TL/TLContactsFound.cs @@ -0,0 +1,70 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLContactsFoundBase : TLObject + { + public TLVector Users { get; set; } + } + + public class TLContactsFound : TLContactsFoundBase + { + public const uint Signature = TLConstructors.TLContactsFound; + + public TLVector Results { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Results = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } + + public class TLContactsFound40 : TLContactsFoundBase + { + public const uint Signature = TLConstructors.TLContactsFound40; + + public TLVector Results { get; set; } + + public TLVector Chats { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Results = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } + + public class TLContactsFound74 : TLContactsFound40 + { + public new const uint Signature = TLConstructors.TLContactsFound74; + + public TLVector MyResults { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + MyResults = GetObject>(bytes, ref position); + Results = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLContainerTransportMessage.cs b/Telegram.Api/TL/TLContainerTransportMessage.cs new file mode 100755 index 0000000..c18fab5 --- /dev/null +++ b/Telegram.Api/TL/TLContainerTransportMessage.cs @@ -0,0 +1,76 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + public class TLTransportMessageWithIdBase : TLObject + { + public TLLong MessageId { get; set; } + } + + public class TLContainerTransportMessage : TLTransportMessageWithIdBase + { + public TLInt SeqNo { get; set; } + public TLInt MessageDataLength { get; set; } + public TLObject MessageData { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + MessageId = GetObject(bytes, ref position); + SeqNo = GetObject(bytes, ref position); + MessageDataLength = GetObject(bytes, ref position); + MessageData = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + var objectBytes = MessageData.ToBytes(); + + return TLUtils.Combine( + MessageId.ToBytes(), + SeqNo.ToBytes(), + BitConverter.GetBytes(objectBytes.Length), + objectBytes); + } + } + + public class TLTransportMessage : TLContainerTransportMessage + { + public TLLong Salt { get; set; } + public TLLong SessionId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + Salt = GetObject(bytes, ref position); + SessionId = GetObject(bytes, ref position); + + MessageId = GetObject(bytes, ref position); + SeqNo = GetObject(bytes, ref position); + MessageDataLength = GetObject(bytes, ref position); + MessageData = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + var objectBytes = MessageData.ToBytes(); + + return TLUtils.Combine( + Salt.ToBytes(), + SessionId.ToBytes(), + MessageId.ToBytes(), + SeqNo.ToBytes(), + BitConverter.GetBytes(objectBytes.Length), + objectBytes); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLDCOption.cs b/Telegram.Api/TL/TLDCOption.cs new file mode 100755 index 0000000..98c8ac1 --- /dev/null +++ b/Telegram.Api/TL/TLDCOption.cs @@ -0,0 +1,317 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum DCOptionFlags + { + IPv6 = 0x1, + Media = 0x2, + TCPO = 0x4, + CDN = 0x8, + Static = 0x10, + Secret = 0x400 + } + + [KnownType(typeof(TLDCOption78))] + [KnownType(typeof(TLDCOption30))] + [DataContract] + public class TLDCOption : TLObject + { + public const uint Signature = TLConstructors.TLDCOption; + + [DataMember] + public TLInt Id { get; set; } + + [DataMember] + public TLString Hostname { get; set; } + + private TLString _ipAddress; + + [DataMember] + public TLString IpAddress + { + get { return _ipAddress; } + set { _ipAddress = value; } + } + + [DataMember] + public TLInt Port { get; set; } + + #region Additional + public TLLong CustomFlags { get; set; } + + [DataMember] + public byte[] AuthKey { get; set; } + + [DataMember] + public bool IsAuthorized { get; set; } + + [DataMember] + public TLLong Salt { get; set; } + + [DataMember] + public long ClientTicksDelta { get; set; } + + //[DataMember] //Important this field initialize with random value on each app startup to avoid TLBadMessage result with 32, 33 code (incorrect MsgSeqNo) + public TLLong SessionId { get; set; } + + public virtual TLBool IPv6 + { + get { return TLBool.False; } + set { } + } + + public virtual TLBool Media + { + get { return TLBool.False; } + set { } + } + + public virtual TLBool TCPO + { + get { return TLBool.False; } + set { } + } + + public virtual TLBool CDN + { + get { return TLBool.False; } + set { } + } + + public virtual TLBool Static + { + get { return TLBool.False; } + set { } + } + + public bool IsValidIPv4Option(TLInt dcId) + { + return !IPv6.Value && Id != null && Id.Value == dcId.Value; + } + + public virtual bool IsValidIPv4WithTCPO25Option(TLInt dcId) + { + return false; + } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Hostname = GetObject(bytes, ref position); + IpAddress = GetObject(bytes, ref position); + Port = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + Hostname.ToStream(output); + IpAddress.ToStream(output); + Port.ToStream(output); + + CustomFlags.NullableToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Hostname = GetObject(input); + IpAddress = GetObject(input); + Port = GetObject(input); + + CustomFlags = GetNullableObject(input); + + return this; + } + + public bool AreEquals(TLDCOption dcOption) + { + if (dcOption == null) return false; + + return Id.Value == dcOption.Id.Value; + } + + public override string ToString() + { + return string.Format("{0}) {1}:{2} (AuthKey {3})\n Salt {4} TicksDelta {5}", Id, IpAddress, Port, AuthKey != null, Salt, ClientTicksDelta); + } + + protected string AuthKeySignature(byte[] authKey) + { + if (authKey == null || authKey.Length == 0) return "null"; + + return string.Join(" ", AuthKey.Take(7).ToArray()); + } + } + + [DataContract] + public class TLDCOption30 : TLDCOption + { + public new const uint Signature = TLConstructors.TLDCOption30; + + protected TLInt _flags; + + [DataMember] + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override TLBool IPv6 + { + get { return new TLBool(IsSet(_flags, (int)DCOptionFlags.IPv6)); } + set { SetUnset(ref _flags, value.Value, (int)DCOptionFlags.IPv6); } + } + + public override TLBool Media + { + get { return new TLBool(IsSet(_flags, (int)DCOptionFlags.Media)); } + set { SetUnset(ref _flags, value.Value, (int)DCOptionFlags.Media); } + } + + public override TLBool TCPO + { + get { return new TLBool(IsSet(_flags, (int)DCOptionFlags.TCPO)); } + set { SetUnset(ref _flags, value.Value, (int)DCOptionFlags.TCPO); } + } + + public override TLBool CDN + { + get { return new TLBool(IsSet(_flags, (int)DCOptionFlags.CDN)); } + set { SetUnset(ref _flags, value.Value, (int)DCOptionFlags.CDN); } + } + + public override TLBool Static + { + get { return new TLBool(IsSet(_flags, (int)DCOptionFlags.Static)); } + set { SetUnset(ref _flags, value.Value, (int)DCOptionFlags.Static); } + } + + public static string DCOptionFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (DCOptionFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + //Hostname = GetObject(bytes, ref position); + IpAddress = GetObject(bytes, ref position); + Port = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + //Hostname.ToStream(output); + IpAddress.ToStream(output); + Port.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + //Hostname = GetObject(input); + IpAddress = GetObject(input); + Port = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("{0}) {1}:{2} (AuthKey {3} IsAuthorized={7})\n Flags {6} Salt {4} TicksDelta {5}", Id, IpAddress, Port, AuthKeySignature(AuthKey), Salt, ClientTicksDelta, DCOptionFlagsString(Flags), IsAuthorized); + } + } + + [DataContract] + public class TLDCOption78 : TLDCOption30 + { + public new const uint Signature = TLConstructors.TLDCOption78; + + protected TLString _secret; + + [DataMember] + public TLString Secret + { + get { return _secret; } + set { SetField(out _secret, value, ref _flags, (int)DCOptionFlags.Secret); } + } + + public override bool IsValidIPv4WithTCPO25Option(TLInt dcId) + { + return IsValidIPv4Option(dcId) && !TLString.IsNullOrEmpty(Secret) && Secret.Data.Length == 16; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + IpAddress = GetObject(bytes, ref position); + Port = GetObject(bytes, ref position); + _secret = GetObject(Flags, (int)DCOptionFlags.Secret, null, bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + IpAddress.ToStream(output); + Port.ToStream(output); + ToStream(output, _secret, _flags, (int)DCOptionFlags.Secret); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + IpAddress = GetObject(input); + Port = GetObject(input); + _secret = GetObject(Flags, (int)DCOptionFlags.Secret, null, input); + + return this; + } + + public override string ToString() + { + return string.Format("{0}) {1}:{2} (AuthKey {3} IsAuthorized={7})\n Flags {6} Salt {4} TicksDelta {5}", Id, IpAddress, Port, AuthKeySignature(AuthKey), Salt, ClientTicksDelta, DCOptionFlagsString(Flags), IsAuthorized); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLDHConfig.cs b/Telegram.Api/TL/TLDHConfig.cs new file mode 100755 index 0000000..33460b9 --- /dev/null +++ b/Telegram.Api/TL/TLDHConfig.cs @@ -0,0 +1,59 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLDHConfigBase : TLObject { } + + public class TLDHConfig : TLDHConfigBase + { + public const uint Signature = TLConstructors.TLDHConfig; + + public TLInt G { get; set; } + + public TLString P { get; set; } + + public TLInt Version { get; set; } + + public TLString Random { get; set; } + + #region Additional + + public TLString A { get; set; } + + public TLString GA { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + G = GetObject(bytes, ref position); + P = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + Random = GetObject(bytes, ref position); + + return this; + } + } + + public class TLDHConfigNotModified : TLDHConfigBase + { + public const uint Signature = TLConstructors.TLDHConfigNotModified; + + public TLString Random { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Random = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLDHGen.cs b/Telegram.Api/TL/TLDHGen.cs new file mode 100755 index 0000000..cf4b4cf --- /dev/null +++ b/Telegram.Api/TL/TLDHGen.cs @@ -0,0 +1,68 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLDHGenBase : TLObject + { + public TLInt128 Nonce { get; set; } + + public TLInt128 ServerNonce { get; set; } + + public TLInt128 NewNonce { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + Nonce = GetObject(bytes, ref position); + ServerNonce = GetObject(bytes, ref position); + NewNonce = GetObject(bytes, ref position); + + return this; + } + } + + public class TLDHGenOk : TLDHGenBase + { + public const uint Signature = TLConstructors.TLDHGenOk; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLDHGenOk--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return base.FromBytes(bytes, ref position); + } + } + + public class TLDHGenRetry : TLDHGenBase + { + public const uint Signature = TLConstructors.TLDHGenRetry; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLDHGenRetry--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return base.FromBytes(bytes, ref position); + } + } + + public class TLDHGenFail : TLDHGenBase + { + public const uint Signature = TLConstructors.TLDHGenFail; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLDHGenFail--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return base.FromBytes(bytes, ref position); + } + } + + +} diff --git a/Telegram.Api/TL/TLDataJSON.cs b/Telegram.Api/TL/TLDataJSON.cs new file mode 100755 index 0000000..d41a369 --- /dev/null +++ b/Telegram.Api/TL/TLDataJSON.cs @@ -0,0 +1,54 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLDataJSON : TLUpdateBase + { + public const uint Signature = TLConstructors.TLDataJSON; + + public TLString Data { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Data = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Data.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Data.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Data = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } +} diff --git a/Telegram.Api/TL/TLDecryptedMessage.cs b/Telegram.Api/TL/TLDecryptedMessage.cs new file mode 100755 index 0000000..980ddb3 --- /dev/null +++ b/Telegram.Api/TL/TLDecryptedMessage.cs @@ -0,0 +1,1228 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using System.Linq; +using Telegram.Api.Services.Cache; +#if WIN_RT +using Windows.UI.Xaml; +#else +using System.Windows; +#endif +using Telegram.Api.Extensions; +using Telegram.Api.Services; + +namespace Telegram.Api.TL +{ + + public interface IMessage + { + TLString Message { get; set; } + + TLObject From { get; } + } + + public interface ISeqNo + { + TLInt InSeqNo { get; set; } + + TLInt OutSeqNo { get; set; } + } + + public abstract class TLDecryptedMessageBase : TLObject + { + public TLDecryptedMessageBase Self { get { return this; } } + + public TLDecryptedMessageBase MediaSelf { get { return this; } } + + public TLLong RandomId { get; set; } + + public long RandomIndex + { + get { return RandomId != null ? RandomId.Value : 0; } + set { RandomId = new TLLong(value); } + } + + public TLString RandomBytes { get; set; } + + private bool _isHighlighted; + + public bool IsHighlighted + { + get { return _isHighlighted; } + set { SetField(ref _isHighlighted, value, () => IsHighlighted); } + } + + private TLObject _from; + + public TLObject From + { + get + { + if (_from != null) return _from; + + var cacheService = InMemoryCacheService.Instance; + _from = cacheService.GetUser(FromId); + + return _from; + } + } + + #region Additional + public TLInt ChatId { get; set; } + public TLInputEncryptedFileBase InputFile { get; set; } // to send media + + public TLInt FromId { get; set; } + public TLBool Out { get; set; } + public TLBool Unread { get; set; } + + public TLInt Date { get; set; } + public int DateIndex + { + get { return Date != null ? Date.Value : 0; } + set { Date = new TLInt(value); } + } + + public TLInt Qts { get; set; } + public int QtsIndex + { + get { return Qts != null ? Qts.Value : 0; } + set { Qts = new TLInt(value); } + } + + public TLLong DeleteDate { get; set; } + + public long DeleteIndex + { + get { return DeleteDate != null ? DeleteDate.Value : 0; } + set { DeleteDate = new TLLong(value); } + } + + public MessageStatus Status { get; set; } + + public virtual bool ShowFrom + { + get { return false; } + } + + private bool _isSelected; + + public bool IsSelected + { + get { return _isSelected; } + set { SetField(ref _isSelected, value, () => IsSelected); } + } + + public abstract Visibility SelectionVisibility { get; } + + public TLInt TTL { get; set; } + + private bool _isTTLStarted; + + public bool IsTTLStarted + { + get { return _isTTLStarted; } + set { SetField(ref _isTTLStarted, value, () => IsTTLStarted); } + } + + public abstract Visibility SecretPhotoMenuVisibility { get; } + + public abstract Visibility MessageVisibility { get; } + + public TLDecryptedMessageBase Reply { get; set; } + + public virtual ReplyInfo ReplyInfo + { + get { return null; } + } + + public virtual Visibility ReplyVisibility { get { return Visibility.Collapsed; } } + + public virtual double MediaWidth { get { return 12.0 + 311.0 + 12.0; } } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + RandomId = GetObject(bytes, ref position); + RandomBytes = GetObject(bytes, ref position); + + return this; + } + + public virtual void Update(TLDecryptedMessageBase message) + { + ChatId = message.ChatId ?? ChatId; + InputFile = message.InputFile ?? InputFile; + FromId = message.FromId ?? FromId; + Out = message.Out ?? Out; + Unread = message.Unread ?? Unread; + Date = message.Date ?? Date; + Qts = message.Qts ?? Qts; + DeleteDate = message.DeleteDate ?? DeleteDate; + Status = message.Status; + TTL = message.TTL ?? TTL; + } + + public virtual bool IsSticker() + { + return false; + } + + public static bool IsSticker(TLDecryptedMessageMediaExternalDocument document) + { +#if WP8 + if (document != null + && document.Size.Value > 0 + && document.Size.Value < Constants.StickerMaxSize) + { + //var documentStickerAttribute = document22.Attributes.FirstOrDefault(x => x is TLDocumentAttributeSticker); + + if (//documentStickerAttribute != null + //&& + string.Equals(document.MimeType.ToString(), "image/webp", StringComparison.OrdinalIgnoreCase) + || string.Equals(document.FileExt, "webp", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } +#endif + + return false; + } + + public virtual bool IsGif() + { + return false; + } + + public virtual bool IsVoice() + { + return false; + } + + public static bool IsVoice(IAttributes attributes, TLInt size) + { +#if WP8 + if (size == null || size.Value > 0) + { + var audioAttribute = attributes.Attributes.FirstOrDefault(x => x is TLDocumentAttributeAudio46) as TLDocumentAttributeAudio46; + if (audioAttribute != null && audioAttribute.Voice) + { + return true; + } + } +#endif + + return false; + } + + public static bool IsVoice(TLDecryptedMessageMediaDocument45 document) + { +#if WP8 + var document22 = document; + if (document22 != null) + { + return IsVoice(document22, document22.Size); + } +#endif + + return false; + } + + public virtual bool IsVideo() + { + return false; + } + + public static bool IsVideo(IAttributes attributes, TLInt size) + { +#if WP8 + if (size == null || size.Value > 0) + { + var videoAttribute = attributes.Attributes.FirstOrDefault(x => x is TLDocumentAttributeVideo) as TLDocumentAttributeVideo; + var animatedAttribute = attributes.Attributes.FirstOrDefault(x => x is TLDocumentAttributeAnimated) as TLDocumentAttributeAnimated; + if (videoAttribute != null && animatedAttribute == null) + { + return true; + } + } +#endif + + return false; + } + + public static bool IsVideo(TLDecryptedMessageMediaDocument45 document) + { +#if WP8 + var document22 = document; + if (document22 != null) + { + return IsVideo(document22, document22.Size); + } +#endif + + return false; + } + } + + public class TLDecryptedMessagesContainter : TLDecryptedMessageBase + { + public const uint Signature = TLConstructors.TLDecryptedMessagesContainter; + + public TLMessageMediaBase WebPageMedia { get; set; } + + public TLVector FwdMessages { get; set; } + + public override Visibility SelectionVisibility + { + get { return Visibility.Collapsed; } + } + + public override Visibility SecretPhotoMenuVisibility + { + get { return Visibility.Collapsed; } + } + + public override Visibility MessageVisibility + { + get { return Visibility.Collapsed; } + } + + public TLObject From + { + get + { + //if (FwdMessages != null && FwdMessages.Count > 0) + //{ + // var fwdMessage = FwdMessages[0] as TLDecryptedMessage; + // if (fwdMessage != null) + // { + // var fwdPeer = fwdMessage.FwdFromPeer; + // if (fwdPeer != null) + // { + // var cacheService = InMemoryCacheService.Instance; + // if (fwdPeer is TLPeerChannel) + // { + // return cacheService.GetChat(fwdPeer.Id); + // } + + // return cacheService.GetUser(fwdPeer.Id); + // } + // } + + // return FwdMessages[0].FwdFrom; + //} + + return null; + } + } + + public TLString Message + { + get + { + if (FwdMessages != null && FwdMessages.Count > 0) + { + return FwdMessages[0].Message; + } + + return null; + } + } + + public TLDecryptedMessageMediaBase Media + { + get + { + if (FwdMessages != null && FwdMessages.Count > 0) + { + return FwdMessages[0].Media; + } + + return null; + } + } + } + + public class TLDecryptedMessage73 : TLDecryptedMessage45 + { + public new const uint Signature = TLConstructors.TLDecryptedMessage73; + + private TLLong _groupedId; + + public TLLong GroupedId + { + get { return _groupedId; } + set { SetField(out _groupedId, value, ref _flags, (int) MessageFlags.GroupedId); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + RandomId = GetObject(bytes, ref position); + TTL = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Media = IsSet(Flags, (int)MessageFlags.Media) + ? GetObject(bytes, ref position) + : new TLDecryptedMessageMediaEmpty(); + Entities = GetObject>(Flags, (int) MessageFlags.Entities, null, bytes, ref position); + ViaBotName = GetObject(Flags, (int) MessageFlags.ViaBotId, null, bytes, ref position); + ReplyToRandomMsgId = GetObject(Flags, (int) MessageFlags.ReplyToMsgId, null, bytes, ref position); + GroupedId = GetObject(Flags, (int) MessageFlags.GroupedId, null, bytes, ref position); + + if (IsVoice()) + { + NotListened = true; + } + + System.Diagnostics.Debug.WriteLine(" >>TLDecryptedMessage73.FromBytes random_id={0} ttl={1} message={2} media=[{3}]", RandomId, TTL, Message, Media); + + return this; + } + + public override byte[] ToBytes() + { + + System.Diagnostics.Debug.WriteLine(" <(input); + RandomId = GetObject(input); + TTL = GetObject(input); + Message = GetObject(input); + Media = IsSet(Flags, (int)MessageFlags.Media) + ? GetObject(input) + : new TLDecryptedMessageMediaEmpty(); + Entities = GetObject>(Flags, (int)MessageFlags.Entities, null, input); + ViaBotName = GetObject(Flags, (int)MessageFlags.ViaBotId, null, input); + ReplyToRandomMsgId = GetObject(Flags, (int)MessageFlags.ReplyToMsgId, null, input); + GroupedId = GetObject(Flags, (int)MessageFlags.GroupedId, null, input); + + ChatId = GetNullableObject(input); + InputFile = GetNullableObject(input); + FromId = GetNullableObject(input); + Out = GetNullableObject(input); + Unread = GetNullableObject(input); + Date = GetNullableObject(input); + DeleteDate = GetNullableObject(input); + Qts = GetNullableObject(input); + + var status = GetObject(input); + Status = (MessageStatus)status.Value; + + InSeqNo = GetNullableObject(input); + OutSeqNo = GetNullableObject(input); + CustomFlags = GetNullableObject(input); + + if (IsSet(CustomFlags, (int)MessageCustomFlags.BotInlineResult)) + { + _inlineBotResult = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + output.Write(RandomId.ToBytes()); + output.Write(TTL.ToBytes()); + output.Write(Message.ToBytes()); + ToStream(output, Media, Flags, (int)MessageFlags.Media); + ToStream(output, Entities, Flags, (int)MessageFlags.Entities); + ToStream(output, ViaBotName, Flags, (int)MessageFlags.ViaBotId); + ToStream(output, ReplyToRandomMsgId, Flags, (int)MessageFlags.ReplyToMsgId); + ToStream(output, GroupedId, Flags, (int)MessageFlags.GroupedId); + + ChatId.NullableToStream(output); + InputFile.NullableToStream(output); + FromId.NullableToStream(output); + Out.NullableToStream(output); + Unread.NullableToStream(output); + Date.NullableToStream(output); + DeleteDate.NullableToStream(output); + Qts.NullableToStream(output); + + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + + InSeqNo.NullableToStream(output); + OutSeqNo.NullableToStream(output); + CustomFlags.NullableToStream(output); + + if (IsSet(CustomFlags, (int)MessageCustomFlags.BotInlineResult)) + { + _inlineBotResult.ToStream(output); + } + } + + public override string ToString() + { + if (Media is TLDecryptedMessageMediaEmpty) + { + return string.Format("TLDecryptedMessage73 random_id={7} qts={0} in_seq_no={1} out_seq_no={2} flags=[{3}] date={4} delete_date={5} message={6}", Qts, InSeqNo, OutSeqNo, TLMessageBase.MessageFlagsString(Flags), Date, DeleteDate, Message, RandomId); + } + + return string.Format("TLDecryptedMessage73 random_id={7} qts={0} in_seq_no={1} out_seq_no={2} flags=[{3}] date={4} delete_date={5} media={6}", Qts, InSeqNo, OutSeqNo, TLMessageBase.MessageFlagsString(Flags), Date, DeleteDate, Media, RandomId); + } + } + + public class TLDecryptedMessage45 : TLDecryptedMessage17 + { + public new const uint Signature = TLConstructors.TLDecryptedMessage45; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLVector _entities; + + public TLVector Entities + { + get { return _entities; } + set + { + if (value != null) + { + _entities = value; + Set(ref _flags, (int)MessageFlags.Entities); + } + else + { + Unset(ref _flags, (int)MessageFlags.Entities); + } + } + } + + private TLString _viaBotBane; + + public TLString ViaBotName + { + get { return _viaBotBane; } + set + { + if (value != null) + { + _viaBotBane = value; + Set(ref _flags, (int)MessageFlags.ViaBotId); + } + else + { + Unset(ref _flags, (int)MessageFlags.ViaBotId); + } + } + } + + private TLLong _replyToRandomMsgId; + + public TLLong ReplyToRandomMsgId + { + get { return _replyToRandomMsgId; } + set + { + if (value != null && value.Value != 0) + { + _replyToRandomMsgId = value; + Set(ref _flags, (int)MessageFlags.ReplyToMsgId); + } + else + { + Unset(ref _flags, (int)MessageFlags.ReplyToMsgId); + } + } + } + + protected TLBotInlineResultBase _inlineBotResult; + + public TLBotInlineResultBase InlineBotResult + { + get { return _inlineBotResult; } + set + { + if (value != null) + { + Set(ref _customFlags, (int)MessageCustomFlags.BotInlineResult); + _inlineBotResult = value; + } + else + { + Unset(ref _customFlags, (int)MessageCustomFlags.BotInlineResult); + _inlineBotResult = null; + } + } + } + + public void SetMedia() + { + Set(ref _flags, (int)MessageFlags.Media); + } + + public void SetListened() + { + Unset(ref _flags, (int)MessageFlags.MediaUnread); + } + + public bool NotListened + { + get { return IsSet(_flags, (int)MessageFlags.MediaUnread); } + set { SetUnset(ref _flags, value, (int)MessageFlags.MediaUnread); } + } + + public override ReplyInfo ReplyInfo + { + get { return ReplyToRandomMsgId != null ? new ReplyInfo { ReplyToRandomMsgId = ReplyToRandomMsgId, Reply = Reply } : null; } + } + + public override Visibility ReplyVisibility + { + get { return ReplyToRandomMsgId != null && ReplyToRandomMsgId.Value != 0 ? Visibility.Visible : Visibility.Collapsed; } + } + + public override bool IsVoice() + { + var mediaAudio = Media as TLDecryptedMessageMediaAudio; + if (mediaAudio != null) + { + return true; + } + + var mediaDocument = Media as TLDecryptedMessageMediaDocument45; + if (mediaDocument != null) + { + return IsVoice(mediaDocument); + } + + return false; + } + + public override bool IsVideo() + { + var mediaVideo = Media as TLDecryptedMessageMediaVideo; + if (mediaVideo != null) + { + return true; + } + + var mediaDocument = Media as TLDecryptedMessageMediaDocument45; + if (mediaDocument != null) + { + return IsVideo(mediaDocument); + } + + return false; + } + + public override bool IsGif() + { + var mediaDocument = Media as TLDecryptedMessageMediaDocument45; + if (mediaDocument != null && TLString.Equals(mediaDocument.MimeType, new TLString("video/mp4"), StringComparison.OrdinalIgnoreCase)) + { + return TLMessageBase.IsGif(mediaDocument, mediaDocument.Size); + } + + return false; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + RandomId = GetObject(bytes, ref position); + TTL = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Media = IsSet(Flags, (int)MessageFlags.Media) + ? GetObject(bytes, ref position) + : new TLDecryptedMessageMediaEmpty(); + if (IsSet(Flags, (int) MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ViaBotId)) + { + ViaBotName = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToRandomMsgId = GetObject(bytes, ref position); + } + + if (IsVoice()) + { + NotListened = true; + } + + System.Diagnostics.Debug.WriteLine(" >>TLDecryptedMessage45.FromBytes random_id={0} ttl={1} message={2} media=[{3}]", RandomId, TTL, Message, Media); + + return this; + } + + public override byte[] ToBytes() + { + System.Diagnostics.Debug.WriteLine(" <(input); + RandomId = GetObject(input); + TTL = GetObject(input); + Message = GetObject(input); + Media = IsSet(Flags, (int)MessageFlags.Media) + ? GetObject(input) + : new TLDecryptedMessageMediaEmpty(); + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(input); + } + if (IsSet(Flags, (int)MessageFlags.ViaBotId)) + { + ViaBotName = GetObject(input); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToRandomMsgId = GetObject(input); + } + + ChatId = GetNullableObject(input); + InputFile = GetNullableObject(input); + FromId = GetNullableObject(input); + Out = GetNullableObject(input); + Unread = GetNullableObject(input); + Date = GetNullableObject(input); + DeleteDate = GetNullableObject(input); + Qts = GetNullableObject(input); + + var status = GetObject(input); + Status = (MessageStatus)status.Value; + + InSeqNo = GetNullableObject(input); + OutSeqNo = GetNullableObject(input); + CustomFlags = GetNullableObject(input); + + if (IsSet(CustomFlags, (int)MessageCustomFlags.BotInlineResult)) + { + _inlineBotResult = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + output.Write(RandomId.ToBytes()); + output.Write(TTL.ToBytes()); + output.Write(Message.ToBytes()); + ToStream(output, Media, Flags, (int)MessageFlags.Media); + ToStream(output, Entities, Flags, (int)MessageFlags.Entities); + ToStream(output, ViaBotName, Flags, (int)MessageFlags.ViaBotId); + ToStream(output, ReplyToRandomMsgId, Flags, (int)MessageFlags.ReplyToMsgId); + + ChatId.NullableToStream(output); + InputFile.NullableToStream(output); + FromId.NullableToStream(output); + Out.NullableToStream(output); + Unread.NullableToStream(output); + Date.NullableToStream(output); + DeleteDate.NullableToStream(output); + Qts.NullableToStream(output); + + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + + InSeqNo.NullableToStream(output); + OutSeqNo.NullableToStream(output); + CustomFlags.NullableToStream(output); + + if (IsSet(CustomFlags, (int)MessageCustomFlags.BotInlineResult)) + { + _inlineBotResult.ToStream(output); + } + } + + public override string ToString() + { + if (Media is TLDecryptedMessageMediaEmpty) + { + return string.Format("TLDecryptedMessage45 qts={0} in_seq_no={1} out_seq_no={2} flags=[{3}] date={4} delete_date={5} message={6}", Qts, InSeqNo, OutSeqNo, TLMessageBase.MessageFlagsString(Flags), Date, DeleteDate, Message); + } + + return string.Format("TLDecryptedMessage45 qts={0} in_seq_no={1} out_seq_no={2} flags=[{3}] date={4} delete_date={5} media={6}", Qts, InSeqNo, OutSeqNo, TLMessageBase.MessageFlagsString(Flags), Date, DeleteDate, Media); + } + } + + public class TLDecryptedMessage17 : TLDecryptedMessage, ISeqNo + { + public new const uint Signature = TLConstructors.TLDecryptedMessage17; + + public TLInt InSeqNo { get; set; } + + public TLInt OutSeqNo { get; set; } + + protected TLInt _customFlags; + + public TLInt CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + public override Visibility SecretPhotoMenuVisibility + { + get + { + var isSecretPhoto = Media is TLDecryptedMessageMediaPhoto; + return isSecretPhoto && TTL.Value > 0.0 && TTL.Value <= 60.0 ? Visibility.Collapsed : Visibility.Visible; + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + RandomId = GetObject(bytes, ref position); + TTL = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Media = GetObject(bytes, ref position); + + System.Diagnostics.Debug.WriteLine(" >>TLDecryptedMessage17.FromBytes random_id={0} ttl={1} message={2} media=[{3}]", RandomId, TTL, Message, Media); + + return this; + } + + public override byte[] ToBytes() + { + System.Diagnostics.Debug.WriteLine(" <(input); + TTL = GetObject(input); + //RandomBytes = GetObject(input); + Message = GetObject(input); + Media = GetObject(input); + + ChatId = GetNullableObject(input); + InputFile = GetNullableObject(input); + FromId = GetNullableObject(input); + Out = GetNullableObject(input); + Unread = GetNullableObject(input); + Date = GetNullableObject(input); + DeleteDate = GetNullableObject(input); + Qts = GetNullableObject(input); + + var status = GetObject(input); + Status = (MessageStatus)status.Value; + + InSeqNo = GetNullableObject(input); + OutSeqNo = GetNullableObject(input); + CustomFlags = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(RandomId.ToBytes()); + output.Write(TTL.ToBytes()); + //output.Write(RandomBytes.ToBytes()); + output.Write(Message.ToBytes()); + Media.ToStream(output); + + ChatId.NullableToStream(output); + InputFile.NullableToStream(output); + FromId.NullableToStream(output); + Out.NullableToStream(output); + Unread.NullableToStream(output); + Date.NullableToStream(output); + DeleteDate.NullableToStream(output); + Qts.NullableToStream(output); + + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + + InSeqNo.NullableToStream(output); + OutSeqNo.NullableToStream(output); + CustomFlags.NullableToStream(output); + } + + public override string ToString() + { + if (Media is TLDecryptedMessageMediaEmpty) + { + return string.Format("TLDecryptedMessage17 qts={0} in_seq_no={1} out_seq_no={2} date={3} delete_date={4} message={5}", Qts, InSeqNo, OutSeqNo, Date, DeleteDate, Message); + } + + return string.Format("TLDecryptedMessage17 qts={0} in_seq_no={1} out_seq_no={2} date={3} delete_date={4} media={5}", Qts, InSeqNo, OutSeqNo, Date, DeleteDate, Media); + } + } + + public class TLDecryptedMessage : TLDecryptedMessageBase, IMessage + { + public const uint Signature = TLConstructors.TLDecryptedMessage; + + public TLString Message { get; set; } + + public TLDecryptedMessageMediaBase Media { get; set; } + + public override double MediaWidth + { + get + { + if (Media != null) + { + return Media.MediaWidth; + } + + return base.MediaWidth; + } + } + + public override bool IsSticker() + { + var mediaDocument = Media as TLDecryptedMessageMediaExternalDocument; + if (mediaDocument != null) + { + return IsSticker(mediaDocument); + } + + return false; + } + + public override Visibility MessageVisibility + { + get { return Message == null || string.IsNullOrEmpty(Message.ToString()) ? Visibility.Collapsed : Visibility.Visible; } + } + + public override Visibility SelectionVisibility + { + get { return Visibility.Visible; } + } + + public override Visibility SecretPhotoMenuVisibility + { + get { return Visibility.Visible; } + } + + public override string ToString() + { + if (Media is TLDecryptedMessageMediaEmpty) + { + return string.Format("TLDecryptedMessage qts={0} date={1} delete_date={2} message={3}", Qts, Date, DeleteDate, Message); + } + + return string.Format("TLDecryptedMessage qts={0} date={1} delete_date={2} media={3}", Qts, Date, DeleteDate, Media); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + base.FromBytes(bytes, ref position); + + Message = GetObject(bytes, ref position); + Media = GetObject(bytes, ref position); + + System.Diagnostics.Debug.WriteLine(" >>TLDecryptedMessage.FromBytes message={0} media=[{1}]", Message, Media); + + return this; + } + + public override byte[] ToBytes() + { + System.Diagnostics.Debug.WriteLine(" <(input); + RandomBytes = GetObject(input); + Message = GetObject(input); + Media = GetObject(input); + + ChatId = GetNullableObject(input); + InputFile = GetNullableObject(input); + FromId = GetNullableObject(input); + Out = GetNullableObject(input); + Unread = GetNullableObject(input); + Date = GetNullableObject(input); + DeleteDate = GetNullableObject(input); + Qts = GetNullableObject(input); + + var status = GetObject(input); + Status = (MessageStatus)status.Value; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(RandomId.ToBytes()); + output.Write(RandomBytes.ToBytes()); + output.Write(Message.ToBytes()); + Media.ToStream(output); + + ChatId.NullableToStream(output); + InputFile.NullableToStream(output); + FromId.NullableToStream(output); + Out.NullableToStream(output); + Unread.NullableToStream(output); + Date.NullableToStream(output); + DeleteDate.NullableToStream(output); + Qts.NullableToStream(output); + + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + } + } + + public class TLDecryptedMessageService17 : TLDecryptedMessageService, ISeqNo + { + public new const uint Signature = TLConstructors.TLDecryptedMessageService17; + + public TLInt InSeqNo { get; set; } + + public TLInt OutSeqNo { get; set; } + + public TLInt Flags { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + RandomId = GetObject(bytes, ref position); + Action = GetObject(bytes, ref position); + + System.Diagnostics.Debug.WriteLine(" >>TLDecryptedMessageService17.FromBytes random_id={0} action=[{1}]", RandomId, Action); + + return this; + } + + public override byte[] ToBytes() + { + + System.Diagnostics.Debug.WriteLine(" <(input); + //RandomBytes = GetObject(input); + Action = GetObject(input); + + ChatId = GetNullableObject(input); + FromId = GetNullableObject(input); + Out = GetNullableObject(input); + Unread = GetNullableObject(input); + Date = GetNullableObject(input); + DeleteDate = GetNullableObject(input); + Qts = GetNullableObject(input); + + var status = GetObject(input); + Status = (MessageStatus)status.Value; + + InSeqNo = GetNullableObject(input); + OutSeqNo = GetNullableObject(input); + Flags = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(RandomId.ToBytes()); + //output.Write(RandomBytes.ToBytes()); + Action.ToStream(output); + + ChatId.NullableToStream(output); + FromId.NullableToStream(output); + Out.NullableToStream(output); + Unread.NullableToStream(output); + Date.NullableToStream(output); + DeleteDate.NullableToStream(output); + Qts.NullableToStream(output); + + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + + InSeqNo.NullableToStream(output); + OutSeqNo.NullableToStream(output); + Flags.NullableToStream(output); + } + + public override string ToString() + { + return string.Format("TLDecryptedMessageService17 qts={0} in_seq_no={1} out_seq_no={2} random_id={3} date={4} delete_date={5} action=[{6}]", Qts, InSeqNo, OutSeqNo, RandomId, Date, DeleteDate, Action); + } + } + + public class TLDecryptedMessageService : TLDecryptedMessageBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageService; + + public TLDecryptedMessageActionBase Action { get; set; } + + public override Visibility SelectionVisibility + { + get { return Visibility.Collapsed; } + } + + public override Visibility SecretPhotoMenuVisibility + { + get { return Visibility.Visible; } + } + + public override Visibility MessageVisibility + { + get { return Visibility.Collapsed; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + base.FromBytes(bytes, ref position); + + Action = GetObject(bytes, ref position); + + System.Diagnostics.Debug.WriteLine(" >>TLDecryptedMessageService.FromBytes random_id={0} action=[{1}]", RandomId, Action); + + return this; + } + + public override byte[] ToBytes() + { + System.Diagnostics.Debug.WriteLine(" <(input); + RandomBytes = GetObject(input); + Action = GetObject(input); + + ChatId = GetNullableObject(input); + FromId = GetNullableObject(input); + Out = GetNullableObject(input); + Unread = GetNullableObject(input); + Date = GetNullableObject(input); + DeleteDate = GetNullableObject(input); + Qts = GetNullableObject(input); + + var status = GetObject(input); + Status = (MessageStatus)status.Value; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(RandomId.ToBytes()); + output.Write(RandomBytes.ToBytes()); + output.Write(Action.ToBytes()); + + ChatId.NullableToStream(output); + FromId.NullableToStream(output); + Out.NullableToStream(output); + Unread.NullableToStream(output); + Date.NullableToStream(output); + DeleteDate.NullableToStream(output); + Qts.NullableToStream(output); + + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + } + + public override string ToString() + { + var dateTimeString = "null"; + try + { + if (Date != null) + { + var clientDelta = MTProtoService.Instance.ClientTicksDelta; + //var utc0SecsLong = Date.Value * 4294967296 - clientDelta; + var utc0SecsInt = Date.Value - clientDelta / 4294967296.0; + DateTime? dateTime = Helpers.Utils.UnixTimestampToDateTime(utc0SecsInt); + dateTimeString = dateTime.Value.ToString("H:mm:ss"); + } + } + catch (Exception ex) + { + + } + + return string.Format("TLDecryptedMessageService qts={0} random_id={1} date={2} delete_date={3} action=[{4}]", Qts, RandomId, Date, DeleteDate, Action); + } + } +} diff --git a/Telegram.Api/TL/TLDecryptedMessageAction.cs b/Telegram.Api/TL/TLDecryptedMessageAction.cs new file mode 100755 index 0000000..1d095d7 --- /dev/null +++ b/Telegram.Api/TL/TLDecryptedMessageAction.cs @@ -0,0 +1,529 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLDecryptedMessageActionBase : TLObject { } + + #region Additional + public class TLDecryptedMessageActionEmpty : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + #endregion + + public class TLDecryptedMessageActionSetMessageTTL : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionSetMessageTTL; + + public TLInt TTLSeconds { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + TTLSeconds = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + TTLSeconds.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + TTLSeconds = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(TTLSeconds.ToBytes()); + } + } + + public class TLDecryptedMessageActionReadMessages : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionReadMessages; + + public TLVector RandomIds { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + RandomIds = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + RandomIds.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + RandomIds = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(RandomIds.ToBytes()); + } + } + + public class TLDecryptedMessageActionDeleteMessages : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionDeleteMessages; + + public TLVector RandomIds { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + RandomIds = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + RandomIds.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + RandomIds = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(RandomIds.ToBytes()); + } + } + + public class TLDecryptedMessageActionScreenshotMessages : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionScreenshotMessages; + + public TLVector RandomIds { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + RandomIds = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + RandomIds.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + RandomIds = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(RandomIds.ToBytes()); + } + } + + public class TLDecryptedMessageActionFlushHistory : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionFlushHistory; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLDecryptedMessageActionNotifyLayer : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionNotifyLayer; + + public TLInt Layer { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Layer = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Layer.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Layer = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Layer.ToBytes()); + } + + public override string ToString() + { + return string.Format("TLDecryptedMessageActionNotifyLayer layer={0}", Layer); + } + } + + public class TLDecryptedMessageActionResend : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionResend; + + public TLInt StartSeqNo { get; set; } + + public TLInt EndSeqNo { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + StartSeqNo = GetObject(bytes, ref position); + EndSeqNo = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + StartSeqNo.ToBytes(), + EndSeqNo.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + StartSeqNo = GetObject(input); + EndSeqNo = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(StartSeqNo.ToBytes()); + output.Write(EndSeqNo.ToBytes()); + } + } + + public class TLDecryptedMessageActionTyping : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionTyping; + + public TLSendMessageActionBase Action { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Action = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Action.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Action = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Action.ToBytes()); + } + } + + public class TLDecryptedMessageActionRequestKey : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionRequestKey; + + public TLLong ExchangeId { get; set; } + + public TLString GA { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ExchangeId = GetObject(bytes, ref position); + GA = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ExchangeId.ToBytes(), + GA.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + ExchangeId = GetObject(input); + GA = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(ExchangeId.ToBytes()); + output.Write(GA.ToBytes()); + } + } + + public class TLDecryptedMessageActionAcceptKey : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionAcceptKey; + + public TLLong ExchangeId { get; set; } + + public TLString GB { get; set; } + + public TLLong KeyFingerprint { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ExchangeId = GetObject(bytes, ref position); + GB = GetObject(bytes, ref position); + KeyFingerprint = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ExchangeId.ToBytes(), + GB.ToBytes(), + KeyFingerprint.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + ExchangeId = GetObject(input); + GB = GetObject(input); + KeyFingerprint = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(ExchangeId.ToBytes()); + output.Write(GB.ToBytes()); + output.Write(KeyFingerprint.ToBytes()); + } + } + + public class TLDecryptedMessageActionAbortKey : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionAbortKey; + + public TLLong ExchangeId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ExchangeId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ExchangeId.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + ExchangeId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(ExchangeId.ToBytes()); + } + } + + public class TLDecryptedMessageActionCommitKey : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionCommitKey; + + public TLLong ExchangeId { get; set; } + + public TLLong KeyFingerprint { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ExchangeId = GetObject(bytes, ref position); + KeyFingerprint = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ExchangeId.ToBytes(), + KeyFingerprint.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + ExchangeId = GetObject(input); + KeyFingerprint = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(ExchangeId.ToBytes()); + output.Write(KeyFingerprint.ToBytes()); + } + } + + public class TLDecryptedMessageActionNoop : TLDecryptedMessageActionBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageActionNoop; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLDecryptedMessageLayer.cs b/Telegram.Api/TL/TLDecryptedMessageLayer.cs new file mode 100755 index 0000000..c5975a0 --- /dev/null +++ b/Telegram.Api/TL/TLDecryptedMessageLayer.cs @@ -0,0 +1,79 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLDecryptedMessageLayer : TLObject + { + public const uint Signature = TLConstructors.TLDecryptedMessageLayer; + + public TLInt Layer { get; set; } + + public TLDecryptedMessageBase Message { get; set; } + + public override byte[] ToBytes() + { + System.Diagnostics.Debug.WriteLine(" <>TLDecryptedMessageLayer.FromBytes layer={0} message=[{1}]", Layer, Message); + + Layer = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + + return this; + } + } + + public class TLDecryptedMessageLayer17 : TLDecryptedMessageLayer + { + public const uint Signature = TLConstructors.TLDecryptedMessageLayer17; + + public TLString RandomBytes { get; set; } + + public TLInt InSeqNo { get; set; } + + public TLInt OutSeqNo { get; set; } + + public override byte[] ToBytes() + { + System.Diagnostics.Debug.WriteLine(" <(bytes, ref position); + Layer = GetObject(bytes, ref position); + InSeqNo = GetObject(bytes, ref position); + OutSeqNo = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + + System.Diagnostics.Debug.WriteLine(" >>TLDecryptedMessageLayer17.FromBytes layer={0} in_seq_no={1} out_seq_no={2} message=[{3}]", Layer, InSeqNo, OutSeqNo, Message); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLDecryptedMessageMedia.cs b/Telegram.Api/TL/TLDecryptedMessageMedia.cs new file mode 100755 index 0000000..93827a7 --- /dev/null +++ b/Telegram.Api/TL/TLDecryptedMessageMedia.cs @@ -0,0 +1,1639 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using System.Linq; +#if WP8 +using Windows.Storage; +#endif +using Telegram.Api.Extensions; +using Telegram.Api.Services.Cache; + +namespace Telegram.Api.TL +{ + public class TTLParams + { + public bool IsStarted { get; set; } + public int Total { get; set; } + public DateTime StartTime { get; set; } + public bool Out { get; set; } + } + + public abstract class TLDecryptedMessageMediaBase : TLObject + { + public double LastProgress { get; set; } + public string IsoFileName { get; set; } + public bool? AutoPlayGif { get; set; } + public bool Forbidden { get; set; } + public TLInt TTLSeconds { get; set; } + + private double _uploadingProgress; + + public double UploadingProgress + { + get { return _uploadingProgress; } + set { SetField(ref _uploadingProgress, value, () => UploadingProgress); } + } + + private double _downloadingProgress; + + public double DownloadingProgress + { + get { return _downloadingProgress; } + set { SetField(ref _downloadingProgress, value, () => DownloadingProgress); } + } + #region Additional +#if WP8 + public StorageFile StorageFile { get; set; } +#endif + private TLEncryptedFileBase _file; + + public TLEncryptedFileBase File + { + get { return _file; } + set { _file = value; } + } + + public TLDecryptedMessageMediaBase Self { get { return this; } } + + public TLDecryptedMessageMediaBase ThumbSelf { get { return this; } } + + public bool IsCanceled { get; set; } + + public TTLParams _ttlParams; + + public TTLParams TTLParams + { + get { return _ttlParams; } + set { SetField(ref _ttlParams, value, () => TTLParams); } + } + + public bool NotListened { get; set; } + + private bool _out = true; + + public bool Out + { + get { return _out; } + set { _out = value; } + } + + public virtual double MediaWidth + { + get { return 12.0 + 311.0 + 12.0; } + } + + #endregion + } + + public class TLDecryptedMessageMediaEmpty : TLDecryptedMessageMediaBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageMediaEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLDecryptedMessageThumbMediaBase : TLDecryptedMessageMediaBase + { + public TLString Thumb { get; set; } + + public TLInt ThumbW { get; set; } + + public TLInt ThumbH { get; set; } + + public TLInt Size { get; set; } + + public TLString Key { get; set; } + + public TLString IV { get; set; } + } + + public class TLDecryptedMessageMediaPhoto45 : TLDecryptedMessageMediaPhoto, IMediaCaption + { + public new const uint Signature = TLConstructors.TLDecryptedMessageMediaPhoto45; + + public TLString Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Thumb = GetObject(bytes, ref position); + ThumbW = GetObject(bytes, ref position); + ThumbH = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Key = GetObject(bytes, ref position); + IV = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Thumb.ToBytes(), + ThumbW.ToBytes(), + ThumbH.ToBytes(), + W.ToBytes(), + H.ToBytes(), + Size.ToBytes(), + Key.ToBytes(), + IV.ToBytes(), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Thumb = GetObject(input); + ThumbW = GetObject(input); + ThumbH = GetObject(input); + W = GetObject(input); + H = GetObject(input); + Size = GetObject(input); + Key = GetObject(input); + IV = GetObject(input); + Caption = GetObject(input); + + File = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Thumb.ToBytes()); + output.Write(ThumbW.ToBytes()); + output.Write(ThumbH.ToBytes()); + output.Write(W.ToBytes()); + output.Write(H.ToBytes()); + output.Write(Size.ToBytes()); + output.Write(Key.ToBytes()); + output.Write(IV.ToBytes()); + output.Write(Caption.ToBytes()); + + File.NullableToStream(output); + } + } + + public class TLDecryptedMessageMediaPhoto : TLDecryptedMessageThumbMediaBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageMediaPhoto; + + public TLInt W { get; set; } + + public TLInt H { get; set; } + + #region Additional + + public TLEncryptedFileBase Photo { get { return File; } } + #endregion + + public override double MediaWidth + { + get + { + var ttl = TTLSeconds; + if (ttl != null && ttl.Value > 0 && ttl.Value <= 60.0) + { + return 2.0 + 256.0 + 2.0; + } + + var minVerticalRatioToScale = 1.2; + var scale = 1.2; // must be less than minVerticalRatioToScale to avoid large square photos + var maxDimension = 323.0; + + if (H.Value > W.Value) + { + if (TLMessageMediaPhoto.IsScaledVerticalPhoto(minVerticalRatioToScale, H, W)) + { + return 2.0 + scale * maxDimension / H.Value * W.Value + 2.0; + } + + return 2.0 + maxDimension / H.Value * W.Value + 2.0; + } + + return 2.0 + maxDimension + 2.0; + } + } + + //public override double MediaWidth + //{ + // get + // { + // if (TLMessageBase.HasTTL(this) && Photo != null) + // { + // return 2.0 + 256.0 + 2.0; + // } + + // return base.MediaWidth; + // } + //} + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Thumb = GetObject(bytes, ref position); + ThumbW = GetObject(bytes, ref position); + ThumbH = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Key = GetObject(bytes, ref position); + IV = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Thumb.ToBytes(), + ThumbW.ToBytes(), + ThumbH.ToBytes(), + W.ToBytes(), + H.ToBytes(), + Size.ToBytes(), + Key.ToBytes(), + IV.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Thumb = GetObject(input); + ThumbW = GetObject(input); + ThumbH = GetObject(input); + W = GetObject(input); + H = GetObject(input); + Size = GetObject(input); + Key = GetObject(input); + IV = GetObject(input); + + File = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Thumb.ToBytes()); + output.Write(ThumbW.ToBytes()); + output.Write(ThumbH.ToBytes()); + output.Write(W.ToBytes()); + output.Write(H.ToBytes()); + output.Write(Size.ToBytes()); + output.Write(Key.ToBytes()); + output.Write(IV.ToBytes()); + + File.NullableToStream(output); + } + } + + public class TLDecryptedMessageMediaVideo45 : TLDecryptedMessageMediaVideo17, IMediaCaption + { + public new const uint Signature = TLConstructors.TLDecryptedMessageMediaVideo45; + + public TLString Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Thumb = GetObject(bytes, ref position); + ThumbW = GetObject(bytes, ref position); + ThumbH = GetObject(bytes, ref position); + Duration = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Key = GetObject(bytes, ref position); + IV = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Thumb.ToBytes(), + ThumbW.ToBytes(), + ThumbH.ToBytes(), + Duration.ToBytes(), + MimeType.ToBytes(), + W.ToBytes(), + H.ToBytes(), + Size.ToBytes(), + Key.ToBytes(), + IV.ToBytes(), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Thumb = GetObject(input); + ThumbW = GetObject(input); + ThumbH = GetObject(input); + Duration = GetObject(input); + MimeType = GetObject(input); + W = GetObject(input); + H = GetObject(input); + Size = GetObject(input); + Key = GetObject(input); + IV = GetObject(input); + Caption = GetObject(input); + + File = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Thumb.ToBytes()); + output.Write(ThumbW.ToBytes()); + output.Write(ThumbH.ToBytes()); + output.Write(Duration.ToBytes()); + output.Write(MimeType.ToBytes()); + output.Write(W.ToBytes()); + output.Write(H.ToBytes()); + output.Write(Size.ToBytes()); + output.Write(Key.ToBytes()); + output.Write(IV.ToBytes()); + output.Write(Caption.ToBytes()); + + File.NullableToStream(output); + } + } + + public class TLDecryptedMessageMediaVideo17 : TLDecryptedMessageMediaVideo + { + public new const uint Signature = TLConstructors.TLDecryptedMessageMediaVideo17; + + public TLString MimeType { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Thumb = GetObject(bytes, ref position); + ThumbW = GetObject(bytes, ref position); + ThumbH = GetObject(bytes, ref position); + Duration = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Key = GetObject(bytes, ref position); + IV = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Thumb.ToBytes(), + ThumbW.ToBytes(), + ThumbH.ToBytes(), + Duration.ToBytes(), + MimeType.ToBytes(), + W.ToBytes(), + H.ToBytes(), + Size.ToBytes(), + Key.ToBytes(), + IV.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Thumb = GetObject(input); + ThumbW = GetObject(input); + ThumbH = GetObject(input); + Duration = GetObject(input); + MimeType = GetObject(input); + W = GetObject(input); + H = GetObject(input); + Size = GetObject(input); + Key = GetObject(input); + IV = GetObject(input); + + File = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Thumb.ToBytes()); + output.Write(ThumbW.ToBytes()); + output.Write(ThumbH.ToBytes()); + output.Write(Duration.ToBytes()); + output.Write(MimeType.ToBytes()); + output.Write(W.ToBytes()); + output.Write(H.ToBytes()); + output.Write(Size.ToBytes()); + output.Write(Key.ToBytes()); + output.Write(IV.ToBytes()); + + File.NullableToStream(output); + } + } + + public class TLDecryptedMessageMediaVideo : TLDecryptedMessageThumbMediaBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageMediaVideo; + + public TLInt Duration { get; set; } + + public TLInt W { get; set; } + + public TLInt H { get; set; } + + #region Additional + + public TLDecryptedMessageMediaVideo Video { get { return this; } } + + public string DurationString + { + get + { + if (Duration == null) return string.Empty; + + var timeSpan = TimeSpan.FromSeconds(Duration.Value); + + if (timeSpan.Hours > 0) + { + return timeSpan.ToString(@"h\:mm\:ss"); + } + + return timeSpan.ToString(@"m\:ss"); + } + } + #endregion + + public override double MediaWidth + { + get { return 2.0 + 230.0 + 2.0; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Thumb = GetObject(bytes, ref position); + ThumbW = GetObject(bytes, ref position); + ThumbH = GetObject(bytes, ref position); + Duration = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Key = GetObject(bytes, ref position); + IV = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Thumb.ToBytes(), + ThumbW.ToBytes(), + ThumbH.ToBytes(), + Duration.ToBytes(), + W.ToBytes(), + H.ToBytes(), + Size.ToBytes(), + Key.ToBytes(), + IV.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Thumb = GetObject(input); + ThumbW = GetObject(input); + ThumbH = GetObject(input); + Duration = GetObject(input); + W = GetObject(input); + H = GetObject(input); + Size = GetObject(input); + Key = GetObject(input); + IV = GetObject(input); + + File = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Thumb.ToBytes()); + output.Write(ThumbW.ToBytes()); + output.Write(ThumbH.ToBytes()); + output.Write(Duration.ToBytes()); + output.Write(W.ToBytes()); + output.Write(H.ToBytes()); + output.Write(Size.ToBytes()); + output.Write(Key.ToBytes()); + output.Write(IV.ToBytes()); + + File.NullableToStream(output); + } + } + + public class TLDecryptedMessageMediaVenue : TLDecryptedMessageMediaGeoPoint + { + public new const uint Signature = TLConstructors.TLDecryptedMessageMediaVenue; + + public TLString Title { get; set; } + + public TLString Address { get; set; } + + public TLString Provider { get; set; } + + public TLString VenueId { get; set; } + + public override double MediaWidth + { + get { return 2.0 + 320.0 + 2.0; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Lat = GetObject(bytes, ref position); + Long = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + Address = GetObject(bytes, ref position); + Provider = GetObject(bytes, ref position); + VenueId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Lat.ToBytes(), + Long.ToBytes(), + Title.ToBytes(), + Address.ToBytes(), + Provider.ToBytes(), + VenueId.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Lat = GetObject(input); + Long = GetObject(input); + Title = GetObject(input); + Address = GetObject(input); + Provider = GetObject(input); + VenueId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Lat.ToStream(output); + Long.ToStream(output); + Title.ToStream(output); + Address.ToStream(output); + Provider.ToStream(output); + VenueId.ToStream(output); + } + } + + public class TLDecryptedMessageMediaGeoPoint : TLDecryptedMessageMediaBase, IMessageMediaGeoPoint + { + public const uint Signature = TLConstructors.TLDecryptedMessageMediaGeoPoint; + + public TLDouble Lat { get; set; } + + public TLDouble Long { get; set; } + + #region Additional + + public TLGeoPointBase Geo + { + get + { + return Lat != null && Long != null + ? (TLGeoPointBase) new TLGeoPoint{ Lat = Lat, Long = Long } + : new TLGeoPointEmpty(); + } + } + + #endregion + + public override double MediaWidth + { + get { return 2.0 + 320.0 + 2.0; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Lat = GetObject(bytes, ref position); + Long = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Lat.ToBytes(), + Long.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Lat = GetObject(input); + Long = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Lat.ToBytes()); + output.Write(Long.ToBytes()); + } + } + + public class TLDecryptedMessageMediaContact : TLDecryptedMessageMediaBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageMediaContact; + + public TLString PhoneNumber { get; set; } + + public TLString FirstName { get; set; } + + public TLString LastName { get; set; } + + public TLInt UserId { get; set; } + + public override string ToString() + { + return FullName; + } + + #region Additional + + public virtual string FullName { get { return string.Format("{0} {1}", FirstName, LastName); } } + + public TLUserBase User + { + get + { + var cacheService = InMemoryCacheService.Instance; + var user = cacheService.GetUser(UserId); + + if (user == null) + { + return new TLUser{Phone = PhoneNumber, FirstName = FirstName, LastName = LastName, Id = new TLInt(0)}; + } + + return null; + } + } + #endregion + + public override double MediaWidth + { + get { return 12.0 + 311.0 + 12.0; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhoneNumber = GetObject(bytes, ref position); + FirstName = GetObject(bytes, ref position); + LastName = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumber.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + UserId.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + PhoneNumber = GetObject(input); + FirstName = GetObject(input); + LastName = GetObject(input); + UserId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(PhoneNumber.ToBytes()); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + output.Write(UserId.ToBytes()); + } + } + + public class TLDecryptedMessageMediaAudio : TLDecryptedMessageMediaBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageMediaAudio; + + public TLInt Duration { get; set; } + + public TLInt Size { get; set; } + + public TLString Key { get; set; } + + public TLString IV { get; set; } + + public override double MediaWidth + { + get { return 12.0 + 284.0 + 12.0; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Duration = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Key = GetObject(bytes, ref position); + IV = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Duration.ToBytes(), + Size.ToBytes(), + Key.ToBytes(), + IV.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Duration = GetObject(input); + Size = GetObject(input); + Key = GetObject(input); + IV = GetObject(input); + + UserId = GetNullableObject(input); + File = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Duration.ToBytes()); + output.Write(Size.ToBytes()); + output.Write(Key.ToBytes()); + output.Write(IV.ToBytes()); + + UserId.NullableToStream(output); + File.NullableToStream(output); + } + + #region Additional + + private TLInt _userId; + + public TLInt UserId + { + get { return _userId; } + set { _userId = value; } + } + + public TLDecryptedMessageMediaAudio Audio { get { return this; } } + + public string DurationString + { + get + { + var timeSpan = TimeSpan.FromSeconds(Duration.Value); + + if (timeSpan.Hours > 0) + { + return timeSpan.ToString(@"h\:mm\:ss"); + } + + return timeSpan.ToString(@"m\:ss"); + } + } + + public TLUserBase User + { + get + { + if (UserId == null) return null; + + var cacheService = InMemoryCacheService.Instance; + return cacheService.GetUser(UserId); + } + } + #endregion + } + + public class TLDecryptedMessageMediaAudio17 : TLDecryptedMessageMediaAudio + { + public new const uint Signature = TLConstructors.TLDecryptedMessageMediaAudio17; + + public TLString MimeType { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Duration = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Key = GetObject(bytes, ref position); + IV = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Duration.ToBytes(), + MimeType.ToBytes(), + Size.ToBytes(), + Key.ToBytes(), + IV.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Duration = GetObject(input); + MimeType = GetObject(input); + Size = GetObject(input); + Key = GetObject(input); + IV = GetObject(input); + + UserId = GetNullableObject(input); + File = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Duration.ToBytes()); + output.Write(MimeType.ToBytes()); + output.Write(Size.ToBytes()); + output.Write(Key.ToBytes()); + output.Write(IV.ToBytes()); + + UserId.NullableToStream(output); + File.NullableToStream(output); + } + } + + public class TLDecryptedMessageMediaDocument45 : TLDecryptedMessageMediaDocument, IMediaCaption, IAttributes + { + public new const uint Signature = TLConstructors.TLDecryptedMessageMediaDocument45; + + public override TLString FileName + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var fileNameAttribute = Attributes[i] as TLDocumentAttributeFileName; + if (fileNameAttribute != null) + { + return fileNameAttribute.FileName; + } + } + } + + return TLString.Empty; + } + set + { + Attributes = Attributes ?? new TLVector(); + + for (var i = 0; i < Attributes.Count; i++) + { + if (Attributes[i] is TLDocumentAttributeFileName) + { + Attributes.RemoveAt(i--); + } + } + + Attributes.Add(new TLDocumentAttributeFileName { FileName = value }); + } + } + + + public bool Music + { + get + { + var documentAttributeAudio = Attributes.FirstOrDefault(x => x is TLDocumentAttributeAudio32) as TLDocumentAttributeAudio32; + if (documentAttributeAudio != null) + { + return true; + } + + return false; + } + } + + public override string DocumentName + { + get + { + var documentAttributeAudio = Attributes.FirstOrDefault(x => x is TLDocumentAttributeAudio46) as TLDocumentAttributeAudio46; + if (documentAttributeAudio != null) + { + if (documentAttributeAudio.Title != null && documentAttributeAudio.Performer != null) + { + return string.Format("{0} — {1}", documentAttributeAudio.Title, documentAttributeAudio.Performer); + } + + if (documentAttributeAudio.Title != null) + { + return string.Format("{0}", documentAttributeAudio.Title); + } + + if (documentAttributeAudio.Performer != null) + { + return string.Format("{0}", documentAttributeAudio.Performer); + } + } + + return FileName.ToString(); + } + } + + public TLVector Attributes { get; set; } + + public TLString Caption { get; set; } + + public TLInt Duration + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var audioAttribute = Attributes[i] as TLDocumentAttributeAudio; + if (audioAttribute != null) + { + return audioAttribute.Duration; + } + } + } + + return new TLInt(0); + } + } + + public TLString Waveform + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var audioAttribute = Attributes[i] as TLDocumentAttributeAudio46; + if (audioAttribute != null) + { + return audioAttribute.Waveform; + } + } + } + + return null; + } + } + + public string DurationString + { + get + { + var timeSpan = TimeSpan.FromSeconds(Duration.Value); + + if (timeSpan.Hours > 0) + { + return timeSpan.ToString(@"h\:mm\:ss"); + } + + return timeSpan.ToString(@"m\:ss"); + } + } + + public override double MediaWidth + { + get + { + var document = Document as TLDecryptedMessageMediaDocument45; + if (document != null) + { + if (TLMessageBase.IsSticker(document, document.Size)) + { + var maxStickerDimension = 196.0; + + return 6.0 + TLMessageMediaDocument.GetStickerDimension(document, true, maxStickerDimension) + 6.0; + } + + if (TLMessageBase.IsVoice(document, document.Size)) + { + return 12.0 + 284.0 + 12.0; + } + + //if (TLMessageBase.IsRoundVideo(document)) + //{ + // return 2.0 + 240.0 + 2.0; + //} + + if (TLMessageBase.IsVideo(document, document.Size)) + { + return 2.0 + 230.0 + 2.0; + } + + if (TLMessageBase.IsGif(document, document.Size)) + { + var maxGifDimension = 323.0; + + return 2.0 + TLMessageMediaDocument.GetGifDimension(new TLPhotoCachedSize { W = ThumbW, H = ThumbH }, document, true, maxGifDimension) + 2.0; + } + } + + return base.MediaWidth; + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Thumb = GetObject(bytes, ref position); + ThumbW = GetObject(bytes, ref position); + ThumbH = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Key = GetObject(bytes, ref position); + IV = GetObject(bytes, ref position); + Attributes = GetObject>(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Thumb.ToBytes(), + ThumbW.ToBytes(), + ThumbH.ToBytes(), + MimeType.ToBytes(), + Size.ToBytes(), + Key.ToBytes(), + IV.ToBytes(), + Attributes.ToBytes(), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Thumb = GetObject(input); + ThumbW = GetObject(input); + ThumbH = GetObject(input); + MimeType = GetObject(input); + Size = GetObject(input); + Key = GetObject(input); + IV = GetObject(input); + Attributes = GetObject>(input); + Caption = GetObject(input); + + File = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Thumb.ToBytes()); + output.Write(ThumbW.ToBytes()); + output.Write(ThumbH.ToBytes()); + output.Write(MimeType.ToBytes()); + output.Write(Size.ToBytes()); + output.Write(Key.ToBytes()); + output.Write(IV.ToBytes()); + output.Write(Attributes.ToBytes()); + output.Write(Caption.ToBytes()); + + File.NullableToStream(output); + } + } + + public class TLDecryptedMessageMediaDocument : TLDecryptedMessageMediaBase, IDecryptedMediaGif + { + public const uint Signature = TLConstructors.TLDecryptedMessageMediaDocument; + + public TLString Thumb { get; set; } + + public TLInt ThumbW { get; set; } + + public TLInt ThumbH { get; set; } + + public virtual TLString FileName { get; set; } + + public TLString MimeType { get; set; } + + public TLInt Size { get; set; } + + public TLString Key { get; set; } + + public TLString IV { get; set; } + + #region Additional + + public TLDecryptedMessageMediaDocument Document { get { return this; } } + + public virtual string DocumentName { get { return FileName != null ? FileName.ToString() : string.Empty; } } + + public string FileExt + { + get { return FileName != null ? Path.GetExtension(FileName.ToString()).Replace(".", string.Empty) : null; } + } + + public int DocumentSize + { + get { return Size != null ? Size.Value : 0; } + } + + public string GetFileName() + { + var fileLocation = File as TLEncryptedFile; + if (fileLocation == null) return null;; + + var fileName = String.Format("{0}_{1}_{2}.{3}", + fileLocation.Id, + fileLocation.DCId, + fileLocation.AccessHash, + FileExt); + + return fileName; + } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Thumb = GetObject(bytes, ref position); + ThumbW = GetObject(bytes, ref position); + ThumbH = GetObject(bytes, ref position); + FileName = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Key = GetObject(bytes, ref position); + IV = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Thumb.ToBytes(), + ThumbW.ToBytes(), + ThumbH.ToBytes(), + FileName.ToBytes(), + MimeType.ToBytes(), + Size.ToBytes(), + Key.ToBytes(), + IV.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Thumb = GetObject(input); + ThumbW = GetObject(input); + ThumbH = GetObject(input); + FileName = GetObject(input); + MimeType = GetObject(input); + Size = GetObject(input); + Key = GetObject(input); + IV = GetObject(input); + + File = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Thumb.ToBytes()); + output.Write(ThumbW.ToBytes()); + output.Write(ThumbH.ToBytes()); + output.Write(FileName.ToBytes()); + output.Write(MimeType.ToBytes()); + output.Write(Size.ToBytes()); + output.Write(Key.ToBytes()); + output.Write(IV.ToBytes()); + File.NullableToStream(output); + } + } + + public class TLDecryptedMessageMediaExternalDocument : TLDecryptedMessageMediaBase, IAttributes + { + public const uint Signature = TLConstructors.TLDecryptedMessageMediaExternalDocument; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public TLInt Date { get; set; } + + public TLString MimeType { get; set; } + + public TLInt Size { get; set; } + + public TLPhotoSizeBase Thumb { get; set; } + + public TLInt DCId { get; set; } + + public TLVector Attributes { get; set; } + + public TLInt ImageSizeH + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var imageSizeAttribute = Attributes[i] as TLDocumentAttributeImageSize; + if (imageSizeAttribute != null) + { + return imageSizeAttribute.H; + } + } + } + + return new TLInt(0); + } + } + + public TLInt ImageSizeW + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var imageSizeAttribute = Attributes[i] as TLDocumentAttributeImageSize; + if (imageSizeAttribute != null) + { + return imageSizeAttribute.W; + } + } + } + + return new TLInt(0); + } + } + + public string FileExt + { + get { return Path.GetExtension(FileName.ToString()).Replace(".", string.Empty); } + } + + public TLString FileName + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var fileNameAttribute = Attributes[i] as TLDocumentAttributeFileName; + if (fileNameAttribute != null) + { + return fileNameAttribute.FileName; + } + } + } + + return TLString.Empty; + } + set + { + Attributes = Attributes ?? new TLVector(); + + for (var i = 0; i < Attributes.Count; i++) + { + if (Attributes[i] is TLDocumentAttributeFileName) + { + Attributes.RemoveAt(i--); + } + } + + Attributes.Add(new TLDocumentAttributeFileName { FileName = value }); + } + } + + public string GetFileName() + { + return string.Format("document{0}_{1}.{2}", Id, AccessHash, FileExt); + } + + public TLInputStickerSetBase StickerSet + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var stickerAttribute = Attributes[i] as TLDocumentAttributeSticker29; + if (stickerAttribute != null) + { + return stickerAttribute.Stickerset; + } + } + } + + return null; + } + } + + #region Additional + public string Emoticon { get; set; } + + public TLDecryptedMessageMediaExternalDocument Document { get { return this; } } + #endregion + + public override string ToString() + { + return string.Format("{0} Id={1}", GetType().Name, Id) + (StickerSet != null ? StickerSet.ToString() : string.Empty); + } + + public TLInputDocumentFileLocation ToInputFileLocation() + { + return new TLInputDocumentFileLocation54 + { + Id = Id, + AccessHash = AccessHash, + Version = new TLInt(0) + }; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Thumb = GetObject(bytes, ref position); + DCId = GetObject(bytes, ref position); + Attributes = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + Date.ToBytes(), + MimeType.ToBytes(), + Size.ToBytes(), + Thumb.ToBytes(), + DCId.ToBytes(), + Attributes.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + MimeType = GetObject(input); + Size = GetObject(input); + Thumb = GetObject(input); + DCId = GetObject(input); + Attributes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + AccessHash.ToStream(output); + Date.ToStream(output); + MimeType.ToStream(output); + Size.ToStream(output); + Thumb.ToStream(output); + DCId.ToStream(output); + Attributes.ToStream(output); + } + } + + public class TLDecryptedMessageMediaWebPage : TLDecryptedMessageMediaBase + { + public const uint Signature = TLConstructors.TLDecryptedMessageMediaWebPage; + + public TLString Url { get; set; } + + public TLWebPageBase WebPage { get; set; } + + public TLPhotoBase Photo + { + get + { + var webPage = WebPage as TLWebPage; + if (webPage != null) + { + return webPage.Photo; + } + + return null; + } + } + + public override double MediaWidth + { + get { return 12.0 + 311.0 + 12.0; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Url.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + + WebPage = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Url.ToBytes()); + + WebPage.NullableToStream(output); + } + } + + public class TLDecryptedMessageMediaGroup : TLDecryptedMessageMediaBase, IMessageMediaGroup + { + public const uint Signature = TLConstructors.TLDecryptedMessageMediaGroup; + + public TLVector Group { get; set; } + + public TLVector GroupCommon + { + get + { + if (Group == null) + { + return new TLVector(); + } + + var group = new TLVector(); + foreach (var item in Group) + { + group.Add(item); + } + return group; + } + } + + public override double MediaWidth + { + get { return 1.0 + 311.0 + 1.0; } + } + + public event EventHandler Calculate; + + public virtual void RaiseCalculate() + { + var handler = Calculate; + if (handler != null) handler(this, EventArgs.Empty); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Group = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Group = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Group.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLDialog.cs b/Telegram.Api/TL/TLDialog.cs new file mode 100755 index 0000000..24ce4a0 --- /dev/null +++ b/Telegram.Api/TL/TLDialog.cs @@ -0,0 +1,1650 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using Telegram.Api.Helpers; +#if WIN_RT +using Windows.UI; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Media; +#elif WINDOWS_PHONE +using System.Windows; +using System.Windows.Media; +#endif +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum DialogCustomFlags + { + PinnedId = 0x1, // 0 + Promo = 0x2, // 1 + PromoExpires = 0x4, // 2 + PromoNotification = 0x8, // 3 + UnreadMark = 0x10, // 4 + } + + [Flags] + public enum DialogFlags + { + Pts = 0x1, // 0 + Draft = 0x2, // 1 + Pinned = 0x4, // 2 + UnreadMark = 0x8, // 3 + ReadMaxPosition = 0x10, // 4 + } + + public interface IDialogPts + { + TLInt Pts { get; set; } + } + + public enum TypingType + { + Text, + Record, + Upload + } + + public class Typing + { + public TypingType Type { get; protected set; } + + public string Description { get; protected set; } + + public override string ToString() + { + return Description; + } + + public Typing(TypingType type, string description) + { + Description = description; + Type = type; + } + + public static bool Equals(Typing typing1, Typing typing2) + { + if (typing1 == null && typing2 == null) return true; + if (typing1 == null) return false; + if (typing2 == null) return false; + + return typing1.Type == typing2.Type; + } + } + + public abstract class TLDialogBase : TLObject + { + public static string DialogFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (DialogFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public object MessagesSyncRoot = new object(); + + public int Index + { + get { return Peer != null && Peer.Id != null ? Peer.Id.Value : default(int); } + set + { + //NOTE: No need to set Index during deserialization. Possible null reference + } + } + + public TLPeerBase Peer { get; set; } + + public TLInt TopMessageId { get; set; } + + private TLInt _unreadCount; + + public TLInt UnreadCount + { + get { return _unreadCount; } + set { _unreadCount = value; } + } + + public virtual bool IsPinned { get; set; } + + public virtual TLInt PinnedId { get; set; } + + #region Additional + + public Typing Typing { get; set; } + + public TLDialogBase Self { get { return this; } } + + /// + /// If top message is sending message, than it has RandomId instead of Id + /// + public TLLong TopMessageRandomId { get; set; } + + public TLLong TopDecryptedMessageRandomId { get; set; } + + public TLPeerNotifySettingsBase NotifySettings { get; set; } + + public TLObject _with; + + public TLObject With + { + get { return _with; } + set { SetField(ref _with, value, () => With); } + } + + public int WithId + { + get + { + if (With is TLChatBase) + { + return ((TLChatBase)With).Index; + } + if (With is TLUserBase) + { + return ((TLUserBase)With).Index; + } + return -1; + } + } + + public Visibility ChatIconVisibility + { + get { return Peer is TLPeerChat ? Visibility.Visible : Visibility.Collapsed; } + } + + public Visibility ChatVisibility + { + get { return Peer is TLPeerChat || Peer is TLPeerEncryptedChat || Peer is TLPeerBroadcast ? Visibility.Visible : Visibility.Collapsed; } + } + + public Visibility UserVisibility + { + get { return Peer is TLPeerUser || _with is TLChatForbidden || _with is TLChatEmpty ? Visibility.Visible : Visibility.Collapsed; } + } + + public Visibility BotVisibility + { + get + { + var user = _with as TLUser; + return user != null && user.IsBot ? Visibility.Visible : Visibility.Collapsed; + } + } + + public Visibility EncryptedChatVisibility + { + get { return Peer is TLPeerEncryptedChat ? Visibility.Visible : Visibility.Collapsed; } + } + + public Visibility VerifiedVisibility + { + get + { + var user = With as TLUserBase; + if (user != null) + { + return user.IsVerified ? Visibility.Visible : Visibility.Collapsed; + } + + var channel = With as TLChannel; + if (channel != null) + { + return channel.IsVerified ? Visibility.Visible : Visibility.Collapsed; + } + + return Visibility.Collapsed; + } + } + + public Uri EncryptedImageSource + { + get + { + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + + return !isLightTheme ? + new Uri("/Images/Dialogs/secretchat-white-WXGA.png", UriKind.Relative) : + new Uri("/Images/Dialogs/secretchat-black-WXGA.png", UriKind.Relative); + } + } + + public virtual Brush ForegroundBrush + { + get { return (Brush)Application.Current.Resources["PhoneForegroundBrush"]; } + } + + public Brush MuteIconBackground + { + get { return new SolidColorBrush(Color.FromArgb(255, 39, 164, 236)); } + } + + public bool IsChat + { + get { return Peer is TLPeerChat; } + } + + public bool IsEncryptedChat + { + get { return Peer is TLPeerEncryptedChat; } + } + + public DateTime? LastNotificationTime { get; set; } + + public int UnmutedCount { get; set; } + #endregion + + public abstract int GetDateIndex(); + public abstract int GetDateIndexWithDraft(); + public abstract int CountMessages(); + } + + public class TLEncryptedDialog : TLDialogBase + { + public const uint Signature = TLConstructors.TLDialogSecret; + + #region Additional + + public TLInt UnreadMentionsCount { get; set; } + + public TLDecryptedMessageBase _topMessage; + + public TLDecryptedMessageBase TopMessage + { + get + { + if (TLUtils.IsDisplayedDecryptedMessage(_topMessage, true)) + { + return _topMessage; + } + + if (Messages != null) + { + for (var i = 0; i < Messages.Count; i++) + { + if (TLUtils.IsDisplayedDecryptedMessage(Messages[i], true)) + { + return Messages[i]; + } + } + } + + return null; + } + set { SetField(ref _topMessage, value, () => TopMessage); } + } + + public ObservableCollection Messages { get; set; } + #endregion + + public override Brush ForegroundBrush + { + get { return new SolidColorBrush(Color.FromArgb(255, 0, 170, 8)); } + } + + public override int GetDateIndex() + { + return _topMessage != null ? _topMessage.DateIndex : 0; + } + + public override int GetDateIndexWithDraft() + { + return _topMessage != null ? _topMessage.DateIndex : 0; + } + + public override int CountMessages() + { + return Messages.Count; + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + var topDecryptedMessageRandomId = GetObject(input); + if (topDecryptedMessageRandomId.Value != 0) + { + TopDecryptedMessageRandomId = topDecryptedMessageRandomId; + } + + UnreadCount = GetObject(input); + + _with = GetObject(input); + if (_with is TLNull) { _with = null; } + + var messages = GetObject>(input); + Messages = messages != null ? + new ObservableCollection(messages.Items) : + new ObservableCollection(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Peer.ToStream(output); + + TopDecryptedMessageRandomId = TopDecryptedMessageRandomId ?? new TLLong(0); + TopDecryptedMessageRandomId.ToStream(output); + + output.Write(UnreadCount.ToBytes()); + + With.NullableToStream(output); + + if (Messages != null) + { + var messages = new TLVector { Items = Messages }; + messages.ToStream(output); + } + else + { + var messages = new TLVector(); + messages.ToStream(output); + } + } + + public override string ToString() + { + return string.Format("peer=[{0}] unread_count={1} top_message_id={2} top_message={3}", Peer, UnreadCount, TopMessageId, TopMessage); + } + + public static int InsertMessageInOrder(IList messages, TLDecryptedMessageBase message) + { + var position = -1; + + if (messages.Count == 0) + { + position = 0; + } + + for (var i = 0; i < messages.Count; i++) + { + if (messages[i].DateIndex < message.DateIndex) + { + position = i; + break; + } + } + + if (position != -1) + { + messages.Insert(position, message); + } + + return position; + } + } + + public class TLBroadcastDialog : TLDialogBase + { + public const uint Signature = TLConstructors.TLBroadcastDialog; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + TopMessageId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + var topMessageId = GetObject(input); + if (topMessageId.Value != 0) + { + TopMessageId = topMessageId; + } + + UnreadCount = GetObject(input); + + var notifySettingsObject = GetObject(input); + NotifySettings = notifySettingsObject as TLPeerNotifySettingsBase; + + var topMessageRandomId = GetObject(input); + if (topMessageRandomId.Value != 0) + { + TopMessageRandomId = topMessageRandomId; + } + + _with = GetObject(input); + if (_with is TLNull) { _with = null; } + + var messages = GetObject>(input); + Messages = messages != null ? new ObservableCollection(messages.Items) : new ObservableCollection(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Peer.ToStream(output); + + TopMessageId = TopMessageId ?? new TLInt(0); + TopMessageId.ToStream(output); + + output.Write(UnreadCount.ToBytes()); + + NotifySettings.NullableToStream(output); + + TopMessageRandomId = TopMessageRandomId ?? new TLLong(0); + TopMessageRandomId.ToStream(output); + + With.NullableToStream(output); + if (Messages != null) + { + var messages = new TLVector { Items = Messages }; + messages.ToStream(output); + } + else + { + var messages = new TLVector(); + messages.ToStream(output); + } + } + + #region Additional + + public TLMessageBase _topMessage; + + public TLMessageBase TopMessage + { + get { return _topMessage; } + set { SetField(ref _topMessage, value, () => TopMessage); } + } + + public ObservableCollection Messages { get; set; } + + public bool ShowFrom + { + get { return Peer is TLPeerChat && !(TopMessage is TLMessageService); } + } + + #endregion + + public override int GetDateIndex() + { + return _topMessage != null ? _topMessage.DateIndex : 0; + } + + public override int GetDateIndexWithDraft() + { + return _topMessage != null ? _topMessage.DateIndex : 0; + } + + public override int CountMessages() + { + return Messages.Count; + } + + public override string ToString() + { + return string.Format("peer=[{0}] unread_count={1} top_message_id={2} top_message={3}", Peer, UnreadCount, TopMessageId, TopMessage); + } + + public static int InsertMessageInOrder(IList messages, TLMessageBase message) + { + var position = -1; + + if (messages.Count == 0) + { + position = 0; + } + + for (var i = 0; i < messages.Count; i++) + { + if (messages[i].Index == 0) + { + if (messages[i].DateIndex < message.DateIndex) + { + position = i; + break; + } + + continue; + } + + if (messages[i].Index == message.Index) + { + position = -1; + break; + } + if (messages[i].Index < message.Index) + { + position = i; + break; + } + } + + if (position != -1) + { + //message.IsAnimated = position == 0; + Execute.BeginOnUIThread(() => messages.Insert(position, message)); + } + + return position; + } + + public virtual void Update(TLDialog dialog) + { + Peer = dialog.Peer; + UnreadCount = dialog.UnreadCount; + + //если последнее сообщение отправляется и имеет дату больше, то не меняем + if (TopMessageId == null && TopMessage.DateIndex > dialog.TopMessage.DateIndex) + { + //добавляем сообщение в список в нужное место + InsertMessageInOrder(Messages, dialog.TopMessage); + + return; + } + TopMessageId = dialog.TopMessageId; + TopMessageRandomId = dialog.TopMessageRandomId; + TopMessage = dialog.TopMessage; + if (Messages.Count > 0) + { + for (int i = 0; i < Messages.Count; i++) + { + if (Messages[i].DateIndex < TopMessage.DateIndex) + { + Messages.Insert(i, TopMessage); + break; + } + if (Messages[i].DateIndex == TopMessage.DateIndex) + { + break; + } + } + } + else + { + Messages.Add(TopMessage); + } + } + } + + public class TLDialog : TLDialogBase + { + public const uint Signature = TLConstructors.TLDialog; + + #region Additional + + public TLMessageBase _topMessage; + + public TLMessageBase TopMessage + { + get { return _topMessage; } + set + { + + SetField(ref _topMessage, value, () => TopMessage); + } + } + + public ObservableCollection Messages { get; set; } + + public List CommitMessages { get; set; } + + public bool ShowFrom + { + get { return Peer is TLPeerChat && !(TopMessage is TLMessageService); } + } + + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + TopMessageId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + var topMessageId = GetObject(input); + if (topMessageId.Value != 0) + { + TopMessageId = topMessageId; + } + + UnreadCount = GetObject(input); + + var notifySettingsObject = GetObject(input); + NotifySettings = notifySettingsObject as TLPeerNotifySettingsBase; + + var topMessageRandomId = GetObject(input); + if (topMessageRandomId.Value != 0) + { + TopMessageRandomId = topMessageRandomId; + } + + _with = GetObject(input); + if (_with is TLNull) { _with = null; } + + var messages = GetObject>(input); + Messages = messages != null ? new ObservableCollection(messages.Items) : new ObservableCollection(); + + var dialog71 = new TLDialog71(); + dialog71.Flags = new TLInt(0); + dialog71.Peer = Peer; + dialog71.TopMessageId = TopMessageId; + dialog71.ReadInboxMaxId = new TLInt(0); + dialog71.ReadOutboxMaxId = new TLInt(0); + dialog71.UnreadCount = UnreadCount; + dialog71.UnreadMentionsCount = new TLInt(0); + dialog71.NotifySettings = NotifySettings; + //dialog53.Pts = Pts; + dialog71.Draft = null; + + dialog71.TopMessageRandomId = topMessageRandomId; + dialog71._with = _with; + dialog71.Messages = Messages; + + return dialog71; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Peer.ToStream(output); + + TopMessageId = TopMessageId ?? new TLInt(0); + TopMessageId.ToStream(output); + + output.Write(UnreadCount.ToBytes()); + + NotifySettings.NullableToStream(output); + + TopMessageRandomId = TopMessageRandomId ?? new TLLong(0); + TopMessageRandomId.ToStream(output); + + With.NullableToStream(output); + if (Messages != null) + { + var messages = new TLVector { Items = CommitMessages }; + messages.ToStream(output); + } + else + { + var messages = new TLVector(); + messages.ToStream(output); + } + } + + + public virtual void Update(TLDialog dialog) + { + Peer = dialog.Peer; + UnreadCount = dialog.UnreadCount; + + //если последнее сообщение отправляется и имеет дату больше, то не меняем + if (TopMessageId == null && (TopMessage == null || TopMessage.DateIndex > dialog.TopMessage.DateIndex)) + { + //добавляем сообщение в список в нужное место, если его еще нет + var insertRequired = false; + if (Messages != null && dialog.TopMessage != null) + { + var oldMessage = Messages.FirstOrDefault(x => x.Index == dialog.TopMessage.Index); + if (oldMessage == null) + { + insertRequired = true; + } + } + + if (insertRequired) + { + InsertMessageInOrder(Messages, dialog.TopMessage); + } + + return; + } + + if (TopMessageId != null + && dialog.TopMessageId != null + && TopMessageId.Value == dialog.TopMessageId.Value) + { + } + else if (TopMessage != null && TopMessage.RandomIndex != 0) + { + + } + else + { + TopMessageId = dialog.TopMessageId; + _topMessage = dialog.TopMessage; + TopMessageRandomId = dialog.TopMessageRandomId; + + lock (MessagesSyncRoot) + { + InsertMessageInOrder(Messages, TopMessage); + } + } + } + + #region Methods + + public override int GetDateIndex() + { + return _topMessage != null ? _topMessage.DateIndex : 0; + } + + public override int GetDateIndexWithDraft() + { + return _topMessage != null ? _topMessage.DateIndex : 0; + } + + public override int CountMessages() + { + return Messages.Count; + } + + public override string ToString() + { + return string.Format("peer=[{0}] pinned_id={1} unread_count={2} top_message_id={3} top_message={4}", Peer, PinnedId, UnreadCount, TopMessageId, TopMessage); + } + + public static int InsertMessageInOrder(IList messages, TLMessageBase message) + { + var position = -1; + + if (messages.Count == 0) + { + position = 0; + } + + for (var i = 0; i < messages.Count; i++) + { + if (messages[i].Index == 0) + { + if (messages[i].DateIndex < message.DateIndex) + { + position = i; + break; + } + + continue; + } + + if (messages[i].Index == message.Index) + { + position = -1; + break; + } + if (messages[i].Index < message.Index) + { + position = i; + break; + } + } + + if (position != -1) + { + //message._isAnimated = position == 0; + messages.Insert(position, message); + } + + return position; + } + #endregion + } + + public class TLDialog24 : TLDialog + { + public new const uint Signature = TLConstructors.TLDialog24; + + public TLInt ReadInboxMaxId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + TopMessageId = GetObject(bytes, ref position); + ReadInboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + var topMessageId = GetObject(input); + if (topMessageId.Value != 0) + { + TopMessageId = topMessageId; + } + ReadInboxMaxId = GetObject(input); + UnreadCount = GetObject(input); + + var notifySettingsObject = GetObject(input); + NotifySettings = notifySettingsObject as TLPeerNotifySettingsBase; + + var topMessageRandomId = GetObject(input); + if (topMessageRandomId.Value != 0) + { + TopMessageRandomId = topMessageRandomId; + } + + _with = GetObject(input); + if (_with is TLNull) { _with = null; } + + var messages = GetObject>(input); + Messages = messages != null ? new ObservableCollection(messages.Items) : new ObservableCollection(); + + + var dialog71 = new TLDialog71(); + dialog71.Flags = new TLInt(0); + dialog71.Peer = Peer; + dialog71.TopMessageId = TopMessageId; + dialog71.ReadInboxMaxId = ReadInboxMaxId; + dialog71.ReadOutboxMaxId = new TLInt(0); + dialog71.UnreadCount = UnreadCount; + dialog71.UnreadMentionsCount = new TLInt(0); + dialog71.NotifySettings = NotifySettings; + //dialog53.Pts = Pts; + dialog71.Draft = null; + + dialog71.TopMessageRandomId = topMessageRandomId; + dialog71._with = _with; + dialog71.Messages = Messages; + + return dialog71; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Peer.ToStream(output); + + TopMessageId = TopMessageId ?? new TLInt(0); + TopMessageId.ToStream(output); + + ReadInboxMaxId = ReadInboxMaxId ?? new TLInt(0); + ReadInboxMaxId.ToStream(output); + + output.Write(UnreadCount.ToBytes()); + + NotifySettings.NullableToStream(output); + + TopMessageRandomId = TopMessageRandomId ?? new TLLong(0); + TopMessageRandomId.ToStream(output); + + With.NullableToStream(output); + if (Messages != null) + { + var messages = new TLVector { Items = Messages }; + messages.ToStream(output); + } + else + { + var messages = new TLVector(); + messages.ToStream(output); + } + } + + public override void Update(TLDialog dialog) + { + try + { + base.Update(dialog); + } + catch (Exception ex) + { + Execute.ShowDebugMessage(ex.ToString()); + } + + var dialog24 = dialog as TLDialog24; + if (dialog24 != null) + { + ReadInboxMaxId = dialog24.ReadInboxMaxId; + } + } + } + + public class TLDialog53 : TLDialog24, IReadMaxId, IDialogPts + { + public new const uint Signature = TLConstructors.TLDialog53; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt ReadOutboxMaxId { get; set; } + + protected TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + protected TLInt _pts; + + public TLInt Pts + { + get { return _pts; } + set { SetField(out _pts, value, ref _flags, (int)DialogFlags.Pts); } + } + + protected TLDraftMessageBase _draft; + + public TLDraftMessageBase Draft + { + get { return _draft; } + set { SetField(out _draft, value, ref _flags, (int)DialogFlags.Draft); } + } + + protected TLInt _pinnedId; + + public override TLInt PinnedId + { + get { return _pinnedId; } + set { SetField(out _pinnedId, value, ref _customFlags, (int)DialogCustomFlags.PinnedId); } + } + + public bool UnreadMark + { + get { return IsSet(_customFlags, (int)DialogFlags.UnreadMark); } + set { SetUnset(ref _customFlags, value, (int)DialogFlags.UnreadMark); } + } + + public override int GetDateIndex() + { + if (IsPinned) + { + if (PinnedId != null) + { + return int.MaxValue - PinnedId.Value; + } + + Execute.ShowDebugMessage("GetDateIndex IsPinned=true PinnedId=null with=" + With); + } + + return base.GetDateIndex(); + } + + public override int GetDateIndexWithDraft() + { + var dateIndex = GetDateIndex(); + + if (IsPinned) + { + if (PinnedId != null) + { + return int.MaxValue - PinnedId.Value; + } + } + + var draft = Draft as TLDraftMessage; + if (draft != null) + { + return Math.Max(draft.Date.Value, dateIndex); + } + + return dateIndex; + } + + public override bool IsPinned + { + get { return IsSet(Flags, (int)DialogFlags.Pinned); } + set { SetUnset(ref _flags, value, (int)DialogFlags.Pinned); } + } + + public override string ToString() + { + return string.Format("flags={0} ", DialogFlagsString(Flags)) + "count=" + (Messages != null ? Messages.Count : 0) + " commit_count=" + (CommitMessages != null ? CommitMessages.Count : 0) + " " + base.ToString(); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Peer = GetObject(bytes, ref position); + TopMessageId = GetObject(bytes, ref position); + ReadInboxMaxId = GetObject(bytes, ref position); + ReadOutboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + _pts = GetObject(Flags, (int)DialogFlags.Pts, null, bytes, ref position); + _draft = GetObject(Flags, (int)DialogFlags.Draft, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Peer = GetObject(input); + var topMessageId = GetObject(input); + if (topMessageId.Value != 0) + { + TopMessageId = topMessageId; + } + ReadInboxMaxId = GetObject(input); + ReadOutboxMaxId = GetObject(input); + UnreadCount = GetObject(input); + + var notifySettingsObject = GetObject(input); + NotifySettings = notifySettingsObject as TLPeerNotifySettingsBase; + _pts = GetObject(Flags, (int)DialogFlags.Pts, null, input); + _draft = GetObject(Flags, (int)DialogFlags.Draft, null, input); + + var topMessageRandomId = GetObject(input); + if (topMessageRandomId.Value != 0) + { + TopMessageRandomId = topMessageRandomId; + } + + _with = GetObject(input); + if (_with is TLNull) { _with = null; } + + var messages = GetObject>(input); + Messages = messages != null ? new ObservableCollection(messages.Items) : new ObservableCollection(); + + CustomFlags = GetNullableObject(input); + PinnedId = GetObject(CustomFlags, (int)DialogCustomFlags.PinnedId, null, input); + + + var dialog71 = new TLDialog71(); + dialog71.Flags = new TLInt(0); + dialog71.Peer = Peer; + dialog71.TopMessageId = TopMessageId; + dialog71.ReadInboxMaxId = ReadInboxMaxId; + dialog71.ReadOutboxMaxId = ReadOutboxMaxId; + dialog71.UnreadCount = UnreadCount; + dialog71.UnreadMentionsCount = new TLInt(0); + dialog71.NotifySettings = NotifySettings; + dialog71.Pts = Pts; + dialog71.Draft = Draft; + + dialog71.TopMessageRandomId = TopMessageRandomId; + dialog71._with = _with; + dialog71.Messages = Messages; + + dialog71.PinnedId = PinnedId; + + return dialog71; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Peer.ToStream(output); + + TopMessageId = TopMessageId ?? new TLInt(0); + TopMessageId.ToStream(output); + + ReadInboxMaxId = ReadInboxMaxId ?? new TLInt(0); + ReadInboxMaxId.ToStream(output); + + ReadOutboxMaxId = ReadOutboxMaxId ?? new TLInt(0); + ReadOutboxMaxId.ToStream(output); + + UnreadCount.ToStream(output); + + NotifySettings.NullableToStream(output); + ToStream(output, Pts, Flags, (int)DialogFlags.Pts); + ToStream(output, Draft, Flags, (int)DialogFlags.Draft); + + TopMessageRandomId = TopMessageRandomId ?? new TLLong(0); + TopMessageRandomId.ToStream(output); + + With.NullableToStream(output); + if (Messages != null) + { + var messages = new TLVector { Items = CommitMessages }; + messages.ToStream(output); + } + else + { + var messages = new TLVector(); + messages.ToStream(output); + } + + CustomFlags.NullableToStream(output); + ToStream(output, PinnedId, CustomFlags, (int)DialogCustomFlags.PinnedId); + } + + public override void Update(TLDialog dialog) + { + try + { + base.Update(dialog); + } + catch (Exception ex) + { + Execute.ShowDebugMessage(ex.ToString()); + } + + var dialog53 = dialog as TLDialog53; + if (dialog53 != null) + { + ReadOutboxMaxId = dialog53.ReadOutboxMaxId; + Pts = dialog53.Pts; + Draft = dialog53.Draft; + + if (dialog53.IsPinned) + { + IsPinned = true; + if (dialog53.PinnedId != null) PinnedId = dialog53.PinnedId; + } + else + { + IsPinned = false; + dialog53.PinnedId = null; + } + } + } + } + + public class TLDialog71 : TLDialog53 + { + public new const uint Signature = TLConstructors.TLDialog71; + + public TLInt UnreadMentionsCount { get; set; } + + public TLVector UnreadMentions { get; set; } + + public IList MigratedHistory { get; set; } + + public bool IsPromo + { + get { return IsSet(_customFlags, (int)DialogCustomFlags.Promo); } + set { SetUnset(ref _customFlags, value, (int)DialogCustomFlags.Promo); } + } + + protected TLInt _promoExpires; + + public TLInt PromoExpires + { + get { return _promoExpires; } + set { SetField(out _promoExpires, value, ref _customFlags, (int)DialogCustomFlags.PromoExpires); } + } + + public bool PromoNotification + { + get { return IsSet(_customFlags, (int)DialogCustomFlags.PromoNotification); } + set { SetUnset(ref _customFlags, value, (int)DialogCustomFlags.PromoNotification); } + } + + public override int GetDateIndex() + { + if (IsPromo) + { + return int.MaxValue; + } + + if (IsPinned) + { + if (PinnedId != null) + { + return int.MaxValue - PinnedId.Value - 1; + } + + Execute.ShowDebugMessage("GetDateIndex IsPinned=true PinnedId=null with=" + With); + } + + return base.GetDateIndex(); + } + + public override int GetDateIndexWithDraft() + { + var dateIndex = GetDateIndex(); + + if (IsPromo) + { + return int.MaxValue; + } + + if (IsPinned) + { + if (PinnedId != null) + { + return int.MaxValue - PinnedId.Value - 1; + } + } + + var draft = Draft as TLDraftMessage; + if (draft != null) + { + return Math.Max(draft.Date.Value, dateIndex); + } + + return dateIndex; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Peer = GetObject(bytes, ref position); + TopMessageId = GetObject(bytes, ref position); + ReadInboxMaxId = GetObject(bytes, ref position); + ReadOutboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadMentionsCount = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + _pts = GetObject(Flags, (int)DialogFlags.Pts, null, bytes, ref position); + _draft = GetObject(Flags, (int)DialogFlags.Draft, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Peer = GetObject(input); + var topMessageId = GetObject(input); + if (topMessageId.Value != 0) + { + TopMessageId = topMessageId; + } + ReadInboxMaxId = GetObject(input); + ReadOutboxMaxId = GetObject(input); + UnreadCount = GetObject(input); + UnreadMentionsCount = GetObject(input); + + var notifySettingsObject = GetObject(input); + NotifySettings = notifySettingsObject as TLPeerNotifySettingsBase; + _pts = GetObject(Flags, (int)DialogFlags.Pts, null, input); + _draft = GetObject(Flags, (int)DialogFlags.Draft, null, input); + + var topMessageRandomId = GetObject(input); + if (topMessageRandomId.Value != 0) + { + TopMessageRandomId = topMessageRandomId; + } + + _with = GetObject(input); + if (_with is TLNull) { _with = null; } + + var messages = GetObject>(input); + Messages = messages != null ? new ObservableCollection(messages.Items) : new ObservableCollection(); + + CustomFlags = GetNullableObject(input); + _pinnedId = GetObject(CustomFlags, (int)DialogCustomFlags.PinnedId, null, input); + _promoExpires = GetObject(CustomFlags, (int)DialogCustomFlags.PromoExpires, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Peer.ToStream(output); + + TopMessageId = TopMessageId ?? new TLInt(0); + TopMessageId.ToStream(output); + + ReadInboxMaxId = ReadInboxMaxId ?? new TLInt(0); + ReadInboxMaxId.ToStream(output); + + ReadOutboxMaxId = ReadOutboxMaxId ?? new TLInt(0); + ReadOutboxMaxId.ToStream(output); + + UnreadCount.ToStream(output); + UnreadMentionsCount.ToStream(output); + + NotifySettings.NullableToStream(output); + ToStream(output, Pts, Flags, (int)DialogFlags.Pts); + ToStream(output, Draft, Flags, (int)DialogFlags.Draft); + + TopMessageRandomId = TopMessageRandomId ?? new TLLong(0); + TopMessageRandomId.ToStream(output); + + With.NullableToStream(output); + if (Messages != null) + { + var messages = new TLVector { Items = CommitMessages }; + messages.ToStream(output); + } + else + { + var messages = new TLVector(); + messages.ToStream(output); + } + + CustomFlags.NullableToStream(output); + ToStream(output, PinnedId, CustomFlags, (int)DialogCustomFlags.PinnedId); + ToStream(output, PromoExpires, CustomFlags, (int)DialogCustomFlags.PromoExpires); + } + + public override void Update(TLDialog dialog) + { + try + { + base.Update(dialog); + } + catch (Exception ex) + { + Execute.ShowDebugMessage(ex.ToString()); + } + + var dialog71 = dialog as TLDialog71; + if (dialog71 != null) + { + UnreadMentionsCount = dialog71.UnreadMentionsCount; + IsPromo = dialog71.IsPromo; + PromoExpires = dialog71.PromoExpires; + } + } + } + + public class TLDialogChannel : TLDialog24, IDialogPts + { + public new const uint Signature = TLConstructors.TLDialogChannel; + + public TLInt TopImportantMessageId { get; set; } + + public TLInt UnreadImportantCount { get; set; } + + public TLInt Pts { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + TopMessageId = GetObject(bytes, ref position); + TopImportantMessageId = GetObject(bytes, ref position); + ReadInboxMaxId = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadImportantCount = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + try + { + Peer = GetObject(input); + var topMessageId = GetObject(input); + if (topMessageId.Value != 0) + { + TopMessageId = topMessageId; + } + var topImportantMessageId = GetObject(input); + if (topImportantMessageId.Value != 0) + { + TopImportantMessageId = topImportantMessageId; + } + ReadInboxMaxId = GetObject(input); + UnreadCount = GetObject(input); + UnreadImportantCount = GetObject(input); + + var notifySettingsObject = GetObject(input); + NotifySettings = notifySettingsObject as TLPeerNotifySettingsBase; + Pts = GetObject(input); + + var topMessageRandomId = GetObject(input); + if (topMessageRandomId.Value != 0) + { + TopMessageRandomId = topMessageRandomId; + } + + _with = GetObject(input); + if (_with is TLNull) { _with = null; } + + var messages = GetObject>(input); + Messages = messages != null ? new ObservableCollection(messages.Items) : new ObservableCollection(); + + var dialog71 = new TLDialog71(); + dialog71.Flags = new TLInt(0); + dialog71.Peer = Peer; + dialog71.TopMessageId = TopMessageId; + dialog71.ReadInboxMaxId = ReadInboxMaxId; + dialog71.ReadOutboxMaxId = new TLInt(0); + dialog71.UnreadCount = UnreadCount; + dialog71.UnreadMentionsCount = new TLInt(0); + dialog71.NotifySettings = NotifySettings; + dialog71.Pts = Pts; + dialog71.Draft = null; + + dialog71.TopMessageRandomId = topMessageRandomId; + dialog71._with = _with; + dialog71.Messages = Messages; + + return dialog71; + } + catch (Exception ex) + { + Execute.ShowDebugMessage(ex.ToString()); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Peer.ToStream(output); + + TopMessageId = TopMessageId ?? new TLInt(0); + TopMessageId.ToStream(output); + TopImportantMessageId = TopImportantMessageId ?? new TLInt(0); + TopImportantMessageId.ToStream(output); + + ReadInboxMaxId = ReadInboxMaxId ?? new TLInt(0); + ReadInboxMaxId.ToStream(output); + + output.Write(UnreadCount.ToBytes()); + output.Write(UnreadImportantCount.ToBytes()); + + NotifySettings.NullableToStream(output); + + output.Write(Pts.ToBytes()); + + TopMessageRandomId = TopMessageRandomId ?? new TLLong(0); + TopMessageRandomId.ToStream(output); + + With.NullableToStream(output); + if (Messages != null) + { + var messages = new TLVector { Items = Messages.Where(x => x != null).ToList() }; +#if DEBUG + var indexes = new List(); + for (var i = 0; i < Messages.Count; i++) + { + if (Messages[i] == null) + { + indexes.Add(i); + } + } + if (indexes.Count > 0) + { + Execute.ShowDebugMessage("TLDialogChannel.ToStream Items has null values total=" + Messages.Count + " null indexes=" + string.Join(",", indexes)); + } +#endif + + messages.ToStream(output); + } + else + { + var messages = new TLVector(); + messages.ToStream(output); + } + } + + public override void Update(TLDialog dialog) + { + try + { + base.Update(dialog); + } + catch (Exception ex) + { + Execute.ShowDebugMessage(ex.ToString()); + } + + var d = dialog as TLDialogChannel; + if (d != null) + { + TopImportantMessageId = d.TopImportantMessageId; + UnreadImportantCount = d.UnreadImportantCount; + Pts = d.Pts; + } + } + } + + public class TLDialogFeed : TLDialog + { + public new const uint Signature = TLConstructors.TLDialogFeed; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLLong CustomFlags { get; set; } + + public TLInt FeedId { get; set; } + + public TLVector FeedOtherChannels { get; set; } + + protected TLFeedPosition _readMaxPosition; + + public TLFeedPosition ReadMaxPosition + { + get { return _readMaxPosition; } + set { SetField(out _readMaxPosition, value, ref _flags, (int)DialogFlags.ReadMaxPosition); } + } + + public TLInt UnreadMutedCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Peer = GetObject(bytes, ref position); + TopMessageId = GetObject(bytes, ref position); + FeedId = GetObject(bytes, ref position); + FeedOtherChannels = GetObject>(bytes, ref position); + _readMaxPosition = GetObject(Flags, (int)DialogFlags.ReadMaxPosition, null, bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + UnreadMutedCount = GetObject(bytes, ref position); + NotifySettings = new TLPeerNotifySettingsEmpty(); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Peer = GetObject(input); + TopMessageId = GetObject(input); + FeedId = GetObject(input); + FeedOtherChannels = GetObject>(input); + _readMaxPosition = GetObject(Flags, (int)DialogFlags.ReadMaxPosition, null, input); + UnreadCount = GetObject(input); + UnreadMutedCount = GetObject(input); + + NotifySettings = GetNullableObject(input); + TopMessageRandomId = GetObject(input); + //_with = GetNullableObject(input); + var messages = GetObject>(input) ?? new TLVector(); + Messages = new ObservableCollection(messages.Items); + + CustomFlags = GetNullableObject(input); + PinnedId = GetObject(CustomFlags, (int)DialogCustomFlags.PinnedId, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Peer.ToStream(output); + TopMessageId = TopMessageId ?? new TLInt(0); + TopMessageId.ToStream(output); + FeedId.ToStream(output); + FeedOtherChannels.ToStream(output); + ToStream(output, ReadMaxPosition, Flags, (int)DialogFlags.ReadMaxPosition); + UnreadCount.ToStream(output); + UnreadMutedCount.ToStream(output); + + NotifySettings.NullableToStream(output); + TopMessageRandomId = TopMessageRandomId ?? new TLLong(0); + TopMessageRandomId.ToStream(output); + //With.NullableToStream(output); + if (Messages != null) + { + var messages = new TLVector { Items = CommitMessages }; + messages.ToStream(output); + } + else + { + var messages = new TLVector(); + messages.ToStream(output); + } + + CustomFlags.NullableToStream(output); + ToStream(output, PinnedId, CustomFlags, (int)DialogCustomFlags.PinnedId); + } + + public override void Update(TLDialog dialog) + { + base.Update(dialog); + + var dialogFeed = dialog as TLDialogFeed; + if (dialogFeed != null) + { + FeedId = dialogFeed.FeedId; + FeedOtherChannels = dialogFeed.FeedOtherChannels; + ReadMaxPosition = dialogFeed.ReadMaxPosition; + UnreadMutedCount = dialogFeed.UnreadMutedCount; + + if (dialogFeed.IsPinned) + { + IsPinned = true; + if (dialogFeed.PinnedId != null) PinnedId = dialogFeed.PinnedId; + } + else + { + IsPinned = false; + dialogFeed.PinnedId = null; + } + } + } + } +} diff --git a/Telegram.Api/TL/TLDialogs.cs b/Telegram.Api/TL/TLDialogs.cs new file mode 100755 index 0000000..f62f5d7 --- /dev/null +++ b/Telegram.Api/TL/TLDialogs.cs @@ -0,0 +1,124 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLDialogsBase : TLObject + { + public TLVector Dialogs { get; set; } + + public TLVector Messages { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public abstract TLDialogsBase GetEmptyObject(); + + public TLPeerDialogs ToPeerDialogs(TLState state) + { + return new TLPeerDialogs + { + Dialogs = Dialogs, + Messages = Messages, + Chats = Chats, + Users = Users, + State = state + }; + } + } + public class TLDialogsNotModified : TLDialogsBase + { + public const uint Signature = TLConstructors.TLDialogsNotModified; + + public TLInt Count { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Count = GetObject(bytes, ref position); + Dialogs = new TLVector(); + Messages = new TLVector(); + Chats = new TLVector(); + Users = new TLVector(); + + return this; + } + + public override TLDialogsBase GetEmptyObject() + { + return new TLDialogs + { + Dialogs = new TLVector(Dialogs.Count), + Messages = new TLVector(Messages.Count), + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count) + }; + } + } + + public class TLDialogs : TLDialogsBase + { + public const uint Signature = TLConstructors.TLDialogs; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Dialogs = GetObject>(bytes, ref position); + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLDialogsBase GetEmptyObject() + { + return new TLDialogs + { + Dialogs = new TLVector(Dialogs.Count), + Messages = new TLVector(Messages.Count), + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count) + }; + } + } + + public class TLDialogsSlice : TLDialogsBase + { + public const uint Signature = TLConstructors.TLDialogsSlice; + + public TLInt Count { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Count = GetObject(bytes, ref position); + Dialogs = GetObject>(bytes, ref position); + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLDialogsBase GetEmptyObject() + { + return new TLDialogsSlice + { + Count = Count, + Dialogs = new TLVector(Dialogs.Count), + Messages = new TLVector(Messages.Count), + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count) + }; + } + } +} diff --git a/Telegram.Api/TL/TLDifference.cs b/Telegram.Api/TL/TLDifference.cs new file mode 100755 index 0000000..563105a --- /dev/null +++ b/Telegram.Api/TL/TLDifference.cs @@ -0,0 +1,416 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLDifferenceBase : TLObject + { + public abstract TLDifferenceBase GetEmptyObject(); + } + + public class TLDifferenceEmpty : TLDifferenceBase + { + public const uint Signature = TLConstructors.TLDifferenceEmpty; + + public TLInt Date { get; set; } + + public TLInt Seq { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + Seq = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Date.ToStream(output); + Seq.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Date = GetObject(input); + Seq = GetObject(input); + + return this; + } + + public override TLDifferenceBase GetEmptyObject() + { + return new TLDifferenceEmpty { Date = Date, Seq = Seq }; + } + + public override string ToString() + { + return string.Format("TLDifferenceEmpty date={0} seq={1}", Date, Seq); + } + } + + public class TLDifference : TLDifferenceBase + { + public const uint Signature = TLConstructors.TLDifference; + + public TLVector NewMessages { get; set; } + public TLVector NewEncryptedMessages { get; set; } + public TLVector OtherUpdates { get; set; } + public TLVector Users { get; set; } + public TLVector Chats { get; set; } + public TLState State { get; set; } + + public override TLDifferenceBase GetEmptyObject() + { + return new TLDifference + { + NewMessages = new TLVector(NewMessages.Count), + NewEncryptedMessages = new TLVector(NewEncryptedMessages.Count), + OtherUpdates = new TLVector(OtherUpdates.Count), + Users = new TLVector(Users.Count), + Chats = new TLVector(Chats.Count), + State = State + }; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + NewMessages = GetObject>(bytes, ref position); + NewEncryptedMessages = GetObject>(bytes, ref position); + OtherUpdates = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + State = GetObject(bytes, ref position); + + ProcessReading(); + + return this; + } + + protected void ProcessReading() + { + var readUserInbox = new Dictionary(); + var readUserOutbox = new Dictionary(); + + var readChatInbox = new Dictionary(); + var readChatOutbox = new Dictionary(); + + var readChannelInbox = new Dictionary(); + var readChannelOutbox = new Dictionary(); + + var newMessages = new List(); + var newChannelMessages = new List(); + + foreach (var otherUpdate in OtherUpdates) + { + var updateNewChannelMessage = otherUpdate as TLUpdateNewChannelMessage; + if (updateNewChannelMessage != null) + { + newChannelMessages.Add(updateNewChannelMessage); + continue; + } + + var updateNewMessage = otherUpdate as TLUpdateNewMessage; + if (updateNewMessage != null) + { + newMessages.Add(updateNewMessage); + continue; + } + + var updateReadChannelInbox = otherUpdate as TLUpdateReadChannelInbox; + if (updateReadChannelInbox != null) + { + readChannelInbox[updateReadChannelInbox.ChannelId.Value] = updateReadChannelInbox; + continue; + } + + var updateReadChannelOutbox = otherUpdate as TLUpdateReadChannelOutbox; + if (updateReadChannelOutbox != null) + { + readChannelOutbox[updateReadChannelOutbox.ChannelId.Value] = updateReadChannelOutbox; + continue; + } + + var updateReadHistoryInbox = otherUpdate as TLUpdateReadHistoryInbox; + if (updateReadHistoryInbox != null) + { + if (updateReadHistoryInbox.Peer is TLPeerChat) + { + readChatInbox[updateReadHistoryInbox.Peer.Id.Value] = updateReadHistoryInbox; + } + else if (updateReadHistoryInbox.Peer is TLPeerUser) + { + readUserInbox[updateReadHistoryInbox.Peer.Id.Value] = updateReadHistoryInbox; + } + continue; + } + + var updateReadHistoryOutbox = otherUpdate as TLUpdateReadHistoryOutbox; + if (updateReadHistoryOutbox != null) + { + if (updateReadHistoryOutbox.Peer is TLPeerChat) + { + readChatOutbox[updateReadHistoryOutbox.Peer.Id.Value] = updateReadHistoryOutbox; + } + else if (updateReadHistoryOutbox.Peer is TLPeerUser) + { + readUserOutbox[updateReadHistoryOutbox.Peer.Id.Value] = updateReadHistoryOutbox; + } + continue; + } + } + + for (var i = 0; i < newChannelMessages.Count; i++) + { + var messageCommon = newChannelMessages[i].Message as TLMessageCommon; + if (messageCommon != null) + { + if (IsReadMessage(messageCommon, + readChatOutbox, readChatInbox, + readUserOutbox, readUserInbox, + readChannelOutbox, readChannelInbox)) + { + continue; + } + + messageCommon.SetUnreadSilent(TLBool.True); + } + } + + for (var i = 0; i < newMessages.Count; i++) + { + var messageCommon = newMessages[i].Message as TLMessageCommon; + if (messageCommon != null) + { + if (IsReadMessage(messageCommon, + readChatOutbox, readChatInbox, + readUserOutbox, readUserInbox, + readChannelOutbox, readChannelInbox)) + { + continue; + } + + messageCommon.SetUnreadSilent(TLBool.True); + } + } + + for (var i = 0; i < NewMessages.Count; i++) + { + var messageCommon = NewMessages[i] as TLMessageCommon; + if (messageCommon != null) + { + if (IsReadMessage(messageCommon, + readChatOutbox, readChatInbox, + readUserOutbox, readUserInbox, + readChannelOutbox, readChannelInbox)) + { + continue; + } + + messageCommon.SetUnreadSilent(TLBool.True); + } + } + } + + private static bool IsReadMessage(TLMessageCommon messageCommon, + Dictionary readChatOutbox, Dictionary readChatInbox, + Dictionary readUserOutbox, Dictionary readUserInbox, + Dictionary readChannelOutbox, Dictionary readChannelInbox) + { + if (messageCommon.ToId is TLPeerChat) + { + if (messageCommon.Out.Value) + { + TLUpdateReadHistory updateReadHistory; + if (readChatOutbox.TryGetValue(messageCommon.ToId.Id.Value, out updateReadHistory) + && updateReadHistory.MaxId.Value >= messageCommon.Index) + { + return true; + } + } + else + { + TLUpdateReadHistory updateReadHistory; + if (readChatInbox.TryGetValue(messageCommon.ToId.Id.Value, out updateReadHistory) + && updateReadHistory.MaxId.Value >= messageCommon.Index) + { + return true; + } + } + } + else if (messageCommon.ToId is TLPeerUser) + { + if (messageCommon.Out.Value) + { + TLUpdateReadHistory updateReadHistory; + if (readUserOutbox.TryGetValue(messageCommon.ToId.Id.Value, out updateReadHistory) + && updateReadHistory.MaxId.Value >= messageCommon.Index) + { + return true; + } + } + else + { + TLUpdateReadHistory updateReadHistory; + if (readUserInbox.TryGetValue(messageCommon.FromId.Value, out updateReadHistory) + && updateReadHistory.MaxId.Value >= messageCommon.Index) + { + return true; + } + } + } + else if (messageCommon.ToId is TLPeerChannel) + { + if (messageCommon.Out.Value) + { + TLUpdateReadChannelOutbox updateReadHistory; + if (readChannelOutbox.TryGetValue(messageCommon.ToId.Id.Value, out updateReadHistory) + && updateReadHistory.MaxId.Value >= messageCommon.Index) + { + return true; + } + } + else + { + TLUpdateReadChannelInbox updateReadHistory; + if (readChannelInbox.TryGetValue(messageCommon.ToId.Id.Value, out updateReadHistory) + && updateReadHistory.MaxId.Value >= messageCommon.Index) + { + return true; + } + } + } + + return false; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + NewMessages.ToStream(output); + NewEncryptedMessages.ToStream(output); + OtherUpdates.ToStream(output); + Chats.ToStream(output); + Users.ToStream(output); + State.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + NewMessages = GetObject>(input); + NewEncryptedMessages = GetObject>(input); + OtherUpdates = GetObject>(input); + Chats = GetObject>(input); + Users = GetObject>(input); + State = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLDifference state=[{0}] messages={1} other={2} users={3} chats={4} encrypted={5}", State, NewMessages.Count, OtherUpdates.Count, Users.Count, Chats.Count, NewEncryptedMessages.Count); + } + } + + public class TLDifferenceSlice : TLDifference + { + public new const uint Signature = TLConstructors.TLDifferenceSlice; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + NewMessages = GetObject>(bytes, ref position); + NewEncryptedMessages = GetObject>(bytes, ref position); + OtherUpdates = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + State = GetObject(bytes, ref position); + + ProcessReading(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + NewMessages.ToStream(output); + NewEncryptedMessages.ToStream(output); + OtherUpdates.ToStream(output); + Chats.ToStream(output); + Users.ToStream(output); + State.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + NewMessages = GetObject>(input); + NewEncryptedMessages = GetObject>(input); + OtherUpdates = GetObject>(input); + Chats = GetObject>(input); + Users = GetObject>(input); + State = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLDifferenceSlice state=[{0}] messages={1} other={2} users={3} chats={4} encrypted={5}", State, NewMessages.Count, OtherUpdates.Count, Users.Count, Chats.Count, NewEncryptedMessages.Count); + } + } + + public class TLDifferenceTooLong : TLDifferenceBase + { + public const uint Signature = TLConstructors.TLDifferenceTooLong; + + public TLInt Pts { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Pts = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Pts.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Pts = GetObject(input); + + return this; + } + + public override TLDifferenceBase GetEmptyObject() + { + return new TLDifferenceTooLong { Pts = Pts }; + } + + public override string ToString() + { + return string.Format("TLDifferenceTooLong pts={0}", Pts); + } + } +} diff --git a/Telegram.Api/TL/TLDisabledFeature.cs b/Telegram.Api/TL/TLDisabledFeature.cs new file mode 100755 index 0000000..76c8817 --- /dev/null +++ b/Telegram.Api/TL/TLDisabledFeature.cs @@ -0,0 +1,38 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Runtime.Serialization; + +namespace Telegram.Api.TL +{ + [DataContract] + public class TLDisabledFeature : TLObject + { + public const uint Signature = TLConstructors.TLDisabledFeature; + + [DataMember] + public TLString Feature { get; set; } + + [DataMember] + public TLString Description { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Feature = GetObject(bytes, ref position); + Description = GetObject(bytes, ref position); + + return this; + } + + public override string ToString() + { + return string.Format("{0} {1}", Feature, Description); + } + } +} diff --git a/Telegram.Api/TL/TLDocument.cs b/Telegram.Api/TL/TLDocument.cs new file mode 100755 index 0000000..bc1c0ce --- /dev/null +++ b/Telegram.Api/TL/TLDocument.cs @@ -0,0 +1,680 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using System.Linq; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public interface IAttributes + { + TLVector Attributes { get; set; } + } + + public abstract class TLDocumentBase : TLObject + { + public long Index + { + get { return Id != null ? Id.Value : 0; } + } + + public TLLong Id { get; set; } + + public string ShortId { get { return Id != null ? (Id.Value % 1000).ToString() : "unknown"; } } + + public virtual int DocumentSize { get { return 0; } } + + public static bool DocumentEquals(TLDocumentBase document1, TLDocumentBase document2) + { + var doc1 = document1 as TLDocument; + var doc2 = document2 as TLDocument; + + if (doc1 == null || doc2 == null) return false; + + return doc1.Id.Value == doc2.Id.Value + && doc1.DCId.Value == doc2.DCId.Value + && doc1.AccessHash.Value == doc2.AccessHash.Value; + } + } + + public class TLDocumentExternal : TLDocumentBase, IAttributes + { + public const uint Signature = TLConstructors.TLDocumentExternal; + + public TLString ResultId { get; set; } + + public TLString Type { get; set; } + + public TLString Url { get; set; } + + public TLString ThumbUrl { get; set; } + + public TLString ContentUrl { get; set; } + + public TLString ContentType { get; set; } + + public TLVector Attributes { get; set; } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + ResultId = GetObject(input); + Type = GetObject(input); + ThumbUrl = GetObject(input); + ContentType = GetObject(input); + ContentUrl = GetObject(input); + Url = GetObject(input); + Attributes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + ResultId.ToStream(output); + Type.ToStream(output); + ThumbUrl.ToStream(output); + ContentType.ToStream(output); + ContentUrl.ToStream(output); + Url.ToStream(output); + Attributes.ToStream(output); + } + + public string GetFileName() + { + string extension; + if (!TLString.IsNullOrEmpty(Url)) + { + extension = Path.GetExtension(Url.ToString()); + + if (!string.IsNullOrEmpty(extension)) + { + return ResultId + extension; + } + } + if (!TLString.IsNullOrEmpty(ContentUrl)) + { + extension = Path.GetExtension(ContentUrl.ToString()); + + if (!string.IsNullOrEmpty(extension)) + { + return ResultId + extension; + } + } + + return ResultId + TLUtils.ContentTypeToFileExt(ContentType); + } + } + + public class TLDocumentEmpty : TLDocumentBase + { + public const uint Signature = TLConstructors.TLDocumentEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + } + } + + public abstract class TLDocument : TLDocumentBase + { + public TLLong AccessHash { get; set; } + + public TLInt Date { get; set; } + + public TLString MimeType { get; set; } + + public TLInt Size { get; set; } + + public override int DocumentSize + { + get { return Size != null ? Size.Value : 0; } + } + + public TLPhotoSizeBase Thumb { get; set; } + + public TLInt DCId { get; set; } + + public byte[] Buffer { get; set; } + + public TLInputFileBase ThumbInputFile { get; set; } + + public virtual TLInputDocumentFileLocation ToInputFileLocation() + { + return new TLInputDocumentFileLocation { AccessHash = AccessHash, Id = Id }; + } + + public abstract TLString FileName { get; set; } + + public abstract string DocumentName { get; } + + public string FileExt + { + get { return Path.GetExtension(FileName.ToString()).Replace(".", string.Empty); } + } + + public virtual string GetFileName() + { + return string.Format("document{0}_{1}.{2}", Id, AccessHash, FileExt); + } + } + + public class TLDocument10 : TLDocument + { + public const uint Signature = TLConstructors.TLDocument; + + public TLInt UserId { get; set; } + + public override TLString FileName { get; set; } + + public override string DocumentName { get { return FileName != null ? FileName.ToString() : string.Empty; } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + FileName = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Thumb = GetObject(bytes, ref position); + DCId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + UserId.ToBytes(), + Date.ToBytes(), + FileName.ToBytes(), + MimeType.ToBytes(), + Size.ToBytes(), + Thumb.ToBytes(), + DCId.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + UserId = GetObject(input); + Date = GetObject(input); + FileName = GetObject(input); + MimeType = GetObject(input); + Size = GetObject(input); + Thumb = GetObject(input); + DCId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + AccessHash.ToStream(output); + UserId.ToStream(output); + Date.ToStream(output); + FileName.ToStream(output); + MimeType.ToStream(output); + Size.ToStream(output); + Thumb.ToStream(output); + DCId.ToStream(output); + } + } + + public class TLDocument22 : TLDocument, IAttributes + { + public const uint Signature = TLConstructors.TLDocument22; + + public TLVector Attributes { get; set; } + + public bool Music + { + get + { + var documentAttributeAudio = Attributes.FirstOrDefault(x => x is TLDocumentAttributeAudio46) as TLDocumentAttributeAudio46; + if (documentAttributeAudio != null) + { + return !documentAttributeAudio.Voice; + } + + return false; + } + } + + public override string DocumentName + { + get + { + var documentAttributeAudio = Attributes.FirstOrDefault(x => x is TLDocumentAttributeAudio46) as TLDocumentAttributeAudio46; + if (documentAttributeAudio != null) + { + if (documentAttributeAudio.Title != null && documentAttributeAudio.Performer != null) + { + return string.Format("{0} — {1}", documentAttributeAudio.Title, documentAttributeAudio.Performer); + } + + if (documentAttributeAudio.Title != null) + { + return string.Format("{0}", documentAttributeAudio.Title); + } + + if (documentAttributeAudio.Performer != null) + { + return string.Format("{0}", documentAttributeAudio.Performer); + } + } + + return FileName.ToString(); + } + } + + public override string GetFileName() + { + if (TLMessageBase.IsVideo(this)) + { + return string.Format("video{0}_{1}.{2}", Id, AccessHash, "mp4"); + } + if (TLMessageBase.IsVoice(this)) + { + return string.Format("audio{0}_{1}.{2}", Id, AccessHash, "mp3"); + } + + return string.Format("document{0}_{1}.{2}", Id, AccessHash, FileExt); + } + + public override TLInputDocumentFileLocation ToInputFileLocation() + { + return new TLInputDocumentFileLocation + { + Id = Id, + AccessHash = AccessHash + }; + } + + public TLInt Duration + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var durationAttribute = Attributes[i] as IAttributeDuration; + if (durationAttribute != null) + { + return durationAttribute.Duration; + } + } + } + + return new TLInt(0); + } + } + + public string DurationString + { + get + { + var timeSpan = TimeSpan.FromSeconds(Duration.Value); + + if (timeSpan.Hours > 0) + { + return timeSpan.ToString(@"h\:mm\:ss"); + } + + return timeSpan.ToString(@"m\:ss"); + } + } + + public TLInt ImageSizeH + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var imageSizeAttribute = Attributes[i] as TLDocumentAttributeImageSize; + if (imageSizeAttribute != null) + { + return imageSizeAttribute.H; + } + } + } + + return new TLInt(0); + } + } + + public TLInt ImageSizeW + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var imageSizeAttribute = Attributes[i] as TLDocumentAttributeImageSize; + if (imageSizeAttribute != null) + { + return imageSizeAttribute.W; + } + } + } + + return new TLInt(0); + } + } + + public override TLString FileName + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var fileNameAttribute = Attributes[i] as TLDocumentAttributeFileName; + if (fileNameAttribute != null) + { + return fileNameAttribute.FileName; + } + } + } + + return TLString.Empty; + } + set + { + Attributes = Attributes ?? new TLVector(); + + for (var i = 0; i < Attributes.Count; i++) + { + if (Attributes[i] is TLDocumentAttributeFileName) + { + Attributes.RemoveAt(i--); + } + } + + Attributes.Add(new TLDocumentAttributeFileName{FileName = value}); + } + } + + public TLInputStickerSetBase StickerSet + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var stickerAttribute = Attributes[i] as TLDocumentAttributeSticker29; + if (stickerAttribute != null) + { + return stickerAttribute.Stickerset; + } + } + } + + return null; + } + } + + #region Additional + + private string _emoticon; + + public string Emoticon + { + get + { + if (_emoticon != null) return _emoticon; + + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var stickerAttribute = Attributes[i] as TLDocumentAttributeSticker29; + if (stickerAttribute != null) + { + _emoticon = stickerAttribute.Alt.ToString(); + } + } + } + + _emoticon = _emoticon ?? string.Empty; + + return _emoticon; + } + } + + #endregion + + public override string ToString() + { + return string.Format("{0} Id={1}", GetType().Name, Id) + (StickerSet != null ? StickerSet.ToString() : string.Empty); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Thumb = GetObject(bytes, ref position); + DCId = GetObject(bytes, ref position); + Attributes = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + Date.ToBytes(), + MimeType.ToBytes(), + Size.ToBytes(), + Thumb.ToBytes(), + DCId.ToBytes(), + Attributes.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + MimeType = GetObject(input); + Size = GetObject(input); + Thumb = GetObject(input); + DCId = GetObject(input); + Attributes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + AccessHash.ToStream(output); + Date.ToStream(output); + MimeType.ToStream(output); + Size.ToStream(output); + Thumb.ToStream(output); + DCId.ToStream(output); + Attributes.ToStream(output); + } + } + + public class TLDocument54 : TLDocument22 + { + public new const uint Signature = TLConstructors.TLDocument54; + + public bool Mask + { + get + { + if (Attributes != null) + { + for (var i = 0; i < Attributes.Count; i++) + { + var stickerAttribute = Attributes[i] as TLDocumentAttributeSticker56; + if (stickerAttribute != null) + { + return stickerAttribute.Mask; + } + } + } + + return false; + } + } + + public TLInt Version { get; set; } + + public override string ToString() + { + return string.Format("{0} id={1} version={2}", GetType().Name, Id, Version) + (StickerSet != null ? " stickerset=[" + StickerSet + "]" : string.Empty); + } + + public override string GetFileName() + { + if (TLMessageBase.IsVideo(this)) + { + return string.Format("video{0}_{1}.{2}", Id, AccessHash, "mp4"); + } + if (TLMessageBase.IsVoice(this)) + { + return string.Format("audio{0}_{1}.{2}", Id, AccessHash, "mp3"); + } + + var documentVersion = Version; + if (documentVersion != null && documentVersion.Value > 0) + { + return string.Format("document{0}_{1}.{2}", Id, documentVersion, FileExt); + } + + return string.Format("document{0}_{1}.{2}", Id, AccessHash, FileExt); + } + + public override TLInputDocumentFileLocation ToInputFileLocation() + { + return new TLInputDocumentFileLocation54 + { + Id = Id, + AccessHash = AccessHash, + Version = Version + }; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Thumb = GetObject(bytes, ref position); + DCId = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + Attributes = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + Date.ToBytes(), + MimeType.ToBytes(), + Size.ToBytes(), + Thumb.ToBytes(), + DCId.ToBytes(), + Version.ToBytes(), + Attributes.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + MimeType = GetObject(input); + Size = GetObject(input); + Thumb = GetObject(input); + DCId = GetObject(input); + Version = GetObject(input); + Attributes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + AccessHash.ToStream(output); + Date.ToStream(output); + MimeType.ToStream(output); + Size.ToStream(output); + Thumb.ToStream(output); + DCId.ToStream(output); + Version.ToStream(output); + Attributes.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLDocumentAttribute.cs b/Telegram.Api/TL/TLDocumentAttribute.cs new file mode 100755 index 0000000..9cdcf8a --- /dev/null +++ b/Telegram.Api/TL/TLDocumentAttribute.cs @@ -0,0 +1,664 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum DocumentAttributeVideoFlags + { + RoundMessage = 0x1, // 0 + } + + [Flags] + public enum DocumentAttributeStickerFlags + { + MaskCoords = 0x1, // 0 + Mask = 0x2, // 1 + } + + [Flags] + public enum DocumentAttributeAudioFlags + { + Title = 0x1, // 0 + Performer = 0x2, // 1 + Waveform = 0x4, // 2 + + Voice = 0x400, // 10 + } + + public interface IAttributeDuration + { + TLInt Duration { get; set; } + } + + public interface IAttributeSize + { + TLInt W { get; set; } + + TLInt H { get; set; } + } + + public abstract class TLDocumentAttributeBase : TLObject { } + + public class TLDocumentAttributeImageSize : TLDocumentAttributeBase, IAttributeSize + { + public const uint Signature = TLConstructors.TLDocumentAttributeImageSize; + + public TLInt W { get; set; } + + public TLInt H { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + W.ToBytes(), + H.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + W = GetObject(input); + H = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + W.ToStream(output); + H.ToStream(output); + } + } + + public class TLDocumentAttributeAnimated : TLDocumentAttributeBase + { + public const uint Signature = TLConstructors.TLDocumentAttributeAnimated; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLDocumentAttributeSticker : TLDocumentAttributeBase + { + public const uint Signature = TLConstructors.TLDocumentAttributeSticker; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLDocumentAttributeSticker25 : TLDocumentAttributeSticker + { + public new const uint Signature = TLConstructors.TLDocumentAttributeSticker25; + + public TLString Alt { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Alt = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Alt.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Alt = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Alt.ToStream(output); + } + } + + public class TLDocumentAttributeSticker29 : TLDocumentAttributeSticker25 + { + public new const uint Signature = TLConstructors.TLDocumentAttributeSticker29; + + public TLInputStickerSetBase Stickerset { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Alt = GetObject(bytes, ref position); + Stickerset = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Alt.ToBytes(), + Stickerset.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Alt = GetObject(input); + Stickerset = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Alt.ToStream(output); + Stickerset.ToStream(output); + } + } + + public class TLDocumentAttributeSticker56 : TLDocumentAttributeSticker29 + { + public new const uint Signature = TLConstructors.TLDocumentAttributeSticker56; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLMaskCoords _maskCoords; + + public TLMaskCoords MaskCoords + { + get { return _maskCoords; } + set { SetField(out _maskCoords, value, ref _flags, (int) DocumentAttributeStickerFlags.MaskCoords); } + } + + public bool Mask { get { return IsSet(Flags, (int) DocumentAttributeStickerFlags.Mask); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Alt = GetObject(bytes, ref position); + Stickerset = GetObject(bytes, ref position); + MaskCoords = GetObject(Flags, (int) DocumentAttributeStickerFlags.MaskCoords, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Alt.ToBytes(), + Stickerset.ToBytes(), + ToBytes(MaskCoords, Flags, (int) DocumentAttributeStickerFlags.MaskCoords)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Alt = GetObject(input); + Stickerset = GetObject(input); + MaskCoords = GetObject(Flags, (int) DocumentAttributeStickerFlags.MaskCoords, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Alt.ToStream(output); + Stickerset.ToStream(output); + ToStream(output, MaskCoords, Flags, (int) DocumentAttributeStickerFlags.MaskCoords); + } + } + + public class TLDocumentAttributeVideo66 : TLDocumentAttributeVideo + { + public new const uint Signature = TLConstructors.TLDocumentAttributeVideo66; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool RoundMessage + { + get { return IsSet(Flags, (int) DocumentAttributeVideoFlags.RoundMessage); } + set { SetUnset(ref _flags, value, (int) DocumentAttributeVideoFlags.RoundMessage); } + } + + public bool Mask { get { return IsSet(Flags, (int)DocumentAttributeStickerFlags.Mask); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Duration = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Duration.ToBytes(), + W.ToBytes(), + H.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Duration = GetObject(input); + W = GetObject(input); + H = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Duration.ToStream(output); + W.ToStream(output); + H.ToStream(output); + } + } + + public class TLDocumentAttributeVideo : TLDocumentAttributeBase, IAttributeDuration, IAttributeSize + { + public const uint Signature = TLConstructors.TLDocumentAttributeVideo; + + public TLInt Duration { get; set; } + + public TLInt W { get; set; } + + public TLInt H { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Duration = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Duration.ToBytes(), + W.ToBytes(), + H.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Duration = GetObject(input); + W = GetObject(input); + H = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Duration.ToStream(output); + W.ToStream(output); + H.ToStream(output); + } + } + + public class TLDocumentAttributeAudio : TLDocumentAttributeBase, IAttributeDuration + { + public const uint Signature = TLConstructors.TLDocumentAttributeAudio; + + public TLInt Duration { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Duration = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Duration.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Duration = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Duration.ToStream(output); + } + } + + public class TLDocumentAttributeAudio32 : TLDocumentAttributeAudio + { + public new const uint Signature = TLConstructors.TLDocumentAttributeAudio32; + + public virtual TLString Title { get; set; } + + public virtual TLString Performer { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Duration = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + Performer = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Duration.ToBytes(), + Title.ToBytes(), + Performer.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Duration = GetObject(input); + Title = GetObject(input); + Performer = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Duration.ToStream(output); + Title.ToStream(output); + Performer.ToStream(output); + } + } + + public class TLDocumentAttributeAudio46 : TLDocumentAttributeAudio32 + { + public new const uint Signature = TLConstructors.TLDocumentAttributeAudio46; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Voice + { + get { return IsSet(Flags, (int) DocumentAttributeAudioFlags.Voice); } + set { SetUnset(ref _flags, value, (int) DocumentAttributeAudioFlags.Voice); } + } + + protected TLString _title; + + public override TLString Title + { + get { return _title; } + set { SetFlagValue(value, out _title, ref _flags, (int)DocumentAttributeAudioFlags.Title); } + } + + protected TLString _performer; + + public override TLString Performer + { + get { return _performer; } + set { SetFlagValue(value, out _performer, ref _flags, (int)DocumentAttributeAudioFlags.Performer); } + } + + protected TLString _waveform; + + public TLString Waveform + { + get { return _waveform; } + set { SetFlagValue(value, out _waveform, ref _flags, (int)DocumentAttributeAudioFlags.Waveform); } + } + + private static void SetFlagValue(T value, out T field, ref TLInt flags, int flag) where T : TLObject + { + if (value != null) + { + Set(ref flags, flag); + field = value; + } + else + { + Unset(ref flags, flag); + field = default(T); + } + } + + private static void GetObject(byte[] bytes, ref int position, ref T field, TLInt flags, int flag) where T : TLObject + { + if (IsSet(flags, flag)) + { + field = GetObject(bytes, ref position); + } + } + + private static void GetObject(Stream input, ref T field, TLInt flags, int flag) where T : TLObject + { + if (IsSet(flags, flag)) + { + field = GetObject(input); + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Duration = GetObject(bytes, ref position); + GetObject(bytes, ref position, ref _title, _flags, (int) DocumentAttributeAudioFlags.Title); + GetObject(bytes, ref position, ref _performer, _flags, (int) DocumentAttributeAudioFlags.Performer); + GetObject(bytes, ref position, ref _waveform, _flags, (int) DocumentAttributeAudioFlags.Waveform); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Duration.ToBytes(), + ToBytes(Title, Flags, (int) DocumentAttributeAudioFlags.Title), + ToBytes(Performer, Flags, (int) DocumentAttributeAudioFlags.Performer), + ToBytes(Waveform, Flags, (int) DocumentAttributeAudioFlags.Waveform)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Duration = GetObject(input); + GetObject(input, ref _title, _flags, (int) DocumentAttributeAudioFlags.Title); + GetObject(input, ref _performer, _flags, (int) DocumentAttributeAudioFlags.Performer); + GetObject(input, ref _waveform, _flags, (int) DocumentAttributeAudioFlags.Waveform); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Duration.ToStream(output); + ToStream(output, Title, Flags, (int) DocumentAttributeAudioFlags.Title); + ToStream(output, Performer, Flags, (int) DocumentAttributeAudioFlags.Performer); + ToStream(output, Waveform, Flags, (int) DocumentAttributeAudioFlags.Waveform); + } + } + + public class TLDocumentAttributeFileName : TLDocumentAttributeBase + { + public const uint Signature = TLConstructors.TLDocumentAttributeFileName; + + public TLString FileName { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + FileName = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + FileName.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + FileName = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + FileName.ToStream(output); + } + } + + public class TLDocumentAttributeHasStickers : TLDocumentAttributeBase + { + public const uint Signature = TLConstructors.TLDocumentAttributeHasStickers; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLDouble.cs b/Telegram.Api/TL/TLDouble.cs new file mode 100755 index 0000000..15d8473 --- /dev/null +++ b/Telegram.Api/TL/TLDouble.cs @@ -0,0 +1,60 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.IO; +using System.Runtime.Serialization; + +namespace Telegram.Api.TL +{ + [DataContract] + public class TLDouble : TLObject + { + public TLDouble() { } + + public TLDouble(double value) + { + Value = value; + } + + [DataMember] + public Double Value { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + Value = BitConverter.ToDouble(bytes, position); + position += 8; + + return this; + } + + public override byte[] ToBytes() + { + return BitConverter.GetBytes(Value); + } + + public override TLObject FromStream(Stream input) + { + var buffer = new byte[8]; + input.Read(buffer, 0, 8); + Value = BitConverter.ToDouble(buffer, 0); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(BitConverter.GetBytes(Value), 0, 8); + } + + public override string ToString() + { + return Value.ToString(CultureInfo.InvariantCulture); + } + } +} diff --git a/Telegram.Api/TL/TLDraftMessage.cs b/Telegram.Api/TL/TLDraftMessage.cs new file mode 100755 index 0000000..372dc56 --- /dev/null +++ b/Telegram.Api/TL/TLDraftMessage.cs @@ -0,0 +1,272 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; +using Telegram.Api.TL.Functions.Messages; + +namespace Telegram.Api.TL +{ + [Flags] + public enum DraftMessageEmptyFlags + { + Date = 0x1 // 0 + } + + public abstract class TLDraftMessageBase : TLObject + { + public abstract bool DraftEquals(TLDraftMessageBase draft); + + public abstract bool IsEmpty(); + + public abstract TLSaveDraft ToSaveDraftObject(TLInputPeerBase peer); + } + + public class TLDraftMessageEmpty82 : TLDraftMessageEmpty + { + public new const uint Signature = TLConstructors.TLDraftMessageEmpty82; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + protected TLInt _date; + + public TLInt Date + { + get { return _date; } + set { SetField(out _date, value, ref _flags, (int) DraftMessageEmptyFlags.Date); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Date = GetObject(_flags, (int) DraftMessageEmptyFlags.Date, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Date = GetObject(_flags, (int)DraftMessageEmptyFlags.Date, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, Date, _flags, (int)DraftMessageEmptyFlags.Date); + } + + public override bool DraftEquals(TLDraftMessageBase draft) + { + var emptyDraft = draft as TLDraftMessageEmpty; + return draft == null || emptyDraft != null; + } + + public override TLSaveDraft ToSaveDraftObject(TLInputPeerBase peer) + { + return new TLSaveDraft + { + Flags = new TLInt(0), + Peer = peer, + Message = TLString.Empty + }; + } + + public override string ToString() + { + return "TLDraftMessageEmpty82"; + } + } + + public class TLDraftMessageEmpty : TLDraftMessageBase + { + public const uint Signature = TLConstructors.TLDraftMessageEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override bool DraftEquals(TLDraftMessageBase draft) + { + return draft == null || draft is TLDraftMessageEmpty; + } + + public override bool IsEmpty() + { + return true; + } + + public override TLSaveDraft ToSaveDraftObject(TLInputPeerBase peer) + { + return new TLSaveDraft + { + Flags = new TLInt(0), + Peer = peer, + Message = TLString.Empty + }; + } + + public override string ToString() + { + return "TLDraftMessageEmpty"; + } + } + + public class TLDraftMessage : TLDraftMessageBase + { + public const uint Signature = TLConstructors.TLDraftMessage; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool NoWebpage + { + get { return IsSet(Flags, (int) SendFlags.NoWebpage); } + set { SetUnset(ref _flags, value, (int) SendFlags.NoWebpage); } + } + + private TLInt _replyToMsgId; + + public TLInt ReplyToMsgId + { + get { return _replyToMsgId; } + set { SetField(out _replyToMsgId, value, ref _flags, (int) SendFlags.ReplyToMsgId); } + } + + public TLString Message { get; set; } + + private TLVector _entities; + + public TLVector Entities + { + get { return _entities; } + set { SetField(out _entities, value, ref _flags, (int) SendFlags.Entities); } + } + + public TLInt Date { get; set; } + + public override TLSaveDraft ToSaveDraftObject(TLInputPeerBase peer) + { + var obj = new TLSaveDraft + { + Flags = new TLInt(0), + ReplyToMsgId = ReplyToMsgId, + Peer = peer, + Message = Message, + Entities = Entities, + }; + + if (NoWebpage) + { + obj.DisableWebPagePreview(); + } + + return obj; + } + + public override bool DraftEquals(TLDraftMessageBase draftBase) + { + var draftEmpty = draftBase as TLDraftMessageEmpty; + if (draftEmpty != null) + { + return IsEmpty(); + } + + var draft = draftBase as TLDraftMessage; + if (draft != null) + { + if (Flags.Value != draft.Flags.Value) return false; + + if (!TLString.Equals(Message, draft.Message, StringComparison.Ordinal)) return false; + + if (ReplyToMsgId != null && draft.ReplyToMsgId != null && ReplyToMsgId.Value != draft.ReplyToMsgId.Value) return false; + + if (Entities != null && draft.Entities != null && Entities.Count != draft.Entities.Count) return false; + } + else + { + return false; + } + + return true; + } + + public override bool IsEmpty() + { + return TLString.IsNullOrEmpty(Message) && ReplyToMsgId == null; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + _replyToMsgId = GetObject(Flags, (int)SendFlags.ReplyToMsgId, null, bytes, ref position); + Message = GetObject(bytes, ref position); + _entities = GetObject>(Flags, (int)SendFlags.Entities, null, bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + _replyToMsgId = GetObject(Flags, (int)SendFlags.ReplyToMsgId, null, input); + Message = GetObject(input); + _entities = GetObject>(Flags, (int)SendFlags.Entities, null, input); + Date = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, _replyToMsgId, Flags, (int)SendFlags.ReplyToMsgId); + Message.ToStream(output); + ToStream(output, _entities, Flags, (int)SendFlags.Entities); + Date.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLDraftMessage reply_to_msg_id={0} message={1} no_webpage={2} entities={3}", ReplyToMsgId, Message, NoWebpage, Entities != null? Entities.Count : 0); + } + } +} diff --git a/Telegram.Api/TL/TLEncryptedChat.cs b/Telegram.Api/TL/TLEncryptedChat.cs new file mode 100755 index 0000000..a1a5234 --- /dev/null +++ b/Telegram.Api/TL/TLEncryptedChat.cs @@ -0,0 +1,741 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum EncryptedChatCustomFlags + { + OriginalKey = 0x1, + ExtendedKey = 0x2, + LinkPreview = 0x4 + } + + public abstract class TLEncryptedChatBase : TLObject + { + public int Index { get { return Id.Value; } } + + public TLInt Id { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + Id = GetObject(bytes, ref position); + + return this; + } + + #region Additional + + protected TLString _key; + + public TLString Key + { + get { return _key; } + set + { + if (_key == null && value != null) + { + if (OriginalKey == null) + { + OriginalKey = value; + } + + if (ExtendedKey == null) + { + var chat17 = this as TLEncryptedChat17; + if (chat17 != null && chat17.Layer != null + && chat17.Layer.Value >= Constants.MinSecretChatWithExtendedKeyVisualizationLayer) + { + ExtendedKey = value; + } + } + } + + _key = value; + } + } + + public TLLong KeyFingerprint { get; set; } + + public TLString P { get; set; } + + public TLInt G { get; set; } + + public TLString A { get; set; } + + public TLInt MessageTTL { get; set; } + + protected TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + protected TLString _originalKey; + + public TLString OriginalKey + { + get { return _originalKey; } + set + { + if (value != null) + { + Set(ref _customFlags, (int)EncryptedChatCustomFlags.OriginalKey); + _originalKey = value; + } + else + { + Unset(ref _customFlags, (int)EncryptedChatCustomFlags.OriginalKey); + _originalKey = null; + } + } + } + + protected TLString _extendedKey; + + public TLString ExtendedKey + { + get { return _extendedKey; } + set + { + if (value != null) + { + Set(ref _customFlags, (int)EncryptedChatCustomFlags.ExtendedKey); + _extendedKey = value; + } + else + { + Unset(ref _customFlags, (int)EncryptedChatCustomFlags.ExtendedKey); + _extendedKey = null; + } + } + } + #endregion + + public virtual void Update(TLEncryptedChatBase chat) + { + Id = chat.Id; + if (chat.Key != null) _key = chat._key; + if (chat.KeyFingerprint != null) KeyFingerprint = chat.KeyFingerprint; + if (chat.P != null) P = chat.P; + if (chat.G != null) G = chat.G; + if (chat.A != null) A = chat.A; + + if (chat.CustomFlags != null) CustomFlags = chat.CustomFlags; + if (chat.OriginalKey != null) OriginalKey = chat.OriginalKey; + if (chat.ExtendedKey != null) ExtendedKey = chat.ExtendedKey; + } + } + + public class TLEncryptedChatEmpty : TLEncryptedChatBase + { + public const uint Signature = TLConstructors.TLEncryptedChatEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + base.FromBytes(bytes, ref position); + + return this; + } + + public override void Update(TLEncryptedChatBase chat) + { + base.Update(chat); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + _key = GetNullableObject(input); + KeyFingerprint = GetNullableObject(input); + P = GetNullableObject(input); + G = GetNullableObject(input); + A = GetNullableObject(input); + MessageTTL = GetNullableObject(input); + + CustomFlags = GetNullableObject(input); + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey)) + { + OriginalKey = GetObject(input); + } + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey)) + { + ExtendedKey = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + + Key.NullableToStream(output); + KeyFingerprint.NullableToStream(output); + P.NullableToStream(output); + G.NullableToStream(output); + A.NullableToStream(output); + MessageTTL.NullableToStream(output); + + CustomFlags.NullableToStream(output); + ToStream(output, OriginalKey, CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey); + ToStream(output, ExtendedKey, CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey); + } + } + + public abstract class TLEncryptedChatCommon : TLEncryptedChatBase + { + public TLLong AccessHash { get; set; } + + public TLInt Date { get; set; } + + public TLInt AdminId { get; set; } + + public TLInt ParticipantId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + base.FromBytes(bytes, ref position); + + AccessHash = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + AdminId = GetObject(bytes, ref position); + ParticipantId = GetObject(bytes, ref position); + + return this; + } + + public override void Update(TLEncryptedChatBase chat) + { + base.Update(chat); + + var chatCommon = chat as TLEncryptedChatCommon; + if (chatCommon != null) + { + AccessHash = chatCommon.AccessHash; + Date = chatCommon.Date; + AdminId = chatCommon.AdminId; + ParticipantId = chatCommon.ParticipantId; + } + } + } + + public class TLEncryptedChatWaiting : TLEncryptedChatCommon + { + public const uint Signature = TLConstructors.TLEncryptedChatWaiting; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + base.FromBytes(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + AdminId = GetObject(input); + ParticipantId = GetObject(input); + + _key = GetNullableObject(input); + KeyFingerprint = GetNullableObject(input); + P = GetNullableObject(input); + G = GetNullableObject(input); + A = GetNullableObject(input); + MessageTTL = GetNullableObject(input); + + CustomFlags = GetNullableObject(input); + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey)) + { + OriginalKey = GetObject(input); + } + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey)) + { + ExtendedKey = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Date.ToBytes()); + output.Write(AdminId.ToBytes()); + output.Write(ParticipantId.ToBytes()); + + Key.NullableToStream(output); + KeyFingerprint.NullableToStream(output); + P.NullableToStream(output); + G.NullableToStream(output); + A.NullableToStream(output); + MessageTTL.NullableToStream(output); + + CustomFlags.NullableToStream(output); + ToStream(output, OriginalKey, CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey); + ToStream(output, ExtendedKey, CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey); + } + } + + public class TLEncryptedChatRequested : TLEncryptedChatCommon + { + public const uint Signature = TLConstructors.TLEncryptedChatRequested; + + public TLString GA { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + base.FromBytes(bytes, ref position); + + GA = GetObject(bytes, ref position); + + return this; + } + + public override void Update(TLEncryptedChatBase chat) + { + base.Update(chat); + + var chatRequested = chat as TLEncryptedChatRequested; + if (chatRequested != null) + { + GA = chatRequested.GA; + } + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + AdminId = GetObject(input); + ParticipantId = GetObject(input); + GA = GetObject(input); + + _key = GetNullableObject(input); + KeyFingerprint = GetNullableObject(input); + P = GetNullableObject(input); + G = GetNullableObject(input); + A = GetNullableObject(input); + MessageTTL = GetNullableObject(input); + + CustomFlags = GetNullableObject(input); + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey)) + { + OriginalKey = GetObject(input); + } + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey)) + { + ExtendedKey = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Date.ToBytes()); + output.Write(AdminId.ToBytes()); + output.Write(ParticipantId.ToBytes()); + output.Write(GA.ToBytes()); + + Key.NullableToStream(output); + KeyFingerprint.NullableToStream(output); + P.NullableToStream(output); + G.NullableToStream(output); + A.NullableToStream(output); + MessageTTL.NullableToStream(output); + + CustomFlags.NullableToStream(output); + ToStream(output, OriginalKey, CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey); + ToStream(output, ExtendedKey, CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey); + } + } + + public class TLEncryptedChat20 : TLEncryptedChat17 + { + public new const uint Signature = TLConstructors.TLEncryptedChat20; + + public TLLong PFS_ExchangeId { get; set; } + public TLString PFS_A { get; set; } + public TLString PFS_Key { get; set; } + + public TLLong PFS_KeyFingerprint { get; set; } + + public override void Update(TLEncryptedChatBase chat) + { + base.Update(chat); + + var encryptedChat = chat as TLEncryptedChat20; + if (encryptedChat != null) + { + PFS_ExchangeId = encryptedChat.PFS_ExchangeId; + PFS_A = encryptedChat.PFS_A; + PFS_Key = encryptedChat.PFS_Key; + PFS_KeyFingerprint = encryptedChat.PFS_KeyFingerprint; + } + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + AdminId = GetObject(input); + ParticipantId = GetObject(input); + GAorB = GetObject(input); + + _key = GetNullableObject(input); + KeyFingerprint = GetNullableObject(input); + P = GetNullableObject(input); + G = GetNullableObject(input); + A = GetNullableObject(input); + MessageTTL = GetNullableObject(input); + + CustomFlags = GetNullableObject(input); + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey)) + { + OriginalKey = GetObject(input); + } + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey)) + { + ExtendedKey = GetObject(input); + } + + RawInSeqNo = GetNullableObject(input); + RawOutSeqNo = GetNullableObject(input); + Layer = GetNullableObject(input); + + PFS_ExchangeId = GetNullableObject(input); + PFS_A = GetNullableObject(input); + PFS_Key = GetNullableObject(input); + PFS_KeyFingerprint = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Date.ToBytes()); + output.Write(AdminId.ToBytes()); + output.Write(ParticipantId.ToBytes()); + output.Write(GAorB.ToBytes()); + + Key.NullableToStream(output); + KeyFingerprint.NullableToStream(output); + P.NullableToStream(output); + G.NullableToStream(output); + A.NullableToStream(output); + MessageTTL.NullableToStream(output); + + CustomFlags.NullableToStream(output); + ToStream(output, OriginalKey, CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey); + ToStream(output, ExtendedKey, CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey); + + RawInSeqNo.NullableToStream(output); + RawOutSeqNo.NullableToStream(output); + Layer.NullableToStream(output); + + PFS_ExchangeId.NullableToStream(output); + PFS_A.NullableToStream(output); + PFS_Key.NullableToStream(output); + PFS_KeyFingerprint.NullableToStream(output); + } + + public override string ToString() + { + return string.Format("EncryptedChat20={0} Hash={1}", Index, GetHashCode()); + } + } + + public class TLEncryptedChat17 : TLEncryptedChat + { + public new const uint Signature = TLConstructors.TLEncryptedChat17; + + private TLInt _rawInSeqNo; + + // from 0, increment by 1 after each received decryptedMessage/decryptedMessageService + public TLInt RawInSeqNo + { + get { return _rawInSeqNo; } + set + { + System.Diagnostics.Debug.WriteLine(" raw_in_seq_no chat={0} old={1} new={2}", Id, _rawInSeqNo, value); + _rawInSeqNo = value; + } + } + + private TLInt _rawOutSeqNo; + + // from 0, increment by 1 after each sent decryptedMessage/decryptedMessageService + public TLInt RawOutSeqNo + { + get { return _rawOutSeqNo; } + set + { + System.Diagnostics.Debug.WriteLine(" raw_out_seq_no chat={0} old={1} new={2}", Id, _rawOutSeqNo, value); + _rawOutSeqNo = value; + } + } + + private TLInt _layer; + + public TLInt Layer + { + get { return _layer; } + set + { + System.Diagnostics.Debug.WriteLine(" layer chat={0} old={1} new={2}", Id, _layer, value); + _layer = value; + } + } + + public TLBool IsConfirmed { get; set; } + + public override void Update(TLEncryptedChatBase chat) + { + base.Update(chat); + + var encryptedChat = chat as TLEncryptedChat17; + if (encryptedChat != null) + { + RawInSeqNo = encryptedChat.RawInSeqNo; + RawOutSeqNo = encryptedChat.RawOutSeqNo; + Layer = encryptedChat.Layer; + } + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + AdminId = GetObject(input); + ParticipantId = GetObject(input); + GAorB = GetObject(input); + + _key = GetNullableObject(input); + KeyFingerprint = GetNullableObject(input); + P = GetNullableObject(input); + G = GetNullableObject(input); + A = GetNullableObject(input); + MessageTTL = GetNullableObject(input); + + CustomFlags = GetNullableObject(input); + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey)) + { + OriginalKey = GetObject(input); + } + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey)) + { + ExtendedKey = GetObject(input); + } + + RawInSeqNo = GetNullableObject(input); + RawOutSeqNo = GetNullableObject(input); + Layer = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Date.ToBytes()); + output.Write(AdminId.ToBytes()); + output.Write(ParticipantId.ToBytes()); + output.Write(GAorB.ToBytes()); + + Key.NullableToStream(output); + KeyFingerprint.NullableToStream(output); + P.NullableToStream(output); + G.NullableToStream(output); + A.NullableToStream(output); + MessageTTL.NullableToStream(output); + + CustomFlags.NullableToStream(output); + ToStream(output, OriginalKey, CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey); + ToStream(output, ExtendedKey, CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey); + + RawInSeqNo.NullableToStream(output); + RawOutSeqNo.NullableToStream(output); + Layer.NullableToStream(output); + } + + public override string ToString() + { + return string.Format("EncryptedChat17={0} Hash={1}", Index, GetHashCode()); + } + } + + public class TLEncryptedChat : TLEncryptedChatCommon + { + public const uint Signature = TLConstructors.TLEncryptedChat; + + public TLString GAorB { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + base.FromBytes(bytes, ref position); + + GAorB = GetObject(bytes, ref position); + KeyFingerprint = GetObject(bytes, ref position); + + return this; + } + + public override void Update(TLEncryptedChatBase chat) + { + base.Update(chat); + + var encryptedChat = chat as TLEncryptedChat; + if (encryptedChat != null) + { + GAorB = encryptedChat.GAorB; + KeyFingerprint = encryptedChat.KeyFingerprint; + } + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + AdminId = GetObject(input); + ParticipantId = GetObject(input); + GAorB = GetObject(input); + + _key = GetNullableObject(input); + KeyFingerprint = GetNullableObject(input); + P = GetNullableObject(input); + G = GetNullableObject(input); + A = GetNullableObject(input); + MessageTTL = GetNullableObject(input); + + CustomFlags = GetNullableObject(input); + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey)) + { + OriginalKey = GetObject(input); + } + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey)) + { + ExtendedKey = GetObject(input); + } + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Date.ToBytes()); + output.Write(AdminId.ToBytes()); + output.Write(ParticipantId.ToBytes()); + output.Write(GAorB.ToBytes()); + + Key.NullableToStream(output); + KeyFingerprint.NullableToStream(output); + P.NullableToStream(output); + G.NullableToStream(output); + A.NullableToStream(output); + MessageTTL.NullableToStream(output); + + CustomFlags.NullableToStream(output); + ToStream(output, OriginalKey, CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey); + ToStream(output, ExtendedKey, CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey); + } + + public override string ToString() + { + return string.Format("EncryptedChat={0} Hash={1}", Index, GetHashCode()); + } + } + + public class TLEncryptedChatDiscarded : TLEncryptedChatBase + { + public const uint Signature = TLConstructors.TLEncryptedChatDiscarded; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + base.FromBytes(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + _key = GetNullableObject(input); + KeyFingerprint = GetNullableObject(input); + P = GetNullableObject(input); + G = GetNullableObject(input); + A = GetNullableObject(input); + MessageTTL = GetNullableObject(input); + + CustomFlags = GetNullableObject(input); + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey)) + { + OriginalKey = GetObject(input); + } + if (IsSet(CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey)) + { + ExtendedKey = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + + Key.NullableToStream(output); + KeyFingerprint.NullableToStream(output); + P.NullableToStream(output); + G.NullableToStream(output); + A.NullableToStream(output); + MessageTTL.NullableToStream(output); + + CustomFlags.NullableToStream(output); + ToStream(output, OriginalKey, CustomFlags, (int)EncryptedChatCustomFlags.OriginalKey); + ToStream(output, ExtendedKey, CustomFlags, (int)EncryptedChatCustomFlags.ExtendedKey); + } + } +} diff --git a/Telegram.Api/TL/TLEncryptedFile.cs b/Telegram.Api/TL/TLEncryptedFile.cs new file mode 100755 index 0000000..579732f --- /dev/null +++ b/Telegram.Api/TL/TLEncryptedFile.cs @@ -0,0 +1,125 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLEncryptedFileBase : TLObject { } + + public class TLEncryptedFileEmpty : TLEncryptedFileBase + { + public const uint Signature = TLConstructors.TLEncryptedFileEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLEncryptedFile : TLEncryptedFileBase + { + public const uint Signature = TLConstructors.TLEncryptedFile; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public TLInt Size { get; set; } + + public TLInt DCId { get; set; } + + public TLInt KeyFingerprint { get; set; } + + #region Additional + public TLString FileName { get; set; } + + public string FileExt + { + get + { + return FileName != null + ? Path.GetExtension(FileName.ToString()).Replace(".", string.Empty) + : null; + } + } + + public TLInt Duration { get; set; } + + public string DurationString + { + get + { + if (Duration == null) return string.Empty; + + var timeSpan = TimeSpan.FromSeconds(Duration.Value); + + if (timeSpan.Hours > 0) + { + return timeSpan.ToString(@"h\:mm\:ss"); + } + + return timeSpan.ToString(@"m\:ss"); + } + } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + DCId = GetObject(bytes, ref position); + KeyFingerprint = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Size = GetObject(input); + DCId = GetObject(input); + KeyFingerprint = GetObject(input); + + FileName = GetNullableObject(input); + Duration = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Size.ToBytes()); + output.Write(DCId.ToBytes()); + output.Write(KeyFingerprint.ToBytes()); + + FileName.NullableToStream(output); + Duration.NullableToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLEncryptedMessage.cs b/Telegram.Api/TL/TLEncryptedMessage.cs new file mode 100755 index 0000000..ef671dc --- /dev/null +++ b/Telegram.Api/TL/TLEncryptedMessage.cs @@ -0,0 +1,139 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define MTPROTO + +using System; +using System.Linq; +using Org.BouncyCastle.Security; +using Telegram.Api.Helpers; + +namespace Telegram.Api.TL +{ + public class TLEncryptedTransportMessage : TLObject + { + public TLLong AuthKeyId { get; set; } + public byte[] MsgKey { get; set; } //128 bit + public byte[] Data { get; set; } + + public TLEncryptedTransportMessage Decrypt(byte[] authKey) + { + return Decrypt(this, authKey); + } + + public static TLEncryptedTransportMessage Decrypt(TLEncryptedTransportMessage transportMessage, byte[] authKey) + { + var keyIV = TLUtils.GetDecryptKeyIV(authKey, transportMessage.MsgKey); + transportMessage.Data = Utils.AesIge(transportMessage.Data, keyIV.Item1, keyIV.Item2, false); + + //var msgKey = TLUtils.GetDecryptMsgKey(authKey, transportMessage.Data); + //if (!TLUtils.ByteArraysEqual(msgKey, transportMessage.MsgKey)) + //{ + // transportMessage.Data = null; + //} + + return transportMessage; + } + + public TLEncryptedTransportMessage Encrypt(byte[] authKey) + { + return Encrypt(this, authKey); + } + + public static TLEncryptedTransportMessage Encrypt(TLEncryptedTransportMessage transportMessage, byte[] authKey) + { +#if MTPROTO + var random = new SecureRandom(); + + var data = transportMessage.Data; + + var length = data.Length; + var padding = 16 - (length % 16); + byte[] paddingBytes = null; + if (padding < 12) + { + padding += 16; + } + if (padding >= 12 && padding <= 1024) + { + paddingBytes = new byte[padding]; + random.NextBytes(paddingBytes); + } + + var dataWithPadding = data; + if (paddingBytes != null) + { + dataWithPadding = TLUtils.Combine(data, paddingBytes); + } + + var msgKey = TLUtils.GetEncryptMsgKey(authKey, dataWithPadding); + var keyIV = TLUtils.GetEncryptKeyIV(authKey, msgKey); + var encryptedData = Utils.AesIge(dataWithPadding, keyIV.Item1, keyIV.Item2, true); + + var authKeyId = TLUtils.GenerateLongAuthKeyId(authKey); + + transportMessage.AuthKeyId = new TLLong(authKeyId); + transportMessage.MsgKey = msgKey; + transportMessage.Data = encryptedData; + + return transportMessage; +#else + var random = new SecureRandom(); + + var data = transportMessage.Data; + + var length = data.Length; + var padding = 16 - (length % 16); + byte[] paddingBytes = null; + if (padding > 0 && padding < 16) + { + paddingBytes = new byte[padding]; + random.NextBytes(paddingBytes); + } + + byte[] dataWithPadding = data; + if (paddingBytes != null) + { + dataWithPadding = TLUtils.Combine(data, paddingBytes); + } + + + var msgKey = TLUtils.GetMsgKey(data); + var keyIV = TLUtils.GetEncryptKeyIV(authKey, msgKey); + var encryptedData = Utils.AesIge(dataWithPadding, keyIV.Item1, keyIV.Item2, true); + + var authKeyId = TLUtils.GenerateLongAuthKeyId(authKey); + + transportMessage.AuthKeyId = new TLLong(authKeyId); + transportMessage.MsgKey = msgKey; + transportMessage.Data = encryptedData; + + return transportMessage; +#endif + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + var response = new TLEncryptedTransportMessage(); + response.AuthKeyId = GetObject(bytes, ref position); + response.MsgKey = bytes.SubArray(position, 16); + + position += 16; + response.Data = bytes.SubArray(position, bytes.Length - position); + position = bytes.Length; + return response; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + AuthKeyId.ToBytes(), + MsgKey, + Data); + } + } +} diff --git a/Telegram.Api/TL/TLExportedAuthorization.cs b/Telegram.Api/TL/TLExportedAuthorization.cs new file mode 100755 index 0000000..462ab74 --- /dev/null +++ b/Telegram.Api/TL/TLExportedAuthorization.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLExportedAuthorization : TLObject + { + public const uint Signature = TLConstructors.TLExportedAuthorization; + + public TLInt Id { get; set; } + + public TLString Bytes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Bytes = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLExportedMessageLink.cs b/Telegram.Api/TL/TLExportedMessageLink.cs new file mode 100755 index 0000000..add6597 --- /dev/null +++ b/Telegram.Api/TL/TLExportedMessageLink.cs @@ -0,0 +1,41 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLExportedMessageLink : TLObject + { + public const uint Signature = TLConstructors.TLExportedMessageLink; + + public TLString Link { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Link = GetObject(bytes, ref position); + + return this; + } + } + public class TLExportedMessageLink74 : TLExportedMessageLink + { + public new const uint Signature = TLConstructors.TLExportedMessageLink74; + + public TLString Html { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Link = GetObject(bytes, ref position); + Html = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLFavedStickers.cs b/Telegram.Api/TL/TLFavedStickers.cs new file mode 100755 index 0000000..35bb00b --- /dev/null +++ b/Telegram.Api/TL/TLFavedStickers.cs @@ -0,0 +1,166 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using System.Linq; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLFavedStickersBase : TLObject { } + + public class TLFavedStickersNotModified : TLFavedStickersBase + { + public const uint Signature = TLConstructors.TLFavedStickersNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLFavedStickers : TLFavedStickersBase + { + public const uint Signature = TLConstructors.TLFavedStickers; + + public virtual TLInt Hash { get; set; } + + public TLVector Packs { get; set; } + + public TLVector Documents { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + Packs = GetObject>(bytes, ref position); + Documents = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes(), + Packs.ToBytes(), + Documents.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Hash = GetObject(input); + Packs = GetObject>(input); + Documents = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Hash.ToStream(output); + Packs.ToStream(output); + Documents.ToStream(output); + } + + public void AddSticker(TLDocumentBase document) + { + Documents.Insert(0, document); + Hash = TLUtils.GetFavedStickersHash(Documents); + + var document54 = document as TLDocument54; + if (document54 != null) + { + var emoticon = document54.Emoticon; + if (!string.IsNullOrEmpty(emoticon)) + { + var added = false; + for (var i = 0; i < Packs.Count; i++) + { + if (Packs[i].Emoticon.ToString() == emoticon) + { + var item = Packs[i].Documents.FirstOrDefault(x => x.Value == document54.Index); + if (item == null) + { + Packs[i].Documents.Insert(0, document54.Id); + added = true; + break; + } + } + } + if (!added) + { + Packs.Insert(0, new TLStickerPack{ Emoticon = new TLString(emoticon), Documents = new TLVector{ document54.Id }}); + } + } + } + } + + public void RemoveSticker(TLDocumentBase document) + { + for (var i = 0; i < Documents.Count; i++) + { + if (Documents[i].Index == document.Index) + { + Documents.RemoveAt(i); + break; + } + } + + Hash = TLUtils.GetFavedStickersHash(Documents); + + var document54 = document as TLDocument54; + if (document54 != null) + { + var emoticon = document54.Emoticon; + if (!string.IsNullOrEmpty(emoticon)) + { + for (var i = 0; i < Packs.Count; i++) + { + if (Packs[i].Emoticon.ToString() == emoticon) + { + for (int j = 0; j < Packs[i].Documents.Count; j++) + { + if (Packs[i].Documents[j].Value == document54.Index) + { + Packs[i].Documents.RemoveAt(j); + break; + } + } + + if (Packs[i].Documents.Count == 0) + { + Packs.RemoveAt(i); + break; + } + } + } + } + } + } + } +} diff --git a/Telegram.Api/TL/TLFeaturedStickers.cs b/Telegram.Api/TL/TLFeaturedStickers.cs new file mode 100755 index 0000000..c527594 --- /dev/null +++ b/Telegram.Api/TL/TLFeaturedStickers.cs @@ -0,0 +1,127 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; + +namespace Telegram.Api.TL +{ + public abstract class TLFeaturedStickersBase : TLObject { } + + public class TLFeaturedStickersNotModified : TLFeaturedStickersBase + { + public const uint Signature = TLConstructors.TLFeaturedStickersNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLFeaturedStickers : TLFeaturedStickersBase, IStickers + { + public const uint Signature = TLConstructors.TLFeaturedStickers; + + public TLInt HashValue { get; set; } + + public TLVector SetsCovered { get; set; } + + public TLVector Sets + { + get + { + var sets = new TLVector(); + foreach (var setCovered in SetsCovered) + { + sets.Add(setCovered.StickerSet); + } + return sets; + } + set + { + Execute.ShowDebugMessage("TLFeaturedStickers.Sets set"); + } + } + + public TLVector Unread { get; set; } + + public TLVector Packs { get; set; } + + public TLVector Documents { get; set; } + + public TLString Hash { get; set; } + + public TLVector MessagesStickerSets { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + HashValue = GetObject(bytes, ref position); + SetsCovered = GetObject>(bytes, ref position); + Unread = GetObject>(bytes, ref position); + + Packs = new TLVector(); + Documents = new TLVector(); + MessagesStickerSets = new TLVector(); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + HashValue.ToBytes(), + SetsCovered.ToBytes(), + Unread.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + HashValue = GetObject(input); + SetsCovered = GetObject>(input); + Unread = GetObject>(input); + + Packs = GetObject>(input); + Documents = GetObject>(input); + MessagesStickerSets = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + HashValue.ToStream(output); + SetsCovered.ToStream(output); + Unread.ToStream(output); + + Packs.ToStream(output); + Documents.ToStream(output); + MessagesStickerSets.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLFile.cs b/Telegram.Api/TL/TLFile.cs new file mode 100755 index 0000000..4e74fdd --- /dev/null +++ b/Telegram.Api/TL/TLFile.cs @@ -0,0 +1,142 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLFileBase : TLObject { } + + public class TLFile : TLFileBase + { + public const uint Signature = TLConstructors.TLFile; + + public TLFileTypeBase Type { get; set; } + + public TLInt MTime { get; set; } + + public TLString Bytes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + MTime = GetObject(bytes, ref position); + Bytes = GetObject(bytes, ref position); + + return this; + } + } + + public class TLFileCdnRedirect : TLFileBase + { + public const uint Signature = TLConstructors.TLFileCdnRedirect; + + public TLInt DCId { get; set; } + + public TLString FileToken { get; set; } + + public TLString EncryptionKey { get; set; } + + public TLString EncryptionIV { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + DCId = GetObject(bytes, ref position); + FileToken = GetObject(bytes, ref position); + EncryptionKey = GetObject(bytes, ref position); + EncryptionIV = GetObject(bytes, ref position); + + return this; + } + } + + public class TLFileCdnRedirect76 : TLFileCdnRedirect + { + public new const uint Signature = TLConstructors.TLFileCdnRedirect76; + + public TLVector FileHashes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + DCId = GetObject(bytes, ref position); + FileToken = GetObject(bytes, ref position); + EncryptionKey = GetObject(bytes, ref position); + EncryptionIV = GetObject(bytes, ref position); + FileHashes = GetObject>(bytes, ref position); + + return this; + } + } + + public class TLFileCdnRedirect70 : TLFileCdnRedirect + { + public new const uint Signature = TLConstructors.TLFileCdnRedirect70; + + public TLVector CdnFileHashes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + DCId = GetObject(bytes, ref position); + FileToken = GetObject(bytes, ref position); + EncryptionKey = GetObject(bytes, ref position); + EncryptionIV = GetObject(bytes, ref position); + CdnFileHashes = GetObject>(bytes, ref position); + + return this; + } + } + + public class TLCdnFileHash : TLObject + { + public const uint Signature = TLConstructors.TLCdnFileHash; + + public TLInt Offset { get; set; } + + public TLInt Limit { get; set; } + + public TLString Bytes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Limit = GetObject(bytes, ref position); + Bytes = GetObject(bytes, ref position); + + return this; + } + } + + public class TLFileHash : TLObject + { + public const uint Signature = TLConstructors.TLFileHash; + + public TLInt Offset { get; set; } + + public TLInt Limit { get; set; } + + public TLString Bytes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Limit = GetObject(bytes, ref position); + Bytes = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLFileLocation.cs b/Telegram.Api/TL/TLFileLocation.cs new file mode 100755 index 0000000..ad70560 --- /dev/null +++ b/Telegram.Api/TL/TLFileLocation.cs @@ -0,0 +1,163 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLFileLocationBase : TLObject//, IFileData + { + public TLLong VolumeId { get; set; } + + public TLInt LocalId { get; set; } + + public TLLong Secret { get; set; } + + #region Additional + + //public string SendingFileName { get; set; } + //public byte[] Buffer { get; set; } + //public byte[] Bytes { get; set; } + #endregion + + public virtual void Update(TLFileLocationBase fileLocation) + { + if (fileLocation != null) + { + //if (Buffer == null || LocalId.Value != fileLocation.LocalId.Value) + //{ + // Buffer = fileLocation.Buffer; + //} + + VolumeId = fileLocation.VolumeId; + LocalId = fileLocation.LocalId; + Secret = fileLocation.Secret; + + } + } + } + + public class TLFileLocationUnavailable : TLFileLocationBase + { + public const uint Signature = TLConstructors.TLFileLocationUnavailable; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + VolumeId = GetObject(bytes, ref position); + LocalId = GetObject(bytes, ref position); + Secret = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + VolumeId.ToBytes(), + LocalId.ToBytes(), + Secret.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + VolumeId = GetObject(input); + LocalId = GetObject(input); + Secret = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(VolumeId.ToBytes()); + output.Write(LocalId.ToBytes()); + output.Write(Secret.ToBytes()); + } + + public override string ToString() + { + return string.Format("TLFileLocationUnavailable=[volume_id={0}, local_id={1}, secret={2}]", VolumeId.Value, LocalId.Value, Secret.Value); + } + } + + public class TLFileLocation : TLFileLocationBase + { + public const uint Signature = TLConstructors.TLFileLocation; + + public TLInt DCId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + DCId = GetObject(bytes, ref position); + VolumeId = GetObject(bytes, ref position); + LocalId = GetObject(bytes, ref position); + Secret = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + DCId.ToBytes(), + VolumeId.ToBytes(), + LocalId.ToBytes(), + Secret.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + DCId = GetObject(input); + VolumeId = GetObject(input); + LocalId = GetObject(input); + Secret = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(DCId.ToBytes()); + output.Write(VolumeId.ToBytes()); + output.Write(LocalId.ToBytes()); + output.Write(Secret.ToBytes()); + } + + public override string ToString() + { + return string.Format("TLFileLocation=[dc_id={0}, volume_id={1}, local_id={2}, secret={3}]", DCId, VolumeId.Value, LocalId.Value, Secret.Value); + } + + public override void Update(TLFileLocationBase baseFileLocation) + { + base.Update(baseFileLocation); + + var fileLocation = baseFileLocation as TLFileLocation; + if (fileLocation != null) + { + DCId = fileLocation.DCId; + } + } + + public TLInputFileLocation ToInputFileLocation() + { + return new TLInputFileLocation + { + LocalId = LocalId, + Secret = Secret, + VolumeId = VolumeId + }; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLFileType.cs b/Telegram.Api/TL/TLFileType.cs new file mode 100755 index 0000000..0ce4f5f --- /dev/null +++ b/Telegram.Api/TL/TLFileType.cs @@ -0,0 +1,128 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLFileTypeBase : TLObject { } + + public class TLFileTypeUnknown : TLFileTypeBase + { + public const uint Signature = TLConstructors.TLFileTypeUnknown; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLFileTypeUnknown--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLFileTypeJpeg : TLFileTypeBase + { + public const uint Signature = TLConstructors.TLFileTypeJpeg; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLFileTypeJpeg--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLFileTypeGif : TLFileTypeBase + { + public const uint Signature = TLConstructors.TLFileTypeGif; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLFileTypeGif--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLFileTypePng : TLFileTypeBase + { + public const uint Signature = TLConstructors.TLFileTypePng; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLFileTypePng--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLFileTypeMp3 : TLFileTypeBase + { + public const uint Signature = TLConstructors.TLFileTypeMp3; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLFileTypeMp3--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLFileTypeMov : TLFileTypeBase + { + public const uint Signature = TLConstructors.TLFileTypeMov; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLFileTypeMov--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLFileTypePartial : TLFileTypeBase + { + public const uint Signature = TLConstructors.TLFileTypePartial; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLFileTypePartial--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLFileTypeMp4 : TLFileTypeBase + { + public const uint Signature = TLConstructors.TLFileTypeMp4; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLFileTypeMp4--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLFileTypeWebp : TLFileTypeBase + { + public const uint Signature = TLConstructors.TLFileTypeWebp; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLFileTypeWebp--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLForeignLink.cs b/Telegram.Api/TL/TLForeignLink.cs new file mode 100755 index 0000000..71085f6 --- /dev/null +++ b/Telegram.Api/TL/TLForeignLink.cs @@ -0,0 +1,87 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLForeignLinkBase : TLObject { } + + public class TLForeignLinkUnknown : TLForeignLinkBase + { + public const uint Signature = TLConstructors.TLForeignLinkUnknown; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLForeignLinkRequested : TLForeignLinkBase + { + public const uint Signature = TLConstructors.TLForeignLinkRequested; + + public TLBool HasPhone { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + HasPhone = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + HasPhone = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(HasPhone.ToBytes()); + } + } + + public class TLForeignLinkMutual : TLForeignLinkBase + { + public const uint Signature = TLConstructors.TLForeignLinkMutual; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLFoundGif.cs b/Telegram.Api/TL/TLFoundGif.cs new file mode 100755 index 0000000..0bed0ea --- /dev/null +++ b/Telegram.Api/TL/TLFoundGif.cs @@ -0,0 +1,109 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLFoundGifBase : TLObject { } + + public class TLFoundGif : TLFoundGifBase + { + public const uint Signature = TLConstructors.TLFoundGif; + + public TLString Url { get; set; } + + public TLString ThumbUrl { get; set; } + + public TLString ContentUrl { get; set; } + + public TLString ContentType { get; set; } + + public TLInt W { get; set; } + + public TLInt H { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + ThumbUrl = GetObject(bytes, ref position); + ContentUrl = GetObject(bytes, ref position); + ContentType = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + ThumbUrl = GetObject(input); + ContentUrl = GetObject(input); + ContentType = GetObject(input); + W = GetObject(input); + H = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Url.ToStream(output); + ThumbUrl.ToStream(output); + ContentUrl.ToStream(output); + ContentType.ToStream(output); + W.ToStream(output); + H.ToStream(output); + } + } + + public class TLFoundGifCached : TLFoundGifBase + { + public const uint Signature = TLConstructors.TLFoundGifCached; + + public TLString Url { get; set; } + + public TLPhotoBase Photo { get; set; } + + public TLDocumentBase Document { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + Photo = GetObject(bytes, ref position); + Document = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + Photo = GetObject(input); + Document = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Url.ToStream(output); + Photo.ToStream(output); + Document.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLFoundGifs.cs b/Telegram.Api/TL/TLFoundGifs.cs new file mode 100755 index 0000000..fc5c31c --- /dev/null +++ b/Telegram.Api/TL/TLFoundGifs.cs @@ -0,0 +1,47 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLFoundGifs : TLObject + { + public const uint Signature = TLConstructors.TLFoundGifs; + + public TLInt NextOffset { get; set; } + + public TLVector Results { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + NextOffset = GetObject(bytes, ref position); + Results = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + NextOffset = GetObject(input); + Results = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + NextOffset.ToStream(output); + Results.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLFutureSalt.cs b/Telegram.Api/TL/TLFutureSalt.cs new file mode 100755 index 0000000..f246795 --- /dev/null +++ b/Telegram.Api/TL/TLFutureSalt.cs @@ -0,0 +1,65 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLFutureSalt : TLObject + { + public const uint Signature = TLConstructors.TLFutureSalt; + + public TLInt ValidSince { get; set; } + + public TLInt ValidUntil { get; set; } + + public TLLong Salt { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLFutureSalt--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ValidSince = GetObject(bytes, ref position); + ValidUntil = GetObject(bytes, ref position); + Salt = GetObject(bytes, ref position); + + TLUtils.WriteLine("ValidSince: " + TLUtils.MessageIdString(ValidSince)); + TLUtils.WriteLine("ValidUntil: " + TLUtils.MessageIdString(ValidUntil)); + TLUtils.WriteLine("Salt: " + Salt); + + return this; + } + } + + public class TLFutureSalts : TLObject + { + public const uint Signature = TLConstructors.TLFutureSalts; + + public TLLong ReqMsgId { get; set; } + + public TLInt Now { get; set; } + + public TLVector Salts { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLFutureSalts--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ReqMsgId = GetObject(bytes, ref position); + Now = GetObject(bytes, ref position); + + TLUtils.WriteLine("ReqMsgId: " + ReqMsgId); + TLUtils.WriteLine("Now: " + TLUtils.MessageIdString(Now)); + TLUtils.WriteLine("Salts:"); + + Salts = GetObject>(bytes, ref position); + + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLGame.cs b/Telegram.Api/TL/TLGame.cs new file mode 100755 index 0000000..cbd8333 --- /dev/null +++ b/Telegram.Api/TL/TLGame.cs @@ -0,0 +1,113 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public enum GameFlags + { + Document = 0x1 + } + + public class TLGame : TLObject + { + public const uint Signature = TLConstructors.TLGame; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public TLString ShortName { get; set; } + + public TLString Title { get; set; } + + public TLString Description { get; set; } + + public TLPhotoBase Photo { get; set; } + + private TLDocumentBase _document; + + public TLDocumentBase Document + { + get { return _document; } + set { SetField(out _document, value, ref _flags, (int) GameFlags.Document); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + ShortName = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + Description = GetObject(bytes, ref position); + Photo = GetObject(bytes, ref position); + Document = GetObject(Flags, (int) GameFlags.Document, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + AccessHash.ToBytes(), + ShortName.ToBytes(), + Title.ToBytes(), + Description.ToBytes(), + Photo.ToBytes(), + ToBytes(Document, Flags, (int) GameFlags.Document)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(input); + ShortName = GetObject(input); + Title = GetObject(input); + Description = GetObject(input); + + Photo = GetObject(input); + Document = GetObject(Flags, (int) GameFlags.Document, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + AccessHash.ToStream(output); + ShortName.ToStream(output); + Title.ToStream(output); + Description.ToStream(output); + Photo.ToStream(output); + ToStream(output, Document, Flags, (int) GameFlags.Document); + } + + public override string ToString() + { + return string.Format("TLGame id={0} short_name={1} title={2} description={3} photo={4} document={5}", Id, ShortName, Title, Description, Photo, Document); + } + } +} diff --git a/Telegram.Api/TL/TLGeoPoint.cs b/Telegram.Api/TL/TLGeoPoint.cs new file mode 100755 index 0000000..0fe9dbe --- /dev/null +++ b/Telegram.Api/TL/TLGeoPoint.cs @@ -0,0 +1,131 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Globalization; +using System.IO; +using System.Runtime.Serialization; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [KnownType(typeof(TLGeoPointEmpty))] + [KnownType(typeof(TLGeoPoint))] + [DataContract] + public abstract class TLGeoPointBase : TLObject { } + + [DataContract] + public class TLGeoPointEmpty : TLGeoPointBase + { + public const uint Signature = TLConstructors.TLGeoPointEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + [DataContract] + public class TLGeoPoint82 : TLGeoPoint + { + public new const uint Signature = TLConstructors.TLGeoPoint82; + + [DataMember] + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Long = GetObject(bytes, ref position); + Lat = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Long = GetObject(input); + Lat = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Long.ToBytes()); + output.Write(Lat.ToBytes()); + output.Write(AccessHash.ToBytes()); + } + + public override string ToString() + { + return string.Format("TLGeoPoint82 [lat={0} long={1} access_hash={2}]", Lat, Long, AccessHash); + } + } + + [DataContract] + public class TLGeoPoint : TLGeoPointBase + { + public const uint Signature = TLConstructors.TLGeoPoint; + + [DataMember] + public TLDouble Long { get; set; } + + [DataMember] + public TLDouble Lat { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Long = GetObject(bytes, ref position); + Lat = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Long = GetObject(input); + Lat = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Long.ToBytes()); + output.Write(Lat.ToBytes()); + } + + public string GetFileName() + { + return string.Format("staticmap{0}_{1}.jpg", Lat.Value.ToString(new CultureInfo("en-US")), Long.Value.ToString(new CultureInfo("en-US"))); + } + + public override string ToString() + { + return string.Format("TLGeoPoint[lat={0} long={1}]", Lat, Long); + } + } +} diff --git a/Telegram.Api/TL/TLGzipPacked.cs b/Telegram.Api/TL/TLGzipPacked.cs new file mode 100755 index 0000000..4e19d8c --- /dev/null +++ b/Telegram.Api/TL/TLGzipPacked.cs @@ -0,0 +1,55 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +#if SILVERLIGHT +using SharpGIS; +#else +using System.IO.Compression; +#endif +using Telegram.Api.Helpers; + +namespace Telegram.Api.TL +{ + public class TLGzipPacked : TLObject + { + public const uint Signature = TLConstructors.TLGzipPacked; + + public TLString PackedData { get; set; } + + public TLObject Data { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PackedData = GetObject(bytes, ref position); + + var decopressedData = new byte[] {}; + var compressedData = PackedData.Data; + var buffer = new byte[4096]; + +#if SILVERLIGHT + var hgs = new GZipInflateStream(new MemoryStream(compressedData)); +#else + var hgs = new GZipStream(new MemoryStream(compressedData), CompressionMode.Decompress); +#endif + + var bytesRead = hgs.Read(buffer, 0, buffer.Length); + while (bytesRead > 0) + { + decopressedData = TLUtils.Combine(decopressedData, buffer.SubArray(0, bytesRead)); + bytesRead = hgs.Read(buffer, 0, buffer.Length); + } + + bytesRead = 0; + Data = GetObject(decopressedData, ref bytesRead); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLHashtagItem.cs b/Telegram.Api/TL/TLHashtagItem.cs new file mode 100755 index 0000000..3f919ba --- /dev/null +++ b/Telegram.Api/TL/TLHashtagItem.cs @@ -0,0 +1,64 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using System.Linq; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLHashtagItem : TLObject + { + public const uint Signature = TLConstructors.TLHashtagItem; + + public TLString Hashtag { get; set; } + + public TLHashtagItem() + { + + } + + public TLHashtagItem(string hashtag) + { + Hashtag = new TLString(hashtag); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hashtag = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hashtag.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Hashtag = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Hashtag.ToBytes()); + } + + public override string ToString() + { + return Hashtag != null ? Hashtag.ToString() : string.Empty; + } + } +} diff --git a/Telegram.Api/TL/TLHighScore.cs b/Telegram.Api/TL/TLHighScore.cs new file mode 100755 index 0000000..d33aab4 --- /dev/null +++ b/Telegram.Api/TL/TLHighScore.cs @@ -0,0 +1,60 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLHighScore : TLObject + { + public const uint Signature = TLConstructors.TLHighScore; + + public TLInt Pos { get; set; } + + public TLInt UserId { get; set; } + + public TLInt Score { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Pos.ToBytes(), + UserId.ToBytes(), + Score.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Pos = GetObject(input); + UserId = GetObject(input); + Score = GetObject(input); + + return this; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Pos = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Score = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Pos.ToStream(output); + UserId.ToStream(output); + Score.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLHighScores.cs b/Telegram.Api/TL/TLHighScores.cs new file mode 100755 index 0000000..5c4cb94 --- /dev/null +++ b/Telegram.Api/TL/TLHighScores.cs @@ -0,0 +1,54 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLHighScores : TLObject + { + public const uint Signature = TLConstructors.TLHighScores; + + public TLVector HighScores { get; set; } + + public TLVector Users { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + HighScores.ToBytes(), + Users.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + HighScores = GetObject>(input); + Users = GetObject>(input); + + return this; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + HighScores = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + HighScores.ToStream(output); + Users.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLImportedContact.cs b/Telegram.Api/TL/TLImportedContact.cs new file mode 100755 index 0000000..6ddfcaf --- /dev/null +++ b/Telegram.Api/TL/TLImportedContact.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLImportedContact : TLObject + { + public const uint Signature = TLConstructors.TLImportedContact; + + public TLInt UserId { get; set; } + + public TLLong ClientId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + ClientId = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLImportedContacts.cs b/Telegram.Api/TL/TLImportedContacts.cs new file mode 100755 index 0000000..90c237d --- /dev/null +++ b/Telegram.Api/TL/TLImportedContacts.cs @@ -0,0 +1,76 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLImportedContacts : TLObject + { + public const uint Signature = TLConstructors.TLImportedContacts; + + public TLVector Imported { get; set; } + + public TLVector RetryContacts { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Imported = GetObject>(bytes, ref position); + RetryContacts = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public virtual TLImportedContacts GetEmptyObject() + { + return new TLImportedContacts + { + Imported = new TLVector(Imported.Count), + RetryContacts = new TLVector(RetryContacts.Count), + Users = new TLVector(Users.Count) + }; + } + } + + public class TLImportedContacts69 : TLImportedContacts + { + public new const uint Signature = TLConstructors.TLImportedContacts69; + + public TLVector PopularInvites { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Imported = GetObject>(bytes, ref position); + PopularInvites = GetObject>(bytes, ref position); + RetryContacts = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLImportedContacts GetEmptyObject() + { + return new TLImportedContacts69 + { + Imported = new TLVector(Imported.Count), + PopularInvites = new TLVector(PopularInvites.Count), + RetryContacts = new TLVector(RetryContacts.Count), + Users = new TLVector(Users.Count) + }; + } + + public override string ToString() + { + return string.Format("TLImportedContacts imported={0} popular_invites={1} retry_contacts={2} users={3}", Imported.Count, PopularInvites.Count, RetryContacts.Count, Users.Count); + } + } +} diff --git a/Telegram.Api/TL/TLInitConnection.cs b/Telegram.Api/TL/TLInitConnection.cs new file mode 100755 index 0000000..3329634 --- /dev/null +++ b/Telegram.Api/TL/TLInitConnection.cs @@ -0,0 +1,196 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public enum InitConnectionFlags + { + Proxy = 0x1 + } + + public class TLInitConnection : TLObject + { + public const uint Signature = 0x69796de9; + + public TLInt AppId { get; set; } + + public TLString DeviceModel { get; set; } + + public TLString SystemVersion { get; set; } + + public TLString AppVersion { get; set; } + + public TLString LangCode { get; set; } + + public TLObject Data { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + AppId.ToBytes(), + DeviceModel.ToBytes(), + SystemVersion.ToBytes(), + AppVersion.ToBytes(), + LangCode.ToBytes(), + Data.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + AppId.ToStream(output); + DeviceModel.ToStream(output); + SystemVersion.ToStream(output); + AppVersion.ToStream(output); + LangCode.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + AppId = GetObject(input); + DeviceModel = GetObject(input); + SystemVersion = GetObject(input); + AppVersion = GetObject(input); + LangCode = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("app_id={0} device_model={1} system_version={2} app_version={3} lang_code={4}", AppId, DeviceModel, SystemVersion, AppVersion, LangCode); + } + } + + public class TLInitConnection67 : TLInitConnection + { + public new const uint Signature = 0xc7481da6; + + public TLString SystemLangCode { get; set; } + + public TLString LangPack { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + AppId.ToBytes(), + DeviceModel.ToBytes(), + SystemVersion.ToBytes(), + AppVersion.ToBytes(), + SystemLangCode.ToBytes(), + LangPack.ToBytes(), + LangCode.ToBytes(), + Data.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + AppId.ToStream(output); + DeviceModel.ToStream(output); + SystemVersion.ToStream(output); + AppVersion.ToStream(output); + SystemLangCode.ToStream(output); + LangPack.ToStream(output); + LangCode.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + AppId = GetObject(input); + DeviceModel = GetObject(input); + SystemVersion = GetObject(input); + AppVersion = GetObject(input); + SystemLangCode = GetObject(input); + LangPack = GetObject(input); + LangCode = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("app_id={0} device_model={1} system_version={2} app_version={3} system_lang_code={4} lang_pack={5} lang_code={6}", AppId, DeviceModel, SystemVersion, AppVersion, SystemLangCode, LangPack, LangCode); + } + } + + public class TLInitConnection78 : TLInitConnection67 + { + public new const uint Signature = 0x785188b8; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + protected TLInputClientProxy _proxy; + + public TLInputClientProxy Proxy + { + get { return _proxy; } + set { SetField(out _proxy, value, ref _flags, (int)InitConnectionFlags.Proxy); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + AppId.ToBytes(), + DeviceModel.ToBytes(), + SystemVersion.ToBytes(), + AppVersion.ToBytes(), + SystemLangCode.ToBytes(), + LangPack.ToBytes(), + LangCode.ToBytes(), + ToBytes(_proxy, _flags, (int)InitConnectionFlags.Proxy), + Data.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + AppId.ToStream(output); + DeviceModel.ToStream(output); + SystemVersion.ToStream(output); + AppVersion.ToStream(output); + SystemLangCode.ToStream(output); + LangPack.ToStream(output); + LangCode.ToStream(output); + ToStream(output, _proxy, _flags, (int)InitConnectionFlags.Proxy); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + AppId = GetObject(input); + DeviceModel = GetObject(input); + SystemVersion = GetObject(input); + AppVersion = GetObject(input); + SystemLangCode = GetObject(input); + LangPack = GetObject(input); + LangCode = GetObject(input); + _proxy = GetObject(_flags, (int)InitConnectionFlags.Proxy, null, input); + + return this; + } + + public override string ToString() + { + return string.Format("app_id={0} device_model={1} system_version={2} app_version={3} system_lang_code={4} lang_pack={5} lang_code={6} proxy=[{7}]", AppId, DeviceModel, SystemVersion, AppVersion, SystemLangCode, LangPack, LangCode, Proxy); + } + } +} diff --git a/Telegram.Api/TL/TLInlineBotSwitchPM.cs b/Telegram.Api/TL/TLInlineBotSwitchPM.cs new file mode 100755 index 0000000..08370b8 --- /dev/null +++ b/Telegram.Api/TL/TLInlineBotSwitchPM.cs @@ -0,0 +1,54 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLInlineBotSwitchPM : TLObject + { + public const uint Signature = TLConstructors.TLInlineBotSwitchPM; + + public TLString Text { get; set; } + + public TLString StartParam { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + StartParam = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes(), + StartParam.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + StartParam = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Text.ToStream(output); + StartParam.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLInputAudio.cs b/Telegram.Api/TL/TLInputAudio.cs new file mode 100755 index 0000000..95f06c7 --- /dev/null +++ b/Telegram.Api/TL/TLInputAudio.cs @@ -0,0 +1,38 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLInputAudioBase : TLObject { } + + public class TLInputAudioEmpty : TLInputAudioBase + { + public const uint Signature = TLConstructors.TLInputAudioEmpty; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputAudio : TLInputAudioBase + { + public const uint Signature = TLConstructors.TLInputAudio; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLInputBotInlineMessage.cs b/Telegram.Api/TL/TLInputBotInlineMessage.cs new file mode 100755 index 0000000..3e36f54 --- /dev/null +++ b/Telegram.Api/TL/TLInputBotInlineMessage.cs @@ -0,0 +1,462 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum InputBotInlineMessageFlags + { + NoWebpage = 0x1, // 0 + Entities = 0x2, // 1 + ReplyMarkup = 0x4, // 2 + } + + public abstract class TLInputBotInlineMessageBase : TLObject + { + public TLReplyKeyboardBase ReplyMarkup { get; set; } + } + + public class TLInputBotInlineMessageMediaAuto75 : TLInputBotInlineMessageMediaAuto51 + { + public new const uint Signature = TLConstructors.TLInputBotInlineMessageMediaAuto75; + + protected TLVector _entities; + + public TLVector Entities + { + get { return _entities; } + set { SetField(out _entities, value, ref _flags, (int)InputBotInlineMessageFlags.Entities); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Caption.ToBytes(), + ToBytes(Entities, Flags, (int)InputBotInlineMessageFlags.Entities), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Caption = TLString.Empty; + Entities = GetObject>(Flags, (int)InputBotInlineMessageFlags.Entities, null, input); + ReplyMarkup = GetObject(Flags, (int)InputBotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Caption.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLInputBotInlineMessageMediaAuto51 : TLInputBotInlineMessageMediaAuto + { + public new const uint Signature = TLConstructors.TLInputBotInlineMessageMediaAuto51; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Caption.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Caption = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)InputBotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Caption.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLInputBotInlineMessageMediaAuto : TLInputBotInlineMessageBase + { + public const uint Signature = TLConstructors.TLInputBotInlineMessageMediaAuto; + + public TLString Caption { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Caption = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Caption.ToStream(output); + } + } + + public class TLInputBotInlineMessageText51 : TLInputBotInlineMessageText + { + public new const uint Signature = TLConstructors.TLInputBotInlineMessageText51; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(NoWebpage, Flags, (int)InputBotInlineMessageFlags.NoWebpage), + Message.ToBytes(), + ToBytes(Entities, Flags, (int)InputBotInlineMessageFlags.Entities), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + NoWebpage = GetObject(Flags, (int)InputBotInlineMessageFlags.NoWebpage, null, input); + Message = GetObject(input); + Entities = GetObject>(Flags, (int)InputBotInlineMessageFlags.Entities, null, input); + ReplyMarkup = GetObject(Flags, (int)InputBotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, NoWebpage, Flags, (int)InputBotInlineMessageFlags.NoWebpage); + Message.ToStream(output); + ToStream(output, Entities, Flags, (int)InputBotInlineMessageFlags.Entities); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLInputBotInlineMessageText : TLInputBotInlineMessageBase + { + public const uint Signature = TLConstructors.TLInputBotInlineMessageText; + + public TLInt Flags { get; set; } + + public TLBool NoWebpage { get; set; } + + public TLString Message { get; set; } + + public TLVector Entities { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(NoWebpage, Flags, (int)InputBotInlineMessageFlags.NoWebpage), + Message.ToBytes(), + ToBytes(Entities, Flags, (int)InputBotInlineMessageFlags.Entities)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + NoWebpage = GetObject(Flags, (int)InputBotInlineMessageFlags.NoWebpage, null, input); + Message = GetObject(input); + Entities = GetObject>(Flags, (int)InputBotInlineMessageFlags.Entities, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, NoWebpage, Flags, (int)InputBotInlineMessageFlags.NoWebpage); + Message.ToStream(output); + ToStream(output, Entities, Flags, (int)InputBotInlineMessageFlags.Entities); + } + } + + public class TLInputBotInlineMessageMediaGeo : TLInputBotInlineMessageBase + { + public const uint Signature = TLConstructors.TLInputBotInlineMessageMediaGeo; + + public TLInt Flags { get; set; } + + public TLGeoPointBase GeoPoint { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + GeoPoint.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + GeoPoint = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)InputBotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + GeoPoint.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLInputBotInlineMessageMediaVenue78 : TLInputBotInlineMessageMediaVenue + { + public new const uint Signature = TLConstructors.TLInputBotInlineMessageMediaVenue78; + + public TLString VenueType { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + GeoPoint.ToBytes(), + Title.ToBytes(), + Address.ToBytes(), + Provider.ToBytes(), + VenueId.ToBytes(), + VenueType.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + GeoPoint = GetObject(input); + Title = GetObject(input); + Address = GetObject(input); + Provider = GetObject(input); + VenueId = GetObject(input); + VenueType = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)InputBotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + GeoPoint.ToStream(output); + Title.ToStream(output); + Address.ToStream(output); + Provider.ToStream(output); + VenueId.ToStream(output); + VenueType.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLInputBotInlineMessageMediaVenue : TLInputBotInlineMessageMediaGeo + { + public new const uint Signature = TLConstructors.TLInputBotInlineMessageMediaVenue; + + public TLString Title { get; set; } + + public TLString Address { get; set; } + + public TLString Provider { get; set; } + + public TLString VenueId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + GeoPoint.ToBytes(), + Title.ToBytes(), + Address.ToBytes(), + Provider.ToBytes(), + VenueId.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + GeoPoint = GetObject(input); + Title = GetObject(input); + Address = GetObject(input); + Provider = GetObject(input); + VenueId = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)InputBotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + GeoPoint.ToStream(output); + Title.ToStream(output); + Address.ToStream(output); + Provider.ToStream(output); + VenueId.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLInputBotInlineMessageMediaContact82 : TLInputBotInlineMessageMediaContact + { + public new const uint Signature = TLConstructors.TLInputBotInlineMessageMediaContact82; + + public TLString VCard { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + PhoneNumber.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + VCard.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + PhoneNumber = GetObject(input); + FirstName = GetObject(input); + LastName = GetObject(input); + VCard = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)InputBotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + PhoneNumber.ToStream(output); + FirstName.ToStream(output); + LastName.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLInputBotInlineMessageMediaContact : TLInputBotInlineMessageBase + { + public const uint Signature = TLConstructors.TLInputBotInlineMessageMediaContact; + + public TLInt Flags { get; set; } + + public TLString PhoneNumber { get; set; } + + public TLString FirstName { get; set; } + + public TLString LastName { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + PhoneNumber.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + PhoneNumber = GetObject(input); + FirstName = GetObject(input); + LastName = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)InputBotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + PhoneNumber.ToStream(output); + FirstName.ToStream(output); + LastName.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } + + public class TLInputBotInlineMessageGame : TLInputBotInlineMessageBase + { + public const uint Signature = TLConstructors.TLInputBotInlineMessageGame; + + public TLInt Flags { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + ReplyMarkup = GetObject(Flags, (int)InputBotInlineMessageFlags.ReplyMarkup, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, ReplyMarkup, Flags, (int)InputBotInlineMessageFlags.ReplyMarkup); + } + } +} diff --git a/Telegram.Api/TL/TLInputBotInlineMessageId.cs b/Telegram.Api/TL/TLInputBotInlineMessageId.cs new file mode 100755 index 0000000..8af73ee --- /dev/null +++ b/Telegram.Api/TL/TLInputBotInlineMessageId.cs @@ -0,0 +1,51 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLInputBotInlineMessageId : TLObject + { + public const uint Signature = TLConstructors.TLInputBotInlineMessageId; + + public TLInt DCId { get; set; } + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + DCId = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + DCId.ToStream(output); + Id.ToStream(output); + AccessHash.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + DCId = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLInputBotInlineResult.cs b/Telegram.Api/TL/TLInputBotInlineResult.cs new file mode 100755 index 0000000..db9ebfc --- /dev/null +++ b/Telegram.Api/TL/TLInputBotInlineResult.cs @@ -0,0 +1,352 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum InputBotInlineResultFlags + { + //Unread = 0x1, // 0 + Title = 0x2, // 1 + Description = 0x4, // 2 + Url = 0x8, // 3 + Thumb = 0x10, // 4 + Content = 0x20, // 5 + Size = 0x40, // 6 + Duration = 0x80, // 7 + } + + public abstract class TLInputBotInlineResultBase : TLObject { } + + public class TLInputBotInlineResult : TLInputBotInlineResultBase + { + public const uint Signature = TLConstructors.TLInputBotInlineResult; + + public TLInt Flags { get; set; } + + public TLString Id { get; set; } + + public TLString Type { get; set; } + + public TLString Title { get; set; } + + public TLString Description { get; set; } + + public TLString Url { get; set; } + + public virtual TLString ThumbUrl { get; protected set; } + + public virtual TLString ContentUrl { get; protected set; } + + public virtual TLString ContentType { get; protected set; } + + public virtual TLInt W { get; protected set; } + + public virtual TLInt H { get; protected set; } + + public virtual TLInt Duration { get; protected set; } + + public TLInputBotInlineMessageBase SendMessage { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + Type.ToBytes(), + ToBytes(Title, Flags, (int)InputBotInlineResultFlags.Title), + ToBytes(Description, Flags, (int)InputBotInlineResultFlags.Description), + ToBytes(Url, Flags, (int)InputBotInlineResultFlags.Url), + ToBytes(ThumbUrl, Flags, (int)InputBotInlineResultFlags.Thumb), + ToBytes(ContentUrl, Flags, (int)InputBotInlineResultFlags.Content), + ToBytes(ContentType, Flags, (int)InputBotInlineResultFlags.Content), + ToBytes(W, Flags, (int)InputBotInlineResultFlags.Size), + ToBytes(H, Flags, (int)InputBotInlineResultFlags.Size), + ToBytes(Duration, Flags, (int)InputBotInlineResultFlags.Duration), + SendMessage.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Type = GetObject(input); + if (IsSet(Flags, (int)InputBotInlineResultFlags.Title)) + { + Title = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Description)) + { + Description = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Url)) + { + Url = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Thumb)) + { + ThumbUrl = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Content)) + { + ContentUrl = GetObject(input); + ContentType = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Size)) + { + W = GetObject(input); + H = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Duration)) + { + Duration = GetObject(input); + } + SendMessage = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + Type.ToStream(output); + ToStream(output, Title, Flags, (int) InputBotInlineResultFlags.Title); + ToStream(output, Description, Flags, (int)InputBotInlineResultFlags.Description); + ToStream(output, Url, Flags, (int)InputBotInlineResultFlags.Url); + ToStream(output, ThumbUrl, Flags, (int)InputBotInlineResultFlags.Thumb); + ToStream(output, ContentUrl, Flags, (int)InputBotInlineResultFlags.Content); + ToStream(output, ContentType, Flags, (int)InputBotInlineResultFlags.Content); + ToStream(output, W, Flags, (int)InputBotInlineResultFlags.Size); + ToStream(output, H, Flags, (int)InputBotInlineResultFlags.Size); + ToStream(output, Duration, Flags, (int)InputBotInlineResultFlags.Duration); + SendMessage.ToStream(output); + } + } + + public class TLInputBotInlineResult76 : TLInputBotInlineResult + { + public new const uint Signature = TLConstructors.TLInputBotInlineResult76; + + public TLInputWebDocument Thumb { get; set; } + + public override TLString ThumbUrl { get { return Thumb != null ? Thumb.Url : null; } } + + public TLInputWebDocument Content { get; set; } + + public override TLString ContentUrl { get { return Content != null ? Content.Url : null; } } + + public override TLString ContentType { get { return Content != null ? Content.MimeType : null; } } + + public override TLInt W + { + get { return Content != null ? Content.W : null; } + } + + public override TLInt H + { + get { return Content != null ? Content.H : null; } + } + + public override TLInt Duration + { + get { return Content != null ? Content.Duration : null; } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + Type.ToBytes(), + ToBytes(Title, Flags, (int)InputBotInlineResultFlags.Title), + ToBytes(Description, Flags, (int)InputBotInlineResultFlags.Description), + ToBytes(Url, Flags, (int)InputBotInlineResultFlags.Url), + ToBytes(Thumb, Flags, (int)InputBotInlineResultFlags.Thumb), + ToBytes(Content, Flags, (int)InputBotInlineResultFlags.Content), + SendMessage.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Type = GetObject(input); + Title = GetObject(Flags, (int)InputBotInlineResultFlags.Title, null, input); + Description = GetObject(Flags, (int)InputBotInlineResultFlags.Description, null, input); + Url = GetObject(Flags, (int)InputBotInlineResultFlags.Url, null, input); + Thumb = GetObject(Flags, (int)InputBotInlineResultFlags.Thumb, null, input); + Content = GetObject(Flags, (int)InputBotInlineResultFlags.Content, null, input); + SendMessage = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + Type.ToStream(output); + ToStream(output, Title, Flags, (int)InputBotInlineResultFlags.Title); + ToStream(output, Description, Flags, (int)InputBotInlineResultFlags.Description); + ToStream(output, Url, Flags, (int)InputBotInlineResultFlags.Url); + ToStream(output, Thumb, Flags, (int)InputBotInlineResultFlags.Thumb); + ToStream(output, Content, Flags, (int)InputBotInlineResultFlags.Content); + SendMessage.ToStream(output); + } + } + + public class TLInputBotInlineResultPhoto : TLInputBotInlineResultBase + { + public const uint Signature = TLConstructors.TLInputBotInlineResultPhoto; + + public TLString Id { get; set; } + + public TLString Type { get; set; } + + public TLInputPhotoBase Photo { get; set; } + + public TLInputBotInlineMessageBase SendMessage { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Type.ToBytes(), + Photo.ToBytes(), + SendMessage.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Type = GetObject(input); + Photo = GetObject(input); + SendMessage = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + Type.ToStream(output); + Photo.ToStream(output); + SendMessage.ToStream(output); + } + } + + public class TLInputBotInlineResultDocument : TLInputBotInlineResultBase + { + public const uint Signature = TLConstructors.TLInputBotInlineResultDocument; + + public TLInt Flags { get; set; } + + public TLString Id { get; set; } + + public TLString Type { get; set; } + + public TLString Title { get; set; } + + public TLString Description { get; set; } + + public TLInputDocumentBase Document { get; set; } + + public TLInputBotInlineMessageBase SendMessage { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + Type.ToBytes(), + ToBytes(Title, Flags, (int)InputBotInlineResultFlags.Title), + ToBytes(Description, Flags, (int)InputBotInlineResultFlags.Description), + Document.ToBytes(), + SendMessage.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Type = GetObject(input); + if (IsSet(Flags, (int)InputBotInlineResultFlags.Title)) + { + Title = GetObject(input); + } + if (IsSet(Flags, (int)InputBotInlineResultFlags.Description)) + { + Description = GetObject(input); + } + Document = GetObject(input); + SendMessage = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + Type.ToStream(output); + ToStream(output, Title, Flags, (int)InputBotInlineResultFlags.Title); + ToStream(output, Description, Flags, (int)InputBotInlineResultFlags.Description); + Document.ToStream(output); + SendMessage.ToStream(output); + } + } + + public class TLInputBotInlineResultGame : TLInputBotInlineResultBase + { + public const uint Signature = TLConstructors.TLInputBotInlineResultGame; + + public TLString Id { get; set; } + + public TLString ShortName { get; set; } + + public TLInputBotInlineMessageBase SendMessage { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + ShortName.ToBytes(), + SendMessage.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + ShortName = GetObject(input); + SendMessage = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + ShortName.ToStream(output); + SendMessage.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLInputChatBase.cs b/Telegram.Api/TL/TLInputChatBase.cs new file mode 100755 index 0000000..baf9450 --- /dev/null +++ b/Telegram.Api/TL/TLInputChatBase.cs @@ -0,0 +1,95 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputChannelBase : TLObject { } + + public class TLInputChannelEmpty : TLInputChannelBase + { + public const uint Signature = TLConstructors.TLInputChannelEmpty; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override string ToString() + { + return "TLInputChannelEmpty"; + } + } + + public class TLInputChannel : TLInputChannelBase + { + public const uint Signature = TLConstructors.TLInputChannel; + + public TLInt ChannelId { get; set; } + + public TLLong AccessHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChannelId.ToBytes(), + AccessHash.ToBytes() + ); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + ChannelId.ToStream(output); + AccessHash.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputChannel channel_id={0} access_hash={1}", ChannelId, AccessHash); + } + } +} diff --git a/Telegram.Api/TL/TLInputChatPhoto.cs b/Telegram.Api/TL/TLInputChatPhoto.cs new file mode 100755 index 0000000..d894f49 --- /dev/null +++ b/Telegram.Api/TL/TLInputChatPhoto.cs @@ -0,0 +1,129 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLInputChatPhotoBase : TLObject { } + + public class TLInputChatPhotoEmpty : TLInputChatPhotoBase + { + public const uint Signature = TLConstructors.TLInputChatPhotoEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLInputChatUploadedPhoto56 : TLInputChatPhotoBase + { + public const uint Signature = TLConstructors.TLInputChatUploadedPhoto56; + + public TLInputFile File { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + File = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes()); + } + } + + public class TLInputChatUploadedPhoto : TLInputChatPhotoBase + { + public const uint Signature = TLConstructors.TLInputChatUploadedPhoto; + + public TLInputFile File { get; set; } + + public TLInputPhotoCropBase Crop { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + File = GetObject(bytes, ref position); + Crop = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + Crop.ToBytes()); + } + } + + public class TLInputChatPhoto56 : TLInputChatPhotoBase + { + public const uint Signature = TLConstructors.TLInputChatPhoto; + + public TLInputPhotoBase Id { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } + + public class TLInputChatPhoto : TLInputChatPhotoBase + { + public const uint Signature = TLConstructors.TLInputChatPhoto; + + public TLInputPhotoBase Id { get; set; } + + public TLInputPhotoCropBase Crop { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Crop = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Crop.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLInputContact.cs b/Telegram.Api/TL/TLInputContact.cs new file mode 100755 index 0000000..18ba671 --- /dev/null +++ b/Telegram.Api/TL/TLInputContact.cs @@ -0,0 +1,39 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLInputContactBase : TLObject { } + + public class TLInputContact : TLInputContactBase + { + public const uint Signature = TLConstructors.TLInputContact; + + public TLLong ClientId { get; set; } + + public TLString Phone { get; set; } + + public TLString FirstName { get; set; } + + public TLString LastName { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ClientId.ToBytes(), + Phone.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes()); + } + + public override string ToString() + { + return string.Format("{0} {1}, {2}, {3}", FirstName, LastName, ClientId, Phone); + } + } +} diff --git a/Telegram.Api/TL/TLInputDocument.cs b/Telegram.Api/TL/TLInputDocument.cs new file mode 100755 index 0000000..39c25f3 --- /dev/null +++ b/Telegram.Api/TL/TLInputDocument.cs @@ -0,0 +1,75 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputDocumentBase : TLObject { } + + public class TLInputDocumentEmpty : TLInputDocumentBase + { + public const uint Signature = TLConstructors.TLInputDocumentEmpty; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override string ToString() + { + return "TLInputDocumentEmpty"; + } + } + + public class TLInputDocument : TLInputDocumentBase + { + public const uint Signature = TLConstructors.TLInputDocument; + + public TLLong Id { get; set; } + public TLLong AccessHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + AccessHash.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLInputDocument id={0}", Id); + } + } +} diff --git a/Telegram.Api/TL/TLInputEncryptedChat.cs b/Telegram.Api/TL/TLInputEncryptedChat.cs new file mode 100755 index 0000000..95e894c --- /dev/null +++ b/Telegram.Api/TL/TLInputEncryptedChat.cs @@ -0,0 +1,56 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLInputEncryptedChat : TLObject + { + public const uint Signature = TLConstructors.TLInputEncryptedChat; + + public TLInt ChatId { get; set; } + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes(), + AccessHash.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + ChatId.ToStream(output); + AccessHash.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLInputEncryptedFile.cs b/Telegram.Api/TL/TLInputEncryptedFile.cs new file mode 100755 index 0000000..6c49805 --- /dev/null +++ b/Telegram.Api/TL/TLInputEncryptedFile.cs @@ -0,0 +1,186 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputEncryptedFileBase : TLObject { } + + public class TLInputEncryptedFileEmpty : TLInputEncryptedFileBase + { + public const uint Signature = TLConstructors.TLInputEncryptedFileEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLInputEncryptedFileUploaded : TLInputEncryptedFileBase + { + public const uint Signature = TLConstructors.TLInputEncryptedFileUploaded; + + public TLLong Id { get; set; } + + public TLInt Parts { get; set; } + + public TLString MD5Checksum { get; set; } + + public TLInt KeyFingerprint { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Parts = GetObject(bytes, ref position); + MD5Checksum = GetObject(bytes, ref position); + KeyFingerprint = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Parts.ToBytes(), + MD5Checksum.ToBytes(), + KeyFingerprint.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Parts = GetObject(input); + MD5Checksum = GetObject(input); + KeyFingerprint = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(Parts.ToBytes()); + output.Write(MD5Checksum.ToBytes()); + output.Write(KeyFingerprint.ToBytes()); + } + } + + public class TLInputEncryptedFileBigUploaded : TLInputEncryptedFileBase + { + public const uint Signature = TLConstructors.TLInputEncryptedFileBigUploaded; + + public TLLong Id { get; set; } + + public TLInt Parts { get; set; } + + public TLInt KeyFingerprint { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Parts = GetObject(bytes, ref position); + KeyFingerprint = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Parts.ToBytes(), + KeyFingerprint.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Parts = GetObject(input); + KeyFingerprint = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(Parts.ToBytes()); + output.Write(KeyFingerprint.ToBytes()); + } + } + + public class TLInputEncryptedFile : TLInputEncryptedFileBase + { + public const uint Signature = TLConstructors.TLInputEncryptedFile; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLInputEncryptedFileBigUploaded.cs b/Telegram.Api/TL/TLInputEncryptedFileBigUploaded.cs new file mode 100755 index 0000000..82acf4d --- /dev/null +++ b/Telegram.Api/TL/TLInputEncryptedFileBigUploaded.cs @@ -0,0 +1,10 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ +} diff --git a/Telegram.Api/TL/TLInputEncryptedFileLocation.cs b/Telegram.Api/TL/TLInputEncryptedFileLocation.cs new file mode 100755 index 0000000..2b184a9 --- /dev/null +++ b/Telegram.Api/TL/TLInputEncryptedFileLocation.cs @@ -0,0 +1,11 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + +} diff --git a/Telegram.Api/TL/TLInputFile.cs b/Telegram.Api/TL/TLInputFile.cs new file mode 100755 index 0000000..759dc70 --- /dev/null +++ b/Telegram.Api/TL/TLInputFile.cs @@ -0,0 +1,96 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputFileBase : TLObject { } + + public class TLInputFile : TLInputFileBase + { + public const uint Signature = TLConstructors.TLInputFile; + + public TLLong Id { get; set; } + public TLInt Parts { get; set; } + public TLString Name { get; set; } + public TLString MD5Checksum { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Parts = GetObject(bytes, ref position); + Name = GetObject(bytes, ref position); + MD5Checksum = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Parts.ToBytes(), + Name.ToBytes(), + MD5Checksum.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Parts = GetObject(input); + Name = GetObject(input); + MD5Checksum = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + Parts.ToStream(output); + Name.ToStream(output); + MD5Checksum.ToStream(output); + } + } + + public class TLInputFileBig : TLInputFileBase + { + public const uint Signature = TLConstructors.TLInputFileBig; + + public TLLong Id { get; set; } + + public TLInt Parts { get; set; } + + public TLString Name { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Parts = GetObject(bytes, ref position); + Name = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Parts.ToBytes(), + Name.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLInputFileBig.cs b/Telegram.Api/TL/TLInputFileBig.cs new file mode 100755 index 0000000..2b184a9 --- /dev/null +++ b/Telegram.Api/TL/TLInputFileBig.cs @@ -0,0 +1,11 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + +} diff --git a/Telegram.Api/TL/TLInputFileLocation.cs b/Telegram.Api/TL/TLInputFileLocation.cs new file mode 100755 index 0000000..15a9a37 --- /dev/null +++ b/Telegram.Api/TL/TLInputFileLocation.cs @@ -0,0 +1,502 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + public abstract class TLInputFileLocationBase : TLObject + { + public abstract bool LocationEquals(TLInputFileLocationBase location); + + public abstract string GetPartFileName(int partNumbert, string prefix = "file"); + + public abstract string GetFileName(string prefix = "file", string ext = ".dat"); + + public abstract string GetLocationString(); + } + + public class TLInputFileLocation : TLInputFileLocationBase + { + public const uint Signature = TLConstructors.TLInputFileLocation; + + public TLLong VolumeId { get; set; } + + public TLInt LocalId { get; set; } + + public TLLong Secret { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + VolumeId.ToBytes(), + LocalId.ToBytes(), + Secret.ToBytes()); + } + + public override bool LocationEquals(TLInputFileLocationBase location) + { + if (location == null) return false; + + var fileLocation = location as TLInputFileLocation; + if (fileLocation == null) return false; + + return + VolumeId.Value == fileLocation.VolumeId.Value + && LocalId.Value == fileLocation.LocalId.Value + && Secret.Value == fileLocation.Secret.Value; + } + + public override string GetPartFileName(int partNumbert, string prefix = "file") + { + return string.Format(prefix + "{0}_{1}_{2}_{3}.dat", VolumeId.Value, LocalId.Value, Secret.Value, partNumbert); + } + + public override string GetFileName(string prefix = "file", string ext = ".dat") + { + return string.Format(prefix + "{0}_{1}_{2}{3}", VolumeId.Value, LocalId.Value, Secret.Value, ext); + } + + public override string GetLocationString() + { + return string.Format("volume_id={0} local_id={1}", VolumeId, LocalId); + } + } + + [Obsolete] + public class TLInputVideoFileLocation : TLInputFileLocationBase + { + public const uint Signature = TLConstructors.TLInputVideoFileLocation; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + + public override bool LocationEquals(TLInputFileLocationBase location) + { + if (location == null) return false; + + var fileLocation = location as TLInputVideoFileLocation; + if (fileLocation == null) return false; + + return + Id.Value == fileLocation.Id.Value + && AccessHash.Value == fileLocation.AccessHash.Value; + } + + public override string GetPartFileName(int partNumbert, string prefix = "video") + { + return string.Format(prefix + "{0}_{1}_{2}.dat", Id.Value, AccessHash.Value, partNumbert); + } + + public override string GetFileName(string prefix = "video", string ext = ".dat") + { + return string.Format(prefix + "{0}_{1}{2}", Id.Value, AccessHash.Value, ext); + } + + public override string GetLocationString() + { + return string.Format("id={0}", Id); + } + } + + [Obsolete] + public class TLInputAudioFileLocation : TLInputFileLocationBase + { + public const uint Signature = TLConstructors.TLInputAudioFileLocation; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + + public override bool LocationEquals(TLInputFileLocationBase location) + { + if (location == null) return false; + + var fileLocation = location as TLInputAudioFileLocation; + if (fileLocation == null) return false; + + return + Id.Value == fileLocation.Id.Value + && AccessHash.Value == fileLocation.AccessHash.Value; + } + + public override string GetPartFileName(int partNumbert, string prefix = "audio") + { + return string.Format(prefix + "{0}_{1}_{2}.dat", Id.Value, AccessHash.Value, partNumbert); + } + + public override string GetFileName(string prefix = "audio", string ext = ".dat") + { + return string.Format(prefix + "{0}_{1}{2}", Id.Value, AccessHash.Value, ext); + } + + public override string GetLocationString() + { + return string.Format("id={0}", Id); + } + } + + public class TLInputDocumentFileLocation : TLInputFileLocationBase + { + public const uint Signature = TLConstructors.TLInputDocumentFileLocation; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + + public override bool LocationEquals(TLInputFileLocationBase location) + { + if (location == null) return false; + + var fileLocation = location as TLInputDocumentFileLocation; + if (fileLocation == null) return false; + + return + Id.Value == fileLocation.Id.Value + && AccessHash.Value == fileLocation.AccessHash.Value; + } + + public override string GetPartFileName(int partNumbert, string prefix = "document") + { + return string.Format(prefix + "{0}_{1}_{2}.dat", Id.Value, AccessHash.Value, partNumbert); + } + + public override string GetFileName(string prefix = "document", string ext = ".dat") + { + return string.Format(prefix + "{0}_{1}{2}", Id.Value, AccessHash.Value, ext); + } + + public override string GetLocationString() + { + return string.Format("id={0}", Id); + } + } + + public class TLInputDocumentFileLocation54 : TLInputDocumentFileLocation + { + public new const uint Signature = TLConstructors.TLInputDocumentFileLocation54; + + public TLInt Version { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + Version.ToBytes()); + } + + public override bool LocationEquals(TLInputFileLocationBase location) + { + if (location == null) return false; + + var fileLocation = location as TLInputDocumentFileLocation; + if (fileLocation == null) return false; + + var fileLocation54 = location as TLInputDocumentFileLocation54; + if (fileLocation54 != null) + { + return + Id.Value == fileLocation54.Id.Value + && AccessHash.Value == fileLocation54.AccessHash.Value + && Version.Value == fileLocation54.Version.Value; + } + + return + Id.Value == fileLocation.Id.Value + && AccessHash.Value == fileLocation.AccessHash.Value; + } + + public override string GetPartFileName(int partNumbert, string prefix = "document") + { + if (Version.Value > 0) + { + return string.Format(prefix + "{0}_{1}_{2}.dat", Id.Value, Version.Value, partNumbert); + } + + return string.Format(prefix + "{0}_{1}_{2}.dat", Id.Value, AccessHash.Value, partNumbert); + } + + public override string GetFileName(string prefix = "document", string ext = ".dat") + { + if (Version.Value > 0) + { + return string.Format(prefix + "{0}_{1}{2}", Id.Value, Version.Value, ext); + } + + return string.Format(prefix + "{0}_{1}{2}", Id.Value, AccessHash.Value, ext); + } + + public override string GetLocationString() + { + return string.Format("id={0} version={1}", Id, Version); + } + } + + public class TLInputEncryptedFileLocation : TLInputFileLocationBase + { + public const uint Signature = TLConstructors.TLInputEncryptedFileLocation; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override bool LocationEquals(TLInputFileLocationBase location) + { + if (location == null) return false; + + var fileLocation = location as TLInputEncryptedFileLocation; + if (fileLocation == null) return false; + + return + Id.Value == fileLocation.Id.Value + && AccessHash.Value == fileLocation.AccessHash.Value; + } + + public override string GetPartFileName(int partNumbert, string prefix = "encrypted") + { + return string.Format(prefix + "{0}_{1}_{2}.dat", Id.Value, AccessHash.Value, partNumbert); + } + + public override string GetFileName(string prefix = "encrypted", string ext = ".dat") + { + return string.Format(prefix + "{0}_{1}{2}", Id.Value, AccessHash.Value, ext); + } + + public override string GetLocationString() + { + return string.Format("id={0}", Id); + } + } + + public abstract class TLInputWebFileLocationBase : TLInputFileLocationBase + { + public TLLong AccessHash { get; set; } + } + + public class TLInputWebFileGeoPointLocation : TLInputWebFileLocationBase + { + public const uint Signature = TLConstructors.TLInputWebFileGeoPointLocation; + + public TLInputGeoPointBase GeoPoint { get; set; } + + public TLInt W { get; set; } + + public TLInt H { get; set; } + + public TLInt Zoom { get; set; } + + public TLInt Scale { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + GeoPoint.ToBytes(), + AccessHash.ToBytes(), + W.ToBytes(), + H.ToBytes(), + Zoom.ToBytes(), + Scale.ToBytes()); + } + + public override string GetPartFileName(int partNumbert, string prefix = "map") + { + return string.Format(prefix + "{0}_{1}_{2}_{3}_{4}_{5}_{6}.dat", GeoPoint, AccessHash.Value, W, H, Zoom, Scale, partNumbert); + } + + public override string GetFileName(string prefix = "map", string ext = ".dat") + { + return string.Format(prefix + "{0}_{1}_{2}_{3}_{4}_{5}{6}", GeoPoint, AccessHash.Value, W, H, Zoom, Scale, ext); + } + + public override string GetLocationString() + { + return string.Format("point={0} w={1} h={2} zoom={3} scale={4}", GeoPoint, W, H, Zoom, Scale); + } + + public override bool LocationEquals(TLInputFileLocationBase locationBase) + { + if (locationBase == null) return false; + + var location = locationBase as TLInputWebFileGeoPointLocation; + if (location == null) return false; + + return + GeoPoint.GeoPointEquals(location.GeoPoint) + && AccessHash.Value == location.AccessHash.Value + && W.Value == location.W.Value + && H.Value == location.H.Value + && Zoom.Value == location.Zoom.Value + && Scale.Value == location.Scale.Value; + } + } + + public class TLInputWebFileLocation : TLInputWebFileLocationBase + { + public const uint Signature = TLConstructors.TLInputWebFileLocation; + + public TLString Url { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Url.ToBytes(), + AccessHash.ToBytes()); + } + + public override string GetPartFileName(int partNumbert, string prefix = "url") + { + return string.Format(prefix + "{0}_{1}_{2}.dat", Url.ToString().GetHashCode(), AccessHash.Value, partNumbert); + } + + public override string GetFileName(string prefix = "url", string ext = ".dat") + { + return string.Format(prefix + "{0}_{1}{2}", Url.ToString().GetHashCode(), AccessHash.Value, ext); + } + + public override string GetLocationString() + { + return string.Format("id={0}", Url.ToString().GetHashCode()); + } + + public override bool LocationEquals(TLInputFileLocationBase location) + { + if (location == null) return false; + + var fileLocation = location as TLInputWebFileLocation; + if (fileLocation == null) return false; + + return + Url.Value == fileLocation.Url.Value + && AccessHash.Value == fileLocation.AccessHash.Value; + } + } + + public class TLInputSecureFileLocation : TLInputFileLocationBase + { + public const uint Signature = TLConstructors.TLInputSecureFileLocation; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + + public override bool LocationEquals(TLInputFileLocationBase location) + { + if (location == null) return false; + + var fileLocation = location as TLInputSecureFileLocation; + if (fileLocation == null) return false; + + return + Id.Value == fileLocation.Id.Value + && AccessHash.Value == fileLocation.AccessHash.Value; + } + + public override string GetPartFileName(int partNumbert, string prefix = "document") + { + return string.Format(prefix + "{0}_{1}_{2}.dat", Id.Value, AccessHash.Value, partNumbert); + } + + public override string GetFileName(string prefix = "document", string ext = ".dat") + { + return string.Format(prefix + "{0}_{1}{2}", Id.Value, AccessHash.Value, ext); + } + + public override string GetLocationString() + { + return string.Format("id={0}", Id); + } + } + + public class TLInputTakeoutFileLocation : TLInputFileLocationBase + { + public const uint Signature = TLConstructors.TLInputTakeoutFileLocation; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override bool LocationEquals(TLInputFileLocationBase location) + { + var fileLocation = location as TLInputSecureFileLocation; + if (fileLocation == null) return false; + + return true; + } + + public override string GetPartFileName(int partNumbert, string prefix = "document") + { + return string.Format(prefix + "{0}.dat", partNumbert); + } + + public override string GetFileName(string prefix = "document", string ext = ".dat") + { + return string.Format(prefix + "{2}", ext); + } + + public override string GetLocationString() + { + return ""; + } + } +} diff --git a/Telegram.Api/TL/TLInputGame.cs b/Telegram.Api/TL/TLInputGame.cs new file mode 100755 index 0000000..d6ca429 --- /dev/null +++ b/Telegram.Api/TL/TLInputGame.cs @@ -0,0 +1,88 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputGameBase : TLObject { } + + public class TLInputGameId : TLInputGameBase + { + public const uint Signature = TLConstructors.TLInputGameId; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + AccessHash.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLInputGameId id={0} access_hash={1}", Id, AccessHash); + } + } + + public class TLInputGameShortName : TLInputGameBase + { + public const uint Signature = TLConstructors.TLInputGameShortName; + + public TLInputUserBase BotId { get; set; } + + public TLString ShortName { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + BotId.ToBytes(), + ShortName.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + BotId = GetObject(input); + ShortName = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + BotId.ToStream(output); + ShortName.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLInputGameShortName bot_id={0} short_name={1}", BotId, ShortName); + } + } +} diff --git a/Telegram.Api/TL/TLInputGeoPoint.cs b/Telegram.Api/TL/TLInputGeoPoint.cs new file mode 100755 index 0000000..93d76e8 --- /dev/null +++ b/Telegram.Api/TL/TLInputGeoPoint.cs @@ -0,0 +1,108 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Globalization; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputGeoPointBase : TLObject + { + public abstract bool GeoPointEquals(TLInputGeoPointBase locationGeoPoint); + } + + public class TLInputGeoPointEmpty : TLInputGeoPointBase + { + public const uint Signature = TLConstructors.TLInputGeoPointEmpty; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override string ToString() + { + return "empty"; + } + + public override bool GeoPointEquals(TLInputGeoPointBase geoPointBase) + { + var geoPointEmpty = geoPointBase as TLInputGeoPointEmpty; + if (geoPointEmpty != null) + { + return true; + } + + return false; + } + } + + public class TLInputGeoPoint : TLInputGeoPointBase + { + public const uint Signature = TLConstructors.TLInputGeoPoint; + + public TLDouble Lat { get; set; } + public TLDouble Long { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Lat.ToBytes(), + Long.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Lat = GetObject(input); + Long = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Lat.ToStream(output); + Long.ToStream(output); + } + + public string GetFileName() + { + return string.Format("staticmap{0}_{1}.jpg", Lat.Value.ToString(new CultureInfo("en-US")), Long.Value.ToString(new CultureInfo("en-US"))); + } + + public override string ToString() + { + return string.Format("{0}_{1}", Lat, Long); + } + + public override bool GeoPointEquals(TLInputGeoPointBase geoPointBase) + { + var geoPoint = geoPointBase as TLInputGeoPoint; + if (geoPoint != null) + { + return + Lat.Value == geoPoint.Lat.Value + && Long.Value == geoPoint.Long.Value; + } + + return false; + } + } +} diff --git a/Telegram.Api/TL/TLInputMedia.cs b/Telegram.Api/TL/TLInputMedia.cs new file mode 100755 index 0000000..ad25dcd --- /dev/null +++ b/Telegram.Api/TL/TLInputMedia.cs @@ -0,0 +1,1985 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum InputMediaUploadedPhotoFlags + { + Stickers = 0x1, + TTLSeconds = 0x2 + } + + [Flags] + public enum InputMediaPhotoFlags + { + TTLSeconds = 0x1 + } + + [Flags] + public enum InputMediaUploadedDocumentFlags + { + Stickers = 0x1, + TTLSeconds = 0x2, + Thumb = 0x4, + NosoundVideo = 0x8, + } + + [Flags] + public enum InputMediaDocumentFlags + { + TTLSeconds = 0x1, + } + + [Flags] + public enum InputMediaPhotoExternalFlags + { + TTLSeconds = 0x1, + } + + [Flags] + public enum InputMediaDocumentExternalFlags + { + TTLSeconds = 0x1, + } + + [Flags] + public enum InputMediaInvoiceFlags + { + Photo = 0x1 + } + + public interface IInputMediaCaption + { + TLString Caption { get; set; } + } + + public interface IInputTTLMedia + { + TLInt TTLSeconds { get; set; } + } + + public abstract class TLInputMediaBase : TLObject + { +#region Additional + public byte[] MD5Hash { get; set; } +#endregion + } + + public class TLInputMediaEmpty : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaEmpty; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLInputMediaUploadedDocument : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaUploadedDocument; + + public TLInputFileBase File { get; set; } + + public TLString FileName { get; set; } + + public TLString MimeType { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + FileName.ToBytes(), + MimeType.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + FileName = GetObject(input); + MimeType = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + FileName.ToStream(output); + MimeType.ToStream(output); + } + } + + public class TLInputMediaUploadedDocument22 : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaUploadedDocument22; + + public TLInputFileBase File { get; set; } + + public TLString MimeType { get; set; } + + public TLVector Attributes { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + MimeType.ToBytes(), + Attributes.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + MimeType = GetObject(input); + Attributes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + MimeType.ToStream(output); + Attributes.ToStream(output); + } + } + + public class TLInputMediaUploadedDocument75 : TLInputMediaUploadedDocument70 + { + public new const uint Signature = TLConstructors.TLInputMediaUploadedDocument75; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + File.ToBytes(), + ToBytes(Thumb, Flags, (int)InputMediaUploadedDocumentFlags.Thumb), + MimeType.ToBytes(), + Attributes.ToBytes(), + ToBytes(Stickers, Flags, (int)InputMediaUploadedDocumentFlags.Stickers), + ToBytes(TTLSeconds, Flags, (int)InputMediaUploadedDocumentFlags.TTLSeconds)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + File = GetObject(input); + Thumb = GetObject(Flags, (int)InputMediaUploadedDocumentFlags.Thumb, null, input); + MimeType = GetObject(input); + Attributes = GetObject>(input); + Stickers = GetObject>(Flags, (int)InputMediaUploadedDocumentFlags.Stickers, null, input); + TTLSeconds = GetObject(Flags, (int)InputMediaUploadedDocumentFlags.TTLSeconds, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + File.ToStream(output); + ToStream(output, Thumb, Flags, (int)InputMediaUploadedDocumentFlags.Thumb); + MimeType.ToStream(output); + Attributes.ToStream(output); + ToStream(output, Stickers, Flags, (int)InputMediaUploadedDocumentFlags.Stickers); + ToStream(output, TTLSeconds, Flags, (int)InputMediaUploadedDocumentFlags.TTLSeconds); + } + } + + public class TLInputMediaUploadedDocument70 : TLInputMediaUploadedDocument56, IInputTTLMedia + { + public new const uint Signature = TLConstructors.TLInputMediaUploadedDocument70; + + private TLInputFileBase _thumb; + + public TLInputFileBase Thumb + { + get { return _thumb; } + set { SetField(out _thumb, value, ref _flags, (int)InputMediaUploadedDocumentFlags.Thumb); } + } + + private TLInt _ttlSeconds; + + public TLInt TTLSeconds + { + get { return _ttlSeconds; } + set { SetField(out _ttlSeconds, value, ref _flags, (int)InputMediaUploadedDocumentFlags.TTLSeconds); } + } + + public bool NosoundVideo + { + get { return IsSet(_flags, (int) InputMediaUploadedDocumentFlags.NosoundVideo); } + set { SetUnset(ref _flags, value, (int) InputMediaUploadedDocumentFlags.NosoundVideo); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + File.ToBytes(), + ToBytes(Thumb, Flags, (int)InputMediaUploadedDocumentFlags.Thumb), + MimeType.ToBytes(), + Attributes.ToBytes(), + Caption.ToBytes(), + ToBytes(Stickers, Flags, (int)InputMediaUploadedDocumentFlags.Stickers), + ToBytes(TTLSeconds, Flags, (int)InputMediaUploadedDocumentFlags.TTLSeconds)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + File = GetObject(input); + Thumb = GetObject(Flags, (int)InputMediaUploadedDocumentFlags.Thumb, null, input); + MimeType = GetObject(input); + Attributes = GetObject>(input); + Caption = GetObject(input); + Stickers = GetObject>(Flags, (int)InputMediaUploadedDocumentFlags.Stickers, null, input); + TTLSeconds = GetObject(Flags, (int)InputMediaUploadedDocumentFlags.TTLSeconds, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + File.ToStream(output); + ToStream(output, Thumb, Flags, (int)InputMediaUploadedDocumentFlags.Thumb); + MimeType.ToStream(output); + Attributes.ToStream(output); + Caption.ToStream(output); + ToStream(output, Stickers, Flags, (int)InputMediaUploadedDocumentFlags.Stickers); + ToStream(output, TTLSeconds, Flags, (int)InputMediaUploadedDocumentFlags.TTLSeconds); + } + } + + public class TLInputMediaUploadedDocument56 : TLInputMediaUploadedDocument45 + { + public new const uint Signature = TLConstructors.TLInputMediaUploadedDocument56; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLVector _stickers; + + public TLVector Stickers + { + get { return _stickers; } + set { SetField(out _stickers, value, ref _flags, (int)InputMediaUploadedDocumentFlags.Stickers); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + File.ToBytes(), + MimeType.ToBytes(), + Attributes.ToBytes(), + Caption.ToBytes(), + ToBytes(Stickers, Flags, (int)InputMediaUploadedDocumentFlags.Stickers)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + File = GetObject(input); + MimeType = GetObject(input); + Attributes = GetObject>(input); + Caption = GetObject(input); + Stickers = GetObject>(Flags, (int)InputMediaUploadedDocumentFlags.Stickers, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + File.ToStream(output); + MimeType.ToStream(output); + Attributes.ToStream(output); + Caption.ToStream(output); + ToStream(output, Stickers, Flags, (int)InputMediaUploadedDocumentFlags.Stickers); + } + } + + public class TLInputMediaUploadedDocument45 : TLInputMediaBase, IAttributes, IInputMediaCaption + { + public const uint Signature = TLConstructors.TLInputMediaUploadedDocument45; + + public TLInputFileBase File { get; set; } + + public TLString MimeType { get; set; } + + public TLVector Attributes { get; set; } + + public TLString Caption { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + MimeType.ToBytes(), + Attributes.ToBytes(), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + MimeType = GetObject(input); + Attributes = GetObject>(input); + Caption = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + MimeType.ToStream(output); + Attributes.ToStream(output); + Caption.ToStream(output); + } + } + + public class TLInputMediaUploadedThumbDocument : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaUploadedThumbDocument; + + public TLInputFileBase File { get; set; } + + public TLInputFileBase Thumb { get; set; } + + public TLString FileName { get; set; } + + public TLString MimeType { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + Thumb.ToBytes(), + FileName.ToBytes(), + MimeType.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + Thumb = GetObject(input); + FileName = GetObject(input); + MimeType = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + Thumb.ToStream(output); + FileName.ToStream(output); + MimeType.ToStream(output); + } + } + + public class TLInputMediaUploadedThumbDocument22 : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaUploadedThumbDocument22; + + public TLInputFileBase File { get; set; } + + public TLInputFileBase Thumb { get; set; } + + public TLString MimeType { get; set; } + + public TLVector Attributes { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + Thumb.ToBytes(), + MimeType.ToBytes(), + Attributes.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + Thumb = GetObject(input); + MimeType = GetObject(input); + Attributes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + Thumb.ToStream(output); + MimeType.ToStream(output); + Attributes.ToStream(output); + } + } + + [Obsolete] + public class TLInputMediaUploadedThumbDocument56 : TLInputMediaUploadedThumbDocument45 + { + public new const uint Signature = TLConstructors.TLInputMediaUploadedThumbDocument56; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLVector _stickers; + + public TLVector Stickers + { + get { return _stickers; } + set { SetField(out _stickers, value, ref _flags, (int)InputMediaUploadedDocumentFlags.Stickers); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + File.ToBytes(), + Thumb.ToBytes(), + MimeType.ToBytes(), + Attributes.ToBytes(), + Caption.ToBytes(), + ToBytes(Stickers, Flags, (int)InputMediaUploadedDocumentFlags.Stickers)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + File = GetObject(input); + Thumb = GetObject(input); + MimeType = GetObject(input); + Attributes = GetObject>(input); + Caption = GetObject(input); + Stickers = GetObject>(Flags, (int)InputMediaUploadedDocumentFlags.Stickers, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + File.ToStream(output); + Thumb.ToStream(output); + MimeType.ToStream(output); + Attributes.ToStream(output); + Caption.ToStream(output); + ToStream(output, Stickers, Flags, (int)InputMediaUploadedDocumentFlags.Stickers); + } + } + + public class TLInputMediaUploadedThumbDocument45 : TLInputMediaBase, IAttributes, IInputMediaCaption + { + public const uint Signature = TLConstructors.TLInputMediaUploadedThumbDocument45; + + public TLInputFileBase File { get; set; } + + public TLInputFileBase Thumb { get; set; } + + public TLString MimeType { get; set; } + + public TLVector Attributes { get; set; } + + public TLString Caption { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + Thumb.ToBytes(), + MimeType.ToBytes(), + Attributes.ToBytes(), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + Thumb = GetObject(input); + MimeType = GetObject(input); + Attributes = GetObject>(input); + Caption = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + Thumb.ToStream(output); + MimeType.ToStream(output); + Attributes.ToStream(output); + Caption.ToStream(output); + } + } + + public class TLInputMediaDocument : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaDocument; + + public TLInputDocumentBase Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + } + } + + public class TLInputMediaDocument75 : TLInputMediaDocument70 + { + public new const uint Signature = TLConstructors.TLInputMediaDocument75; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + ToBytes(TTLSeconds, Flags, (int)InputMediaDocumentFlags.TTLSeconds)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + TTLSeconds = GetObject(Flags, (int)InputMediaDocumentFlags.TTLSeconds, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + ToStream(output, TTLSeconds, Flags, (int)InputMediaDocumentFlags.TTLSeconds); + } + } + + public class TLInputMediaDocument70 : TLInputMediaDocument45, IInputTTLMedia + { + public new const uint Signature = TLConstructors.TLInputMediaDocument70; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLInt _ttlSeconds; + + public TLInt TTLSeconds + { + get { return _ttlSeconds; } + set { SetField(out _ttlSeconds, value, ref _flags, (int)InputMediaDocumentFlags.TTLSeconds); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + Caption.ToBytes(), + ToBytes(TTLSeconds, Flags, (int)InputMediaDocumentFlags.TTLSeconds)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Caption = GetObject(input); + TTLSeconds = GetObject(Flags, (int)InputMediaDocumentFlags.TTLSeconds, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + Caption.ToStream(output); + ToStream(output, TTLSeconds, Flags, (int)InputMediaDocumentFlags.TTLSeconds); + } + } + + public class TLInputMediaDocument45 : TLInputMediaBase, IInputMediaCaption + { + public const uint Signature = TLConstructors.TLInputMediaDocument45; + + public TLInputDocumentBase Id { get; set; } + + public TLString Caption { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Caption = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + Caption.ToStream(output); + } + } + + public class TLInputMediaUploadedAudio : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaUploadedAudio; + + public TLInputFile File { get; set; } + + public TLInt Duration { get; set; } + + public TLString MimeType { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + Duration.ToBytes(), + MimeType.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + Duration = GetObject(input); + MimeType = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + Duration.ToStream(output); + MimeType.ToStream(output); + } + } + + public class TLInputMediaAudio : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaAudio; + + public TLInputAudioBase Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } + + public class TLInputMediaUploadedPhoto : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaUploadedPhoto; + + public TLInputFileBase File { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + } + } + + public class TLInputMediaUploadedPhoto28 : TLInputMediaUploadedPhoto, IInputMediaCaption + { + public new const uint Signature = TLConstructors.TLInputMediaUploadedPhoto28; + + public TLString Caption { get; set; } + + public TLInputMediaUploadedPhoto28() + { + + } + + public TLInputMediaUploadedPhoto28(TLInputMediaUploadedPhoto inputMediaUploadedPhoto, TLString caption) + { + File = inputMediaUploadedPhoto.File; + Caption = caption; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + Caption = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + Caption.ToStream(output); + } + } + + public class TLInputMediaUploadedPhoto56 : TLInputMediaUploadedPhoto28 + { + public new const uint Signature = TLConstructors.TLInputMediaUploadedPhoto56; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLVector _stickers; + + public TLVector Stickers + { + get { return _stickers; } + set { SetField(out _stickers, value, ref _flags, (int)InputMediaUploadedPhotoFlags.Stickers); } + } + + public TLInputMediaUploadedPhoto56() + { + + } + + public TLInputMediaUploadedPhoto56(TLInputMediaUploadedPhoto inputMediaUploadedPhoto, TLString caption, TLVector stickers) + { + Flags = new TLInt(0); + File = inputMediaUploadedPhoto.File; + Caption = caption; + Stickers = stickers; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + File.ToBytes(), + Caption.ToBytes(), + ToBytes(Stickers, Flags, (int)InputMediaUploadedPhotoFlags.Stickers)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + File = GetObject(input); + Caption = GetObject(input); + Stickers = GetObject>(Flags, (int)InputMediaUploadedPhotoFlags.Stickers, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + File.ToStream(output); + Caption.ToStream(output); + ToStream(output, Stickers, Flags, (int)InputMediaUploadedPhotoFlags.Stickers); + } + } + + public class TLInputMediaUploadedPhoto70 : TLInputMediaUploadedPhoto56, IInputTTLMedia + { + public new const uint Signature = TLConstructors.TLInputMediaUploadedPhoto70; + + private TLInt _ttlSeconds; + + public TLInt TTLSeconds + { + get { return _ttlSeconds; } + set { SetField(out _ttlSeconds, value, ref _flags, (int)InputMediaUploadedPhotoFlags.TTLSeconds); } + } + + public TLInputMediaUploadedPhoto70() + { + + } + + public TLInputMediaUploadedPhoto70(TLInputMediaUploadedPhoto inputMediaUploadedPhoto, TLString caption, TLVector stickers) + { + Flags = new TLInt(0); + File = inputMediaUploadedPhoto.File; + Caption = caption; + Stickers = stickers; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + File.ToBytes(), + Caption.ToBytes(), + ToBytes(Stickers, Flags, (int)InputMediaUploadedPhotoFlags.Stickers), + ToBytes(TTLSeconds, Flags, (int)InputMediaUploadedPhotoFlags.TTLSeconds)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + File = GetObject(input); + Caption = GetObject(input); + Stickers = GetObject>(Flags, (int)InputMediaUploadedPhotoFlags.Stickers, null, input); + TTLSeconds = GetObject(Flags, (int)InputMediaUploadedPhotoFlags.TTLSeconds, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + File.ToStream(output); + Caption.ToStream(output); + ToStream(output, Stickers, Flags, (int)InputMediaUploadedPhotoFlags.Stickers); + ToStream(output, TTLSeconds, Flags, (int)InputMediaUploadedPhotoFlags.TTLSeconds); + } + } + + public class TLInputMediaUploadedPhoto75 : TLInputMediaUploadedPhoto70 + { + public new const uint Signature = TLConstructors.TLInputMediaUploadedPhoto75; + + public TLInputMediaUploadedPhoto75() + { + + } + + public TLInputMediaUploadedPhoto75(TLInputMediaUploadedPhoto inputMediaUploadedPhoto, TLVector stickers) + { + Flags = new TLInt(0); + File = inputMediaUploadedPhoto.File; + Caption = TLString.Empty; + Stickers = stickers; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + File.ToBytes(), + ToBytes(Stickers, Flags, (int)InputMediaUploadedPhotoFlags.Stickers), + ToBytes(TTLSeconds, Flags, (int)InputMediaUploadedPhotoFlags.TTLSeconds)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + File = GetObject(input); + Stickers = GetObject>(Flags, (int)InputMediaUploadedPhotoFlags.Stickers, null, input); + TTLSeconds = GetObject(Flags, (int)InputMediaUploadedPhotoFlags.TTLSeconds, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + File.ToStream(output); + ToStream(output, Stickers, Flags, (int)InputMediaUploadedPhotoFlags.Stickers); + ToStream(output, TTLSeconds, Flags, (int)InputMediaUploadedPhotoFlags.TTLSeconds); + } + } + + public class TLInputMediaPhoto : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaPhoto; + + public TLInputPhotoBase Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + } + } + + public class TLInputMediaPhoto28 : TLInputMediaPhoto, IInputMediaCaption + { + public new const uint Signature = TLConstructors.TLInputMediaPhoto28; + + public TLString Caption { get; set; } + + public TLInputMediaPhoto28() + { + + } + + public TLInputMediaPhoto28(TLInputMediaPhoto inputMediaPhoto, TLString caption) + { + Id = inputMediaPhoto.Id; + Caption = caption; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Caption = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + Caption.ToStream(output); + } + } + + public class TLInputMediaPhoto70 : TLInputMediaPhoto28, IInputTTLMedia + { + public new const uint Signature = TLConstructors.TLInputMediaPhoto70; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLInt _ttlSeconds; + + public TLInt TTLSeconds + { + get { return _ttlSeconds; } + set { SetField(out _ttlSeconds, value, ref _flags, (int)InputMediaPhotoFlags.TTLSeconds); } + } + + public TLInputMediaPhoto70() + { + + } + + public TLInputMediaPhoto70(TLInputMediaPhoto inputMediaPhoto, TLString caption) + { + Flags = new TLInt(0); + Id = inputMediaPhoto.Id; + Caption = caption; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + Caption.ToBytes(), + ToBytes(TTLSeconds, Flags, (int) InputMediaPhotoFlags.TTLSeconds)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Caption = GetObject(input); + TTLSeconds = GetObject(Flags, (int) InputMediaPhotoFlags.TTLSeconds, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + Caption.ToStream(output); + ToStream(output, TTLSeconds, Flags, (int)InputMediaPhotoFlags.TTLSeconds); + } + } + + public class TLInputMediaPhoto75 : TLInputMediaPhoto70 + { + public new const uint Signature = TLConstructors.TLInputMediaPhoto75; + + public TLInputMediaPhoto75() + { + + } + + public TLInputMediaPhoto75(TLInputMediaPhoto inputMediaPhoto) + { + Flags = new TLInt(0); + Id = inputMediaPhoto.Id; + Caption = TLString.Empty; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + ToBytes(TTLSeconds, Flags, (int)InputMediaPhotoFlags.TTLSeconds)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Caption = TLString.Empty; + TTLSeconds = GetObject(Flags, (int)InputMediaPhotoFlags.TTLSeconds, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + ToStream(output, TTLSeconds, Flags, (int)InputMediaPhotoFlags.TTLSeconds); + } + } + + public class TLInputMediaGeoPoint : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaGeoPoint; + + public TLInputGeoPointBase GeoPoint { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + GeoPoint.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + GeoPoint = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + GeoPoint.ToStream(output); + } + } + + public class TLInputMediaVenue : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaVenue; + + public TLInputGeoPointBase GeoPoint { get; set; } + + public TLString Title { get; set; } + + public TLString Address { get; set; } + + public TLString Provider { get; set; } + + public TLString VenueId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + GeoPoint.ToBytes(), + Title.ToBytes(), + Address.ToBytes(), + Provider.ToBytes(), + VenueId.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + GeoPoint = GetObject(input); + Title = GetObject(input); + Address = GetObject(input); + Provider = GetObject(input); + VenueId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + GeoPoint.ToStream(output); + Title.ToStream(output); + Address.ToStream(output); + Provider.ToStream(output); + VenueId.ToStream(output); + } + } + + public class TLInputMediaVenue72 : TLInputMediaVenue + { + public new const uint Signature = TLConstructors.TLInputMediaVenue72; + + public TLString VenueType { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + GeoPoint.ToBytes(), + Title.ToBytes(), + Address.ToBytes(), + Provider.ToBytes(), + VenueId.ToBytes(), + VenueType.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + GeoPoint = GetObject(input); + Title = GetObject(input); + Address = GetObject(input); + Provider = GetObject(input); + VenueId = GetObject(input); + VenueType = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + GeoPoint.ToStream(output); + Title.ToStream(output); + Address.ToStream(output); + Provider.ToStream(output); + VenueId.ToStream(output); + VenueType.ToStream(output); + } + } + + public class TLInputMediaContact82 : TLInputMediaContact + { + public new const uint Signature = TLConstructors.TLInputMediaContact82; + + public TLString VCard { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumber.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + VCard.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + PhoneNumber = GetObject(input); + FirstName = GetObject(input); + LastName = GetObject(input); + VCard = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PhoneNumber.ToStream(output); + FirstName.ToStream(output); + LastName.ToStream(output); + VCard.ToStream(output); + } + } + + public class TLInputMediaContact : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaContact; + + public TLString PhoneNumber { get; set; } + + public TLString FirstName { get; set; } + + public TLString LastName { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneNumber.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + PhoneNumber = GetObject(input); + FirstName = GetObject(input); + LastName = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PhoneNumber.ToStream(output); + FirstName.ToStream(output); + LastName.ToStream(output); + } + } + + public class TLInputMediaUploadedVideo : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaUploadedVideo; + + public TLInputFileBase File { get; set; } + public TLInt Duration { get; set; } + public TLInt W { get; set; } + public TLInt H { get; set; } + public TLString MimeType { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + Duration.ToBytes(), + W.ToBytes(), + H.ToBytes(), + MimeType.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + Duration = GetObject(input); + W = GetObject(input); + H = GetObject(input); + MimeType = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + Duration.ToStream(output); + W.ToStream(output); + H.ToStream(output); + MimeType.ToStream(output); + } + } + + public class TLInputMediaUploadedVideo28 : TLInputMediaUploadedVideo, IInputMediaCaption + { + public new const uint Signature = TLConstructors.TLInputMediaUploadedVideo28; + + public TLString Caption { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + Duration.ToBytes(), + W.ToBytes(), + H.ToBytes(), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + Duration = GetObject(input); + W = GetObject(input); + H = GetObject(input); + Caption = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + Duration.ToStream(output); + W.ToStream(output); + H.ToStream(output); + Caption.ToStream(output); + } + } + + public class TLInputMediaUploadedVideo36 : TLInputMediaUploadedVideo28 + { + public new const uint Signature = TLConstructors.TLInputMediaUploadedVideo36; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + Duration.ToBytes(), + W.ToBytes(), + H.ToBytes(), + MimeType.ToBytes(), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + Duration = GetObject(input); + W = GetObject(input); + H = GetObject(input); + MimeType = GetObject(input); + Caption = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + Duration.ToStream(output); + W.ToStream(output); + H.ToStream(output); + MimeType.ToStream(output); + Caption.ToStream(output); + } + } + + public class TLInputMediaUploadedThumbVideo : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaUploadedThumbVideo; + + public TLInputFileBase File { get; set; } + public TLInputFile Thumb { get; set; } + public TLInt Duration { get; set; } + public TLInt W { get; set; } + public TLInt H { get; set; } + public TLString MimeType { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + Thumb.ToBytes(), + Duration.ToBytes(), + W.ToBytes(), + H.ToBytes(), + MimeType.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + Thumb = GetObject(input); + Duration = GetObject(input); + W = GetObject(input); + H = GetObject(input); + MimeType = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + Thumb.ToStream(output); + Duration.ToStream(output); + W.ToStream(output); + H.ToStream(output); + MimeType.ToStream(output); + } + } + + public class TLInputMediaUploadedThumbVideo28 : TLInputMediaUploadedThumbVideo, IInputMediaCaption + { + public new const uint Signature = TLConstructors.TLInputMediaUploadedThumbVideo28; + + public TLString Caption { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + Thumb.ToBytes(), + Duration.ToBytes(), + W.ToBytes(), + H.ToBytes(), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + Thumb = GetObject(input); + Duration = GetObject(input); + W = GetObject(input); + H = GetObject(input); + Caption = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + Thumb.ToStream(output); + Duration.ToStream(output); + W.ToStream(output); + H.ToStream(output); + Caption.ToStream(output); + } + } + + public class TLInputMediaUploadedThumbVideo36 : TLInputMediaUploadedThumbVideo28 + { + public new const uint Signature = TLConstructors.TLInputMediaUploadedThumbVideo36; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + File.ToBytes(), + Thumb.ToBytes(), + Duration.ToBytes(), + W.ToBytes(), + H.ToBytes(), + MimeType.ToBytes(), + Caption.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + File = GetObject(input); + Thumb = GetObject(input); + Duration = GetObject(input); + W = GetObject(input); + H = GetObject(input); + MimeType = GetObject(input); + Caption = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + File.ToStream(output); + Thumb.ToStream(output); + Duration.ToStream(output); + W.ToStream(output); + H.ToStream(output); + MimeType.ToStream(output); + Caption.ToStream(output); + } + } + + public class TLInputMediaVideo : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaVideo; + + public TLInputVideoBase Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + } + + public class TLInputMediaVideo28 : TLInputMediaVideo, IInputMediaCaption + { + public new const uint Signature = TLConstructors.TLInputMediaVideo28; + + public TLString Caption { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Caption.ToBytes()); + } + } + + public class TLInputMediaGifExternal : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaGifExternal; + + public TLString Url { get; set; } + + public TLString Q { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Url.ToBytes(), + Q.ToBytes()); + } + } + + public class TLInputMediaPhotoExternal75 : TLInputMediaPhotoExternal70 + { + public new const uint Signature = TLConstructors.TLInputMediaPhotoExternal75; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Url.ToBytes(), + ToBytes(TTLSeconds, Flags, (int)InputMediaPhotoExternalFlags.TTLSeconds)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Url = GetObject(input); + TTLSeconds = GetObject(Flags, (int)InputMediaPhotoFlags.TTLSeconds, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Url.ToStream(output); + ToStream(output, TTLSeconds, Flags, (int)InputMediaPhotoFlags.TTLSeconds); + } + } + + public class TLInputMediaPhotoExternal70 : TLInputMediaPhotoExternal, IInputTTLMedia + { + public new const uint Signature = TLConstructors.TLInputMediaPhotoExternal70; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLInt _ttlSeconds; + + public TLInt TTLSeconds + { + get { return _ttlSeconds; } + set { SetField(out _ttlSeconds, value, ref _flags, (int)InputMediaPhotoExternalFlags.TTLSeconds); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Url.ToBytes(), + Caption.ToBytes(), + ToBytes(TTLSeconds, Flags, (int)InputMediaPhotoExternalFlags.TTLSeconds)); + } + } + + public class TLInputMediaPhotoExternal : TLInputMediaBase, IInputMediaCaption + { + public const uint Signature = TLConstructors.TLInputMediaPhotoExternal; + + public TLString Url { get; set; } + + public TLString Caption { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Url.ToBytes(), + Caption.ToBytes()); + } + } + + public class TLInputMediaDocumentExternal75 : TLInputMediaDocumentExternal70 + { + public new const uint Signature = TLConstructors.TLInputMediaDocumentExternal75; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Url.ToBytes(), + ToBytes(TTLSeconds, Flags, (int)InputMediaDocumentExternalFlags.TTLSeconds)); + } + } + + public class TLInputMediaDocumentExternal70 : TLInputMediaDocumentExternal, IInputTTLMedia + { + public new const uint Signature = TLConstructors.TLInputMediaDocumentExternal70; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLInt _ttlSeconds; + + public TLInt TTLSeconds + { + get { return _ttlSeconds; } + set { SetField(out _ttlSeconds, value, ref _flags, (int)InputMediaDocumentExternalFlags.TTLSeconds); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Url.ToBytes(), + Caption.ToBytes(), + ToBytes(TTLSeconds, Flags, (int)InputMediaDocumentExternalFlags.TTLSeconds)); + } + } + + public class TLInputMediaDocumentExternal : TLInputMediaBase, IInputMediaCaption + { + public const uint Signature = TLConstructors.TLInputMediaDocumentExternal; + + public TLString Url { get; set; } + + public TLString Caption { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Url.ToBytes(), + Caption.ToBytes()); + } + } + + public class TLInputMediaGame : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaGame; + + public TLInputGameBase Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + } + } + + public class TLInputMediaInvoice73 : TLInputMediaInvoice + { + public new const uint Signature = TLConstructors.TLInputMediaInvoice73; + + public TLDataJSON ProviderData { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Title.ToBytes(), + Description.ToBytes(), + ToBytes(Photo, Flags, (int)InputMediaInvoiceFlags.Photo), + Invoice.ToBytes(), + Payload.ToBytes(), + Provider.ToBytes(), + ProviderData.ToBytes(), + StartParam.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Title = GetObject(input); + Description = GetObject(input); + Photo = GetObject(Flags, (int)InputMediaInvoiceFlags.Photo, null, input); + Invoice = GetObject(input); + Payload = GetObject(input); + Provider = GetObject(input); + ProviderData = GetObject(input); + StartParam = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Title.ToStream(output); + Description.ToStream(output); + ToStream(output, Photo, Flags, (int)InputMediaInvoiceFlags.Photo); + Invoice.ToStream(output); + Payload.ToStream(output); + Provider.ToStream(output); + ProviderData.ToStream(output); + StartParam.ToStream(output); + } + } + + public class TLInputMediaInvoice : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaInvoice; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLString Title { get; set; } + + public TLString Description { get; set; } + + private TLInputWebDocument _photo; + + public TLInputWebDocument Photo + { + get { return _photo; } + set { SetField(out _photo, value, ref _flags, (int) InputMediaInvoiceFlags.Photo); } + } + + public TLInvoice Invoice { get; set; } + + public TLString Payload { get; set; } + + public TLString Provider { get; set; } + + public TLString StartParam { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Title.ToBytes(), + Description.ToBytes(), + ToBytes(Photo, Flags, (int) InputMediaInvoiceFlags.Photo), + Invoice.ToBytes(), + Payload.ToBytes(), + Provider.ToBytes(), + StartParam.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Title = GetObject(input); + Description = GetObject(input); + Photo = GetObject(Flags, (int) InputMediaInvoiceFlags.Photo, null, input); + Invoice = GetObject(input); + Payload = GetObject(input); + Provider = GetObject(input); + StartParam = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Title.ToStream(output); + Description.ToStream(output); + ToStream(output, Photo, Flags, (int) InputMediaInvoiceFlags.Photo); + Invoice.ToStream(output); + Payload.ToStream(output); + Provider.ToStream(output); + StartParam.ToStream(output); + } + } + + public class TLInputMediaGeoLive : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputMediaGeoLive; + + public TLInputGeoPointBase GeoPoint { get; set; } + + public TLInt Period { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + GeoPoint.ToBytes(), + Period.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + GeoPoint = GetObject(input); + Period = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + GeoPoint.ToStream(output); + Period.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLInputMessageEntityMentionName.cs b/Telegram.Api/TL/TLInputMessageEntityMentionName.cs new file mode 100755 index 0000000..eb3291b --- /dev/null +++ b/Telegram.Api/TL/TLInputMessageEntityMentionName.cs @@ -0,0 +1,14 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + +} diff --git a/Telegram.Api/TL/TLInputMessagesFilter.cs b/Telegram.Api/TL/TLInputMessagesFilter.cs new file mode 100755 index 0000000..1911241 --- /dev/null +++ b/Telegram.Api/TL/TLInputMessagesFilter.cs @@ -0,0 +1,342 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum InputMessagesFilterPhoneCallsFlags + { + Missed = 0x1, // 0 + } + + public abstract class TLInputMessagesFilterBase : TLObject { } + + public class TLInputMessagesFilterEmpty : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessageFilterEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterPhoto : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessageFilterPhoto; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterVideo : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessageFilterVideo; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterPhotoVideo : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessageFilterPhotoVideo; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterPhotoVideoDocument : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessageFilterPhotoVideoDocument; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterDocument : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessageFilterDocument; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterAudio : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessageFilterAudio; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterAudioDocuments : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessageFilterAudioDocuments; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterUrl : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessageFilterUrl; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterGif : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessagesFilterGif; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterVoice : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessagesFilterVoice; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterMusic : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessagesFilterMusic; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterChatPhotos : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessagesFilterChatPhotos; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterPhoneCalls : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessagesFilterPhoneCalls; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Missed + { + get { return IsSet(Flags, (int) InputMessagesFilterPhoneCallsFlags.Missed); } + set { SetUnset(ref _flags, value, (int) InputMessagesFilterPhoneCallsFlags.Missed); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes()); + } + } + + public class TLInputMessagesFilterRoundVoice : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessagesFilterRoundVoice; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterRoundVideo : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessagesFilterRoundVideo; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterMyMentions : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessagesFilterMyMentions; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterGeo : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessagesFilterGeo; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputMessagesFilterContacts : TLInputMessagesFilterBase + { + public const uint Signature = TLConstructors.TLInputMessagesFilterContacts; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } +} diff --git a/Telegram.Api/TL/TLInputNotifyPeer.cs b/Telegram.Api/TL/TLInputNotifyPeer.cs new file mode 100755 index 0000000..4d2a23a --- /dev/null +++ b/Telegram.Api/TL/TLInputNotifyPeer.cs @@ -0,0 +1,108 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + public abstract class TLInputNotifyPeerBase : TLObject { } + + public class TLInputNotifyPeer : TLInputNotifyPeerBase + { + public const uint Signature = TLConstructors.TLInputNotifyPeer; + + public TLInputPeerBase Peer { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes()); + } + + public override string ToString() + { + return "inputNotifyPeer " + Peer; + } + } + + public class TLInputNotifyUsers : TLInputNotifyPeerBase + { + public const uint Signature = TLConstructors.TLInputNotifyUsers; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override string ToString() + { + return "inputNotifyUsers"; + } + } + + public class TLInputNotifyChats : TLInputNotifyPeerBase + { + public const uint Signature = TLConstructors.TLInputNotifyChats; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override string ToString() + { + return "inputNotifyChats"; + } + } + + [Obsolete] + public class TLInputNotifyAll : TLInputNotifyPeerBase + { + public const uint Signature = TLConstructors.TLInputNotifyAll; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override string ToString() + { + return "inputNotifyAll"; + } + } +} diff --git a/Telegram.Api/TL/TLInputPaymentCredentials.cs b/Telegram.Api/TL/TLInputPaymentCredentials.cs new file mode 100755 index 0000000..09d5f9d --- /dev/null +++ b/Telegram.Api/TL/TLInputPaymentCredentials.cs @@ -0,0 +1,108 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum InputPaymentCredentials + { + Save = 0x1, // 0 + } + + public abstract class TLInputPaymentCredentialsBase : TLObject { } + + public class TLInputPaymentCredentialsSaved : TLInputPaymentCredentialsBase + { + public const uint Signature = TLConstructors.TLInputPaymentCredentialsSaved; + + public TLString Id { get; set; } + + public TLString TmpPassword { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + TmpPassword.ToBytes()); + } + } + + public class TLInputPaymentCredentials : TLInputPaymentCredentialsBase + { + public const uint Signature = TLConstructors.TLInputPaymentCredentials; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Save + { + get { return IsSet(Flags, (int) InputPaymentCredentials.Save); } + set { SetUnset(ref _flags, value, (int) InputPaymentCredentials.Save); } + } + + public TLDataJSON Data { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Data.ToBytes()); + } + } + + public class TLInputPaymentCredentialsApplePay : TLInputPaymentCredentialsBase + { + public const uint Signature = TLConstructors.TLInputPaymentCredentialsApplePay; + + public TLDataJSON PaymentData { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PaymentData.ToBytes()); + } + } + + public class TLInputPaymentCredentialsAndroidPay : TLInputPaymentCredentialsBase + { + public const uint Signature = TLConstructors.TLInputPaymentCredentialsAndroidPay; + + public TLDataJSON PaymentToken { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PaymentToken.ToBytes()); + } + } + + public class TLInputPaymentCredentialsAndroidPay74 : TLInputPaymentCredentialsAndroidPay + { + public new const uint Signature = TLConstructors.TLInputPaymentCredentialsAndroidPay74; + + public TLString GoogleTransactionId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PaymentToken.ToBytes(), + GoogleTransactionId.ToBytes()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLInputPeer.cs b/Telegram.Api/TL/TLInputPeer.cs new file mode 100755 index 0000000..c76144b --- /dev/null +++ b/Telegram.Api/TL/TLInputPeer.cs @@ -0,0 +1,143 @@ +using System.Linq; + +namespace Telegram.Api.TL +{ + abstract class TLInputPeer : TLObject { } + + class TLInputPeerEmpty : TLInputPeer + { + public const uint Signature = TLConstructors.TLInputPeerEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLInputPeerEmpty--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override string ToString() + { + return "TLInputPeerEmpty"; + } + } + + class TLInputPeerSelf : TLInputPeer + { + public const uint Signature = TLConstructors.TLInputPeerSelf; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLInputPeerSelf--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override string ToString() + { + return "TLInputPeerSelf"; + } + } + + class TLInputPeerContact : TLInputPeer + { + public const uint Signature = TLConstructors.TLInputPeerContact; + + public TLInt UserId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLInputPeerContact--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature) + .Concat(UserId.ToBytes()) + .ToArray(); + } + + public override string ToString() + { + return "UserId " + UserId; + } + } + + class TLInputPeerForeign : TLInputPeer + { + public const uint Signature = TLConstructors.TLInputPeerForeign; + + public TLInt UserId { get; set; } + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLInputPeerForeign--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature) + .Concat(UserId.ToBytes()) + .Concat(AccessHash.ToBytes()) + .ToArray(); + } + + public override string ToString() + { + return "UserId " + UserId + " AccessHash " + AccessHash; + } + } + + class TLInputPeerChat : TLInputPeer + { + public const uint Signature = TLConstructors.TLInputPeerChat; + + public TLInt ChatId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + TLUtils.WriteLine("--Parse TLInputPeerChat--"); + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature) + .Concat(ChatId.ToBytes()) + .ToArray(); + } + + public override string ToString() + { + return "ChatId " + ChatId; + } + } +} diff --git a/Telegram.Api/TL/TLInputPeerBase.cs b/Telegram.Api/TL/TLInputPeerBase.cs new file mode 100755 index 0000000..924ab3c --- /dev/null +++ b/Telegram.Api/TL/TLInputPeerBase.cs @@ -0,0 +1,394 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using System.Linq; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputPeerBase : TLObject { } + + public class TLInputPeerEmpty : TLInputPeerBase + { + public const uint Signature = TLConstructors.TLInputPeerEmpty; + + #region Additional + public TLInt UserId { get; set; } + + public TLInt SelfId { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override string ToString() + { + return "TLInputPeerEmpty"; + } + } + + public class TLInputPeerSelf : TLInputPeerBase + { + public const uint Signature = TLConstructors.TLInputPeerSelf; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override string ToString() + { + return "TLInputPeerSelf"; + } + } + + public class TLInputPeerContact : TLInputPeerBase + { + public const uint Signature = TLConstructors.TLInputPeerContact; + + public TLInt UserId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(TLInputPeerUser.Signature), + UserId.ToBytes(), + new TLLong(0).ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + UserId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputPeerContact user_id={0}", UserId); + } + } + + public class TLInputPeerForeign : TLInputPeerBase + { + public const uint Signature = TLConstructors.TLInputPeerForeign; + + public TLInt UserId { get; set; } + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(TLInputPeerUser.Signature), + UserId.ToBytes(), + AccessHash.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + UserId.ToStream(output); + AccessHash.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputPeerForeign user_id={0} access_hash={1}", UserId, AccessHash); + } + } + + public class TLInputPeerChat : TLInputPeerBase + { + public const uint Signature = TLConstructors.TLInputPeerChat; + + public TLInt ChatId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + ChatId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputPeerChat chat_id={0}", ChatId); + } + } + + public class TLInputPeerBroadcast : TLInputPeerBase + { + public const uint Signature = TLConstructors.TLInputPeerBroadcast; + + public TLInt ChatId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + ChatId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputPeerBroadcast chat_id={0}", ChatId); + } + } + + public class TLInputPeerUser : TLInputPeerBase + { + public const uint Signature = TLConstructors.TLInputPeerUser; + + public TLInt UserId { get; set; } + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + UserId.ToBytes(), + AccessHash.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + UserId.ToStream(output); + AccessHash.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputPeerUser user_id={0} access_hash={1}", UserId, AccessHash); + } + } + + public class TLInputPeerChannel : TLInputPeerBroadcast + { + public new const uint Signature = TLConstructors.TLInputPeerChannel; + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes(), + AccessHash.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + ChatId.ToStream(output); + AccessHash.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputPeerChannel channel_id={0} access_hash={1}", ChatId, AccessHash); + } + } + + public class TLInputPeerFeed : TLInputPeerBroadcast + { + public new const uint Signature = TLConstructors.TLInputPeerFeed; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ChatId.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + ChatId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputPeerFeed feed_id={0}", ChatId); + } + } +} diff --git a/Telegram.Api/TL/TLInputPeerNotifyEvents.cs b/Telegram.Api/TL/TLInputPeerNotifyEvents.cs new file mode 100755 index 0000000..790c2ca --- /dev/null +++ b/Telegram.Api/TL/TLInputPeerNotifyEvents.cs @@ -0,0 +1,49 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + public abstract class TLInputPeerNotifyEventsBase : TLObject { } + + [Obsolete] + public class TLInputPeerNotifyEventsEmpty : TLInputPeerNotifyEventsBase + { + public const uint Signature = TLConstructors.TLInputPeerNotifyEventsEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + [Obsolete] + public class TLInputPeerNotifyEventsAll : TLInputPeerNotifyEventsBase + { + public const uint Signature = TLConstructors.TLInputPeerNotifyEventsAll; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } +} diff --git a/Telegram.Api/TL/TLInputPeerNotifySettings.cs b/Telegram.Api/TL/TLInputPeerNotifySettings.cs new file mode 100755 index 0000000..e747a35 --- /dev/null +++ b/Telegram.Api/TL/TLInputPeerNotifySettings.cs @@ -0,0 +1,113 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLInputPeerNotifySettings78 : TLInputPeerNotifySettings48 + { + public new const uint Signature = TLConstructors.TLInputPeerNotifySettings78; + + protected TLInt _muteUntil; + + public override TLInt MuteUntil + { + get { return _muteUntil; } + set { SetField(out _muteUntil, value, ref _flags, (int)PeerNotifySettingsFlags.MuteUntil); } + } + + protected TLString _sound; + + public override TLString Sound + { + get { return _sound; } + set { SetField(out _sound, value, ref _flags, (int)PeerNotifySettingsFlags.Sound); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(ShowPreviews, Flags, (int)PeerNotifySettingsFlags.ShowPreviews), + ToBytes(Silent, Flags, (int)PeerNotifySettingsFlags.Silent), + ToBytes(MuteUntil, Flags, (int)PeerNotifySettingsFlags.MuteUntil), + ToBytes(Sound, Flags, (int)PeerNotifySettingsFlags.Sound)); + } + + public override string ToString() + { + return string.Format("mute_until={0} sound={1} show_previews={2} silent={3}", MuteUntil, Sound, ShowPreviews, Silent); + } + } + + public class TLInputPeerNotifySettings48 : TLInputPeerNotifySettings + { + public new const uint Signature = TLConstructors.TLInputPeerNotifySettings48; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override TLBool ShowPreviews + { + get { return new TLBool(IsSet(Flags, (int)PeerNotifySettingsFlags.ShowPreviews)); } + set { SetUnset(ref _flags, value != null && value.Value, (int)PeerNotifySettingsFlags.ShowPreviews); } + } + + public TLBool Silent + { + get { return new TLBool(IsSet(Flags, (int)PeerNotifySettingsFlags.Silent)); } + set { SetUnset(ref _flags, value != null && value.Value, (int)PeerNotifySettingsFlags.Silent); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + MuteUntil.ToBytes(), + Sound.ToBytes()); + } + + public override string ToString() + { + return string.Format("mute_until={0} sound={1} show_previews={2} silent={3}", MuteUntil, Sound, ShowPreviews, Silent); + } + } + + public class TLInputPeerNotifySettings : TLObject + { + public const uint Signature = TLConstructors.TLInputPeerNotifySettings; + + public virtual TLInt MuteUntil { get; set; } + + public virtual TLString Sound { get; set; } + + public virtual TLBool ShowPreviews { get; set; } + + public TLInt EventsMask { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + MuteUntil.ToBytes(), + Sound.ToBytes(), + ShowPreviews.ToBytes(), + EventsMask.ToBytes()); + } + + public override string ToString() + { + return string.Format("mute_until={0} sound={1} show_previews={2} events_mask={3}", MuteUntil, Sound, ShowPreviews, EventsMask); + } + } +} diff --git a/Telegram.Api/TL/TLInputPhoneCall.cs b/Telegram.Api/TL/TLInputPhoneCall.cs new file mode 100755 index 0000000..5d125ed --- /dev/null +++ b/Telegram.Api/TL/TLInputPhoneCall.cs @@ -0,0 +1,55 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLInputPhoneCall : TLObject + { + public const uint Signature = TLConstructors.TLInputPhoneCall; + + public TLLong Id { get; set; } + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + AccessHash.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLInputPhoto.cs b/Telegram.Api/TL/TLInputPhoto.cs new file mode 100755 index 0000000..9c09a8a --- /dev/null +++ b/Telegram.Api/TL/TLInputPhoto.cs @@ -0,0 +1,75 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputPhotoBase : TLObject { } + + public class TLInputPhotoEmpty : TLInputPhotoBase + { + public const uint Signature = TLConstructors.TLInputPhotoEmpty; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override string ToString() + { + return "TLInputPhotoEmpty"; + } + } + + public class TLInputPhoto : TLInputPhotoBase + { + public const uint Signature = TLConstructors.TLInputPhoto; + + public TLLong Id { get; set; } + public TLLong AccessHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + AccessHash.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLInputPhoto id={0}", Id); + } + } +} diff --git a/Telegram.Api/TL/TLInputPhotoCrop.cs b/Telegram.Api/TL/TLInputPhotoCrop.cs new file mode 100755 index 0000000..be4ac1c --- /dev/null +++ b/Telegram.Api/TL/TLInputPhotoCrop.cs @@ -0,0 +1,59 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLInputPhotoCropBase : TLObject { } + + public class TLInputPhotoCropAuto : TLInputPhotoCropBase + { + public const uint Signature = TLConstructors.TLInputPhotoCropAuto; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputPhotoCrop : TLInputPhotoCropBase + { + public const uint Signature = TLConstructors.TLInputPhotoCrop; + + public TLDouble CropLeft { get; set; } + + public TLDouble CropTop { get; set; } + + public TLDouble CropWidth { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + CropLeft = GetObject(bytes, ref position); + CropTop = GetObject(bytes, ref position); + CropWidth = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + CropLeft.ToBytes(), + CropTop.ToBytes(), + CropWidth.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLInputPrivacyKey.cs b/Telegram.Api/TL/TLInputPrivacyKey.cs new file mode 100755 index 0000000..ad892d9 --- /dev/null +++ b/Telegram.Api/TL/TLInputPrivacyKey.cs @@ -0,0 +1,65 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLInputPrivacyKeyBase : TLObject { } + + public class TLInputPrivacyKeyStatusTimestamp : TLInputPrivacyKeyBase + { + public const uint Signature = TLConstructors.TLInputPrivacyKeyStatusTimestamp; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLInputPrivacyKeyChatInvite : TLInputPrivacyKeyBase + { + public const uint Signature = TLConstructors.TLInputPrivacyKeyChatInvite; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLInputPrivacyKeyPhoneCall : TLInputPrivacyKeyBase + { + public const uint Signature = TLConstructors.TLInputPrivacyKeyPhoneCall; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLInputPrivacyRule.cs b/Telegram.Api/TL/TLInputPrivacyRule.cs new file mode 100755 index 0000000..e808286 --- /dev/null +++ b/Telegram.Api/TL/TLInputPrivacyRule.cs @@ -0,0 +1,129 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLInputPrivacyRuleBase : TLObject { } + + public class TLInputPrivacyValueAllowContacts : TLInputPrivacyRuleBase + { + public const uint Signature = TLConstructors.TLInputPrivacyValueAllowContacts; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLInputPrivacyValueAllowAll : TLInputPrivacyRuleBase + { + public const uint Signature = TLConstructors.TLInputPrivacyValueAllowAll; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLInputPrivacyValueAllowUsers : TLInputPrivacyRuleBase + { + public const uint Signature = TLConstructors.TLInputPrivacyValueAllowUsers; + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Users = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Users.ToBytes()); + } + } + + public class TLInputPrivacyValueDisallowContacts : TLInputPrivacyRuleBase + { + public const uint Signature = TLConstructors.TLInputPrivacyValueDisallowContacts; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLInputPrivacyValueDisallowAll : TLInputPrivacyRuleBase + { + public const uint Signature = TLConstructors.TLInputPrivacyValueDisallowAll; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLInputPrivacyValueDisallowUsers : TLInputPrivacyRuleBase + { + public const uint Signature = TLConstructors.TLInputPrivacyValueDisallowUsers; + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Users = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Users.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLInputReportReason.cs b/Telegram.Api/TL/TLInputReportReason.cs new file mode 100755 index 0000000..87e9461 --- /dev/null +++ b/Telegram.Api/TL/TLInputReportReason.cs @@ -0,0 +1,117 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputReportReasonBase : TLObject { } + + public class TLInputReportReasonSpam : TLInputReportReasonBase + { + public const uint Signature = TLConstructors.TLInputReportReasonSpam; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLInputReportReasonViolence : TLInputReportReasonBase + { + public const uint Signature = TLConstructors.TLInputReportReasonViolence; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLInputReportReasonPornography : TLInputReportReasonBase + { + public const uint Signature = TLConstructors.TLInputReportReasonPornography; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLInputReportReasonCopyright : TLInputReportReasonBase + { + public const uint Signature = TLConstructors.TLInputReportReasonCopyright; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLInputReportReasonOther : TLInputReportReasonBase + { + public const uint Signature = TLConstructors.TLInputReportReasonOther; + + public TLString Text { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), Text.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } +} diff --git a/Telegram.Api/TL/TLInputSingleMedia.cs b/Telegram.Api/TL/TLInputSingleMedia.cs new file mode 100755 index 0000000..1ecd9c0 --- /dev/null +++ b/Telegram.Api/TL/TLInputSingleMedia.cs @@ -0,0 +1,143 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum InputSingleMediaFlags + { + Entities = 0x1, // 0 + } + + public class TLInputSingleMedia76 : TLInputSingleMedia75 + { + public new const uint Signature = TLConstructors.TLInputSingleMedia76; + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Media.ToBytes(), + RandomId.ToBytes(), + Message.ToBytes(), + ToBytes(Entities, Flags, (int)InputSingleMediaFlags.Entities)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Media = GetObject(input); + RandomId = GetObject(input); + Message = GetObject(input); + Entities = GetObject>(Flags, (int)InputSingleMediaFlags.Entities, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Media.ToStream(output); + RandomId.ToStream(output); + Message.ToStream(output); + ToStream(output, Entities, Flags, (int)InputSingleMediaFlags.Entities); + } + } + + public class TLInputSingleMedia75 : TLInputSingleMedia + { + public new const uint Signature = TLConstructors.TLInputSingleMedia75; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLString Message { get; set; } + + protected TLVector _entities; + + public TLVector Entities + { + get { return _entities; } + set { SetField(out _entities, value, ref _flags, (int) InputSingleMediaFlags.Entities); } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Media.ToBytes(), + Flags.ToBytes(), + RandomId.ToBytes(), + Message.ToBytes(), + ToBytes(Entities, Flags, (int) InputSingleMediaFlags.Entities)); + } + + public override TLObject FromStream(Stream input) + { + Media = GetObject(input); + Flags = GetObject(input); + RandomId = GetObject(input); + Message = GetObject(input); + Entities = GetObject>(Flags, (int) InputSingleMediaFlags.Entities, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Media.ToStream(output); + Flags.ToStream(output); + RandomId.ToStream(output); + Message.ToStream(output); + ToStream(output, Entities, Flags, (int) InputSingleMediaFlags.Entities); + } + } + + public class TLInputSingleMedia : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInputSingleMedia; + + public TLInputMediaBase Media { get; set; } + + public TLLong RandomId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Media.ToBytes(), + RandomId.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Media = GetObject(input); + RandomId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Media.ToStream(output); + RandomId.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLInputStickerSet.cs b/Telegram.Api/TL/TLInputStickerSet.cs new file mode 100755 index 0000000..627fdff --- /dev/null +++ b/Telegram.Api/TL/TLInputStickerSet.cs @@ -0,0 +1,153 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputStickerSetBase : TLObject + { + public abstract string Name { get; } + } + + public class TLInputStickerSetEmpty : TLInputStickerSetBase + { + public const uint Signature = TLConstructors.TLInputStickerSetEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override string ToString() + { + return GetType().Name; + } + + public override string Name + { + get { return @"tlg/empty"; } + } + } + + public class TLInputStickerSetId : TLInputStickerSetBase + { + public const uint Signature = TLConstructors.TLInputStickerSetId; + + public TLLong Id { get; set; } + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + AccessHash.ToStream(output); + } + + public override string ToString() + { + return string.Format("{0} Id={1}", GetType().Name, Id); + } + + public override string Name + { + get { return Id.ToString(); } + } + } + + public class TLInputStickerSetShortName : TLInputStickerSetBase + { + public const uint Signature = TLConstructors.TLInputStickerSetShortName; + + public TLString ShortName { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ShortName = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + ShortName.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + ShortName = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + ShortName.ToStream(output); + } + + public override string ToString() + { + return string.Format("{0} ShortName={1}", GetType().Name, ShortName); + } + + public override string Name + { + get { return ShortName.ToString(); } + } + } +} diff --git a/Telegram.Api/TL/TLInputStickeredMedia.cs b/Telegram.Api/TL/TLInputStickeredMedia.cs new file mode 100755 index 0000000..8a77820 --- /dev/null +++ b/Telegram.Api/TL/TLInputStickeredMedia.cs @@ -0,0 +1,100 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLInputStickeredMediaBase : TLObject { } + + public class TLInputStickeredMediaPhoto : TLInputStickeredMediaBase + { + public const uint Signature = TLConstructors.TLInputStickeredMediaPhoto; + + public TLInputPhotoBase Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes() + ); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputStickeredMediaPhoto id=[{0}]", Id); + } + } + + public class TLInputStickeredMediaDocument : TLInputStickeredMediaBase + { + public const uint Signature = TLConstructors.TLInputStickeredMediaDocument; + + public TLInputDocumentBase Id { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes() + ); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLInputStickeredMediaDocument id=[{0}]", Id); + } + } +} diff --git a/Telegram.Api/TL/TLInputUser.cs b/Telegram.Api/TL/TLInputUser.cs new file mode 100755 index 0000000..481f7d2 --- /dev/null +++ b/Telegram.Api/TL/TLInputUser.cs @@ -0,0 +1,224 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public interface IInputUserId + { + TLInt UserId { get; set; } + } + + public abstract class TLInputUserBase : TLObject + { + } + + public class TLInputUserEmpty : TLInputUserBase + { + public const uint Signature = TLConstructors.TLInputUserEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override string ToString() + { + return "user_id=empty"; + } + } + + public class TLInputUserSelf : TLInputUserBase + { + public const uint Signature = TLConstructors.TLInputUserSelf; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override string ToString() + { + return "user_id=self"; + } + } + + public class TLInputUserContact : TLInputUserBase, IInputUserId + { + public const uint Signature = TLConstructors.TLInputUserContact; + + public TLInt UserId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(TLInputUser.Signature), + UserId.ToBytes(), + new TLLong(0).ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + UserId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + + return this; + } + + public override string ToString() + { + return "user_id=" + UserId; + } + } + + public class TLInputUserForeign : TLInputUserBase, IInputUserId + { + public const uint Signature = TLConstructors.TLInputUserForeign; + + public TLInt UserId { get; set; } + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(TLInputUser.Signature), + UserId.ToBytes(), + AccessHash.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + UserId.ToStream(output); + AccessHash.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + + public override string ToString() + { + return "user_id=" + UserId; + } + } + + public class TLInputUser : TLInputUserBase, IInputUserId + { + public const uint Signature = TLConstructors.TLInputUser; + + public TLInt UserId { get; set; } + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + UserId.ToBytes(), + AccessHash.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + UserId.ToStream(output); + AccessHash.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + AccessHash = GetObject(input); + + return this; + } + + public override string ToString() + { + return "user_id=" + UserId; + } + } +} diff --git a/Telegram.Api/TL/TLInputVideo.cs b/Telegram.Api/TL/TLInputVideo.cs new file mode 100755 index 0000000..e8dbc12 --- /dev/null +++ b/Telegram.Api/TL/TLInputVideo.cs @@ -0,0 +1,37 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLInputVideoBase : TLObject { } + + public class TLInputVideoEmpty : TLInputVideoBase + { + public const uint Signature = TLConstructors.TLInputVideoEmpty; + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + } + + public class TLInputVideo : TLInputVideoBase + { + public const uint Signature = TLConstructors.TLInputVideo; + + public TLLong Id { get; set; } + public TLLong AccessHash { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLInputWebDocument.cs b/Telegram.Api/TL/TLInputWebDocument.cs new file mode 100755 index 0000000..7a8a53c --- /dev/null +++ b/Telegram.Api/TL/TLInputWebDocument.cs @@ -0,0 +1,102 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using System.Linq; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLInputWebDocument : TLInputDocumentBase + { + public const uint Signature = TLConstructors.TLInputWebDocument; + + public TLString Url { get; set; } + + public TLInt Size { get; set; } + + public TLString MimeType { get; set; } + + public TLVector Attributes { get; set; } + + public TLInt W + { + get + { + var attributeSize = Attributes.FirstOrDefault(x => x is IAttributeSize) as IAttributeSize; + if (attributeSize != null) + { + return attributeSize.W; + } + + return null; + } + } + + public TLInt H + { + get + { + var attributeSize = Attributes.FirstOrDefault(x => x is IAttributeSize) as IAttributeSize; + if (attributeSize != null) + { + return attributeSize.H; + } + + return null; + } + } + + public TLInt Duration + { + get + { + var attributeDuration = Attributes.FirstOrDefault(x => x is IAttributeDuration) as IAttributeDuration; + if (attributeDuration != null) + { + return attributeDuration.Duration; + } + + return null; + } + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Url.ToBytes(), + Size.ToBytes(), + MimeType.ToBytes(), + Attributes.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + Size = GetObject(input); + MimeType = GetObject(input); + Attributes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Url.ToStream(output); + Size.ToStream(output); + MimeType.ToStream(output); + Attributes.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLInputWebDocument url={0}", Url); + } + } +} diff --git a/Telegram.Api/TL/TLInt.cs b/Telegram.Api/TL/TLInt.cs new file mode 100755 index 0000000..466b484 --- /dev/null +++ b/Telegram.Api/TL/TLInt.cs @@ -0,0 +1,71 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.IO; +using System.Runtime.Serialization; + +namespace Telegram.Api.TL +{ + [DataContract] + public class TLInt : TLObject + { + [DataMember] + public int Value { get; set; } + + public TLInt() { } + + public TLInt(int value) + { + Value = value; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + Value = BitConverter.ToInt32(bytes, position); + position += 4; + + return this; + } + + public override byte[] ToBytes() + { + return BitConverter.GetBytes(Value); + } + + public override TLObject FromStream(Stream input) + { + var buffer = new byte[4]; + input.Read(buffer, 0, 4); + Value = BitConverter.ToInt32(buffer, 0); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(BitConverter.GetBytes(Value), 0, 4); + } + + public override string ToString() + { + return Value.ToString(CultureInfo.InvariantCulture); + } + + private static readonly Random _random = new Random(); + + public static TLInt Random() + { + var randomNumber = new byte[4]; + var random = _random; + random.NextBytes(randomNumber); + return new TLInt { Value = BitConverter.ToInt32(randomNumber, 0) }; + } + + } +} diff --git a/Telegram.Api/TL/TLInt128.cs b/Telegram.Api/TL/TLInt128.cs new file mode 100755 index 0000000..12c17ad --- /dev/null +++ b/Telegram.Api/TL/TLInt128.cs @@ -0,0 +1,39 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Org.BouncyCastle.Security; +using Telegram.Api.Helpers; + +namespace Telegram.Api.TL +{ + public class TLInt128 : TLObject + { + public byte[] Value { get; set; } + + public override byte[] ToBytes() + { + return Value; + } + + public static TLInt128 Random() + { + var randomNumber = new byte[16]; + var random = new SecureRandom(); + random.NextBytes(randomNumber); + return new TLInt128{ Value = randomNumber }; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + Value = bytes.SubArray(position, 16); + position += 16; + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLInt256.cs b/Telegram.Api/TL/TLInt256.cs new file mode 100755 index 0000000..68ba189 --- /dev/null +++ b/Telegram.Api/TL/TLInt256.cs @@ -0,0 +1,38 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.Helpers; + +namespace Telegram.Api.TL +{ + public class TLInt256 : TLObject + { + public byte[] Value { get; set; } + + public override byte[] ToBytes() + { + return Value; + } + + public static TLInt256 Random() + { + var randomNumber = new byte[32]; + var random = new Random(); + random.NextBytes(randomNumber); + return new TLInt256 { Value = randomNumber }; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + Value = bytes.SubArray(position, 32); + position += 32; + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLInviteText.cs b/Telegram.Api/TL/TLInviteText.cs new file mode 100755 index 0000000..77d36e4 --- /dev/null +++ b/Telegram.Api/TL/TLInviteText.cs @@ -0,0 +1,25 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLInviteText : TLObject + { + public const uint Signature = TLConstructors.TLInviteText; + + public TLString Message { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLInvoice.cs b/Telegram.Api/TL/TLInvoice.cs new file mode 100755 index 0000000..ed70d9f --- /dev/null +++ b/Telegram.Api/TL/TLInvoice.cs @@ -0,0 +1,95 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum InvoiceFlags + { + Test = 0x1, // 0 + NameRequested = 0x2, // 1 + PhoneRequested = 0x4, // 2 + EmailRequested = 0x8, // 3 + ShippingAddressRequested = 0x10, // 4 + Flexible = 0x20, // 5 + } + + public class TLInvoice : TLInputMediaBase + { + public const uint Signature = TLConstructors.TLInvoice; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLString Currency { get; set; } + + public TLVector Prices { get; set; } + + public bool Test { get { return IsSet(Flags, (int) InvoiceFlags.Test); } } + + public bool NameRequested { get { return IsSet(Flags, (int) InvoiceFlags.NameRequested); } } + + public bool PhoneRequested { get { return IsSet(Flags, (int) InvoiceFlags.PhoneRequested); } } + + public bool EmailRequested { get { return IsSet(Flags, (int) InvoiceFlags.EmailRequested); } } + + public bool ShippingAddressRequested { get { return IsSet(Flags, (int) InvoiceFlags.ShippingAddressRequested); } } + + public bool Flexible { get { return IsSet(Flags, (int) InvoiceFlags.Flexible); } } + + #region Additional + + public bool ReceiverRequested { get { return NameRequested || PhoneRequested || EmailRequested; } } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Currency = GetObject(bytes, ref position); + Prices = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Currency.ToBytes(), + Prices.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Currency = GetObject(input); + Prices = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Currency.ToStream(output); + Prices.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLInvokeAfterMsg.cs b/Telegram.Api/TL/TLInvokeAfterMsg.cs new file mode 100755 index 0000000..e588b02 --- /dev/null +++ b/Telegram.Api/TL/TLInvokeAfterMsg.cs @@ -0,0 +1,26 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLInvokeAfterMsg : TLObject + { + public const uint Signature = TLConstructors.TLInvokeAfterMsg; + + public TLLong MsgId { get; set; } + + public TLObject Object { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + MsgId.ToBytes(), + Object.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLIpPort.cs b/Telegram.Api/TL/TLIpPort.cs new file mode 100755 index 0000000..819eec0 --- /dev/null +++ b/Telegram.Api/TL/TLIpPort.cs @@ -0,0 +1,53 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; + +namespace Telegram.Api.TL +{ + public class TLIpPort : TLObject + { + public TLInt Ip { get; set; } + + public TLInt Port { get; set; } + + public override string ToString() + { + return string.Format("TLIpPort ip={0}({1}) port={2}", GetIpString(), Ip, Port); + } + + public string GetIpString() + { + var ip = Ip.ToBytes(); + + return string.Format("{0}.{1}.{2}.{3}", ip[3], ip[2], ip[1], ip[0]); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + Ip = GetObject(bytes, ref position); + Port = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Ip = GetObject(input); + Port = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + Ip.ToStream(output); + Port.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLKeyboardButton.cs b/Telegram.Api/TL/TLKeyboardButton.cs new file mode 100755 index 0000000..bf9e7a0 --- /dev/null +++ b/Telegram.Api/TL/TLKeyboardButton.cs @@ -0,0 +1,425 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum KeyboardButtonSwitchInlineFlags + { + SamePeer = 0x1, // 0 + } + + public abstract class TLKeyboardButtonBase : TLObject + { + public TLString Text { get; set; } + } + + public class TLKeyboardButton : TLKeyboardButtonBase + { + public const uint Signature = TLConstructors.TLKeyboardButton; + + public TLKeyboardButton() { } + + public TLKeyboardButton(TLString text) + { + Text = text; + } + + public override string ToString() + { + return string.Format("TLKeyboardButton text={0}", Text); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Text.ToBytes()); + } + } + + public class TLKeyboardButtonUrl : TLKeyboardButtonBase + { + public const uint Signature = TLConstructors.TLKeyboardButtonUrl; + + public TLString Url { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + Url = GetObject(bytes, ref position); + + return this; + } + + public override string ToString() + { + return string.Format("TLKeyboardButtonUrl text={0} url={1}", Text, Url); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes(), + Url.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + Url = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Text.ToBytes()); + output.Write(Url.ToBytes()); + } + } + + public class TLKeyboardButtonCallback : TLKeyboardButtonBase + { + public const uint Signature = TLConstructors.TLKeyboardButtonCallback; + + public TLString Data { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + Data = GetObject(bytes, ref position); + + return this; + } + + public override string ToString() + { + return string.Format("TLKeyboardButtonCallback text={0} data={1}", Text, Data); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes(), + Data.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + Data = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Text.ToBytes()); + output.Write(Data.ToBytes()); + } + } + + public class TLKeyboardButtonRequestPhone : TLKeyboardButtonBase + { + public const uint Signature = TLConstructors.TLKeyboardButtonRequestPhone; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override string ToString() + { + return string.Format("TLKeyboardButtonRequestPhone text={0}", Text); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Text.ToBytes()); + } + } + + public class TLKeyboardButtonRequestGeoLocation : TLKeyboardButtonBase + { + public const uint Signature = TLConstructors.TLKeyboardButtonRequestGeoLocation; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override string ToString() + { + return string.Format("TLKeyboardButtonRequestLocation text={0}", Text); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Text.ToBytes()); + } + } + + public class TLKeyboardButtonSwitchInline : TLKeyboardButtonBase + { + public const uint Signature = TLConstructors.TLKeyboardButtonSwitchInline; + + public TLString Query { get; set; } + + #region Additional + public TLUser Bot { get; set; } + #endregion + + public override string ToString() + { + return string.Format("TLKeyboardButtonSwitchInline text={0} query={1}", Text, Query); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + Query = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes(), + Query.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + Query = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Text.ToBytes()); + output.Write(Query.ToBytes()); + } + } + + public class TLKeyboardButtonSwitchInline55 : TLKeyboardButtonSwitchInline + { + public new const uint Signature = TLConstructors.TLKeyboardButtonSwitchInline55; + + public TLInt Flags { get; set; } + + public bool IsSamePeer { get { return IsSet(Flags, (int) KeyboardButtonSwitchInlineFlags.SamePeer); } } + + public static string KeyboardButtonSwitchInlineFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (KeyboardButtonSwitchInlineFlags) flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public override string ToString() + { + return string.Format("TLKeyboardButtonSwitchInline55 flags={0} text={1} query={2}", KeyboardButtonSwitchInlineFlagsString(Flags), Text, Query); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Text = GetObject(bytes, ref position); + Query = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Text.ToBytes(), + Query.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Text = GetObject(input); + Query = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + output.Write(Text.ToBytes()); + output.Write(Query.ToBytes()); + } + } + + public class TLKeyboardButtonGame : TLKeyboardButtonBase + { + public const uint Signature = TLConstructors.TLKeyboardButtonGame; + + public override string ToString() + { + return string.Format("TLKeyboardButtonGame text={0}", Text); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Text.ToBytes()); + } + } + + public class TLKeyboardButtonBuy : TLKeyboardButtonBase + { + public const uint Signature = TLConstructors.TLKeyboardButtonBuy; + + public override string ToString() + { + return string.Format("TLKeyboardButtonBuy text={0}", Text); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Text.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLKeyboardButtonRow.cs b/Telegram.Api/TL/TLKeyboardButtonRow.cs new file mode 100755 index 0000000..b89b031 --- /dev/null +++ b/Telegram.Api/TL/TLKeyboardButtonRow.cs @@ -0,0 +1,48 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLKeyboardButtonRow : TLObject + { + public const uint Signature = TLConstructors.TLKeyboardButtonRow; + + public TLVector Buttons { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Buttons = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Buttons.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Buttons = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Buttons.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLLabeledPrice.cs b/Telegram.Api/TL/TLLabeledPrice.cs new file mode 100755 index 0000000..b167aa0 --- /dev/null +++ b/Telegram.Api/TL/TLLabeledPrice.cs @@ -0,0 +1,58 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLLabeledPrice : TLObject + { + public const uint Signature = TLConstructors.TLLabeledPrice; + + public TLString Label { get; set; } + + public TLLong Amount { get; set; } + + #region Additional + public TLString Currency { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Label = GetObject(bytes, ref position); + Amount = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Label.ToBytes(), + Amount.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Label = GetObject(input); + Amount = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Label.ToStream(output); + Amount.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLLangPackDifference.cs b/Telegram.Api/TL/TLLangPackDifference.cs new file mode 100755 index 0000000..8ab32d6 --- /dev/null +++ b/Telegram.Api/TL/TLLangPackDifference.cs @@ -0,0 +1,56 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLLangPackDifference : TLObject + { + public const uint Signature = TLConstructors.TLLangPackDifference; + + public TLString LangCode { get; set; } + + public TLInt FromVersion { get; set; } + + public TLInt Version { get; set; } + + public TLVector Strings { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + LangCode = GetObject(bytes, ref position); + FromVersion = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + Strings = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + LangCode.ToStream(output); + FromVersion.ToStream(output); + Version.ToStream(output); + Strings.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + LangCode = GetObject(input); + FromVersion = GetObject(input); + Version = GetObject(input); + Strings = GetObject>(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLLangPackLanguage.cs b/Telegram.Api/TL/TLLangPackLanguage.cs new file mode 100755 index 0000000..179a8fd --- /dev/null +++ b/Telegram.Api/TL/TLLangPackLanguage.cs @@ -0,0 +1,51 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLLangPackLanguage : TLObject + { + public const uint Signature = TLConstructors.TLLangPackLanguage; + + public TLString Name { get; set; } + + public TLString NativeName { get; set; } + + public TLString LangCode { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Name = GetObject(bytes, ref position); + NativeName = GetObject(bytes, ref position); + LangCode = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Name.ToStream(output); + NativeName.ToStream(output); + LangCode.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Name = GetObject(input); + NativeName = GetObject(input); + LangCode = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLLangPackString.cs b/Telegram.Api/TL/TLLangPackString.cs new file mode 100755 index 0000000..0f26cfc --- /dev/null +++ b/Telegram.Api/TL/TLLangPackString.cs @@ -0,0 +1,195 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum LangPackStringPluralizedFlags + { + ZeroValue = 0x1, // 0 + OneValue = 0x2, // 1 + TwoValue = 0x4, // 2 + FewValue = 0x8, // 3 + ManyValue = 0x10, // 4 + OtherValue = 0x20, // 5 + } + + public abstract class TLLangPackStringBase : TLObject { } + + public class TLLangPackString : TLLangPackStringBase + { + public const uint Signature = TLConstructors.TLLangPackString; + + public TLString Key { get; set; } + + public TLString Value { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Key = GetObject(bytes, ref position); + Value = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Key.ToStream(output); + Value.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Key = GetObject(input); + Value = GetObject(input); + + return this; + } + } + + public class TLLangPackStringPluralized : TLLangPackStringBase + { + public const uint Signature = TLConstructors.TLLangPackStringPluralized; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLString Key { get; set; } + + private TLString _zeroValue; + + public TLString ZeroValue + { + get { return _zeroValue; } + set { SetField(out _zeroValue, value, ref _flags, (int) LangPackStringPluralizedFlags.ZeroValue); } + } + + private TLString _oneValue; + + public TLString OneValue + { + get { return _oneValue; } + set { SetField(out _oneValue, value, ref _flags, (int)LangPackStringPluralizedFlags.OneValue); } + } + + private TLString _twoValue; + + public TLString TwoValue + { + get { return _twoValue; } + set { SetField(out _twoValue, value, ref _flags, (int)LangPackStringPluralizedFlags.TwoValue); } + } + + private TLString _fewValue; + + public TLString FewValue + { + get { return _fewValue; } + set { SetField(out _fewValue, value, ref _flags, (int)LangPackStringPluralizedFlags.FewValue); } + } + + private TLString _manyValue; + + public TLString ManyValue + { + get { return _manyValue; } + set { SetField(out _manyValue, value, ref _flags, (int)LangPackStringPluralizedFlags.ManyValue); } + } + + private TLString _otherValue; + + public TLString OtherValue + { + get { return _otherValue; } + set { SetField(out _otherValue, value, ref _flags, (int)LangPackStringPluralizedFlags.OtherValue); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Key = GetObject(bytes, ref position); + ZeroValue = GetObject(Flags, (int)LangPackStringPluralizedFlags.ZeroValue, null, bytes, ref position); + OneValue = GetObject(Flags, (int)LangPackStringPluralizedFlags.OneValue, null, bytes, ref position); + TwoValue = GetObject(Flags, (int)LangPackStringPluralizedFlags.TwoValue, null, bytes, ref position); + FewValue = GetObject(Flags, (int)LangPackStringPluralizedFlags.FewValue, null, bytes, ref position); + ManyValue = GetObject(Flags, (int)LangPackStringPluralizedFlags.ManyValue, null, bytes, ref position); + OtherValue = GetObject(Flags, (int)LangPackStringPluralizedFlags.OtherValue, null, bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Key.ToStream(output); + ToStream(output, ZeroValue, Flags, (int)LangPackStringPluralizedFlags.ZeroValue); + ToStream(output, OneValue, Flags, (int)LangPackStringPluralizedFlags.OneValue); + ToStream(output, TwoValue, Flags, (int)LangPackStringPluralizedFlags.TwoValue); + ToStream(output, FewValue, Flags, (int)LangPackStringPluralizedFlags.FewValue); + ToStream(output, ManyValue, Flags, (int)LangPackStringPluralizedFlags.ManyValue); + ToStream(output, OtherValue, Flags, (int)LangPackStringPluralizedFlags.OtherValue); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Key = GetObject(input); + ZeroValue = GetObject(Flags, (int)LangPackStringPluralizedFlags.ZeroValue, null, input); + OneValue = GetObject(Flags, (int)LangPackStringPluralizedFlags.OneValue, null, input); + TwoValue = GetObject(Flags, (int)LangPackStringPluralizedFlags.TwoValue, null, input); + FewValue = GetObject(Flags, (int)LangPackStringPluralizedFlags.FewValue, null, input); + ManyValue = GetObject(Flags, (int)LangPackStringPluralizedFlags.ManyValue, null, input); + OtherValue = GetObject(Flags, (int)LangPackStringPluralizedFlags.OtherValue, null, input); + + return this; + } + } + + public class TLLangPackStringDeleted : TLLangPackStringBase + { + public const uint Signature = TLConstructors.TLLangPackStringDeleted; + + public TLString Key { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Key = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Key.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Key = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLLink.cs b/Telegram.Api/TL/TLLink.cs new file mode 100755 index 0000000..c69dc83 --- /dev/null +++ b/Telegram.Api/TL/TLLink.cs @@ -0,0 +1,91 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLLinkBase : TLObject + { + public TLUserBase User { get; set; } + } + + public class TLLink : TLLinkBase + { + public const uint Signature = TLConstructors.TLLink; + + public TLMyLinkBase MyLink { get; set; } + public TLForeignLinkBase ForeignLink { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + MyLink = GetObject(bytes, ref position); + ForeignLink = GetObject(bytes, ref position); + User = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + MyLink = GetObject(input); + ForeignLink = GetObject(input); + User = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + MyLink.ToStream(output); + ForeignLink.ToStream(output); + User.ToStream(output); + } + } + + public class TLLink24 : TLLinkBase + { + public const uint Signature = TLConstructors.TLLink24; + + public TLContactLinkBase MyLink { get; set; } + public TLContactLinkBase ForeignLink { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + MyLink = GetObject(bytes, ref position); + ForeignLink = GetObject(bytes, ref position); + User = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + MyLink = GetObject(input); + ForeignLink = GetObject(input); + User = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + MyLink.ToStream(output); + ForeignLink.ToStream(output); + User.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLLong.cs b/Telegram.Api/TL/TLLong.cs new file mode 100755 index 0000000..74a34b0 --- /dev/null +++ b/Telegram.Api/TL/TLLong.cs @@ -0,0 +1,91 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.IO; +using System.Runtime.Serialization; +using Org.BouncyCastle.Security; + +namespace Telegram.Api.TL +{ + [DataContract] + public class TLLong : TLObject + { + [DataMember] + public Int64 Value { get; set; } + + public TLLong() + { + + } + + public TLLong(long value) + { + Value = value; + } + + private static readonly object _randomSyncRoot = new object(); + + private static Random _random; + + public static TLLong Random() + { + //System.Diagnostics.Debug.WriteLine("TLLong.Random 1"); + var randomNumber = new byte[8]; + lock (_randomSyncRoot) + { + //System.Diagnostics.Debug.WriteLine("TLLong.Random 2"); + if (_random == null) + { + //System.Diagnostics.Debug.WriteLine("TLLong.Random 3"); + _random = new Random(); // Note: SecureRandom doesnt work with Creators Update + //System.Diagnostics.Debug.WriteLine("TLLong.Random 4"); + } + + //System.Diagnostics.Debug.WriteLine("TLLong.Random 5"); + _random.NextBytes(randomNumber); + } + + //System.Diagnostics.Debug.WriteLine("TLLong.Random 6"); + + return new TLLong { Value = BitConverter.ToInt64(randomNumber, 0) }; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + Value = BitConverter.ToInt64(bytes, position); + position += 8; + + return this; + } + + public override byte[] ToBytes() + { + return BitConverter.GetBytes(Value); + } + + public override TLObject FromStream(Stream input) + { + var buffer = new byte[8]; + input.Read(buffer, 0, 8); + Value = BitConverter.ToInt64(buffer, 0); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(BitConverter.GetBytes(Value), 0, 8); + } + + public override string ToString() + { + return Value.ToString(CultureInfo.InvariantCulture);// + " " + TLUtils.MessageIdString(this); + } + } +} diff --git a/Telegram.Api/TL/TLMaskCoords.cs b/Telegram.Api/TL/TLMaskCoords.cs new file mode 100755 index 0000000..1ea1916 --- /dev/null +++ b/Telegram.Api/TL/TLMaskCoords.cs @@ -0,0 +1,81 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLMaskCoords : TLObject + { + public const uint Signature = TLConstructors.TLMaskCoords; + + public TLInt N { get; set; } + + public TLDouble X { get; set; } + + public TLDouble Y { get; set; } + + public TLDouble Zoom { get; set; } + + public TLMaskCoords() + { + + } + + public TLMaskCoords(int n, double x, double y, double zoom) + { + N = new TLInt(n); + X = new TLDouble(x); + Y = new TLDouble(y); + Zoom = new TLDouble(zoom); + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + N.ToBytes(), + X.ToBytes(), + Y.ToBytes(), + Zoom.ToBytes() + ); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + N = GetObject(bytes, ref position); + X = GetObject(bytes, ref position); + Y = GetObject(bytes, ref position); + Zoom = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + N.ToStream(output); + X.ToStream(output); + Y.ToStream(output); + Zoom.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + N = GetObject(input); + X = GetObject(input); + Y = GetObject(input); + Zoom = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLMessage.Encrypted.cs b/Telegram.Api/TL/TLMessage.Encrypted.cs new file mode 100755 index 0000000..354ca71 --- /dev/null +++ b/Telegram.Api/TL/TLMessage.Encrypted.cs @@ -0,0 +1,104 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLEncryptedMessageBase : TLObject + { + public TLLong RandomId { get; set; } + + public TLInt ChatId { get; set; } + + public TLInt Date { get; set; } + + public TLString Bytes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + RandomId = GetObject(bytes, ref position); + ChatId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Bytes = GetObject(bytes, ref position); + + return this; + } + } + + public class TLEncryptedMessage : TLEncryptedMessageBase + { + public const uint Signature = TLConstructors.TLEncryptedMessage; + + public TLEncryptedFileBase File { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + base.FromBytes(bytes, ref position); + File = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + RandomId.ToStream(output); + ChatId.ToStream(output); + Date.ToStream(output); + Bytes.ToStream(output); + File.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + RandomId = GetObject(input); + ChatId = GetObject(input); + Date = GetObject(input); + Bytes = GetObject(input); + File = GetObject(input); + + return this; + } + } + + public class TLEncryptedMessageService : TLEncryptedMessageBase + { + public const uint Signature = TLConstructors.TLEncryptedMessageService; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + base.FromBytes(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + RandomId.ToStream(output); + ChatId.ToStream(output); + Date.ToStream(output); + Bytes.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + RandomId = GetObject(input); + ChatId = GetObject(input); + Date = GetObject(input); + Bytes = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLMessage.cs b/Telegram.Api/TL/TLMessage.cs new file mode 100755 index 0000000..a3039b4 --- /dev/null +++ b/Telegram.Api/TL/TLMessage.cs @@ -0,0 +1,4903 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows; +#if WIN_RT +using Windows.UI.Xaml; +#endif +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.Extensions; +using Telegram.Api.TL.Interfaces; +using Telegram.Logs; + +namespace Telegram.Api.TL +{ + public enum MessageStatus + { + Sending = 1, + Confirmed = 0, + Failed = 2, + Read = 3, + Broadcast = 4, + Compressing = 5, + } + + [Flags] + public enum MessageCustomFlags + { + FwdMessageId = 0x1, + FwdFromChannelPeer = 0x2, + BotInlineResult = 0x4, + Documents = 0x8, + InputPeer = 0x10, + } + + [Flags] + public enum MessageFlags + { + Unread = 0x1, // 0 + Out = 0x2, // 1 + FwdFrom = 0x4, // 2 + ReplyToMsgId = 0x8, // 3 + Mentioned = 0x10, // 4 + MediaUnread = 0x20, // 5 + ReplyMarkup = 0x40, // 6 + Entities = 0x80, // 7 + FromId = 0x100, // 8 + Media = 0x200, // 9 + Views = 0x400, // 10 + ViaBotId = 0x800, // 11 + + Silent = 0x2000, // 13 + Post = 0x4000, // 14 + EditDate = 0x8000, // 15 + PostAuthor = 0x10000, // 16 + GroupedId = 0x20000, // 17 + } + + public interface IReplyToMsgId + { + TLInt ReplyToMsgId { get; set; } + TLMessageBase Reply { get; set; } + ReplyInfo ReplyInfo { get; } + TLPeerBase ToId { get; set; } + } + + public abstract class TLMessageBase : TLObject, ISelectable + { + public virtual TLObject FwdFrom { get; set; } + + public virtual Visibility ViaBotVisibility { get { return Visibility.Collapsed; } } + + public virtual Visibility ReplyOrViaBotVisibility { get { return Visibility.Collapsed; } } + + public virtual Visibility FwdViaBotVisibility { get { return Visibility.Collapsed; } } + + public virtual TLUserBase ViaBot { get { return null; } } + + public static string MessageFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (MessageFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public static string MessageCustomFlagsString(TLLong flags) + { + if (flags == null) return string.Empty; + + var list = (MessageCustomFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public abstract int DateIndex { get; set; } + + private TLLong _randomId; + + public TLLong RandomId + { + get { return _randomId; } + set + { + _randomId = value; + } + } + + public long RandomIndex + { + get { return RandomId != null ? RandomId.Value : 0; } + set { RandomId = new TLLong(value); } + } + + /// + /// Message Id + /// + public TLInt Id { get; set; } + + public int Index + { + get { return Id != null ? Id.Value : 0; } + set { Id = new TLInt(value); } + } + + public virtual void Update(TLMessageBase message) + { + Id = message.Id; + Status = message.Status; + } + + public override string ToString() + { + return "Id=" + Index + " RndId=" + RandomIndex; + } + + #region Additional + + public string WebPageTitle { get; set; } + + public bool NoWebpage { get; set; } + + public virtual TLMessageBase Reply { get; set; } + + public virtual ReplyInfo ReplyInfo + { + get { return null; } + } + + public virtual Visibility ReplyVisibility { get { return Visibility.Collapsed; } } + + public virtual double MediaWidth { get { return 12.0 + 311.0 + 12.0; } } + + public MessageStatus _status; + + public virtual MessageStatus Status + { + get { return _status; } + set { _status = value; } + } + + public bool _isAnimated; + + public virtual bool ShowFrom + { + get { return false; } + } + + private bool _isSelected; + + public bool IsSelected + { + get { return _isSelected; } + set { SetField(ref _isSelected, value, () => IsSelected); } + } + + public abstract Visibility SelectionVisibility { get; } + + private bool _isHighlighted; + + public bool IsHighlighted + { + get { return _isHighlighted; } + set { SetField(ref _isHighlighted, value, () => IsHighlighted); } + } + + public virtual int MediaSize { get { return 0; } } + + public virtual Visibility MediaSizeVisibility { get { return Visibility.Collapsed; } } + + public virtual bool IsSelf() + { + return false; + } + + public virtual bool IsAudioVideoMessage() + { + return false; + } + + public virtual bool HasTTL() + { + return false; + } + + public static bool HasTTL(TLMessageMediaBase mediaBase) + { + var mediaPhoto = mediaBase as TLMessageMediaPhoto70; + if (mediaPhoto != null + && mediaPhoto.TTLSeconds != null + && mediaPhoto.TTLSeconds.Value > 0) + { + return true; + } + + var mediaDocument = mediaBase as TLMessageMediaDocument70; + if (mediaDocument != null + && mediaDocument.TTLSeconds != null + && mediaDocument.TTLSeconds.Value > 0) + { + return true; + } + + return false; + } + + public virtual bool IsExpired() + { + return false; + } + + public static bool IsExpired(TLMessageMediaBase mediaBase) + { + var mediaPhoto = mediaBase as TLMessageMediaPhoto70; + if (mediaPhoto != null + && mediaPhoto.Photo == null + && mediaPhoto.TTLSeconds != null + && mediaPhoto.TTLSeconds.Value > 0) + { + return true; + } + + var mediaDocument = mediaBase as TLMessageMediaDocument70; + if (mediaDocument != null + && mediaDocument.Document == null + && mediaDocument.TTLSeconds != null + && mediaDocument.TTLSeconds.Value > 0) + { + return true; + } + + return false; + } + + public virtual bool IsSticker() + { + return false; + } + + public static bool IsSticker(TLDocumentBase document) + { +#if WP8 + var document22 = document as TLDocument22; + if (document22 != null + && document22.DocumentSize > 0 + && document22.DocumentSize < Constants.StickerMaxSize) + { + var documentStickerAttribute = document22.Attributes.FirstOrDefault(x => x is TLDocumentAttributeSticker); + + if (documentStickerAttribute != null + && string.Equals(document22.MimeType.ToString(), "image/webp", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } +#endif + + return false; + } + + public static bool IsSticker(IAttributes attributes, TLInt size) + { +#if WP8 + if (size != null + && size.Value > 0 + && size.Value < Constants.StickerMaxSize) + { + var documentStickerAttribute = attributes.Attributes.FirstOrDefault(x => x is TLDocumentAttributeSticker); + + if (documentStickerAttribute != null) + { + return true; + } + } +#endif + + return false; + } + + public virtual bool IsGif() + { + return false; + } + + public static bool IsGif(IAttributes attributes, TLInt size) + { +#if WP8 + if (size == null + || (size.Value > 0 + && size.Value < Constants.GifMaxSize)) + { + var animatedAttribute = attributes.Attributes.FirstOrDefault(x => x is TLDocumentAttributeAnimated); + var videoAttribute = attributes.Attributes.FirstOrDefault(x => x is TLDocumentAttributeVideo); + if (animatedAttribute != null + && videoAttribute != null) + { + return true; + } + } +#endif + + return false; + } + + public static bool IsGif(TLDocumentBase document) + { +#if WP8 + var document22 = document as TLDocument22; + if (document22 != null && TLString.Equals(document22.MimeType, new TLString("video/mp4"), StringComparison.OrdinalIgnoreCase)) + { + return IsGif(document22, document22.Size); + } + + var documentExternal = document as TLDocumentExternal; + if (documentExternal != null + && string.Equals(documentExternal.Type.ToString(), "gif", StringComparison.OrdinalIgnoreCase)) + { + return IsGif(documentExternal, null); + } +#endif + + return false; + } + + public virtual bool IsMusic() + { + return false; + } + + public static bool IsMusic(IAttributes attributes, TLInt size) + { +#if WP8 + if (size == null || size.Value > 0) + { + var audioAttribute = attributes.Attributes.FirstOrDefault(x => x is TLDocumentAttributeAudio46) as TLDocumentAttributeAudio46; + if (audioAttribute != null && !audioAttribute.Voice) + { + return true; + } + } +#endif + + return false; + } + + public static bool IsMusic(TLDocumentBase document) + { +#if WP8 + var document22 = document as TLDocument22; + if (document22 != null) + { + return IsMusic(document22, document22.Size); + } +#endif + + return false; + } + + public virtual bool IsVoice() + { + return false; + } + + public static bool IsVoice(IAttributes attributes, TLInt size) + { +#if WP8 + //if (size == null || size.Value > 0) // TLInlineBotResult non cached voice with unknown size + { + var audioAttribute = attributes.Attributes.FirstOrDefault(x => x is TLDocumentAttributeAudio46) as TLDocumentAttributeAudio46; + if (audioAttribute != null && audioAttribute.Voice) + { + return true; + } + } +#endif + + return false; + } + + public static bool IsVoice(TLDocumentBase document) + { +#if WP8 + var document22 = document as TLDocument22; + if (document22 != null) + { + return IsVoice(document22, document22.Size); + } +#endif + + return false; + } + + public virtual bool IsRoundVideo() + { + return false; + } + + public static bool IsRoundVideo(IAttributes attributes, TLInt size) + { +#if WP8 + if (size == null || size.Value > 0) + { + var videoAttribute = attributes.Attributes.FirstOrDefault(x => x is TLDocumentAttributeVideo66) as TLDocumentAttributeVideo66; + var animatedAttribute = attributes.Attributes.FirstOrDefault(x => x is TLDocumentAttributeAnimated) as TLDocumentAttributeAnimated; + if (videoAttribute != null && animatedAttribute == null) + { + return videoAttribute.RoundMessage; + } + } +#endif + + return false; + } + + public static bool IsRoundVideo(TLDocumentBase document) + { +#if WP8 + var document22 = document as TLDocument22; + if (document22 != null) + { + return IsRoundVideo(document22, document22.Size); + } +#endif + + return false; + } + + public virtual bool IsVideo() + { + return false; + } + + public static bool IsVideo(IAttributes attributes, TLInt size) + { +#if WP8 + if (size == null || size.Value > 0) + { + var videoAttribute = attributes.Attributes.FirstOrDefault(x => x is TLDocumentAttributeVideo) as TLDocumentAttributeVideo; + var animatedAttribute = attributes.Attributes.FirstOrDefault(x => x is TLDocumentAttributeAnimated) as TLDocumentAttributeAnimated; + if (videoAttribute != null && animatedAttribute == null) + { + return true; + } + } +#endif + + return false; + } + + public static bool IsVideo(TLDocumentBase document) + { +#if WP8 + var document22 = document as TLDocument22; + if (document22 != null) + { + return IsVideo(document22, document22.Size); + } +#endif + + return false; + } + + public TLMessageBase Self { get { return this; } } + + public bool ShowSeparator { get; set; } + + #endregion + + public virtual void Edit(TLMessageBase messageBase) + { + + } + } + + public class ReplyInfo + { + public TLInt ReplyToMsgId { get; set; } + + public TLLong ReplyToRandomMsgId { get; set; } + + public TLObject Reply { get; set; } + } + + public abstract class TLMessageCommon : TLMessageBase + { + private TLInt _fromId; + + public virtual TLInt FromId + { + get { return _fromId; } + set { _fromId = value; } + } + + public TLPeerBase ToId { get; set; } + + public virtual TLBool Out { get; set; } + + private TLBool _unread; + + public virtual void SetUnread(TLBool value) + { + _unread = value; + } + + public virtual void SetUnreadSilent(TLBool value) + { + _unread = value; + } + + public virtual TLBool Unread + { + get { return _unread; } + set + { + SetField(ref _unread, value, () => Unread); + NotifyOfPropertyChange(() => Status); + } + } + + public bool IsChannelMessage + { + get + { + if (FromId == null || FromId.Value <= 0) return true; + + if (ToId is TLPeerChannel) + { + var cacheService = InMemoryCacheService.Instance; + var channel = cacheService.GetChat(ToId.Id) as TLChannel; + if (channel != null && channel.IsBroadcast) return true; + } + + return false; + } + } + + public override MessageStatus Status + { + get + { + if (_status == MessageStatus.Broadcast) + { + return _status; + } + + if (!Unread.Value) + { + return MessageStatus.Read; + } + + return _status; + } + set + { + if (_status == MessageStatus.Broadcast) return; + if (_status == MessageStatus.Read) return; + + //System.Diagnostics.Debug.WriteLine("SetStatus hash={0} status={1}", GetHashCode(), value); + + SetField(ref _status, value, () => Status); + } + } + + public override int DateIndex + { + get { return Date.Value; } + set { Date = new TLInt(value); } + } + + public TLInt _date; + + public TLInt Date + { + get { return _date; } + set { _date = value; } + } + + public virtual Visibility ShareButtonVisibility { get { return Visibility.Collapsed; } } + + public override bool IsSelf() + { + var peerUser = ToId as TLPeerUser; + if (peerUser != null) + { + return FromId.Value != -1 && FromId.Value == peerUser.Id.Value; + } + + return false; + } + + public override string ToString() + { + string dateTimeString = null; + try + { + var clientDelta = MTProtoService.Instance.ClientTicksDelta; + //var utc0SecsLong = Date.Value * 4294967296 - clientDelta; + var utc0SecsInt = Date.Value - clientDelta / 4294967296.0; + DateTime? dateTime = Helpers.Utils.UnixTimestampToDateTime(utc0SecsInt); + dateTimeString = dateTime.Value.ToString("H:mm:ss dd.MM"); + } + catch (Exception ex) + { + + } + + return base.ToString() + string.Format(" [{0} {4}] FromId={1} ToId=[{2}] U={3} S={5}", Date, FromId, ToId, Unread, dateTimeString, Status); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + FromId = GetObject(bytes, ref position); + ToId = GetObject(bytes, ref position); + Out = GetObject(bytes, ref position); + _unread = GetObject(bytes, ref position); + _date = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + FromId = GetObject(input); + ToId = GetObject(input); + Out = GetObject(input); + _unread = GetObject(input); + _date = GetObject(input); + + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + var status = GetObject(input); + Status = (MessageStatus)status.Value; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(FromId.ToBytes()); + ToId.ToStream(output); + output.Write(Out.ToBytes()); + output.Write(Unread.ToBytes()); + output.Write(Date.ToBytes()); + + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + } + + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = (TLMessageCommon)message; + FromId = m.FromId; + ToId = m.ToId; + Out = m.Out; + if (Unread.Value != m.Unread.Value) + { + if (Unread.Value) + { + _unread = m.Unread; + } + } + _date = m.Date; + } + + #region Additional + + protected TLObject _from; + + public virtual TLObject From + { + get + { + if (_from != null) return _from; + + var cacheService = InMemoryCacheService.Instance; + + if (FromId == null || FromId.Value <= 0) + { + _from = cacheService.GetChat(ToId.Id); + return _from; + } + if (ToId is TLPeerChannel) + { + var channel = cacheService.GetChat(ToId.Id) as TLChannel; + if (channel != null && !channel.IsMegaGroup) + { + _from = channel; + return _from; + } + } + + _from = cacheService.GetUser(FromId); + return _from; + } + } + + protected TLObject _to; + + public virtual TLObject To + { + get + { + if (_to != null) return _to; + + var cacheService = InMemoryCacheService.Instance; + + if (ToId is TLPeerUser) + { + var user = cacheService.GetUser(ToId.Id); + if (user != null) + { + _to = user; + return _to; + } + } + if (ToId is TLPeerChat) + { + var chat = cacheService.GetChat(ToId.Id); + if (chat != null) + { + _to = chat; + return _to; + } + } + if (ToId is TLPeerChannel) + { + var channel = cacheService.GetChat(ToId.Id); + if (channel != null) + { + _to = channel; + return _to; + } + } + + return null; + } + } + + + public override bool ShowFrom + { + get + { + if (this is TLMessageService) + { + return false; + } + + if (FromId == null || FromId.Value <= 0) + { + return false; + } + + if (ToId is TLPeerChat) return true; + + if (ToId is TLPeerChannel) + { + var cacheService = InMemoryCacheService.Instance; + var channel = cacheService.GetChat(ToId.Id) as TLChannel; + if (channel != null && channel.IsMegaGroup) return true; + } + + return false; + } + } + #endregion + } + + public class TLMessageEmpty : TLMessageBase + { + public const uint Signature = TLConstructors.TLMessageEmpty; + + public override int DateIndex { get; set; } + + public override string ToString() + { + return base.ToString() + ", TLMessageEmpty"; + } + + public override Visibility SelectionVisibility + { + get { return Visibility.Collapsed; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + RandomId = GetObject(input) as TLLong; + var status = GetObject(input); + _status = (MessageStatus)status.Value; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id = Id ?? new TLInt(0); + output.Write(Id.ToBytes()); + + RandomId.NullableToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + } + } + + public class TLMessagesContainter : TLMessageBase + { + public const uint Signature = TLConstructors.TLMessagesContainter; + + public TLMessageMediaBase WebPageMedia { get; set; } + + public TLVector FwdMessages { get; set; } + + public bool WithMyScore { get; set; } + + public TLMessage25 EditMessage { get; set; } + + public int EditUntil { get; set; } + + public string EditTimerString + { + get + { + var editUntil = EditUntil; + var now = TLUtils.DateToUniversalTimeTLInt(MTProtoService.Instance.ClientTicksDelta, DateTime.Now).Value; + + if (editUntil < now) + { + return string.Empty; + } + + var timeSpan = TimeSpan.FromSeconds(editUntil - now); + if (timeSpan.TotalMinutes > 5.0) + { + return string.Empty; + } + + if (timeSpan.TotalDays > 1.0) + { + return string.Format("({0})", TimeSpan.FromSeconds(editUntil - now)); + } + + if (timeSpan.TotalHours > 1.0) + { + return string.Format("({0:hh\\:mm\\:ss})", TimeSpan.FromSeconds(editUntil - now)); + } + + return string.Format("({0:mm\\:ss})", TimeSpan.FromSeconds(editUntil - now)); + } + } + + public override int DateIndex { get; set; } + + public override Visibility SelectionVisibility + { + get { return Visibility.Collapsed; } + } + + public TLObject From + { + get + { + if (FwdMessages != null && FwdMessages.Count > 0) + { + var fwdMessage48 = FwdMessages[0] as TLMessage48; + if (fwdMessage48 != null) + { + var fwdHeader = fwdMessage48.FwdHeader; + if (fwdHeader != null) + { + var cacheService = InMemoryCacheService.Instance; + if (fwdHeader.ChannelId != null) + { + return cacheService.GetChat(fwdHeader.ChannelId); + } + + if (fwdHeader.FromId != null) + { + return cacheService.GetUser(fwdHeader.FromId); + } + } + } + + var fwdMessage = FwdMessages[0] as TLMessage40; + if (fwdMessage != null) + { + var fwdPeer = fwdMessage.FwdFromPeer; + if (fwdPeer != null) + { + var cacheService = InMemoryCacheService.Instance; + if (fwdPeer is TLPeerChannel) + { + return cacheService.GetChat(fwdPeer.Id); + } + + return cacheService.GetUser(fwdPeer.Id); + } + } + + return FwdMessages[0].FwdFrom; + } + + if (EditMessage != null) + { + var fwdMessage48 = EditMessage as TLMessage48; + if (fwdMessage48 != null) + { + var fwdHeader = fwdMessage48.FwdHeader; + if (fwdHeader != null) + { + var cacheService = InMemoryCacheService.Instance; + if (fwdHeader.ChannelId != null) + { + return cacheService.GetChat(fwdHeader.ChannelId); + } + + if (fwdHeader.FromId != null) + { + return cacheService.GetUser(fwdHeader.FromId); + } + } + } + + return EditMessage.From; + } + + return null; + } + } + + public TLString Message + { + get + { + if (FwdMessages != null && FwdMessages.Count > 0) + { + return FwdMessages[0].Message; + } + if (EditMessage != null) + { + return EditMessage.Message; + } + + return null; + } + } + + public TLMessageMediaBase Media + { + get + { + if (FwdMessages != null && FwdMessages.Count > 0) + { + return FwdMessages[0].Media; + } + if (EditMessage != null) + { + return EditMessage.Media; + } + + return null; + } + } + } + + public class TLMessage73 : TLMessage70 + { + public new const uint Signature = TLConstructors.TLMessage73; + + protected TLLong _groupedId; + + public TLLong GroupedId + { + get { return _groupedId; } + set { SetField(out _groupedId, value, ref _flags, (int)MessageFlags.GroupedId); } + } + + public override void Edit(TLMessageBase messageBase) + { + base.Edit(messageBase); + + var message = messageBase as TLMessage73; + if (message != null) + { + GroupedId = message.GroupedId; + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = GetObject(Flags, (int)MessageFlags.FromId, new TLInt(-1), bytes, ref position); + ToId = GetObject(bytes, ref position); + _fwdHeader = GetObject(Flags, (int)MessageFlags.FwdFrom, null, bytes, ref position); + _viaBotId = GetObject(Flags, (int)MessageFlags.ViaBotId, null, bytes, ref position); + _replyToMsgId = GetObject(Flags, (int)MessageFlags.ReplyToMsgId, null, bytes, ref position); + _date = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + _media = GetObject(Flags, (int)MessageFlags.Media, new TLMessageMediaEmpty(), bytes, ref position); + _replyMarkup = GetObject(Flags, (int)MessageFlags.ReplyMarkup, null, bytes, ref position); + Entities = GetObject(Flags, (int)MessageFlags.Entities, new TLVector(), bytes, ref position); // Important to add empty Entities to avoid BrowseNavigationService.ParseText calls + _views = GetObject(Flags, (int)MessageFlags.Views, new TLInt(0), bytes, ref position); + _editDate = GetObject(Flags, (int)MessageFlags.EditDate, new TLInt(0), bytes, ref position); + _postAuthor = GetObject(Flags, (int)MessageFlags.PostAuthor, null, bytes, ref position); + _groupedId = GetObject(Flags, (int)MessageFlags.GroupedId, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + _fwdHeader = GetObject(Flags, (int)MessageFlags.FwdFrom, null, input); + _viaBotId = GetObject(Flags, (int)MessageFlags.ViaBotId, null, input); + _replyToMsgId = GetObject(Flags, (int)MessageFlags.ReplyToMsgId, null, input); + _date = GetObject(input); + Message = GetObject(input); + _media = GetObject(Flags, (int)MessageFlags.Media, new TLMessageMediaEmpty(), input); + _replyMarkup = GetObject(Flags, (int)MessageFlags.ReplyMarkup, null, input); + Entities = GetObject(Flags, (int)MessageFlags.Entities, new TLVector(), input); // Important to add empty Entities to avoid BrowseNavigationService.ParseText calls + _views = GetObject(Flags, (int)MessageFlags.Views, new TLInt(0), input); + _editDate = GetObject(Flags, (int)MessageFlags.EditDate, new TLInt(0), input); + _postAuthor = GetObject(Flags, (int)MessageFlags.PostAuthor, null, input); + _groupedId = GetObject(Flags, (int)MessageFlags.GroupedId, null, input); + + CustomFlags = GetNullableObject(input); + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + _status = (MessageStatus)GetObject(input).Value; + _fwdMessageId = GetObject(CustomFlags, (int)MessageCustomFlags.FwdMessageId, null, input); + _fwdFromChannelPeer = GetObject(CustomFlags, (int)MessageCustomFlags.FwdFromChannelPeer, null, input); + _inlineBotResultQueryId = GetObject(CustomFlags, (int)MessageCustomFlags.BotInlineResult, null, input); + _inlineBotResultId = GetObject(CustomFlags, (int)MessageCustomFlags.BotInlineResult, null, input); + _documents = GetObject>(CustomFlags, (int)MessageCustomFlags.Documents, null, input); + _inputPeer = GetObject(CustomFlags, (int)MessageCustomFlags.InputPeer, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + try + { + // to set flags before writing to file + Views = Views ?? new TLInt(0); + EditDate = EditDate ?? new TLInt(0); + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + Id.ToStream(output); + FromId.ToStream(output); + ToId.ToStream(output); + ToStream(output, FwdHeader, Flags, (int)MessageFlags.FwdFrom); + ToStream(output, ViaBotId, Flags, (int)MessageFlags.ViaBotId); + ToStream(output, ReplyToMsgId, Flags, (int)MessageFlags.ReplyToMsgId); + Date.ToStream(output); + Message.ToStream(output); + ToStream(output, Media, Flags, (int)MessageFlags.Media); + ToStream(output, ReplyMarkup, Flags, (int)MessageFlags.ReplyMarkup); + ToStream(output, Entities, Flags, (int)MessageFlags.Entities); + ToStream(output, Views, Flags, (int)MessageFlags.Views); + ToStream(output, EditDate, Flags, (int)MessageFlags.EditDate); + ToStream(output, PostAuthor, Flags, (int)MessageFlags.PostAuthor); + ToStream(output, GroupedId, Flags, (int)MessageFlags.GroupedId); + + CustomFlags.NullableToStream(output); + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + status.ToStream(output); + ToStream(output, _fwdMessageId, CustomFlags, (int)MessageCustomFlags.FwdMessageId); + ToStream(output, _fwdFromChannelPeer, CustomFlags, (int)MessageCustomFlags.FwdFromChannelPeer); + ToStream(output, _inlineBotResultQueryId, CustomFlags, (int)MessageCustomFlags.BotInlineResult); + ToStream(output, _inlineBotResultId, CustomFlags, (int)MessageCustomFlags.BotInlineResult); + ToStream(output, _documents, CustomFlags, (int)MessageCustomFlags.Documents); + ToStream(output, _inputPeer, CustomFlags, (int)MessageCustomFlags.InputPeer); + } + catch (Exception ex) + { + var logString = string.Format("TLMessage73.ToStream id={0} flags={1} fwd_from_peer={2} fwd_date={3} reply_to_msg_id={4} media={5} reply_markup={6} entities={7} views={8} from_id={9} edit_date={10} fwd_header={11}", Index, MessageFlagsString(Flags), FwdFromPeer, FwdDate, ReplyToMsgId, Media, ReplyMarkup, Entities, Views, FromId, EditDate, FwdHeader != null); + + TLUtils.WriteException(logString, ex); + } + } + + public override void Update(TLMessageBase message) + { + var message73 = message as TLMessage73; + if (message73 != null) + { + GroupedId = message73.GroupedId; + + base.Update(message); + } + } + } + + public class TLMessage70 : TLMessage48 + { + public new const uint Signature = TLConstructors.TLMessage70; + + protected TLString _postAuthor; + + public TLString PostAuthor + { + get { return _postAuthor; } + set { SetField(out _postAuthor, value, ref _flags, (int)MessageFlags.PostAuthor); } + } + + private string _author; + + public override string Author + { + get + { + if (_author != null) return _author; + + if (!TLString.IsNullOrEmpty(PostAuthor)) + { + _author = PostAuthor.ToString(); + return _author; + } + + if (!(ToId is TLPeerChannel)) return null; + if (FromId == null || FromId.Value < 0) return null; + + var cacheService = InMemoryCacheService.Instance; + var user = cacheService.GetUser(FromId); + _author = user != null ? user.FullName2 : string.Empty; + + return _author; + } + } + + public override Visibility AuthorVisibility + { + get { return !string.IsNullOrEmpty(Author) && !IsMusic() ? Visibility.Visible : Visibility.Collapsed; } + } + + public bool TTLMediaExpired + { + get + { + var mediaPhoto = Media as TLMessageMediaPhoto70; + if (mediaPhoto != null) + { + return mediaPhoto.Photo == null; + } + + var mediaDocument = Media as TLMessageMediaDocument70; + if (mediaDocument != null) + { + return mediaDocument.Document == null; + } + + return false; + } + } + + protected TLInputPeerBase _inputPeer; + + public TLInputPeerBase InputPeer + { + get { return _inputPeer; } + set + { + if (_inputPeer != null && value == null) + { + + } + + SetField(out _inputPeer, value, ref _customFlags, (int)MessageCustomFlags.InputPeer); + } + } + + public override void Edit(TLMessageBase messageBase) + { + base.Edit(messageBase); + + var message = messageBase as TLMessage48; + if (message != null) + { + EditDate = message.EditDate; + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = GetObject(Flags, (int)MessageFlags.FromId, new TLInt(-1), bytes, ref position); + ToId = GetObject(bytes, ref position); + _fwdHeader = GetObject(Flags, (int)MessageFlags.FwdFrom, null, bytes, ref position); + _viaBotId = GetObject(Flags, (int)MessageFlags.ViaBotId, null, bytes, ref position); + _replyToMsgId = GetObject(Flags, (int)MessageFlags.ReplyToMsgId, null, bytes, ref position); + _date = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + _media = GetObject(Flags, (int)MessageFlags.Media, new TLMessageMediaEmpty(), bytes, ref position); + _replyMarkup = GetObject(Flags, (int)MessageFlags.ReplyMarkup, null, bytes, ref position); + _entities = GetObject>(Flags, (int)MessageFlags.Entities, null, bytes, ref position); + _views = GetObject(Flags, (int)MessageFlags.Views, new TLInt(0), bytes, ref position); + _editDate = GetObject(Flags, (int)MessageFlags.EditDate, new TLInt(0), bytes, ref position); + _postAuthor = GetObject(Flags, (int)MessageFlags.PostAuthor, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + //#if DEBUG + // var flagsString = MessageFlagsString(Flags); + //#endif + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + _fwdHeader = GetObject(Flags, (int)MessageFlags.FwdFrom, null, input); + _viaBotId = GetObject(Flags, (int)MessageFlags.ViaBotId, null, input); + _replyToMsgId = GetObject(Flags, (int)MessageFlags.ReplyToMsgId, null, input); + _date = GetObject(input); + Message = GetObject(input); + _media = GetObject(Flags, (int)MessageFlags.Media, new TLMessageMediaEmpty(), input); + _replyMarkup = GetObject(Flags, (int)MessageFlags.ReplyMarkup, null, input); + _entities = GetObject>(Flags, (int)MessageFlags.Entities, null, input); + _views = GetObject(Flags, (int)MessageFlags.Views, new TLInt(0), input); + _editDate = GetObject(Flags, (int)MessageFlags.EditDate, new TLInt(0), input); + _postAuthor = GetObject(Flags, (int)MessageFlags.PostAuthor, null, input); + + CustomFlags = GetNullableObject(input); + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + _status = (MessageStatus)GetObject(input).Value; + _fwdMessageId = GetObject(CustomFlags, (int)MessageCustomFlags.FwdMessageId, null, input); + _fwdFromChannelPeer = GetObject(CustomFlags, (int)MessageCustomFlags.FwdFromChannelPeer, null, input); + _inlineBotResultQueryId = GetObject(CustomFlags, (int)MessageCustomFlags.BotInlineResult, null, input); + _inlineBotResultId = GetObject(CustomFlags, (int)MessageCustomFlags.BotInlineResult, null, input); + _documents = GetObject>(CustomFlags, (int)MessageCustomFlags.Documents, null, input); + _inputPeer = GetObject(CustomFlags, (int)MessageCustomFlags.InputPeer, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + try + { + // to set flags before writing to file + Views = Views ?? new TLInt(0); + EditDate = EditDate ?? new TLInt(0); + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + Id.ToStream(output); + FromId.ToStream(output); + ToId.ToStream(output); + ToStream(output, FwdHeader, Flags, (int)MessageFlags.FwdFrom); + ToStream(output, ViaBotId, Flags, (int)MessageFlags.ViaBotId); + ToStream(output, ReplyToMsgId, Flags, (int)MessageFlags.ReplyToMsgId); + Date.ToStream(output); + Message.ToStream(output); + ToStream(output, Media, Flags, (int)MessageFlags.Media); + ToStream(output, ReplyMarkup, Flags, (int)MessageFlags.ReplyMarkup); + ToStream(output, Entities, Flags, (int)MessageFlags.Entities); + ToStream(output, Views, Flags, (int)MessageFlags.Views); + ToStream(output, EditDate, Flags, (int)MessageFlags.EditDate); + ToStream(output, PostAuthor, Flags, (int)MessageFlags.PostAuthor); + + CustomFlags.NullableToStream(output); + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + status.ToStream(output); + ToStream(output, _fwdMessageId, CustomFlags, (int)MessageCustomFlags.FwdMessageId); + ToStream(output, _fwdFromChannelPeer, CustomFlags, (int)MessageCustomFlags.FwdFromChannelPeer); + ToStream(output, _inlineBotResultQueryId, CustomFlags, (int)MessageCustomFlags.BotInlineResult); + ToStream(output, _inlineBotResultId, CustomFlags, (int)MessageCustomFlags.BotInlineResult); + ToStream(output, _documents, CustomFlags, (int)MessageCustomFlags.Documents); + ToStream(output, _inputPeer, CustomFlags, (int)MessageCustomFlags.InputPeer); + } + catch (Exception ex) + { + var logString = string.Format("TLMessage70.ToStream id={0} flags={1} fwd_from_peer={2} fwd_date={3} reply_to_msg_id={4} media={5} reply_markup={6} entities={7} views={8} from_id={9} edit_date={10} fwd_header={11}", Index, MessageFlagsString(Flags), FwdFromPeer, FwdDate, ReplyToMsgId, Media, ReplyMarkup, Entities, Views, FromId, EditDate, FwdHeader != null); + + TLUtils.WriteException(logString, ex); + } + } + + public override void Update(TLMessageBase message) + { + var message70 = message as TLMessage70; + if (message70 != null) + { + // begin copy flags + Out = message70.Out; + IsMention = message70.IsMention; + NotListened = message70.NotListened; + Silent = message70.Silent; + Post = message70.Post; + // end copy flags + + Id = message70.Id; + Status = message70.Status; + FromId = message70.FromId; + ToId = message70.ToId; + + if (Unread.Value && !message70.Unread.Value) + { + SetUnreadSilent(message70.Unread); + } + if (!Unread.Value && message70.Unread.Value) + { +#if DEBUG && WINDOWS_PHONE + var builder = new StringBuilder(); + var stackTrace = new StackTrace(); + var frames = stackTrace.GetFrames(); + foreach (var r in frames) + { + builder.AppendLine(string.Format("Method: {0}", r.GetMethod())); + } + //Helpers.Execute.ShowDebugMessage("Set read message as unread\ncurrent=" + this + "\nnew=" + message + "\n\n" + builder.ToString()); +#endif + } + + _date = message70.Date; + Message = message70.Message; + + UpdateMedia(message); + + FwdFromId = message70.FwdFromId; + FwdDate = message70.FwdDate; + ReplyToMsgId = message70.ReplyToMsgId; + + if (message70.Reply != null) + { + Reply = message70.Reply; + } + + if (message70.ReplyMarkup != null) + { + var oldCustomFlags = ReplyMarkup != null ? ReplyMarkup.CustomFlags : null; + ReplyMarkup = message70.ReplyMarkup; + ReplyMarkup.CustomFlags = oldCustomFlags; + } + + if (message70.Entities != null) + { + Entities = message70.Entities; + } + + FwdFromPeer = message70.FwdFromPeer; + if (message70.FwdMessageId != null) FwdMessageId = message70.FwdMessageId; + if (message70.FwdFromChannelPeer != null) FwdFromChannelPeer = message70.FwdFromChannelPeer; + if (message70.Views != null) + { + var currentViews = Views != null ? Views.Value : 0; + if (currentViews < message70.Views.Value) + { + Views = message70.Views; + } + } + + if (message70.ViaBotId != null) + { + ViaBotId = message70.ViaBotId; + } + + if (message70.InlineBotResultQueryId != null) + { + InlineBotResultQueryId = message70.InlineBotResultQueryId; + } + + if (message70.InlineBotResultId != null) + { + InlineBotResultId = message70.InlineBotResultId; + } + + FwdHeader = message70.FwdHeader; + + if (message70.EditDate != null) + { + EditDate = message70.EditDate; + } + PostAuthor = message70.PostAuthor; + + if (message70.InputPeer != null) + { + InputPeer = message70.InputPeer; + } + } + } + + private void UpdateMedia(TLMessageBase message) + { + var m = (TLMessage)message; + var oldMedia = Media; + var newMedia = m.Media; + if (oldMedia.GetType() != newMedia.GetType()) + { + _media = m.Media; + if (_media != null) SetMedia(); + } + else + { + var oldMediaGeoLive = oldMedia as TLMessageMediaGeoLive; + var newMediaGeoLive = newMedia as TLMessageMediaGeoLive; + if (oldMediaGeoLive != null && newMediaGeoLive != null) + { + oldMediaGeoLive.Geo = newMediaGeoLive.Geo; + oldMediaGeoLive.Period = newMediaGeoLive.Period; + + return; + } + + var oldMediaVenue = oldMedia as TLMessageMediaVenue; + var newMediaVenue = newMedia as TLMessageMediaVenue; + if (oldMediaVenue != null && newMediaVenue != null) + { + oldMediaVenue.Geo = newMediaVenue.Geo; + + return; + } + + var oldMediaGeo = oldMedia as TLMessageMediaGeo; + var newMediaGeo = newMedia as TLMessageMediaGeo; + if (oldMediaGeo != null && newMediaGeo != null) + { + oldMediaGeo.Geo = newMediaGeo.Geo; + + return; + } + + var oldInvoice = oldMedia as TLMessageMediaInvoice; + var newInvoice = newMedia as TLMessageMediaInvoice; + if (oldInvoice != null && newInvoice != null && newInvoice.ReceiptMsgId != null) + { + oldInvoice.ReceiptMsgId = newInvoice.ReceiptMsgId; + + return; + } + + var oldMediaGame = oldMedia as TLMessageMediaGame; + var newMediaGame = newMedia as TLMessageMediaGame; + if (oldMediaGame != null && newMediaGame != null) + { + newMediaGame.Message = m.Message; + if (oldMediaGame.Game.GetType() != newMediaGame.Game.GetType()) + { + _media = m.Media; + } + else + { + var oldGame = oldMediaGame.Game; + var newGame = newMediaGame.Game; + if (oldGame != null + && newGame != null + && (oldGame.Id.Value != newGame.Id.Value)) + { + newMediaGame.SourceMessage = this; + _media = newMediaGame; + } + else + { + oldMediaGame.Message = m.Message; + } + } + + return; + } + + var oldMediaWebPage = oldMedia as TLMessageMediaWebPage; + var newMediaWebPage = newMedia as TLMessageMediaWebPage; + if (oldMediaWebPage != null && newMediaWebPage != null) + { + if (oldMediaWebPage.WebPage.GetType() != newMediaWebPage.WebPage.GetType()) + { + _media = m.Media; + } + else + { + var oldWebPage = oldMediaWebPage.WebPage as TLWebPage35; + var newWebPage = newMediaWebPage.WebPage as TLWebPage35; + if (oldWebPage != null + && newWebPage != null + && (oldWebPage.Id.Value != newWebPage.Id.Value)) + { + _media = m.Media; + } + } + + return; + } + + var oldMediaDocument = oldMedia as TLMessageMediaDocument; + var newMediaDocument = newMedia as TLMessageMediaDocument; + if (oldMediaDocument != null && newMediaDocument != null) + { + var oldDocument = oldMediaDocument.Document as TLDocument; + var newDocument = newMediaDocument.Document as TLDocument; + if (oldDocument == null || newDocument == null) + { + _media = m.Media; + + if (HasTTL()) + { + if (oldDocument != null) + { + newMediaDocument.Document = oldDocument; + } + + var oldTTLMessageMedia = oldMediaDocument as ITTLMessageMedia; + var newTTLMessageMedia = newMediaDocument as ITTLMessageMedia; + if (oldTTLMessageMedia != null && newTTLMessageMedia != null) + { + newTTLMessageMedia.TTLParams = oldTTLMessageMedia.TTLParams; + } + } + } + else + { + if (oldDocument.Id.Value != newDocument.Id.Value + || oldDocument.AccessHash.Value != newDocument.AccessHash.Value) + { + oldMediaDocument.Document = newMediaDocument.Document; + } + } + + return; + } + + var oldMediaVideo = oldMedia as TLMessageMediaVideo; + var newMediaVideo = newMedia as TLMessageMediaVideo; + if (oldMediaVideo != null && newMediaVideo != null) + { + if (oldMediaVideo.Video.GetType() != newMediaVideo.Video.GetType()) + { + _media = m.Media; + } + else + { + var oldVideo = oldMediaVideo.Video as TLVideo; + var newVideo = newMediaVideo.Video as TLVideo; + if (oldVideo != null + && newVideo != null + && (oldVideo.Id.Value != newVideo.Id.Value + || oldVideo.AccessHash.Value != newVideo.AccessHash.Value)) + { + var isoFileName = Media.IsoFileName; + _media = m.Media; + _media.IsoFileName = isoFileName; + } + } + + return; + } + + var oldMediaAudio = oldMedia as TLMessageMediaAudio; + var newMediaAudio = newMedia as TLMessageMediaAudio; + if (oldMediaAudio != null && newMediaAudio != null) + { + if (oldMediaAudio.Audio.GetType() != newMediaAudio.Audio.GetType()) + { + _media = m.Media; + } + else + { + var oldAudio = oldMediaAudio.Audio as TLAudio; + var newAudio = newMediaAudio.Audio as TLAudio; + if (oldAudio != null + && newAudio != null + && (oldAudio.Id.Value != newAudio.Id.Value + || oldAudio.AccessHash.Value != newAudio.AccessHash.Value)) + { + var isoFileName = Media.IsoFileName; + var notListened = Media.NotListened; + _media = m.Media; + _media.IsoFileName = isoFileName; + _media.NotListened = notListened; + } + } + + return; + } + + var oldMediaPhoto = oldMedia as TLMessageMediaPhoto; + var newMediaPhoto = newMedia as TLMessageMediaPhoto; + if (oldMediaPhoto == null || newMediaPhoto == null) + { + _media = m.Media; + } + else + { + var oldPhoto = oldMediaPhoto.Photo as TLPhoto; + var newPhoto = newMediaPhoto.Photo as TLPhoto; + if (oldPhoto == null || newPhoto == null) + { + _media = m.Media; + + if (HasTTL()) + { + if (oldPhoto != null) + { + newMediaPhoto.Photo = oldPhoto; + } + + var oldTTLMessageMedia = oldMediaPhoto as ITTLMessageMedia; + var newTTLMessageMedia = newMediaPhoto as ITTLMessageMedia; + if (oldTTLMessageMedia != null && newTTLMessageMedia != null) + { + newTTLMessageMedia.TTLParams = oldTTLMessageMedia.TTLParams; + } + } + } + else + { + if (oldPhoto.AccessHash.Value != newPhoto.AccessHash.Value) + { + var oldCachedSize = + oldPhoto.Sizes.FirstOrDefault(x => x is TLPhotoCachedSize) as TLPhotoCachedSize; + var oldMSize = + oldPhoto.Sizes.FirstOrDefault( + x => TLString.Equals(x.Type, new TLString("m"), StringComparison.OrdinalIgnoreCase)); + foreach (var size in newPhoto.Sizes) + { + if (size is TLPhotoCachedSize) + { + size.TempUrl = oldCachedSize != null ? oldCachedSize.TempUrl : null; + } + else if (TLString.Equals(size.Type, new TLString("s"), StringComparison.OrdinalIgnoreCase)) + { + size.TempUrl = oldCachedSize != null ? oldCachedSize.TempUrl : null; + } + else + { + size.TempUrl = oldMSize != null ? oldMSize.TempUrl : null; + } + } + + oldMediaPhoto.Photo = newMediaPhoto.Photo; + } + } + } + } + } + } + + public class TLMessage48 : TLMessage45 + { + public new const uint Signature = TLConstructors.TLMessage48; + + protected TLVector _documents; + + public TLVector Documents + { + get { return _documents; } + set { SetField(out _documents, value, ref _customFlags, (int)MessageCustomFlags.Documents); } + } + + public Visibility HasStickers + { + get + { + var mediaPhoto = Media as TLMessageMediaPhoto; + if (mediaPhoto != null) + { + var photo = mediaPhoto.Photo as TLPhoto56; + if (photo != null) + { + return photo.HasStickers ? Visibility.Visible : Visibility.Collapsed; + } + } + + return Visibility.Collapsed; + } + } + + public bool Silent + { + get { return IsSet(Flags, (int)MessageFlags.Silent); } + set { SetUnset(ref _flags, value, (int)MessageFlags.Silent); } + } + + public bool Post + { + get { return IsSet(Flags, (int)MessageFlags.Post); } + set { SetUnset(ref _flags, value, (int)MessageFlags.Post); } + } + + protected TLMessageFwdHeader _fwdHeader; + + public TLMessageFwdHeader FwdHeader + { + get { return _fwdHeader; } + set { SetField(out _fwdHeader, value, ref _flags, (int)MessageFlags.FwdFrom); } + } + + protected TLInt _editDate; + + public TLInt EditDate + { + get { return _editDate; } + set { SetField(out _editDate, value, ref _flags, (int)MessageFlags.EditDate); } + } + + public Visibility EditDateVisibility + { + get + { + if (ViaBotId != null) return Visibility.Collapsed; + + var from = From; + var user = from as TLUser; + if (user != null && user.IsBot) return Visibility.Collapsed; + + return EditDate != null && EditDate.Value > 0 ? Visibility.Visible : Visibility.Collapsed; + } + } + + public override Visibility ReplyOrViaBotVisibility + { + get + { + var replyVisibility = ReplyVisibility; + if (replyVisibility == Visibility.Visible) return Visibility.Visible; + + return ViaBotVisibility; + } + } + + public override Visibility ViaBotVisibility + { + get + { + if (ViaBotId != null && Media is TLMessageMediaContact) + { + return Visibility.Collapsed; + } + + var viaBot = ViaBot; + + return viaBot != null && !viaBot.IsDeleted ? Visibility.Visible : Visibility.Collapsed; + //return FwdHeader == null && ViaBotId != null ? Visibility.Visible : Visibility.Collapsed; + } + } + + public override Visibility FwdViaBotVisibility + { + get + { + if (ViaBotId != null && Media is TLMessageMediaContact) + { + return Visibility.Collapsed; + } + + return FwdHeader != null && ViaBotId != null ? Visibility.Visible : Visibility.Collapsed; + } + } + + + public override Visibility FwdFromPeerVisibility + { + get + { + var peerChannel = FwdHeader != null && FwdHeader.ChannelId != null; + if (peerChannel) + { + var channelMediaGroup = Media as TLMessageMediaGroup; + if (channelMediaGroup != null) + { + return Visibility.Visible; + } + + var channelMediaPhoto = Media as TLMessageMediaPhoto; + if (channelMediaPhoto != null) + { + return Visibility.Visible; + } + + var channelMediaDocument = Media as TLMessageMediaDocument; + if (channelMediaDocument != null) + { + if (IsMusic()) + { + return Visibility.Collapsed; + } + + return Visibility.Visible; + } + + var channelMediaVideo = Media as TLMessageMediaVideo; + if (channelMediaVideo != null) + { + return Visibility.Visible; + } + + var channelGeo = Media as TLMessageMediaGeo; + if (channelGeo != null) + { + return Visibility.Visible; + } + } + + var mediaGroup = Media as TLMessageMediaGroup; + if (FwdHeader != null && mediaGroup != null) + { + return Visibility.Visible; + } + + var mediaPhoto = Media as TLMessageMediaPhoto; + if (FwdHeader != null && mediaPhoto != null) + { + return Visibility.Visible; + } + + var mediaVideo = Media as TLMessageMediaVideo; + if (FwdHeader != null && mediaVideo != null) + { + return Visibility.Visible; + } + + var mediaDocument = Media as TLMessageMediaDocument; + if (FwdHeader != null && mediaDocument != null) + { + if (IsMusic()) + { + return Visibility.Collapsed; + } + + return Visibility.Visible; + } + + var mediaGeo = Media as TLMessageMediaGeo; + if (FwdHeader != null && mediaGeo != null) + { + return Visibility.Visible; + } + + var emptyMedia = Media as TLMessageMediaEmpty; + var webPageMedia = Media as TLMessageMediaWebPage; + return FwdHeader != null && !TLString.IsNullOrEmpty(Message) && (emptyMedia != null || webPageMedia != null) ? Visibility.Visible : Visibility.Collapsed; + } + } + + public double FwdMaxWidth + { + get + { + if (IsSticker()) return 171.0; + + if (IsVideo()) return 212.0; + + var mediaVideo = Media as TLMessageMediaVideo; + if (mediaVideo != null) return 212.0; + + var mediaGeo = Media as TLMessageMediaGeo; + var mediaVenue = Media as TLMessageMediaVenue; + if (mediaGeo != null && mediaVenue == null) +#if DEBUG + return 302.0;//120.0; +#else + return 302.0;//161.0; +#endif + + return 311.0; + } + } + + public override TLObject FwdFrom + { + get + { + if (FwdHeader != null) + { + return FwdHeader; + } + + if (FwdFromPeer != null) + { + var cacheService = InMemoryCacheService.Instance; + + if (FwdFromPeer is TLPeerChannel) + { + return cacheService.GetChat(FwdFromPeer.Id); + } + + return cacheService.GetUser(FwdFromPeer.Id); + } + + if (FwdFromId != null) + { + var cacheService = InMemoryCacheService.Instance; + return cacheService.GetUser(FwdFromId); + } + + return null; + } + set + { + + } + } + + public override Visibility ShareButtonVisibility + { + get + { + if (Out.Value) return Visibility.Collapsed; + + var user = From as TLUser; + if (user != null && (user.IsBot || ViaBotId != null)) + { + var entities = Entities; + if (entities != null) + { + var url = entities.FirstOrDefault(x => x is TLMessageEntityUrl || x is TLMessageEntityTextUrl); + if (url != null) return Visibility.Visible; + } + + var mediaGame = Media as TLMessageMediaGame; + if (mediaGame != null) return Visibility.Visible; + + var mediaPhoto = Media as TLMessageMediaPhoto; + if (mediaPhoto != null) return Visibility.Visible; + + var mediaVideo = Media as TLMessageMediaVideo; + if (mediaVideo != null) return Visibility.Visible; + + if (IsVideo()) return Visibility.Visible; + } + + return Visibility.Collapsed; + } + } + + public override TLObject From + { + get + { + if (IsSelf()) + { + var fwdHeader = FwdHeader as TLMessageFwdHeader73; + if (fwdHeader != null) + { + var user = fwdHeader.From as TLUser; + if (user == null || !user.IsSelf) + { + return fwdHeader.From; + } + } + } + + return base.From; + } + } + + public override void Edit(TLMessageBase messageBase) + { + base.Edit(messageBase); + + var message = messageBase as TLMessage48; + if (message != null) + { + EditDate = message.EditDate; + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = IsSet(Flags, (int)MessageFlags.FromId) + ? GetObject(bytes, ref position) + : new TLInt(-1); + ToId = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdHeader = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.ViaBotId)) + { + _viaBotId = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + + _date = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + + _media = IsSet(Flags, (int)MessageFlags.Media) + ? GetObject(bytes, ref position) + : new TLMessageMediaEmpty(); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + + _views = IsSet(Flags, (int)MessageFlags.Views) + ? GetObject(bytes, ref position) + : new TLInt(0); + + EditDate = IsSet(Flags, (int)MessageFlags.EditDate) + ? GetObject(bytes, ref position) + : new TLInt(0); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdHeader = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.ViaBotId)) + { + _viaBotId = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(input); + } + + _date = GetObject(input); + Message = GetObject(input); + _media = IsSet(Flags, (int)MessageFlags.Media) + ? GetObject(input) + : new TLMessageMediaEmpty(); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(input); + } + + if (IsSet(Flags, (int)MessageFlags.Views)) + { + Views = GetObject(input); + } + else + { + Views = new TLInt(0); + } + + if (IsSet(Flags, (int)MessageFlags.EditDate)) + { + EditDate = GetObject(input); + } + else + { + EditDate = new TLInt(0); + } + + CustomFlags = GetNullableObject(input); + + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + var status = GetObject(input); + _status = (MessageStatus)status.Value; + + if (IsSet(CustomFlags, (int)MessageCustomFlags.FwdMessageId)) + { + _fwdMessageId = GetObject(input); + } + + if (IsSet(CustomFlags, (int)MessageCustomFlags.FwdFromChannelPeer)) + { + _fwdFromChannelPeer = GetObject(input); + } + + if (IsSet(CustomFlags, (int)MessageCustomFlags.BotInlineResult)) + { + _inlineBotResultQueryId = GetObject(input); + _inlineBotResultId = GetObject(input); + } + + if (IsSet(CustomFlags, (int)MessageCustomFlags.Documents)) + { + _documents = GetObject>(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + try + { + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + output.Write(Id.ToBytes()); + output.Write(FromId.ToBytes()); + ToId.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdHeader.ToStream(output); + //FwdFromPeer.ToStream(output); + //FwdDate.ToStream(output); + } + + if (IsSet(Flags, (int)MessageFlags.ViaBotId)) + { + _viaBotId.ToStream(output); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId.ToStream(output); + } + + output.Write(Date.ToBytes()); + Message.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.Media)) + { + _media.ToStream(output); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup.ToStream(output); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities.ToStream(output); + } + if (IsSet(Flags, (int)MessageFlags.Views)) + { + if (Views == null) + { + var logString = string.Format("TLMessage48.ToStream id={0} flags={1} fwd_from_peer={2} fwd_date={3} reply_to_msg_id={4} media={5} reply_markup={6} entities={7} views={8} from_id={9} edit_date={10} fwd_header={11}", Index, MessageFlagsString(Flags), FwdFromPeer, FwdDate, ReplyToMsgId, Media, ReplyMarkup, Entities, Views, FromId, EditDate, FwdHeader != null); + Log.Write(logString); + } + + Views = Views ?? new TLInt(0); + Views.ToStream(output); + } + if (IsSet(Flags, (int)MessageFlags.EditDate)) + { + EditDate = EditDate ?? new TLInt(0); + EditDate.ToStream(output); + } + + CustomFlags.NullableToStream(output); + + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + + if (IsSet(CustomFlags, (int)MessageCustomFlags.FwdMessageId)) + { + _fwdMessageId.ToStream(output); + } + + if (IsSet(CustomFlags, (int)MessageCustomFlags.FwdFromChannelPeer)) + { + _fwdFromChannelPeer.ToStream(output); + } + + if (IsSet(CustomFlags, (int)MessageCustomFlags.BotInlineResult)) + { + _inlineBotResultQueryId.ToStream(output); + _inlineBotResultId.ToStream(output); + } + + if (IsSet(CustomFlags, (int)MessageCustomFlags.Documents)) + { + _documents.ToStream(output); + } + } + catch (Exception ex) + { + var logString = string.Format("TLMessage48.ToStream id={0} flags={1} fwd_from_peer={2} fwd_date={3} reply_to_msg_id={4} media={5} reply_markup={6} entities={7} views={8} from_id={9} edit_date={10} fwd_header={11}", Index, MessageFlagsString(Flags), FwdFromPeer, FwdDate, ReplyToMsgId, Media, ReplyMarkup, Entities, Views, FromId, EditDate, FwdHeader != null); + + TLUtils.WriteException(logString, ex); + } + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = message as TLMessage48; + if (m != null) + { + FwdHeader = m.FwdHeader; + + if (m.EditDate != null) + { + EditDate = m.EditDate; + } + } + } + } + + public class TLMessage45 : TLMessage40 + { + private string _author; + + public virtual string Author + { + get + { + if (_author != null) return _author; + + if (!(ToId is TLPeerChannel)) return null; + if (FromId == null || FromId.Value < 0) return null; + + var cacheService = InMemoryCacheService.Instance; + var user = cacheService.GetUser(FromId); + _author = user != null ? user.FullName2 : string.Empty; + + return _author; + } + } + + public virtual Visibility AuthorVisibility + { + get { return ToId is TLPeerChannel && FromId != null && FromId.Value >= 0 && !IsMusic() ? Visibility.Visible : Visibility.Collapsed; } + } + + public new const uint Signature = TLConstructors.TLMessage45; + + protected TLInt _viaBotId; + + public TLInt ViaBotId + { + get { return _viaBotId; } + set + { + if (value != null) + { + Set(ref _flags, (int)MessageFlags.ViaBotId); + _viaBotId = value; + } + else + { + Unset(ref _flags, (int)MessageFlags.ViaBotId); + _viaBotId = null; + } + } + } + + private TLUserBase _viaBot; + + public override TLUserBase ViaBot + { + get + { + if (_viaBot != null) return _viaBot; + if (ViaBotId == null) return null; + + var cacheService = InMemoryCacheService.Instance; + _viaBot = cacheService.GetUser(ViaBotId); + + return _viaBot; + } + } + + public override Visibility ViaBotVisibility + { + get { return FwdFromPeer == null && ViaBotId != null ? Visibility.Visible : Visibility.Collapsed; } + } + + public override Visibility FwdViaBotVisibility + { + get { return FwdFromPeer != null && ViaBotId != null ? Visibility.Visible : Visibility.Collapsed; } + } + + protected TLLong _inlineBotResultQueryId; + + public TLLong InlineBotResultQueryId + { + get { return _inlineBotResultQueryId; } + set + { + if (value != null) + { + Set(ref _customFlags, (int)MessageCustomFlags.BotInlineResult); + _inlineBotResultQueryId = value; + } + else + { + Unset(ref _customFlags, (int)MessageCustomFlags.BotInlineResult); + _inlineBotResultQueryId = null; + } + } + } + + protected TLString _inlineBotResultId; + + public TLString InlineBotResultId + { + get { return _inlineBotResultId; } + set + { + if (value != null) + { + Set(ref _customFlags, (int)MessageCustomFlags.BotInlineResult); + _inlineBotResultId = value; + } + else + { + Unset(ref _customFlags, (int)MessageCustomFlags.BotInlineResult); + _inlineBotResultId = null; + } + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = IsSet(Flags, (int)MessageFlags.FromId) + ? GetObject(bytes, ref position) + : new TLInt(-1); + ToId = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromPeer = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.ViaBotId)) + { + _viaBotId = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + + _date = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + + _media = IsSet(Flags, (int)MessageFlags.Media) + ? GetObject(bytes, ref position) + : new TLMessageMediaEmpty(); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + + _views = IsSet(Flags, (int)MessageFlags.Views) + ? GetObject(bytes, ref position) + : new TLInt(0); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromPeer = GetObject(input); + FwdDate = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.ViaBotId)) + { + _viaBotId = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(input); + } + + _date = GetObject(input); + Message = GetObject(input); + + _media = IsSet(Flags, (int)MessageFlags.Media) + ? GetObject(input) + : new TLMessageMediaEmpty(); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(input); + } + + if (IsSet(Flags, (int)MessageFlags.Views)) + { + Views = GetObject(input); + } + else + { + Views = new TLInt(0); + } + + CustomFlags = GetNullableObject(input); + + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + var status = GetObject(input); + _status = (MessageStatus)status.Value; + + if (IsSet(CustomFlags, (int)MessageCustomFlags.FwdMessageId)) + { + _fwdMessageId = GetObject(input); + } + + if (IsSet(CustomFlags, (int)MessageCustomFlags.FwdFromChannelPeer)) + { + _fwdFromChannelPeer = GetObject(input); + } + + if (IsSet(CustomFlags, (int)MessageCustomFlags.BotInlineResult)) + { + _inlineBotResultQueryId = GetObject(input); + _inlineBotResultId = GetObject(input); + } + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + try + { + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + output.Write(Id.ToBytes()); + output.Write(FromId.ToBytes()); + ToId.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromPeer.ToStream(output); + FwdDate.ToStream(output); + } + + if (IsSet(Flags, (int)MessageFlags.ViaBotId)) + { + _viaBotId.ToStream(output); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId.ToStream(output); + } + + output.Write(Date.ToBytes()); + Message.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.Media)) + { + _media.ToStream(output); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup.ToStream(output); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities.ToStream(output); + } + if (IsSet(Flags, (int)MessageFlags.Views)) + { + if (Views == null) + { + var logString = string.Format("TLMessage40.ToStream id={0} flags={1} fwd_from_peer={2} fwd_date={3} reply_to_msg_id={4} media={5} reply_markup={6} entities={7} views={8} from_id={9}", Index, MessageFlagsString(Flags), FwdFromPeer, FwdDate, ReplyToMsgId, Media, ReplyMarkup, Entities, Views, FromId); + Log.Write(logString); + } + + Views = Views ?? new TLInt(0); + Views.ToStream(output); + } + + CustomFlags.NullableToStream(output); + + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + + if (IsSet(CustomFlags, (int)MessageCustomFlags.FwdMessageId)) + { + _fwdMessageId.ToStream(output); + } + + if (IsSet(CustomFlags, (int)MessageCustomFlags.FwdFromChannelPeer)) + { + _fwdFromChannelPeer.ToStream(output); + } + + if (IsSet(CustomFlags, (int)MessageCustomFlags.BotInlineResult)) + { + _inlineBotResultQueryId.ToStream(output); + _inlineBotResultId.ToStream(output); + } + } + catch (Exception ex) + { + var logString = string.Format("TLMessage40.ToStream id={0} flags={1} fwd_from_peer={2} fwd_date={3} reply_to_msg_id={4} media={5} reply_markup={6} entities={7} views={8} from_id={9}", Index, MessageFlagsString(Flags), FwdFromPeer, FwdDate, ReplyToMsgId, Media, ReplyMarkup, Entities, Views, FromId); + + TLUtils.WriteException(logString, ex); + } + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = message as TLMessage45; + if (m != null) + { + if (m.ViaBotId != null) + { + ViaBotId = m.ViaBotId; + } + + if (m.InlineBotResultQueryId != null) + { + InlineBotResultQueryId = m.InlineBotResultQueryId; + } + + if (m.InlineBotResultId != null) + { + InlineBotResultId = m.InlineBotResultId; + } + } + } + } + + public class TLMessage40 : TLMessage36 + { + public new const uint Signature = TLConstructors.TLMessage40; + + public TLPeerBase FwdFromPeer { get; set; } + + protected TLInputPeerBase _fwdFromChannelPeer; + + public TLInputPeerBase FwdFromChannelPeer + { + get { return _fwdFromChannelPeer; } + set + { + if (value != null) + { + Set(ref _customFlags, (int)MessageCustomFlags.FwdFromChannelPeer); + _fwdFromChannelPeer = value; + } + else + { + Unset(ref _customFlags, (int)MessageCustomFlags.FwdFromChannelPeer); + _fwdFromChannelPeer = null; + } + } + } + + protected TLInt _fwdMessageId; + + public TLInt FwdMessageId + { + get { return _fwdMessageId; } + set + { + if (value != null) + { + Set(ref _customFlags, (int)MessageCustomFlags.FwdMessageId); + _fwdMessageId = value; + } + else + { + Unset(ref _customFlags, (int)MessageCustomFlags.FwdMessageId); + _fwdMessageId = null; + } + } + } + + public virtual Visibility FwdFromPeerVisibility + { + get + { + var peerChannel = FwdFromPeer as TLPeerChannel; + if (peerChannel != null) + { + var channelMediaPhoto = Media as TLMessageMediaPhoto; + if (channelMediaPhoto != null) + { + return Visibility.Visible; + } + + var channelMediaDocument = Media as TLMessageMediaDocument; + if (channelMediaDocument != null && IsVideo(channelMediaDocument.Document)) + { + return Visibility.Visible; + } + + var channelMediaVideo = Media as TLMessageMediaVideo; + if (channelMediaVideo != null) + { + return Visibility.Visible; + } + } + + var mediaPhoto = Media as TLMessageMediaPhoto; + if (FwdFromPeer != null && mediaPhoto != null) + { + return Visibility.Visible; + } + + var mediaVideo = Media as TLMessageMediaVideo; + if (FwdFromPeer != null && mediaVideo != null) + { + return Visibility.Visible; + } + + var mediaDocument = Media as TLMessageMediaDocument; + if (FwdFromPeer != null && mediaDocument != null) + { + return Visibility.Visible; + } + + var emptyMedia = Media as TLMessageMediaEmpty; + var webPageMedia = Media as TLMessageMediaWebPage; + return FwdFromPeer != null && !TLString.IsNullOrEmpty(Message) && (emptyMedia != null || webPageMedia != null) ? Visibility.Visible : Visibility.Collapsed; + } + } + + public TLMessageBase Group { get; set; } + + public void SetFromId() + { + Set(ref _flags, (int)MessageFlags.FromId); + } + + public void SetMedia() + { + Set(ref _flags, (int)MessageFlags.Media); + } + + public override TLObject FwdFrom + { + get + { + if (FwdFromId != null) + { + var cacheService = InMemoryCacheService.Instance; + return cacheService.GetUser(FwdFromId); + } + + if (FwdFromPeer != null) + { + var cacheService = InMemoryCacheService.Instance; + + if (FwdFromPeer is TLPeerChannel) + { + return cacheService.GetChat(FwdFromPeer.Id); + } + + return cacheService.GetUser(FwdFromPeer.Id); + } + + return null; + } + set + { + + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = IsSet(Flags, (int)MessageFlags.FromId) + ? GetObject(bytes, ref position) + : new TLInt(-1); + ToId = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromPeer = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + + _date = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + + _media = IsSet(Flags, (int)MessageFlags.Media) + ? GetObject(bytes, ref position) + : new TLMessageMediaEmpty(); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + + _views = IsSet(Flags, (int)MessageFlags.Views) + ? GetObject(bytes, ref position) + : new TLInt(0); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromPeer = GetObject(input); + FwdDate = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(input); + } + + _date = GetObject(input); + Message = GetObject(input); + + _media = IsSet(Flags, (int)MessageFlags.Media) + ? GetObject(input) + : new TLMessageMediaEmpty(); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(input); + } + + if (IsSet(Flags, (int)MessageFlags.Views)) + { + Views = GetObject(input); + } + else + { + Views = new TLInt(0); + } + + CustomFlags = GetNullableObject(input); + + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + var status = GetObject(input); + _status = (MessageStatus)status.Value; + + if (IsSet(CustomFlags, (int)MessageCustomFlags.FwdMessageId)) + { + _fwdMessageId = GetObject(input); + } + + if (IsSet(CustomFlags, (int)MessageCustomFlags.FwdFromChannelPeer)) + { + _fwdFromChannelPeer = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + try + { + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + output.Write(Id.ToBytes()); + output.Write(FromId.ToBytes()); + ToId.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromPeer.ToStream(output); + FwdDate.ToStream(output); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId.ToStream(output); + } + + output.Write(Date.ToBytes()); + Message.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.Media)) + { + _media.ToStream(output); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup.ToStream(output); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities.ToStream(output); + } + if (IsSet(Flags, (int)MessageFlags.Views)) + { + if (Views == null) + { + var logString = string.Format("TLMessage40.ToStream id={0} flags={1} fwd_from_peer={2} fwd_date={3} reply_to_msg_id={4} media={5} reply_markup={6} entities={7} views={8} from_id={9}", Index, MessageFlagsString(Flags), FwdFromPeer, FwdDate, ReplyToMsgId, Media, ReplyMarkup, Entities, Views, FromId); + Log.Write(logString); + } + + Views = Views ?? new TLInt(0); + Views.ToStream(output); + } + + CustomFlags.NullableToStream(output); + + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + + if (IsSet(CustomFlags, (int)MessageCustomFlags.FwdMessageId)) + { + _fwdMessageId.ToStream(output); + } + + if (IsSet(CustomFlags, (int)MessageCustomFlags.FwdFromChannelPeer)) + { + _fwdFromChannelPeer.ToStream(output); + } + } + catch (Exception ex) + { + var logString = string.Format("TLMessage40.ToStream id={0} flags={1} fwd_from_peer={2} fwd_date={3} reply_to_msg_id={4} media={5} reply_markup={6} entities={7} views={8} from_id={9}", Index, MessageFlagsString(Flags), FwdFromPeer, FwdDate, ReplyToMsgId, Media, ReplyMarkup, Entities, Views, FromId); + + TLUtils.WriteException(logString, ex); + } + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = message as TLMessage40; + if (m != null) + { + FwdFromPeer = m.FwdFromPeer; + if (m.FwdMessageId != null) FwdMessageId = m.FwdMessageId; + if (m.FwdFromChannelPeer != null) FwdFromChannelPeer = m.FwdFromChannelPeer; + if (m.Views != null) + { + var currentViews = Views != null ? Views.Value : 0; + if (currentViews < m.Views.Value) + { + Views = m.Views; + } + } + } + } + } + + public class TLMessage36 : TLMessage34 + { + public new const uint Signature = TLConstructors.TLMessage36; + + protected TLInt _views; + + public TLInt Views + { + get { return _views; } + set + { + if (value != null) + { + if (_views == null || _views.Value < value.Value) + { + Set(ref _flags, (int)MessageFlags.Views); + _views = value; + } + } + } + } + + public Visibility ViewsVisibility + { + get + { + var message40 = this as TLMessage40; + if (message40 != null) + { + return Views != null && Views.Value > 0 ? Visibility.Visible : Visibility.Collapsed; + } + + return Visibility.Collapsed; + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = GetObject(bytes, ref position); + ToId = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + + _date = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + + _media = IsSet(Flags, (int)MessageFlags.Media) + ? GetObject(bytes, ref position) + : new TLMessageMediaEmpty(); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId = GetObject(input); + FwdDate = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(input); + } + + _date = GetObject(input); + Message = GetObject(input); + _media = GetObject(input); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(input); + } + + CustomFlags = GetNullableObject(input); + + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + var status = GetObject(input); + _status = (MessageStatus)status.Value; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + output.Write(Id.ToBytes()); + output.Write(FromId.ToBytes()); + ToId.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId.ToStream(output); + FwdDate.ToStream(output); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId.ToStream(output); + } + + output.Write(Date.ToBytes()); + Message.ToStream(output); + _media.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup.ToStream(output); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities.ToStream(output); + } + + CustomFlags.NullableToStream(output); + + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + } + } + + public class TLMessage34 : TLMessage31 + { + public new const uint Signature = TLConstructors.TLMessage34; + + protected TLVector _entities; + + public TLVector Entities + { + get { return _entities; } + set { SetField(out _entities, value, ref _flags, (int)MessageFlags.Entities); } + } + + public override void Edit(TLMessageBase messageBase) + { + var message = messageBase as TLMessage34; + if (message != null) + { + Message = message.Message; + Entities = message.Entities; + ReplyMarkup = message.ReplyMarkup; + + var oldGeoLive = Media as TLMessageMediaGeoLive; + var newGeoLive = message.Media as TLMessageMediaGeoLive; + if (oldGeoLive != null && newGeoLive != null) + { + oldGeoLive.Geo = newGeoLive.Geo; + oldGeoLive.Period = newGeoLive.Period; + } + + var oldInvoice = Media as TLMessageMediaInvoice; + var newInvoice = message.Media as TLMessageMediaInvoice; + if (oldInvoice != null && newInvoice != null && newInvoice.ReceiptMsgId != null) + { + oldInvoice.ReceiptMsgId = newInvoice.ReceiptMsgId; + } + + var oldWebPage = Media as TLMessageMediaWebPage; + var newWebPage = message.Media as TLMessageMediaWebPage; + if ((oldWebPage == null && newWebPage != null) + || (oldWebPage != null && newWebPage == null) + || (oldWebPage != null && newWebPage != null && oldWebPage.WebPage.Id.Value != newWebPage.WebPage.Id.Value)) + { + _media = (TLMessageMediaBase)newWebPage ?? new TLMessageMediaEmpty(); + } + + var oldGame = Media as TLMessageMediaGame; + var newGame = message.Media as TLMessageMediaGame; + if (oldGame != null && newGame != null) + { + oldGame.Message = message.Message; + } + + var mediaCaption = message.Media as IMediaCaption; + var cachedMediaCaption = Media as IMediaCaption; + if (cachedMediaCaption != null && mediaCaption != null) + { + cachedMediaCaption.Caption = mediaCaption.Caption; + } + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = GetObject(bytes, ref position); + ToId = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + + _date = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + _media = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId = GetObject(input); + FwdDate = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(input); + } + + _date = GetObject(input); + Message = GetObject(input); + _media = GetObject(input); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(input); + } + + CustomFlags = GetNullableObject(input); + + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + var status = GetObject(input); + _status = (MessageStatus)status.Value; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + output.Write(Id.ToBytes()); + output.Write(FromId.ToBytes()); + ToId.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId.ToStream(output); + FwdDate.ToStream(output); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId.ToStream(output); + } + + output.Write(Date.ToBytes()); + Message.ToStream(output); + _media.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup.ToStream(output); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities.ToStream(output); + } + + CustomFlags.NullableToStream(output); + + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = message as TLMessage34; + if (m != null) + { + if (m.Entities != null) + { + Entities = m.Entities; + } + } + } + } + + public class TLMessage31 : TLMessage25 + { + public new const uint Signature = TLConstructors.TLMessage31; + + protected TLReplyKeyboardBase _replyMarkup; + + public TLReplyKeyboardBase ReplyMarkup + { + get { return _replyMarkup; } + set { SetField(out _replyMarkup, value, ref _flags, (int)MessageFlags.ReplyMarkup); } + } + + protected TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = GetObject(bytes, ref position); + ToId = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + + _date = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + _media = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup = GetObject(bytes, ref position); + } + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId = GetObject(input); + FwdDate = GetObject(input); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(input); + } + + _date = GetObject(input); + Message = GetObject(input); + _media = GetObject(input); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup = GetObject(input); + } + + CustomFlags = GetNullableObject(input); + + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + var status = GetObject(input); + _status = (MessageStatus)status.Value; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + output.Write(Id.ToBytes()); + output.Write(FromId.ToBytes()); + ToId.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId.ToStream(output); + FwdDate.ToStream(output); + } + + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId.ToStream(output); + } + + output.Write(Date.ToBytes()); + Message.ToStream(output); + _media.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.ReplyMarkup)) + { + ReplyMarkup.ToStream(output); + } + + CustomFlags.NullableToStream(output); + + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = message as TLMessage31; + if (m != null) + { + if (m.ReplyMarkup != null) + { + var oldCustomFlags = ReplyMarkup != null ? ReplyMarkup.CustomFlags : null; + ReplyMarkup = m.ReplyMarkup; + ReplyMarkup.CustomFlags = oldCustomFlags; + } + + if (m.CustomFlags != null) + { + CustomFlags = m.CustomFlags; + } + } + } + } + + public class TLMessage25 : TLMessage17, IReplyToMsgId + { + public new const uint Signature = TLConstructors.TLMessage25; + + public TLInt FwdFromId { get; set; } + + public TLInt FwdDate { get; set; } + + protected TLInt _replyToMsgId; + + public TLInt ReplyToMsgId + { + get { return _replyToMsgId; } + set { SetField(out _replyToMsgId, value, ref _flags, (int)MessageFlags.ReplyToMsgId); } + } + + public override ReplyInfo ReplyInfo + { + get { return ReplyToMsgId != null ? new ReplyInfo { ReplyToMsgId = ReplyToMsgId, Reply = Reply } : null; } + } + + public override Visibility ReplyVisibility + { + get { return ReplyToMsgId != null && ReplyToMsgId.Value != 0 ? Visibility.Visible : Visibility.Collapsed; } + } + + public void SetFwd() + { + Set(ref _flags, (int)MessageFlags.FwdFrom); + } + + public void SetReply() + { + Set(ref _flags, (int)MessageFlags.ReplyToMsgId); + } + + public void SetListened() + { + Unset(ref _flags, (int)MessageFlags.MediaUnread); + } + + public bool NotListened + { + get { return IsSet(_flags, (int)MessageFlags.MediaUnread); } + set { SetUnset(ref _flags, value, (int)MessageFlags.MediaUnread); } + } + + public override TLObject FwdFrom + { + get + { + if (FwdFromId == null) return null; + + var cacheService = InMemoryCacheService.Instance; + return cacheService.GetUser(FwdFromId); + } + set + { + + } + } + + public override string ToString() + { + var messageString = Message != null ? Message.ToString() : string.Empty; + + var mediaString = Media.GetType().Name; + //var mediaPhoto = Media as TLMessageMediaPhoto; + //if (mediaPhoto != null) + //{ + // mediaString = mediaPhoto.ToString() + " "; + //} + var str = Media == null || Media is TLMessageMediaEmpty + ? " Msg=" + messageString.Substring(0, Math.Min(messageString.Length, 5)) + : " Media=" + mediaString; + + return base.ToString() + string.Format(" Flags={0}" + str, MessageFlagsString(Flags)); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = GetObject(bytes, ref position); + ToId = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + + _date = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + _media = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId = GetObject(input); + FwdDate = GetObject(input); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(input); + } + + _date = GetObject(input); + Message = GetObject(input); + _media = GetObject(input); + + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + var status = GetObject(input); + _status = (MessageStatus)status.Value; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + output.Write(Id.ToBytes()); + output.Write(FromId.ToBytes()); + ToId.ToStream(output); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId.ToStream(output); + FwdDate.ToStream(output); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId.ToStream(output); + } + + output.Write(Date.ToBytes()); + Message.ToStream(output); + _media.ToStream(output); + + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = message as TLMessage25; + if (m != null) + { + FwdFromId = m.FwdFromId; + FwdDate = m.FwdDate; + ReplyToMsgId = m.ReplyToMsgId; + + if (m.Reply != null) + { + Reply = m.Reply; + } + } + } + } + + public class TLMessage17 : TLMessage + { + public new const uint Signature = TLConstructors.TLMessage17; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override TLBool Out + { + get { return new TLBool(IsSet(_flags, (int)MessageFlags.Out)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)MessageFlags.Out); + } + } + } + + public override void SetUnread(TLBool value) + { + Unread = value; + } + + public override void SetUnreadSilent(TLBool value) + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)MessageFlags.Unread); + } + } + + public override TLBool Unread + { + get { return new TLBool(IsSet(_flags, (int)MessageFlags.Unread)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)MessageFlags.Unread); + NotifyOfPropertyChange(() => Status); + } + } + } + + public bool IsMention + { + get { return IsSet(_flags, (int)MessageFlags.Mentioned); } + set { SetUnset(ref _flags, value, (int)MessageFlags.Mentioned); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = GetObject(bytes, ref position); + ToId = GetObject(bytes, ref position); + _date = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + _media = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + _date = GetObject(input); + Message = GetObject(input); + _media = GetObject(input); + + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + var status = GetObject(input); + _status = (MessageStatus)status.Value; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + output.Write(Id.ToBytes()); + output.Write(FromId.ToBytes()); + ToId.ToStream(output); + output.Write(Date.ToBytes()); + Message.ToStream(output); + _media.ToStream(output); + + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = (TLMessage17)message; + var fixUnread = false; + if (!Unread.Value && m.Unread.Value) + { + fixUnread = true; +#if DEBUG + var builder = new StringBuilder(); +#if WINDOWS_PHONE + var stackTrace = new StackTrace(); + var frames = stackTrace.GetFrames(); + foreach (var r in frames) + { + builder.AppendLine(string.Format("Method: {0}", r.GetMethod())); + } +#endif + Telegram.Api.Helpers.Execute.ShowDebugMessage("Set read message as unread\ncurrent=" + this + "\nnew=" + message + "\n\n" + builder.ToString()); +#endif + } + + Flags = m.Flags; + + if (fixUnread) + { + SetUnreadSilent(TLBool.False); + } + } + } + + public class TLMessage : TLMessageCommon, IMessage + { + public const uint Signature = TLConstructors.TLMessage; + + public TLString Message { get; set; } + + public TLMessageMediaBase _media; + + public TLMessageMediaBase Media + { + get { return _media; } + set { SetField(ref _media, value, () => Media); } + } + + public override Visibility SelectionVisibility + { + get { return IsExpired() ? Visibility.Collapsed : Visibility.Visible; } + } + + public override int MediaSize + { + get { return Media.MediaSize; } + } + + public override Visibility MediaSizeVisibility + { + get { return _media is TLMessageMediaVideo ? Visibility.Visible : Visibility.Collapsed; } + } + + public override bool IsMusic() + { + var mediaDocument = _media as TLMessageMediaDocument; + if (mediaDocument != null) + { + return IsMusic(mediaDocument.Document); + } + + return false; + } + + public override bool IsVoice() + { + var mediaDocument = _media as TLMessageMediaDocument; + if (mediaDocument != null) + { + return IsVoice(mediaDocument.Document); + } + + return false; + } + + public override bool IsRoundVideo() + { + var mediaDocument = _media as TLMessageMediaDocument; + if (mediaDocument != null) + { + return IsRoundVideo(mediaDocument.Document); + } + + return false; + } + + public override bool IsVideo() + { + var mediaDocument = _media as TLMessageMediaDocument; + if (mediaDocument != null) + { + return IsVideo(mediaDocument.Document); + } + + return false; + } + + public override bool IsSticker() + { + var mediaDocument = _media as TLMessageMediaDocument; + if (mediaDocument != null) + { + return IsSticker(mediaDocument.Document); + } + + return false; + } + + public override bool IsExpired() + { + return IsExpired(_media); + } + + public override bool HasTTL() + { + return HasTTL(_media); + } + + public override bool IsGif() + { + var mediaDocument = _media as IMediaGif; + if (mediaDocument != null) + { + return IsGif(mediaDocument.Document); + } + + return false; + } + + public override double MediaWidth + { + get + { + if (Media != null) + { + return Media.MediaWidth; + } + + return base.MediaWidth; + } + } + + public override string ToString() + { + return base.ToString(); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + base.FromBytes(bytes, ref position); + Message = GetObject(bytes, ref position); + _media = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + base.FromStream(input); + Message = GetObject(input); + _media = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id = Id ?? new TLInt(0); + output.Write(Id.ToBytes()); + base.ToStream(output); + Message.ToStream(output); + _media.ToStream(output); + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = (TLMessage)message; + Message = m.Message; + var oldMedia = Media; + var newMedia = m.Media; + if (oldMedia.GetType() != newMedia.GetType()) + { + _media = m.Media; + } + else + { + var oldInvoice = oldMedia as TLMessageMediaInvoice; + var newInvoice = newMedia as TLMessageMediaInvoice; + if (oldInvoice != null && newInvoice != null && newInvoice.ReceiptMsgId != null) + { + oldInvoice.ReceiptMsgId = newInvoice.ReceiptMsgId; + + return; + } + + var oldMediaGame = oldMedia as TLMessageMediaGame; + var newMediaGame = newMedia as TLMessageMediaGame; + if (oldMediaGame != null && newMediaGame != null) + { + newMediaGame.Message = m.Message; + if (oldMediaGame.Game.GetType() != newMediaGame.Game.GetType()) + { + _media = m.Media; + } + else + { + var oldGame = oldMediaGame.Game; + var newGame = newMediaGame.Game; + if (oldGame != null + && newGame != null + && (oldGame.Id.Value != newGame.Id.Value)) + { + newMediaGame.SourceMessage = this; + _media = newMediaGame; + } + else + { + oldMediaGame.Message = m.Message; + } + } + + return; + } + + var oldMediaWebPage = oldMedia as TLMessageMediaWebPage; + var newMediaWebPage = newMedia as TLMessageMediaWebPage; + if (oldMediaWebPage != null && newMediaWebPage != null) + { + if (oldMediaWebPage.WebPage.GetType() != newMediaWebPage.WebPage.GetType()) + { + _media = m.Media; + } + else + { + var oldWebPage = oldMediaWebPage.WebPage as TLWebPage35; + var newWebPage = newMediaWebPage.WebPage as TLWebPage35; + if (oldWebPage != null + && newWebPage != null + && (oldWebPage.Id.Value != newWebPage.Id.Value)) + { + _media = m.Media; + } + } + + return; + } + + var oldMediaDocument = oldMedia as TLMessageMediaDocument; + var newMediaDocument = newMedia as TLMessageMediaDocument; + if (oldMediaDocument != null && newMediaDocument != null) + { + if (oldMediaDocument.Document.GetType() != newMediaDocument.Document.GetType()) + { + _media = m.Media; + } + else + { + var oldDocument = oldMediaDocument.Document as TLDocument; + var newDocument = newMediaDocument.Document as TLDocument; + if (oldDocument != null + && newDocument != null + && (oldDocument.Id.Value != newDocument.Id.Value + || oldDocument.AccessHash.Value != newDocument.AccessHash.Value)) + { + var isoFileName = Media.IsoFileName; + var notListened = Media.NotListened; +#if WP8 + var file = Media.File; +#endif + _media = m.Media; + _media.IsoFileName = isoFileName; + _media.NotListened = notListened; + +#if WP8 + _media.File = file; +#endif + } + } + + return; + } + + var oldMediaVideo = oldMedia as TLMessageMediaVideo; + var newMediaVideo = newMedia as TLMessageMediaVideo; + if (oldMediaVideo != null && newMediaVideo != null) + { + if (oldMediaVideo.Video.GetType() != newMediaVideo.Video.GetType()) + { + _media = m.Media; + } + else + { + var oldVideo = oldMediaVideo.Video as TLVideo; + var newVideo = newMediaVideo.Video as TLVideo; + if (oldVideo != null + && newVideo != null + && (oldVideo.Id.Value != newVideo.Id.Value + || oldVideo.AccessHash.Value != newVideo.AccessHash.Value)) + { + var isoFileName = Media.IsoFileName; + _media = m.Media; + _media.IsoFileName = isoFileName; + } + } + + return; + } + + var oldMediaAudio = oldMedia as TLMessageMediaAudio; + var newMediaAudio = newMedia as TLMessageMediaAudio; + if (oldMediaAudio != null && newMediaAudio != null) + { + if (oldMediaAudio.Audio.GetType() != newMediaAudio.Audio.GetType()) + { + _media = m.Media; + } + else + { + var oldAudio = oldMediaAudio.Audio as TLAudio; + var newAudio = newMediaAudio.Audio as TLAudio; + if (oldAudio != null + && newAudio != null + && (oldAudio.Id.Value != newAudio.Id.Value + || oldAudio.AccessHash.Value != newAudio.AccessHash.Value)) + { + var isoFileName = Media.IsoFileName; + var notListened = Media.NotListened; + _media = m.Media; + _media.IsoFileName = isoFileName; + _media.NotListened = notListened; + } + } + + return; + } + + var oldMediaPhoto = oldMedia as TLMessageMediaPhoto; + var newMediaPhoto = newMedia as TLMessageMediaPhoto; + if (oldMediaPhoto == null || newMediaPhoto == null) + { + _media = m.Media; + } + else + { + var oldPhoto = oldMediaPhoto.Photo as TLPhoto; + var newPhoto = newMediaPhoto.Photo as TLPhoto; + if (oldPhoto == null || newPhoto == null) + { + _media = m.Media; + } + else + { + if (oldPhoto.AccessHash.Value != newPhoto.AccessHash.Value) + { + var oldCachedSize = oldPhoto.Sizes.FirstOrDefault(x => x is TLPhotoCachedSize) as TLPhotoCachedSize; + var oldMSize = oldPhoto.Sizes.FirstOrDefault(x => TLString.Equals(x.Type, new TLString("m"), StringComparison.OrdinalIgnoreCase)); + foreach (var size in newPhoto.Sizes) + { + if (size is TLPhotoCachedSize) + { + size.TempUrl = oldCachedSize != null ? oldCachedSize.TempUrl : null; + } + else if (TLString.Equals(size.Type, new TLString("s"), StringComparison.OrdinalIgnoreCase)) + { + size.TempUrl = oldCachedSize != null ? oldCachedSize.TempUrl : null; + } + else + { + size.TempUrl = oldMSize != null ? oldMSize.TempUrl : null; + } + } + + _media = m.Media; + } + } + } + } + } + + #region Additional + + private TLInputMediaBase _inputMedia; + + /// + /// To resend canceled message + /// + public TLInputMediaBase InputMedia + { + get { return _inputMedia; } + set { SetField(ref _inputMedia, value, () => InputMedia); } + } + + public List Links { get; set; } + + #endregion + } + + [Obsolete] + public class TLMessageForwarded17 : TLMessageForwarded + { + public new const uint Signature = TLConstructors.TLMessageForwarded17; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override TLBool Out + { + get { return new TLBool(IsSet(_flags, (int)MessageFlags.Out)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)MessageFlags.Out); + } + } + } + + public override void SetUnread(TLBool value) + { + Unread = value; + } + + public override TLBool Unread + { + get { return new TLBool(IsSet(_flags, (int)MessageFlags.Unread)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)MessageFlags.Unread); + NotifyOfPropertyChange(() => Status); + } + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FwdFromId = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + FromId = GetObject(bytes, ref position); + ToId = GetObject(bytes, ref position); + _date = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + _media = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FwdFromId = GetObject(input); + FwdDate = GetObject(input); + FromId = GetObject(input); + ToId = GetObject(input); + _date = GetObject(input); + Message = GetObject(input); + _media = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + Id.ToStream(output); + FwdFromId.ToStream(output); + FwdDate.ToStream(output); + FromId.ToStream(output); + ToId.ToStream(output); + _date.ToStream(output); + Message.ToStream(output); + _media.ToStream(output); + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = (TLMessageForwarded17)message; + Flags = m.Flags; + } + } + + [Obsolete] + public class TLMessageForwarded : TLMessage + { + public new const uint Signature = TLConstructors.TLMessageForwarded; + + public TLInt FwdFromId { get; set; } + + public TLUserBase FwdFrom + { + get + { + var cacheService = InMemoryCacheService.Instance; + return cacheService.GetUser(FwdFromId); + } + } + + public TLInt FwdDate { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + FwdFromId = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + FromId = GetObject(bytes, ref position); + ToId = GetObject(bytes, ref position); + Out = GetObject(bytes, ref position); + Unread = GetObject(bytes, ref position); + _date = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + _media = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FwdFromId = GetObject(input); + FwdDate = GetObject(input); + FromId = GetObject(input); + ToId = GetObject(input); + Out = GetObject(input); + Unread = GetObject(input); + _date = GetObject(input); + Message = GetObject(input); + _media = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id = Id ?? new TLInt(0); + Id.ToStream(output); + FwdFromId.ToStream(output); + FwdDate.ToStream(output); + FromId.ToStream(output); + ToId.ToStream(output); + Out.ToStream(output); + Unread.ToStream(output); + _date.ToStream(output); + Message.ToStream(output); + _media.ToStream(output); + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = (TLMessageForwarded)message; + FwdFromId = m.FwdFromId; + FwdDate = m.FwdDate; + } + } + + public class TLMessageService49 : TLMessageService40, IReplyToMsgId + { + public new const uint Signature = TLConstructors.TLMessageService49; + + private TLInt _replyToMsgId; + + public TLInt ReplyToMsgId + { + get { return _replyToMsgId; } + set { SetField(out _replyToMsgId, value, ref _flags, (int)MessageFlags.ReplyToMsgId); } + } + + public override ReplyInfo ReplyInfo + { + get { return ReplyToMsgId != null ? new ReplyInfo { ReplyToMsgId = ReplyToMsgId, Reply = Reply } : null; } + } + + public TLMessageService49 Media + { + get { return this; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = IsSet(Flags, (int)MessageFlags.FromId) + ? GetObject(bytes, ref position) + : new TLInt(-1); + ToId = GetObject(bytes, ref position); + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + _date = GetObject(bytes, ref position); + Action = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(input); + } + _date = GetObject(input); + + // workaround: RandomId and Status were missing here, so Flags.31 (bits 100000...000) is recerved to handle this issue + if (IsSet(Flags, int.MinValue)) + { + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + var status = GetObject(input); + _status = (MessageStatus)status.Value; + } + + Action = GetObject(input); + + CustomFlags = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Set(ref _flags, int.MinValue); // workaround + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + Id.ToStream(output); + FromId.ToStream(output); + ToId.ToStream(output); + ToStream(output, ReplyToMsgId, Flags, (int)MessageFlags.ReplyToMsgId); + _date.ToStream(output); + + // workaround: RandomId and Status were missing here, so Flags.31 is recerved to handle this issue + + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + + Action.ToStream(output); + + CustomFlags.NullableToStream(output); + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + + var m = message as TLMessageService49; + if (m != null) + { + if (m.ReplyToMsgId != null) + { + ReplyToMsgId = m.ReplyToMsgId; + } + } + } + + public override string ToString() + { + return base.ToString() + string.Format("ReplyToMsgId={0} Reply={1}", ReplyToMsgId != null ? ReplyToMsgId.Value.ToString(CultureInfo.InvariantCulture) : "null", Reply != null ? Reply.GetType().Name : "null"); + } + } + + public class TLMessageService40 : TLMessageService17 + { + public new const uint Signature = TLConstructors.TLMessageService40; + + private TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + public bool Silent { get { return IsSet(Flags, (int)MessageFlags.Silent); } } + + public bool Post { get { return IsSet(Flags, (int)MessageFlags.Post); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = IsSet(Flags, (int)MessageFlags.FromId) + ? GetObject(bytes, ref position) + : new TLInt(-1); + ToId = GetObject(bytes, ref position); + _date = GetObject(bytes, ref position); + Action = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + _date = GetObject(input); + + // workaround: RandomId and Status were missing here, so Flags.31 (bits 100000...000) is recerved to handle this issue + if (IsSet(Flags, int.MinValue)) + { + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + var status = GetObject(input); + _status = (MessageStatus)status.Value; + } + + Action = GetObject(input); + + CustomFlags = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Set(ref _flags, int.MinValue); // workaround + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + Id.ToStream(output); + FromId.ToStream(output); + ToId.ToStream(output); + _date.ToStream(output); + + // workaround: RandomId and Status were missing here, so Flags.31 is recerved to handle this issue + + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + + Action.ToStream(output); + + CustomFlags.NullableToStream(output); + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + + var m = message as TLMessageService40; + if (m != null) + { + if (m.CustomFlags != null) + { + CustomFlags = m.CustomFlags; + } + } + } + + public override string ToString() + { + return base.ToString() + " CustomFlags=" + MessageCustomFlagsString(CustomFlags); + } + } + + public class TLMessageService17 : TLMessageService + { + public new const uint Signature = TLConstructors.TLMessageService17; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override TLBool Out + { + get { return new TLBool(IsSet(_flags, (int)MessageFlags.Out)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)MessageFlags.Out); + } + } + } + + public override void SetUnread(TLBool value) + { + Unread = value; + } + + public override void SetUnreadSilent(TLBool value) + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)MessageFlags.Unread); + } + } + + public override TLBool Unread + { + get { return new TLBool(IsSet(_flags, (int)MessageFlags.Unread)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)MessageFlags.Unread); + NotifyOfPropertyChange(() => Status); + } + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + FromId = GetObject(bytes, ref position); + ToId = GetObject(bytes, ref position); + _date = GetObject(bytes, ref position); + Action = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + FromId = GetObject(input); + ToId = GetObject(input); + _date = GetObject(input); + + // workaround: RandomId and Status were missing here, so Flags.31 (bits 100000...000) is recerved to handle this issue + if (IsSet(_flags, int.MinValue)) + { + var randomId = GetObject(input); + if (randomId.Value != 0) + { + RandomId = randomId; + } + var status = GetObject(input); + _status = (MessageStatus)status.Value; + } + + Action = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Set(ref _flags, int.MinValue); // workaround + + Flags.ToStream(output); + Id = Id ?? new TLInt(0); + Id.ToStream(output); + FromId.ToStream(output); + ToId.ToStream(output); + _date.ToStream(output); + + // workaround: RandomId and Status were missing here, so Flags.31 is recerved to handle this issue + + RandomId = RandomId ?? new TLLong(0); + RandomId.ToStream(output); + var status = new TLInt((int)Status); + output.Write(status.ToBytes()); + + Action.ToStream(output); + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = (TLMessageService17)message; + + Flags = m.Flags; + } + + public override string ToString() + { + return base.ToString() + " Flags=" + MessageFlagsString(Flags); + } + } + + public class TLMessageService : TLMessageCommon + { + public const uint Signature = TLConstructors.TLMessageService; + + public TLMessageActionBase Action { get; set; } + + public override double MediaWidth + { + get + { + var phoneCall = Action as TLMessageActionPhoneCall; + if (phoneCall != null) + { + return 12.0 + 284.0 + 12.0; + } + + return base.MediaWidth; + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + base.FromBytes(bytes, ref position); + Action = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + var id = GetObject(input); + if (id.Value != 0) + { + Id = id; + } + base.FromStream(input); + Action = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id = Id ?? new TLInt(0); + Id.ToStream(output); + base.ToStream(output); + Action.ToStream(output); + } + + public override void Update(TLMessageBase message) + { + base.Update(message); + var m = (TLMessageService)message; + + if (Action != null) + { + Action.Update(m.Action); + } + else + { + Action = m.Action; + } + } + + + public override void Edit(TLMessageBase messageBase) + { + var message = messageBase as TLMessageService; + if (message != null) + { + var oldMessageMediaActionGame = Action as TLMessageActionGameScore; + var newMessageMediaActionGame = message.Action as TLMessageActionGameScore; + + if (oldMessageMediaActionGame != null + && newMessageMediaActionGame != null + && oldMessageMediaActionGame.Score.Value != newMessageMediaActionGame.Score.Value) + { + oldMessageMediaActionGame.Score = newMessageMediaActionGame.Score; + } + } + } + + public override Visibility SelectionVisibility + { + get { return Visibility.Collapsed; } + } + + public override string ToString() + { + return base.ToString() + " action=" + Action; + } + } +} diff --git a/Telegram.Api/TL/TLMessageAction.cs b/Telegram.Api/TL/TLMessageAction.cs new file mode 100755 index 0000000..502ad03 --- /dev/null +++ b/Telegram.Api/TL/TLMessageAction.cs @@ -0,0 +1,1167 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum MessageActionPhoneCallFlags + { + Reason = 0x1, // 0 + Duration = 0x2, // 1 + } + + [Flags] + public enum MessageActionPaymentSentMeFlags + { + Info = 0x1, // 0 + ShippingOptionId = 0x2, // 1 + } + + public abstract class TLMessageActionBase : TLObject + { + public abstract void Update(TLMessageActionBase newAction); + + public TLPhotoBase Photo { get; set; } + } + + public class TLMessageActionEmpty : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionChatCreate : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionChatCreate; + + public TLString Title { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Title = GetObject(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Title = GetObject(input); + Users = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Title.ToStream(output); + Users.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + var action = newAction as TLMessageActionChatCreate; + if (action != null) + { + Title = action.Title; + Users = action.Users; + } + } + } + + public class TLMessageActionChannelCreate : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionChannelCreate; + + public TLString Title { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Title = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Title = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Title.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + var action = newAction as TLMessageActionChannelCreate; + if (action != null) + { + Title = action.Title; + } + } + } + + public class TLMessageActionToggleComments : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionToggleComments; + + public TLBool Enabled { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Enabled = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Enabled = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Enabled.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + var action = newAction as TLMessageActionToggleComments; + if (action != null) + { + Enabled = action.Enabled; + } + } + } + + public class TLMessageActionChatEditTitle : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionChatEditTitle; + + public TLString Title { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Title = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Title = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Title.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + var action = newAction as TLMessageActionChatEditTitle; + if (action != null) + { + Title = action.Title; + } + } + } + + public class TLMessageActionChatEditPhoto : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionChatEditPhoto; + + //public TLPhotoBase Photo { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Photo = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Photo = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Photo.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + var action = newAction as TLMessageActionChatEditPhoto; + if (action != null) + { + if (Photo != null) + { + Photo.Update(action.Photo); + } + else + { + Photo = action.Photo; + } + } + } + } + + public class TLMessageActionChatDeletePhoto : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionChatDeletePhoto; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override void Update(TLMessageActionBase newAction) + { + + } + } + + public class TLMessageActionChannelJoined : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionChannelJoined; + + public TLInt InviterId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + InviterId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + InviterId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + InviterId.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + var action = newAction as TLMessageActionChannelJoined; + if (action != null) + { + InviterId = action.InviterId; + } + } + } + + public abstract class TLMessageActionChatAddUserBase : TLMessageActionBase + { + + } + + public class TLMessageActionChatAddUser : TLMessageActionChatAddUserBase + { + public const uint Signature = TLConstructors.TLMessageActionChatAddUser; + + public TLInt UserId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + var action = newAction as TLMessageActionChatAddUser; + if (action != null) + { + UserId = action.UserId; + } + } + } + + public class TLMessageActionChatAddUser41 : TLMessageActionChatAddUserBase + { + public const uint Signature = TLConstructors.TLMessageActionChatAddUser41; + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Users = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Users.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + var action = newAction as TLMessageActionChatAddUser41; + if (action != null) + { + Users = action.Users; + } + } + } + + public class TLMessageActionChatDeleteUser : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionChatDeleteUser; + + public TLInt UserId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + var action = newAction as TLMessageActionChatDeleteUser; + if (action != null) + { + UserId = action.UserId; + } + } + } + + public class TLMessageActionChatJoinedByLink : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionChatJoinedByLink; + + public TLInt InviterId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + InviterId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + InviterId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + InviterId.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionUnreadMessages : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionUnreadMessages; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override void Update(TLMessageActionBase newAction) + { + + } + } + + public class TLMessageActionContactRegistered : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionContactRegistered; + + public TLInt UserId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionMessageGroup : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionMessageGroup; + + public TLMessageGroup Group { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Group = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Group = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Group.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionChatMigrateTo : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionChatMigrateTo; + + public TLInt ChannelId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChannelId.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionChatDeactivate : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionChatDeactivate; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionChatActivate : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionChatActivate; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionChannelMigrateFrom : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionChannelMigrateFrom; + + public TLString Title { get; set; } + + public TLInt ChatId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Title = GetObject(bytes, ref position); + ChatId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Title = GetObject(input); + ChatId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Title.ToStream(output); + ChatId.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionPinMessage : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionPinMessage; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionClearHistory : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionClearHistory; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionGameScore : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionGameScore; + + public TLLong GameId { get; set; } + + public TLInt Score { get; set; } + + public override string ToString() + { + return string.Format("{0} game_id={1} score={2}", GetType().Name, GameId, Score); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + GameId = GetObject(bytes, ref position); + Score = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + GameId = GetObject(input); + Score = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + GameId.ToStream(output); + Score.ToStream(output); + } + + public override void Update(TLMessageActionBase action) + { + var actionGameScore = action as TLMessageActionGameScore; + if (actionGameScore != null) + { + GameId = actionGameScore.GameId; + Score = actionGameScore.Score; + } + } + } + + public class TLMessageActionPhoneCall : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionPhoneCall; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLLong CallId { get; set; } + + protected TLPhoneCallDiscardReasonBase _reason; + + public TLPhoneCallDiscardReasonBase Reason + { + get { return _reason; } + set { SetField(out _reason, value, ref _flags, (int) MessageActionPhoneCallFlags.Reason); } + } + + protected TLInt _duration; + + public TLInt Duration + { + get { return _duration; } + set { SetField(out _duration, value, ref _flags, (int) MessageActionPhoneCallFlags.Duration); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + CallId = GetObject(bytes, ref position); + _reason = GetObject(Flags, (int) MessageActionPhoneCallFlags.Reason, null, bytes, ref position); + _duration = GetObject(Flags, (int) MessageActionPhoneCallFlags.Duration, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + CallId = GetObject(input); + _reason = GetObject(Flags, (int) MessageActionPhoneCallFlags.Reason, null, input); + _duration = GetObject(Flags, (int) MessageActionPhoneCallFlags.Duration, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + CallId.ToStream(output); + ToStream(output, Reason, Flags, (int) MessageActionPhoneCallFlags.Reason); + ToStream(output, Duration, Flags, (int) MessageActionPhoneCallFlags.Duration); + } + + public override void Update(TLMessageActionBase action) + { + var actionPhoneCall = action as TLMessageActionPhoneCall; + if (actionPhoneCall != null) + { + CallId = actionPhoneCall.CallId; + Reason = actionPhoneCall.Reason; + Duration = actionPhoneCall.Duration; + } + } + } + + public abstract class TLMessageActionPaymentSentBase : TLMessageActionBase + { + public TLString Currency { get; set; } + + public TLLong TotalAmount { get; set; } + } + + public class TLMessageActionPaymentSentMe : TLMessageActionPaymentSentBase + { + public const uint Signature = TLConstructors.TLMessageActionPaymentSentMe; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLString Payload { get; set; } + + protected TLPaymentRequestedInfo _info; + + public TLPaymentRequestedInfo Info + { + get { return _info; } + set { SetField(out _info, value, ref _flags, (int) MessageActionPaymentSentMeFlags.Info); } + } + + protected TLString _shippingOptionId; + + public TLString ShippingOptionId + { + get { return _shippingOptionId; } + set { SetField(out _shippingOptionId, value, ref _flags, (int) MessageActionPaymentSentMeFlags.ShippingOptionId); } + } + + public TLPaymentCharge Charge { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Currency = GetObject(bytes, ref position); + TotalAmount = GetObject(bytes, ref position); + Payload = GetObject(bytes, ref position); + _info = GetObject(Flags, (int) MessageActionPaymentSentMeFlags.Info, null, bytes, ref position); + _shippingOptionId = GetObject(Flags, (int) MessageActionPaymentSentMeFlags.ShippingOptionId, null, bytes, ref position); + Charge = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Currency = GetObject(input); + TotalAmount = GetObject(input); + Payload = GetObject(input); + _info = GetObject(Flags, (int) MessageActionPaymentSentMeFlags.Info, null, input); + _shippingOptionId = GetObject(Flags, (int) MessageActionPaymentSentMeFlags.ShippingOptionId, null, input); + Charge = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Currency.ToStream(output); + TotalAmount.ToStream(output); + Payload.ToStream(output); + ToStream(output, _info, Flags, (int) MessageActionPaymentSentMeFlags.Info); + ToStream(output, _shippingOptionId, Flags, (int) MessageActionPaymentSentMeFlags.ShippingOptionId); + Charge.ToStream(output); + } + + public override void Update(TLMessageActionBase action) + { + var actionPaymentSentMe = action as TLMessageActionPaymentSentMe; + if (actionPaymentSentMe != null) + { + Currency = actionPaymentSentMe.Currency; + TotalAmount = actionPaymentSentMe.TotalAmount; + Payload = actionPaymentSentMe.Payload; + Info = actionPaymentSentMe.Info; + ShippingOptionId = actionPaymentSentMe.ShippingOptionId; + Charge = actionPaymentSentMe.Charge; + } + } + } + + public class TLMessageActionPaymentSent : TLMessageActionPaymentSentBase + { + public const uint Signature = TLConstructors.TLMessageActionPaymentSent; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Currency = GetObject(bytes, ref position); + TotalAmount = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Currency = GetObject(input); + TotalAmount = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Currency.ToStream(output); + TotalAmount.ToStream(output); + } + + public override void Update(TLMessageActionBase action) + { + var actionPaymentSent = action as TLMessageActionPaymentSent; + if (actionPaymentSent != null) + { + Currency = actionPaymentSent.Currency; + TotalAmount = actionPaymentSent.TotalAmount; + } + } + } + + public class TLMessageActionScreenshotTaken : TLMessageActionPaymentSentBase + { + public const uint Signature = TLConstructors.TLMessageActionScreenshotTaken; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override void Update(TLMessageActionBase action) + { + + } + } + + public class TLMessageActionCustomAction : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionCustomAction; + + public TLString Message { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Message = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Message.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionBotAllowed : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionBotAllowed; + + public TLString Domain { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Domain = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Domain = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Domain.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionSecureValuesSentMe : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionSecureValuesSentMe; + + public TLVector Values { get; set; } + + public TLSecureCredentialsEncrypted Credentials { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Values = GetObject>(bytes, ref position); + Credentials = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Values = GetObject>(input); + Credentials = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Values.ToStream(output); + Credentials.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } + + public class TLMessageActionSecureValuesSent : TLMessageActionBase + { + public const uint Signature = TLConstructors.TLMessageActionSecureValuesSent; + + public TLVector Types { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Types = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Types = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Types.ToStream(output); + } + + public override void Update(TLMessageActionBase newAction) + { + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLMessageContainer.cs b/Telegram.Api/TL/TLMessageContainer.cs new file mode 100755 index 0000000..c0133f1 --- /dev/null +++ b/Telegram.Api/TL/TLMessageContainer.cs @@ -0,0 +1,52 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Telegram.Api.TL +{ + public class TLContainer : TLObject + { + public const uint Signature = TLConstructors.TLContainer; + + public List Messages { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = new List(); + + var length = BitConverter.ToInt32(bytes, position); + position += 4; + for (var i = 0; i < length; i++) + { + Messages.Add(GetObject(bytes, ref position)); + } + + return this; + } + + public override byte[] ToBytes() + { + var stream = new MemoryStream(); + foreach (var message in Messages) + { + var bytes = message.ToBytes(); + stream.Write(bytes, 0, bytes.Length); + } + + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + BitConverter.GetBytes(Messages.Count), + stream.ToArray()); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLMessageEditData.cs b/Telegram.Api/TL/TLMessageEditData.cs new file mode 100755 index 0000000..d572be6 --- /dev/null +++ b/Telegram.Api/TL/TLMessageEditData.cs @@ -0,0 +1,36 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + + [Flags] + public enum MessageEditDataFlags + { + Caption = 0x1, // 0 + } + + public class TLMessageEditData : TLObject + { + public const uint Signature = TLConstructors.TLMessageEditData; + + public TLInt Flags { get; set; } + + public bool Caption { get { return IsSet(Flags, (int) MessageEditDataFlags.Caption); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLMessageEntity.cs b/Telegram.Api/TL/TLMessageEntity.cs new file mode 100755 index 0000000..c44e7ae --- /dev/null +++ b/Telegram.Api/TL/TLMessageEntity.cs @@ -0,0 +1,643 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLMessageEntityBase : TLObject + { + public TLInt Offset { get; set; } + + public TLInt Length { get; set; } + } + + public class TLMessageEntityUnknown : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityUnknown; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + + return this; + } + } + + public class TLMessageEntityMention : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityMention; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + + return this; + } + } + + public class TLMessageEntityHashtag : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityHashtag; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + + return this; + } + } + + public class TLMessageEntityBotCommand : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityBotCommand; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + + return this; + } + } + + public class TLMessageEntityUrl : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityUrl; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + + return this; + } + } + + public class TLMessageEntityEmail : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityEmail; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + + return this; + } + } + + public class TLMessageEntityBold : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityBold; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + + return this; + } + } + + public class TLMessageEntityItalic : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityItalic; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + + return this; + } + } + + public class TLMessageEntityCode : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityCode; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + + return this; + } + } + + public class TLMessageEntityPre : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityPre; + + public TLString Language { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + Language = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes(), + Language.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + Language.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + Language = GetObject(input); + + return this; + } + } + + public class TLMessageEntityTextUrl : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityTextUrl; + + public TLString Url { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + Url = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes(), + Url.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + Url.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + Url = GetObject(input); + + return this; + } + } + + public class TLInputMessageEntityMentionName : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLInputMessageEntityMentionName; + + public TLInputUserBase User { get; set; } + + public string Name { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + User = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes(), + User.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + User.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + User = GetObject(input); + + return this; + } + } + + public class TLMessageEntityMentionName : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityMentionName; + + public TLInt UserId { get; set; } + + public string Name { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes(), + UserId.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + UserId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + UserId = GetObject(input); + + return this; + } + } + + public class TLMessageEntityPhone : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityPhone; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + + return this; + } + } + + public class TLMessageEntityCashtag : TLMessageEntityBase + { + public const uint Signature = TLConstructors.TLMessageEntityCashtag; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Offset = GetObject(bytes, ref position); + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Offset.ToBytes(), + Length.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Offset.ToStream(output); + Length.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Offset = GetObject(input); + Length = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLMessageFwdHeader.cs b/Telegram.Api/TL/TLMessageFwdHeader.cs new file mode 100755 index 0000000..8bf4d0c --- /dev/null +++ b/Telegram.Api/TL/TLMessageFwdHeader.cs @@ -0,0 +1,373 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; +using Telegram.Api.Services.Cache; + +namespace Telegram.Api.TL +{ + + [Flags] + public enum MessageFwdHeaderFlags + { + From = 0x1, // 0 + Channel = 0x2, // 1 + ChannelPost = 0x4, // 2 + PostAuthor = 0x8, // 3 + Saved = 0x10, // 4 + } + + public class TLMessageFwdHeader : TLObject + { + public const uint Signature = TLConstructors.TLMessageFwdHeader; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLInt _fromId; + + public TLInt FromId + { + get { return _fromId; } + set + { + if (value != null) + { + _fromId = value; + Set(ref _flags, (int)MessageFwdHeaderFlags.From); + } + else + { + Unset(ref _flags, (int)MessageFwdHeaderFlags.From); + } + } + } + + public TLInt Date { get; set; } + + private TLInt _channelId; + + public TLInt ChannelId + { + get { return _channelId; } + set + { + if (value != null) + { + _channelId = value; + Set(ref _flags, (int) MessageFwdHeaderFlags.Channel); + } + else + { + Unset(ref _flags, (int)MessageFwdHeaderFlags.Channel); + } + } + } + + private TLInt _channelPost; + + public TLInt ChannelPost + { + get { return _channelPost; } + set + { + if (value != null) + { + _channelPost = value; + Set(ref _flags, (int)MessageFwdHeaderFlags.ChannelPost); + } + else + { + Unset(ref _flags, (int)MessageFwdHeaderFlags.ChannelPost); + } + } + } + + private string _fullName; + + public virtual string FullName + { + get + { + if (_fullName != null) return _fullName; + + var cacheService = InMemoryCacheService.Instance; + + var channel = ChannelId != null? cacheService.GetChat(ChannelId) : null; + var user = FromId != null? cacheService.GetUser(FromId) : null; + + if (channel != null && user != null) + { + _fullName = string.Format("{0} ({1})", channel.FullName, user.FullName); + return _fullName; + } + + if (channel != null) + { + _fullName = channel.FullName; + return _fullName; + } + + if (user != null) + { + _fullName = user.FullName2; + return _fullName; + } + + return null; + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + if (IsSet(Flags, (int) MessageFwdHeaderFlags.From)) + { + FromId = GetObject(bytes, ref position); + } + Date = GetObject(bytes, ref position); + if (IsSet(Flags, (int) MessageFwdHeaderFlags.Channel)) + { + ChannelId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFwdHeaderFlags.ChannelPost)) + { + ChannelPost = GetObject(bytes, ref position); + } + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + if (IsSet(Flags, (int) MessageFwdHeaderFlags.From)) + { + FromId = GetObject(input); + } + Date = GetObject(input); + if (IsSet(Flags, (int) MessageFwdHeaderFlags.Channel)) + { + ChannelId = GetObject(input); + } + if (IsSet(Flags, (int)MessageFwdHeaderFlags.ChannelPost)) + { + ChannelPost = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, FromId, Flags, (int)MessageFwdHeaderFlags.From); + Date.ToStream(output); + ToStream(output, ChannelId, Flags, (int)MessageFwdHeaderFlags.Channel); + ToStream(output, ChannelPost, Flags, (int)MessageFwdHeaderFlags.ChannelPost); + } + + public TLPeerBase ToFwdFromPeer() + { + if (ChannelId != null) + { + return new TLPeerChannel{ Id = ChannelId }; + } + + return new TLPeerUser { Id = FromId }; + } + } + + public class TLMessageFwdHeader73 : TLMessageFwdHeader70 + { + public new const uint Signature = TLConstructors.TLMessageFwdHeader73; + + private TLPeerBase _savedFromPeer; + + public TLPeerBase SavedFromPeer + { + get { return _savedFromPeer; } + set { SetField(out _savedFromPeer, value, ref _flags, (int)MessageFwdHeaderFlags.Saved); } + } + + private TLInt _savedFromMsgId; + + public TLInt SavedFromMsgId + { + get { return _savedFromMsgId; } + set { SetField(out _savedFromMsgId, value, ref _flags, (int)MessageFwdHeaderFlags.Saved); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + FromId = GetObject(Flags, (int)MessageFwdHeaderFlags.From, null, bytes, ref position); + Date = GetObject(bytes, ref position); + ChannelId = GetObject(Flags, (int)MessageFwdHeaderFlags.Channel, null, bytes, ref position); + ChannelPost = GetObject(Flags, (int)MessageFwdHeaderFlags.ChannelPost, null, bytes, ref position); + PostAuthor = GetObject(Flags, (int)MessageFwdHeaderFlags.PostAuthor, null, bytes, ref position); + SavedFromPeer = GetObject(Flags, (int)MessageFwdHeaderFlags.Saved, null, bytes, ref position); + SavedFromMsgId = GetObject(Flags, (int)MessageFwdHeaderFlags.Saved, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + FromId = GetObject(Flags, (int)MessageFwdHeaderFlags.From, null, input); + Date = GetObject(input); + ChannelId = GetObject(Flags, (int)MessageFwdHeaderFlags.Channel, null, input); + ChannelPost = GetObject(Flags, (int)MessageFwdHeaderFlags.ChannelPost, null, input); + PostAuthor = GetObject(Flags, (int)MessageFwdHeaderFlags.PostAuthor, null, input); + SavedFromPeer = GetObject(Flags, (int)MessageFwdHeaderFlags.Saved, null, input); + SavedFromMsgId = GetObject(Flags, (int)MessageFwdHeaderFlags.Saved, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, FromId, Flags, (int)MessageFwdHeaderFlags.From); + Date.ToStream(output); + ToStream(output, ChannelId, Flags, (int)MessageFwdHeaderFlags.Channel); + ToStream(output, ChannelPost, Flags, (int)MessageFwdHeaderFlags.ChannelPost); + ToStream(output, PostAuthor, Flags, (int)MessageFwdHeaderFlags.PostAuthor); + ToStream(output, SavedFromPeer, Flags, (int)MessageFwdHeaderFlags.Saved); + ToStream(output, SavedFromMsgId, Flags, (int)MessageFwdHeaderFlags.Saved); + } + } + + public class TLMessageFwdHeader70 : TLMessageFwdHeader + { + public new const uint Signature = TLConstructors.TLMessageFwdHeader70; + + private TLString _postAuthor; + + public TLString PostAuthor + { + get { return _postAuthor; } + set { SetField(out _postAuthor, value, ref _flags, (int) MessageFwdHeaderFlags.PostAuthor); } + } + + private TLObject _from; + + public TLObject From + { + get + { + if (_from != null) return _from; + + if (FromId == null && ChannelId == null) return null; + + if (ChannelId != null) + { + var cacheService = InMemoryCacheService.Instance; + _from = cacheService.GetChat(ChannelId); + } + else if (FromId != null) + { + var cacheService = InMemoryCacheService.Instance; + _from = cacheService.GetUser(FromId); + } + + return _from; + } + } + + private string _fullName; + + public override string FullName + { + get + { + if (_fullName != null) return _fullName; + + var cacheService = InMemoryCacheService.Instance; + + var channel = ChannelId != null ? cacheService.GetChat(ChannelId) : null; + var user = FromId != null ? cacheService.GetUser(FromId) : null; + + if (channel != null && (user != null || !TLString.IsNullOrEmpty(PostAuthor))) + { + _fullName = string.Format("{0} ({1})", channel.FullName, user != null ? user.FullName : PostAuthor.ToString()); + return _fullName; + } + + if (channel != null) + { + _fullName = channel.FullName; + return _fullName; + } + + if (!TLString.IsNullOrEmpty(PostAuthor)) + { + return _fullName = PostAuthor.ToString(); + } + + if (user != null) + { + _fullName = user.FullName2; + return _fullName; + } + + return null; + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + FromId = GetObject(Flags, (int)MessageFwdHeaderFlags.From, null, bytes, ref position); + Date = GetObject(bytes, ref position); + ChannelId = GetObject(Flags, (int)MessageFwdHeaderFlags.Channel, null, bytes, ref position); + ChannelPost = GetObject(Flags, (int)MessageFwdHeaderFlags.ChannelPost, null, bytes, ref position); + PostAuthor = GetObject(Flags, (int)MessageFwdHeaderFlags.PostAuthor, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + FromId = GetObject(Flags, (int)MessageFwdHeaderFlags.From, null, input); + Date = GetObject(input); + ChannelId = GetObject(Flags, (int)MessageFwdHeaderFlags.Channel, null, input); + ChannelPost = GetObject(Flags, (int)MessageFwdHeaderFlags.ChannelPost, null, input); + PostAuthor = GetObject(Flags, (int)MessageFwdHeaderFlags.PostAuthor, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, FromId, Flags, (int)MessageFwdHeaderFlags.From); + Date.ToStream(output); + ToStream(output, ChannelId, Flags, (int)MessageFwdHeaderFlags.Channel); + ToStream(output, ChannelPost, Flags, (int)MessageFwdHeaderFlags.ChannelPost); + ToStream(output, PostAuthor, Flags, (int)MessageFwdHeaderFlags.PostAuthor); + } + } +} diff --git a/Telegram.Api/TL/TLMessageGroup.cs b/Telegram.Api/TL/TLMessageGroup.cs new file mode 100755 index 0000000..6d0228a --- /dev/null +++ b/Telegram.Api/TL/TLMessageGroup.cs @@ -0,0 +1,68 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLMessageGroup : TLObject + { + public const uint Signature = TLConstructors.TLMessageGroup; + + public TLInt MinId { get; set; } + + public TLInt MaxId { get; set; } + + public TLInt Count { get; set; } + + public TLInt Date { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + MinId.ToBytes(), + MaxId.ToBytes(), + Count.ToBytes(), + Date.ToBytes() + ); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + MinId = GetObject(bytes, ref position); + MaxId = GetObject(bytes, ref position); + Count = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + MinId.ToStream(output); + MaxId.ToStream(output); + Count.ToStream(output); + Date.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + MinId = GetObject(input); + MaxId = GetObject(input); + Count = GetObject(input); + Date = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLMessageInfo.cs b/Telegram.Api/TL/TLMessageInfo.cs new file mode 100755 index 0000000..6a25197 --- /dev/null +++ b/Telegram.Api/TL/TLMessageInfo.cs @@ -0,0 +1,74 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLMessageDetailedInfoBase : TLObject + { + public TLLong AnswerMessageId { get; set; } + + public TLInt Bytes { get; set; } + + public TLInt Status { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + AnswerMessageId = GetObject(bytes, ref position); + Bytes = GetObject(bytes, ref position); + Status = GetObject(bytes, ref position); + + return this; + } + } + + public class TLMessageDetailedInfo : TLMessageDetailedInfoBase + { + public const uint Signature = TLConstructors.TLMessageDetailedInfo; + + public TLLong MessageId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + MessageId = GetObject(bytes, ref position); + + return base.FromBytes(bytes, ref position); + } + } + + public class TLMessageNewDetailedInfo : TLMessageDetailedInfoBase + { + public const uint Signature = TLConstructors.TLMessageNewDetailedInfo; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return base.FromBytes(bytes, ref position); + } + } + + public class TLMessagesAllInfo : TLObject + { + public const uint Signature = TLConstructors.TLMessagesAllInfo; + + public TLVector MessageIds { get; set; } + + public TLString Info { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + MessageIds = GetObject>(bytes, ref position); + Info = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLMessageMedia.cs b/Telegram.Api/TL/TLMessageMedia.cs new file mode 100755 index 0000000..5cb1b41 --- /dev/null +++ b/Telegram.Api/TL/TLMessageMedia.cs @@ -0,0 +1,1712 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.IO; +#if WP81 +using Windows.Media.Transcoding; +#endif +using System.Linq; +#if WIN_RT +using Windows.UI.Xaml; +#else +using System.Windows; +#endif +#if WP8 +using Windows.Storage; +#endif +using Telegram.Api.Services.Cache; +using Telegram.Api.Extensions; +using Telegram.Api.Services; + +namespace Telegram.Api.TL +{ + [Flags] + public enum MessageMediaPhotoFlags + { + Photo = 0x1, // 0 + Caption = 0x2, // 1 + TTLSeconds = 0x4, // 2 + } + + [Flags] + public enum MessageMediaDocumentFlags + { + Document = 0x1, // 0 + Caption = 0x2, // 1 + TTLSeconds = 0x4, // 2 + } + + [Flags] + public enum MessageMediaInvoiceFlags + { + Photo = 0x1, // 0 + ShippingAddressRequested = 0x2, // 1 + ReceiptMsgId = 0x4, // 2 + Test = 0x8, // 3 + } + + public interface IMediaCaption + { + TLString Caption { get; set; } + } + + public interface ITTLMessageMedia + { + TLInt TTLSeconds { get; set; } + + TTLParams TTLParams { get; set; } + } + + public interface IMediaGifBase + { + double DownloadingProgress { get; set; } + + double LastProgress { get; set; } + + bool IsCanceled { get; set; } + + string IsoFileName { get; set; } + + bool? AutoPlayGif { get; set; } + + bool Forbidden { get; set; } + } + + public interface IMediaGif : IMediaGifBase + { + TLDocumentBase Document { get; } + } + + public interface IDecryptedMediaGif : IMediaGifBase + { + TLDecryptedMessageMediaDocument Document { get; } + } + + public interface IMessageMediaGeoPoint + { + TLGeoPointBase Geo { get; } + } + + public abstract class TLMessageMediaBase : TLObject + { + public bool Forbidden { get; set; } + + public virtual bool? AutoPlayGif { get; set; } + + public TLMessageMediaBase Self { get { return this; } } + + public TLMessageMediaBase ThumbSelf { get { return this; } } + + public virtual int MediaSize { get { return 0; } } + + private double _uploadingProgress; + + public double UploadingProgress + { + get { return _uploadingProgress; } + set { SetField(ref _uploadingProgress, value, () => UploadingProgress); } + } + + private double _downloadingProgress; + + public double DownloadingProgress + { + get { return _downloadingProgress; } + set { SetField(ref _downloadingProgress, value, () => DownloadingProgress); } + } + + private double _compressingProgress; + + public double CompressingProgress + { + get { return _compressingProgress; } + set { SetField(ref _compressingProgress, value, () => CompressingProgress); } + } + + public double LastProgress { get; set; } + + private bool _notListened; + + public bool NotListened + { + get { return _notListened; } + set { _notListened = value; } + } + + private bool _out = true; + + public bool Out + { + get { return _out; } + set { _out = value; } + } + + /// + /// For internal use + /// + public TLLong FileId { get; set; } + + public string IsoFileName { get; set; } + +#if WP8 + public StorageFile File { get; set; } +#endif +#if WP81 + public PrepareTranscodeResult TranscodeResult { get; set; } +#endif + + private bool _isCanceled; + + public bool IsCanceled + { + get { return _isCanceled; } + set { _isCanceled = value; } + } + + public virtual double MediaWidth + { + get { return 12.0 + 311.0 + 12.0; } + } + } + + public class TLMessageMediaEmpty : TLMessageMediaBase + { + public const uint Signature = TLConstructors.TLMessageMediaEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLMessageMediaDocument75 : TLMessageMediaDocument70 + { + public new const uint Signature = TLConstructors.TLMessageMediaDocument75; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + _document = GetObject(Flags, (int)MessageMediaDocumentFlags.Document, null, bytes, ref position); + Caption = null; + _ttlSeconds = GetObject(Flags, (int)MessageMediaPhotoFlags.TTLSeconds, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + _document = GetObject(Flags, (int)MessageMediaDocumentFlags.Document, null, input); + Caption = null; + _ttlSeconds = GetObject(Flags, (int)MessageMediaDocumentFlags.TTLSeconds, null, input); + + var isoFileName = GetObject(input); + IsoFileName = isoFileName.ToString(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, Document, Flags, (int)MessageMediaDocumentFlags.Document); + ToStream(output, TTLSeconds, Flags, (int)MessageMediaDocumentFlags.TTLSeconds); + + var isoFileName = new TLString(IsoFileName); + isoFileName.ToStream(output); + } + + public override string ToString() + { + return Document != null ? "TLMessageMediaDocument75 " + Document : "TLMessageMediaDocument70"; + } + } + + public class TLMessageMediaDocument70 : TLMessageMediaDocument45, ITTLMessageMedia + { + public new const uint Signature = TLConstructors.TLMessageMediaDocument70; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + protected TLDocumentBase _document; + + public override TLDocumentBase Document + { + get { return _document; } + set { SetField(out _document, value, ref _flags, (int)MessageMediaDocumentFlags.Document); } + } + + protected TLString _caption; + + public override TLString Caption + { + get { return _caption; } + set { SetField(out _caption, value, ref _flags, (int)MessageMediaDocumentFlags.Caption); } + } + + protected TLInt _ttlSeconds; + + public TLInt TTLSeconds + { + get { return _ttlSeconds; } + set { SetField(out _ttlSeconds, value, ref _flags, (int)MessageMediaDocumentFlags.TTLSeconds); } + } + + public TTLParams TTLParams { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + _document = GetObject(Flags, (int)MessageMediaDocumentFlags.Document, null, bytes, ref position); + Caption = GetObject(Flags, (int)MessageMediaPhotoFlags.Caption, TLString.Empty, bytes, ref position); + _ttlSeconds = GetObject(Flags, (int)MessageMediaPhotoFlags.TTLSeconds, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + _document = GetObject(Flags, (int)MessageMediaDocumentFlags.Document, null, input); + Caption = GetObject(Flags, (int)MessageMediaDocumentFlags.Caption, TLString.Empty, input); + _ttlSeconds = GetObject(Flags, (int)MessageMediaDocumentFlags.TTLSeconds, null, input); + + var isoFileName = GetObject(input); + IsoFileName = isoFileName.ToString(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, Document, Flags, (int)MessageMediaDocumentFlags.Document); + ToStream(output, Caption, Flags, (int)MessageMediaDocumentFlags.Caption); + ToStream(output, TTLSeconds, Flags, (int)MessageMediaDocumentFlags.TTLSeconds); + + var isoFileName = new TLString(IsoFileName); + isoFileName.ToStream(output); + } + + public override string ToString() + { + return Document != null ? "TLMessageMediaDocument70 " + Document : "TLMessageMediaDocument70"; + } + } + + public class TLMessageMediaDocument45 : TLMessageMediaDocument, IMediaCaption + { + public new const uint Signature = TLConstructors.TLMessageMediaDocument45; + + private bool? _autoPlayGif; + + public override bool? AutoPlayGif + { + get + { + if (TLMessageBase.IsRoundVideo(Document)) + { + return true; + } + + return _autoPlayGif; + } + set { _autoPlayGif = value; } + } + + public virtual TLString Caption { get; set; } + + public TLString Waveform + { + get + { + var document = Document as TLDocument22; + if (document != null) + { + var documentAttributeAudio = document.Attributes.FirstOrDefault(x => x is TLDocumentAttributeAudio46) as TLDocumentAttributeAudio46; + if (documentAttributeAudio != null) + { + return documentAttributeAudio.Waveform; + } + } + + return null; + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Document = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Document = GetObject(input); + Caption = GetObject(input); + + var isoFileName = GetObject(input); + IsoFileName = isoFileName.ToString(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Document.ToStream(output); + Caption.ToStream(output); + + var isoFileName = new TLString(IsoFileName); + isoFileName.ToStream(output); + } + } + + public class TLMessageMediaDocument : TLMessageMediaBase, IMediaGif + { + public const uint Signature = TLConstructors.TLMessageMediaDocument; + + public virtual TLDocumentBase Document { get; set; } + + public TLDocumentBase Video { get { return Document; } } + + public override int MediaSize + { + get + { + return Document.DocumentSize; + } + } + + public override double MediaWidth + { + get + { + var document = Document as TLDocument22; + if (document != null) + { + if (TLMessageBase.HasTTL(this)) + { + return 2.0 + 256.0 + 2.0; + } + if (TLMessageBase.IsSticker(document)) + { + var maxStickerDimension = 196.0; + + return 6.0 + GetStickerDimension(document, true, maxStickerDimension) + 6.0; + } + if (TLMessageBase.IsVoice(document)) + { + return 12.0 + 284.0 + 12.0; + } + if (TLMessageBase.IsRoundVideo(document)) + { + return 2.0 + 240.0 + 2.0; + } + if (TLMessageBase.IsVideo(document)) + { + return 2.0 + 230.0 + 2.0; + } + if (TLMessageBase.IsGif(document)) + { + var maxGifDimension = 323.0; + + return 2.0 + GetGifDimension(document.Thumb as IPhotoSize, document, true, maxGifDimension) + 2.0; + } + } + + return base.MediaWidth; + + } + } + + public static double GetGifDimension(IPhotoSize thumb, IAttributes source, bool isWidth, double maxGifDimension) + { + TLDocumentAttributeVideo videoAttribute = null; + if (source != null) + { + for (var i = 0; i < source.Attributes.Count; i++) + { + videoAttribute = source.Attributes[i] as TLDocumentAttributeVideo; + if (videoAttribute != null) + { + break; + } + } + } + + if (videoAttribute != null) + { + var width = videoAttribute.W.Value; + var height = videoAttribute.H.Value; + + var maxDimension = width; + if (maxDimension > 0) + { + var scaleFactor = maxGifDimension / maxDimension; + + return isWidth ? scaleFactor * width : scaleFactor * height; + } + } + + if (thumb != null) + { + var width = thumb.W.Value; + var height = thumb.H.Value; + + var maxDimension = width; + if (maxDimension > 0) + { + var scaleFactor = maxGifDimension / maxDimension; + + return isWidth ? scaleFactor * width : scaleFactor * height; + } + } + + return maxGifDimension; + } + + public static double GetStickerDimension(IAttributes source, bool isWidth, double maxImageDimension) + { + TLDocumentAttributeImageSize imageSizeAttribute = null; + for (var i = 0; i < source.Attributes.Count; i++) + { + imageSizeAttribute = source.Attributes[i] as TLDocumentAttributeImageSize; + if (imageSizeAttribute != null) + { + break; + } + } + + if (imageSizeAttribute != null) + { + var width = imageSizeAttribute.W.Value; + var height = imageSizeAttribute.H.Value; + + var maxDimension = Math.Max(width, height); + if (maxDimension > maxImageDimension) + { + var scaleFactor = maxImageDimension / maxDimension; + + return isWidth ? scaleFactor * width : scaleFactor * height; + } + + return isWidth ? width : height; + } + + return isWidth ? double.NaN : maxImageDimension; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Document = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Document = GetObject(input); + + var isoFileName = GetObject(input); + IsoFileName = isoFileName.ToString(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Document.ToStream(output); + + var isoFileName = new TLString(IsoFileName); + isoFileName.ToStream(output); + } + } + + public class TLMessageMediaAudio : TLMessageMediaBase + { + public const uint Signature = TLConstructors.TLMessageMediaAudio; + + public TLAudioBase Audio { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Audio = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Audio = GetObject(input); + + var isoFileName = GetObject(input); + IsoFileName = isoFileName.ToString(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Audio.ToStream(output); + + var isoFileName = new TLString(IsoFileName); + isoFileName.ToStream(output); + } + } + + public class TLMessageMediaPhoto75 : TLMessageMediaPhoto70 + { + public new const uint Signature = TLConstructors.TLMessageMediaPhoto75; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + _photo = GetObject(Flags, (int)MessageMediaPhotoFlags.Photo, null, bytes, ref position); + Caption = null; + _ttlSeconds = GetObject(Flags, (int)MessageMediaPhotoFlags.TTLSeconds, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + _photo = GetObject(Flags, (int)MessageMediaPhotoFlags.Photo, null, input); + Caption = null; + _ttlSeconds = GetObject(Flags, (int)MessageMediaPhotoFlags.TTLSeconds, null, input); + + var isoFileName = GetObject(input); + IsoFileName = isoFileName.ToString(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, Photo, Flags, (int)MessageMediaPhotoFlags.Photo); + ToStream(output, TTLSeconds, Flags, (int)MessageMediaPhotoFlags.TTLSeconds); + + var isoFileName = new TLString(IsoFileName); + isoFileName.ToStream(output); + } + + public override string ToString() + { + return Photo != null ? "TLMessageMediaPhoto75 " + Photo : "TLMessageMediaPhoto75"; + } + } + + public class TLMessageMediaPhoto70 : TLMessageMediaPhoto28, ITTLMessageMedia + { + public new const uint Signature = TLConstructors.TLMessageMediaPhoto70; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + protected TLPhotoBase _photo; + + public override TLPhotoBase Photo + { + get { return _photo; } + set { SetField(out _photo, value, ref _flags, (int)MessageMediaPhotoFlags.Photo); } + } + + protected TLString _caption; + + public override TLString Caption + { + get { return _caption; } + set { SetField(out _caption, value, ref _flags, (int)MessageMediaPhotoFlags.Caption); } + } + + protected TLInt _ttlSeconds; + + public TLInt TTLSeconds + { + get { return _ttlSeconds; } + set { SetField(out _ttlSeconds, value, ref _flags, (int)MessageMediaPhotoFlags.TTLSeconds); } + } + + public TTLParams TTLParams { get; set; } + + public override double MediaWidth + { + get + { + if (TLMessageBase.HasTTL(this) && Photo != null) + { + return 2.0 + 256.0 + 2.0; + } + + return base.MediaWidth; + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + _photo = GetObject(Flags, (int)MessageMediaPhotoFlags.Photo, null, bytes, ref position); + Caption = GetObject(Flags, (int)MessageMediaPhotoFlags.Caption, TLString.Empty, bytes, ref position); + _ttlSeconds = GetObject(Flags, (int)MessageMediaPhotoFlags.TTLSeconds, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + _photo = GetObject(Flags, (int)MessageMediaPhotoFlags.Photo, null, input); + Caption = GetObject(Flags, (int)MessageMediaPhotoFlags.Caption, TLString.Empty, input); + _ttlSeconds = GetObject(Flags, (int)MessageMediaPhotoFlags.TTLSeconds, null, input); + + var isoFileName = GetObject(input); + IsoFileName = isoFileName.ToString(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, Photo, Flags, (int)MessageMediaPhotoFlags.Photo); + ToStream(output, Caption, Flags, (int)MessageMediaPhotoFlags.Caption); + ToStream(output, TTLSeconds, Flags, (int)MessageMediaPhotoFlags.TTLSeconds); + + var isoFileName = new TLString(IsoFileName); + isoFileName.ToStream(output); + } + + public override string ToString() + { + return Photo != null ? "TLMessageMediaPhoto70" + Photo : "TLMessageMediaPhoto70"; + } + } + + public class TLMessageMediaPhoto28 : TLMessageMediaPhoto, IMediaCaption + { + public new const uint Signature = TLConstructors.TLMessageMediaPhoto28; + + public virtual TLString Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Photo = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Photo = GetObject(input); + Caption = GetObject(input); + + var isoFileName = GetObject(input); + IsoFileName = isoFileName.ToString(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Photo.ToStream(output); + Caption.ToStream(output); + + var isoFileName = new TLString(IsoFileName); + isoFileName.ToStream(output); + } + + public override string ToString() + { + return Photo.ToString(); + } + } + + public class TLMessageMediaPhoto : TLMessageMediaBase + { + public const uint Signature = TLConstructors.TLMessageMediaPhoto; + + public virtual TLPhotoBase Photo { get; set; } + + public override double MediaWidth + { + get + { + var minVerticalRatioToScale = 1.2; + var scale = 1.2; // must be less than minVerticalRatioToScale to avoid large square photos + var maxDimension = 323.0; + + var photo = Photo as TLPhoto; + if (photo != null) + { + IPhotoSize size = null; + var sizes = photo.Sizes.OfType(); + foreach (var photoSize in sizes) + { + if (size == null + || Math.Abs(maxDimension - size.H.Value) > Math.Abs(maxDimension - photoSize.H.Value)) + { + size = photoSize; + } + } + + if (size != null) + { + if (size.H.Value > size.W.Value) + { + if (IsScaledVerticalPhoto(minVerticalRatioToScale, size.H, size.W)) + { + return 2.0 + scale * maxDimension / size.H.Value * size.W.Value + 2.0; + } + + return 2.0 + maxDimension / size.H.Value * size.W.Value + 2.0; + } + + return 2.0 + maxDimension + 2.0; + } + } + + return base.MediaWidth; + } + } + + public static bool IsScaledVerticalPhoto(double minRatio, TLInt heigth, TLInt width) + { + var ratio = (double)heigth.Value / width.Value; + + return ratio > minRatio; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Photo = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Photo = GetObject(input); + + var isoFileName = GetObject(input); + IsoFileName = isoFileName.ToString(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Photo.ToStream(output); + + var isoFileName = new TLString(IsoFileName); + isoFileName.ToStream(output); + } + + public override string ToString() + { + return Photo.ToString(); + } + } + + public class TLMessageMediaVideo28 : TLMessageMediaVideo, IMediaCaption + { + public new const uint Signature = TLConstructors.TLMessageMediaVideo28; + + public TLString Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Video = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Video = GetObject(input); + Caption = GetObject(input); + + var isoFileName = GetObject(input); + IsoFileName = isoFileName.ToString(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Video.ToStream(output); + Caption.ToStream(output); + + var isoFileName = new TLString(IsoFileName); + isoFileName.ToStream(output); + } + } + + public class TLMessageMediaVideo : TLMessageMediaBase + { + public const uint Signature = TLConstructors.TLMessageMediaVideo; + + public TLVideoBase Video { get; set; } + + public override int MediaSize + { + get + { + return Video.VideoSize; + } + } + + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Video = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Video = GetObject(input); + + var isoFileName = GetObject(input); + IsoFileName = isoFileName.ToString(); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Video.ToStream(output); + + var isoFileName = new TLString(IsoFileName); + isoFileName.ToStream(output); + } + } + + public class TLMessageMediaGeo : TLMessageMediaBase, IMessageMediaGeoPoint + { + public const uint Signature = TLConstructors.TLMessageMediaGeo; + + public TLGeoPointBase Geo { get; set; } + + public override double MediaWidth + { + get { return 2.0 + 320.0 + 2.0; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Geo = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Geo = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Geo.ToStream(output); + } + } + + public class TLMessageMediaVenue72 : TLMessageMediaVenue + { + public new const uint Signature = TLConstructors.TLMessageMediaVenue72; + + public TLString VenueType { get; set; } + + #region Additional + + public Uri IconSource { get; set; } + + public TLUserBase User { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Geo = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + Address = GetObject(bytes, ref position); + Provider = GetObject(bytes, ref position); + VenueId = GetObject(bytes, ref position); + VenueType = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Geo = GetObject(input); + Title = GetObject(input); + Address = GetObject(input); + Provider = GetObject(input); + VenueId = GetObject(input); + VenueType = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Geo.ToStream(output); + Title.ToStream(output); + Address.ToStream(output); + Provider.ToStream(output); + VenueId.ToStream(output); + VenueType.ToStream(output); + } + } + + public class TLMessageMediaVenue : TLMessageMediaGeo + { + public new const uint Signature = TLConstructors.TLMessageMediaVenue; + + public TLString Title { get; set; } + + public TLString Address { get; set; } + + public TLString Provider { get; set; } + + public TLString VenueId { get; set; } + + public override double MediaWidth + { + get { return 2.0 + 320.0 + 2.0; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Geo = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + Address = GetObject(bytes, ref position); + Provider = GetObject(bytes, ref position); + VenueId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Geo = GetObject(input); + Title = GetObject(input); + Address = GetObject(input); + Provider = GetObject(input); + VenueId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Geo.ToStream(output); + Title.ToStream(output); + Address.ToStream(output); + Provider.ToStream(output); + VenueId.ToStream(output); + } + } + + public class TLMessageMediaContact82 : TLMessageMediaContact + { + public new const uint Signature = TLConstructors.TLMessageMediaContact82; + + public TLString VCard { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhoneNumber = GetObject(bytes, ref position); + FirstName = GetObject(bytes, ref position); + LastName = GetObject(bytes, ref position); + VCard = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PhoneNumber = GetObject(input); + FirstName = GetObject(input); + LastName = GetObject(input); + VCard = GetObject(input); + UserId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PhoneNumber.ToStream(output); + FirstName.ToStream(output); + LastName.ToStream(output); + VCard.ToStream(output); + UserId.ToStream(output); + } + } + + public class TLMessageMediaContact : TLMessageMediaBase + { + public const uint Signature = TLConstructors.TLMessageMediaContact; + + public TLString PhoneNumber { get; set; } + + public TLString FirstName { get; set; } + + public TLString LastName { get; set; } + + public TLInt UserId { get; set; } + + public override double MediaWidth + { + get { return 12.0 + 311.0 + 12.0; } + } + + #region Additional + + public virtual string FullName { get { return string.Format("{0} {1}", FirstName, LastName); } } + + private TLUserBase _user; + + public TLUserBase User + { + get + { + if (_user != null) return _user; + + var cacheService = InMemoryCacheService.Instance; + _user = cacheService.GetUser(UserId); + if (_user == null) + { + if (UserId.Value > 0) + { + _user = new TLUser + { + FirstName = FirstName, + LastName = LastName, + Id = UserId, + Phone = PhoneNumber, + Photo = new TLPhotoEmpty { Id = new TLLong(0) } + }; + } + else + { + _user = new TLUserNotRegistered + { + FirstName = FirstName, + LastName = LastName, + Id = UserId, + Phone = PhoneNumber, + Photo = new TLPhotoEmpty { Id = new TLLong(0) } + }; + } + } + + return _user; + } + } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhoneNumber = GetObject(bytes, ref position); + FirstName = GetObject(bytes, ref position); + LastName = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PhoneNumber = GetObject(input); + FirstName = GetObject(input); + LastName = GetObject(input); + UserId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PhoneNumber.ToStream(output); + FirstName.ToStream(output); + LastName.ToStream(output); + UserId.ToStream(output); + } + + public override string ToString() + { + return FullName; + } + } + + public abstract class TLMessageMediaUnsupportedBase : TLMessageMediaBase { } + + public class TLMessageMediaUnsupported : TLMessageMediaUnsupportedBase + { + public const uint Signature = TLConstructors.TLMessageMediaUnsupported; + + public TLString Bytes { get; set; } + + public override double MediaWidth + { + get { return 12.0 + 311.0 + 12.0; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Bytes = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Bytes = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Bytes.ToStream(output); + } + } + + public class TLMessageMediaUnsupported24 : TLMessageMediaUnsupportedBase + { + public const uint Signature = TLConstructors.TLMessageMediaUnsupported24; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLMessageMediaWebPage : TLMessageMediaBase, IMediaGif + { + public const uint Signature = TLConstructors.TLMessageMediaWebPage; + + public TLWebPageBase WebPage { get; set; } + + #region Additional + + public TLDocumentBase Document + { + get + { + var webPage = WebPage as TLWebPage35; + if (webPage != null) + { + return webPage.Document; + } + + return null; + } + } + + public TLPhotoBase Photo + { + get + { + var webPage = WebPage as TLWebPage; + if (webPage != null) + { + return webPage.Photo; + } + + return null; + } + } + + #endregion + + public override double MediaWidth + { + get { return 12.0 + 311.0 + 12.0; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + WebPage = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + WebPage = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + WebPage.ToStream(output); + } + } + + public class TLMessageMediaGame : TLMessageMediaBase, IMediaGif + { + public const uint Signature = TLConstructors.TLMessageMediaGame; + + public TLGame Game { get; set; } + + #region Additional + public TLDocumentBase Document + { + get + { + if (Game != null) + { + return Game.Document; + } + + return null; + } + } + + public TLPhotoBase Photo + { + get + { + if (Game != null) + { + return Game.Photo; + } + + return null; + } + } + #endregion + + public override double MediaWidth + { + get { return 12.0 + 311.0 + 12.0; } + } + + public Visibility MessageVisibility + { + get + { + return !TLString.IsNullOrEmpty(Message) + ? Visibility.Visible + : Visibility.Collapsed; + } + } + + public Visibility DescriptionVisibility + { + get + { + return TLString.IsNullOrEmpty(Message) && Game != null && !TLString.IsNullOrEmpty(Game.Description) + ? Visibility.Visible + : Visibility.Collapsed; + } + } + + public TLString Message { get; set; } + + public TLMessageBase SourceMessage { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Game = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Game = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Game.ToStream(output); + } + } + + public class TLMessageMediaInvoice : TLMessageMediaBase + { + public const uint Signature = TLConstructors.TLMessageMediaInvoice; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool ShippingAddressRequested + { + get { return IsSet(Flags, (int)MessageMediaInvoiceFlags.ShippingAddressRequested); } + set { SetUnset(ref _flags, value, (int)MessageMediaInvoiceFlags.ShippingAddressRequested); } + } + + public bool Test + { + get { return IsSet(Flags, (int)MessageMediaInvoiceFlags.Test); } + set { SetUnset(ref _flags, value, (int)MessageMediaInvoiceFlags.Test); } + } + + public TLString Title { get; set; } + + public TLString Description { get; set; } + + private TLWebDocumentBase _photo; + + public TLWebDocumentBase Photo + { + get { return _photo; } + set { SetField(out _photo, value, ref _flags, (int)MessageMediaInvoiceFlags.Photo); } + } + + private TLInt _receiptMsgId; + + public TLInt ReceiptMsgId + { + get { return _receiptMsgId; } + set { SetField(out _receiptMsgId, value, ref _flags, (int)MessageMediaInvoiceFlags.ReceiptMsgId); } + } + + public TLString Currency { get; set; } + + public TLLong TotalAmount { get; set; } + + public TLString StartParam { get; set; } + + public Visibility DescriptionVisibility + { + get + { + return !TLString.IsNullOrEmpty(Description) + ? Visibility.Visible + : Visibility.Collapsed; + } + } + + public override double MediaWidth + { + get { return 2.0 + 323.0 + 2.0; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + Description = GetObject(bytes, ref position); + _photo = GetObject(Flags, (int)MessageMediaInvoiceFlags.Photo, null, bytes, ref position); + _receiptMsgId = GetObject(Flags, (int)MessageMediaInvoiceFlags.ReceiptMsgId, null, bytes, ref position); + Currency = GetObject(bytes, ref position); + TotalAmount = GetObject(bytes, ref position); + StartParam = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Title = GetObject(input); + Description = GetObject(input); + _photo = GetObject(Flags, (int)MessageMediaInvoiceFlags.Photo, null, input); + _receiptMsgId = GetObject(Flags, (int)MessageMediaInvoiceFlags.ReceiptMsgId, null, input); + Currency = GetObject(input); + TotalAmount = GetObject(input); + StartParam = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Title.ToStream(output); + Description.ToStream(output); + ToStream(output, Photo, Flags, (int)MessageMediaInvoiceFlags.Photo); + ToStream(output, ReceiptMsgId, Flags, (int)MessageMediaInvoiceFlags.ReceiptMsgId); + Currency.ToStream(output); + TotalAmount.ToStream(output); + StartParam.ToStream(output); + } + } + + public class TLMessageMediaGeoLive : TLMessageMediaGeo + { + public new const uint Signature = TLConstructors.TLMessageMediaGeoLive; + + public TLInt Period { get; set; } + + #region Additional + + public TLObject From { get; set; } + + public TLInt EditDate { get; set; } + + public TLInt Date { get; set; } + + public bool Active + { + get + { + if (Date != null) + { + if (Period.Value == 0) + { + return false; + } + + var mtProtoService = MTProtoService.Instance; + var clientDelta = mtProtoService.ClientTicksDelta; + + var now = TLUtils.DateToUniversalTimeTLInt(clientDelta, DateTime.Now); + + var expired = Date.Value + Period.Value <= now.Value; + + var defaultPeriod = Period.Value == 15 * 60 || Period.Value == 60 * 60 || Period.Value == 8 * 60 * 60; + + return defaultPeriod && !expired; + + //var mtProtoService = MTProtoService.Instance; + //var clientDelta = mtProtoService.ClientTicksDelta; + + //if (clientDelta == 0) + //{ + // var defaultPeriod = Period.Value == 15 * 60 || Period.Value == 60 * 60 || Period.Value == 8 * 60 * 60; + + // if (!defaultPeriod) + // { + // return false; + // } + //} + + //var date = TLUtils.DateToUniversalTimeTLInt(clientDelta, DateTime.Now); + + //return Date.Value + Period.Value > date.Value; + } + + return false; + } + } + + #endregion + + public override double MediaWidth + { + get { return 2.0 + 320.0 + 2.0; } + } + + public TLMessageMediaBase ToMediaGeo() + { + return new TLMessageMediaGeo + { + Geo = Geo + }; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Geo = GetObject(bytes, ref position); + Period = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Geo = GetObject(input); + Period = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Geo.ToStream(output); + Period.ToStream(output); + } + } + + public interface IMessageMediaGroup + { + TLVector GroupCommon { get; } + event EventHandler Calculate; + } + + public class TLMessageMediaGroup : TLMessageMediaBase, IMessageMediaGroup + { + public const uint Signature = TLConstructors.TLMessageMediaGroup; + + public TLVector Group { get; set; } + + public TLVector GroupCommon + { + get + { + if (Group == null) + { + return new TLVector(); + } + + var group = new TLVector(); + foreach (var item in Group) + { + group.Add(item); + } + return group; + } + } + + public override double MediaWidth + { + get { return 1.0 + 311.0 + 1.0; } + } + + public event EventHandler Calculate; + + public virtual void RaiseCalculate() + { + var handler = Calculate; + if (handler != null) handler(this, EventArgs.Empty); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Group = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Group = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Group.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLMessageRange.cs b/Telegram.Api/TL/TLMessageRange.cs new file mode 100755 index 0000000..fed0c8b --- /dev/null +++ b/Telegram.Api/TL/TLMessageRange.cs @@ -0,0 +1,56 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLMessageRange : TLObject + { + public const uint Signature = TLConstructors.TLMessageRange; + + public TLInt MinId { get; set; } + + public TLInt MaxId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + MinId.ToBytes(), + MaxId.ToBytes() + ); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + MinId = GetObject(bytes, ref position); + MaxId = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + MinId.ToStream(output); + MaxId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + MinId = GetObject(input); + MaxId = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLMessages.cs b/Telegram.Api/TL/TLMessages.cs new file mode 100755 index 0000000..6759778 --- /dev/null +++ b/Telegram.Api/TL/TLMessages.cs @@ -0,0 +1,259 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum MessagesFlags + { + Collapsed = 0x1 + } + + [Flags] + public enum FeedMessagesFlags + { + MaxPosition = 0x1, + MinPosition = 0x2, + ReadMaxPosition = 0x4, + } + + public abstract class TLMessagesBase : TLObject + { + public TLVector Messages { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public abstract TLMessagesBase GetEmptyObject(); + } + + public class TLMessages : TLMessagesBase + { + public const uint Signature = TLConstructors.TLMessages; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLMessagesBase GetEmptyObject() + { + return new TLMessages + { + Messages = new TLVector(Messages.Count), + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count) + }; + } + } + + public class TLMessagesSlice : TLMessages + { + public new const uint Signature = TLConstructors.TLMessagesSlice; + + public TLInt Count { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Count = GetObject(bytes, ref position); + + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLMessagesBase GetEmptyObject() + { + return new TLMessagesSlice + { + Count = Count, + Messages = new TLVector(Messages.Count), + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count) + }; + } + } + + public class TLChannelMessages : TLMessagesSlice + { + public new const uint Signature = TLConstructors.TLChannelMessages; + + public TLInt Flags { get; set; } + + public TLInt Pts { get; set; } + + public TLVector Collapsed { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + Count = GetObject(bytes, ref position); + + Messages = GetObject>(bytes, ref position); + if (IsSet(Flags, (int) MessagesFlags.Collapsed)) + { + Collapsed = GetObject>(bytes, ref position); + } + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLMessagesBase GetEmptyObject() + { + return new TLMessagesSlice + { + Count = Count, + Messages = new TLVector(Messages.Count), + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count) + }; + } + } + + public class TLChannelMessages53 : TLChannelMessages + { + public new const uint Signature = TLConstructors.TLChannelMessages53; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + Count = GetObject(bytes, ref position); + + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLMessagesBase GetEmptyObject() + { + return new TLMessagesSlice + { + Count = Count, + Messages = new TLVector(Messages.Count), + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count) + }; + } + } + + public class TLFeedMessagesNotModified : TLMessagesBase + { + public const uint Signature = TLConstructors.TLFeedMessagesNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = new TLVector(); + Chats = new TLVector(); + Users = new TLVector(); + + return this; + } + + public override TLMessagesBase GetEmptyObject() + { + return new TLFeedMessages + { + Messages = new TLVector(Messages.Count), + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count) + }; + } + } + + public class TLFeedMessages : TLMessagesBase + { + public const uint Signature = TLConstructors.TLFeedMessages; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + protected TLFeedPosition _maxPosition; + + public TLFeedPosition MaxPosition + { + get { return _maxPosition; } + set { SetField(out _maxPosition, value, ref _flags, (int) FeedMessagesFlags.MaxPosition); } + } + + protected TLFeedPosition _minPosition; + + public TLFeedPosition MinPosition + { + get { return _minPosition; } + set { SetField(out _minPosition, value, ref _flags, (int)FeedMessagesFlags.MinPosition); } + } + + protected TLFeedPosition _readMaxPosition; + + public TLFeedPosition ReadMaxPosition + { + get { return _readMaxPosition; } + set { SetField(out _readMaxPosition, value, ref _flags, (int)FeedMessagesFlags.ReadMaxPosition); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + _flags = GetObject(bytes, ref position); + _maxPosition = GetObject(Flags, (int)FeedMessagesFlags.MaxPosition, null, bytes, ref position); + _minPosition = GetObject(Flags, (int)FeedMessagesFlags.MinPosition, null, bytes, ref position); + _readMaxPosition = GetObject(Flags, (int)FeedMessagesFlags.ReadMaxPosition, null, bytes, ref position); + + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLMessagesBase GetEmptyObject() + { + return new TLFeedMessages + { + Flags = Flags, + MaxPosition = MaxPosition, + MinPosition = MinPosition, + ReadMaxPosition = ReadMaxPosition, + + Messages = new TLVector(Messages.Count), + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count) + }; + } + } +} diff --git a/Telegram.Api/TL/TLMessagesAcknowledgment.cs b/Telegram.Api/TL/TLMessagesAcknowledgment.cs new file mode 100755 index 0000000..3d953ed --- /dev/null +++ b/Telegram.Api/TL/TLMessagesAcknowledgment.cs @@ -0,0 +1,25 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLMessagesAcknowledgment : TLObject + { + public const uint Signature = TLConstructors.TLMessagesAcknowledgment; + + public TLVector MessageIds { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + MessageIds = GetObject>(bytes, ref position); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLMessagesChannelParticipants.cs b/Telegram.Api/TL/TLMessagesChannelParticipants.cs new file mode 100755 index 0000000..9b4d9ed --- /dev/null +++ b/Telegram.Api/TL/TLMessagesChannelParticipants.cs @@ -0,0 +1,109 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLChannelParticipantsBase : TLObject { } + + public class TLChannelParticipants : TLChannelParticipantsBase + { + public const uint Signature = TLConstructors.TLChannelParticipants; + + public TLInt Count { get; set; } + + public TLVector Participants { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Count = GetObject(bytes, ref position); + Participants = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Count = GetObject(input); + Participants = GetObject>(input); + Users = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Count.ToStream(output); + Participants.ToStream(output); + Users.ToStream(output); + } + } + + public class TLChannelParticipantsNotModified : TLChatParticipantsBase + { + public const uint Signature = TLConstructors.TLChannelParticipantsNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLChannelsChannelParticipant : TLObject + { + public const uint Signature = TLConstructors.TLChannelsChannelParticipant; + + public TLChannelParticipantBase Participant { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Participant = GetObject(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Participant = GetObject(input); + Users = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Participant.ToStream(output); + Users.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLMessagesChatFull.cs b/Telegram.Api/TL/TLMessagesChatFull.cs new file mode 100755 index 0000000..fe34347 --- /dev/null +++ b/Telegram.Api/TL/TLMessagesChatFull.cs @@ -0,0 +1,31 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLMessagesChatFull : TLObject + { + public const uint Signature = TLConstructors.TLMessagesChatFull; + + public TLChatFull FullChat { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + FullChat = GetObject(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLMessagesStickerSet.cs b/Telegram.Api/TL/TLMessagesStickerSet.cs new file mode 100755 index 0000000..29074a4 --- /dev/null +++ b/Telegram.Api/TL/TLMessagesStickerSet.cs @@ -0,0 +1,58 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLMessagesStickerSet : TLObject + { + public const uint Signature = TLConstructors.TLMessagesStickerSet; + + public TLStickerSetBase Set { get; set; } + public TLVector Packs { get; set; } + public TLVector Documents { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Set = GetObject(bytes, ref position); + Packs = GetObject>(bytes, ref position); + Documents = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Set.ToBytes(), + Packs.ToBytes(), + Documents.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Set = GetObject(input); + Packs = GetObject>(input); + Documents = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Set.ToStream(output); + Packs.ToStream(output); + Documents.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLMyLink.cs b/Telegram.Api/TL/TLMyLink.cs new file mode 100755 index 0000000..5fb2818 --- /dev/null +++ b/Telegram.Api/TL/TLMyLink.cs @@ -0,0 +1,86 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLMyLinkBase : TLObject { } + + public class TLMyLinkEmpty : TLMyLinkBase + { + public const uint Signature = TLConstructors.TLMyLinkEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLMyLinkRequested : TLMyLinkBase + { + public const uint Signature = TLConstructors.TLMyLinkRequested; + + public TLBool Contact { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Contact = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Contact = GetObject(input); + + return this; + } + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Contact.ToStream(output); + } + } + + public class TLMyLinkContact : TLMyLinkBase + { + public const uint Signature = TLConstructors.TLMyLinkContact; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLNearestDC.cs b/Telegram.Api/TL/TLNearestDC.cs new file mode 100755 index 0000000..01e3514 --- /dev/null +++ b/Telegram.Api/TL/TLNearestDC.cs @@ -0,0 +1,31 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLNearestDC : TLObject + { + public const uint Signature = TLConstructors.TLNearestDC; + + public TLString Country { get; set; } + + public TLInt ThisDC { get; set; } + + public TLInt NearestDC { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Country = GetObject(bytes,ref position); + ThisDC = GetObject(bytes, ref position); + NearestDC = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLNewSessionCreated.cs b/Telegram.Api/TL/TLNewSessionCreated.cs new file mode 100755 index 0000000..e0973aa --- /dev/null +++ b/Telegram.Api/TL/TLNewSessionCreated.cs @@ -0,0 +1,31 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + internal class TLNewSessionCreated : TLObject + { + public const uint Signature = TLConstructors.TLNewSessionCreated; + + public TLLong FirstMessageId { get; set; } + + public TLLong UniqueId { get; set; } + + public TLLong ServerSalt { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + FirstMessageId = GetObject(bytes, ref position); + UniqueId = GetObject(bytes, ref position); + ServerSalt = GetObject(bytes, ref position); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLNonEncryptedMessage.cs b/Telegram.Api/TL/TLNonEncryptedMessage.cs new file mode 100755 index 0000000..a57dd04 --- /dev/null +++ b/Telegram.Api/TL/TLNonEncryptedMessage.cs @@ -0,0 +1,37 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLNonEncryptedMessage : TLTransportMessageWithIdBase + { + public TLLong AuthKeyId { get; set; } + public TLObject Data { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + AuthKeyId = GetObject(bytes, ref position); + MessageId = GetObject(bytes, ref position); + var length = GetObject(bytes, ref position); + Data = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + var dataBytes = Data.ToBytes(); + var length = new TLInt(dataBytes.Length); + + return TLUtils.Combine( + AuthKeyId.ToBytes(), + MessageId.ToBytes(), + length.ToBytes(), + dataBytes); + } + } +} diff --git a/Telegram.Api/TL/TLNotifyPeer.cs b/Telegram.Api/TL/TLNotifyPeer.cs new file mode 100755 index 0000000..5cc3c0d --- /dev/null +++ b/Telegram.Api/TL/TLNotifyPeer.cs @@ -0,0 +1,111 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLNotifyPeerBase : TLObject { } + + public class TLNotifyPeer : TLNotifyPeerBase + { + public TLPeerBase Peer { get; set; } + + public const uint Signature = TLConstructors.TLNotifyPeer; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Peer.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + + return this; + } + } + + public class TLNotifyUsers : TLNotifyPeerBase + { + public const uint Signature = TLConstructors.TLNotifyUsers; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLNotifyChats : TLNotifyPeerBase + { + public const uint Signature = TLConstructors.TLNotifyChats; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + [Obsolete] + public class TLNotifyAll : TLNotifyPeerBase + { + public const uint Signature = TLConstructors.TLNotifyAll; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } +} diff --git a/Telegram.Api/TL/TLNull.cs b/Telegram.Api/TL/TLNull.cs new file mode 100755 index 0000000..05f68b4 --- /dev/null +++ b/Telegram.Api/TL/TLNull.cs @@ -0,0 +1,39 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLNull : TLObject + { + public const uint Signature = TLConstructors.TLNull; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLObject.cs b/Telegram.Api/TL/TLObject.cs new file mode 100755 index 0000000..eba7c48 --- /dev/null +++ b/Telegram.Api/TL/TLObject.cs @@ -0,0 +1,327 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Linq.Expressions; +using System.Reflection; +using System.Runtime.Serialization; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache.EventArgs; +#if WINDOWS_PHONE +using System.Windows.Media.Imaging; +#elif WIN_RT +using Windows.UI.Xaml.Media.Imaging; +#endif +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; + +namespace Telegram.Api.TL +{ + [DataContract] + public abstract class TLObject : TelegramPropertyChangedBase + { + public TLDialogBase Dialog { get; set; } + + public bool IsGlobalResult { get; set; } + + #region Flags + + public static byte[] ToBytes(TLObject obj, TLInt flags, int flag) + { + return obj != null && IsSet(flags, flag) ? obj.ToBytes() : new byte[] {}; + } + + public static void ToStream(Stream output, TLObject obj, TLInt flags, int flag) + { + if (IsSet(flags, flag)) + { + obj.ToStream(output); + } + } + + public static void ToStream(Stream output, TLObject obj, TLLong customFlags, int flag) + { + if (IsSet(customFlags, flag)) + { + if (obj == null) + { + + } + + obj.ToStream(output); + } + } + + protected static bool IsSet(TLLong flags, int flag) + { + var isSet = false; + + if (flags != null) + { + var intFlag = flag; + isSet = (flags.Value & intFlag) == intFlag; + } + + return isSet; + } + + protected static bool IsSet(TLInt flags, int flag) + { + var isSet = false; + + if (flags != null) + { + var intFlag = flag; + isSet = (flags.Value & intFlag) == intFlag; + } + + return isSet; + } + + protected static void Set(ref TLLong flags, int flag) + { + var intFlag = flag; + + if (flags != null) + { + flags.Value |= intFlag; + } + else + { + flags = new TLLong(intFlag); + } + } + + protected static void Set(ref TLInt flags, int flag) + { + var intFlag = flag; + + if (flags != null) + { + flags.Value |= intFlag; + } + else + { + flags = new TLInt(intFlag); + } + } + + protected static void Unset(ref TLInt flags, int flag) + { + var intFlag = flag; + + if (flags != null) + { + flags.Value &= ~intFlag; + } + else + { + flags = new TLInt(0); + } + } + + protected static void Unset(ref TLLong flags, int flag) + { + var intFlag = flag; + + if (flags != null) + { + flags.Value &= ~intFlag; + } + else + { + flags = new TLLong(0); + } + } + + protected static void SetUnset(ref TLInt flags, bool set, int flag) + { + if (set) + { + Set(ref flags, flag); + } + else + { + Unset(ref flags, flag); + } + } + + protected static void SetUnset(ref TLLong flags, bool set, int flag) + { + if (set) + { + Set(ref flags, flag); + } + else + { + Unset(ref flags, flag); + } + } + + + protected static void SetField(out T field, T value, ref TLInt flags, int flag) where T : TLObject + { + if (value != null) + { + Set(ref flags, flag); + field = value; + } + else + { + Unset(ref flags, flag); + field = null; + } + } + + protected static void SetField(out T field, T value, ref TLLong flags, int flag) where T : TLObject + { + if (value != null) + { + Set(ref flags, flag); + field = value; + } + else + { + Unset(ref flags, flag); + field = null; + } + } + #endregion + + public virtual TLObject FromBytes(byte[] bytes, ref int position) + { + throw new NotImplementedException(); + } + + public virtual byte[] ToBytes() + { + throw new NotImplementedException(); + } + + public virtual TLObject FromStream(Stream input) + { + throw new NotImplementedException(); + } + + public virtual void ToStream(Stream output) + { + throw new NotImplementedException(); + } + + public static T GetObject(byte[] bytes, ref int position) where T : TLObject + { + try + { + return (T)TLObjectGenerator.GetObject(bytes, position).FromBytes(bytes, ref position); + } + catch (Exception e) + { + Execute.ShowDebugMessage(e.ToString()); + TLUtils.WriteLine(e.StackTrace, LogSeverity.Error); + } + + return null; + } + + public static T GetObject(Stream input) where T : TLObject + { + //try + //{ + return (T)TLObjectGenerator.GetObject(input).FromStream(input); + //} + //catch (Exception e) + //{ + // TLUtils.WriteLine(e.StackTrace, LogSeverity.Error); + //} + + //return null; + } + + public static T GetObject(TLInt flags, int flag, T defaultValue, byte[] bytes, ref int position) where T : TLObject + { + var value = IsSet(flags, flag) ? GetObject(bytes, ref position) : defaultValue; + //if (value != null) + //{ + // Set(ref flags, flag); + //} + return value; + } + + public static T GetObject(TLInt flags, int flag, T defaultValue, Stream inputStream) where T : TLObject + { + var value = IsSet(flags, flag) ? GetObject(inputStream) : defaultValue; + //if (value != null) + //{ + // Set(ref flags, flag); + //} + return value; + } + + public static T GetObject(TLLong customFlags, int flag, T defaultValue, Stream inputStream) where T : TLObject + { + var value = IsSet(customFlags, flag) ? GetObject(inputStream) : defaultValue; + //if (value != null) + //{ + // Set(ref customFlags, flag); + //} + return value; + } + + public static T GetNullableObject(Stream input) where T : TLObject + { + return TLObjectExtensions.NullableFromStream(input); + } + + protected bool SetField(ref T field, T value, string propertyName) + { + if (EqualityComparer.Default.Equals(field, value)) return false; + field = value; + NotifyOfPropertyChange(propertyName); + return true; + } + + protected bool SetField(ref T field, T value, Expression> selectorExpression) + { + if (EqualityComparer.Default.Equals(field, value)) return false; + field = value; + NotifyOfPropertyChange(selectorExpression); + return true; + } + + private WriteableBitmap _bitmap; + + public WriteableBitmap Bitmap + { + get { return _bitmap; } + set + { + SetField(ref _bitmap, value, () => Bitmap); + } + } + + public void SetBitmap(WriteableBitmap bitmap) + { + //if (_bitmap == null) + //{ + Bitmap = bitmap; + //} + //else + //{ + // _bitmap = bitmap; + //} + } + + public void ClearBitmap() + { + _bitmap = null; + } + } +} diff --git a/Telegram.Api/TL/TLObjectGenerator.cs b/Telegram.Api/TL/TLObjectGenerator.cs new file mode 100755 index 0000000..07300a8 --- /dev/null +++ b/Telegram.Api/TL/TLObjectGenerator.cs @@ -0,0 +1,1751 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using Telegram.Api.Helpers; +using Telegram.Api.Services; +using Telegram.Api.TL.Account; +using Telegram.Api.TL.Functions.Channels; +using Telegram.Api.TL.Functions.Contacts; +using Telegram.Api.TL.Functions.Messages; + +namespace Telegram.Api.TL +{ + public class TLObjectGenerator + { + private static readonly Dictionary> _baredTypes = + new Dictionary> + { + {typeof (TLDouble), () => new TLDouble()}, + {typeof (TLBool), () => new TLBool()}, + {typeof (TLInt), () => new TLInt()}, + {typeof (TLLong), () => new TLLong()}, + {typeof (TLInt128), () => new TLInt128()}, + {typeof (TLInt256), () => new TLInt256()}, + {typeof (TLString), () => new TLString()}, + {typeof (TLNonEncryptedMessage), () => new TLNonEncryptedMessage()}, + {typeof (TLTransportMessage), () => new TLTransportMessage()}, + {typeof (TLContainerTransportMessage), () => new TLContainerTransportMessage()}, + {typeof (TLIpPort), () => new TLIpPort()}, + }; + + private static readonly Dictionary> _clothedTypes = + new Dictionary> + { + {TLUpdateUserBlocked.Signature, () => new TLUpdateUserBlocked()}, + {TLUpdateNotifySettings.Signature, () => new TLUpdateNotifySettings()}, + + {TLNotifyPeer.Signature, () => new TLNotifyPeer()}, + {TLNotifyUsers.Signature, () => new TLNotifyUsers()}, + {TLNotifyChats.Signature, () => new TLNotifyChats()}, + {TLNotifyAll.Signature, () => new TLNotifyAll()}, + + {TLDecryptedMessageLayer.Signature, () => new TLDecryptedMessageLayer()}, + {TLUpdateDCOptions.Signature, () => new TLUpdateDCOptions()}, + + {TLDecryptedMessageMediaAudio.Signature, () => new TLDecryptedMessageMediaAudio()}, + {TLDecryptedMessageMediaDocument.Signature, () => new TLDecryptedMessageMediaDocument()}, + + {TLInputMediaDocument.Signature, () => new TLInputMediaDocument()}, + {TLInputMediaUploadedDocument.Signature, () => new TLInputMediaUploadedDocument()}, + {TLInputMediaUploadedThumbDocument.Signature, () => new TLInputMediaUploadedThumbDocument()}, + + {TLInputMediaAudio.Signature, () => new TLInputMediaAudio()}, + {TLInputMediaUploadedAudio.Signature, () => new TLInputMediaUploadedAudio()}, + + {TLInputDocument.Signature, () => new TLInputDocument()}, + {TLInputDocumentEmpty.Signature, () => new TLInputDocumentEmpty()}, + + {TLInputAudio.Signature, () => new TLInputAudio()}, + {TLInputAudioEmpty.Signature, () => new TLInputAudioEmpty()}, + + {TLMessageMediaAudio.Signature, () => new TLMessageMediaAudio()}, + {TLMessageMediaDocument.Signature, () => new TLMessageMediaDocument()}, + + {TLAudioEmpty.Signature, () => new TLAudioEmpty()}, + {TLAudio.Signature, () => new TLAudio()}, + + {TLDocumentEmpty.Signature, () => new TLDocumentEmpty()}, + {TLDocument10.Signature, () => new TLDocument10()}, + + {TLUpdateChatParticipantAdd.Signature, () => new TLUpdateChatParticipantAdd()}, + {TLUpdateChatParticipantDelete.Signature, () => new TLUpdateChatParticipantDelete()}, + + {TLInputEncryptedFileBigUploaded.Signature, () => new TLInputEncryptedFileBigUploaded()}, + {TLInputFileBig.Signature, () => new TLInputFileBig()}, + + {TLDecryptedMessageActionSetMessageTTL.Signature, () => new TLDecryptedMessageActionSetMessageTTL()}, + {TLDecryptedMessageActionReadMessages.Signature, () => new TLDecryptedMessageActionReadMessages()}, + {TLDecryptedMessageActionDeleteMessages.Signature, () => new TLDecryptedMessageActionDeleteMessages()}, + {TLDecryptedMessageActionScreenshotMessages.Signature, () => new TLDecryptedMessageActionScreenshotMessages()}, + {TLDecryptedMessageActionFlushHistory.Signature, () => new TLDecryptedMessageActionFlushHistory()}, + {TLDecryptedMessageActionNotifyLayer.Signature, () => new TLDecryptedMessageActionNotifyLayer()}, + + {TLDecryptedMessage.Signature, () => new TLDecryptedMessage()}, + {TLDecryptedMessageService.Signature, () => new TLDecryptedMessageService()}, + + {TLUpdateNewEncryptedMessage.Signature, () => new TLUpdateNewEncryptedMessage()}, + {TLUpdateEncryptedChatTyping.Signature, () => new TLUpdateEncryptedChatTyping()}, + {TLUpdateEncryption.Signature, () => new TLUpdateEncryption()}, + {TLUpdateEncryptedMessagesRead.Signature, () => new TLUpdateEncryptedMessagesRead()}, + + {TLEncryptedChatEmpty.Signature, () => new TLEncryptedChatEmpty()}, + {TLEncryptedChatWaiting.Signature, () => new TLEncryptedChatWaiting()}, + {TLEncryptedChatRequested.Signature, () => new TLEncryptedChatRequested()}, + {TLEncryptedChat.Signature, () => new TLEncryptedChat()}, + {TLEncryptedChatDiscarded.Signature, () => new TLEncryptedChatDiscarded()}, + + {TLInputEncryptedChat.Signature, () => new TLInputEncryptedChat()}, + + {TLInputEncryptedFileEmpty.Signature, () => new TLInputEncryptedFileEmpty()}, + {TLInputEncryptedFileUploaded.Signature, () => new TLInputEncryptedFileUploaded()}, + {TLInputEncryptedFile.Signature, () => new TLInputEncryptedFile()}, + + {TLInputEncryptedFileLocation.Signature, () => new TLInputEncryptedFileLocation()}, + + {TLEncryptedFileEmpty.Signature, () => new TLEncryptedFileEmpty()}, + {TLEncryptedFile.Signature, () => new TLEncryptedFile()}, + + {TLEncryptedMessage.Signature, () => new TLEncryptedMessage()}, + {TLEncryptedMessageService.Signature, () => new TLEncryptedMessageService()}, + + {TLDecryptedMessageMediaEmpty.Signature, () => new TLDecryptedMessageMediaEmpty()}, + {TLDecryptedMessageMediaPhoto.Signature, () => new TLDecryptedMessageMediaPhoto()}, + {TLDecryptedMessageMediaVideo.Signature, () => new TLDecryptedMessageMediaVideo()}, + {TLDecryptedMessageMediaGeoPoint.Signature, () => new TLDecryptedMessageMediaGeoPoint()}, + {TLDecryptedMessageMediaContact.Signature, () => new TLDecryptedMessageMediaContact()}, + + {TLDHConfig.Signature, () => new TLDHConfig()}, + {TLDHConfigNotModified.Signature, () => new TLDHConfigNotModified()}, + + {TLSentEncryptedMessage.Signature, () => new TLSentEncryptedMessage()}, + {TLSentEncryptedFile.Signature, () => new TLSentEncryptedFile()}, + + {TLMessageDetailedInfo.Signature, () => new TLMessageDetailedInfo()}, + {TLMessageNewDetailedInfo.Signature, () => new TLMessageNewDetailedInfo()}, + {TLMessagesAllInfo.Signature, () => new TLMessagesAllInfo()}, + + {TLUpdateNewMessage.Signature, () => new TLUpdateNewMessage()}, + {TLUpdateMessageId.Signature, () => new TLUpdateMessageId()}, + {TLUpdateReadMessages.Signature, () => new TLUpdateReadMessages()}, + {TLUpdateDeleteMessages.Signature, () => new TLUpdateDeleteMessages()}, + {TLUpdateRestoreMessages.Signature, () => new TLUpdateRestoreMessages()}, + {TLUpdateUserTyping.Signature, () => new TLUpdateUserTyping()}, + {TLUpdateChatUserTyping.Signature, () => new TLUpdateChatUserTyping()}, + {TLUpdateChatParticipants.Signature, () => new TLUpdateChatParticipants()}, + {TLUpdateUserStatus.Signature, () => new TLUpdateUserStatus()}, + {TLUpdateUserName.Signature, () => new TLUpdateUserName()}, + {TLUpdateUserPhoto.Signature, () => new TLUpdateUserPhoto()}, + {TLUpdateContactRegistered.Signature, () => new TLUpdateContactRegistered()}, + {TLUpdateContactLink.Signature, () => new TLUpdateContactLink()}, + {TLUpdateActivation.Signature, () => new TLUpdateActivation()}, + {TLUpdateNewAuthorization.Signature, () => new TLUpdateNewAuthorization()}, + + {TLDifferenceEmpty.Signature, () => new TLDifferenceEmpty()}, + {TLDifference.Signature, () => new TLDifference()}, + {TLDifferenceSlice.Signature, () => new TLDifferenceSlice()}, + + {TLUpdatesTooLong.Signature, () => new TLUpdatesTooLong()}, + {TLUpdatesShortMessage.Signature, () => new TLUpdatesShortMessage()}, + {TLUpdatesShortChatMessage.Signature, () => new TLUpdatesShortChatMessage()}, + {TLUpdatesShort.Signature, () => new TLUpdatesShort()}, + {TLUpdatesCombined.Signature, () => new TLUpdatesCombined()}, + {TLUpdates.Signature, () => new TLUpdates()}, + + {TLFutureSalt.Signature, () => new TLFutureSalt()}, + {TLFutureSalts.Signature, () => new TLFutureSalts()}, + + {TLGzipPacked.Signature, () => new TLGzipPacked()}, + {TLState.Signature, () => new TLState()}, + + {TLFileTypeUnknown.Signature, () => new TLFileTypeUnknown()}, + {TLFileTypeJpeg.Signature, () => new TLFileTypeJpeg()}, + {TLFileTypeGif.Signature, () => new TLFileTypeGif()}, + {TLFileTypePng.Signature, () => new TLFileTypePng()}, + {TLFileTypeMp3.Signature, () => new TLFileTypeMp3()}, + {TLFileTypeMov.Signature, () => new TLFileTypeMov()}, + {TLFileTypePartial.Signature, () => new TLFileTypePartial()}, + {TLFileTypeMp4.Signature, () => new TLFileTypeMp4()}, + {TLFileTypeWebp.Signature, () => new TLFileTypeWebp()}, + + + {TLFile.Signature, () => new TLFile()}, + + {TLInputFileLocation.Signature, () => new TLInputFileLocation()}, + {TLInputVideoFileLocation.Signature, () => new TLInputVideoFileLocation()}, + + {TLInviteText.Signature, () => new TLInviteText()}, + + {TLDHGenOk.Signature, () => new TLDHGenOk()}, + {TLDHGenRetry.Signature, () => new TLDHGenRetry()}, + {TLDHGenFail.Signature, () => new TLDHGenFail()}, + + {TLServerDHInnerData.Signature, () => new TLServerDHInnerData()}, + {TLServerDHParamsFail.Signature, () => new TLServerDHParamsFail()}, + {TLServerDHParamsOk.Signature, () => new TLServerDHParamsOk()}, + {TLPQInnerData.Signature, () => new TLPQInnerData()}, + {TLResPQ.Signature, () => new TLResPQ()}, + + {TLContactsBlocked.Signature, () => new TLContactsBlocked()}, + {TLContactsBlockedSlice.Signature, () => new TLContactsBlockedSlice()}, + {TLContactBlocked.Signature, () => new TLContactBlocked()}, + + {TLImportedContacts.Signature, () => new TLImportedContacts()}, + {TLImportedContact.Signature, () => new TLImportedContact()}, + + {TLInputContact.Signature, () => new TLInputContact()}, + + {TLContactStatus.Signature, () => new TLContactStatus()}, + + {TLForeignLinkUnknown.Signature, () => new TLForeignLinkUnknown()}, + {TLForeignLinkRequested.Signature, () => new TLForeignLinkRequested()}, + {TLForeignLinkMutual.Signature, () => new TLForeignLinkMutual()}, + + {TLMyLinkEmpty.Signature, () => new TLMyLinkEmpty()}, + {TLMyLinkContact.Signature, () => new TLMyLinkContact()}, + {TLMyLinkRequested.Signature, () => new TLMyLinkRequested()}, + + {TLLink.Signature, () => new TLLink()}, + + {TLUserFull.Signature, () => new TLUserFull()}, + + {TLPhotos.Signature, () => new TLPhotos()}, + {TLPhotosSlice.Signature, () => new TLPhotosSlice()}, + {TLPhotosPhoto.Signature, () => new TLPhotosPhoto()}, + + {TLInputPeerNotifyEventsEmpty.Signature, () => new TLInputPeerNotifyEventsEmpty()}, + {TLInputPeerNotifyEventsAll.Signature, () => new TLInputPeerNotifyEventsAll()}, + + {TLInputPeerNotifySettings.Signature, () => new TLInputPeerNotifySettings()}, + + {TLInputNotifyPeer.Signature, () => new TLInputNotifyPeer()}, + {TLInputNotifyUsers.Signature, () => new TLInputNotifyUsers()}, + {TLInputNotifyChats.Signature, () => new TLInputNotifyChats()}, + {TLInputNotifyAll.Signature, () => new TLInputNotifyAll()}, + + {TLInputUserEmpty.Signature, () => new TLInputUserEmpty()}, + {TLInputUserSelf.Signature, () => new TLInputUserSelf()}, + {TLInputUserContact.Signature, () => new TLInputUserContact()}, + {TLInputUserForeign.Signature, () => new TLInputUserForeign()}, + + {TLInputPhotoCropAuto.Signature, () => new TLInputPhotoCropAuto()}, + {TLInputPhotoCrop.Signature, () => new TLInputPhotoCrop()}, + + {TLInputChatPhotoEmpty.Signature, () => new TLInputChatPhotoEmpty()}, + {TLInputChatUploadedPhoto.Signature, () => new TLInputChatUploadedPhoto()}, + {TLInputChatPhoto.Signature, () => new TLInputChatPhoto()}, + + {TLMessagesChatFull.Signature, () => new TLMessagesChatFull()}, + {TLChatFull.Signature, () => new TLChatFull()}, + + {TLChatParticipant.Signature, () => new TLChatParticipant()}, + + {TLChatParticipantsForbidden.Signature, () => new TLChatParticipantsForbidden()}, + {TLChatParticipants.Signature, () => new TLChatParticipants()}, + + {TLPeerNotifySettingsEmpty.Signature, () => new TLPeerNotifySettingsEmpty()}, + {TLPeerNotifySettings.Signature, () => new TLPeerNotifySettings()}, + + {TLPeerNotifyEventsEmpty.Signature, () => new TLPeerNotifyEventsEmpty()}, + {TLPeerNotifyEventsAll.Signature, () => new TLPeerNotifyEventsAll()}, + + {TLChats.Signature, () => new TLChats()}, + + {TLMessages.Signature, () => new TLMessages()}, + {TLMessagesSlice.Signature, () => new TLMessagesSlice()}, + + {TLExportedAuthorization.Signature, () => new TLExportedAuthorization()}, + + {TLInputFile.Signature, () => new TLInputFile()}, + {TLInputPhotoEmpty.Signature, () => new TLInputPhotoEmpty()}, + {TLInputPhoto.Signature, () => new TLInputPhoto()}, + {TLInputGeoPoint.Signature, () => new TLInputGeoPoint()}, + {TLInputGeoPointEmpty.Signature, () => new TLInputGeoPointEmpty()}, + {TLInputVideo.Signature, () => new TLInputVideo()}, + {TLInputVideoEmpty.Signature, () => new TLInputVideoEmpty()}, + + {TLInputMediaEmpty.Signature, () => new TLInputMediaEmpty()}, + {TLInputMediaUploadedPhoto.Signature, () => new TLInputMediaUploadedPhoto()}, + {TLInputMediaPhoto.Signature, () => new TLInputMediaPhoto()}, + {TLInputMediaGeoPoint.Signature, () => new TLInputMediaGeoPoint()}, + {TLInputMediaContact.Signature, () => new TLInputMediaContact()}, + {TLInputMediaUploadedVideo.Signature, () => new TLInputMediaUploadedVideo()}, + {TLInputMediaUploadedThumbVideo.Signature, () => new TLInputMediaUploadedThumbVideo()}, + {TLInputMediaVideo.Signature, () => new TLInputMediaVideo()}, + + {TLInputMessagesFilterEmpty.Signature, () => new TLInputMessagesFilterEmpty()}, + {TLInputMessagesFilterPhoto.Signature, () => new TLInputMessagesFilterPhoto()}, + {TLInputMessagesFilterVideo.Signature, () => new TLInputMessagesFilterVideo()}, + {TLInputMessagesFilterPhotoVideo.Signature, () => new TLInputMessagesFilterPhotoVideo()}, + {TLInputMessagesFilterPhotoVideoDocument.Signature, () => new TLInputMessagesFilterPhotoVideoDocument()}, + {TLInputMessagesFilterDocument.Signature, () => new TLInputMessagesFilterDocument()}, + {TLInputMessagesFilterAudio.Signature, () => new TLInputMessagesFilterAudio()}, + {TLInputMessagesFilterAudioDocuments.Signature, () => new TLInputMessagesFilterAudioDocuments()}, + {TLInputMessagesFilterUrl.Signature, () => new TLInputMessagesFilterUrl()}, + + {TLSentMessageLink.Signature, () => new TLSentMessageLink()}, + {TLStatedMessage.Signature, () => new TLStatedMessage()}, + {TLStatedMessageLink.Signature, () => new TLStatedMessageLink()}, + {TLStatedMessages.Signature, () => new TLStatedMessages()}, + {TLStatedMessagesLinks.Signature, () => new TLStatedMessagesLinks()}, + + {TLAffectedHistory.Signature, () => new TLAffectedHistory()}, + + {TLNull.Signature, () => new TLNull()}, + + {TLBool.BoolTrue, () => new TLBool()}, + {TLBool.BoolFalse, () => new TLBool()}, + + {TLChatEmpty.Signature, () => new TLChatEmpty()}, + {TLChat.Signature, () => new TLChat()}, + {TLChatForbidden.Signature, () => new TLChatForbidden()}, + + {TLSentMessage.Signature, () => new TLSentMessage()}, + + {TLMessageEmpty.Signature, () => new TLMessageEmpty()}, + {TLMessage.Signature, () => new TLMessage()}, + {TLMessageForwarded.Signature, () => new TLMessageForwarded()}, + {TLMessageService.Signature, () => new TLMessageService()}, + + {TLMessageMediaEmpty.Signature, () => new TLMessageMediaEmpty()}, + {TLMessageMediaPhoto.Signature, () => new TLMessageMediaPhoto()}, + {TLMessageMediaVideo.Signature, () => new TLMessageMediaVideo()}, + {TLMessageMediaGeo.Signature, () => new TLMessageMediaGeo()}, + {TLMessageMediaContact.Signature, () => new TLMessageMediaContact()}, + {TLMessageMediaUnsupported.Signature, () => new TLMessageMediaUnsupported()}, + + {TLMessageActionEmpty.Signature, () => new TLMessageActionEmpty()}, + {TLMessageActionChatCreate.Signature, () => new TLMessageActionChatCreate()}, + {TLMessageActionChatEditTitle.Signature, () => new TLMessageActionChatEditTitle()}, + {TLMessageActionChatEditPhoto.Signature, () => new TLMessageActionChatEditPhoto()}, + {TLMessageActionChatDeletePhoto.Signature, () => new TLMessageActionChatDeletePhoto()}, + {TLMessageActionChatAddUser.Signature, () => new TLMessageActionChatAddUser()}, + {TLMessageActionChatDeleteUser.Signature, () => new TLMessageActionChatDeleteUser()}, + + {TLPhoto.Signature, () => new TLPhoto()}, + {TLPhotoEmpty.Signature, () => new TLPhotoEmpty()}, + + {TLPhotoSize.Signature, () => new TLPhotoSize()}, + {TLPhotoSizeEmpty.Signature, () => new TLPhotoSizeEmpty()}, + {TLPhotoCachedSize.Signature, () => new TLPhotoCachedSize()}, + + {TLVideoEmpty.Signature, () => new TLVideoEmpty()}, + {TLVideo.Signature, () => new TLVideo()}, + + {TLGeoPointEmpty.Signature, () => new TLGeoPointEmpty()}, + {TLGeoPoint.Signature, () => new TLGeoPoint()}, + + {TLDialog.Signature, () => new TLDialog()}, + {TLDialogs.Signature, () => new TLDialogs()}, + {TLDialogsSlice.Signature, () => new TLDialogsSlice()}, + + {TLInputPeerEmpty.Signature, () => new TLInputPeerEmpty()}, + {TLInputPeerSelf.Signature, () => new TLInputPeerSelf()}, + {TLInputPeerContact.Signature, () => new TLInputPeerContact()}, + {TLInputPeerForeign.Signature, () => new TLInputPeerForeign()}, + {TLInputPeerChat.Signature, () => new TLInputPeerChat()}, + + {TLPeerUser.Signature, () => new TLPeerUser()}, + {TLPeerChat.Signature, () => new TLPeerChat()}, + + {TLUserStatusEmpty.Signature, () => new TLUserStatusEmpty()}, + {TLUserStatusOnline.Signature, () => new TLUserStatusOnline()}, + {TLUserStatusOffline.Signature, () => new TLUserStatusOffline()}, + + {TLChatPhotoEmpty.Signature, () => new TLChatPhotoEmpty()}, + {TLChatPhoto.Signature, () => new TLChatPhoto()}, + {TLUserProfilePhotoEmpty.Signature, () => new TLUserProfilePhotoEmpty()}, + {TLUserProfilePhoto.Signature, () => new TLUserProfilePhoto()}, + + {TLUserEmpty.Signature, () => new TLUserEmpty()}, + {TLUserSelf.Signature, () => new TLUserSelf()}, + {TLUserContact.Signature, () => new TLUserContact()}, + {TLUserRequest.Signature, () => new TLUserRequest()}, + {TLUserForeign.Signature, () => new TLUserForeign()}, + {TLUserDeleted.Signature, () => new TLUserDeleted()}, + + {TLSentCode.Signature, () => new TLSentCode()}, + + {TLRPCResult.Signature, () => new TLRPCResult()}, + + {TLRPCError.Signature, () => new TLRPCError()}, + {TLRPCReqError.Signature, () => new TLRPCReqError()}, + + {TLNewSessionCreated.Signature, () => new TLNewSessionCreated()}, + + {TLNearestDC.Signature, () => new TLNearestDC()}, + + {TLMessagesAcknowledgment.Signature, () => new TLMessagesAcknowledgment()}, + + {TLContainer.Signature, () => new TLContainer()}, + + {TLFileLocationUnavailable.Signature, () => new TLFileLocationUnavailable()}, + {TLFileLocation.Signature, () => new TLFileLocation()}, + + {TLDCOption.Signature, () => new TLDCOption()}, + + {TLContacts.Signature, () => new TLContacts()}, + {TLContactsNotModified.Signature, () => new TLContactsNotModified()}, + + {TLContact.Signature, () => new TLContact()}, + + {TLConfig.Signature, () => new TLConfig()}, + + {TLCheckedPhone.Signature, () => new TLCheckedPhone()}, + + {TLBadServerSalt.Signature, () => new TLBadServerSalt()}, + {TLBadMessageNotification.Signature, () => new TLBadMessageNotification()}, + + {TLAuthorization.Signature, () => new TLAuthorization()}, + + {TLPong.Signature, () => new TLPong()}, + {TLWallPaper.Signature, () => new TLWallPaper()}, + {TLWallPaperSolid.Signature, () => new TLWallPaperSolid()}, + + {TLSupport.Signature, () => new TLSupport()}, + + //16 layer + {TLSentAppCode.Signature, () => new TLSentAppCode()}, + + //17 layer + {TLSendMessageTypingAction.Signature, () => new TLSendMessageTypingAction()}, + {TLSendMessageCancelAction.Signature, () => new TLSendMessageCancelAction()}, + {TLSendMessageRecordVideoAction.Signature, () => new TLSendMessageRecordVideoAction()}, + {TLSendMessageUploadVideoAction.Signature, () => new TLSendMessageUploadVideoAction()}, + {TLSendMessageRecordAudioAction.Signature, () => new TLSendMessageRecordAudioAction()}, + {TLSendMessageUploadAudioAction.Signature, () => new TLSendMessageUploadAudioAction()}, + {TLSendMessageUploadPhotoAction.Signature, () => new TLSendMessageUploadPhotoAction()}, + {TLSendMessageUploadDocumentAction.Signature, () => new TLSendMessageUploadDocumentAction()}, + {TLSendMessageGeoLocationAction.Signature, () => new TLSendMessageGeoLocationAction()}, + {TLSendMessageChooseContactAction.Signature, () => new TLSendMessageChooseContactAction()}, + {TLUpdateUserTyping17.Signature, () => new TLUpdateUserTyping17()}, + {TLUpdateChatUserTyping17.Signature, () => new TLUpdateChatUserTyping17()}, + {TLMessage17.Signature, () => new TLMessage17()}, + {TLMessageForwarded17.Signature, () => new TLMessageForwarded17()}, + {TLMessageService17.Signature, () => new TLMessageService17()}, + + //17 layer encrypted + {TLDecryptedMessage17.Signature, () => new TLDecryptedMessage17()}, + {TLDecryptedMessageService17.Signature, () => new TLDecryptedMessageService17()}, + {TLDecryptedMessageMediaAudio17.Signature, () => new TLDecryptedMessageMediaAudio17()}, + {TLDecryptedMessageMediaVideo17.Signature, () => new TLDecryptedMessageMediaVideo17()}, + {TLDecryptedMessageLayer17.Signature, () => new TLDecryptedMessageLayer17()}, + {TLDecryptedMessageActionResend.Signature, () => new TLDecryptedMessageActionResend()}, + {TLDecryptedMessageActionTyping.Signature, () => new TLDecryptedMessageActionTyping()}, + + //18 layer + {TLUpdateServiceNotification.Signature, () => new TLUpdateServiceNotification()}, + {TLContactFound.Signature, () => new TLContactFound()}, + {TLContactsFound.Signature, () => new TLContactsFound()}, + {TLUserSelf18.Signature, () => new TLUserSelf18()}, + {TLUserContact18.Signature, () => new TLUserContact18()}, + {TLUserRequest18.Signature, () => new TLUserRequest18()}, + {TLUserForeign18.Signature, () => new TLUserForeign18()}, + {TLUserDeleted18.Signature, () => new TLUserDeleted18()}, + + //19 layer + {TLUserStatusRecently.Signature, () => new TLUserStatusRecently()}, + {TLUserStatusLastWeek.Signature, () => new TLUserStatusLastWeek()}, + {TLUserStatusLastMonth.Signature, () => new TLUserStatusLastMonth()}, + {TLContactStatus19.Signature, () => new TLContactStatus19()}, + {TLUpdatePrivacy.Signature, () => new TLUpdatePrivacy()}, + {TLInputPrivacyKeyStatusTimestamp.Signature, () => new TLInputPrivacyKeyStatusTimestamp()}, + {TLPrivacyKeyStatusTimestamp.Signature, () => new TLPrivacyKeyStatusTimestamp()}, + {TLInputPrivacyValueAllowContacts.Signature, () => new TLInputPrivacyValueAllowContacts()}, + {TLInputPrivacyValueAllowAll.Signature, () => new TLInputPrivacyValueAllowAll()}, + {TLInputPrivacyValueAllowUsers.Signature, () => new TLInputPrivacyValueAllowUsers()}, + {TLInputPrivacyValueDisallowContacts.Signature, () => new TLInputPrivacyValueDisallowContacts()}, + {TLInputPrivacyValueDisallowAll.Signature, () => new TLInputPrivacyValueDisallowAll()}, + {TLInputPrivacyValueDisallowUsers.Signature, () => new TLInputPrivacyValueDisallowUsers()}, + {TLPrivacyValueAllowContacts.Signature, () => new TLPrivacyValueAllowContacts()}, + {TLPrivacyValueAllowAll.Signature, () => new TLPrivacyValueAllowAll()}, + {TLPrivacyValueAllowUsers.Signature, () => new TLPrivacyValueAllowUsers()}, + {TLPrivacyValueDisallowContacts.Signature, () => new TLPrivacyValueDisallowContacts()}, + {TLPrivacyValueDisallowAll.Signature, () => new TLPrivacyValueDisallowAll()}, + {TLPrivacyValueDisallowUsers.Signature, () => new TLPrivacyValueDisallowUsers()}, + {TLPrivacyRules.Signature, () => new TLPrivacyRules()}, + {TLAccountDaysTTL.Signature, () => new TLAccountDaysTTL()}, + + //20 layer + {TLSentChangePhoneCode.Signature, () => new TLSentChangePhoneCode()}, + {TLUpdateUserPhone.Signature, () => new TLUpdateUserPhone()}, + + //20 layer encrypted + {TLEncryptedChat20.Signature, () => new TLEncryptedChat20()}, + {TLDecryptedMessageActionRequestKey.Signature, () => new TLDecryptedMessageActionRequestKey()}, + {TLDecryptedMessageActionAcceptKey.Signature, () => new TLDecryptedMessageActionAcceptKey()}, + {TLDecryptedMessageActionAbortKey.Signature, () => new TLDecryptedMessageActionAbortKey()}, + {TLDecryptedMessageActionCommitKey.Signature, () => new TLDecryptedMessageActionCommitKey()}, + {TLDecryptedMessageActionNoop.Signature, () => new TLDecryptedMessageActionNoop()}, + + //21 layer + + //22 layer + {TLInputMediaUploadedDocument22.Signature, () => new TLInputMediaUploadedDocument22()}, + {TLInputMediaUploadedThumbDocument22.Signature, () => new TLInputMediaUploadedThumbDocument22()}, + {TLDocument22.Signature, () => new TLDocument22()}, + {TLDocumentAttributeImageSize.Signature, () => new TLDocumentAttributeImageSize()}, + {TLDocumentAttributeAnimated.Signature, () => new TLDocumentAttributeAnimated()}, + {TLDocumentAttributeSticker.Signature, () => new TLDocumentAttributeSticker()}, + {TLDocumentAttributeVideo.Signature, () => new TLDocumentAttributeVideo()}, + {TLDocumentAttributeAudio.Signature, () => new TLDocumentAttributeAudio()}, + {TLDocumentAttributeFileName.Signature, () => new TLDocumentAttributeFileName()}, + {TLStickersNotModified.Signature, () => new TLStickersNotModified()}, + {TLStickers.Signature, () => new TLStickers()}, + {TLStickerPack.Signature, () => new TLStickerPack()}, + {TLAllStickersNotModified.Signature, () => new TLAllStickersNotModified()}, + {TLAllStickers.Signature, () => new TLAllStickers()}, + + //23 layer + {TLDisabledFeature.Signature, () => new TLDisabledFeature()}, + {TLConfig23.Signature, () => new TLConfig23()}, + + //23 layer encrypted + {TLDecryptedMessageMediaExternalDocument.Signature, () => new TLDecryptedMessageMediaExternalDocument()}, + + //24 layer + {TLUpdateNewMessage24.Signature, () => new TLUpdateNewMessage24()}, + {TLUpdateReadMessages24.Signature, () => new TLUpdateReadMessages24()}, + {TLUpdateDeleteMessages24.Signature, () => new TLUpdateDeleteMessages24()}, + {TLUpdatesShortMessage24.Signature, () => new TLUpdatesShortMessage24()}, + {TLUpdatesShortChatMessage24.Signature, () => new TLUpdatesShortChatMessage24()}, + {TLUpdateReadHistoryInbox.Signature, () => new TLUpdateReadHistoryInbox()}, + {TLUpdateReadHistoryOutbox.Signature, () => new TLUpdateReadHistoryOutbox()}, + {TLDialog24.Signature, () => new TLDialog24()}, + {TLStatedMessages24.Signature, () => new TLStatedMessages24()}, + {TLStatedMessagesLinks24.Signature, () => new TLStatedMessagesLinks24()}, + {TLStatedMessage24.Signature, () => new TLStatedMessage24()}, + {TLStatedMessageLink24.Signature, () => new TLStatedMessageLink24()}, + {TLSentMessage24.Signature, () => new TLSentMessage24()}, + {TLSentMessageLink24.Signature, () => new TLSentMessageLink24()}, + {TLAffectedMessages.Signature, () => new TLAffectedMessages()}, + {TLAffectedHistory24.Signature, () => new TLAffectedHistory24()}, + {TLMessageMediaUnsupported24.Signature, () => new TLMessageMediaUnsupported24()}, + {TLChats24.Signature, () => new TLChats24()}, + {TLUserSelf24.Signature, () => new TLUserSelf24()}, + {TLCheckedPhone24.Signature, () => new TLCheckedPhone24()}, + {TLContactLinkUnknown.Signature, () => new TLContactLinkUnknown()}, + {TLContactLinkNone.Signature, () => new TLContactLinkNone()}, + {TLContactLinkHasPhone.Signature, () => new TLContactLinkHasPhone()}, + {TLContactLink.Signature, () => new TLContactLink()}, + {TLUpdateContactLink24.Signature, () => new TLUpdateContactLink24()}, + {TLLink24.Signature, () => new TLLink24()}, + {TLConfig24.Signature, () => new TLConfig24()}, + + //25 layer + {TLMessage25.Signature, () => new TLMessage25()}, + {TLDocumentAttributeSticker25.Signature, () => new TLDocumentAttributeSticker25()}, + {TLUpdatesShortMessage25.Signature, () => new TLUpdatesShortMessage25()}, + {TLUpdatesShortChatMessage25.Signature, () => new TLUpdatesShortChatMessage25()}, + + //26 layer + {TLSentMessage26.Signature, () => new TLSentMessage26()}, + {TLSentMessageLink26.Signature, () => new TLSentMessageLink26()}, + {TLConfig26.Signature, () => new TLConfig26()}, + {TLUpdateWebPage.Signature, () => new TLUpdateWebPage()}, + {TLWebPageEmpty.Signature, () => new TLWebPageEmpty()}, + {TLWebPagePending.Signature, () => new TLWebPagePending()}, + {TLWebPage.Signature, () => new TLWebPage()}, + {TLMessageMediaWebPage.Signature, () => new TLMessageMediaWebPage()}, + {TLAccountAuthorization.Signature, () => new TLAccountAuthorization()}, + {TLAccountAuthorizations.Signature, () => new TLAccountAuthorizations()}, + + //27 layer + {TLPassword.Signature, () => new TLPassword()}, + {TLNoPassword.Signature, () => new TLNoPassword()}, + {TLPasswordSettings.Signature, () => new TLPasswordSettings()}, + {TLPasswordInputSettings.Signature, () => new TLPasswordInputSettings()}, + {TLPasswordRecovery.Signature, () => new TLPasswordRecovery()}, + + //layer 28 + {TLInputMediaUploadedPhoto28.Signature, () => new TLInputMediaUploadedPhoto28()}, + {TLInputMediaPhoto28.Signature, () => new TLInputMediaPhoto28()}, + {TLInputMediaUploadedVideo28.Signature, () => new TLInputMediaUploadedVideo28()}, + {TLInputMediaUploadedThumbVideo28.Signature, () => new TLInputMediaUploadedThumbVideo28()}, + {TLInputMediaVideo28.Signature, () => new TLInputMediaVideo28()}, + {TLSendMessageUploadVideoAction28.Signature, () => new TLSendMessageUploadVideoAction28()}, + {TLSendMessageUploadAudioAction28.Signature, () => new TLSendMessageUploadAudioAction28()}, + {TLSendMessageUploadPhotoAction28.Signature, () => new TLSendMessageUploadPhotoAction28()}, + {TLSendMessageUploadDocumentAction28.Signature, () => new TLSendMessageUploadDocumentAction28()}, + {TLInputMediaVenue.Signature, () => new TLInputMediaVenue()}, + {TLMessageMediaVenue.Signature, () => new TLMessageMediaVenue()}, + {TLChatInviteEmpty.Signature, () => new TLChatInviteEmpty()}, + {TLChatInviteExported.Signature, () => new TLChatInviteExported()}, + {TLChatInviteAlready.Signature, () => new TLChatInviteAlready()}, + {TLChatInvite.Signature, () => new TLChatInvite()}, + {TLUpdateReadMessagesContents.Signature, () => new TLUpdateReadMessagesContents()}, + {TLConfig28.Signature, () => new TLConfig28()}, + {TLChatFull28.Signature, () => new TLChatFull28()}, + {TLReceivedNotifyMessage.Signature, () => new TLReceivedNotifyMessage()}, + {TLMessageActionChatJoinedByLink.Signature, () => new TLMessageActionChatJoinedByLink()}, + {TLPhoto28.Signature, () => new TLPhoto28()}, + {TLVideo28.Signature, () => new TLVideo28()}, + {TLMessageMediaPhoto28.Signature, () => new TLMessageMediaPhoto28()}, + {TLMessageMediaVideo28.Signature, () => new TLMessageMediaVideo28()}, + + //layer 29 + {TLDocumentAttributeSticker29.Signature, () => new TLDocumentAttributeSticker29()}, + {TLAllStickers29.Signature, () => new TLAllStickers29()}, + {TLInputStickerSetEmpty.Signature, () => new TLInputStickerSetEmpty()}, + {TLInputStickerSetId.Signature, () => new TLInputStickerSetId()}, + {TLInputStickerSetShortName.Signature, () => new TLInputStickerSetShortName()}, + {TLStickerSet.Signature, () => new TLStickerSet()}, + {TLMessagesStickerSet.Signature, () => new TLMessagesStickerSet()}, + + //layer 30 + {TLDCOption30.Signature, () => new TLDCOption30()}, + + //layer 31 + {TLChatFull31.Signature, () => new TLChatFull31()}, + {TLMessage31.Signature, () => new TLMessage31()}, + {TLAuthorization31.Signature, () => new TLAuthorization31()}, + {TLUserFull31.Signature, () => new TLUserFull31()}, + {TLUser.Signature, () => new TLUser()}, + {TLBotCommand.Signature, () => new TLBotCommand()}, + {TLBotInfoEmpty.Signature, () => new TLBotInfoEmpty()}, + {TLBotInfo.Signature, () => new TLBotInfo()}, + {TLKeyboardButton.Signature, () => new TLKeyboardButton()}, + {TLKeyboardButtonRow.Signature, () => new TLKeyboardButtonRow()}, + {TLReplyKeyboardMarkup.Signature, () => new TLReplyKeyboardMarkup()}, + {TLReplyKeyboardHide.Signature, () => new TLReplyKeyboardHide()}, + {TLReplyKeyboardForceReply.Signature, () => new TLReplyKeyboardForceReply()}, + + //layer 32 + {TLAllStickers32.Signature, () => new TLAllStickers32()}, + {TLStickerSet32.Signature, () => new TLStickerSet32()}, + {TLDocumentAttributeAudio32.Signature, () => new TLDocumentAttributeAudio32()}, + + //layer 33 + {TLInputPeerUser.Signature, () => new TLInputPeerUser()}, + {TLInputUser.Signature, () => new TLInputUser()}, + {TLPhoto33.Signature, () => new TLPhoto33()}, + {TLVideo33.Signature, () => new TLVideo33()}, + {TLAudio33.Signature, () => new TLAudio33()}, + {TLAppChangelogEmpty.Signature, () => new TLAppChangelogEmpty()}, + {TLAppChangelog.Signature, () => new TLAppChangelog()}, + + //layer 34 + {TLMessageEntityUnknown.Signature, () => new TLMessageEntityUnknown()}, + {TLMessageEntityMention.Signature, () => new TLMessageEntityMention()}, + {TLMessageEntityHashtag.Signature, () => new TLMessageEntityHashtag()}, + {TLMessageEntityBotCommand.Signature, () => new TLMessageEntityBotCommand()}, + {TLMessageEntityUrl.Signature, () => new TLMessageEntityUrl()}, + {TLMessageEntityEmail.Signature, () => new TLMessageEntityEmail()}, + {TLMessageEntityBold.Signature, () => new TLMessageEntityBold()}, + {TLMessageEntityItalic.Signature, () => new TLMessageEntityItalic()}, + {TLMessageEntityCode.Signature, () => new TLMessageEntityCode()}, + {TLMessageEntityPre.Signature, () => new TLMessageEntityPre()}, + {TLMessageEntityTextUrl.Signature, () => new TLMessageEntityTextUrl()}, + {TLMessage34.Signature, () => new TLMessage34()}, + {TLSentMessage34.Signature, () => new TLSentMessage34()}, + {TLUpdatesShortMessage34.Signature, () => new TLUpdatesShortMessage34()}, + {TLUpdatesShortChatMessage34.Signature, () => new TLUpdatesShortChatMessage34()}, + + //layer 35 + {TLWebPage35.Signature, () => new TLWebPage35()}, + + //layer 36 + {TLInputMediaUploadedVideo36.Signature, () => new TLInputMediaUploadedVideo36()}, + {TLInputMediaUploadedThumbVideo36.Signature, () => new TLInputMediaUploadedThumbVideo36()}, + {TLMessage36.Signature, () => new TLMessage36()}, + {TLUpdatesShortSentMessage.Signature, () => new TLUpdatesShortSentMessage()}, + + //layer 37 + {TLChatParticipantsForbidden37.Signature, () => new TLChatParticipantsForbidden37()}, + {TLUpdateChatParticipantAdd37.Signature, () => new TLUpdateChatParticipantAdd37()}, + {TLUpdateWebPage37.Signature, () => new TLUpdateWebPage37()}, + + //layer 40 + {TLInputPeerChannel.Signature, () => new TLInputPeerChannel()}, + {TLPeerChannel.Signature, () => new TLPeerChannel()}, + {TLChat40.Signature, () => new TLChat40()}, + {TLChatForbidden40.Signature, () => new TLChatForbidden40()}, + {TLChannel.Signature, () => new TLChannel()}, + {TLChannelForbidden.Signature, () => new TLChannelForbidden()}, + {TLChannelFull.Signature, () => new TLChannelFull()}, + {TLChannelParticipants40.Signature, () => new TLChannelParticipants40()}, + {TLMessage40.Signature, () => new TLMessage40()}, + {TLMessageService40.Signature, () => new TLMessageService40()}, + {TLMessageActionChannelCreate.Signature, () => new TLMessageActionChannelCreate()}, + {TLDialogChannel.Signature, () => new TLDialogChannel()}, + {TLChannelMessages.Signature, () => new TLChannelMessages()}, + {TLUpdateChannelTooLong.Signature, () => new TLUpdateChannelTooLong()}, + {TLUpdateChannel.Signature, () => new TLUpdateChannel()}, + {TLUpdateChannelGroup.Signature, () => new TLUpdateChannelGroup()}, + {TLUpdateNewChannelMessage.Signature, () => new TLUpdateNewChannelMessage()}, + {TLUpdateReadChannelInbox.Signature, () => new TLUpdateReadChannelInbox()}, + {TLUpdateDeleteChannelMessages.Signature, () => new TLUpdateDeleteChannelMessages()}, + {TLUpdateChannelMessageViews.Signature, () => new TLUpdateChannelMessageViews()}, + {TLUpdatesShortMessage40.Signature, () => new TLUpdatesShortMessage40()}, + {TLUpdatesShortChatMessage40.Signature, () => new TLUpdatesShortChatMessage40()}, + {TLContactsFound40.Signature, () => new TLContactsFound40()}, + //{TLInputChatEmpty.Signature, () => new TLInputChatEmpty()}, // delete + //{TLInputChat.Signature, () => new TLInputChat()}, // delete + {TLInputChannel.Signature, () => new TLInputChannel()}, + {TLInputChannelEmpty.Signature, () => new TLInputChannelEmpty()}, + {TLMessageRange.Signature, () => new TLMessageRange()}, + {TLMessageGroup.Signature, () => new TLMessageGroup()}, + {TLChannelDifferenceEmpty.Signature, () => new TLChannelDifferenceEmpty()}, + {TLChannelDifferenceTooLong.Signature, () => new TLChannelDifferenceTooLong()}, + {TLChannelDifference.Signature, () => new TLChannelDifference()}, + {TLChannelMessagesFilterEmpty.Signature, () => new TLChannelMessagesFilterEmpty()}, + {TLChannelMessagesFilter.Signature, () => new TLChannelMessagesFilter()}, + {TLChannelMessagesFilterCollapsed.Signature, () => new TLChannelMessagesFilterCollapsed()}, + {TLResolvedPeer.Signature, () => new TLResolvedPeer()}, + {TLChannelParticipant.Signature, () => new TLChannelParticipant()}, + {TLChannelParticipantSelf.Signature, () => new TLChannelParticipantSelf()}, + {TLChannelParticipantModerator.Signature, () => new TLChannelParticipantModerator()}, + {TLChannelParticipantEditor.Signature, () => new TLChannelParticipantEditor()}, + {TLChannelParticipantKicked.Signature, () => new TLChannelParticipantKicked()}, + {TLChannelParticipantCreator.Signature, () => new TLChannelParticipantCreator()}, + {TLChannelParticipantsRecent.Signature, () => new TLChannelParticipantsRecent()}, + {TLChannelParticipantsAdmins.Signature, () => new TLChannelParticipantsAdmins()}, + {TLChannelParticipantsKicked.Signature, () => new TLChannelParticipantsKicked()}, + {TLChannelRoleEmpty.Signature, () => new TLChannelRoleEmpty()}, + {TLChannelRoleModerator.Signature, () => new TLChannelRoleModerator()}, + {TLChannelRoleEditor.Signature, () => new TLChannelRoleEditor()}, + {TLChannelParticipants.Signature, () => new TLChannelParticipants()}, + {TLChannelsChannelParticipant.Signature, () => new TLChannelsChannelParticipant()}, + {TLChatInvite40.Signature, () => new TLChatInvite40()}, + + {TLChatParticipantCreator.Signature, () => new TLChatParticipantCreator()}, + {TLChatParticipantAdmin.Signature, () => new TLChatParticipantAdmin()}, + {TLChatParticipants40.Signature, () => new TLChatParticipants40()}, + {TLUpdateChatAdmins.Signature, () => new TLUpdateChatAdmins()}, + {TLUpdateChatParticipantAdmin.Signature, () => new TLUpdateChatParticipantAdmin()}, + + // layer 41 + {TLConfig41.Signature, () => new TLConfig41()}, + + {TLMessageActionChatMigrateTo.Signature, () => new TLMessageActionChatMigrateTo()}, + {TLMessageActionChatDeactivate.Signature, () => new TLMessageActionChatDeactivate()}, + {TLMessageActionChatActivate.Signature, () => new TLMessageActionChatActivate()}, + {TLMessageActionChannelMigrateFrom.Signature, () => new TLMessageActionChannelMigrateFrom()}, + + {TLChannelParticipantsBots.Signature, () => new TLChannelParticipantsBots()}, + {TLChat41.Signature, () => new TLChat41()}, + {TLChannelFull41.Signature, () => new TLChannelFull41()}, + {TLMessageActionChatAddUser41.Signature, () => new TLMessageActionChatAddUser41()}, + + // layer 42 + {TLTermsOfService.Signature, () => new TLTermsOfService()}, + + {TLInputReportReasonSpam.Signature, () => new TLInputReportReasonSpam()}, + {TLInputReportReasonViolence.Signature, () => new TLInputReportReasonViolence()}, + {TLInputReportReasonPornography.Signature, () => new TLInputReportReasonPornography()}, + {TLInputReportReasonOther.Signature, () => new TLInputReportReasonOther()}, + + // layer 43 + {TLUpdateNewStickerSet.Signature, () => new TLUpdateNewStickerSet()}, + {TLUpdateStickerSetsOrder.Signature, () => new TLUpdateStickerSetsOrder()}, + {TLUpdateStickerSets.Signature, () => new TLUpdateStickerSets()}, + {TLAllStickers43.Signature, () => new TLAllStickers43()}, + + // layer 44 + {TLInputMediaGifExternal.Signature, () => new TLInputMediaGifExternal()}, + {TLUser44.Signature, () => new TLUser44()}, + {TLChannel44.Signature, () => new TLChannel44()}, + {TLInputMessagesFilterGif.Signature, () => new TLInputMessagesFilterGif()}, + {TLUpdateSavedGifs.Signature, () => new TLUpdateSavedGifs()}, + {TLConfig44.Signature, () => new TLConfig44()}, + {TLFoundGif.Signature, () => new TLFoundGif()}, + {TLFoundGifCached.Signature, () => new TLFoundGifCached()}, + {TLFoundGifs.Signature, () => new TLFoundGifs()}, + {TLSavedGifsNotModified.Signature, () => new TLSavedGifsNotModified()}, + {TLSavedGifs.Signature, () => new TLSavedGifs()}, + + // layer 45 + {TLInputMediaUploadedDocument45.Signature, () => new TLInputMediaUploadedDocument45()}, + {TLInputMediaUploadedThumbDocument45.Signature, () => new TLInputMediaUploadedThumbDocument45()}, + {TLInputMediaDocument45.Signature, () => new TLInputMediaDocument45()}, + {TLUser45.Signature, () => new TLUser45()}, + {TLMessage45.Signature, () => new TLMessage45()}, + {TLMessageMediaDocument45.Signature, () => new TLMessageMediaDocument45()}, + {TLUpdateBotInlineQuery.Signature, () => new TLUpdateBotInlineQuery()}, + {TLUpdatesShortMessage45.Signature, () => new TLUpdatesShortMessage45()}, + {TLUpdatesShortChatMessage45.Signature, () => new TLUpdatesShortChatMessage45()}, + + {TLInputBotInlineMessageMediaAuto.Signature, () => new TLInputBotInlineMessageMediaAuto()}, + {TLInputBotInlineMessageText.Signature, () => new TLInputBotInlineMessageText()}, + {TLInputBotInlineResult.Signature, () => new TLInputBotInlineResult()}, + {TLBotInlineMessageMediaAuto.Signature, () => new TLBotInlineMessageMediaAuto()}, + {TLBotInlineMessageText.Signature, () => new TLBotInlineMessageText()}, + //{TLBotInlineMediaResultDocument.Signature, () => new TLBotInlineMediaResultDocument()}, + {TLBotInlineMediaResultPhoto.Signature, () => new TLBotInlineMediaResultPhoto()}, + {TLBotInlineResult.Signature, () => new TLBotInlineResult()}, + {TLBotResults.Signature, () => new TLBotResults()}, + + // layer 46 + {TLDocumentAttributeAudio46.Signature, () => new TLDocumentAttributeAudio46()}, + {TLInputMessagesFilterVoice.Signature, () => new TLInputMessagesFilterVoice()}, + {TLInputMessagesFilterMusic.Signature, () => new TLInputMessagesFilterMusic()}, + {TLInputPrivacyKeyChatInvite.Signature, () => new TLInputPrivacyKeyChatInvite()}, + {TLPrivacyKeyChatInvite.Signature, () => new TLPrivacyKeyChatInvite()}, + + // layer 48 + {TLMessage48.Signature, () => new TLMessage48()}, + {TLInputPeerNotifySettings48.Signature, () => new TLInputPeerNotifySettings48()}, + {TLPeerNotifySettings48.Signature, () => new TLPeerNotifySettings48()}, + {TLUpdateEditChannelMessage.Signature, () => new TLUpdateEditChannelMessage()}, + {TLUpdatesShortMessage48.Signature, () => new TLUpdatesShortMessage48()}, + {TLUpdatesShortChatMessage48.Signature, () => new TLUpdatesShortChatMessage48()}, + {TLConfig48.Signature, () => new TLConfig48()}, + {TLExportedMessageLink.Signature, () => new TLExportedMessageLink()}, + {TLMessageFwdHeader.Signature, () => new TLMessageFwdHeader()}, + {TLMessageEditData.Signature, () => new TLMessageEditData()}, + + // layer 49 + {TLChannel49.Signature, () => new TLChannel49()}, + {TLChannelFull49.Signature, () => new TLChannelFull49()}, + {TLMessageService49.Signature, () => new TLMessageService49()}, + {TLMessageActionPinMessage.Signature, () => new TLMessageActionPinMessage()}, + {TLPeerSettings.Signature, () => new TLPeerSettings()}, + {TLUserFull49.Signature, () => new TLUserFull49()}, + {TLUpdateChannelTooLong49.Signature, () => new TLUpdateChannelTooLong49()}, + {TLUpdateChannelPinnedMessage.Signature, () => new TLUpdateChannelPinnedMessage()}, + {TLBotInfo49.Signature, () => new TLBotInfo49()}, + + // layer 50 + {TLSentCode50.Signature, () => new TLSentCode50()}, + {TLCodeTypeSms.Signature, () => new TLCodeTypeSms()}, + {TLCodeTypeCall.Signature, () => new TLCodeTypeCall()}, + {TLCodeTypeFlashCall.Signature, () => new TLCodeTypeFlashCall()}, + {TLSentCodeTypeApp.Signature, () => new TLSentCodeTypeApp()}, + {TLSentCodeTypeSms.Signature, () => new TLSentCodeTypeSms()}, + {TLSentCodeTypeCall.Signature, () => new TLSentCodeTypeCall()}, + {TLSentCodeTypeFlashCall.Signature, () => new TLSentCodeTypeFlashCall()}, + + // layer 51 + {TLUpdateBotCallbackQuery.Signature, () => new TLUpdateBotCallbackQuery()}, + {TLUpdateInlineBotCallbackQuery.Signature, () => new TLUpdateInlineBotCallbackQuery()}, + {TLUpdateBotInlineQuery51.Signature, () => new TLUpdateBotInlineQuery51()}, + {TLUpdateBotInlineSend.Signature, () => new TLUpdateBotInlineSend()}, + {TLUpdateEditMessage.Signature, () => new TLUpdateEditMessage()}, + + {TLKeyboardButtonUrl.Signature, () => new TLKeyboardButtonUrl()}, + {TLKeyboardButtonCallback.Signature, () => new TLKeyboardButtonCallback()}, + {TLKeyboardButtonRequestPhone.Signature, () => new TLKeyboardButtonRequestPhone()}, + {TLKeyboardButtonRequestGeoLocation.Signature, () => new TLKeyboardButtonRequestGeoLocation()}, + {TLKeyboardButtonSwitchInline.Signature, () => new TLKeyboardButtonSwitchInline()}, + + {TLBotCallbackAnswer.Signature, () => new TLBotCallbackAnswer()}, + {TLReplyInlineMarkup.Signature, () => new TLReplyInlineMarkup()}, + + {TLInputBotInlineMessageMediaAuto51.Signature, () => new TLInputBotInlineMessageMediaAuto51()}, + {TLInputBotInlineMessageText51.Signature, () => new TLInputBotInlineMessageText51()}, + {TLInputBotInlineMessageMediaGeo.Signature, () => new TLInputBotInlineMessageMediaGeo()}, + {TLInputBotInlineMessageMediaVenue.Signature, () => new TLInputBotInlineMessageMediaVenue()}, + {TLInputBotInlineMessageMediaContact.Signature, () => new TLInputBotInlineMessageMediaContact()}, + + {TLInputBotInlineResultPhoto.Signature, () => new TLInputBotInlineResultPhoto()}, + {TLInputBotInlineResultDocument.Signature, () => new TLInputBotInlineResultDocument()}, + + {TLBotInlineMessageMediaAuto51.Signature, () => new TLBotInlineMessageMediaAuto51()}, + {TLBotInlineMessageText51.Signature, () => new TLBotInlineMessageText51()}, + {TLBotInlineMessageMediaGeo.Signature, () => new TLBotInlineMessageMediaGeo()}, + {TLBotInlineMessageMediaVenue.Signature, () => new TLBotInlineMessageMediaVenue()}, + {TLBotInlineMessageMediaContact.Signature, () => new TLBotInlineMessageMediaContact()}, + + {TLBotInlineMediaResult.Signature, () => new TLBotInlineMediaResult()}, + {TLInputBotInlineMessageId.Signature, () => new TLInputBotInlineMessageId()}, + + {TLBotResults51.Signature, () => new TLBotResults51()}, + {TLInlineBotSwitchPM.Signature, () => new TLInlineBotSwitchPM()}, + + // layer 52 + {TLConfig52.Signature, () => new TLConfig52()}, + {TLMessageEntityMentionName.Signature, () => new TLMessageEntityMentionName()}, + {TLInputMessageEntityMentionName.Signature, () => new TLInputMessageEntityMentionName()}, + {TLPeerDialogs.Signature, () => new TLPeerDialogs()}, + {TLTopPeer.Signature, () => new TLTopPeer()}, + {TLTopPeerCategoryBotsPM.Signature, () => new TLTopPeerCategoryBotsPM()}, + {TLTopPeerCategoryBotsInline.Signature, () => new TLTopPeerCategoryBotsInline()}, + {TLTopPeerCategoryCorrespondents.Signature, () => new TLTopPeerCategoryCorrespondents()}, + {TLTopPeerCategoryGroups.Signature, () => new TLTopPeerCategoryGroups()}, + {TLTopPeerCategoryChannels.Signature, () => new TLTopPeerCategoryChannels()}, + {TLTopPeerCategoryPeers.Signature, () => new TLTopPeerCategoryPeers()}, + {TLTopPeersNotModified.Signature, () => new TLTopPeersNotModified()}, + {TLTopPeers.Signature, () => new TLTopPeers()}, + + // layer 53 + {TLChannelFull53.Signature, () => new TLChannelFull53()}, + {TLDialog53.Signature, () => new TLDialog53()}, + {TLChannelMessages53.Signature, () => new TLChannelMessages53()}, + {TLUpdateDraftMessage.Signature, () => new TLUpdateDraftMessage()}, + {TLChannelDifferenceTooLong53.Signature, () => new TLChannelDifferenceTooLong53()}, + {TLInputMessagesFilterChatPhotos.Signature, () => new TLInputMessagesFilterChatPhotos()}, + {TLUpdateReadChannelOutbox.Signature, () => new TLUpdateReadChannelOutbox()}, + {TLDraftMessageEmpty.Signature, () => new TLDraftMessageEmpty()}, + {TLDraftMessage.Signature, () => new TLDraftMessage()}, + {TLChannelForbidden53.Signature, () => new TLChannelForbidden53()}, + {TLMessageActionClearHistory.Signature, () => new TLMessageActionClearHistory()}, + + // layer 54 + {TLConfig54.Signature, () => new TLConfig54()}, + {TLFeaturedStickersNotModified.Signature, () => new TLFeaturedStickersNotModified()}, + {TLFeaturedStickers.Signature, () => new TLFeaturedStickers()}, + {TLUpdateReadFeaturedStickers.Signature, () => new TLUpdateReadFeaturedStickers()}, + {TLBotCallbackAnswer54.Signature, () => new TLBotCallbackAnswer54()}, + {TLDocument54.Signature, () => new TLDocument54()}, + {TLInputDocumentFileLocation54.Signature, () => new TLInputDocumentFileLocation54()}, + {TLRecentStickersNotModified.Signature, () => new TLRecentStickersNotModified()}, + {TLRecentStickers.Signature, () => new TLRecentStickers()}, + {TLUpdateRecentStickers.Signature, () => new TLUpdateRecentStickers()}, + {TLChatInvite54.Signature, () => new TLChatInvite54()}, + {TLStickerSetInstallResult.Signature, () => new TLStickerSetInstallResult()}, + {TLStickerSetInstallResultArchive.Signature, () => new TLStickerSetInstallResultArchive()}, + {TLArchivedStickers.Signature, () => new TLArchivedStickers()}, + {TLStickerSetCovered.Signature, () => new TLStickerSetCovered()}, + + // layer 55 + {TLInputMediaPhotoExternal.Signature, () => new TLInputMediaPhotoExternal()}, + {TLInputMediaDocumentExternal.Signature, () => new TLInputMediaDocumentExternal()}, + {TLAuthorization55.Signature, () => new TLAuthorization55()}, + {TLUpdateConfig.Signature, () => new TLUpdateConfig()}, + {TLUpdatePtsChanged.Signature, () => new TLUpdatePtsChanged()}, + {TLConfig55.Signature, () => new TLConfig55()}, + {TLKeyboardButtonSwitchInline55.Signature, () => new TLKeyboardButtonSwitchInline55()}, + + // layer 56 + {TLUpdateBotCallbackQuery56.Signature, () => new TLUpdateBotCallbackQuery56()}, + {TLUpdateInlineBotCallbackQuery56.Signature, () => new TLUpdateInlineBotCallbackQuery56()}, + {TLUpdateStickerSetsOrder56.Signature, () => new TLUpdateStickerSetsOrder56()}, + {TLStickerSetMultiCovered.Signature, () => new TLStickerSetMultiCovered()}, + {TLInputMediaUploadedPhoto56.Signature, () => new TLInputMediaUploadedPhoto56()}, + {TLInputMediaUploadedDocument56.Signature, () => new TLInputMediaUploadedDocument56()}, + {TLInputMediaUploadedThumbDocument56.Signature, () => new TLInputMediaUploadedThumbDocument56()}, + {TLInputStickeredMediaPhoto.Signature, () => new TLInputStickeredMediaPhoto()}, + {TLInputStickeredMediaDocument.Signature, () => new TLInputStickeredMediaDocument()}, + {TLPhoto56.Signature, () => new TLPhoto56()}, + {TLMaskCoords.Signature, () => new TLMaskCoords()}, + {TLDocumentAttributeSticker56.Signature, () => new TLDocumentAttributeSticker56()}, + {TLDocumentAttributeHasStickers.Signature, () => new TLDocumentAttributeHasStickers()}, + + // layer 57 + {TLInputMediaGame.Signature, () => new TLInputMediaGame()}, + {TLInputGameId.Signature, () => new TLInputGameId()}, + {TLInputGameShortName.Signature, () => new TLInputGameShortName()}, + {TLGame.Signature, () => new TLGame()}, + {TLHighScore.Signature, () => new TLHighScore()}, + {TLHighScores.Signature, () => new TLHighScores()}, + {TLInputBotInlineMessageGame.Signature, () => new TLInputBotInlineMessageGame()}, + {TLInputBotInlineResultGame.Signature, () => new TLInputBotInlineResultGame()}, + {TLKeyboardButtonGame.Signature, () => new TLKeyboardButtonGame()}, + {TLMessageActionGameScore.Signature, () => new TLMessageActionGameScore()}, + {TLMessageMediaGame.Signature, () => new TLMessageMediaGame()}, + + // layer 58 + {TLUserFull58.Signature, () => new TLUserFull58()}, + {TLChatsSlice.Signature, () => new TLChatsSlice()}, + {TLUpdateChannelWebPage.Signature, () => new TLUpdateChannelWebPage()}, + {TLDifferenceTooLong.Signature, () => new TLDifferenceTooLong()}, + {TLBotResults58.Signature, () => new TLBotResults58()}, + {TLBotCallbackAnswer58.Signature, () => new TLBotCallbackAnswer58()}, + + // layer 59 + {TLChatsSlice59.Signature, () => new TLChatsSlice59()}, + {TLUpdateServiceNotification59.Signature, () => new TLUpdateServiceNotification59()}, + {TLWebPage59.Signature, () => new TLWebPage59()}, + {TLWebPageNotModified.Signature, () => new TLWebPageNotModified()}, + {TLAppChangelog59.Signature, () => new TLAppChangelog59()}, + + {TLTextEmpty.Signature, () => new TLTextEmpty()}, + {TLTextPlain.Signature, () => new TLTextPlain()}, + {TLTextBold.Signature, () => new TLTextBold()}, + {TLTextItalic.Signature, () => new TLTextItalic()}, + {TLTextUnderline.Signature, () => new TLTextUnderline()}, + {TLTextStrike.Signature, () => new TLTextStrike()}, + {TLTextFixed.Signature, () => new TLTextFixed()}, + {TLTextUrl.Signature, () => new TLTextUrl()}, + {TLTextEmail.Signature, () => new TLTextEmail()}, + {TLTextConcat.Signature, () => new TLTextConcat()}, + + {TLPageBlockUnsupported.Signature, () => new TLPageBlockUnsupported()}, + {TLPageBlockTitle.Signature, () => new TLPageBlockTitle()}, + {TLPageBlockSubtitle.Signature, () => new TLPageBlockSubtitle()}, + {TLPageBlockAuthorDate.Signature, () => new TLPageBlockAuthorDate()}, + {TLPageBlockHeader.Signature, () => new TLPageBlockHeader()}, + {TLPageBlockSubheader.Signature, () => new TLPageBlockSubheader()}, + {TLPageBlockParagraph.Signature, () => new TLPageBlockParagraph()}, + {TLPageBlockPreformatted.Signature, () => new TLPageBlockPreformatted()}, + {TLPageBlockFooter.Signature, () => new TLPageBlockFooter()}, + {TLPageBlockDivider.Signature, () => new TLPageBlockDivider()}, + {TLPageBlockAnchor.Signature, () => new TLPageBlockAnchor()}, + {TLPageBlockList.Signature, () => new TLPageBlockList()}, + {TLPageBlockBlockquote.Signature, () => new TLPageBlockBlockquote()}, + {TLPageBlockPullquote.Signature, () => new TLPageBlockPullquote()}, + {TLPageBlockPhoto.Signature, () => new TLPageBlockPhoto()}, + {TLPageBlockVideo.Signature, () => new TLPageBlockVideo()}, + {TLPageBlockCover.Signature, () => new TLPageBlockCover()}, + {TLPageBlockEmbed.Signature, () => new TLPageBlockEmbed()}, + {TLPageBlockEmbedPost.Signature, () => new TLPageBlockEmbedPost()}, + {TLPageBlockCollage.Signature, () => new TLPageBlockCollage()}, + {TLPageBlockSlideshow.Signature, () => new TLPageBlockSlideshow()}, + + {TLPagePart.Signature, () => new TLPagePart()}, + {TLPageFull.Signature, () => new TLPageFull()}, + + // layer 60 + {TLUpdatePhoneCall.Signature, () => new TLUpdatePhoneCall()}, + {TLConfig60.Signature, () => new TLConfig60()}, + {TLSendMessageGamePlayAction.Signature, () => new TLSendMessageGamePlayAction()}, + {TLInputPrivacyKeyPhoneCall.Signature, () => new TLInputPrivacyKeyPhoneCall()}, + {TLPrivacyKeyPhoneCall.Signature, () => new TLPrivacyKeyPhoneCall()}, + {TLInputPhoneCall.Signature, () => new TLInputPhoneCall()}, + {TLPhoneCallEmpty.Signature, () => new TLPhoneCallEmpty()}, + {TLPhoneCallWaiting.Signature, () => new TLPhoneCallWaiting()}, + {TLPhoneCallRequested.Signature, () => new TLPhoneCallRequested()}, + {TLPhoneCall.Signature, () => new TLPhoneCall()}, + {TLPhoneCallDiscarded.Signature, () => new TLPhoneCallDiscarded()}, + {TLPhoneConnection.Signature, () => new TLPhoneConnection()}, + {TLPhoneCallProtocol.Signature, () => new TLPhoneCallProtocol()}, + {TLPhonePhoneCall.Signature, () => new TLPhonePhoneCall()}, + + // layer 61 + {TLUpdateDialogPinned.Signature, () => new TLUpdateDialogPinned()}, + {TLUpdatePinnedDialogs.Signature, () => new TLUpdatePinnedDialogs()}, + {TLConfig61.Signature, () => new TLConfig61()}, + {TLPageBlockAuthorDate61.Signature, () => new TLPageBlockAuthorDate61()}, + {TLPageBlockEmbed61.Signature, () => new TLPageBlockEmbed61()}, + {TLPhoneCallDiscarded61.Signature, () => new TLPhoneCallDiscarded61()}, + {TLPhoneConnection61.Signature, () => new TLPhoneConnection61()}, + {TLPhoneCallDiscardReasonMissed.Signature, () => new TLPhoneCallDiscardReasonMissed()}, + {TLPhoneCallDiscardReasonDisconnect.Signature, () => new TLPhoneCallDiscardReasonDisconnect()}, + {TLPhoneCallDiscardReasonHangup.Signature, () => new TLPhoneCallDiscardReasonHangup()}, + {TLPhoneCallDiscardReasonBusy.Signature, () => new TLPhoneCallDiscardReasonBusy()}, + + // layer 62 + {TLMessageActionPhoneCall.Signature, () => new TLMessageActionPhoneCall()}, + {TLInputMessagesFilterPhoneCalls.Signature, () => new TLInputMessagesFilterPhoneCalls()}, + {TLUpdateBotWebhookJSON.Signature, () => new TLUpdateBotWebhookJSON()}, + {TLUpdateBotWebhookJSONQuery.Signature, () => new TLUpdateBotWebhookJSONQuery()}, + {TLDataJSON.Signature, () => new TLDataJSON()}, + + // layer 63 + {TLConfig63.Signature, () => new TLConfig63()}, + + // layer 64 + {TLInputMediaInvoice.Signature, () => new TLInputMediaInvoice()}, + {TLMessageMediaInvoice.Signature, () => new TLMessageMediaInvoice()}, + {TLMessageActionPaymentSentMe.Signature, () => new TLMessageActionPaymentSentMe()}, + {TLMessageActionPaymentSent.Signature, () => new TLMessageActionPaymentSent()}, + {TLUpdateBotShippingQuery.Signature, () => new TLUpdateBotShippingQuery()}, + {TLUpdateBotPrecheckoutQuery.Signature, () => new TLUpdateBotPrecheckoutQuery()}, + {TLKeyboardButtonBuy.Signature, () => new TLKeyboardButtonBuy()}, + + {TLLabeledPrice.Signature, () => new TLLabeledPrice()}, + {TLInvoice.Signature, () => new TLInvoice()}, + {TLPaymentCharge.Signature, () => new TLPaymentCharge()}, + {TLPostAddress.Signature, () => new TLPostAddress()}, + {TLPaymentRequestedInfo.Signature, () => new TLPaymentRequestedInfo()}, + {TLPaymentSavedCredentialsCard.Signature, () => new TLPaymentSavedCredentialsCard()}, + {TLWebDocument.Signature, () => new TLWebDocument()}, + {TLInputWebDocument.Signature, () => new TLInputWebDocument()}, + {TLInputWebFileLocation.Signature, () => new TLInputWebFileLocation()}, + {TLWebFile.Signature, () => new TLWebFile()}, + {TLPaymentForm.Signature, () => new TLPaymentForm()}, + {TLValidatedRequestedInfo.Signature, () => new TLValidatedRequestedInfo()}, + {TLPaymentResult.Signature, () => new TLPaymentResult()}, + {TLPaymentVerificationNeeded.Signature, () => new TLPaymentVerificationNeeded()}, + {TLPaymentReceipt.Signature, () => new TLPaymentReceipt()}, + {TLSavedInfo.Signature, () => new TLSavedInfo()}, + {TLInputPaymentCredentialsSaved.Signature, () => new TLInputPaymentCredentialsSaved()}, + {TLInputPaymentCredentials.Signature, () => new TLInputPaymentCredentials()}, + {TLTmpPassword.Signature, () => new TLTmpPassword()}, + {TLShippingOption.Signature, () => new TLShippingOption()}, + + {TLPhoneCallRequested64.Signature, () => new TLPhoneCallRequested64()}, + {TLPhoneCallAccepted.Signature, () => new TLPhoneCallAccepted()}, + + // layer 65, 66 + {TLUser66.Signature, () => new TLUser66()}, + {TLInputMessagesFilterRoundVideo.Signature, () => new TLInputMessagesFilterRoundVideo()}, + {TLInputMessagesFilterRoundVoice.Signature, () => new TLInputMessagesFilterRoundVoice()}, + {TLFileCdnRedirect.Signature, () => new TLFileCdnRedirect()}, + {TLSendMessageRecordRoundAction.Signature, () => new TLSendMessageRecordRoundAction()}, + {TLSendMessageUploadRoundAction.Signature, () => new TLSendMessageUploadRoundAction()}, + {TLSendMessageUploadRoundAction66.Signature, () => new TLSendMessageUploadRoundAction66()}, + {TLDocumentAttributeVideo66.Signature, () => new TLDocumentAttributeVideo66()}, + {TLPageBlockChannel.Signature, () => new TLPageBlockChannel()}, + {TLCdnConfig.Signature, () => new TLCdnConfig()}, + {TLCdnPublicKey.Signature, () => new TLCdnPublicKey()}, + {TLCdnFile.Signature, () => new TLCdnFile()}, + {TLCdnFileReuploadNeeded.Signature, () => new TLCdnFileReuploadNeeded()}, + + // layer 67 + {TLUpdateLangPackTooLong.Signature, () => new TLUpdateLangPackTooLong()}, + {TLUpdateLangPack.Signature, () => new TLUpdateLangPack()}, + {TLConfig67.Signature, () => new TLConfig67()}, + {TLLangPackString.Signature, () => new TLLangPackString()}, + {TLLangPackStringPluralized.Signature, () => new TLLangPackStringPluralized()}, + {TLLangPackStringDeleted.Signature, () => new TLLangPackStringDeleted()}, + {TLLangPackDifference.Signature, () => new TLLangPackDifference()}, + {TLLangPackLanguage.Signature, () => new TLLangPackLanguage()}, + + // layer 68 + {TLChannel68.Signature, () => new TLChannel68()}, + {TLChannelForbidden68.Signature, () => new TLChannelForbidden68()}, + {TLChannelFull68.Signature, () => new TLChannelFull68()}, + {TLChannelParticipantAdmin.Signature, () => new TLChannelParticipantAdmin()}, + {TLChannelParticipantBanned.Signature, () => new TLChannelParticipantBanned()}, + {TLChannelParticipantsKicked68.Signature, () => new TLChannelParticipantsKicked68()}, + {TLChannelParticipantsBanned.Signature, () => new TLChannelParticipantsBanned()}, + {TLChannelParticipantsSearch.Signature, () => new TLChannelParticipantsSearch()}, + {TLTopPeerCategoryPhoneCalls.Signature, () => new TLTopPeerCategoryPhoneCalls()}, + {TLPageBlockAudio.Signature, () => new TLPageBlockAudio()}, + {TLPagePart68.Signature, () => new TLPagePart68()}, + {TLPageFull68.Signature, () => new TLPageFull68()}, + {TLChannelAdminRights.Signature, () => new TLChannelAdminRights()}, + {TLChannelBannedRights.Signature, () => new TLChannelBannedRights()}, + {TLChannelAdminLogEventActionChangeTitle.Signature, () => new TLChannelAdminLogEventActionChangeTitle()}, + {TLChannelAdminLogEventActionChangeAbout.Signature, () => new TLChannelAdminLogEventActionChangeAbout()}, + {TLChannelAdminLogEventActionChangeUsername.Signature, () => new TLChannelAdminLogEventActionChangeUsername()}, + {TLChannelAdminLogEventActionChangePhoto.Signature, () => new TLChannelAdminLogEventActionChangePhoto()}, + {TLChannelAdminLogEventActionToggleInvites.Signature, () => new TLChannelAdminLogEventActionToggleInvites()}, + {TLChannelAdminLogEventActionToggleSignatures.Signature, () => new TLChannelAdminLogEventActionToggleSignatures()}, + {TLChannelAdminLogEventActionUpdatePinned.Signature, () => new TLChannelAdminLogEventActionUpdatePinned()}, + {TLChannelAdminLogEventActionEditMessage.Signature, () => new TLChannelAdminLogEventActionEditMessage()}, + {TLChannelAdminLogEventActionDeleteMessage.Signature, () => new TLChannelAdminLogEventActionDeleteMessage()}, + {TLChannelAdminLogEventActionParticipantJoin.Signature, () => new TLChannelAdminLogEventActionParticipantJoin()}, + {TLChannelAdminLogEventActionParticipantLeave.Signature, () => new TLChannelAdminLogEventActionParticipantLeave()}, + {TLChannelAdminLogEventActionParticipantInvite.Signature, () => new TLChannelAdminLogEventActionParticipantInvite()}, + {TLChannelAdminLogEventActionParticipantToggleBan.Signature, () => new TLChannelAdminLogEventActionParticipantToggleBan()}, + {TLChannelAdminLogEventActionParticipantToggleAdmin.Signature, () => new TLChannelAdminLogEventActionParticipantToggleAdmin()}, + {TLChannelAdminLogEvent.Signature, () => new TLChannelAdminLogEvent()}, + {TLAdminLogResults.Signature, () => new TLAdminLogResults()}, + {TLChannelAdminLogEventsFilter.Signature, () => new TLChannelAdminLogEventsFilter()}, + + // layer 69 + {TLPopularContact.Signature, () => new TLPopularContact()}, + {TLImportedContacts69.Signature, () => new TLImportedContacts69()}, + + // layer 70 + {TLInputMediaUploadedPhoto70.Signature, () => new TLInputMediaUploadedPhoto70()}, + {TLInputMediaPhoto70.Signature, () => new TLInputMediaPhoto70()}, + {TLInputMediaUploadedDocument70.Signature, () => new TLInputMediaUploadedDocument70()}, + {TLInputMediaDocument70.Signature, () => new TLInputMediaDocument70()}, + {TLInputMediaPhotoExternal70.Signature, () => new TLInputMediaPhotoExternal70()}, + {TLInputMediaDocumentExternal70.Signature, () => new TLInputMediaDocumentExternal70()}, + {TLMessage70.Signature, () => new TLMessage70()}, + {TLMessageMediaPhoto70.Signature, () => new TLMessageMediaPhoto70()}, + {TLMessageMediaDocument70.Signature, () => new TLMessageMediaDocument70()}, + {TLMessageActionScreenshotTaken.Signature, () => new TLMessageActionScreenshotTaken()}, + {TLFileCdnRedirect70.Signature, () => new TLFileCdnRedirect70()}, + {TLMessageFwdHeader70.Signature, () => new TLMessageFwdHeader70()}, + {TLCdnFileHash.Signature, () => new TLCdnFileHash()}, + + // layer 71 + {TLChannelFull71.Signature, () => new TLChannelFull71()}, + {TLDialog71.Signature, () => new TLDialog71()}, + {TLContacts71.Signature, () => new TLContacts71()}, + {TLInputMessagesFilterMyMentions.Signature, () => new TLInputMessagesFilterMyMentions()}, + {TLUpdateFavedStickers.Signature, () => new TLUpdateFavedStickers()}, + {TLUpdateChannelReadMessagesContents.Signature, () => new TLUpdateChannelReadMessagesContents()}, + {TLUpdateContactsReset.Signature, () => new TLUpdateContactsReset()}, + {TLConfig71.Signature, () => new TLConfig71()}, + {TLChannelDifferenceTooLong71.Signature, () => new TLChannelDifferenceTooLong71()}, + {TLChannelAdminLogEventActionChangeStickerSet.Signature, () => new TLChannelAdminLogEventActionChangeStickerSet()}, + {TLFavedStickersNotModified.Signature, () => new TLFavedStickersNotModified()}, + {TLFavedStickers.Signature, () => new TLFavedStickers()}, + + // layer 72 + {TLInputMediaVenue72.Signature, () => new TLInputMediaVenue72()}, + {TLInputMediaGeoLive.Signature, () => new TLInputMediaGeoLive()}, + {TLChannelFull72.Signature, () => new TLChannelFull72()}, + {TLMessageMediaVenue72.Signature, () => new TLMessageMediaVenue72()}, + {TLMessageMediaGeoLive.Signature, () => new TLMessageMediaGeoLive()}, + {TLMessageActionCustomAction.Signature, () => new TLMessageActionCustomAction()}, + {TLInputMessagesFilterGeo.Signature, () => new TLInputMessagesFilterGeo()}, + {TLInputMessagesFilterContacts.Signature, () => new TLInputMessagesFilterContacts()}, + {TLUpdateChannelAvailableMessages.Signature, () => new TLUpdateChannelAvailableMessages()}, + {TLConfig72.Signature, () => new TLConfig72()}, + {TLBotResults72.Signature, () => new TLBotResults72()}, + {TLInputPaymentCredentialsApplePay.Signature, () => new TLInputPaymentCredentialsApplePay()}, + {TLInputPaymentCredentialsAndroidPay.Signature, () => new TLInputPaymentCredentialsAndroidPay()}, + {TLChannelAdminLogEventActionTogglePreHistoryHidden.Signature, () => new TLChannelAdminLogEventActionTogglePreHistoryHidden()}, + {TLRecentMeUrlUnknown.Signature, () => new TLRecentMeUrlUnknown()}, + {TLRecentMeUrlUser.Signature, () => new TLRecentMeUrlUser()}, + {TLRecentMeUrlChat.Signature, () => new TLRecentMeUrlChat()}, + {TLRecentMeUrlChatInvite.Signature, () => new TLRecentMeUrlChatInvite()}, + {TLRecentMeUrlStickerSet.Signature, () => new TLRecentMeUrlStickerSet()}, + {TLRecentMeUrls.Signature, () => new TLRecentMeUrls()}, + {TLChannelParticipantsNotModified.Signature, () => new TLChannelParticipantsNotModified()}, + + // layer 73 + {TLChannel73.Signature, () => new TLChannel73()}, + {TLMessage73.Signature, () => new TLMessage73()}, + {TLMessageFwdHeader73.Signature, () => new TLMessageFwdHeader73()}, + {TLInputMediaInvoice73.Signature, () => new TLInputMediaInvoice73()}, + {TLInputSingleMedia.Signature, () => new TLInputSingleMedia()}, + + // layer 74 + {TLContactsFound74.Signature, () => new TLContactsFound74()}, + {TLExportedMessageLink74.Signature, () => new TLExportedMessageLink74()}, + {TLInputPaymentCredentialsAndroidPay74.Signature, () => new TLInputPaymentCredentialsAndroidPay74()}, + + // layer 75 + {TLInputMediaUploadedPhoto75.Signature, () => new TLInputMediaUploadedPhoto75()}, + {TLInputMediaPhoto75.Signature, () => new TLInputMediaPhoto75()}, + {TLInputMediaUploadedDocument75.Signature, () => new TLInputMediaUploadedDocument75()}, + {TLInputMediaDocument75.Signature, () => new TLInputMediaDocument75()}, + {TLInputMediaPhotoExternal75.Signature, () => new TLInputMediaPhotoExternal75()}, + {TLInputMediaDocumentExternal75.Signature, () => new TLInputMediaDocumentExternal75()}, + {TLMessageMediaPhoto75.Signature, () => new TLMessageMediaPhoto75()}, + {TLMessageMediaDocument75.Signature, () => new TLMessageMediaDocument75()}, + {TLInputBotInlineMessageMediaAuto75.Signature, () => new TLInputBotInlineMessageMediaAuto75()}, + {TLBotInlineMessageMediaAuto75.Signature, () => new TLBotInlineMessageMediaAuto75()}, + {TLInputSingleMedia75.Signature, () => new TLInputSingleMedia75()}, + + // layer 76 + {TLChannel76.Signature, () => new TLChannel76()}, + {TLDialogFeed.Signature, () => new TLDialogFeed()}, + {TLUpdateDialogPinned76.Signature, () => new TLUpdateDialogPinned76()}, + {TLUpdatePinnedDialogs76.Signature, () => new TLUpdatePinnedDialogs76()}, + {TLUpdateReadFeed.Signature, () => new TLUpdateReadFeed()}, + {TLStickerSet76.Signature, () => new TLStickerSet76()}, + {TLRecentStickers76.Signature, () => new TLRecentStickers76()}, + {TLFeedPosition.Signature, () => new TLFeedPosition()}, + {TLInputDialogPeerFeed.Signature, () => new TLInputDialogPeerFeed()}, + {TLInputDialogPeer.Signature, () => new TLInputDialogPeer()}, + {TLDialogPeerFeed.Signature, () => new TLDialogPeerFeed()}, + {TLDialogPeer.Signature, () => new TLDialogPeer()}, + {TLWebAuthorization.Signature, () => new TLWebAuthorization()}, + {TLWebAuthorizations.Signature, () => new TLWebAuthorizations()}, + {TLInputMessageId.Signature, () => new TLInputMessageId()}, + {TLInputMessageReplyTo.Signature, () => new TLInputMessageReplyTo()}, + {TLInputMessagePinned.Signature, () => new TLInputMessagePinned()}, + {TLInputSingleMedia76.Signature, () => new TLInputSingleMedia76()}, + {TLMessageEntityPhone.Signature, () => new TLMessageEntityPhone()}, + {TLMessageEntityCashtag.Signature, () => new TLMessageEntityCashtag()}, + {TLFeedMessagesNotModified.Signature, () => new TLFeedMessagesNotModified()}, + {TLFeedMessages.Signature, () => new TLFeedMessages()}, + {TLFeedBroadcastsUngrouped.Signature, () => new TLFeedBroadcastsUngrouped()}, + {TLFeedBroadcasts.Signature, () => new TLFeedBroadcasts()}, + {TLFeedSourcesNotModified.Signature, () => new TLFeedSourcesNotModified()}, + {TLFeedSources.Signature, () => new TLFeedSources()}, + {TLMessageActionBotAllowed.Signature, () => new TLMessageActionBotAllowed()}, + {TLPeerFeed.Signature, () => new TLPeerFeed()}, + {TLInputPeerFeed.Signature, () => new TLInputPeerFeed()}, + {TLConfig76.Signature, () => new TLConfig76()}, + {TLFoundStickerSetsNotModified.Signature, () => new TLFoundStickerSetsNotModified()}, + {TLFoundStickerSets.Signature, () => new TLFoundStickerSets()}, + {TLFileHash.Signature, () => new TLFileHash()}, + {TLFileCdnRedirect76.Signature, () => new TLFileCdnRedirect76()}, + {TLInputBotInlineResult76.Signature, () => new TLInputBotInlineResult76()}, + {TLBotInlineResult76.Signature, () => new TLBotInlineResult76()}, + {TLWebDocumentNoProxy.Signature, () => new TLWebDocumentNoProxy()}, + + // layer 77 + // layer 78 + {TLDCOption78.Signature, () => new TLDCOption78()}, + {TLConfig78.Signature, () => new TLConfig78()}, + {TLInputClientProxy.Signature, () => new TLInputClientProxy()}, + {TLProxyDataEmpty.Signature, () => new TLProxyDataEmpty()}, + {TLProxyDataPromo.Signature, () => new TLProxyDataPromo()}, + + // layer 79 + {TLStickers79.Signature, () => new TLStickers79()}, + {TLPeerNotifySettings78.Signature, () => new TLPeerNotifySettings78()}, + {TLInputPeerNotifySettings78.Signature, () => new TLInputPeerNotifySettings78()}, + {TLBotInlineMessageMediaVenue78.Signature, () => new TLBotInlineMessageMediaVenue78()}, + {TLInputBotInlineMessageMediaVenue78.Signature, () => new TLInputBotInlineMessageMediaVenue78()}, + + // layer 80 + {TLSentCode80.Signature, () => new TLSentCode80()}, + {TLTermsOfService80.Signature, () => new TLTermsOfService80()}, + {TLTermsOfServiceUpdateEmpty.Signature, () => new TLTermsOfServiceUpdateEmpty()}, + {TLTermsOfServiceUpdate.Signature, () => new TLTermsOfServiceUpdate()}, + + // layer 81 + {TLInputSecureFileLocation.Signature, () => new TLInputSecureFileLocation()}, + {TLMessageActionSecureValuesSentMe.Signature, () => new TLMessageActionSecureValuesSentMe()}, + {TLMessageActionSecureValuesSent.Signature, () => new TLMessageActionSecureValuesSent()}, + {TLNoPassword81.Signature, () => new TLNoPassword81()}, + {TLPassword81.Signature, () => new TLPassword81()}, + {TLPasswordSettings81.Signature, () => new TLPasswordSettings81()}, + {TLPasswordInputSettings81.Signature, () => new TLPasswordInputSettings81()}, + {TLInputSecureFileUploaded.Signature, () => new TLInputSecureFileUploaded()}, + {TLInputSecureFile.Signature, () => new TLInputSecureFile()}, + {TLSecureFileEmpty.Signature, () => new TLSecureFileEmpty()}, + {TLSecureFile.Signature, () => new TLSecureFile()}, + {TLSecureData.Signature, () => new TLSecureData()}, + {TLSecurePlainPhone.Signature, () => new TLSecurePlainPhone()}, + {TLSecurePlainEmail.Signature, () => new TLSecurePlainEmail()}, + {TLSecureValueTypePersonalDetails.Signature, () => new TLSecureValueTypePersonalDetails()}, + {TLSecureValueTypePassport.Signature, () => new TLSecureValueTypePassport()}, + {TLSecureValueTypeDriverLicense.Signature, () => new TLSecureValueTypeDriverLicense()}, + {TLSecureValueTypeIdentityCard.Signature, () => new TLSecureValueTypeIdentityCard()}, + {TLSecureValueTypeInternalPassport.Signature, () => new TLSecureValueTypeInternalPassport()}, + {TLSecureValueTypeAddress.Signature, () => new TLSecureValueTypeAddress()}, + {TLSecureValueTypeUtilityBill.Signature, () => new TLSecureValueTypeUtilityBill()}, + {TLSecureValueTypeBankStatement.Signature, () => new TLSecureValueTypeBankStatement()}, + {TLSecureValueTypeRentalAgreement.Signature, () => new TLSecureValueTypeRentalAgreement()}, + {TLSecureValueTypePassportRegistration.Signature, () => new TLSecureValueTypePassportRegistration()}, + {TLSecureValueTypeTemporaryRegistration.Signature, () => new TLSecureValueTypeTemporaryRegistration()}, + {TLSecureValueTypePhone.Signature, () => new TLSecureValueTypePhone()}, + {TLSecureValueTypeEmail.Signature, () => new TLSecureValueTypeEmail()}, + {TLSecureValue.Signature, () => new TLSecureValue()}, + {TLInputSecureValue.Signature, () => new TLInputSecureValue()}, + {TLSecureValueHash.Signature, () => new TLSecureValueHash()}, + {TLSecureValueErrorData.Signature, () => new TLSecureValueErrorData()}, + {TLSecureValueErrorFrontSide.Signature, () => new TLSecureValueErrorFrontSide()}, + {TLSecureValueErrorReverseSide.Signature, () => new TLSecureValueErrorReverseSide()}, + {TLSecureValueErrorSelfie.Signature, () => new TLSecureValueErrorSelfie()}, + {TLSecureValueErrorFile.Signature, () => new TLSecureValueErrorFile()}, + {TLSecureValueErrorFiles.Signature, () => new TLSecureValueErrorFiles()}, + {TLSecureCredentialsEncrypted.Signature, () => new TLSecureCredentialsEncrypted()}, + {TLAuthorizationForm.Signature, () => new TLAuthorizationForm()}, + {TLSentEmailCode.Signature, () => new TLSentEmailCode()}, + {TLDeepLinkInfoEmpty.Signature, () => new TLDeepLinkInfoEmpty()}, + {TLDeepLinkInfo.Signature, () => new TLDeepLinkInfo()}, + {TLSavedPhoneContact.Signature, () => new TLSavedPhoneContact()}, + {TLTakeout.Signature, () => new TLTakeout()}, + + // layer 82 + {TLInputTakeoutFileLocation.Signature, () => new TLInputTakeoutFileLocation()}, + {TLAppUpdate.Signature, () => new TLAppUpdate()}, + {TLNoAppUpdate.Signature, () => new TLNoAppUpdate()}, + {TLInputMediaContact82.Signature, () => new TLInputMediaContact82()}, + {TLMessageMediaContact82.Signature, () => new TLMessageMediaContact82()}, + {TLGeoPoint82.Signature, () => new TLGeoPoint82()}, + {TLDialogsNotModified.Signature, () => new TLDialogsNotModified()}, + {TLUpdateDialogUnreadMark.Signature, () => new TLUpdateDialogUnreadMark()}, + {TLConfig82.Signature, () => new TLConfig82()}, + {TLInputBotInlineMessageMediaContact82.Signature, () => new TLInputBotInlineMessageMediaContact82()}, + {TLBotInlineMessageMediaContact82.Signature, () => new TLBotInlineMessageMediaContact82()}, + {TLDraftMessageEmpty82.Signature, () => new TLDraftMessageEmpty82()}, + {TLWebDocument82.Signature, () => new TLWebDocument82()}, + {TLInputWebFileGeoPointLocation.Signature, () => new TLInputWebFileGeoPointLocation()}, + {TLInputReportReasonCopyright.Signature, () => new TLInputReportReasonCopyright()}, + {TLTopPeersDisabled.Signature, () => new TLTopPeersDisabled()}, + + // layer 83 + {TLPassword83.Signature, () => new TLPassword83()}, + {TLPasswordSettings83.Signature, () => new TLPasswordSettings83()}, + {TLPasswordInputSettings83.Signature, () => new TLPasswordInputSettings83()}, + {TLPasswordKdfAlgoUnknown.Signature, () => new TLPasswordKdfAlgoUnknown()}, + {TLSecurePasswordKdfAlgoUnknown.Signature, () => new TLSecurePasswordKdfAlgoUnknown()}, + {TLSecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000.Signature, () => new TLSecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000()}, + {TLSecurePasswordKdfAlgoSHA512.Signature, () => new TLSecurePasswordKdfAlgoSHA512()}, + {TLSecureSecretSettings.Signature, () => new TLSecureSecretSettings()}, + + // layer 84 + {TLPassword84.Signature, () => new TLPassword84()}, + {TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow.Signature, () => new TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow()}, + {TLInputCheckPasswordEmpty.Signature, () => new TLInputCheckPasswordEmpty()}, + {TLInputCheckPasswordSRP.Signature, () => new TLInputCheckPasswordSRP()}, + + // layer 85 + {TLSecureValue85.Signature, () => new TLSecureValue85()}, + {TLInputSecureValue85.Signature, () => new TLInputSecureValue85()}, + {TLSecureValueError.Signature, () => new TLSecureValueError()}, + {TLSecureValueErrorTranslationFile.Signature, () => new TLSecureValueErrorTranslationFile()}, + {TLSecureValueErrorTranslationFiles.Signature, () => new TLSecureValueErrorTranslationFiles()}, + {TLAuthorizationForm85.Signature, () => new TLAuthorizationForm85()}, + {TLSecureRequiredType.Signature, () => new TLSecureRequiredType()}, + {TLSecureRequiredTypeOneOf.Signature, () => new TLSecureRequiredTypeOneOf()}, + {TLPassportConfigNotModified.Signature, () => new TLPassportConfigNotModified()}, + {TLPassportConfig.Signature, () => new TLPassportConfig()}, + + // + {TLConfigSimple.Signature, () => new TLConfigSimple()}, + + //45 layer encrypted + {TLDecryptedMessage45.Signature, () => new TLDecryptedMessage45()}, + {TLDecryptedMessageMediaPhoto45.Signature, () => new TLDecryptedMessageMediaPhoto45()}, + {TLDecryptedMessageMediaVideo45.Signature, () => new TLDecryptedMessageMediaVideo45()}, + {TLDecryptedMessageMediaDocument45.Signature, () => new TLDecryptedMessageMediaDocument45()}, + {TLDecryptedMessageMediaVenue.Signature, () => new TLDecryptedMessageMediaVenue()}, + {TLDecryptedMessageMediaWebPage.Signature, () => new TLDecryptedMessageMediaWebPage()}, + + //73 layer encrypted + {TLDecryptedMessage73.Signature, () => new TLDecryptedMessage73()}, + + // functions + {TLSendMessage.Signature, () => new TLSendMessage()}, + {TLSendInlineBotResult.Signature, () => new TLSendInlineBotResult()}, + {TLSendMedia.Signature, () => new TLSendMedia()}, + {TLForwardMessage.Signature, () => new TLForwardMessage()}, + {TLForwardMessages.Signature, () => new TLForwardMessages()}, + {TLStartBot.Signature, () => new TLStartBot()}, + {TLReadHistory.Signature, () => new TLReadHistory()}, + {TLReadChannelHistory.Signature, () => new TLReadChannelHistory()}, + {Functions.Messages.TLReadMessageContents.Signature, () => new Functions.Messages.TLReadMessageContents()}, + {Functions.Channels.TLReadMessageContents.Signature, () => new Functions.Channels.TLReadMessageContents()}, + + {TLSendEncrypted.Signature, () => new TLSendEncrypted()}, + {TLSendEncryptedFile.Signature, () => new TLSendEncryptedFile()}, + {TLSendEncryptedService.Signature, () => new TLSendEncryptedService()}, + {TLReadEncryptedHistory.Signature, () => new TLReadEncryptedHistory()}, + + {TLInitConnection.Signature, () => new TLInitConnection()}, + {TLInitConnection67.Signature, () => new TLInitConnection67()}, + + // additional sigantures + {TLEncryptedDialog.Signature, () => new TLEncryptedDialog()}, + {TLUserExtendedInfo.Signature, () => new TLUserExtendedInfo()}, + {TLDecryptedMessageActionEmpty.Signature, () => new TLDecryptedMessageActionEmpty()}, + {TLPeerEncryptedChat.Signature, () => new TLPeerEncryptedChat()}, + {TLBroadcastChat.Signature, () => new TLBroadcastChat()}, + {TLPeerBroadcast.Signature, () => new TLPeerBroadcast()}, + {TLBroadcastDialog.Signature, () => new TLBroadcastDialog()}, + {TLInputPeerBroadcast.Signature, () => new TLInputPeerBroadcast()}, + {TLServerFile.Signature, () => new TLServerFile()}, + {TLEncryptedChat17.Signature, () => new TLEncryptedChat17()}, + {TLMessageActionUnreadMessages.Signature, () => new TLMessageActionUnreadMessages()}, + {TLMessagesContainter.Signature, () => new TLMessagesContainter()}, + {TLHashtagItem.Signature, () => new TLHashtagItem()}, + {TLMessageActionContactRegistered.Signature, () => new TLMessageActionContactRegistered()}, + {TLPasscodeParams.Signature, () => new TLPasscodeParams()}, + {TLRecentlyUsedSticker.Signature, () => new TLRecentlyUsedSticker()}, + {TLActionInfo.Signature, () => new TLActionInfo()}, + {TLResultInfo.Signature, () => new TLResultInfo()}, + {TLMessageActionMessageGroup.Signature, () => new TLMessageActionMessageGroup()}, + {TLMessageActionChannelJoined.Signature, () => new TLMessageActionChannelJoined()}, + {TLChatSettings.Signature, () => new TLChatSettings()}, + {TLDocumentExternal.Signature, () => new TLDocumentExternal()}, + {TLDecryptedMessagesContainter.Signature, () => new TLDecryptedMessagesContainter()}, + {TLCameraSettings.Signature, () => new TLCameraSettings()}, + {TLPhotoPickerSettings.Signature, () => new TLPhotoPickerSettings()}, + {TLProxyConfig.Signature, () => new TLProxyConfig()}, + {TLCallsSecurity.Signature, () => new TLCallsSecurity()}, + {TLStickerSetEmpty.Signature, () => new TLStickerSetEmpty()}, + {TLMessageMediaGroup.Signature, () => new TLMessageMediaGroup()}, + {TLDecryptedMessageMediaGroup.Signature, () => new TLDecryptedMessageMediaGroup()}, + {TLSecureFileUploaded.Signature, () => new TLSecureFileUploaded()}, + {TLProxyConfig76.Signature, () => new TLProxyConfig76()}, + {TLSocks5Proxy.Signature, () => new TLSocks5Proxy()}, + {TLMTProtoProxy.Signature, () => new TLMTProtoProxy()}, + {TLContactsSettings.Signature, () => new TLContactsSettings()}, + }; + + public static TimeSpan ElapsedClothedTypes; + + public static TimeSpan ElapsedBaredTypes; + + public static TimeSpan ElapsedVectorTypes; + + public static T GetObject(byte[] bytes, int position) where T : TLObject + { + + //var stopwatch = Stopwatch.StartNew(); + + // bared types + + + var stopwatch2 = Stopwatch.StartNew(); + try + { + + if (_baredTypes.ContainsKey(typeof (T))) + { + return (T) _baredTypes[typeof (T)].Invoke(); + } + } + catch (Exception ex) + { + Execute.ShowDebugMessage(ex.ToString()); + } + finally + { + ElapsedBaredTypes += stopwatch2.Elapsed; + } + + var stopwatch = Stopwatch.StartNew(); + uint signature = 0; + try + { + // clothed types + //var signatureBytes = bytes.SubArray(position, 4); + //Array.Reverse(signatureBytes); + signature = BitConverter.ToUInt32(bytes, position); + Func getInstance; + + + // exact matching + if (_clothedTypes.TryGetValue(signature, out getInstance)) + { + return (T)getInstance.Invoke(); + } + + + //// matching with removed leading 0 + //while (signature.StartsWith("0")) + //{ + // signature = signature.Remove(0, 1); + // if (_clothedTypes.TryGetValue("#" + signature, out getInstance)) + // { + // return (T)getInstance.Invoke(); + // } + //} + } + catch (Exception ex) + { + Execute.ShowDebugMessage(ex.ToString()); + } + finally + { + ElapsedClothedTypes += stopwatch.Elapsed; + } + + + + + var stopwatch3 = Stopwatch.StartNew(); + //throw new Exception("Signature exception"); + try + { + // TLVector + if (bytes.StartsWith(position, TLConstructors.TLVector)) + { + + + //TODO: remove workaround for TLRPCRESULT: TLVECTOR + if (typeof (T) == typeof (TLObject)) + { + Func getObject; + var internalSignature = BitConverter.ToUInt32(bytes, position + 8); + var length = BitConverter.ToInt32(bytes, position + 4); + if (length > 0) + { + if (_clothedTypes.TryGetValue(internalSignature, out getObject)) + { + var obj = getObject.Invoke(); + if (obj is TLUserBase) + { + return (T)Activator.CreateInstance(typeof(TLVector)); + } + } + } + + if (bytes.StartsWith(position + 8, TLConstructors.TLStickerSet) + || bytes.StartsWith(position + 8, TLConstructors.TLStickerSet32)) + { + return (T)Activator.CreateInstance(typeof(TLVector)); + } + else if (bytes.StartsWith(position + 8, TLConstructors.TLContactStatus19) + || bytes.StartsWith(position + 8, TLConstructors.TLContactStatus)) + { + return (T)Activator.CreateInstance(typeof(TLVector)); + } + else if (bytes.StartsWith(position + 8, TLConstructors.TLWallPaper) + || bytes.StartsWith(position + 8, TLConstructors.TLWallPaperSolid)) + { + return (T)Activator.CreateInstance(typeof(TLVector)); + } + else if (bytes.StartsWith(position + 8, TLConstructors.TLStickerSetCovered) + || bytes.StartsWith(position + 8, TLConstructors.TLStickerSetMultiCovered)) + { + return (T)Activator.CreateInstance(typeof(TLVector)); + } + else if (bytes.StartsWith(position + 8, TLConstructors.TLSecureValue) + || bytes.StartsWith(position + 8, TLConstructors.TLSecureValue85)) + { + return (T)Activator.CreateInstance(typeof(TLVector)); + } + TLUtils.WriteLine("TLVecto hack ", LogSeverity.Error); + return (T) Activator.CreateInstance(typeof(TLVector)); + } + else + { + return (T) Activator.CreateInstance(typeof (T)); + } + } + + } + catch (Exception ex) + { + Execute.ShowDebugMessage(ex.ToString()); + } + finally + { + ElapsedVectorTypes += stopwatch3.Elapsed; + } + + var signatureBytes = BitConverter.GetBytes(signature); + Array.Reverse(signatureBytes); + var signatureString = BitConverter.ToString(signatureBytes).Replace("-", string.Empty).ToLowerInvariant(); + if (typeof (T) == typeof (TLObject)) + { + var error = string.Format(" ERROR TLObjectGenerator: Cannot find signature #{0} ({1})\n\n{2}", signatureString, signature, GetStackTrace()); + TLUtils.WriteLine(error, LogSeverity.Error); + Logs.Log.Write(error); + Execute.ShowDebugMessage(error); + } + else + { + var error = string.Format(" ERROR TLObjectGenerator: Incorrect signature #{0} ({1}) for type {2}\n\n{3}", signatureString, signature, typeof(T), GetStackTrace()); + TLUtils.WriteLine(error, LogSeverity.Error); + Logs.Log.Write(error); + Execute.ShowDebugMessage(error); + } + + return null; + } + + public static string GetStackTrace() + { + try + { + var type = typeof(Environment); + foreach (var p in type.GetRuntimeProperties()) + { + if (p.Name == "StackTrace") + { + var v = p.GetValue(null, null); + + return v != null ? v.ToString() : null; + } + } + } + catch + { + + } + + return null; + } + + public static T GetNullableObject(Stream input) where T : TLObject + { + // clothed types + var signatureBytes = new byte[4]; + input.Read(signatureBytes, 0, 4); + uint signature = BitConverter.ToUInt32(signatureBytes, 0); + + if (signature == TLNull.Signature) return null; + + input.Position = input.Position - 4; + return GetObject(input); + } + + public static T GetObject(Stream input) where T : TLObject + { + //var startPosition = input.Position; + //var stopwatch = Stopwatch.StartNew(); + + // bared types + + + var stopwatch2 = Stopwatch.StartNew(); + try + { + + if (_baredTypes.ContainsKey(typeof(T))) + { + return (T)_baredTypes[typeof(T)].Invoke(); + } + } + catch (Exception ex) + { + Execute.ShowDebugMessage(ex.ToString()); + } + finally + { + ElapsedBaredTypes += stopwatch2.Elapsed; + } + + var stopwatch = Stopwatch.StartNew(); + uint signature = 0; + try + { + // clothed types + var signatureBytes = new byte[4]; + input.Read(signatureBytes, 0, 4); + signature = BitConverter.ToUInt32(signatureBytes, 0); + Func getInstance; + + + // exact matching + if (_clothedTypes.TryGetValue(signature, out getInstance)) + { + return (T)getInstance.Invoke(); + } + } + catch (Exception ex) + { + Execute.ShowDebugMessage(ex.ToString()); + } + finally + { + + ElapsedClothedTypes += stopwatch.Elapsed; + } + + + + + var stopwatch3 = Stopwatch.StartNew(); + //throw new Exception("Signature exception"); + try + { + // TLVector + if (signature == TLConstructors.TLVector) + { + //TODO: remove workaround for TLRPCRESULT: TLVECTOR + if (typeof(T) == typeof(TLObject)) + { + TLUtils.WriteLine("TLVecto hack ", LogSeverity.Error); + return (T)Activator.CreateInstance(typeof(TLVector)); + } + else + { + return (T)Activator.CreateInstance(typeof(T)); + } + } + + } + catch (Exception ex) + { + Execute.ShowDebugMessage(ex.ToString()); + } + finally + { + ElapsedVectorTypes += stopwatch3.Elapsed; + } + + var bytes = BitConverter.GetBytes(signature); + Array.Reverse(bytes); + var signatureString = BitConverter.ToString(bytes).Replace("-", string.Empty).ToLowerInvariant(); + if (typeof(T) == typeof(TLObject)) + { + var error = string.Format(" ERROR TLObjectGenerator FromStream: Cannot find signature #{0} ({1})\n\n{2}", signatureString, signature, GetStackTrace()); + TLUtils.WriteLine(error, LogSeverity.Error); + Execute.ShowDebugMessage(error); + } + else + { + var error = string.Format(" ERROR TLObjectGenerator FromStream: Incorrect signature #{0} ({1}) for type {2}\n\n{3}", signatureString, signature, typeof(T), GetStackTrace()); + + //var count = 0; + //while (input.Position < input.Length) + //{ + // input.Position = startPosition + count; + // var signatureBytes = new byte[4]; + // input.Read(signatureBytes, 0, 4); + // signature = BitConverter.ToUInt32(signatureBytes, 0); + // Func getInstance; + // if (_clothedTypes.TryGetValue(signature, out getInstance)) + // { + // var instance = getInstance.Invoke(); + // } + // count++; + //} + + TLUtils.WriteLine(error, LogSeverity.Error); + Execute.ShowDebugMessage(error); + } + + return null; + } + } +} diff --git a/Telegram.Api/TL/TLPQInnerData.cs b/Telegram.Api/TL/TLPQInnerData.cs new file mode 100755 index 0000000..9c6ae95 --- /dev/null +++ b/Telegram.Api/TL/TLPQInnerData.cs @@ -0,0 +1,58 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLPQInnerData : TLObject + { + public const uint Signature = TLConstructors.TLPQInnerData; + + public TLString PQ { get; set; } + + public TLString P { get; set; } + + public TLString Q { get; set; } + + public TLInt128 Nonce { get; set; } + + public TLInt128 ServerNonce { get; set; } + + public TLInt256 NewNonce { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PQ.ToBytes(), + P.ToBytes(), + Q.ToBytes(), + Nonce.ToBytes(), + ServerNonce.ToBytes(), + NewNonce.ToBytes()); + } + } + + public class TLPQInnerDataDC : TLPQInnerData + { + public new const uint Signature = TLConstructors.TLPQInnerDataDC; + + public TLInt DCId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PQ.ToBytes(), + P.ToBytes(), + Q.ToBytes(), + Nonce.ToBytes(), + ServerNonce.ToBytes(), + NewNonce.ToBytes(), + DCId.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLPage.cs b/Telegram.Api/TL/TLPage.cs new file mode 100755 index 0000000..5e35a5b --- /dev/null +++ b/Telegram.Api/TL/TLPage.cs @@ -0,0 +1,193 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLPageBase : TLObject + { + public TLVector Blocks { get; set; } + + public TLVector Photos { get; set; } + + public TLVector Documents { get; set; } + } + + public class TLPagePart : TLPageBase + { + public const uint Signature = TLConstructors.TLPagePart; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Blocks = GetObject>(bytes, ref position); + Photos = GetObject>(bytes, ref position); + Documents = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Blocks.ToBytes(), + Photos.ToBytes(), + Documents.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Blocks.ToStream(output); + Photos.ToStream(output); + Documents.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Blocks = GetObject>(input); + Photos = GetObject>(input); + Documents = GetObject>(input); + + return this; + } + } + + public class TLPagePart68 : TLPageBase + { + public const uint Signature = TLConstructors.TLPagePart68; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Blocks = GetObject>(bytes, ref position); + Photos = GetObject>(bytes, ref position); + Documents = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Blocks.ToBytes(), + Photos.ToBytes(), + Documents.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Blocks.ToStream(output); + Photos.ToStream(output); + Documents.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Blocks = GetObject>(input); + Photos = GetObject>(input); + Documents = GetObject>(input); + + return this; + } + } + + public class TLPageFull : TLPageBase + { + public const uint Signature = TLConstructors.TLPageFull; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Blocks = GetObject>(bytes, ref position); + Photos = GetObject>(bytes, ref position); + Documents = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Blocks.ToBytes(), + Photos.ToBytes(), + Documents.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Blocks.ToStream(output); + Photos.ToStream(output); + Documents.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Blocks = GetObject>(input); + Photos = GetObject>(input); + Documents = GetObject>(input); + + return this; + } + } + + public class TLPageFull68 : TLPageBase + { + public const uint Signature = TLConstructors.TLPageFull68; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Blocks = GetObject>(bytes, ref position); + Photos = GetObject>(bytes, ref position); + Documents = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Blocks.ToBytes(), + Photos.ToBytes(), + Documents.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Blocks.ToStream(output); + Photos.ToStream(output); + Documents.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Blocks = GetObject>(input); + Photos = GetObject>(input); + Documents = GetObject>(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPageBlock.cs b/Telegram.Api/TL/TLPageBlock.cs new file mode 100755 index 0000000..e995300 --- /dev/null +++ b/Telegram.Api/TL/TLPageBlock.cs @@ -0,0 +1,1134 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PageBlockVideoFlags + { + Autoplay = 0x1, // 0 + Loop = 0x2, // 1 + } + + [Flags] + public enum PageBlockEmbedFlags + { + FullWidth = 0x1, // 0 + Url = 0x2, // 1 + Html = 0x4, // 2 + AllowScrolling = 0x8, // 3 + PosterPhotoId = 0x10, // 4 + } + + public abstract class TLPageBlockBase : TLObject { } + + public class TLPageBlockUnsupported : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockUnsupported; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLPageBlockTitle : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockTitle; + + public TLRichTextBase Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + } + + public class TLPageBlockSubtitle : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockSubtitle; + + public TLRichTextBase Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + } + + public abstract class TLPageBlockPublishedDateBase : TLPageBlockBase + { + public TLInt PublishedDate { get; set; } + } + + public class TLPageBlockAuthorDate : TLPageBlockPublishedDateBase + { + public const uint Signature = TLConstructors.TLPageBlockAuthorDate; + + public TLString Author { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Author = GetObject(bytes, ref position); + PublishedDate = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Author.ToBytes(), + PublishedDate.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Author.ToStream(output); + PublishedDate.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Author = GetObject(input); + PublishedDate = GetObject(input); + + return this; + } + } + + public class TLPageBlockAuthorDate61 : TLPageBlockPublishedDateBase + { + public const uint Signature = TLConstructors.TLPageBlockAuthorDate61; + + public TLRichTextBase Author { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Author = GetObject(bytes, ref position); + PublishedDate = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Author.ToBytes(), + PublishedDate.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Author.ToStream(output); + PublishedDate.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Author = GetObject(input); + PublishedDate = GetObject(input); + + return this; + } + } + + public class TLPageBlockHeader : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockHeader; + + public TLRichTextBase Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + } + + public class TLPageBlockSubheader : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockSubheader; + + public TLRichTextBase Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + } + + public class TLPageBlockParagraph : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockParagraph; + + public TLRichTextBase Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + } + + public class TLPageBlockPreformatted : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockPreformatted; + + public TLRichTextBase Text { get; set; } + + public TLString Language { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + Language = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes(), + Language.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + Language.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + Language = GetObject(input); + + return this; + } + } + + public class TLPageBlockFooter : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockFooter; + + public TLRichTextBase Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + } + + public class TLPageBlockDivider : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockDivider; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLPageBlockAnchor : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockAnchor; + + public TLString Name { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Name = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Name.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Name.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Name = GetObject(input); + + return this; + } + } + + public class TLPageBlockList : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockList; + + public TLBool Ordered { get; set; } + + public TLVector Items { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Ordered = GetObject(bytes, ref position); + Items = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Ordered.ToBytes(), + Items.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Ordered.ToStream(output); + Items.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Ordered = GetObject(input); + Items = GetObject>(input); + + return this; + } + } + + public class TLPageBlockBlockquote : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockBlockquote; + + public TLRichTextBase Text { get; set; } + + public TLRichTextBase Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes(), + Caption.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + Caption.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + Caption = GetObject(input); + + return this; + } + } + + public class TLPageBlockPullquote : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockPullquote; + + public TLRichTextBase Text { get; set; } + + public TLRichTextBase Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes(), + Caption.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + Caption.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + Caption = GetObject(input); + + return this; + } + } + + public class TLPageBlockPhoto : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockPhoto; + + public TLLong PhotoId { get; set; } + + public TLRichTextBase Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhotoId = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhotoId.ToBytes(), + Caption.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + PhotoId.ToStream(output); + Caption.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + PhotoId = GetObject(input); + Caption = GetObject(input); + + return this; + } + } + + public class TLPageBlockVideo : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockVideo; + + public TLInt Flags { get; set; } + + public bool Autoplay { get { return IsSet(Flags, (int) PageBlockVideoFlags.Autoplay); } } + + public bool Loop { get { return IsSet(Flags, (int) PageBlockVideoFlags.Loop); } } + + public TLLong VideoId { get; set; } + + public TLRichTextBase Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + VideoId = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + VideoId.ToBytes(), + Caption.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + VideoId.ToStream(output); + Caption.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + VideoId = GetObject(input); + Caption = GetObject(input); + + return this; + } + } + + public class TLPageBlockCover : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockCover; + + public TLPageBlockBase Cover { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Cover = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Cover.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Cover.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Cover = GetObject(input); + + return this; + } + } + + public class TLPageBlockEmbed : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockEmbed; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool FullWidth { get { return IsSet(Flags, (int) PageBlockEmbedFlags.FullWidth); } } + + public bool AllowScrolling { get { return IsSet(Flags, (int) PageBlockEmbedFlags.AllowScrolling); } } + + protected TLString _url; + + public TLString Url + { + get { return _url; } + set { SetField(out _url, value, ref _flags, (int) PageBlockEmbedFlags.Url); } + } + + protected TLString _html; + + public TLString Html + { + get { return _html; } + set { SetField(out _html, value, ref _flags, (int) PageBlockEmbedFlags.Html); } + } + + public TLInt W { get; set; } + + public TLInt H { get; set; } + + public TLRichTextBase Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + _url = GetObject(Flags, (int) PageBlockEmbedFlags.Url, null, bytes, ref position); + _html = GetObject(Flags, (int) PageBlockEmbedFlags.Html, null, bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(Url, Flags, (int) PageBlockEmbedFlags.Url), + ToBytes(Html, Flags, (int) PageBlockEmbedFlags.Html), + W.ToBytes(), + H.ToBytes(), + Caption.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + ToStream(output, Url, Flags, (int) PageBlockEmbedFlags.Url); + ToStream(output, Html, Flags, (int) PageBlockEmbedFlags.Html); + W.ToStream(output); + H.ToStream(output); + Caption.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + _url = GetObject(Flags, (int) PageBlockEmbedFlags.Url, null, input); + _html = GetObject(Flags, (int) PageBlockEmbedFlags.Html, null, input); + W = GetObject(input); + H = GetObject(input); + Caption = GetObject(input); + + return this; + } + } + + public class TLPageBlockEmbed61 : TLPageBlockEmbed + { + public new const uint Signature = TLConstructors.TLPageBlockEmbed61; + + protected TLLong _posterPhotoId; + + public TLLong PosterPhotoId + { + get { return _posterPhotoId; } + set { SetField(out _posterPhotoId, value, ref _flags, (int) PageBlockEmbedFlags.PosterPhotoId); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + _url = GetObject(Flags, (int)PageBlockEmbedFlags.Url, null, bytes, ref position); + _html = GetObject(Flags, (int)PageBlockEmbedFlags.Html, null, bytes, ref position); + _posterPhotoId = GetObject(Flags, (int)PageBlockEmbedFlags.PosterPhotoId, null, bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(Url, Flags, (int)PageBlockEmbedFlags.Url), + ToBytes(Html, Flags, (int)PageBlockEmbedFlags.Html), + ToBytes(PosterPhotoId, Flags, (int)PageBlockEmbedFlags.PosterPhotoId), + W.ToBytes(), + H.ToBytes(), + Caption.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + ToStream(output, Url, Flags, (int)PageBlockEmbedFlags.Url); + ToStream(output, Html, Flags, (int)PageBlockEmbedFlags.Html); + ToStream(output, PosterPhotoId, Flags, (int)PageBlockEmbedFlags.PosterPhotoId); + W.ToStream(output); + H.ToStream(output); + Caption.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + _url = GetObject(Flags, (int)PageBlockEmbedFlags.Url, null, input); + _html = GetObject(Flags, (int)PageBlockEmbedFlags.Html, null, input); + _posterPhotoId = GetObject(Flags, (int)PageBlockEmbedFlags.PosterPhotoId, null, input); + W = GetObject(input); + H = GetObject(input); + Caption = GetObject(input); + + return this; + } + } + + public class TLPageBlockEmbedPost : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockEmbedPost; + + public TLString Url { get; set; } + + public TLLong WebPageId { get; set; } + + public TLLong AuthorPhotoId { get; set; } + + public TLString Author { get; set; } + + public TLInt Date { get; set; } + + public TLVector Blocks { get; set; } + + public TLRichTextBase Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + WebPageId = GetObject(bytes, ref position); + AuthorPhotoId = GetObject(bytes, ref position); + Author = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Blocks = GetObject>(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Url.ToBytes(), + WebPageId.ToBytes(), + AuthorPhotoId.ToBytes(), + Author.ToBytes(), + Date.ToBytes(), + Blocks.ToBytes(), + Caption.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Url.ToStream(output); + WebPageId.ToStream(output); + AuthorPhotoId.ToStream(output); + Author.ToStream(output); + Date.ToStream(output); + Blocks.ToStream(output); + Caption.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + WebPageId = GetObject(input); + AuthorPhotoId = GetObject(input); + Author = GetObject(input); + Date = GetObject(input); + Blocks = GetObject>(input); + Caption = GetObject(input); + + return this; + } + } + + public class TLPageBlockCollage : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockCollage; + + public TLVector Items { get; set; } + + public TLRichTextBase Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Items = GetObject>(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Items.ToBytes(), + Caption.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Items.ToStream(output); + Caption.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Items = GetObject>(input); + Caption = GetObject(input); + + return this; + } + } + + public class TLPageBlockSlideshow : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockSlideshow; + + public TLVector Items { get; set; } + + public TLRichTextBase Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Items = GetObject>(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Items.ToBytes(), + Caption.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Items.ToStream(output); + Caption.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Items = GetObject>(input); + Caption = GetObject(input); + + return this; + } + } + + public class TLPageBlockChannel : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockChannel; + + public TLChatBase Channel { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Channel = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Channel.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Channel.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Channel = GetObject(input); + + return this; + } + } + + public class TLPageBlockAudio : TLPageBlockBase + { + public const uint Signature = TLConstructors.TLPageBlockAudio; + + public TLLong AudioId { get; set; } + + public TLRichTextBase Caption { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + AudioId = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + AudioId.ToBytes(), + Caption.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + AudioId.ToStream(output); + Caption.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + AudioId = GetObject(input); + Caption = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPasscodeParams.cs b/Telegram.Api/TL/TLPasscodeParams.cs new file mode 100755 index 0000000..12766f9 --- /dev/null +++ b/Telegram.Api/TL/TLPasscodeParams.cs @@ -0,0 +1,73 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLPasscodeParams : TLObject + { + public const uint Signature = TLConstructors.TLPasscodeParams; + + public TLString Hash { get; set; } + public TLString Salt { get; set; } + public TLBool IsSimple { get; set; } + public TLInt CloseTime { get; set; } + public TLInt AutolockTimeout { get; set; } + public TLBool Locked { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + Salt = GetObject(bytes, ref position); + IsSimple = GetObject(bytes, ref position); + CloseTime = GetObject(bytes, ref position); + AutolockTimeout = GetObject(bytes, ref position); + Locked = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + Hash.ToBytes(), + Salt.ToBytes(), + IsSimple.ToBytes(), + CloseTime.ToBytes(), + AutolockTimeout.ToBytes(), + Locked.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Hash = GetObject(input); + Salt = GetObject(input); + IsSimple = GetObject(input); + CloseTime = GetObject(input); + AutolockTimeout = GetObject(input); + Locked = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Hash.ToStream(output); + Salt.ToStream(output); + IsSimple.ToStream(output); + CloseTime.ToStream(output); + AutolockTimeout.ToStream(output); + Locked.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLPassword.cs b/Telegram.Api/TL/TLPassword.cs new file mode 100755 index 0000000..9144c03 --- /dev/null +++ b/Telegram.Api/TL/TLPassword.cs @@ -0,0 +1,252 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PasswordFlags + { + HasRecovery = 0x1, // 0 + HasSecureValues = 0x2, // 1 + HasPassword = 0x4, // 2 + Hint = 0x8, // 3 + EmailUnconfirmedPattern = 0x10, // 4 + } + + public interface IPasswordSecret + { + TLString SecretRandom { get; set; } + + TLSecurePasswordKdfAlgoBase NewSecureAlgo { get; set; } + } + + public interface IPasswordSRPParams + { + TLString SRPB { get; set; } + + TLLong SRPId { get; set; } + + TLPasswordKdfAlgoBase CurrentAlgo { get; set; } + } + + public abstract class TLPasswordBase : TLObject + { + public TLString NewSalt { get; set; } + + public virtual TLString EmailUnconfirmedPattern { get; set; } + + public bool IsAvailable { get { return HasPassword || !TLString.IsNullOrEmpty(EmailUnconfirmedPattern); } } + + public bool IsAuthRecovery { get; set; } + + public abstract bool HasPassword { get; } + + public TLString CurrentPasswordHash { get; set; } + } + + public class TLPassword : TLPasswordBase + { + public const uint Signature = TLConstructors.TLPassword; + + public TLString CurrentSalt { get; set; } + + public virtual TLString Hint { get; set; } + + public virtual TLBool HasRecovery { get; set; } + + public override bool HasPassword { get { return true; } } + + #region Additional + + public TLPasswordSettings Settings { get; set; } + + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + CurrentSalt = GetObject(bytes, ref position); + NewSalt = GetObject(bytes, ref position); + Hint = GetObject(bytes, ref position); + HasRecovery = GetObject(bytes, ref position); + EmailUnconfirmedPattern = GetObject(bytes, ref position); + + return this; + } + } + + public class TLPassword81 : TLPassword + { + public new const uint Signature = TLConstructors.TLPassword81; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override TLBool HasRecovery + { + get { return new TLBool(IsSet(_flags, (int) PasswordFlags.HasRecovery)); } + set { SetUnset(ref _flags, value != null && value.Value, (int)PasswordFlags.HasRecovery); } + } + + public bool HasSecureValues + { + get { return IsSet(_flags, (int) PasswordFlags.HasSecureValues); } + } + + public TLString NewSecureSalt { get; set; } + + public TLString SecretRandom { get; set; } + + #region Additional + public TLString CurrentSecret { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + _flags = GetObject(bytes, ref position); + CurrentSalt = GetObject(bytes, ref position); + NewSalt = GetObject(bytes, ref position); + NewSecureSalt = GetObject(bytes, ref position); + SecretRandom = GetObject(bytes, ref position); + Hint = GetObject(bytes, ref position); + EmailUnconfirmedPattern = GetObject(bytes, ref position); + + return this; + } + } + + public class TLPassword83 : TLPassword81 + { + public new const uint Signature = TLConstructors.TLPassword83; + + public override bool HasPassword { get { return IsSet(_flags, (int)PasswordFlags.HasPassword); } } + + protected TLPasswordKdfAlgoBase _currentAlgo; + + public TLPasswordKdfAlgoBase CurrentAlgo + { + get { return _currentAlgo; } + set { SetField(out _currentAlgo, value, ref _flags, (int)PasswordFlags.HasPassword); } + } + + protected TLString _hint; + + public override TLString Hint + { + get { return _hint; } + set { SetField(out _hint, value, ref _flags, (int)PasswordFlags.Hint); } + } + + protected TLString _emailUnconfirmedPattern; + + public override TLString EmailUnconfirmedPattern + { + get { return _emailUnconfirmedPattern; } + set { SetField(out _emailUnconfirmedPattern, value, ref _flags, (int)PasswordFlags.EmailUnconfirmedPattern); } + } + + public TLPasswordKdfAlgoBase NewAlgo { get; set; } + + public TLSecurePasswordKdfAlgoBase NewSecureAlgo { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + _flags = GetObject(bytes, ref position); + _currentAlgo = GetObject(Flags, (int) PasswordFlags.HasPassword, null, bytes, ref position); + _hint = GetObject(Flags, (int)PasswordFlags.Hint, null, bytes, ref position); + _emailUnconfirmedPattern = GetObject(Flags, (int)PasswordFlags.EmailUnconfirmedPattern, null, bytes, ref position); + NewAlgo = GetObject(bytes, ref position); + NewSecureAlgo = GetObject(bytes, ref position); + SecretRandom = GetObject(bytes, ref position); + + return this; + } + } + + public class TLPassword84 : TLPassword83, IPasswordSecret, IPasswordSRPParams + { + public new const uint Signature = TLConstructors.TLPassword84; + + public TLString SRPB { get; set; } + + public TLLong SRPId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + _flags = GetObject(bytes, ref position); + _currentAlgo = GetObject(Flags, (int)PasswordFlags.HasPassword, null, bytes, ref position); + SRPB = GetObject(Flags, (int)PasswordFlags.HasPassword, null, bytes, ref position); + SRPId = GetObject(Flags, (int)PasswordFlags.HasPassword, null, bytes, ref position); + _hint = GetObject(Flags, (int)PasswordFlags.Hint, null, bytes, ref position); + _emailUnconfirmedPattern = GetObject(Flags, (int)PasswordFlags.EmailUnconfirmedPattern, null, bytes, ref position); + NewAlgo = GetObject(bytes, ref position); + NewSecureAlgo = GetObject(bytes, ref position); + SecretRandom = GetObject(bytes, ref position); + + return this; + } + } + + public class TLNoPassword : TLPasswordBase + { + public const uint Signature = TLConstructors.TLNoPassword; + + public override bool HasPassword { get { return false; } } + + #region Additional + + public TLPasswordSettings Settings { get; set; } + + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + NewSalt = GetObject(bytes, ref position); + EmailUnconfirmedPattern = GetObject(bytes, ref position); + + return this; + } + } + + public class TLNoPassword81 : TLNoPassword + { + public new const uint Signature = TLConstructors.TLNoPassword81; + + public TLString NewSecureSalt { get; set; } + + public TLString SecretRandom { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + NewSalt = GetObject(bytes, ref position); + NewSecureSalt = GetObject(bytes, ref position); + SecretRandom = GetObject(bytes, ref position); + EmailUnconfirmedPattern = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPasswordInputSettings.cs b/Telegram.Api/TL/TLPasswordInputSettings.cs new file mode 100755 index 0000000..3902e7d --- /dev/null +++ b/Telegram.Api/TL/TLPasswordInputSettings.cs @@ -0,0 +1,198 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PasswordInputSettingsFlags + { + Password = 0x1, + Email = 0x2, + NewSecureSecret = 0x4, + } + + public class TLPasswordInputSettings : TLObject + { + public const uint Signature = TLConstructors.TLPasswordInputSettings; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLString _newSalt; + + public virtual TLString NewSalt + { + get { return _newSalt; } + set { SetField(out _newSalt, value, ref _flags, (int)PasswordInputSettingsFlags.Password); } + } + + protected TLString _newPasswordHash; + + public TLString NewPasswordHash + { + get { return _newPasswordHash; } + set { SetField(out _newPasswordHash, value, ref _flags, (int)PasswordInputSettingsFlags.Password); } + } + + protected TLString _hint; + + public TLString Hint + { + get { return _hint; } + set { SetField(out _hint, value, ref _flags, (int)PasswordInputSettingsFlags.Password); } + } + + protected TLString _email; + + public TLString Email + { + get { return _email; } + set { SetField(out _email, value, ref _flags, (int)PasswordInputSettingsFlags.Email); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + NewSalt = GetObject(Flags, (int)PasswordInputSettingsFlags.Password, null, bytes, ref position); + NewPasswordHash = GetObject(Flags, (int)PasswordInputSettingsFlags.Password, null, bytes, ref position); + Hint = GetObject(Flags, (int)PasswordInputSettingsFlags.Password, null, bytes, ref position); + Email = GetObject(Flags, (int)PasswordInputSettingsFlags.Email, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(NewSalt, Flags, (int)PasswordInputSettingsFlags.Password), + ToBytes(NewPasswordHash, Flags, (int)PasswordInputSettingsFlags.Password), + ToBytes(Hint, Flags, (int)PasswordInputSettingsFlags.Password), + ToBytes(Email, Flags, (int)PasswordInputSettingsFlags.Email)); + } + } + + public class TLPasswordInputSettings81 : TLPasswordInputSettings + { + public new const uint Signature = TLConstructors.TLPasswordInputSettings81; + + private TLString _newSecureSalt; + + public virtual TLString NewSecureSalt + { + get { return _newSecureSalt; } + set { SetField(out _newSecureSalt, value, ref _flags, (int)PasswordInputSettingsFlags.NewSecureSecret); } + } + + private TLString _newSecureSecret; + + public virtual TLString NewSecureSecret + { + get { return _newSecureSecret; } + set { SetField(out _newSecureSecret, value, ref _flags, (int)PasswordInputSettingsFlags.NewSecureSecret); } + } + + private TLLong _newSecureSecretId; + + public virtual TLLong NewSecureSecretId + { + get { return _newSecureSecretId; } + set { SetField(out _newSecureSecretId, value, ref _flags, (int)PasswordInputSettingsFlags.NewSecureSecret); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + NewSalt = GetObject(Flags, (int)PasswordInputSettingsFlags.Password, null, bytes, ref position); + NewPasswordHash = GetObject(Flags, (int)PasswordInputSettingsFlags.Password, null, bytes, ref position); + Hint = GetObject(Flags, (int)PasswordInputSettingsFlags.Password, null, bytes, ref position); + Email = GetObject(Flags, (int)PasswordInputSettingsFlags.Email, null, bytes, ref position); + NewSecureSalt = GetObject(Flags, (int)PasswordInputSettingsFlags.NewSecureSecret, null, bytes, ref position); + NewSecureSecret = GetObject(Flags, (int)PasswordInputSettingsFlags.NewSecureSecret, null, bytes, ref position); + NewSecureSecretId = GetObject(Flags, (int)PasswordInputSettingsFlags.NewSecureSecret, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(NewSalt, Flags, (int)PasswordInputSettingsFlags.Password), + ToBytes(NewPasswordHash, Flags, (int)PasswordInputSettingsFlags.Password), + ToBytes(Hint, Flags, (int)PasswordInputSettingsFlags.Password), + ToBytes(Email, Flags, (int)PasswordInputSettingsFlags.Email), + ToBytes(NewSecureSalt, Flags, (int)PasswordInputSettingsFlags.NewSecureSecret), + ToBytes(NewSecureSecret, Flags, (int)PasswordInputSettingsFlags.NewSecureSecret), + ToBytes(NewSecureSecretId, Flags, (int)PasswordInputSettingsFlags.NewSecureSecret)); + } + } + + public class TLPasswordInputSettings83 : TLPasswordInputSettings81 + { + public new const uint Signature = TLConstructors.TLPasswordInputSettings83; + + private TLPasswordKdfAlgoBase _newAlgo; + + public TLPasswordKdfAlgoBase NewAlgo + { + get { return _newAlgo; } + set { SetField(out _newAlgo, value, ref _flags, (int)PasswordInputSettingsFlags.Password); } + } + + private TLSecureSecretSettings _newSecureSettings; + + public TLSecureSecretSettings NewSecureSettings + { + get { return _newSecureSettings; } + set { SetField(out _newSecureSettings, value, ref _flags, (int)PasswordInputSettingsFlags.NewSecureSecret); } + } + + #region Additional + public string NewPassword { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + _newAlgo = GetObject(Flags, (int)PasswordInputSettingsFlags.Password, null, bytes, ref position); + _newPasswordHash = GetObject(Flags, (int)PasswordInputSettingsFlags.Password, null, bytes, ref position); + _hint = GetObject(Flags, (int)PasswordInputSettingsFlags.Password, null, bytes, ref position); + _email = GetObject(Flags, (int)PasswordInputSettingsFlags.Email, null, bytes, ref position); + _newSecureSettings = GetObject(Flags, (int)PasswordInputSettingsFlags.NewSecureSecret, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(NewAlgo, Flags, (int)PasswordInputSettingsFlags.Password), + ToBytes(NewPasswordHash, Flags, (int)PasswordInputSettingsFlags.Password), + ToBytes(Hint, Flags, (int)PasswordInputSettingsFlags.Password), + ToBytes(Email, Flags, (int)PasswordInputSettingsFlags.Email), + ToBytes(NewSecureSettings, Flags, (int)PasswordInputSettingsFlags.NewSecureSecret)); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLPasswordRecovery.cs b/Telegram.Api/TL/TLPasswordRecovery.cs new file mode 100755 index 0000000..39aa8dc --- /dev/null +++ b/Telegram.Api/TL/TLPasswordRecovery.cs @@ -0,0 +1,25 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLPasswordRecovery : TLObject + { + public const uint Signature = TLConstructors.TLPasswordRecovery; + + public TLString EmailPattern { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + EmailPattern = GetObject(bytes, ref position); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLPasswordSettings.cs b/Telegram.Api/TL/TLPasswordSettings.cs new file mode 100755 index 0000000..a07e898 --- /dev/null +++ b/Telegram.Api/TL/TLPasswordSettings.cs @@ -0,0 +1,98 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PasswordSettingsFlags + { + Email = 0x1, // 0 + SecureSettings = 0x2, // 1 + } + + public class TLPasswordSettings : TLObject + { + public const uint Signature = TLConstructors.TLPasswordSettings; + + public virtual TLString Email { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Email = GetObject(bytes, ref position); + + return this; + } + } + + public class TLPasswordSettings81 : TLPasswordSettings + { + public new const uint Signature = TLConstructors.TLPasswordSettings81; + + public TLString SecureSalt { get; set; } + + public TLString SecureSecret { get; set; } + + public TLLong SecureSecretId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Email = GetObject(bytes, ref position); + SecureSalt = GetObject(bytes, ref position); + SecureSecret = GetObject(bytes, ref position); + SecureSecretId = GetObject(bytes, ref position); + + return this; + } + } + + public class TLPasswordSettings83 : TLPasswordSettings81 + { + public new const uint Signature = TLConstructors.TLPasswordSettings83; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + protected TLString _email; + + public override TLString Email + { + get { return _email; } + set { SetField(out _email, value, ref _flags, (int)PasswordSettingsFlags.Email); } + } + + protected TLSecureSecretSettings _secureSettings; + + public TLSecureSecretSettings SecureSettings + { + get { return _secureSettings; } + set { SetField(out _secureSettings, value, ref _flags, (int)PasswordSettingsFlags.SecureSettings); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + _flags = GetObject(bytes, ref position); + _email = GetObject(Flags, (int)PasswordSettingsFlags.Email, null, bytes, ref position); + _secureSettings = GetObject(Flags, (int)PasswordSettingsFlags.SecureSettings, null, bytes, ref position); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLPaymentCharge.cs b/Telegram.Api/TL/TLPaymentCharge.cs new file mode 100755 index 0000000..0b02f67 --- /dev/null +++ b/Telegram.Api/TL/TLPaymentCharge.cs @@ -0,0 +1,44 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; + +namespace Telegram.Api.TL +{ + public class TLPaymentCharge : TLObject + { + public const uint Signature = TLConstructors.TLPaymentCharge; + + public TLString Id { get; set; } + + public TLString ProviderChargeId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + ProviderChargeId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + ProviderChargeId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + Id.ToStream(output); + ProviderChargeId.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLPaymentForm.cs b/Telegram.Api/TL/TLPaymentForm.cs new file mode 100755 index 0000000..d35a832 --- /dev/null +++ b/Telegram.Api/TL/TLPaymentForm.cs @@ -0,0 +1,120 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PaymentFormFlags + { + SavedInfo = 0x1, // 0 + SavedCredentials = 0x2, // 1 + CanSaveCredentials = 0x4, // 2 + PasswordMissing = 0x8, // 3 + Native = 0x10, // 4 + } + + public class TLPaymentForm : TLObject + { + public const uint Signature = TLConstructors.TLPaymentForm; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool CanSaveCredentials + { + get { return IsSet(Flags, (int) PaymentFormFlags.CanSaveCredentials); } + set { SetUnset(ref _flags, value, (int) PaymentFormFlags.CanSaveCredentials); } + } + + public bool PasswordMissing + { + get { return IsSet(Flags, (int) PaymentFormFlags.PasswordMissing); } + set { SetUnset(ref _flags, value, (int) PaymentFormFlags.PasswordMissing); } + } + + public TLInt BotId { get; set; } + + public TLInvoice Invoice { get; set; } + + public TLInt ProviderId { get; set; } + + public TLString Url { get; set; } + + private TLString _nativeProvider; + + public TLString NativeProvider + { + get { return _nativeProvider; } + set { SetField(out _nativeProvider, value, ref _flags, (int) PaymentFormFlags.Native); } + } + + private TLDataJSON _nativeParams; + + public TLDataJSON NativeParams + { + get { return _nativeParams; } + set { SetField(out _nativeParams, value, ref _flags, (int) PaymentFormFlags.Native); } + } + + private TLPaymentRequestedInfo _savedInfo; + + public TLPaymentRequestedInfo SavedInfo + { + get { return _savedInfo; } + set { SetField(out _savedInfo, value, ref _flags, (int) PaymentFormFlags.SavedInfo); } + } + + private TLPaymentSavedCredentials _savedCredentials; + + public TLPaymentSavedCredentials SavedCredentials + { + get { return _savedCredentials; } + set { SetField(out _savedCredentials, value, ref _flags, (int) PaymentFormFlags.SavedCredentials); } + } + + public TLVector Users { get; set; } + + public bool IsNativeProvider + { + get + { + if (TLString.Equals(NativeProvider, new TLString("stripe"), StringComparison.Ordinal) + && NativeParams != null) + { + return true; + } + + return false; + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + BotId = GetObject(bytes, ref position); + Invoice = GetObject(bytes, ref position); + ProviderId = GetObject(bytes, ref position); + Url = GetObject(bytes, ref position); + _nativeProvider = GetObject(Flags, (int) PaymentFormFlags.Native, null, bytes, ref position); + _nativeParams = GetObject(Flags, (int) PaymentFormFlags.Native, null, bytes, ref position); + _savedInfo = GetObject(Flags, (int) PaymentFormFlags.SavedInfo, null, bytes, ref position); + _savedCredentials = GetObject(Flags, (int) PaymentFormFlags.SavedCredentials, null, bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPaymentReceipt.cs b/Telegram.Api/TL/TLPaymentReceipt.cs new file mode 100755 index 0000000..359ec7a --- /dev/null +++ b/Telegram.Api/TL/TLPaymentReceipt.cs @@ -0,0 +1,82 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PaymentReceiptFlags + { + Info = 0x1, // 0 + Shipping = 0x2, // 1 + } + + public class TLPaymentReceipt : TLObject + { + public const uint Signature = TLConstructors.TLPaymentReceipt; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt Date { get; set; } + + public TLInt BotId { get; set; } + + public TLInvoice Invoice { get; set; } + + public TLInt ProviderId { get; set; } + + private TLPaymentRequestedInfo _info; + + public TLPaymentRequestedInfo SavedInfo + { + get { return _info; } + set { SetField(out _info, value, ref _flags, (int) PaymentReceiptFlags.Info); } + } + + private TLShippingOption _shipping; + + public TLShippingOption Shipping + { + get { return _shipping; } + set { SetField(out _shipping, value, ref _flags, (int) PaymentReceiptFlags.Shipping); } + } + + public TLString Currency { get; set; } + + public TLLong TotalAmount { get; set; } + + public TLString CredentialsTitle { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + BotId = GetObject(bytes, ref position); + Invoice = GetObject(bytes, ref position); + ProviderId = GetObject(bytes, ref position); + _info = GetObject(Flags, (int) PaymentReceiptFlags.Info, null, bytes, ref position); + _shipping = GetObject(Flags, (int) PaymentReceiptFlags.Shipping, null, bytes, ref position); + Currency = GetObject(bytes, ref position); + TotalAmount = GetObject(bytes, ref position); + CredentialsTitle = GetObject(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLPaymentRequestedInfo.cs b/Telegram.Api/TL/TLPaymentRequestedInfo.cs new file mode 100755 index 0000000..dce83e7 --- /dev/null +++ b/Telegram.Api/TL/TLPaymentRequestedInfo.cs @@ -0,0 +1,112 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PaymentRequestedInfoFlags + { + Name = 0x1, // 0 + Phone = 0x2, // 1 + Email = 0x4, // 2 + ShippingAddress = 0x8, // 3 + } + + public class TLPaymentRequestedInfo : TLObject + { + public const uint Signature = TLConstructors.TLPaymentRequestedInfo; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + protected TLString _name; + + public TLString Name + { + get { return _name; } + set { SetField(out _name, value, ref _flags, (int)PaymentRequestedInfoFlags.Name); } + } + + protected TLString _phone; + + public TLString Phone + { + get { return _phone; } + set { SetField(out _phone, value, ref _flags, (int)PaymentRequestedInfoFlags.Phone); } + } + + protected TLString _email; + + public TLString Email + { + get { return _email; } + set { SetField(out _email, value, ref _flags, (int)PaymentRequestedInfoFlags.Email); } + } + + protected TLPostAddress _shippingAddress; + + public TLPostAddress ShippingAddress + { + get { return _shippingAddress; } + set { SetField(out _shippingAddress, value, ref _flags, (int)PaymentRequestedInfoFlags.ShippingAddress); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + _name = GetObject(Flags, (int)PaymentRequestedInfoFlags.Name, null, bytes, ref position); + _phone = GetObject(Flags, (int)PaymentRequestedInfoFlags.Phone, null, bytes, ref position); + _email = GetObject(Flags, (int)PaymentRequestedInfoFlags.Email, null, bytes, ref position); + _shippingAddress = GetObject(Flags, (int)PaymentRequestedInfoFlags.ShippingAddress, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(Name, Flags, (int)PaymentRequestedInfoFlags.Name), + ToBytes(Phone, Flags, (int)PaymentRequestedInfoFlags.Phone), + ToBytes(Email, Flags, (int)PaymentRequestedInfoFlags.Email), + ToBytes(ShippingAddress, Flags, (int)PaymentRequestedInfoFlags.ShippingAddress)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + _name = GetObject(Flags, (int)PaymentRequestedInfoFlags.Name, null, input); + _phone = GetObject(Flags, (int)PaymentRequestedInfoFlags.Phone, null, input); + _email = GetObject(Flags, (int)PaymentRequestedInfoFlags.Email, null, input); + _shippingAddress = GetObject(Flags, (int)PaymentRequestedInfoFlags.ShippingAddress, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, _name, Flags, (int)PaymentRequestedInfoFlags.Name); + ToStream(output, _phone, Flags, (int)PaymentRequestedInfoFlags.Phone); + ToStream(output, _email, Flags, (int)PaymentRequestedInfoFlags.Email); + ToStream(output, _shippingAddress, Flags, (int)PaymentRequestedInfoFlags.ShippingAddress); + } + } +} diff --git a/Telegram.Api/TL/TLPaymentResult.cs b/Telegram.Api/TL/TLPaymentResult.cs new file mode 100755 index 0000000..9efe6db --- /dev/null +++ b/Telegram.Api/TL/TLPaymentResult.cs @@ -0,0 +1,43 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLPaymentResultBase : TLObject { } + + public class TLPaymentResult : TLPaymentResultBase + { + public const uint Signature = TLConstructors.TLPaymentResult; + + public TLUpdatesBase Updates { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Updates = GetObject(bytes, ref position); + + return this; + } + } + + public class TLPaymentVerificationNeeded : TLPaymentResultBase + { + public const uint Signature = TLConstructors.TLPaymentVerificationNeeded; + + public TLString Url { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLPaymentSavedCredentialsCard.cs b/Telegram.Api/TL/TLPaymentSavedCredentialsCard.cs new file mode 100755 index 0000000..8658c58 --- /dev/null +++ b/Telegram.Api/TL/TLPaymentSavedCredentialsCard.cs @@ -0,0 +1,56 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLPaymentSavedCredentials : TLObject { } + + public class TLPaymentSavedCredentialsCard : TLPaymentSavedCredentials + { + public const uint Signature = TLConstructors.TLPaymentSavedCredentialsCard; + + public TLString Id { get; set; } + + public TLString Title { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Title.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Title = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(Title.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLPeer.cs b/Telegram.Api/TL/TLPeer.cs new file mode 100755 index 0000000..c73afeb --- /dev/null +++ b/Telegram.Api/TL/TLPeer.cs @@ -0,0 +1,252 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using System.Linq; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLPeerBase : TLObject + { + public TLInt Id { get; set; } + } + + public class TLPeerUser : TLPeerBase + { + public const uint Signature = TLConstructors.TLPeerUser; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + } + + public override string ToString() + { + return "UserId=" + Id; + } + } + + public class TLPeerChat : TLPeerBase + { + public const uint Signature = TLConstructors.TLPeerChat; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + } + + public override string ToString() + { + return "ChatId=" + Id; + } + } + + public class TLPeerEncryptedChat : TLPeerBase + { + public const uint Signature = TLConstructors.TLPeerEncryptedChat; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + } + + public override string ToString() + { + return "EncryptedChatId=" + Id; + } + } + + public class TLPeerBroadcast : TLPeerBase + { + public const uint Signature = TLConstructors.TLPeerBroadcastChat; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + } + + public override string ToString() + { + return "BroadcastChatId=" + Id; + } + } + + public class TLPeerChannel : TLPeerBase + { + public const uint Signature = TLConstructors.TLPeerChannel; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + } + + public override string ToString() + { + return "ChannelId=" + Id; + } + } + + public class TLPeerFeed : TLPeerBase + { + public const uint Signature = TLConstructors.TLPeerFeed; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + } + + public override string ToString() + { + return "FeedId=" + Id; + } + } +} diff --git a/Telegram.Api/TL/TLPeerDialogs.cs b/Telegram.Api/TL/TLPeerDialogs.cs new file mode 100755 index 0000000..f986068 --- /dev/null +++ b/Telegram.Api/TL/TLPeerDialogs.cs @@ -0,0 +1,48 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLPeerDialogs : TLObject + { + public const uint Signature = TLConstructors.TLPeerDialogs; + + public TLVector Dialogs { get; set; } + + public TLVector Messages { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public TLState State { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Dialogs = GetObject>(bytes, ref position); + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + State = GetObject(bytes, ref position); + + return this; + } + + public TLDialogsBase ToDialogs() + { + return new TLDialogs + { + Dialogs = Dialogs, + Messages = Messages, + Chats = Chats, + Users = Users + }; + } + } +} diff --git a/Telegram.Api/TL/TLPeerNotifyEvents.cs b/Telegram.Api/TL/TLPeerNotifyEvents.cs new file mode 100755 index 0000000..50720f0 --- /dev/null +++ b/Telegram.Api/TL/TLPeerNotifyEvents.cs @@ -0,0 +1,45 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Runtime.Serialization; + +namespace Telegram.Api.TL +{ + [KnownType(typeof(TLPeerNotifyEventsEmpty))] + [KnownType(typeof(TLPeerNotifyEventsAll))] + [DataContract] + public abstract class TLPeerNotifyEventsBase : TLObject { } + + [Obsolete] + [DataContract] + public class TLPeerNotifyEventsEmpty : TLPeerNotifyEventsBase + { + public const uint Signature = TLConstructors.TLPeerNotifyEventsEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + [Obsolete] + [DataContract] + public class TLPeerNotifyEventsAll : TLPeerNotifyEventsBase + { + public const uint Signature = TLConstructors.TLPeerNotifyEventsAll; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPeerNotifySettings.cs b/Telegram.Api/TL/TLPeerNotifySettings.cs new file mode 100755 index 0000000..5942994 --- /dev/null +++ b/Telegram.Api/TL/TLPeerNotifySettings.cs @@ -0,0 +1,220 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PeerNotifySettingsFlags + { + ShowPreviews = 0x1, // 0 + Silent = 0x2, // 1 + MuteUntil = 0x4, // 2 + Sound = 0x8, // 3 + } + + public abstract class TLPeerNotifySettingsBase : TLObject + { + #region Additional + public DateTime? LastNotificationTime { get; set; } + #endregion + } + + public class TLPeerNotifySettings78 : TLPeerNotifySettings48 + { + public new const uint Signature = TLConstructors.TLPeerNotifySettings78; + + protected TLBool _showPreviews; + + public override TLBool ShowPreviews + { + get { return _showPreviews; } + set { SetField(out _showPreviews, value, ref _flags, (int)PeerNotifySettingsFlags.ShowPreviews); } + } + + protected TLBool _silent; + + public override TLBool Silent + { + get { return _silent; } + set { SetField(out _silent, value, ref _flags, (int)PeerNotifySettingsFlags.Silent); } + } + + protected TLInt _muteUntil; + + public override TLInt MuteUntil + { + get { return _muteUntil; } + set { SetField(out _muteUntil, value, ref _flags, (int)PeerNotifySettingsFlags.MuteUntil); } + } + + protected TLString _sound; + + public override TLString Sound + { + get { return _sound; } + set { SetField(out _sound, value, ref _flags, (int)PeerNotifySettingsFlags.Sound); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + ShowPreviews = GetObject(Flags, (int)PeerNotifySettingsFlags.ShowPreviews, null, bytes, ref position); + Silent = GetObject(Flags, (int)PeerNotifySettingsFlags.Silent, null, bytes, ref position); + MuteUntil = GetObject(Flags, (int)PeerNotifySettingsFlags.MuteUntil, null, bytes, ref position); + Sound = GetObject(Flags, (int)PeerNotifySettingsFlags.Sound, null, bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + ShowPreviews = GetObject(Flags, (int)PeerNotifySettingsFlags.ShowPreviews, null, input); + Silent = GetObject(Flags, (int)PeerNotifySettingsFlags.Silent, null, input); + MuteUntil = GetObject(Flags, (int)PeerNotifySettingsFlags.MuteUntil, null, input); + Sound = GetObject(Flags, (int)PeerNotifySettingsFlags.Sound, null, input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + ToStream(output, ShowPreviews, Flags, (int)PeerNotifySettingsFlags.ShowPreviews); + ToStream(output, Silent, Flags, (int)PeerNotifySettingsFlags.Silent); + ToStream(output, MuteUntil, Flags, (int)PeerNotifySettingsFlags.MuteUntil); + ToStream(output, Sound, Flags, (int)PeerNotifySettingsFlags.Sound); + } + } + + public class TLPeerNotifySettings48 : TLPeerNotifySettings + { + public new const uint Signature = TLConstructors.TLPeerNotifySettings48; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override TLBool ShowPreviews + { + get { return new TLBool(IsSet(Flags, (int)PeerNotifySettingsFlags.ShowPreviews)); } + set { SetUnset(ref _flags, value != null && value.Value, (int)PeerNotifySettingsFlags.ShowPreviews); } + } + + public virtual TLBool Silent + { + get { return new TLBool(IsSet(Flags, (int)PeerNotifySettingsFlags.Silent)); } + set { SetUnset(ref _flags, value != null && value.Value, (int)PeerNotifySettingsFlags.Silent); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + MuteUntil = GetObject(bytes, ref position); + Sound = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + MuteUntil = GetObject(input); + Sound = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + output.Write(MuteUntil.ToBytes()); + output.Write(Sound.ToBytes()); + } + } + + public class TLPeerNotifySettings : TLPeerNotifySettingsBase + { + public const uint Signature = TLConstructors.TLPeerNotifySettings; + + public virtual TLInt MuteUntil { get; set; } + + public virtual TLString Sound { get; set; } + + public virtual TLBool ShowPreviews { get; set; } + + public TLInt EventsMask { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + MuteUntil = GetObject(bytes, ref position); + Sound = GetObject(bytes, ref position); + ShowPreviews = GetObject(bytes, ref position); + EventsMask = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + MuteUntil = GetObject(input); + Sound = GetObject(input); + ShowPreviews = GetObject(input); + EventsMask = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(MuteUntil.ToBytes()); + output.Write(Sound.ToBytes()); + output.Write(ShowPreviews.ToBytes()); + output.Write(EventsMask.ToBytes()); + } + } + + [Obsolete] + public class TLPeerNotifySettingsEmpty : TLPeerNotifySettingsBase + { + public const uint Signature = TLConstructors.TLPeerNotifySettingsEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLPeerSettings.cs b/Telegram.Api/TL/TLPeerSettings.cs new file mode 100755 index 0000000..a3371a8 --- /dev/null +++ b/Telegram.Api/TL/TLPeerSettings.cs @@ -0,0 +1,35 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PeerSettingsFlags + { + ReportSpam = 0x1, + } + + public class TLPeerSettings : TLObject + { + public const uint Signature = TLConstructors.TLPeerSettings; + + public TLInt Flags { get; set; } + + public bool ReportSpam { get { return IsSet(Flags, (int)PeerSettingsFlags.ReportSpam); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPhoneCall.cs b/Telegram.Api/TL/TLPhoneCall.cs new file mode 100755 index 0000000..9b9bf6b --- /dev/null +++ b/Telegram.Api/TL/TLPhoneCall.cs @@ -0,0 +1,610 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Org.BouncyCastle.Security; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PhoneCallWaitingFlags + { + ReceiveDate = 0x1, // 0 + } + + [Flags] + public enum PhoneCallDiscardedFlags + { + Reason = 0x1, // 0 + Duration = 0x2, // 1 + NeedDebug = 0x4, // 2 + NeedRating = 0x8, // 3 + } + + public abstract class TLPhoneCallBase : TLObject + { + public TLLong Id { get; set; } + } + + public interface IInputPhoneCall + { + TLLong Id { get; } + TLLong AccessHash { get; } + TLInputPhoneCall ToInputPhoneCall(); + } + + public class TLPhoneCallEmpty : TLPhoneCallBase + { + public const uint Signature = TLConstructors.TLPhoneCallEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLPhoneCallEmpty id={0}", Id); + } + } + + public class TLPhoneCallWaiting : TLPhoneCallBase, IInputPhoneCall + { + public const uint Signature = TLConstructors.TLPhoneCallWaiting; + + public TLInt Flags { get; set; } + + public TLLong AccessHash { get; set; } + + public TLInt Date { get; set; } + + public TLInt AdminId { get; set; } + + public TLInt ParticipantId { get; set; } + + public TLPhoneCallProtocol Protocol { get; set; } + + public TLInt ReceiveDate { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + AdminId = GetObject(bytes, ref position); + ParticipantId = GetObject(bytes, ref position); + Protocol = GetObject(bytes, ref position); + ReceiveDate = GetObject(Flags, (int) PhoneCallWaitingFlags.ReceiveDate, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + AccessHash.ToBytes(), + Date.ToBytes(), + AdminId.ToBytes(), + ParticipantId.ToBytes(), + Protocol.ToBytes(), + ToBytes(ReceiveDate, Flags, (int) PhoneCallWaitingFlags.ReceiveDate)); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Id.ToStream(output); + AccessHash.ToStream(output); + Date.ToStream(output); + AdminId.ToStream(output); + ParticipantId.ToStream(output); + Protocol.ToStream(output); + ToStream(output, ReceiveDate, Flags, (int) PhoneCallWaitingFlags.ReceiveDate); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + AdminId = GetObject(input); + ParticipantId = GetObject(input); + Protocol = GetObject(input); + ReceiveDate = GetObject(Flags, (int) PhoneCallWaitingFlags.ReceiveDate, null, input); + + return this; + } + + public override string ToString() + { + return string.Format("TLPhoneCallWaiting flags={0} id={1} access_hash={2} date={3} admin_id={4} participant_id={5} protocol={6} receive_date={7}", Flags, Id, AccessHash, Date, AdminId, ParticipantId, Protocol, ReceiveDate); + } + + public TLInputPhoneCall ToInputPhoneCall() + { + return new TLInputPhoneCall { Id = Id, AccessHash = AccessHash }; + } + } + + public class TLPhoneCallRequestedBase : TLPhoneCallBase, IInputPhoneCall + { + public TLLong AccessHash { get; set; } + + public TLInt Date { get; set; } + + public TLInt AdminId { get; set; } + + public TLInt ParticipantId { get; set; } + + public TLPhoneCallProtocol Protocol { get; set; } + + public TLInputPhoneCall ToInputPhoneCall() + { + return new TLInputPhoneCall { Id = Id, AccessHash = AccessHash }; + } + } + + public class TLPhoneCallRequested64 : TLPhoneCallRequestedBase + { + public const uint Signature = TLConstructors.TLPhoneCallRequested64; + + public TLString GAHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + AdminId = GetObject(bytes, ref position); + ParticipantId = GetObject(bytes, ref position); + GAHash = GetObject(bytes, ref position); + Protocol = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + Date.ToBytes(), + AdminId.ToBytes(), + ParticipantId.ToBytes(), + GAHash.ToBytes(), + Protocol.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + AccessHash.ToStream(output); + Date.ToStream(output); + AdminId.ToStream(output); + ParticipantId.ToStream(output); + GAHash.ToStream(output); + Protocol.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + AdminId = GetObject(input); + ParticipantId = GetObject(input); + GAHash = GetObject(input); + Protocol = GetObject(input); + + return this; + } + + public override string ToString() + { + return string.Format("TLPhoneCallRequested id={0} access_hash={1} date={2} admin_id={3} participant_id={4} protocol={5}", Id, AccessHash, Date, AdminId, ParticipantId, Protocol); + } + } + + public class TLPhoneCallRequested : TLPhoneCallRequestedBase + { + public const uint Signature = TLConstructors.TLPhoneCallRequested; + + public TLString GA { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + AdminId = GetObject(bytes, ref position); + ParticipantId = GetObject(bytes, ref position); + GA = GetObject(bytes, ref position); + Protocol = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + Date.ToBytes(), + AdminId.ToBytes(), + ParticipantId.ToBytes(), + GA.ToBytes(), + Protocol.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + AccessHash.ToStream(output); + Date.ToStream(output); + AdminId.ToStream(output); + ParticipantId.ToStream(output); + GA.ToStream(output); + Protocol.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + AdminId = GetObject(input); + ParticipantId = GetObject(input); + GA = GetObject(input); + Protocol = GetObject(input); + + return this; + } + } + + public class TLPhoneCall : TLPhoneCallBase, IInputPhoneCall + { + public const uint Signature = TLConstructors.TLPhoneCall; + + public TLLong AccessHash { get; set; } + + public TLInt Date { get; set; } + + public TLInt AdminId { get; set; } + + public TLInt ParticipantId { get; set; } + + public TLString GAorB { get; set; } + + public TLLong KeyFingerprint { get; set; } + + public TLPhoneCallProtocol Protocol { get; set; } + + public TLPhoneConnection Connection { get; set; } + + public TLVector AlternativeConnections { get; set; } + + public TLInt StartDate { get; set; } + + public override string ToString() + { + return string.Format("TLPhoneCall id={0} access_hash={1} date={2} admin_id={3} participant_id={4} protocol={5} start_date={6}", Id, AccessHash, Date, AdminId, ParticipantId, Protocol, StartDate); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + AdminId = GetObject(bytes, ref position); + ParticipantId = GetObject(bytes, ref position); + GAorB = GetObject(bytes, ref position); + KeyFingerprint = GetObject(bytes, ref position); + Protocol = GetObject(bytes, ref position); + Connection = GetObject(bytes, ref position); + AlternativeConnections = GetObject>(bytes, ref position); + StartDate = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + Date.ToBytes(), + AdminId.ToBytes(), + ParticipantId.ToBytes(), + GAorB.ToBytes(), + KeyFingerprint.ToBytes(), + Protocol.ToBytes(), + Connection.ToBytes(), + AlternativeConnections.ToBytes(), + StartDate.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + AccessHash.ToStream(output); + Date.ToStream(output); + AdminId.ToStream(output); + ParticipantId.ToStream(output); + GAorB.ToStream(output); + KeyFingerprint.ToStream(output); + Protocol.ToStream(output); + Connection.ToStream(output); + AlternativeConnections.ToStream(output); + StartDate.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + AdminId = GetObject(input); + ParticipantId = GetObject(input); + GAorB = GetObject(input); + KeyFingerprint = GetObject(input); + Protocol = GetObject(input); + Connection = GetObject(input); + AlternativeConnections = GetObject>(input); + StartDate = GetObject(input); + + return this; + } + + public TLInputPhoneCall ToInputPhoneCall() + { + return new TLInputPhoneCall { Id = Id, AccessHash = AccessHash }; + } + } + + public class TLPhoneCallDiscarded : TLPhoneCallBase + { + public const uint Signature = TLConstructors.TLPhoneCallDiscarded; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + } + + public class TLPhoneCallDiscarded61 : TLPhoneCallDiscarded + { + public new const uint Signature = TLConstructors.TLPhoneCallDiscarded61; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLPhoneCallDiscardReasonBase Reason { get; set; } + + public TLInt Duration { get; set; } + + public bool NeedDebug + { + get { return IsSet(Flags, (int) PhoneCallDiscardedFlags.NeedDebug); } + set { SetUnset(ref _flags, value, (int) PhoneCallDiscardedFlags.NeedDebug); } + } + + public bool NeedRating + { + get { return IsSet(Flags, (int) PhoneCallDiscardedFlags.NeedRating); } + set { SetUnset(ref _flags, value, (int) PhoneCallDiscardedFlags.NeedRating); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + Reason = GetObject(Flags, (int) PhoneCallDiscardedFlags.Reason, null, bytes, ref position); + Duration = GetObject(Flags, (int) PhoneCallDiscardedFlags.Duration, null, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + ToBytes(Reason, Flags, (int) PhoneCallDiscardedFlags.Reason), + ToBytes(Duration, Flags, (int) PhoneCallDiscardedFlags.Duration)); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + Id.ToStream(output); + ToStream(output, Reason, Flags, (int) PhoneCallDiscardedFlags.Reason); + ToStream(output, Duration, Flags, (int) PhoneCallDiscardedFlags.Duration); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Reason = GetObject(Flags, (int) PhoneCallDiscardedFlags.Reason, null, input); + Duration = GetObject(Flags, (int) PhoneCallDiscardedFlags.Duration, null, input); + + return this; + } + + public override string ToString() + { + return string.Format("TLPhoneCallDiscarded id={0} reason={1} duration={2}", Id, Reason, Duration); + } + } + + public class TLPhoneCallAccepted : TLPhoneCallBase, IInputPhoneCall + { + public const uint Signature = TLConstructors.TLPhoneCallAccepted; + + public TLLong AccessHash { get; set; } + + public TLInt Date { get; set; } + + public TLInt AdminId { get; set; } + + public TLInt ParticipantId { get; set; } + + public TLPhoneCallProtocol Protocol { get; set; } + + public TLString GB { get; set; } + + public override string ToString() + { + return string.Format("TLPhoneAccepted id={0} access_hash={1} date={2} admin_id={3} participant_id={4} protocol={5}", Id, AccessHash, Date, AdminId, ParticipantId, Protocol); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + AdminId = GetObject(bytes, ref position); + ParticipantId = GetObject(bytes, ref position); + GB = GetObject(bytes, ref position); + Protocol = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + Date.ToBytes(), + AdminId.ToBytes(), + ParticipantId.ToBytes(), + GB.ToBytes(), + Protocol.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + AccessHash.ToStream(output); + Date.ToStream(output); + AdminId.ToStream(output); + ParticipantId.ToStream(output); + GB.ToStream(output); + Protocol.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + AdminId = GetObject(input); + ParticipantId = GetObject(input); + GB = GetObject(input); + Protocol = GetObject(input); + + return this; + } + + public TLInputPhoneCall ToInputPhoneCall() + { + return new TLInputPhoneCall { Id = Id, AccessHash = AccessHash }; + } + } +} diff --git a/Telegram.Api/TL/TLPhoneCallDiscardReason.cs b/Telegram.Api/TL/TLPhoneCallDiscardReason.cs new file mode 100755 index 0000000..a597a2e --- /dev/null +++ b/Telegram.Api/TL/TLPhoneCallDiscardReason.cs @@ -0,0 +1,122 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLPhoneCallDiscardReasonBase : TLObject { } + + public class TLPhoneCallDiscardReasonMissed : TLPhoneCallDiscardReasonBase + { + public const uint Signature = TLConstructors.TLPhoneCallDiscardReasonMissed; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLPhoneCallDiscardReasonDisconnect : TLPhoneCallDiscardReasonBase + { + public const uint Signature = TLConstructors.TLPhoneCallDiscardReasonDisconnect; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLPhoneCallDiscardReasonHangup : TLPhoneCallDiscardReasonBase + { + public const uint Signature = TLConstructors.TLPhoneCallDiscardReasonHangup; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLPhoneCallDiscardReasonBusy : TLPhoneCallDiscardReasonBase + { + public const uint Signature = TLConstructors.TLPhoneCallDiscardReasonBusy; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPhoneCallProtocol.cs b/Telegram.Api/TL/TLPhoneCallProtocol.cs new file mode 100755 index 0000000..74ad4a1 --- /dev/null +++ b/Telegram.Api/TL/TLPhoneCallProtocol.cs @@ -0,0 +1,92 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PhoneCallProtocolFlags + { + UdpP2P = 0x1, // 0 + UdpReflector = 0x2, // 1 + } + + public class TLPhoneCallProtocol : TLPhoneCallBase + { + public const uint Signature = TLConstructors.TLPhoneCallProtocol; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool UdpP2P + { + get { return IsSet(Flags, (int) PhoneCallProtocolFlags.UdpP2P); } + set { SetUnset(ref _flags, value, (int) PhoneCallProtocolFlags.UdpP2P); } + } + + public bool UdpReflector + { + get { return IsSet(Flags, (int) PhoneCallProtocolFlags.UdpReflector); } + set { SetUnset(ref _flags, value, (int) PhoneCallProtocolFlags.UdpReflector); } + } + + public TLInt MinLayer { get; set; } + + public TLInt MaxLayer { get; set; } + + public override string ToString() + { + return string.Format("TLPhoneCallProtocol min_layer={0} max_layer={1}", MinLayer, MaxLayer); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + MinLayer = GetObject(bytes, ref position); + MaxLayer = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + MinLayer.ToBytes(), + MaxLayer.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + MinLayer.ToStream(output); + MaxLayer.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + MinLayer = GetObject(input); + MaxLayer = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPhoneConnection.cs b/Telegram.Api/TL/TLPhoneConnection.cs new file mode 100755 index 0000000..aed9b6b --- /dev/null +++ b/Telegram.Api/TL/TLPhoneConnection.cs @@ -0,0 +1,120 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLPhoneConnection : TLObject + { + public const uint Signature = TLConstructors.TLPhoneConnection; + + public TLString Ip { get; set; } + + public TLString IpV6 { get; set; } + + public TLInt Port { get; set; } + + public TLString PeerTag { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Ip = GetObject(bytes, ref position); + IpV6 = GetObject(bytes, ref position); + Port = GetObject(bytes, ref position); + PeerTag = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Ip.ToBytes(), + IpV6.ToBytes(), + Port.ToBytes(), + PeerTag.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Ip.ToStream(output); + IpV6.ToStream(output); + Port.ToStream(output); + PeerTag.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Ip = GetObject(input); + IpV6 = GetObject(input); + Port = GetObject(input); + PeerTag = GetObject(input); + + return this; + } + } + + public class TLPhoneConnection61 : TLPhoneConnection + { + public new const uint Signature = TLConstructors.TLPhoneConnection61; + + public TLLong Id { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Ip = GetObject(bytes, ref position); + IpV6 = GetObject(bytes, ref position); + Port = GetObject(bytes, ref position); + PeerTag = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Ip.ToBytes(), + IpV6.ToBytes(), + Port.ToBytes(), + PeerTag.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Id.ToStream(output); + Ip.ToStream(output); + IpV6.ToStream(output); + Port.ToStream(output); + PeerTag.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Ip = GetObject(input); + IpV6 = GetObject(input); + Port = GetObject(input); + PeerTag = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPhonePhoneCall.cs b/Telegram.Api/TL/TLPhonePhoneCall.cs new file mode 100755 index 0000000..95806e8 --- /dev/null +++ b/Telegram.Api/TL/TLPhonePhoneCall.cs @@ -0,0 +1,55 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLPhonePhoneCall : TLObject + { + public const uint Signature = TLConstructors.TLPhonePhoneCall; + + public TLPhoneCallBase PhoneCall { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhoneCall = GetObject(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneCall.ToBytes(), + Users.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + PhoneCall.ToStream(output); + Users.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + PhoneCall = GetObject(input); + Users = GetObject>(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPhoto.cs b/Telegram.Api/TL/TLPhoto.cs new file mode 100755 index 0000000..d78b641 --- /dev/null +++ b/Telegram.Api/TL/TLPhoto.cs @@ -0,0 +1,492 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using System.Linq; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PhotoFlags + { + HasStickers = 0x1 + } + + public abstract class TLPhotoBase : TLObject + { + public abstract void Update(TLPhotoBase photo); + + public TLPhotoBase Self{ get { return this; } } + } + + public abstract class TLPhotoCommon : TLPhotoBase + { + public TLFileLocationBase PhotoSmall { get; set; } + + public TLFileLocationBase PhotoBig { get; set; } + + public override void Update(TLPhotoBase photo) + { + var photoCommon = photo as TLPhotoCommon; + if (photoCommon != null) + { + if (PhotoSmall != null) + { + PhotoSmall.Update(photoCommon.PhotoSmall); + } + else + { + PhotoSmall = photoCommon.PhotoSmall; + } + if (PhotoBig != null) + { + PhotoBig.Update(photoCommon.PhotoBig); + } + else + { + PhotoBig = photoCommon.PhotoBig; + } + } + } + } + + public abstract class TLMediaPhotoBase : TLPhotoBase + { + public TLLong Id { get; set; } + + public override void Update(TLPhotoBase photo) + { + var mediaPhoto = photo as TLMediaPhotoBase; + if (mediaPhoto != null) + { + Id = mediaPhoto.Id; + } + } + } + + public class TLPhotoEmpty : TLMediaPhotoBase + { + public const uint Signature = TLConstructors.TLPhotoEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + } + } + + public class TLPhoto56 : TLPhoto33 + { + public new const uint Signature = TLConstructors.TLPhoto56; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool HasStickers + { + get { return IsSet(Flags, (int) PhotoFlags.HasStickers); } + set { SetUnset(ref _flags, value, (int) PhotoFlags.HasStickers); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Sizes = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + Sizes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Date.ToBytes()); + Sizes.ToStream(output); + } + } + + public class TLPhoto33 : TLPhoto28 + { + public new const uint Signature = TLConstructors.TLPhoto33; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Sizes = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Date = GetObject(input); + Sizes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Date.ToBytes()); + Sizes.ToStream(output); + } + } + + public class TLPhoto28 : TLPhoto + { + public new const uint Signature = TLConstructors.TLPhoto28; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Geo = GetObject(bytes, ref position); + Sizes = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + UserId = GetObject(input); + Date = GetObject(input); + Geo = GetObject(input); + Sizes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(UserId.ToBytes()); + output.Write(Date.ToBytes()); + Geo.ToStream(output); + Sizes.ToStream(output); + } + + public override void Update(TLPhotoBase photo) + { + var p = photo as TLPhoto28; + if (p != null) + { + base.Update(p); + + AccessHash = p.AccessHash; + UserId = p.UserId; + Date = p.Date; + Caption = p.Caption; + Geo = p.Geo; + + if (AccessHash.Value != p.AccessHash.Value) + { + Sizes = p.Sizes; + } + else + { + for (var i = 0; i < Sizes.Count; i++) + { + Sizes[i].Update(p.Sizes[i]); + } + } + } + } + } + + public class TLPhoto : TLMediaPhotoBase + { + public const uint Signature = TLConstructors.TLPhoto; + + public TLLong AccessHash { get; set; } + + public TLInt UserId { get; set; } + + public TLInt Date { get; set; } + + public TLString Caption { get; set; } + + public TLGeoPointBase Geo { get; set; } + + public TLVector Sizes { get; set; } + + public string GetFileName() + { + var photoSize = Sizes.FirstOrDefault() as TLPhotoSize; + if (photoSize != null) + { + var fileLocation = photoSize.Location; + if (fileLocation == null) return null; + + var fileName = String.Format("{0}_{1}_{2}.jpg", + fileLocation.VolumeId, + fileLocation.LocalId, + fileLocation.Secret); + + return fileName; + } + + return null; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + Geo = GetObject(bytes, ref position); + Sizes = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + UserId = GetObject(input); + Date = GetObject(input); + Caption = GetObject(input); + Geo = GetObject(input); + Sizes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(UserId.ToBytes()); + output.Write(Date.ToBytes()); + output.Write(Caption.ToBytes()); + Geo.ToStream(output); + Sizes.ToStream(output); + } + + public override void Update(TLPhotoBase photo) + { + var p = photo as TLPhoto; + if (p != null) + { + base.Update(p); + + AccessHash = p.AccessHash; + UserId = p.UserId; + Date = p.Date; + Caption = p.Caption; + Geo = p.Geo; + + if (AccessHash.Value != p.AccessHash.Value) + { + Sizes = p.Sizes; + } + else + { + for (var i = 0; i < Sizes.Count; i++) + { + Sizes[i].Update(p.Sizes[i]); + } + } + } + } + + public TLPhotoCachedSize CachedSize + { + get + { + return Sizes != null ? (TLPhotoCachedSize)Sizes.FirstOrDefault(x => x is TLPhotoCachedSize) : null; + } + } + + public override string ToString() + { + return string.Format("TLPhoto Sizes=[{0}]", string.Join(", ", Sizes.Select(x => x.ToString()))); + } + } + + public class TLUserProfilePhotoEmpty : TLPhotoBase + { + public const uint Signature = TLConstructors.TLUserProfilePhotoEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override void Update(TLPhotoBase photo) + { + + } + } + + public class TLUserProfilePhoto : TLPhotoCommon + { + public const uint Signature = TLConstructors.TLUserProfilePhoto; + + public TLLong PhotoId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhotoId = GetObject(bytes, ref position); + PhotoSmall = GetObject(bytes, ref position); + PhotoBig = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PhotoId = GetObject(input); + PhotoSmall = GetObject(input); + PhotoBig = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(PhotoId != null ? PhotoId.ToBytes() : new TLLong(0).ToBytes()); + PhotoSmall.ToStream(output); + PhotoBig.ToStream(output); + } + } + + public class TLChatPhotoEmpty : TLPhotoBase + { + public const uint Signature = TLConstructors.TLChatPhotoEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override void Update(TLPhotoBase photo) + { + + } + } + + public class TLChatPhoto : TLPhotoCommon + { + public const uint Signature = TLConstructors.TLChatPhoto; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhotoSmall = GetObject(bytes, ref position); + PhotoBig = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + PhotoSmall = GetObject(input); + PhotoBig = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PhotoSmall.ToStream(output); + PhotoBig.ToStream(output); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLPhotoPickerSettings.cs b/Telegram.Api/TL/TLPhotoPickerSettings.cs new file mode 100755 index 0000000..11c45bf --- /dev/null +++ b/Telegram.Api/TL/TLPhotoPickerSettings.cs @@ -0,0 +1,68 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum PhotoPickerSettingsFlags + { + External = 0x1, // 0 + } + + public class TLPhotoPickerSettings : TLObject + { + public const uint Signature = TLConstructors.TLPhotoPickerSettings; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool External + { + get { return IsSet(Flags, (int)PhotoPickerSettingsFlags.External); } + set { SetUnset(ref _flags, value, (int)PhotoPickerSettingsFlags.External); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Flags.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLPhotoSize.cs b/Telegram.Api/TL/TLPhotoSize.cs new file mode 100755 index 0000000..12043f3 --- /dev/null +++ b/Telegram.Api/TL/TLPhotoSize.cs @@ -0,0 +1,257 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using System.Runtime.Serialization; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public interface IPhotoSize + { + TLInt W { get; set; } + + TLInt H { get; set; } + } + + [KnownType(typeof(TLPhotoSizeEmpty))] + [KnownType(typeof(TLPhotoSize))] + [KnownType(typeof(TLPhotoCachedSize))] + [DataContract] + public abstract class TLPhotoSizeBase : TLObject + { + [DataMember] + public TLString Type { get; set; } + + public string TempUrl { get; set; } + + public virtual void Update(TLPhotoSizeBase photoSizeBase) + { + if (photoSizeBase != null) + { + Type = photoSizeBase.Type; + } + } + } + + [DataContract] + public class TLPhotoSizeEmpty : TLPhotoSizeBase + { + public const uint Signature = TLConstructors.TLPhotoSizeEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + Type.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Type = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Type.ToBytes()); + } + + public override string ToString() + { + return string.Format("empty {0}", Type); + } + } + + [DataContract] + public class TLPhotoSize : TLPhotoSizeBase, IPhotoSize + { + public const uint Signature = TLConstructors.TLPhotoSize; + + [DataMember] + public TLFileLocationBase Location { get; set; } + + [DataMember] + public TLInt W { get; set; } + + [DataMember] + public TLInt H { get; set; } + + [DataMember] + public TLInt Size { get; set; } + + public TLString Bytes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + Location = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + Type.ToBytes(), + Location.ToBytes(), + W.ToBytes(), + H.ToBytes(), + Size.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Type = GetObject(input); + Location = GetObject(input); + W = GetObject(input); + H = GetObject(input); + Size = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Type.ToBytes()); + Location.ToStream(output); + output.Write(W.ToBytes()); + output.Write(H.ToBytes()); + output.Write(Size.ToBytes()); + } + + public override void Update(TLPhotoSizeBase photoSizeBase) + { + base.Update(photoSizeBase); + + var photoSize = photoSizeBase as TLPhotoSize; + if (photoSize != null) + { + W = photoSize.W; + H = photoSize.H; + Size = photoSize.Size; + if (Location != null) + { + Location.Update(photoSize.Location); + } + else + { + Location = photoSize.Location; + } + } + } + + public override string ToString() + { + return string.Format("{0}{1}x{2} {3}", Type, W, H, Size); + } + } + + [DataContract] + public class TLPhotoCachedSize : TLPhotoSizeBase, IPhotoSize + { + public const uint Signature = TLConstructors.TLPhotoCachedSize; + + [DataMember] + public TLFileLocationBase Location { get; set; } + + [DataMember] + public TLInt W { get; set; } + + [DataMember] + public TLInt H { get; set; } + + [DataMember] + public TLString Bytes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + Location = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + Bytes = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + Type.ToBytes(), + Location.ToBytes(), + W.ToBytes(), + H.ToBytes(), + Bytes.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Type = GetObject(input); + Location = GetObject(input); + W = GetObject(input); + H = GetObject(input); + Bytes = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Type.ToBytes()); + Location.ToStream(output); + output.Write(W.ToBytes()); + output.Write(H.ToBytes()); + output.Write(Bytes.ToBytes()); + } + + public override void Update(TLPhotoSizeBase photoSizeBase) + { + base.Update(photoSizeBase); + + var photoSize = photoSizeBase as TLPhotoCachedSize; + if (photoSize != null) + { + W = photoSize.W; + H = photoSize.H; + Bytes = photoSize.Bytes; + if (Location != null) + { + Location.Update(photoSize.Location); + } + else + { + Location = photoSize.Location; + } + } + } + + public override string ToString() + { + return string.Format("cached {0}{1}x{2}", Type, H, W); + } + } +} diff --git a/Telegram.Api/TL/TLPhotos.cs b/Telegram.Api/TL/TLPhotos.cs new file mode 100755 index 0000000..436ff36 --- /dev/null +++ b/Telegram.Api/TL/TLPhotos.cs @@ -0,0 +1,49 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLPhotosBase : TLObject + { + public TLVector Photos { get; set; } + + public TLVector Users { get; set; } + } + + public class TLPhotos : TLPhotosBase + { + public const uint Signature = TLConstructors.TLPhotos; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Photos = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } + + public class TLPhotosSlice : TLPhotosBase + { + public const uint Signature = TLConstructors.TLPhotosSlice; + + public TLInt Count { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Count = GetObject(bytes, ref position); + Photos = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPhotosPhoto.cs b/Telegram.Api/TL/TLPhotosPhoto.cs new file mode 100755 index 0000000..29e3501 --- /dev/null +++ b/Telegram.Api/TL/TLPhotosPhoto.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLPhotosPhoto : TLObject + { + public const uint Signature = TLConstructors.TLPhotosPhoto; + + public TLPhotoBase Photo { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Photo = GetObject(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPong.cs b/Telegram.Api/TL/TLPong.cs new file mode 100755 index 0000000..e44596e --- /dev/null +++ b/Telegram.Api/TL/TLPong.cs @@ -0,0 +1,59 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLPing : TLObject + { + public const uint Signature = TLConstructors.TLPing; + + public TLLong PingId { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PingId.ToBytes()); + } + } + + public class TLPingDelayDisconnect : TLObject + { + public const uint Signature = TLConstructors.TLPingDelayDisconnect; + + public TLLong PingId { get; set; } + + public TLInt DisconnectDelay { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PingId.ToBytes(), + DisconnectDelay.ToBytes()); + } + } + + public class TLPong : TLObject + { + public const uint Signature = TLConstructors.TLPong; + + public TLLong MessageId { get; set; } + + public TLLong PingId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + MessageId = GetObject(bytes, ref position); + PingId = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPopularContact.cs b/Telegram.Api/TL/TLPopularContact.cs new file mode 100755 index 0000000..0b0b824 --- /dev/null +++ b/Telegram.Api/TL/TLPopularContact.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLPopularContact : TLObject + { + public const uint Signature = TLConstructors.TLPopularContact; + + public TLLong ClientId { get; set; } + + public TLInt Importers { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ClientId = GetObject(bytes, ref position); + Importers = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPostAddress.cs b/Telegram.Api/TL/TLPostAddress.cs new file mode 100755 index 0000000..8599ba2 --- /dev/null +++ b/Telegram.Api/TL/TLPostAddress.cs @@ -0,0 +1,90 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using System.IO; + +namespace Telegram.Api.TL +{ + public class TLPostAddress : TLObject + { + public const uint Signature = TLConstructors.TLPostAddress; + + public TLString StreetLine1 { get; set; } + + public TLString StreetLine2 { get; set; } + + public TLString City { get; set; } + + public TLString State { get; set; } + + public TLString CountryIso2 { get; set; } + + public TLString PostCode { get; set; } + + public override string ToString() + { + var list = new List(); + if (!TLString.IsNullOrEmpty(StreetLine1)) list.Add(StreetLine1); + if (!TLString.IsNullOrEmpty(StreetLine2)) list.Add(StreetLine2); + if (!TLString.IsNullOrEmpty(City)) list.Add(City); + if (!TLString.IsNullOrEmpty(State)) list.Add(State); + if (!TLString.IsNullOrEmpty(CountryIso2)) list.Add(CountryIso2); + if (!TLString.IsNullOrEmpty(PostCode)) list.Add(PostCode); + + return string.Join(", ", list); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + StreetLine1 = GetObject(bytes, ref position); + StreetLine2 = GetObject(bytes, ref position); + City = GetObject(bytes, ref position); + State = GetObject(bytes, ref position); + CountryIso2 = GetObject(bytes, ref position); + PostCode = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + StreetLine1.ToBytes(), + StreetLine2.ToBytes(), + City.ToBytes(), + State.ToBytes(), + CountryIso2.ToBytes(), + PostCode.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + StreetLine1 = GetObject(input); + StreetLine2 = GetObject(input); + City = GetObject(input); + State = GetObject(input); + CountryIso2 = GetObject(input); + PostCode = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + StreetLine1.ToStream(output); + StreetLine2.ToStream(output); + City.ToStream(output); + State.ToStream(output); + CountryIso2.ToStream(output); + PostCode.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLPrivacyKey.cs b/Telegram.Api/TL/TLPrivacyKey.cs new file mode 100755 index 0000000..61586b5 --- /dev/null +++ b/Telegram.Api/TL/TLPrivacyKey.cs @@ -0,0 +1,80 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLPrivacyKeyBase : TLObject { } + + public class TLPrivacyKeyStatusTimestamp : TLPrivacyKeyBase + { + public const uint Signature = TLConstructors.TLPrivacyKeyStatusTimestamp; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLPrivacyKeyChatInvite : TLPrivacyKeyBase + { + public const uint Signature = TLConstructors.TLPrivacyKeyChatInvite; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLPrivacyKeyPhoneCall : TLPrivacyKeyBase + { + public const uint Signature = TLConstructors.TLPrivacyKeyPhoneCall; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } +} diff --git a/Telegram.Api/TL/TLPrivacyRule.cs b/Telegram.Api/TL/TLPrivacyRule.cs new file mode 100755 index 0000000..b4391ce --- /dev/null +++ b/Telegram.Api/TL/TLPrivacyRule.cs @@ -0,0 +1,206 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLPrivacyRuleBase : TLObject + { + public string Label { get; set; } + public bool IsChecked { get; set; } + + public override string ToString() + { + return Label; + } + + public abstract TLInputPrivacyRuleBase ToInputRule(); + } + + public class TLPrivacyValueAllowContacts : TLPrivacyRuleBase + { + public const uint Signature = TLConstructors.TLPrivacyValueAllowContacts; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override TLInputPrivacyRuleBase ToInputRule() + { + return new TLInputPrivacyValueAllowContacts(); + } + } + + public class TLPrivacyValueAllowAll : TLPrivacyRuleBase + { + public const uint Signature = TLConstructors.TLPrivacyValueAllowAll; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override TLInputPrivacyRuleBase ToInputRule() + { + return new TLInputPrivacyValueAllowAll(); + } + } + + public class TLPrivacyValueAllowUsers : TLPrivacyRuleBase, IPrivacyValueUsersRule + { + public const uint Signature = TLConstructors.TLPrivacyValueAllowUsers; + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Users = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Users.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Users = GetObject>(input); + + return this; + } + + public override TLInputPrivacyRuleBase ToInputRule() + { + return new TLInputPrivacyValueAllowUsers{Users = new TLVector()}; + } + } + + public class TLPrivacyValueDisallowContacts : TLPrivacyRuleBase + { + public const uint Signature = TLConstructors.TLPrivacyValueDisallowContacts; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override TLInputPrivacyRuleBase ToInputRule() + { + return new TLInputPrivacyValueDisallowContacts(); + } + } + + public class TLPrivacyValueDisallowAll : TLPrivacyRuleBase + { + public const uint Signature = TLConstructors.TLPrivacyValueDisallowAll; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override TLInputPrivacyRuleBase ToInputRule() + { + return new TLInputPrivacyValueDisallowAll(); + } + } + + public class TLPrivacyValueDisallowUsers : TLPrivacyRuleBase, IPrivacyValueUsersRule + { + public const uint Signature = TLConstructors.TLPrivacyValueDisallowUsers; + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Users = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Users.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Users = GetObject>(input); + + return this; + } + + public override TLInputPrivacyRuleBase ToInputRule() + { + return new TLInputPrivacyValueDisallowUsers{Users = new TLVector()}; + } + } + + public interface IPrivacyValueUsersRule + { + TLVector Users { get; set; } + } +} diff --git a/Telegram.Api/TL/TLPrivacyRules.cs b/Telegram.Api/TL/TLPrivacyRules.cs new file mode 100755 index 0000000..1b4a5ec --- /dev/null +++ b/Telegram.Api/TL/TLPrivacyRules.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLPrivacyRules : TLObject + { + public const uint Signature = TLConstructors.TLPrivacyRules; + + public TLVector Rules { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Rules = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLProxyConfig.cs b/Telegram.Api/TL/TLProxyConfig.cs new file mode 100755 index 0000000..cf63f11 --- /dev/null +++ b/Telegram.Api/TL/TLProxyConfig.cs @@ -0,0 +1,444 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ProxyConfigCustomFlags + { + IsEnabled = 0x1, + UseForCalls = 0x2 + } + + [Flags] + public enum ProxyCustomFlags + { + Ping = 0x1, + CheckTime = 0x2 + } + + public enum ProxyStatus + { + Available, + Unavailable, + Connecting + } + + public abstract class TLProxyConfigBase : TLObject + { + public virtual TLBool IsEnabled { get; set; } + + public virtual TLBool UseForCalls { get; set; } + + public abstract bool IsEmpty { get; } + + public abstract TLProxyBase GetProxy(); + + public abstract TLProxyConfigBase ToLastProxyConfig(); + + public static TLProxyConfigBase Empty + { + get + { + var proxyConfig = new TLProxyConfig76 + { + CustomFlags = new TLLong(0), + IsEnabled = TLBool.False, + UseForCalls = TLBool.False, + SelectedIndex = new TLInt(-1), + Items = new TLVector() + }; + + return proxyConfig; + } + } + } + + public class TLProxyConfig : TLProxyConfigBase + { + public const uint Signature = TLConstructors.TLProxyConfig; + + public TLString Server { get; set; } + + public TLInt Port { get; set; } + + public TLString Username { get; set; } + + public TLString Password { get; set; } + + public override bool IsEmpty + { + get { return TLString.IsNullOrEmpty(Server) || Port.Value < 0; } + } + + public override TLProxyBase GetProxy() + { + return IsEmpty + ? null + : new TLSocks5Proxy + { + CustomFlags = new TLLong(0), + Server = Server, + Port = Port, + Username = Username, + Password = Password + }; + } + + public override TLProxyConfigBase ToLastProxyConfig() + { + return new TLProxyConfig76 + { + CustomFlags = new TLLong(0), + IsEnabled = IsEnabled, + SelectedIndex = new TLInt(0), + Items = new TLVector + { + new TLSocks5Proxy + { + CustomFlags = new TLLong(0), + Server = Server, + Port = Port, + Username = Username, + Password = Password + } + } + }; + } + + public override TLObject FromStream(Stream input) + { + IsEnabled = GetObject(input); + Server = GetObject(input); + Port = GetObject(input); + Username = GetObject(input); + Password = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + IsEnabled.ToStream(output); + Server.ToStream(output); + Port.ToStream(output); + Username.ToStream(output); + Password.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLProxyConfig server={0} port={1} username={2} password={3}", Server, Port, Username, Password); + } + } + + public class TLProxyConfig76 : TLProxyConfigBase + { + public const uint Signature = TLConstructors.TLProxyConfig76; + + protected TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + public override TLBool IsEnabled + { + get { return IsSet(CustomFlags, (int)ProxyConfigCustomFlags.IsEnabled) ? TLBool.True : TLBool.False; } + set { SetUnset(ref _customFlags, value.Value, (int)ProxyConfigCustomFlags.IsEnabled); } + } + + public override TLBool UseForCalls + { + get { return IsSet(CustomFlags, (int)ProxyConfigCustomFlags.UseForCalls) ? TLBool.True : TLBool.False; } + set { SetUnset(ref _customFlags, value.Value, (int)ProxyConfigCustomFlags.UseForCalls); } + } + + public TLInt SelectedIndex { get; set; } + + public TLVector Items { get; set; } + + public override bool IsEmpty + { + get { return SelectedIndex.Value < 0 || SelectedIndex.Value > Items.Count - 1 || Items[SelectedIndex.Value].IsEmpty; } + } + + public override TLProxyConfigBase ToLastProxyConfig() + { + return this; + } + + public override TLProxyBase GetProxy() + { + return IsEmpty + ? null + : Items[SelectedIndex.Value]; + } + + public override TLObject FromStream(Stream input) + { + CustomFlags = GetObject(input); + SelectedIndex = GetObject(input); + Items = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + CustomFlags.ToStream(output); + SelectedIndex.ToStream(output); + Items.ToStream(output); + } + } + + public abstract class TLProxyBase : TLObject + { + protected TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + protected TLInt _ping; + + public TLInt Ping + { + get { return _ping; } + set + { + SetField(out _ping, value, ref _customFlags, (int)ProxyCustomFlags.Ping); + NotifyOfPropertyChange(() => Ping); + } + } + + protected TLInt _checkTime; + + public TLInt CheckTime + { + get { return _checkTime; } + set { SetField(out _checkTime, value, ref _customFlags, (int)ProxyCustomFlags.CheckTime); } + } + + public TLString Server { get; set; } + + public TLInt Port { get; set; } + + protected ProxyStatus _proxyStatus; + + public ProxyStatus Status + { + get { return _proxyStatus; } + set + { + SetField(ref _proxyStatus, value, () => Status); + NotifyOfPropertyChange(() => Self); + } + } + + public virtual string About { get { return string.Format("{0}:{1}", Server, Port); } } + + public abstract bool IsEmpty { get; } + + private bool _isSelected; + + public bool IsSelected + { + get { return _isSelected; } + set + { + SetField(ref _isSelected, value, () => IsSelected); + NotifyOfPropertyChange(() => Self); + } + } + + public abstract bool ProxyEquals(TLProxyBase proxy); + + public static bool ProxyEquals(TLProxyBase proxyItem1, TLProxyBase proxyItem2) + { + if (proxyItem1 != null && proxyItem2 == null) return false; + if (proxyItem1 == null && proxyItem2 == null) return false; + if (proxyItem1 == null && proxyItem2 != null) return false; + + return proxyItem1.ProxyEquals(proxyItem2); + } + + public TLProxyBase Self + { + get { return this; } + } + + public abstract string GetUrl(string prefix); + + public abstract TLInputClientProxy ToInputProxy(); + } + + public class TLSocks5Proxy : TLProxyBase + { + public const uint Signature = TLConstructors.TLSocks5Proxy; + + public TLString Username { get; set; } + + public TLString Password { get; set; } + + public override bool IsEmpty + { + get { return TLString.IsNullOrEmpty(Server) || Port.Value < 0; } + } + + public override bool ProxyEquals(TLProxyBase proxy) + { + var socks5Proxy = proxy as TLSocks5Proxy; + if (socks5Proxy == null) return false; + + return + TLString.Equals(Server, socks5Proxy.Server, StringComparison.OrdinalIgnoreCase) + && Port.Value == socks5Proxy.Port.Value + && TLString.Equals(Username, socks5Proxy.Username, StringComparison.Ordinal) + && TLString.Equals(Password, socks5Proxy.Password, StringComparison.Ordinal); + } + + public override TLObject FromStream(Stream input) + { + CustomFlags = GetObject(input); + Server = GetObject(input); + Port = GetObject(input); + Username = GetObject(input); + Password = GetObject(input); + + Ping = GetObject(CustomFlags, (int)ProxyCustomFlags.Ping, null, input); + CheckTime = GetObject(CustomFlags, (int)ProxyCustomFlags.CheckTime, null, input); + Status = Ping != null ? ProxyStatus.Available : ProxyStatus.Unavailable; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + CustomFlags.ToStream(output); + Server.ToStream(output); + Port.ToStream(output); + Username.ToStream(output); + Password.ToStream(output); + + ToStream(output, Ping, CustomFlags, (int)ProxyCustomFlags.Ping); + ToStream(output, CheckTime, CustomFlags, (int)ProxyCustomFlags.CheckTime); + } + + public override string ToString() + { + return string.Format("TLSocks5Proxy server={0} port={1} username={2} password={3}", Server, Port, Username, Password); + } + + public override string GetUrl(string prefix) + { + var proxyString = prefix + string.Format("socks?server={0}&port={1}", Server, Port); + + if (!TLString.IsNullOrEmpty(Username) && !TLString.IsNullOrEmpty(Password)) + { + proxyString += string.Format("&user={0}&pass={1}", Username, Password); + } + + return proxyString; + } + + public override TLInputClientProxy ToInputProxy() + { + return null; + } + } + + public class TLMTProtoProxy : TLProxyBase + { + public const uint Signature = TLConstructors.TLMTProtoProxy; + + public TLString Secret { get; set; } + + public override bool IsEmpty + { + get { return TLString.IsNullOrEmpty(Server) || Port.Value < 0 || TLString.IsNullOrEmpty(Secret); } + } + + public override bool ProxyEquals(TLProxyBase proxy) + { + var mtProtoProxy = proxy as TLMTProtoProxy; + if (mtProtoProxy == null) return false; + + return + TLString.Equals(Server, mtProtoProxy.Server, StringComparison.OrdinalIgnoreCase) + && Port.Value == mtProtoProxy.Port.Value + && TLString.Equals(Secret, mtProtoProxy.Secret, StringComparison.Ordinal); + } + + public override TLObject FromStream(Stream input) + { + CustomFlags = GetObject(input); + Server = GetObject(input); + Port = GetObject(input); + Secret = GetObject(input); + + Ping = GetObject(CustomFlags, (int)ProxyCustomFlags.Ping, null, input); + CheckTime = GetObject(CustomFlags, (int)ProxyCustomFlags.CheckTime, null, input); + Status = Ping != null ? ProxyStatus.Available : ProxyStatus.Unavailable; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + CustomFlags.ToStream(output); + Server.ToStream(output); + Port.ToStream(output); + Secret.ToStream(output); + + ToStream(output, Ping, CustomFlags, (int)ProxyCustomFlags.Ping); + ToStream(output, CheckTime, CustomFlags, (int)ProxyCustomFlags.CheckTime); + } + + public override string ToString() + { + return string.Format("TLMTProtoProxy server={0} port={1} secret={2}", Server, Port, Secret); + } + + public override string GetUrl(string prefix) + { + var proxyString = prefix + string.Format("proxy?server={0}&port={1}", Server, Port); + + if (!TLString.IsNullOrEmpty(Secret)) + { + proxyString += string.Format("&secret={0}", Secret); + } + + return proxyString; + } + + public override TLInputClientProxy ToInputProxy() + { + return new TLInputClientProxy + { + Address = Server, + Port = Port + }; + } + } +} diff --git a/Telegram.Api/TL/TLRPCDropAnswer.cs b/Telegram.Api/TL/TLRPCDropAnswer.cs new file mode 100755 index 0000000..4730de9 --- /dev/null +++ b/Telegram.Api/TL/TLRPCDropAnswer.cs @@ -0,0 +1,55 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLRPCAnswerUnknown : TLObject + { + public const uint Signature = TLConstructors.TLRPCAnswerUnknown; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLRPCAnswerDroppedRunning : TLObject + { + public const uint Signature = TLConstructors.TLRPCAnswerDroppedRunning; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + } + + public class TLRPCAnswerDropped : TLObject + { + public const uint Signature = TLConstructors.TLRPCAnswerDropped; + + public TLLong MsgId { get; set; } + + public TLInt SeqNo { get; set; } + + public TLInt Bytes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + MsgId = GetObject(bytes, ref position); + SeqNo = GetObject(bytes, ref position); + Bytes = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLRPCError.cs b/Telegram.Api/TL/TLRPCError.cs new file mode 100755 index 0000000..00a81ae --- /dev/null +++ b/Telegram.Api/TL/TLRPCError.cs @@ -0,0 +1,340 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +#if !WIN_RT +using System.Net.Sockets; +#endif + +namespace Telegram.Api.TL +{ + public enum ErrorType + { + PHONE_MIGRATE, + NETWORK_MIGRATE, + FILE_MIGRATE, + USER_MIGRATE, + PHONE_NUMBER_INVALID, + PHONE_CODE_EMPTY, + PHONE_CODE_EXPIRED, + PHONE_CODE_INVALID, + PHONE_NUMBER_OCCUPIED, + PHONE_NUMBER_UNOCCUPIED, + FLOOD_WAIT, + PEER_FLOOD, + FIRSTNAME_INVALID, + MIDDLENAME_INVALID, + LASTNAME_INVALID, + FIRSTNAMENATIVE_INVALID, + MIDDLENAMENATIVE_INVALID, + LASTNAMENATIVE_INVALID, + QUERY_TOO_SHORT, + USERNAME_INVALID, + USERNAME_OCCUPIED, + USERNAME_NOT_OCCUPIED, // 400 + USERNAME_NOT_MODIFIED, // 400 + CHANNELS_ADMIN_PUBLIC_TOO_MUCH, // 400 + CHANNEL_PRIVATE, // 400 + PEER_ID_INVALID, // 400 + MESSAGE_EMPTY, // 400 + MESSAGE_TOO_LONG, // 400 + MSG_WAIT_FAILED, // 400 + MESSAGE_ID_INVALID, // 400 + MESSAGE_NOT_MODIFIED, // 400 + MESSAGE_EDIT_TIME_EXPIRED, // 400 + + PASSWORD_HASH_INVALID, // 400 + NEW_PASSWORD_BAD, // 400 + NEW_SALT_INVALID, // 400 + EMAIL_INVALID, // 400 + EMAIL_UNCONFIRMED, // 400 + EMAIL_VERIFY_EXPIRED, // 400 + + CODE_EMPTY, // 400 + CODE_INVALID, // 400 + PASSWORD_EMPTY, // 400 + PASSWORD_RECOVERY_NA, // 400 + PASSWORD_RECOVERY_EXPIRED, //400 + + CHAT_INVALID, // 400 + CHAT_ADMIN_REQUIRED, // 400 + CHAT_NOT_MODIFIED, // 400 + CHAT_ABOUT_NOT_MODIFIED,// 400 + INVITE_HASH_EMPTY, // 400 + INVITE_HASH_INVALID, // 400 + INVITE_HASH_EXPIRED, // 400 + USERS_TOO_MUCH, // 400 + BOTS_TOO_MUCH, // 400 + ADMINS_TOO_MUCH, // 400 + CHANNELS_TOO_MUCH, // 400 + USER_CHANNELS_TOO_MUCH, // 400 + USER_NOT_MUTUAL_CONTACT, // 400 + USER_ALREADY_PARTICIPANT, // 400 + USER_NOT_PARTICIPANT, // 400 + + STICKERSET_INVALID, // 400 + LOCATION_INVALID, // 400 upload.getFile + VOLUME_LOC_NOT_FOUND, // 400 upload.getFile + + SRP_ID_INVALID, + SRP_PASSWORD_CHANGED, + + REQ_INFO_NAME_INVALID, + REQ_INFO_PHONE_INVALID, + REQ_INFO_EMAIL_INVALID, + ADDRESS_COUNTRY_INVALID, + ADDRESS_RESIDENCE_COUNTRY_INVALID, + ADDRESS_CITY_INVALID, + ADDRESS_POSTCODE_INVALID, + ADDRESS_STATE_INVALID, + ADDRESS_STREET_LINE1_INVALID, + ADDRESS_STREET_LINE2_INVALID, + SHIPPING_BOT_TIMEOUT, + SHIPPING_NOT_AVAILABLE, + + BIRTHDATE_INVALID, + GENDER_INVALID, + DOCUMENT_NUMBER_INVALID, + EXPIRYDATE_INVALID, + + PROVIDER_ACCOUNT_INVALID, + PROVIDER_ACCOUNT_TIMEOUT, + INVOICE_ALREADY_PAID, + + REQUESTED_INFO_INVALID, + SHIPPING_OPTION_INVALID, + PAYMENT_FAILED, + PAYMENT_CREDENTIALS_INVALID, + PAYMENT_CREDENTIALS_ID_INVALID, + BOT_PRECHECKOUT_FAILED, + + FILE_TOKEN_INVALID, + REQUEST_TOKEN_INVALID, + + FILES_EMPTY, + FILES_TOO_MUCH, + FILE_ERROR, + TRANSLATION_ERROR, + TRANSLATION_EMPTY, + FRONT_SIDE_REQUIRED, + REVERSE_SIDE_REQUIRED, + SELFIE_REQUIRED, + + PHONE_VERIFICATION_NEEDED, + EMAIL_VERIFICATION_NEEDED, + + APP_VERSION_OUTDATED, + + SESSION_PASSWORD_NEEDED,// 401 + SESSION_REVOKED, // 401 + USER_PRIVACY_RESTRICTED,// 403 + + //2FA_RECENT_CONFIRM, // 420 + //2FA_CONFIRM_WAIT_XXX, // 420 + + RPC_CALL_FAIL, // 500 + + CANTPARSE + } + + public enum ErrorCode + { + ERROR_SEE_OTHER = 303, + BAD_REQUEST = 400, + UNAUTHORIZED = 401, + FORBIDDEN = 403, + NOT_FOUND = 404, + FLOOD = 420, + INTERNAL = 500, + + #region Additional + TIMEOUT = 408, + #endregion + } + + public class TLRPCReqError : TLRPCError + { + public new const uint Signature = TLConstructors.TLRPCReqError; + + public TLLong QueryId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + QueryId = GetObject(bytes, ref position); + Code = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + QueryId.ToBytes(), + Code.ToBytes(), + Message.ToBytes()); + } + } + + public class TLRPCError : TLObject + { + public TLRPCError() + { + Code = new TLInt(0); + } + + public TLRPCError(int errorCode) + { + Code = new TLInt(errorCode); + } + + #region Additional +#if !WIN_RT + public SocketError? SocketError { get; set; } +#endif + + public Exception Exception { get; set; } + + /// + /// Await time before next request (ms) + /// + public int AwaitTime { get; set; } + #endregion + + + public bool CodeEquals(ErrorCode code) + { + if (Code != null && Enum.IsDefined(typeof (ErrorCode), Code.Value)) + { + return (ErrorCode) Code.Value == code; + } + + return false; + } + + public static bool CodeEquals(TLRPCError error, ErrorCode code) + { + if (error.Code != null && Enum.IsDefined(typeof(ErrorCode), error.Code.Value)) + { + return (ErrorCode)error.Code.Value == code; + } + + return false; + } + + public ErrorType GetErrorType() + { + var strings = Message.ToString().Split(':'); + var typeString = strings[0]; + if (Enum.IsDefined(typeof(ErrorType), typeString)) + { + var value = (ErrorType) Enum.Parse(typeof(ErrorType), typeString, true); + + return value; + } + + return ErrorType.CANTPARSE; + } + + public string GetErrorTypeString() + { + var strings = Message.ToString().Split(':'); + return strings[0]; + } + + public bool TypeStarsWith(string type) + { + var strings = Message.ToString().Split(':'); + var typeString = strings[0]; + + return typeString.StartsWith(type, StringComparison.OrdinalIgnoreCase); + } + + public bool TypeStarsWith(ErrorType type) + { + var strings = Message.ToString().Split(':'); + var typeString = strings[0]; + + return typeString.StartsWith(type.ToString(), StringComparison.OrdinalIgnoreCase); + } + + public bool TypeEquals(string type) + { + if (Message == null) return false; + + var strings = Message.ToString().Split(':'); + var typeString = strings[0]; + + return string.Equals(type, typeString, StringComparison.OrdinalIgnoreCase); + } + + public bool TypeEquals(ErrorType type) + { + if (Message == null) return false; + + var strings = Message.ToString().Split(':'); + var typeString = strings[0]; + if (Enum.IsDefined(typeof(ErrorType), typeString)) + { + var value = (ErrorType)Enum.Parse(typeof (ErrorType), typeString, true); + + return value == type; + } + + return false; + } + + public static bool TypeEquals(TLRPCError error, ErrorType type) + { + if (error == null) return false; + + return error.TypeEquals(type); + } + + public const uint Signature = TLConstructors.TLRPCError; + + public TLInt Code { get; set; } + + public TLString Message { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Code = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Code.ToBytes(), + Message.ToBytes()); + } + + public override string ToString() + { +#if DEBUG + return string.Format("{0} {1}{2}{3}", Code, Message, +#if WINDOWS_PHONE + SocketError != null ? "\nSocketError=" + SocketError : string.Empty, +#else + string.Empty, +#endif + Exception != null ? "\nException=" : string.Empty); +#else + return string.Format("{0} {1}", Code, Message); +#endif + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLRPCResult.cs b/Telegram.Api/TL/TLRPCResult.cs new file mode 100755 index 0000000..af1bd84 --- /dev/null +++ b/Telegram.Api/TL/TLRPCResult.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLRPCResult : TLObject + { + public const uint Signature = TLConstructors.TLRPCResult; + + public TLLong RequestMessageId { get; set; } + + public TLObject Object { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + RequestMessageId = GetObject(bytes, ref position); + Object = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLReceivedNotifyMessage.cs b/Telegram.Api/TL/TLReceivedNotifyMessage.cs new file mode 100755 index 0000000..6dace3a --- /dev/null +++ b/Telegram.Api/TL/TLReceivedNotifyMessage.cs @@ -0,0 +1,54 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLReceivedNotifyMessage : TLObject + { + public const uint Signature = TLConstructors.TLReceivedNotifyMessage; + + public TLInt Id { get; set; } + + public TLInt Flags { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Flags = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Flags.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Flags = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(Flags.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLRecentMeUrl.cs b/Telegram.Api/TL/TLRecentMeUrl.cs new file mode 100755 index 0000000..9c51f63 --- /dev/null +++ b/Telegram.Api/TL/TLRecentMeUrl.cs @@ -0,0 +1,172 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLRecentMeUrlBase : TLObject + { + public TLString Url { get; set; } + } + + public class TLRecentMeUrlUnknown : TLRecentMeUrlBase + { + public const uint Signature = TLConstructors.TLRecentMeUrlUnknown; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Url.ToStream(output); + } + } + + public class TLRecentMeUrlUser : TLRecentMeUrlBase + { + public const uint Signature = TLConstructors.TLRecentMeUrlUser; + + public TLInt UserId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + UserId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Url.ToStream(output); + UserId.ToStream(output); + } + } + + public class TLRecentMeUrlChat : TLRecentMeUrlBase + { + public const uint Signature = TLConstructors.TLRecentMeUrlChat; + + public TLInt ChatId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + ChatId = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + ChatId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Url.ToStream(output); + ChatId.ToStream(output); + } + } + + public class TLRecentMeUrlChatInvite : TLRecentMeUrlBase + { + public const uint Signature = TLConstructors.TLRecentMeUrlChatInvite; + + public TLChatInviteBase ChatInvite { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + ChatInvite = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + ChatInvite = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Url.ToStream(output); + ChatInvite.ToStream(output); + } + } + + public class TLRecentMeUrlStickerSet : TLRecentMeUrlBase + { + public const uint Signature = TLConstructors.TLRecentMeUrlStickerSet; + + public TLStickerSetCoveredBase Set { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + Set = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + Set = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Url.ToStream(output); + Set.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLRecentMeUrls.cs b/Telegram.Api/TL/TLRecentMeUrls.cs new file mode 100755 index 0000000..4761392 --- /dev/null +++ b/Telegram.Api/TL/TLRecentMeUrls.cs @@ -0,0 +1,51 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLRecentMeUrls : TLObject + { + public const uint Signature = TLConstructors.TLRecentMeUrls; + + public TLVector Urls { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Urls = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Urls = GetObject>(input); + Chats = GetObject>(input); + Users = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Urls.ToStream(output); + Chats.ToStream(output); + Users.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLRecentStickers.cs b/Telegram.Api/TL/TLRecentStickers.cs new file mode 100755 index 0000000..b40f688 --- /dev/null +++ b/Telegram.Api/TL/TLRecentStickers.cs @@ -0,0 +1,133 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLRecentStickersBase : TLObject { } + + public class TLRecentStickersNotModified : TLRecentStickersBase + { + public const uint Signature = TLConstructors.TLRecentStickersNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLRecentStickers76 : TLRecentStickers + { + public new const uint Signature = TLConstructors.TLRecentStickers76; + + public TLVector Packs { get; set; } + + public TLVector Dates { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + Packs = GetObject>(bytes, ref position); + Documents = GetObject>(bytes, ref position); + Dates = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes(), + Packs.ToBytes(), + Documents.ToBytes(), + Dates.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Hash = GetObject(input); + Packs = GetObject>(input); + Documents = GetObject>(input); + Dates = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Hash.ToStream(output); + Packs.ToStream(output); + Documents.ToStream(output); + Dates.ToStream(output); + } + } + + public class TLRecentStickers : TLRecentStickersBase + { + public const uint Signature = TLConstructors.TLRecentStickers; + + public virtual TLInt Hash { get; set; } + + public TLVector Documents { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + Documents = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes(), + Documents.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Hash = GetObject(input); + Documents = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Hash.ToStream(output); + Documents.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLRecentlyUsedSticker.cs b/Telegram.Api/TL/TLRecentlyUsedSticker.cs new file mode 100755 index 0000000..a51cea5 --- /dev/null +++ b/Telegram.Api/TL/TLRecentlyUsedSticker.cs @@ -0,0 +1,58 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLRecentlyUsedSticker : TLObject + { + public const uint Signature = TLConstructors.TLRecentlyUsedSticker; + + public TLLong Id { get; set; } + public TLLong Count { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Count = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Count.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Count = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + Count.ToStream(output); + } + + public override string ToString() + { + return string.Format("Id={0} Count={1}", Id, Count); + } + } +} diff --git a/Telegram.Api/TL/TLReplyKeyboardMarkup.cs b/Telegram.Api/TL/TLReplyKeyboardMarkup.cs new file mode 100755 index 0000000..6397eb6 --- /dev/null +++ b/Telegram.Api/TL/TLReplyKeyboardMarkup.cs @@ -0,0 +1,265 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + enum ReplyKeyboardFlags + { + Resize = 0x1, + SingleUse = 0x2, + Personal = 0x4 + } + + enum ReplyKeyboardCustomFlags + { + HasResponse = 0x1, + } + + public interface IReplyKeyboardRows + { + TLVector Rows { get; set; } + } + + public abstract class TLReplyKeyboardBase : TLObject + { + public TLInt Flags { get; set; } + + private TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + public bool IsResizable + { + get { return IsSet(Flags, (int)ReplyKeyboardFlags.Resize); } + } + + public bool IsSingleUse + { + get { return IsSet(Flags, (int)ReplyKeyboardFlags.SingleUse); } + } + + public bool IsPersonal + { + get { return IsSet(Flags, (int)ReplyKeyboardFlags.Personal); } + } + + public bool HasResponse + { + get { return IsSet(CustomFlags, (int) ReplyKeyboardCustomFlags.HasResponse); } + set { Set(ref _customFlags, (int) ReplyKeyboardCustomFlags.HasResponse);} + } + + public override string ToString() + { + var isPersonal = IsPersonal ? "p" : string.Empty; + var isResizable = IsResizable ? "r" : string.Empty; + var isSingleUse = IsSingleUse ? "s" : string.Empty; + var hasResponse = HasResponse ? "h" : string.Empty; + return string.Format("{0} {1} {2} {3}", isPersonal, isResizable, isSingleUse, hasResponse); + } + } + + public class TLReplyInlineMarkup : TLReplyKeyboardBase, IReplyKeyboardRows + { + public const uint Signature = TLConstructors.TLReplyInlineMarkup; + + public TLVector Rows { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Rows = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Rows.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Rows = GetObject>(input); + + CustomFlags = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Rows.ToBytes()); + + CustomFlags.NullableToStream(output); + } + + public override string ToString() + { + var rowsString = new List(); + foreach (var row in Rows) + { + rowsString.Add(row.Buttons.Count.ToString()); + } + + return "IM " + string.Join(" ", rowsString) + base.ToString(); + } + } + + public class TLReplyKeyboardMarkup : TLReplyKeyboardBase, IReplyKeyboardRows + { + public const uint Signature = TLConstructors.TLReplyKeyboardMarkup; + + public TLVector Rows { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Rows = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Rows.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Rows = GetObject>(input); + + CustomFlags = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + output.Write(Rows.ToBytes()); + + CustomFlags.NullableToStream(output); + } + + public override string ToString() + { + var rowsString = new List(); + foreach (var row in Rows) + { + rowsString.Add(row.Buttons.Count.ToString()); + } + + return "KM " + string.Join(" ", rowsString) + base.ToString(); + } + } + + public class TLReplyKeyboardHide : TLReplyKeyboardBase + { + public const uint Signature = TLConstructors.TLReplyKeyboardHide; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + + CustomFlags = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + + CustomFlags.NullableToStream(output); + } + + public override string ToString() + { + return "KH " + base.ToString(); + } + } + + public class TLReplyKeyboardForceReply : TLReplyKeyboardBase + { + public const uint Signature = TLConstructors.TLReplyKeyboardForceReply; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + + CustomFlags = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Flags.ToBytes()); + + CustomFlags.NullableToStream(output); + } + + public override string ToString() + { + return "KFR " + base.ToString(); + } + } +} diff --git a/Telegram.Api/TL/TLRequest.cs b/Telegram.Api/TL/TLRequest.cs new file mode 100755 index 0000000..c137c5d --- /dev/null +++ b/Telegram.Api/TL/TLRequest.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Telegram.Api.TL +{ + +} diff --git a/Telegram.Api/TL/TLResPQ.cs b/Telegram.Api/TL/TLResPQ.cs new file mode 100755 index 0000000..e823220 --- /dev/null +++ b/Telegram.Api/TL/TLResPQ.cs @@ -0,0 +1,44 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLResPQ : TLObject + { + public const uint Signature = TLConstructors.TLResPQ; + + public TLInt128 Nonce { get; set; } + + public TLInt128 ServerNonce { get; set; } + + public TLString PQ { get; set; } + + public TLVector ServerPublicKeyFingerprints { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Nonce = GetObject(bytes, ref position); + ServerNonce = GetObject(bytes, ref position); + PQ = GetObject(bytes, ref position); + ServerPublicKeyFingerprints = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Nonce.ToBytes(), + ServerNonce.ToBytes(), + PQ.ToBytes(), + ServerPublicKeyFingerprints.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLResolvedPeer.cs b/Telegram.Api/TL/TLResolvedPeer.cs new file mode 100755 index 0000000..0fa2a03 --- /dev/null +++ b/Telegram.Api/TL/TLResolvedPeer.cs @@ -0,0 +1,51 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLResolvedPeer : TLObject + { + public const uint Signature = TLConstructors.TLResolvedPeer; + + public TLPeerBase Peer { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + Chats = GetObject>(input); + Users = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Peer.ToBytes()); + output.Write(Chats.ToBytes()); + output.Write(Users.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLResponse.cs b/Telegram.Api/TL/TLResponse.cs new file mode 100755 index 0000000..5ffb719 --- /dev/null +++ b/Telegram.Api/TL/TLResponse.cs @@ -0,0 +1,85 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.Helpers; + +namespace Telegram.Api.TL +{ + public class TLResponse + { + public byte[] AuthKeyId { get; set; } + + public byte[] MessageKey { get; set; } + + public byte[] EncryptedData { get; set; } + + public byte[] DecryptedData { get; set; } + + public byte[] Salt { get; set; } + + public byte[] SessionId { get; set; } + + public TLLong MessageId { get; set; } + + public TLInt SequenceNumber { get; set; } + + public Int32 MessageLength { get; set; } + + public byte[] MessageData { get; set; } + + public TLObject Data { get; set; } + + public static TLResponse Parse(byte[] bytes, byte[] authKey) + { + TLUtils.WriteLine("-------------------"); + TLUtils.WriteLine("--Parse response --"); + TLUtils.WriteLine("-------------------"); + + + int position = 0; + var response = new TLResponse(); + response.AuthKeyId = bytes.SubArray(0, 8); + TLUtils.WriteLine("AuthKeyId: " + BitConverter.ToString(response.AuthKeyId)); + response.MessageKey = bytes.SubArray(8, 16); + TLUtils.WriteLine("MessageKey: " + BitConverter.ToString(response.MessageKey)); + + response.EncryptedData = bytes.SubArray(24, bytes.Length - 24); + //TLUtils.WriteLine("Encrypted data: " + BitConverter.ToString(response.Data)); + + var keyIV = TLUtils.GetDecryptKeyIV(authKey, response.MessageKey); + + response.DecryptedData = Utils.AesIge(response.EncryptedData, keyIV.Item1, keyIV.Item2, false); + //TLUtils.WriteLine("Decrypted data: " + BitConverter.ToString(response.DecryptedData)); + + response.Salt = response.DecryptedData.SubArray(0, 8); + TLUtils.WriteLine("Salt: " + BitConverter.ToString(response.Salt)); + + response.SessionId = response.DecryptedData.SubArray(8, 8); + TLUtils.WriteLine("SessionId: " + BitConverter.ToString(response.SessionId)); + + position = 0; + response.MessageId = TLObject.GetObject(response.DecryptedData.SubArray(16, 8), ref position); + TLUtils.WriteLine("<-MESSAGEID: " + TLUtils.MessageIdString(response.MessageId)); + + position = 0; + response.SequenceNumber = TLObject.GetObject(response.DecryptedData.SubArray(24, 4), ref position); + TLUtils.WriteLine(" SEQUENCENUMBER: " + response.SequenceNumber); + + response.MessageLength = BitConverter.ToInt32(response.DecryptedData.SubArray(28, 4), 0); + TLUtils.WriteLine("MessageLength: " + response.MessageLength); + + response.MessageData = response.DecryptedData.SubArray(32, response.MessageLength); + TLUtils.WriteLine("MessageData: " + BitConverter.ToString(response.MessageData)); + + position = 0; + response.Data = TLObject.GetObject(response.MessageData, ref position); + + return response; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLResultInfo.cs b/Telegram.Api/TL/TLResultInfo.cs new file mode 100755 index 0000000..35382c3 --- /dev/null +++ b/Telegram.Api/TL/TLResultInfo.cs @@ -0,0 +1,40 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLResultInfo : TLObject + { + public const uint Signature = TLConstructors.TLResultInfo; + + public TLString Type { get; set; } + + public TLInt Id { get; set; } + + public TLLong Count { get; set; } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Type.ToStream(output); + Id.ToStream(output); + Count.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Type = GetObject(input); + Id = GetObject(input); + Count = GetObject(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLRichText.cs b/Telegram.Api/TL/TLRichText.cs new file mode 100755 index 0000000..a442a04 --- /dev/null +++ b/Telegram.Api/TL/TLRichText.cs @@ -0,0 +1,402 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLRichTextBase : TLObject { } + + public class TLTextEmpty : TLRichTextBase + { + public const uint Signature = TLConstructors.TLTextEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLTextPlain : TLRichTextBase + { + public const uint Signature = TLConstructors.TLTextPlain; + + public TLString Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + } + + public class TLTextBold : TLRichTextBase + { + public const uint Signature = TLConstructors.TLTextBold; + + public TLRichTextBase Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + } + + public class TLTextItalic : TLRichTextBase + { + public const uint Signature = TLConstructors.TLTextItalic; + + public TLRichTextBase Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + } + + public class TLTextUnderline : TLRichTextBase + { + public const uint Signature = TLConstructors.TLTextUnderline; + + public TLRichTextBase Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + } + + public class TLTextStrike : TLRichTextBase + { + public const uint Signature = TLConstructors.TLTextStrike; + + public TLRichTextBase Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + } + + public class TLTextFixed : TLRichTextBase + { + public const uint Signature = TLConstructors.TLTextFixed; + + public TLRichTextBase Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + + return this; + } + } + + public class TLTextUrl : TLRichTextBase + { + public const uint Signature = TLConstructors.TLTextUrl; + + public TLRichTextBase Text { get; set; } + + public TLString Url { get; set; } + + public TLLong WebPageId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + Url = GetObject(bytes, ref position); + WebPageId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes(), + Url.ToBytes(), + WebPageId.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + Url.ToStream(output); + WebPageId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + Url = GetObject(input); + WebPageId = GetObject(input); + + return this; + } + } + + public class TLTextEmail : TLRichTextBase + { + public const uint Signature = TLConstructors.TLTextEmail; + + public TLRichTextBase Text { get; set; } + + public TLString Email { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + Email = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Text.ToBytes(), + Email.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Text.ToStream(output); + Email.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Text = GetObject(input); + Email = GetObject(input); + + return this; + } + } + + public class TLTextConcat : TLRichTextBase + { + public const uint Signature = TLConstructors.TLTextConcat; + + public TLVector Texts { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Texts = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Texts.ToBytes()); + } + + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Texts.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Texts = GetObject>(input); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLSavedGifs.cs b/Telegram.Api/TL/TLSavedGifs.cs new file mode 100755 index 0000000..3155e60 --- /dev/null +++ b/Telegram.Api/TL/TLSavedGifs.cs @@ -0,0 +1,71 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLSavedGifsBase : TLObject { } + + public class TLSavedGifsNotModified : TLSavedGifsBase + { + public const uint Signature = TLConstructors.TLSavedGifsNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLSavedGifs : TLSavedGifsBase + { + public const uint Signature = TLConstructors.TLSavedGifs; + + public TLInt Hash { get; set; } + + public TLVector Gifs { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + Gifs = GetObject>(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Hash = GetObject(input); + Gifs = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + + Hash.ToStream(output); + Gifs.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLSavedInfo.cs b/Telegram.Api/TL/TLSavedInfo.cs new file mode 100755 index 0000000..94cfe2b --- /dev/null +++ b/Telegram.Api/TL/TLSavedInfo.cs @@ -0,0 +1,55 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum SavedInfoFlags + { + SavedInfo = 0x1, // 0 + HasSavedCredentials = 0x2, // 1 + } + + public class TLSavedInfo : TLObject + { + public const uint Signature = TLConstructors.TLSavedInfo; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool HasSavedCredentials + { + get { return IsSet(Flags, (int) SavedInfoFlags.HasSavedCredentials); } + set { SetUnset(ref _flags, value, (int) SavedInfoFlags.HasSavedCredentials); } + } + + private TLPaymentRequestedInfo _savedInfo; + + public TLPaymentRequestedInfo SavedInfo + { + get { return _savedInfo; } + set { SetField(out _savedInfo, value, ref _flags, (int) SavedInfoFlags.SavedInfo); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + _savedInfo = GetObject(Flags, (int) SavedInfoFlags.SavedInfo, null, bytes, ref position); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLSendMessageAction.cs b/Telegram.Api/TL/TLSendMessageAction.cs new file mode 100755 index 0000000..589154f --- /dev/null +++ b/Telegram.Api/TL/TLSendMessageAction.cs @@ -0,0 +1,540 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLSendMessageActionBase : TLObject { } + + public class TLSendMessageTypingAction : TLSendMessageActionBase + { + public const uint Signature = TLConstructors.TLSendMessageTypingAction; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLSendMessageCancelAction : TLSendMessageActionBase + { + public const uint Signature = TLConstructors.TLSendMessageCancelAction; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLSendMessageRecordVideoAction : TLSendMessageActionBase + { + public const uint Signature = TLConstructors.TLSendMessageRecordVideoAction; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLSendMessageUploadVideoAction : TLSendMessageActionBase + { + public const uint Signature = TLConstructors.TLSendMessageUploadVideoAction; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLSendMessageUploadVideoAction28 : TLSendMessageUploadVideoAction + { + public new const uint Signature = TLConstructors.TLSendMessageUploadVideoAction28; + + public TLInt Progress { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Progress = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + Progress.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Progress.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Progress = GetObject(input); + + return this; + } + } + + public class TLSendMessageRecordAudioAction : TLSendMessageActionBase + { + public const uint Signature = TLConstructors.TLSendMessageRecordAudioAction; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLSendMessageUploadAudioAction : TLSendMessageActionBase + { + public const uint Signature = TLConstructors.TLSendMessageUploadAudioAction; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLSendMessageUploadAudioAction28 : TLSendMessageUploadAudioAction + { + public new const uint Signature = TLConstructors.TLSendMessageUploadAudioAction28; + + public TLInt Progress { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Progress = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + Progress.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Progress.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Progress = GetObject(input); + + return this; + } + } + + public class TLSendMessageUploadPhotoAction : TLSendMessageActionBase + { + public const uint Signature = TLConstructors.TLSendMessageUploadPhotoAction; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLSendMessageUploadPhotoAction28 : TLSendMessageUploadPhotoAction + { + public new const uint Signature = TLConstructors.TLSendMessageUploadPhotoAction28; + + public TLInt Progress { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Progress = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + Progress.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Progress.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Progress = GetObject(input); + + return this; + } + } + + public class TLSendMessageUploadDocumentAction : TLSendMessageActionBase + { + public const uint Signature = TLConstructors.TLSendMessageUploadDocumentAction; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLSendMessageUploadDocumentAction28 : TLSendMessageUploadDocumentAction + { + public new const uint Signature = TLConstructors.TLSendMessageUploadDocumentAction28; + + public TLInt Progress { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Progress = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + Progress.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Progress.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Progress = GetObject(input); + + return this; + } + } + + public class TLSendMessageGeoLocationAction : TLSendMessageActionBase + { + public const uint Signature = TLConstructors.TLSendMessageGeoLocationAction; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLSendMessageChooseContactAction : TLSendMessageActionBase + { + public const uint Signature = TLConstructors.TLSendMessageChooseContactAction; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLSendMessageGamePlayAction : TLSendMessageActionBase + { + public const uint Signature = TLConstructors.TLSendMessageGamePlayAction; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLSendMessageRecordRoundAction : TLSendMessageActionBase + { + public const uint Signature = TLConstructors.TLSendMessageRecordRoundAction; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } + + public class TLSendMessageUploadRoundAction : TLSendMessageUploadDocumentAction + { + public new const uint Signature = TLConstructors.TLSendMessageUploadRoundAction; + + public TLInt Progress { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Progress = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), + Progress.ToBytes()); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Progress.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Progress = GetObject(input); + + return this; + } + } + + public class TLSendMessageUploadRoundAction66 : TLSendMessageUploadDocumentAction + { + public new const uint Signature = TLConstructors.TLSendMessageUploadRoundAction66; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + } +} diff --git a/Telegram.Api/TL/TLSentChangePhoneCode.cs b/Telegram.Api/TL/TLSentChangePhoneCode.cs new file mode 100755 index 0000000..bd432ae --- /dev/null +++ b/Telegram.Api/TL/TLSentChangePhoneCode.cs @@ -0,0 +1,49 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Text; + +namespace Telegram.Api.TL +{ + public class TLSentChangePhoneCode : TLObject + { + public const uint Signature = TLConstructors.TLSentChangePhoneCode; + + public TLString PhoneCodeHash { get; set; } + + public TLInt SendCodeTimeout { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhoneCodeHash = GetObject(bytes, ref position); + SendCodeTimeout = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneCodeHash.ToBytes(), + SendCodeTimeout.ToBytes()); + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine("SentChangePhoneCode"); + sb.AppendLine(string.Format("PhoneCodeHash " + PhoneCodeHash)); + sb.AppendLine(string.Format("SendCodeTimeout " + SendCodeTimeout)); + + return sb.ToString(); + } + } +} diff --git a/Telegram.Api/TL/TLSentCode.cs b/Telegram.Api/TL/TLSentCode.cs new file mode 100755 index 0000000..e8becbc --- /dev/null +++ b/Telegram.Api/TL/TLSentCode.cs @@ -0,0 +1,210 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Text; + +namespace Telegram.Api.TL +{ + [Flags] + public enum SentCodeFlags + { + PhoneRegistered = 0x1, // 0 + NextType = 0x2, // 1 + Timeout = 0x4, // 2 + TermsOfService = 0x8, // 3 + } + + public abstract class TLSentCodeBase : TLObject + { + public virtual TLBool PhoneRegistered { get; set; } + + public TLString PhoneCodeHash { get; set; } + + public TLInt SendCallTimeout { get; set; } + + public TLBool IsPassword { get; set; } + } + + public class TLSentCode80 : TLSentCode50 + { + public new const uint Signature = TLConstructors.TLSentCode80; + + protected TLTermsOfServiceBase _termsOfService; + + public TLTermsOfServiceBase TermsOfService + { + get { return _termsOfService; } + set { SetField(out _termsOfService, value, ref _flags, (int)SentCodeFlags.TermsOfService); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Type = GetObject(bytes, ref position); + PhoneCodeHash = GetObject(bytes, ref position); + NextType = GetObject(Flags, (int)SentCodeFlags.NextType, null, bytes, ref position); + SendCallTimeout = GetObject(Flags, (int)SentCodeFlags.Timeout, null, bytes, ref position); + _termsOfService = GetObject(Flags, (int)SentCodeFlags.TermsOfService, null, bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine("SentCode80"); + sb.AppendLine(string.Format("PhoneRegistered " + PhoneRegistered)); + sb.AppendLine(string.Format("Type " + Type)); + sb.AppendLine(string.Format("PhoneCodeHash " + PhoneCodeHash)); + sb.AppendLine(string.Format("NextType " + NextType)); + sb.AppendLine(string.Format("SendCallTimeout " + SendCallTimeout)); + sb.AppendLine(string.Format("TermsOfService " + TermsOfService)); + + return sb.ToString(); + } + } + + public class TLSentCode50 : TLSentCodeBase + { + public const uint Signature = TLConstructors.TLSentCode50; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override TLBool PhoneRegistered + { + get { return new TLBool(IsSet(Flags, (int)SentCodeFlags.PhoneRegistered)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)SentCodeFlags.PhoneRegistered); + } + } + } + + public TLSentCodeTypeBase Type { get; set; } + + public TLCodeTypeBase NextType { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Type = GetObject(bytes, ref position); + PhoneCodeHash = GetObject(bytes, ref position); + NextType = GetObject(Flags, (int)SentCodeFlags.NextType, null, bytes, ref position); + SendCallTimeout = GetObject(Flags, (int)SentCodeFlags.Timeout, null, bytes, ref position); + + return this; + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine("SentCode50"); + sb.AppendLine(string.Format("PhoneRegistered " + PhoneRegistered)); + sb.AppendLine(string.Format("Type " + Type)); + sb.AppendLine(string.Format("PhoneCodeHash " + PhoneCodeHash)); + sb.AppendLine(string.Format("NextType " + NextType)); + sb.AppendLine(string.Format("SendCallTimeout " + SendCallTimeout)); + + return sb.ToString(); + } + } + + public class TLSentCode : TLSentCodeBase + { + public const uint Signature = TLConstructors.TLSentCode; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhoneRegistered = GetObject(bytes, ref position); + PhoneCodeHash = GetObject(bytes, ref position); + SendCallTimeout = GetObject(bytes, ref position); + IsPassword = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneRegistered.ToBytes(), + PhoneCodeHash.ToBytes(), + SendCallTimeout.ToBytes(), + IsPassword.ToBytes()); + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine("SentCode"); + sb.AppendLine(string.Format("PhoneRegistered " + PhoneRegistered)); + sb.AppendLine(string.Format("PhoneCodeHash " + PhoneCodeHash)); + sb.AppendLine(string.Format("SendCallTimeout " + SendCallTimeout)); + sb.AppendLine(string.Format("IsPassword " + IsPassword)); + + return sb.ToString(); + } + } + + public class TLSentAppCode : TLSentCodeBase + { + public const uint Signature = TLConstructors.TLSentAppCode; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhoneRegistered = GetObject(bytes, ref position); + PhoneCodeHash = GetObject(bytes, ref position); + SendCallTimeout = GetObject(bytes, ref position); + IsPassword = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + PhoneRegistered.ToBytes(), + PhoneCodeHash.ToBytes(), + SendCallTimeout.ToBytes(), + IsPassword.ToBytes()); + } + + public override string ToString() + { + var sb = new StringBuilder(); + + sb.AppendLine("SentAppCode"); + sb.AppendLine(string.Format("PhoneRegistered " + PhoneRegistered)); + sb.AppendLine(string.Format("PhoneCodeHash " + PhoneCodeHash)); + sb.AppendLine(string.Format("SendCallTimeout " + SendCallTimeout)); + sb.AppendLine(string.Format("IsPassword " + IsPassword)); + + return sb.ToString(); + } + } +} diff --git a/Telegram.Api/TL/TLSentCodeType.cs b/Telegram.Api/TL/TLSentCodeType.cs new file mode 100755 index 0000000..79a73c7 --- /dev/null +++ b/Telegram.Api/TL/TLSentCodeType.cs @@ -0,0 +1,110 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public interface ILength + { + TLInt Length { get; set; } + } + + public abstract class TLSentCodeTypeBase : TLObject + { + } + + public class TLSentCodeTypeApp : TLSentCodeTypeBase, ILength + { + public const uint Signature = TLConstructors.TLSentCodeTypeApp; + + public TLInt Length { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Length.ToBytes()); + } + } + + public class TLSentCodeTypeSms : TLSentCodeTypeBase, ILength + { + public const uint Signature = TLConstructors.TLSentCodeTypeSms; + + public TLInt Length { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Length.ToBytes()); + } + } + + public class TLSentCodeTypeCall : TLSentCodeTypeBase, ILength + { + public const uint Signature = TLConstructors.TLSentCodeTypeCall; + + public TLInt Length { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Length = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Length.ToBytes()); + } + } + + public class TLSentCodeTypeFlashCall : TLSentCodeTypeBase + { + public const uint Signature = TLConstructors.TLSentCodeTypeFlashCall; + + public TLString Pattern { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Pattern = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Pattern.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLSentEncryptedFile.cs b/Telegram.Api/TL/TLSentEncryptedFile.cs new file mode 100755 index 0000000..820add8 --- /dev/null +++ b/Telegram.Api/TL/TLSentEncryptedFile.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLSentEncryptedFile : TLObject + { + public const uint Signature = TLConstructors.TLSentEncryptedFile; + + public TLInt Date { get; set; } + + public TLEncryptedFileBase EncryptedFile { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + EncryptedFile = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLSentEncryptedMessage.cs b/Telegram.Api/TL/TLSentEncryptedMessage.cs new file mode 100755 index 0000000..99b7720 --- /dev/null +++ b/Telegram.Api/TL/TLSentEncryptedMessage.cs @@ -0,0 +1,25 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLSentEncryptedMessage : TLObject + { + public const uint Signature = TLConstructors.TLSentEncryptedMessage; + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Date = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLSentMessage.cs b/Telegram.Api/TL/TLSentMessage.cs new file mode 100755 index 0000000..2bd8535 --- /dev/null +++ b/Telegram.Api/TL/TLSentMessage.cs @@ -0,0 +1,249 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLSentMessageBase : TLObject + { + public TLInt Id { get; set; } + public TLInt Date { get; set; } + public TLInt Pts { get; set; } + + public virtual TLInt GetSeq() + { + return null; + } + } + + public interface ISentMessageMedia + { + TLMessageMediaBase Media { get; set; } + } + + public class TLSentMessage : TLSentMessageBase + { + public const uint Signature = TLConstructors.TLSentMessage; + + public TLInt Seq { get; set; } + + public override TLInt GetSeq() + { + return Seq; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + Seq = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Date.ToBytes(), + Pts.ToBytes(), + Seq.ToBytes()); + } + } + + public class TLSentMessage24 : TLSentMessageBase, IMultiPts + { + public const uint Signature = TLConstructors.TLSentMessage24; + + public TLInt PtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Date.ToBytes(), + Pts.ToBytes(), + PtsCount.ToBytes()); + } + } + + public class TLSentMessage26 : TLSentMessage24, ISentMessageMedia + { + public new const uint Signature = TLConstructors.TLSentMessage26; + + public TLMessageMediaBase Media { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Media = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Date.ToBytes(), + Media.ToBytes(), + Pts.ToBytes(), + PtsCount.ToBytes()); + } + } + + public class TLSentMessage34 : TLSentMessage26 + { + public new const uint Signature = TLConstructors.TLSentMessage34; + + public TLVector Entities { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Media = GetObject(bytes, ref position); + Entities = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Date.ToBytes(), + Media.ToBytes(), + Entities.ToBytes(), + Pts.ToBytes(), + PtsCount.ToBytes()); + } + } + + public class TLSentMessageLink : TLSentMessage + { + public new const uint Signature = TLConstructors.TLSentMessageLink; + + public TLVector Links { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + Seq = GetObject(bytes, ref position); + Links = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Date.ToBytes(), + Pts.ToBytes(), + Seq.ToBytes(), + Links.ToBytes()); + } + } + + public class TLSentMessageLink24 : TLSentMessage24 + { + public new const uint Signature = TLConstructors.TLSentMessageLink24; + + public TLVector Links { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Links = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Date.ToBytes(), + Pts.ToBytes(), + PtsCount.ToBytes(), + Links.ToBytes()); + } + } + + public class TLSentMessageLink26 : TLSentMessageLink24, ISentMessageMedia + { + public new const uint Signature = TLConstructors.TLSentMessageLink26; + + public TLMessageMediaBase Media { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Media = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Links = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Date.ToBytes(), + Media.ToBytes(), + Pts.ToBytes(), + PtsCount.ToBytes(), + Links.ToBytes()); + } + } +} diff --git a/Telegram.Api/TL/TLServerDHInnerData.cs b/Telegram.Api/TL/TLServerDHInnerData.cs new file mode 100755 index 0000000..d15956d --- /dev/null +++ b/Telegram.Api/TL/TLServerDHInnerData.cs @@ -0,0 +1,52 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLServerDHInnerData : TLObject + { + public const uint Signature = TLConstructors.TLServerDHInnerData; + + public TLInt128 Nonce { get; set; } + + public TLInt128 ServerNonce { get; set; } + + public TLInt G { get; set; } + + public TLString DHPrime { get; set; } + + public TLString GA { get; set; } + + public TLInt ServerTime { get; set; } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Nonce.ToBytes(), + ServerNonce.ToBytes(), + G.ToBytes(), + DHPrime.ToBytes(), + GA.ToBytes(), + ServerTime.ToBytes()); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Nonce = GetObject(bytes, ref position); + ServerNonce = GetObject(bytes, ref position); + G = GetObject(bytes, ref position); + DHPrime = GetObject(bytes, ref position); + GA = GetObject(bytes, ref position); + ServerTime = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLServerDHParams.cs b/Telegram.Api/TL/TLServerDHParams.cs new file mode 100755 index 0000000..1c27bc0 --- /dev/null +++ b/Telegram.Api/TL/TLServerDHParams.cs @@ -0,0 +1,52 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLServerDHParamsBase : TLObject + { + public TLInt128 Nonce { get; set; } + + public TLInt128 ServerNonce { get; set; } + } + + public class TLServerDHParamsFail : TLServerDHParamsBase + { + public const uint Signature = TLConstructors.TLServerDHParamsFail; + + public TLInt128 NewNonceHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Nonce = GetObject(bytes, ref position); + ServerNonce = GetObject(bytes, ref position); + NewNonceHash = GetObject(bytes, ref position); + + return this; + } + } + + public class TLServerDHParamsOk : TLServerDHParamsBase + { + public const uint Signature = TLConstructors.TLServerDHParamsOk; + + public TLString EncryptedAnswer { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Nonce = GetObject(bytes, ref position); + ServerNonce = GetObject(bytes, ref position); + EncryptedAnswer = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLServerFile.cs b/Telegram.Api/TL/TLServerFile.cs new file mode 100755 index 0000000..711f362 --- /dev/null +++ b/Telegram.Api/TL/TLServerFile.cs @@ -0,0 +1,36 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLServerFile : TLObject + { + public const uint Signature = TLConstructors.TLServerFile; + + public TLLong MD5Checksum { get; set; } + + public TLInputMediaBase Media { get; set; } + + public override TLObject FromStream(Stream input) + { + MD5Checksum = GetObject(input); + Media = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + MD5Checksum.ToStream(output); + Media.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLShippingOption.cs b/Telegram.Api/TL/TLShippingOption.cs new file mode 100755 index 0000000..eeba8a1 --- /dev/null +++ b/Telegram.Api/TL/TLShippingOption.cs @@ -0,0 +1,35 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLShippingOption : TLObject + { + public const uint Signature = TLConstructors.TLShippingOption; + + public TLString Id { get; set; } + + public TLString Title { get; set; } + + public TLVector Prices { get; set; } + + #region Additional + public bool IsSelected { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + Prices = GetObject>(bytes, ref position); + + return this; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLSignatures.cs b/Telegram.Api/TL/TLSignatures.cs new file mode 100755 index 0000000..d84fb1e --- /dev/null +++ b/Telegram.Api/TL/TLSignatures.cs @@ -0,0 +1,1274 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public static class TLConstructors + { + public const uint TLUpdateUserBlocked = 0x80ece81a; + public const uint TLUpdateNotifySettings = 0xbec268ef; + public const uint TLNotifyPeer = 0x9fd40bd8; + public const uint TLNotifyUsers = 0xb4c83b4c; + public const uint TLNotifyChats = 0xc007cec3; + public const uint TLNotifyAll = 0x74d07c60; + public const uint TLDecryptedMessageActionReadMessages = 0xc4f40be; + public const uint TLDecryptedMessageActionDeleteMessages = 0x65614304; + public const uint TLDecryptedMessageActionScreenshotMessages = 0x8ac1f475; + public const uint TLDecryptedMessageActionFlushHistory = 0x6719e45c; + public const uint TLDecryptedMessageActionNotifyLayer = 0xf3048883; + public const uint TLDecryptedMessageLayer = 0x99a438cf; + public const uint TLSupport = 0x17c6b5f6; + public const uint TLDecryptedMessageMediaAudio = 0x6080758f; + public const uint TLDecryptedMessageMediaDocument = 0xb095434b; + public const uint TLInputAudioFileLocation = 0x74dc404d; + public const uint TLInputDocumentFileLocation = 0x4e45abe9; + public const uint TLInputMediaUploadedDocument = 0x34e794bd; + public const uint TLInputMediaUploadedThumbDocument = 0x3e46de5d; + public const uint TLInputMediaDocument = 0xd184e841; + public const uint TLInputMediaAudio = 0x89938781; + public const uint TLInputMediaUploadedAudio = 0x4e498cab; + public const uint TLInputAudio = 0x77d440ff; + public const uint TLInputAudioEmpty = 0xd95adc84; + public const uint TLInputDocument = 0x18798952; + public const uint TLInputDocumentEmpty = 0x72f0eaae; + public const uint TLMessageMediaAudio = 0xc6b68300; + public const uint TLMessageMediaDocument = 0x2fda2204; + public const uint TLAudioEmpty = 0x586988d8; + public const uint TLAudio = 0xc7ac6496; + public const uint TLDocumentEmpty = 0x36f8c871; + public const uint TLDocument = 0x9efc6326; + public const uint TLUpdateChatParticipantAdd = 0x3a0eeb22; + public const uint TLUpdateChatParticipantDelete = 0x6e5f8c22; + public const uint TLInputEncryptedFileBigUploaded = 0x2dc173c8; + public const uint TLInputFileBig = 0xfa4f0bb5; + public const uint TLDecryptedMessage = 0x1f814f1f; + public const uint TLDecryptedMessageService = 0xaa48327d; + public const uint TLUpdateNewEncryptedMessage = 0x12bcbd9a; + public const uint TLUpdateEncryptedChatTyping = 0x1710f156; + public const uint TLUpdateEncryption = 0xb4a2e88d; + public const uint TLUpdateEncryptedMessagesRead = 0x38fe25b7; + public const uint TLEncryptedChatEmpty = 0xab7ec0a0; + public const uint TLEncryptedChatWaiting = 0x3bf703dc; + public const uint TLEncryptedChatRequested = 0xc878527e; + public const uint TLEncryptedChat = 0xfa56ce36; + public const uint TLEncryptedChatDiscarded = 0x13d6dd27; + public const uint TLInputEncryptedChat = 0xf141b5e1; + public const uint TLInputEncryptedFileEmpty = 0x1837c364; + public const uint TLInputEncryptedFileUploaded = 0x64bd0306; + public const uint TLInputEncryptedFile = 0x5a17b5e5; + public const uint TLInputEncryptedFileLocation = 0xf5235d55; + public const uint TLEncryptedFileEmpty = 0xc21f497e; + public const uint TLEncryptedFile = 0x4a70994c; + public const uint TLEncryptedMessage = 0xed18c118; + public const uint TLEncryptedMessageService = 0x23734b06; + public const uint TLDecryptedMessageActionSetMessageTTL = 0xa1733aec; + public const uint TLDecryptedMessageMediaEmpty = 0x089f5c4a; + public const uint TLDecryptedMessageMediaPhoto = 0x32798a8c; + public const uint TLDecryptedMessageMediaVideo = 0x4cee6ef3; + public const uint TLDecryptedMessageMediaGeoPoint = 0x35480a59; + public const uint TLDecryptedMessageMediaContact = 0x588a0a97; + public const uint TLDHConfig = 0x2c221edd; + public const uint TLDHConfigNotModified = 0xc0e24635; + public const uint TLSentEncryptedMessage = 0x560f8935; + public const uint TLSentEncryptedFile = 0x9493ff32; + public const uint TLRPCAnswerUnknown = 0x5e2ad36e; + public const uint TLRPCAnswerDroppedRunning = 0xcd78e586; + public const uint TLRPCAnswerDropped = 0xa43ad8b7; + public const uint TLMessageDetailedInfo = 0x276d3ec6; + public const uint TLMessageNewDetailedInfo = 0x809db6df; + public const uint TLMessagesAllInfo = 0x8cc0d131; + public const uint TLInvokeAfterMsg = 0xcb9f372d; + public const uint TLDifferenceEmpty = 0x5d75a138; + public const uint TLDifference = 0xf49ca0; + public const uint TLDifferenceSlice = 0xa8fb1981; + public const uint TLUpdateNewMessage = 0x013abdb3; + public const uint TLUpdateMessageId = 0x4e90bfd6; + public const uint TLUpdateReadMessages = 0xc6649e31; + public const uint TLUpdateDeleteMessages = 0xa92bfe26; + public const uint TLUpdateRestoreMessages = 0xd15de04d; + public const uint TLUpdateUserTyping = 0x6baa8508; + public const uint TLUpdateChatUserTyping = 0x3c46cfe6; + public const uint TLUpdateChatParticipants = 0x07761198; + public const uint TLUpdateUserStatus = 0x1bfbd823; + public const uint TLUpdateUserName = 0xa7332b73; + public const uint TLUpdateUserPhoto = 0x95313b0c; + public const uint TLUpdateContactRegistered = 0x2575bbb9; + public const uint TLUpdateContactLink = 0x51a48a9a; + public const uint TLUpdateActivation = 0x6f690963; + public const uint TLUpdateNewAuthorization = 0x8f06529a; + public const uint TLUpdateDCOptions = 0x8e5e9873; + public const uint TLUpdatesTooLong = 0xe317af7e; + public const uint TLUpdateShortMessage = 0xd3f45784; + public const uint TLUpdateShortChatMessage = 0x2b2fbd4e; + public const uint TLUpdateShort = 0x78d4dec1; + public const uint TLUpdatesCombined = 0x725b04c3; + public const uint TLUpdates = 0x74ae4240; + public const uint TLFutureSalt = 0x0949d9dc; + public const uint TLFutureSalts = 0xae500895; + public const uint TLGzipPacked = 0x3072cfa1; + public const uint TLState = 0xa56c2a3e; + public const uint TLFileTypeUnknown = 0xaa963b05; + public const uint TLFileTypeJpeg = 0x7efe0e; + public const uint TLFileTypeGif = 0xcae1aadf; + public const uint TLFileTypePng = 0x0a4f63c0; + public const uint TLFileTypeMp3 = 0x528a0677; + public const uint TLFileTypeMov = 0x4b09ebbc; + public const uint TLFileTypePartial = 0x40bc6f52; + public const uint TLFileTypeMp4 = 0xb3cea0e4; + public const uint TLFileTypeWebp = 0x1081464c; + public const uint TLFile = 0x096a18d5; + public const uint TLInputFileLocation = 0x14637196; + public const uint TLInputVideoFileLocation = 0x3d0364ec; + public const uint TLInviteText = 0x18cb9f78; + public const uint TLDHGenOk = 0x3bcbf734; + public const uint TLDHGenRetry = 0x46dc1fb9; + public const uint TLDHGenFail = 0xa69dae02; + public const uint TLServerDHInnerData = 0xb5890dba; + public const uint TLServerDHParamsFail = 0x79cb045d; + public const uint TLServerDHParamsOk = 0xd0e8075c; + public const uint TLPQInnerData = 0x83c95aec; + public const uint TLPQInnerDataDC = 0xa9f55f95; + public const uint TLResPQ = 0x05162463; + public const uint TLContactsBlocked = 0x1c138d15; + public const uint TLContactsBlockedSlice = 0x900802a1; + public const uint TLContactBlocked = 0x561bc879; + public const uint TLImportedContacts = 0xad524315; + public const uint TLImportedContact = 0xd0028438; + public const uint TLInputContact = 0xf392b7f4; + public const uint TLContactStatus = 0xaa77b873; + public const uint TLForeignLinkUnknown = 0x133421f8; + public const uint TLForeignLinkRequested = 0xa7801f47; + public const uint TLForeignLinkMutual = 0x1bea8ce1; + public const uint TLMyLinkEmpty = 0xd22a1c60; + public const uint TLMyLinkRequested = 0x6c69efee; + public const uint TLMyLinkContact = 0xc240ebd9; + public const uint TLLink = 0xeccea3f5; + public const uint TLUserFull = 0x771095da; + public const uint TLPhotos = 0x8dca6aa5; + public const uint TLPhotosSlice = 0x15051f54; + public const uint TLPhotosPhoto = 0x20212ca8; + public const uint TLInputPeerNotifyEventsEmpty = 0xf03064d8; + public const uint TLInputPeerNotifyEventsAll = 0xe86a2c74; + public const uint TLInputPeerNotifySettings = 0x46a2ce98; + public const uint TLInputNotifyPeer = 0xb8bc5b0c; + public const uint TLInputNotifyUsers = 0x193b4417; + public const uint TLInputNotifyChats = 0x4a95e84e; + public const uint TLInputNotifyAll = 0xa429b886; + public const uint TLInputUserEmpty = 0xb98886cf; + public const uint TLInputUserSelf = 0xf7c1b13f; + public const uint TLInputUserContact = 0x86e94f65; + public const uint TLInputUserForeign = 0x655e74ff; + public const uint TLInputPhotoCropAuto = 0xade6b004; + public const uint TLInputPhotoCrop = 0xd9915325; + public const uint TLInputChatPhotoEmpty = 0x1ca48f57; + public const uint TLInputChatUploadedPhoto = 0x94254732; + public const uint TLInputChatPhoto = 0xb2e1bf08; + public const uint TLMessagesChatFull = 0xe5d7d19c; + public const uint TLChatFull = 0x630e61be; + public const uint TLChatParticipant = 0xc8d7493e; + public const uint TLChatParticipantsForbidden = 0x0fd2bb8a; + public const uint TLChatParticipants = 0x7841b415; + public const uint TLPeerNotifySettingsEmpty = 0x70a68512; + public const uint TLPeerNotifySettings = 0x8d5e11ee; + public const uint TLPeerNotifyEventsEmpty = 0xadd53cb3; + public const uint TLPeerNotifyEventsAll = 0x6d1ded88; + public const uint TLChats = 0x8150cbd8; + public const uint TLMessages = 0x8c718e87; + public const uint TLMessagesSlice = 0x0b446ae3; + public const uint TLExportedAuthorization = 0xdf969c2d; + public const uint TLInputFile = 0xf52ff27f; + public const uint TLInputPhotoEmpty = 0x1cd7bf0d; + public const uint TLInputPhoto = 0xfb95c6c4; + public const uint TLInputGeoPointEmpty = 0xe4c123d6; + public const uint TLInputGeoPoint = 0xf3b7acc9; + public const uint TLInputVideoEmpty = 0x5508ec75; + public const uint TLInputVideo = 0xee579652; + public const uint TLInputMediaEmpty = 0x9664f57f; + public const uint TLInputMediaUploadedPhoto = 0x2dc53a7d; + public const uint TLInputMediaPhoto = 0x8f2ab2ec; + public const uint TLInputMediaGeoPoint = 0xf9c44144; + public const uint TLInputMediaContact = 0xa6e45987; + public const uint TLInputMediaUploadedVideo = 0x133ad6f6; + public const uint TLInputMediaUploadedThumbVideo = 0x9912dabf; + public const uint TLInputMediaVideo = 0x7f023ae6; + public const uint TLInputMessageFilterEmpty = 0x57e2f66c; + public const uint TLInputMessageFilterPhoto = 0x9609a51c; + public const uint TLInputMessageFilterVideo = 0x9fc00e65; + public const uint TLInputMessageFilterPhotoVideo = 0x56e9f0e4; + public const uint TLInputMessageFilterPhotoVideoDocument = 0xd95e73bb; + public const uint TLInputMessageFilterDocument = 0x9eddf188; + public const uint TLInputMessageFilterAudio = 0xcfc87522; + public const uint TLInputMessageFilterAudioDocuments = 0x5afbf764; + public const uint TLInputMessageFilterUrl = 0x7ef0dd87; + public const uint TLStatedMessage = 0xd07ae726; + public const uint TLStatedMessageLink = 0xa9af2881; + public const uint TLStatedMessages = 0x969478bb; + public const uint TLStatedMessagesLinks = 0x3e74f5c6; + public const uint TLAffectedHistory = 0xb7de36f2; + public const uint TLNull = 0x56730bcc; + public const uint TLChatEmpty = 0x9ba2d800; + public const uint TLChat = 0x6e9c9bc7; + public const uint TLChatForbidden = 0xfb0ccc41; + public const uint TLSentMessage = 0xd1f4d35c; + public const uint TLSentMessageLink = 0xe9db4a3f; + public const uint TLMessageEmpty = 0x83e5de54; + public const uint TLMessage = 0x22eb6aba; + public const uint TLMessageForwarded = 0x05f46804; + public const uint TLMessageService = 0x9f8d60bb; + public const uint TLMessageMediaEmpty = 0x3ded6320; + public const uint TLMessageMediaPhoto = 0xc8c45a2a; + public const uint TLMessageMediaVideo = 0xa2d24290; + public const uint TLMessageMediaGeo = 0x56e0d474; + public const uint TLMessageMediaContact = 0x5e7d2f39; + public const uint TLMessageMediaUnsupported = 0x29632a36; + public const uint TLMessageActionEmpty = 0xb6aef7b0; + public const uint TLMessageActionChatCreate = 0xa6638b9a; + public const uint TLMessageActionChatEditTitle = 0xb5a1ce5a; + public const uint TLMessageActionChatEditPhoto = 0x7fcb13a8; + public const uint TLMessageActionChatDeletePhoto = 0x95e3fbef; + public const uint TLMessageActionChatAddUser = 0x5e3cfc4b; + public const uint TLMessageActionChatDeleteUser = 0xb2ae9b0c; + public const uint TLPhotoEmpty = 0x2331b22d; + public const uint TLPhoto = 0x22b56751; + public const uint TLPhotoSizeEmpty = 0x0e17e23c; + public const uint TLPhotoSize = 0x77bfb61b; + public const uint TLPhotoCachedSize = 0xe9a734fa; + public const uint TLVideoEmpty = 0xc10658a8; + public const uint TLVideo = 0x388fa391; + public const uint TLGeoPointEmpty = 0x1117dd5f; + public const uint TLGeoPoint = 0x2049d70c; + public const uint TLDialogs = 0x15ba6c40; + public const uint TLDialogsSlice = 0x71e094f3; + public const uint TLDialog = 0xab3a99ac; + public const uint TLInputPeerEmpty = 0x7f3b18ea; + public const uint TLInputPeerSelf = 0x7da07ec9; + public const uint TLInputPeerContact = 0x1023dbe8; + public const uint TLInputPeerForeign = 0x9b447325; + public const uint TLInputPeerChat = 0x179be863; + public const uint TLPeerUser = 0x9db1bc6d; + public const uint TLPeerChat = 0xbad0e5bb; + public const uint TLVector = 0x1cb5c415; + public const uint TLUserStatusEmpty = 0x09d05049; + public const uint TLUserStatusOnline = 0xedb93949; + public const uint TLUserStatusOffline = 0x8c703f; + public const uint TLChatPhotoEmpty = 0x37c1011c; + public const uint TLChatPhoto = 0x6153276a; + public const uint TLUserProfilePhotoEmpty = 0x4f11bae1; + public const uint TLUserProfilePhoto = 0xd559d8c8; + public const uint TLUserEmpty = 0x200250ba; + public const uint TLUserSelf = 0x720535ec; + public const uint TLUserContact = 0xf2fb8319; + public const uint TLUserRequest = 0x22e8ceb0; + public const uint TLUserForeign = 0x5214c89d; + public const uint TLUserDeleted = 0xb29ad7cc; + public const uint TLSentCode = 0xefed51d9; + public const uint TLRPCResult = 0xf35c6d01; + public const uint TLRPCError = 0x2144ca19; + public const uint TLRPCReqError = 0x7ae432f5; + public const uint TLNewSessionCreated = 0x9ec20908; + public const uint TLNearestDC = 0x8e1a1775; + public const uint TLMessagesAcknowledgment = 0x62d6b459; + public const uint TLContainer = 0x73f1f8dc; + public const uint TLFileLocationUnavailable = 0x7c596b46; + public const uint TLFileLocation = 0x53d69076; + public const uint TLDCOption = 0x2ec2a43c; + public const uint TLContacts = 0x6f8b8cb2; + public const uint TLContactsNotModified = 0xb74ba9d2; + public const uint TLContact = 0xf911c994; + public const uint TLConfig = 0x2e54dd74; + public const uint TLConfig23 = 0x7dae33e0; + public const uint TLCheckedPhone = 0xe300cc3b; + public const uint TLBadServerSalt = 0xedab447b; + public const uint TLBadMessageNotification = 0xa7eff811; + public const uint TLAuthorization = 0xf6b673a4; + public const uint TLWallPaper = 0xccb03657; + public const uint TLWallPaperSolid = 0x63117f24; + public const uint TLPing = 0x7abe77ec; + public const uint TLPong = 0x347773c5; + public const uint TLPingDelayDisconnect = 0xf3427b8c; + public const uint TLContactFound = 0xea879f95; + public const uint TLContactsFound = 0x566000e; + + // layer 16 + public const uint TLSentAppCode = 0xe325edcf; + + // layer 17 + public const uint TLSendMessageTypingAction = 0x16bf744e; + public const uint TLSendMessageCancelAction = 0xfd5ec8f5; + public const uint TLSendMessageRecordVideoAction = 0xa187d66f; + public const uint TLSendMessageUploadVideoAction = 0x92042ff7; + public const uint TLSendMessageRecordAudioAction = 0xd52f73f7; + public const uint TLSendMessageUploadAudioAction = 0xe6ac8a6f; + public const uint TLSendMessageUploadPhotoAction = 0x990a3c1a; + public const uint TLSendMessageUploadDocumentAction = 0x8faee98e; + public const uint TLSendMessageGeoLocationAction = 0x176f8ba1; + public const uint TLSendMessageChooseContactAction = 0x628cbc6f; + public const uint TLUpdateUserTyping17 = 0x5c486927; + public const uint TLUpdateChatUserTyping17 = 0x9a65ea1f; + public const uint TLMessage17 = 0x567699b3; + public const uint TLMessageForwarded17 = 0xa367e716; + public const uint TLMessageService17 = 0x1d86f70e; + + // layer 17 encrypted + public const uint TLDecryptedMessage17 = 0x204d3878; + public const uint TLDecryptedMessageService17 = 0x73164160; + public const uint TLDecryptedMessageMediaVideo17 = 0x524a415d; + public const uint TLDecryptedMessageMediaAudio17 = 0x57e0a9cb; + public const uint TLDecryptedMessageLayer17 = 0x1be31789; + public const uint TLDecryptedMessageActionResend = 0x511110b0; + public const uint TLDecryptedMessageActionTyping = 0xccb27641; + + // layer 18 + public const uint TLUpdateServiceNotification = 0x382dd3e4; + public const uint TLUserSelf18 = 0x7007b451; + public const uint TLUserContact18 = 0xcab35e18; + public const uint TLUserRequest18 = 0xd9ccc4ef; + public const uint TLUserForeign18 = 0x75cf7a8; + public const uint TLUserDeleted18 = 0xd6016d7a; + + // layer 19 + public const uint TLUserStatusRecently = 0xe26f42f1; + public const uint TLUserStatusLastWeek = 0x7bf09fc; + public const uint TLUserStatusLastMonth = 0x77ebc742; + public const uint TLContactStatus19 = 0xd3680c61; + public const uint TLUpdatePrivacy = 0xee3b272a; + public const uint TLInputPrivacyKeyStatusTimestamp = 0x4f96cb18; + public const uint TLPrivacyKeyStatusTimestamp = 0xbc2eab30; + public const uint TLInputPrivacyValueAllowContacts = 0xd09e07b; + public const uint TLInputPrivacyValueAllowAll = 0x184b35ce; + public const uint TLInputPrivacyValueAllowUsers = 0x131cc67f; + public const uint TLInputPrivacyValueDisallowContacts = 0xba52007; + public const uint TLInputPrivacyValueDisallowAll = 0xd66b66c9; + public const uint TLInputPrivacyValueDisallowUsers = 0x90110467; + public const uint TLPrivacyValueAllowContacts = 0xfffe1bac; + public const uint TLPrivacyValueAllowAll = 0x65427b82; + public const uint TLPrivacyValueAllowUsers = 0x4d5bbe0c; + public const uint TLPrivacyValueDisallowContacts = 0xf888fa1a; + public const uint TLPrivacyValueDisallowAll = 0x8b73e763; + public const uint TLPrivacyValueDisallowUsers = 0xc7f49b7; + public const uint TLPrivacyRules = 0x554abb6f; + public const uint TLAccountDaysTTL = 0xb8d0afdf; + + // layer 20 + public const uint TLSentChangePhoneCode = 0xa4f58c4c; + public const uint TLUpdateUserPhone = 0x12b9417b; + + // layer 20 encrypted + public const uint TLDecryptedMessageActionRequestKey = 0xf3c9611b; + public const uint TLDecryptedMessageActionAcceptKey = 0x6fe1735b; + public const uint TLDecryptedMessageActionAbortKey = 0xdd05ec6b; + public const uint TLDecryptedMessageActionCommitKey = 0xec2e0b9b; + public const uint TLDecryptedMessageActionNoop = 0xa82fdd63; + + // layer 21 + + // layer 22 + public const uint TLInputMediaUploadedDocument22 = 0xffe76b78; + public const uint TLInputMediaUploadedThumbDocument22 = 0x41481486; + public const uint TLDocument22 = 0xf9a39f4f; + public const uint TLDocumentAttributeImageSize = 0x6c37c15c; + public const uint TLDocumentAttributeAnimated = 0x11b58939; + public const uint TLDocumentAttributeSticker = 0xfb0a5727; + public const uint TLDocumentAttributeVideo = 0x5910cccb; + public const uint TLDocumentAttributeAudio = 0x51448e5; + public const uint TLDocumentAttributeFileName = 0x15590068; + public const uint TLStickersNotModified = 0xf1749a22; + public const uint TLStickers = 0x8a8ecd32; + public const uint TLStickerPack = 0x12b299d4; + public const uint TLAllStickersNotModified = 0xe86602c3; + public const uint TLAllStickers = 0xdcef3102; + + // layer 23 + public const uint TLDisabledFeature = 0xae636f24; + + // layer 23 encrypted + public const uint TLDecryptedMessageMediaExternalDocument = 0xfa95b0dd; + + // layer 24 + public const uint TLUpdateNewMessage24 = 0x1f2b0afd; + public const uint TLUpdateReadMessages24 = 0x2e5ab668; + public const uint TLUpdateDeleteMessages24 = 0xa20db0e5; + public const uint TLUpdateShortMessage24 = 0xb87da3b1; + public const uint TLUpdateShortChatMessage24 = 0x20e85ded; + public const uint TLUpdateReadHistoryInbox = 0x9961fd5c; + public const uint TLUpdateReadHistoryOutbox = 0x2f2f21bf; + public const uint TLDialog24 = 0xc1dd804a; + public const uint TLStatedMessages24 = 0x7d84b48; + public const uint TLStatedMessagesLinks24 = 0x51be5d19; + public const uint TLStatedMessage24 = 0x96240c6a; + public const uint TLStatedMessageLink24 = 0x948a288; + public const uint TLSentMessage24 = 0x900eac40; + public const uint TLSentMessageLink24 = 0xe923400d; + public const uint TLAffectedMessages = 0x84d19185; + public const uint TLAffectedHistory24 = 0xb45c69d1; + public const uint TLMessageMediaUnsupported24 = 0x9f84f49e; + public const uint TLChats24 = 0x64ff9fd5; + public const uint TLUserSelf24 = 0x1c60e608; + public const uint TLCheckedPhone24 = 0x811ea28e; + public const uint TLContactLinkUnknown = 0x5f4f9247; + public const uint TLContactLinkNone = 0xfeedd3ad; + public const uint TLContactLinkHasPhone = 0x268f3f59; + public const uint TLContactLink = 0xd502c2d0; + public const uint TLUpdateContactLink24 = 0x9d2e67c5; + public const uint TLLink24 = 0x3ace484c; + public const uint TLConfig24 = 0x3e6f732a; + + // layer 25 + public const uint TLMessage25 = 0xa7ab1991; + public const uint TLDocumentAttributeSticker25 = 0x994c9882; + public const uint TLUpdatesShortMessage25 = 0xed5c2127; + public const uint TLUpdatesShortChatMessage25 = 0x52238b3c; + + // layer 26 + public const uint TLSentMessage26 = 0x4c3d47f3; + public const uint TLSentMessageLink26 = 0x35a1a663; + public const uint TLConfig26 = 0x68bac247; + public const uint TLUpdateWebPage = 0x2cc36971; + public const uint TLWebPageEmpty = 0xeb1477e8; + public const uint TLWebPagePending = 0xc586da1c; + public const uint TLWebPage = 0xa31ea0b5; + public const uint TLMessageMediaWebPage = 0xa32dd600; + public const uint TLAccountAuthorization = 0x7bf2e6f6; + public const uint TLAccountAuthorizations = 0x1250abde; + + // layer 27 + public const uint TLNoPassword = 0x96dabc18; + public const uint TLPassword = 0x7c18141c; + public const uint TLPasswordSettings = 0xb7b72ab3; + public const uint TLPasswordInputSettings = 0x86916deb; //0xbcfc532c; + public const uint TLPasswordRecovery = 0x137948a5; + + // layer 28 + public const uint TLInvokeWithoutUpdates = 0xbf9459b7; + public const uint TLInputMediaUploadedPhoto28 = 0xf7aff1c0; + public const uint TLInputMediaPhoto28 = 0xe9bfb4f3; + public const uint TLInputMediaUploadedVideo28 = 0xe13fd4bc; + public const uint TLInputMediaUploadedThumbVideo28 = 0x96fb97dc; + public const uint TLInputMediaVideo28 = 0x936a4ebd; + public const uint TLSendMessageUploadVideoAction28 = 0xe9763aec; + public const uint TLSendMessageUploadAudioAction28 = 0xf351d7ab; + public const uint TLSendMessageUploadDocumentAction28 = 0xaa0cd9e4; + public const uint TLSendMessageUploadPhotoAction28 = 0xd1d34a26; + public const uint TLInputMediaVenue = 0x2827a81a; + public const uint TLMessageMediaVenue = 0x7912b71f; + public const uint TLReceivedNotifyMessage = 0xa384b779; + public const uint TLChatInviteEmpty = 0x69df3769; + public const uint TLChatInviteExported = 0xfc2e05bc; + public const uint TLChatInviteAlready = 0x5a686d7c; + public const uint TLChatInvite = 0xce917dcd; + public const uint TLMessageActionChatJoinedByLink = 0xf89cf5e8; + public const uint TLUpdateReadMessagesContents = 0x68c13933; + public const uint TLChatFull28 = 0xcade0791; + public const uint TLConfig28 = 0x4e32b894; + public const uint TLMessageMediaPhoto28 = 0x3d8ce53d; + public const uint TLMessageMediaVideo28 = 0x5bcf1675; + public const uint TLPhoto28 = 0xc3838076; + public const uint TLVideo28 = 0xee9f4a4d; + + // layer 29 + public const uint TLDocumentAttributeSticker29 = 0x3a556302; + public const uint TLAllStickers29 = 0x5ce352ec; + public const uint TLInputStickerSetEmpty = 0xffb62b95; + public const uint TLInputStickerSetId = 0x9de7a269; + public const uint TLInputStickerSetShortName = 0x861cc8a0; + public const uint TLStickerSet = 0xa7a43b17; + public const uint TLMessagesStickerSet = 0xb60a24a6; + + // layer 30 + public const uint TLDCOption30 = 0x5d8c6cc; + + // layer 31 + public const uint TLAuthorization31 = 0xff036af1; + public const uint TLMessage31 = 0xc3060325; + public const uint TLChatFull31 = 0x2e02a614; + public const uint TLUserFull31 = 0x5a89ac5b; + public const uint TLUser = 0x22e49072; + public const uint TLBotCommand = 0xc27ac8c7; + public const uint TLBotInfoEmpty = 0xbb2e37ce; + public const uint TLBotInfo = 0x9cf585d; + public const uint TLKeyboardButton = 0xa2fa4880; + public const uint TLKeyboardButtonRow = 0x77608b83; + public const uint TLReplyKeyboardMarkup = 0x3502758c; + public const uint TLReplyKeyboardHide = 0xa03e5b85; + public const uint TLReplyKeyboardForceReply = 0xf4108aa0; + + // layer 32 + public const uint TLDocumentAttributeAudio32 = 0xded218e0; + public const uint TLAllStickers32 = 0xd51dafdb; + public const uint TLStickerSet32 = 0xcd303b41; + + // layer 33 + public const uint TLInputPeerUser = 0x7b8e7de6; + public const uint TLInputUser = 0xd8292816; + public const uint TLPhoto33 = 0xcded42fe; + public const uint TLVideo33 = 0xf72887d3; + public const uint TLAudio33 = 0xf9e35055; + public const uint TLAppChangelogEmpty = 0xaf7e0394; + public const uint TLAppChangelog = 0x4668e6bd; + + // layer 34 + public const uint TLMessageEntityUnknown = 0xbb92ba95; + public const uint TLMessageEntityMention = 0xfa04579d; + public const uint TLMessageEntityHashtag = 0x6f635b0d; + public const uint TLMessageEntityBotCommand = 0x6cef8ac7; + public const uint TLMessageEntityUrl = 0x6ed02538; + public const uint TLMessageEntityEmail = 0x64e475c2; + public const uint TLMessageEntityBold = 0xbd610bc9; + public const uint TLMessageEntityItalic = 0x826f8b60; + public const uint TLMessageEntityCode = 0x28a20571; + public const uint TLMessageEntityPre = 0x73924be0; + public const uint TLMessageEntityTextUrl = 0x76a6d327; + public const uint TLMessage34 = 0xf07814c8; + public const uint TLSentMessage34 = 0x8a99d8e0; + public const uint TLUpdatesShortMessage34 = 0x3f32d858; + public const uint TLUpdatesShortChatMessage34 = 0xf9409b3d; + + // layer 35 + public const uint TLWebPage35 = 0xca820ed7; + + // layer 36 + public const uint TLInputMediaUploadedVideo36 = 0x82713fdf; + public const uint TLInputMediaUploadedThumbVideo36 = 0x7780ddf9; + public const uint TLMessage36 = 0x2bebfa86; + public const uint TLUpdatesShortSentMessage = 0x11f1331c; + + // layer 37 + public const uint TLChatParticipantsForbidden37 = 0xfc900c2b; + public const uint TLUpdateChatParticipantAdd37 = 0xea4b0e5c; + public const uint TLUpdateWebPage37 = 0x7f891213; + + // layer 40 + public const uint TLInputPeerChannel = 0x20adaef8; + public const uint TLPeerChannel = 0xbddde532; + public const uint TLChat40 = 0x7312bc48; + public const uint TLChatForbidden40 = 0x7328bdb; + public const uint TLChannel = 0x678e9587; //0x1bcc63f2; + public const uint TLChannelForbidden = 0x2d85832c; + public const uint TLChannelFull = 0xfab31aa3; //0xf6945b65; + public const uint TLChannelParticipants40 = 0xb561ad0c; + public const uint TLMessage40 = 0x5ba66c13; + public const uint TLMessageService40 = 0xc06b9607; + public const uint TLMessageActionChannelCreate = 0x95d2ac92; + public const uint TLMessageActionToggleComments = 0xf2863903; + public const uint TLDialogChannel = 0x5b8496b2; + public const uint TLChannelMessages = 0xbc0f17bc; + public const uint TLUpdateChannelTooLong = 0x60946422; + public const uint TLUpdateChannelGroup = 0xc36c1e3c; + public const uint TLUpdateNewChannelMessage = 0x62ba04d9; + public const uint TLUpdateReadChannelInbox = 0x4214f37f;// 0x87b87b7d; + public const uint TLUpdateDeleteChannelMessages = 0xc37521c9;// 0x11da3046; + public const uint TLUpdateChannelMessageViews = 0x98a12b4b;//0xf3349b09; + public const uint TLUpdateChannel = 0xb6d45656; + public const uint TLUpdatesShortMessage40 = 0xf7d91a46; + public const uint TLUpdatesShortChatMessage40 = 0xcac7fdd2; + public const uint TLContactsFound40 = 0x1aa1f784; + //public const uint TLInputChatEmpty = 0xd9ff343c; + //public const uint TLInputChat = 0x43a5b9c3; + public const uint TLInputChannel = 0xafeb712e;// 0x30c6ce73; + public const uint TLInputChannelEmpty = 0xee8c1e86; + public const uint TLMessageRange = 0xae30253; + public const uint TLMessageGroup = 0xe8346f53; + public const uint TLChannelDifferenceEmpty = 0x3e11affb; + public const uint TLChannelDifferenceTooLong = 0x5e167646; + public const uint TLChannelDifference = 0x2064674e; + public const uint TLChannelMessagesFilterEmpty = 0x94d42ee7; + public const uint TLChannelMessagesFilter = 0xcd77d957; + public const uint TLChannelMessagesFilterCollapsed = 0xfa01232e; + public const uint TLResolvedPeer = 0x7f077ad9; + public const uint TLChannelParticipant = 0x15ebac1d; + public const uint TLChannelParticipantSelf = 0xa3289a6d; + public const uint TLChannelParticipantModerator = 0x91057fef; + public const uint TLChannelParticipantEditor = 0x98192d61; + public const uint TLChannelParticipantKicked = 0x8cc5e69a; + public const uint TLChannelParticipantCreator = 0xe3e2e1f9; + public const uint TLChannelParticipantsRecent = 0xde3f3c79; + public const uint TLChannelParticipantsAdmins = 0xb4608969; + public const uint TLChannelParticipantsKicked = 0x3c37bb7a; + public const uint TLChannelRoleEmpty = 0xb285a0c6; + public const uint TLChannelRoleModerator = 0x9618d975; + public const uint TLChannelRoleEditor = 0x820bfe8c; + public const uint TLChannelParticipants = 0xf56ee2a8; + public const uint TLChannelsChannelParticipant = 0xd0d9b163; + public const uint TLChatInvite40 = 0x93e99b60; + public const uint TLChatParticipants40 = 0x3f460fed; + public const uint TLChatParticipantCreator = 0xda13538a; + public const uint TLChatParticipantAdmin = 0xe2d6e436; + public const uint TLUpdateChatAdmins = 0x6e947941; + public const uint TLUpdateChatParticipantAdmin = 0xb6901959; + public const uint TLConfig41 = 0x6cb6e65e; + public const uint TLMessageActionChatMigrateTo = 0x51bdb021; + public const uint TLMessageActionChatDeactivate = 0x64ad20a8; + public const uint TLMessageActionChatActivate = 0x40ad8cb2; + public const uint TLMessageActionChannelMigrateFrom = 0xb055eaee; + public const uint TLChannelParticipantsBots = 0xb0d1865b; + public const uint TLChat41 = 0xd91cdd54; + public const uint TLChannelFull41 = 0x9e341ddf; + public const uint TLMessageActionChatAddUser41 = 0x488a7337; + + // layer 42 + public const uint TLInputReportReasonSpam = 0x58dbcab8; + public const uint TLInputReportReasonViolence = 0x1e22c78d; + public const uint TLInputReportReasonPornography = 0x2e59d922; + public const uint TLInputReportReasonOther = 0xe1746d0a; + public const uint TLTermsOfService = 0xf1ee3e90; + + // layer 43 + public const uint TLUpdateNewStickerSet = 0x688a30aa; + public const uint TLUpdateStickerSetsOrder = 0xf0dfb451; + public const uint TLUpdateStickerSets = 0x43ae3dec; + public const uint TLAllStickers43 = 0xedfd405f; + + // layer 44 + public const uint TLInputMediaGifExternal = 0x4843b0fd; + public const uint TLUser44 = 0x603539b4; + public const uint TLChannel44 = 0x4b1b7506; + public const uint TLInputMessagesFilterGif = 0xffc86587; + public const uint TLUpdateSavedGifs = 0x9375341e; + public const uint TLConfig44 = 0x6bbc5f8; + public const uint TLFoundGif = 0x162ecc1f; + public const uint TLFoundGifCached = 0x9c750409; + public const uint TLFoundGifs = 0x450a1c0a; + public const uint TLSavedGifsNotModified = 0xe8025ca2; + public const uint TLSavedGifs = 0x2e0709a5; + + // layer 45 + public const uint TLInputMediaUploadedDocument45 = 0x1d89306d; + public const uint TLInputMediaUploadedThumbDocument45 = 0xad613491; + public const uint TLInputMediaDocument45 = 0x1a77f29c; + public const uint TLUser45 = 0xd10d979a; + public const uint TLMessage45 = 0xc992e15c; + public const uint TLMessageMediaDocument45 = 0xf3e02ea8; + public const uint TLUpdateBotInlineQuery = 0xc01eea08; + public const uint TLUpdatesShortMessage45 = 0x13e4deaa; + public const uint TLUpdatesShortChatMessage45 = 0x248afa62; + public const uint TLInputBotInlineMessageMediaAuto = 0x2e43e587; + public const uint TLInputBotInlineMessageText = 0xadf0df71; + public const uint TLInputBotInlineResult = 0x2cbbe15a; + public const uint TLBotInlineMessageMediaAuto = 0xfc56e87d; + public const uint TLBotInlineMessageText = 0xa56197a9; + public const uint TLBotInlineMediaResultDocument = 0xf897d33e; + public const uint TLBotInlineMediaResultPhoto = 0xc5528587; + public const uint TLBotInlineResult = 0x9bebaeb9; + public const uint TLBotResults = 0x1170b0a3; + + // layer 46 + public const uint TLDocumentAttributeAudio46 = 0x9852f9c6; + public const uint TLInputMessagesFilterVoice = 0x50f5c392; + public const uint TLInputMessagesFilterMusic = 0x3751b49e; + public const uint TLInputPrivacyKeyChatInvite = 0xbdfb0426; + public const uint TLPrivacyKeyChatInvite = 0x500e6dfa; + + // layer 48 + public const uint TLMessage48 = 0xc09be45f; + public const uint TLInputPeerNotifySettings48 = 0x38935eb2; + public const uint TLPeerNotifySettings48 = 0x9acda4c0; + public const uint TLUpdateEditChannelMessage = 0x1b3f4df7; + public const uint TLUpdatesShortMessage48 = 0x914fbf11; + public const uint TLUpdatesShortChatMessage48 = 0x16812688; + public const uint TLConfig48 = 0x317ceef4; + public const uint TLConfig54 = 0xf401a4bf; + public const uint TLExportedMessageLink = 0x1f486803; + public const uint TLMessageFwdHeader = 0xc786ddcb; + public const uint TLMessageEditData = 0x26b5dde6; + + // layer 49 + public const uint TLPeerSettings = 0x818426cd; + public const uint TLMessageService49 = 0x9e19a1f6; + public const uint TLMessageActionPinMessage = 0x94bd38ed; + public const uint TLChannel49 = 0xa14dca52; + public const uint TLChannelFull49 = 0x97bee562; + public const uint TLUserFull49 = 0x5932fc03; + public const uint TLBotInfo49 = 0x98e81d3a; + public const uint TLUpdateChannelPinnedMessage = 0x98592475; + public const uint TLUpdateChannelTooLong49 = 0xeb0467fb; + + // layer 50 + public const uint TLSentCode50 = 0x5e002502; + public const uint TLCodeTypeSms = 0x72a3158c; + public const uint TLCodeTypeCall = 0x741cd3e3; + public const uint TLCodeTypeFlashCall = 0x226ccefb; + public const uint TLSentCodeTypeApp = 0x3dbb5986; + public const uint TLSentCodeTypeSms = 0xc000bba2; + public const uint TLSentCodeTypeCall = 0x5353e5a7; + public const uint TLSentCodeTypeFlashCall = 0xab03c6d9; + + // layer 51 + public const uint TLUpdateBotCallbackQuery = 0xa68c688c; + public const uint TLUpdateInlineBotCallbackQuery = 0x2cbd95af; + public const uint TLUpdateBotInlineQuery51 = 0x54826690; + public const uint TLUpdateBotInlineSend = 0xe48f964; + public const uint TLUpdateEditMessage = 0xe40370a3; + public const uint TLKeyboardButtonUrl = 0x258aff05; + public const uint TLKeyboardButtonCallback = 0x683a5e46; + public const uint TLKeyboardButtonRequestPhone = 0xb16a6c29; + public const uint TLKeyboardButtonRequestGeoLocation = 0xfc796b3f; + public const uint TLKeyboardButtonSwitchInline = 0xea1b7a14; + public const uint TLBotCallbackAnswer = 0x1264f1c6; + public const uint TLReplyInlineMarkup = 0x48a30254; + public const uint TLInputBotInlineMessageMediaAuto51 = 0x292fed13; + public const uint TLInputBotInlineMessageText51 = 0x3dcd7a87; + public const uint TLInputBotInlineMessageMediaGeo = 0xf4a59de1; + public const uint TLInputBotInlineMessageMediaVenue = 0xaaafadc8; + public const uint TLInputBotInlineMessageMediaContact = 0x2daf01a7; + public const uint TLInputBotInlineResultPhoto = 0xa8d864a7; + public const uint TLInputBotInlineResultDocument = 0xfff8fdc4; + public const uint TLBotInlineMessageMediaAuto51 = 0xa74b15b; + public const uint TLBotInlineMessageText51 = 0x8c7f65e2; + public const uint TLBotInlineMessageMediaGeo = 0x3a8fd8b8; + public const uint TLBotInlineMessageMediaVenue = 0x4366232e; + public const uint TLBotInlineMessageMediaContact = 0x35edb4d4; + public const uint TLBotInlineMediaResult = 0x17db940b; + public const uint TLInputBotInlineMessageId = 0x890c3d89; + public const uint TLBotResults51 = 0x256709a6; + public const uint TLInlineBotSwitchPM = 0x3c20629f; + + // layer 52 + public const uint TLConfig52 = 0xc9411388; + public const uint TLMessageEntityMentionName = 0x352dca58; + public const uint TLInputMessageEntityMentionName = 0x208e68c9; + public const uint TLPeerDialogs = 0x3371c354; + public const uint TLTopPeer = 0xedcdc05b; + public const uint TLTopPeerCategoryBotsPM = 0xab661b5b; + public const uint TLTopPeerCategoryBotsInline = 0x148677e2; + public const uint TLTopPeerCategoryCorrespondents = 0x637b7ed; + public const uint TLTopPeerCategoryGroups = 0xbd17a14a; + public const uint TLTopPeerCategoryChannels = 0x161d9628; + public const uint TLTopPeerCategoryPeers = 0xfb834291; + public const uint TLTopPeersNotModified = 0xde266ef5; + public const uint TLTopPeers = 0x70b772a8; + + // layer 53 + public const uint TLInputMessagesFilterChatPhotos = 0x3a20ecb8; + public const uint TLUpdateReadChannelOutbox = 0x25d6c9c7; + public const uint TLChannelFull53 = 0xc3d5512f; + public const uint TLDialog53 = 0x66ffba14; + public const uint TLChannelMessages53 = 0x99262e37; + public const uint TLUpdateDraftMessage = 0xee2bb969; + public const uint TLChannelDifferenceTooLong53 = 0x410dee07; + public const uint TLChannelMessagesFilter53 = 0xcd77d957; + public const uint TLDraftMessageEmpty = 0xba4baec5; + public const uint TLDraftMessage = 0xfd8e711f; + public const uint TLChannelForbidden53 = 0x8537784f; + public const uint TLMessageActionClearHistory = 0x9fbab604; + + // layer 54 + public const uint TLFeaturedStickersNotModified = 0x4ede3cf; + public const uint TLUpdateReadFeaturedStickers = 0x571d2742; + public const uint TLBotCallbackAnswer54 = 0xb10df1fb; //0x31fde6e4; + public const uint TLInputDocumentFileLocation54 = 0x430f0724; + public const uint TLDocument54 = 0x87232bc7; + public const uint TLUpdateRecentStickers = 0x9a422c20; + public const uint TLRecentStickersNotModified = 0xb17f890; + public const uint TLRecentStickers = 0x5ce20970; + public const uint TLChatInvite54 = 0xdb74f558; + public const uint TLStickerSetInstallResult = 0x38641628; + public const uint TLStickerSetInstallResultArchive = 0x35e410a8; + public const uint TLFeaturedStickers = 0xf89d88e5; + public const uint TLArchivedStickers = 0x4fcba9c8; + public const uint TLStickerSetCovered = 0x6410a5d2; + + // layer 55 + public const uint TLInputMediaPhotoExternal = 0xb55f4f18; + public const uint TLInputMediaDocumentExternal = 0xe5e9607c; + public const uint TLAuthorization55 = 0xcd050916; + public const uint TLUpdateConfig = 0xa229dd06; + public const uint TLUpdatePtsChanged = 0x3354678f; + public const uint TLConfig55 = 0x9a6b2e2a; + public const uint TLKeyboardButtonSwitchInline55 = 0x568a748; + + // layer 56 + public const uint TLUpdateBotCallbackQuery56 = 0x81c5615f; + public const uint TLUpdateInlineBotCallbackQuery56 = 0xd618a28b; + public const uint TLUpdateStickerSetsOrder56 = 0xbb2d201; + public const uint TLStickerSetMultiCovered = 0x3407e51b; + public const uint TLInputMediaUploadedPhoto56 = 0x630c9af1; + public const uint TLInputMediaUploadedDocument56 = 0xd070f1e9; + public const uint TLInputMediaUploadedThumbDocument56 = 0x50d88cae; + public const uint TLPhoto56 = 0x9288dd29; + public const uint TLDocumentAttributeSticker56 = 0x6319d612; + public const uint TLDocumentAttributeHasStickers = 0x9801d2f7; + public const uint TLMaskCoords = 0xaed6dbb2; + public const uint TLInputStickeredMediaPhoto = 0x4a992157; + public const uint TLInputStickeredMediaDocument = 0x438865b; + public const uint TLInputChatUploadedPhoto56 = 0x927c55b4; + public const uint TLInputChatPhoto56 = 0x8953ad37; + + // layer 57 + public const uint TLInputMediaGame = 0xd33f43f3; + public const uint TLInputGameId = 0x32c3e77; + public const uint TLInputGameShortName = 0xc331e80a; + public const uint TLGame = 0xbdf9653b; + public const uint TLHighScore = 0x58fffcd0; + public const uint TLHighScores = 0x9a3bfd99; + public const uint TLInputBotInlineMessageGame = 0x4b425864; + public const uint TLInputBotInlineResultGame = 0x4fa417f2; + public const uint TLKeyboardButtonGame = 0x50f41ccf; + public const uint TLMessageActionGameScore = 0x92a72876; + public const uint TLMessageMediaGame = 0xfdb19008; + + // layer 58 + public const uint TLUserFull58 = 0xf220f3f; + public const uint TLChatsSlice = 0x78f69146; + public const uint TLUpdateChannelWebPage = 0x40771900; + public const uint TLDifferenceTooLong = 0x4afe8f6d; + public const uint TLBotResults58 = 0xccd3563d; + public const uint TLBotCallbackAnswer58 = 0x36585ea4; + + // layer 59 + public const uint TLChatsSlice59 = 0x9cd81144; + public const uint TLUpdateServiceNotification59 = 0xebe46819; + public const uint TLWebPage59 = 0x5f07b4bc; + public const uint TLWebPageNotModified = 0x85849473; + public const uint TLAppChangelog59 = 0x2a137e7c; + public const uint TLTextEmpty = 0xdc3d824f; + public const uint TLTextPlain = 0x744694e0; + public const uint TLTextBold = 0x6724abc4; + public const uint TLTextItalic = 0xd912a59c; + public const uint TLTextUnderline = 0xc12622c4; + public const uint TLTextStrike = 0x9bf8bb95; + public const uint TLTextFixed = 0x6c3f19b9; + public const uint TLTextUrl = 0x3c2884c1; + public const uint TLTextEmail = 0xde5a0dd6; + public const uint TLTextConcat = 0x7e6260d7; + public const uint TLPageBlockUnsupported = 0x13567e8a; + public const uint TLPageBlockTitle = 0x70abc3fd; + public const uint TLPageBlockSubtitle = 0x8ffa9a1f; + public const uint TLPageBlockAuthorDate = 0x3d5b64f2; + public const uint TLPageBlockHeader = 0xbfd064ec; + public const uint TLPageBlockSubheader = 0xf12bb6e1; + public const uint TLPageBlockParagraph = 0x467a0766; + public const uint TLPageBlockPreformatted = 0xc070d93e; + public const uint TLPageBlockFooter = 0x48870999; + public const uint TLPageBlockDivider = 0xdb20b188; + public const uint TLPageBlockAnchor = 0xce0d37b0; + public const uint TLPageBlockList = 0x3a58c7f4; + public const uint TLPageBlockBlockquote = 0x263d7c26; + public const uint TLPageBlockPullquote = 0x4f4456d3; + public const uint TLPageBlockPhoto = 0xe9c69982; + public const uint TLPageBlockVideo = 0xd9d71866; + public const uint TLPageBlockCover = 0x39f23300; + public const uint TLPageBlockEmbed = 0xd935d8fb; + public const uint TLPageBlockEmbedPost = 0x292c7be9; + public const uint TLPageBlockCollage = 0x8b31c4f; + public const uint TLPageBlockSlideshow = 0x130c8963; + public const uint TLPagePart = 0x8dee6c44; + public const uint TLPageFull = 0xd7a19d69; + + // layer 60 + public const uint TLUpdatePhoneCall = 0xab0f6b1e; + public const uint TLConfig60 = 0xb6735d71; + public const uint TLSendMessageGamePlayAction = 0xdd6a8f48; + public const uint TLInputPrivacyKeyPhoneCall = 0xfabadc5f; + public const uint TLPrivacyKeyPhoneCall = 0x3d662b7b; + public const uint TLInputPhoneCall = 0x1e36fded; + public const uint TLPhoneCallEmpty = 0x5366c915; + public const uint TLPhoneCallWaiting = 0x1b8f4ad1; + public const uint TLPhoneCallRequested = 0x6c448ae8; + public const uint TLPhoneCall = 0xffe6ab67; + public const uint TLPhoneCallDiscarded = 0xcc3740bd; + public const uint TLPhoneConnection = 0x6b7411c9; + public const uint TLPhoneCallProtocol = 0xa2bb35cb; + public const uint TLPhonePhoneCall = 0xec82e140; + + // layer 61 + public const uint TLUpdateDialogPinned = 0xd711a2cc; + public const uint TLUpdatePinnedDialogs = 0xd8caf68d; + public const uint TLConfig61 = 0x3af6fb5f; + public const uint TLPageBlockAuthorDate61 = 0xbaafe5e0; + public const uint TLPageBlockEmbed61 = 0xcde200d1; + public const uint TLPhoneCallDiscarded61 = 0x50ca4de1; + public const uint TLPhoneConnection61 = 0x9d4c17c0; + public const uint TLPhoneCallDiscardReasonMissed = 0x85e42301; + public const uint TLPhoneCallDiscardReasonDisconnect = 0xe095c1a0; + public const uint TLPhoneCallDiscardReasonHangup = 0x57adc690; + public const uint TLPhoneCallDiscardReasonBusy = 0xfaf7e8c9; + + // layer 62 + public const uint TLMessageActionPhoneCall = 0x80e11a7f; + public const uint TLInputMessagesFilterPhoneCalls = 0x80c99768; + public const uint TLUpdateBotWebhookJSON = 0x8317c0c3; + public const uint TLUpdateBotWebhookJSONQuery = 0x9b9240a6; + public const uint TLDataJSON = 0x7d748d04; + + // layer 63 + public const uint TLConfig63 = 0xcb601684; + + // layer 64 + public const uint TLInputMediaInvoice = 0x92153685; + public const uint TLMessageMediaInvoice = 0x84551347; + public const uint TLMessageActionPaymentSentMe = 0x8f31b327; + public const uint TLMessageActionPaymentSent = 0x40699cd0; + public const uint TLUpdateBotShippingQuery = 0xe0cdc940; + public const uint TLUpdateBotPrecheckoutQuery = 0x5d2f3aa9; + public const uint TLKeyboardButtonBuy = 0xafd93fbb; + public const uint TLLabeledPrice = 0xcb296bf8; + public const uint TLInvoice = 0xc30aa358; + public const uint TLPaymentCharge = 0xea02c27e; + public const uint TLPostAddress = 0x1e8caaeb; + public const uint TLPaymentRequestedInfo = 0x909c3f94; + public const uint TLPaymentSavedCredentialsCard = 0xcdc27a1f; + public const uint TLWebDocument = 0xc61acbd8; + public const uint TLInputWebDocument = 0x9bed434d; + public const uint TLInputWebFileLocation = 0xc239d686; + public const uint TLWebFile = 0x21e753bc; + public const uint TLPaymentForm = 0x3f56aea3; + public const uint TLValidatedRequestedInfo = 0xd1451883; + public const uint TLPaymentResult = 0x4e5f810d; + public const uint TLPaymentVerificationNeeded = 0x6b56b921; + public const uint TLPaymentReceipt = 0x500911e1; + public const uint TLSavedInfo = 0xfb8fe43c; + public const uint TLInputPaymentCredentialsSaved = 0xc10eb2cf; + public const uint TLInputPaymentCredentials = 0x3417d728; + public const uint TLTmpPassword = 0xdb64fd34; + public const uint TLShippingOption = 0xb6213cdf; + + public const uint TLPhoneCallRequested64 = 0x83761ce4; + public const uint TLPhoneCallAccepted = 0x6d003d3f; + + // layer 65, 66 + public const uint TLUser66 = 0x2e13f4c3; + public const uint TLInputMessagesFilterRoundVoice = 0x7a7c17a4; + public const uint TLInputMessagesFilterRoundVideo = 0xb549da53; + public const uint TLFileCdnRedirect = 0x1508485a; + public const uint TLSendMessageRecordRoundAction = 0x88f27fbc; + public const uint TLSendMessageUploadRoundAction = 0x243e1c66; + public const uint TLSendMessageUploadRoundAction66 = 0xbb718624; + public const uint TLDocumentAttributeVideo66 = 0xef02ce6; + public const uint TLPageBlockChannel = 0xef1751b5; + public const uint TLCdnFileReuploadNeeded = 0xeea8e46e; + public const uint TLCdnFile = 0xa99fca4f; + public const uint TLCdnPublicKey = 0xc982eaba; + public const uint TLCdnConfig = 0x5725e40a; + + // layer 67 + public const uint TLUpdateLangPackTooLong = 0x10c2404b; + public const uint TLUpdateLangPack = 0x56022f4d; + public const uint TLConfig67 = 0x7feec888; + public const uint TLLangPackString = 0xcad181f6; + public const uint TLLangPackStringPluralized = 0x6c47ac9f; + public const uint TLLangPackStringDeleted = 0x2979eeb2; + public const uint TLLangPackDifference = 0xf385c1f6; + public const uint TLLangPackLanguage = 0x117698f1; + + // layer 68 + public const uint TLChannel68 = 0xcb44b1c; + public const uint TLChannelForbidden68 = 0x289da732; + public const uint TLChannelFull68 = 0x95cb5f57; + public const uint TLChannelParticipantAdmin = 0xa82fa898; + public const uint TLChannelParticipantBanned = 0x222c1886; + public const uint TLChannelParticipantsKicked68 = 0xa3b54985; + public const uint TLChannelParticipantsBanned = 0x1427a5e1; + public const uint TLChannelParticipantsSearch = 0x656ac4b; + public const uint TLTopPeerCategoryPhoneCalls = 0x1e76a78c; + public const uint TLPageBlockAudio = 0x31b81a7f; + public const uint TLPagePart68 = 0x8e3f9ebe; + public const uint TLPageFull68 = 0x556ec7aa; + public const uint TLChannelAdminRights = 0x5d7ceba5; + public const uint TLChannelBannedRights = 0x58cf4249; + public const uint TLChannelAdminLogEventActionChangeTitle = 0xe6dfb825; + public const uint TLChannelAdminLogEventActionChangeAbout = 0x55188a2e; + public const uint TLChannelAdminLogEventActionChangeUsername = 0x6a4afc38; + public const uint TLChannelAdminLogEventActionChangePhoto = 0xb82f55c3; + public const uint TLChannelAdminLogEventActionToggleInvites = 0x1b7907ae; + public const uint TLChannelAdminLogEventActionToggleSignatures = 0x26ae0971; + public const uint TLChannelAdminLogEventActionUpdatePinned = 0xe9e82c18; + public const uint TLChannelAdminLogEventActionEditMessage = 0x709b2405; + public const uint TLChannelAdminLogEventActionDeleteMessage = 0x42e047bb; + public const uint TLChannelAdminLogEventActionParticipantJoin = 0x183040d3; + public const uint TLChannelAdminLogEventActionParticipantLeave = 0xf89777f2; + public const uint TLChannelAdminLogEventActionParticipantInvite = 0xe31c34d8; + public const uint TLChannelAdminLogEventActionParticipantToggleBan = 0xe6d83d7e; + public const uint TLChannelAdminLogEventActionParticipantToggleAdmin = 0xd5676710; + public const uint TLChannelAdminLogEvent = 0x3b5a3e40; + public const uint TLAdminLogResults = 0xed8af74d; + public const uint TLChannelAdminLogEventsFilter = 0xea107ae4; + + // layer 69 + public const uint TLImportedContacts69 = 0x77d01c3b; + public const uint TLPopularContact = 0x5ce14175; + + // layer 70 + public const uint TLInputMediaUploadedPhoto70 = 0x2f37e231; + public const uint TLInputMediaPhoto70 = 0x81fa373a; + public const uint TLInputMediaUploadedDocument70 = 0xe39621fd; + public const uint TLInputMediaDocument70 = 0x5acb668e; + public const uint TLInputMediaPhotoExternal70 = 0x922aec1; + public const uint TLInputMediaDocumentExternal70 = 0xb6f74335; + public const uint TLMessage70 = 0x90dddc11; + public const uint TLMessageMediaPhoto70 = 0xb5223b0f; + public const uint TLMessageMediaDocument70 = 0x7c4414d3; + public const uint TLMessageActionScreenshotTaken = 0x4792929b; + public const uint TLFileCdnRedirect70 = 0xea52fe5a; + public const uint TLMessageFwdHeader70 = 0xfadff4ac; + public const uint TLCdnFileHash = 0x77eec38f; + + // layer 71 + public const uint TLChannelFull71 = 0x17f45fcf; + public const uint TLDialog71 = 0xe4def5db; + public const uint TLContacts71 = 0xeae87e42; + public const uint TLInputMessagesFilterMyMentions = 0xc1f8e69a; + public const uint TLUpdateFavedStickers = 0xe511996d; + public const uint TLUpdateChannelReadMessagesContents = 0x89893b45; + public const uint TLUpdateContactsReset = 0x7084a7be; + public const uint TLConfig71 = 0x8df376a4; + public const uint TLChannelDifferenceTooLong71 = 0x6a9d7b35; + public const uint TLChannelAdminLogEventActionChangeStickerSet = 0xb1c3caa7; + public const uint TLFavedStickersNotModified = 0x9e8fa6d3; + public const uint TLFavedStickers = 0xf37f2f16; + + // layer 72 + public const uint TLInputMediaVenue72 = 0xc13d1c11; + public const uint TLInputMediaGeoLive = 0x7b1a118f; + public const uint TLChannelFull72 = 0x76af5481; + public const uint TLMessageMediaVenue72 = 0x2ec0533f; + public const uint TLMessageMediaGeoLive = 0x7c3c2609; + public const uint TLMessageActionCustomAction = 0xfae69f56; + public const uint TLInputMessagesFilterGeo = 0xe7026d0d; + public const uint TLInputMessagesFilterContacts = 0xe062db83; + public const uint TLUpdateChannelAvailableMessages = 0x70db6837; + public const uint TLConfig72 = 0x9c840964; + public const uint TLBotResults72 = 0x947ca848; + public const uint TLInputPaymentCredentialsApplePay = 0xaa1c39f; + public const uint TLInputPaymentCredentialsAndroidPay = 0x795667a6; + public const uint TLChannelAdminLogEventActionTogglePreHistoryHidden = 0x5f5c95f1; + public const uint TLRecentMeUrlUnknown = 0x46e1d13d; + public const uint TLRecentMeUrlUser = 0x8dbc3336; + public const uint TLRecentMeUrlChat = 0xa01b22f9; + public const uint TLRecentMeUrlChatInvite = 0xeb49081d; + public const uint TLRecentMeUrlStickerSet = 0xbc0a57dc; + public const uint TLRecentMeUrls = 0xe0310d7; + public const uint TLChannelParticipantsNotModified = 0xf0173fe9; + + // layer 73 + public const uint TLChannel73 = 0x450b7115; + public const uint TLMessage73 = 0x44f9b43d; + public const uint TLMessageFwdHeader73 = 0x559ebe6d; + public const uint TLInputSingleMedia = 0x5eaa7809; + public const uint TLInputMediaInvoice73 = 0xf4e096c3; + public const uint TLDecryptedMessage73 = 0x91cc4674; + + // layer 74 + public const uint TLContactsFound74 = 0xb3134d9d; + public const uint TLExportedMessageLink74 = 0x5dab1af4; + public const uint TLInputPaymentCredentialsAndroidPay74 = 0xca05d50e; + + // layer 75 + public const uint TLInputMediaUploadedPhoto75 = 0x1e287d04; + public const uint TLInputMediaPhoto75 = 0xb3ba0635; + public const uint TLInputMediaUploadedDocument75 = 0x5b38c6c1; + public const uint TLInputMediaDocument75 = 0x23ab23d2; + public const uint TLInputMediaPhotoExternal75 = 0xe5bbfe1a; + public const uint TLInputMediaDocumentExternal75 = 0xfb52dc99; + public const uint TLMessageMediaPhoto75 = 0x695150d7; + public const uint TLMessageMediaDocument75 = 0x9cb070d7; + public const uint TLInputBotInlineMessageMediaAuto75 = 0x3380c786; + public const uint TLBotInlineMessageMediaAuto75 = 0x764cf810; + public const uint TLInputSingleMedia75 = 0x31bc3d25; + + // layer 76 + public const uint TLChannel76 = 0xc88974ac; + public const uint TLDialogFeed = 0x36086d42; + public const uint TLUpdateDialogPinned76 = 0x19d27f3c; + public const uint TLUpdatePinnedDialogs76 = 0xea4cb65b; + public const uint TLUpdateReadFeed = 0x6fa68e41; + public const uint TLStickerSet76 = 0x5585a139; + public const uint TLRecentStickers76 = 0x22f3afb3; + public const uint TLFeedPosition = 0x5059dc73; + public const uint TLFeedMessagesNotModified = 0x4678d0cf; + public const uint TLFeedMessages = 0x55c3a1b1; + public const uint TLFeedBroadcasts = 0x4f4feaf1; + public const uint TLFeedBroadcastsUngrouped = 0x9a687cba; + public const uint TLFeedSourcesNotModified = 0x88b12a17; + public const uint TLFeedSources = 0x8e8bca3d; + public const uint TLInputDialogPeerFeed = 0x2c38b8cf; + public const uint TLInputDialogPeer = 0xfcaafeb7; + public const uint TLDialogPeerFeed = 0xda429411; + public const uint TLDialogPeer = 0xe56dbf05; + public const uint TLWebAuthorization = 0xcac943f2; + public const uint TLWebAuthorizations = 0xed56c9fc; + public const uint TLInputMessageId = 0xa676a322; + public const uint TLInputMessageReplyTo = 0xbad88395; + public const uint TLInputMessagePinned = 0x86872538; + public const uint TLInputSingleMedia76 = 0x1cc6e91f; + public const uint TLMessageEntityPhone = 0x9b69e34b; + public const uint TLMessageEntityCashtag = 0x4c4e743f; + public const uint TLMessageActionBotAllowed = 0xabe9affe; + public const uint TLConfig76 = 0x86b5778e; + public const uint TLFoundStickerSetsNotModified = 0xd54b65d; + public const uint TLFoundStickerSets = 0x5108d648; + public const uint TLFileHash = 0x6242c773; + public const uint TLFileCdnRedirect76 = 0xf18cda44; + public const uint TLInputBotInlineResult76 = 0x88bf9319; + public const uint TLBotInlineResult76 = 0x11965f3a; + public const uint TLWebDocumentNoProxy = 0xf9c8bcc6; + + // layer 77 + // layer 78 + public const uint TLDCOption78 = 0x18b7a10d; + public const uint TLConfig78 = 0xeb7bb160; + public const uint TLInputClientProxy = 0x75588b3f; + public const uint TLProxyDataEmpty = 0xe09e1fb8; + public const uint TLProxyDataPromo = 0x2bf7ee23; + + // layer 79 + public const uint TLInputPeerNotifySettings78 = 0x9c3d198e; + public const uint TLPeerNotifySettings78 = 0xaf509d20; + public const uint TLStickers79 = 0xe4599bbd; + public const uint TLInputBotInlineMessageMediaVenue78 = 0x417bbf11; + public const uint TLBotInlineMessageMediaVenue78 = 0x8a86659c; + + // layer 80 + public const uint TLSentCode80 = 0x38faab5f; + public const uint TLTermsOfService80 = 0x780a0310; + public const uint TLTermsOfServiceUpdateEmpty = 0xe3309f7f; + public const uint TLTermsOfServiceUpdate = 0x28ecf961; + + // layer 81 + public const uint TLInputSecureFileLocation = 0xcbc7ee28; + public const uint TLMessageActionSecureValuesSentMe = 0x1b287353; + public const uint TLMessageActionSecureValuesSent = 0xd95c6154; + public const uint TLNoPassword81 = 0x5ea182f6; + public const uint TLPassword81 = 0xca39b447; + public const uint TLPasswordSettings81 = 0x7bd9c3f1; + public const uint TLPasswordInputSettings81 = 0x21ffa60d; + public const uint TLInputSecureFileUploaded = 0x3334b0f0; + public const uint TLInputSecureFile = 0x5367e5be; + public const uint TLSecureFileEmpty = 0x64199744; + public const uint TLSecureFile = 0xe0277a62; + public const uint TLSecureData = 0x8aeabec3; + public const uint TLSecurePlainPhone = 0x7d6099dd; + public const uint TLSecurePlainEmail = 0x21ec5a5f; + public const uint TLSecureValueTypePersonalDetails = 0x9d2a81e3; + public const uint TLSecureValueTypePassport = 0x3dac6a00; + public const uint TLSecureValueTypeDriverLicense = 0x6e425c4; + public const uint TLSecureValueTypeIdentityCard = 0xa0d0744b; + public const uint TLSecureValueTypeInternalPassport = 0x99a48f23; + public const uint TLSecureValueTypeAddress = 0xcbe31e26; + public const uint TLSecureValueTypeUtilityBill = 0xfc36954e; + public const uint TLSecureValueTypeBankStatement = 0x89137c0d; + public const uint TLSecureValueTypeRentalAgreement = 0x8b883488; + public const uint TLSecureValueTypePassportRegistration = 0x99e3806a; + public const uint TLSecureValueTypeTemporaryRegistration = 0xea02ec33; + public const uint TLSecureValueTypePhone = 0xb320aadb; + public const uint TLSecureValueTypeEmail = 0x8e3ca7ee; + public const uint TLSecureValue = 0xb4b4b699; + public const uint TLInputSecureValue = 0x67872e8; + public const uint TLSecureValueHash = 0xed1ecdb0; + public const uint TLSecureValueErrorData = 0xe8a40bd9; + public const uint TLSecureValueErrorFrontSide = 0xbe3dfa; + public const uint TLSecureValueErrorReverseSide = 0x868a2aa5; + public const uint TLSecureValueErrorSelfie = 0xe537ced6; + public const uint TLSecureValueErrorFile = 0x7a700873; + public const uint TLSecureValueErrorFiles = 0x666220e9; + public const uint TLSecureCredentialsEncrypted = 0x33f0ea47; + public const uint TLAuthorizationForm = 0xcb976d53; + public const uint TLSentEmailCode = 0x811f854f; + public const uint TLDeepLinkInfoEmpty = 0x66afa166; + public const uint TLDeepLinkInfo = 0x6a4ee832; + public const uint TLSavedPhoneContact = 0x1142bd56; + public const uint TLTakeout = 0x4dba4501; + + // layer 82 + public const uint TLInputTakeoutFileLocation = 0x29be5899; + public const uint TLAppUpdate = 0x1da7158f; + public const uint TLNoAppUpdate = 0xc45a6536; + public const uint TLInvokeWithMessagesRange = 0x365275f2; + public const uint TLInputMediaContact82 = 0xf8ab7dfb; + public const uint TLMessageMediaContact82 = 0xcbf24940; + public const uint TLGeoPoint82 = 0x296f104; + public const uint TLDialogsNotModified = 0xf0e3e596; + public const uint TLUpdateDialogUnreadMark = 0xe16459c3; + public const uint TLConfig82 = 0x3213dbba; + public const uint TLInputBotInlineMessageMediaContact82 = 0xa6edbffd; + public const uint TLBotInlineMessageMediaContact82 = 0x18d1cdc2; + public const uint TLDraftMessageEmpty82 = 0x1b0c841a; + public const uint TLWebDocument82 = 0x1c570ed1; + public const uint TLInputWebFileGeoPointLocation = 0x9f2221c9; + public const uint TLInputReportReasonCopyright = 0x9b89f93a; + public const uint TLTopPeersDisabled = 0xb52c939d; + + // layer 83 + public const uint TLPassword83 = 0x68873ba5; + public const uint TLPasswordSettings83 = 0x9a5c33e5; + public const uint TLPasswordInputSettings83 = 0xc23727c9; + public const uint TLPasswordKdfAlgoUnknown = 0xd45ab096; + public const uint TLSecurePasswordKdfAlgoUnknown = 0x4a8537; + public const uint TLSecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000 = 0xbbf2dda0; + public const uint TLSecurePasswordKdfAlgoSHA512 = 0x86471d92; + public const uint TLSecureSecretSettings = 0x1527bcac; + + // layer 84 + public const uint TLPassword84 = 0xad2641f8; + public const uint TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow = 0x3a912d4a; + public const uint TLInputCheckPasswordEmpty = 0x9880f658; + public const uint TLInputCheckPasswordSRP = 0xd27ff082; + + // layer 85 + public const uint TLSecureValue85 = 0x187fa0ca; + public const uint TLInputSecureValue85 = 0xdb21d0a7; + public const uint TLSecureValueError = 0x869d758f; + public const uint TLSecureValueErrorTranslationFile = 0xa1144770; + public const uint TLSecureValueErrorTranslationFiles = 0x34636dd8; + public const uint TLAuthorizationForm85 = 0xad2e1cd8; + public const uint TLSecureRequiredType = 0x829d99da; + public const uint TLSecureRequiredTypeOneOf = 0x27477b4; + public const uint TLPassportConfigNotModified = 0xbfb9f457; + public const uint TLPassportConfig = 0xa098d6af; + + // + public const uint TLConfigSimple = 0xd997c3c5; + + // layer 45 encrypted + public const uint TLDecryptedMessage45 = 0x36b091de; + public const uint TLDecryptedMessageMediaPhoto45 = 0xf1fa8d78; + public const uint TLDecryptedMessageMediaVideo45 = 0x970c8c0e; + public const uint TLDecryptedMessageMediaDocument45 = 0x7afe8ae2; + public const uint TLDecryptedMessageMediaVenue = 0x8a0df56f; + public const uint TLDecryptedMessageMediaWebPage = 0xe50511d8; + + // additional signatures + public const uint TLMessageActionChannelJoined = 0xffffff00; + public const uint TLUserExtendedInfo = 0xffffff01; + public const uint TLDialogSecret = 0xffffff02; + public const uint TLDecryptedMessageActionEmpty = 0xffffff03; + public const uint TLPeerEncryptedChat = 0xffffff04; + public const uint TLBroadcastChat = 0xffffff05; + public const uint TLPeerBroadcastChat = 0xffffff06; + public const uint TLBroadcastDialog = 0xffffff07; + public const uint TLInputPeerBroadcast = 0xffffff08; + public const uint TLServerFile = 0xffffff09; + public const uint TLMessageActionContactRegistered = 0xffffff0a; + public const uint TLPasscodeParams = 0xffffff0b; + public const uint TLRecentlyUsedSticker = 0xffffff0c; + public const uint TLActionInfo = 0xffffff0d; + public const uint TLResultInfo = 0xffffff0e; + public const uint TLEncryptedChat20 = 0xffffff0f; + public const uint TLEncryptedChat17 = 0xffffff10; + public const uint TLMessageActionUnreadMessages = 0xffffff11; + public const uint TLMessagesContainter = 0xffffff12; + public const uint TLHashtagItem = 0xffffff13; + public const uint TLMessageActionMessageGroup = 0xffffff14; + public const uint TLChatSettings = 0xffffff15; + public const uint TLDocumentExternal = 0xffffff16; + public const uint TLDecryptedMessagesContainter = 0xffffff17; + public const uint TLCameraSettings = 0xffffff18; + public const uint TLPhotoPickerSettings = 0xffffff19; + public const uint TLProxyConfig = 0xffffff1a; + public const uint TLCallsSecurity = 0xffffff1b; + public const uint TLStickerSetEmpty = 0xffffff1c; + public const uint TLMessagesGroup = 0xffffff1d; + public const uint TLMessageMediaGroup = 0xffffff1e; + public const uint TLDecryptedMessageMediaGroup = 0xffffff1f; + public const uint TLPeerFeed = 0xffffff20; + public const uint TLInputPeerFeed = 0xffffff21; + public const uint TLProxyConfig76 = 0xffffff22; + public const uint TLSocks5Proxy = 0xffffff23; + public const uint TLMTProtoProxy = 0xffffff24; + public const uint TLContactsSettings = 0xffffff25; + public const uint TLSecureFileUploaded = 0xffffff26; + } +} diff --git a/Telegram.Api/TL/TLState.cs b/Telegram.Api/TL/TLState.cs new file mode 100755 index 0000000..0c6fa7f --- /dev/null +++ b/Telegram.Api/TL/TLState.cs @@ -0,0 +1,67 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLState : TLObject + { + public const uint Signature = TLConstructors.TLState; + + public TLInt Pts { get; set; } + + public TLInt Qts { get; set; } + + public TLInt Date { get; set; } + + public TLInt Seq { get; set; } + + public TLInt UnreadCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Pts = GetObject(bytes, ref position); + Qts = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Seq = GetObject(bytes, ref position); + UnreadCount = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Pts = GetNullableObject(input); + Qts = GetNullableObject(input); + Date = GetNullableObject(input); + Seq = GetNullableObject(input); + UnreadCount = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Pts.NullableToStream(output); + Qts.NullableToStream(output); + Date.NullableToStream(output); + Seq.NullableToStream(output); + UnreadCount.NullableToStream(output); + } + + public override string ToString() + { + return string.Format("p={0} q={1} s={2} u_c={3} d={4} [{5}]", Pts, Qts, Seq, UnreadCount, Date, Date != null ? TLUtils.ToDateTime(Date) : DateTime.MinValue); + } + } +} diff --git a/Telegram.Api/TL/TLStatedMessage.cs b/Telegram.Api/TL/TLStatedMessage.cs new file mode 100755 index 0000000..9c5ad4e --- /dev/null +++ b/Telegram.Api/TL/TLStatedMessage.cs @@ -0,0 +1,165 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLStatedMessageBase : TLObject + { + public TLMessageBase Message { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public TLInt Pts { get; set; } + + public abstract TLStatedMessageBase GetEmptyObject(); + + public virtual TLInt GetSeq() + { + return null; + } + } + + public interface ILinks + { + TLVector Links { get; set; } + } + + public class TLStatedMessage : TLStatedMessageBase + { + public const uint Signature = TLConstructors.TLStatedMessage; + + public TLInt Seq { get; set; } + + public override TLInt GetSeq() + { + return Seq; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + Seq = GetObject(bytes, ref position); + + return this; + } + + public override TLStatedMessageBase GetEmptyObject() + { + return new TLStatedMessage + { + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count), + Pts = Pts, + Seq = Seq + }; + } + } + + public class TLStatedMessage24 : TLStatedMessageBase, IMultiPts + { + public const uint Signature = TLConstructors.TLStatedMessage24; + + public TLInt PtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + + public override TLStatedMessageBase GetEmptyObject() + { + return new TLStatedMessage24 + { + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count), + Pts = Pts, + PtsCount = PtsCount + }; + } + } + + public class TLStatedMessageLink : TLStatedMessage, ILinks + { + public new const uint Signature = TLConstructors.TLStatedMessageLink; + + public TLVector Links { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + Links = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + Seq = GetObject(bytes, ref position); + + return this; + } + + public override TLStatedMessageBase GetEmptyObject() + { + return new TLStatedMessageLink + { + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count), + Links = new TLVector(Links.Count), + Pts = Pts, + Seq = Seq + }; + } + } + + public class TLStatedMessageLink24 : TLStatedMessage24, ILinks + { + public new const uint Signature = TLConstructors.TLStatedMessageLink24; + + public TLVector Links { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + Links = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + + public override TLStatedMessageBase GetEmptyObject() + { + return new TLStatedMessageLink24 + { + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count), + Links = new TLVector(Links.Count), + Pts = Pts, + PtsCount = PtsCount + }; + } + } +} diff --git a/Telegram.Api/TL/TLStatedMessages.cs b/Telegram.Api/TL/TLStatedMessages.cs new file mode 100755 index 0000000..2c8bcf8 --- /dev/null +++ b/Telegram.Api/TL/TLStatedMessages.cs @@ -0,0 +1,164 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public abstract class TLStatedMessagesBase : TLObject + { + public TLVector Messages { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public TLInt Pts { get; set; } + + public abstract TLStatedMessagesBase GetEmptyObject(); + + public virtual TLInt GetSeq() + { + return null; + } + } + + public class TLStatedMessages : TLStatedMessagesBase + { + public const uint Signature = TLConstructors.TLStatedMessages; + + public TLInt Seq { get; set; } + + public override TLInt GetSeq() + { + return Seq; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + Seq = GetObject(bytes, ref position); + + return this; + } + + public override TLStatedMessagesBase GetEmptyObject() + { + return new TLStatedMessages + { + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count), + Messages = new TLVector(Messages.Count), + Pts = Pts, + Seq = Seq + }; + } + } + + public class TLStatedMessages24 : TLStatedMessagesBase, IMultiPts + { + public const uint Signature = TLConstructors.TLStatedMessages24; + + public TLInt PtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + + public override TLStatedMessagesBase GetEmptyObject() + { + return new TLStatedMessages24 + { + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count), + Messages = new TLVector(Messages.Count), + Pts = Pts, + PtsCount = PtsCount + }; + } + } + + public class TLStatedMessagesLinks : TLStatedMessages, ILinks + { + public new const uint Signature = TLConstructors.TLStatedMessagesLinks; + + public TLVector Links { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + Links = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + Seq = GetObject(bytes, ref position); + + return this; + } + + public override TLStatedMessagesBase GetEmptyObject() + { + return new TLStatedMessagesLinks + { + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count), + Messages = new TLVector(Messages.Count), + Links = new TLVector(Links.Count), + Pts = Pts, + Seq = Seq + }; + } + } + + public class TLStatedMessagesLinks24 : TLStatedMessages24, ILinks + { + public new const uint Signature = TLConstructors.TLStatedMessagesLinks24; + + public TLVector Links { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + Links = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + + public override TLStatedMessagesBase GetEmptyObject() + { + return new TLStatedMessagesLinks24 + { + Chats = new TLVector(Chats.Count), + Users = new TLVector(Users.Count), + Messages = new TLVector(Messages.Count), + Links = new TLVector(Links.Count), + Pts = Pts, + PtsCount = PtsCount + }; + } + } +} diff --git a/Telegram.Api/TL/TLStickerPack.cs b/Telegram.Api/TL/TLStickerPack.cs new file mode 100755 index 0000000..636e47e --- /dev/null +++ b/Telegram.Api/TL/TLStickerPack.cs @@ -0,0 +1,54 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLStickerPack : TLObject + { + public const uint Signature = TLConstructors.TLStickerPack; + + public TLString Emoticon { get; set; } + + public TLVector Documents { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Emoticon = GetObject(bytes, ref position); + Documents = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Emoticon.ToBytes(), + Documents.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Emoticon = GetObject(input); + Documents = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Emoticon.ToStream(output); + Documents.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLStickerSet.cs b/Telegram.Api/TL/TLStickerSet.cs new file mode 100755 index 0000000..4078f19 --- /dev/null +++ b/Telegram.Api/TL/TLStickerSet.cs @@ -0,0 +1,294 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [Flags] + public enum StickerSetFlags + { + Installed = 0x1, + Disabled = 0x2, + Official = 0x4, + Masks = 0x8 + } + + public abstract class TLStickerSetBase : TLObject + { + public TLLong Id { get; set; } + public TLLong AccessHash { get; set; } + public TLString Title { get; set; } + public TLString ShortName { get; set; } + + #region Additional + public TLVector Stickers { get; set; } + public bool Unread { get; set; } + public bool IsSelected { get; set; } + #endregion + } + + public class TLStickerSet : TLStickerSetBase + { + public const uint Signature = TLConstructors.TLStickerSet; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + ShortName = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + Title.ToBytes(), + ShortName.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + Title = GetObject(input); + ShortName = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + AccessHash.ToStream(output); + Title.ToStream(output); + ShortName.ToStream(output); + } + } + + public class TLStickerSet76 : TLStickerSet32 + { + public new const uint Signature = TLConstructors.TLStickerSet76; + + protected TLInt _installedDate; + + public TLInt InstalledDate + { + get { return _installedDate; } + set { SetField(out _installedDate, value, ref _flags, (int) StickerSetFlags.Installed); } + } + + public int SortDate { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + InstalledDate = GetObject(Flags, (int) StickerSetFlags.Installed, null, bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + ShortName = GetObject(bytes, ref position); + Count = GetObject(bytes, ref position); + Hash = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + ToBytes(InstalledDate, Flags, (int) StickerSetFlags.Installed), + Id.ToBytes(), + AccessHash.ToBytes(), + Title.ToBytes(), + ShortName.ToBytes(), + Count.ToBytes(), + Hash.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + InstalledDate = GetObject(Flags, (int) StickerSetFlags.Installed, null, input); + Id = GetObject(input); + AccessHash = GetObject(input); + Title = GetObject(input); + ShortName = GetObject(input); + Count = GetObject(input); + Hash = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, InstalledDate, Flags, (int) StickerSetFlags.Installed); + Id.ToStream(output); + AccessHash.ToStream(output); + Title.ToStream(output); + ShortName.ToStream(output); + Count.ToStream(output); + Hash.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLStickerSet76 id={0} short_name={1} flags={2}", Id, ShortName, StickerSetFlagsString(Flags)); + } + } + + public class TLStickerSet32 : TLStickerSet + { + public new const uint Signature = TLConstructors.TLStickerSet32; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt Count { get; set; } + + public TLInt Hash { get; set; } + + public bool Installed + { + get { return IsSet(Flags, (int) StickerSetFlags.Installed); } + set { SetUnset(ref _flags, value, (int) StickerSetFlags.Installed); } + } + + public bool Archived + { + get { return IsSet(Flags, (int)StickerSetFlags.Disabled); } + set { SetUnset(ref _flags, value, (int)StickerSetFlags.Disabled); } + } + + public bool Official + { + get { return IsSet(Flags, (int)StickerSetFlags.Official); } + set { SetUnset(ref _flags, value, (int)StickerSetFlags.Official); } + } + + public bool Masks + { + get { return IsSet(Flags, (int)StickerSetFlags.Masks); } + set { SetUnset(ref _flags, value, (int)StickerSetFlags.Masks); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + ShortName = GetObject(bytes, ref position); + Count = GetObject(bytes, ref position); + Hash = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + AccessHash.ToBytes(), + Title.ToBytes(), + ShortName.ToBytes(), + Count.ToBytes(), + Hash.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(input); + Title = GetObject(input); + ShortName = GetObject(input); + Count = GetObject(input); + Hash = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + AccessHash.ToStream(output); + Title.ToStream(output); + ShortName.ToStream(output); + Count.ToStream(output); + Hash.ToStream(output); + } + + public static string StickerSetFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (StickerSetFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public override string ToString() + { + return string.Format("TLStickerSet32 id={0} short_name={1} flags={2}", Id, ShortName, StickerSetFlagsString(Flags)); + } + } + + public class TLStickerSetEmpty : TLStickerSetBase + { + public const uint Signature = TLConstructors.TLStickerSetEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLStickerSetCovered.cs b/Telegram.Api/TL/TLStickerSetCovered.cs new file mode 100755 index 0000000..dcb4372 --- /dev/null +++ b/Telegram.Api/TL/TLStickerSetCovered.cs @@ -0,0 +1,96 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLStickerSetCoveredBase : TLObject + { + public TLStickerSetBase StickerSet { get; set; } + } + public class TLStickerSetCovered : TLStickerSetCoveredBase + { + public const uint Signature = TLConstructors.TLStickerSetCovered; + + public TLDocumentBase Cover { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + StickerSet = GetObject(bytes, ref position); + Cover = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + StickerSet.ToBytes(), + Cover.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + StickerSet = GetObject(input); + Cover = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + StickerSet.ToStream(output); + Cover.ToStream(output); + } + } + + public class TLStickerSetMultiCovered : TLStickerSetCoveredBase + { + public const uint Signature = TLConstructors.TLStickerSetMultiCovered; + + public TLVector Covers { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + StickerSet = GetObject(bytes, ref position); + Covers = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + StickerSet.ToBytes(), + Covers.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + StickerSet = GetObject(input); + Covers = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + StickerSet.ToStream(output); + Covers.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLStickerSetInstallResult.cs b/Telegram.Api/TL/TLStickerSetInstallResult.cs new file mode 100755 index 0000000..fed8213 --- /dev/null +++ b/Telegram.Api/TL/TLStickerSetInstallResult.cs @@ -0,0 +1,114 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using System.Linq; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; + +namespace Telegram.Api.TL +{ + public abstract class TLStickerSetInstallResultBase : TLObject { } + + public class TLStickerSetInstallResult : TLStickerSetInstallResultBase + { + public const uint Signature = TLConstructors.TLStickerSetInstallResult; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override string ToString() + { + return "TLStickerSetInstallResult"; + } + } + + public class TLStickerSetInstallResultArchive : TLStickerSetInstallResultBase, IStickers + { + public const uint Signature = TLConstructors.TLStickerSetInstallResultArchive; + + public TLString Hash { get; set; } + + public TLVector SetsCovered { get; set; } + + #region Additional + + public TLVector Sets + { + get + { + var sets = new TLVector(); + foreach (var setCovered in SetsCovered) + { + sets.Add(setCovered.StickerSet); + } + return sets; + } + set + { + Execute.ShowDebugMessage("TLStickerSetInstallResultArchive.Sets set"); + } + } + public TLVector Packs { get; set; } + public TLVector Documents { get; set; } + public TLVector MessagesStickerSets { get; set; } + #endregion + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + SetsCovered = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + SetsCovered.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + SetsCovered = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + SetsCovered.ToStream(output); + } + + public override string ToString() + { + return string.Format("TLStickerSetInstallResultArchive sets=[{0}]", string.Join(", ", Sets.Select(x => x.Id))); + } + } +} diff --git a/Telegram.Api/TL/TLStickers.cs b/Telegram.Api/TL/TLStickers.cs new file mode 100755 index 0000000..79c06f1 --- /dev/null +++ b/Telegram.Api/TL/TLStickers.cs @@ -0,0 +1,125 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLStickersBase : TLObject { } + + public class TLStickersNotModified : TLStickersBase + { + public const uint Signature = TLConstructors.TLStickersNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLStickers79 : TLStickersBase + { + public const uint Signature = TLConstructors.TLStickers79; + + public TLInt Hash { get; set; } + + public TLVector Stickers { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + Stickers = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes(), + Stickers.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Hash = GetObject(input); + Stickers = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Hash.ToStream(output); + Stickers.ToStream(output); + } + } + + public class TLStickers : TLStickersBase + { + public const uint Signature = TLConstructors.TLStickers; + + public TLString Hash { get; set; } + + public TLVector Stickers { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Hash = GetObject(bytes, ref position); + Stickers = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Hash.ToBytes(), + Stickers.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Hash = GetObject(input); + Stickers = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Hash.ToStream(output); + Stickers.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLString.cs b/Telegram.Api/TL/TLString.cs new file mode 100755 index 0000000..7c99380 --- /dev/null +++ b/Telegram.Api/TL/TLString.cs @@ -0,0 +1,240 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Numerics; +using System.Runtime.Serialization; +using System.Text; +using Org.BouncyCastle.Security; +using Telegram.Api.Helpers; + +namespace Telegram.Api.TL +{ + [DataContract] + public class TLString : TLObject + { + public TLString(){ } + + public TLString(string s) + { + if (s == null) s = ""; + var data = Encoding.UTF8.GetBytes(s); + //Length = data.Length; + Data = data; // NOTE: remove Reverse here + } + + public static TLString Random(int count) + { + var random = new SecureRandom(); + var randomBytes = new byte[count]; + random.NextBytes(randomBytes); + + return FromBigEndianData(randomBytes); + } + + public static TLString Empty + { + get + { + return new TLString(""); + } + } + + //little endian data with leading 0x00 padding + [DataMember] + public byte[] Data { get; set; } // NOT: now its big endian with 0x0 padding at the end + + public static TLString FromBigEndianData(byte[] data) + { + var str = new TLString(); + str.Data = data; // NOTE: remove Reverse here + return str; + } + + // UInt64 - little endian + public static TLString FromUInt64(UInt64 data) + { + var str = new TLString(); + + // revert to big endian and remove first zero bytes + var bigEndianBytes = RemoveFirstZeroBytes(BitConverter.GetBytes(data).Reverse().ToArray()); + + // revert to little endian again + str.Data = bigEndianBytes; // NOTE: remove Reverse here + + return str; + } + + private static byte[] RemoveFirstZeroBytes(IList bytes) + { + var result = new List(bytes); + + while (result.Count > 0 && result[0] == 0x00) + { + result.RemoveAt(0); + } + + return result.ToArray(); + } + + public BigInteger ToBigInteger() + { + var data = new List(Data); + while (data[0] == 0x00) + { + data.RemoveAt(0); + } + + return new BigInteger(Data.Reverse().Concat(new byte[] {0x00}).ToArray()); //NOTE: add reverse here + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + int bytesRead; + int length; + if (bytes[position] == 0xfe) + { + var lengthBytes = bytes.SubArray(position + 1, 3); + length = BitConverter.ToInt32(lengthBytes.Concat(new byte[] { 0x00 }).ToArray(), 0); + bytesRead = 4; + } + else + { + length = bytes[position]; + bytesRead = 1; + } + Data = bytes.SubArray(position + bytesRead, length); //NOTE: remove Reverse here + + bytesRead += Data.Length; + var padding = (bytesRead % 4 == 0) ? 0 : (4 - (bytesRead % 4)); + bytesRead += padding; + if (bytesRead % 4 != 0) throw new Exception("Length must be divisible on 4"); + + position += bytesRead; + + return this; + } + + // length + big endian data + zero bytes + public override byte[] ToBytes() + { + var length = (Data.Length >= 254) ? 4 + Data.Length : 1 + Data.Length; + var padding = (length % 4 == 0)? 0 : (4 - (length % 4)); + length = length + padding; + var bytes = new byte[length]; + + if (Data.Length >= 254) + { + bytes[0] = 0xFE; + var lengthBytes = BitConverter.GetBytes(Data.Length); + Array.Copy(lengthBytes, 0, bytes, 1, 3); + Array.Copy(Data, 0, bytes, 4, Data.Length); //NOTE: Remove Reverse here + } + else + { + bytes[0] = (byte)Data.Length; + Array.Copy(Data, 0, bytes, 1, Data.Length); //NOTE: Remove Reverse here + } + + return bytes; + } + + public override TLObject FromStream(Stream input) + { + int bytesRead; + int length; + var bytes = new byte[1]; + input.Read(bytes, 0, 1); + if (bytes[0] == 0xfe) + { + var lengthBytes = new byte[3]; + input.Read(lengthBytes, 0, 3); + length = BitConverter.ToInt32(lengthBytes.Concat(new byte[] { 0x00 }).ToArray(), 0); + bytesRead = 4; + } + else + { + length = bytes[0]; + bytesRead = 1; + } + Data = new byte[length]; + input.Read(Data, 0, Data.Length); + // bytes.SubArray(position + bytesRead, length); //NOTE: remove Reverse here + + bytesRead += Data.Length; + var padding = (bytesRead % 4 == 0) ? 0 : (4 - (bytesRead % 4)); + bytesRead += padding; + if (bytesRead % 4 != 0) throw new Exception("Length must be divisible on 4"); + + input.Position += padding; + + return this; + } + + public override void ToStream(Stream output) + { + var buffer = ToBytes(); + output.Write(buffer, 0, buffer.Length); + } + + private WeakReference _str; + + public override string ToString() + { +#if SILVERLIGHT || WIN_RT + string str; + if (_str != null && _str.TryGetTarget(out str)) return str; + + str = Data == null ? string.Empty : Encoding.UTF8.GetString(Data, 0, Data.Length); + _str = new WeakReference(str); + + return str; +#else + string str; + if (_str != null && _str.TryGetTarget(out str)) return str; + + str = Data == null? string.Empty : Encoding.UTF8.GetString(Data); + _str = new WeakReference(str); + + return str; +#endif + } + + public string Value + { + get { return ToString(); } + } + + public static bool IsNullOrEmpty(TLString str) + { + return str == null || string.IsNullOrEmpty(str.ToString()); + } + + public static bool Equals(TLString str1, TLString str2, StringComparison comparison) + { + if (str1 == null && str2 == null) + { + return true; + } + + if (str1 != null && str2 == null) + { + return false; + } + + if (str1 == null) + { + return false; + } + + return string.Equals(str1.ToString(), str2.ToString(), comparison); + } + } +} diff --git a/Telegram.Api/TL/TLSupport.cs b/Telegram.Api/TL/TLSupport.cs new file mode 100755 index 0000000..2445803 --- /dev/null +++ b/Telegram.Api/TL/TLSupport.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLSupport : TLObject + { + public const uint Signature = TLConstructors.TLSupport; + + public TLString PhoneNumber { get; set; } + + public TLUserBase User { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhoneNumber = GetObject(bytes, ref position); + User = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLTermsOfService.cs b/Telegram.Api/TL/TLTermsOfService.cs new file mode 100755 index 0000000..2356476 --- /dev/null +++ b/Telegram.Api/TL/TLTermsOfService.cs @@ -0,0 +1,77 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum TermsOfServiceFlags + { + Popup = 0x1, + MinAgeConfirm = 0x2 + } + + public abstract class TLTermsOfServiceBase : TLObject { } + + public class TLTermsOfService80 : TLTermsOfService + { + public new const uint Signature = TLConstructors.TLTermsOfService80; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Popup + { + get { return IsSet(_flags, (int)TermsOfServiceFlags.Popup); } + set { SetUnset(ref _flags, value, (int)TermsOfServiceFlags.Popup); } + } + + public TLDataJSON Id { get; set; } + + public TLVector Entities { get; set; } + + public bool MinAgeConfirm + { + get { return IsSet(_flags, (int)TermsOfServiceFlags.MinAgeConfirm); } + set { SetUnset(ref _flags, value, (int)TermsOfServiceFlags.MinAgeConfirm); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + _flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + Text = GetObject(bytes, ref position); + Entities = GetObject>(bytes, ref position); + + return this; + } + } + + public class TLTermsOfService : TLTermsOfServiceBase + { + public const uint Signature = TLConstructors.TLTermsOfService; + + public TLString Text { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Text = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLTmpPassword.cs b/Telegram.Api/TL/TLTmpPassword.cs new file mode 100755 index 0000000..d76153b --- /dev/null +++ b/Telegram.Api/TL/TLTmpPassword.cs @@ -0,0 +1,46 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLTmpPassword : TLObject + { + public const uint Signature = TLConstructors.TLTmpPassword; + + public TLString TmpPassword { get; set; } + + public TLInt ValidUntil { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + TmpPassword = GetObject(bytes, ref position); + ValidUntil = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + TmpPassword = GetObject(input); + ValidUntil = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + TmpPassword.ToStream(output); + ValidUntil.ToStream(output); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLTopPeer.cs b/Telegram.Api/TL/TLTopPeer.cs new file mode 100755 index 0000000..ebfbbda --- /dev/null +++ b/Telegram.Api/TL/TLTopPeer.cs @@ -0,0 +1,56 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLTopPeer : TLObject + { + public const uint Signature = TLConstructors.TLTopPeer; + + public TLPeerBase Peer { get; set; } + + public TLDouble Rating { get; set; } + + public TLObject Object { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + Rating = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Peer.ToBytes(), + Rating.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + Rating = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Peer.ToStream(output); + Rating.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLTopPeerCategory.cs b/Telegram.Api/TL/TLTopPeerCategory.cs new file mode 100755 index 0000000..dc0a1dc --- /dev/null +++ b/Telegram.Api/TL/TLTopPeerCategory.cs @@ -0,0 +1,176 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLTopPeerCategoryBase : TLObject { } + + public class TLTopPeerCategoryBotsPM : TLTopPeerCategoryBase + { + public const uint Signature = TLConstructors.TLTopPeerCategoryBotsPM; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLTopPeerCategoryBotsInline : TLTopPeerCategoryBase + { + public const uint Signature = TLConstructors.TLTopPeerCategoryBotsInline; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLTopPeerCategoryCorrespondents : TLTopPeerCategoryBase + { + public const uint Signature = TLConstructors.TLTopPeerCategoryCorrespondents; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLTopPeerCategoryGroups : TLTopPeerCategoryBase + { + public const uint Signature = TLConstructors.TLTopPeerCategoryGroups; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLTopPeerCategoryChannels : TLTopPeerCategoryBase + { + public const uint Signature = TLConstructors.TLTopPeerCategoryChannels; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLTopPeerCategoryPhoneCalls : TLTopPeerCategoryBase + { + public const uint Signature = TLConstructors.TLTopPeerCategoryPhoneCalls; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLTopPeerCategoryPeers.cs b/Telegram.Api/TL/TLTopPeerCategoryPeers.cs new file mode 100755 index 0000000..24e3eb8 --- /dev/null +++ b/Telegram.Api/TL/TLTopPeerCategoryPeers.cs @@ -0,0 +1,60 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public class TLTopPeerCategoryPeers : TLObject + { + public const uint Signature = TLConstructors.TLTopPeerCategoryPeers; + + public TLTopPeerCategoryBase Category { get; set; } + + public TLInt Count { get; set; } + + public TLVector Peers { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Category = GetObject(bytes, ref position); + Count = GetObject(bytes, ref position); + Peers = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Category.ToBytes(), + Count.ToBytes(), + Peers.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Category = GetObject(input); + Count = GetObject(input); + Peers = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Category.ToStream(output); + Count.ToStream(output); + Peers.ToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLTopPeers.cs b/Telegram.Api/TL/TLTopPeers.cs new file mode 100755 index 0000000..efb5819 --- /dev/null +++ b/Telegram.Api/TL/TLTopPeers.cs @@ -0,0 +1,116 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLTopPeersBase : TLObject { } + + public class TLTopPeers : TLTopPeersBase + { + public const uint Signature = TLConstructors.TLTopPeers; + + public TLVector Categories { get; set; } + + public TLVector Chats { get; set; } + + public TLVector Users { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Categories = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Categories.ToBytes(), + Chats.ToBytes(), + Users.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Categories = GetObject>(input); + Chats = GetObject>(input); + Users = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Categories.ToStream(output); + Chats.ToStream(output); + Users.ToStream(output); + } + } + + public class TLTopPeersNotModified : TLTopPeersBase + { + public const uint Signature = TLConstructors.TLTopPeersNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + public class TLTopPeersDisabled : TLTopPeersBase + { + public const uint Signature = TLConstructors.TLTopPeersDisabled; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} diff --git a/Telegram.Api/TL/TLUpdate.cs b/Telegram.Api/TL/TLUpdate.cs new file mode 100755 index 0000000..a0d817f --- /dev/null +++ b/Telegram.Api/TL/TLUpdate.cs @@ -0,0 +1,3860 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.IO; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; + +namespace Telegram.Api.TL +{ + [Flags] + public enum UpdateFlags + { + Geo = 0x1, // 0 + MessageId = 0x2, // 1 + } + + [Flags] + public enum UpdateServiceNotificationFlags + { + Popup = 0x1, // 0 + InboxDate = 0x2, // 1 + } + + [Flags] + public enum UpdateDilogPinnedFlags + { + Pinned = 0x1, // 0 + } + + [Flags] + public enum UpdatePinnedDialogsFlags + { + Order = 0x1, // 0 + } + + [Flags] + public enum UpdateBotPrecheckoutQueryFlags + { + Info = 0x1, // 0 + ShippingOptionId = 0x2, // 1 + } + + [Flags] + public enum UpdateReadFeedFlags + { + UnreadCount = 0x1, // 0 + } + + [Flags] + public enum UpdateDialogUnreadMarkFlags + { + Unread = 0x1, // 0 + } + + public abstract class TLUpdateBase : TLObject + { + public abstract IList GetPts(); + } + + public interface IMultiPts + { + TLInt Pts { get; set; } + + TLInt PtsCount { get; set; } + } + + public interface IMultiChannelPts + { + TLInt ChannelPts { get; set; } + + TLInt ChannelPtsCount { get; set; } + } + + public class TLUpdateNewMessage : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateNewMessage; + + public TLMessageBase Message { get; set; } + public TLInt Pts { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + + var messageCommon = Message as TLMessageCommon; + if (messageCommon != null) messageCommon.SetUnreadSilent(TLBool.True); + + Pts = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Message.ToStream(output); + Pts.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Message = GetObject(input); + Pts = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List { Pts }; + } + } + + public class TLUpdateNewMessage24 : TLUpdateNewMessage, IMultiPts + { + public new const uint Signature = TLConstructors.TLUpdateNewMessage24; + + public TLInt PtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + var messageCommon = Message as TLMessageCommon; + if (messageCommon != null) messageCommon.SetUnreadSilent(TLBool.True); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Message.ToStream(output); + Pts.ToStream(output); + PtsCount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Message = GetObject(input); + Pts = GetObject(input); + PtsCount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + } + + public class TLUpdateChatParticipantAdd37 : TLUpdateChatParticipantAdd + { + public new const uint Signature = TLConstructors.TLUpdateChatParticipantAdd37; + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + InviterId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChatId.ToStream(output); + UserId.ToStream(output); + InviterId.ToStream(output); + Date.ToStream(output); + Version.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + UserId = GetObject(input); + InviterId = GetObject(input); + Date = GetObject(input); + Version = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChatParticipantAdd : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateChatParticipantAdd; + + public TLInt ChatId { get; set; } + public TLInt UserId { get; set; } + public TLInt InviterId { get; set; } + public TLInt Version { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + InviterId = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChatId.ToStream(output); + UserId.ToStream(output); + InviterId.ToStream(output); + Version.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + UserId = GetObject(input); + InviterId = GetObject(input); + Version = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChatParticipantDelete : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateChatParticipantDelete; + + public TLInt ChatId { get; set; } + public TLInt UserId { get; set; } + public TLInt Version { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChatId.ToStream(output); + UserId.ToStream(output); + Version.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + UserId = GetObject(input); + Version = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateNewEncryptedMessage : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateNewEncryptedMessage; + + public TLEncryptedMessageBase Message { get; set; } + public TLInt Qts { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + Qts = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Message.ToStream(output); + Qts.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Message = GetObject(input); + Qts = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateEncryption : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateEncryption; + + public TLEncryptedChatBase Chat { get; set; } + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Chat = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Chat.ToStream(output); + Date.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Chat = GetObject(input); + Date = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateMessageId : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateMessageId; + + public TLInt Id { get; set; } + + public TLLong RandomId { get; set; } + + public override string ToString() + { + return string.Format("TLUpdateMessageId id={0} random_id={1}", Id, RandomId); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + RandomId = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + RandomId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + RandomId = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateReadMessages : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateReadMessages; + + public TLVector Messages { get; set; } + public TLInt Pts { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Messages.ToStream(output); + Pts.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Messages = GetObject>(input); + Pts = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List { Pts }; + } + } + + public class TLUpdateReadMessages24 : TLUpdateReadMessages, IMultiPts + { + public new const uint Signature = TLConstructors.TLUpdateReadMessages24; + + public TLInt PtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Messages.ToStream(output); + Pts.ToStream(output); + PtsCount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Messages = GetObject>(input); + Pts = GetObject(input); + PtsCount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + } + + public class TLUpdateReadMessagesContents : TLUpdateReadMessages, IMultiPts + { + public new const uint Signature = TLConstructors.TLUpdateReadMessagesContents; + + public TLInt PtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Messages.ToStream(output); + Pts.ToStream(output); + PtsCount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Messages = GetObject>(input); + Pts = GetObject(input); + PtsCount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + } + + public abstract class TLUpdateReadHistory : TLUpdateBase, IMultiPts + { + public TLPeerBase Peer { get; set; } + + public TLInt MaxId { get; set; } + + public TLInt Pts { get; set; } + + public TLInt PtsCount { get; set; } + } + + public class TLUpdateReadHistoryInbox : TLUpdateReadHistory + { + public const uint Signature = TLConstructors.TLUpdateReadHistoryInbox; + + public override string ToString() + { + return string.Format("TLUpdateReadHistoryInbox peer={0} max_id={1} pts={2} pts_count={3}", Peer, MaxId, Pts, PtsCount); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + MaxId = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Peer.ToStream(output); + MaxId.ToStream(output); + Pts.ToStream(output); + PtsCount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + MaxId = GetObject(input); + Pts = GetObject(input); + PtsCount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + } + + public class TLUpdateReadHistoryOutbox : TLUpdateReadHistory + { + public const uint Signature = TLConstructors.TLUpdateReadHistoryOutbox; + + public override string ToString() + { + return string.Format("TLUpdateReadHistoryOutbox peer={0} max_id={1} pts={2} pts_count={3}", Peer, MaxId, Pts, PtsCount); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + MaxId = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Peer.ToStream(output); + MaxId.ToStream(output); + Pts.ToStream(output); + PtsCount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + MaxId = GetObject(input); + Pts = GetObject(input); + PtsCount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + } + + public class TLUpdateEncryptedMessagesRead : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateEncryptedMessagesRead; + + public TLInt ChatId { get; set; } + public TLInt MaxDate { get; set; } + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + MaxDate = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChatId.ToStream(output); + MaxDate.ToStream(output); + Date.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + MaxDate = GetObject(input); + Date = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + + public override string ToString() + { + return string.Format("{0} ChatId={1} MaxDate={2} Date={3}", GetType().Name, ChatId, MaxDate, Date); + } + } + + public class TLUpdateDeleteMessages : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateDeleteMessages; + + public TLVector Messages { get; set; } + public TLInt Pts { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Messages.ToStream(output); + Pts.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Messages = GetObject>(input); + Pts = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List { Pts }; + } + } + + public class TLUpdateDeleteMessages24 : TLUpdateDeleteMessages, IMultiPts + { + public new const uint Signature = TLConstructors.TLUpdateDeleteMessages24; + + public TLInt PtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Messages.ToStream(output); + Pts.ToStream(output); + PtsCount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Messages = GetObject>(input); + Pts = GetObject(input); + PtsCount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + } + + public class TLUpdateRestoreMessages : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateRestoreMessages; + + public TLVector Messages { get; set; } + public TLInt Pts { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Messages = GetObject>(bytes, ref position); + Pts = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Messages.ToStream(output); + Pts.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Messages = GetObject>(input); + Pts = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List { Pts }; + } + } + + public interface IUserTypingAction + { + TLSendMessageActionBase Action { get; set; } + } + + public abstract class TLUpdateTypingBase : TLUpdateBase + { + public TLInt UserId { get; set; } + } + + public class TLUpdateUserTyping : TLUpdateTypingBase + { + public const uint Signature = TLConstructors.TLUpdateUserTyping; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateUserTyping17 : TLUpdateUserTyping, IUserTypingAction + { + public new const uint Signature = TLConstructors.TLUpdateUserTyping17; + + public TLSendMessageActionBase Action { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + Action = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + Action.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + Action = GetObject(input); + + return this; + } + } + + + public class TLUpdateChatUserTyping : TLUpdateTypingBase + { + public const uint Signature = TLConstructors.TLUpdateChatUserTyping; + + public TLInt ChatId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChatId.ToStream(output); + UserId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + UserId = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChatUserTyping17 : TLUpdateChatUserTyping, IUserTypingAction + { + public new const uint Signature = TLConstructors.TLUpdateChatUserTyping17; + + public TLSendMessageActionBase Action { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Action = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChatId.ToStream(output); + UserId.ToStream(output); + Action.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + UserId = GetObject(input); + Action = GetObject(input); + + return this; + } + } + + public class TLUpdateEncryptedChatTyping : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateEncryptedChatTyping; + + public TLInt ChatId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChatId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChatParticipants : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateChatParticipants; + + public TLChatParticipantsBase Participants { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Participants = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Participants.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Participants = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateUserStatus : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateUserStatus; + + public TLInt UserId { get; set; } + public TLUserStatus Status { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + Status = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + Status.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + Status = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateUserName : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateUserName; + + public TLInt UserId { get; set; } + public TLString FirstName { get; set; } + public TLString LastName { get; set; } + public TLString UserName { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + FirstName = GetObject(bytes, ref position); + LastName = GetObject(bytes, ref position); + UserName = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + FirstName.ToStream(output); + LastName.ToStream(output); + UserName.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + FirstName = GetObject(input); + LastName = GetObject(input); + UserName = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateUserPhoto : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateUserPhoto; + + public TLInt UserId { get; set; } + + public TLInt Date { get; set; } + + public TLPhotoBase Photo { get; set; } + + public TLBool Previous { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Photo = GetObject(bytes, ref position); + Previous = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + Date.ToStream(output); + Photo.ToStream(output); + Previous.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + Date = GetObject(input); + Photo = GetObject(input); + Previous = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateContactRegistered : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateContactRegistered; + + public TLInt UserId { get; set; } + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + Date.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + Date = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public abstract class TLUpdateContactLinkBase : TLUpdateBase + { + public TLInt UserId { get; set; } + } + + public class TLUpdateContactLink : TLUpdateContactLinkBase + { + public const uint Signature = TLConstructors.TLUpdateContactLink; + + public TLMyLinkBase MyLink { get; set; } + public TLForeignLinkBase ForeignLink { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + MyLink = GetObject(bytes, ref position); + ForeignLink = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + MyLink.ToStream(output); + ForeignLink.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + MyLink = GetObject(input); + ForeignLink = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateContactLink24 : TLUpdateContactLinkBase + { + public const uint Signature = TLConstructors.TLUpdateContactLink24; + + public TLContactLinkBase MyLink { get; set; } + public TLContactLinkBase ForeignLink { get; set; } + + public override string ToString() + { + return string.Format("TLUpdateContactLink24 user_id={0} my_link={1} foreign_link={2}", UserId, MyLink, ForeignLink); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + MyLink = GetObject(bytes, ref position); + ForeignLink = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + MyLink.ToStream(output); + ForeignLink.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + MyLink = GetObject(input); + ForeignLink = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateActivation : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateActivation; + + public TLInt UserId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateNewAuthorization : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateNewAuthorization; + + public TLLong AuthKeyId { get; set; } + public TLInt Date { get; set; } + public TLString Device { get; set; } + public TLString Location { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + AuthKeyId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Device = GetObject(bytes, ref position); + Location = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + AuthKeyId.ToStream(output); + Date.ToStream(output); + Device.ToStream(output); + Location.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + AuthKeyId = GetObject(input); + Date = GetObject(input); + Device = GetObject(input); + Location = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateDCOptions : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateDCOptions; + + public TLVector DCOptions { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + DCOptions = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + DCOptions.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + DCOptions = GetObject>(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateNotifySettings : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateNotifySettings; + + public TLNotifyPeerBase Peer { get; set; } + + public TLPeerNotifySettingsBase NotifySettings { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Peer.ToStream(output); + NotifySettings.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + NotifySettings = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateUserBlocked : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateUserBlocked; + + public TLInt UserId { get; set; } + + public TLBool Blocked { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + Blocked = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + Blocked.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + Blocked = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdatePrivacy : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdatePrivacy; + + public TLPrivacyKeyBase Key { get; set; } + + public TLVector Rules { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Key = GetObject(bytes, ref position); + Rules = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Key.ToStream(output); + Rules.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Key = GetObject(input); + Rules = GetObject>(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateUserPhone : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateUserPhone; + + public TLInt UserId { get; set; } + + public TLString Phone { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + UserId = GetObject(bytes, ref position); + Phone = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + Phone.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + Phone = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateServiceNotification : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateServiceNotification; + + public TLString Type { get; set; } + + public TLString Message { get; set; } + + public TLMessageMediaBase Media { get; set; } + + public virtual TLBool Popup { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Type = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Media = GetObject(bytes, ref position); + Popup = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Type.ToStream(output); + Message.ToStream(output); + Media.ToStream(output); + Popup.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Type = GetObject(input); + Message = GetObject(input); + Media = GetObject(input); + Popup = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateServiceNotification59 : TLUpdateServiceNotification + { + public new const uint Signature = TLConstructors.TLUpdateServiceNotification59; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override TLBool Popup + { + get { return new TLBool(IsSet(_flags, (int)UpdateServiceNotificationFlags.Popup)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)UpdateServiceNotificationFlags.Popup); + } + } + } + + public TLInt InboxDate { get; set; } + + public TLVector Entities { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + InboxDate = GetObject(Flags, (int)UpdateServiceNotificationFlags.InboxDate, null, bytes, ref position); + Type = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Media = GetObject(bytes, ref position); + Entities = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, InboxDate, Flags, (int)UpdateServiceNotificationFlags.InboxDate); + Type.ToStream(output); + Message.ToStream(output); + Media.ToStream(output); + Entities.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + InboxDate = GetObject(Flags, (int)UpdateServiceNotificationFlags.InboxDate, null, input); + Type = GetObject(input); + Message = GetObject(input); + Media = GetObject(input); + Entities = GetObject>(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateWebPage37 : TLUpdateWebPage, IMultiPts + { + public new const uint Signature = TLConstructors.TLUpdateWebPage37; + + public TLInt Pts { get; set; } + + public TLInt PtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + WebPage = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + WebPage.ToStream(output); + Pts.ToStream(output); + PtsCount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + WebPage = GetObject(input); + Pts = GetObject(input); + PtsCount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + } + + public class TLUpdateWebPage : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateWebPage; + + public TLWebPageBase WebPage { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + WebPage = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + WebPage.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + WebPage = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + [Flags] + public enum UpdateChannelTooLongFlags + { + ChannelPts = 0x1 + } + + public class TLUpdateChannelTooLong49 : TLUpdateChannelTooLong + { + public new const uint Signature = TLConstructors.TLUpdateChannelTooLong49; + + public TLInt Flags { get; set; } + + public TLInt ChannelPts { get; set; } + + public override string ToString() + { + return string.Format("TLUpdateChannelTooLong49 channel_id={0} channel_pts={1} flags={2}", ChannelId, ChannelPts, Flags); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + ChannelId = GetObject(bytes, ref position); + ChannelPts = GetObject(Flags, (int)UpdateChannelTooLongFlags.ChannelPts, null, bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ChannelId.ToStream(output); + ToStream(output, ChannelPts, Flags, (int)UpdateChannelTooLongFlags.ChannelPts); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + ChannelId = GetObject(input); + ChannelPts = GetObject(Flags, (int)UpdateChannelTooLongFlags.ChannelPts, null, input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChannelTooLong : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateChannelTooLong; + + public TLInt ChannelId { get; set; } + + public override string ToString() + { + return "TLUpdateChannelTooLong channel_id=" + ChannelId; + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChannelId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChannelGroup : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateChannelGroup; + + public TLInt ChannelId { get; set; } + + public TLMessageGroup Group { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + Group = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChannelId.ToStream(output); + Group.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + Group = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateNewChannelMessage : TLUpdateBase, IMultiChannelPts + { + public const uint Signature = TLConstructors.TLUpdateNewChannelMessage; + + public TLMessageBase Message { get; set; } + + public TLInt ChannelPts { get; set; } + + public TLInt ChannelPtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + + var messageCommon = Message as TLMessageCommon; + if (messageCommon != null) messageCommon.SetUnreadSilent(TLBool.True); + + ChannelPts = GetObject(bytes, ref position); + ChannelPtsCount = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Message.ToStream(output); + ChannelPts.ToStream(output); + ChannelPtsCount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Message = GetObject(input); + ChannelPts = GetObject(input); + ChannelPtsCount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + + public override string ToString() + { + var toId = Message is TLMessageCommon ? ((TLMessageCommon) Message).ToId : null; + return string.Format("{0} message_id={1} channel=[{2}]", GetType(), Message.Index, toId); + } + } + + public class TLUpdateReadChannelInbox : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateReadChannelInbox; + + public TLInt ChannelId { get; set; } + + public TLInt MaxId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + MaxId = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChannelId.ToStream(output); + MaxId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + MaxId = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateDeleteChannelMessages : TLUpdateBase, IMultiChannelPts + { + public const uint Signature = TLConstructors.TLUpdateDeleteChannelMessages; + + public TLInt ChannelId { get; set; } + + public TLVector Messages { get; set; } + + public TLInt ChannelPts { get; set; } + + public TLInt ChannelPtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + Messages = GetObject>(bytes, ref position); + ChannelPts = GetObject(bytes, ref position); + ChannelPtsCount = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChannelId.ToStream(output); + Messages.ToStream(output); + ChannelPts.ToStream(output); + ChannelPtsCount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + Messages = GetObject>(input); + ChannelPts = GetObject(input); + ChannelPtsCount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChannelMessageViews : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateChannelMessageViews; + + public TLInt ChannelId { get; set; } + + public TLInt Id { get; set; } + + public TLInt Views { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + Views = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChannelId.ToStream(output); + Id.ToStream(output); + Views.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + Id = GetObject(input); + Views = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChannel : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateChannel; + + public TLInt ChannelId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + + return this; + } + + public override string ToString() + { + return "TLUpdateChannel channel_id=" + ChannelId; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChannelId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChatAdmins : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateChatAdmins; + + public TLInt ChatId { get; set; } + + public TLBool Enabled { get; set; } + + public TLInt Version { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + Enabled = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChatId.ToStream(output); + Enabled.ToStream(output); + Version.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + Enabled = GetObject(input); + Version = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChatParticipantAdmin : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateChatParticipantAdmin; + + public TLInt ChatId { get; set; } + + public TLInt UserId { get; set; } + + public TLBool IsAdmin { get; set; } + + public TLInt Version { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChatId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + IsAdmin = GetObject(bytes, ref position); + Version = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChatId.ToStream(output); + UserId.ToStream(output); + IsAdmin.ToStream(output); + Version.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChatId = GetObject(input); + UserId = GetObject(input); + IsAdmin = GetObject(input); + Version = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateNewStickerSet : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateNewStickerSet; + + public TLMessagesStickerSet Stickerset { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Stickerset = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Stickerset.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Stickerset = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + [Flags] + public enum UpdateStickerSetsOrderFlags + { + Masks = 0x1 + } + + public class TLUpdateStickerSetsOrder56 : TLUpdateStickerSetsOrder + { + public new const uint Signature = TLConstructors.TLUpdateStickerSetsOrder56; + + public TLInt Flags { get; set; } + + public bool Masks { get { return IsSet(Flags, (int)UpdateStickerSetsOrderFlags.Masks); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Order = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Order.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Order = GetObject>(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateStickerSetsOrder : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateStickerSetsOrder; + + public TLVector Order { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Order = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Order.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Order = GetObject>(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateStickerSets : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateStickerSets; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateSavedGifs : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateSavedGifs; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateBotInlineQuery : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateBotInlineQuery; + + public TLLong QueryId { get; set; } + + public TLInt UserId { get; set; } + + public TLString Query { get; set; } + + public TLString Offset { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + QueryId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Query = GetObject(bytes, ref position); + Offset = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + QueryId.ToStream(output); + UserId.ToStream(output); + Query.ToStream(output); + Offset.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + QueryId = GetObject(input); + UserId = GetObject(input); + Query = GetObject(input); + Offset = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateBotInlineQuery51 : TLUpdateBotInlineQuery + { + public new const uint Signature = TLConstructors.TLUpdateBotInlineQuery51; + + public TLInt Flags { get; set; } + + public TLGeoPointBase Geo { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + QueryId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Query = GetObject(bytes, ref position); + Geo = GetObject(Flags, (int)UpdateFlags.Geo, null, bytes, ref position); + Offset = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + QueryId.ToStream(output); + UserId.ToStream(output); + Query.ToStream(output); + ToStream(output, Geo, Flags, (int)UpdateFlags.Geo); + Offset.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + QueryId = GetObject(input); + UserId = GetObject(input); + Query = GetObject(input); + Geo = GetObject(Flags, (int)UpdateFlags.Geo, null, input); + Offset = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateBotInlineSend : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateBotInlineSend; + + public TLInt Flags { get; set; } + + public TLInt UserId { get; set; } + + public TLString Query { get; set; } + + public TLGeoPointBase Geo { get; set; } + + public TLString Id { get; set; } + + public TLInputBotInlineMessageId MessageId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Query = GetObject(bytes, ref position); + Geo = GetObject(Flags, (int)UpdateFlags.Geo, null, bytes, ref position); + Id = GetObject(bytes, ref position); + MessageId = GetObject(Flags, (int)UpdateFlags.MessageId, null, bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + UserId.ToStream(output); + Query.ToStream(output); + ToStream(output, Geo, Flags, (int)UpdateFlags.Geo); + Id.ToStream(output); + ToStream(output, MessageId, Flags, (int)UpdateFlags.MessageId); + } + + public override TLObject FromStream(Stream input) + { + UserId = GetObject(input); + Query = GetObject(input); + Geo = GetObject(Flags, (int)UpdateFlags.Geo, null, input); + Id = GetObject(input); + MessageId = GetObject(Flags, (int)UpdateFlags.MessageId, null, input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateEditChannelMessage : TLUpdateBase, IMultiChannelPts + { + public const uint Signature = TLConstructors.TLUpdateEditChannelMessage; + + public TLMessageBase Message { get; set; } + + public TLInt ChannelPts { get; set; } + + public TLInt ChannelPtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + //Execute.ShowDebugMessage(string.Format("TLUpdateEditChannelMessage.FromBytes channel_pts={0} channel_pts_count={1} message={2}", ChannelPts, ChannelPtsCount, Message)); + + Message = GetObject(bytes, ref position); + ChannelPts = GetObject(bytes, ref position); + ChannelPtsCount = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Message.ToStream(output); + ChannelPts.ToStream(output); + ChannelPtsCount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Message = GetObject(input); + ChannelPts = GetObject(input); + ChannelPtsCount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChannelPinnedMessage : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateChannelPinnedMessage; + + public TLInt ChannelId { get; set; } + + public TLInt Id { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChannelId.ToStream(output); + Id.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + Id = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + [Flags] + public enum UpdateBotCallbackQueryFlags + { + Data = 0x1, + GameId = 0x2, + } + + public class TLUpdateBotCallbackQuery56 : TLUpdateBotCallbackQuery + { + public new const uint Signature = TLConstructors.TLUpdateBotCallbackQuery56; + + public TLInt Flags { get; set; } + + public TLInt GameId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + QueryId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Peer = GetObject(bytes, ref position); + MessageId = GetObject(bytes, ref position); + Data = GetObject(Flags, (int)UpdateBotCallbackQueryFlags.Data, null, bytes, ref position); + GameId = GetObject(Flags, (int)UpdateBotCallbackQueryFlags.GameId, null, bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + QueryId.ToStream(output); + UserId.ToStream(output); + Peer.ToStream(output); + MessageId.ToStream(output); + ToStream(output, Data, Flags, (int)UpdateBotCallbackQueryFlags.Data); + ToStream(output, GameId, Flags, (int)UpdateBotCallbackQueryFlags.GameId); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + QueryId = GetObject(input); + UserId = GetObject(input); + Peer = GetObject(input); + MessageId = GetObject(input); + Data = GetObject(Flags, (int)UpdateBotCallbackQueryFlags.Data, null, input); + GameId = GetObject(Flags, (int)UpdateBotCallbackQueryFlags.GameId, null, input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateBotCallbackQuery : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateBotCallbackQuery; + + public TLLong QueryId { get; set; } + + public TLInt UserId { get; set; } + + public TLPeerBase Peer { get; set; } + + public TLInt MessageId { get; set; } + + public TLString Data { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + QueryId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Peer = GetObject(bytes, ref position); + MessageId = GetObject(bytes, ref position); + Data = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + QueryId.ToStream(output); + UserId.ToStream(output); + Peer.ToStream(output); + MessageId.ToStream(output); + Data.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + QueryId = GetObject(input); + UserId = GetObject(input); + Peer = GetObject(input); + MessageId = GetObject(input); + Data = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + [Flags] + public enum UpdateInlineBotCallbackQueryFlags + { + Data = 0x1, + GameId = 0x2 + } + + public class TLUpdateInlineBotCallbackQuery56 : TLUpdateInlineBotCallbackQuery + { + public new const uint Signature = TLConstructors.TLUpdateInlineBotCallbackQuery56; + + public TLInt Flags { get; set; } + + public TLInt GameId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + QueryId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + MessageId = GetObject(bytes, ref position); + Data = GetObject(Flags, (int)UpdateInlineBotCallbackQueryFlags.Data, null, bytes, ref position); + GameId = GetObject(Flags, (int)UpdateInlineBotCallbackQueryFlags.GameId, null, bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + QueryId.ToStream(output); + UserId.ToStream(output); + MessageId.ToStream(output); + ToStream(output, Data, Flags, (int)UpdateBotCallbackQueryFlags.Data); + ToStream(output, GameId, Flags, (int)UpdateBotCallbackQueryFlags.GameId); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + QueryId = GetObject(input); + UserId = GetObject(input); + MessageId = GetObject(input); + Data = GetObject(Flags, (int)UpdateInlineBotCallbackQueryFlags.Data, null, input); + GameId = GetObject(Flags, (int)UpdateInlineBotCallbackQueryFlags.GameId, null, input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateInlineBotCallbackQuery : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateInlineBotCallbackQuery; + + public TLLong QueryId { get; set; } + + public TLInt UserId { get; set; } + + public TLInputBotInlineMessageId MessageId { get; set; } + + public TLString Data { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + QueryId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + MessageId = GetObject(bytes, ref position); + Data = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + QueryId.ToStream(output); + UserId.ToStream(output); + MessageId.ToStream(output); + Data.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + QueryId = GetObject(input); + UserId = GetObject(input); + MessageId = GetObject(input); + Data = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateEditMessage : TLUpdateBase, IMultiPts + { + public const uint Signature = TLConstructors.TLUpdateEditMessage; + + public TLMessageBase Message { get; set; } + + public TLInt Pts { get; set; } + + public TLInt PtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + + Execute.ShowDebugMessage(string.Format("TLUpdateEditMessage.FromBytes pts={0} pts_count={1} message={2}", Pts, PtsCount, Message)); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Message.ToStream(output); + Pts.ToStream(output); + PtsCount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Message = GetObject(input); + Pts = GetObject(input); + PtsCount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + } + + public class TLUpdateReadChannelOutbox : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateReadChannelOutbox; + + public TLInt ChannelId { get; set; } + + public TLInt MaxId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + MaxId = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChannelId.ToStream(output); + MaxId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + MaxId = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateDraftMessage : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateDraftMessage; + + public TLPeerBase Peer { get; set; } + + public TLDraftMessageBase Draft { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Peer = GetObject(bytes, ref position); + Draft = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Peer.ToStream(output); + Draft.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Peer = GetObject(input); + Draft = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateReadFeaturedStickers : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateReadFeaturedStickers; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateRecentStickers : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateRecentStickers; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateConfig : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateConfig; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdatePtsChanged : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdatePtsChanged; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChannelWebPage : TLUpdateWebPage, IMultiChannelPts + { + public new const uint Signature = TLConstructors.TLUpdateChannelWebPage; + + public TLInt ChannelId { get; set; } + + public TLInt ChannelPts { get; set; } + + public TLInt ChannelPtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + WebPage = GetObject(bytes, ref position); + ChannelPts = GetObject(bytes, ref position); + ChannelPtsCount = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChannelId.ToStream(output); + WebPage.ToStream(output); + ChannelPts.ToStream(output); + ChannelPtsCount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + WebPage = GetObject(input); + ChannelPts = GetObject(input); + ChannelPtsCount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); //TLUtils.GetPtsRange(Pts, PtsCount); + } + } + + public class TLUpdatePhoneCall : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdatePhoneCall; + + public TLPhoneCallBase PhoneCall { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + PhoneCall = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + PhoneCall.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + PhoneCall = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + + public override string ToString() + { + return string.Format("TLUpdatePhoneCall PhoneCall={0}", PhoneCall); + } + } + + public abstract class TLUpdateDialogPinnedBase : TLUpdateBase + { + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Pinned + { + get { return IsSet(Flags, (int)UpdateDilogPinnedFlags.Pinned); } + set { SetUnset(ref _flags, value, (int)UpdateDilogPinnedFlags.Pinned); } + } + } + + public class TLUpdateDialogPinned76 : TLUpdateDialogPinnedBase + { + public const uint Signature = TLConstructors.TLUpdateDialogPinned76; + + public TLDialogPeerBase Peer { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Peer = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Peer.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Peer = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateDialogPinned : TLUpdateDialogPinnedBase + { + public const uint Signature = TLConstructors.TLUpdateDialogPinned; + + public TLPeerBase Peer { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Peer = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Peer.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Peer = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public abstract class TLUpdatePinnedDialogsBase : TLUpdateBase + { + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + } + + public class TLUpdatePinnedDialogs76 : TLUpdatePinnedDialogsBase + { + public const uint Signature = TLConstructors.TLUpdatePinnedDialogs76; + + protected TLVector _order; + + public TLVector Order + { + get { return _order; } + set { SetField(out _order, value, ref _flags, (int)UpdatePinnedDialogsFlags.Order); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Order = GetObject>(Flags, (int)UpdatePinnedDialogsFlags.Order, null, bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, Order, Flags, (int)UpdatePinnedDialogsFlags.Order); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Order = GetObject>(Flags, (int)UpdatePinnedDialogsFlags.Order, null, input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdatePinnedDialogs : TLUpdatePinnedDialogsBase + { + public const uint Signature = TLConstructors.TLUpdatePinnedDialogs; + + protected TLVector _order; + + public TLVector Order + { + get { return _order; } + set { SetField(out _order, value, ref _flags, (int)UpdatePinnedDialogsFlags.Order); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Order = GetObject>(Flags, (int)UpdatePinnedDialogsFlags.Order, null, bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + ToStream(output, Order, Flags, (int)UpdatePinnedDialogsFlags.Order); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Order = GetObject>(Flags, (int)UpdatePinnedDialogsFlags.Order, null, input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateBotWebhookJSON : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateBotWebhookJSON; + + public TLString DataJSON { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + DataJSON = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + DataJSON.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + DataJSON = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateBotWebhookJSONQuery : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateBotWebhookJSONQuery; + + public TLLong QueryId { get; set; } + + public TLString DataJSON { get; set; } + + public TLInt Timeout { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + QueryId = GetObject(bytes, ref position); + DataJSON = GetObject(bytes, ref position); + Timeout = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + QueryId.ToStream(output); + DataJSON.ToStream(output); + Timeout.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + QueryId = GetObject(input); + DataJSON = GetObject(input); + Timeout = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateBotShippingQuery : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateBotShippingQuery; + + public TLLong QueryId { get; set; } + + public TLInt UserId { get; set; } + + public TLString Payload { get; set; } + + public TLPostAddress ShippingAddress { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + QueryId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Payload = GetObject(bytes, ref position); + ShippingAddress = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + QueryId.ToStream(output); + UserId.ToStream(output); + Payload.ToStream(output); + ShippingAddress.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + QueryId = GetObject(input); + UserId = GetObject(input); + Payload = GetObject(input); + ShippingAddress = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateBotPrecheckoutQuery : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateBotPrecheckoutQuery; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLLong QueryId { get; set; } + + public TLInt UserId { get; set; } + + public TLString Payload { get; set; } + + protected TLPaymentRequestedInfo _info; + + public TLPaymentRequestedInfo Info + { + get { return _info; } + set { SetField(out _info, value, ref _flags, (int)UpdateBotPrecheckoutQueryFlags.Info); } + } + + protected TLString _shippingOptionId; + + public TLString ShippingOptionId + { + get { return _shippingOptionId; } + set { SetField(out _shippingOptionId, value, ref _flags, (int)UpdateBotPrecheckoutQueryFlags.ShippingOptionId); } + } + + public TLString Currency { get; set; } + + public TLLong TotalAmount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + QueryId = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Payload = GetObject(bytes, ref position); + _info = GetObject(Flags, (int)UpdateBotPrecheckoutQueryFlags.Info, null, bytes, ref position); + _shippingOptionId = GetObject(Flags, (int)UpdateBotPrecheckoutQueryFlags.ShippingOptionId, null, bytes, ref position); + Currency = GetObject(bytes, ref position); + TotalAmount = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + QueryId.ToStream(output); + UserId.ToStream(output); + Payload.ToStream(output); + ToStream(output, Info, Flags, (int)UpdateBotPrecheckoutQueryFlags.Info); + ToStream(output, ShippingOptionId, Flags, (int)UpdateBotPrecheckoutQueryFlags.ShippingOptionId); + Currency.ToStream(output); + TotalAmount.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + QueryId = GetObject(input); + UserId = GetObject(input); + Payload = GetObject(input); + _info = GetObject(Flags, (int)UpdateBotPrecheckoutQueryFlags.Info, null, input); + _shippingOptionId = GetObject(Flags, (int)UpdateBotPrecheckoutQueryFlags.ShippingOptionId, null, input); + Currency = GetObject(input); + TotalAmount = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateLangPackTooLong : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateLangPackTooLong; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateLangPack : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateLangPack; + + public TLLangPackDifference Difference { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Difference = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Difference.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Difference = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateFavedStickers : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateFavedStickers; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChannelReadMessagesContents : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateChannelReadMessagesContents; + + public TLInt ChannelId { get; set; } + + public TLVector Messages { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + Messages = GetObject>(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChannelId.ToStream(output); + Messages.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + Messages = GetObject>(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateContactsReset : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateContactsReset; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateChannelAvailableMessages : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateChannelAvailableMessages; + + public TLInt ChannelId { get; set; } + + public TLInt AvailableMinId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + ChannelId = GetObject(bytes, ref position); + AvailableMinId = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + ChannelId.ToStream(output); + AvailableMinId.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + ChannelId = GetObject(input); + AvailableMinId = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateReadFeed : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateReadFeed; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt FeedId { get; set; } + + public TLFeedPosition MaxPosition { get; set; } + + protected TLInt _unreadCount; + + public TLInt UnreadCount + { + get { return _unreadCount; } + set { SetField(out _unreadCount, value, ref _flags, (int)UpdateReadFeedFlags.UnreadCount); } + } + + protected TLInt _unreadMutedCount; + + public TLInt UnreadMutedCount + { + get { return _unreadMutedCount; } + set { SetField(out _unreadMutedCount, value, ref _flags, (int)UpdateReadFeedFlags.UnreadCount); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + FeedId = GetObject(bytes, ref position); + MaxPosition = GetObject(bytes, ref position); + _unreadCount = GetObject(Flags, (int)UpdateReadFeedFlags.UnreadCount, null, bytes, ref position); + _unreadMutedCount = GetObject(Flags, (int)UpdateReadFeedFlags.UnreadCount, null, bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + FeedId.ToStream(output); + MaxPosition.ToStream(output); + ToStream(output, _unreadCount, Flags, (int)UpdateReadFeedFlags.UnreadCount); + ToStream(output, _unreadMutedCount, Flags, (int)UpdateReadFeedFlags.UnreadCount); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + FeedId = GetObject(input); + MaxPosition = GetObject(input); + _unreadCount = GetObject(Flags, (int)UpdateReadFeedFlags.UnreadCount, null, input); + _unreadMutedCount = GetObject(Flags, (int)UpdateReadFeedFlags.UnreadCount, null, input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdateDialogUnreadMark : TLUpdateBase + { + public const uint Signature = TLConstructors.TLUpdateDialogUnreadMark; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public bool Unread + { + get { return IsSet(_flags, (int)UpdateDialogUnreadMarkFlags.Unread); } + set { SetUnset(ref _flags, value, (int)UpdateDialogUnreadMarkFlags.Unread); } + } + + public TLDialogPeerBase Peer { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Peer = GetObject(bytes, ref position); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Peer.ToStream(output); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Peer = GetObject(input); + + return this; + } + + public override IList GetPts() + { + return new List(); + } + } +} diff --git a/Telegram.Api/TL/TLUpdates.cs b/Telegram.Api/TL/TLUpdates.cs new file mode 100755 index 0000000..b3532c5 --- /dev/null +++ b/Telegram.Api/TL/TLUpdates.cs @@ -0,0 +1,947 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Telegram.Api.TL +{ + public abstract class TLUpdatesBase : TLObject + { + public abstract IList GetSeq(); + + public abstract IList GetPts(); + } + + public class TLUpdatesTooLong : TLUpdatesBase + { + public const uint Signature = TLConstructors.TLUpdatesTooLong; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override IList GetSeq() + { + return new List(); + } + + public override IList GetPts() + { + return new List(); + } + } + + public class TLUpdatesShortSentMessage : TLUpdatesBase, ISentMessageMedia, IMultiPts + { + public const uint Signature = TLConstructors.TLUpdatesShortSentMessage; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt Id { get; set; } + + public TLInt Pts { get; set; } + + public TLInt PtsCount { get; set; } + + public TLInt Date { get; set; } + + public TLMessageMediaBase Media { get; set; } + + public TLVector Entities { get; set; } + + public bool HasMedia { get { return IsSet(Flags, (int) MessageFlags.Media); } } + + public bool HasEntities { get { return IsSet(Flags, (int) MessageFlags.Entities); } } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.Media)) + { + Media = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + + _flags.Value |= (int) MessageFlags.Unread; + + return this; + } + + public override IList GetSeq() + { + return new List(); + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + + public override string ToString() + { + return string.Format("TLUpdatesShortSentMessage id={0} media={1} flags={2}", Id, Media, TLMessageBase.MessageFlagsString(Flags)); + } + } + + public class TLUpdatesShortMessage : TLUpdatesBase + { + public const uint Signature = TLConstructors.TLUpdateShortMessage; + + public TLInt Id { get; set; } + + public TLInt UserId { get; set; } + + public TLString Message { get; set; } + + public TLInt Pts { get; set; } + + public TLInt Date { get; set; } + + public TLInt Seq { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Seq = GetObject(bytes, ref position); + + return this; + } + + public override IList GetSeq() + { + return new List { Seq }; + } + + public override IList GetPts() + { + return new List { Pts }; + } + + public override string ToString() + { + return string.Format("UserMessage: FromId: {0} Message: {1}", UserId, Message); + } + } + + public class TLUpdatesShortMessage24 : TLUpdatesShortMessage, IMultiPts + { + public new const uint Signature = TLConstructors.TLUpdateShortMessage24; + + public TLInt PtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override IList GetSeq() + { + return new List(); + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + + public override string ToString() + { + return string.Format("UserMessage: FromId: {0} Message: {1}", UserId, Message); + } + } + + public class TLUpdatesShortMessage25 : TLUpdatesShortMessage24 + { + public new const uint Signature = TLConstructors.TLUpdatesShortMessage25; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt FwdFromId { get; set; } + + public TLInt FwdDate { get; set; } + + public TLInt ReplyToMsgId { get; set; } + + public TLBool Out + { + get { return new TLBool(IsSet(_flags, (int)MessageFlags.Out)); } + } + + public TLBool Unread + { + get { return new TLBool(IsSet(_flags, (int)MessageFlags.Unread)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)MessageFlags.Unread); + } + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + + return this; + } + + public override IList GetSeq() + { + return new List(); + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + + public override string ToString() + { + return string.Format("UserMessage: FromId: {0} Message: {1}", UserId, Message); + } + } + + public class TLUpdatesShortMessage34 : TLUpdatesShortMessage25 + { + public new const uint Signature = TLConstructors.TLUpdatesShortMessage34; + + public TLVector Entities { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + + return this; + } + + public override IList GetSeq() + { + return new List(); + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + + public override string ToString() + { + return string.Format("UserMessage: FromId: {0} Message: {1}", UserId, Message); + } + } + + public class TLUpdatesShortMessage40 : TLUpdatesShortMessage34 + { + public new const uint Signature = TLConstructors.TLUpdatesShortMessage40; + + public TLPeerBase FwdFrom { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFrom = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + +#if DEBUG + var messageString = Message.ToString(); + var logString = string.Format("TLUpdateShortMessage40 id={0} flags={1} user_id={2} message={3} pts={4} pts_count={5} date={6} fwd_from={7} fwd_date={8} reply_to_msg_id={9} entities={10}", Id, TLMessageBase.MessageFlagsString(Flags), UserId, messageString.Substring(0, Math.Min(messageString.Length, 5)), Pts, PtsCount, Date, FwdFrom, FwdDate, ReplyToMsgId, Entities); + + Logs.Log.Write(logString); +#endif + + return this; + } + + public override IList GetSeq() + { + return new List(); + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + + public override string ToString() + { + return string.Format("UserMessage: FromId: {0} Message: {1}", UserId, Message); + } + } + + public class TLUpdatesShortMessage45 : TLUpdatesShortMessage40 + { + public new const uint Signature = TLConstructors.TLUpdatesShortMessage45; + + public TLInt ViaBotId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFrom = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ViaBotId)) + { + ViaBotId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + +//#if DEBUG +// var messageString = Message.ToString(); +// var logString = string.Format("TLUpdateShortMessage45 id={0} flags={1} user_id={2} message={3} pts={4} pts_count={5} date={6} fwd_from={7} fwd_date={8} via_bot_id={9} reply_to_msg_id={10} entities={11}", Id, TLMessageBase.MessageFlagsString(Flags), UserId, messageString.Substring(0, Math.Min(messageString.Length, 5)), Pts, PtsCount, Date, FwdFrom, FwdDate, ViaBotId, ReplyToMsgId, Entities); + +// Logs.Log.Write(logString); +//#endif + + return this; + } + + public override IList GetSeq() + { + return new List(); + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + + public override string ToString() + { + return string.Format("UserMessage: FromId: {0} Message: {1}", UserId, Message); + } + } + + public class TLUpdatesShortMessage48 : TLUpdatesShortMessage45 + { + public new const uint Signature = TLConstructors.TLUpdatesShortMessage48; + + public TLMessageFwdHeader FwdHeader { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdHeader = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ViaBotId)) + { + ViaBotId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + + _flags.Value |= (int)MessageFlags.Unread; + +//#if DEBUG +// var messageString = Message.ToString(); +// var logString = string.Format("TLUpdateShortMessage45 id={0} flags={1} user_id={2} message={3} pts={4} pts_count={5} date={6} fwd_from={7} fwd_date={8} via_bot_id={9} reply_to_msg_id={10} entities={11}, fwd_header={12}", Id, TLMessageBase.MessageFlagsString(Flags), UserId, messageString.Substring(0, Math.Min(messageString.Length, 5)), Pts, PtsCount, Date, FwdFrom, FwdDate, ViaBotId, ReplyToMsgId, Entities, FwdHeader); + +// Logs.Log.Write(logString); +//#endif + + return this; + } + + public override IList GetSeq() + { + return new List(); + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + + public override string ToString() + { + return string.Format("UserMessage: FromId: {0} Message: {1}", UserId, Message); + } + } + + public class TLUpdatesShortChatMessage : TLUpdatesShortMessage + { + public new const uint Signature = TLConstructors.TLUpdateShortChatMessage; + + public TLInt ChatId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + ChatId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Seq = GetObject(bytes, ref position); + + return this; + } + + public override string ToString() + { + return string.Format("ChatMessage: ChatId: {0} FromId: {1} Message: {2}", ChatId, UserId, Message); + } + } + + public class TLUpdatesShortChatMessage24 : TLUpdatesShortChatMessage, IMultiPts + { + public new const uint Signature = TLConstructors.TLUpdateShortChatMessage24; + + public TLInt PtsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + ChatId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override IList GetSeq() + { + return new List(); + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + + public override string ToString() + { + return string.Format("ChatMessage: ChatId: {0} FromId: {1} Message: {2}", ChatId, UserId, Message); + } + } + + public class TLUpdatesShortChatMessage25 : TLUpdatesShortChatMessage24 + { + public new const uint Signature = TLConstructors.TLUpdatesShortChatMessage25; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public TLInt FwdFromId { get; set; } + + public TLInt FwdDate { get; set; } + + public TLInt ReplyToMsgId { get; set; } + + public TLBool Out + { + get { return new TLBool(IsSet(_flags, (int)MessageFlags.Out)); } + } + + public TLBool Unread + { + get { return new TLBool(IsSet(_flags, (int)MessageFlags.Unread)); } + set + { + if (value != null) + { + SetUnset(ref _flags, value.Value, (int)MessageFlags.Unread); + } + } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + ChatId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + + return this; + } + + public override IList GetSeq() + { + return new List(); + } + + public override IList GetPts() + { + return TLUtils.GetPtsRange(Pts, PtsCount); + } + + public override string ToString() + { + return string.Format("ChatMessage: ChatId: {0} FromId: {1} Message: {2}", ChatId, UserId, Message); + } + } + + public class TLUpdatesShortChatMessage34 : TLUpdatesShortChatMessage25 + { + public new const uint Signature = TLConstructors.TLUpdatesShortChatMessage34; + + public TLVector Entities { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + ChatId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFromId = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + + return this; + } + } + + public class TLUpdatesShortChatMessage40 : TLUpdatesShortChatMessage34 + { + public new const uint Signature = TLConstructors.TLUpdatesShortChatMessage40; + + public TLPeerBase FwdFrom { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + ChatId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFrom = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + + + +#if DEBUG + var messageString = Message.ToString(); + var logString = string.Format("TLUpdateShortChatMessage40 id={0} flags={1} user_id={2} message={3} pts={4} pts_count={5} date={6} fwd_from={7} fwd_date={8} reply_to_msg_id={9} entities={10}", Id, TLMessageBase.MessageFlagsString(Flags), UserId, messageString.Substring(0, Math.Min(messageString.Length, 5)), Pts, PtsCount, Date, FwdFrom, FwdDate, ReplyToMsgId, Entities); + + Logs.Log.Write(logString); +#endif + + return this; + } + } + + public class TLUpdatesShortChatMessage45 : TLUpdatesShortChatMessage40 + { + public new const uint Signature = TLConstructors.TLUpdatesShortChatMessage45; + + public TLInt ViaBotId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + ChatId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdFrom = GetObject(bytes, ref position); + FwdDate = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ViaBotId)) + { + ViaBotId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + +#if DEBUG + var messageString = Message.ToString(); + var logString = string.Format("TLUpdateShortChatMessage44 id={0} flags={1} user_id={2} message={3} pts={4} pts_count={5} date={6} fwd_from={7} fwd_date={8} reply_to_msg_id={9} via_bot_id={10} entities={11}", Id, TLMessageBase.MessageFlagsString(Flags), UserId, messageString.Substring(0, Math.Min(messageString.Length, 5)), Pts, PtsCount, Date, FwdFrom, FwdDate, ViaBotId, ReplyToMsgId, Entities); + + Logs.Log.Write(logString); +#endif + + return this; + } + } + + public class TLUpdatesShortChatMessage48 : TLUpdatesShortChatMessage45 + { + public new const uint Signature = TLConstructors.TLUpdatesShortChatMessage48; + + public TLMessageFwdHeader FwdHeader { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + ChatId = GetObject(bytes, ref position); + Message = GetObject(bytes, ref position); + Pts = GetObject(bytes, ref position); + PtsCount = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + if (IsSet(Flags, (int)MessageFlags.FwdFrom)) + { + FwdHeader = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ViaBotId)) + { + ViaBotId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.ReplyToMsgId)) + { + ReplyToMsgId = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)MessageFlags.Entities)) + { + Entities = GetObject>(bytes, ref position); + } + + _flags.Value |= (int)MessageFlags.Unread; + +#if DEBUG + var messageString = Message.ToString(); + var logString = string.Format("TLUpdateShortChatMessage48 id={0} flags={1} user_id={2} message={3} pts={4} pts_count={5} date={6} fwd_from={7} fwd_date={8} reply_to_msg_id={9} via_bot_id={10} entities={11} fwd_header={12}", Id, TLMessageBase.MessageFlagsString(Flags), UserId, messageString.Substring(0, Math.Min(messageString.Length, 5)), Pts, PtsCount, Date, FwdFrom, FwdDate, ViaBotId, ReplyToMsgId, Entities, FwdHeader); + + Logs.Log.Write(logString); +#endif + + return this; + } + } + + public class TLUpdatesShort : TLUpdatesBase + { + public const uint Signature = TLConstructors.TLUpdateShort; + + public TLUpdateBase Update { get; set; } + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Update = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override IList GetSeq() + { + return new List(); + } + + public override IList GetPts() + { + return Update.GetPts(); + } + + public override string ToString() + { + return "TLUpdatesShort Update: " + Update; + } + } + + public class TLUpdates : TLUpdatesBase + { + public const uint Signature = TLConstructors.TLUpdates; + + public TLVector Updates { get; set; } + + public TLVector Users { get; set; } + + public TLVector Chats { get; set; } + + public TLInt Date { get; set; } + + public TLInt Seq { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Updates = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Date = GetObject(bytes, ref position); + Seq = GetObject(bytes, ref position); + + return this; + } + + public override string ToString() + { + var info = new StringBuilder(); + + info.AppendLine("TLUpdates"); + for (var i = 0; i < Updates.Count; i++) + { + info.AppendLine(Updates[i].ToString()); + } + + return info.ToString(); + } + + public override IList GetSeq() + { + return new List{Seq}; + } + + public override IList GetPts() + { + return Updates.SelectMany(x => x.GetPts()).ToList(); + } + } + + public class TLUpdatesCombined : TLUpdates + { + public new const uint Signature = TLConstructors.TLUpdatesCombined; + + public TLInt SeqStart { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Updates = GetObject>(bytes, ref position); + Users = GetObject>(bytes, ref position); + Chats = GetObject>(bytes, ref position); + Date = GetObject(bytes, ref position); + SeqStart = GetObject(bytes, ref position); // seq младший + Seq = GetObject(bytes, ref position); // seq старший + + return this; + } + + public override IList GetSeq() + { + var list = new List(); + + for (var i = SeqStart.Value; i <= Seq.Value; i++) + { + list.Add(new TLInt(i)); + } + + return list; + } + + public override IList GetPts() + { + return Updates.SelectMany(x => x.GetPts()).ToList(); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLUserBase.cs b/Telegram.Api/TL/TLUserBase.cs new file mode 100755 index 0000000..b6cf4cb --- /dev/null +++ b/Telegram.Api/TL/TLUserBase.cs @@ -0,0 +1,2985 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.IO; +#if WINDOWS_PHONE +using System.Windows; +using Microsoft.Phone.UserData; +#elif WIN_RT +using Windows.UI.Xaml; +#endif +using Telegram.Api.TL.Interfaces; +using Telegram.Api.Extensions; +using Telegram.Api.Resources; + +namespace Telegram.Api.TL +{ + [Flags] + public enum UserFlags + { + AccessHash = 0x1, // 0 + FirstName = 0x2, // 1 + LastName = 0x4, + UserName = 0x8, + Phone = 0x10, + Photo = 0x20, + Status = 0x40, // 6 + // = 0x80, // 7 + // = 0x100, // 8 + // = 0x200, // 9 + Self = 0x400, // 10 + Contact = 0x800, + ContactMutual = 0x1000, + Deleted = 0x2000, + Bot = 0x4000, + BotAllHistory = 0x8000, + BotGroupsBlocked = 0x10000, + Verified = 0x20000, + Restricted = 0x40000, + BotInlinePlaceholder = 0x80000, + Min = 0x100000, // 20 + BotInlineGeo = 0x200000, + LangCode = 0x400000, + } + + [Flags] + public enum UserCustomFlags + { + Blocked = 0x1, // 0 + About = 0x2, // 1 + BotInlineGeoAccess = 0x4, + NotifyGeoAccessDate = 0x8, + ReadInboxMaxId = 0x10, + ReadOutboxMaxId = 0x20, + BotOpenUrlPermission = 0x40, + BotPassTelegramNameToWebPagesPermission = 0x80, + CommonChatsCount = 0x100, + BotPaymentsPermission = 0x200, + } + + public interface IReadMaxId + { + TLInt ReadInboxMaxId { get; set; } + + TLInt ReadOutboxMaxId { get; set; } + } + + public interface IUserName + { + TLString UserName { get; set; } + } + + public interface INotifySettings + { + TLPeerNotifySettingsBase NotifySettings { get; set; } + } + + public class TLUserExtendedInfo : TLObject + { + public const uint Signature = TLConstructors.TLUserExtendedInfo; + + public TLString FirstName { get; set; } + + public TLString LastName { get; set; } + + public override TLObject FromStream(Stream input) + { + FirstName = GetObject(input); + LastName = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + } + } + + public class TLUserPhone : TLObject + { + public TLInt Kind { get; set; } + + public TLString Number { get; set; } + + public TLString Description { get; set; } + + protected bool _isSelected; + + public bool IsSelected + { + get { return _isSelected; } + set { SetField(ref _isSelected, value, () => IsSelected); } + } + + protected bool _isIconVisible; + + public bool IsIconVisible + { + get { return _isIconVisible; } + set { SetField(ref _isIconVisible, value, () => IsIconVisible); } + } + } + + public class TLUserNotRegistered : TLUserBase + { + public TLVector Phones { get; set; } + + public override TLInputUserBase ToInputUser() + { + return null; + } + + public override TLInputPeerBase ToInputPeer() + { + return null; + } + + public override string GetUnsendedTextFileName() + { + return "u" + Id + ".dat"; + } + + public override bool IsDeleted { get { return false; } set { } } + + public override bool IsSelf { get { return false; } set { } } + + public override bool IsForeign { get { return false; } } + + public override bool IsRequest { get { return false; } } + + public override bool IsContact { get { return false; } set { } } + + public override bool IsContactMutual { get { return false; } set { } } + } + + public abstract class TLUserBase : TLObject, IInputPeer, ISelectable, IFullName, INotifySettings, IVIsibility + { + public abstract bool IsDeleted { get; set; } + + public abstract bool IsSelf { get; set; } + + public abstract bool IsForeign { get; } //access_hash, !phone, !contact, !contact_mutual + + public abstract bool IsRequest { get; } //access_hash, phone, !contact, !contact_mutual + + public abstract bool IsContact { get; set; } //access_hash, phone, contact + + public abstract bool IsContactMutual { get; set; } //access_hash, phone, contact_mutual + + public bool IsAdmin { get; set; } + + public string AccessToken { get; set; } + + public TLUserBase Self + { + get { return this; } + } + + public int Index + { + get { return Id.Value; } + set { Id = new TLInt(value); } + } + + public TLInt Id { get; set; } + + public TLString _firstName; + + public TLString FirstName + { + get { return _firstName; } + set + { + SetField(ref _firstName, value, () => FirstName); + NotifyOfPropertyChange(() => FullName2); + } + } + + public TLString _lastName; + + public TLString LastName + { + get { return _lastName; } + set + { + SetField(ref _lastName, value, () => LastName); + NotifyOfPropertyChange(() => FullName2); + } + } + + public TLString Phone { get; set; } + + public TLPhotoBase _photo; + + public TLPhotoBase Photo + { + get { return _photo; } + set { SetField(ref _photo, value, () => Photo); } + } + + public TLUserStatus _status; + + public TLUserStatus Status + { + get { return _status; } + set + { + if (_status != value) + { + _status = value; + NotifyOfPropertyChange(() => Status); + NotifyOfPropertyChange(() => StatusCommon); + } + } + } + + public TLUserBase StatusCommon + { + get { return this; } + } + + public int StatusValue + { + get + { + if (Status is TLUserStatusOnline) + { + return int.MaxValue; + } + var offline = Status as TLUserStatusOffline; + if (offline != null) + { + return offline.WasOnline.Value; + } + + return int.MinValue; + } + } + + public static string UserFlagsString(TLInt flags) + { + if (flags == null) return string.Empty; + + var list = (UserFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + public static string UserCustomFlagsString(TLLong flags) + { + if (flags == null) return string.Empty; + + var list = (UserCustomFlags)flags.Value; + + return string.Format("{0} [{1}]", flags, list); + } + + #region Additional + + public virtual bool IsVerified + { + get { return Index == 777000; } + set { throw new NotImplementedException(); } + } + + public IList FullNameWords { get; set; } + + public bool RemoveUserAction { get; set; } + + public TLContact Contact { get; set; } + + public override string ToString() + { + return string.Format("{0} {1} {2}", GetType().Name, Index, FullName); + } + + public static string GetFirstName(TLString FirstName, TLString LastName, TLString Phone) + { + var firstName = FirstName != null ? FirstName.ToString().Trim() : string.Empty; + + if (!string.IsNullOrEmpty(firstName)) + { + return firstName; + } + + var lastName = LastName != null ? LastName.ToString().Trim() : string.Empty; + if (!string.IsNullOrEmpty(lastName)) + { + return lastName; + } + + if (string.IsNullOrEmpty(firstName) && string.IsNullOrEmpty(lastName)) + { + return Phone != null ? "+" + Phone : string.Empty; + } + + return string.Empty; + } + + public virtual string ShortName + { + get + { + if (IsSelf) + { + return AppResources.SavedMessages; + } + + if (this is TLUserEmpty) + { + return AppResources.EmptyUser; + } + + if (IsDeleted) + { + return AppResources.DeletedUser; + } + + var firstName = FirstName != null ? FirstName.ToString() : string.Empty; + var lastName = LastName != null ? LastName.ToString() : string.Empty; + if (ExtendedInfo != null) + { + firstName = ExtendedInfo.FirstName != null ? ExtendedInfo.FirstName.ToString() : string.Empty; + lastName = ExtendedInfo.LastName != null ? ExtendedInfo.LastName.ToString() : string.Empty; + } + + if (string.Equals(firstName, lastName, StringComparison.OrdinalIgnoreCase)) + { + return firstName; + } + + if (!string.IsNullOrEmpty(firstName)) + { + return firstName; + } + + if (!string.IsNullOrEmpty(lastName)) + { + return lastName; + } + + return Phone != null ? "+" + Phone : string.Empty; + } + } + + public virtual string FullName + { + get + { + if (IsSelf) + { + return AppResources.SavedMessages; + } + + if (this is TLUserEmpty) + { + return AppResources.EmptyUser; + } + + if (IsDeleted) + { + return AppResources.DeletedUser; + } + + var firstName = FirstName != null ? FirstName.ToString() : string.Empty; + var lastName = LastName != null ? LastName.ToString() : string.Empty; + if (ExtendedInfo != null) + { + firstName = ExtendedInfo.FirstName != null ? ExtendedInfo.FirstName.ToString() : string.Empty; + lastName = ExtendedInfo.LastName != null ? ExtendedInfo.LastName.ToString() : string.Empty; + } + + if (string.IsNullOrEmpty(firstName) && string.IsNullOrEmpty(lastName)) + { + return Phone != null ? "+" + Phone : string.Empty; + } + + if (string.Equals(firstName, lastName, StringComparison.OrdinalIgnoreCase)) + { + return firstName; + } + + if (string.IsNullOrEmpty(firstName)) + { + return lastName; + } + + if (string.IsNullOrEmpty(lastName)) + { + return firstName; + } + + return string.Format("{0} {1}", firstName, lastName); + } + } + + public virtual string FullName2 + { + get + { + if (this is TLUserEmpty) + { + return AppResources.EmptyUser; + } + + if (IsDeleted) + { + return AppResources.DeletedUser; + } + + var firstName = FirstName != null ? FirstName.ToString() : string.Empty; + var lastName = LastName != null ? LastName.ToString() : string.Empty; + if (ExtendedInfo != null) + { + firstName = ExtendedInfo.FirstName != null ? ExtendedInfo.FirstName.ToString() : string.Empty; + lastName = ExtendedInfo.LastName != null ? ExtendedInfo.LastName.ToString() : string.Empty; + } + + if (string.IsNullOrEmpty(firstName) && string.IsNullOrEmpty(lastName)) + { + return Phone != null ? "+" + Phone : string.Empty; + } + + if (string.Equals(firstName, lastName, StringComparison.OrdinalIgnoreCase)) + { + return firstName; + } + + if (string.IsNullOrEmpty(firstName)) + { + return lastName; + } + + if (string.IsNullOrEmpty(lastName)) + { + return firstName; + } + + return string.Format("{0} {1}", firstName, lastName); + } + } + + public virtual bool HasPhone { get { return Phone != null && !string.IsNullOrEmpty(Phone.ToString()); } } + + public abstract TLInputUserBase ToInputUser(); + + public virtual void Update(TLUserBase user) + { + try + { + _firstName = user.FirstName; + _lastName = user.LastName; + Phone = user.Phone; + + if (Photo != null + && user.Photo != null + && Photo.GetType() == user.Photo.GetType()) + { + Photo.Update(user.Photo); + } + else + { + _photo = user.Photo; + } + + _status = user.Status; + + if (user.Contact != null) + { + Contact = user.Contact; + } + + if (user.Link != null) + { + Link = user.Link; + } + + if (user.ProfilePhoto != null) + { + ProfilePhoto = user.ProfilePhoto; + } + + if (user.NotifySettings != null) + { + NotifySettings = user.NotifySettings; + } + + if (user.ExtendedInfo != null) + { + ExtendedInfo = user.ExtendedInfo; + } + + if (user.Blocked != null) + { + Blocked = user.Blocked; + } + } + catch (Exception e) + { + + } + + } + + public abstract TLInputPeerBase ToInputPeer(); + + public virtual string GetUnsendedTextFileName() + { + return "u" + Id + ".dat"; + } + + public TLUserExtendedInfo ExtendedInfo { get; set; } + + #region UserFull information + + public TLLinkBase Link { get; set; } + + public TLPhotoBase ProfilePhoto { get; set; } + + public TLPeerNotifySettingsBase NotifySettings { get; set; } + + public virtual TLBool Blocked { get; set; } + + public TLBotInfoBase BotInfo { get; set; } + #endregion + + public Visibility DeleteActionVisibility { get; set; } + + #endregion + + public TLInputNotifyPeerBase ToInputNotifyPeer() + { + return new TLInputNotifyPeer { Peer = ToInputPeer() }; + } + + private bool _isVisible; + + public bool IsVisible + { + get { return _isVisible; } + set { SetField(ref _isVisible, value, () => IsVisible); } + } + + public bool _isSelected; + + public bool IsSelected + { + get { return _isSelected; } + set { SetField(ref _isSelected, value, () => IsSelected); } + } + + private string _selectedText; + + public string SelectedText + { + get { return _selectedText; } + set { SetField(ref _selectedText, value, () => SelectedText); } + } + + #region PhoneBook + public TLLong ClientId { get; set; } + + public string Mobile { get; set; } + + public string Mobile2 { get; set; } + + + public string Home { get; set; } + + public string Home2 { get; set; } + + + public string Work { get; set; } + + public string Work2 { get; set; } + + + public string Company { get; set; } + + public string Pager { get; set; } + + public string HomeFax { get; set; } + + public string WorkFax { get; set; } + + #endregion + + public static string GetLastNameKey(TLUserBase person) + { + if (person.LastName == null) return ('#').ToString(); + + char key = char.ToLower(person.LastName.Value[0]); + + if (key < 'a' || key > 'z') + { + if (key < 'а' || key > 'я') + { + key = '#'; + } + } + + return key.ToString(); + } + + public static int CompareByLastName(object obj1, object obj2) + { + var p1 = (TLUserBase)obj1; + var p2 = (TLUserBase)obj2; + + if (p1.LastName == null && p2.LastName != null) + { + return -1; + } + + if (p1.LastName != null && p2.LastName == null) + { + return 1; + } + + if (p1.LastName == null && p2.LastName == null) + { + return 0; + } + + + int result = String.Compare(p1.LastName.Value, p2.LastName.Value, StringComparison.Ordinal); + //if (result == 0) + //{ + // result = String.Compare(p1.FirstName.Value, p2.FirstName.Value, StringComparison.Ordinal); + //} + + return result; + } + } + + public class TLUser66 : TLUser45 + { + public new const uint Signature = TLConstructors.TLUser66; + + private TLString _langCode; + + public TLString LangCode + { + get { return _langCode; } + set { SetField(out _langCode, value, ref _flags, (int)UserFlags.LangCode); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(Flags, (int)UserFlags.AccessHash, new TLLong(0), bytes, ref position); + _firstName = GetObject(Flags, (int)UserFlags.FirstName, TLString.Empty, bytes, ref position); + _lastName = GetObject(Flags, (int)UserFlags.LastName, TLString.Empty, bytes, ref position); + UserName = GetObject(Flags, (int)UserFlags.UserName, TLString.Empty, bytes, ref position); + Phone = GetObject(Flags, (int)UserFlags.Phone, TLString.Empty, bytes, ref position); + _photo = GetObject(Flags, (int)UserFlags.Photo, new TLUserProfilePhotoEmpty(), bytes, ref position); + _status = GetObject(Flags, (int)UserFlags.Status, new TLUserStatusEmpty(), bytes, ref position); + BotInfoVersion = GetObject(Flags, (int)UserFlags.Bot, new TLInt(0), bytes, ref position); + RestrictionReason = GetObject(Flags, (int)UserFlags.Restricted, TLString.Empty, bytes, ref position); + _botInlinePlaceholder = GetObject(Flags, (int)UserFlags.BotInlinePlaceholder, TLString.Empty, bytes, ref position); + _langCode = GetObject(Flags, (int)UserFlags.LangCode, TLString.Empty, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + ToBytes(AccessHash, Flags, (int)UserFlags.AccessHash), + ToBytes(FirstName, Flags, (int)UserFlags.FirstName), + ToBytes(LastName, Flags, (int)UserFlags.LastName), + ToBytes(UserName, Flags, (int)UserFlags.UserName), + ToBytes(Phone, Flags, (int)UserFlags.Phone), + ToBytes(Photo, Flags, (int)UserFlags.Photo), + ToBytes(Status, Flags, (int)UserFlags.Status), + ToBytes(BotInfoVersion, Flags, (int)UserFlags.Bot), + ToBytes(RestrictionReason, Flags, (int)UserFlags.Restricted), + ToBytes(BotInlinePlaceholder, Flags, (int)UserFlags.BotInlinePlaceholder), + ToBytes(LangCode, Flags, (int)UserFlags.LangCode)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(Flags, (int)UserFlags.AccessHash, new TLLong(0), input); + _firstName = GetObject(Flags, (int)UserFlags.FirstName, TLString.Empty, input); + _lastName = GetObject(Flags, (int)UserFlags.LastName, TLString.Empty, input); + UserName = GetObject(Flags, (int)UserFlags.UserName, TLString.Empty, input); + Phone = GetObject(Flags, (int)UserFlags.Phone, TLString.Empty, input); + _photo = GetObject(Flags, (int)UserFlags.Photo, new TLUserProfilePhotoEmpty(), input); + _status = GetObject(Flags, (int)UserFlags.Status, new TLUserStatusEmpty(), input); + BotInfoVersion = GetObject(Flags, (int)UserFlags.Bot, new TLInt(0), input); + RestrictionReason = GetObject(Flags, (int)UserFlags.Restricted, TLString.Empty, input); + BotInlinePlaceholder = GetObject(Flags, (int)UserFlags.BotInlinePlaceholder, TLString.Empty, input); + LangCode = GetObject(Flags, (int)UserFlags.LangCode, TLString.Empty, input); + + CustomFlags = GetNullableObject(input); + + NotifySettings = GetNullableObject(input); + ExtendedInfo = GetNullableObject(input); + BotInfo = GetNullableObject(input); + + // as bit + _blocked = GetObject(CustomFlags, (int)UserCustomFlags.Blocked, null, input); + _about = GetObject(CustomFlags, (int)UserCustomFlags.About, null, input); + _notifyGeoAccessDate = GetObject(CustomFlags, (int)UserCustomFlags.NotifyGeoAccessDate, null, input); + + _readInboxMaxId = GetObject(CustomFlags, (int)UserCustomFlags.ReadInboxMaxId, null, input); + _readOutboxMaxId = GetObject(CustomFlags, (int)UserCustomFlags.ReadOutboxMaxId, null, input); + _commonChatsCount = GetObject(CustomFlags, (int)UserCustomFlags.CommonChatsCount, null, input); + + return this; + } + + public override void Update(TLUserBase userBase) + { + var user = userBase as TLUser66; + if (user != null) + { + if (user.Min) + { + _firstName = user.FirstName ?? TLString.Empty; + _lastName = user.LastName ?? TLString.Empty; + _photo = user.Photo ?? new TLUserProfilePhotoEmpty(); + + return; + } + + // set bits + Flags = user.Flags; + //IsSelf = user.IsSelf; + //IsContact = user.IsContact; + //IsMutualContact = user.IsMutualContact; + //IsDeleted = user.IsDeleted; + //IsBot = user.IsBot; + //IsBotAllHistory = user.IsBotAllHistory; + //IsBotGroupsBlocked = user.IsBotGroupsBlocked; + //IsVerified = user.IsVerified; + //IsRestricted = user.IsRestricted; + //IsBotInlineGeo = user.IsBotInlineGeo; + // end set bits + + Id = user.Id; + AccessHash = user.AccessHash ?? new TLLong(0); + _firstName = user.FirstName ?? TLString.Empty; + _lastName = user.LastName ?? TLString.Empty; + UserName = user.UserName ?? TLString.Empty; + Phone = user.Phone ?? TLString.Empty; + if (Photo != null + && user.Photo != null + && Photo.GetType() == user.Photo.GetType()) + { + Photo.Update(user.Photo); + } + else + { + _photo = user.Photo ?? new TLUserProfilePhotoEmpty(); + } + _status = user.Status ?? new TLUserStatusEmpty(); + BotInfoVersion = user.BotInfoVersion ?? new TLInt(0); + RestrictionReason = user.RestrictionReason ?? TLString.Empty; + _botInlinePlaceholder = user.BotInlinePlaceholder ?? TLString.Empty; + _langCode = user.LangCode ?? TLString.Empty; + + if (user.ReadInboxMaxId != null + && (ReadInboxMaxId == null || ReadInboxMaxId.Value < user.ReadInboxMaxId.Value)) + { + ReadInboxMaxId = user.ReadInboxMaxId; + } + + if (user.ReadOutboxMaxId != null + && (ReadOutboxMaxId == null || ReadOutboxMaxId.Value < user.ReadOutboxMaxId.Value)) + { + ReadOutboxMaxId = user.ReadOutboxMaxId; + } + + if (user.About != null) + { + About = user.About; + } + + if (user.NotifyGeoAccessDate != null) + { + NotifyGeoAccessDate = user.NotifyGeoAccessDate; + } + + if (user.BotInlineGeoAccess) + { + BotInlineGeoAccess = true; + } + + if (user.BotInfo != null) + { + BotInfo = user.BotInfo; + } + + if (user.Contact != null) + { + Contact = user.Contact; + } + + if (user.Link != null) + { + Link = user.Link; + } + + if (user.ProfilePhoto != null) + { + ProfilePhoto = user.ProfilePhoto; + } + + if (user.NotifySettings != null) + { + NotifySettings = user.NotifySettings; + } + + if (user.ExtendedInfo != null) + { + ExtendedInfo = user.ExtendedInfo; + } + + if (user.Blocked != null) + { + Blocked = user.Blocked; + } + + if (user.CommonChatsCount != null) + { + CommonChatsCount = user.CommonChatsCount; + } + } + + //base.Update(userBase); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + ToStream(output, AccessHash, Flags, (int)UserFlags.AccessHash); + ToStream(output, FirstName, Flags, (int)UserFlags.FirstName); + ToStream(output, LastName, Flags, (int)UserFlags.LastName); + ToStream(output, UserName, Flags, (int)UserFlags.UserName); + ToStream(output, Phone, Flags, (int)UserFlags.Phone); + ToStream(output, Photo, Flags, (int)UserFlags.Photo); + ToStream(output, Status, Flags, (int)UserFlags.Status); + ToStream(output, BotInfoVersion, Flags, (int)UserFlags.Bot); + ToStream(output, RestrictionReason, Flags, (int)UserFlags.Restricted); + ToStream(output, BotInlinePlaceholder, Flags, (int)UserFlags.BotInlinePlaceholder); + ToStream(output, LangCode, Flags, (int)UserFlags.LangCode); + + CustomFlags.NullableToStream(output); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + BotInfo.NullableToStream(output); + + // as bit + ToStream(output, Blocked, CustomFlags, (int)UserCustomFlags.Blocked); + ToStream(output, About, CustomFlags, (int)UserCustomFlags.About); + ToStream(output, NotifyGeoAccessDate, CustomFlags, (int)UserCustomFlags.NotifyGeoAccessDate); + ToStream(output, ReadInboxMaxId, CustomFlags, (int)UserCustomFlags.ReadInboxMaxId); + ToStream(output, ReadOutboxMaxId, CustomFlags, (int)UserCustomFlags.ReadOutboxMaxId); + ToStream(output, CommonChatsCount, CustomFlags, (int)UserCustomFlags.CommonChatsCount); + } + } + + public class TLUser45 : TLUser44, IReadMaxId + { + public new const uint Signature = TLConstructors.TLUser45; + + protected TLString _botInlinePlaceholder; + + public TLString BotInlinePlaceholder + { + get { return _botInlinePlaceholder; } + set { SetField(out _botInlinePlaceholder, value, ref _flags, (int)UserFlags.BotInlinePlaceholder); } + } + + protected TLString _about; + + public TLString About + { + get { return _about; } + set { SetField(out _about, value, ref _customFlags, (int)UserCustomFlags.About); } + } + + public bool BotInlineGeoAccess + { + get { return IsSet(CustomFlags, (int)UserCustomFlags.BotInlineGeoAccess); } + set { SetUnset(ref _customFlags, value, (int)UserCustomFlags.BotInlineGeoAccess); } + } + + public bool BotOpenUrlPermission + { + get { return IsSet(CustomFlags, (int)UserCustomFlags.BotOpenUrlPermission); } + set { SetUnset(ref _customFlags, value, (int)UserCustomFlags.BotOpenUrlPermission); } + } + + public bool BotPassTelegramNameToWebPagesPermission + { + get { return IsSet(CustomFlags, (int)UserCustomFlags.BotPassTelegramNameToWebPagesPermission); } + set { SetUnset(ref _customFlags, value, (int)UserCustomFlags.BotPassTelegramNameToWebPagesPermission); } + } + + public bool BotPaymentsPermission + { + get { return IsSet(CustomFlags, (int)UserCustomFlags.BotPaymentsPermission); } + set { SetUnset(ref _customFlags, value, (int)UserCustomFlags.BotPaymentsPermission); } + } + + protected TLInt _notifyGeoAccessDate; + + public TLInt NotifyGeoAccessDate + { + get { return _notifyGeoAccessDate; } + set { SetField(out _notifyGeoAccessDate, value, ref _customFlags, (int)UserCustomFlags.NotifyGeoAccessDate); } + } + + protected TLInt _readInboxMaxId; + + public TLInt ReadInboxMaxId + { + get { return _readInboxMaxId; } + set { SetField(out _readInboxMaxId, value, ref _customFlags, (int)UserCustomFlags.ReadInboxMaxId); } + } + + protected TLInt _readOutboxMaxId; + + public TLInt ReadOutboxMaxId + { + get { return _readOutboxMaxId; } + set { SetField(out _readOutboxMaxId, value, ref _customFlags, (int)UserCustomFlags.ReadOutboxMaxId); } + } + + protected TLInt _commonChatsCount; + + public TLInt CommonChatsCount + { + get { return _commonChatsCount; } + set { SetField(out _commonChatsCount, value, ref _customFlags, (int)UserCustomFlags.CommonChatsCount); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(Flags, (int)UserFlags.AccessHash, new TLLong(0), bytes, ref position); + _firstName = GetObject(Flags, (int)UserFlags.FirstName, TLString.Empty, bytes, ref position); + _lastName = GetObject(Flags, (int)UserFlags.LastName, TLString.Empty, bytes, ref position); + UserName = GetObject(Flags, (int)UserFlags.UserName, TLString.Empty, bytes, ref position); + Phone = GetObject(Flags, (int)UserFlags.Phone, TLString.Empty, bytes, ref position); + _photo = GetObject(Flags, (int)UserFlags.Photo, new TLUserProfilePhotoEmpty(), bytes, ref position); + _status = GetObject(Flags, (int)UserFlags.Status, new TLUserStatusEmpty(), bytes, ref position); + BotInfoVersion = GetObject(Flags, (int)UserFlags.Bot, new TLInt(0), bytes, ref position); + RestrictionReason = GetObject(Flags, (int)UserFlags.Restricted, TLString.Empty, bytes, ref position); + _botInlinePlaceholder = GetObject(Flags, (int)UserFlags.BotInlinePlaceholder, TLString.Empty, bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + ToBytes(AccessHash, Flags, (int)UserFlags.AccessHash), + ToBytes(FirstName, Flags, (int)UserFlags.FirstName), + ToBytes(LastName, Flags, (int)UserFlags.LastName), + ToBytes(UserName, Flags, (int)UserFlags.UserName), + ToBytes(Phone, Flags, (int)UserFlags.Phone), + ToBytes(Photo, Flags, (int)UserFlags.Photo), + ToBytes(Status, Flags, (int)UserFlags.Status), + ToBytes(BotInfoVersion, Flags, (int)UserFlags.Bot), + ToBytes(RestrictionReason, Flags, (int)UserFlags.Restricted), + ToBytes(BotInlinePlaceholder, Flags, (int)UserFlags.BotInlinePlaceholder)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(Flags, (int)UserFlags.AccessHash, new TLLong(0), input); + _firstName = GetObject(Flags, (int)UserFlags.FirstName, TLString.Empty, input); + _lastName = GetObject(Flags, (int)UserFlags.LastName, TLString.Empty, input); + UserName = GetObject(Flags, (int)UserFlags.UserName, TLString.Empty, input); + Phone = GetObject(Flags, (int)UserFlags.Phone, TLString.Empty, input); + _photo = GetObject(Flags, (int)UserFlags.Photo, new TLUserProfilePhotoEmpty(), input); + _status = GetObject(Flags, (int)UserFlags.Status, new TLUserStatusEmpty(), input); + BotInfoVersion = GetObject(Flags, (int)UserFlags.Bot, new TLInt(0), input); + RestrictionReason = GetObject(Flags, (int)UserFlags.Restricted, TLString.Empty, input); + BotInlinePlaceholder = GetObject(Flags, (int)UserFlags.BotInlinePlaceholder, TLString.Empty, input); + + CustomFlags = GetNullableObject(input); + + NotifySettings = GetNullableObject(input); + ExtendedInfo = GetNullableObject(input); + BotInfo = GetNullableObject(input); + + // as bit + _blocked = GetObject(CustomFlags, (int)UserCustomFlags.Blocked, null, input); + _about = GetObject(CustomFlags, (int)UserCustomFlags.About, null, input); + _notifyGeoAccessDate = GetObject(CustomFlags, (int)UserCustomFlags.NotifyGeoAccessDate, null, input); + + _readInboxMaxId = GetObject(CustomFlags, (int)UserCustomFlags.ReadInboxMaxId, null, input); + _readOutboxMaxId = GetObject(CustomFlags, (int)UserCustomFlags.ReadOutboxMaxId, null, input); + _commonChatsCount = GetObject(CustomFlags, (int)UserCustomFlags.CommonChatsCount, null, input); + + return this; + } + + public override void Update(TLUserBase userBase) + { + var user = userBase as TLUser45; + if (user != null) + { + if (user.Min) + { + _firstName = user.FirstName ?? TLString.Empty; + _lastName = user.LastName ?? TLString.Empty; + _photo = user.Photo ?? new TLUserProfilePhotoEmpty(); + + return; + } + + // set bits + Flags = user.Flags; + //IsSelf = user.IsSelf; + //IsContact = user.IsContact; + //IsMutualContact = user.IsMutualContact; + //IsDeleted = user.IsDeleted; + //IsBot = user.IsBot; + //IsBotAllHistory = user.IsBotAllHistory; + //IsBotGroupsBlocked = user.IsBotGroupsBlocked; + //IsVerified = user.IsVerified; + //IsRestricted = user.IsRestricted; + //IsBotInlineGeo = user.IsBotInlineGeo; + // end set bits + + Id = user.Id; + AccessHash = user.AccessHash ?? new TLLong(0); + _firstName = user.FirstName ?? TLString.Empty; + _lastName = user.LastName ?? TLString.Empty; + UserName = user.UserName ?? TLString.Empty; + Phone = user.Phone ?? TLString.Empty; + if (Photo != null + && user.Photo != null + && Photo.GetType() == user.Photo.GetType()) + { + Photo.Update(user.Photo); + } + else + { + _photo = user.Photo ?? new TLUserProfilePhotoEmpty(); + } + _status = user.Status ?? new TLUserStatusEmpty(); + BotInfoVersion = user.BotInfoVersion ?? new TLInt(0); + RestrictionReason = user.RestrictionReason ?? TLString.Empty; + _botInlinePlaceholder = user.BotInlinePlaceholder ?? TLString.Empty; + + + if (user.ReadInboxMaxId != null + && (ReadInboxMaxId == null || ReadInboxMaxId.Value < user.ReadInboxMaxId.Value)) + { + ReadInboxMaxId = user.ReadInboxMaxId; + } + + if (user.ReadOutboxMaxId != null + && (ReadOutboxMaxId == null || ReadOutboxMaxId.Value < user.ReadOutboxMaxId.Value)) + { + ReadOutboxMaxId = user.ReadOutboxMaxId; + } + + if (user.About != null) + { + About = user.About; + } + + if (user.NotifyGeoAccessDate != null) + { + NotifyGeoAccessDate = user.NotifyGeoAccessDate; + } + + if (user.BotInlineGeoAccess) + { + BotInlineGeoAccess = true; + } + + if (user.BotInfo != null) + { + BotInfo = user.BotInfo; + } + + if (user.Contact != null) + { + Contact = user.Contact; + } + + if (user.Link != null) + { + Link = user.Link; + } + + if (user.ProfilePhoto != null) + { + ProfilePhoto = user.ProfilePhoto; + } + + if (user.NotifySettings != null) + { + NotifySettings = user.NotifySettings; + } + + if (user.ExtendedInfo != null) + { + ExtendedInfo = user.ExtendedInfo; + } + + if (user.Blocked != null) + { + Blocked = user.Blocked; + } + + if (user.CommonChatsCount != null) + { + CommonChatsCount = user.CommonChatsCount; + } + } + + //base.Update(userBase); + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + ToStream(output, AccessHash, Flags, (int)UserFlags.AccessHash); + ToStream(output, FirstName, Flags, (int)UserFlags.FirstName); + ToStream(output, LastName, Flags, (int)UserFlags.LastName); + ToStream(output, UserName, Flags, (int)UserFlags.UserName); + ToStream(output, Phone, Flags, (int)UserFlags.Phone); + ToStream(output, Photo, Flags, (int)UserFlags.Photo); + ToStream(output, Status, Flags, (int)UserFlags.Status); + ToStream(output, BotInfoVersion, Flags, (int)UserFlags.Bot); + ToStream(output, RestrictionReason, Flags, (int)UserFlags.Restricted); + ToStream(output, BotInlinePlaceholder, Flags, (int)UserFlags.BotInlinePlaceholder); + + CustomFlags.NullableToStream(output); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + BotInfo.NullableToStream(output); + + // as bit + ToStream(output, Blocked, CustomFlags, (int)UserCustomFlags.Blocked); + ToStream(output, About, CustomFlags, (int)UserCustomFlags.About); + ToStream(output, NotifyGeoAccessDate, CustomFlags, (int)UserCustomFlags.NotifyGeoAccessDate); + ToStream(output, ReadInboxMaxId, CustomFlags, (int)UserCustomFlags.ReadInboxMaxId); + ToStream(output, ReadOutboxMaxId, CustomFlags, (int)UserCustomFlags.ReadOutboxMaxId); + ToStream(output, CommonChatsCount, CustomFlags, (int)UserCustomFlags.CommonChatsCount); + } + } + + public class TLUser44 : TLUser + { + public new const uint Signature = TLConstructors.TLUser44; + + public TLString RestrictionReason { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(Flags, (int)UserFlags.AccessHash, new TLLong(0), bytes, ref position); + _firstName = GetObject(Flags, (int)UserFlags.FirstName, TLString.Empty, bytes, ref position); + _lastName = GetObject(Flags, (int)UserFlags.LastName, TLString.Empty, bytes, ref position); + UserName = GetObject(Flags, (int)UserFlags.UserName, TLString.Empty, bytes, ref position); + Phone = GetObject(Flags, (int)UserFlags.Phone, TLString.Empty, bytes, ref position); + _photo = GetObject(Flags, (int)UserFlags.Photo, new TLUserProfilePhotoEmpty(), bytes, ref position); + _status = GetObject(Flags, (int)UserFlags.Status, new TLUserStatusEmpty(), bytes, ref position); + BotInfoVersion = GetObject(Flags, (int)UserFlags.Bot, new TLInt(0), bytes, ref position); + RestrictionReason = GetObject(Flags, (int)UserFlags.Restricted, TLString.Empty, bytes, ref position); + + if (IsSet(Flags, (int)UserFlags.Bot) + || IsSet(Flags, (int)UserFlags.BotAllHistory)) + { + return this; + } + + if (IsSet(Flags, (int)UserFlags.AccessHash)) + { + if (IsSet(Flags, (int)UserFlags.Contact) + || IsSet(Flags, (int)UserFlags.ContactMutual)) + { + var userContact = new TLUserContact18 + { + Id = Id, + AccessHash = AccessHash, + _firstName = _firstName, + _lastName = _lastName, + UserName = UserName, + Phone = Phone, + _photo = _photo, + _status = _status, + }; + + return userContact; + } + + if (IsSet(Flags, (int)UserFlags.Phone)) + { + var userRequest = new TLUserRequest18 + { + Id = Id, + AccessHash = AccessHash, + _firstName = _firstName, + _lastName = _lastName, + UserName = UserName, + Phone = Phone, + _photo = _photo, + _status = _status, + }; + + return userRequest; + } + + var userForeign = new TLUserForeign18 + { + Id = Id, + AccessHash = AccessHash, + _firstName = _firstName, + _lastName = _lastName, + UserName = UserName, + _photo = _photo, + _status = _status, + }; + + return userForeign; + } + + if (IsSet(Flags, (int)UserFlags.Deleted)) + { + var userDeleted = new TLUserDeleted18 + { + Id = Id, + _firstName = _firstName, + _lastName = _lastName, + UserName = UserName + }; + + return userDeleted; + } + + if (IsSet(Flags, (int)UserFlags.Self)) + { + var userSelf = new TLUserSelf24 + { + Id = Id, + _firstName = _firstName, + _lastName = _lastName, + UserName = UserName, + Phone = Phone, + _photo = _photo, + _status = _status, + }; + + return userSelf; + } + + Helpers.Execute.ShowDebugMessage("TLUser unknown " + FullName); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + ToBytes(AccessHash, Flags, (int)UserFlags.AccessHash), + ToBytes(FirstName, Flags, (int)UserFlags.FirstName), + ToBytes(LastName, Flags, (int)UserFlags.LastName), + ToBytes(UserName, Flags, (int)UserFlags.UserName), + ToBytes(Phone, Flags, (int)UserFlags.Phone), + ToBytes(Photo, Flags, (int)UserFlags.Photo), + ToBytes(Status, Flags, (int)UserFlags.Status), + ToBytes(BotInfoVersion, Flags, (int)UserFlags.Bot), + ToBytes(RestrictionReason, Flags, (int)UserFlags.Restricted)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(Flags, (int)UserFlags.AccessHash, new TLLong(0), input); + _firstName = GetObject(Flags, (int)UserFlags.FirstName, TLString.Empty, input); + _lastName = GetObject(Flags, (int)UserFlags.LastName, TLString.Empty, input); + UserName = GetObject(Flags, (int)UserFlags.UserName, TLString.Empty, input); + Phone = GetObject(Flags, (int)UserFlags.Phone, TLString.Empty, input); + _photo = GetObject(Flags, (int)UserFlags.Photo, new TLUserProfilePhotoEmpty(), input); + _status = GetObject(Flags, (int)UserFlags.Status, new TLUserStatusEmpty(), input); + BotInfoVersion = GetObject(Flags, (int)UserFlags.Bot, new TLInt(0), input); + RestrictionReason = GetObject(Flags, (int)UserFlags.Restricted, TLString.Empty, input); + + CustomFlags = GetNullableObject(input); + + NotifySettings = GetNullableObject(input); + ExtendedInfo = GetNullableObject(input); + BotInfo = GetNullableObject(input); + + // as bit + _blocked = GetObject(CustomFlags, (int)UserCustomFlags.Blocked, null, input); + + return this; + } + + public override void Update(TLUserBase userBase) + { + base.Update(userBase); + + var user = userBase as TLUser44; + if (user != null) + { + if (user.RestrictionReason != null) + { + RestrictionReason = user.RestrictionReason; + } + } + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + ToStream(output, AccessHash, Flags, (int)UserFlags.AccessHash); + ToStream(output, FirstName, Flags, (int)UserFlags.FirstName); + ToStream(output, LastName, Flags, (int)UserFlags.LastName); + ToStream(output, UserName, Flags, (int)UserFlags.UserName); + ToStream(output, Phone, Flags, (int)UserFlags.Phone); + ToStream(output, Photo, Flags, (int)UserFlags.Photo); + ToStream(output, Status, Flags, (int)UserFlags.Status); + ToStream(output, BotInfoVersion, Flags, (int)UserFlags.Bot); + ToStream(output, RestrictionReason, Flags, (int)UserFlags.Restricted); + + CustomFlags.NullableToStream(output); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + BotInfo.NullableToStream(output); + + // as bit + ToStream(output, Blocked, CustomFlags, (int)UserCustomFlags.Blocked); + } + } + + public class TLUser : TLUserBase, IUserName + { + public const uint Signature = TLConstructors.TLUser; + + protected TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override bool IsForeign + { + get + { + return + IsSet(Flags, (int)UserFlags.AccessHash) + && !IsSet(Flags, (int)UserFlags.Phone) + && !IsSet(Flags, (int)UserFlags.Self) + && !IsSet(Flags, (int)UserFlags.Contact) + && !IsSet(Flags, (int)UserFlags.ContactMutual); + } + } + + public override bool IsRequest + { + get + { + return + IsSet(Flags, (int)UserFlags.AccessHash) + && IsSet(Flags, (int)UserFlags.Phone) + && !IsSet(Flags, (int)UserFlags.Self) + && !IsSet(Flags, (int)UserFlags.Contact) + && !IsSet(Flags, (int)UserFlags.ContactMutual); + } + } + + public override bool IsSelf + { + get { return IsSet(Flags, (int)UserFlags.Self); } + set { SetUnset(ref _flags, value, (int)UserFlags.Self); } + } + + public override bool IsContact + { + get { return IsSet(Flags, (int)UserFlags.Contact); } + set { SetUnset(ref _flags, value, (int)UserFlags.Contact); } + } + + public override bool IsContactMutual + { + get { return IsSet(Flags, (int)UserFlags.ContactMutual); } + set { SetUnset(ref _flags, value, (int)UserFlags.ContactMutual); } + } + + public override bool IsDeleted + { + get { return IsSet(Flags, (int)UserFlags.Deleted); } + set { SetUnset(ref _flags, value, (int)UserFlags.Deleted); } + } + + public bool IsBot + { + get { return IsSet(Flags, (int)UserFlags.Bot); } + set { SetUnset(ref _flags, value, (int)UserFlags.Bot); } + } + + public bool IsBotAllHistory + { + get { return IsSet(Flags, (int)UserFlags.BotAllHistory); } + set { SetUnset(ref _flags, value, (int)UserFlags.BotAllHistory); } + } + + public bool IsBotGroupsBlocked + { + get { return IsSet(Flags, (int)UserFlags.BotGroupsBlocked); } + set { SetUnset(ref _flags, value, (int)UserFlags.BotGroupsBlocked); } + } + + public override bool IsVerified + { + get { return IsSet(Flags, (int)UserFlags.Verified); } + set { SetUnset(ref _flags, value, (int)UserFlags.Verified); } + } + + public bool IsRestricted + { + get { return IsSet(Flags, (int)ChannelFlags.Restricted); } + set { SetUnset(ref _flags, value, (int)UserFlags.Restricted); } + } + + public bool Min { get { return IsSet(Flags, (int)UserFlags.Min); } } + + public bool IsBotInlineGeo + { + get { return IsSet(Flags, (int)UserFlags.BotInlineGeo); } + set { SetUnset(ref _flags, value, (int)UserFlags.BotInlineGeo); } + } + + public bool IsInlineBot + { + get { return IsSet(Flags, (int)UserFlags.BotInlinePlaceholder); } + } + + public TLLong AccessHash { get; set; } + + public TLString UserName { get; set; } + + public TLInt BotInfoVersion { get; set; } + + protected TLLong _customFlags; + + public TLLong CustomFlags + { + get { return _customFlags; } + set { _customFlags = value; } + } + + protected TLBool _blocked; + + public override TLBool Blocked + { + get { return _blocked; } + set + { + if (value != null) + { + Set(ref _customFlags, (int)UserCustomFlags.Blocked); + _blocked = value; + } + } + } + + public override string ToString() + { + return base.ToString() + string.Format(" flags={0} custom_flags={1}", UserFlagsString(Flags), UserCustomFlagsString(CustomFlags)); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + AccessHash = GetObject(Flags, (int)UserFlags.AccessHash, new TLLong(0), bytes, ref position); + _firstName = GetObject(Flags, (int)UserFlags.FirstName, TLString.Empty, bytes, ref position); + _lastName = GetObject(Flags, (int)UserFlags.LastName, TLString.Empty, bytes, ref position); + UserName = GetObject(Flags, (int)UserFlags.UserName, TLString.Empty, bytes, ref position); + Phone = GetObject(Flags, (int)UserFlags.Phone, TLString.Empty, bytes, ref position); + _photo = GetObject(Flags, (int)UserFlags.Photo, new TLUserProfilePhotoEmpty(), bytes, ref position); + _status = GetObject(Flags, (int)UserFlags.Status, new TLUserStatusEmpty(), bytes, ref position); + BotInfoVersion = GetObject(Flags, (int)UserFlags.Bot, new TLInt(0), bytes, ref position); + + if (IsSet(Flags, (int)UserFlags.Bot) + || IsSet(Flags, (int)UserFlags.BotAllHistory)) + { + return this; + } + + if (IsSet(Flags, (int)UserFlags.AccessHash)) + { + if (IsSet(Flags, (int)UserFlags.Contact) + || IsSet(Flags, (int)UserFlags.ContactMutual)) + { + var userContact = new TLUserContact18 + { + Id = Id, + AccessHash = AccessHash, + _firstName = _firstName, + _lastName = _lastName, + UserName = UserName, + Phone = Phone, + _photo = _photo, + _status = _status, + }; + + return userContact; + } + + if (IsSet(Flags, (int)UserFlags.Phone)) + { + var userRequest = new TLUserRequest18 + { + Id = Id, + AccessHash = AccessHash, + _firstName = _firstName, + _lastName = _lastName, + UserName = UserName, + Phone = Phone, + _photo = _photo, + _status = _status, + }; + + return userRequest; + } + + var userForeign = new TLUserForeign18 + { + Id = Id, + AccessHash = AccessHash, + _firstName = _firstName, + _lastName = _lastName, + UserName = UserName, + _photo = _photo, + _status = _status, + }; + + return userForeign; + } + + if (IsSet(Flags, (int)UserFlags.Deleted)) + { + var userDeleted = new TLUserDeleted18 + { + Id = Id, + _firstName = _firstName, + _lastName = _lastName, + UserName = UserName + }; + + return userDeleted; + } + + if (IsSet(Flags, (int)UserFlags.Self)) + { + var userSelf = new TLUserSelf24 + { + Id = Id, + _firstName = _firstName, + _lastName = _lastName, + UserName = UserName, + Phone = Phone, + _photo = _photo, + _status = _status, + }; + + return userSelf; + } + + Helpers.Execute.ShowDebugMessage("TLUser unknown " + FullName); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + ToBytes(AccessHash, Flags, (int)UserFlags.AccessHash), + ToBytes(FirstName, Flags, (int)UserFlags.FirstName), + ToBytes(LastName, Flags, (int)UserFlags.LastName), + ToBytes(UserName, Flags, (int)UserFlags.UserName), + ToBytes(Phone, Flags, (int)UserFlags.Phone), + ToBytes(Photo, Flags, (int)UserFlags.Photo), + ToBytes(Status, Flags, (int)UserFlags.Status), + ToBytes(BotInfoVersion, Flags, (int)UserFlags.Bot)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + AccessHash = GetObject(Flags, (int)UserFlags.AccessHash, new TLLong(0), input); + _firstName = GetObject(Flags, (int)UserFlags.FirstName, TLString.Empty, input); + _lastName = GetObject(Flags, (int)UserFlags.LastName, TLString.Empty, input); + UserName = GetObject(Flags, (int)UserFlags.UserName, TLString.Empty, input); + Phone = GetObject(Flags, (int)UserFlags.Phone, TLString.Empty, input); + _photo = GetObject(Flags, (int)UserFlags.Photo, new TLUserProfilePhotoEmpty(), input); + _status = GetObject(Flags, (int)UserFlags.Status, new TLUserStatusEmpty(), input); + BotInfoVersion = GetObject(Flags, (int)UserFlags.Bot, new TLInt(0), input); + + CustomFlags = GetNullableObject(input); + + NotifySettings = GetNullableObject(input); + ExtendedInfo = GetNullableObject(input); + BotInfo = GetNullableObject(input); + + // as bit + _blocked = GetObject(CustomFlags, (int)UserCustomFlags.Blocked, null, input); + + return this; + } + + public override void Update(TLUserBase userBase) + { + base.Update(userBase); + + var user = userBase as TLUser; + if (user != null) + { + Flags = user.Flags; + Id = user.Id; + AccessHash = user.AccessHash; + UserName = user.UserName; + BotInfoVersion = user.BotInfoVersion; + + //if (user.CustomFlags != null) // will be erased user.NotifyGeoAccessDate user.BotInlineGeoAccess after user.getFullUser + //{ + // CustomFlags = user.CustomFlags; + //} + + if (user.BotInfo != null) + { + BotInfo = user.BotInfo; + } + } + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + ToStream(output, AccessHash, Flags, (int)UserFlags.AccessHash); + ToStream(output, FirstName, Flags, (int)UserFlags.FirstName); + ToStream(output, LastName, Flags, (int)UserFlags.LastName); + ToStream(output, UserName, Flags, (int)UserFlags.UserName); + ToStream(output, Phone, Flags, (int)UserFlags.Phone); + ToStream(output, Photo, Flags, (int)UserFlags.Photo); + ToStream(output, Status, Flags, (int)UserFlags.Status); + ToStream(output, BotInfoVersion, Flags, (int)UserFlags.Bot); + + CustomFlags.NullableToStream(output); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + BotInfo.NullableToStream(output); + + // as bit + ToStream(output, Blocked, CustomFlags, (int)UserCustomFlags.Blocked); + } + + public override TLInputUserBase ToInputUser() + { + if (IsSet(Flags, (int)UserFlags.AccessHash)) + { + if (IsSet(Flags, (int)UserFlags.Contact) + || IsSet(Flags, (int)UserFlags.ContactMutual)) + { + var userContact = new TLInputUser + { + UserId = Id, + AccessHash = new TLLong(0) + }; + + return userContact; + } + + var userForeign = new TLInputUser + { + UserId = Id, + AccessHash = AccessHash + }; + + return userForeign; + } + + if (IsSet(Flags, (int)UserFlags.Deleted)) + { + var userDeleted = new TLInputUser { UserId = Id, AccessHash = new TLLong(0) }; + + return userDeleted; + } + + if (IsSet(Flags, (int)UserFlags.Self)) + { + var userSelf = new TLInputUserSelf(); + + return userSelf; + } + + Helpers.Execute.ShowDebugMessage("TLUser.ToInputUser unknown " + FullName); + + return null; + } + + public override TLInputPeerBase ToInputPeer() + { + if (IsSet(Flags, (int)UserFlags.AccessHash)) + { + if (IsSet(Flags, (int)UserFlags.Contact) + || IsSet(Flags, (int)UserFlags.ContactMutual)) + { + var userContact = new TLInputPeerUser + { + UserId = Id, + AccessHash = new TLLong(0) + }; + + return userContact; + } + + var userForeign = new TLInputPeerUser + { + UserId = Id, + AccessHash = AccessHash + }; + + return userForeign; + } + + if (IsSet(Flags, (int)UserFlags.Deleted)) + { + var userDeleted = new TLInputPeerUser { UserId = Id, AccessHash = new TLLong(0) }; + + return userDeleted; + } + + if (IsSet(Flags, (int)UserFlags.Self)) + { + var userSelf = new TLInputPeerSelf(); + + return userSelf; + } + + Helpers.Execute.ShowDebugMessage("TLUser.ToInputPeer unknown " + FullName); + + return null; + } + + //public string AccessToken { get; set; } + } + + public class TLUserEmpty : TLUserBase + { + public const uint Signature = TLConstructors.TLUserEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + } + + public override void Update(TLUserBase user) + { + return; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + public override TLInputUserBase ToInputUser() + { + return new TLInputUser { UserId = Id, AccessHash = new TLLong(0) }; + } + + public override TLInputPeerBase ToInputPeer() + { + return new TLInputPeerUser { UserId = Id, AccessHash = new TLLong(0) }; + } + + public override bool IsDeleted + { + get { return false; } + set { } + } + + public override bool IsSelf + { + get { return false; } + set { } + } + + public override bool IsForeign + { + get { return false; } + } + + public override bool IsRequest + { + get { return false; } + } + + public override bool IsContact + { + get { return false; } + set { } + } + + public override bool IsContactMutual + { + get { return false; } + set { } + } + } + + public abstract class TLUserSelfBase : TLUserBase + { + public override bool HasPhone { get { return true; } } + + public override TLInputUserBase ToInputUser() + { + return new TLInputUserSelf(); + } + + public override TLInputPeerBase ToInputPeer() + { + return new TLInputPeerSelf(); + } + + public override bool IsDeleted + { + get { return false; } + set { } + } + + public override bool IsSelf + { + get { return true; } + set { } + } + + public override bool IsForeign + { + get { return false; } + } + + public override bool IsRequest + { + get { return false; } + } + + public override bool IsContact + { + get { return false; } + set { } + } + + public override bool IsContactMutual + { + get { return false; } + set { } + } + } + + public class TLUserSelf : TLUserSelfBase + { + public const uint Signature = TLConstructors.TLUserSelf; + + public TLBool Inactive { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + _firstName = GetObject(bytes, ref position); + _lastName = GetObject(bytes, ref position); + Phone = GetObject(bytes, ref position); + _photo = GetObject(bytes, ref position); + _status = GetObject(bytes, ref position); + Inactive = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + Phone.ToBytes(), + Photo.ToBytes(), + Status.ToBytes(), + Inactive.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _firstName = GetObject(input); + _lastName = GetObject(input); + Phone = GetObject(input); + _photo = GetObject(input); + _status = GetObject(input); + Inactive = GetObject(input); + + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + ExtendedInfo = GetObject(input) as TLUserExtendedInfo; + Contact = GetObject(input) as TLContact; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + output.Write(Phone.ToBytes()); + Photo.ToStream(output); + Status.ToStream(output); + output.Write(Inactive.ToBytes()); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + Contact.NullableToStream(output); + } + + public override void Update(TLUserBase user) + { + base.Update(user); + + Inactive = ((TLUserSelf)user).Inactive; + } + } + + public class TLUserSelf18 : TLUserSelfBase, IUserName + { + public const uint Signature = TLConstructors.TLUserSelf18; + + public TLString UserName { get; set; } + public TLBool Inactive { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + _firstName = GetObject(bytes, ref position); + _lastName = GetObject(bytes, ref position); + UserName = GetObject(bytes, ref position); + Phone = GetObject(bytes, ref position); + _photo = GetObject(bytes, ref position); + _status = GetObject(bytes, ref position); + Inactive = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + UserName.ToBytes(), + Phone.ToBytes(), + Photo.ToBytes(), + Status.ToBytes(), + Inactive.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _firstName = GetObject(input); + _lastName = GetObject(input); + UserName = GetObject(input); + Phone = GetObject(input); + _photo = GetObject(input); + _status = GetObject(input); + Inactive = GetObject(input); + + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + ExtendedInfo = GetObject(input) as TLUserExtendedInfo; + Contact = GetObject(input) as TLContact; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + output.Write(UserName.ToBytes()); + output.Write(Phone.ToBytes()); + Photo.ToStream(output); + Status.ToStream(output); + output.Write(Inactive.ToBytes()); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + Contact.NullableToStream(output); + } + + public override void Update(TLUserBase user) + { + base.Update(user); + + var user18 = user as TLUserSelf18; + if (user18 != null) + { + UserName = user18.UserName; + } + } + + public override string ToString() + { + var userNameString = UserName != null ? " @" + UserName : string.Empty; + return base.ToString() + userNameString; + } + } + + public class TLUserSelf24 : TLUserSelfBase, IUserName + { + public const uint Signature = TLConstructors.TLUserSelf24; + + public TLString UserName { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + _firstName = GetObject(bytes, ref position); + _lastName = GetObject(bytes, ref position); + UserName = GetObject(bytes, ref position); + Phone = GetObject(bytes, ref position); + _photo = GetObject(bytes, ref position); + _status = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + UserName.ToBytes(), + Phone.ToBytes(), + Photo.ToBytes(), + Status.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _firstName = GetObject(input); + _lastName = GetObject(input); + UserName = GetObject(input); + Phone = GetObject(input); + _photo = GetObject(input); + _status = GetObject(input); + + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + ExtendedInfo = GetObject(input) as TLUserExtendedInfo; + Contact = GetObject(input) as TLContact; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + output.Write(UserName.ToBytes()); + output.Write(Phone.ToBytes()); + Photo.ToStream(output); + Status.ToStream(output); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + Contact.NullableToStream(output); + } + + public override void Update(TLUserBase user) + { + base.Update(user); + + var userName = user as IUserName; + if (userName != null) + { + UserName = userName.UserName; + } + } + + public override string ToString() + { + var userNameString = UserName != null ? " @" + UserName : string.Empty; + return base.ToString() + userNameString; + } + } + + public class TLUserContact18 : TLUserContact, IUserName + { + public new const uint Signature = TLConstructors.TLUserContact18; + + public TLString UserName { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + _firstName = GetObject(bytes, ref position); + _lastName = GetObject(bytes, ref position); + UserName = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Phone = GetObject(bytes, ref position); + _photo = GetObject(bytes, ref position); + _status = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + UserName.ToBytes(), + AccessHash.ToBytes(), + Phone.ToBytes(), + Photo.ToBytes(), + Status.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _firstName = GetObject(input); + _lastName = GetObject(input); + UserName = GetObject(input); + AccessHash = GetObject(input); + Phone = GetObject(input); + _photo = GetObject(input); + _status = GetObject(input); + + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + ExtendedInfo = GetObject(input) as TLUserExtendedInfo; + Contact = GetObject(input) as TLContact; + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + output.Write(UserName.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Phone.ToBytes()); + Photo.ToStream(output); + Status.ToStream(output); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + Contact.NullableToStream(output); + } + + public override void Update(TLUserBase user) + { + base.Update(user); + + var user18 = user as TLUserContact18; + if (user18 != null) + { + UserName = user18.UserName; + } + } + + public override string ToString() + { + var userNameString = !TLString.IsNullOrEmpty(UserName) ? " @" + UserName : string.Empty; + return base.ToString() + userNameString; + } + } + + public class TLUserContact : TLUserBase + { + public const uint Signature = TLConstructors.TLUserContact; + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + _firstName = GetObject(bytes, ref position); + _lastName = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Phone = GetObject(bytes, ref position); + _photo = GetObject(bytes, ref position); + _status = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + AccessHash.ToBytes(), + Phone.ToBytes(), + Photo.ToBytes(), + Status.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _firstName = GetObject(input); + _lastName = GetObject(input); + AccessHash = GetObject(input); + Phone = GetObject(input); + _photo = GetObject(input); + _status = GetObject(input); + + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + ExtendedInfo = GetObject(input) as TLUserExtendedInfo; + Contact = GetObject(input) as TLContact; + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Phone.ToBytes()); + Photo.ToStream(output); + Status.ToStream(output); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + Contact.NullableToStream(output); + } + + public override void Update(TLUserBase user) + { + base.Update(user); + + AccessHash = ((TLUserContact)user).AccessHash; + } + + public override TLInputUserBase ToInputUser() + { + return new TLInputUser { UserId = Id, AccessHash = new TLLong(0) }; + } + + public override TLInputPeerBase ToInputPeer() + { + return new TLInputPeerUser { UserId = Id, AccessHash = new TLLong(0) }; + } + + public override bool IsDeleted + { + get { return false; } + set { } + } + + public override bool IsSelf + { + get { return false; } + set { } + } + + public override bool IsForeign + { + get { return false; } + } + + public override bool IsRequest + { + get { return false; } + } + + public override bool IsContact + { + get { return true; } + set { } + } + + public override bool IsContactMutual + { + get { return Contact != null && Contact.Mutual.Value; } + set { } + } + } + + public class TLUserRequest18 : TLUserRequest, IUserName + { + public new const uint Signature = TLConstructors.TLUserRequest18; + + public TLString UserName { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + _firstName = GetObject(bytes, ref position); + _lastName = GetObject(bytes, ref position); + UserName = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Phone = GetObject(bytes, ref position); + _photo = GetObject(bytes, ref position); + _status = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + UserName.ToBytes(), + AccessHash.ToBytes(), + Phone.ToBytes(), + Photo.ToBytes(), + Status.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _firstName = GetObject(input); + _lastName = GetObject(input); + UserName = GetObject(input); + AccessHash = GetObject(input); + Phone = GetObject(input); + _photo = GetObject(input); + _status = GetObject(input); + + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + ExtendedInfo = GetObject(input) as TLUserExtendedInfo; + Contact = GetObject(input) as TLContact; + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + output.Write(UserName.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Phone.ToBytes()); + Photo.ToStream(output); + Status.ToStream(output); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + Contact.NullableToStream(output); + } + + public override void Update(TLUserBase user) + { + base.Update(user); + + var user18 = user as TLUserRequest18; + if (user18 != null) + { + UserName = user18.UserName; + } + } + + public override string ToString() + { + var userNameString = UserName != null ? " @" + UserName : string.Empty; + return base.ToString() + userNameString; + } + } + + public class TLUserRequest : TLUserBase + { + public const uint Signature = TLConstructors.TLUserRequest; + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + _firstName = GetObject(bytes, ref position); + _lastName = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Phone = GetObject(bytes, ref position); + _photo = GetObject(bytes, ref position); + _status = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + AccessHash.ToBytes(), + Phone.ToBytes(), + Photo.ToBytes(), + Status.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _firstName = GetObject(input); + _lastName = GetObject(input); + AccessHash = GetObject(input); + Phone = GetObject(input); + _photo = GetObject(input); + _status = GetObject(input); + + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + ExtendedInfo = GetObject(input) as TLUserExtendedInfo; + Contact = GetObject(input) as TLContact; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + output.Write(AccessHash.ToBytes()); + output.Write(Phone.ToBytes()); + Photo.ToStream(output); + Status.ToStream(output); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + Contact.NullableToStream(output); + } + + public override TLInputUserBase ToInputUser() + { + return new TLInputUser { UserId = Id, AccessHash = AccessHash }; + } + + public override void Update(TLUserBase user) + { + base.Update(user); + + AccessHash = ((TLUserRequest)user).AccessHash; + } + + public override TLInputPeerBase ToInputPeer() + { + return new TLInputPeerUser { UserId = Id, AccessHash = AccessHash }; + } + + public override bool IsDeleted + { + get { return false; } + set { } + } + + public override bool IsSelf + { + get { return false; } + set { } + } + + public override bool IsForeign + { + get { return false; } + } + + public override bool IsRequest + { + get { return true; } + } + + public override bool IsContact + { + get { return false; } + set { } + } + + public override bool IsContactMutual + { + get { return false; } + set { } + } + } + + public class TLUserForeign18 : TLUserForeign, IUserName + { + public new const uint Signature = TLConstructors.TLUserForeign18; + + public TLString UserName { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + _firstName = GetObject(bytes, ref position); + _lastName = GetObject(bytes, ref position); + UserName = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + _photo = GetObject(bytes, ref position); + _status = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + UserName.ToBytes(), + AccessHash.ToBytes(), + Photo.ToBytes(), + Status.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _firstName = GetObject(input); + _lastName = GetObject(input); + UserName = GetObject(input); + AccessHash = GetObject(input); + _photo = GetObject(input); + _status = GetObject(input); + + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + ExtendedInfo = GetObject(input) as TLUserExtendedInfo; + Contact = GetObject(input) as TLContact; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + output.Write(UserName.ToBytes()); + output.Write(AccessHash.ToBytes()); + Photo.ToStream(output); + Status.ToStream(output); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + Contact.NullableToStream(output); + } + + public override void Update(TLUserBase user) + { + base.Update(user); + + var user18 = user as TLUserForeign18; + if (user18 != null) + { + UserName = user18.UserName; + } + } + + public override string ToString() + { + var userNameString = UserName != null ? " @" + UserName : string.Empty; + return base.ToString() + userNameString; + } + } + + public class TLUserForeign : TLUserBase + { + public const uint Signature = TLConstructors.TLUserForeign; + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + _firstName = GetObject(bytes, ref position); + _lastName = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + _photo = GetObject(bytes, ref position); + _status = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + AccessHash.ToBytes(), + Photo.ToBytes(), + Status.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _firstName = GetObject(input); + _lastName = GetObject(input); + AccessHash = GetObject(input); + _photo = GetObject(input); + _status = GetObject(input); + + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + ExtendedInfo = GetObject(input) as TLUserExtendedInfo; + Contact = GetObject(input) as TLContact; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + output.Write(AccessHash.ToBytes()); + Photo.ToStream(output); + Status.ToStream(output); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + Contact.NullableToStream(output); + } + + public override TLInputUserBase ToInputUser() + { + return new TLInputUser { UserId = Id, AccessHash = AccessHash }; + } + + public override void Update(TLUserBase user) + { + base.Update(user); + + AccessHash = ((TLUserForeign)user).AccessHash; + } + + public override TLInputPeerBase ToInputPeer() + { + return new TLInputPeerUser { UserId = Id, AccessHash = AccessHash }; + } + + public override bool IsDeleted + { + get { return false; } + set { } + } + + public override bool IsSelf + { + get { return false; } + set { } + } + + public override bool IsForeign + { + get { return true; } + } + + public override bool IsRequest + { + get { return false; } + } + + public override bool IsContact + { + get { return false; } + set { } + } + + public override bool IsContactMutual + { + get { return false; } + set { } + } + } + + public class TLUserDeleted18 : TLUserDeleted, IUserName + { + public new const uint Signature = TLConstructors.TLUserDeleted18; + + public TLString UserName { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + _firstName = GetObject(bytes, ref position); + _lastName = GetObject(bytes, ref position); + UserName = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes(), + UserName.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _firstName = GetObject(input); + _lastName = GetObject(input); + UserName = GetObject(input); + + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + ExtendedInfo = GetObject(input) as TLUserExtendedInfo; + Contact = GetObject(input) as TLContact; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + output.Write(UserName.ToBytes()); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + Contact.NullableToStream(output); + } + + public override void Update(TLUserBase user) + { + base.Update(user); + + var user18 = user as TLUserDeleted18; + if (user18 != null) + { + UserName = user18.UserName; + } + } + + public override string ToString() + { + var userNameString = UserName != null ? " @" + UserName : string.Empty; + return base.ToString() + userNameString; + } + } + + public class TLUserDeleted : TLUserBase + { + public const uint Signature = TLConstructors.TLUserDeleted; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + _firstName = GetObject(bytes, ref position); + _lastName = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + FirstName.ToBytes(), + LastName.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + _firstName = GetObject(input); + _lastName = GetObject(input); + + NotifySettings = GetObject(input) as TLPeerNotifySettingsBase; + ExtendedInfo = GetObject(input) as TLUserExtendedInfo; + Contact = GetObject(input) as TLContact; + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(Id.ToBytes()); + output.Write(FirstName.ToBytes()); + output.Write(LastName.ToBytes()); + + NotifySettings.NullableToStream(output); + ExtendedInfo.NullableToStream(output); + Contact.NullableToStream(output); + } + + public override TLInputUserBase ToInputUser() + { + return new TLInputUser { UserId = Id, AccessHash = new TLLong(0) }; + } + + public override TLInputPeerBase ToInputPeer() + { + return new TLInputPeerUser { UserId = Id, AccessHash = new TLLong(0) }; + } + + public override bool IsDeleted + { + get { return true; } + set { } + } + + public override bool IsSelf + { + get { return false; } + set { } + } + + public override bool IsForeign + { + get { return false; } + } + + public override bool IsRequest + { + get { return false; } + } + + public override bool IsContact + { + get { return false; } + set { } + } + + public override bool IsContactMutual + { + get { return false; } + set { } + } + } +} diff --git a/Telegram.Api/TL/TLUserFull.cs b/Telegram.Api/TL/TLUserFull.cs new file mode 100755 index 0000000..78d963b --- /dev/null +++ b/Telegram.Api/TL/TLUserFull.cs @@ -0,0 +1,185 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum UserFullFlags + { + Blocked = 0x1, // 0 + About = 0x2, // 1 + ProfilePhoto = 0x4, // 2 + BotInfo = 0x8, // 3 + } + + public class TLUserFull : TLObject + { + public const uint Signature = TLConstructors.TLUserFull; + + public TLUserBase User { get; set; } + + public TLLinkBase Link { get; set; } + + public TLPhotoBase ProfilePhoto { get; set; } + + public TLPeerNotifySettingsBase NotifySettings { get; set; } + + public virtual TLBool Blocked { get; set; } + + public TLString RealFirstName { get; set; } + + public TLString RealLastName { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + User = GetObject(bytes, ref position); + Link = GetObject(bytes, ref position); + ProfilePhoto = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + Blocked = GetObject(bytes, ref position); + RealFirstName = GetObject(bytes, ref position); + RealLastName = GetObject(bytes, ref position); + + return this; + } + + public virtual TLUserBase ToUser() + { + User.Link = Link; + User.ProfilePhoto = ProfilePhoto; + User.NotifySettings = NotifySettings; + User.Blocked = Blocked; + + return User; + } + } + + public class TLUserFull31 : TLUserFull + { + public new const uint Signature = TLConstructors.TLUserFull31; + + public TLBotInfoBase BotInfo { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + User = GetObject(bytes, ref position); + Link = GetObject(bytes, ref position); + ProfilePhoto = GetObject(bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + Blocked = GetObject(bytes, ref position); + BotInfo = GetObject(bytes, ref position); + + return this; + } + + public override TLUserBase ToUser() + { + User.Link = Link; + User.ProfilePhoto = ProfilePhoto; + User.NotifySettings = NotifySettings; + User.Blocked = Blocked; + User.BotInfo = BotInfo; + + return User; + } + } + + public class TLUserFull49 : TLUserFull31 + { + public new const uint Signature = TLConstructors.TLUserFull49; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + public override TLBool Blocked + { + get { return new TLBool(IsSet(Flags, (int) UserFullFlags.Blocked)); } + set { SetUnset(ref _flags, value != null && value.Value, (int) UserFullFlags.Blocked); } + } + + public TLString About { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + User = GetObject(bytes, ref position); + About = GetObject(Flags, (int)UserFullFlags.About, TLString.Empty, bytes, ref position); + Link = GetObject(bytes, ref position); + ProfilePhoto = GetObject(Flags, (int)UserFullFlags.ProfilePhoto, null, bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + BotInfo = GetObject(Flags, (int) UserFullFlags.BotInfo, new TLBotInfoEmpty(), bytes, ref position); + + return this; + } + + public override TLUserBase ToUser() + { + User.Link = Link; + var user45 = User as TLUser45; + if (user45 != null) user45.About = About; + if (ProfilePhoto != null) User.ProfilePhoto = ProfilePhoto; + User.NotifySettings = NotifySettings; + User.Blocked = Blocked; + User.BotInfo = BotInfo; + + return User; + } + } + + public class TLUserFull58 : TLUserFull49 + { + public new const uint Signature = TLConstructors.TLUserFull58; + + public TLInt CommonChatsCount { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + User = GetObject(bytes, ref position); + About = GetObject(Flags, (int)UserFullFlags.About, TLString.Empty, bytes, ref position); + Link = GetObject(bytes, ref position); + ProfilePhoto = GetObject(Flags, (int)UserFullFlags.ProfilePhoto, null, bytes, ref position); + NotifySettings = GetObject(bytes, ref position); + BotInfo = GetObject(Flags, (int)UserFullFlags.BotInfo, new TLBotInfoEmpty(), bytes, ref position); + CommonChatsCount = GetObject(bytes, ref position); + + return this; + } + + public override TLUserBase ToUser() + { + User.Link = Link; + var user45 = User as TLUser45; + if (user45 != null) + { + user45.About = About; + user45.CommonChatsCount = CommonChatsCount; + } + if (ProfilePhoto != null) User.ProfilePhoto = ProfilePhoto; + User.NotifySettings = NotifySettings; + User.Blocked = Blocked; + User.BotInfo = BotInfo; + + return User; + } + } +} diff --git a/Telegram.Api/TL/TLUserStatus.cs b/Telegram.Api/TL/TLUserStatus.cs new file mode 100755 index 0000000..fbf86bc --- /dev/null +++ b/Telegram.Api/TL/TLUserStatus.cs @@ -0,0 +1,215 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using System.Runtime.Serialization; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [KnownType(typeof(TLUserStatusEmpty))] + [KnownType(typeof(TLUserStatusOnline))] + [KnownType(typeof(TLUserStatusOffline))] + [KnownType(typeof(TLUserStatusRecently))] + [KnownType(typeof(TLUserStatusLastWeek))] + [KnownType(typeof(TLUserStatusLastMonth))] + [DataContract] + public abstract class TLUserStatus : TLObject{ } + + [DataContract] + public class TLUserStatusEmpty : TLUserStatus + { + public const uint Signature = TLConstructors.TLUserStatusEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + var buffer = ToBytes(); + output.Write(buffer, 0, buffer.Length); + } + } + + [DataContract] + public class TLUserStatusOnline : TLUserStatus + { + public const uint Signature = TLConstructors.TLUserStatusOnline; + + [DataMember] + public TLInt Expires { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Expires = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Expires.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Expires = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + var buffer = ToBytes(); + output.Write(buffer, 0, buffer.Length); + } + } + + [DataContract] + public class TLUserStatusOffline : TLUserStatus + { + public const uint Signature = TLConstructors.TLUserStatusOffline; + + [DataMember] + public TLInt WasOnline { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + WasOnline = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + WasOnline.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + WasOnline = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + var buffer = ToBytes(); + output.Write(buffer, 0, buffer.Length); + } + } + + [DataContract] + public class TLUserStatusRecently : TLUserStatus + { + public const uint Signature = TLConstructors.TLUserStatusRecently; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + [DataContract] + public class TLUserStatusLastWeek : TLUserStatus + { + public const uint Signature = TLConstructors.TLUserStatusLastWeek; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } + + [DataContract] + public class TLUserStatusLastMonth : TLUserStatus + { + public const uint Signature = TLConstructors.TLUserStatusLastMonth; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.SignatureToBytes(Signature); + } + + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLUtils.Log.cs b/Telegram.Api/TL/TLUtils.Log.cs new file mode 100755 index 0000000..e24f87a --- /dev/null +++ b/Telegram.Api/TL/TLUtils.Log.cs @@ -0,0 +1,174 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; +using Telegram.Api.Helpers; +#if WIN_RT +using Windows.UI.Popups; +using Windows.UI.Core; +#endif +using Telegram.Api.Aggregator; +using Telegram.Api.Services.Cache; +using Telegram.Logs; +#if WINDOWS_PHONE +using System.Threading; +using System.Windows; +#endif + +namespace Telegram.Api.TL +{ + public enum LogSeverity + { + Error, + Warning, + Info + } + + public static partial class TLUtils + { + private static void LogBugsenseError(string caption, Exception e) + { + var eventAggregator = TelegramEventAggregator.Instance; + + eventAggregator.Publish(new ExceptionInfo{ Caption = caption, Exception = e }); + } + + private static bool _isLogEnabled = false; + + public static bool IsLogEnabled + { + get { return _isLogEnabled; } + set { _isLogEnabled = value; } + } + + private static bool _isDebugEnabled = false; + + public static bool IsDebugEnabled + { + get { return _isDebugEnabled; } + set { _isDebugEnabled = value; } + } + + private static bool _isLongPollLogEnabled = false; + + public static bool IsLongPollDebugEnabled + { + get { return _isLongPollLogEnabled; } + set { _isLongPollLogEnabled = value; } + } +#if DEBUG + private static bool _isPerformanceLogEnabled = false; +#else + private static bool _isPerformanceLogEnabled = false; + +#endif + + + public static bool IsPerformanceLogEnabled + { + get { return _isPerformanceLogEnabled; } + set { _isPerformanceLogEnabled = value; } + } + + public static ObservableCollection LongPollItems = new ObservableCollection(); + + public static ObservableCollection PerformanceItems = new ObservableCollection(); + + public static ObservableCollection DebugItems = new ObservableCollection(); + + public static ObservableCollection LogItems = new ObservableCollection(); + + public static void WritePerformance(string str) + { + if (!IsPerformanceLogEnabled) return; + + Execute.BeginOnUIThread(() => PerformanceItems.Add(str)); + } + + public static void WriteLog(string str) + { + if (!IsLogEnabled) return; + + var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture); + Execute.BeginOnUIThread(() => LogItems.Add(timestamp + ": " + str)); + } + + public static void WriteLongPoll(string str) + { + if (!IsLongPollDebugEnabled) return; + + Execute.BeginOnUIThread(() => LongPollItems.Add(str)); + } + + public static void WriteLine(LogSeverity severity = LogSeverity.Info) + { + if (!IsDebugEnabled && severity != LogSeverity.Error) return; + + Execute.BeginOnUIThread(() => DebugItems.Add(" ")); + } + + public static void WriteLineAtBegin(string str, LogSeverity severity = LogSeverity.Info) + { + if (!IsDebugEnabled && severity != LogSeverity.Error) return; + + Execute.BeginOnUIThread(() => DebugItems.Insert(0, str)); + } + + public static void WriteException(string caption, Exception e) + { + Execute.ShowDebugMessage(caption + Environment.NewLine + e); + +#if LOG_REGISTRATION + WriteLog(caption + Environment.NewLine + e); +#endif + Log.Write(caption + Environment.NewLine + e); + + Execute.BeginOnUIThread(() => + { + DebugItems.Add(caption + Environment.NewLine + e); + LogBugsenseError(caption, e); + }); + } + + public static void WriteException(Exception e) + { + WriteException(null, e); + } + + public static void WriteLine(string str, LogSeverity severity = LogSeverity.Info) + { +#if DEBUG + if (!IsDebugEnabled && severity != LogSeverity.Error) return; + + Execute.BeginOnUIThread(() => DebugItems.Add(str)); +#endif + } + + public static void WriteLine(string fieldName, T fieldValue, LogSeverity severity = LogSeverity.Info) + { + if (!IsDebugEnabled && severity != LogSeverity.Error) return; + + Execute.BeginOnUIThread(() => DebugItems.Add(String.Format("{0}: {1}", fieldName, fieldValue))); + } + + public static string WriteThreadInfo() + { + var threadId = + +#if WINDOWS_PHONE + Thread.CurrentThread.ManagedThreadId; +#elif WIN_RT + Environment.CurrentManagedThreadId; +#endif + + return "ThreadId " + threadId; + } + } +} diff --git a/Telegram.Api/TL/TLUtils.cs b/Telegram.Api/TL/TLUtils.cs new file mode 100755 index 0000000..4d6cba3 --- /dev/null +++ b/Telegram.Api/TL/TLUtils.cs @@ -0,0 +1,1957 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define MTPROTO +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Telegram.Api.TL.Functions.Channels; +using Telegram.Api.TL.Functions.Messages; +using Telegram.Logs; +using Telegram.Api.Helpers; +using Telegram.Api.Services; + +namespace Telegram.Api.TL +{ + public static partial class TLUtils + { + public static TLInputClientProxy GetInputProxy(TLProxyConfigBase proxyConfig) + { + TLInputClientProxy inputProxy = null; + if (proxyConfig != null && !proxyConfig.IsEmpty && proxyConfig.IsEnabled.Value) + { + var proxy = proxyConfig.GetProxy(); + inputProxy = proxy != null ? proxy.ToInputProxy() : null; + } + + return inputProxy; + } + + public static TLDCOption GetDCOption(TLConfig config, TLInt dcId, bool media = false) + { + TLDCOption dcOption = null; + if (config != null) + { + dcOption = config.DCOptions.FirstOrDefault(x => x.IsValidIPv4WithTCPO25Option(dcId) && x.Media.Value == media); + if (dcOption == null) + { + dcOption = config.DCOptions.FirstOrDefault(x => x.IsValidIPv4Option(dcId) && x.Media.Value == media); + } + } + + return dcOption; + } + + public static short GetProtocolDCId(int dcId, bool media, bool testServer) + { + dcId = testServer ? 10000 + dcId : dcId; + + return media ? (short)-dcId : (short)dcId; + } + + public static byte[] ParseSecret(TLDCOption dcOption) + { + var dcOption78 = dcOption as TLDCOption78; + if (dcOption78 != null && !TLString.IsNullOrEmpty(dcOption78.Secret)) + { + return dcOption78.Secret.Data; //ParseSecret(dcOption78.Secret); + } + + return null; + } + + public static byte[] ParseSecret(TLString str) + { + if (TLString.IsNullOrEmpty(str)) return null; + + var hexStr = str.ToString().ToLowerInvariant(); + for (var i = 0; i < hexStr.Length; i++) + { + if (hexStr[i] >= '0' && hexStr[i] <= '9') + { + continue; + } + if (hexStr[i] >= 'a' && hexStr[i] <= 'f') + { + continue; + } + + return null; + } + + var bytes = new byte[hexStr.Length / 2]; + for (var i = 0; i < hexStr.Length; i += 2) + { + bytes[i / 2] = Convert.ToByte(hexStr.Substring(i, 2), 16); + } + + return bytes; + } + + public static string ContentTypeToFileExt(TLString contentType) + { + if (contentType != null) + { + if (TLString.Equals(contentType, new TLString("image/jpg"), StringComparison.OrdinalIgnoreCase)) + { + return ".jpg"; + } + if (TLString.Equals(contentType, new TLString("video/mp4"), StringComparison.OrdinalIgnoreCase)) + { + return ".mp4"; + } + } + + return null; + } + + public static TLInt ToTLInt(TLString value) + { + try + { + var intValue = Convert.ToInt32(value.Value); + return new TLInt(intValue); + } + catch (Exception ex) + { + + } + + return null; + } + + public static TLString ToTLString(TLInt value) + { + try + { + var intValue = value.Value.ToString(CultureInfo.InvariantCulture); + return new TLString(intValue); + } + catch (Exception ex) + { + + } + + return null; + } + + public static int GetTopPeersHash(TLTopPeers topPeers) + { + long acc = 0; + foreach (var category in topPeers.Categories) + { + foreach (var topPeer in category.Peers) + { + acc = ((acc * 20261) + 0x80000000 + topPeer.Peer.Id.Value) % 0x80000000; + } + } + + return (int)acc; + } + + public static int GetAllStickersHash(IList sets) + { + long acc = 0; + foreach (var set in sets) + { + var stickerSet32 = set as TLStickerSet32; + if (stickerSet32 != null) + { + if (stickerSet32.Archived) continue; + + acc = ((acc * 20261) + 0x80000000 + stickerSet32.Hash.Value) % 0x80000000; + } + } + + return (int)acc; + } + + public static int GetFeaturedStickersHash(IList sets, IList unreadSets) + { + long acc = 0; + foreach (var set in sets) + { + var stickerSet32 = set as TLStickerSet32; + if (stickerSet32 != null) + { + if (stickerSet32.Archived) continue; + + var high_id = (int)(stickerSet32.Id.Value >> 32); + var low_id = (int)stickerSet32.Id.Value; + + acc = ((acc * 20261) + 0x80000000L + high_id) % 0x80000000L; + acc = ((acc * 20261) + 0x80000000L + low_id) % 0x80000000L; + + if (unreadSets.FirstOrDefault(x => x.Value == stickerSet32.Id.Value) != null) + { + acc = ((acc * 20261) + 0x80000000L + 1) % 0x80000000L; + } + } + } + + return (int)acc; + } + + public static TLInt GetFavedStickersHash(IList documents) + { + long acc = 0; + foreach (var documentBase in documents) + { + var document = documentBase as TLDocument; + if (document == null) continue; + + var high_id = (int)(document.Id.Value >> 32); + var low_id = (int)document.Id.Value; + + acc = ((acc * 20261) + 0x80000000L + high_id) % 0x80000000L; + acc = ((acc * 20261) + 0x80000000L + low_id) % 0x80000000L; + } + + return new TLInt((int)acc); + } + + public static TLInt GetRecentStickersHash(IList documents) + { + long acc = 0; + foreach (var documentBase in documents) + { + var document = documentBase as TLDocument; + if (document == null) continue; + + var high_id = (int)(document.Id.Value >> 32); + var low_id = (int)document.Id.Value; + + acc = ((acc * 20261) + 0x80000000L + high_id) % 0x80000000L; + acc = ((acc * 20261) + 0x80000000L + low_id) % 0x80000000L; + } + + return new TLInt((int)acc); + } + + public static int GetContactsHash(TLInt savedCount, IList contacts) + { + savedCount = savedCount ?? new TLInt(0); + if (contacts == null) + { + return 0; + } + + long acc = 0; + acc = ((acc * 20261) + 0x80000000L + savedCount.Value) % 0x80000000L; + + foreach (var contact in contacts) + { + if (contact == null) continue; + + acc = ((acc * 20261) + 0x80000000L + contact.Id.Value) % 0x80000000L; + } + + return (int)acc; + } + + public static void AddStickerSetCovered(IStickers stickers, TLMessagesStickerSet messagesSet, TLVector coveredSets, TLStickerSetCoveredBase coveredSet) + { + coveredSets.Insert(0, coveredSet); + //stickers.SetsCovered.Insert(0, messagesSet.Set); + + stickers.Hash = new TLString(GetAllStickersHash(stickers.Sets).ToString(CultureInfo.InvariantCulture)); + + var packsDict = new Dictionary(); + for (var i = 0; i < messagesSet.Packs.Count; i++) + { + packsDict[messagesSet.Packs[i].Emoticon.ToString()] = messagesSet.Packs[i]; + } + + for (var i = 0; i < messagesSet.Packs.Count; i++) + { + TLStickerPack pack; + if (packsDict.TryGetValue(messagesSet.Packs[i].Emoticon.ToString(), out pack)) + { + for (var j = messagesSet.Packs[i].Documents.Count - 1; j >= 0; j--) + { + pack.Documents.Insert(0, messagesSet.Packs[i].Documents[j]); + } + } + else + { + stickers.Packs.Insert(0, messagesSet.Packs[i]); + } + } + + for (var i = messagesSet.Documents.Count - 1; i >= 0; i--) + { + stickers.Documents.Insert(0, messagesSet.Documents[i]); + } + } + + public static void AddStickerSet(IStickers stickers, TLMessagesStickerSet messagesSet) + { + stickers.Sets.Insert(0, messagesSet.Set); + + stickers.Hash = new TLString(GetAllStickersHash(stickers.Sets).ToString(CultureInfo.InvariantCulture)); + + var packsDict = new Dictionary(); + for (var i = 0; i < messagesSet.Packs.Count; i++) + { + packsDict[messagesSet.Packs[i].Emoticon.ToString()] = messagesSet.Packs[i]; + } + + for (var i = 0; i < messagesSet.Packs.Count; i++) + { + TLStickerPack pack; + if (packsDict.TryGetValue(messagesSet.Packs[i].Emoticon.ToString(), out pack)) + { + for (var j = messagesSet.Packs[i].Documents.Count - 1; j >= 0; j--) + { + pack.Documents.Insert(0, messagesSet.Packs[i].Documents[j]); + } + } + else + { + stickers.Packs.Insert(0, messagesSet.Packs[i]); + } + } + + for (var i = messagesSet.Documents.Count - 1; i >= 0; i--) + { + stickers.Documents.Insert(0, messagesSet.Documents[i]); + } + } + + public static TLMessagesStickerSet RemoveStickerSetCovered(IStickers stickers, TLStickerSetBase set, TLVector coveredSets) + { + TLStickerSetCoveredBase s = null; + for (var i = 0; i < coveredSets.Count; i++) + { + if (coveredSets[i].StickerSet.Id.Value == set.Id.Value) + { + s = coveredSets[i]; + coveredSets.RemoveAt(i); + break; + } + } + + var s32 = s.StickerSet as TLStickerSet32; + var set32 = set as TLStickerSet32; + if (s32 != null && set32 != null) + { + s32.Flags = set32.Flags; + } + + stickers.Hash = new TLString(GetAllStickersHash(stickers.Sets).ToString(CultureInfo.InvariantCulture)); + + var documents = new TLVector(); + var documentsDict = new Dictionary(); + for (var i = 0; i < stickers.Documents.Count; i++) + { + var document = stickers.Documents[i] as TLDocument54; + if (document != null) + { + var inputStickerSetId = document.StickerSet as TLInputStickerSetId; + if (inputStickerSetId != null && inputStickerSetId.Id.Value == set.Id.Value) + { + documents.Add(document); + documentsDict[document.Id.Value] = document.Id.Value; + + stickers.Documents.RemoveAt(i--); + continue; + } + + var inputStickerSetShortName = document.StickerSet as TLInputStickerSetShortName; + if (inputStickerSetShortName != null && inputStickerSetShortName.ShortName.ToString() == set.ShortName.ToString()) + { + documents.Add(document); + documentsDict[document.Id.Value] = document.Id.Value; + + stickers.Documents.RemoveAt(i--); + } + } + } + + var packs = new TLVector(); + for (var i = 0; i < stickers.Packs.Count; i++) + { + var pack = new TLStickerPack { Emoticon = stickers.Packs[i].Emoticon, Documents = new TLVector() }; + + for (var j = 0; j < stickers.Packs[i].Documents.Count; j++) + { + if (documentsDict.ContainsKey(stickers.Packs[i].Documents[j].Value)) + { + pack.Documents.Add(stickers.Packs[i].Documents[j]); + stickers.Packs[i].Documents.RemoveAt(j--); + } + } + + if (pack.Documents.Count > 0) + { + packs.Add(pack); + } + + if (stickers.Packs[i].Documents.Count == 0) + { + stickers.Packs.RemoveAt(i--); + } + } + + return new TLMessagesStickerSet { Set = s.StickerSet, Packs = packs, Documents = documents }; + } + + public static TLMessagesStickerSet RemoveStickerSet(IStickers stickers, TLStickerSetBase set) + { + TLStickerSetBase s = null; + for (var i = 0; i < stickers.Sets.Count; i++) + { + if (stickers.Sets[i].Id.Value == set.Id.Value) + { + s = stickers.Sets[i]; + stickers.Sets.RemoveAt(i); + break; + } + } + + var s32 = s as TLStickerSet32; + var set32 = set as TLStickerSet32; + if (s32 != null && set32 != null) + { + s32.Flags = set32.Flags; + } + + stickers.Hash = new TLString(GetAllStickersHash(stickers.Sets).ToString(CultureInfo.InvariantCulture)); + + var documents = new TLVector(); + var documentsDict = new Dictionary(); + for (var i = 0; i < stickers.Documents.Count; i++) + { + var document = stickers.Documents[i] as TLDocument54; + if (document != null) + { + var inputStickerSetId = document.StickerSet as TLInputStickerSetId; + if (inputStickerSetId != null && inputStickerSetId.Id.Value == set.Id.Value) + { + documents.Add(document); + documentsDict[document.Id.Value] = document.Id.Value; + + stickers.Documents.RemoveAt(i--); + continue; + } + + var inputStickerSetShortName = document.StickerSet as TLInputStickerSetShortName; + if (inputStickerSetShortName != null && inputStickerSetShortName.ShortName.ToString() == set.ShortName.ToString()) + { + documents.Add(document); + documentsDict[document.Id.Value] = document.Id.Value; + + stickers.Documents.RemoveAt(i--); + } + } + } + + var packs = new TLVector(); + for (var i = 0; i < stickers.Packs.Count; i++) + { + var pack = new TLStickerPack { Emoticon = stickers.Packs[i].Emoticon, Documents = new TLVector() }; + + for (var j = 0; j < stickers.Packs[i].Documents.Count; j++) + { + if (documentsDict.ContainsKey(stickers.Packs[i].Documents[j].Value)) + { + pack.Documents.Add(stickers.Packs[i].Documents[j]); + stickers.Packs[i].Documents.RemoveAt(j--); + } + } + + if (pack.Documents.Count > 0) + { + packs.Add(pack); + } + + if (stickers.Packs[i].Documents.Count == 0) + { + stickers.Packs.RemoveAt(i--); + } + } + + return new TLMessagesStickerSet { Set = s ?? set32, Packs = packs, Documents = documents }; + } + + public static bool IsValidAction(TLObject obj) + { + var readChannelHistoryAction = obj as TLReadChannelHistory; + if (readChannelHistoryAction != null) + { + return true; + } + + var readHistoryAction = obj as TLReadHistory; + if (readHistoryAction != null) + { + return true; + } + + var readMessageContents = obj as Functions.Messages.TLReadMessageContents; + if (readMessageContents != null) + { + return true; + } + + var readChannelMessageContents = obj as Functions.Channels.TLReadMessageContents; + if (readChannelMessageContents != null) + { + return true; + } + + var sendMessageAction = obj as TLSendMessage; + if (sendMessageAction != null) + { + return true; + } + + var sendMediaAction = obj as TLSendMedia; + if (sendMediaAction != null) + { + var mediaGame = sendMediaAction.Media as TLInputMediaGame; + if (mediaGame != null) + { + return true; + } + + var mediaContact = sendMediaAction.Media as TLInputMediaContact; + if (mediaContact != null) + { + return true; + } + + var mediaGeoPoint = sendMediaAction.Media as TLInputMediaGeoPoint; + if (mediaGeoPoint != null) + { + return true; + } + + var mediaVenue = sendMediaAction.Media as TLInputMediaVenue; + if (mediaVenue != null) + { + return true; + } + } + + var forwardMessagesAction = obj as TLForwardMessages; + if (forwardMessagesAction != null) + { + return true; + } + + var forwardMessageAction = obj as TLForwardMessage; + if (forwardMessageAction != null) + { + return true; + } + + var startBotAction = obj as TLStartBot; + if (startBotAction != null) + { + return true; + } + + var sendInlineBotResult = obj as TLSendInlineBotResult; + if (sendInlineBotResult != null) + { + return true; + } + + var sendEncrypted = obj as TLSendEncrypted; + if (sendEncrypted != null) + { + return true; + } + + var sendEncryptedFile = obj as TLSendEncryptedFile; + if (sendEncryptedFile != null) + { + return true; + } + + var sendEncryptedService = obj as TLSendEncryptedService; + if (sendEncryptedService != null) + { + return true; + } + + var readEncryptedHistory = obj as TLReadEncryptedHistory; + if (readEncryptedHistory != null) + { + return true; + } + + return false; + } + + public static TLMessage48 GetShortMessage( + TLInt id, + TLInt fromId, + TLPeerBase toId, + TLInt date, + TLString message) + { + + var m = new TLMessage73 + { + Flags = new TLInt(0), + Id = id, + FromId = fromId, + ToId = toId, + Out = TLBool.False, + _date = date, + Message = message, + _media = new TLMessageMediaEmpty() + }; + + if (m.FromId != null) m.SetFromId(); + if (m._media != null) m.SetMedia(); + + return m; + } + + public static TLMessage36 GetMessage( + TLInt fromId, + TLPeerBase toId, + MessageStatus status, + TLBool outFlag, + TLBool unreadFlag, + TLInt date, + TLString message, + TLMessageMediaBase media, + TLLong randomId, + TLInt replyToMsgId) + { + var m = new TLMessage73 + { + Flags = new TLInt(0), + FromId = fromId, + ToId = toId, + _status = status, + Out = outFlag, + Unread = unreadFlag, + _date = date, + Message = message, + _media = media, + RandomId = randomId, + ReplyToMsgId = replyToMsgId + }; + + if (m.FromId != null) m.SetFromId(); + if (m._media != null) m.SetMedia(); + if (m.ReplyToMsgId != null && m.ReplyToMsgId.Value != 0) m.SetReply(); + + return m; + } + + [MethodImpl(MethodImplOptions.NoOptimization)] + public static bool ByteArraysEqual(byte[] a, byte[] b) + { + if (ReferenceEquals(a, b)) + { + return true; + } + if (((a == null) || (b == null)) || (a.Length != b.Length)) + { + return false; + } + var flag = true; + for (var i = 0; i < a.Length; i++) + { + flag &= a[i] == b[i]; + } + return flag; + } + + public static IList GetPtsRange(IMultiPts multiPts) + { + var pts = multiPts.Pts; + var ptsCount = multiPts.PtsCount; + + return GetPtsRange(pts, ptsCount); + } + + public static IList GetPtsRange(TLInt pts, TLInt ptsCount) + { + var ptsList = new List(ptsCount.Value); + for (var i = ptsCount.Value - 1; i >= 0; i--) + { + ptsList.Add(new TLInt(pts.Value - i)); + } + + return ptsList; + } + + public static bool IsDisplayedDecryptedMessage(TLDecryptedMessageBase message, bool displayEmpty = false) + { + if (message == null) return false; + +#if DEBUG + //return true; +#endif + return IsDisplayedDecryptedMessageInternal(message, displayEmpty); + } + + public static bool CheckPrime(byte[] prime, int g) + { + if (!(g >= 2 && g <= 7)) + { + return false; + } + + if (prime.Length != 256 || prime[0] <= 127) + { + return false; + } + + var dhBI = new BigInteger(1, prime); + + if (g == 2) + { // p mod 8 = 7 for g = 2; + var res = dhBI.Mod(BigInteger.ValueOf(8)); + if (res.IntValue != 7) + { + return false; + } + } + else if (g == 3) + { // p mod 3 = 2 for g = 3; + var res = dhBI.Mod(BigInteger.ValueOf(3)); + if (res.IntValue != 2) + { + return false; + } + } + else if (g == 5) + { // p mod 5 = 1 or 4 for g = 5; + var res = dhBI.Mod(BigInteger.ValueOf(5)); + int val = res.IntValue; + if (val != 1 && val != 4) + { + return false; + } + } + else if (g == 6) + { // p mod 24 = 19 or 23 for g = 6; + var res = dhBI.Mod(BigInteger.ValueOf(24)); + int val = res.IntValue; + if (val != 19 && val != 23) + { + return false; + } + } + else if (g == 7) + { // p mod 7 = 3, 5 or 6 for g = 7. + var res = dhBI.Mod(BigInteger.ValueOf(7)); + int val = res.IntValue; + if (val != 3 && val != 5 && val != 6) + { + return false; + } + } + + var hex = BitConverter.ToString(prime).Replace("-", String.Empty).ToUpperInvariant(); + if (hex.Equals("C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5B")) + { + return true; + } + + var dhBI2 = dhBI.Subtract(BigInteger.ValueOf(1)).Divide(BigInteger.ValueOf(2)); + return !(!dhBI.IsProbablePrime(30) || !dhBI2.IsProbablePrime(30)); + } + + public static bool CheckGaAndGb(byte[] ga, byte[] prime) + { + var g_a = new BigInteger(1, ga); + var p = new BigInteger(1, prime); + + return CheckGaAndGb(g_a, p); + } + + public static bool CheckGaAndGb(BigInteger ga, BigInteger prime) + { + return !(ga.CompareTo(BigInteger.ValueOf(1)) != 1 || ga.CompareTo(prime.Subtract(BigInteger.ValueOf(1))) != -1); + } + + public static bool IsDisplayedDecryptedMessageInternal(TLDecryptedMessageBase message, bool displayEmpty = false) + { + var serviceMessage = message as TLDecryptedMessageService; + if (serviceMessage != null) + { + var emptyAction = serviceMessage.Action as TLDecryptedMessageActionEmpty; + if (emptyAction != null) + { + if (displayEmpty) + { + return true; + } + + return false; + } + + var notifyLayerAction = serviceMessage.Action as TLDecryptedMessageActionNotifyLayer; + if (notifyLayerAction != null) + { + return false; + } + + var deleteMessagesAction = serviceMessage.Action as TLDecryptedMessageActionDeleteMessages; + if (deleteMessagesAction != null) + { + return false; + } + + var readMessagesAction = serviceMessage.Action as TLDecryptedMessageActionReadMessages; + if (readMessagesAction != null) + { + return false; + } + + var flushHistoryAction = serviceMessage.Action as TLDecryptedMessageActionFlushHistory; + if (flushHistoryAction != null) + { + return false; + } + + var resendAction = serviceMessage.Action as TLDecryptedMessageActionResend; + if (resendAction != null) + { + return false; + } + + var requestKey = serviceMessage.Action as TLDecryptedMessageActionRequestKey; + if (requestKey != null) + { + return false; + } + + var commitKey = serviceMessage.Action as TLDecryptedMessageActionCommitKey; + if (commitKey != null) + { + return false; + } + + var acceptKey = serviceMessage.Action as TLDecryptedMessageActionAcceptKey; + if (acceptKey != null) + { + return false; + } + + var noop = serviceMessage.Action as TLDecryptedMessageActionNoop; + if (noop != null) + { + return false; + } + + var abortKey = serviceMessage.Action as TLDecryptedMessageActionAbortKey; + if (abortKey != null) + { + return false; + } + } + + return true; + } + + public static TLInt GetOutSeqNo(TLInt currentUserId, TLEncryptedChat17 chat) + { + var isAdmin = chat.AdminId.Value == currentUserId.Value; + var seqNo = 2 * chat.RawOutSeqNo.Value + (isAdmin ? 1 : 0); + + return new TLInt(seqNo); + } + + public static TLInt GetInSeqNo(TLInt currentUserId, TLEncryptedChat17 chat) + { + var isAdmin = chat.AdminId.Value == currentUserId.Value; + var seqNo = 2 * chat.RawInSeqNo.Value + (isAdmin ? 0 : 1); + + return new TLInt(seqNo); + } + + public static TLString EncryptMessage2(TLObject decryptedMessage, TLInt currentUserId, TLEncryptedChatCommon chat) + { + Debug.WriteLine("TLUtils.EncryptMessage2"); + + var random = new Random(); + + var key = chat.Key.Data; + var keyHash = Utils.ComputeSHA1(key); + var keyFingerprint = new TLLong(BitConverter.ToInt64(keyHash, 12)); + var decryptedBytes = decryptedMessage.ToBytes(); + var bytes = Combine(BitConverter.GetBytes(decryptedBytes.Length), decryptedBytes); + + var padding = 16 - bytes.Length % 16; + if (padding < 12) + { + padding += 16; + } + var paddingBytes = new byte[padding]; + random.NextBytes(paddingBytes); + var bytesWithPadding = Combine(bytes, paddingBytes); + + var x = chat.AdminId.Value == currentUserId.Value ? 0 : 8; //8; + var msgKeyLarge = Utils.ComputeSHA256(Combine(key.SubArray(88 + x, 32), bytesWithPadding)); + var msgKey = msgKeyLarge.SubArray(8, 16); + + var sha256_a = Utils.ComputeSHA256(Combine(msgKey, key.SubArray(x, 36))); + var sha256_b = Utils.ComputeSHA256(Combine(key.SubArray(40 + x, 36), msgKey)); + var aesKey = Combine(sha256_a.SubArray(0, 8), sha256_b.SubArray(8, 16), sha256_a.SubArray(24, 8)); + var aesIV = Combine(sha256_b.SubArray(0, 8), sha256_a.SubArray(8, 16), sha256_b.SubArray(24, 8)); + + var encryptedBytes = Utils.AesIge(bytesWithPadding, aesKey, aesIV, true); + + var resultBytes = Combine(keyFingerprint.ToBytes(), msgKey, encryptedBytes); + + return TLString.FromBigEndianData(resultBytes); + } + + public static TLDecryptedMessageBase DecryptMessage2(TLString data, TLInt currentUserId, TLEncryptedChat chat, out bool commitChat) + { + Debug.WriteLine("TLUtils.DecryptMessage2"); + + commitChat = false; + + var bytes = data.Data; + + var keyFingerprint = BitConverter.ToInt64(bytes, 0); + var msgKey = bytes.SubArray(8, 16); + var key = chat.Key.Data; + var keyHash = Utils.ComputeSHA1(key); + var calculatedKeyFingerprint = BitConverter.ToInt64(keyHash, keyHash.Length - 8); + + if (keyFingerprint != calculatedKeyFingerprint) + { + var chat20 = chat as TLEncryptedChat20; + if (chat20 != null && chat20.PFS_Key != null) + { + var pfsKeyHash = Utils.ComputeSHA1(chat20.PFS_Key.Data); + var pfsKeyFingerprint = BitConverter.ToInt64(pfsKeyHash, pfsKeyHash.Length - 8); + if (pfsKeyFingerprint == keyFingerprint) + { + chat20.Key = chat20.PFS_Key; + chat20.PFS_Key = null; + chat20.PFS_KeyFingerprint = null; + chat20.PFS_A = null; + chat20.PFS_ExchangeId = null; + commitChat = true; + } + else + { + return null; + } + } + else + { + return null; + } + } + + var x = chat.AdminId.Value == currentUserId.Value ? 8 : 0; //0; + var sha256_a = Utils.ComputeSHA256(Combine(msgKey, key.SubArray(x, 36))); + var sha256_b = Utils.ComputeSHA256(Combine(key.SubArray(40 + x, 36), msgKey)); + var aesKey = Combine(sha256_a.SubArray(0, 8), sha256_b.SubArray(8, 16), sha256_a.SubArray(24, 8)); + var aesIV = Combine(sha256_b.SubArray(0, 8), sha256_a.SubArray(8, 16), sha256_b.SubArray(24, 8)); + + var encryptedBytes = bytes.SubArray(24, bytes.Length - 24); + var decryptedBytes = Utils.AesIge(encryptedBytes, aesKey, aesIV, false); + + var length = BitConverter.ToInt32(decryptedBytes, 0); + if (length <= 0 || (4 + length) > decryptedBytes.Length) + { + Log.Write("TLUtils.DecryptMessage length <= 0 || (4 + length) > decryptedBytes.Length"); + return null; + } + + var calculatedMsgKeyLarge = Utils.ComputeSHA256(Combine(key.SubArray(88 + x, 32), decryptedBytes)); + var calculatedMsgKey = calculatedMsgKeyLarge.SubArray(8, 16); + for (var i = 0; i < 16; i++) + { + if (msgKey[i] != calculatedMsgKey[i]) + { + Log.Write("TLUtils.DecryptMessage msgKey != calculatedMsgKey"); + return null; + } + } + + var position = 4; + var decryptedObject = TLObject.GetObject(decryptedBytes, ref position); + var decryptedMessageLayer = decryptedObject as TLDecryptedMessageLayer; + var decryptedMessageLayer17 = decryptedObject as TLDecryptedMessageLayer17; + TLDecryptedMessageBase decryptedMessage = null; + + if (decryptedMessageLayer17 != null) + { + var randomBytes = decryptedMessageLayer17.RandomBytes.Data; + if (randomBytes == null || randomBytes.Length < Constants.MinRandomBytesLength) + { + Log.Write("TLUtils.DecryptMessage randomBytes.Length<" + Constants.MinRandomBytesLength); + return null; + } + + decryptedMessage = decryptedMessageLayer17.Message; + var decryptedMessage17 = decryptedMessage as ISeqNo; + if (decryptedMessage17 != null) + { + decryptedMessage17.InSeqNo = decryptedMessageLayer17.InSeqNo; + decryptedMessage17.OutSeqNo = decryptedMessageLayer17.OutSeqNo; + } + } + else if (decryptedMessageLayer != null) + { + decryptedMessage = decryptedMessageLayer.Message; + } + else if (decryptedObject is TLDecryptedMessageBase) + { + decryptedMessage = (TLDecryptedMessageBase)decryptedObject; + } + + return decryptedMessage; + } + + public static TLString EncryptMessage(TLObject decryptedMessage, TLInt currentUserId, TLEncryptedChatCommon chat) + { + Debug.WriteLine("TLUtils.EncryptMessage"); + var chat20 = chat as TLEncryptedChat20; + if (chat20 != null && chat20.Layer.Value >= Constants.MinSecretChatWithMTProto2Layer) + { + return EncryptMessage2(decryptedMessage, currentUserId, chat); + } + + var random = new Random(); + + var key = chat.Key.Data; + var keyHash = Utils.ComputeSHA1(key); + var keyFingerprint = new TLLong(BitConverter.ToInt64(keyHash, 12)); + var decryptedBytes = decryptedMessage.ToBytes(); + var bytes = Combine(BitConverter.GetBytes(decryptedBytes.Length), decryptedBytes); + var sha1Hash = Utils.ComputeSHA1(bytes); + var msgKey = sha1Hash.SubArray(sha1Hash.Length - 16, 16); + + var padding = (bytes.Length % 16 == 0) ? 0 : (16 - (bytes.Length % 16)); + var paddingBytes = new byte[padding]; + random.NextBytes(paddingBytes); + var bytesWithPadding = Combine(bytes, paddingBytes); + + var x = 0; + var sha1_a = Utils.ComputeSHA1(Combine(msgKey, key.SubArray(x, 32))); + var sha1_b = Utils.ComputeSHA1(Combine(key.SubArray(32 + x, 16), msgKey, key.SubArray(48 + x, 16))); + var sha1_c = Utils.ComputeSHA1(Combine(key.SubArray(64 + x, 32), msgKey)); + var sha1_d = Utils.ComputeSHA1(Combine(msgKey, key.SubArray(96 + x, 32))); + var aesKey = Combine(sha1_a.SubArray(0, 8), sha1_b.SubArray(8, 12), sha1_c.SubArray(4, 12)); + var aesIV = Combine(sha1_a.SubArray(8, 12), sha1_b.SubArray(0, 8), sha1_c.SubArray(16, 4), sha1_d.SubArray(0, 8)); + + var encryptedBytes = Utils.AesIge(bytesWithPadding, aesKey, aesIV, true); + + var resultBytes = Combine(keyFingerprint.ToBytes(), msgKey, encryptedBytes); + + return TLString.FromBigEndianData(resultBytes); + } + + public static TLDecryptedMessageBase DecryptMessage(TLString data, TLInt currentUserId, TLEncryptedChat chat, out bool commitChat) + { + Debug.WriteLine("TLUtils.DecryptMessage"); + + commitChat = false; + + var bytes = data.Data; + + var keyFingerprint = BitConverter.ToInt64(bytes, 0); + var msgKey = bytes.SubArray(8, 16); + var key = chat.Key.Data; + var keyHash = Utils.ComputeSHA1(key); + var calculatedKeyFingerprint = BitConverter.ToInt64(keyHash, keyHash.Length - 8); + + if (keyFingerprint != calculatedKeyFingerprint) + { + var chat20 = chat as TLEncryptedChat20; + if (chat20 != null && chat20.PFS_Key != null) + { + var pfsKeyHash = Utils.ComputeSHA1(chat20.PFS_Key.Data); + var pfsKeyFingerprint = BitConverter.ToInt64(pfsKeyHash, pfsKeyHash.Length - 8); + if (pfsKeyFingerprint == keyFingerprint) + { + chat20.Key = chat20.PFS_Key; + chat20.PFS_Key = null; + chat20.PFS_KeyFingerprint = null; + chat20.PFS_A = null; + chat20.PFS_ExchangeId = null; + commitChat = true; + } + else + { + return null; + } + } + else + { + return null; + } + } + + var x = 0; + var sha1_a = Utils.ComputeSHA1(Combine(msgKey, key.SubArray(x, 32))); + var sha1_b = Utils.ComputeSHA1(Combine(key.SubArray(32 + x, 16), msgKey, key.SubArray(48 + x, 16))); + var sha1_c = Utils.ComputeSHA1(Combine(key.SubArray(64 + x, 32), msgKey)); + var sha1_d = Utils.ComputeSHA1(Combine(msgKey, key.SubArray(96 + x, 32))); + + var aesKey = Combine(sha1_a.SubArray(0, 8), sha1_b.SubArray(8, 12), sha1_c.SubArray(4, 12)); + var aesIV = Combine(sha1_a.SubArray(8, 12), sha1_b.SubArray(0, 8), sha1_c.SubArray(16, 4), sha1_d.SubArray(0, 8)); + + var encryptedBytes = bytes.SubArray(24, bytes.Length - 24); + var decryptedBytes = Utils.AesIge(encryptedBytes, aesKey, aesIV, false); + + var msgKeyEquals = true; + var length = BitConverter.ToInt32(decryptedBytes, 0); + if (length <= 0 || 4 + length > decryptedBytes.Length) + { + Log.Write("TLUtils.DecryptMessage length <= 0 || (4 + length) > decryptedBytes.Length"); + msgKeyEquals = false; + } + var calculatedMsgKey = msgKeyEquals ? Utils.ComputeSHA1(decryptedBytes.SubArray(0, 4 + length)) : new byte[] { }; + for (var i = 0; i < 16; i++) + { + if (msgKeyEquals && msgKey[i] != calculatedMsgKey[i + 4]) + { + msgKeyEquals = false; + } + } + if (!msgKeyEquals) + { + Log.Write("TLUtils.DecryptMessage msgKey != calculatedMsgKey"); + + var result = DecryptMessage2(data, currentUserId, chat, out commitChat); + return result; + } + + var position = 4; + var decryptedObject = TLObject.GetObject(decryptedBytes, ref position); + var decryptedMessageLayer = decryptedObject as TLDecryptedMessageLayer; + var decryptedMessageLayer17 = decryptedObject as TLDecryptedMessageLayer17; + TLDecryptedMessageBase decryptedMessage = null; + + if (decryptedMessageLayer17 != null) + { + var randomBytes = decryptedMessageLayer17.RandomBytes.Data; + if (randomBytes == null || randomBytes.Length < Constants.MinRandomBytesLength) + { + Log.Write("TLUtils.DecryptMessage randomBytes.Length<" + Constants.MinRandomBytesLength); + return null; + } + + decryptedMessage = decryptedMessageLayer17.Message; + var decryptedMessage17 = decryptedMessage as ISeqNo; + if (decryptedMessage17 != null) + { + decryptedMessage17.InSeqNo = decryptedMessageLayer17.InSeqNo; + decryptedMessage17.OutSeqNo = decryptedMessageLayer17.OutSeqNo; + } + } + else if (decryptedMessageLayer != null) + { + decryptedMessage = decryptedMessageLayer.Message; + } + else if (decryptedObject is TLDecryptedMessageBase) + { + decryptedMessage = (TLDecryptedMessageBase)decryptedObject; + } + + return decryptedMessage; + } + + public static T OpenObjectFromFile(object syncRoot, string fileName) + where T : class + { + try + { + Debug.WriteLine("::OpenFile " + fileName); + + lock (syncRoot) + { + using (var fileStream = FileUtils.GetLocalFileStreamForRead(fileName)) + { + if (fileStream.Length > 0) + { + var serializer = new DataContractSerializer(typeof(T)); + return serializer.ReadObject(fileStream) as T; + } + } + } + } + catch (Exception e) + { + var caption = String.Format("MTPROTO FILE ERROR: cannot read {0} from file {1}", typeof(T), fileName); + WriteLine(caption, LogSeverity.Error); + WriteException(caption, e); + } + return default(T); + } + + + public static T OpenObjectFromMTProtoFile(object syncRoot, string fileName, out long length) + where T : TLObject + { + length = 0; + + try + { + + Debug.WriteLine("::OpenMTProtoFile " + fileName); + + lock (syncRoot) + { + using (var fileStream = FileUtils.GetLocalFileStreamForRead(fileName)) + { + if (fileStream.Length > 0) + { + length = fileStream.Length; + return TLObject.GetObject(fileStream); + } + } + } + } + catch (Exception e) + { + var caption = String.Format("MTPROTO FILE ERROR: cannot read {0} from file {1}", typeof(T), fileName); + WriteLine(caption, LogSeverity.Error); + WriteException(caption, e); + } + return default(T); + } + + public static T OpenObjectFromMTProtoFile(object syncRoot, string fileName) + where T : TLObject + { + try + { + Debug.WriteLine("::OpenMTProtoFile " + fileName); + + lock (syncRoot) + { + using (var fileStream = FileUtils.GetLocalFileStreamForRead(fileName)) + { + if (fileStream.Length > 0) + { + return TLObject.GetObject(fileStream); + } + } + } + } + catch (Exception e) + { + var caption = String.Format("MTPROTO FILE ERROR: cannot read {0} from file {1}", typeof(T), fileName); + WriteLine(caption, LogSeverity.Error); + WriteException(caption, e); + } + return default(T); + } + + public static void SaveObjectToFile(object syncRoot, string fileName, T data) + { + try + { + lock (syncRoot) + { + using (var fileStream = FileUtils.GetLocalFileStreamForWrite(fileName)) + { + var dcs = new DataContractSerializer(typeof(T)); + dcs.WriteObject(fileStream, data); + } + } + } + catch (Exception e) + { + var caption = String.Format("FILE ERROR: cannot write {0} to file {1}", typeof(T), fileName); + WriteLine(caption, LogSeverity.Error); + WriteException(caption, e); + } + } + + public static void SaveObjectToMTProtoFile(object syncRoot, string fileName, T data) + where T : TLObject + { + try + { + lock (syncRoot) + { + FileUtils.SaveWithTempFile(fileName, data); + } + } + catch (Exception e) + { + var caption = String.Format("MTPROTO FILE ERROR: cannot write {0} to file {1}", typeof(T), fileName); + WriteLine(caption, LogSeverity.Error); + WriteException(caption, e); + } + } + + public static TLPeerBase GetPeerFromMessage(TLDecryptedMessageBase message) + { + TLPeerBase peer = null; + var commonMessage = message; + if (commonMessage != null) + { + if (commonMessage.ChatId != null) + { + peer = new TLPeerEncryptedChat { Id = commonMessage.ChatId }; + } + } + else + { + WriteLine("Cannot get peer from non TLDecryptedMessage", LogSeverity.Error); + } + + return peer; + } + + public static TLPeerBase GetPeerFromMessage(TLMessageBase message) + { + TLPeerBase peer = null; + var commonMessage = message as TLMessageCommon; + if (commonMessage != null) + { + if (commonMessage.ToId is TLPeerChannel) + { + peer = commonMessage.ToId; + } + else if (commonMessage.ToId is TLPeerChat) + { + peer = commonMessage.ToId; + } + else + { + if (commonMessage.Out.Value) + { + peer = commonMessage.ToId; + } + else + { + peer = new TLPeerUser { Id = commonMessage.FromId }; + } + } + } + else + { + WriteLine("Cannot get peer from non TLMessageCommon", LogSeverity.Error); + } + + return peer; + } + + public static bool IsChannelMessage(TLMessageBase message, out TLPeerChannel channel) + { + var isChannel = false; + channel = null; + + var messageCommon = message as TLMessageCommon; + if (messageCommon != null) + { + channel = messageCommon.ToId as TLPeerChannel; + isChannel = channel != null; + } + + return isChannel; + } + + public static bool InsertItem(IList items, T item, Func getField, Func equalitysField = null) + where T : TLObject + { + var fieldValue = getField(item); + for (var i = 0; i < items.Count; i++) + { + if (getField(items[i]) > fieldValue) + { + items.Insert(i, item); + return true; + } + if (getField(items[i]) == fieldValue + && equalitysField != null + && equalitysField(items[i]) == equalitysField(item)) + { + return false; + } + } + + items.Add(item); + return true; + } + + public static bool InsertItemByDesc(IList items, T item, Func getField, Func equalityField = null) + where T : TLObject + { + var fieldValue = getField(item); + for (var i = 0; i < items.Count; i++) + { + if (getField(items[i]) < fieldValue) + { + items.Insert(i, item); + return true; + } + if (getField(items[i]) == fieldValue + && equalityField != null + && equalityField(items[i]) == equalityField(item)) + { + return false; + } + } + + items.Add(item); + return true; + } + + public static IEnumerable FindInnerObjects(TLTransportMessage obj) + where T : TLObject + { + var result = obj.MessageData as T; + if (result != null) + { + yield return (T)obj.MessageData; + } + else + { + var gzipData = obj.MessageData as TLGzipPacked; + if (gzipData != null) + { + result = gzipData.Data as T; + if (result != null) + { + yield return result; + } + } + + var container = obj.MessageData as TLContainer; + if (container != null) + { + foreach (var message in container.Messages) + { + result = message.MessageData as T; + if (result != null) + { + yield return (T)message.MessageData; + } + gzipData = message.MessageData as TLGzipPacked; + if (gzipData != null) + { + result = gzipData.Data as T; + if (result != null) + { + yield return result; + } + } + } + } + } + } + + public static int InputPeerToId(TLInputPeerBase inputPeer, TLInt selfId) + { + var chat = inputPeer as TLInputPeerChat; + if (chat != null) + { + return chat.ChatId.Value; + } + + var contact = inputPeer as TLInputPeerContact; + if (contact != null) + { + return contact.UserId.Value; + } + + var foreign = inputPeer as TLInputPeerForeign; + if (foreign != null) + { + return foreign.UserId.Value; + } + + var user = inputPeer as TLInputPeerUser; + if (user != null) + { + return user.UserId.Value; + } + + var self = inputPeer as TLInputPeerSelf; + if (self != null) + { + return selfId.Value; + } + + return -1; + } + + public static TLPeerBase InputPeerToPeer(TLInputPeerBase inputPeer, int selfId) + { + var channel = inputPeer as TLInputPeerChannel; + if (channel != null) + { + return new TLPeerChannel { Id = channel.ChatId }; + } + + var broadcast = inputPeer as TLInputPeerBroadcast; + if (broadcast != null) + { + return new TLPeerBroadcast { Id = broadcast.ChatId }; + } + + var chat = inputPeer as TLInputPeerChat; + if (chat != null) + { + return new TLPeerChat { Id = chat.ChatId }; + } + + var contact = inputPeer as TLInputPeerContact; + if (contact != null) + { + return new TLPeerUser { Id = contact.UserId }; + } + + var foreign = inputPeer as TLInputPeerForeign; + if (foreign != null) + { + return new TLPeerUser { Id = foreign.UserId }; + } + + var user = inputPeer as TLInputPeerUser; + if (user != null) + { + return new TLPeerUser { Id = user.UserId }; + } + + var self = inputPeer as TLInputPeerSelf; + if (self != null) + { + return new TLPeerUser { Id = new TLInt(selfId) }; + } + + return null; + } + + + public static int MergeItemsDesc(Func dateIndexFunc, IList current, IList updated, int offset, int maxId, int count, out IList removedItems, Func indexFunc, Func skipTailFunc) + { + removedItems = new List(); + + var currentIndex = 0; + var updatedIndex = 0; + + var index = new Dictionary(); + foreach (var item in current) + { + var id = indexFunc(item); + if (id > 0) + { + index[id] = id; + } + } + + + //skip just added or sending items + while (updatedIndex < updated.Count + && currentIndex < current.Count + && dateIndexFunc(updated[updatedIndex]) < dateIndexFunc(current[currentIndex])) + { + currentIndex++; + } + + // insert before current items + while (updatedIndex < updated.Count + && (current.Count < currentIndex + || (currentIndex < current.Count && dateIndexFunc(updated[updatedIndex]) > dateIndexFunc(current[currentIndex])))) + { + if (dateIndexFunc(current[currentIndex]) == 0) + { + currentIndex++; + continue; + } + if (index.ContainsKey(indexFunc(updated[updatedIndex]))) + { + updatedIndex++; + continue; + } + current.Insert(currentIndex, updated[updatedIndex]); + updatedIndex++; + currentIndex++; + } + + // update existing items + if (updatedIndex < updated.Count) + { + for (; currentIndex < current.Count; currentIndex++) + { + if (indexFunc != null + && indexFunc(current[currentIndex]) == 0) + { + continue; + } + + for (; updatedIndex < updated.Count; updatedIndex++) + { + // missing item at current list + if (dateIndexFunc(updated[updatedIndex]) > dateIndexFunc(current[currentIndex])) + { + current.Insert(currentIndex, updated[updatedIndex]); + updatedIndex++; + break; + } + // equal item + if (dateIndexFunc(updated[updatedIndex]) == dateIndexFunc(current[currentIndex])) + { + updatedIndex++; + break; + } + // deleted item + if (dateIndexFunc(updated[updatedIndex]) < dateIndexFunc(current[currentIndex])) + { + var removedItem = current[currentIndex]; + removedItems.Add(removedItem); + current.RemoveAt(currentIndex); + currentIndex--; + break; + } + } + + // at the end of updated list + if (updatedIndex == updated.Count) + { + currentIndex++; + break; + } + } + } + + + // all other items were deleted + if (updated.Count > 0 && updated.Count < count && current.Count != currentIndex) + { + for (var i = current.Count - 1; i >= updatedIndex; i--) + { + if (skipTailFunc != null && skipTailFunc(current[i])) + { + continue; + } + current.RemoveAt(i); + } + return currentIndex - 1; + } + + // add after current items + while (updatedIndex < updated.Count) + { + current.Add(updated[updatedIndex]); + updatedIndex++; + currentIndex++; + } + + return currentIndex - 1; + } + + public static TLInt DateToUniversalTimeTLInt(long clientDelta, DateTime date) + { + clientDelta = MTProtoService.Instance.ClientTicksDelta; + + var unixTime = (int)Utils.DateTimeToUnixTimestamp(date) + clientDelta / 4294967296.0; //int * 2^32 + clientDelta + + return new TLInt((int)unixTime); + } + + public static TLInt ToTLInt(DateTime date) + { + var unixTime = (int)Utils.DateTimeToUnixTimestamp(date); //int * 2^32 + clientDelta + + return new TLInt(unixTime); + } + + public static byte[] GenerateAuthKeyId(byte[] authKey) + { + var authKeyHash = Utils.ComputeSHA1(authKey); + var authKeyId = authKeyHash.SubArray(12, 8); + + return authKeyId; + } + + public static long GenerateLongAuthKeyId(byte[] authKey) + { + var authKeyHash = Utils.ComputeSHA1(authKey); + var authKeyId = authKeyHash.SubArray(12, 8); + + return BitConverter.ToInt64(authKeyId, 0); + } + + private const int encryptXParam = 0; + private const int decryptXParam = 8; + + public static WindowsPhone.Tuple GetEncryptKeyIV(byte[] authKey, byte[] msgKey) + { + return GetKeyIVCommon(authKey, msgKey, encryptXParam); + } + + public static WindowsPhone.Tuple GetDecryptKeyIV(byte[] authKey, byte[] msgKey) + { + return GetKeyIVCommon(authKey, msgKey, decryptXParam); + } + + private static WindowsPhone.Tuple GetKeyIVCommon(byte[] authKey, byte[] msgKey, int x) + { +#if MTPROTO + var sha256_a = Utils.ComputeSHA256(Combine(msgKey, authKey.SubArray(x, 36))); + var sha256_b = Utils.ComputeSHA256(Combine(authKey.SubArray(40 + x, 36), msgKey)); + + var aesKey = Combine( + sha256_a.SubArray(0, 8), + sha256_b.SubArray(8, 16), + sha256_a.SubArray(24, 8)); + + var aesIV = Combine( + sha256_b.SubArray(0, 8), + sha256_a.SubArray(8, 16), + sha256_b.SubArray(24, 8)); +#else + var sha1_a = Utils.ComputeSHA1(Combine(msgKey, authKey.SubArray(x, 32))); + var sha1_b = Utils.ComputeSHA1(Combine(authKey.SubArray(32 + x, 16), msgKey, authKey.SubArray(48 + x, 16))); + var sha1_c = Utils.ComputeSHA1(Combine(authKey.SubArray(64 + x, 32), msgKey)); + var sha1_d = Utils.ComputeSHA1(Combine(msgKey, authKey.SubArray(96 + x, 32))); + + var aesKey = Combine( + sha1_a.SubArray(0, 8), + sha1_b.SubArray(8, 12), + sha1_c.SubArray(4, 12)); + + var aesIV = Combine( + sha1_a.SubArray(8, 12), + sha1_b.SubArray(0, 8), + sha1_c.SubArray(16, 4), + sha1_d.SubArray(0, 8)); +#endif + + return new WindowsPhone.Tuple(aesKey, aesIV); + } + +#if MTPROTO + public static byte[] GetEncryptMsgKey(byte[] authKey, byte[] dataWithPadding) + { + return GetMsgKeyCommon(authKey, dataWithPadding, encryptXParam); + } + + public static byte[] GetDecryptMsgKey(byte[] authKey, byte[] dataWithPadding) + { + return GetMsgKeyCommon(authKey, dataWithPadding, decryptXParam); + } + + private static byte[] GetMsgKeyCommon(byte[] authKey, byte[] dataWithPadding, int x) + { + var bytes = Combine(authKey.SubArray(88 + x, 32), dataWithPadding); + + var msgKeyLarge = Utils.ComputeSHA256(bytes); + var msgKey = msgKeyLarge.SubArray(8, 16); + + return msgKey; + } +#else + public static byte[] GetMsgKey(byte[] data) + { + var bytes = Utils.ComputeSHA1(data); + var last16Bytes = bytes.SubArray(4, 16); + + return last16Bytes; + } +#endif + + public static byte[] Combine(params byte[][] arrays) + { + var length = 0; + for (var i = 0; i < arrays.Length; i++) + { + length += arrays[i].Length; + } + + var result = new byte[length]; ////[arrays.Sum(a => a.Length)]; + var offset = 0; + foreach (var array in arrays) + { + Buffer.BlockCopy(array, 0, result, offset, array.Length); + offset += array.Length; + } + return result; + } + + public static string MessageIdString(byte[] bytes) + { + var ticks = BitConverter.ToInt64(bytes, 0); + var date = Utils.UnixTimestampToDateTime(ticks >> 32); + + return BitConverter.ToString(bytes) + " " + + ticks + "%4=" + ticks % 4 + " " + + date; + } + + public static string MessageIdString(TLLong messageId) + { + var bytes = BitConverter.GetBytes(messageId.Value); + var ticks = BitConverter.ToInt64(bytes, 0); + var date = Utils.UnixTimestampToDateTime(ticks >> 32); + + return BitConverter.ToString(bytes) + " " + + ticks + "%4=" + ticks % 4 + " " + + date; + } + + public static string MessageIdString(TLInt messageId) + { + var ticks = messageId.Value; + var date = Utils.UnixTimestampToDateTime(ticks >> 32); + + return BitConverter.ToString(BitConverter.GetBytes(messageId.Value)) + " " + + ticks + "%4=" + ticks % 4 + " " + + date; + } + + public static DateTime ToDateTime(TLInt date) + { + var ticks = date.Value; + return Utils.UnixTimestampToDateTime(ticks >> 32); + } + + public static void ThrowNotSupportedException(this byte[] bytes, string objectType) + { + throw new NotSupportedException(String.Format("Not supported {0} signature: {1}", objectType, BitConverter.ToString(bytes.SubArray(0, 4)))); + } + + public static void ThrowNotSupportedException(this byte[] bytes, int position, string objectType) + { + throw new NotSupportedException(String.Format("Not supported {0} signature: {1}", objectType, BitConverter.ToString(bytes.SubArray(position, position + 4)))); + } + + public static void ThrowExceptionIfIncorrect(this byte[] bytes, ref int position, uint signature) + { + //if (!bytes.SubArray(position, 4).StartsWith(signature)) + //{ + // throw new ArgumentException(String.Format("Incorrect signature: actual - {1}, expected - {0}", SignatureToBytesString(signature), BitConverter.ToString(bytes.SubArray(0, 4)))); + //} + position += 4; + } + + public static void ThrowExceptionIfIncorrect(this byte[] bytes, ref int position, string signature) + { + //if (!bytes.SubArray(position, 4).StartsWith(signature)) + //{ + // throw new ArgumentException(String.Format("Incorrect signature: actual - {1}, expected - {0}", SignatureToBytesString(signature), BitConverter.ToString(bytes.SubArray(0, 4)))); + //} + position += 4; + } + + private static bool StartsWith(this byte[] array, byte[] startArray) + { + for (var i = 0; i < startArray.Length; i++) + { + if (array[i] != startArray[i]) return false; + } + return true; + } + + private static bool StartsWith(this byte[] array, int position, byte[] startArray) + { + for (var i = 0; i < startArray.Length; i++) + { + if (array[position + i] != startArray[i]) return false; + } + return true; + } + + public static bool StartsWith(this byte[] bytes, uint signature) + { + var sign = BitConverter.ToUInt32(bytes, 0); + + return sign == signature; + } + + public static bool StartsWith(this Stream input, uint signature) + { + var bytes = new byte[4]; + input.Read(bytes, 0, 4); + var sign = BitConverter.ToUInt32(bytes, 0); + + return sign == signature; + } + + public static bool StartsWith(this byte[] bytes, string signature) + { + if (signature[0] != '#') throw new ArgumentException("Incorrect first symbol of signature: expexted - #, actual - " + signature[0]); + + var signatureBytes = SignatureToBytes(signature); + + return bytes.StartsWith(signatureBytes); + } + + public static bool StartsWith(this byte[] bytes, int position, uint signature) + { + var sign = BitConverter.ToUInt32(bytes, position); + + return sign == signature; + } + + public static bool StartsWith(this byte[] bytes, int position, string signature) + { + if (signature[0] != '#') throw new ArgumentException("Incorrect first symbol of signature: expexted - #, actual - " + signature[0]); + + var signatureBytes = SignatureToBytes(signature); + + return bytes.StartsWith(position, signatureBytes); + } + + public static string SignatureToBytesString(string signature) + { + if (signature[0] != '#') throw new ArgumentException("Incorrect first symbol of signature: expexted - #, actual - " + signature[0]); + + return BitConverter.ToString(SignatureToBytes(signature)); + } + + public static byte[] SignatureToBytes(uint signature) + { + return BitConverter.GetBytes(signature); + } + + public static byte[] SignatureToBytes(string signature) + { + if (signature[0] != '#') throw new ArgumentException("Incorrect first symbol of signature: expexted - #, actual - " + signature[0]); + + var bytesString = + signature.Length % 2 == 0 ? + new string(signature.Replace("#", "0").ToArray()) : + new string(signature.Replace("#", String.Empty).ToArray()); + + var bytes = Utils.StringToByteArray(bytesString); + Array.Reverse(bytes); + return bytes; + } + + + public static TLDecryptedMessageLayer GetDecryptedMessageLayer(TLInt layer, TLInt inSeqNo, TLInt outSeqNo, TLDecryptedMessageBase message) + { + var randomBytes = new byte[15]; + var random = new SecureRandom(); + random.NextBytes(randomBytes); + + var decryptedMessageLayer17 = new TLDecryptedMessageLayer17(); + decryptedMessageLayer17.Layer = layer; + decryptedMessageLayer17.InSeqNo = inSeqNo; + decryptedMessageLayer17.OutSeqNo = outSeqNo; + decryptedMessageLayer17.RandomBytes = TLString.FromBigEndianData(randomBytes); + decryptedMessageLayer17.Message = message; + + return decryptedMessageLayer17; + } + + } +} + diff --git a/Telegram.Api/TL/TLValidatedRequestedInfo.cs b/Telegram.Api/TL/TLValidatedRequestedInfo.cs new file mode 100755 index 0000000..dba7279 --- /dev/null +++ b/Telegram.Api/TL/TLValidatedRequestedInfo.cs @@ -0,0 +1,58 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.TL +{ + [Flags] + public enum ValidatedRequestedInfoFlags + { + Id = 0x1, // 0 + ShippingOptions = 0x2, // 1 + } + + public class TLValidatedRequestedInfo : TLObject + { + public const uint Signature = TLConstructors.TLValidatedRequestedInfo; + + private TLInt _flags; + + public TLInt Flags + { + get { return _flags; } + set { _flags = value; } + } + + private TLString _id; + + public TLString Id + { + get { return _id; } + set { SetField(out _id, value, ref _flags, (int) ValidatedRequestedInfoFlags.Id); } + } + + private TLVector _shippingOptions; + + public TLVector ShippingOptions + { + get { return _shippingOptions; } + set { SetField(out _shippingOptions, value, ref _flags, (int) ValidatedRequestedInfoFlags.ShippingOptions); } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Flags = GetObject(bytes, ref position); + _id = GetObject(Flags, (int) ValidatedRequestedInfoFlags.Id, null, bytes, ref position); + _shippingOptions = GetObject>(Flags, (int)ValidatedRequestedInfoFlags.ShippingOptions, null, bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLVector.cs b/Telegram.Api/TL/TLVector.cs new file mode 100755 index 0000000..cfde116 --- /dev/null +++ b/Telegram.Api/TL/TLVector.cs @@ -0,0 +1,166 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + [DataContract] + public class TLVector : TLObject, IList + where T : TLObject + { + public const uint Signature = TLConstructors.TLVector; + + [DataMember] + public IList Items { get; set; } + + public TLVector() + { + Items = new List(); + } + + public TLVector(int count) + { + Items = new List(count); + } + + public TLVector(IList items) + { + Items = items; + } + + public T this[int index] + { + get { return Items[index]; } + set { Items[index] = value; } + } + + public int IndexOf(T item) + { + return Items.IndexOf(item); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + var length = GetObject(bytes, ref position); + Items = new List(length.Value); + + for (var i = 0; i < length.Value; i++) + { + Items.Add(GetObject(bytes, ref position)); + } + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + BitConverter.GetBytes(Items.Count), + TLUtils.Combine(Items.Select(x => x.ToBytes()).ToArray()) + ); + } + + public override TLObject FromStream(Stream input) + { + var length = GetObject(input); + Items = new List(length.Value); + + try + { + for (var i = 0; i < length.Value; i++) + { + Items.Add(GetObject(input)); + } + } + catch (Exception ex) + { + + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + output.Write(new TLInt(Items.Count).ToBytes()); + for (var i = 0; i < Items.Count; i++) + { + Items[i].ToStream(output); + } + } + + public IEnumerator GetEnumerator() + { + return Items.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(T item) + { + Items.Add(item); + } + + public void Clear() + { + Items.Clear(); + } + + public bool Contains(T item) + { + return Items.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + Items.CopyTo(array, arrayIndex); + } + + public bool Remove(T item) + { + return Items.Remove(item); + } + + public void RemoveAt(int index) + { + Items.RemoveAt(index); + } + + public void Insert(int index, T item) + { + Items.Insert(index, item); + } + + public int Count { get { return Items.Count; } } + public bool IsReadOnly { get { return Items.IsReadOnly; } } + + public int IndexOf(TLDCOption dcOption) + { + for (var i = 0; i < Items.Count; i++) + { + if (Items[i] == dcOption) + return i; + } + + return -1; + } + } +} diff --git a/Telegram.Api/TL/TLVideo.cs b/Telegram.Api/TL/TLVideo.cs new file mode 100755 index 0000000..8557b7e --- /dev/null +++ b/Telegram.Api/TL/TLVideo.cs @@ -0,0 +1,322 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLVideoBase : TLObject + { + public TLLong Id { get; set; } + + public virtual int VideoSize { get { return 0; } } + } + + public class TLVideoEmpty : TLVideoBase + { + public const uint Signature = TLConstructors.TLVideoEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine(TLUtils.SignatureToBytes(Signature), Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + } + } + + public class TLVideo33 : TLVideo28 + { + public new const uint Signature = TLConstructors.TLVideo33; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + //UserId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Duration = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Thumb = GetObject(bytes, ref position); + DCId = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + //UserId.ToBytes(), + Date.ToBytes(), + Duration.ToBytes(), + MimeType.ToBytes(), + Size.ToBytes(), + Thumb.ToBytes(), + DCId.ToBytes(), + W.ToBytes(), + H.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + //UserId = GetObject(input); + Date = GetObject(input); + Duration = GetObject(input); + MimeType = GetObject(input); + Size = GetObject(input); + Thumb = GetObject(input); + DCId = GetObject(input); + W = GetObject(input); + H = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + AccessHash.ToStream(output); + //UserId.ToStream(output); + Date.ToStream(output); + Duration.ToStream(output); + MimeType.ToStream(output); + Size.ToStream(output); + Thumb.ToStream(output); + DCId.ToStream(output); + W.ToStream(output); + H.ToStream(output); + } + } + + public class TLVideo28 : TLVideo + { + public new const uint Signature = TLConstructors.TLVideo28; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Duration = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Thumb = GetObject(bytes, ref position); + DCId = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + UserId.ToBytes(), + Date.ToBytes(), + Duration.ToBytes(), + Size.ToBytes(), + Thumb.ToBytes(), + DCId.ToBytes(), + W.ToBytes(), + H.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + UserId = GetObject(input); + Date = GetObject(input); + Duration = GetObject(input); + Size = GetObject(input); + Thumb = GetObject(input); + DCId = GetObject(input); + W = GetObject(input); + H = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + AccessHash.ToStream(output); + UserId.ToStream(output); + Date.ToStream(output); + Duration.ToStream(output); + Size.ToStream(output); + Thumb.ToStream(output); + DCId.ToStream(output); + W.ToStream(output); + H.ToStream(output); + } + } + + public class TLVideo : TLVideoBase + { + public const uint Signature = TLConstructors.TLVideo; + + public TLLong AccessHash { get; set; } + public TLInt UserId { get; set; } + public TLInt Date { get; set; } + public TLString Caption { get; set; } + public TLInt Duration { get; set; } + public TLString MimeType { get; set; } + public TLInt Size { get; set; } + public TLPhotoSizeBase Thumb { get; set; } + public TLInt DCId { get; set; } + public TLInt W { get; set; } + public TLInt H { get; set; } + + public string GetFileName() + { + return string.Format("video{0}_{1}.mp4", Id, AccessHash); + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + UserId = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + Caption = GetObject(bytes, ref position); + Duration = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + Thumb = GetObject(bytes, ref position); + DCId = GetObject(bytes, ref position); + W = GetObject(bytes, ref position); + H = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + AccessHash.ToBytes(), + UserId.ToBytes(), + Date.ToBytes(), + Caption.ToBytes(), + Duration.ToBytes(), + MimeType.ToBytes(), + Size.ToBytes(), + Thumb.ToBytes(), + DCId.ToBytes(), + W.ToBytes(), + H.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + AccessHash = GetObject(input); + UserId = GetObject(input); + Date = GetObject(input); + Caption = GetObject(input); + Duration = GetObject(input); + MimeType = GetObject(input); + Size = GetObject(input); + Thumb = GetObject(input); + DCId = GetObject(input); + W = GetObject(input); + H = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + AccessHash.ToStream(output); + UserId.ToStream(output); + Date.ToStream(output); + Caption.ToStream(output); + Duration.ToStream(output); + MimeType.ToStream(output); + Size.ToStream(output); + Thumb.ToStream(output); + DCId.ToStream(output); + W.ToStream(output); + H.ToStream(output); + } + + #region Additional + + public override int VideoSize + { + get { return Size != null ? Size.Value : 0; } + } + + public string DurationString + { + get + { + var timeSpan = TimeSpan.FromSeconds(Duration.Value); + + if (timeSpan.Hours > 0) + { + return timeSpan.ToString(@"h\:mm\:ss"); + } + + return timeSpan.ToString(@"m\:ss"); + } + } + + public TLInputFile ThumbInputFile { get; set; } + + #endregion + + public TLInputVideoFileLocation ToInputFileLocation() + { + return new TLInputVideoFileLocation {AccessHash = AccessHash, Id = Id}; + } + } +} diff --git a/Telegram.Api/TL/TLWallpaperSolid.cs b/Telegram.Api/TL/TLWallpaperSolid.cs new file mode 100755 index 0000000..4112251 --- /dev/null +++ b/Telegram.Api/TL/TLWallpaperSolid.cs @@ -0,0 +1,105 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.IO; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLWallPaperBase : TLObject + { + public TLInt Id { get; set; } + + public TLString Title { get; set; } + + public TLInt Color { get; set; } + + public TLLong CustomFlags { get; set; } + } + + public class TLWallPaper : TLWallPaperBase + { + public const uint Signature = TLConstructors.TLWallPaper; + + public TLVector Sizes { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + Sizes = GetObject>(bytes, ref position); + Color = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Title = GetObject(input); + Sizes = GetObject>(input); + Color = GetObject(input); + CustomFlags = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + Title.ToStream(output); + Sizes.ToStream(output); + Color.ToStream(output); + + CustomFlags.NullableToStream(output); + } + } + + public class TLWallPaperSolid : TLWallPaperBase + { + public const uint Signature = TLConstructors.TLWallPaperSolid; + + public TLInt BgColor { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Title = GetObject(bytes, ref position); + BgColor = GetObject(bytes, ref position); + Color = GetObject(bytes, ref position); + + return this; + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Title = GetObject(input); + BgColor = GetObject(input); + Color = GetObject(input); + CustomFlags = GetNullableObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + Title.ToStream(output); + BgColor.ToStream(output); + Color.ToStream(output); + + CustomFlags.NullableToStream(output); + } + } +} diff --git a/Telegram.Api/TL/TLWebDocument.cs b/Telegram.Api/TL/TLWebDocument.cs new file mode 100755 index 0000000..2d394a1 --- /dev/null +++ b/Telegram.Api/TL/TLWebDocument.cs @@ -0,0 +1,233 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using System.Linq; +using Telegram.Api.Extensions; + +namespace Telegram.Api.TL +{ + public abstract class TLWebDocumentBase : TLObject, IAttributes + { + public TLString Url { get; set; } + + public TLInt Size { get; set; } + + public TLString MimeType { get; set; } + + public TLVector Attributes { get; set; } + + public TLInt W + { + get + { + var attributeSize = Attributes.FirstOrDefault(x => x is IAttributeSize) as IAttributeSize; + if (attributeSize != null) + { + return attributeSize.W; + } + + return null; + } + } + + public TLInt H + { + get + { + var attributeSize = Attributes.FirstOrDefault(x => x is IAttributeSize) as IAttributeSize; + if (attributeSize != null) + { + return attributeSize.H; + } + + return null; + } + } + + public TLInt Duration + { + get + { + var attributeDuration = Attributes.FirstOrDefault(x => x is IAttributeDuration) as IAttributeDuration; + if (attributeDuration != null) + { + return attributeDuration.Duration; + } + + return null; + } + } + + public Uri Uri + { + get + { + if (TLString.IsNullOrEmpty(Url)) return null; + + return new Uri(Url.ToString(), UriKind.Absolute); + } + } + } + + public class TLWebDocument82 : TLWebDocumentBase + { + public const uint Signature = TLConstructors.TLWebDocument82; + + public TLLong AccessHash { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Attributes = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Url.ToBytes(), + AccessHash.ToBytes(), + Size.ToBytes(), + MimeType.ToBytes(), + Attributes.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + AccessHash = GetObject(input); + Size = GetObject(input); + MimeType = GetObject(input); + Attributes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Url.ToStream(output); + AccessHash.ToStream(output); + Size.ToStream(output); + MimeType.ToStream(output); + Attributes.ToStream(output); + } + } + + public class TLWebDocument : TLWebDocumentBase + { + public const uint Signature = TLConstructors.TLWebDocument; + + public TLLong AccessHash { get; set; } + + public TLInt DCId { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + AccessHash = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Attributes = GetObject>(bytes, ref position); + DCId = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Url.ToBytes(), + AccessHash.ToBytes(), + Size.ToBytes(), + MimeType.ToBytes(), + Attributes.ToBytes(), + DCId.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + AccessHash = GetObject(input); + Size = GetObject(input); + MimeType = GetObject(input); + Attributes = GetObject>(input); + DCId = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Url.ToStream(output); + AccessHash.ToStream(output); + Size.ToStream(output); + MimeType.ToStream(output); + Attributes.ToStream(output); + DCId.ToStream(output); + } + } + + public class TLWebDocumentNoProxy : TLWebDocumentBase + { + public const uint Signature = TLConstructors.TLWebDocumentNoProxy; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Url = GetObject(bytes, ref position); + Size = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Attributes = GetObject>(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Url.ToBytes(), + Size.ToBytes(), + MimeType.ToBytes(), + Attributes.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Url = GetObject(input); + Size = GetObject(input); + MimeType = GetObject(input); + Attributes = GetObject>(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Url.ToStream(output); + Size.ToStream(output); + MimeType.ToStream(output); + Attributes.ToStream(output); + } + } +} \ No newline at end of file diff --git a/Telegram.Api/TL/TLWebFile.cs b/Telegram.Api/TL/TLWebFile.cs new file mode 100755 index 0000000..51beeb7 --- /dev/null +++ b/Telegram.Api/TL/TLWebFile.cs @@ -0,0 +1,31 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.TL +{ + public class TLWebFile : TLFile + { + public new const uint Signature = TLConstructors.TLWebFile; + + public TLInt Size { get; set; } + + public TLString MimeType { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Size = GetObject(bytes, ref position); + MimeType = GetObject(bytes, ref position); + Type = GetObject(bytes, ref position); + MTime = GetObject(bytes, ref position); + Bytes = GetObject(bytes, ref position); + + return this; + } + } +} diff --git a/Telegram.Api/TL/TLWebPage.cs b/Telegram.Api/TL/TLWebPage.cs new file mode 100755 index 0000000..9d79573 --- /dev/null +++ b/Telegram.Api/TL/TLWebPage.cs @@ -0,0 +1,745 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +#if WINDOWS_PHONE +using System.Net; +using System.Windows; +#elif WIN_RT +using Windows.UI.Xaml; +#endif +using Telegram.Api.Extensions; +using Telegram.Api.TL; + +namespace Telegram.Api +{ + [Flags] + public enum WebPageFlags + { + Type = 0x1, + SiteName = 0x2, + Title = 0x4, + Description = 0x8, + Photo = 0x10, + Embed = 0x20, + EmbedSize = 0x40, + Duration = 0x80, + Author = 0x100, + Document = 0x200, + CachedPage = 0x400, + } + + public abstract class TLWebPageBase : TLObject + { + public TLLong Id { get; set; } + + #region Additional + public abstract Visibility SiteNameVisibility { get; } + public abstract Visibility AuthorVisibility { get; } + public abstract Visibility TitleVisibility { get; } + public abstract Visibility DescriptionVisibility { get; } + #endregion + } + + public class TLWebPageEmpty : TLWebPageBase + { + public const uint Signature = TLConstructors.TLWebPageEmpty; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + } + + public override Visibility SiteNameVisibility + { + get { return Visibility.Collapsed; } + } + + public override Visibility AuthorVisibility + { + get { return Visibility.Collapsed; } + } + + public override Visibility TitleVisibility + { + get { return Visibility.Collapsed; } + } + + public override Visibility DescriptionVisibility + { + get { return Visibility.Collapsed; } + } + } + + public class TLWebPagePending : TLWebPageBase + { + public const uint Signature = TLConstructors.TLWebPagePending; + + public TLInt Date { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + Id = GetObject(bytes, ref position); + Date = GetObject(bytes, ref position); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Id.ToBytes(), + Date.ToBytes()); + } + + public override TLObject FromStream(Stream input) + { + Id = GetObject(input); + Date = GetObject(input); + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Id.ToStream(output); + Date.ToStream(output); + } + + public override Visibility SiteNameVisibility + { + get { return Visibility.Collapsed; } + } + + public override Visibility AuthorVisibility + { + get { return Visibility.Collapsed; } + } + + public override Visibility TitleVisibility + { + get { return Visibility.Collapsed; } + } + + public override Visibility DescriptionVisibility + { + get { return Visibility.Collapsed; } + } + } + + public class TLWebPage : TLWebPageBase + { + public const uint Signature = TLConstructors.TLWebPage; + + public TLInt Flags { get; set; } + + public TLString Url { get; set; } + + public TLString DisplayUrl { get; set; } + + public TLString Type { get; set; } + + public TLString SiteName { get; set; } + + public TLString Title { get; set; } + + public TLString Description { get; set; } + + public TLPhotoBase Photo { get; set; } + + public TLString EmbedUrl { get; set; } + + public TLString EmbedType { get; set; } + + public TLInt EmbedWidth { get; set; } + + public TLInt EmbedHeight { get; set; } + + public TLInt Duration { get; set; } + + public string DurationString + { + get + { + if (Duration == null) return null; + + var timeSpan = TimeSpan.FromSeconds(Duration.Value); + + if (timeSpan.Hours > 0) + { + return timeSpan.ToString(@"h\:mm\:ss"); + } + + return timeSpan.ToString(@"m\:ss"); + } + } + + public TLString Author { get; set; } + + + public override Visibility SiteNameVisibility + { + get { return TLString.IsNullOrEmpty(SiteName) ? Visibility.Collapsed : Visibility.Visible; } + } + + public override Visibility AuthorVisibility + { + get { return TLString.IsNullOrEmpty(Author) ? Visibility.Collapsed : Visibility.Visible; } + } + + public override Visibility TitleVisibility + { + get { return TLString.IsNullOrEmpty(Title)? Visibility.Collapsed : Visibility.Visible; } + } + + public override Visibility DescriptionVisibility + { + get { return TLString.IsNullOrEmpty(Description) ? Visibility.Collapsed : Visibility.Visible; } + } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + Url = GetObject(bytes, ref position); + DisplayUrl = GetObject(bytes, ref position); + if (IsSet(Flags, (int)WebPageFlags.Type)) + { + Type = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.SiteName)) + { + SiteName = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Title)) + { + Title = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Description)) + { + Description = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Photo)) + { + Photo = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Embed)) + { + EmbedUrl = GetObject(bytes, ref position); + EmbedType = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.EmbedSize)) + { + EmbedWidth = GetObject(bytes, ref position); + EmbedHeight = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Duration)) + { + Duration = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Author)) + { + Author = GetObject(bytes, ref position); + } + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + Url.ToBytes(), + DisplayUrl.ToBytes(), + ToBytes(Type, Flags, (int)WebPageFlags.Type), + ToBytes(SiteName, Flags, (int)WebPageFlags.SiteName), + ToBytes(Title, Flags, (int)WebPageFlags.Title), + ToBytes(Description, Flags, (int)WebPageFlags.Description), + ToBytes(Photo, Flags, (int)WebPageFlags.Photo), + ToBytes(EmbedUrl, Flags, (int)WebPageFlags.Embed), + ToBytes(EmbedType, Flags, (int)WebPageFlags.Embed), + ToBytes(EmbedWidth, Flags, (int)WebPageFlags.EmbedSize), + ToBytes(EmbedHeight, Flags, (int)WebPageFlags.EmbedSize), + ToBytes(Duration, Flags, (int)WebPageFlags.Duration), + ToBytes(Author, Flags, (int)WebPageFlags.Author)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Url = GetObject(input); + DisplayUrl = GetObject(input); + if (IsSet(Flags, (int)WebPageFlags.Type)) + { + Type = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.SiteName)) + { + SiteName = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Title)) + { + Title = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Description)) + { + Description = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Photo)) + { + Photo = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Embed)) + { + EmbedUrl = GetObject(input); + EmbedType = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.EmbedSize)) + { + EmbedWidth = GetObject(input); + EmbedHeight = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Duration)) + { + Duration = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Author)) + { + Author = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + Url.ToStream(output); + DisplayUrl.ToStream(output); + ToStream(output, Type, Flags, (int)WebPageFlags.Type); + ToStream(output, SiteName, Flags, (int)WebPageFlags.SiteName); + ToStream(output, Title, Flags, (int)WebPageFlags.Title); + ToStream(output, Description, Flags, (int)WebPageFlags.Description); + ToStream(output, Photo, Flags, (int)WebPageFlags.Photo); + ToStream(output, EmbedUrl, Flags, (int)WebPageFlags.Embed); + ToStream(output, EmbedType, Flags, (int)WebPageFlags.Embed); + ToStream(output, EmbedWidth, Flags, (int)WebPageFlags.EmbedSize); + ToStream(output, EmbedHeight, Flags, (int)WebPageFlags.EmbedSize); + ToStream(output, Duration, Flags, (int)WebPageFlags.Duration); + ToStream(output, Author, Flags, (int) WebPageFlags.Author); + } + } + + public class TLWebPage35 : TLWebPage + { + public new const uint Signature = TLConstructors.TLWebPage35; + + public TLDocumentBase Document { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + Url = GetObject(bytes, ref position); + DisplayUrl = GetObject(bytes, ref position); + if (IsSet(Flags, (int)WebPageFlags.Type)) + { + Type = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.SiteName)) + { + SiteName = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Title)) + { + Title = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Description)) + { + Description = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Photo)) + { + Photo = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Embed)) + { + EmbedUrl = GetObject(bytes, ref position); + EmbedType = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.EmbedSize)) + { + EmbedWidth = GetObject(bytes, ref position); + EmbedHeight = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Duration)) + { + Duration = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Author)) + { + Author = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Document)) + { + Document = GetObject(bytes, ref position); + } + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + Url.ToBytes(), + DisplayUrl.ToBytes(), + ToBytes(Type, Flags, (int)WebPageFlags.Type), + ToBytes(SiteName, Flags, (int)WebPageFlags.SiteName), + ToBytes(Title, Flags, (int)WebPageFlags.Title), + ToBytes(Description, Flags, (int)WebPageFlags.Description), + ToBytes(Photo, Flags, (int)WebPageFlags.Photo), + ToBytes(EmbedUrl, Flags, (int)WebPageFlags.Embed), + ToBytes(EmbedType, Flags, (int)WebPageFlags.Embed), + ToBytes(EmbedWidth, Flags, (int)WebPageFlags.EmbedSize), + ToBytes(EmbedHeight, Flags, (int)WebPageFlags.EmbedSize), + ToBytes(Duration, Flags, (int)WebPageFlags.Duration), + ToBytes(Author, Flags, (int)WebPageFlags.Author), + ToBytes(Document, Flags, (int)WebPageFlags.Document)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Url = GetObject(input); + DisplayUrl = GetObject(input); + if (IsSet(Flags, (int)WebPageFlags.Type)) + { + Type = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.SiteName)) + { + SiteName = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Title)) + { + Title = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Description)) + { + Description = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Photo)) + { + Photo = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Embed)) + { + EmbedUrl = GetObject(input); + EmbedType = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.EmbedSize)) + { + EmbedWidth = GetObject(input); + EmbedHeight = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Duration)) + { + Duration = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Author)) + { + Author = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Document)) + { + Document = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + Url.ToStream(output); + DisplayUrl.ToStream(output); + ToStream(output, Type, Flags, (int)WebPageFlags.Type); + ToStream(output, SiteName, Flags, (int)WebPageFlags.SiteName); + ToStream(output, Title, Flags, (int)WebPageFlags.Title); + ToStream(output, Description, Flags, (int)WebPageFlags.Description); + ToStream(output, Photo, Flags, (int)WebPageFlags.Photo); + ToStream(output, EmbedUrl, Flags, (int)WebPageFlags.Embed); + ToStream(output, EmbedType, Flags, (int)WebPageFlags.Embed); + ToStream(output, EmbedWidth, Flags, (int)WebPageFlags.EmbedSize); + ToStream(output, EmbedHeight, Flags, (int)WebPageFlags.EmbedSize); + ToStream(output, Duration, Flags, (int)WebPageFlags.Duration); + ToStream(output, Author, Flags, (int)WebPageFlags.Author); + ToStream(output, Document, Flags, (int)WebPageFlags.Document); + } + } + + public class TLWebPage59 : TLWebPage35 + { + public new const uint Signature = TLConstructors.TLWebPage59; + + public TLInt Hash { get; set; } + + public TLPageBase CachedPage { get; set; } + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + Flags = GetObject(bytes, ref position); + Id = GetObject(bytes, ref position); + Url = GetObject(bytes, ref position); + DisplayUrl = GetObject(bytes, ref position); + Hash = GetObject(bytes, ref position); + if (IsSet(Flags, (int)WebPageFlags.Type)) + { + Type = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.SiteName)) + { + SiteName = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Title)) + { + Title = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Description)) + { + Description = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Photo)) + { + Photo = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Embed)) + { + EmbedUrl = GetObject(bytes, ref position); + EmbedType = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.EmbedSize)) + { + EmbedWidth = GetObject(bytes, ref position); + EmbedHeight = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Duration)) + { + Duration = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Author)) + { + Author = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.Document)) + { + Document = GetObject(bytes, ref position); + } + if (IsSet(Flags, (int)WebPageFlags.CachedPage)) + { + CachedPage = GetObject(bytes, ref position); + } + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature), + Flags.ToBytes(), + Id.ToBytes(), + Url.ToBytes(), + DisplayUrl.ToBytes(), + Hash.ToBytes(), + ToBytes(Type, Flags, (int)WebPageFlags.Type), + ToBytes(SiteName, Flags, (int)WebPageFlags.SiteName), + ToBytes(Title, Flags, (int)WebPageFlags.Title), + ToBytes(Description, Flags, (int)WebPageFlags.Description), + ToBytes(Photo, Flags, (int)WebPageFlags.Photo), + ToBytes(EmbedUrl, Flags, (int)WebPageFlags.Embed), + ToBytes(EmbedType, Flags, (int)WebPageFlags.Embed), + ToBytes(EmbedWidth, Flags, (int)WebPageFlags.EmbedSize), + ToBytes(EmbedHeight, Flags, (int)WebPageFlags.EmbedSize), + ToBytes(Duration, Flags, (int)WebPageFlags.Duration), + ToBytes(Author, Flags, (int)WebPageFlags.Author), + ToBytes(Document, Flags, (int)WebPageFlags.Document), + ToBytes(CachedPage, Flags, (int)WebPageFlags.CachedPage)); + } + + public override TLObject FromStream(Stream input) + { + Flags = GetObject(input); + Id = GetObject(input); + Url = GetObject(input); + DisplayUrl = GetObject(input); + Hash = GetObject(input); + if (IsSet(Flags, (int)WebPageFlags.Type)) + { + Type = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.SiteName)) + { + SiteName = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Title)) + { + Title = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Description)) + { + Description = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Photo)) + { + Photo = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Embed)) + { + EmbedUrl = GetObject(input); + EmbedType = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.EmbedSize)) + { + EmbedWidth = GetObject(input); + EmbedHeight = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Duration)) + { + Duration = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Author)) + { + Author = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.Document)) + { + Document = GetObject(input); + } + if (IsSet(Flags, (int)WebPageFlags.CachedPage)) + { + CachedPage = GetObject(input); + } + + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + Flags.ToStream(output); + Id.ToStream(output); + Url.ToStream(output); + DisplayUrl.ToStream(output); + Hash.ToStream(output); + ToStream(output, Type, Flags, (int)WebPageFlags.Type); + ToStream(output, SiteName, Flags, (int)WebPageFlags.SiteName); + ToStream(output, Title, Flags, (int)WebPageFlags.Title); + ToStream(output, Description, Flags, (int)WebPageFlags.Description); + ToStream(output, Photo, Flags, (int)WebPageFlags.Photo); + ToStream(output, EmbedUrl, Flags, (int)WebPageFlags.Embed); + ToStream(output, EmbedType, Flags, (int)WebPageFlags.Embed); + ToStream(output, EmbedWidth, Flags, (int)WebPageFlags.EmbedSize); + ToStream(output, EmbedHeight, Flags, (int)WebPageFlags.EmbedSize); + ToStream(output, Duration, Flags, (int)WebPageFlags.Duration); + ToStream(output, Author, Flags, (int)WebPageFlags.Author); + ToStream(output, Document, Flags, (int)WebPageFlags.Document); + ToStream(output, CachedPage, Flags, (int)WebPageFlags.CachedPage); + } + } + + public class TLWebPageNotModified : TLWebPageBase + { + public const uint Signature = TLConstructors.TLWebPageNotModified; + + public override TLObject FromBytes(byte[] bytes, ref int position) + { + bytes.ThrowExceptionIfIncorrect(ref position, Signature); + + return this; + } + + public override byte[] ToBytes() + { + return TLUtils.Combine( + TLUtils.SignatureToBytes(Signature)); + } + + public override TLObject FromStream(Stream input) + { + return this; + } + + public override void ToStream(Stream output) + { + output.Write(TLUtils.SignatureToBytes(Signature)); + } + + public override Visibility SiteNameVisibility + { + get { return Visibility.Collapsed; } + } + + public override Visibility AuthorVisibility + { + get { return Visibility.Collapsed; } + } + + public override Visibility TitleVisibility + { + get { return Visibility.Collapsed; } + } + + public override Visibility DescriptionVisibility + { + get { return Visibility.Collapsed; } + } + } +} diff --git a/Telegram.Api/Telegram.Api.csproj b/Telegram.Api/Telegram.Api.csproj new file mode 100755 index 0000000..6a35936 --- /dev/null +++ b/Telegram.Api/Telegram.Api.csproj @@ -0,0 +1,1171 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {0C2F1B61-A8FE-45FB-8538-AA6925A415B6} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Telegram.Api + Telegram.Api + v4.0 + $(TargetFrameworkVersion) + WindowsPhone71 + Silverlight + false + true + true + ..\ + true + + + true + full + false + Bin\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;LOG_REGISTRATION;LAYER_29;LAYER_40 + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;LOG_REGISTRATION;LAYER_29;LAYER_40 + true + true + prompt + 4 + + + true + bin\Debug Private Beta\ + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;PRIVATE_BETA; + true + full + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + bin\Release Private Beta\ + TRACE;SILVERLIGHT;WINDOWS_PHONE;PRIVATE_BETA;LOG_REGISTRATION; + true + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + ..\Libraries\BouncyCastle.Crypto.WP71.dll + + + + + ..\packages\Rx-Core.2.2.2\lib\windowsphone71\System.Reactive.Core.dll + + + ..\packages\Rx-Interfaces.2.2.2\lib\windowsphone71\System.Reactive.Interfaces.dll + + + ..\packages\Rx-Linq.2.2.2\lib\windowsphone71\System.Reactive.Linq.dll + + + + + + + + + + + + Compression\GZipDeflateStream.cs + + + Constants.cs + + + CRC.cs + + + Extensions\ActionExtensions.cs + + + Extensions\HttpWebRequestExtensions.cs + + + Extensions\StreamExtensions.cs + + + Extensions\TLObjectExtensions.cs + + + Helpers\Execute.cs + + + Helpers\FileUtils.cs + + + Helpers\PhoneHelper.cs + + + Helpers\SettingsHelper.cs + + + Helpers\Utils.cs + + + MD5\MD5.cs + + + MD5\MD5CryptoServiceProvider.cs + + + MD5\MD5Managed.cs + + + Services\Cache\Context.cs + + + Services\Cache\EventArgs\DialogAddedEventArgs.cs + + + Services\Cache\EventArgs\TopMessageUpdatedEventArgs.cs + + + Services\Cache\ICacheService.cs + + + Services\Cache\InMemoryCacheService.cs + + + Services\Cache\InMemoryDatabase.cs + + + Services\Connection\ConnectionService.cs + + + Services\DCOptionItem.cs + + + Services\DelayedItem.cs + + + Services\FileManager\AudioFileManager.cs + + + Services\FileManager\DocumentFileManager.cs + + + Services\FileManager\DownloadableItem.cs + + + Services\FileManager\DownloadablePart.cs + + + Services\FileManager\DownloadingCanceledEventArgs.cs + + + Services\FileManager\EncryptedFileManager.cs + + + Services\FileManager\FileManager.cs + + + Services\FileManager\IAudioFileManager.cs + + + Services\FileManager\IDocumentFileManager.cs + + + Services\FileManager\IEncryptedFileManager.cs + + + Services\FileManager\IFileManager.cs + + + Services\FileManager\IUploadAudioFileManager.cs + + + Services\FileManager\IUploadFileManager.cs + + + Services\FileManager\IUploadVideoFileManager.cs + + + Services\FileManager\IVideoFileManager.cs + + + Services\FileManager\ProgressChangedEventArgs.cs + + + Services\FileManager\UploadAudioFileManager.cs + + + Services\FileManager\UploadFileManager.cs + + + Services\FileManager\UploadVideoFileManager.cs + + + Services\FileManager\VideoFileManager.cs + + + Services\FileManager\Worker.cs + + + Services\HistoryItem.cs + + + Services\IMTProtoService.cs + + + Services\MTProtoService.Account.cs + + + Services\MTProtoService.Auth.cs + + + Services\MTProtoService.ByTransport.cs + + + Services\MTProtoService.Config.cs + + + Services\MTProtoService.Contacts.cs + + + Services\MTProtoService.cs + + + Services\MTProtoService.DHKeyExchange.cs + + + Services\MTProtoService.Help.cs + + + Services\MTProtoService.Helpers.cs + + + Services\MTProtoService.HttpLongPoll.cs + + + Services\MTProtoService.Messages.cs + + + Services\MTProtoService.Photos.cs + + + Services\MTProtoService.SecretChats.cs + + + Services\MTProtoService.SendingQueue.cs + + + Services\MTProtoService.Stuff.cs + + + Services\MTProtoService.Updates.cs + + + Services\MTProtoService.Upload.cs + + + Services\MTProtoService.Users.cs + + + Services\ServiceBase.cs + + + Services\Updates\IUpdatesService.cs + + + Services\Updates\ReceiveUpdatesEventArgs.cs + + + Services\Updates\UpdatesBySeqComparer.cs + + + Services\Updates\UpdatesService.cs + + + TL\Enums.cs + + + TL\Account\TLCheckUsername.cs + + + TL\Account\TLDeleteAccount.cs + + + TL\Account\TLGetAccountTTL.cs + + + TL\Account\TLGetNotifySettings.cs + + + TL\Account\TLGetPrivacy.cs + + + TL\Account\TLRegisterDevice.cs + + + TL\Account\TLResetNotifySettings.cs + + + TL\Account\TLSetPrivacy.cs + + + TL\Account\TLUnregisterDevice.cs + + + TL\Account\TLUpdateNotifySettings.cs + + + TL\Account\TLUpdateProfile.cs + + + TL\Account\TLUpdateStatus.cs + + + TL\Account\TLUpdateUserName.cs + + + TL\Functions\Auth\TLCheckPhone.cs + + + TL\Functions\Auth\TLExportAuthorization.cs + + + TL\Functions\Auth\TLImportAuthorization.cs + + + TL\Functions\Auth\TLLogOut.cs + + + TL\Functions\Auth\TLResetAuthorizations.cs + + + TL\Functions\Auth\TLSendCall.cs + + + TL\Functions\Auth\TLSendCode.cs + + + TL\Functions\Auth\TLSendInvites.cs + + + TL\Functions\Auth\TLSendSms.cs + + + TL\Functions\Auth\TLSignIn.cs + + + TL\Functions\Auth\TLSignUp.cs + + + TL\Functions\Contacts\TLBlock.cs + + + TL\Functions\Contacts\TLDeleteContact.cs + + + TL\Functions\Contacts\TLDeleteContacts.cs + + + TL\Functions\Contacts\TLGetBlocked.cs + + + TL\Functions\Contacts\TLGetContacts.cs + + + TL\Functions\Contacts\TLGetStatuses.cs + + + TL\Functions\Contacts\TLImportContacts.cs + + + TL\Functions\Contacts\TLSearch.cs + + + TL\Functions\Contacts\TLUnblock.cs + + + TL\Functions\DHKeyExchange\TLReqDHParams.cs + + + TL\Functions\DHKeyExchange\TLReqPQ.cs + + + TL\Functions\DHKeyExchange\TLSetClientDHParams.cs + + + TL\Functions\Help\TLGetConfig.cs + + + TL\Functions\Help\TLGetInviteText.cs + + + TL\Functions\Help\TLGetNearestDC.cs + + + TL\Functions\Help\TLGetSupport.cs + + + TL\Functions\Help\TLInvokeWithLayerN.cs + + + TL\Functions\Messages\TLAcceptEncryption.cs + + + TL\Functions\Messages\TLAddChatUser.cs + + + TL\Functions\Messages\TLCreateChat.cs + + + TL\Functions\Messages\TLDeleteChatUser.cs + + + TL\Functions\Messages\TLDeleteHistory.cs + + + TL\Functions\Messages\TLDeleteMessages.cs + + + TL\Functions\Messages\TLDiscardEncryption.cs + + + TL\Functions\Messages\TLEditChatPhoto.cs + + + TL\Functions\Messages\TLEditChatTitle.cs + + + TL\Functions\Messages\TLForwardMessage.cs + + + TL\Functions\Messages\TLForwardMessages.cs + + + TL\Functions\Messages\TLGetChats.cs + + + TL\Functions\Messages\TLGetDHConfig.cs + + + TL\Functions\Messages\TLGetDialogs.cs + + + TL\Functions\Messages\TLGetFullChat.cs + + + TL\Functions\Messages\TLGetHistory.cs + + + TL\Functions\Messages\TLGetMessages.cs + + + TL\Functions\Messages\TLReadEncryptedHistory.cs + + + TL\Functions\Messages\TLReadHistory.cs + + + TL\Functions\Messages\TLReadMessageContents.cs + + + TL\Functions\Messages\TLReceivedMessages.cs + + + TL\Functions\Messages\TLReceivedQueue.cs + + + TL\Functions\Messages\TLRequestEncryption.cs + + + TL\Functions\Messages\TLRestoreMessages.cs + + + TL\Functions\Messages\TLSearch.cs + + + TL\Functions\Messages\TLSendBroadcast.cs + + + TL\Functions\Messages\TLSendEncrypted.cs + + + TL\Functions\Messages\TLSendEncryptedFile.cs + + + TL\Functions\Messages\TLSendEncryptedService.cs + + + TL\Functions\Messages\TLSendMedia.cs + + + TL\Functions\Messages\TLSendMessage.cs + + + TL\Functions\Messages\TLSetEncryptedTyping.cs + + + TL\Functions\Messages\TLSetTyping.cs + + + TL\Functions\Photos\TLGetUserPhotos.cs + + + TL\Functions\Photos\TLUpdateProfilePhoto.cs + + + TL\Functions\Photos\TLUploadProfilePhoto.cs + + + TL\Functions\Stuff\TLGetFutureSalts.cs + + + TL\Functions\Stuff\TLHttpWait.cs + + + TL\Functions\Stuff\TLMessageAcknowledgments.cs + + + TL\Functions\Stuff\TLRPCDropAnswer.cs + + + TL\Functions\Updates\TLGetDifference.cs + + + TL\Functions\Updates\TLGetState.cs + + + TL\Functions\Upload\TLGetFile.cs + + + TL\Functions\Upload\TLSaveFilePart.cs + + + TL\Functions\Users\TLGetFullUser.cs + + + TL\Functions\Users\TLGetUsers.cs + + + TL\Interfaces\IBytes.cs + + + TL\Interfaces\IFullName.cs + + + TL\Interfaces\IInputPeer.cs + + + TL\Interfaces\ISelectable.cs + + + TL\Interfaces\IVIsibility.cs + + + TL\SignatureAttribute.cs + + + TL\TLAffectedHistory.cs + + + TL\TLAudio.cs + + + TL\TLAuthorization.cs + + + TL\TLBadMessageNotification.cs + + + TL\TLBadServerSalt.cs + + + TL\TLBool.cs + + + TL\TLChat.cs + + + TL\TLChatFull.cs + + + TL\TLChatParticipant.cs + + + TL\TLChatParticipants.cs + + + TL\TLChats.cs + + + TL\TLCheckedPhone.cs + + + TL\TLClientDHInnerData.cs + + + TL\TLConfig.cs + + + TL\TLContact.cs + + + TL\TLContactBlocked.cs + + + TL\TLContactFound.cs + + + TL\TLContacts.cs + + + TL\TLContactsBlocked.cs + + + TL\TLContactsFound.cs + + + TL\TLContactStatus.cs + + + TL\TLContainerTransportMessage.cs + + + TL\TLDCOption.cs + + + TL\TLDecryptedMessage.cs + + + TL\TLDecryptedMessageAction.cs + + + TL\TLDecryptedMessageLayer.cs + + + TL\TLDecryptedMessageMedia.cs + + + TL\TLDHConfig.cs + + + TL\TLDHGen.cs + + + TL\TLDialog.cs + + + TL\TLDialogs.cs + + + TL\TLDifference.cs + + + TL\TLDocument.cs + + + TL\TLDouble.cs + + + TL\TLEncryptedChat.cs + + + TL\TLEncryptedFile.cs + + + TL\TLEncryptedMessage.cs + + + TL\TLExportedAuthorization.cs + + + TL\TLFile.cs + + + TL\TLFileLocation.cs + + + TL\TLFileType.cs + + + TL\TLForeignLink.cs + + + TL\TLFutureSalt.cs + + + TL\TLGeoPoint.cs + + + TL\TLGzipPacked.cs + + + TL\TLImportedContact.cs + + + TL\TLImportedContacts.cs + + + TL\TLInitConnection.cs + + + TL\TLInputAudio.cs + + + TL\TLInputChatPhoto.cs + + + TL\TLInputContact.cs + + + TL\TLInputDocument.cs + + + TL\TLInputEncryptedChat.cs + + + TL\TLInputEncryptedFile.cs + + + TL\TLInputEncryptedFileLocation.cs + + + TL\TLInputFile.cs + + + TL\TLInputFileLocation.cs + + + TL\TLInputGeoPoint.cs + + + TL\TLInputMedia.cs + + + TL\TLInputMessagesFilter.cs + + + TL\TLInputNotifyPeer.cs + + + TL\TLInputPeerBase.cs + + + TL\TLInputPeerNotifyEvents.cs + + + TL\TLInputPeerNotifySettings.cs + + + TL\TLInputPhoto.cs + + + TL\TLInputPhotoCrop.cs + + + TL\TLInputUser.cs + + + TL\TLInputVideo.cs + + + TL\TLInt.cs + + + TL\TLInt128.cs + + + TL\TLInt256.cs + + + TL\TLInviteText.cs + + + TL\TLInvokeAfterMsg.cs + + + TL\TLLink.cs + + + TL\TLLong.cs + + + TL\TLMessage.cs + + + TL\TLMessage.Encrypted.cs + + + TL\TLMessageAction.cs + + + TL\TLMessageContainer.cs + + + TL\TLMessageInfo.cs + + + TL\TLMessageMedia.cs + + + TL\TLMessages.cs + + + TL\TLMessagesAcknowledgment.cs + + + TL\TLMessagesChatFull.cs + + + TL\TLMyLink.cs + + + TL\TLNearestDC.cs + + + TL\TLNewSessionCreated.cs + + + TL\TLNonEncryptedMessage.cs + + + TL\TLNotifyPeer.cs + + + TL\TLNull.cs + + + TL\TLObject.cs + + + TL\TLObjectGenerator.cs + + + TL\TLPeer.cs + + + TL\TLPeerNotifyEvents.cs + + + TL\TLPeerNotifySettings.cs + + + TL\TLPhoto.cs + + + TL\TLPhotos.cs + + + TL\TLPhotoSize.cs + + + TL\TLPhotosPhoto.cs + + + TL\TLPong.cs + + + TL\TLPQInnerData.cs + + + TL\TLRequest.cs + + + TL\TLResponse.cs + + + TL\TLResPQ.cs + + + TL\TLRPCDropAnswer.cs + + + TL\TLRPCError.cs + + + TL\TLRPCResult.cs + + + TL\TLSendMessageAction.cs + + + TL\TLSentCode.cs + + + TL\TLSentEncryptedFile.cs + + + TL\TLSentEncryptedMessage.cs + + + TL\TLSentMessage.cs + + + TL\TLServerDHInnerData.cs + + + TL\TLServerDHParams.cs + + + TL\TLServerFile.cs + + + TL\TLSignatures.cs + + + TL\TLState.cs + + + TL\TLStatedMessage.cs + + + TL\TLStatedMessages.cs + + + TL\TLString.cs + + + TL\TLSupport.cs + + + TL\TLUpdate.cs + + + TL\TLUpdates.cs + + + TL\TLUserBase.cs + + + TL\TLUserFull.cs + + + TL\TLUserStatus.cs + + + TL\TLUtils.cs + + + TL\TLUtils.Log.cs + + + TL\TLVector.cs + + + TL\TLVideo.cs + + + TL\TLWallpaperSolid.cs + + + Transport\DataEventArgs.cs + + + Transport\HttpTransport.cs + + + Transport\ITransport.cs + + + Transport\ITransportService.cs + + + Transport\TCPTransport.cs + + + Transport\TCPTransportBase.cs + + + Transport\TCPTransportResult.cs + + + Transport\TransportService.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Telegram.Api/Transport/DataEventArgs.cs b/Telegram.Api/Transport/DataEventArgs.cs new file mode 100755 index 0000000..a2393c8 --- /dev/null +++ b/Telegram.Api/Transport/DataEventArgs.cs @@ -0,0 +1,30 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Api.Transport +{ + public class DataEventArgs : EventArgs + { + public byte[] Data { get; set; } + public DateTime? LastReceiveTime { get; set; } + public int NextPacketLength { get; set; } + + public DataEventArgs(byte[] data) + { + Data = data; + } + + public DataEventArgs(byte[] data, int packetLength, DateTime? lastReceiveTime) + { + Data = data; + NextPacketLength = packetLength; + LastReceiveTime = lastReceiveTime; + } + } +} \ No newline at end of file diff --git a/Telegram.Api/Transport/HttpTransport.cs b/Telegram.Api/Transport/HttpTransport.cs new file mode 100755 index 0000000..e07e231 --- /dev/null +++ b/Telegram.Api/Transport/HttpTransport.cs @@ -0,0 +1,421 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Net; +using System.Text; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.Services; +using Telegram.Api.TL; +using Action = System.Action; +using TransportType = Telegram.Api.Services.TransportType; + +namespace Telegram.Api.Transport +{ + public class HttpTransport : ITransport + { + public ulong Ping { get { return 0; } } + + public MTProtoTransportType MTProtoType { get; protected set; } + + public long MinMessageId { get; set; } + public Dictionary MessageIdDict { get; set; } + + public bool Additional { get; set; } + + private bool _once; + + public void UpdateTicksDelta(TLLong msgId) + { + lock (SyncRoot) + { + if (_once) return; + _once = true; + + var clientTime = GenerateMessageId().Value; + var serverTime = msgId.Value; + ClientTicksDelta += serverTime - clientTime; + } + } + + public event EventHandler ConnectionLost; + + public event EventHandler Connecting; + + public event EventHandler Connected; + + public DateTime? FirstReceiveTime + { + get { throw new NotImplementedException(); } + } + + public DateTime? LastReceiveTime + { + get { throw new NotImplementedException(); } + } + + public int PacketLength + { + get { throw new NotImplementedException(); } + } + + public int LastPacketLength + { + get { throw new NotImplementedException(); } + } + + public DateTime? FirstSendTime + { + get { throw new NotImplementedException(); } + } + + public DateTime? LastSendTime + { + get { throw new NotImplementedException(); } + } + + public WindowsPhone.Tuple GetCurrentPacketInfo() + { + throw new NotImplementedException(); + } + + public string GetTransportInfo() + { + throw new NotImplementedException(); + } + + public int Id { get; protected set; } + + private readonly object _previousMessageRoot = new object(); + + public long PreviousMessageId; + + public TLLong GenerateMessageId(bool checkPreviousMessageId = false) + { + var clientDelta = ClientTicksDelta; + // serverTime = clientTime + clientDelta + var now = DateTime.Now; + //var unixTime = (long)Utils.DateTimeToUnixTimestamp(now) << 32; + + var unixTime = (long)(Utils.DateTimeToUnixTimestamp(now) * 4294967296) + clientDelta; //2^32 + long correctUnixTime; + + var addingTicks = 4 - (unixTime % 4); + if ((unixTime % 4) == 0) + { + correctUnixTime = unixTime; + } + else + { + correctUnixTime = unixTime + addingTicks; + } + + // check with previous messageId + + lock (_previousMessageRoot) + { + if (PreviousMessageId != 0 && checkPreviousMessageId) + { + correctUnixTime = Math.Max(PreviousMessageId + 4, correctUnixTime); + } + PreviousMessageId = correctUnixTime; + } + + // refactor this: + // addTicks = 4 - (unixTime % 4) + // fixedUnixTime = unixTime + addTicks + // max(fixedUnixTime, previousMessageId + 4) + + //if ((unixTime % 4) == 0) + //{ + // correctUnixTime = unixTime; + //} + //else + //{ + // for (int i = 0; i < 300; i++) + // { + // var temp = unixTime - i; + // if ((temp % 4) == 0) + // { + // correctUnixTime = unixTime; + // break; + // } + // } + //} + //TLUtils.WriteLine("TLMessage ID: " + correctUnixTime); + //TLUtils.WriteLine("MessageId % 4 =" + (correctUnixTime % 4)); + //TLUtils.WriteLine("Corresponding time: " + Utils.UnixTimestampToDateTime(correctUnixTime >> 32)); + + if (correctUnixTime == 0) + throw new Exception("Bad message id"); + + return new TLLong(correctUnixTime); + } + + #region NonEncryptedHistory + + private readonly object _nonEncryptedHistoryRoot = new object(); + + private readonly Dictionary _nonEncryptedHistory = new Dictionary(); + + public IList RemoveTimeOutRequests(double timeout = Constants.TimeoutInterval) + { + var now = DateTime.Now; + var timedOutKeys = new List(); + var timedOutValues = new List(); + + lock (_nonEncryptedHistoryRoot) + { + foreach (var historyKeyValue in _nonEncryptedHistory) + { + var historyValue = historyKeyValue.Value; + if (historyValue.SendTime != default(DateTime) + && historyValue.SendTime.AddSeconds(timeout) < now) + { + timedOutKeys.Add(historyKeyValue.Key); + timedOutValues.Add(historyKeyValue.Value); + } + } + + foreach (var key in timedOutKeys) + { + _nonEncryptedHistory.Remove(key); + } + } + + return timedOutValues; + } + + public void EnqueueNonEncryptedItem(HistoryItem item) + { + lock (_nonEncryptedHistoryRoot) + { + _nonEncryptedHistory[item.Hash] = item; + } + } + + public HistoryItem DequeueFirstNonEncryptedItem() + { + HistoryItem item; + lock (_nonEncryptedHistoryRoot) + { + item = _nonEncryptedHistory.Values.FirstOrDefault(); + if (item != null) + { + _nonEncryptedHistory.Remove(item.Hash); + } + } + + return item; + } + + public bool RemoveNonEncryptedItem(HistoryItem item) + { + bool result; + lock (_nonEncryptedHistoryRoot) + { + result = _nonEncryptedHistory.Remove(item.Hash); + } + + return result; + } + + public void ClearNonEncryptedHistory(Exception e = null) + { + lock (_nonEncryptedHistoryRoot) + { + foreach (var historyItem in _nonEncryptedHistory) + { + var error = new StringBuilder(); + error.AppendLine("Clear NonEncrypted History: "); + if (e != null) + { + error.AppendLine(e.ToString()); + } + historyItem.Value.FaultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString(error.ToString()) }); + } + + _nonEncryptedHistory.Clear(); + } + } + + public string PrintNonEncryptedHistory() + { + var sb = new StringBuilder(); + + lock (_nonEncryptedHistoryRoot) + { + sb.AppendLine("NonEncryptedHistory items:"); + foreach (var historyItem in _nonEncryptedHistory.Values) + { + sb.AppendLine(historyItem.Caption); + } + } + + return sb.ToString(); + } + #endregion + + public void StartListening() + { + + } + private readonly object _syncRoot = new object(); + + public object SyncRoot { get { return _syncRoot; } } + + public int DCId { get; set; } + public byte[] Secret { get; set; } + public byte[] AuthKey { get; set; } + public TLLong SessionId { get; set; } + public TLLong Salt { get; set; } + public int SequenceNumber { get; set; } + public long ClientTicksDelta { get; set; } + + public bool Initiated { get; set; } + + public bool Initialized { get; set; } + + public bool IsInitializing { get; set; } + + public bool IsAuthorized { get; set; } + + public bool IsAuthorizing { get; set; } + + public string Host { get { return _host; } } + public int Port { get { return 80; } } + public string StaticHost { get; protected set; } + public int StaticPort { get; protected set; } + public string ActualHost { get; protected set; } + public int ActualPort { get; protected set; } + public TLProxyConfigBase ProxyConfig { get; protected set; } + + public TransportType Type { get { return TransportType.Http; } } + public bool Closed { get; private set; } + + private string _host; + + public HttpTransport(string address, MTProtoTransportType mtProtoType, TLProxyConfigBase proxyConfig) + { + var host = string.IsNullOrEmpty(address) ? Constants.FirstServerIpAddress : address; + _host = string.Format("http://{0}:80/api", host); + + MTProtoType = mtProtoType; + ProxyConfig = proxyConfig; + + MessageIdDict = new Dictionary(); + } + + public void ConnectAsync(Action callback, Action faultCallback) + { + + } + + public event EventHandler PacketReceived; + + private void RaiseGetBytes(byte[] data) + { + var eventHandler = PacketReceived; + if (eventHandler != null) + { + eventHandler.Invoke(this, new DataEventArgs(data)); + } + } + + private static HttpWebRequest CreateRequest(int contentLength, string address) + { + var request = (HttpWebRequest)WebRequest.Create(address); + request.Method = "POST"; +#if SILVERLIGHT + + request.Headers["Connection"] = "Keep-alive"; + request.Headers["Content-Length"] = contentLength.ToString(CultureInfo.InvariantCulture); +#else + request.KeepAlive = true; + request.ContentLength = contentLength; + ServicePointManager.Expect100Continue = false; +#endif + //IWebProxy proxy = request.Proxy; + //if (proxy != null) + //{ + // string proxyuri = proxy.GetProxy(request.RequestUri).ToString(); + // request.UseDefaultCredentials = true; + // request.Proxy = new WebProxy(proxyuri, false); + // request.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials; + //} + + return request; + } + + public void SendPacketAsync(string caption, byte[] message, Action callback, Action faultCallback = null) + { + //var guid = Guid.NewGuid(); + var stopwatch = Stopwatch.StartNew(); + TLUtils.WriteLine(" HTTP: Send " + caption); + var request = CreateRequest(message.Length, _host); + + + request.BeginAsync(message, result => + { + TLUtils.WriteLine(); + TLUtils.WriteLine(); + TLUtils.WriteLine(" HTTP: Receive " + caption + " (" + stopwatch.Elapsed + ")"); + RaiseGetBytes(result); + ///callback(result); + }, + () => + { + TLUtils.WriteLine(); + TLUtils.WriteLine(); + TLUtils.WriteLine(" HTTP: Receive Falt " + caption + " (" + stopwatch.Elapsed + ")"); + faultCallback.SafeInvoke(null); + }); + } + + public byte[] SendBytes(byte[] message) + { + //95.142.192.65:80 + //173.240.5.253:443 +#if SILVERLIGHT + throw new NotImplementedException("Sync mode is not supported in Windows Phone"); +#else + + var request = CreateRequest(message.Length, _host); + var dataStream = request.GetRequestStream(); + dataStream.Write(message, 0, message.Length); + dataStream.Close(); + var response = request.GetResponse(); + //TLUtils.WriteLine(((HttpWebResponse)response).StatusDescription); + dataStream = response.GetResponseStream(); + var buffer = new byte[Int32.Parse(response.Headers["Content-Length"])]; + var bytesRead = 0; + var totalBytesRead = bytesRead; + while (totalBytesRead < buffer.Length) + { + bytesRead = dataStream.Read(buffer, bytesRead, buffer.Length - bytesRead); + totalBytesRead += bytesRead; + } + dataStream.Close(); + dataStream.Close(); + response.Close(); + + RaiseGetBytes(buffer); + return buffer; +#endif + } + + public void Close() + { + + } + } +} diff --git a/Telegram.Api/Transport/ITransport.cs b/Telegram.Api/Transport/ITransport.cs new file mode 100755 index 0000000..3d48d8f --- /dev/null +++ b/Telegram.Api/Transport/ITransport.cs @@ -0,0 +1,90 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using Telegram.Api.Services; +using Telegram.Api.TL; + +namespace Telegram.Api.Transport +{ + public interface ITransport + { + ulong Ping { get; } + + MTProtoTransportType MTProtoType { get; } + + event EventHandler Connecting; + event EventHandler Connected; + event EventHandler ConnectionLost; + event EventHandler PacketReceived; + + void SendPacketAsync(string caption, byte[] data, Action callback, Action faultCallback = null); + void Close(); + + // check hang connection + DateTime? FirstSendTime { get; } + DateTime? LastReceiveTime { get; } + int PacketLength { get; } + int LastPacketLength { get; } + + // debug + WindowsPhone.Tuple GetCurrentPacketInfo(); + string GetTransportInfo(); + string PrintNonEncryptedHistory(); + + TLLong GenerateMessageId(bool checkPreviousMessageId = false); + void EnqueueNonEncryptedItem(HistoryItem item); + HistoryItem DequeueFirstNonEncryptedItem(); + bool RemoveNonEncryptedItem(HistoryItem item); + void ClearNonEncryptedHistory(Exception e = null); + IList RemoveTimeOutRequests(double timeout = Constants.TimeoutInterval); + void UpdateTicksDelta(TLLong msgId); + + object SyncRoot { get; } + int Id { get; } + int DCId { get; set; } + byte[] Secret { get; set; } + byte[] AuthKey { get; set; } + + TLLong SessionId { get; set; } + long MinMessageId { get; set; } + Dictionary MessageIdDict { get; set; } + + TLLong Salt { get; set; } + int SequenceNumber { get; set; } + long ClientTicksDelta { get; set; } + + string Host { get; } + int Port { get; } + string StaticHost { get; } + int StaticPort { get; } + string ActualHost { get; } + int ActualPort { get; } + TLProxyConfigBase ProxyConfig { get; } + + TransportType Type { get; } + + //сделан initConnection + bool Initiated { get; set; } + //создан ключ + bool Initialized { get; set; } + bool IsInitializing { get; set; } + //перенесена авторизация из активного dc (import/export authorization) + bool IsAuthorized { get; set; } + bool IsAuthorizing { get; set; } + //вызван метод Close + bool Closed { get; } + } + + public enum MTProtoTransportType + { + Main, + File, + Special, + } +} diff --git a/Telegram.Api/Transport/ITransportService.cs b/Telegram.Api/Transport/ITransportService.cs new file mode 100755 index 0000000..99fcc3e --- /dev/null +++ b/Telegram.Api/Transport/ITransportService.cs @@ -0,0 +1,43 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.Services; +using Telegram.Api.TL; + +namespace Telegram.Api.Transport +{ + public interface ITransportService + { + void SetProxyConfig(TLProxyConfigBase proxyConfig); + TLProxyConfigBase GetProxyConfig(); + + ITransport GetTransport(string host, int port, string staticHost, int staticPort, TransportType type, short protocolDCId, byte[] protocolSecret, out bool isCreated); + ITransport GetFileTransport(string host, int port, string staticHost, int staticPort, TransportType type, short protocolDCId, byte[] protocolSecret, out bool isCreated); + ITransport GetFileTransport2(string host, int port, string staticHost, int staticPort, TransportType type, short protocolDCId, byte[] protocolSecret, out bool isCreated); + ITransport GetSpecialTransport(string host, int port, string staticHost, int staticPort, TransportType type, short protocolDCId, byte[] protocolSecret, out bool isCreated); + ITransport GetSpecialTransport(string host, int port, string staticHost, int staticPort, TransportType type, short protocolDCId, byte[] protocolSecret, TLProxyBase proxy, out bool isCreated); + + + void Close(); + void CloseTransport(ITransport transport); + void CloseSpecialTransport(ITransport transport); + + event EventHandler TransportConnecting; + event EventHandler TransportConnected; + + event EventHandler ConnectionLost; + event EventHandler FileConnectionLost; + event EventHandler SpecialConnectionLost; + + event EventHandler CheckConfig; + } + + public delegate ITransport GetTransportFunc(string host, int port, string staticHost, int staticPort, TransportType type, short protocolDCId, byte[] protocolSecret, out bool isCreated); + + public delegate ITransport GetTransportWithProxyFunc(string host, int port, string staticHost, int staticPort, TransportType type, short protocolDCId, byte[] protocolSecret, TLProxyBase proxy, out bool isCreated); +} diff --git a/Telegram.Api/Transport/SocksProxy.cs b/Telegram.Api/Transport/SocksProxy.cs new file mode 100755 index 0000000..2d6b529 --- /dev/null +++ b/Telegram.Api/Transport/SocksProxy.cs @@ -0,0 +1,597 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Windows.Networking; +using Windows.Storage.Streams; +using Telegram.Api.Helpers; +using Windows.Networking.Sockets; +#if WIN_RT +#else +using System.Net.Sockets; +using Microsoft.Phone.Net.NetworkInformation; +#endif + +namespace Telegram.Api.Transport +{ + /// + /// Provides sock5 functionality to clients (Connect only). + /// + public class SocksProxy + { + private SocksProxy() { } + + #region ErrorMessages + private static string[] errorMsgs = { + "Operation completed successfully.", + "General SOCKS server failure.", + "Connection not allowed by ruleset.", + "Network unreachable.", + "Host unreachable.", + "Connection refused.", + "TTL expired.", + "Command not supported.", + "Address type not supported.", + "Unknown error." + }; + #endregion + + private static bool Send(DataWriter dataWriter, byte[] buffer, int offset, int length) + { + var sendBuffer = buffer.SubArray(offset, length); + dataWriter.WriteBytes(sendBuffer); + var resul = dataWriter.StoreAsync().AsTask().Result; + + return true; + } + + private static int Receive(DataReader dataReader, byte[] buffer, int offset, int length) + { + var bytesTransferred = dataReader.LoadAsync((uint)buffer.Length).AsTask().Result; + var receiveBuffer = new byte[bytesTransferred]; + dataReader.ReadBytes(receiveBuffer); + + Array.Copy(receiveBuffer, buffer, receiveBuffer.Length); + + return (int) bytesTransferred; + } + + + public static async Task ConnectToSocks5Proxy(double timeout, StreamSocket s, DataWriter _dataWriter, DataReader _dataReader, string proxyAddress, ushort proxyPort, string destAddress, ushort destPort, string userName, string password) + { + var destIP = new HostName(destAddress); + var proxyIP = new HostName(proxyAddress); + var request = new byte[256]; + var response = new byte[256]; + ushort nIndex; + + // open a TCP connection to SOCKS server... + //Connect(s, proxyEndPoint); + await s.ConnectAsync(proxyIP, proxyPort.ToString(CultureInfo.InvariantCulture)).WithTimeout(timeout); + + nIndex = 0; + request[nIndex++] = 0x05; // Version 5. + request[nIndex++] = 0x02; // 2 Authentication methods are in packet... + request[nIndex++] = 0x00; // NO AUTHENTICATION REQUIRED + request[nIndex++] = 0x02; // USERNAME/PASSWORD + + Send(_dataWriter, request, 0, nIndex); + var nGot = Receive(_dataReader, response, 0, response.Length); + + // Receive 2 byte response... + if (nGot != 2) + throw new ConnectionException("Bad response received from proxy server."); + + if (response[1] == 0xFF) + { // No authentication method was accepted close the socket. + s.Dispose(); + throw new ConnectionException("None of the authentication method was accepted by proxy server."); + } + + byte[] rawBytes; + //Username/Password Authentication protocol + if (response[1] == 0x02) + { + nIndex = 0; + request[nIndex++] = 0x01; // Version 5. + + // add user name + request[nIndex++] = (byte)userName.Length; + rawBytes = Encoding.UTF8.GetBytes(userName); + rawBytes.CopyTo(request, nIndex); + nIndex += (ushort)rawBytes.Length; + + // add password + request[nIndex++] = (byte)password.Length; + rawBytes = Encoding.UTF8.GetBytes(password); + rawBytes.CopyTo(request, nIndex); + nIndex += (ushort)rawBytes.Length; + + // Send the Username/Password request + Send(_dataWriter, request, 0, nIndex); + nGot = Receive(_dataReader, response, 0, response.Length); + + if (nGot != 2) + throw new ConnectionException("Bad response received from proxy server."); + if (response[1] != 0x00) + throw new ConnectionException("Bad Usernaem/Password."); + } + //// This version only supports connect command. + //// UDP and Bind are not supported. + + // Send connect request now... + nIndex = 0; + request[nIndex++] = 0x05; // version 5. + request[nIndex++] = 0x01; // command = connect. + request[nIndex++] = 0x00; // Reserve = must be 0x00 + + // Destination adress in an IP. + switch (destIP.Type) + { + case HostNameType.Ipv4: + // Address is IPV4 format + request[nIndex++] = 0x01; + rawBytes = destIP.GetAddressBytes(); + rawBytes.CopyTo(request, nIndex); + nIndex += (ushort)rawBytes.Length; + break; + case HostNameType.Ipv6: + // Address is IPV6 format + request[nIndex++] = 0x04; + rawBytes = destIP.GetAddressBytes(); + rawBytes.CopyTo(request, nIndex); + nIndex += (ushort)rawBytes.Length; + break; + //case HostNameType.DomainName: + // // Dest. address is domain name. + // request[nIndex++] = 0x03; // Address is full-qualified domain name. + // request[nIndex++] = Convert.ToByte(destAddress.Length); // length of address. + // rawBytes = Encoding.UTF8.GetBytes(destAddress); + // rawBytes.CopyTo(request, nIndex); + // nIndex += (ushort)rawBytes.Length; + // break; + } + + // using big-edian byte order + byte[] portBytes = BitConverter.GetBytes(destPort); + for (int i = portBytes.Length - 1; i >= 0; i--) + request[nIndex++] = portBytes[i]; + + // send connect request. + Send(_dataWriter, request, 0, nIndex); + nGot = Receive(_dataReader, response, 0, response.Length); + + if (response[1] != 0x00) + throw new ConnectionException(errorMsgs[response[1]]); + + // Success Connected... + return s; + } +#if !WIN_RT + private static bool Send(Socket s, byte[] buffer, int offset, int length) + { + var send1Event = new AutoResetEvent(false); + var sendArgs = new SocketAsyncEventArgs(); + sendArgs.SetBuffer(buffer, offset, length); + sendArgs.Completed += (sender, eventArgs) => + { + send1Event.Set(); + }; + + var result = s.SendAsync(sendArgs); + send1Event.WaitOne(); + + return result; + } + + private static int Receive(Socket s, byte[] buffer, int offset, int length) + { + var receive1Event = new AutoResetEvent(false); + var receive1Args = new SocketAsyncEventArgs(); + receive1Args.SetBuffer(buffer, offset, length); + receive1Args.Completed += (sender, eventArgs) => + { + receive1Event.Set(); + }; + var result = s.ReceiveAsync(receive1Args); + receive1Event.WaitOne(); + + return receive1Args.BytesTransferred; + } + + private static bool Connect(Socket s, IPEndPoint remoteEndpoit) + { + var connectEvent = new AutoResetEvent(false); + var connectArgs = new SocketAsyncEventArgs(); + connectArgs.RemoteEndPoint = remoteEndpoit; + connectArgs.Completed += (sender, eventArgs) => + { + connectEvent.Set(); + }; + s.ConnectAsync(connectArgs); + connectEvent.WaitOne(); + + return connectArgs.SocketError == System.Net.Sockets.SocketError.Success; + } + + public static Socket ConnectToSocks5Proxy(Socket s, string proxyAdress, ushort proxyPort, string destAddress, ushort destPort, string userName, string password) + { + IPAddress destIP = null; + IPAddress proxyIP = null; + var request = new byte[256]; + var response = new byte[256]; + ushort nIndex; + + try + { + proxyIP = IPAddress.Parse(proxyAdress); + } + catch (FormatException) + { // get the IP address + NameResolutionResult resolutionResult = null; + var dnsResolveEvent = new AutoResetEvent(false); + var endpoint = new DnsEndPoint(proxyAdress, 0); + DeviceNetworkInformation.ResolveHostNameAsync(endpoint, result => + { + resolutionResult = result; + dnsResolveEvent.Set(); + }, null); + dnsResolveEvent.WaitOne(); + proxyIP = resolutionResult.IPEndPoints[0].Address; + } + + // Parse destAddress (assume it in string dotted format "212.116.65.112" ) + try + { + destIP = IPAddress.Parse(destAddress); + } + catch (FormatException) + { + // wrong assumption its in domain name format "www.microsoft.com" + } + + var proxyEndPoint = new IPEndPoint(proxyIP, proxyPort); + + // open a TCP connection to SOCKS server... + var connected = Connect(s, proxyEndPoint); + if (!connected) + { + throw new ConnectionException("Can't connect to proxy server."); + } + + nIndex = 0; + request[nIndex++] = 0x05; // Version 5. + request[nIndex++] = 0x02; // 2 Authentication methods are in packet... + request[nIndex++] = 0x00; // NO AUTHENTICATION REQUIRED + request[nIndex++] = 0x02; // USERNAME/PASSWORD + + Send(s, request, 0, nIndex); + var nGot = Receive(s, response, 0, response.Length); + + // Receive 2 byte response... + if (nGot != 2) + throw new ConnectionException("Bad response received from proxy server."); + + if (response[1] == 0xFF) + { // No authentication method was accepted close the socket. + s.Close(); + throw new ConnectionException("None of the authentication method was accepted by proxy server."); + } + + byte[] rawBytes; + //Username/Password Authentication protocol + if (response[1] == 0x02) + { + nIndex = 0; + request[nIndex++] = 0x01; // Version 5. + + // add user name + request[nIndex++] = (byte)userName.Length; + rawBytes = Encoding.UTF8.GetBytes(userName); + rawBytes.CopyTo(request, nIndex); + nIndex += (ushort)rawBytes.Length; + + // add password + request[nIndex++] = (byte)password.Length; + rawBytes = Encoding.UTF8.GetBytes(password); + rawBytes.CopyTo(request, nIndex); + nIndex += (ushort)rawBytes.Length; + + // Send the Username/Password request + Send(s, request, 0, nIndex); + nGot = Receive(s, response, 0, response.Length); + + if (nGot != 2) + throw new ConnectionException("Bad response received from proxy server."); + if (response[1] != 0x00) + throw new ConnectionException("Bad Usernaem/Password."); + } + //// This version only supports connect command. + //// UDP and Bind are not supported. + + // Send connect request now... + nIndex = 0; + request[nIndex++] = 0x05; // version 5. + request[nIndex++] = 0x01; // command = connect. + request[nIndex++] = 0x00; // Reserve = must be 0x00 + + if (destIP != null) + { + // Destination adress in an IP. + switch (destIP.AddressFamily) + { + case AddressFamily.InterNetwork: + // Address is IPV4 format + request[nIndex++] = 0x01; + rawBytes = destIP.GetAddressBytes(); + rawBytes.CopyTo(request, nIndex); + nIndex += (ushort)rawBytes.Length; + break; + case AddressFamily.InterNetworkV6: + // Address is IPV6 format + request[nIndex++] = 0x04; + rawBytes = destIP.GetAddressBytes(); + rawBytes.CopyTo(request, nIndex); + nIndex += (ushort)rawBytes.Length; + break; + } + } + else + { + // Dest. address is domain name. + request[nIndex++] = 0x03; // Address is full-qualified domain name. + request[nIndex++] = Convert.ToByte(destAddress.Length); // length of address. + rawBytes = Encoding.UTF8.GetBytes(destAddress); + rawBytes.CopyTo(request, nIndex); + nIndex += (ushort)rawBytes.Length; + } + + // using big-edian byte order + byte[] portBytes = BitConverter.GetBytes(destPort); + for (int i = portBytes.Length - 1; i >= 0; i--) + request[nIndex++] = portBytes[i]; + + // send connect request. + Send(s, request, 0, nIndex); + nGot = Receive(s, response, 0, response.Length); + + if (response[1] != 0x00) + throw new ConnectionException(errorMsgs[response[1]]); + // Success Connected... + return s; + } +#endif + } + + public class ConnectionException : Exception + { + public ConnectionException(string message) + : base(message) + { + } + } + + public static class NetworkConverter + { + public static bool IsLoopBackForIPv4(string ipv4) + { + var data = GetBytesForIPv4(ipv4); + return data[3] == 1 && data[0] == 127 && data[1] == 0 && data[2] == 0; + } + + public static bool IsLoopBackForIPv6(string ipv6) + { + var data = GetWordsForIPv6(ipv6); + return IsLoopBackForIPv6(data); + } + + public static bool IsLoopBack(this HostName hostName) + { + switch (hostName.Type) + { + case HostNameType.Ipv4: + return IsLoopBackForIPv4(hostName.CanonicalName); + case HostNameType.Ipv6: + return IsLoopBackForIPv6(hostName.CanonicalName); + } + + throw new NotSupportedException(); + } + + public static bool IsLoopBackForIPv6(ushort[] data) + { + for (var i = 0; i != 5; ++i) + if (data[i] != 0) + return false; + if (data[5] == 0) + return data[6] == 0 && data[7] == 1; + if (data[5] != 0xFFFF) + return false; + return data[6] == 0x7F00 && data[7] == 1; + } + + public static byte[] GetPortBytes(int port) + { + var portBytes = BitConverter.GetBytes((ushort)port); + if (BitConverter.IsLittleEndian) + Array.Reverse(portBytes); + return portBytes; + } + + public static int ToPort(byte[] data) + { + if (BitConverter.IsLittleEndian) + Array.Reverse(data); + return BitConverter.ToUInt16(data, 0); + } + + public static byte[] GetAddressBytes(this HostName hostName) + { + switch (hostName.Type) + { + case HostNameType.Ipv4: + return GetBytesForIPv4(hostName.CanonicalName); + case HostNameType.Ipv6: + return GetBytesForIPv6(hostName.CanonicalName); + } + throw new NotSupportedException(); + } + + public static byte[] GetBytesForIPv6(string ipv6) + { + var result = new byte[16]; + var idxDst = 0; + var words = GetWordsForIPv6(ipv6); + for (var idxSrc = 0; idxSrc != words.Length; ++idxSrc) + { + var v = words[idxSrc]; + result[idxDst++] = (byte)((v >> 8) & 0xFF); + result[idxDst++] = (byte)(v & 0xFF); + } + + return result; + } + + public static byte[] GetBytesForIPv4(string ipv4) + { + var result = ipv4.Split('.').Select(byte.Parse) + .ToArray(); + return result; + } + + public static ushort[] GetWordsForIPv6(string ipv6) + { + var data = new ushort[8]; + ipv6 = ipv6.Replace(" ", string.Empty); + if (ipv6.StartsWith("::ffff:")) + { + data[5] = 0xFFFF; + var ipv4 = ipv6.Substring(7); + if (ipv4.IndexOf(':') != -1) + { + var parts = ipv4.Split(':') + .Select(x => ushort.Parse(x, System.Globalization.NumberStyles.HexNumber)) + .ToArray(); + data[6] = parts[0]; + data[7] = parts[1]; + } + else + { + var d = GetBytesForIPv4(ipv4); + data[6] = (ushort)((d[0] << 8) + d[1]); + data[7] = (ushort)((d[2] << 8) + d[3]); + } + } + else + { + var parts = ipv6.Split(':') + .Select(x => string.IsNullOrWhiteSpace(x) ? -1 : int.Parse(x, System.Globalization.NumberStyles.HexNumber)) + .ToArray(); + var prefixSize = Array.IndexOf(parts, -1); + if (prefixSize == -1) + { + if (parts.Length != 8) + throw new ArgumentOutOfRangeException(); + data = parts.Select(x => (ushort)x).ToArray(); + } + else + { + var nonEmptyIndex = prefixSize; + while (nonEmptyIndex < (parts.Length - 1) && parts[nonEmptyIndex + 1] == -1) + nonEmptyIndex += 1; + var suffixSize = parts.Length - nonEmptyIndex - 1; + for (var i = 0; i != prefixSize; ++i) + data[i] = (ushort)parts[i]; + var suffixIndexSrc = parts.Length - suffixSize; + var suffixIndexDst = data.Length - suffixSize; + for (var i = 0; i != suffixSize; ++i) + data[suffixIndexDst++] = (ushort)parts[suffixIndexSrc++]; + } + } + + return data; + } + + public static string ToIPv4(byte[] data) + { + return string.Join(".", data.Reverse().Select(x => x.ToString())); + } + + public static string ToIPv6(byte[] data) + { + var words = new ushort[8]; + var idxDst = 0; + for (var idxSrc = 0; idxSrc != data.Length; idxSrc += 2) + words[idxDst++] = (ushort)((data[idxSrc] << 8) + data[idxSrc + 1]); + return ToIPv6(words); + } + + public static string ToIPv6(ushort[] data) + { + var zeroRanges = new List>(); + var startIndex = -1; + var indexCount = 0; + for (var i = 0; i != 8; ++i) + { + var v = data[i]; + if (v == 0) + { + if (startIndex == -1) + { + startIndex = i; + indexCount = 1; + } + else + indexCount += 1; + } + else if (v != 0 && startIndex != -1) + { + zeroRanges.Add(Tuple.Create(startIndex, indexCount)); + startIndex = -1; + } + } + + if (startIndex != -1) + zeroRanges.Add(Tuple.Create(startIndex, indexCount)); + + if (zeroRanges.Count != 0) + { + var largestRange = zeroRanges.OrderByDescending(x => x.Item2).First(); + startIndex = largestRange.Item1; + indexCount = largestRange.Item2; + } + + ushort[] wordsPrefix, wordsSuffix; + if (startIndex != -1) + { + wordsPrefix = data.Take(startIndex).ToArray(); + wordsSuffix = data.Skip(startIndex + indexCount).ToArray(); + } + else + { + wordsPrefix = data; + wordsSuffix = null; + } + + var result = new StringBuilder(); + if (wordsPrefix.Length != 0) + result.Append(string.Join(":", wordsPrefix.Select(x => x.ToString("x")))); + if (wordsSuffix != null) + result + .Append("::") + .Append(string.Join(":", wordsSuffix.Select(x => x.ToString("x")))); + return result.ToString(); + } + } +} diff --git a/Telegram.Api/Transport/TCPTransport.cs b/Telegram.Api/Transport/TCPTransport.cs new file mode 100755 index 0000000..dfae758 --- /dev/null +++ b/Telegram.Api/Transport/TCPTransport.cs @@ -0,0 +1,413 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define TCP_OBFUSCATED_2 +using System; +using System.Globalization; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; +using Action = System.Action; +using SocketError = System.Net.Sockets.SocketError; + +namespace Telegram.Api.Transport +{ + public class TcpTransport : TcpTransportBase + { + private readonly object _isConnectedSocketRoot = new object(); + + private readonly object _encryptedStreamSyncRoot = new object(); + + private readonly Socket _socket; + + private const int BufferSize = 64; + + private readonly byte[] _buffer; + + private readonly SocketAsyncEventArgs _listener = new SocketAsyncEventArgs(); + + private readonly IPAddress _address; + + public TcpTransport(string host, int port, string staticHost, int staticPort, MTProtoTransportType mtProtoType, TLProxyConfigBase proxyConfig) + : base(host, port, staticHost, staticPort, mtProtoType, proxyConfig) + { + // ipv6 support + _address = proxyConfig != null && !proxyConfig.IsEmpty + ? IPAddress.Parse(staticHost) + : IPAddress.Parse(host); + + _socket = new Socket(_address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + + _buffer = new byte[BufferSize]; + _listener.SetBuffer(_buffer, 0, _buffer.Length); + _listener.Completed += OnReceived; + } + + public override string GetTransportInfo() + { + var info = new StringBuilder(); + info.AppendLine("TCP transport"); + info.AppendLine(string.Format("Socket {0}:{1}, Connected={2}, Ttl={3}, HashCode={4}", Host, Port, _socket.Connected, _socket.Ttl, _socket.GetHashCode())); + info.AppendLine(string.Format("Listener LastOperation={0}, SocketError={1}, RemoteEndPoint={2}, SocketHash={3}", _listener.LastOperation, _listener.SocketError, _listener.RemoteEndPoint, _listener.ConnectSocket != null ? _listener.ConnectSocket.GetHashCode().ToString() : "null")); + info.AppendLine(string.Format("FirstReceiveTime={0}", FirstReceiveTime.GetValueOrDefault().ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture))); + info.AppendLine(string.Format("FirstSendTime={0}", FirstSendTime.GetValueOrDefault().ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture))); + info.AppendLine(string.Format("LastSendTime={0}", LastSendTime.GetValueOrDefault().ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture))); + + return info.ToString(); + } + + public override void SendPacketAsync(string caption, byte[] data, Action callback, Action faultCallback = null) + { + var now = DateTime.Now; + if (!FirstSendTime.HasValue) + { + FirstSendTime = now; + } + LastSendTime = now; + + Execute.BeginOnThreadPool(() => + { + TLUtils.WriteLine(" TCP: Send " + caption); + + lock (_isConnectedSocketRoot) + { + var manualResetEvent = new ManualResetEvent(false); + if (!_socket.Connected) + { + if (caption.StartsWith("msgs_ack")) + { + TLUtils.WriteLine("!!!!!!MSGS_ACK FAULT!!!!!!!", LogSeverity.Error); + faultCallback.SafeInvoke(new TcpTransportResult(SocketAsyncOperation.Send, new Exception("MSGS_ACK_FAULT"))); + return; + } + + ConnectAsync(() => + { + manualResetEvent.Set(); + + try + { + lock (_encryptedStreamSyncRoot) + { + var args = CreateArgs(data, callback); + _socket.SendAsync(args); + } + } + catch (Exception ex) + { + faultCallback.SafeInvoke(new TcpTransportResult(SocketAsyncOperation.Send, ex)); + + WRITE_LOG("Socket.ConnectAsync SendAsync[1]", ex); + } + }, + error => + { + manualResetEvent.Set(); + faultCallback.SafeInvoke(error); + }); + + var connected = manualResetEvent.WaitOne(25000); + if (!connected) + { + faultCallback.SafeInvoke(new TcpTransportResult(SocketAsyncOperation.Connect, new Exception("Connect timeout exception 25s"))); + } + } + else + { + try + { + lock (_encryptedStreamSyncRoot) + { + var args = CreateArgs(data, callback); + _socket.SendAsync(args); + } + } + catch (Exception ex) + { + faultCallback.SafeInvoke(new TcpTransportResult(SocketAsyncOperation.Send, ex)); + + WRITE_LOG("Socket.SendAsync[1]", ex); + } + } + } + }); + } + + private SocketAsyncEventArgs CreateArgs(byte[] data, Action callback = null) + { + var packet = CreatePacket(data); + +#if TCP_OBFUSCATED_2 + packet = Encrypt(packet); +#endif + + var args = new SocketAsyncEventArgs(); + args.SetBuffer(packet, 0, packet.Length); + args.Completed += (sender, eventArgs) => + { + callback.SafeInvoke(eventArgs.SocketError == SocketError.Success); + }; + return args; + } + + private void ConnectAsync(Action callback, Action faultCallback) + { + WRITE_LOG(string.Format("Socket.ConnectAsync[#3] {0} ({1}:{2})", Id, Host, Port)); + + TLSocks5Proxy socks5Proxy = ProxyConfig != null && ProxyConfig.IsEnabled.Value && !ProxyConfig.IsEmpty + ? ProxyConfig.GetProxy() as TLSocks5Proxy + : null; + + if (socks5Proxy != null) + { + try + { + ActualHost = StaticHost; + ActualPort = StaticPort; + + RaiseConnectingAsync(); + + SocksProxy.ConnectToSocks5Proxy(_socket, socks5Proxy.Server.ToString(), (ushort)socks5Proxy.Port.Value, StaticHost, (ushort)StaticPort, socks5Proxy.Username.ToString(), socks5Proxy.Password.ToString()); + + OnConnected(new SocketAsyncEventArgs { SocketError = SocketError.Success }, callback, faultCallback); + } + catch (Exception ex) + { + faultCallback.SafeInvoke(new TcpTransportResult(SocketAsyncOperation.Connect, ex)); + + WRITE_LOG("Socket.ConnectAsync[#3]", ex); + } + } + else + { + System.Diagnostics.Debug.WriteLine(" Connecting mtproto=[server={0} port={1}]", Host, Port); + + var args = new SocketAsyncEventArgs + { + RemoteEndPoint = new IPEndPoint(_address, Port) + }; + + args.Completed += (o, e) => OnConnected(e, callback, faultCallback); + + try + { + ActualHost = Host; + ActualPort = Port; + + RaiseConnectingAsync(); + _socket.ConnectAsync(args); + } + catch (Exception ex) + { + faultCallback.SafeInvoke(new TcpTransportResult(SocketAsyncOperation.Connect, ex)); + + WRITE_LOG("Socket.ConnectAsync[#3]", ex); + } + } + } + +#if TCP_OBFUSCATED_2 + protected override byte[] GetInitBuffer() + { + var buffer = new byte[64]; + var random = new Random(); + while (true) + { + random.NextBytes(buffer); + + var val = (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | (buffer[0]); + var val2 = (buffer[7] << 24) | (buffer[6] << 16) | (buffer[5] << 8) | (buffer[4]); + if (buffer[0] != 0xef + && val != 0x44414548 + && val != 0x54534f50 + && val != 0x20544547 + && val != 0x4954504f + && val != 0xeeeeeeee + && val2 != 0x00000000) + { + buffer[56] = buffer[57] = buffer[58] = buffer[59] = 0xef; + break; + } + } + + var keyIvEncrypt = buffer.SubArray(8, 48); + EncryptKey = keyIvEncrypt.SubArray(0, 32); + EncryptIV = keyIvEncrypt.SubArray(32, 16); + + Array.Reverse(keyIvEncrypt); + DecryptKey = keyIvEncrypt.SubArray(0, 32); + DecryptIV = keyIvEncrypt.SubArray(32, 16); + + var encryptedBuffer = Encrypt(buffer); + for (var i = 56; i < encryptedBuffer.Length; i++) + { + buffer[i] = encryptedBuffer[i]; + } + + return buffer; + } +#endif + + private void OnConnected(SocketAsyncEventArgs args, Action callback = null, Action faultCallback = null) + { + WRITE_LOG(string.Format("Socket.OnConnected[#4] {0} socketError={1}", Id, args.SocketError)); + + try + { + if (args.SocketError != SocketError.Success) + { + faultCallback.SafeInvoke(new TcpTransportResult(SocketAsyncOperation.Connect, args.SocketError)); + } + else + { + RaiseConnectedAsync(); + + ReceiveAsync(); + + try + { + lock (_encryptedStreamSyncRoot) + { + var buffer = GetInitBuffer(); + + var sendArgs = new SocketAsyncEventArgs(); + sendArgs.SetBuffer(buffer, 0, buffer.Length); + sendArgs.Completed += (o, e) => callback.SafeInvoke(); + + _socket.SendAsync(sendArgs); + } + } + catch (Exception ex) + { + faultCallback.SafeInvoke(new TcpTransportResult(SocketAsyncOperation.Send, ex)); + + WRITE_LOG("Socket.OnConnected[#4]", ex); + } + } + + } + catch (Exception ex) + { + faultCallback.SafeInvoke(new TcpTransportResult(SocketAsyncOperation.Connect, ex)); + + WRITE_LOG("Socket.OnConnected[#4] SendAsync", ex); + } + } + + private void ReceiveAsync() + { + if (Closed) + { + //Execute.ShowDebugMessage("TCPTransport ReceiveAsync closed=true"); + return; + } + + try + { + if (_socket != null) + { + if (_socket.Connected) + { + try + { + _socket.ReceiveAsync(_listener); + } + catch (Exception ex) + { + WRITE_LOG("Socket.ReceiveAsync[#5] ReceiveAsync", ex); + + if (ex is ObjectDisposedException) + { + return; + } + } + } + else + { + //Execute.ShowDebugMessage("TCPTransport ReceiveAsync socket.Connected=false"); + //throw new Exception("Socket is not connected"); + } + } + else + { + throw new NullReferenceException("Socket is null"); + } + } + catch (Exception ex) + { + WRITE_LOG("Socket.ReceiveAsync[#5]", ex); + } + } + + private void OnReceived(object sender, SocketAsyncEventArgs e) + { + var socket = sender as Socket; + if (socket == null || socket != _socket) + { + return; + } + + if (e.SocketError != SocketError.Success) + { + //Log.Write(string.Format(" TCPTransport.OnReceived transport={0} error={1}", Id, e.SocketError)); + Execute.ShowDebugMessage(string.Format("!!!TCPTransport OnReceived connection lost; BytesTransferred={0} SocketError={1}", e.BytesTransferred, e.SocketError)); + ReceiveAsync(); + return; + } + + if (e.BytesTransferred > 0) + { + //Log.Write(string.Format(" TCPTransport.OnReceived transport={0} bytes_transferred={1}", Id, e.BytesTransferred)); + var now = DateTime.Now; + + if (!FirstReceiveTime.HasValue) + { + FirstReceiveTime = now; + } + + LastReceiveTime = now; + + // AES-CTR decrypt +#if TCP_OBFUSCATED_2 + var buffer = e.Buffer.SubArray(e.Offset, e.BytesTransferred); + buffer = Decrypt(buffer); + OnBufferReceived(buffer, 0, buffer.Length); +#else + OnBufferReceived(e.Buffer, e.Offset, e.BytesTransferred); +#endif + } + else + { + Closed = true; + RaiseConnectionLost(); + //Log.Write(" TCPTransport.Recconect reason=BytesTransferred=0 transport=" + Id); + //Execute.ShowDebugMessage(string.Format("TCPTransport id={0} dc_id={1} hash={2} OnReceived connection lost bytesTransferred=0; close transport; error={3}", Id, DCId, GetHashCode(), e.SocketError)); + } + + ReceiveAsync(); + } + + public override void Close() + { + WRITE_LOG(string.Format("Close socket {2} {0}:{1}", Host, Port, Id)); + + if (_socket != null) + { + _socket.Close(); + Closed = true; + } + + StopCheckConfigTimer(); + } + + public DateTime? LastSendTime { get; protected set; } + } +} diff --git a/Telegram.Api/Transport/TCPTransportBase.cs b/Telegram.Api/Transport/TCPTransportBase.cs new file mode 100755 index 0000000..4fea81b --- /dev/null +++ b/Telegram.Api/Transport/TCPTransportBase.cs @@ -0,0 +1,690 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define TCP_OBFUSCATED_2 +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.Services; +using Telegram.Api.TL; +using TransportType = Telegram.Api.Services.TransportType; + +namespace Telegram.Api.Transport +{ + public abstract class TcpTransportBase : ITransport + { + public virtual ulong Ping + { + get { return 0; } + } + + public MTProtoTransportType MTProtoType { get; protected set; } + + public long MinMessageId { get; set; } + public Dictionary MessageIdDict { get; set; } + + public string Host { get; protected set; } + public int Port { get; protected set; } + public string StaticHost { get; protected set; } + public int StaticPort { get; protected set; } + public string ActualHost { get; protected set; } + public int ActualPort { get; protected set; } + public TLProxyConfigBase ProxyConfig { get; protected set; } + public virtual TransportType Type { get { return TransportType.Tcp; } } + + private readonly Timer _timer; + + protected TcpTransportBase(string host, int port, string staticHost, int staticPort, MTProtoTransportType mtProtoType, TLProxyConfigBase proxyConfig) + { + MessageIdDict = new Dictionary(); + + Host = host; + Port = port; + StaticHost = staticHost; + StaticPort = staticPort; + MTProtoType = mtProtoType; + ProxyConfig = proxyConfig; + + var random = new Random(); + Id = random.Next(0, 255); + + _timer = new Timer(OnTimerTick, _timer, Timeout.Infinite, Timeout.Infinite); + } + + #region Check Config + + public event EventHandler CheckConfig; + + protected virtual void RaiseCheckConfig() + { + Execute.BeginOnThreadPool(() => + { + var handler = CheckConfig; + if (handler != null) handler(this, EventArgs.Empty); + }); + } + + private void OnTimerTick(object state) + { + _timer.Change(Timeout.Infinite, Timeout.Infinite); + + RaiseCheckConfig(); + } + + protected void StartCheckConfigTimer() + { + if (MTProtoType != MTProtoTransportType.Main) return; + + _timer.Change(TimeSpan.FromSeconds(Constants.CheckConfigTimeout), Timeout.InfiniteTimeSpan); + } + + protected void StopCheckConfigTimer() + { + _timer.Change(Timeout.Infinite, Timeout.Infinite); + } + #endregion + + public bool Initiated { get; set; } + public bool Initialized { get; set; } + public bool IsInitializing { get; set; } + public bool IsAuthorized { get; set; } + public bool IsAuthorizing { get; set; } + public bool Closed { get; protected set; } + + private readonly object _syncRoot = new object(); + public object SyncRoot { get { return _syncRoot; } } + + public int Id { get; protected set; } + public int DCId { get; set; } + public byte[] Secret { get; set; } + public byte[] AuthKey { get; set; } + public TLLong SessionId { get; set; } + public TLLong Salt { get; set; } + + private int _sequenceNumber; + + public int SequenceNumber + { + get { return _sequenceNumber; } + set + { + _sequenceNumber = value; + } + } + + private long _clientTicksDelta; + public long ClientTicksDelta + { + get + { + return _clientTicksDelta; + } + set + { + _clientTicksDelta = value; + } + } + + private bool _once; + + public void UpdateTicksDelta(TLLong msgId) + { + if (_once) return; // to avoid lock + + lock (SyncRoot) + { + if (_once) return; + _once = true; + + var clientTime = GenerateMessageId().Value; + var serverTime = msgId.Value; + ClientTicksDelta += serverTime - clientTime; + } + //Execute.ShowDebugMessage("ITransport.UpdateTicksDelta dc_id=" + DCId); + } + + public abstract void SendPacketAsync(string caption, byte[] data, Action callback, Action faultCallback = null); + public abstract void Close(); + + public int PacketLength { get { return _packetLength; } } + + private int _lastPacketLength; + + public int LastPacketLength { get { return _lastPacketLength; } } + + + public WindowsPhone.Tuple GetCurrentPacketInfo() + { + return new WindowsPhone.Tuple(_packetLengthBytesRead, _packetLength, _bytesReceived); + } + + public abstract string GetTransportInfo(); + + public DateTime? FirstSendTime { get; protected set; } + public DateTime? FirstReceiveTime { get; protected set; } + public DateTime? LastReceiveTime { get; protected set; } + + protected static byte[] CreatePacket(byte[] buffer) + { + const int maxShortLength = 0x7E; + var shortLength = buffer.Length / 4; + var length = (shortLength > maxShortLength) ? 4 + buffer.Length : 1 + buffer.Length; + var bytes = new byte[length]; + + if (shortLength > maxShortLength) + { + bytes[0] = 0x7F; + var shortLengthBytes = BitConverter.GetBytes(shortLength); + Array.Copy(shortLengthBytes, 0, bytes, 1, 3); + Array.Copy(buffer, 0, bytes, 4, buffer.Length); + } + else + { + bytes[0] = (byte)shortLength; + Array.Copy(buffer, 0, bytes, 1, buffer.Length); + } + + return bytes; + } + + protected static int GetPacketLength(byte[] bytes, int position, out int bytesRead) + { + if (bytes.Length <= position) + { + if (bytes.Length != 0 && position != 0) + { + Execute.ShowDebugMessage("TCPTransport.0x7F l<=p p=" + position + " l=" + bytes.Length); + } + bytesRead = 0; + return 0; + } + + int shortLength; + if (bytes[position] == 0x7F) + { + if (bytes.Length < (position + 1 + 3)) + { + Execute.ShowDebugMessage("TCPTransport.0x7F error p=" + position + " l=" + bytes.Length); + } + + var lengthBytes = bytes.SubArray(1 + position, 3); + + shortLength = BitConverter.ToInt32(TLUtils.Combine(lengthBytes, new byte[] { 0x00 }), 0); + bytesRead = 4; + } + else + { + //Execute.ShowDebugMessage("TCPTransport.!=0x7F " + position); + + shortLength = bytes[position]; + bytesRead = 1; + } + + return shortLength * 4; + } + + protected virtual byte[] GetInitBuffer() + { + var buffer = new byte[64]; + var random = new Random(); + while (true) + { + random.NextBytes(buffer); + + var val = (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | (buffer[0]); + var val2 = (buffer[7] << 24) | (buffer[6] << 16) | (buffer[5] << 8) | (buffer[4]); + if (buffer[0] != 0xef + && val != 0x44414548 + && val != 0x54534f50 + && val != 0x20544547 + && val != 0x4954504f + && val != 0xeeeeeeee + && val2 != 0x00000000) + { + buffer[56] = buffer[57] = buffer[58] = buffer[59] = 0xef; + break; + } + } + + return buffer; + } + + private int _bytesReceived; + private int _packetLength = 0; + private byte[] _previousTail = new byte[0]; + private bool _usePreviousTail; + private int _packetLengthBytesRead = 0; + readonly MemoryStream _stream = new MemoryStream(32 * 1024); + + protected void OnBufferReceived(byte[] buffer, int offset, int bytesTransferred) + { + if (bytesTransferred > 0) + { + StopCheckConfigTimer(); + + _bytesReceived += bytesTransferred; + + if (_packetLength == 0) + { + byte[] fullBuffer; + + if (_usePreviousTail) + { + _usePreviousTail = false; + fullBuffer = TLUtils.Combine(_previousTail, buffer); + _previousTail = new byte[0]; + } + else + { + fullBuffer = buffer; + } + + _packetLength = GetPacketLength(fullBuffer, offset, out _packetLengthBytesRead); + } + + _stream.Write(buffer, offset, bytesTransferred); + + if (_bytesReceived >= _packetLength + _packetLengthBytesRead) + { + var bytes = _stream.ToArray(); + + var data = bytes.SubArray(_packetLengthBytesRead, _packetLength); + _previousTail = new byte[] { }; + if (_bytesReceived > _packetLength + _packetLengthBytesRead) + { + _previousTail = bytes.SubArray(_packetLengthBytesRead + _packetLength, _bytesReceived - (_packetLengthBytesRead + _packetLength)); + } + + _stream.SetLength(0); + _stream.Write(_previousTail, 0, _previousTail.Length); + _bytesReceived = _previousTail.Length; + + if (_previousTail.Length > 0) + { + if (_previousTail.Length >= 4) + { + _packetLength = GetPacketLength(_previousTail, 0, out _packetLengthBytesRead); + + if (_packetLength != 0 + && _previousTail.Length >= _packetLength + _packetLengthBytesRead) + { + Execute.ShowDebugMessage("TCPTransport.0x7F forgot package length=" + _packetLength + " tail=" + _previousTail.Length); + } + } + else + { + _packetLengthBytesRead = 0; + _packetLength = 0; + _usePreviousTail = true; + } + } + else + { + _packetLength = GetPacketLength(_previousTail, 0, out _packetLengthBytesRead); + } + _lastPacketLength = data.Length; + + + + if (MinMessageId == 0 && AuthKey != null) + { + SetMinMessageId(data); + } + RaisePacketReceived(new DataEventArgs(data, PacketLength, LastReceiveTime)); + } + } + else + { + Execute.ShowDebugMessage("TCP bytesTransferred=" + bytesTransferred); + } + } + + private void SetMinMessageId(byte[] bytes) + { + try + { + var position = 0; + var encryptedMessage = (TLEncryptedTransportMessage)new TLEncryptedTransportMessage().FromBytes(bytes, ref position); + encryptedMessage.Decrypt(AuthKey); + + position = 0; + TLTransportMessage transportMessage; + transportMessage = TLObject.GetObject(encryptedMessage.Data, ref position); + + MinMessageId = transportMessage.MessageId.Value; + System.Diagnostics.Debug.WriteLine("TCPTransport set min message_id={0} seq_no={1}", transportMessage.MessageId, transportMessage.SeqNo); + } + catch (Exception ex) + { + Execute.ShowDebugMessage("SetMessageId exception " + ex); + } + } + + #region MessageId + private static readonly object _messageIdRoot = new object(); + + public static long PreviousMessageId; + + public TLLong GenerateMessageId(bool checkPreviousMessageId = false) + { + long correctUnixTime; + lock (_messageIdRoot) + { + var clientDelta = ClientTicksDelta; + // serverTime = clientTime + clientDelta + var now = DateTime.Now; + //var unixTime = (long)Utils.DateTimeToUnixTimestamp(now) << 32; + + var unixTime = (long)(Utils.DateTimeToUnixTimestamp(now) * 4294967296) + clientDelta; //2^32 + + var addingTicks = 4 - (unixTime % 4); + if ((unixTime % 4) == 0) + { + correctUnixTime = unixTime; + } + else + { + correctUnixTime = unixTime + addingTicks; + } + + // check with previous messageId + if (PreviousMessageId != 0 && checkPreviousMessageId) + { + correctUnixTime = Math.Max(PreviousMessageId + 4, correctUnixTime); + } + PreviousMessageId = correctUnixTime; + } + + if (correctUnixTime == 0) + throw new Exception("Bad message id"); + + return new TLLong(correctUnixTime); + } + #endregion + + #region NonEncryptedHistory + + private readonly object _nonEncryptedHistoryRoot = new object(); + + private readonly Dictionary _nonEncryptedHistory = new Dictionary(); + + public void EnqueueNonEncryptedItem(HistoryItem item) + { + lock (_nonEncryptedHistoryRoot) + { + _nonEncryptedHistory[item.Hash] = item; + } +#if LOG_REGISTRATION + var info = new StringBuilder(); + info.AppendLine(String.Format("Socket.EnqueueNonEncryptedItem {0} item {1} hash={2}", Id, item.Caption, item.Hash)); + info.AppendLine("Items: " + _nonEncryptedHistory.Count); + foreach (var historyItem in _nonEncryptedHistory.Values) + { + info.AppendLine(historyItem.Caption + " " + historyItem.Hash); + } + TLUtils.WriteLog(info.ToString()); +#endif + } + + public IList RemoveTimeOutRequests(double timeout = Constants.TimeoutInterval) + { + var now = DateTime.Now; + var timedOutKeys = new List(); + var timedOutValues = new List(); + + lock (_nonEncryptedHistoryRoot) + { + foreach (var historyKeyValue in _nonEncryptedHistory) + { + var historyValue = historyKeyValue.Value; + if (historyValue.SendTime != default(DateTime) + && historyValue.SendTime.AddSeconds(timeout) < now) + { + timedOutKeys.Add(historyKeyValue.Key); + timedOutValues.Add(historyKeyValue.Value); + } + } + + if (timedOutKeys.Count > 0) + { +#if LOG_REGISTRATION + var info = new StringBuilder(); + info.AppendLine(String.Format("Socket.RemoveTimeOutRequests {0}", Id)); + info.AppendLine("Items before: " + _nonEncryptedHistory.Count); + foreach (var historyItem in _nonEncryptedHistory.Values) + { + info.AppendLine(historyItem.Caption + " " + historyItem.Hash); + } +#endif + foreach (var key in timedOutKeys) + { + _nonEncryptedHistory.Remove(key); + } +#if LOG_REGISTRATION + info.AppendLine("Items after: " + _nonEncryptedHistory.Count); + foreach (var historyItem in _nonEncryptedHistory.Values) + { + info.AppendLine(historyItem.Caption + " " + historyItem.Hash); + } + TLUtils.WriteLog(info.ToString()); +#endif + } + } + + return timedOutValues; + } + + public HistoryItem DequeueFirstNonEncryptedItem() + { + HistoryItem item; + lock (_nonEncryptedHistoryRoot) + { + item = _nonEncryptedHistory.Values.FirstOrDefault(); + if (item != null) + { + _nonEncryptedHistory.Remove(item.Hash); + } + } + + return item; + } + + public bool RemoveNonEncryptedItem(HistoryItem item) + { + bool result; + lock (_nonEncryptedHistoryRoot) + { +#if LOG_REGISTRATION + var info = new StringBuilder(); + info.AppendLine(String.Format("Socket.RemoveNonEncryptedItem {0} item {1} hash={2}", Id, item.Caption, item.Hash)); + info.AppendLine("Items before: " + _nonEncryptedHistory.Count); + foreach (var historyItem in _nonEncryptedHistory.Values) + { + info.AppendLine(historyItem.Caption + " " + historyItem.Hash); + } +#endif + + result = _nonEncryptedHistory.Remove(item.Hash); + +#if LOG_REGISTRATION + info.AppendLine("Items after: " + _nonEncryptedHistory.Count); + foreach (var historyItem in _nonEncryptedHistory.Values) + { + info.AppendLine(historyItem.Caption + " " + historyItem.Hash); + } + TLUtils.WriteLog(info.ToString()); +#endif + } + + return result; + } + + public void ClearNonEncryptedHistory(Exception e = null) + { + lock (_nonEncryptedHistoryRoot) + { + var error = new StringBuilder(); + error.Append(String.Format("Socket.ClearNonEncryptedHistory {0} count={1}", Id, _nonEncryptedHistory.Count)); + if (e != null) + { + error.AppendLine(e.ToString()); + } + +#if LOG_REGISTRATION + TLUtils.WriteLog(error.ToString()); +#endif + + foreach (var historyItem in _nonEncryptedHistory) + { +#if LOG_REGISTRATION + TLUtils.WriteLog(String.Format("Socket.ClearNonEncryptedHistory {0} item {1}", Id, historyItem.Value.Caption)); +#endif + historyItem.Value.FaultCallback.SafeInvoke(new TLRPCError { Code = new TLInt(404), Message = new TLString(error.ToString()) }); + } + + _nonEncryptedHistory.Clear(); + } + } + + public string PrintNonEncryptedHistory() + { + var sb = new StringBuilder(); + + lock (_nonEncryptedHistoryRoot) + { + sb.AppendLine("NonEncryptedHistory items:"); + foreach (var historyItem in _nonEncryptedHistory.Values) + { + sb.AppendLine(historyItem.Caption + " msgId " + historyItem.Hash); + } + } + + return sb.ToString(); + } + #endregion + + #region Events + public event EventHandler PacketReceived; + + protected virtual void RaisePacketReceived(DataEventArgs args) + { + var handler = PacketReceived; + if (handler != null) + { + Execute.BeginOnThreadPool(() => + { + handler(this, args); + }); + } + } + + public event EventHandler Connecting; + + private bool _connectingRaised; + + protected virtual void RaiseConnectingAsync() + { + if (_connectingRaised) return; + _connectingRaised = true; + + StartCheckConfigTimer(); + + var handler = Connecting; + if (handler != null) + { + Execute.BeginOnThreadPool(() => handler(this, EventArgs.Empty)); + } + } + + public event EventHandler Connected; + + protected virtual void RaiseConnectedAsync() + { + var handler = Connected; + if (handler != null) + { + Execute.BeginOnThreadPool(() => handler(this, EventArgs.Empty)); + } + } + + public event EventHandler ConnectionLost; + + protected virtual void RaiseConnectionLost() + { + var handler = ConnectionLost; + if (handler != null) + { + Execute.BeginOnThreadPool(() => handler(this, EventArgs.Empty)); + } + } + + #endregion + + public override string ToString() + { + return String.Format("Id={0} {1}) {2}:{3} (AuthKey {4})\n Salt {5}\n SessionId {6} TicksDelta {7}", Id, DCId, Host, Port, AuthKey != null, Salt, SessionId, ClientTicksDelta); + } + + protected virtual void WRITE_LOG(string str) + { +#if LOG_REGISTRATION + TLUtils.WriteLog(str); +#endif + } + + protected virtual void WRITE_LOG(string str, Exception ex) + { + var type = ex != null ? ex.GetType().Name : "null"; + WRITE_LOG(String.Format("{0} {1} {2}={3}", str, Id, type, ex)); + } + +#if TCP_OBFUSCATED_2 + protected byte[] EncryptKey; + + protected byte[] EncryptIV; + + protected byte[] DecryptKey; + + protected byte[] DecryptIV; + + private byte[] EncryptCountBuf; + + private uint EncryptNum; + + public byte[] Encrypt(byte[] data) + { + if (EncryptCountBuf == null) + { + EncryptCountBuf = new byte[16]; + EncryptNum = 0; + } + + return Utils.AES_ctr128_encrypt(data, EncryptKey, ref EncryptIV, ref EncryptCountBuf, ref EncryptNum); + } + + private byte[] DecryptCountBuf; + + private uint DecryptNum; + + public byte[] Decrypt(byte[] data) + { + if (DecryptCountBuf == null) + { + DecryptCountBuf = new byte[16]; + DecryptNum = 0; + } + + return Utils.AES_ctr128_encrypt(data, DecryptKey, ref DecryptIV, ref DecryptCountBuf, ref DecryptNum); + } +#endif + } +} diff --git a/Telegram.Api/Transport/TCPTransportResult.cs b/Telegram.Api/Transport/TCPTransportResult.cs new file mode 100755 index 0000000..d87cfbe --- /dev/null +++ b/Telegram.Api/Transport/TCPTransportResult.cs @@ -0,0 +1,58 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +#if WINDOWS_PHONE +using System.Net.Sockets; +using SocketError = System.Net.Sockets.SocketError; +#endif +using System.Text; + +namespace Telegram.Api.Transport +{ + public class TcpTransportResult + { +#if WINDOWS_PHONE + public SocketError Error { get; set; } + + public SocketAsyncOperation Operation { get; set; } +#endif + + public Exception Exception { get; set; } + + public TcpTransportResult(Exception exception) + { + Exception = exception; + } + +#if WINDOWS_PHONE + public TcpTransportResult(SocketAsyncOperation operation, SocketError error) + { + Operation = operation; + Error = error; + } + + public TcpTransportResult(SocketAsyncOperation operation, Exception exception) + { + Operation = operation; + Exception = exception; + } +#endif + + public override string ToString() + { + var sb = new StringBuilder(); +#if WINDOWS_PHONE + sb.AppendLine("Operation=" + Operation); + sb.AppendLine("Error=" + Error); +#endif + sb.AppendLine("Exception=" + Exception); + + return sb.ToString(); + } + } +} diff --git a/Telegram.Api/Transport/TransportService.cs b/Telegram.Api/Transport/TransportService.cs new file mode 100755 index 0000000..a25ee9b --- /dev/null +++ b/Telegram.Api/Transport/TransportService.cs @@ -0,0 +1,499 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define NATIVE +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Telegram.Api.Services; +using Telegram.Api.TL; + +namespace Telegram.Api.Transport +{ + public class TransportService : ITransportService + { + public TransportService() + { + + } + + private readonly object _proxyConfigSyncRoot = new object(); + + private TLProxyConfigBase _proxyConfig; + + public TLProxyConfigBase GetProxyConfig() + { + if (_proxyConfig != null) + { + return _proxyConfig; + } + + _proxyConfig = TLUtils.OpenObjectFromMTProtoFile(_proxyConfigSyncRoot, Constants.ProxyConfigFileName) ?? TLProxyConfigBase.Empty; + + _proxyConfig = _proxyConfig.ToLastProxyConfig(); + + return _proxyConfig; + } + + public void SetProxyConfig(TLProxyConfigBase proxyConfig) + { + _proxyConfig = proxyConfig; + + TLUtils.SaveObjectToMTProtoFile(_proxyConfigSyncRoot, Constants.ProxyConfigFileName, _proxyConfig); + } + + private readonly Dictionary _cache = new Dictionary(); + + private readonly Dictionary _fileCache = new Dictionary(); + + private readonly Dictionary _specialCache = new Dictionary(); + + public ITransport GetFileTransport(string host, int port, string staticHost, int staticPort, TransportType type, short protocolDCId, byte[] protocolSecret, out bool isCreated) + { + var key = string.Format("{0} {1} {2} {3}", host, port, protocolDCId, type); + if (_fileCache.ContainsKey(key)) + { + isCreated = false; + return _fileCache[key]; + } + +#if WINDOWS_PHONE + if (type == TransportType.Http) + { + var transport = new HttpTransport(host, MTProtoTransportType.File, GetProxyConfig()); + + _fileCache.Add(key, transport); + isCreated = true; + return transport; + //transport.SetAddress(host, port, () => callback(transport)); + } + else +#endif + { + var transport = +#if WIN_RT + new TcpTransportWinRT(host, port, staticHost, staticPort, MTProtoTransportType.File, GetProxyConfig()); +#elif NATIVE + new NativeTcpTransport(host, port, staticHost, staticPort, MTProtoTransportType.File, protocolDCId, protocolSecret, GetProxyConfig()); +#else + new TcpTransport(host, port, staticHost, staticPort, MTProtoTransportType.File, GetProxyConfig()); +#endif + transport.ConnectionLost += OnConnectionLost; + TLUtils.WritePerformance(string.Format(" TCP: New file transport {0}:{1}", host, port)); + + _fileCache.Add(key, transport); + isCreated = true; + + Debug.WriteLine(" TCP: New transport {0}:{1}", host, port); + return transport; + //trasport.SetAddress(host, port, () => callback(trasport)); + } + } + + private readonly Dictionary _fileCache2 = new Dictionary(); + + public ITransport GetFileTransport2(string host, int port, string staticHost, int staticPort, TransportType type, short protocolDCId, byte[] protocolSecret, out bool isCreated) + { + var key = string.Format("{0} {1} {2} {3}", host, port, protocolDCId, type); + if (_fileCache2.ContainsKey(key)) + { + isCreated = false; + return _fileCache2[key]; + } + +#if WINDOWS_PHONE + if (type == TransportType.Http) + { + var transport = new HttpTransport(host, MTProtoTransportType.File, GetProxyConfig()); + + _fileCache2.Add(key, transport); + isCreated = true; + return transport; + //transport.SetAddress(host, port, () => callback(transport)); + } + else +#endif + { + var transport = +#if WIN_RT + new TcpTransportWinRT(host, port, staticHost, staticPort, MTProtoTransportType.File, GetProxyConfig()); +#elif NATIVE + new NativeTcpTransport(host, port, staticHost, staticPort, MTProtoTransportType.File, protocolDCId, protocolSecret, GetProxyConfig()); +#else + new TcpTransport(host, port, staticHost, staticPort, MTProtoTransportType.File, GetProxyConfig()); +#endif + transport.ConnectionLost += OnConnectionLost; + TLUtils.WritePerformance(string.Format(" TCP: New file transport 2 {0}:{1}", host, port)); + + _fileCache2.Add(key, transport); + isCreated = true; + + Debug.WriteLine(" TCP: New transport {0}:{1}", host, port); + return transport; + //trasport.SetAddress(host, port, () => callback(trasport)); + } + } + + public ITransport GetTransport(string host, int port, string staticHost, int staticPort, TransportType type, short protocolDCId, byte[] protocolSecret, out bool isCreated) + { + var key = string.Format("{0} {1} {2} {3}", host, port, protocolDCId, type); + if (_cache.ContainsKey(key)) + { + isCreated = false; + +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("Old transport {2} {0}:{1}", host, port, _cache[key].Id)); +#endif + return _cache[key]; + } + +#if WINDOWS_PHONE + if (type == TransportType.Http) + { + var transport = new HttpTransport(host, MTProtoTransportType.Main, GetProxyConfig()); + + _cache.Add(key, transport); + isCreated = true; + return transport; + //transport.SetAddress(host, port, () => callback(transport)); + } + else +#endif + { + var transport = +#if WIN_RT + new TcpTransportWinRT(host, port, staticHost, staticPort, MTProtoTransportType.Main, GetProxyConfig()); +#elif NATIVE + new NativeTcpTransport(host, port, staticHost, staticPort, MTProtoTransportType.Main, protocolDCId, protocolSecret, GetProxyConfig()); +#else + new TcpTransport(host, port, staticHost, staticPort, MTProtoTransportType.Main, GetProxyConfig()); +#endif + + transport.Connecting += OnConnecting; + transport.Connected += OnConnected; + transport.ConnectionLost += OnConnectionLost; + transport.CheckConfig += OnCheckConfig; + +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("New transport {2} {0}:{1}", host, port, transport.Id)); +#endif + TLUtils.WritePerformance(string.Format(" TCP: New transport {0}:{1}", host, port)); + + _cache.Add(key, transport); + isCreated = true; + + Debug.WriteLine(" TCP: New transport {0}:{1}", host, port); + return transport; + //trasport.SetAddress(host, port, () => callback(trasport)); + } + } + + public ITransport GetSpecialTransport(string host, int port, string staticHost, int staticPort, TransportType type, short protocolDCId, byte[] protocolSecret, out bool isCreated) + { + var random = TLLong.Random(); // Important! To ping multiple connections to one proxy, will be closed after first ping otherwise + var proxyConfig = GetProxyConfig(); + var proxy = proxyConfig != null ? proxyConfig.GetProxy() : null; + var key = string.Format("{0} {1} {2} {3} {4} {5}", host, port, protocolDCId, type, random, proxy != null ? string.Format("{0}:{1}", proxy.Server, proxy.Port) : string.Empty); + if (_specialCache.ContainsKey(key)) + { + isCreated = false; + +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("Old transport {2} {0}:{1}", host, port, _specialCache[key].Id)); +#endif + return _specialCache[key]; + } + +#if WINDOWS_PHONE + if (type == TransportType.Http) + { + var transport = new HttpTransport(host, MTProtoTransportType.Special, GetProxyConfig()); + + _specialCache.Add(key, transport); + isCreated = true; + return transport; + //transport.SetAddress(host, port, () => callback(transport)); + } + else +#endif + { + var transport = +#if WIN_RT + new TcpTransportWinRT(host, port, staticHost, staticPort, MTProtoTransportType.Special, GetProxyConfig()); +#elif NATIVE + new NativeTcpTransport(host, port, staticHost, staticPort, MTProtoTransportType.Special, protocolDCId, protocolSecret, GetProxyConfig()); +#else + new TcpTransport(host, port, staticHost, staticPort, MTProtoTransportType.Special, GetProxyConfig()); +#endif + transport.Connecting += OnConnecting; + transport.Connected += OnConnected; + transport.ConnectionLost += OnConnectionLost; + transport.CheckConfig += OnCheckConfig; + +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("New transport {2} {0}:{1}", host, port, transport.Id)); +#endif + TLUtils.WritePerformance(string.Format(" TCP: New transport {0}:{1}", host, port)); + + _specialCache.Add(key, transport); + isCreated = true; + + Debug.WriteLine(" TCP: New transport {0}:{1}", host, port); + return transport; + //trasport.SetAddress(host, port, () => callback(trasport)); + } + } + + public ITransport GetSpecialTransport(string host, int port, string staticHost, int staticPort, TransportType type, short protocolDCId, byte[] protocolSecret, TLProxyBase proxy, out bool isCreated) + { + var random = TLLong.Random(); // Important! To ping multiple connections to one proxy, will be closed after first ping otherwise + var key = string.Format("{0} {1} {2} {3} {4} {5}", host, port, protocolDCId, type, random, proxy != null ? string.Format("{0}:{1}", proxy.Server, proxy.Port) : string.Empty); + if (_specialCache.ContainsKey(key)) + { + isCreated = false; + +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("Old transport {2} {0}:{1}", host, port, _specialCache[key].Id)); +#endif + return _specialCache[key]; + } + +#if WINDOWS_PHONE + if (type == TransportType.Http) + { + var transport = new HttpTransport(host, MTProtoTransportType.Special, GetProxyConfig()); + + _specialCache.Add(key, transport); + isCreated = true; + return transport; + //transport.SetAddress(host, port, () => callback(transport)); + } + else +#endif + { + var proxyConfig = new TLProxyConfig76 + { + CustomFlags = new TLLong(0), + IsEnabled = TLBool.True, + SelectedIndex = new TLInt(0), + UseForCalls = TLBool.False, + Items = new TLVector { proxy } + }; + + var transport = +#if WIN_RT + new TcpTransportWinRT(host, port, staticHost, staticPort, MTProtoTransportType.Special, proxyConfig); +#elif NATIVE + new NativeTcpTransport(host, port, staticHost, staticPort, MTProtoTransportType.Special, protocolDCId, protocolSecret, proxyConfig); +#else + new TcpTransport(host, port, staticHost, staticPort, MTProtoTransportType.Special, proxyConfig); +#endif + transport.Connecting += OnConnecting; + transport.Connected += OnConnected; + transport.ConnectionLost += OnConnectionLost; + transport.CheckConfig += OnCheckConfig; + +#if LOG_REGISTRATION + TLUtils.WriteLog(string.Format("New transport {2} {0}:{1}", host, port, transport.Id)); +#endif + TLUtils.WritePerformance(string.Format(" TCP: New transport {0}:{1}", host, port)); + + _specialCache.Add(key, transport); + isCreated = true; + + Debug.WriteLine(" TCP: New transport {0}:{1}", host, port); + return transport; + //trasport.SetAddress(host, port, () => callback(trasport)); + } + } + + public event EventHandler CheckConfig; + + protected virtual void RaiseCheckConfig() + { + var handler = CheckConfig; + if (handler != null) handler(this, EventArgs.Empty); + } + + private void OnCheckConfig(object sender, EventArgs e) + { + var transport = sender as ITransport; + if (transport != null && transport.MTProtoType == MTProtoTransportType.Main) + { + Logs.Log.Write(string.Format("TransportService CheckConfig Transport=[dc_id={0} ip={1} port={2} proxy=[{3}]]", transport.DCId, transport.Host, transport.Port, transport.ProxyConfig)); + + RaiseCheckConfig(); + } + } + + public void Close() + { + var transports = new List(_cache.Values); + foreach (var transport in transports) + { + transport.Connecting -= OnConnecting; + transport.Connected -= OnConnected; + transport.ConnectionLost -= OnConnectionLost; + transport.Close(); + } + _cache.Clear(); + + var fileTransports = new List(_fileCache.Values); + foreach (var transport in fileTransports) + { + transport.Connecting -= OnConnecting; + transport.Connected -= OnConnected; + transport.ConnectionLost -= OnConnectionLost; + transport.Close(); + } + _fileCache.Clear(); + + var fileTransports2 = new List(_fileCache2.Values); + foreach (var transport in fileTransports2) + { + transport.Connecting -= OnConnecting; + transport.Connected -= OnConnected; + transport.ConnectionLost -= OnConnectionLost; + transport.Close(); + } + _fileCache2.Clear(); + + /*var specialTransports = new List(_specialCache.Values); + foreach (var transport in specialTransports) + { + transport.Connecting -= OnConnecting; + transport.Connected -= OnConnected; + transport.ConnectionLost -= OnConnectionLost; + transport.Close(); + } + _specialCache.Clear();*/ + } + + public void CloseTransport(ITransport transport) + { + foreach (var value in _cache.Values.Where(x => string.Equals(x.Host, transport.Host, StringComparison.OrdinalIgnoreCase))) + { + value.Close(); + transport.Connecting -= OnConnecting; + transport.Connected -= OnConnected; + transport.ConnectionLost -= OnConnectionLost; + } + _cache.Remove(string.Format("{0} {1} {2}", transport.Host, transport.Port, transport.Type)); + + foreach (var value in _fileCache.Values.Where(x => string.Equals(x.Host, transport.Host, StringComparison.OrdinalIgnoreCase))) + { + value.Close(); + transport.Connecting -= OnConnecting; + transport.Connected -= OnConnected; + transport.ConnectionLost -= OnConnectionLost; + } + _fileCache.Remove(string.Format("{0} {1} {2}", transport.Host, transport.Port, transport.Type)); + + foreach (var value in _fileCache2.Values.Where(x => string.Equals(x.Host, transport.Host, StringComparison.OrdinalIgnoreCase))) + { + value.Close(); + transport.Connecting -= OnConnecting; + transport.Connected -= OnConnected; + transport.ConnectionLost -= OnConnectionLost; + } + _fileCache2.Remove(string.Format("{0} {1} {2}", transport.Host, transport.Port, transport.Type)); + } + + public void CloseSpecialTransport(ITransport transport) + { + transport.Connecting -= OnConnecting; + transport.Connected -= OnConnected; + transport.ConnectionLost -= OnConnectionLost; + transport.Close(); + + _specialCache.Remove(GetSpecialTransportKey(transport)); + } + + private static string GetSpecialTransportKey(ITransport transport) + { + var proxy = transport.ProxyConfig != null ? transport.ProxyConfig.GetProxy() : null; + return string.Format("{0} {1} {2} {3}", + transport.Host, + transport.Port, + transport.Type, + proxy != null ? string.Format("{0}:{1}", proxy.Server, proxy.Port) : String.Empty); + } + + public event EventHandler TransportConnecting; + + protected virtual void RaiseTransportConnecting(ITransport transport) + { + var handler = TransportConnecting; + if (handler != null) handler(this, new TransportEventArgs { Transport = transport }); + } + + public void OnConnecting(object sender, EventArgs args) + { + RaiseTransportConnecting(sender as ITransport); + } + + public event EventHandler TransportConnected; + + protected virtual void RaiseTransportConnected(ITransport transport) + { + var handler = TransportConnected; + if (handler != null) handler(this, new TransportEventArgs { Transport = transport }); + } + + public void OnConnected(object sender, EventArgs args) + { + RaiseTransportConnected(sender as ITransport); + } + + public event EventHandler ConnectionLost; + + protected virtual void RaiseConnectionLost(ITransport transport) + { + var handler = ConnectionLost; + if (handler != null) handler(this, new TransportEventArgs { Transport = transport }); + } + + public event EventHandler FileConnectionLost; + + protected virtual void RaiseFileConnectionLost(ITransport transport) + { + var handler = FileConnectionLost; + if (handler != null) handler(this, new TransportEventArgs { Transport = transport }); + } + + public event EventHandler SpecialConnectionLost; + + protected virtual void RaiseSpecialConnectionLost(ITransport transport) + { + var handler = SpecialConnectionLost; + if (handler != null) handler(this, new TransportEventArgs { Transport = transport }); + } + + private void OnConnectionLost(object sender, EventArgs e) + { + var transport = (ITransport)sender; + if (transport.MTProtoType == MTProtoTransportType.File) + { + RaiseFileConnectionLost(sender as ITransport); + } + else if (transport.MTProtoType == MTProtoTransportType.Special) + { + RaiseSpecialConnectionLost(sender as ITransport); + } + else + { + RaiseConnectionLost(sender as ITransport); + } + } + } + + public class TransportEventArgs : EventArgs + { + public ITransport Transport { get; set; } + } +} diff --git a/Telegram.Api/WindowsPhone/BigInteger.cs b/Telegram.Api/WindowsPhone/BigInteger.cs new file mode 100755 index 0000000..c2c9944 --- /dev/null +++ b/Telegram.Api/WindowsPhone/BigInteger.cs @@ -0,0 +1,2426 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Text; +using System.Threading; + +/* +Optimization + Have proper popcount function for IsPowerOfTwo + Use unsafe ops to avoid bounds check + CoreAdd could avoid some resizes by checking for equal sized array that top overflow + For bitwise operators, hoist the conditionals out of their main loop + Optimize BitScanBackward + Use a carry variable to make shift opts do half the number of array ops. + Schoolbook multiply is O(n^2), use Karatsuba /Toom-3 for large numbers +*/ +namespace System.Numerics +{ + public struct BigInteger : IComparable, IFormattable, IComparable, IEquatable + { + //LSB on [0] + readonly uint[] data; + readonly short sign; + + static readonly uint[] ZERO = new uint[1]; + static readonly uint[] ONE = new uint[1] { 1 }; + + BigInteger(short sign, uint[] data) + { + this.sign = sign; + this.data = data; + } + + public BigInteger(int value) + { + if (value == 0) + { + sign = 0; + data = ZERO; + } + else if (value > 0) + { + sign = 1; + data = new uint[] { (uint)value }; + } + else + { + sign = -1; + data = new uint[1] { (uint)-value }; + } + } + + [CLSCompliantAttribute(false)] + public BigInteger(uint value) + { + if (value == 0) + { + sign = 0; + data = ZERO; + } + else + { + sign = 1; + data = new uint[1] { value }; + } + } + + public BigInteger(long value) + { + if (value == 0) + { + sign = 0; + data = ZERO; + } + else if (value > 0) + { + sign = 1; + uint low = (uint)value; + uint high = (uint)(value >> 32); + + data = new uint[high != 0 ? 2 : 1]; + data[0] = low; + if (high != 0) + data[1] = high; + } + else + { + sign = -1; + value = -value; + uint low = (uint)value; + uint high = (uint)((ulong)value >> 32); + + data = new uint[high != 0 ? 2 : 1]; + data[0] = low; + if (high != 0) + data[1] = high; + } + } + + [CLSCompliantAttribute(false)] + public BigInteger(ulong value) + { + if (value == 0) + { + sign = 0; + data = ZERO; + } + else + { + sign = 1; + uint low = (uint)value; + uint high = (uint)(value >> 32); + + data = new uint[high != 0 ? 2 : 1]; + data[0] = low; + if (high != 0) + data[1] = high; + } + } + + + static bool Negative(byte[] v) + { + return ((v[7] & 0x80) != 0); + } + + static ushort Exponent(byte[] v) + { + return (ushort)((((ushort)(v[7] & 0x7F)) << (ushort)4) | (((ushort)(v[6] & 0xF0)) >> 4)); + } + + static ulong Mantissa(byte[] v) + { + uint i1 = ((uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24)); + uint i2 = ((uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16)); + + return (ulong)((ulong)i1 | ((ulong)i2 << 32)); + } + + const int bias = 1075; + public BigInteger(double value) + { + if (double.IsNaN(value) || Double.IsInfinity(value)) + throw new OverflowException(); + + byte[] bytes = BitConverter.GetBytes(value); + ulong mantissa = Mantissa(bytes); + if (mantissa == 0) + { + // 1.0 * 2**exp, we have a power of 2 + int exponent = Exponent(bytes); + if (exponent == 0) + { + sign = 0; + data = ZERO; + return; + } + + BigInteger res = Negative(bytes) ? MinusOne : One; + res = res << (exponent - 0x3ff); + this.sign = res.sign; + this.data = res.data; + } + else + { + // 1.mantissa * 2**exp + int exponent = Exponent(bytes); + mantissa |= 0x10000000000000ul; + BigInteger res = mantissa; + res = exponent > bias ? res << (exponent - bias) : res >> (bias - exponent); + + this.sign = (short)(Negative(bytes) ? -1 : 1); + this.data = res.data; + } + } + + public BigInteger(float value) + : this((double)value) + { + } + + const Int32 DecimalScaleFactorMask = 0x00FF0000; + const Int32 DecimalSignMask = unchecked((Int32)0x80000000); + + public BigInteger(decimal value) + { + // First truncate to get scale to 0 and extract bits + int[] bits = Decimal.GetBits(Decimal.Truncate(value)); + + int size = 3; + while (size > 0 && bits[size - 1] == 0) size--; + + if (size == 0) + { + sign = 0; + data = ZERO; + return; + } + + sign = (short)((bits[3] & DecimalSignMask) != 0 ? -1 : 1); + + data = new uint[size]; + data[0] = (uint)bits[0]; + if (size > 1) + data[1] = (uint)bits[1]; + if (size > 2) + data[2] = (uint)bits[2]; + } + + [CLSCompliantAttribute(false)] + public BigInteger(byte[] value) + { + if (value == null) + throw new ArgumentNullException("value"); + + int len = value.Length; + + if (len == 0 || (len == 1 && value[0] == 0)) + { + sign = 0; + data = ZERO; + return; + } + + if ((value[len - 1] & 0x80) != 0) + sign = -1; + else + sign = 1; + + if (sign == 1) + { + while (value[len - 1] == 0) + { + if (--len == 0) + { + sign = 0; + data = ZERO; + return; + } + } + + int full_words, size; + full_words = size = len / 4; + if ((len & 0x3) != 0) + ++size; + + data = new uint[size]; + int j = 0; + for (int i = 0; i < full_words; ++i) + { + data[i] = (uint)value[j++] | + (uint)(value[j++] << 8) | + (uint)(value[j++] << 16) | + (uint)(value[j++] << 24); + } + size = len & 0x3; + if (size > 0) + { + int idx = data.Length - 1; + for (int i = 0; i < size; ++i) + data[idx] |= (uint)(value[j++] << (i * 8)); + } + } + else + { + int full_words, size; + full_words = size = len / 4; + if ((len & 0x3) != 0) + ++size; + + data = new uint[size]; + + uint word, borrow = 1; + ulong sub = 0; + int j = 0; + + for (int i = 0; i < full_words; ++i) + { + word = (uint)value[j++] | + (uint)(value[j++] << 8) | + (uint)(value[j++] << 16) | + (uint)(value[j++] << 24); + + sub = (ulong)word - borrow; + word = (uint)sub; + borrow = (uint)(sub >> 32) & 0x1u; + data[i] = ~word; + } + size = len & 0x3; + + if (size > 0) + { + word = 0; + uint store_mask = 0; + for (int i = 0; i < size; ++i) + { + word |= (uint)(value[j++] << (i * 8)); + store_mask = (store_mask << 8) | 0xFF; + } + + sub = word - borrow; + word = (uint)sub; + borrow = (uint)(sub >> 32) & 0x1u; + + data[data.Length - 1] = ~word & store_mask; + } + if (borrow != 0) //FIXME I believe this can't happen, can someone write a test for it? + throw new Exception("non zero final carry"); + } + + } + + public bool IsEven + { + get { return sign == 0 || (data[0] & 0x1) == 0; } + } + + public bool IsOne + { + get { return sign == 1 && data.Length == 1 && data[0] == 1; } + } + + + //Gem from Hacker's Delight + //Returns the number of bits set in @x + static int PopulationCount(uint x) + { + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x = x + (x >> 8); + x = x + (x >> 16); + return (int)(x & 0x0000003F); + } + + public bool IsPowerOfTwo + { + get + { + bool foundBit = false; + if (sign != 1) + return false; + //This function is pop count == 1 for positive numbers + for (int i = 0; i < data.Length; ++i) + { + int p = PopulationCount(data[i]); + if (p > 0) + { + if (p > 1 || foundBit) + return false; + foundBit = true; + } + } + return foundBit; + } + } + + public bool IsZero + { + get { return sign == 0; } + } + + public int Sign + { + get { return sign; } + } + + public static BigInteger MinusOne + { + get { return new BigInteger(-1, ONE); } + } + + public static BigInteger One + { + get { return new BigInteger(1, ONE); } + } + + public static BigInteger Zero + { + get { return new BigInteger(0, ZERO); } + } + + public static explicit operator int(BigInteger value) + { + if (value.sign == 0) + return 0; + if (value.data.Length > 1) + throw new OverflowException(); + uint data = value.data[0]; + + if (value.sign == 1) + { + if (data > (uint)int.MaxValue) + throw new OverflowException(); + return (int)data; + } + else if (value.sign == -1) + { + if (data > 0x80000000u) + throw new OverflowException(); + return -(int)data; + } + + return 0; + } + + [CLSCompliantAttribute(false)] + public static explicit operator uint(BigInteger value) + { + if (value.sign == 0) + return 0; + if (value.data.Length > 1 || value.sign == -1) + throw new OverflowException(); + return value.data[0]; + } + + public static explicit operator short(BigInteger value) + { + int val = (int)value; + if (val < short.MinValue || val > short.MaxValue) + throw new OverflowException(); + return (short)val; + } + + [CLSCompliantAttribute(false)] + public static explicit operator ushort(BigInteger value) + { + uint val = (uint)value; + if (val > ushort.MaxValue) + throw new OverflowException(); + return (ushort)val; + } + + public static explicit operator byte(BigInteger value) + { + uint val = (uint)value; + if (val > byte.MaxValue) + throw new OverflowException(); + return (byte)val; + } + + [CLSCompliantAttribute(false)] + public static explicit operator sbyte(BigInteger value) + { + int val = (int)value; + if (val < sbyte.MinValue || val > sbyte.MaxValue) + throw new OverflowException(); + return (sbyte)val; + } + + + public static explicit operator long(BigInteger value) + { + if (value.sign == 0) + return 0; + + if (value.data.Length > 2) + throw new OverflowException(); + + uint low = value.data[0]; + + if (value.data.Length == 1) + { + if (value.sign == 1) + return (long)low; + long res = (long)low; + return -res; + } + + uint high = value.data[1]; + + if (value.sign == 1) + { + if (high >= 0x80000000u) + throw new OverflowException(); + return (((long)high) << 32) | low; + } + + if (high > 0x80000000u) + throw new OverflowException(); + + return -((((long)high) << 32) | (long)low); + } + + [CLSCompliantAttribute(false)] + public static explicit operator ulong(BigInteger value) + { + if (value.sign == 0) + return 0; + if (value.data.Length > 2 || value.sign == -1) + throw new OverflowException(); + + uint low = value.data[0]; + if (value.data.Length == 1) + return low; + + uint high = value.data[1]; + return (((ulong)high) << 32) | low; + } + + public static explicit operator double(BigInteger value) + { + //FIXME + try + { + return double.Parse(value.ToString(), + System.Globalization.CultureInfo.InvariantCulture.NumberFormat); + } + catch (OverflowException) + { + return value.sign == -1 ? double.NegativeInfinity : double.PositiveInfinity; + } + } + + public static explicit operator float(BigInteger value) + { + //FIXME + try + { + return float.Parse(value.ToString(), + System.Globalization.CultureInfo.InvariantCulture.NumberFormat); + } + catch (OverflowException) + { + return value.sign == -1 ? float.NegativeInfinity : float.PositiveInfinity; + } + } + + public static explicit operator decimal(BigInteger value) + { + if (value.sign == 0) + return Decimal.Zero; + + uint[] data = value.data; + if (data.Length > 3) + throw new OverflowException(); + + int lo = 0, mi = 0, hi = 0; + if (data.Length > 2) + hi = (Int32)data[2]; + if (data.Length > 1) + mi = (Int32)data[1]; + if (data.Length > 0) + lo = (Int32)data[0]; + + return new Decimal(lo, mi, hi, value.sign < 0, 0); + } + + public static implicit operator BigInteger(int value) + { + return new BigInteger(value); + } + + [CLSCompliantAttribute(false)] + public static implicit operator BigInteger(uint value) + { + return new BigInteger(value); + } + + public static implicit operator BigInteger(short value) + { + return new BigInteger(value); + } + + [CLSCompliantAttribute(false)] + public static implicit operator BigInteger(ushort value) + { + return new BigInteger(value); + } + + public static implicit operator BigInteger(byte value) + { + return new BigInteger(value); + } + + [CLSCompliantAttribute(false)] + public static implicit operator BigInteger(sbyte value) + { + return new BigInteger(value); + } + + public static implicit operator BigInteger(long value) + { + return new BigInteger(value); + } + + [CLSCompliantAttribute(false)] + public static implicit operator BigInteger(ulong value) + { + return new BigInteger(value); + } + + public static explicit operator BigInteger(double value) + { + return new BigInteger(value); + } + + public static explicit operator BigInteger(float value) + { + return new BigInteger(value); + } + + public static explicit operator BigInteger(decimal value) + { + return new BigInteger(value); + } + + public static BigInteger operator +(BigInteger left, BigInteger right) + { + if (left.sign == 0) + return right; + if (right.sign == 0) + return left; + + if (left.sign == right.sign) + return new BigInteger(left.sign, CoreAdd(left.data, right.data)); + + int r = CoreCompare(left.data, right.data); + + if (r == 0) + return new BigInteger(0, ZERO); + + if (r > 0) //left > right + return new BigInteger(left.sign, CoreSub(left.data, right.data)); + + return new BigInteger(right.sign, CoreSub(right.data, left.data)); + } + + public static BigInteger operator -(BigInteger left, BigInteger right) + { + if (right.sign == 0) + return left; + if (left.sign == 0) + return new BigInteger((short)-right.sign, right.data); + + if (left.sign == right.sign) + { + int r = CoreCompare(left.data, right.data); + + if (r == 0) + return new BigInteger(0, ZERO); + + if (r > 0) //left > right + return new BigInteger(left.sign, CoreSub(left.data, right.data)); + + return new BigInteger((short)-right.sign, CoreSub(right.data, left.data)); + } + + return new BigInteger(left.sign, CoreAdd(left.data, right.data)); + } + + public static BigInteger operator *(BigInteger left, BigInteger right) + { + if (left.sign == 0 || right.sign == 0) + return new BigInteger(0, ZERO); + + if (left.data[0] == 1 && left.data.Length == 1) + { + if (left.sign == 1) + return right; + return new BigInteger((short)-right.sign, right.data); + } + + if (right.data[0] == 1 && right.data.Length == 1) + { + if (right.sign == 1) + return left; + return new BigInteger((short)-left.sign, left.data); + } + + uint[] a = left.data; + uint[] b = right.data; + + uint[] res = new uint[a.Length + b.Length]; + + for (int i = 0; i < a.Length; ++i) + { + uint ai = a[i]; + int k = i; + + ulong carry = 0; + for (int j = 0; j < b.Length; ++j) + { + carry = carry + ((ulong)ai) * b[j] + res[k]; + res[k++] = (uint)carry; + carry >>= 32; + } + + while (carry != 0) + { + carry += res[k]; + res[k++] = (uint)carry; + carry >>= 32; + } + } + + int m; + for (m = res.Length - 1; m >= 0 && res[m] == 0; --m) ; + if (m < res.Length - 1) + res = Resize(res, m + 1); + + return new BigInteger((short)(left.sign * right.sign), res); + } + + public static BigInteger operator /(BigInteger dividend, BigInteger divisor) + { + if (divisor.sign == 0) + throw new DivideByZeroException(); + + if (dividend.sign == 0) + return dividend; + + uint[] quotient; + uint[] remainder_value; + + DivModUnsigned(dividend.data, divisor.data, out quotient, out remainder_value); + + int i; + for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) ; + if (i == -1) + return new BigInteger(0, ZERO); + if (i < quotient.Length - 1) + quotient = Resize(quotient, i + 1); + + return new BigInteger((short)(dividend.sign * divisor.sign), quotient); + } + + public static BigInteger operator %(BigInteger dividend, BigInteger divisor) + { + if (divisor.sign == 0) + throw new DivideByZeroException(); + + if (dividend.sign == 0) + return dividend; + + uint[] quotient; + uint[] remainder_value; + + DivModUnsigned(dividend.data, divisor.data, out quotient, out remainder_value); + + int i; + for (i = remainder_value.Length - 1; i >= 0 && remainder_value[i] == 0; --i) ; + if (i == -1) + return new BigInteger(0, ZERO); + + if (i < remainder_value.Length - 1) + remainder_value = Resize(remainder_value, i + 1); + return new BigInteger(dividend.sign, remainder_value); + } + + public static BigInteger operator -(BigInteger value) + { + if (value.sign == 0) + return value; + return new BigInteger((short)-value.sign, value.data); + } + + public static BigInteger operator +(BigInteger value) + { + return value; + } + + public static BigInteger operator ++(BigInteger value) + { + if (value.sign == 0) + return One; + + short sign = value.sign; + uint[] data = value.data; + if (data.Length == 1) + { + if (sign == -1 && data[0] == 1) + return new BigInteger(0, ZERO); + if (sign == 0) + return new BigInteger(1, ONE); + } + + if (sign == -1) + data = CoreSub(data, 1); + else + data = CoreAdd(data, 1); + + return new BigInteger(sign, data); + } + + public static BigInteger operator --(BigInteger value) + { + if (value.sign == 0) + return MinusOne; + + short sign = value.sign; + uint[] data = value.data; + if (data.Length == 1) + { + if (sign == 1 && data[0] == 1) + return new BigInteger(0, ZERO); + if (sign == 0) + return new BigInteger(-1, ONE); + } + + if (sign == -1) + data = CoreAdd(data, 1); + else + data = CoreSub(data, 1); + + return new BigInteger(sign, data); + } + + public static BigInteger operator &(BigInteger left, BigInteger right) + { + if (left.sign == 0) + return left; + + if (right.sign == 0) + return right; + + uint[] a = left.data; + uint[] b = right.data; + int ls = left.sign; + int rs = right.sign; + + bool neg_res = (ls == rs) && (ls == -1); + + uint[] result = new uint[Math.Max(a.Length, b.Length)]; + + ulong ac = 1, bc = 1, borrow = 1; + + int i; + for (i = 0; i < result.Length; ++i) + { + uint va = 0; + if (i < a.Length) + va = a[i]; + if (ls == -1) + { + ac = ~va + ac; + va = (uint)ac; + ac = (uint)(ac >> 32); + } + + uint vb = 0; + if (i < b.Length) + vb = b[i]; + if (rs == -1) + { + bc = ~vb + bc; + vb = (uint)bc; + bc = (uint)(bc >> 32); + } + + uint word = va & vb; + + if (neg_res) + { + borrow = word - borrow; + word = ~(uint)borrow; + borrow = (uint)(borrow >> 32) & 0x1u; + } + + result[i] = word; + } + + for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ; + if (i == -1) + return new BigInteger(0, ZERO); + + if (i < result.Length - 1) + result = Resize(result, i + 1); + + return new BigInteger(neg_res ? (short)-1 : (short)1, result); + } + + public static BigInteger operator |(BigInteger left, BigInteger right) + { + if (left.sign == 0) + return right; + + if (right.sign == 0) + return left; + + uint[] a = left.data; + uint[] b = right.data; + int ls = left.sign; + int rs = right.sign; + + bool neg_res = (ls == -1) || (rs == -1); + + uint[] result = new uint[Math.Max(a.Length, b.Length)]; + + ulong ac = 1, bc = 1, borrow = 1; + + int i; + for (i = 0; i < result.Length; ++i) + { + uint va = 0; + if (i < a.Length) + va = a[i]; + if (ls == -1) + { + ac = ~va + ac; + va = (uint)ac; + ac = (uint)(ac >> 32); + } + + uint vb = 0; + if (i < b.Length) + vb = b[i]; + if (rs == -1) + { + bc = ~vb + bc; + vb = (uint)bc; + bc = (uint)(bc >> 32); + } + + uint word = va | vb; + + if (neg_res) + { + borrow = word - borrow; + word = ~(uint)borrow; + borrow = (uint)(borrow >> 32) & 0x1u; + } + + result[i] = word; + } + + for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ; + if (i == -1) + return new BigInteger(0, ZERO); + + if (i < result.Length - 1) + result = Resize(result, i + 1); + + return new BigInteger(neg_res ? (short)-1 : (short)1, result); + } + + public static BigInteger operator ^(BigInteger left, BigInteger right) + { + if (left.sign == 0) + return right; + + if (right.sign == 0) + return left; + + uint[] a = left.data; + uint[] b = right.data; + int ls = left.sign; + int rs = right.sign; + + bool neg_res = (ls == -1) ^ (rs == -1); + + uint[] result = new uint[Math.Max(a.Length, b.Length)]; + + ulong ac = 1, bc = 1, borrow = 1; + + int i; + for (i = 0; i < result.Length; ++i) + { + uint va = 0; + if (i < a.Length) + va = a[i]; + if (ls == -1) + { + ac = ~va + ac; + va = (uint)ac; + ac = (uint)(ac >> 32); + } + + uint vb = 0; + if (i < b.Length) + vb = b[i]; + if (rs == -1) + { + bc = ~vb + bc; + vb = (uint)bc; + bc = (uint)(bc >> 32); + } + + uint word = va ^ vb; + + if (neg_res) + { + borrow = word - borrow; + word = ~(uint)borrow; + borrow = (uint)(borrow >> 32) & 0x1u; + } + + result[i] = word; + } + + for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ; + if (i == -1) + return new BigInteger(0, ZERO); + + if (i < result.Length - 1) + result = Resize(result, i + 1); + + return new BigInteger(neg_res ? (short)-1 : (short)1, result); + } + + public static BigInteger operator ~(BigInteger value) + { + if (value.sign == 0) + return new BigInteger(-1, ONE); + + uint[] data = value.data; + int sign = value.sign; + + bool neg_res = sign == 1; + + uint[] result = new uint[data.Length]; + + ulong carry = 1, borrow = 1; + + int i; + for (i = 0; i < result.Length; ++i) + { + uint word = data[i]; + if (sign == -1) + { + carry = ~word + carry; + word = (uint)carry; + carry = (uint)(carry >> 32); + } + + word = ~word; + + if (neg_res) + { + borrow = word - borrow; + word = ~(uint)borrow; + borrow = (uint)(borrow >> 32) & 0x1u; + } + + result[i] = word; + } + + for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ; + if (i == -1) + return new BigInteger(0, ZERO); + + if (i < result.Length - 1) + result = Resize(result, i + 1); + + return new BigInteger(neg_res ? (short)-1 : (short)1, result); + } + + //returns the 0-based index of the most significant set bit + //returns 0 if no bit is set, so extra care when using it + static int BitScanBackward(uint word) + { + for (int i = 31; i >= 0; --i) + { + uint mask = 1u << i; + if ((word & mask) == mask) + return i; + } + return 0; + } + + public static BigInteger operator <<(BigInteger value, int shift) + { + if (shift == 0 || value.sign == 0) + return value; + if (shift < 0) + return value >> -shift; + + uint[] data = value.data; + int sign = value.sign; + + int topMostIdx = BitScanBackward(data[data.Length - 1]); + int bits = shift - (31 - topMostIdx); + int extra_words = (bits >> 5) + ((bits & 0x1F) != 0 ? 1 : 0); + + uint[] res = new uint[data.Length + extra_words]; + + int idx_shift = shift >> 5; + int bit_shift = shift & 0x1F; + int carry_shift = 32 - bit_shift; + + if (carry_shift == 32) + { + for (int i = 0; i < data.Length; ++i) + { + uint word = data[i]; + res[i + idx_shift] |= word << bit_shift; + } + } + else + { + for (int i = 0; i < data.Length; ++i) + { + uint word = data[i]; + res[i + idx_shift] |= word << bit_shift; + if (i + idx_shift + 1 < res.Length) + res[i + idx_shift + 1] = word >> carry_shift; + } + } + + return new BigInteger((short)sign, res); + } + + public static BigInteger operator >>(BigInteger value, int shift) + { + if (shift == 0 || value.sign == 0) + return value; + if (shift < 0) + return value << -shift; + + uint[] data = value.data; + int sign = value.sign; + + int topMostIdx = BitScanBackward(data[data.Length - 1]); + int idx_shift = shift >> 5; + int bit_shift = shift & 0x1F; + + int extra_words = idx_shift; + if (bit_shift > topMostIdx) + ++extra_words; + int size = data.Length - extra_words; + + if (size <= 0) + { + if (sign == 1) + return new BigInteger(0, ZERO); + return new BigInteger(-1, ONE); + } + + uint[] res = new uint[size]; + int carry_shift = 32 - bit_shift; + + if (carry_shift == 32) + { + for (int i = data.Length - 1; i >= idx_shift; --i) + { + uint word = data[i]; + + if (i - idx_shift < res.Length) + res[i - idx_shift] |= word >> bit_shift; + } + } + else + { + for (int i = data.Length - 1; i >= idx_shift; --i) + { + uint word = data[i]; + + if (i - idx_shift < res.Length) + res[i - idx_shift] |= word >> bit_shift; + if (i - idx_shift - 1 >= 0) + res[i - idx_shift - 1] = word << carry_shift; + } + + } + + //Round down instead of toward zero + if (sign == -1) + { + for (int i = 0; i < idx_shift; i++) + { + if (data[i] != 0u) + { + var tmp = new BigInteger((short)sign, res); + --tmp; + return tmp; + } + } + if (bit_shift > 0 && (data[idx_shift] << carry_shift) != 0u) + { + var tmp = new BigInteger((short)sign, res); + --tmp; + return tmp; + } + } + return new BigInteger((short)sign, res); + } + + public static bool operator <(BigInteger left, BigInteger right) + { + return Compare(left, right) < 0; + } + + public static bool operator <(BigInteger left, long right) + { + return left.CompareTo(right) < 0; + } + + + public static bool operator <(long left, BigInteger right) + { + return right.CompareTo(left) > 0; + } + + + [CLSCompliantAttribute(false)] + public static bool operator <(BigInteger left, ulong right) + { + return left.CompareTo(right) < 0; + } + + [CLSCompliantAttribute(false)] + public static bool operator <(ulong left, BigInteger right) + { + return right.CompareTo(left) > 0; + } + + public static bool operator <=(BigInteger left, BigInteger right) + { + return Compare(left, right) <= 0; + } + + public static bool operator <=(BigInteger left, long right) + { + return left.CompareTo(right) <= 0; + } + + public static bool operator <=(long left, BigInteger right) + { + return right.CompareTo(left) >= 0; + } + + [CLSCompliantAttribute(false)] + public static bool operator <=(BigInteger left, ulong right) + { + return left.CompareTo(right) <= 0; + } + + [CLSCompliantAttribute(false)] + public static bool operator <=(ulong left, BigInteger right) + { + return right.CompareTo(left) >= 0; + } + + public static bool operator >(BigInteger left, BigInteger right) + { + return Compare(left, right) > 0; + } + + public static bool operator >(BigInteger left, long right) + { + return left.CompareTo(right) > 0; + } + + public static bool operator >(long left, BigInteger right) + { + return right.CompareTo(left) < 0; + } + + [CLSCompliantAttribute(false)] + public static bool operator >(BigInteger left, ulong right) + { + return left.CompareTo(right) > 0; + } + + [CLSCompliantAttribute(false)] + public static bool operator >(ulong left, BigInteger right) + { + return right.CompareTo(left) < 0; + } + + public static bool operator >=(BigInteger left, BigInteger right) + { + return Compare(left, right) >= 0; + } + + public static bool operator >=(BigInteger left, long right) + { + return left.CompareTo(right) >= 0; + } + + public static bool operator >=(long left, BigInteger right) + { + return right.CompareTo(left) <= 0; + } + + [CLSCompliantAttribute(false)] + public static bool operator >=(BigInteger left, ulong right) + { + return left.CompareTo(right) >= 0; + } + + [CLSCompliantAttribute(false)] + public static bool operator >=(ulong left, BigInteger right) + { + return right.CompareTo(left) <= 0; + } + + public static bool operator ==(BigInteger left, BigInteger right) + { + return Compare(left, right) == 0; + } + + public static bool operator ==(BigInteger left, long right) + { + return left.CompareTo(right) == 0; + } + + public static bool operator ==(long left, BigInteger right) + { + return right.CompareTo(left) == 0; + } + + [CLSCompliantAttribute(false)] + public static bool operator ==(BigInteger left, ulong right) + { + return left.CompareTo(right) == 0; + } + + [CLSCompliantAttribute(false)] + public static bool operator ==(ulong left, BigInteger right) + { + return right.CompareTo(left) == 0; + } + + public static bool operator !=(BigInteger left, BigInteger right) + { + return Compare(left, right) != 0; + } + + public static bool operator !=(BigInteger left, long right) + { + return left.CompareTo(right) != 0; + } + + public static bool operator !=(long left, BigInteger right) + { + return right.CompareTo(left) != 0; + } + + [CLSCompliantAttribute(false)] + public static bool operator !=(BigInteger left, ulong right) + { + return left.CompareTo(right) != 0; + } + + [CLSCompliantAttribute(false)] + public static bool operator !=(ulong left, BigInteger right) + { + return right.CompareTo(left) != 0; + } + + public override bool Equals(object obj) + { + if (!(obj is BigInteger)) + return false; + return Equals((BigInteger)obj); + } + + public bool Equals(BigInteger other) + { + if (sign != other.sign) + return false; + + int alen = data != null ? data.Length : 0; + int blen = other.data != null ? other.data.Length : 0; + + if (alen != blen) + return false; + for (int i = 0; i < alen; ++i) + { + if (data[i] != other.data[i]) + return false; + } + return true; + } + + public bool Equals(long other) + { + return CompareTo(other) == 0; + } + + public override string ToString() + { + return ToString(10, null); + } + + string ToStringWithPadding(string format, uint radix, IFormatProvider provider) + { + if (format.Length > 1) + { + int precision = Convert.ToInt32(format.Substring(1), CultureInfo.InvariantCulture.NumberFormat); + string baseStr = ToString(radix, provider); + if (baseStr.Length < precision) + { + string additional = new String('0', precision - baseStr.Length); + if (baseStr[0] != '-') + { + return additional + baseStr; + } + else + { + return "-" + additional + baseStr.Substring(1); + } + } + return baseStr; + } + return ToString(radix, provider); + } + + public string ToString(string format) + { + return ToString(format, null); + } + + public string ToString(IFormatProvider provider) + { + return ToString(null, provider); + } + + + public string ToString(string format, IFormatProvider provider) + { + if (format == null || format == "") + return ToString(10, provider); + + switch (format[0]) + { + case 'd': + case 'D': + case 'g': + case 'G': + case 'r': + case 'R': + return ToStringWithPadding(format, 10, provider); + case 'x': + case 'X': + return ToStringWithPadding(format, 16, null); + default: + throw new FormatException(string.Format("format '{0}' not implemented", format)); + } + } + + static uint[] MakeTwoComplement(uint[] v) + { + uint[] res = new uint[v.Length]; + + ulong carry = 1; + for (int i = 0; i < v.Length; ++i) + { + uint word = v[i]; + carry = (ulong)~word + carry; + word = (uint)carry; + carry = (uint)(carry >> 32); + res[i] = word; + } + + uint last = res[res.Length - 1]; + int idx = FirstNonFFByte(last); + uint mask = 0xFF; + for (int i = 1; i < idx; ++i) + mask = (mask << 8) | 0xFF; + + res[res.Length - 1] = last & mask; + return res; + } + + string ToString(uint radix, IFormatProvider provider) + { + const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + if (characterSet.Length < radix) + throw new ArgumentException("charSet length less than radix", "characterSet"); + if (radix == 1) + throw new ArgumentException("There is no such thing as radix one notation", "radix"); + + if (sign == 0) + return "0"; + if (data.Length == 1 && data[0] == 1) + return sign == 1 ? "1" : "-1"; + + List digits = new List(1 + data.Length * 3 / 10); + + BigInteger a; + if (sign == 1) + a = this; + else + { + uint[] dt = data; + if (radix > 10) + dt = MakeTwoComplement(dt); + a = new BigInteger(1, dt); + } + + while (a != 0) + { + BigInteger rem; + a = DivRem(a, radix, out rem); + digits.Add(characterSet[(int)rem]); + } + + if (sign == -1 && radix == 10) + { + NumberFormatInfo info = null; + if (provider != null) + info = provider.GetFormat(typeof(NumberFormatInfo)) as NumberFormatInfo; + if (info != null) + { + string str = info.NegativeSign; + for (int i = str.Length - 1; i >= 0; --i) + digits.Add(str[i]); + } + else + { + digits.Add('-'); + } + } + + char last = digits[digits.Count - 1]; + if (sign == 1 && radix > 10 && (last < '0' || last > '9')) + digits.Add('0'); + + digits.Reverse(); + + return new String(digits.ToArray()); + } + +#if NET_4_0 + [MonoTODO] + public static BigInteger Parse (string value, NumberStyles style) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public static BigInteger Parse (string value, IFormatProvider provider) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public static BigInteger Parse ( + string value, NumberStyles style, IFormatProvider provider) + { + throw new InvalidOperationException (); + } + + [MonoTODO] + public static bool TryParse ( + string value, NumberStyles style, IFormatProvider provider, + out BigInteger result) + { + throw new NotImplementedException (); + } +#endif + + + static Exception GetFormatException() + { + return new FormatException("Input string was not in the correct format"); + } + + static bool ProcessTrailingWhitespace(bool tryParse, string s, int position, ref Exception exc) + { + int len = s.Length; + + for (int i = position; i < len; i++) + { + char c = s[i]; + + if (c != 0 && !Char.IsWhiteSpace(c)) + { + if (!tryParse) + exc = GetFormatException(); + return false; + } + } + return true; + } + + public static BigInteger Min(BigInteger left, BigInteger right) + { + int ls = left.sign; + int rs = right.sign; + + if (ls < rs) + return left; + if (rs < ls) + return right; + + int r = CoreCompare(left.data, right.data); + if (ls == -1) + r = -r; + + if (r <= 0) + return left; + return right; + } + + + public static BigInteger Max(BigInteger left, BigInteger right) + { + int ls = left.sign; + int rs = right.sign; + + if (ls > rs) + return left; + if (rs > ls) + return right; + + int r = CoreCompare(left.data, right.data); + if (ls == -1) + r = -r; + + if (r >= 0) + return left; + return right; + } + + public static BigInteger Abs(BigInteger value) + { + return new BigInteger((short)Math.Abs(value.sign), value.data); + } + + + public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder) + { + if (divisor.sign == 0) + throw new DivideByZeroException(); + + if (dividend.sign == 0) + { + remainder = dividend; + return dividend; + } + + uint[] quotient; + uint[] remainder_value; + + DivModUnsigned(dividend.data, divisor.data, out quotient, out remainder_value); + + int i; + for (i = remainder_value.Length - 1; i >= 0 && remainder_value[i] == 0; --i) ; + if (i == -1) + { + remainder = new BigInteger(0, ZERO); + } + else + { + if (i < remainder_value.Length - 1) + remainder_value = Resize(remainder_value, i + 1); + remainder = new BigInteger(dividend.sign, remainder_value); + } + + for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) ; + if (i == -1) + return new BigInteger(0, ZERO); + if (i < quotient.Length - 1) + quotient = Resize(quotient, i + 1); + + return new BigInteger((short)(dividend.sign * divisor.sign), quotient); + } + + public static BigInteger Pow(BigInteger value, int exponent) + { + if (exponent < 0) + throw new ArgumentOutOfRangeException("exponent", "exp must be >= 0"); + if (exponent == 0) + return One; + if (exponent == 1) + return value; + + BigInteger result = One; + while (exponent != 0) + { + if ((exponent & 1) != 0) + result = result * value; + if (exponent == 1) + break; + + value = value * value; + exponent >>= 1; + } + return result; + } + + public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigInteger modulus) + { + if (exponent.sign == -1) + throw new ArgumentOutOfRangeException("exponent", "power must be >= 0"); + if (modulus.sign == 0) + throw new DivideByZeroException(); + + BigInteger result = One % modulus; + while (exponent.sign != 0) + { + if (!exponent.IsEven) + { + result = result * value; + result = result % modulus; + } + if (exponent.IsOne) + break; + value = value * value; + value = value % modulus; + exponent >>= 1; + } + return result; + } + + public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right) + { + if (left.sign != 0 && left.data.Length == 1 && left.data[0] == 1) + return new BigInteger(1, ONE); + if (right.sign != 0 && right.data.Length == 1 && right.data[0] == 1) + return new BigInteger(1, ONE); + if (left.IsZero) + return Abs(right); + if (right.IsZero) + return Abs(left); + + BigInteger x = new BigInteger(1, left.data); + BigInteger y = new BigInteger(1, right.data); + + BigInteger g = y; + + while (x.data.Length > 1) + { + g = x; + x = y % x; + y = g; + + } + if (x.IsZero) return g; + + // TODO: should we have something here if we can convert to long? + + // + // Now we can just do it with single precision. I am using the binary gcd method, + // as it should be faster. + // + + uint yy = x.data[0]; + uint xx = (uint)(y % yy); + + int t = 0; + + while (((xx | yy) & 1) == 0) + { + xx >>= 1; yy >>= 1; t++; + } + while (xx != 0) + { + while ((xx & 1) == 0) xx >>= 1; + while ((yy & 1) == 0) yy >>= 1; + if (xx >= yy) + xx = (xx - yy) >> 1; + else + yy = (yy - xx) >> 1; + } + + return yy << t; + } + + /*LAMESPEC Log doesn't specify to how many ulp is has to be precise + We are equilavent to MS with about 2 ULP + */ + public static double Log(BigInteger value, Double baseValue) + { + if (value.sign == -1 || baseValue == 1.0d || baseValue == -1.0d || + baseValue == Double.NegativeInfinity || double.IsNaN(baseValue)) + return double.NaN; + + if (baseValue == 0.0d || baseValue == Double.PositiveInfinity) + return value.IsOne ? 0 : double.NaN; + + if (value.sign == 0) + return double.NegativeInfinity; + + int length = value.data.Length - 1; + int bitCount = -1; + for (int curBit = 31; curBit >= 0; curBit--) + { + if ((value.data[length] & (1 << curBit)) != 0) + { + bitCount = curBit + length * 32; + break; + } + } + + long bitlen = bitCount; + Double c = 0, d = 1; + + BigInteger testBit = One; + long tempBitlen = bitlen; + while (tempBitlen > Int32.MaxValue) + { + testBit = testBit << Int32.MaxValue; + tempBitlen -= Int32.MaxValue; + } + testBit = testBit << (int)tempBitlen; + + for (long curbit = bitlen; curbit >= 0; --curbit) + { + if ((value & testBit).sign != 0) + c += d; + d *= 0.5; + testBit = testBit >> 1; + } + return (System.Math.Log(c) + System.Math.Log(2) * bitlen) / System.Math.Log(baseValue); + } + + + public static double Log(BigInteger value) + { + return Log(value, Math.E); + } + + + public static double Log10(BigInteger value) + { + return Log(value, 10); + } + + [CLSCompliantAttribute(false)] + public bool Equals(ulong other) + { + return CompareTo(other) == 0; + } + + public override int GetHashCode() + { + uint hash = (uint)(sign * 0x01010101u); + int len = data != null ? data.Length : 0; + + for (int i = 0; i < len; ++i) + hash ^= data[i]; + return (int)hash; + } + + public static BigInteger Add(BigInteger left, BigInteger right) + { + return left + right; + } + + public static BigInteger Subtract(BigInteger left, BigInteger right) + { + return left - right; + } + + public static BigInteger Multiply(BigInteger left, BigInteger right) + { + return left * right; + } + + public static BigInteger Divide(BigInteger dividend, BigInteger divisor) + { + return dividend / divisor; + } + + public static BigInteger Remainder(BigInteger dividend, BigInteger divisor) + { + return dividend % divisor; + } + + public static BigInteger Negate(BigInteger value) + { + return -value; + } + + public int CompareTo(object obj) + { + if (obj == null) + return 1; + + if (!(obj is BigInteger)) + return -1; + + return Compare(this, (BigInteger)obj); + } + + public int CompareTo(BigInteger other) + { + return Compare(this, other); + } + + [CLSCompliantAttribute(false)] + public int CompareTo(ulong other) + { + if (sign < 0) + return -1; + if (sign == 0) + return other == 0 ? 0 : -1; + + if (data.Length > 2) + return 1; + + uint high = (uint)(other >> 32); + uint low = (uint)other; + + return LongCompare(low, high); + } + + int LongCompare(uint low, uint high) + { + uint h = 0; + if (data.Length > 1) + h = data[1]; + + if (h > high) + return 1; + if (h < high) + return -1; + + uint l = data[0]; + + if (l > low) + return 1; + if (l < low) + return -1; + + return 0; + } + + public int CompareTo(long other) + { + int ls = sign; + int rs = Math.Sign(other); + + if (ls != rs) + return ls > rs ? 1 : -1; + + if (ls == 0) + return 0; + + if (data.Length > 2) + return sign; + + if (other < 0) + other = -other; + uint low = (uint)other; + uint high = (uint)((ulong)other >> 32); + + int r = LongCompare(low, high); + if (ls == -1) + r = -r; + + return r; + } + + public static int Compare(BigInteger left, BigInteger right) + { + int ls = left.sign; + int rs = right.sign; + + if (ls != rs) + return ls > rs ? 1 : -1; + + int r = CoreCompare(left.data, right.data); + if (ls < 0) + r = -r; + return r; + } + + + static int TopByte(uint x) + { + if ((x & 0xFFFF0000u) != 0) + { + if ((x & 0xFF000000u) != 0) + return 4; + return 3; + } + if ((x & 0xFF00u) != 0) + return 2; + return 1; + } + + static int FirstNonFFByte(uint word) + { + if ((word & 0xFF000000u) != 0xFF000000u) + return 4; + else if ((word & 0xFF0000u) != 0xFF0000u) + return 3; + else if ((word & 0xFF00u) != 0xFF00u) + return 2; + return 1; + } + + public byte[] ToByteArray() + { + if (sign == 0) + return new byte[1]; + + //number of bytes not counting upper word + int bytes = (data.Length - 1) * 4; + bool needExtraZero = false; + + uint topWord = data[data.Length - 1]; + int extra; + + //if the topmost bit is set we need an extra + if (sign == 1) + { + extra = TopByte(topWord); + uint mask = 0x80u << ((extra - 1) * 8); + if ((topWord & mask) != 0) + { + needExtraZero = true; + } + } + else + { + extra = TopByte(topWord); + } + + byte[] res = new byte[bytes + extra + (needExtraZero ? 1 : 0)]; + if (sign == 1) + { + int j = 0; + int end = data.Length - 1; + for (int i = 0; i < end; ++i) + { + uint word = data[i]; + + res[j++] = (byte)word; + res[j++] = (byte)(word >> 8); + res[j++] = (byte)(word >> 16); + res[j++] = (byte)(word >> 24); + } + while (extra-- > 0) + { + res[j++] = (byte)topWord; + topWord >>= 8; + } + } + else + { + int j = 0; + int end = data.Length - 1; + + uint carry = 1, word; + ulong add; + for (int i = 0; i < end; ++i) + { + word = data[i]; + add = (ulong)~word + carry; + word = (uint)add; + carry = (uint)(add >> 32); + + res[j++] = (byte)word; + res[j++] = (byte)(word >> 8); + res[j++] = (byte)(word >> 16); + res[j++] = (byte)(word >> 24); + } + + add = (ulong)~topWord + (carry); + word = (uint)add; + carry = (uint)(add >> 32); + if (carry == 0) + { + int ex = FirstNonFFByte(word); + bool needExtra = (word & (1 << (ex * 8 - 1))) == 0; + int to = ex + (needExtra ? 1 : 0); + + if (to != extra) + res = Resize(res, bytes + to); + + while (ex-- > 0) + { + res[j++] = (byte)word; + word >>= 8; + } + if (needExtra) + res[j++] = 0xFF; + } + else + { + res = Resize(res, bytes + 5); + res[j++] = (byte)word; + res[j++] = (byte)(word >> 8); + res[j++] = (byte)(word >> 16); + res[j++] = (byte)(word >> 24); + res[j++] = 0xFF; + } + } + + return res; + } + + static byte[] Resize(byte[] v, int len) + { + byte[] res = new byte[len]; + Array.Copy(v, res, Math.Min(v.Length, len)); + return res; + } + + static uint[] Resize(uint[] v, int len) + { + uint[] res = new uint[len]; + Array.Copy(v, res, Math.Min(v.Length, len)); + return res; + } + + static uint[] CoreAdd(uint[] a, uint[] b) + { + if (a.Length < b.Length) + { + uint[] tmp = a; + a = b; + b = tmp; + } + + int bl = a.Length; + int sl = b.Length; + + uint[] res = new uint[bl]; + + ulong sum = 0; + + int i = 0; + for (; i < sl; i++) + { + sum = sum + a[i] + b[i]; + res[i] = (uint)sum; + sum >>= 32; + } + + for (; i < bl; i++) + { + sum = sum + a[i]; + res[i] = (uint)sum; + sum >>= 32; + } + + if (sum != 0) + { + res = Resize(res, bl + 1); + res[i] = (uint)sum; + } + + return res; + } + + /*invariant a > b*/ + static uint[] CoreSub(uint[] a, uint[] b) + { + int bl = a.Length; + int sl = b.Length; + + uint[] res = new uint[bl]; + + ulong borrow = 0; + int i; + for (i = 0; i < sl; ++i) + { + borrow = (ulong)a[i] - b[i] - borrow; + + res[i] = (uint)borrow; + borrow = (borrow >> 32) & 0x1; + } + + for (; i < bl; i++) + { + borrow = (ulong)a[i] - borrow; + res[i] = (uint)borrow; + borrow = (borrow >> 32) & 0x1; + } + + //remove extra zeroes + for (i = bl - 1; i >= 0 && res[i] == 0; --i) ; + if (i < bl - 1) + res = Resize(res, i + 1); + + return res; + } + + + static uint[] CoreAdd(uint[] a, uint b) + { + int len = a.Length; + uint[] res = new uint[len]; + + ulong sum = b; + int i; + for (i = 0; i < len; i++) + { + sum = sum + a[i]; + res[i] = (uint)sum; + sum >>= 32; + } + + if (sum != 0) + { + res = Resize(res, len + 1); + res[i] = (uint)sum; + } + + return res; + } + + static uint[] CoreSub(uint[] a, uint b) + { + int len = a.Length; + uint[] res = new uint[len]; + + ulong borrow = b; + int i; + for (i = 0; i < len; i++) + { + borrow = (ulong)a[i] - borrow; + res[i] = (uint)borrow; + borrow = (borrow >> 32) & 0x1; + } + + //remove extra zeroes + for (i = len - 1; i >= 0 && res[i] == 0; --i) ; + if (i < len - 1) + res = Resize(res, i + 1); + + return res; + } + + static int CoreCompare(uint[] a, uint[] b) + { + int al = a != null ? a.Length : 0; + int bl = b != null ? b.Length : 0; + + if (al > bl) + return 1; + if (bl > al) + return -1; + + for (int i = al - 1; i >= 0; --i) + { + uint ai = a[i]; + uint bi = b[i]; + if (ai > bi) + return 1; + if (ai < bi) + return -1; + } + return 0; + } + + static int GetNormalizeShift(uint value) + { + int shift = 0; + + if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; } + if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; } + if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; } + if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; } + if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; } + + return shift; + } + + static void Normalize(uint[] u, int l, uint[] un, int shift) + { + uint carry = 0; + int i; + if (shift > 0) + { + int rshift = 32 - shift; + for (i = 0; i < l; i++) + { + uint ui = u[i]; + un[i] = (ui << shift) | carry; + carry = ui >> rshift; + } + } + else + { + for (i = 0; i < l; i++) + { + un[i] = u[i]; + } + } + + while (i < un.Length) + { + un[i++] = 0; + } + + if (carry != 0) + { + un[l] = carry; + } + } + + static void Unnormalize(uint[] un, out uint[] r, int shift) + { + int length = un.Length; + r = new uint[length]; + + if (shift > 0) + { + int lshift = 32 - shift; + uint carry = 0; + for (int i = length - 1; i >= 0; i--) + { + uint uni = un[i]; + r[i] = (uni >> shift) | carry; + carry = (uni << lshift); + } + } + else + { + for (int i = 0; i < length; i++) + { + r[i] = un[i]; + } + } + } + + const ulong Base = 0x100000000; + static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] r) + { + int m = u.Length; + int n = v.Length; + + if (n <= 1) + { + // Divide by single digit + // + ulong rem = 0; + uint v0 = v[0]; + q = new uint[m]; + r = new uint[1]; + + for (int j = m - 1; j >= 0; j--) + { + rem *= Base; + rem += u[j]; + + ulong div = rem / v0; + rem -= div * v0; + q[j] = (uint)div; + } + r[0] = (uint)rem; + } + else if (m >= n) + { + int shift = GetNormalizeShift(v[n - 1]); + + uint[] un = new uint[m + 1]; + uint[] vn = new uint[n]; + + Normalize(u, m, un, shift); + Normalize(v, n, vn, shift); + + q = new uint[m - n + 1]; + r = null; + + // Main division loop + // + for (int j = m - n; j >= 0; j--) + { + ulong rr, qq; + int i; + + rr = Base * un[j + n] + un[j + n - 1]; + qq = rr / vn[n - 1]; + rr -= qq * vn[n - 1]; + + for (; ; ) + { + // Estimate too big ? + // + if ((qq >= Base) || (qq * vn[n - 2] > (rr * Base + un[j + n - 2]))) + { + qq--; + rr += (ulong)vn[n - 1]; + if (rr < Base) + continue; + } + break; + } + + + // Multiply and subtract + // + long b = 0; + long t = 0; + for (i = 0; i < n; i++) + { + ulong p = vn[i] * qq; + t = (long)un[i + j] - (long)(uint)p - b; + un[i + j] = (uint)t; + p >>= 32; + t >>= 32; + b = (long)p - t; + } + t = (long)un[j + n] - b; + un[j + n] = (uint)t; + + // Store the calculated value + // + q[j] = (uint)qq; + + // Add back vn[0..n] to un[j..j+n] + // + if (t < 0) + { + q[j]--; + ulong c = 0; + for (i = 0; i < n; i++) + { + c = (ulong)vn[i] + un[j + i] + c; + un[j + i] = (uint)c; + c >>= 32; + } + c += (ulong)un[j + n]; + un[j + n] = (uint)c; + } + } + + Unnormalize(un, out r, shift); + } + else + { + q = new uint[] { 0 }; + r = u; + } + } + } +} \ No newline at end of file diff --git a/Telegram.Api/WindowsPhone/Tuple.cs b/Telegram.Api/WindowsPhone/Tuple.cs new file mode 100755 index 0000000..2843cce --- /dev/null +++ b/Telegram.Api/WindowsPhone/Tuple.cs @@ -0,0 +1,38 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Api.WindowsPhone +{ + public class Tuple + { + public T1 Item1 { get; set; } + + public T2 Item2 { get; set; } + + public T3 Item3 { get; set; } + + public Tuple(T1 item1, T2 item2, T3 item3) + { + Item1 = item1; + Item2 = item2; + Item3 = item3; + } + } + + public class Tuple + { + public T1 Item1 { get; set; } + + public T2 Item2 { get; set; } + + public Tuple(T1 item1, T2 item2) + { + Item1 = item1; + Item2 = item2; + } + } +} diff --git a/Telegram.Api/packages.config b/Telegram.Api/packages.config new file mode 100755 index 0000000..5030f28 --- /dev/null +++ b/Telegram.Api/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Telegram.Client.TileUpdated/Properties/AssemblyInfo.cs b/Telegram.Client.TileUpdated/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..5f8046c --- /dev/null +++ b/Telegram.Client.TileUpdated/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("Telegram.Client.TileUpdated")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Telegram.Client.TileUpdated")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[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("8c9a6178-3edd-4995-92e5-194220a0ece6")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/Telegram.Client.TileUpdated/ScheduledAgent.cs b/Telegram.Client.TileUpdated/ScheduledAgent.cs new file mode 100755 index 0000000..c4dd6be --- /dev/null +++ b/Telegram.Client.TileUpdated/ScheduledAgent.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.IO.IsolatedStorage; +using System.Linq; +using System.Threading; +using System.Windows; +using System.Windows.Threading; +//using Caliburn.Micro; +using Mangopollo.Tiles; +using Microsoft.Phone.Scheduler; +using Microsoft.Phone.Shell; +using Telegram.Api; +using Telegram.Api.Helpers; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.Updates; +using Telegram.Api.Transport; + +namespace Telegram.Client.TileUpdated +{ + public class ScheduledAgent : ScheduledTaskAgent + { + private static volatile bool _classInitialized; + + /// + /// ScheduledAgent constructor, initializes the UnhandledException handler + /// + public ScheduledAgent() + { + if (!_classInitialized) + { + _classInitialized = true; + // Subscribe to the managed exception handler + Deployment.Current.Dispatcher.BeginInvoke(delegate + { + Application.Current.UnhandledException += ScheduledAgent_UnhandledException; + }); + } + } + + /// Code to execute on Unhandled Exceptions + private void ScheduledAgent_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) + { + if (System.Diagnostics.Debugger.IsAttached) + { + // An unhandled exception has occurred; break into the debugger + System.Diagnostics.Debugger.Break(); + } + } + + /// + /// Agent that runs a scheduled task + /// + /// + /// The invoked task + /// + /// + /// This method is called when a periodic or resource intensive task is invoked + /// + protected override void OnInvoke(ScheduledTask task) + { + /*var manualResetEvent = new ManualResetEvent(false); + var eventAggregator = new EventAggregator(); + var cacheService = new InMemoryCacheService(eventAggregator); + var updatesService = new UpdatesService(cacheService, eventAggregator); + //TODO: Add code to perform your task in background + var mtProtoService = new MTProtoService(updatesService, cacheService, new TransportService()); + mtProtoService.GetStateAsync( + state => + { + + var unreadCount = state.UnreadCount.Value; + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + //var shellTileData = Mangopollo.Utils.CanUseLiveTiles + // ? (ShellTileData)new IconicTileData { Count = unreadCount } + // : new StandardTileData {Count = unreadCount}; + + var shellTileData = new StandardTileData { Count = unreadCount }; + + var tile = ShellTile.ActiveTiles.FirstOrDefault(); + if (tile != null) + { + tile.Update(shellTileData); + } + + //if (previousUnreadCount < unreadCount) + //{ + // //_previousUnreadCount = unreadCount; + // var toast = new ShellToast + // { + // Content = string.Format("Previous - {0}, current - {1}", previousUnreadCount, unreadCount), + // Title = "Telegram", + // NavigationUri = new System.Uri("/Views/ShellView.xaml", System.UriKind.Relative) + // }; + + // settings["UnreadCountKey"] = unreadCount; + // toast.Show(); + //} + + + manualResetEvent.Set(); + }); + + }, + error => + { + manualResetEvent.Set(); + }); + + manualResetEvent.WaitOne(20000);*/ + NotifyComplete(); + } + } +} \ No newline at end of file diff --git a/Telegram.Client.TileUpdated/Telegram.Client.TileUpdated.csproj b/Telegram.Client.TileUpdated/Telegram.Client.TileUpdated.csproj new file mode 100755 index 0000000..3daf331 --- /dev/null +++ b/Telegram.Client.TileUpdated/Telegram.Client.TileUpdated.csproj @@ -0,0 +1,105 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {8C9A6178-3EDD-4995-92E5-194220A0ECE6} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Telegram.Client.TileUpdated + Telegram.Client.TileUpdated + v4.0 + $(TargetFrameworkVersion) + WindowsPhone71 + Silverlight + false + true + true + ScheduledTaskAgent + ..\ + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + bin\Debug Private Beta\ + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + full + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + bin\Release Private Beta\ + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + ..\..\..\Vkontakte\Libraries\Caliburn.Micro.dll + + + ..\packages\Mangopollo.Light.1.3\lib\sl4-windowsphone71\Mangopollo.Light.dll + + + + + + + + + + + + + + + + {0C2F1B61-A8FE-45FB-8538-AA6925A415B6} + Telegram.Api + + + + + + + + + + + \ No newline at end of file diff --git a/Telegram.Client.TileUpdated/packages.config b/Telegram.Client.TileUpdated/packages.config new file mode 100755 index 0000000..a8c482d --- /dev/null +++ b/Telegram.Client.TileUpdated/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Telegram.Controls.WP8/Properties/AssemblyInfo.cs b/Telegram.Controls.WP8/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..ece3f87 --- /dev/null +++ b/Telegram.Controls.WP8/Properties/AssemblyInfo.cs @@ -0,0 +1,44 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("Telegram.Controls.WP8")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Telegram.Controls.WP8")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[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("f04be5a2-70df-4e82-bfb5-cd03985c9746")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/Telegram.Controls.WP8/Telegram.Controls.WP8.csproj b/Telegram.Controls.WP8/Telegram.Controls.WP8.csproj new file mode 100755 index 0000000..5b75392 --- /dev/null +++ b/Telegram.Controls.WP8/Telegram.Controls.WP8.csproj @@ -0,0 +1,275 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Telegram.Controls + Telegram.Controls + WindowsPhone + v8.0 + $(TargetFrameworkVersion) + false + true + 11.0 + true + ..\ + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\x86\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\x86\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\ARM\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8 + true + true + prompt + 4 + + + pdbonly + true + Bin\ARM\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8 + true + true + prompt + 4 + + + + AnimationMediator.cs + + + BindingListener.cs + + + Extensions\ScrollViewerExtensions.cs + + + Extensions\VisualTreeExtensions.cs + + + FlipCounter.xaml.cs + FlipCounter.xaml + + + FlipPanel.xaml.cs + FlipPanel.xaml + + + Helpers\DependencyPropertyChangedListener.cs + + + Helpers\DependencyPropertyValueChangedEventArgs.cs + + + HighlightingTextBlock.cs + + + IHighlightable.cs + + + LazyItemsControl.cs + + + LazyListBox.cs + + + LongListSelector\Common\MotionParameters.cs + + + LongListSelector\Common\SafeRaise.cs + + + LongListSelector\Common\TempaltedVisualTreeExtensions.cs + + + LongListSelector\Common\VisualStates.cs + + + LongListSelector\LongListSelector.cs + + + LongListSelector\LongListSelectorEventArgs.cs + + + LongListSelector\LongListSelectorGroup.cs + + + LongListSelector\LongListSelectorItem.cs + + + LongListSelector\LongListSelectorItemsControl.cs + + + LongListSelector\LongListSelectorItemType.cs + + + LongListSelector\TemplatedListBox.cs + + + LongListSelector\TemplatedListBoxItem.cs + + + MultiTemplateItemsControl.cs + + + MultiTemplateLazyListBox.cs + + + Notifications\DialogService.cs + + + Notifications\PopUp.cs + + + Notifications\ToastPrompt.cs + + + Profiling\ApplicationSpace.cs + + + Profiling\MemoryCounter.cs + + + RangeSlider.cs + + + ReorderListBox\ReorderListBox.cs + + + ReorderListBox\ReorderListBoxItem.cs + + + ScrollableTextBlock.cs + + + SmoothProgressBar.xaml.cs + SmoothProgressBar.xaml + + + Triggers\CompressionTrigger.cs + + + UnreadCounter.xaml.cs + UnreadCounter.xaml + + + Utils\Language.cs + + + WatermarkTextBox.cs + + + + + + + FlipCounter.xaml + MSBuild:Compile + Designer + + + FlipPanel.xaml + MSBuild:Compile + Designer + + + SmoothProgressBar.xaml + MSBuild:Compile + Designer + + + Themes\generic.xaml + MSBuild:Compile + Designer + + + UnreadCounter.xaml + MSBuild:Compile + Designer + + + + + + + + + ..\packages\Coding4Fun.Toolkit.Controls.2.0.7\lib\windowsphone8\Coding4Fun.Toolkit.Controls.dll + + + ..\Libraries\LayoutTransformer.dll + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/Telegram.Controls.WP8/Toolkit.Content/ApplicationBar.Cancel.png b/Telegram.Controls.WP8/Toolkit.Content/ApplicationBar.Cancel.png new file mode 100755 index 0000000..4dd724f Binary files /dev/null and b/Telegram.Controls.WP8/Toolkit.Content/ApplicationBar.Cancel.png differ diff --git a/Telegram.Controls.WP8/Toolkit.Content/ApplicationBar.Check.png b/Telegram.Controls.WP8/Toolkit.Content/ApplicationBar.Check.png new file mode 100755 index 0000000..7a07466 Binary files /dev/null and b/Telegram.Controls.WP8/Toolkit.Content/ApplicationBar.Check.png differ diff --git a/Telegram.Controls.WP8/Utils/Currency.cs b/Telegram.Controls.WP8/Utils/Currency.cs new file mode 100755 index 0000000..3cff40c --- /dev/null +++ b/Telegram.Controls.WP8/Utils/Currency.cs @@ -0,0 +1,115 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Telegram.Controls.Utils +{ + public static class Currency + { + public static int GetPow(string currency) + { + if (currency == "CLF") + { + return 4; + } + + string[] cur3 = + { + "BHD", "IQD", "JOD", "KWD", "LYD", "OMR", "TND" + }; + if (cur3.Contains(currency)) + { + return 3; + } + + string[] cur0 = + { + "BIF", "BYR", "CLP", "CVE", "DJF", "GNF", "ISK", "JPY", "KMF", "KRW", "MGA", "PYG", "RWF", "UGX", "UYI", "VND", "VUV", "XAF", "XOF", "XPF" + }; + if (cur0.Contains(currency)) + { + return 0; + } + + if (currency == "MRO") + { + return 1; + } + + return 2; + } + + private static Dictionary _dict = new Dictionary + { + {"AED", "د.إ"}, + {"AFN", "؋"}, + {"ARS", "$"}, + {"AUD", "$"}, + {"AZN", "₼"}, + {"BND", "B$"}, + {"BRL", "R$"}, + {"CAD", "$"}, + {"CHF", "Fr"}, + {"CLP", "$"}, + {"CNY", "¥"}, + {"COP", "$"}, + {"EGP", "E£"}, + {"EUR", "€"}, + {"GBP", "£"}, + {"HKD", "$"}, + {"IDR", "Rp"}, + {"ILS", "₪"}, + {"INR", "₹"}, + {"ISK", "kr"}, + {"JPY", "¥"}, + {"KRW", "₩"}, + {"KZT", "₸"}, + {"MXN", "$"}, + {"MYR", "RM"}, + {"NOK", "kr"}, + {"NZD", "$"}, + {"PHP", "₱"}, + {"RUB", "₽"}, + {"SAR", "SR"}, + {"SEK", "kr"}, + {"SGD", "$"}, + {"TRY", "₺"}, + {"TTD", "$"}, + {"TWD", "$"}, + {"TZS", "TSh"}, + {"UAH", "₴"}, + {"UGX", "USh"}, + {"USD", "$"}, + {"UYU", "$"}, + {"VND", "₫"}, + {"YER", "﷼"}, + {"ZAR", "R"}, + {"IRR", "﷼"}, + {"IQD", "ع.د"}, + {"VEF", "Bs.F."} + }; + + public static string GetSymbol(string currency) + { + string symbol; + if (_dict.TryGetValue(currency, out symbol)) + { + return symbol; + } + + return currency; + } + + public static string GetString(long totalAmount, string currency) + { + return string.Format("{0:0.00} {1}", totalAmount / Math.Pow(10.0, GetPow(currency)), GetSymbol(currency)); + } + } +} diff --git a/Telegram.Controls.WP8/packages.config b/Telegram.Controls.WP8/packages.config new file mode 100755 index 0000000..4b9cd66 --- /dev/null +++ b/Telegram.Controls.WP8/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Telegram.Controls/AnimationMediator.cs b/Telegram.Controls/AnimationMediator.cs new file mode 100755 index 0000000..bc2c48e --- /dev/null +++ b/Telegram.Controls/AnimationMediator.cs @@ -0,0 +1,100 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using System.Globalization; +using System.Windows; +using System.Windows.Controls; + +namespace Telegram.Controls +{ + /// + /// Class that acts as a Mediator between a Storyboard animation and a + /// Transform used by the Silverlight Toolkit's LayoutTransformer. + /// + /// + /// Works around an issue with the Silverlight platform where changes to + /// properties of child Transforms assigned to a Transform property do not + /// trigger the top-level property changed handler (as on WPF). + /// + public class AnimationMediator : FrameworkElement + { + /// + /// Gets or sets a reference to the LayoutTransformer to update. + /// + //public LayoutTransformer LayoutTransformer { get; set; } + + public static readonly DependencyProperty LayoutTransformerProperty = + DependencyProperty.Register("LayoutTransformer", typeof (LayoutTransformer), typeof (AnimationMediator), new PropertyMetadata(default(LayoutTransformer))); + + public LayoutTransformer LayoutTransformer + { + get { return (LayoutTransformer) GetValue(LayoutTransformerProperty); } + set { SetValue(LayoutTransformerProperty, value); } + } + + /// + /// Gets or sets the name of the LayoutTransformer to update. + /// + /// + /// This property is used iff the LayoutTransformer property is null. + /// + public string LayoutTransformerName + { + get + { + return _layoutTransformerName; + } + set + { + _layoutTransformerName = value; + // Force a new name lookup + LayoutTransformer = null; + } + } + private string _layoutTransformerName; + + /// + /// Gets or sets the value being animated. + /// + public double AnimationValue + { + get { return (double)GetValue(AnimationValueProperty); } + set { SetValue(AnimationValueProperty, value); } + } + public static readonly DependencyProperty AnimationValueProperty = + DependencyProperty.Register( + "AnimationValue", + typeof(double), + typeof(AnimationMediator), + new PropertyMetadata(AnimationValuePropertyChanged)); + private static void AnimationValuePropertyChanged( + DependencyObject o, + DependencyPropertyChangedEventArgs e) + { + //Debug.WriteLine(e.NewValue); + ((AnimationMediator)o).AnimationValuePropertyChanged(); + } + private void AnimationValuePropertyChanged() + { + if (null == LayoutTransformer) + { + // No LayoutTransformer set; try to find it by LayoutTransformerName + LayoutTransformer = FindName(LayoutTransformerName) as LayoutTransformer; + if (null == LayoutTransformer) + { + throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, + "AnimationMediator was unable to find a LayoutTransformer named \"{0}\".", + LayoutTransformerName)); + } + } + // The Transform hasn't been updated yet; schedule an update to run after it has + Dispatcher.BeginInvoke(() => LayoutTransformer.ApplyLayoutTransform()); + } + } +} diff --git a/Telegram.Controls/BindingListener.cs b/Telegram.Controls/BindingListener.cs new file mode 100755 index 0000000..cc8f2cb --- /dev/null +++ b/Telegram.Controls/BindingListener.cs @@ -0,0 +1,182 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Data; + +namespace DanielVaughan.WindowsPhone7Unleashed +{ + public class BindingListener + { + public delegate void ChangedHandler(object sender, BindingChangedEventArgs e); + + static readonly List freeListeners = new List(); + + readonly ChangedHandler changedHandler; + Binding binding; + DependencyPropertyListener listener; + FrameworkElement target; + object value; + + public BindingListener(ChangedHandler changedHandler) + { + this.changedHandler = changedHandler; + } + + public Binding Binding + { + get + { + return binding; + } + set + { + binding = value; + Attach(); + } + } + + public FrameworkElement Element + { + get + { + return target; + } + set + { + target = value; + Attach(); + } + } + + public object Value + { + get + { + return value; + } + } + + void Attach() + { + Detach(); + + if (target != null && binding != null) + { + listener = GetListener(); + listener.Attach(target, binding); + } + } + + void Detach() + { + if (listener != null) + { + this.listener.Detach(); // This is not called in the original samples + ReturnListener(); + } + } + + DependencyPropertyListener GetListener() + { + DependencyPropertyListener listener; + + if (freeListeners.Count != 0) + { + listener = freeListeners[freeListeners.Count - 1]; + freeListeners.RemoveAt(freeListeners.Count - 1); + + //return listener; //Memory leak here + } + listener = new DependencyPropertyListener(); + + listener.Changed += HandleValueChanged; + + return listener; + } + + void ReturnListener() + { + listener.Changed -= HandleValueChanged; + + freeListeners.Add(listener); + + listener = null; + } + + void HandleValueChanged(object sender, BindingChangedEventArgs e) + { + value = e.EventArgs.NewValue; + + changedHandler(this, e); + } + } + + public class DependencyPropertyListener + { + static int index; + readonly DependencyProperty property; + FrameworkElement target; + + public DependencyPropertyListener() + { + property = DependencyProperty.RegisterAttached( + "DependencyPropertyListener" + index++, + typeof(object), + typeof(DependencyPropertyListener), + new PropertyMetadata(null, HandleValueChanged)); + } + + public event EventHandler Changed; + + void HandleValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) + { + OnChanged(new BindingChangedEventArgs(e)); + } + + protected void OnChanged(BindingChangedEventArgs e) + { + var temp = Changed; + if (temp != null) + { + temp(target, e); + } + } + + public void Attach(FrameworkElement element, Binding binding) + { + if (target != null) + { + throw new Exception( + "Cannot attach an already attached listener"); + } + + target = element; + target.SetBinding(property, binding); + } + + public void Detach() + { + if (target == null) return; + + target.ClearValue(property); + target = null; + } + } + + public class BindingChangedEventArgs : EventArgs + { + public BindingChangedEventArgs(DependencyPropertyChangedEventArgs e) + { + EventArgs = e; + } + + public DependencyPropertyChangedEventArgs EventArgs { get; private set; } + } +} \ No newline at end of file diff --git a/Telegram.Controls/Extensions/ScrollViewerExtensions.cs b/Telegram.Controls/Extensions/ScrollViewerExtensions.cs new file mode 100755 index 0000000..8813acb --- /dev/null +++ b/Telegram.Controls/Extensions/ScrollViewerExtensions.cs @@ -0,0 +1,535 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media.Animation; + +namespace Telegram.Controls.Extensions + { + /// + /// Provides useful extensions to ScrollViewer instances. + /// + /// + /// Experimental + public static class ScrollViewerExtensions + { + /// + /// The amount to scroll a ScrollViewer for a line change. + /// + /// + private const double LineChange = 16.0; + /// + /// Identifies the IsMouseWheelScrollingEnabled dependency property. + /// + /// + public static readonly DependencyProperty IsMouseWheelScrollingEnabledProperty; + /// + /// Identifies the VerticalOffset dependency property. + /// + /// + private static readonly DependencyProperty VerticalOffsetProperty; + /// + /// Identifies the HorizontalOffset dependency property. + /// + /// + private static readonly DependencyProperty HorizontalOffsetProperty; + + static ScrollViewerExtensions() + { + // ISSUE: method pointer + ScrollViewerExtensions.IsMouseWheelScrollingEnabledProperty = DependencyProperty.RegisterAttached("IsMouseWheelScrollingEnabled", typeof(bool), typeof(ScrollViewerExtensions), new PropertyMetadata((object)false, new PropertyChangedCallback(OnIsMouseWheelScrollingEnabledPropertyChanged))); + // ISSUE: method pointer + ScrollViewerExtensions.VerticalOffsetProperty = DependencyProperty.RegisterAttached("VerticalOffset", typeof(double), typeof(ScrollViewerExtensions), new PropertyMetadata(new PropertyChangedCallback(OnVerticalOffsetPropertyChanged))); + // ISSUE: method pointer + ScrollViewerExtensions.HorizontalOffsetProperty = DependencyProperty.RegisterAttached("HorizontalOffset", typeof(double), typeof(ScrollViewerExtensions), new PropertyMetadata(new PropertyChangedCallback(OnHorizontalOffsetPropertyChanged))); + } + + /// + /// Gets a value indicating whether the ScrollViewer has enabled + /// scrolling via the mouse wheel. + /// + /// + /// The ScrollViewer. + /// + /// A value indicating whether the ScrollViewer has enabled scrolling + /// via the mouse wheel. + /// + /// + public static bool GetIsMouseWheelScrollingEnabled(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + else + return (bool)viewer.GetValue(ScrollViewerExtensions.IsMouseWheelScrollingEnabledProperty); + } + + /// + /// Sets a value indicating whether the ScrollViewer will enable + /// scrolling via the mouse wheel. + /// + /// + /// The ScrollViewer.A value indicating whether the ScrollViewer will enable scrolling + /// via the mouse wheel. + /// + public static void SetIsMouseWheelScrollingEnabled(this ScrollViewer viewer, bool value) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + viewer.SetValue(ScrollViewerExtensions.IsMouseWheelScrollingEnabledProperty, (value ? 1 : 0)); + } + + /// + /// IsMouseWheelScrollingEnabledProperty property changed handler. + /// + /// + /// ScrollViewerExtensions that changed its IsMouseWheelScrollingEnabled.Event arguments. + private static void OnIsMouseWheelScrollingEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ScrollViewer scrollViewer = d as ScrollViewer; + if ((bool)e.NewValue) + { + // ISSUE: method pointer + scrollViewer.MouseWheel += new MouseWheelEventHandler(OnMouseWheel); + } + else + { + // ISSUE: method pointer + scrollViewer.MouseWheel -= new MouseWheelEventHandler(OnMouseWheel); + } + } + + /// + /// Handles the mouse wheel event. + /// + /// + /// The ScrollViewer.Event arguments. + private static void OnMouseWheel(object sender, MouseWheelEventArgs e) + { + ScrollViewer viewer = sender as ScrollViewer; + Debug.Assert(viewer != null, "sender should be a non-null ScrollViewer!"); + Debug.Assert(e != null, "e should not be null!"); + if (e.Handled) + return; + double offset = ScrollViewerExtensions.CoerceVerticalOffset(viewer, viewer.VerticalOffset - (double)e.Delta); + viewer.ScrollToVerticalOffset(offset); + e.Handled = true; + } + + /// + /// Gets the value of the VerticalOffset attached property for a specified ScrollViewer. + /// + /// + /// The ScrollViewer from which the property value is read. + /// + /// The VerticalOffset property value for the ScrollViewer. + /// + private static double GetVerticalOffset(ScrollViewer element) + { + if (element == null) + throw new ArgumentNullException("element"); + else + return (double)element.GetValue(ScrollViewerExtensions.VerticalOffsetProperty); + } + + /// + /// Sets the value of the VerticalOffset attached property to a specified ScrollViewer. + /// + /// + /// The ScrollViewer to which the attached property is written.The needed VerticalOffset value. + private static void SetVerticalOffset(ScrollViewer element, double value) + { + if (element == null) + throw new ArgumentNullException("element"); + element.SetValue(ScrollViewerExtensions.VerticalOffsetProperty, (object)value); + } + + /// + /// VerticalOffsetProperty property changed handler. + /// + /// + /// ScrollViewer that changed its VerticalOffset.Event arguments. + private static void OnVerticalOffsetPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs) + { + ScrollViewer scrollViewer = dependencyObject as ScrollViewer; + if (scrollViewer == null) + throw new ArgumentNullException("dependencyObject"); + scrollViewer.ScrollToVerticalOffset((double)eventArgs.NewValue); + } + + /// + /// Gets the value of the HorizontalOffset attached property for a specified ScrollViewer. + /// + /// + /// The ScrollViewer from which the property value is read. + /// + /// The HorizontalOffset property value for the ScrollViewer. + /// + private static double GetHorizontalOffset(ScrollViewer element) + { + if (element == null) + throw new ArgumentNullException("element"); + else + return (double)element.GetValue(ScrollViewerExtensions.HorizontalOffsetProperty); + } + + /// + /// Sets the value of the HorizontalOffset attached property to a specified ScrollViewer. + /// + /// + /// The ScrollViewer to which the attached property is written.The needed HorizontalOffset value. + private static void SetHorizontalOffset(ScrollViewer element, double value) + { + if (element == null) + throw new ArgumentNullException("element"); + element.SetValue(ScrollViewerExtensions.HorizontalOffsetProperty, (object)value); + } + + /// + /// HorizontalOffsetProperty property changed handler. + /// + /// + /// ScrollViewer that changed its HorizontalOffset.Event arguments. + private static void OnHorizontalOffsetPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs) + { + ScrollViewer scrollViewer = dependencyObject as ScrollViewer; + if (scrollViewer == null) + throw new ArgumentNullException("dependencyObject"); + scrollViewer.ScrollToHorizontalOffset((double)eventArgs.NewValue); + } + + /// + /// Coerce a vertical offset to fall within the vertical bounds of a + /// ScrollViewer. + /// + /// + /// The ScrollViewer.The vertical offset to coerce. + /// + /// The coerced vertical offset that falls within the ScrollViewer's + /// vertical bounds. + /// + /// + private static double CoerceVerticalOffset(ScrollViewer viewer, double offset) + { + Debug.Assert(viewer != null, "viewer should not be null!"); + return Math.Max(Math.Min(offset, viewer.ExtentHeight), 0.0); + } + + /// + /// Coerce a horizontal offset to fall within the horizontal bounds of a + /// ScrollViewer. + /// + /// + /// The ScrollViewer.The horizontal offset to coerce. + /// + /// The coerced horizontal offset that falls within the ScrollViewer's + /// horizontal bounds. + /// + /// + private static double CoerceHorizontalOffset(ScrollViewer viewer, double offset) + { + Debug.Assert(viewer != null, "viewer should not be null!"); + return Math.Max(Math.Min(offset, viewer.ExtentWidth), 0.0); + } + + /// + /// Scroll a ScrollViewer vertically by a given offset. + /// + /// + /// The ScrollViewer.The vertical offset to scroll. + private static void ScrollByVerticalOffset(ScrollViewer viewer, double offset) + { + Debug.Assert(viewer != null, "viewer should not be null!"); + offset += viewer.VerticalOffset; + offset = ScrollViewerExtensions.CoerceVerticalOffset(viewer, offset); + viewer.ScrollToVerticalOffset(offset); + } + + /// + /// Scroll a ScrollViewer horizontally by a given offset. + /// + /// + /// The ScrollViewer.The horizontal offset to scroll. + private static void ScrollByHorizontalOffset(ScrollViewer viewer, double offset) + { + Debug.Assert(viewer != null, "viewer should not be null!"); + offset += viewer.HorizontalOffset; + offset = ScrollViewerExtensions.CoerceHorizontalOffset(viewer, offset); + viewer.ScrollToHorizontalOffset(offset); + } + + /// + /// Scroll the ScrollViewer up by a line. + /// + /// + /// The ScrollViewer. is null. + /// + public static void LineUp(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + ScrollViewerExtensions.ScrollByVerticalOffset(viewer, -16.0); + } + + /// + /// Scroll the ScrollViewer down by a line. + /// + /// + /// The ScrollViewer. is null. + /// + public static void LineDown(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + ScrollViewerExtensions.ScrollByVerticalOffset(viewer, 16.0); + } + + /// + /// Scroll the ScrollViewer left by a line. + /// + /// + /// The ScrollViewer. is null. + /// + public static void LineLeft(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + ScrollViewerExtensions.ScrollByHorizontalOffset(viewer, -16.0); + } + + /// + /// Scroll the ScrollViewer right by a line. + /// + /// + /// The ScrollViewer. is null. + /// + public static void LineRight(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + ScrollViewerExtensions.ScrollByHorizontalOffset(viewer, 16.0); + } + + /// + /// Scroll the ScrollViewer up by a page. + /// + /// + /// The ScrollViewer. is null. + /// + public static void PageUp(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + ScrollViewerExtensions.ScrollByVerticalOffset(viewer, -viewer.ViewportHeight); + } + + /// + /// Scroll the ScrollViewer down by a page. + /// + /// + /// The ScrollViewer. is null. + /// + public static void PageDown(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + ScrollViewerExtensions.ScrollByVerticalOffset(viewer, viewer.ViewportHeight); + } + + /// + /// Scroll the ScrollViewer left by a page. + /// + /// + /// The ScrollViewer. is null. + /// + public static void PageLeft(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + ScrollViewerExtensions.ScrollByHorizontalOffset(viewer, -viewer.ViewportWidth); + } + + /// + /// Scroll the ScrollViewer right by a page. + /// + /// + /// The ScrollViewer. is null. + /// + public static void PageRight(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + ScrollViewerExtensions.ScrollByHorizontalOffset(viewer, viewer.ViewportWidth); + } + + /// + /// Scroll the ScrollViewer to the top. + /// + /// + /// The ScrollViewer. is null. + /// + public static void ScrollToTop(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + viewer.ScrollToVerticalOffset(0.0); + } + + /// + /// Scroll the ScrollViewer to the bottom. + /// + /// + /// The ScrollViewer. is null. + /// + public static void ScrollToBottom(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + viewer.ScrollToVerticalOffset(viewer.ExtentHeight); + } + + /// + /// Scroll the ScrollViewer to the left. + /// + /// + /// The ScrollViewer. is null. + /// + public static void ScrollToLeft(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + viewer.ScrollToHorizontalOffset(0.0); + } + + /// + /// Scroll the ScrollViewer to the right. + /// + /// + /// The ScrollViewer. is null. + /// + public static void ScrollToRight(this ScrollViewer viewer) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + viewer.ScrollToHorizontalOffset(viewer.ExtentWidth); + } + + /// + /// Scroll the desired element into the ScrollViewer's viewport. + /// + /// + /// The ScrollViewer.The element to scroll into view. is null. + /// is null. + /// + public static void ScrollIntoView(this ScrollViewer viewer, FrameworkElement element) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + if (element == null) + throw new ArgumentNullException("element"); + ScrollViewerExtensions.ScrollIntoView(viewer, element, 0.0, 112.0, TimeSpan.FromSeconds(0.25)); + } + + public static void ScrollToBeginnig(this ScrollViewer viewer, Duration duration) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + + Storyboard storyboard = new Storyboard(); + ScrollViewerExtensions.SetVerticalOffset(viewer, viewer.VerticalOffset); + ScrollViewerExtensions.SetHorizontalOffset(viewer, viewer.HorizontalOffset); + DoubleAnimation doubleAnimation1 = new DoubleAnimation(); + doubleAnimation1.To = new double?(0.0); + doubleAnimation1.Duration = duration; + DoubleAnimation doubleAnimation2 = doubleAnimation1; + DoubleAnimation doubleAnimation3 = new DoubleAnimation(); + doubleAnimation3.To = new double?(0.0); + doubleAnimation3.Duration = duration; + DoubleAnimation doubleAnimation4 = doubleAnimation3; + Storyboard.SetTarget((Timeline)doubleAnimation2, (DependencyObject)viewer); + Storyboard.SetTarget((Timeline)doubleAnimation4, (DependencyObject)viewer); + Storyboard.SetTargetProperty((Timeline)doubleAnimation4, new PropertyPath((object)ScrollViewerExtensions.HorizontalOffsetProperty)); + Storyboard.SetTargetProperty((Timeline)doubleAnimation2, new PropertyPath((object)ScrollViewerExtensions.VerticalOffsetProperty)); + storyboard.Children.Add((Timeline)doubleAnimation2); + storyboard.Children.Add((Timeline)doubleAnimation4); + storyboard.Begin(); + } + + /// + /// Scroll the desired element into the ScrollViewer's viewport. + /// + /// + /// The ScrollViewer.The element to scroll into view.The margin to add on the left or right. + /// The margin to add on the top or bottom. + /// The duration of the animation. is null. + /// is null. + /// + public static void ScrollIntoView(this ScrollViewer viewer, FrameworkElement element, double horizontalMargin, double verticalMargin, Duration duration) + { + if (viewer == null) + throw new ArgumentNullException("viewer"); + if (element == null) + throw new ArgumentNullException("element"); + Rect? boundsRelativeTo = VisualTreeExtensions.GetBoundsRelativeTo(element, (UIElement)viewer); + if (!boundsRelativeTo.HasValue) + return; + double verticalOffset = viewer.VerticalOffset; + double num1 = 0.0; + double viewportHeight = viewer.ViewportHeight; + double num2 = boundsRelativeTo.Value.Bottom + verticalMargin; + if (viewportHeight < num2) + { + num1 = num2 - viewportHeight; + verticalOffset += num1; + } + double num3 = boundsRelativeTo.Value.Top - verticalMargin; + if (num3 - num1 < 0.0) + verticalOffset -= num1 - num3; + double horizontalOffset = viewer.HorizontalOffset; + double num4 = 0.0; + double viewportWidth = viewer.ViewportWidth; + double num5 = boundsRelativeTo.Value.Right + horizontalMargin; + if (viewportWidth < num5) + { + num4 = num5 - viewportWidth; + horizontalOffset += num4; + } + double num6 = boundsRelativeTo.Value.Left - horizontalMargin; + if (num6 - num4 < 0.0) + horizontalOffset -= num4 - num6; + if (duration == (Duration)TimeSpan.Zero) + { + viewer.ScrollToVerticalOffset(verticalOffset); + viewer.ScrollToHorizontalOffset(horizontalOffset); + } + else + { + Storyboard storyboard = new Storyboard(); + ScrollViewerExtensions.SetVerticalOffset(viewer, viewer.VerticalOffset); + ScrollViewerExtensions.SetHorizontalOffset(viewer, viewer.HorizontalOffset); + DoubleAnimation doubleAnimation1 = new DoubleAnimation(); + doubleAnimation1.To = new double?(verticalOffset); + doubleAnimation1.Duration = duration; + DoubleAnimation doubleAnimation2 = doubleAnimation1; + DoubleAnimation doubleAnimation3 = new DoubleAnimation(); + doubleAnimation3.To = new double?(verticalOffset); + doubleAnimation3.Duration = duration; + DoubleAnimation doubleAnimation4 = doubleAnimation3; + Storyboard.SetTarget((Timeline)doubleAnimation2, (DependencyObject)viewer); + Storyboard.SetTarget((Timeline)doubleAnimation4, (DependencyObject)viewer); + Storyboard.SetTargetProperty((Timeline)doubleAnimation4, new PropertyPath((object)ScrollViewerExtensions.HorizontalOffsetProperty)); + Storyboard.SetTargetProperty((Timeline)doubleAnimation2, new PropertyPath((object)ScrollViewerExtensions.VerticalOffsetProperty)); + storyboard.Children.Add((Timeline)doubleAnimation2); + storyboard.Children.Add((Timeline)doubleAnimation4); + storyboard.Begin(); + } + } + } + } diff --git a/Telegram.Controls/Extensions/VisualTreeExtensions.cs b/Telegram.Controls/Extensions/VisualTreeExtensions.cs new file mode 100755 index 0000000..aa9839b --- /dev/null +++ b/Telegram.Controls/Extensions/VisualTreeExtensions.cs @@ -0,0 +1,1022 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Media; + +namespace Telegram.Controls.Extensions +{ + /// + /// Provides useful extensions for working with the visual tree. + /// + /// + /// Since many of these extension methods are declared on types like + /// DependencyObject high up in the class hierarchy, we've placed them in + /// the Primitives namespace which is less likely to be imported for normal + /// scenarios. + /// + /// Experimental + public static class VisualTreeExtensions + { + /// + /// Retrieves all the logical children of a specified type using a + /// breadth-first search. A visual element is assumed to be a logical + /// child of another visual element if they are in the same namescope. + /// For performance reasons this method manually manages the queue + /// instead of using recursion. + /// + /// The parent framework element. + /// Specifies whether to apply templates on the traversed framework elements + /// The logical children of the framework element of the specified type. + internal static IEnumerable GetLogicalChildrenByType(this FrameworkElement parent, bool applyTemplates) + where T : FrameworkElement + { + Debug.Assert(parent != null, "The parent cannot be null."); + + if (applyTemplates && parent is Control) + { + ((Control)parent).ApplyTemplate(); + } + + Queue queue = + new Queue(parent.GetVisualChildren().OfType()); + + while (queue.Count > 0) + { + FrameworkElement element = queue.Dequeue(); + if (applyTemplates && element is Control) + { + ((Control)element).ApplyTemplate(); + } + + if (element is T) + { + yield return (T)element; + } + + foreach (FrameworkElement visualChild in element.GetVisualChildren().OfType()) + { + queue.Enqueue(visualChild); + } + } + } + + public static T FindParentOfType(this DependencyObject root) where T : class + { + var parent = VisualTreeHelper.GetParent(root); + while (parent != null) + { + var typedParent = parent as T; + if (typedParent != null) return typedParent; + parent = VisualTreeHelper.GetParent(parent); + } + return null; + } + + public static T FindChildOfType(this DependencyObject root) where T : class + { + var queue = new Queue(); + queue.Enqueue(root); + + while (queue.Count > 0) + { + var current = queue.Dequeue(); + for (var i = VisualTreeHelper.GetChildrenCount(current) - 1; 0 <= i; i--) + { + var child = VisualTreeHelper.GetChild(current, i); + var typedChild = child as T; + if (typedChild != null) + { + return typedChild; + } + queue.Enqueue(child); + } + } + return null; + } + + public static T FindByName(this DependencyObject parentElement, string name) where T : FrameworkElement + { + var count = VisualTreeHelper.GetChildrenCount(parentElement); + if (count == 0) + return null; + + for (int i = 0; i < count; i++) + { + var child = VisualTreeHelper.GetChild(parentElement, i); + + if (child != null && child is T && (string.IsNullOrEmpty(name) || ((T)child).Name == name)) + { + return (T)child; + } + + var result = FindByName(child, name); + if (result != null) + return result; + } + return null; + } + + /// + /// Get the visual tree ancestors of an element. + /// + /// The element. + /// The visual tree ancestors of the element. + /// + /// is null. + /// + public static IEnumerable GetVisualAncestors(this DependencyObject element) + { + if (element == null) + { + throw new ArgumentNullException("element"); + } + + return GetVisualAncestorsAndSelfIterator(element).Skip(1); + } + + /// + /// Get the visual tree ancestors of an element and the element itself. + /// + /// The element. + /// + /// The visual tree ancestors of an element and the element itself. + /// + /// + /// is null. + /// + public static IEnumerable GetVisualAncestorsAndSelf(this DependencyObject element) + { + if (element == null) + { + throw new ArgumentNullException("element"); + } + + return GetVisualAncestorsAndSelfIterator(element); + } + + /// + /// Get the visual tree ancestors of an element and the element itself. + /// + /// The element. + /// + /// The visual tree ancestors of an element and the element itself. + /// + private static IEnumerable GetVisualAncestorsAndSelfIterator(DependencyObject element) + { + Debug.Assert(element != null, "element should not be null!"); + + for (DependencyObject obj = element; + obj != null; + obj = VisualTreeHelper.GetParent(obj)) + { + yield return obj; + } + } + + /// + /// Gets the visual children of type T. + /// + /// + /// + /// + public static IEnumerable GetVisualChildren(this DependencyObject target) + where T : DependencyObject + { + return GetVisualChildren(target).Where(child => child is T).Cast(); + } + + /// + /// Gets the visual children of type T. + /// + /// + /// + /// + public static IEnumerable GetVisualChildren(this DependencyObject target, bool strict) + where T : DependencyObject + { + return GetVisualChildren(target, strict).Where(child => child is T).Cast(); + } + + /// + /// Gets the visual children. + /// + /// + /// Prevents the search from navigating the logical tree; eg. ContentControl.Content + /// + public static IEnumerable GetVisualChildren(this DependencyObject target, bool strict) + { + int count = VisualTreeHelper.GetChildrenCount(target); + if (count == 0) + { + if (!strict && target is ContentControl) + { + var child = ((ContentControl)target).Content as DependencyObject; + if (child != null) + { + yield return child; + } + else + { + yield break; + } + } + } + else + { + for (int i = 0; i < count; i++) + { + yield return VisualTreeHelper.GetChild(target, i); + } + } + yield break; + } + + /// + /// Get the visual tree children of an element. + /// + /// The element. + /// The visual tree children of an element. + /// + /// is null. + /// + public static IEnumerable GetVisualChildren(this DependencyObject element) + { + if (element == null) + { + throw new ArgumentNullException("element"); + } + + return GetVisualChildrenAndSelfIterator(element).Skip(1); + } + + /// + /// Get the visual tree children of an element and the element itself. + /// + /// The element. + /// + /// The visual tree children of an element and the element itself. + /// + /// + /// is null. + /// + public static IEnumerable GetVisualChildrenAndSelf(this DependencyObject element) + { + if (element == null) + { + throw new ArgumentNullException("element"); + } + + return GetVisualChildrenAndSelfIterator(element); + } + + /// + /// Get the visual tree children of an element and the element itself. + /// + /// The element. + /// + /// The visual tree children of an element and the element itself. + /// + private static IEnumerable GetVisualChildrenAndSelfIterator(this DependencyObject element) + { + Debug.Assert(element != null, "element should not be null!"); + + yield return element; + + int count = VisualTreeHelper.GetChildrenCount(element); + for (int i = 0; i < count; i++) + { + yield return VisualTreeHelper.GetChild(element, i); + } + } + + /// + /// A helper method used to get visual decnedants using a breadth-first strategy. + /// + /// + /// Prevents the search from navigating the logical tree; eg. ContentControl.Content + /// + /// + private static IEnumerable GetVisualDecendants(DependencyObject target, bool strict, Queue queue) + { + foreach (var child in GetVisualChildren(target, strict)) + { + queue.Enqueue(child); + } + + if (queue.Count == 0) + { + yield break; + } + else + { + DependencyObject node = queue.Dequeue(); + yield return node; + + foreach (var decendant in GetVisualDecendants(node, strict, queue)) + { + yield return decendant; + } + } + } + + /// + /// A helper method used to get visual decnedants using a depth-first strategy. + /// + /// + /// Prevents the search from navigating the logical tree; eg. ContentControl.Content + /// + /// + private static IEnumerable GetVisualDecendants(DependencyObject target, bool strict, Stack stack) + { + foreach (var child in GetVisualChildren(target, strict)) + { + stack.Push(child); + } + + if (stack.Count == 0) + { + yield break; + } + else + { + DependencyObject node = stack.Pop(); + yield return node; + + foreach (var decendant in GetVisualDecendants(node, strict, stack)) + { + yield return decendant; + } + } + } + + /// + /// Get the visual tree descendants of an element. + /// + /// The element. + /// The visual tree descendants of an element. + /// + /// is null. + /// + public static IEnumerable GetVisualDescendants(this DependencyObject element) + { + if (element == null) + { + throw new ArgumentNullException("element"); + } + + return GetVisualDescendantsAndSelfIterator(element).Skip(1); + } + + /// + /// Get the visual tree descendants of an element and the element + /// itself. + /// + /// The element. + /// + /// The visual tree descendants of an element and the element itself. + /// + /// + /// is null. + /// + public static IEnumerable GetVisualDescendantsAndSelf(this DependencyObject element) + { + if (element == null) + { + throw new ArgumentNullException("element"); + } + + return GetVisualDescendantsAndSelfIterator(element); + } + + /// + /// Get the visual tree descendants of an element and the element + /// itself. + /// + /// The element. + /// + /// The visual tree descendants of an element and the element itself. + /// + private static IEnumerable GetVisualDescendantsAndSelfIterator(DependencyObject element) + { + Debug.Assert(element != null, "element should not be null!"); + + Queue remaining = new Queue(); + remaining.Enqueue(element); + + while (remaining.Count > 0) + { + DependencyObject obj = remaining.Dequeue(); + yield return obj; + + foreach (DependencyObject child in obj.GetVisualChildren()) + { + remaining.Enqueue(child); + } + } + } + + /// + /// Get the visual tree siblings of an element. + /// + /// The element. + /// The visual tree siblings of an element. + /// + /// is null. + /// + public static IEnumerable GetVisualSiblings(this DependencyObject element) + { + return element + .GetVisualSiblingsAndSelf() + .Where(p => p != element); + } + + /// + /// Get the visual tree siblings of an element and the element itself. + /// + /// The element. + /// + /// The visual tree siblings of an element and the element itself. + /// + /// + /// is null. + /// + public static IEnumerable GetVisualSiblingsAndSelf(this DependencyObject element) + { + if (element == null) + { + throw new ArgumentNullException("element"); + } + + DependencyObject parent = VisualTreeHelper.GetParent(element); + return parent == null ? + Enumerable.Empty() : + parent.GetVisualChildren(); + } + + /// + /// Get the bounds of an element relative to another element. + /// + /// The element. + /// + /// The element relative to the other element. + /// + /// + /// The bounds of the element relative to another element, or null if + /// the elements are not related. + /// + /// + /// is null. + /// + /// + /// is null. + /// + public static Rect? GetBoundsRelativeTo(this FrameworkElement element, UIElement otherElement) + { + if (element == null) + { + throw new ArgumentNullException("element"); + } + else if (otherElement == null) + { + throw new ArgumentNullException("otherElement"); + } + + try + { + Point origin, bottom; + GeneralTransform transform = element.TransformToVisual(otherElement); + if (transform != null && + transform.TryTransform(new Point(), out origin) && + transform.TryTransform(new Point(element.ActualWidth, element.ActualHeight), out bottom)) + { + return new Rect(origin, bottom); + } + } + catch (ArgumentException) + { + // Ignore any exceptions thrown while trying to transform + } + + return null; + } + + public static childItem FindVisualChild(DependencyObject obj) where childItem : DependencyObject + { + for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) + { + var child = VisualTreeHelper.GetChild(obj, i); + if (child != null && child is childItem) + { + return (childItem)child; + } + else + { + var childOfChild = FindVisualChild(child); + if (childOfChild != null) + { + return childOfChild; + } + } + } + return null; + } + + public static TItem FindVisualChildWithPredicate(DependencyObject obj, Predicate predicate) where TItem : DependencyObject + { + for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) + { + var child = VisualTreeHelper.GetChild(obj, i); + if (child is TItem && predicate((TItem)child)) + { + return (TItem)child; + } + + var childOfChild = FindVisualChild(child); + if (childOfChild != null) + { + return childOfChild; + } + } + return null; + } + + /// + /// Equivalent of FindName, but works on the visual tree to go through templates, etc. + /// + /// The node to search from + /// The name to look for + /// The found node, or null if not found + public static FrameworkElement FindVisualChild(this FrameworkElement root, string name) + { + FrameworkElement temp = root.FindName(name) as FrameworkElement; + if (temp != null) + return temp; + + foreach (FrameworkElement element in root.GetVisualChildren()) + { + temp = element.FindName(name) as FrameworkElement; + if (temp != null) + return temp; + } + + return null; + } + + public static IEnumerable GetVisuals(this DependencyObject root) + { + int count = VisualTreeHelper.GetChildrenCount(root); + for (int i = 0; i < count; i++) + { + var child = VisualTreeHelper.GetChild(root, i); + yield return child; + foreach (var descendants in child.GetVisuals()) + { + yield return descendants; + } + } + } + + /// + /// Gets a visual child of the element + /// + /// The element to check + /// The index of the child + /// The found child + public static FrameworkElement GetVisualChild(this FrameworkElement node, int index) + { + return VisualTreeHelper.GetChild(node, index) as FrameworkElement; + } + + + /// + /// Gets the visual parent of the element + /// + /// The element to check + /// The visual parent + public static FrameworkElement GetVisualParent(this FrameworkElement node) + { + return VisualTreeHelper.GetParent(node) as FrameworkElement; + } + + public static T GetParent(DependencyObject child) where T : DependencyObject + { + //get parent item + DependencyObject parentObject = VisualTreeHelper.GetParent(child); + + //we've reached the end of the tree + if (parentObject == null) return null; + + //check if the parent matches the type we're looking for + T parent = parentObject as T; + if (parent != null) + return parent; + else + return GetParent(parentObject); + } + + + /// + /// Gets the VisualStateGroup with the given name, looking up the visual tree + /// + /// Element to start from + /// Name of the group to look for + /// Whether or not to look up the tree + /// The group, if found + public static VisualStateGroup GetVisualStateGroup(this FrameworkElement root, string groupName, bool searchAncestors) + { + IList groups = VisualStateManager.GetVisualStateGroups(root); + foreach (object o in groups) + { + VisualStateGroup group = o as VisualStateGroup; + if (group != null && group.Name == groupName) + return group; + } + + if (searchAncestors) + { + FrameworkElement parent = root.GetVisualParent(); + if (parent != null) + return parent.GetVisualStateGroup(groupName, true); + } + + return null; + } + + /// + /// Provides a debug string that represents the visual child tree + /// + /// The root node + /// StringBuilder into which the text is appended + /// This method only works in DEBUG mode + [Conditional("DEBUG")] + public static void GetVisualChildTreeDebugText(this FrameworkElement root, StringBuilder result) + { + List results = new List(); + root.GetChildTree("", " ", results); + foreach (string s in results) + result.AppendLine(s); + } + + private static void GetChildTree(this FrameworkElement root, string prefix, string addPrefix, List results) + { + string thisElement = ""; + if (String.IsNullOrEmpty(root.Name)) + thisElement = "[Anonymous]"; + else + thisElement = "[" + root.Name + "]"; + + thisElement += " : " + root.GetType().Name; + + results.Add(prefix + thisElement); + foreach (FrameworkElement directChild in root.GetVisualChildren()) + { + directChild.GetChildTree(prefix + addPrefix, addPrefix, results); + } + } + + /// + /// Provides a debug string that represents the visual child tree + /// + /// The root node + /// StringBuilder into which the text is appended + /// This method only works in DEBUG mode + [Conditional("DEBUG")] + public static void GetAncestorVisualTreeDebugText(this FrameworkElement node, StringBuilder result) + { + List tree = new List(); + node.GetAncestorVisualTree(tree); + string prefix = ""; + foreach (string s in tree) + { + result.AppendLine(prefix + s); + prefix = prefix + " "; + } + } + + private static void GetAncestorVisualTree(this FrameworkElement node, List children) + { + string name = String.IsNullOrEmpty(node.Name) ? "[Anon]" : node.Name; + string thisNode = name + ": " + node.GetType().Name; + + // Ensure list is in reverse order going up the tree + children.Insert(0, thisNode); + FrameworkElement parent = node.GetVisualParent(); + if (parent != null) + GetAncestorVisualTree(parent, children); + } + + /// + /// Returns a render transform of the specified type from the element, creating it if necessary + /// + /// The type of transform (Rotate, Translate, etc) + /// The element to check + /// The mode to use for creating transforms, if not found + /// The specified transform, or null if not found and not created + public static RequestedTransform GetTransform(this UIElement element, TransformCreationMode mode) where RequestedTransform : Transform, new() + { + //if (element == null) + // return null; + + Transform originalTransform = element.RenderTransform; + RequestedTransform requestedTransform = null; + MatrixTransform matrixTransform = null; + TransformGroup transformGroup = null; + + // Current transform is null -- create if necessary and return + if (originalTransform == null) + { + if ((mode & TransformCreationMode.Create) == TransformCreationMode.Create) + { + requestedTransform = new RequestedTransform(); + element.RenderTransform = requestedTransform; + return requestedTransform; + } + + return null; + } + + // Transform is exactly what we want -- return it + requestedTransform = originalTransform as RequestedTransform; + if (requestedTransform != null) + return requestedTransform; + + + // The existing transform is matrix transform - overwrite if necessary and return + matrixTransform = originalTransform as MatrixTransform; + if (matrixTransform != null) + { + if (matrixTransform.Matrix.IsIdentity + && (mode & TransformCreationMode.Create) == TransformCreationMode.Create + && (mode & TransformCreationMode.IgnoreIdentityMatrix) == TransformCreationMode.IgnoreIdentityMatrix) + { + requestedTransform = new RequestedTransform(); + element.RenderTransform = requestedTransform; + return requestedTransform; + } + + return null; + } + + // Transform is actually a group -- check for the requested type + transformGroup = originalTransform as TransformGroup; + if (transformGroup != null) + { + foreach (Transform child in transformGroup.Children) + { + // Child is the right type -- return it + if (child is RequestedTransform) + return child as RequestedTransform; + } + + // Right type was not found, but we are OK to add it + if ((mode & TransformCreationMode.AddToGroup) == TransformCreationMode.AddToGroup) + { + requestedTransform = new RequestedTransform(); + transformGroup.Children.Add(requestedTransform); + return requestedTransform; + } + + return null; + } + + // Current ransform is not a group and is not what we want; + // create a new group containing the existing transform and the new one + if ((mode & TransformCreationMode.CombineIntoGroup) == TransformCreationMode.CombineIntoGroup) + { + transformGroup = new TransformGroup(); + transformGroup.Children.Add(originalTransform); + transformGroup.Children.Add(requestedTransform); + element.RenderTransform = transformGroup; + return requestedTransform; + } + + Debug.Assert(false, "Shouldn't get here"); + return null; + } + + /// + /// Returns a string representation of a property path needed to update a Storyboard + /// + /// The element to get the path for + /// The property of the transform + /// The type of transform to look fo + /// A property path + public static string GetTransformPropertyPath(this FrameworkElement element, string subProperty) where RequestedType : Transform + { + Transform t = element.RenderTransform; + if (t is RequestedType) + return String.Format("(RenderTransform).({0}.{1})", typeof(RequestedType).Name, subProperty); + + else if (t is TransformGroup) + { + TransformGroup g = t as TransformGroup; + for (int i = 0; i < g.Children.Count; i++) + { + if (g.Children[i] is RequestedType) + return String.Format("(RenderTransform).(TransformGroup.Children)[" + i + "].({0}.{1})", + typeof(RequestedType).Name, subProperty); + } + } + + return ""; + } + + /// + /// Returns a plane projection, creating it if necessary + /// + /// The element + /// Whether or not to create the projection if it doesn't already exist + /// The plane project, or null if not found / created + public static PlaneProjection GetPlaneProjection(this UIElement element, bool create) + { + Projection originalProjection = element.Projection; + PlaneProjection projection = null; + + // Projection is already a plane projection; return it + if (originalProjection is PlaneProjection) + return originalProjection as PlaneProjection; + + // Projection is null; create it if necessary + if (originalProjection == null) + { + if (create) + { + projection = new PlaneProjection(); + element.Projection = projection; + } + } + + // Note that if the project is a Matrix projection, it will not be + // changed and null will be returned. + return projection; + } + + /// + /// Perform an action when the element's LayoutUpdated event fires. + /// + /// The element. + /// The action to perform. + /// + /// is null. + /// + /// + /// is null. + /// + public static void InvokeOnLayoutUpdated(this FrameworkElement element, Action action) + { + if (element == null) + { + throw new ArgumentNullException("element"); + } + else if (action == null) + { + throw new ArgumentNullException("action"); + } + + // Create an event handler that unhooks itself before calling the + // action and then attach it to the LayoutUpdated event. + EventHandler handler = null; + handler = (s, e) => + { + //TODO: is this the right thing to do? + //Deployment.Current.Dispatcher.BeginInvoke(() => { element.LayoutUpdated -= handler; }); + element.LayoutUpdated -= handler; + + action(); + }; + element.LayoutUpdated += handler; + } + + /// + /// Retrieves all the logical children of a framework element using a + /// breadth-first search. For performance reasons this method manually + /// manages the stack instead of using recursion. + /// + /// The parent framework element. + /// The logical children of the framework element. + internal static IEnumerable GetLogicalChildren(this FrameworkElement parent) + { + Debug.Assert(parent != null, "The parent cannot be null."); + + Popup popup = parent as Popup; + if (popup != null) + { + FrameworkElement popupChild = popup.Child as FrameworkElement; + if (popupChild != null) + { + yield return popupChild; + } + } + + // If control is an items control return all children using the + // Item container generator. + ItemsControl itemsControl = parent as ItemsControl; + if (itemsControl != null) + { + foreach (FrameworkElement logicalChild in + Enumerable + .Range(0, itemsControl.Items.Count) + .Select(index => itemsControl.ItemContainerGenerator.ContainerFromIndex(index)) + .OfType()) + { + yield return logicalChild; + } + } + + string parentName = parent.Name; + Queue queue = + new Queue(parent.GetVisualChildren().OfType()); + + while (queue.Count > 0) + { + FrameworkElement element = queue.Dequeue(); + if (element.Parent == parent || element is UserControl) + { + yield return element; + } + else + { + foreach (FrameworkElement visualChild in element.GetVisualChildren().OfType()) + { + queue.Enqueue(visualChild); + } + } + } + } + + /// + /// Retrieves all the logical descendents of a framework element using a + /// breadth-first search. For performance reasons this method manually + /// manages the stack instead of using recursion. + /// + /// The parent framework element. + /// The logical children of the framework element. + internal static IEnumerable GetLogicalDescendents(this FrameworkElement parent) + { + Debug.Assert(parent != null, "The parent cannot be null."); + + //return + // FunctionalProgramming.TraverseBreadthFirst( + // parent, + // node => node.GetLogicalChildren(), + // node => true); + + return null; + } + } + + /// + /// Possible modes for creating a transform + /// + [Flags] + public enum TransformCreationMode + { + /// + /// Don't try and create a transform if it doesn't already exist + /// + None = 0, + + /// + /// Create a transform if none exists + /// + Create = 1, + + /// + /// Create and add to an existing group + /// + AddToGroup = 2, + + /// + /// Create a group and combine with existing transform; may break existing animations + /// + CombineIntoGroup = 4, + + /// + /// Treat identity matrix as if it wasn't there; may break existing animations + /// + IgnoreIdentityMatrix = 8, + + /// + /// Create a new transform or add to group + /// + CreateOrAddAndIgnoreMatrix = Create | AddToGroup | IgnoreIdentityMatrix, + + /// + /// Default behaviour, equivalent to CreateOrAddAndIgnoreMatrix + /// + Default = CreateOrAddAndIgnoreMatrix, + } +} diff --git a/Telegram.Controls/FlipCounter.xaml b/Telegram.Controls/FlipCounter.xaml new file mode 100755 index 0000000..89b2851 --- /dev/null +++ b/Telegram.Controls/FlipCounter.xaml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + Visible + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Telegram.Controls/FlipCounter.xaml.cs b/Telegram.Controls/FlipCounter.xaml.cs new file mode 100755 index 0000000..e78f59d --- /dev/null +++ b/Telegram.Controls/FlipCounter.xaml.cs @@ -0,0 +1,74 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; + +namespace Telegram.Controls +{ + public partial class FlipCounter + { + public FlipCounter() + { + // Required to initialize variables + InitializeComponent(); + + BackTile.Width = 2*6.0 + 1*8.66; + FrontTile.Width = 2 * 6.0 + 1 * 8.66; + } + + private int _previousCounter; + + public static readonly DependencyProperty CounterProperty = + DependencyProperty.Register("Counter", typeof (int), typeof (FlipCounter), new PropertyMetadata(default(int), OnCounterChanged)); + + private bool _initialized; + + private static void OnCounterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var flipCounter = (FlipCounter) d; + if (flipCounter != null) + { + var oldCounter = (int)e.OldValue; + var oldCounterLength = e.OldValue.ToString().Length; + var newCounter = (int)e.NewValue; + var newCounterLength = e.NewValue.ToString().Length; + if (!flipCounter._initialized) + { + flipCounter._initialized = true; + flipCounter.BackTile.Width = 2 * 6.0 + newCounterLength * 8.66; + flipCounter.FrontTile.Width = 2 * 6.0 + newCounterLength * 8.66; + } + if (oldCounter != newCounter) + { + if (oldCounterLength != newCounterLength) + { + flipCounter.BackTile.Width = 2 * 6.0 + newCounterLength * 8.66; + flipCounter.FrontTile.Width = 2 * 6.0 + newCounterLength * 8.66; + } + + flipCounter.FrontText.Text = flipCounter.BackText.Text; + var check1 = VisualStateManager.GoToState(flipCounter, "Normal", false); + flipCounter.BackText.Text = Convert.ToString(newCounter); + var check = VisualStateManager.GoToState(flipCounter, "Flipped", true); + } + } + } + + public int Counter + { + get { return (int) GetValue(CounterProperty); } + set { SetValue(CounterProperty, value); } + } + + private void Flip_Completed(object sender, EventArgs e) + { + //FrontText.Text = BackText.Text; + //var check = VisualStateManager.GoToState(this, "Normal", false); + } + } +} \ No newline at end of file diff --git a/Telegram.Controls/FlipPanel.xaml b/Telegram.Controls/FlipPanel.xaml new file mode 100755 index 0000000..9ac1847 --- /dev/null +++ b/Telegram.Controls/FlipPanel.xaml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + Visible + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Telegram.Controls/FlipPanel.xaml.cs b/Telegram.Controls/FlipPanel.xaml.cs new file mode 100755 index 0000000..9271303 --- /dev/null +++ b/Telegram.Controls/FlipPanel.xaml.cs @@ -0,0 +1,69 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; + +namespace Telegram.Controls +{ + public partial class FlipPanel + { + public FlipPanel() + { + InitializeComponent(); + } + + public static readonly DependencyProperty TextBlockStyleProperty = + DependencyProperty.Register("TextBlockStyle", typeof (Style), typeof (FlipPanel), new PropertyMetadata(default(Style), OnTextBlockStyleChanged)); + + private static void OnTextBlockStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var panel = (FlipPanel)d; + if (panel != null) + { + panel.FrontText.Style = (Style)e.NewValue; + panel.BackText.Style = (Style)e.NewValue; + } + + } + + public Style TextBlockStyle + { + get { return (Style) GetValue(TextBlockStyleProperty); } + set { SetValue(TextBlockStyleProperty, value); } + } + + + public static readonly DependencyProperty TextProperty = + DependencyProperty.Register("Text", typeof(string), typeof(FlipPanel), new PropertyMetadata(default(string), OnTextChanged)); + + private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var panel = (FlipPanel)d; + if (panel != null) + { + var oldText = (string)e.OldValue; + var newText = (string)e.NewValue; + + if (oldText != newText) + { + + panel.FrontText.Text = panel.BackText.Text; + var check1 = VisualStateManager.GoToState(panel, "Normal", false); + panel.BackText.Text = Convert.ToString(newText); + var check = VisualStateManager.GoToState(panel, "Flipped", true); + } + } + } + + public string Text + { + get { return (string)GetValue(TextProperty); } + set { SetValue(TextProperty, value); } + } + } +} diff --git a/Telegram.Controls/Helpers/DependencyPropertyChangedListener.cs b/Telegram.Controls/Helpers/DependencyPropertyChangedListener.cs new file mode 100755 index 0000000..e4370d4 --- /dev/null +++ b/Telegram.Controls/Helpers/DependencyPropertyChangedListener.cs @@ -0,0 +1,131 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Data; + +namespace Telegram.Controls.Helpers +{ + /// + /// This class implements a listener to receive notifications for dependency property changes. + /// + public class DependencyPropertyChangedListener + { + + #region Inner types + + // Helper element to make it possible to use the binding engine to get notified when the source element property changes. + private sealed class RelayObject : DependencyObject + { + private DependencyPropertyChangedListener _listener; + + internal RelayObject(DependencyPropertyChangedListener listener) + { + _listener = listener; + } + + #region Value (DependencyProperty) + + public object Value + { + get { return (object)GetValue(ValueProperty); } + set { SetValue(ValueProperty, value); } + } + public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(RelayObject), new PropertyMetadata(default(object), new PropertyChangedCallback(OnValueChanged))); + + private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + object oldValue = (object)e.OldValue; + object newValue = (object)e.NewValue; + RelayObject source = (RelayObject)d; + source.OnValueChanged(oldValue, newValue); + } + + private void OnValueChanged(object oldValue, object newValue) + { + _listener.OnValueChanged(oldValue, newValue); + } + + #endregion + } + + #endregion + + #region Events + + /// + /// Raises when the dependency property changes. + /// + public event EventHandler ValueChanged; + + #endregion + + #region Ctor + + private DependencyPropertyChangedListener() + { + // just to make it private + } + + #endregion + + // holds a reference to the relay object in order that the GC does not collect it + private RelayObject RelayInstance { get; set; } + + public static DependencyPropertyChangedListener Create(DependencyObject sourceElement, string propertyPath) + //public static DependencyPropertyChangedListener Create(DependencyObject sourceElement, DependencyProperty property) + { + // check input + if (sourceElement == null) + throw new ArgumentNullException("sourceElement"); + if (string.IsNullOrWhiteSpace(propertyPath)) + throw new ArgumentException("propertyPath is empty"); + + // create listener + DependencyPropertyChangedListener listener = new DependencyPropertyChangedListener(); + + // setup binding + Binding binding = new Binding(); + binding.Source = sourceElement; + binding.Mode = BindingMode.OneWay; + //binding.Path = new PropertyPath(property); // throws exception + binding.Path = new PropertyPath(propertyPath); + + // create relay object + RelayObject relay = new RelayObject(listener); + // ...the listener holds a reference to the relay object in order that the GC does not collect it + listener.RelayInstance = relay; + + // set binding + BindingOperations.SetBinding(relay, RelayObject.ValueProperty, binding); + + return listener; + } + + public void Detach() + { + if (this.RelayInstance != null) + { + // first: reset member to prevent further eventing of ValueChanged event. + RelayObject temp = this.RelayInstance; + this.RelayInstance = null; + + // second: clear the binding -> raises property changed event... + temp.ClearValue(RelayObject.ValueProperty); + } + } + + private void OnValueChanged(object oldValue, object newValue) + { + // raise event, but only if the listener is not detached. + if (ValueChanged != null && this.RelayInstance != null) + ValueChanged(this, new DependencyPropertyValueChangedEventArgs(oldValue, newValue)); + } + + } +} diff --git a/Telegram.Controls/Helpers/DependencyPropertyValueChangedEventArgs.cs b/Telegram.Controls/Helpers/DependencyPropertyValueChangedEventArgs.cs new file mode 100755 index 0000000..db561c8 --- /dev/null +++ b/Telegram.Controls/Helpers/DependencyPropertyValueChangedEventArgs.cs @@ -0,0 +1,33 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace Telegram.Controls.Helpers +{ + /// + /// Provides data for a DependencyPropertyChangedListener ValueChanged implementation. + /// + public class DependencyPropertyValueChangedEventArgs : EventArgs + { + internal DependencyPropertyValueChangedEventArgs(object oldValue, object newValue) + { + OldValue = oldValue; + NewValue = newValue; + } + + /// + /// Gets the value of the property before the change. + /// + public object OldValue { get; private set; } + + /// + /// Gets the value of the property after the change. + /// + public object NewValue { get; private set; } + } +} diff --git a/Telegram.Controls/HighlightingTextBlock.cs b/Telegram.Controls/HighlightingTextBlock.cs new file mode 100755 index 0000000..40af796 --- /dev/null +++ b/Telegram.Controls/HighlightingTextBlock.cs @@ -0,0 +1,418 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Media; + +namespace Telegram.Controls +{ + /// + /// A specialized highlighting text block control. + /// + public class HighlightingTextBlock : ContentControl + { + /// + /// Gets or sets the text block reference. + /// + private TextBlock _textBlock { get; set; } + + #region public string Text + /// + /// Gets or sets the contents of the TextBox. + /// + public string Text + { + get { return GetValue(TextProperty) as string; } + set { SetValue(TextProperty, value); } + } + + /// + /// Identifies the Text dependency property. + /// + public static readonly DependencyProperty TextProperty = + DependencyProperty.Register( + "Text", + typeof(string), + typeof(HighlightingTextBlock), + new PropertyMetadata(OnTextPropertyChanged)); + + /// + /// TextProperty property changed handler. + /// + /// AutoCompleteBox that changed its Text. + /// Event arguments. + private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var source = d as HighlightingTextBlock; + + if (source != null + && source._textBlock != null) + { + source._textBlock.Inlines.Clear(); + + var value = e.NewValue as string; + + if (value != null) + { + var highlight = source.HighlightText ?? string.Empty; + if (string.IsNullOrEmpty(highlight)) + { + var run = new Run + { + Text = value, + Foreground = source._textBlock.Foreground, + FontWeight = source._textBlock.FontWeight + }; + + source._textBlock.Inlines.Add(run); + } + else + { + var index = 0; + var previousIndex = -1; + while ((index = value.IndexOf(highlight, index, StringComparison.OrdinalIgnoreCase)) != -1) + { + if (previousIndex == -1 + || index > previousIndex + highlight.Length) + { + var startIndex = previousIndex == -1 ? 0 : previousIndex + highlight.Length; + var run = new Run + { + Text = value.Substring(startIndex, index - startIndex), + Foreground = source._textBlock.Foreground, + FontWeight = source._textBlock.FontWeight + }; + + source._textBlock.Inlines.Add(run); + } + + var highlightedRun = new Run + { + Text = value.Substring(index, highlight.Length), + Foreground = source.HighlightBrush, + FontWeight = source.HighlightFontWeight + }; + + source._textBlock.Inlines.Add(highlightedRun); + + previousIndex = index; + index = index + highlight.Length; + } + + if (previousIndex == -1) + { + var run = new Run + { + Text = value, + Foreground = source._textBlock.Foreground, + FontWeight = source._textBlock.FontWeight + }; + + source._textBlock.Inlines.Add(run); + } + else if (value.Length > previousIndex + highlight.Length) + { + var run = new Run + { + Text = value.Substring(previousIndex + highlight.Length, value.Length - (previousIndex + highlight.Length)), + Foreground = source._textBlock.Foreground, + FontWeight = source._textBlock.FontWeight + }; + + source._textBlock.Inlines.Add(run); + } + } + } + } + } + + #endregion public string Text + + public static readonly DependencyProperty UseTransliterationProperty = DependencyProperty.Register( + "UseTransliteration", typeof (bool), typeof (HighlightingTextBlock), new PropertyMetadata(default(bool))); + + public bool UseTransliteration + { + get { return (bool) GetValue(UseTransliterationProperty); } + set { SetValue(UseTransliterationProperty, value); } + } + + #region public string HighlightText + /// + /// Gets or sets the highlighted text. + /// + public string HighlightText + { + get { return GetValue(HighlightTextProperty) as string; } + set { SetValue(HighlightTextProperty, value); } + } + + /// + /// Identifies the HighlightText dependency property. + /// + public static readonly DependencyProperty HighlightTextProperty = + DependencyProperty.Register( + "HighlightText", + typeof(string), + typeof(HighlightingTextBlock), + new PropertyMetadata(OnHighlightTextPropertyChanged)); + + /// + /// HighlightText property changed handler. + /// + /// AutoCompleteBox that changed its HighlightText. + /// Event arguments. + private static void OnHighlightTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + } + + #endregion public string HighlightText + + #region public Style TextBlockStyle + + public static readonly DependencyProperty TextBlockStyleProperty = + DependencyProperty.Register("TextBlockStyle", typeof (Style), typeof (HighlightingTextBlock), new PropertyMetadata(default(Style), OnTextBlockStyleChanged)); + + private static void OnTextBlockStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var highlightingTextBlock = (HighlightingTextBlock) d; + + if (highlightingTextBlock != null + && highlightingTextBlock._textBlock != null) + { + highlightingTextBlock._textBlock.Style = (Style) e.NewValue; + } + } + + public Style TextBlockStyle + { + get { return (Style)GetValue(TextBlockStyleProperty); } + set { SetValue(TextBlockStyleProperty, value); } + } + + #endregion + + #region public Brush HighlightBrush + /// + /// Gets or sets the highlight brush. + /// + public Brush HighlightBrush + { + get { return GetValue(HighlightBrushProperty) as Brush; } + set { SetValue(HighlightBrushProperty, value); } + } + + /// + /// Identifies the HighlightBrush dependency property. + /// + public static readonly DependencyProperty HighlightBrushProperty = + DependencyProperty.Register( + "HighlightBrush", + typeof(Brush), + typeof(HighlightingTextBlock), + new PropertyMetadata(null, OnHighlightBrushPropertyChanged)); + + /// + /// HighlightBrushProperty property changed handler. + /// + /// HighlightingTextBlock that changed its HighlightBrush. + /// Event arguments. + private static void OnHighlightBrushPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + //HighlightingTextBlock source = d as HighlightingTextBlock; + //source.ApplyHighlighting(); + } + #endregion public Brush HighlightBrush + + #region public FontWeight HighlightFontWeight + /// + /// Gets or sets the font weight used on highlighted text. + /// + public FontWeight HighlightFontWeight + { + get { return (FontWeight)GetValue(HighlightFontWeightProperty); } + set { SetValue(HighlightFontWeightProperty, value); } + } + + /// + /// Identifies the HighlightFontWeight dependency property. + /// + public static readonly DependencyProperty HighlightFontWeightProperty = + DependencyProperty.Register( + "HighlightFontWeight", + typeof(FontWeight), + typeof(HighlightingTextBlock), + new PropertyMetadata(FontWeights.Normal, OnHighlightFontWeightPropertyChanged)); + + /// + /// HighlightFontWeightProperty property changed handler. + /// + /// HighlightingTextBlock that changed its HighlightFontWeight. + /// Event arguments. + private static void OnHighlightFontWeightPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + HighlightingTextBlock source = d as HighlightingTextBlock; + FontWeight value = (FontWeight)e.NewValue; + } + #endregion public FontWeight HighlightFontWeight + + /// + /// Initializes a new HighlightingTextBlock class. + /// + public HighlightingTextBlock() + { + _textBlock = new TextBlock(); + if (TextBlockStyle != null) + { + _textBlock.Style = TextBlockStyle; + } + Content = _textBlock; + } + } + + + public static class Emoji + + { + /** + * Emoji codes combined into the groups corresponding to the categories in the interface + * + **/ + + public static ulong[][] Data = { + new ulong[]{ + 0x00000000D83DDE04L, 0x00000000D83DDE03L, 0x00000000D83DDE00L, 0x00000000D83DDE0AL, 0x000000000000263AL, 0x00000000D83DDE09L, 0x00000000D83DDE0DL, + 0x00000000D83DDE18L, 0x00000000D83DDE1AL, 0x00000000D83DDE17L, 0x00000000D83DDE19L, 0x00000000D83DDE1CL, 0x00000000D83DDE1DL, 0x00000000D83DDE1BL, + 0x00000000D83DDE33L, 0x00000000D83DDE01L, 0x00000000D83DDE14L, 0x00000000D83DDE0CL, 0x00000000D83DDE12L, 0x00000000D83DDE1EL, 0x00000000D83DDE23L, + 0x00000000D83DDE22L, 0x00000000D83DDE02L, 0x00000000D83DDE2DL, 0x00000000D83DDE2AL, 0x00000000D83DDE25L, 0x00000000D83DDE30L, 0x00000000D83DDE05L, + 0x00000000D83DDE13L, 0x00000000D83DDE29L, 0x00000000D83DDE2BL, 0x00000000D83DDE28L, 0x00000000D83DDE31L, 0x00000000D83DDE20L, 0x00000000D83DDE21L, + 0x00000000D83DDE24L, 0x00000000D83DDE16L, 0x00000000D83DDE06L, 0x00000000D83DDE0BL, 0x00000000D83DDE37L, 0x00000000D83DDE0EL, 0x00000000D83DDE34L, + 0x00000000D83DDE35L, 0x00000000D83DDE32L, 0x00000000D83DDE1FL, 0x00000000D83DDE26L, 0x00000000D83DDE27L, 0x00000000D83DDE08L, 0x00000000D83DDC7FL, + 0x00000000D83DDE2EL, 0x00000000D83DDE2CL, 0x00000000D83DDE10L, 0x00000000D83DDE15L, 0x00000000D83DDE2FL, 0x00000000D83DDE36L, 0x00000000D83DDE07L, + 0x00000000D83DDE0FL, 0x00000000D83DDE11L, 0x00000000D83DDC72L, 0x00000000D83DDC73L, 0x00000000D83DDC6EL, 0x00000000D83DDC77L, 0x00000000D83DDC82L, + 0x00000000D83DDC76L, 0x00000000D83DDC66L, 0x00000000D83DDC67L, 0x00000000D83DDC68L, 0x00000000D83DDC69L, 0x00000000D83DDC74L, 0x00000000D83DDC75L, + 0x00000000D83DDC71L, 0x00000000D83DDC7CL, 0x00000000D83DDC78L, 0x00000000D83DDE3AL, 0x00000000D83DDE38L, 0x00000000D83DDE3BL, 0x00000000D83DDE3DL, + 0x00000000D83DDE3CL, 0x00000000D83DDE40L, 0x00000000D83DDE3FL, 0x00000000D83DDE39L, 0x00000000D83DDE3EL, 0x00000000D83DDC79L, 0x00000000D83DDC7AL, + 0x00000000D83DDE48L, 0x00000000D83DDE49L, 0x00000000D83DDE4AL, 0x00000000D83DDC80L, 0x00000000D83DDC7DL, 0x00000000D83DDCA9L, 0x00000000D83DDD25L, + 0x0000000000002728L, 0x00000000D83CDF1FL, 0x00000000D83DDCABL, 0x00000000D83DDCA5L, 0x00000000D83DDCA2L, 0x00000000D83DDCA6L, 0x00000000D83DDCA7L, + 0x00000000D83DDCA4L, 0x00000000D83DDCA8L, 0x00000000D83DDC42L, 0x00000000D83DDC40L, 0x00000000D83DDC43L, 0x00000000D83DDC45L, 0x00000000D83DDC44L, + 0x00000000D83DDC4DL, 0x00000000D83DDC4EL, 0x00000000D83DDC4CL, 0x00000000D83DDC4AL, 0x000000000000270AL, 0x000000000000270CL, 0x00000000D83DDC4BL, + 0x000000000000270BL, 0x00000000D83DDC50L, 0x00000000D83DDC46L, 0x00000000D83DDC47L, 0x00000000D83DDC49L, 0x00000000D83DDC48L, 0x00000000D83DDE4CL, + 0x00000000D83DDE4FL, 0x000000000000261DL, 0x00000000D83DDC4FL, 0x00000000D83DDCAAL, 0x00000000D83DDEB6L, 0x00000000D83CDFC3L, 0x00000000D83DDC83L, + 0x00000000D83DDC6BL, 0x00000000D83DDC6AL, 0x00000000D83DDC6CL, 0x00000000D83DDC6DL, 0x00000000D83DDC8FL, 0x00000000D83DDC91L, 0x00000000D83DDC6FL, + 0x00000000D83DDE46L, 0x00000000D83DDE45L, 0x00000000D83DDC81L, 0x00000000D83DDE4BL, 0x00000000D83DDC86L, 0x00000000D83DDC87L, 0x00000000D83DDC85L, + 0x00000000D83DDC70L, 0x00000000D83DDE4EL, 0x00000000D83DDE4DL, 0x00000000D83DDE47L, 0x00000000D83CDFA9L, 0x00000000D83DDC51L, 0x00000000D83DDC52L, + 0x00000000D83DDC5FL, 0x00000000D83DDC5EL, 0x00000000D83DDC61L, 0x00000000D83DDC60L, 0x00000000D83DDC62L, 0x00000000D83DDC55L, 0x00000000D83DDC54L, + 0x00000000D83DDC5AL, 0x00000000D83DDC57L, 0x00000000D83CDFBDL, 0x00000000D83DDC56L, 0x00000000D83DDC58L, 0x00000000D83DDC59L, 0x00000000D83DDCBCL, + 0x00000000D83DDC5CL, 0x00000000D83DDC5DL, 0x00000000D83DDC5BL, 0x00000000D83DDC53L, 0x00000000D83CDF80L, 0x00000000D83CDF02L, 0x00000000D83DDC84L, + 0x00000000D83DDC9BL, 0x00000000D83DDC99L, 0x00000000D83DDC9CL, 0x00000000D83DDC9AL, 0x0000000000002764L, 0x00000000D83DDC94L, 0x00000000D83DDC97L, + 0x00000000D83DDC93L, 0x00000000D83DDC95L, 0x00000000D83DDC96L, 0x00000000D83DDC9EL, 0x00000000D83DDC98L, 0x00000000D83DDC8CL, 0x00000000D83DDC8BL, + 0x00000000D83DDC8DL, 0x00000000D83DDC8EL, 0x00000000D83DDC64L, 0x00000000D83DDC65L, 0x00000000D83DDCACL, 0x00000000D83DDC63L, 0x00000000D83DDCADL}, + new ulong[]{ + 0x00000000D83DDC36L, 0x00000000D83DDC3AL, 0x00000000D83DDC31L, 0x00000000D83DDC2DL, 0x00000000D83DDC39L, 0x00000000D83DDC30L, 0x00000000D83DDC38L, 0x00000000D83DDC2FL, + 0x00000000D83DDC28L, 0x00000000D83DDC3BL, 0x00000000D83DDC37L, 0x00000000D83DDC3DL, 0x00000000D83DDC2EL, 0x00000000D83DDC17L, 0x00000000D83DDC35L, + 0x00000000D83DDC12L, 0x00000000D83DDC34L, 0x00000000D83DDC11L, 0x00000000D83DDC18L, 0x00000000D83DDC3CL, 0x00000000D83DDC27L, 0x00000000D83DDC26L, + 0x00000000D83DDC24L, 0x00000000D83DDC25L, 0x00000000D83DDC23L, 0x00000000D83DDC14L, 0x00000000D83DDC0DL, 0x00000000D83DDC22L, 0x00000000D83DDC1BL, + 0x00000000D83DDC1DL, 0x00000000D83DDC1CL, 0x00000000D83DDC1EL, 0x00000000D83DDC0CL, 0x00000000D83DDC19L, 0x00000000D83DDC1AL, 0x00000000D83DDC20L, + 0x00000000D83DDC1FL, 0x00000000D83DDC2CL, 0x00000000D83DDC33L, 0x00000000D83DDC0BL, 0x00000000D83DDC04L, 0x00000000D83DDC0FL, 0x00000000D83DDC00L, + 0x00000000D83DDC03L, 0x00000000D83DDC05L, 0x00000000D83DDC07L, 0x00000000D83DDC09L, 0x00000000D83DDC0EL, 0x00000000D83DDC10L, 0x00000000D83DDC13L, + 0x00000000D83DDC15L, 0x00000000D83DDC16L, 0x00000000D83DDC01L, 0x00000000D83DDC02L, 0x00000000D83DDC32L, 0x00000000D83DDC21L, 0x00000000D83DDC0AL, + 0x00000000D83DDC2BL, 0x00000000D83DDC2AL, 0x00000000D83DDC06L, 0x00000000D83DDC08L, 0x00000000D83DDC29L, 0x00000000D83DDC3EL, 0x00000000D83DDC90L, + 0x00000000D83CDF38L, 0x00000000D83CDF37L, 0x00000000D83CDF40L, 0x00000000D83CDF39L, 0x00000000D83CDF3BL, 0x00000000D83CDF3AL, 0x00000000D83CDF41L, + 0x00000000D83CDF43L, 0x00000000D83CDF42L, 0x00000000D83CDF3FL, 0x00000000D83CDF3EL, 0x00000000D83CDF44L, 0x00000000D83CDF35L, 0x00000000D83CDF34L, + 0x00000000D83CDF32L, 0x00000000D83CDF33L, 0x00000000D83CDF30L, 0x00000000D83CDF31L, 0x00000000D83CDF3CL, 0x00000000D83CDF10L, 0x00000000D83CDF1EL, + 0x00000000D83CDF1DL, 0x00000000D83CDF1AL, 0x00000000D83CDF11L, 0x00000000D83CDF12L, 0x00000000D83CDF13L, 0x00000000D83CDF14L, 0x00000000D83CDF15L, + 0x00000000D83CDF16L, 0x00000000D83CDF17L, 0x00000000D83CDF18L, 0x00000000D83CDF1CL, 0x00000000D83CDF1BL, 0x00000000D83CDF19L, 0x00000000D83CDF0DL, + 0x00000000D83CDF0EL, 0x00000000D83CDF0FL, 0x00000000D83CDF0BL, 0x00000000D83CDF0CL, 0x00000000D83CDF20L, 0x0000000000002B50L, 0x0000000000002600L, + 0x00000000000026C5L, 0x0000000000002601L, 0x00000000000026A1L, 0x0000000000002614L, 0x0000000000002744L, 0x00000000000026C4L, 0x00000000D83CDF00L, + 0x00000000D83CDF01L, 0x00000000D83CDF08L, 0x00000000D83CDF0AL}, + new ulong[]{ + 0x00000000D83CDF8DL, 0x00000000D83DDC9DL, 0x00000000D83CDF8EL, 0x00000000D83CDF92L, 0x00000000D83CDF93L, 0x00000000D83CDF8FL, 0x00000000D83CDF86L, 0x00000000D83CDF87L, + 0x00000000D83CDF90L, 0x00000000D83CDF91L, 0x00000000D83CDF83L, 0x00000000D83DDC7BL, 0x00000000D83CDF85L, 0x00000000D83CDF84L, 0x00000000D83CDF81L, + 0x00000000D83CDF8BL, 0x00000000D83CDF89L, 0x00000000D83CDF8AL, 0x00000000D83CDF88L, 0x00000000D83CDF8CL, 0x00000000D83DDD2EL, 0x00000000D83CDFA5L, + 0x00000000D83DDCF7L, 0x00000000D83DDCF9L, 0x00000000D83DDCFCL, 0x00000000D83DDCBFL, 0x00000000D83DDCC0L, 0x00000000D83DDCBDL, 0x00000000D83DDCBEL, + 0x00000000D83DDCBBL, 0x00000000D83DDCF1L, 0x000000000000260EL, 0x00000000D83DDCDEL, 0x00000000D83DDCDFL, 0x00000000D83DDCE0L, 0x00000000D83DDCE1L, + 0x00000000D83DDCFAL, 0x00000000D83DDCFBL, 0x00000000D83DDD0AL, 0x00000000D83DDD09L, 0x00000000D83DDD08L, 0x00000000D83DDD07L, 0x00000000D83DDD14L, + 0x00000000D83DDD14L, 0x00000000D83DDCE2L, 0x00000000D83DDCE3L, 0x00000000000023F3L, 0x000000000000231BL, 0x00000000000023F0L, 0x000000000000231AL, + 0x00000000D83DDD13L, 0x00000000D83DDD12L, 0x00000000D83DDD0FL, 0x00000000D83DDD10L, 0x00000000D83DDD11L, 0x00000000D83DDD0EL, 0x00000000D83DDCA1L, + 0x00000000D83DDD26L, 0x00000000D83DDD06L, 0x00000000D83DDD05L, 0x00000000D83DDD0CL, 0x00000000D83DDD0BL, 0x00000000D83DDD0DL, 0x00000000D83DDEC0L, + 0x00000000D83DDEBFL, 0x00000000D83DDEBDL, 0x00000000D83DDD27L, 0x00000000D83DDD29L, 0x00000000D83DDD28L, 0x00000000D83DDEAAL, 0x00000000D83DDEACL, + 0x00000000D83DDCA3L, 0x00000000D83DDD2BL, 0x00000000D83DDD2AL, 0x00000000D83DDC8AL, 0x00000000D83DDC89L, 0x00000000D83DDCB0L, 0x00000000D83DDCB4L, + 0x00000000D83DDCB5L, 0x00000000D83DDCB7L, 0x00000000D83DDCB6L, 0x00000000D83DDCB3L, 0x00000000D83DDCB8L, 0x00000000D83DDCF2L, 0x00000000D83DDCE7L, + 0x00000000D83DDCE5L, 0x00000000D83DDCE4L, 0x0000000000002709L, 0x00000000D83DDCE9L, 0x00000000D83DDCE8L, 0x00000000D83DDCEFL, 0x00000000D83DDCEBL, + 0x00000000D83DDCEAL, 0x00000000D83DDCECL, 0x00000000D83DDCEDL, 0x00000000D83DDCEEL, 0x00000000D83DDCE6L, 0x00000000D83DDCDDL, 0x00000000D83DDCC4L, + 0x00000000D83DDCC3L, 0x00000000D83DDCD1L, 0x00000000D83DDCCAL, 0x00000000D83DDCC8L, 0x00000000D83DDCC9L, 0x00000000D83DDCDCL, 0x00000000D83DDCCBL, + 0x00000000D83DDCC5L, 0x00000000D83DDCC6L, 0x00000000D83DDCC7L, 0x00000000D83DDCC1L, 0x00000000D83DDCC2L, 0x0000000000002702L, 0x00000000D83DDCCCL, + 0x00000000D83DDCCEL, 0x0000000000002712L, 0x000000000000270FL, 0x00000000D83DDCCFL, 0x00000000D83DDCD0L, 0x00000000D83DDCD5L, 0x00000000D83DDCD7L, + 0x00000000D83DDCD8L, 0x00000000D83DDCD9L, 0x00000000D83DDCD3L, 0x00000000D83DDCD4L, 0x00000000D83DDCD2L, 0x00000000D83DDCDAL, 0x00000000D83DDCD6L, + 0x00000000D83DDD16L, 0x00000000D83DDCDBL, 0x00000000D83DDD2CL, 0x00000000D83DDD2DL, 0x00000000D83DDCF0L, 0x00000000D83CDFA8L, 0x00000000D83CDFACL, + 0x00000000D83CDFA4L, 0x00000000D83CDFA7L, 0x00000000D83CDFBCL, 0x00000000D83CDFB5L, 0x00000000D83CDFB6L, 0x00000000D83CDFB9L, 0x00000000D83CDFBBL, + 0x00000000D83CDFBAL, 0x00000000D83CDFB7L, 0x00000000D83CDFB8L, 0x00000000D83DDC7EL, 0x00000000D83CDFAEL, 0x00000000D83CDCCFL, 0x00000000D83CDFB4L, + 0x00000000D83CDC04L, 0x00000000D83CDFB2L, 0x00000000D83CDFAFL, 0x00000000D83CDFC8L, 0x00000000D83CDFC0L, 0x00000000000026BDL, 0x00000000000026BEL, + 0x00000000D83CDFBEL, 0x00000000D83CDFB1L, 0x00000000D83CDFC9L, 0x00000000D83CDFB3L, 0x00000000000026F3L, 0x00000000D83DDEB5L, 0x00000000D83DDEB4L, + 0x00000000D83CDFC1L, 0x00000000D83CDFC7L, 0x00000000D83CDFC6L, 0x00000000D83CDFBFL, 0x00000000D83CDFC2L, 0x00000000D83CDFCAL, 0x00000000D83CDFC4L, + 0x00000000D83CDFA3L, 0x0000000000002615L, 0x00000000D83CDF75L, 0x00000000D83CDF76L, 0x00000000D83CDF7CL, 0x00000000D83CDF7AL, 0x00000000D83CDF7BL, + 0x00000000D83CDF78L, 0x00000000D83CDF79L, 0x00000000D83CDF77L, 0x00000000D83CDF74L, 0x00000000D83CDF55L, 0x00000000D83CDF54L, 0x00000000D83CDF5FL, + 0x00000000D83CDF57L, 0x00000000D83CDF56L, 0x00000000D83CDF5DL, 0x00000000D83CDF5BL, 0x00000000D83CDF64L, 0x00000000D83CDF71L, 0x00000000D83CDF63L, + 0x00000000D83CDF65L, 0x00000000D83CDF59L, 0x00000000D83CDF58L, 0x00000000D83CDF5AL, 0x00000000D83CDF5CL, 0x00000000D83CDF72L, 0x00000000D83CDF62L, + 0x00000000D83CDF61L, 0x00000000D83CDF73L, 0x00000000D83CDF5EL, 0x00000000D83CDF69L, 0x00000000D83CDF6EL, 0x00000000D83CDF66L, 0x00000000D83CDF68L, + 0x00000000D83CDF67L, 0x00000000D83CDF82L, 0x00000000D83CDF70L, 0x00000000D83CDF6AL, 0x00000000D83CDF6BL, 0x00000000D83CDF6CL, 0x00000000D83CDF6DL, + 0x00000000D83CDF6FL, 0x00000000D83CDF4EL, 0x00000000D83CDF4FL, 0x00000000D83CDF4AL, 0x00000000D83CDF4BL, 0x00000000D83CDF52L, 0x00000000D83CDF47L, + 0x00000000D83CDF49L, 0x00000000D83CDF53L, 0x00000000D83CDF51L, 0x00000000D83CDF48L, 0x00000000D83CDF4CL, 0x00000000D83CDF50L, 0x00000000D83CDF4DL, + 0x00000000D83CDF60L, 0x00000000D83CDF46L, 0x00000000D83CDF45L, 0x00000000D83CDF3DL}, + new ulong[]{ + 0x00000000D83CDFE0L, 0x00000000D83CDFE1L, 0x00000000D83CDFEBL, 0x00000000D83CDFE2L, 0x00000000D83CDFE3L, 0x00000000D83CDFE5L, 0x00000000D83CDFE6L, 0x00000000D83CDFEAL, + 0x00000000D83CDFE9L, 0x00000000D83CDFE8L, 0x00000000D83DDC92L, 0x00000000000026EAL, 0x00000000D83CDFECL, 0x00000000D83CDFE4L, 0x00000000D83CDF07L, + 0x00000000D83CDF06L, 0x00000000D83CDFEFL, 0x00000000D83CDFF0L, 0x00000000000026FAL, 0x00000000D83CDFEDL, 0x00000000D83DDDFCL, 0x00000000D83DDDFEL, + 0x00000000D83DDDFBL, 0x00000000D83CDF04L, 0x00000000D83CDF05L, 0x00000000D83CDF03L, 0x00000000D83DDDFDL, 0x00000000D83CDF09L, 0x00000000D83CDFA0L, + 0x00000000D83CDFA1L, 0x00000000000026F2L, 0x00000000D83CDFA2L, 0x00000000D83DDEA2L, 0x00000000000026F5L, 0x00000000D83DDEA4L, 0x00000000D83DDEA3L, + 0x0000000000002693L, 0x00000000D83DDE80L, 0x0000000000002708L, 0x00000000D83DDCBAL, 0x00000000D83DDE81L, 0x00000000D83DDE82L, 0x00000000D83DDE8AL, + 0x00000000D83DDE89L, 0x00000000D83DDE9EL, 0x00000000D83DDE86L, 0x00000000D83DDE84L, 0x00000000D83DDE85L, 0x00000000D83DDE88L, 0x00000000D83DDE87L, + 0x00000000D83DDE9DL, 0x00000000D83DDE8BL, 0x00000000D83DDE83L, 0x00000000D83DDE8EL, 0x00000000D83DDE8CL, 0x00000000D83DDE8DL, 0x00000000D83DDE99L, + 0x00000000D83DDE98L, 0x00000000D83DDE97L, 0x00000000D83DDE95L, 0x00000000D83DDE96L, 0x00000000D83DDE9BL, 0x00000000D83DDE9AL, 0x00000000D83DDEA8L, + 0x00000000D83DDE93L, 0x00000000D83DDE94L, 0x00000000D83DDE92L, 0x00000000D83DDE91L, 0x00000000D83DDE90L, 0x00000000D83DDEB2L, 0x00000000D83DDEA1L, + 0x00000000D83DDE9FL, 0x00000000D83DDEA0L, 0x00000000D83DDE9CL, 0x00000000D83DDC88L, 0x00000000D83DDE8FL, 0x00000000D83CDFABL, 0x00000000D83DDEA6L, + 0x00000000D83DDEA5L, 0x00000000000026A0L, 0x00000000D83DDEA7L, 0x00000000D83DDD30L, 0x00000000000026FDL, 0x00000000D83CDFEEL, 0x00000000D83CDFB0L, + 0x0000000000002668L, 0x00000000D83DDDFFL, 0x00000000D83CDFAAL, 0x00000000D83CDFADL, 0x00000000D83DDCCDL, 0x00000000D83DDEA9L, 0xD83CDDEFD83CDDF5L, + 0xD83CDDF0D83CDDF7L, 0xD83CDDE9D83CDDEAL, 0xD83CDDE8D83CDDF3L, 0xD83CDDFAD83CDDF8L, 0xD83CDDEBD83CDDF7L, 0xD83CDDEAD83CDDF8L, 0xD83CDDEED83CDDF9L, + 0xD83CDDF7D83CDDFAL, 0xD83CDDECD83CDDE7L}, + new ulong[]{ + 0x00000000003120E3L, 0x00000000003220E3L, 0x00000000003320E3L, 0x00000000003420E3L, 0x00000000003520E3L, 0x00000000003620E3L, 0x00000000003720E3L, 0x00000000003820E3L, + 0x00000000003920E3L, 0x00000000003020E3L, 0x00000000D83DDD1FL, 0x00000000D83DDD22L, 0x00000000002320E3L, 0x00000000D83DDD23L, 0x0000000000002B06L, + 0x0000000000002B07L, 0x0000000000002B05L, 0x00000000000027A1L, 0x00000000D83DDD20L, 0x00000000D83DDD21L, 0x00000000D83DDD24L, 0x0000000000002197L, + 0x0000000000002196L, 0x0000000000002198L, 0x0000000000002199L, 0x0000000000002194L, 0x0000000000002195L, 0x00000000D83DDD04L, 0x00000000000025C0L, + 0x00000000000025B6L, 0x00000000D83DDD3CL, 0x00000000D83DDD3DL, 0x00000000000021A9L, 0x00000000000021AAL, 0x0000000000002139L, 0x00000000000023EAL, + 0x00000000000023E9L, 0x00000000000023EBL, 0x00000000000023ECL, 0x0000000000002935L, 0x0000000000002934L, 0x00000000D83CDD97L, 0x00000000D83DDD00L, + 0x00000000D83DDD01L, 0x00000000D83DDD02L, 0x00000000D83CDD95L, 0x00000000D83CDD99L, 0x00000000D83CDD92L, 0x00000000D83CDD93L, 0x00000000D83CDD96L, + 0x00000000D83DDCF6L, 0x00000000D83CDFA6L, 0x00000000D83CDE01L, 0x00000000D83CDE2FL, 0x00000000D83CDE33L, 0x00000000D83CDE35L, 0x00000000D83CDE32L, + 0x00000000D83CDE34L, 0x00000000D83CDE32L, 0x00000000D83CDE50L, 0x00000000D83CDE39L, 0x00000000D83CDE3AL, 0x00000000D83CDE36L, 0x00000000D83CDE1AL, + 0x00000000D83DDEBBL, 0x00000000D83DDEB9L, 0x00000000D83DDEBAL, 0x00000000D83DDEBCL, 0x00000000D83DDEBEL, 0x00000000D83DDEB0L, 0x00000000D83DDEAEL, + 0x00000000D83CDD7FL, 0x000000000000267FL, 0x00000000D83DDEADL, 0x00000000D83CDE37L, 0x00000000D83CDE38L, 0x00000000D83CDE02L, 0x00000000000024C2L, + 0x00000000D83CDE51L, 0x0000000000003299L, 0x0000000000003297L, 0x00000000D83CDD91L, 0x00000000D83CDD98L, 0x00000000D83CDD94L, 0x00000000D83DDEABL, + 0x00000000D83DDD1EL, 0x00000000D83DDCF5L, 0x00000000D83DDEAFL, 0x00000000D83DDEB1L, 0x00000000D83DDEB3L, 0x00000000D83DDEB7L, 0x00000000D83DDEB8L, + 0x00000000000026D4L, 0x0000000000002733L, 0x0000000000002747L, 0x000000000000274EL, 0x0000000000002705L, 0x0000000000002734L, 0x00000000D83DDC9FL, + 0x00000000D83CDD9AL, 0x00000000D83DDCF3L, 0x00000000D83DDCF4L, 0x00000000D83CDD70L, 0x00000000D83CDD71L, 0x00000000D83CDD8EL, 0x00000000D83CDD7EL, + 0x00000000D83DDCA0L, 0x00000000000027BFL, 0x000000000000267BL, 0x0000000000002648L, 0x0000000000002649L, 0x000000000000264AL, 0x000000000000264BL, + 0x000000000000264CL, 0x000000000000264DL, 0x000000000000264EL, 0x000000000000264FL, 0x0000000000002650L, 0x0000000000002651L, 0x0000000000002652L, + 0x0000000000002653L, 0x00000000000026CEL, 0x00000000D83DDD2FL, 0x00000000D83CDFE7L, 0x00000000D83DDCB9L, 0x00000000D83DDCB2L, 0x00000000D83DDCB1L, + 0x00000000000000A9L, 0x00000000000000AEL, 0x0000000000002122L, 0x000000000000303DL, 0x0000000000003030L, 0x00000000D83DDD1DL, 0x00000000D83DDD1AL, + 0x00000000D83DDD19L, 0x00000000D83DDD1BL, 0x00000000D83DDD1CL, 0x000000000000274CL, 0x0000000000002B55L, 0x0000000000002757L, 0x0000000000002753L, + 0x0000000000002755L, 0x0000000000002754L, 0x00000000D83DDD03L, 0x00000000D83DDD5BL, 0x00000000D83DDD67L, 0x00000000D83DDD50L, 0x00000000D83DDD5CL, + 0x00000000D83DDD51L, 0x00000000D83DDD5DL, 0x00000000D83DDD52L, 0x00000000D83DDD5EL, 0x00000000D83DDD53L, 0x00000000D83DDD5FL, 0x00000000D83DDD54L, + 0x00000000D83DDD60L, 0x00000000D83DDD55L, 0x00000000D83DDD56L, 0x00000000D83DDD57L, 0x00000000D83DDD58L, 0x00000000D83DDD59L, 0x00000000D83DDD5AL, + 0x00000000D83DDD61L, 0x00000000D83DDD62L, 0x00000000D83DDD63L, 0x00000000D83DDD64L, 0x00000000D83DDD65L, 0x00000000D83DDD66L, 0x0000000000002716L, + 0x0000000000002795L, 0x0000000000002796L, 0x0000000000002797L, 0x0000000000002660L, 0x0000000000002665L, 0x0000000000002663L, 0x0000000000002666L, + 0x00000000D83DDCAEL, 0x00000000D83DDCAFL, 0x0000000000002714L, 0x0000000000002611L, 0x00000000D83DDD18L, 0x00000000D83DDD17L, 0x00000000000027B0L, + 0x00000000D83DDD31L, 0x00000000D83DDD32L, 0x00000000D83DDD33L, 0x00000000000025FCL, 0x00000000000025FBL, 0x00000000000025FEL, 0x00000000000025FDL, + 0x00000000000025AAL, 0x00000000000025ABL, 0x00000000D83DDD3AL, 0x0000000000002B1CL, 0x0000000000002B1BL, 0x00000000000026ABL, 0x00000000000026AAL, + 0x00000000D83DDD34L, 0x00000000D83DDD35L, 0x00000000D83DDD3BL, 0x00000000D83DDD36L, 0x00000000D83DDD37L, 0x00000000D83DDD38L, 0x00000000D83DDD39L}}; + } +} diff --git a/Telegram.Controls/IHighlightable.cs b/Telegram.Controls/IHighlightable.cs new file mode 100755 index 0000000..caa02ba --- /dev/null +++ b/Telegram.Controls/IHighlightable.cs @@ -0,0 +1,14 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Controls +{ + public interface IHighlightable + { + bool HighlightItem { get; set; } + } +} diff --git a/Telegram.Controls/LazyItemsControl.cs b/Telegram.Controls/LazyItemsControl.cs new file mode 100755 index 0000000..0f907ef --- /dev/null +++ b/Telegram.Controls/LazyItemsControl.cs @@ -0,0 +1,154 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Media; +using Telegram.Controls.Extensions; + +namespace Telegram.Controls +{ + public class LazyItemsControl : ItemsControl, ICompression + { + private const string VerticalCompressionGroup = "VerticalCompression"; + private const string ScrollStatesGroup = "ScrollStates"; + + private const string CompressionTopState = "CompressionTop"; + private const string CompressionBottomState = "CompressionBottom"; + private const string ScrollingState = "Scrolling"; + + private ScrollViewer _scrollViewer; + + public LazyItemsControl() + { + Loaded += LazyItemsControl_Loaded; + } + + private void LazyItemsControl_Loaded(object sender, RoutedEventArgs e) + { + Loaded -= LazyItemsControl_Loaded; + + _scrollViewer = this.FindChildOfType(); + + if (_scrollViewer != null) + { + var element = VisualTreeHelper.GetChild(_scrollViewer, 0) as FrameworkElement; + if (element != null) + { + var verticalGroup = FindVisualState(element, VerticalCompressionGroup); + var scrollStatesGroup = FindVisualState(element, ScrollStatesGroup); + + if (verticalGroup != null) + verticalGroup.CurrentStateChanging += VerticalGroup_CurrentStateChanging; + + if (scrollStatesGroup != null) + scrollStatesGroup.CurrentStateChanging += ScrollStateGroup_CurrentStateChanging; + } + + var binding = new Binding("VerticalOffset") { Source = _scrollViewer }; + SetBinding(VerticalOffsetProperty, binding); + } + } + + public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.Register( + "VerticalOffset", typeof (double), typeof (LazyItemsControl), new PropertyMetadata(default(double), OnVerticalOffsetChanged)); + + public double VerticalOffset + { + get { return (double) GetValue(VerticalOffsetProperty); } + set { SetValue(VerticalOffsetProperty, value); } + } + + private static void OnVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var lazyItemsControl = (LazyItemsControl)d; + + lazyItemsControl.OnListenerChanged(d, e); + } + + private double _closeToEndPercent = 0.7; + + public double CloseToEndPercent + { + get { return _closeToEndPercent; } + set { _closeToEndPercent = value; } + } + + private double _prevVerticalOffset; + + public event EventHandler CloseToEnd; + + protected virtual void RaiseCloseToEnd() + { + var handler = CloseToEnd; + if (handler != null) handler(this, EventArgs.Empty); + } + + private void OnListenerChanged(object sender, DependencyPropertyChangedEventArgs e) + { + if (_prevVerticalOffset >= _scrollViewer.VerticalOffset) return; + if (_scrollViewer.VerticalOffset == 0.0 && _scrollViewer.ScrollableHeight == 0.0) return; + + _prevVerticalOffset = _scrollViewer.VerticalOffset; + var atBottom = _scrollViewer.VerticalOffset >= _scrollViewer.ScrollableHeight * CloseToEndPercent; + + if (atBottom) + { + RaiseCloseToEnd(); + } + } + + private static VisualStateGroup FindVisualState(FrameworkElement element, string stateName) + { + if (element == null) + return null; + + var groups = VisualStateManager.GetVisualStateGroups(element); + return groups.Cast().FirstOrDefault(group => group.Name == stateName); + } + + public event EventHandler Compression; + + protected virtual void RaiseCompression(CompressionEventArgs e) + { + var handler = Compression; + if (handler != null) handler(this, e); + } + + private void VerticalGroup_CurrentStateChanging(object sender, VisualStateChangedEventArgs e) + { + if (e.NewState.Name == CompressionTopState) + { + RaiseCompression(new CompressionEventArgs(CompressionType.Top)); + } + if (e.NewState.Name == CompressionBottomState) + { + RaiseCompression(new CompressionEventArgs(CompressionType.Bottom)); + } + } + + private void ScrollStateGroup_CurrentStateChanging(object sender, VisualStateChangedEventArgs e) + { + IsScrolling = (e.NewState.Name == ScrollingState); + } + + public static readonly DependencyProperty IsScrollingProperty = DependencyProperty.Register( + "IsScrolling", + typeof(bool), + typeof(LazyItemsControl), + new PropertyMetadata(false)); + + public bool IsScrolling + { + get { return (bool)GetValue(IsScrollingProperty); } + set { SetValue(IsScrollingProperty, value); } + } + } +} diff --git a/Telegram.Controls/LazyListBox.cs b/Telegram.Controls/LazyListBox.cs new file mode 100755 index 0000000..d31710d --- /dev/null +++ b/Telegram.Controls/LazyListBox.cs @@ -0,0 +1,525 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Diagnostics; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Input; +using System.Windows.Media; +using DanielVaughan.WindowsPhone7Unleashed; +using Telegram.Controls.Extensions; + +namespace Telegram.Controls +{ + public enum CompressionType { Top, Bottom, Left, Right }; + + public interface ICompression + { + event EventHandler Compression; + } + + public class LazyListBox : ListBox, ICompression + { + public static readonly DependencyProperty KeepScrollingPositionProperty = DependencyProperty.Register( + "KeepScrollingPosition", typeof (bool), typeof (LazyListBox), new PropertyMetadata(default(bool))); + + public bool KeepScrollingPosition + { + get { return (bool) GetValue(KeepScrollingPositionProperty); } + set { SetValue(KeepScrollingPositionProperty, value); } + } + + public bool SuppressVerticalOffsetListener { get; set; } + + public static readonly DependencyProperty IsHorizontalProperty = DependencyProperty.Register( + "IsHorizontal", typeof (bool), typeof (LazyListBox), new PropertyMetadata(default(bool), OnIsHorizontalChanged)); + + private static void OnIsHorizontalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var listBox = d as LazyListBox; + if (listBox != null) + { + var isHorizontal = (bool) e.NewValue; + if (isHorizontal) + { + listBox.ToHorizontalOrientation(); + } + else + { + listBox.ToVerticalOrientation(); + } + } + } + + public bool IsHorizontal + { + get { return (bool) GetValue(IsHorizontalProperty); } + set { SetValue(IsHorizontalProperty, value); } + } + + public void ToHorizontalOrientation() + { + if (_stackPanel != null) + { + _stackPanel.Orientation = Orientation.Horizontal; + } + + if (_scrollViewer != null) + { + _scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled; + _scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto; + } + } + + public void ToVerticalOrientation() + { + if (_stackPanel != null) + { + _stackPanel.Orientation = Orientation.Vertical; + } + + if (_scrollViewer != null) + { + _scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Auto; + _scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled; + } + } + + private const string VerticalCompressionGroup = "VerticalCompression"; + private const string HorizontalCompressionGroup = "HorizontalCompression"; + private const string ScrollStatesGroup = "ScrollStates"; + private const string NoHorizontalCompressionState = "NoHorizontalCompression"; + private const string CompressionRightState = "CompressionRight"; + private const string CompressionLeftState = "CompressionLeft"; + private const string NoVerticalCompressionState = "NoVerticalCompression"; + private const string CompressionTopState = "CompressionTop"; + private const string CompressionBottomState = "CompressionBottom"; + private const string ScrollingState = "Scrolling"; + + public double PanelVerticalOffset { get; set; } + + public double PanelViewPortHeight { get; set; } + + private VirtualizingStackPanel _stackPanel; + + private ScrollViewer _scrollViewer; + + public ScrollViewer Scroll + { + get { return _scrollViewer; } + } + + protected bool IsBouncy; + + private bool _isInitialized; + + public LazyListBox() + { + Loaded += ListBox_Loaded; + //Unloaded += ListBox_Unloaded; + } + + //~LazyListBox() + //{ + + //} + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + } + + public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.Register( + "VerticalOffset", typeof(double), typeof(LazyListBox), new PropertyMetadata(default(double), OnVerticalOffsetChanged)); + + private static void OnVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var lazyListBox = d as LazyListBox; + if (lazyListBox != null) + { + lazyListBox.OnListenerChanged(lazyListBox, new BindingChangedEventArgs(e)); + } + } + + public double VerticalOffset + { + get { return (double) GetValue(VerticalOffsetProperty); } + set { SetValue(VerticalOffsetProperty, value); } + } + + private void OnListenerChanged(object sender, BindingChangedEventArgs e) + { + if (_prevVerticalOffset >= _scrollViewer.VerticalOffset) return; + if (_scrollViewer.VerticalOffset == 0.0 && _scrollViewer.ScrollableHeight == 0.0) return; + + _prevVerticalOffset = _scrollViewer.VerticalOffset; + var atBottom = _scrollViewer.VerticalOffset >= _scrollViewer.ScrollableHeight * CloseToEndPercent; + + if (atBottom) + { + RaiseCloseToEnd(); + } + } + + public void StopScrolling() + { + //stop scrolling + + + var offset = _stackPanel.VerticalOffset; + + if (_scrollViewer != null) + { + _scrollViewer.InvalidateScrollInfo(); + _scrollViewer.ScrollToVerticalOffset(offset); + VisualStateManager.GoToState(_scrollViewer, "NotScrolling", true); + } + } + + public void ScrollToBeginning() + { + _scrollViewer.ScrollToBeginnig(new Duration(TimeSpan.FromSeconds(0.3))); + } + + private void ListBox_Loaded(object sender, RoutedEventArgs e) + { + if (_isInitialized) + return; + + _isInitialized = true; + + AddHandler(ManipulationCompletedEvent, new EventHandler(ListBox_ManipulationCompleted), true); + + _scrollViewer = this.FindChildOfType(); + + if (_scrollViewer != null) + { + _stackPanel = _scrollViewer.FindChildOfType(); + + if (IsHorizontal) + { + ToHorizontalOrientation(); + } + else + { + ToVerticalOrientation(); + } + // Visual States are always on the first child of the control template + var element = VisualTreeHelper.GetChild(_scrollViewer, 0) as FrameworkElement; + if (element != null) + { + var verticalGroup = FindVisualState(element, VerticalCompressionGroup); + var horizontalGroup = FindVisualState(element, HorizontalCompressionGroup); + var scrollStatesGroup = FindVisualState(element, ScrollStatesGroup); + + if (verticalGroup != null) + verticalGroup.CurrentStateChanging += VerticalGroup_CurrentStateChanging; + if (horizontalGroup != null) + horizontalGroup.CurrentStateChanging += HorizontalGroup_CurrentStateChanging; + if (scrollStatesGroup != null) + scrollStatesGroup.CurrentStateChanging += ScrollStateGroup_CurrentStateChanging; + } + + + if (!SuppressVerticalOffsetListener) + { + var binding = new Binding("VerticalOffset") { Source = _scrollViewer }; + SetBinding(VerticalOffsetProperty, binding); + } + } + } + + private double _closeToEndPercent = 0.7; + + public double CloseToEndPercent + { + get { return _closeToEndPercent; } + set { _closeToEndPercent = value; } + } + + private double _prevVerticalOffset; + + public event EventHandler CloseToEnd; + + protected virtual void RaiseCloseToEnd() + { + var handler = CloseToEnd; + if (handler != null) handler(this, EventArgs.Empty); + } + + private void ScrollStateGroup_CurrentStateChanging(object sender, VisualStateChangedEventArgs e) + { + IsScrolling = (e.NewState.Name == ScrollingState); + } + + public event EventHandler ScrollingStateChanged; + + protected virtual void RaiseScrollingStateChanged(ScrollingStateChangedEventArgs e) + { + var handler = ScrollingStateChanged; + if (handler != null) handler(this, e); + } + + public static readonly DependencyProperty IsScrollingProperty = DependencyProperty.Register( + "IsScrolling", + typeof(bool), + typeof(LazyListBox), + new PropertyMetadata(false, IsScrollingPropertyChanged)); + + public bool IsScrolling + { + get { return (bool)GetValue(IsScrollingProperty); } + set { SetValue(IsScrollingProperty, value); } + } + + static void IsScrollingPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) + { + var listbox = source as LazyListBox; + if (listbox == null) return; + + listbox.RaiseScrollingStateChanged(new ScrollingStateChangedEventArgs((bool) e.OldValue, (bool) e.NewValue)); + } + + #region Compression + public event EventHandler Compression; + + protected virtual void RaiseCompression(CompressionEventArgs e) + { + var handler = Compression; + if (handler != null) handler(this, e); + } + + private void HorizontalGroup_CurrentStateChanging(object sender, VisualStateChangedEventArgs e) + { + if (e.NewState.Name == CompressionLeftState) + { + IsBouncy = true; + RaiseCompression(new CompressionEventArgs(CompressionType.Left)); + } + + if (e.NewState.Name == CompressionRightState) + { + IsBouncy = true; + RaiseCompression(new CompressionEventArgs(CompressionType.Right)); + } + if (e.NewState.Name == NoHorizontalCompressionState) + { + IsBouncy = false; + } + } + + private void VerticalGroup_CurrentStateChanging(object sender, VisualStateChangedEventArgs e) + { + if (e.NewState.Name == CompressionTopState) + { + IsBouncy = true; + RaiseCompression(new CompressionEventArgs(CompressionType.Top)); + } + if (e.NewState.Name == CompressionBottomState) + { + IsBouncy = true; + RaiseCompression(new CompressionEventArgs(CompressionType.Bottom)); + } + if (e.NewState.Name == NoVerticalCompressionState) + IsBouncy = false; + } + + private void ListBox_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + if (IsBouncy) + IsBouncy = false; + } + + private static VisualStateGroup FindVisualState(FrameworkElement element, string stateName) + { + if (element == null) + return null; + + var groups = VisualStateManager.GetVisualStateGroups(element); + return groups.Cast().FirstOrDefault(group => group.Name == stateName); + } + #endregion + + + public List GetVisibleItems() + { + + var items = new List(); + + //if (_stackPanel == null) return items; + + //var firstVisibleItem = IsHorizontal ? (int)_stackPanel.HorizontalOffset : (int)_stackPanel.VerticalOffset; + //var visibleItemCount = IsHorizontal ? (int)_stackPanel.ViewportWidth : (int)_stackPanel.ViewportHeight; + //for (int index = firstVisibleItem; index < firstVisibleItem + visibleItemCount + 1; index++) + //{ + // var item = ItemContainerGenerator.ContainerFromIndex(index) as ListBoxItem; + // if (item == null) + // continue; + + // items.Add(item); + //} + + //return items; + + foreach (var item in Items) + { + var listBoxItem = ItemContainerGenerator.ContainerFromItem(item) as ListBoxItem; + if (IsInView(listBoxItem, this)) + { + items.Add(listBoxItem); + } + else if (items.Any()) + { + break; + } + } + + return items; + } + + private static bool IsInView(FrameworkElement element, FrameworkElement container) + { + if (element == null) return false; + + var elementBounds = element.TransformToVisual(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight)); + var containerBounds = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight); + + return containerBounds.Contains(new Point(elementBounds.X, elementBounds.Y)) // topLeft point + || containerBounds.Contains(new Point(elementBounds.X + elementBounds.Width, elementBounds.Y + elementBounds.Height)); // bottomRight point + } + + public event EventHandler Clear; + + protected virtual void RaiseClear() + { + var handler = Clear; + if (handler != null) handler(this, EventArgs.Empty); + } + + public event EventHandler FirstSliceLoaded; + + protected virtual void RaiseFirstSliceLoaded() + { + var handler = FirstSliceLoaded; + if (handler != null) handler(this, EventArgs.Empty); + } + + public event EventHandler VerticalOffsetChanged; + + protected virtual void RaiseVerticalOffsetChanged(VerticalOffsetChangedEventArgs e) + { + EventHandler handler = VerticalOffsetChanged; + if (handler != null) handler(this, e); + } + + private object _lastRemovedItem; + + protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) + { + if (KeepScrollingPosition) + { + if (_scrollViewer != null && _scrollViewer.VerticalOffset > 0.0001) + { + if (e.Action == NotifyCollectionChangedAction.Add) + { + if (e.NewItems != null && e.NewItems.Count == 1 && e.NewStartingIndex == 0) + { + if (_lastRemovedItem != e.NewItems[0]) + { + var nextOffset = Math.Min(_scrollViewer.VerticalOffset + 1.0, _scrollViewer.ScrollableHeight + 1.0); + + Debug.WriteLine("VerticalOffset={0} ExtentHeight={1} ViewportHeight={2} ScrollableHeight={3}", _scrollViewer.VerticalOffset, _scrollViewer.ExtentHeight, _scrollViewer.ViewportHeight, _scrollViewer.ScrollableHeight); + RaiseVerticalOffsetChanged(new VerticalOffsetChangedEventArgs { Viewer = _scrollViewer }); + _scrollViewer.ScrollToVerticalOffset(nextOffset); + } + } + } + else if (e.Action == NotifyCollectionChangedAction.Remove) + { + if (e.OldItems != null && e.OldItems.Count == 1 && + (e.OldStartingIndex) <= _scrollViewer.VerticalOffset) + { + _lastRemovedItem = e.OldItems[0]; + } + else + { + _lastRemovedItem = null; + } + } + } + + //if (_scrollViewer != null && _scrollViewer.VerticalOffset > 0.0001) + //{ + // if (e.Action == NotifyCollectionChangedAction.Add) + // { + // if (e.NewItems != null && e.NewStartingIndex == 0) + // { + // foreach (var newItem in e.NewItems) + // { + // _scrollViewer.ScrollToVerticalOffset(Math.Min(_scrollViewer.VerticalOffset + 1.0, _scrollViewer.ScrollableHeight)); + // } + // } + // } + // else if (e.Action == NotifyCollectionChangedAction.Remove) + // { + // if (e.OldItems != null && e.OldStartingIndex == 0) + // { + // foreach (var oldItem in e.OldItems) + // { + // _scrollViewer.ScrollToVerticalOffset(Math.Max(_scrollViewer.VerticalOffset - 1.0, 0.0)); + // } + // } + // } + //} + } + + if (e.Action == NotifyCollectionChangedAction.Reset) + { + RaiseClear(); + } + else if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null && Items != null && Items.Count == e.NewItems.Count) + { + RaiseFirstSliceLoaded(); + } + + base.OnItemsChanged(e); + } + } + + public class VerticalOffsetChangedEventArgs : EventArgs + { + public ScrollViewer Viewer { get; set; } + } + + public class ScrollingStateChangedEventArgs : EventArgs + { + public bool OldValue { get; private set; } + + public bool NewValue { get; private set; } + + public ScrollingStateChangedEventArgs(bool oldValue, bool newValue) + { + OldValue = oldValue; + NewValue = newValue; + } + } + + public class CompressionEventArgs : EventArgs + { + public CompressionType Type { get; protected set; } + + public CompressionEventArgs(CompressionType type) + { + Type = type; + } + } +} diff --git a/Telegram.Controls/LongListSelector/Common/MotionParameters.cs b/Telegram.Controls/LongListSelector/Common/MotionParameters.cs new file mode 100755 index 0000000..308fd31 --- /dev/null +++ b/Telegram.Controls/LongListSelector/Common/MotionParameters.cs @@ -0,0 +1,16 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Controls.LongListSelector.Common +{ + internal static class MotionParameters + { + public static double MaximumSpeed { get { return 4000.0; } } + public static double ParkingSpeed { get { return 80.0; } } + public static double Friction { get { return 0.2; } } + } +} diff --git a/Telegram.Controls/LongListSelector/Common/SafeRaise.cs b/Telegram.Controls/LongListSelector/Common/SafeRaise.cs new file mode 100755 index 0000000..c4fadfe --- /dev/null +++ b/Telegram.Controls/LongListSelector/Common/SafeRaise.cs @@ -0,0 +1,95 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Telegram.Controls.LongListSelector.Common +{ + /// + /// A helper class for raising events safely. + /// + internal static class SafeRaise + { + /// + /// Raises an event in a thread-safe manner, also does the null check. + /// + /// The event to raise. + /// The event sender. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")] + public static void Raise(EventHandler eventToRaise, object sender) + { + if (eventToRaise != null) + { + eventToRaise(sender, EventArgs.Empty); + } + } + + /// + /// Raises an event in a thread-safe manner, also does the null check. + /// + /// The event to raise. + /// The event sender. + public static void Raise(EventHandler eventToRaise, object sender) + { + Raise(eventToRaise, sender, EventArgs.Empty); + } + + /// + /// Raises an event in a thread-safe manner, also does the null check. + /// + /// The event args type. + /// The event to raise. + /// The event sender. + /// The event args. + public static void Raise(EventHandler eventToRaise, object sender, T args) where T : EventArgs + { + if (eventToRaise != null) + { + eventToRaise(sender, args); + } + } + + // Lazy event args creation example: + // + // public class MyEventArgs : EventArgs + // { + // public MyEventArgs(int x) { X = x; } + // public int X { get; set; } + // } + // + // event EventHandler Foo; + // + // public void Bar() + // { + // int y = 2; + // Raise(Foo, null, () => { return new MyEventArgs(y); }); + // } + + /// + /// This is a method that returns event args, used for lazy creation. + /// + /// The event type. + /// + public delegate T GetEventArgs() where T : EventArgs; + + /// + /// Raise an event in a thread-safe manner, with the required null check. Lazily creates event args. + /// + /// The event args type. + /// The event to raise. + /// The event sender. + /// The delegate to return the event args if needed. + public static void Raise(EventHandler eventToRaise, object sender, GetEventArgs getEventArgs) where T : EventArgs + { + if (eventToRaise != null) + { + eventToRaise(sender, getEventArgs()); + } + } + } +} diff --git a/Telegram.Controls/LongListSelector/Common/TempaltedVisualTreeExtensions.cs b/Telegram.Controls/LongListSelector/Common/TempaltedVisualTreeExtensions.cs new file mode 100755 index 0000000..35c0309 --- /dev/null +++ b/Telegram.Controls/LongListSelector/Common/TempaltedVisualTreeExtensions.cs @@ -0,0 +1,112 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using Telegram.Controls.Extensions; + +namespace Telegram.Controls.LongListSelector.Common +{ + /// + /// A static class providing methods for working with the visual tree using generics. + /// + public static class TemplatedVisualTreeExtensions + { + + #region GetFirstLogicalChildByType(...) + /// + /// Retrieves the first logical child of a specified type using a + /// breadth-first search. A visual element is assumed to be a logical + /// child of another visual element if they are in the same namescope. + /// For performance reasons this method manually manages the queue + /// instead of using recursion. + /// + /// The parent framework element. + /// Specifies whether to apply templates on the traversed framework elements + /// The first logical child of the framework element of the specified type. + internal static T GetFirstLogicalChildByType(this FrameworkElement parent, bool applyTemplates) + where T : FrameworkElement + { + Debug.Assert(parent != null, "The parent cannot be null."); + + Queue queue = new Queue(); + queue.Enqueue(parent); + + while (queue.Count > 0) + { + FrameworkElement element = queue.Dequeue(); + var elementAsControl = element as Control; + if (applyTemplates && elementAsControl != null) + { + elementAsControl.ApplyTemplate(); + } + + if (element is T && element != parent) + { + return (T)element; + } + + foreach (FrameworkElement visualChild in element.GetVisualChildren().OfType()) + { + queue.Enqueue(visualChild); + } + } + + return null; + } + #endregion + + #region GetLogicalChildrenByType(...) + /// + /// Retrieves all the logical children of a specified type using a + /// breadth-first search. A visual element is assumed to be a logical + /// child of another visual element if they are in the same namescope. + /// For performance reasons this method manually manages the queue + /// instead of using recursion. + /// + /// The parent framework element. + /// Specifies whether to apply templates on the traversed framework elements + /// The logical children of the framework element of the specified type. + internal static IEnumerable GetLogicalChildrenByType(this FrameworkElement parent, bool applyTemplates) + where T : FrameworkElement + { + Debug.Assert(parent != null, "The parent cannot be null."); + + if (applyTemplates && parent is Control) + { + ((Control)parent).ApplyTemplate(); + } + + Queue queue = + new Queue(parent.GetVisualChildren().OfType()); + + while (queue.Count > 0) + { + FrameworkElement element = queue.Dequeue(); + if (applyTemplates && element is Control) + { + ((Control)element).ApplyTemplate(); + } + + if (element is T) + { + yield return (T)element; + } + + foreach (FrameworkElement visualChild in element.GetVisualChildren().OfType()) + { + queue.Enqueue(visualChild); + } + } + } + #endregion + + } +} diff --git a/Telegram.Controls/LongListSelector/Common/VisualStates.cs b/Telegram.Controls/LongListSelector/Common/VisualStates.cs new file mode 100755 index 0000000..5347928 --- /dev/null +++ b/Telegram.Controls/LongListSelector/Common/VisualStates.cs @@ -0,0 +1,413 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Diagnostics; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +namespace Telegram.Controls.LongListSelector.Common +{ + + /// + /// Names and helpers for visual states in the controls. + /// + internal static class VisualStates + { + #region GroupCommon + /// + /// Common state group. + /// + public const string GroupCommon = "CommonStates"; + + /// + /// Normal state of the Common state group. + /// + public const string StateNormal = "Normal"; + + /// + /// Normal state of the Common state group. + /// + public const string StateReadOnly = "ReadOnly"; + + /// + /// MouseOver state of the Common state group. + /// + public const string StateMouseOver = "MouseOver"; + + /// + /// Pressed state of the Common state group. + /// + public const string StatePressed = "Pressed"; + + /// + /// Disabled state of the Common state group. + /// + public const string StateDisabled = "Disabled"; + #endregion GroupCommon + + #region GroupFocus + /// + /// Focus state group. + /// + public const string GroupFocus = "FocusStates"; + + /// + /// Unfocused state of the Focus state group. + /// + public const string StateUnfocused = "Unfocused"; + + /// + /// Focused state of the Focus state group. + /// + public const string StateFocused = "Focused"; + #endregion GroupFocus + + #region GroupSelection + /// + /// Selection state group. + /// + public const string GroupSelection = "SelectionStates"; + + /// + /// Selected state of the Selection state group. + /// + public const string StateSelected = "Selected"; + + /// + /// Unselected state of the Selection state group. + /// + public const string StateUnselected = "Unselected"; + + /// + /// Selected inactive state of the Selection state group. + /// + public const string StateSelectedInactive = "SelectedInactive"; + #endregion GroupSelection + + #region GroupExpansion + /// + /// Expansion state group. + /// + public const string GroupExpansion = "ExpansionStates"; + + /// + /// Expanded state of the Expansion state group. + /// + public const string StateExpanded = "Expanded"; + + /// + /// Collapsed state of the Expansion state group. + /// + public const string StateCollapsed = "Collapsed"; + #endregion GroupExpansion + + #region GroupPopup + /// + /// Popup state group. + /// + public const string GroupPopup = "PopupStates"; + + /// + /// Opened state of the Popup state group. + /// + public const string StatePopupOpened = "PopupOpened"; + + /// + /// Closed state of the Popup state group. + /// + public const string StatePopupClosed = "PopupClosed"; + #endregion + + #region GroupValidation + /// + /// ValidationStates state group. + /// + public const string GroupValidation = "ValidationStates"; + + /// + /// The valid state for the ValidationStates group. + /// + public const string StateValid = "Valid"; + + /// + /// Invalid, focused state for the ValidationStates group. + /// + public const string StateInvalidFocused = "InvalidFocused"; + + /// + /// Invalid, unfocused state for the ValidationStates group. + /// + public const string StateInvalidUnfocused = "InvalidUnfocused"; + #endregion + + #region GroupExpandDirection + /// + /// ExpandDirection state group. + /// + public const string GroupExpandDirection = "ExpandDirectionStates"; + + /// + /// Down expand direction state of ExpandDirection state group. + /// + public const string StateExpandDown = "ExpandDown"; + + /// + /// Up expand direction state of ExpandDirection state group. + /// + public const string StateExpandUp = "ExpandUp"; + + /// + /// Left expand direction state of ExpandDirection state group. + /// + public const string StateExpandLeft = "ExpandLeft"; + + /// + /// Right expand direction state of ExpandDirection state group. + /// + public const string StateExpandRight = "ExpandRight"; + #endregion + + #region GroupHasItems + /// + /// HasItems state group. + /// + public const string GroupHasItems = "HasItemsStates"; + + /// + /// HasItems state of the HasItems state group. + /// + public const string StateHasItems = "HasItems"; + + /// + /// NoItems state of the HasItems state group. + /// + public const string StateNoItems = "NoItems"; + #endregion GroupHasItems + + #region GroupIncrease + /// + /// Increment state group. + /// + public const string GroupIncrease = "IncreaseStates"; + + /// + /// State enabled for increment group. + /// + public const string StateIncreaseEnabled = "IncreaseEnabled"; + + /// + /// State disabled for increment group. + /// + public const string StateIncreaseDisabled = "IncreaseDisabled"; + #endregion GroupIncrease + + #region GroupDecrease + /// + /// Decrement state group. + /// + public const string GroupDecrease = "DecreaseStates"; + + /// + /// State enabled for decrement group. + /// + public const string StateDecreaseEnabled = "DecreaseEnabled"; + + /// + /// State disabled for decrement group. + /// + public const string StateDecreaseDisabled = "DecreaseDisabled"; + #endregion GroupDecrease + + #region GroupIteractionMode + /// + /// InteractionMode state group. + /// + public const string GroupInteractionMode = "InteractionModeStates"; + + /// + /// Edit of the DisplayMode state group. + /// + public const string StateEdit = "Edit"; + + /// + /// Display of the DisplayMode state group. + /// + public const string StateDisplay = "Display"; + #endregion GroupIteractionMode + + #region GroupLocked + /// + /// DisplayMode state group. + /// + public const string GroupLocked = "LockedStates"; + + /// + /// Edit of the DisplayMode state group. + /// + public const string StateLocked = "Locked"; + + /// + /// Display of the DisplayMode state group. + /// + public const string StateUnlocked = "Unlocked"; + #endregion GroupLocked + + #region GroupActive + /// + /// Active state. + /// + public const string StateActive = "Active"; + + /// + /// Inactive state. + /// + public const string StateInactive = "Inactive"; + + /// + /// Active state group. + /// + public const string GroupActive = "ActiveStates"; + #endregion GroupActive + + #region GroupWatermark + /// + /// Non-watermarked state. + /// + public const string StateUnwatermarked = "Unwatermarked"; + + /// + /// Watermarked state. + /// + public const string StateWatermarked = "Watermarked"; + + /// + /// Watermark state group. + /// + public const string GroupWatermark = "WatermarkStates"; + #endregion GroupWatermark + + #region GroupCalendarButtonFocus + /// + /// Unfocused state for Calendar Buttons. + /// + public const string StateCalendarButtonUnfocused = "CalendarButtonUnfocused"; + + /// + /// Focused state for Calendar Buttons. + /// + public const string StateCalendarButtonFocused = "CalendarButtonFocused"; + + /// + /// CalendarButtons Focus state group. + /// + public const string GroupCalendarButtonFocus = "CalendarButtonFocusStates"; + #endregion GroupCalendarButtonFocus + + #region GroupBusyStatus + /// + /// Busy state for BusyIndicator. + /// + public const string StateBusy = "Busy"; + + /// + /// Idle state for BusyIndicator. + /// + public const string StateIdle = "Idle"; + + /// + /// Busyness group name. + /// + public const string GroupBusyStatus = "BusyStatusStates"; + #endregion + + #region GroupVisibility + /// + /// Visible state name for BusyIndicator. + /// + public const string StateVisible = "Visible"; + + /// + /// Hidden state name for BusyIndicator. + /// + public const string StateHidden = "Hidden"; + + /// + /// BusyDisplay group. + /// + public const string GroupVisibility = "VisibilityStates"; + #endregion + + /// + /// Use VisualStateManager to change the visual state of the control. + /// + /// + /// Control whose visual state is being changed. + /// + /// + /// A value indicating whether to use transitions when updating the + /// visual state, or to snap directly to the new visual state. + /// + /// + /// Ordered list of state names and fallback states to transition into. + /// Only the first state to be found will be used. + /// + public static void GoToState(Control control, bool useTransitions, params string[] stateNames) + { + Debug.Assert(control != null, "control should not be null!"); + Debug.Assert(stateNames != null, "stateNames should not be null!"); + Debug.Assert(stateNames.Length > 0, "stateNames should not be empty!"); + + foreach (string name in stateNames) + { + if (VisualStateManager.GoToState(control, name, useTransitions)) + { + break; + } + } + } + + /// + /// Gets the implementation root of the Control. + /// + /// The DependencyObject. + /// + /// Implements Silverlight's corresponding internal property on Control. + /// + /// Returns the implementation root or null. + public static FrameworkElement GetImplementationRoot(DependencyObject dependencyObject) + { + Debug.Assert(dependencyObject != null, "DependencyObject should not be null."); + return (1 == VisualTreeHelper.GetChildrenCount(dependencyObject)) ? + VisualTreeHelper.GetChild(dependencyObject, 0) as FrameworkElement : + null; + } + + /// + /// This method tries to get the named VisualStateGroup for the + /// dependency object. The provided object's ImplementationRoot will be + /// looked up in this call. + /// + /// The dependency object. + /// The visual state group's name. + /// Returns null or the VisualStateGroup object. + public static VisualStateGroup TryGetVisualStateGroup(DependencyObject dependencyObject, string groupName) + { + FrameworkElement root = GetImplementationRoot(dependencyObject); + if (root == null) + { + return null; + } + + return VisualStateManager.GetVisualStateGroups(root) + .OfType() + .Where(group => string.CompareOrdinal(groupName, group.Name) == 0) + .FirstOrDefault(); + } + } +} diff --git a/Telegram.Controls/LongListSelector/LongListSelector.cs b/Telegram.Controls/LongListSelector/LongListSelector.cs new file mode 100755 index 0000000..a8d7d77 --- /dev/null +++ b/Telegram.Controls/LongListSelector/LongListSelector.cs @@ -0,0 +1,1906 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Markup; +using System.Windows.Media; +using DanielVaughan.WindowsPhone7Unleashed; +using Telegram.Controls.LongListSelector.Common; + +namespace Telegram.Controls.LongListSelector +{ + + /// + /// Represents a virtualizing list designed for grouped lists. Can also be + /// used with flat lists. + /// + /// Preview + [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "LongListSelector is a complicated control.")] + [TemplatePart(Name = TemplatedListBoxName, Type = typeof(TemplatedListBox))] + public partial class LongListSelector : Control + { + #region Constants + /// + /// The templated list box name. + /// + private const string TemplatedListBoxName = "TemplatedListBox"; + + /// + /// This constant is not actively used in the new version, however, the + /// value is exposed through a deprecated property. For backward- + /// compatibility only. + /// + private const double BufferSizeDefault = 1.0; + + /// + /// The Scrolling state name. + /// + private const string ScrollingState = "Scrolling"; + + /// + /// The NotScrolling state name. + /// + private const string NotScrollingState = "NotScrolling"; + + /// + /// The vertical compression top state name. + /// + private const string CompressionTop = "CompressionTop"; + + /// + /// The vertical compression bottom state name. + /// + private const string CompressionBottom = "CompressionBottom"; + + /// + /// The absense of vertical compression state name. + /// + private const string NoVerticalCompression = "NoVerticalCompression"; + + /// + /// The vertical compression state name. + /// + private const string VerticalCompressionStateName = "VerticalCompression"; + + /// + /// The name of the scroll states visual state group. + /// + private const string ScrollStatesGroupName = "ScrollStates"; + #endregion + + /// + /// Reference to the ListBox hosted in this control. + /// + private TemplatedListBox _listBox; + + private ScrollViewer _scrollViewer; + + /// + /// Reference to the visual state group for scrolling. + /// + private VisualStateGroup _scrollGroup; + + /// + /// Reference to the visual state group for vertical compression. + /// + private VisualStateGroup _verticalCompressionGroup; + + /// + /// // Used to listen for changes in the ItemsSource + /// (_rootCollection = ItemsSource as INotifyCollectionChanged). + /// + private INotifyCollectionChanged _rootCollection; + + /// + /// Used to listen for changes in the groups within ItemsSource. + /// + private List _groupCollections = new List(); + + #region Properties + + /// + /// Gets or sets whether the list is flat instead of a group hierarchy. + /// + public bool IsFlatList { get; set; } + + /// + /// Gets or sets the selected item. + /// + public object SelectedItem + { + get + { + if (_listBox != null && _listBox.SelectedItem != null) + { + LongListSelectorItem tuple = (LongListSelectorItem)_listBox.SelectedItem; + if (tuple.ItemType == LongListSelectorItemType.Item) + return tuple.Item; + } + return null; + } + set + { + if (_listBox != null) + { + if (value == null) + { + _listBox.SelectedItem = null; + } + else + { + foreach (LongListSelectorItem tuple in _listBox.ItemsSource) + { + if (tuple.Item == value) + { + _listBox.SelectedItem = tuple; + break; + } + } + } + } + } + } + + /// + /// Gets or sets whether the list can be (temporarily) scrolled off of the ends. + /// + [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Backward compatible public setter.")] + [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value", Justification = "Backward compatible public setter.")] + [Obsolete("IsBouncy is always set to true.")] + public bool IsBouncy + { + get { return true; } + set { } + } + + /// + /// Gets whether a list header is shown. + /// + private bool HasListHeader { get { return ListHeaderTemplate != null || ListHeader is UIElement; } } + + /// + /// Gets whether a list footer is shown. + /// + private bool HasListFooter { get { return ListFooterTemplate != null || ListFooter is UIElement; } } + + /// + /// Gets whether or not the user is manipulating the list, or if an inertial animation is taking place. + /// + public bool IsScrolling + { + get; + private set; + } + + /// + /// Gets whether or not stretching is taking place. + /// + public bool IsStretching + { + get; + private set; + } + #endregion + + #region Dependency Properties + + #region HorizontalScrollBar DependencyProperty + + public static readonly DependencyProperty HorizontalScrollBarVisibilityProperty = DependencyProperty.Register( + "HorizontalScrollBarVisibility", typeof(ScrollBarVisibility), typeof(LongListSelector), new PropertyMetadata(ScrollBarVisibility.Disabled)); + + public ScrollBarVisibility HorizontalScrollBarVisibility + { + get { return (ScrollBarVisibility) GetValue(HorizontalScrollBarVisibilityProperty); } + set { SetValue(HorizontalScrollBarVisibilityProperty, value); } + } + #endregion + + #region VerticalScrollBar DependencyProperty + + public static readonly DependencyProperty VerticalScrollBarVisibilityProperty = DependencyProperty.Register( + "VerticalScrollBarVisibility", typeof(ScrollBarVisibility), typeof(LongListSelector), new PropertyMetadata(ScrollBarVisibility.Auto)); + + public ScrollBarVisibility VerticalScrollBarVisibility + { + get { return (ScrollBarVisibility) GetValue(VerticalScrollBarVisibilityProperty); } + set { SetValue(VerticalScrollBarVisibilityProperty, value); } + } + #endregion + + #region ItemsSource DependencyProperty + + /// + /// The DataSource property. Where all of the items come from. + /// + public IEnumerable ItemsSource + { + get { return (IEnumerable)GetValue(ItemsSourceProperty); } + set { SetValue(ItemsSourceProperty, value); } + } + + /// + /// The DataSource DependencyProperty. + /// + public static readonly DependencyProperty ItemsSourceProperty = + DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(LongListSelector), new PropertyMetadata(null, OnItemsSourceChanged)); + + private static void OnItemsSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) + { + ((LongListSelector)obj).OnItemsSourceChanged(); + } + + + + #endregion + + #region ListHeader DependencyProperty + + /// + /// The ListHeader property. Will be used as the first scrollItem in the list. + /// + public object ListHeader + { + get { return (object)GetValue(ListHeaderProperty); } + set { SetValue(ListHeaderProperty, value); } + } + + /// + /// The ListHeader DependencyProperty. + /// + public static readonly DependencyProperty ListHeaderProperty = + DependencyProperty.Register("ListHeader", typeof(object), typeof(LongListSelector), new PropertyMetadata(null)); + + #endregion + + #region ItemsPanel DependencyProperty + + /// + /// The ItemsPanel provides the template for the ListHeader. + /// + public ItemsPanelTemplate ItemsPanel + { + get { return (ItemsPanelTemplate)GetValue(ItemsPanelProperty); } + set { SetValue(ItemsPanelProperty, value); } + } + + /// + /// The ItemsPanel DependencyProperty. + /// + public static readonly DependencyProperty ItemsPanelProperty = + DependencyProperty.Register("ItemsPanel", typeof(ItemsPanelTemplate), typeof(LongListSelector), new PropertyMetadata(OnItemsPanelChanged)); + + private static void OnItemsPanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as LongListSelector; + if (control != null) + { + if (control._listBox != null) + { + control._listBox.ItemsPanel = e.NewValue as ItemsPanelTemplate; + } + } + } + + #endregion + + #region ListHeaderTemplate DependencyProperty + + /// + /// The ListHeaderTemplate provides the template for the ListHeader. + /// + public DataTemplate ListHeaderTemplate + { + get { return (DataTemplate)GetValue(ListHeaderTemplateProperty); } + set { SetValue(ListHeaderTemplateProperty, value); } + } + + /// + /// The ListHeaderTemplate DependencyProperty. + /// + public static readonly DependencyProperty ListHeaderTemplateProperty = + DependencyProperty.Register("ListHeaderTemplate", typeof(DataTemplate), typeof(LongListSelector), new PropertyMetadata(null, OnDataTemplateChanged)); + + #endregion + + #region ListFooter DependencyProperty + + /// + /// The ListFooter property. Will be used as the first scrollItem in the list. + /// + public object ListFooter + { + get { return (object)GetValue(ListFooterProperty); } + set { SetValue(ListFooterProperty, value); } + } + + /// + /// The ListFooter DependencyProperty. + /// + public static readonly DependencyProperty ListFooterProperty = + DependencyProperty.Register("ListFooter", typeof(object), typeof(LongListSelector), new PropertyMetadata(null)); + + #endregion + + #region ListFooterTemplate DependencyProperty + + /// + /// The ListFooterTemplate provides the template for the ListFooter. + /// + public DataTemplate ListFooterTemplate + { + get { return (DataTemplate)GetValue(ListFooterTemplateProperty); } + set { SetValue(ListFooterTemplateProperty, value); } + } + + /// + /// The ListFooterTemplate DependencyProperty. + /// + public static readonly DependencyProperty ListFooterTemplateProperty = + DependencyProperty.Register("ListFooterTemplate", typeof(DataTemplate), typeof(LongListSelector), new PropertyMetadata(null, OnDataTemplateChanged)); + + #endregion + + #region GroupHeaderTemplate DependencyProperty + + /// + /// The GroupHeaderTemplate provides the template for the groups in the items view. + /// + public DataTemplate GroupHeaderTemplate + { + get { return (DataTemplate)GetValue(GroupHeaderProperty); } + set { SetValue(GroupHeaderProperty, value); } + } + + /// + /// The GroupHeaderTemplate DependencyProperty. + /// + public static readonly DependencyProperty GroupHeaderProperty = + DependencyProperty.Register("GroupHeaderTemplate", typeof(DataTemplate), typeof(LongListSelector), new PropertyMetadata(null, OnDataTemplateChanged)); + #endregion + + #region GroupFooterTemplate DependencyProperty + + /// + /// The GroupFooterTemplate provides the template for the groups in the items view. + /// + public DataTemplate GroupFooterTemplate + { + get { return (DataTemplate)GetValue(GroupFooterProperty); } + set { SetValue(GroupFooterProperty, value); } + } + + /// + /// The GroupFooterTemplate DependencyProperty. + /// + public static readonly DependencyProperty GroupFooterProperty = + DependencyProperty.Register("GroupFooterTemplate", typeof(DataTemplate), typeof(LongListSelector), new PropertyMetadata(null, OnDataTemplateChanged)); + + #endregion + + #region ItemTemplate DependencyProperty + + /// + /// The ItemTemplate provides the template for the items in the items view. + /// + public DataTemplate ItemTemplate + { + get { return (DataTemplate)GetValue(ItemsTemplateProperty); } + set { SetValue(ItemsTemplateProperty, value); } + } + + /// + /// The ItemTemplate DependencyProperty. + /// + public static readonly DependencyProperty ItemsTemplateProperty = + DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(LongListSelector), new PropertyMetadata(null, OnDataTemplateChanged)); + + #endregion + + #region DisplayAllGroups DependencyProperty + + /// + /// Display all groups whether or not they have items. + /// + public bool DisplayAllGroups + { + get { return (bool)GetValue(DisplayAllGroupsProperty); } + set { SetValue(DisplayAllGroupsProperty, value); } + } + + /// + /// DisplayAllGroups DependencyProperty + /// + public static readonly DependencyProperty DisplayAllGroupsProperty = + DependencyProperty.Register("DisplayAllGroups", typeof(bool), typeof(LongListSelector), new PropertyMetadata(false, OnDisplayAllGroupsChanged)); + #endregion + + #region GroupItemTemplate DependencyProperty + + /// + /// The GroupItemTemplate specifies the template that will be used in group view mode. + /// + public DataTemplate GroupItemTemplate + { + get { return (DataTemplate)GetValue(GroupItemTemplateProperty); } + set { SetValue(GroupItemTemplateProperty, value); } + } + + /// + /// The GroupItemTemplate DependencyProperty. + /// + public static readonly DependencyProperty GroupItemTemplateProperty = + DependencyProperty.Register("GroupItemTemplate", typeof(DataTemplate), typeof(LongListSelector), new PropertyMetadata(null)); + + #endregion + + #region GroupItemsPanel DependencyProperty + + /// + /// The GroupItemsPanel specifies the panel that will be used in group view mode. + /// + public ItemsPanelTemplate GroupItemsPanel + { + get { return (ItemsPanelTemplate)GetValue(GroupItemsPanelProperty); } + set { SetValue(GroupItemsPanelProperty, value); } + } + + /// + /// The GroupItemsPanel DependencyProperty. + /// + public static readonly DependencyProperty GroupItemsPanelProperty = + DependencyProperty.Register("GroupItemsPanel", typeof(ItemsPanelTemplate), typeof(LongListSelector), new PropertyMetadata(null)); + + #endregion + + #region BufferSize DependencyProperty + /// + /// The number of "screens" (as defined by the ActualHeight of the LongListSelector) above and below the visible + /// items of the list that will be filled with items. + /// + [Obsolete("BufferSize no longer affect items virtualization")] + public double BufferSize + { + get { return (double)GetValue(BufferSizeProperty); } + set { SetValue(BufferSizeProperty, value); } + } + + /// + /// The BufferSize DependencyProperty + /// + [Obsolete("BufferSizeProperty no longer affect items virtualization")] + public static readonly DependencyProperty BufferSizeProperty = + DependencyProperty.Register("BufferSize", typeof(double), typeof(LongListSelector), new PropertyMetadata(BufferSizeDefault, OnBufferSizeChanged)); + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] + private static void OnBufferSizeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) + { + double newValue = (double)e.NewValue; + + if (newValue < 0) + { + throw new ArgumentOutOfRangeException("BufferSize"); + } + } + + #endregion + + #region MaximumFlickVelocity DependencyProperty + /// + /// The maximum velocity for flicks, in pixels per second. + /// + [Obsolete("MaximumFlickVelocity is not used anymore.")] + public double MaximumFlickVelocity + { + get { return (double)GetValue(MaximumFlickVelocityProperty); } + set { SetValue(MaximumFlickVelocityProperty, value); } + } + + /// + /// The MaximumFlickVelocity DependencyProperty. + /// + [Obsolete("MaximumFlickVelocityProperty is not used anymore.")] + public static readonly DependencyProperty MaximumFlickVelocityProperty = + DependencyProperty.Register("MaximumFlickVelocity", typeof(double), typeof(LongListSelector), new PropertyMetadata(MotionParameters.MaximumSpeed)); + + #endregion + + #region ShowListHeader DependencyProperty + + /// + /// Controls whether or not the ListHeader is shown. + /// + public bool ShowListHeader + { + get { return (bool)GetValue(ShowListHeaderProperty); } + set { SetValue(ShowListHeaderProperty, value); } + } + + /// + /// The ShowListHeader DependencyProperty. + /// + public static readonly DependencyProperty ShowListHeaderProperty = + DependencyProperty.Register("ShowListHeader", typeof(bool), typeof(LongListSelector), new PropertyMetadata(true, OnShowListHeaderChanged)); + + private static void OnShowListHeaderChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) + { + LongListSelector control = (LongListSelector)obj; + + if (control._listBox != null) + { + Collection tuples = (Collection)control._listBox.ItemsSource; + if (control.ShowListHeader) + { + control.AddListHeader(tuples); + } + else + { + RemoveListHeader(tuples); + } + } + } + #endregion + + #region ShowListFooter DependencyProperty + + /// + /// Controls whether or not the ListFooter is shown. + /// + public bool ShowListFooter + { + get { return (bool)GetValue(ShowListFooterProperty); } + set { SetValue(ShowListFooterProperty, value); } + } + + /// + /// The ShowListFooter DependencyProperty. + /// + public static readonly DependencyProperty ShowListFooterProperty = + DependencyProperty.Register("ShowListFooter", typeof(bool), typeof(LongListSelector), new PropertyMetadata(true, OnShowListFooterChanged)); + + private static void OnShowListFooterChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) + { + LongListSelector control = (LongListSelector)obj; + + if (control._listBox != null) + { + Collection tuples = (Collection)control._listBox.ItemsSource; + if (control.ShowListFooter) + { + control.AddListFooter(tuples); + } + else + { + RemoveListFooter(tuples); + } + } + + } + + #endregion + + #endregion + + #region Events + + /// + /// Occurs when the currently selected item changes. + /// + public event SelectionChangedEventHandler SelectionChanged; + + /// + /// Occurs when this control starts scrolling. + /// + public event EventHandler ScrollingStarted; + + /// + /// Occurs when this control stops scrolling. + /// + public event EventHandler ScrollingCompleted; + + /// + /// Occurs when the group Popup's IsOpen has been set to true. + /// + public event EventHandler GroupViewOpened; + + /// + /// Occurs when the group popup is about to close. + /// + public event EventHandler GroupViewClosing; + + /// + /// Occurs when an item is about to be "realized". + /// + public event EventHandler Link; + + /// + /// Occurs when an item is about to be "un-realized". + /// + public event EventHandler Unlink; + + /// + /// Occurs when the user has dragged the items up from the bottom as far as they can go. + /// + public event EventHandler StretchingBottom; + + /// + /// Occurs when the user is no longer stretching. + /// + public event EventHandler StretchingCompleted; + + /// + /// Occurs when the user has dragged the items down from the top as far as they can go. + /// + public event EventHandler StretchingTop; + + #endregion + + #region Constructor + /// + /// Initializes a new instance of . + /// + public LongListSelector() + { + DefaultStyleKey = typeof(LongListSelector); + } + + //~LongListSelector() + //{ + + //} + #endregion + + // + // Public methods + // + + public void ScrollToTop() + { + if (_scrollViewer != null) + { + _scrollViewer.ScrollToVerticalOffset(0.0); + } + } + + #region ScrollTo(...) + /// + /// Instantly jump to the specified item. + /// + /// Item to jump to. + public void ScrollTo(object item) + { + if (_listBox != null && item != null) + { + ObservableCollection tuples = (ObservableCollection)_listBox.ItemsSource; + LongListSelectorItem lastTuple = tuples[tuples.Count - 1]; + + _listBox.ScrollIntoView(lastTuple); + + UpdateLayout(); + + foreach (LongListSelectorItem tuple in _listBox.ItemsSource) + { + if (tuple.Item != null && tuple.Item.Equals(item)) + { + _listBox.ScrollIntoView(tuple); + break; + } + } + } + } + #endregion + + #region ScrollToGroup(...) + /// + /// Instantly jump to the specified group. + /// + /// Group to jump to. + public void ScrollToGroup(object group) + { + ScrollTo(group); + } + #endregion + + #region DisplayGroupView() + /// + /// Invokes the group view if a GroupItemTemplate has been defined. + /// + public void DisplayGroupView() + { + if (GroupItemTemplate != null && !IsFlatList) + { + OpenPopup(); + } + } + #endregion + + #region CloseGroupView() + /// + /// Closes the group view unconditionally. + /// + /// Does not raise the GroupViewClosingEventArgs event. + public void CloseGroupView() + { + ClosePopup(null, false); + } + #endregion + + // Obsolete: + + #region AnimateTo(...) + /// + /// Animate the scrolling of the list to the specified item. + /// + /// Item to scroll to. + [Obsolete("AnimateTo(...) call ScrollTo(...) to jump without animation to the given item.")] + public void AnimateTo(object item) + { + ScrollTo(item); + } + #endregion + + /// + /// Returns either containers or items for either all items with + /// containers or just the visible ones, as specified by the + /// parameters. + /// + /// When true, will return values for + /// only items that are in view. + /// When true, will return the containers + /// rather than the items. + /// Returns either containers or items for either all items + /// with containers or just the visible ones, as specified by the + /// parameters. + [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "getContainers", Justification = "This is an obsolete old method that cannot change now.")] + [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "onlyItemsInView", Justification = "This is an obsolete old method that cannot change now.")] + [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This is an obsolete old method that cannot change now.")] + [Obsolete("GetItemsWithContainers(...) always returns an empty collection of items. Rely on Link/Unlink to know an item get realized or unrealized.")] + public ICollection GetItemsWithContainers(bool onlyItemsInView, bool getContainers) + { + return new Collection(); + } + + #region GetItemsInView() + /// + /// Returns all of the items that are currently in view. + /// This is not the same as the items that have associated visual elements: there are usually some visuals offscreen. + /// This might be an empty list if scrolling is happening too quickly. + /// + /// Returns all of the items that are currently in view. + [Obsolete("GetItemsInView() always returns an empty collection of items. Rely on Link/Unlink to know an item get realized or unrealized.")] + public ICollection GetItemsInView() + { + return GetItemsWithContainers(true, false); + } + #endregion + + #region OnItemsSourceChanged() + /// + /// Called when the ItemsSource dependency property changes. + /// + private void OnItemsSourceChanged() + { + // Reload the whole list. + LoadDataIntoListBox(); + } + #endregion + + #region OnApplyTemplate() + /// + /// Called whenever a template gets applied on this control. + /// + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + // Unsubscribe from events we registered for in the past. + if (_listBox != null) + { + _listBox.SelectionChanged -= OnSelectionChanged; + _listBox.Link -= OnLink; + _listBox.Unlink -= OnUnlink; + } + + if (_scrollGroup != null) + { + _scrollGroup.CurrentStateChanging -= OnScrollStateChanging; + } + + // Locates and setup the TemplatedListBox in the template. If no TemplatedListBox is found, we + // initialize one. + _listBox = GetTemplateChild(TemplatedListBoxName) as TemplatedListBox ?? new TemplatedListBox(); + _listBox.ItemsPanel = ItemsPanel; + _listBox.ListHeaderTemplate = ListHeaderTemplate; + _listBox.ListFooterTemplate = ListFooterTemplate; + _listBox.GroupHeaderTemplate = GroupHeaderTemplate; + _listBox.GroupFooterTemplate = GroupFooterTemplate; + _listBox.ItemTemplate = ItemTemplate; + _listBox.SelectionChanged += OnSelectionChanged; + _listBox.Link += OnLink; + _listBox.Unlink += OnUnlink; + + // Retrieves the ScrollViewer of the list box. + ScrollViewer sv = _listBox.GetFirstLogicalChildByType(true); + + if (sv != null) + { + _scrollViewer = sv; + + _scrollViewer.HorizontalScrollBarVisibility = HorizontalScrollBarVisibility; + _scrollViewer.VerticalScrollBarVisibility = VerticalScrollBarVisibility; + + // Visual States are always on the first child of the control template + FrameworkElement element = VisualTreeHelper.GetChild(sv, 0) as FrameworkElement; + if (element != null) + { + _scrollGroup = VisualStates.TryGetVisualStateGroup(sv, ScrollStatesGroupName); + if (_scrollGroup != null) + { + _scrollGroup.CurrentStateChanging += OnScrollStateChanging; + } + + _verticalCompressionGroup = VisualStates.TryGetVisualStateGroup(sv, VerticalCompressionStateName); + if(_verticalCompressionGroup != null) + { + _verticalCompressionGroup.CurrentStateChanging += OnStretchStateChanging; + } + } + + var binding = new Binding("VerticalOffset") { Source = _scrollViewer }; + SetBinding(VerticalOffsetProperty, binding); + } + + LoadDataIntoListBox(); + } + #endregion + + #region LoadDataIntoListBox() + /// + /// Loads ItemsSource into the hosted list box. + /// + private void LoadDataIntoListBox() + { + if (_listBox != null) + { + ObservableCollection tuples = new ObservableCollection(); + + AddListHeader(tuples); + + UnsubscribeFromAllCollections(); + + // if it's a flat list, add the items without grouping. + if (IsFlatList) + { + if (ItemsSource != null) + { + foreach (object item in ItemsSource) + { + tuples.Add(new LongListSelectorItem() { Item = item, ItemType = LongListSelectorItemType.Item }); + } + } + } + // Otherwise, apply the grouping logic. + else + { + IEnumerable groups = ItemsSource; + if (groups != null) + { + foreach (object group in groups) + { + AddGroup(group, tuples); + } + } + } + + + AddListFooter(tuples); + + _rootCollection = ItemsSource as INotifyCollectionChanged; + if (_rootCollection != null) + { + _rootCollection.CollectionChanged += OnCollectionChanged; + } + + _listBox.ItemsSource = tuples; + } + } + #endregion + + #region List/Footer Headers + /// + /// Adds a list header to the given list. + /// + private void AddListHeader(IList tuples) + { + if (HasListHeader && ShowListHeader && // Adds the list header if it got a template or if it's a UI element itself. + (tuples.Count == 0 || tuples[0].ItemType != LongListSelectorItemType.ListHeader)) // Also, make sure its not already there + { + tuples.Insert(0, new LongListSelectorItem() { Item = ListHeader, ItemType = LongListSelectorItemType.ListHeader }); + } + } + /// + /// Adds a list header to the listbox. + /// + private void AddListHeader() + { + AddListHeader((ObservableCollection)_listBox.ItemsSource); + } + + /// + /// Removes the list header from the given list. + /// + private static void RemoveListHeader(IList tuples) + { + if (tuples.Count > 0 && tuples[0].ItemType == LongListSelectorItemType.ListHeader) + { + tuples.RemoveAt(0); + } + } + + /// + /// Removes the list header from the listbox. + /// + private void RemoveListHeader() + { + RemoveListHeader((ObservableCollection)_listBox.ItemsSource); + } + + /// + /// Adds a list footer to the given list. + /// + private void AddListFooter(IList tuples) + { + if (HasListFooter && ShowListFooter && // Adds the list footer if it got a template or if it's a UI element itself. + (tuples.Count == 0 || tuples[tuples.Count - 1].ItemType != LongListSelectorItemType.ListFooter)) // Also, make sure its not already there + { + tuples.Add(new LongListSelectorItem() { Item = ListFooter, ItemType = LongListSelectorItemType.ListFooter }); + } + } + + /// + /// Adds a list footer to the listbox. + /// + private void AddListFooter() + { + AddListFooter((ObservableCollection)_listBox.ItemsSource); + } + + /// + /// Removes the list footer from the given list. + /// + private static void RemoveListFooter(IList tuples) + { + LongListSelectorItem lastTuple = tuples[tuples.Count - 1]; + if (lastTuple != null && lastTuple.ItemType == LongListSelectorItemType.ListFooter) + { + tuples.RemoveAt(tuples.Count - 1); + } + } + + /// + /// Removes the list footer from the listbox. + /// + private void RemoveListFooter() + { + RemoveListFooter((ObservableCollection)_listBox.ItemsSource); + } + #endregion + + #region AddGroup(...) + /// + /// Adds a group to a list of tuples. + /// + /// Group to add. + /// List to which the method will add the group. + private void AddGroup(object groupToAdd, IList tuples) + { + IEnumerable group = groupToAdd as IEnumerable; + if (group != null) + { + bool groupHasItems = false; + + // Adds the group header + if (GroupHeaderTemplate != null) + { + tuples.Add(new LongListSelectorItem() { Item = group, ItemType = LongListSelectorItemType.GroupHeader }); + } + + // For each group header, add its items + foreach (object item in group) + { + tuples.Add(new LongListSelectorItem() { Item = item, ItemType = LongListSelectorItemType.Item, Group = group }); + groupHasItems = true; + } + + // Add the group footer if the group has items or if we must display all groups whether or not they have items. + if (groupHasItems || DisplayAllGroups) + { + if (GroupFooterTemplate != null) + { + tuples.Add(new LongListSelectorItem() { Item = group, ItemType = LongListSelectorItemType.GroupFooter }); + } + } + // Otherwise, remove the group header + else if (GroupHeaderTemplate != null) + { + tuples.RemoveAt(tuples.Count - 1); + } + + // Subscribe to collection change event + INotifyCollectionChanged groupCollection = group as INotifyCollectionChanged; + if (groupCollection != null && !_groupCollections.Contains(groupCollection)) + { + groupCollection.CollectionChanged += OnCollectionChanged; + _groupCollections.Add(groupCollection); + } + + } + } + #endregion + + #region AddGroupHeadersAndFooters(...) + /// + /// Adds group headers or footers after their template switch from being null + /// to an actual value. + /// + /// Specifies whether or not to add group headers. + /// Specifies whether or not to add group footers. + /// Used only when templates for group headers/footers switch from being null. + /// In this case, they must be added to the lisbox if a group is not empty or DisplayAllGroups is true. + /// For performance reasons, this method makes an assumption that headers/footers are not already present. + /// Which is the case when its called from OnDataTemplateChanged. + private void AddGroupHeadersAndFooters(bool addHeaders, bool addFooters) + { + int indexInListBox = 0; + + if (HasListHeader && ShowListHeader) + { + ++indexInListBox; + } + + IEnumerable groups = ItemsSource; + ObservableCollection tuples = (ObservableCollection)_listBox.ItemsSource; + + if (groups != null) + { + foreach (object group in groups) + { + var groupAsEnumerable = group as IEnumerable; + if (groupAsEnumerable != null) + { + int itemsCount = GetHeadersAndItemsCountFromGroup(groupAsEnumerable); + + // Adds the group header + if (addHeaders && GroupHeaderTemplate != null && itemsCount > 0) + { + tuples.Insert(indexInListBox, new LongListSelectorItem + { + Item = group, + ItemType = LongListSelectorItemType.GroupHeader + }); + } + + indexInListBox += itemsCount; + + // Adds the group footer + if (addFooters && GroupFooterTemplate != null && itemsCount > 0) + { + tuples.Insert(indexInListBox - 1, new LongListSelectorItem + { + Item = group, + ItemType = LongListSelectorItemType.GroupFooter + }); + } + } + } + } + } + + /// + /// Adds group headers after the GroupHeaderTeamplate switch from being null + /// to an actual value. + /// + private void AddGroupHeaders() + { + AddGroupHeadersAndFooters(true, false); + } + + /// + /// Adds group headers after the GroupFooterTeamplate switch from being null + /// to an actual value. + /// + private void AddGroupFooters() + { + AddGroupHeadersAndFooters(false, true); + } + #endregion + + #region RemoveAllGroupHeadersAndFooters(...) + /// + /// Removes group headers or footers after their template becomes null. + /// + /// Specifies whether or not to remove group headers. + /// Specifies whether or not to remove group footers. + private void RemoveAllGroupHeadersAndFooters(bool removeHeaders, bool removeFooters) + { + ObservableCollection tuples = (ObservableCollection)_listBox.ItemsSource; + for (int i = 0; i < tuples.Count; ++i) + { + if ((removeHeaders && tuples[i].ItemType == LongListSelectorItemType.GroupHeader) || + (removeFooters && tuples[i].ItemType == LongListSelectorItemType.GroupFooter)) + { + tuples.RemoveAt(i--); // the -- is there so we don't skip tuples + } + } + } + private void RemoveAllGroupHeaders() + { + RemoveAllGroupHeadersAndFooters(true, false); + } + private void RemoveAllGroupFooters() + { + RemoveAllGroupHeadersAndFooters(false, true); + } + #endregion + + #region UnsubscribeFromAllCollections() + /// + /// Unsubscrives from every collection in ItemsSource. + /// + private void UnsubscribeFromAllCollections() + { + if (_rootCollection != null) + { + _rootCollection.CollectionChanged -= OnCollectionChanged; + } + + foreach (INotifyCollectionChanged collection in _groupCollections) + { + collection.CollectionChanged -= OnCollectionChanged; + } + + _rootCollection = null; + _groupCollections.Clear(); + } + #endregion + + #region InsertNewGroups(...) + /// + /// Inserts new groups in the list box. + /// + /// List of the new groups to insert. + /// Insertion index relative to the collection. + private void InsertNewGroups(IList newGroups, int newGroupsIndex) + { + ObservableCollection tuples = (ObservableCollection)_listBox.ItemsSource; + + // 1 - Builds items tuples for the new groups + List newGroupsTuples = new List(); + + foreach (object group in newGroups) + { + AddGroup(group, newGroupsTuples); + } + + if (newGroupsTuples.Count > 0) + { + // 2 - Finds insertion index in the list box + int insertIndex = GetGroupIndexInListBox(newGroupsIndex); + + // 3 - Inserts the new items into the list box + foreach (LongListSelectorItem tuple in newGroupsTuples) + { + tuples.Insert(insertIndex++, tuple); + } + } + } + #endregion + + #region InsertNewItems(...) + /// + /// Inserts new items in the list box. + /// + /// List of new items to insert. + /// Insertion index relative to the collection + /// Group into which the items are inserted. Can be null if IsFlatList == true + private void InsertNewItems(IList newItems, int newItemsIndex, IEnumerable group) + { + ObservableCollection tuples = (ObservableCollection)_listBox.ItemsSource; + + // 1 - Builds items tuples for the new items + List newItemsTuples = new List(); + foreach (object item in newItems) + { + newItemsTuples.Add(new LongListSelectorItem + { + Group = group, + Item = item, + ItemType = LongListSelectorItemType.Item + }); + } + + // 2 - Finds the insertion index in the listbox + // Since a single group might be referenced by more than one, we might need to update more than one spot in the listbox + if (group != null) + { + int i = 0; + bool groupWasNotDisplayed = ((IList)group).Count == newItems.Count && !DisplayAllGroups; + + foreach (object g in ItemsSource) + { + if (g == group) + { + int insertIndex = GetGroupIndexInListBox(i); + + if (GroupHeaderTemplate != null) + { + if (groupWasNotDisplayed) + { + tuples.Insert(insertIndex, new LongListSelectorItem() { ItemType = LongListSelectorItemType.GroupHeader, Item = group }); + } + ++insertIndex; + } + + insertIndex += newItemsIndex; + + // 3 - Inserts the new items into the list box + foreach (LongListSelectorItem tuple in newItemsTuples) + { + tuples.Insert(insertIndex++, tuple); + } + + if (groupWasNotDisplayed && GroupFooterTemplate != null) + { + tuples.Insert(insertIndex++, new LongListSelectorItem() { ItemType = LongListSelectorItemType.GroupFooter, Item = group }); + } + } + ++i; + } + } + else + { + int insertIndex = newItemsIndex; + if (HasListHeader && ShowListHeader) + { + ++insertIndex; + } + + // 3 - Inserts the new items into the list box + foreach (LongListSelectorItem tuple in newItemsTuples) + { + tuples.Insert(insertIndex++, tuple); + } + } + } + #endregion + + #region RemoveOldGroups(...) + /// + /// Removes groups from the list box. + /// + /// List of groups to remove. + /// Start index relative to the root collection. + private void RemoveOldGroups(IList oldGroups, int oldGroupsIndex) + { + ObservableCollection tuples = (ObservableCollection)_listBox.ItemsSource; + + // 1 - Find the index at which we start removing groups + int removeStartIndex = 0; + if (oldGroupsIndex > 0) + { + removeStartIndex = GetGroupIndexInListBox(oldGroupsIndex - 1); + IEnumerable group = ((IList)ItemsSource)[oldGroupsIndex - 1] as IEnumerable; + if (group != null) + { + removeStartIndex += GetHeadersAndItemsCountFromGroup(group); + } + } + else + { + if (HasListHeader && ShowListHeader) + { + ++removeStartIndex; + } + } + + // 2 - Calculates how many items to delete from the ListBox + int itemsToRemoveCount = GetItemsCountFromGroups(oldGroups); + + // 3 - Removes the old items from the ListBox + for (int i = 0; i < itemsToRemoveCount; ++i) + { + tuples.RemoveAt(removeStartIndex); + } + + // 4 - Unsubscribe from the old groups + foreach (INotifyCollectionChanged collection in oldGroups) + { + collection.CollectionChanged -= OnCollectionChanged; + } + + } + #endregion + + #region RemoveOldItems(...) + /// + /// Removes old items from a group or from the root collection. + /// + /// List of items to remove. + /// Start index relative to the group or root collection. + /// Group from which items are removed. Can be null if IsFlatList == true. + private void RemoveOldItems(IList oldItems, int oldItemsIndex, IEnumerable group) + { + ObservableCollection tuples = (ObservableCollection)_listBox.ItemsSource; + + // 1 - Finds the remove index in the listbox + // Since a single group might be referenced by more than one, we might need to update more than one group + if (group != null) + { + int i = 0; + + foreach (object g in ItemsSource) + { + if (g == group) + { + int removeIndex = GetGroupIndexInListBox(i); + removeIndex += oldItemsIndex; + + if (GroupHeaderTemplate != null) + { + ++removeIndex; + } + + // 2 - Removes the old items + for (int j = 0; j < oldItems.Count; ++j) + { + tuples.RemoveAt(removeIndex); + } + + // 3 - Hides the group header and footer if it's empty and DisplayAllGroups is false + if (((IList)group).Count == 0 && !DisplayAllGroups) + { + if (GroupFooterTemplate != null) + { + tuples.RemoveAt(removeIndex); // Removes the group footer + } + if (GroupHeaderTemplate != null) + { + tuples.RemoveAt(removeIndex - 1); // Removes the group header + } + } + } + ++i; + } + } + else + { + int removeIndex = oldItemsIndex; + if (HasListHeader && ShowListHeader) + { + ++removeIndex; + } + for(int i = 0; i < oldItems.Count; ++i) + tuples.RemoveAt(removeIndex); + } + } + #endregion + + #region GetGroupIndexInListBox(...) + /// + /// Returns, for a group, an index relative to the templated list box from an index relative to the root collection. + /// + /// Index relative to the root collection. + /// Returns, for a group, an index relative to the templated list box from an index relative to the root collection. + private int GetGroupIndexInListBox(int indexInLLS) + { + int indexInListBox = 0, index = 0; + + if (HasListHeader && ShowListHeader) + { + ++indexInListBox; + } + + IEnumerable groups = ItemsSource; + + if (groups != null) + { + foreach (object group in groups) + { + if (indexInLLS == index) + { + break; + } + + ++index; + + var groupAsEnumerable = group as IEnumerable; + if (groupAsEnumerable != null) + { + indexInListBox += GetHeadersAndItemsCountFromGroup(groupAsEnumerable); + } + } + } + + return indexInListBox; + } + #endregion + + #region GetItemsCountFromGroups(...) + /// + /// Returns the number of items in a list of groups. + /// + /// List of groups from which to retrieve the items count. + /// Returns the number of items in a list of groups. + private int GetItemsCountFromGroups(IEnumerable groups) + { + int count = 0; + + foreach (object g in groups) + { + IEnumerable group = g as IEnumerable; + if (group != null) + { + count += GetHeadersAndItemsCountFromGroup(group); + } + } + + return count; + } + #endregion + + #region GetItemsCountFromGroup(...) + /// + /// Returns the number of items in a group including the group header. + /// + /// Group from which to retrieve the items count. + /// Returns the number of items in a group including the group header. + private int GetHeadersAndItemsCountFromGroup(IEnumerable group) + { + int count = 0; + + IList groupAsList = group as IList; + if (groupAsList != null) + { + count += groupAsList.Count; + } + else + { + count += group.Cast().Count(); + } + + bool groupHasItems = count > 0; + + if ((groupHasItems || DisplayAllGroups) && GroupHeaderTemplate != null) + { + ++count; + } + + if ((groupHasItems || DisplayAllGroups) && GroupFooterTemplate != null) + { + ++count; + } + + return count; + } + #endregion + + #region UpdateListBoxItemsTemplate(...) + /// + /// Updates the templates for a given item type in the list box. + /// + /// Item type for which to update the template. + /// New template that will replace the old one. + private void UpdateItemsTemplate(LongListSelectorItemType itemType, DataTemplate newTemplate) + { + if (_listBox != null) + { + // Update template for items that have been linked (realized) + IEnumerable items = _listBox.GetLogicalChildrenByType(false); + foreach (TemplatedListBoxItem item in items) + { + LongListSelectorItem tuple = (LongListSelectorItem)item.Tuple; + if (tuple.ItemType == itemType) + { + item.ContentTemplate = newTemplate; + } + } + + // Save the new template so they can be applied in the future when new items + // are linked (realized) + switch (itemType) + { + case LongListSelectorItemType.ListHeader: + _listBox.ListHeaderTemplate = newTemplate; + break; + case LongListSelectorItemType.ListFooter: + _listBox.ListFooterTemplate = newTemplate; + break; + case LongListSelectorItemType.GroupHeader: + _listBox.GroupHeaderTemplate = newTemplate; + break; + case LongListSelectorItemType.GroupFooter: + _listBox.GroupFooterTemplate = newTemplate; + break; + case LongListSelectorItemType.Item: + _listBox.ItemTemplate = newTemplate; + break; + } + } + } + #endregion + + #region OnDataTemplateChanged(...) + /// + /// Called when a data template has changed. + /// + private static void OnDataTemplateChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + LongListSelector lls = (LongListSelector)o; + if (lls._listBox == null) + return; + + DataTemplate newTemplate = (DataTemplate)e.NewValue; + + if (e.Property == ListHeaderTemplateProperty) + { + lls.UpdateItemsTemplate(LongListSelectorItemType.ListHeader, newTemplate); + + // If the old value was null, we might need to add the list header. + if (e.OldValue == null) + { + lls.AddListHeader(); // Will add a list header if it's not already there. + } + // If we don't have a list header anymore, then remove it from the listbox + else if (e.NewValue == null && !lls.HasListHeader) + { + lls.RemoveListHeader(); + } + + } + else if (e.Property == ListFooterTemplateProperty) + { + lls.UpdateItemsTemplate(LongListSelectorItemType.ListFooter, newTemplate); + + // If the old value was null, we might need to add the list footer. + if (e.OldValue == null) + { + lls.AddListFooter(); // Will add a list footer if it's not already there. + } + // If we don't have a list footer anymore, then remove it from the listbox + else if (e.NewValue == null && !lls.HasListHeader) + { + lls.RemoveListFooter(); + } + + } + else if (e.Property == GroupHeaderProperty) + { + lls.UpdateItemsTemplate(LongListSelectorItemType.GroupHeader, newTemplate); + + // If the old value was null, this means we might need to add group headers to the listbox + if (e.OldValue == null) + { + lls.AddGroupHeaders(); + } + // If the new value is null, this means we might need to remove group headers from the listbox + else if (e.NewValue == null) + { + lls.RemoveAllGroupHeaders(); + } + + } + else if(e.Property == GroupFooterProperty) + { + lls.UpdateItemsTemplate(LongListSelectorItemType.GroupFooter, newTemplate); + + // If the old value was null, this means we might need to add group footers to the listbox + if (e.OldValue == null) + { + lls.AddGroupFooters(); + } + // If the new value is null, this means we might need to remove group footers from the listbox + else if (e.NewValue == null) + { + lls.RemoveAllGroupFooters(); + } + + } + else if (e.Property == ItemsTemplateProperty) + { + lls.UpdateItemsTemplate(LongListSelectorItemType.Item, newTemplate); + } + } + #endregion + + #region OnDisplayAllGroupsChanged(...) + /// + /// Called when the DisplayAllGroups dependency property changes + /// + private static void OnDisplayAllGroupsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) + { + ((LongListSelector)obj).LoadDataIntoListBox(); + } + #endregion + + #region OnSelectionChanged(...) + /// + /// Called when there is a change in the selected item(s) in the listbox. + /// + private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + // Group navigation + //var group = (from t in (IEnumerable)e.AddedItems where ((ItemTuple)t).ItemType == ItemType.GroupHeader select (ItemTuple)t).FirstOrDefault(); + LongListSelectorItem group = null; + foreach (LongListSelectorItem tuple in e.AddedItems) + { + if (tuple.ItemType == LongListSelectorItemType.GroupHeader) + { + group = tuple; + break; + } + } + + if (group != null) + { + SelectedItem = null; + DisplayGroupView(); + } + else + { + var handler = SelectionChanged; + + if (handler != null) + { + List addedItems = new List(); + List removedItems = new List(); + + foreach (LongListSelectorItem tuple in e.AddedItems) + { + if (tuple.ItemType == LongListSelectorItemType.Item) + { + addedItems.Add(tuple); + } + } + + foreach (LongListSelectorItem tuple in e.RemovedItems) + { + if (tuple.ItemType == LongListSelectorItemType.Item) + { + removedItems.Add(tuple); + } + } + + handler(this, new SelectionChangedEventArgs(removedItems, addedItems)); + } + } + + } + #endregion + + #region OnCollectionChanged(...) + /// + /// Called when there is a change in the root or a group collection. + /// + private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + var senderAsEnumerable = sender as IEnumerable; + + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + if (sender == _rootCollection) + { + if (IsFlatList) + { + InsertNewItems(e.NewItems, e.NewStartingIndex, null); + } + else + { + InsertNewGroups(e.NewItems, e.NewStartingIndex); + } + } + else + { + InsertNewItems(e.NewItems, e.NewStartingIndex, senderAsEnumerable); + } + break; + + case NotifyCollectionChangedAction.Remove: + if (sender == _rootCollection) + { + if (IsFlatList) + { + RemoveOldItems(e.OldItems, e.OldStartingIndex, null); + } + else + { + RemoveOldGroups(e.OldItems, e.OldStartingIndex); + } + } + else + { + RemoveOldItems(e.OldItems, e.OldStartingIndex, senderAsEnumerable); + } + break; + + case NotifyCollectionChangedAction.Replace: + case NotifyCollectionChangedAction.Reset: + LoadDataIntoListBox(); + break; + } + } + #endregion + + #region OnScrollStateChanging(...) + /// + /// Called when the scrolling state of the list box changes. + /// + private void OnScrollStateChanging(object sender, VisualStateChangedEventArgs e) + { + IsScrolling = e.NewState.Name == ScrollingState; + + if (e.NewState.Name == ScrollingState && ScrollingStarted != null) + { + ScrollingStarted(this, null); + } + else if (e.NewState.Name == NotScrollingState && ScrollingCompleted != null) + { + ScrollingCompleted(this, null); + } + } + #endregion + + #region OnScrollStateChanging(...) + /// + /// Called when the scrolling state of the list box changes. + /// + private void OnStretchStateChanging(object sender, VisualStateChangedEventArgs e) + { + IsStretching = e.NewState.Name == CompressionBottom || e.NewState.Name == CompressionTop; + + if (e.NewState.Name == CompressionTop && StretchingTop != null) + { + StretchingTop(this, null); + } + else if (e.NewState.Name == CompressionBottom && StretchingBottom != null) + { + StretchingBottom(this, null); + } + else if (e.NewState.Name == NoVerticalCompression && StretchingCompleted != null) + { + StretchingCompleted(this, null); + } + } + #endregion + + #region OnLink(...) + /// + /// Called when an item gets realized. + /// + void OnLink(object sender, LinkUnlinkEventArgs e) + { + if (Link != null) + { + Link(this, e); + } + } + #endregion + + #region OnUnlink(...) + /// + /// Called when an item gets unrealized. + /// + void OnUnlink(object sender, LinkUnlinkEventArgs e) + { + if (Unlink != null) + { + Unlink(this, e); + } + } + #endregion + + public int SelectedIndex + { + get { return _listBox.SelectedIndex; } + } + + public DependencyObject ContainerFromSelectedItem() + { + if (_listBox == null + || _listBox.ItemContainerGenerator == null) + { + return null; + } + + return _listBox.ItemContainerGenerator.ContainerFromItem(_listBox.SelectedItem); + } + + public DependencyObject ContainerFromItem(object item) + { + if (_listBox == null + || _listBox.ItemContainerGenerator == null) + { + return null; + } + + var tuples = (ObservableCollection)_listBox.ItemsSource; + if (tuples != null && tuples.Count > 0) + { + foreach (var tuple in tuples) + { + if (tuple.Item == item) + { + return _listBox.ItemContainerGenerator.ContainerFromItem(tuple); + } + } + } + + return null; + } + + #region Additional + + private double _closeToEndPercent = 0.7; + + public double CloseToEndPercent + { + get { return _closeToEndPercent; } + set { _closeToEndPercent = value; } + } + + private double _prevVerticalOffset; + + public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.Register( + "VerticalOffset", typeof(double), typeof(LongListSelector), new PropertyMetadata(default(double), OnVerticalOffsetChanged)); + + private static void OnVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var longListSelector = d as LongListSelector; + if (longListSelector != null) + { + longListSelector.OnListenerChanged(longListSelector, new BindingChangedEventArgs(e)); + } + } + + public double VerticalOffset + { + get { return (double) GetValue(VerticalOffsetProperty); } + set { SetValue(VerticalOffsetProperty, value); } + } + + private void OnListenerChanged(object sender, BindingChangedEventArgs e) + { + if (_prevVerticalOffset >= _scrollViewer.VerticalOffset) return; + if (_scrollViewer.VerticalOffset == 0.0 && _scrollViewer.ScrollableHeight == 0.0) return; + + _prevVerticalOffset = _scrollViewer.VerticalOffset; + var atBottom = _scrollViewer.VerticalOffset >= _scrollViewer.ScrollableHeight * CloseToEndPercent; + + if (atBottom) + { + RaiseCloseToEnd(); + } + } + + public event EventHandler CloseToEnd; + + protected virtual void RaiseCloseToEnd() + { + var handler = CloseToEnd; + if (handler != null) handler(this, EventArgs.Empty); + } + #endregion + } +} \ No newline at end of file diff --git a/Telegram.Controls/LongListSelector/LongListSelectorEventArgs.cs b/Telegram.Controls/LongListSelector/LongListSelectorEventArgs.cs new file mode 100755 index 0000000..025326c --- /dev/null +++ b/Telegram.Controls/LongListSelector/LongListSelectorEventArgs.cs @@ -0,0 +1,75 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows.Controls; + +namespace Telegram.Controls.LongListSelector +{ + /// + /// The event args for the Link/Unlink events. + /// + public class LinkUnlinkEventArgs : EventArgs + { + /// + /// Create new LinkUnlinkEventArgs. + /// + /// The ContentPresenter. + public LinkUnlinkEventArgs(ContentPresenter cp) + { + ContentPresenter = cp; + } + + /// + /// The ContentPresenter which is displaying the item. + /// + public ContentPresenter ContentPresenter { get; private set; } + } + + /// + /// The GroupPopupOpened event args. + /// + public class GroupViewOpenedEventArgs : EventArgs + { + internal GroupViewOpenedEventArgs(ItemsControl itemsControl) + { + ItemsControl = itemsControl; + } + + /// + /// The ItemsControl containing the groups. + /// + public ItemsControl ItemsControl { get; private set; } + } + + /// + /// The GroupPopupClosing event args. + /// + public class GroupViewClosingEventArgs : EventArgs + { + internal GroupViewClosingEventArgs(ItemsControl itemsControl, object selectedGroup) + { + ItemsControl = itemsControl; + SelectedGroup = selectedGroup; + } + + /// + /// The ItemsControl containing the groups. + /// + public ItemsControl ItemsControl { get; private set; } + + /// + /// The selected group. Will be null if the back button was pressed. + /// + public object SelectedGroup { get; private set; } + + /// + /// Set this to true if the application will handle the popup closing and scrolling to the group. + /// + public bool Cancel { get; set; } + } +} diff --git a/Telegram.Controls/LongListSelector/LongListSelectorGroup.cs b/Telegram.Controls/LongListSelector/LongListSelectorGroup.cs new file mode 100755 index 0000000..6525304 --- /dev/null +++ b/Telegram.Controls/LongListSelector/LongListSelectorGroup.cs @@ -0,0 +1,302 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Media; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; +using Telegram.Controls.LongListSelector.Common; + +namespace Telegram.Controls.LongListSelector +{ + /// + /// Partial definition of LongListSelector. Includes group view code. + /// + public partial class LongListSelector : Control + { + private PhoneApplicationPage _page; + + private bool _systemTrayVisible; + private bool _applicationBarVisible; + private Border _border; + private LongListSelectorItemsControl _itemsControl; + private Popup _groupSelectorPopup; + + private static double _screenWidth = Application.Current.Host.Content.ActualWidth; + private static double _screenHeight = Application.Current.Host.Content.ActualHeight; + + private void OpenPopup() + { + SaveSystemState(true, false); + BuildPopup(); + AttachToPageEvents(); + _groupSelectorPopup.IsOpen = true; + + // This has to happen eventually anyway, and this forces the ItemsControl to + // expand it's template, populate it's items etc. + UpdateLayout(); + } + + private void popup_Opened(object sender, EventArgs e) + { + SafeRaise.Raise(GroupViewOpened, this, () => { return new GroupViewOpenedEventArgs(_itemsControl); }); + } + + /// + /// Closes the group popup. + /// + /// The selected group. + /// Should the GroupPopupClosing event be raised. + /// True if the event was not raised or if it was raised and e.Handled is false. + private bool ClosePopup(object selectedGroup, bool raiseEvent) + { + if (raiseEvent) + { + GroupViewClosingEventArgs args = null; + + SafeRaise.Raise(GroupViewClosing, this, () => { return args = new GroupViewClosingEventArgs(_itemsControl, selectedGroup); }); + + if (args != null && args.Cancel) + { + return false; + } + } + + if (_groupSelectorPopup != null) + { + RestoreSystemState(); + _groupSelectorPopup.IsOpen = false; + DetachFromPageEvents(); + _groupSelectorPopup.Child = null; + _border = null; + _itemsControl = null; + _groupSelectorPopup = null; + } + + return true; + } + + private Thickness _borderPadding; + + private void BuildPopup() + { + _groupSelectorPopup = new Popup(); + _groupSelectorPopup.Opened += popup_Opened; + + // Support the background color jumping through. Note that the + // alpha channel will be ignored, unless it is a purely transparent + // value (such as when a user uses Transparent as the background + // on the control). + SolidColorBrush background = Background as SolidColorBrush; + Color bg = (Color)Resources["PhoneBackgroundColor"]; + if (background != null + && background.Color != null + && background.Color.A > 0) + { + bg = background.Color; + } + _border = new Border + { + Background = new SolidColorBrush( + Color.FromArgb(0xa0, bg.R, bg.G, bg.B)) + }; + + // Prevents touch events from bubbling up for most handlers. + _border.ManipulationStarted += ((o, e) => e.Handled = true); + _border.ManipulationCompleted += ((o, e) => e.Handled = true); + _border.ManipulationDelta += ((o, e) => e.Handled = true); + + var gestureHandler = new EventHandler((o, e) => e.Handled = true); + _border.Tap += gestureHandler; + _border.DoubleTap += gestureHandler; + _border.Hold += gestureHandler; + _borderPadding = _border.Padding; + + _itemsControl = new LongListSelectorItemsControl(); + _itemsControl.ItemTemplate = GroupItemTemplate; + _itemsControl.ItemsPanel = GroupItemsPanel; + _itemsControl.ItemsSource = ItemsSource; + + _itemsControl.GroupSelected += itemsControl_GroupSelected; + + _groupSelectorPopup.Child = _border; + ScrollViewer sv = new ScrollViewer() { HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled }; + + _itemsControl.HorizontalAlignment = HorizontalAlignment.Center; + _itemsControl.Margin = new Thickness(0, 12, 0, 0); + _border.Child = sv; + sv.Content = _itemsControl; + + SetItemsControlSize(); + } + + private void SetItemsControlSize() + { + Rect client = GetTransformedRect(); + if (_border != null) + { + _border.RenderTransform = GetTransform(); + + _border.Width = client.Width; + _border.Height = client.Height; + } + } + + private void itemsControl_GroupSelected(object sender, LongListSelector.GroupSelectedEventArgs e) + { + if (ClosePopup(e.Group, true)) + { + ScrollToGroup(e.Group); + } + } + + private void AttachToPageEvents() + { + PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame; + if (frame != null) + { + _page = frame.Content as PhoneApplicationPage; + if (_page != null) + { + _page.BackKeyPress += page_BackKeyPress; + _page.OrientationChanged += page_OrientationChanged; + } + } + } + + private void DetachFromPageEvents() + { + if (_page != null) + { + _page.BackKeyPress -= page_BackKeyPress; + _page.OrientationChanged -= page_OrientationChanged; + _page = null; + } + } + + private void page_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e) + { + e.Cancel = false; + e.Cancel = true; + ClosePopup(null, true); + } + + void page_OrientationChanged(object sender, OrientationChangedEventArgs e) + { + SetItemsControlSize(); + } + + private static Rect GetTransformedRect() + { + bool isLandscape = IsLandscape(GetPageOrientation()); + + var frame = Application.Current.RootVisual as PhoneApplicationFrame; + if (frame != null) + { + var page = frame.Content as PhoneApplicationPage; + + //if (page != null) + //{ + // _screenHeight = page.ActualHeight; + // _screenWidth = page.ActualWidth; + + // //return new Rect(0, 0, _screenWidth, _screenHeight); + //} + //else + { + _screenWidth = Application.Current.Host.Content.ActualWidth; + _screenHeight = Application.Current.Host.Content.ActualHeight; + } + + } + else + { + _screenWidth = Application.Current.Host.Content.ActualWidth; + _screenHeight = Application.Current.Host.Content.ActualHeight; + } + + return new Rect(0, 0, + isLandscape ? _screenHeight : _screenWidth, + isLandscape ? _screenWidth : _screenHeight); + } + + private Transform GetTransform() + { + PageOrientation orientation = GetPageOrientation(); + + switch (orientation) + { + case PageOrientation.LandscapeLeft: + case PageOrientation.Landscape: + _border.Padding = new Thickness(_borderPadding.Left + 68.0, _borderPadding.Top, _borderPadding.Right, _borderPadding.Bottom); + return new CompositeTransform { Rotation = 90, TranslateX = _screenWidth }; + case PageOrientation.LandscapeRight: + _border.Padding = new Thickness(_borderPadding.Left, _borderPadding.Top, _borderPadding.Right + 68.0, _borderPadding.Bottom); + return new CompositeTransform { Rotation = -90, TranslateY = _screenHeight }; + default: + _border.Padding = _borderPadding; + return null; + } + } + + private static bool IsLandscape(PageOrientation orientation) + { + return orientation == PageOrientation.Landscape || orientation == PageOrientation.LandscapeLeft || orientation == PageOrientation.LandscapeRight; + } + + private static PageOrientation GetPageOrientation() + { + PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame; + if (frame != null) + { + PhoneApplicationPage page = frame.Content as PhoneApplicationPage; + + if (page != null) + { + return page.Orientation; + } + } + + return PageOrientation.None; + } + + private void SaveSystemState(bool newSystemTrayVisible, bool newApplicationBarVisible) + { + _systemTrayVisible = SystemTray.IsVisible; + SystemTray.IsVisible = newSystemTrayVisible; + + PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame; + if (frame != null) + { + PhoneApplicationPage page = frame.Content as PhoneApplicationPage; + if (page != null && page.ApplicationBar != null) + { + _applicationBarVisible = page.ApplicationBar.IsVisible; + page.ApplicationBar.IsVisible = newApplicationBarVisible; + } + } + } + + private void RestoreSystemState() + { + SystemTray.IsVisible = _systemTrayVisible; + + PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame; + if (frame != null) + { + PhoneApplicationPage page = frame.Content as PhoneApplicationPage; + if (page != null && page.ApplicationBar != null) + { + page.ApplicationBar.IsVisible = _applicationBarVisible; + } + } + } + } +} \ No newline at end of file diff --git a/Telegram.Controls/LongListSelector/LongListSelectorItem.cs b/Telegram.Controls/LongListSelector/LongListSelectorItem.cs new file mode 100755 index 0000000..1acf731 --- /dev/null +++ b/Telegram.Controls/LongListSelector/LongListSelectorItem.cs @@ -0,0 +1,45 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Diagnostics.CodeAnalysis; + +namespace Telegram.Controls.LongListSelector +{ + /// + /// Holds information about an item for use in the LongListSelector. + /// + public class LongListSelectorItem + { + /// + /// Gets or sets the item type. + /// + public LongListSelectorItemType ItemType + { + get; + set; + } + + /// + /// Gets or sets the associated group for the item. + /// + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Assists in debugging.")] + public object Group + { + get; + set; + } + + /// + /// Gets or sets the underlying item instance. + /// + public object Item + { + get; + set; + } + } +} diff --git a/Telegram.Controls/LongListSelector/LongListSelectorItemType.cs b/Telegram.Controls/LongListSelector/LongListSelectorItemType.cs new file mode 100755 index 0000000..27b3321 --- /dev/null +++ b/Telegram.Controls/LongListSelector/LongListSelectorItemType.cs @@ -0,0 +1,45 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Controls.LongListSelector +{ + /// + /// Describes different items. + /// + public enum LongListSelectorItemType + { + /// + /// Indicates an unknown item type. + /// + Unknown, + + /// + /// Represents a standard list item. + /// + Item, + + /// + /// Represents a group header. + /// + GroupHeader, + + /// + /// Represents a group footer. + /// + GroupFooter, + + /// + /// Represents a list header. + /// + ListHeader, + + /// + /// Represents a list footer. + /// + ListFooter, + } +} diff --git a/Telegram.Controls/LongListSelector/LongListSelectorItemsControl.cs b/Telegram.Controls/LongListSelector/LongListSelectorItemsControl.cs new file mode 100755 index 0000000..828e0f8 --- /dev/null +++ b/Telegram.Controls/LongListSelector/LongListSelectorItemsControl.cs @@ -0,0 +1,64 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Controls; + +namespace Telegram.Controls.LongListSelector +{ + /// + /// Partial definition of LongListSelector. Includes ItemsControl subclass. + /// + public partial class LongListSelector : Control + { + private class GroupSelectedEventArgs : EventArgs + { + public GroupSelectedEventArgs(object group) + { + Group = group; + } + + public object Group { get; private set; } + } + + private delegate void GroupSelectedEventHandler(object sender, GroupSelectedEventArgs e); + + private class LongListSelectorItemsControl : ItemsControl + { + public event GroupSelectedEventHandler GroupSelected; + + protected override void PrepareContainerForItemOverride(DependencyObject element, object item) + { + base.PrepareContainerForItemOverride(element, item); + ((UIElement)element).Tap += LongListSelectorItemsControl_Tap; + } + + protected override void ClearContainerForItemOverride(DependencyObject element, object item) + { + base.ClearContainerForItemOverride(element, item); + + ((UIElement)element).Tap -= LongListSelectorItemsControl_Tap; + } + + private void LongListSelectorItemsControl_Tap(object sender, System.Windows.Input.GestureEventArgs e) + { + ContentPresenter cc = sender as ContentPresenter; + if (cc != null) + { + var handler = GroupSelected; + if (handler != null) + { + GroupSelectedEventArgs args = new GroupSelectedEventArgs(cc.Content); + handler(this, args); + } + + } + } + } + } +} diff --git a/Telegram.Controls/LongListSelector/TemplatedListBox.cs b/Telegram.Controls/LongListSelector/TemplatedListBox.cs new file mode 100755 index 0000000..5a88567 --- /dev/null +++ b/Telegram.Controls/LongListSelector/TemplatedListBox.cs @@ -0,0 +1,130 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Controls; +using Telegram.Controls.LongListSelector.Common; + +namespace Telegram.Controls.LongListSelector +{ + /// + /// Represents a ListBox with item-specific templates. + /// + /// Preview + public class TemplatedListBox : ListBox + { + /// + /// Gets or sets the list header template. + /// + public DataTemplate ListHeaderTemplate { get; set; } + + /// + /// Gets or sets the list footer template. + /// + public DataTemplate ListFooterTemplate { get; set; } + + /// + /// Gets or sets the group header template. + /// + public DataTemplate GroupHeaderTemplate { get; set; } + + /// + /// Gets or sets the footer template. + /// + public DataTemplate GroupFooterTemplate { get; set; } + + /// + /// Occurs when an item is about to be "realized". + /// + public event EventHandler Link; + + /// + /// Occurs when an item is about to be "un-realized". + /// + public event EventHandler Unlink; + + /// + /// Creates or identifies the element used to display a specified item. + /// + /// Returns the new container. + protected override DependencyObject GetContainerForItemOverride() + { + return new TemplatedListBoxItem(); + } + + /// + /// Prepares the specified element to display the specified item. + /// + /// Element used to display the specified item. + /// Specified item. + protected override void PrepareContainerForItemOverride(DependencyObject element, object item) + { + base.PrepareContainerForItemOverride(element, item); + + DataTemplate template = null; + LongListSelectorItem itemTuple = item as LongListSelectorItem; + + if (itemTuple != null) + { + switch (itemTuple.ItemType) + { + case LongListSelectorItemType.ListHeader: + template = this.ListHeaderTemplate; + break; + case LongListSelectorItemType.ListFooter: + template = this.ListFooterTemplate; + break; + case LongListSelectorItemType.GroupHeader: + template = this.GroupHeaderTemplate; + break; + case LongListSelectorItemType.GroupFooter: + template = this.GroupFooterTemplate; + break; + case LongListSelectorItemType.Item: + template = this.ItemTemplate; + break; + } + + TemplatedListBoxItem listBoxItem = (TemplatedListBoxItem)element; + listBoxItem.Content = itemTuple.Item; + listBoxItem.Tuple = itemTuple; + listBoxItem.ContentTemplate = template; + + var result = listBoxItem.GetFirstLogicalChildByType(true); + var handler = Link; + if (result != null && handler != null) + { + handler(this, new LinkUnlinkEventArgs(result)); + } + } + } + + /// + /// When overridden in a derived class, undoes the effects of the + /// PrepareContainerForItemOverride method. + /// + /// The container element. + /// The item. + protected override void ClearContainerForItemOverride(DependencyObject element, object item) + { + LongListSelectorItem itemTuple = item as LongListSelectorItem; + + if (itemTuple != null) + { + var result = ((FrameworkElement)element).GetFirstLogicalChildByType(true); + var handler = Unlink; + if (result != null && handler != null) + { + handler(this, new LinkUnlinkEventArgs(result)); + } + } + + base.ClearContainerForItemOverride(element, item); + } + } +} diff --git a/Telegram.Controls/LongListSelector/TemplatedListBoxItem.cs b/Telegram.Controls/LongListSelector/TemplatedListBoxItem.cs new file mode 100755 index 0000000..006f6f5 --- /dev/null +++ b/Telegram.Controls/LongListSelector/TemplatedListBoxItem.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows.Controls; + +namespace Telegram.Controls.LongListSelector +{ + /// + /// Represents an item within a + /// + /// Preview + internal class TemplatedListBoxItem : ListBoxItem + { + public LongListSelectorItem Tuple { get; set; } + } +} diff --git a/Telegram.Controls/MultiTemplateItemsControl.cs b/Telegram.Controls/MultiTemplateItemsControl.cs new file mode 100755 index 0000000..a9e4af6 --- /dev/null +++ b/Telegram.Controls/MultiTemplateItemsControl.cs @@ -0,0 +1,50 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Controls; + +namespace Telegram.Controls +{ + public interface ITemplateSelector + { + DataTemplate SelectTemplate(object item, DependencyObject container); + } + + public class MultiTemplateItemsControl : ItemsControl + { + public static readonly DependencyProperty TemplateSelectorProperty = + DependencyProperty.Register("TemplateSelector", + typeof(ITemplateSelector), typeof(MultiTemplateItemsControl), + new PropertyMetadata(OnTemplateChanged)); + + public ITemplateSelector TemplateSelector + { + get { return (ITemplateSelector)GetValue(TemplateSelectorProperty); } + set { SetValue(TemplateSelectorProperty, value); } + } + + private static void OnTemplateChanged(DependencyObject d, + DependencyPropertyChangedEventArgs e) + { + + } + + protected override void PrepareContainerForItemOverride( + DependencyObject element, object item) + { + base.PrepareContainerForItemOverride(element, item); + + var content = element as ContentPresenter; + + if (content != null) + { + content.ContentTemplate = TemplateSelector.SelectTemplate(item, this); + } + } + } +} diff --git a/Telegram.Controls/MultiTemplateLazyListBox.cs b/Telegram.Controls/MultiTemplateLazyListBox.cs new file mode 100755 index 0000000..ac4354a --- /dev/null +++ b/Telegram.Controls/MultiTemplateLazyListBox.cs @@ -0,0 +1,46 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Controls; + +namespace Telegram.Controls +{ + public class MultiTemplateLazyListBox : LazyListBox + { + + public static readonly DependencyProperty TemplateSelectorProperty = + DependencyProperty.Register("TemplateSelector", + typeof(ITemplateSelector), typeof(MultiTemplateLazyListBox), + new PropertyMetadata(OnTemplateChanged)); + + public ITemplateSelector TemplateSelector + { + get { return (ITemplateSelector)GetValue(TemplateSelectorProperty); } + set { SetValue(TemplateSelectorProperty, value); } + } + + private static void OnTemplateChanged(DependencyObject d, + DependencyPropertyChangedEventArgs e) + { + + } + + protected override void PrepareContainerForItemOverride( + DependencyObject element, object item) + { + base.PrepareContainerForItemOverride(element, item); + + var listBoxItem = element as ListBoxItem; + + if (listBoxItem != null) + { + listBoxItem.ContentTemplate = TemplateSelector.SelectTemplate(item, this); + } + } + } +} diff --git a/Telegram.Controls/Notifications/DialogService.cs b/Telegram.Controls/Notifications/DialogService.cs new file mode 100755 index 0000000..f1be007 --- /dev/null +++ b/Telegram.Controls/Notifications/DialogService.cs @@ -0,0 +1,556 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Markup; +using System.Windows.Media; +using System.Windows.Media.Animation; +using Coding4Fun.Toolkit.Controls; +using Coding4Fun.Toolkit.Controls.Binding; +using Coding4Fun.Toolkit.Controls.Common; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; + +namespace Telegram.Controls.Notifications +{ + // this code has been modified from the orginal code + // from Kevin Marshall's post + // http://blogs.claritycon.com/kevinmarshall/2010/10/13/wp7-page-transitions-sample/ + + public class DialogService + { + public enum AnimationTypes + { + Slide, + SlideHorizontal, + Swivel, + SwivelHorizontal, + Fade + } + + private const string SlideUpStoryboard = @" + + + + + + + + + + + + + + + "; + + private const string SlideHorizontalInStoryboard = @" + + + + + + + + + + + + + + + "; + + private const string SlideHorizontalOutStoryboard = @" + + + + + + + + + + + + + + + "; + + private const string SlideDownStoryboard = @" + + + + + + + + + + + + + + + "; + + private const string SwivelInStoryboard = + @" + + + + + + + + + + + + + "; + + private const string SwivelOutStoryboard = + @" + + + + + + + + + + + + + + "; + + private const string FadeInStoryboard = + @" + + "; + + private const string FadeOutStoryboard = + @" + + "; + + private Panel _popupContainer; + private Frame _rootFrame; + private PhoneApplicationPage _page; + private Grid _childPanel; + private Grid _overlay; + + public bool IsOverlayApplied + { + get { return _isOverlayApplied; } + set { _isOverlayApplied = value; } + } + private bool _isOverlayApplied = true; + + public FrameworkElement Child { get; set; } + public AnimationTypes AnimationType { get; set; } + public TimeSpan MainBodyDelay { get; set; } + + public double VerticalOffset { get; set; } + internal double ControlVerticalOffset { get; set; } + public bool BackButtonPressed { get; set; } + + public Brush BackgroundBrush { get; set; } + + internal bool IsOpen { get; set; } + protected internal bool IsBackKeyOverride { get; set; } + + public event EventHandler Closed; + public event EventHandler Opened; + + // set this to prevent the dialog service from closing on back click + public bool HasPopup { get; set; } + + internal PhoneApplicationPage Page + { + get { return _page ?? (_page = RootFrame.GetFirstLogicalChildByType(false)); } + } + + internal Frame RootFrame + { + get { return _rootFrame ?? (_rootFrame = ApplicationSpace.RootFrame); } + } + + internal Panel PopupContainer + { + get + { + if (_popupContainer == null) + { + //var popups = RootFrame.GetLogicalChildrenByType(false).Where(x => x.IsOpen); + + //if (popups.Any()) + //{ + // for (var i = 0; i < popups.Count(); i++) + // { + // var child = popups.ElementAt(i).Child as Panel; + + // if (child == null) + // continue; + + // _popupContainer = child; + // break; + // } + //} + //else + { + var presenters = RootFrame.GetLogicalChildrenByType(false); + + for (var i = 0; i < presenters.Count(); i++) + { + var panels = presenters.ElementAt(i).GetLogicalChildrenByType(false); + + if (!panels.Any()) + continue; + + _popupContainer = panels.First(); + break; + } + } + + } + + return _popupContainer; + } + } + + public DialogService() + { + AnimationType = AnimationTypes.Slide; + + BackButtonPressed = false; + } + + bool _deferredShowToLoaded; + private void InitializePopup() + { + // Add overlay which is the size of RootFrame + _childPanel = CreateGrid(); + + if (IsOverlayApplied) + { + _overlay = CreateGrid(); + PreventScrollBinding.SetIsEnabled(_overlay, true); + } + + ApplyOverlayBackground(); + + // Initialize popup to draw the context menu over all controls + if (PopupContainer != null) + { + if (_overlay != null) + PopupContainer.Children.Add(_overlay); + + PopupContainer.Children.Add(_childPanel); + _childPanel.Children.Add(Child); + } + else + { + _deferredShowToLoaded = true; + RootFrame.Loaded += RootFrameDeferredShowLoaded; + } + } + + internal void ApplyOverlayBackground() + { + if (IsOverlayApplied && BackgroundBrush != null) + _overlay.Background = BackgroundBrush; + } + + private Grid CreateGrid() + { + var grid = new Grid { Name = Guid.NewGuid().ToString() }; + + Grid.SetColumnSpan(grid, int.MaxValue); + Grid.SetRowSpan(grid, int.MaxValue); + + grid.Opacity = 0; + + CalculateVerticalOffset(grid); + + return grid; + } + + internal void CalculateVerticalOffset() + { + CalculateVerticalOffset(_childPanel); + } + + internal void CalculateVerticalOffset(Panel panel) + { + if (panel == null) + return; + + var sysTrayVerticalOffset = 0; + + if (SystemTray.IsVisible && SystemTray.Opacity < 1 && SystemTray.Opacity > 0) + { + sysTrayVerticalOffset += 32; + } + + panel.Margin = new Thickness(0, VerticalOffset + sysTrayVerticalOffset + ControlVerticalOffset, 0, 0); + } + + void RootFrameDeferredShowLoaded(object sender, RoutedEventArgs e) + { + RootFrame.Loaded -= RootFrameDeferredShowLoaded; + _deferredShowToLoaded = false; + + Show(); + } + + protected internal void SetAlignmentsOnOverlay(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment) + { + if (_childPanel != null) + { + _childPanel.HorizontalAlignment = horizontalAlignment; + _childPanel.VerticalAlignment = verticalAlignment; + } + } + + private static readonly object Lockobj = new object(); + /// + /// Shows the context menu. + /// + public void Show() + { + lock (Lockobj) + { + Page.BackKeyPress -= OnBackKeyPress; + + IsOpen = true; + + InitializePopup(); + + if (_deferredShowToLoaded) + return; + + if (!IsBackKeyOverride) + Page.BackKeyPress += OnBackKeyPress; + + Page.NavigationService.Navigated += OnNavigated; + + RunShowStoryboard(_overlay, AnimationTypes.Fade); + RunShowStoryboard(_childPanel, AnimationType, MainBodyDelay); + + if (Opened != null) + Opened.Invoke(this, null); + + } + } + + private void RunShowStoryboard(UIElement grid, AnimationTypes animation) + { + RunShowStoryboard(grid, animation, TimeSpan.MinValue); + } + + private void RunShowStoryboard(UIElement grid, AnimationTypes animation, TimeSpan delay) + { + if (grid == null) + return; + + Storyboard storyboard; + switch (animation) + { + case AnimationTypes.SlideHorizontal: + storyboard = XamlReader.Load(SlideHorizontalInStoryboard) as Storyboard; + grid.RenderTransform = new TranslateTransform(); + break; + + case AnimationTypes.Slide: + storyboard = XamlReader.Load(SlideUpStoryboard) as Storyboard; + grid.RenderTransform = new TranslateTransform(); + break; + case AnimationTypes.Fade: + storyboard = XamlReader.Load(FadeInStoryboard) as Storyboard; + break; + case AnimationTypes.Swivel: + case AnimationTypes.SwivelHorizontal: + default: + storyboard = XamlReader.Load(SwivelInStoryboard) as Storyboard; + grid.Projection = new PlaneProjection(); + break; + } + + if (storyboard != null) + { + foreach (var storyboardAnimation in storyboard.Children) + { + if (!(storyboardAnimation is DoubleAnimationUsingKeyFrames)) + continue; + + var doubleKey = storyboardAnimation as DoubleAnimationUsingKeyFrames; + + foreach (var frame in doubleKey.KeyFrames) + { + frame.KeyTime = KeyTime.FromTimeSpan(frame.KeyTime.TimeSpan.Add(delay)); + } + } + + Page.Dispatcher.BeginInvoke(() => + { + foreach (var t in storyboard.Children) + Storyboard.SetTarget(t, grid); + + storyboard.Begin(); + }); + } + } + + void OnNavigated(object sender, System.Windows.Navigation.NavigationEventArgs e) + { + if (e.IsNavigationInitiator) //current app initialized navigation? + Hide(); + } + + public void Hide() + { + if (!IsOpen) + return; + + if (Page != null) + { + Page.BackKeyPress -= OnBackKeyPress; + Page.NavigationService.Navigated -= OnNavigated; + + _page = null; + } + + RunHideStoryboard(_overlay, AnimationTypes.Fade); + RunHideStoryboard(_childPanel, AnimationType); + } + + void RunHideStoryboard(Grid grid, AnimationTypes animation) + { + if (grid == null) + return; + + Storyboard storyboard; + + switch (animation) + { + case AnimationTypes.SlideHorizontal: + storyboard = XamlReader.Load(SlideHorizontalOutStoryboard) as Storyboard; + break; + case AnimationTypes.Slide: + storyboard = XamlReader.Load(SlideDownStoryboard) as Storyboard; + break; + case AnimationTypes.Fade: + storyboard = XamlReader.Load(FadeOutStoryboard) as Storyboard; + break; + case AnimationTypes.Swivel: + case AnimationTypes.SwivelHorizontal: + default: + storyboard = XamlReader.Load(SwivelOutStoryboard) as Storyboard; + break; + } + + try + { + if (storyboard != null) + { + storyboard.Completed += HideStoryboardCompleted; + + foreach (var t in storyboard.Children) + Storyboard.SetTarget(t, grid); + + storyboard.Begin(); + } + } + catch (Exception) + { + // chances are user nav'ed away + // attempting to be extremely robust here + // if this fails, go straight to complete + // and attempt to remove it from the visual tree + HideStoryboardCompleted(null, null); + } + } + + void HideStoryboardCompleted(object sender, EventArgs e) + { + IsOpen = false; + + try + { + if (PopupContainer != null && PopupContainer.Children != null) + { + if (_overlay != null) + PopupContainer.Children.Remove(_overlay); + + PopupContainer.Children.Remove(_childPanel); + } + + _childPanel.Children.Clear(); + } + catch + { + // chances are user nav'ed away + // attempting to be extremely robust here + // if this fails, go straight to complete + // and attempt to remove it from the visual tree + } + + try + { + if (Closed != null) + Closed(this, null); + + } + catch + { + // chances are user nav'ed away + // attempting to be extremely robust here + // if this fails, go straight to complete + // and attempt to remove it from the visual tree + } + } + + public void OnBackKeyPress(object sender, CancelEventArgs e) + { + if (HasPopup) + { + e.Cancel = true; + return; + } + + if (IsOpen) + { + e.Cancel = true; + BackButtonPressed = true; + Hide(); + } + } + } +} diff --git a/Telegram.Controls/Notifications/PopUp.cs b/Telegram.Controls/Notifications/PopUp.cs new file mode 100755 index 0000000..141b628 --- /dev/null +++ b/Telegram.Controls/Notifications/PopUp.cs @@ -0,0 +1,250 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using Clarity.Phone.Extensions; +using Coding4Fun.Toolkit.Controls; +using Coding4Fun.Toolkit.Controls.Common; +using Microsoft.Phone.Controls; + +namespace Telegram.Controls.Notifications +{ + public abstract class PopUp : Control + { + internal DialogService PopUpService; + private PhoneApplicationPage _startingPage; + private bool _alreadyFired; + + public event EventHandler> Completed; + public event EventHandler Opened; + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + if (PopUpService != null) + { + // template hasn't been applied yet + // overlay is null until now + PopUpService.BackgroundBrush = Overlay; + + PopUpService.ApplyOverlayBackground(); + PopUpService.SetAlignmentsOnOverlay(HorizontalAlignment, VerticalAlignment); + } + } + + public virtual void Show() + { + if (IsOpen) + return; + + if (_alreadyFired) + throw new InvalidOperationException("Invalid control state, do not reuse object after calling Show()"); + + if (PopUpService == null) + { + PopUpService = new DialogService + { + AnimationType = AnimationType, + Child = this, + IsBackKeyOverride = IsBackKeyOverride, + IsOverlayApplied = IsOverlayApplied, + MainBodyDelay = MainBodyDelay, + }; + } + + // this will happen if the user comes in OnNavigate or + // something where the DOM hasn't been created yet. + if (PopUpService.Page == null) + { + Dispatcher.BeginInvoke(Show); + + return; + } + + if (IsCalculateFrameVerticalOffset) + { + PopUpService.ControlVerticalOffset = -FrameTransform; + } + + PopUpService.Closed -= PopUpClosed; + PopUpService.Opened -= PopUpOpened; + + PopUpService.Closed += PopUpClosed; + PopUpService.Opened += PopUpOpened; + + + if (!IsAppBarVisible && PopUpService.Page.ApplicationBar != null && PopUpService.Page.ApplicationBar.IsVisible) + { + PopUpService.Page.ApplicationBar.IsVisible = false; + + IsSetAppBarVisibiilty = true; + } + + _startingPage = PopUpService.Page; + + PopUpService.Show(); + } + + + + protected virtual TPopUpResult GetOnClosedValue() + { + return default(TPopUpResult); + } + + public void Hide() + { + PopUpClosed(this, null); + } + + + + #region Control Events + void PopUpOpened(object sender, EventArgs e) + { + if (Opened != null) + Opened(sender, e); + } + + void PopUpClosed(object sender, EventArgs e) + { + if (!_alreadyFired) + { + OnCompleted(new PopUpEventArgs { PopUpResult = GetOnClosedValue() }); + return; + } + + ResetWorldAndDestroyPopUp(); + } + + public virtual void OnCompleted(PopUpEventArgs result) + { + _alreadyFired = true; + + if (Completed != null) + Completed(this, result); + + if (PopUpService != null) + PopUpService.Hide(); + + if (PopUpService != null && PopUpService.BackButtonPressed) + ResetWorldAndDestroyPopUp(); + } + #endregion + + #region helper methods + private void ResetWorldAndDestroyPopUp() + { + if (PopUpService != null) + { + if (!IsAppBarVisible && IsSetAppBarVisibiilty) + { + _startingPage.ApplicationBar.IsVisible = IsSetAppBarVisibiilty; + } + + _startingPage = null; + + PopUpService.Child = null; + PopUpService = null; + } + } + #endregion + + #region Dependency Property Callbacks + static void OnFrameTransformPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) + { + var sender = source as PopUp; + + if (sender == null || sender.PopUpService == null) + return; + + if (!sender.IsCalculateFrameVerticalOffset) + return; + + sender.PopUpService.ControlVerticalOffset = -sender.FrameTransform; + sender.PopUpService.CalculateVerticalOffset(); + } + #endregion + + #region Dependency Properties / Properties + public bool IsOpen { get { return PopUpService != null && PopUpService.IsOpen; } } + public bool IsAppBarVisible { get; set; } + + // adjust for SIP + private bool _isCalculateFrameVerticalOffset; + + protected bool IsCalculateFrameVerticalOffset + { + get { return _isCalculateFrameVerticalOffset; } + set + { + _isCalculateFrameVerticalOffset = value; + + if (_isCalculateFrameVerticalOffset) + { + var bind = new System.Windows.Data.Binding("Y"); + + var rootFrame = ApplicationSpace.RootFrame; + + if (rootFrame != null) + { + var transGroup = rootFrame.RenderTransform as TransformGroup; + + if (transGroup != null) + { + bind.Source = transGroup.Children.FirstOrDefault(t => t is TranslateTransform); + SetBinding(FrameTransformProperty, bind); + } + } + } + } + } + + public bool IsOverlayApplied + { + get { return _isOverlayApplied; } + set { _isOverlayApplied = value; } + } + private bool _isOverlayApplied = true; + + internal bool IsSetAppBarVisibiilty { get; set; } + internal TimeSpan MainBodyDelay { get; set; } + + protected internal bool IsBackKeyOverride { get; set; } + protected DialogService.AnimationTypes AnimationType { get; set; } + + double FrameTransform + { + get { return (double)GetValue(FrameTransformProperty); } + set { SetValue(FrameTransformProperty, value); } + } + + static readonly DependencyProperty FrameTransformProperty = DependencyProperty.Register( + "FrameTransform", + typeof(double), + typeof(PopUp), + new PropertyMetadata(0.0, OnFrameTransformPropertyChanged)); + + public Brush Overlay + { + get { return (Brush)GetValue(OverlayProperty); } + set { SetValue(OverlayProperty, value); } + } + + // Using a DependencyProperty as the backing store for Overlay. This enables animation, styling, binding, etc... + public static readonly DependencyProperty OverlayProperty = + DependencyProperty.Register("Overlay", typeof(Brush), typeof(PopUp), new PropertyMetadata(default(SolidColorBrush))); + #endregion + } +} diff --git a/Telegram.Controls/Notifications/ToastPrompt.cs b/Telegram.Controls/Notifications/ToastPrompt.cs new file mode 100755 index 0000000..69f4e7e --- /dev/null +++ b/Telegram.Controls/Notifications/ToastPrompt.cs @@ -0,0 +1,307 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using Clarity.Phone.Extensions; +using Coding4Fun.Toolkit.Controls; +using Coding4Fun.Toolkit.Controls.Binding; +using Coding4Fun.Toolkit.Controls.Common; + +namespace Telegram.Controls.Notifications +{ + public class ToastPrompt : PopUp, IDisposable, IImageSourceFull + { + protected Image ToastImage; + private const string ToastImageName = "ToastImage"; + private Timer _timer; + + private TranslateTransform _translate; + + public ToastPrompt() + { + DefaultStyleKey = typeof(ToastPrompt); + + IsAppBarVisible = true; + IsBackKeyOverride = true; + IsCalculateFrameVerticalOffset = true; + + IsOverlayApplied = false; + + AnimationType = DialogService.AnimationTypes.Swivel; + //AnimationType = DialogService.AnimationTypes.SlideHorizontal; + + ManipulationStarted += ToastPromptManipulationStarted; + ManipulationDelta += ToastPromptManipulationDelta; + ManipulationCompleted += ToastPromptManipulationCompleted; + + Opened += ToastPromptOpened; + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + SetRenderTransform(); + + ToastImage = GetTemplateChild(ToastImageName) as Image; + + if (ToastImage != null && ImageSource != null) + { + ToastImage.Source = ImageSource; + SetImageVisibility(ImageSource); + } + + SetTextOrientation(TextWrapping); + } + + public override void Show() + { + if (!IsTimerEnabled) + return; + + base.Show(); + + SetRenderTransform(); + PreventScrollBinding.SetIsEnabled(this, true); + } + + public void Dispose() + { + if (_timer != null) + { + _timer.Dispose(); + _timer = null; + } + } + + #region Control Events + void ToastPromptManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + PauseTimer(); + } + + void ToastPromptManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + _translate.X += e.DeltaManipulation.Translation.X; + + if (_translate.X < 0) + _translate.X = 0; + } + + void ToastPromptManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + if (e.TotalManipulation.Translation.X > 200 || e.FinalVelocities.LinearVelocity.X > 1000) + { + OnCompleted(new PopUpEventArgs { PopUpResult = PopUpResult.UserDismissed }); + } + else if (e.TotalManipulation.Translation.X < 20) + { + OnCompleted(new PopUpEventArgs { PopUpResult = PopUpResult.Ok }); + } + else + { + _translate.X = 0; + StartTimer(); + } + } + + void ToastPromptOpened(object sender, EventArgs e) + { + StartTimer(); + } + + void TimerTick(object state) + { + Dispatcher.BeginInvoke(() => OnCompleted(new PopUpEventArgs { PopUpResult = PopUpResult.NoResponse })); + } + + public override void OnCompleted(PopUpEventArgs result) + { + if (PopUpService != null && result.PopUpResult == PopUpResult.UserDismissed) + { + PopUpService.AnimationType = DialogService.AnimationTypes.SlideHorizontal; + } + + PreventScrollBinding.SetIsEnabled(this, false); + + PauseTimer(); + Dispose(); + + + base.OnCompleted(result); + } + #endregion + + #region helper methods + private void SetImageVisibility(ImageSource source) + { + ToastImage.Visibility = (source == null) ? Visibility.Collapsed : Visibility.Visible; + } + + private void SetTextOrientation(TextWrapping value) + { + if (value == TextWrapping.Wrap) + { + TextOrientation = Orientation.Vertical; + } + } + + private void StartTimer() + { + if (_timer == null) + _timer = new Timer(TimerTick); + + _timer.Change(TimeSpan.FromMilliseconds(MillisecondsUntilHidden), TimeSpan.FromMilliseconds(-1)); + } + + private void PauseTimer() + { + if (_timer != null) + _timer.Change(TimeSpan.FromMilliseconds(-1), TimeSpan.FromMilliseconds(-1)); + } + + private void SetRenderTransform() + { + _translate = new TranslateTransform(); + RenderTransform = _translate; + } + #endregion + + #region Dependency Property Callbacks + private static void OnTextWrapping(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + var sender = o as ToastPrompt; + + if (sender == null || sender.ToastImage == null) + return; + + sender.SetTextOrientation((TextWrapping)e.NewValue); + } + + private static void OnImageSource(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + var sender = o as ToastPrompt; + + if (sender == null || sender.ToastImage == null) + return; + + sender.SetImageVisibility(e.NewValue as ImageSource); + } + #endregion + + #region Dependency Properties / Properties + + public int MillisecondsUntilHidden + { + get { return (int)GetValue(MillisecondsUntilHiddenProperty); } + set { SetValue(MillisecondsUntilHiddenProperty, value); } + } + + // Using a DependencyProperty as the backing store for MillisecondsUntilHidden. This enables animation, styling, binding, etc... + public static readonly DependencyProperty MillisecondsUntilHiddenProperty = + DependencyProperty.Register("MillisecondsUntilHidden", typeof(int), typeof(ToastPrompt), new PropertyMetadata(4000)); + + public bool IsTimerEnabled + { + get { return (bool)GetValue(IsTimerEnabledProperty); } + set { SetValue(IsTimerEnabledProperty, value); } + } + + // Using a DependencyProperty as the backing store for IsTimerEnabled. This enables animation, styling, binding, etc... + public static readonly DependencyProperty IsTimerEnabledProperty = + DependencyProperty.Register("IsTimerEnabled", typeof(bool), typeof(ToastPrompt), new PropertyMetadata(true)); + + public string Title + { + get { return (string)GetValue(TitleProperty); } + set { SetValue(TitleProperty, value); } + } + + // Using a DependencyProperty as the backing store for Title. This enables animation, styling, binding, etc... + public static readonly DependencyProperty TitleProperty = + DependencyProperty.Register("Title", typeof(string), typeof(ToastPrompt), new PropertyMetadata("")); + + public string Message + { + get { return (string)GetValue(MessageProperty); } + set { SetValue(MessageProperty, value); } + } + + // Using a DependencyProperty as the backing store for Message. This enables animation, styling, binding, etc... + public static readonly DependencyProperty MessageProperty = + DependencyProperty.Register("Message", typeof(string), typeof(ToastPrompt), new PropertyMetadata("")); + + public ImageSource ImageSource + { + get { return (ImageSource)GetValue(ImageSourceProperty); } + set { SetValue(ImageSourceProperty, value); } + } + + // Using a DependencyProperty as the backing store for ImageSource. This enables animation, styling, binding, etc... + public static readonly DependencyProperty ImageSourceProperty = + DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(ToastPrompt), + new PropertyMetadata(OnImageSource)); + + public Stretch Stretch + { + get { return (Stretch)GetValue(StretchProperty); } + set { SetValue(StretchProperty, value); } + } + + // Using a DependencyProperty as the backing store for Stretch. This enables animation, styling, binding, etc... + public static readonly DependencyProperty StretchProperty = + DependencyProperty.Register("Stretch", typeof(Stretch), typeof(ToastPrompt), + new PropertyMetadata(Stretch.None)); + + public double ImageWidth + { + get { return (double)GetValue(ImageWidthProperty); } + set { SetValue(ImageWidthProperty, value); } + } + + // Using a DependencyProperty as the backing store for ImageWidth. This enables animation, styling, binding, etc... + public static readonly DependencyProperty ImageWidthProperty = + DependencyProperty.Register("ImageWidth", typeof(double), typeof(ToastPrompt), new PropertyMetadata(double.NaN)); + + public double ImageHeight + { + get { return (double)GetValue(ImageHeightProperty); } + set { SetValue(ImageHeightProperty, value); } + } + + // Using a DependencyProperty as the backing store for ImageWidth. This enables animation, styling, binding, etc... + public static readonly DependencyProperty ImageHeightProperty = + DependencyProperty.Register("ImageHeight", typeof(double), typeof(ToastPrompt), new PropertyMetadata(double.NaN)); + + public Orientation TextOrientation + { + get { return (Orientation)GetValue(TextOrientationProperty); } + set { SetValue(TextOrientationProperty, value); } + } + + // Using a DependencyProperty as the backing store for TextOrientation. This enables animation, styling, binding, etc... + public static readonly DependencyProperty TextOrientationProperty = + DependencyProperty.Register("TextOrientation", typeof(Orientation), typeof(ToastPrompt), new PropertyMetadata(Orientation.Horizontal)); + + public TextWrapping TextWrapping + { + get { return (TextWrapping)GetValue(TextWrappingProperty); } + set { SetValue(TextWrappingProperty, value); } + } + + // Using a DependencyProperty as the backing store for TextWrapping. This enables animation, styling, binding, etc... + public static readonly DependencyProperty TextWrappingProperty = + DependencyProperty.Register("TextWrapping", typeof(TextWrapping), typeof(ToastPrompt), new PropertyMetadata(TextWrapping.NoWrap, OnTextWrapping)); + + #endregion + } +} diff --git a/Telegram.Controls/Profiling/ApplicationSpace.cs b/Telegram.Controls/Profiling/ApplicationSpace.cs new file mode 100755 index 0000000..dd958f7 --- /dev/null +++ b/Telegram.Controls/Profiling/ApplicationSpace.cs @@ -0,0 +1,50 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Threading; + +namespace Telegram.Controls.Profiling +{ + public static class ApplicationSpace + { + public static Frame RootFrame + { + get + { + return Application.Current.RootVisual as Frame; + } + } + + public static bool IsDesignMode + { + get + { + return DesignerProperties.IsInDesignTool; + } + } + + public static Dispatcher CurrentDispatcher + { + get + { + return Deployment.Current.Dispatcher; + } + } + + public static int ScaleFactor() + { + return 100; + } + } +} diff --git a/Telegram.Controls/Profiling/MemoryCounter.cs b/Telegram.Controls/Profiling/MemoryCounter.cs new file mode 100755 index 0000000..d2a05af --- /dev/null +++ b/Telegram.Controls/Profiling/MemoryCounter.cs @@ -0,0 +1,152 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Navigation; +using System.Windows.Threading; +using Microsoft.Phone.Info; + +namespace Telegram.Controls.Profiling +{ + public class MemoryCounter : Control, IDisposable + { + private const float ByteToMega = 1024 * 1024; + private DispatcherTimer _timer; + + private bool _threwException; + + public MemoryCounter() + { + DefaultStyleKey = typeof(MemoryCounter); + DataContext = this; + + Loaded += ControlLoaded; + Unloaded += ControlUnloaded; + } + + public int UpdateInterval + { + get { return (int)GetValue(UpdateIntervalProperty); } + set { SetValue(UpdateIntervalProperty, value); } + } + + public static readonly DependencyProperty UpdateIntervalProperty = + DependencyProperty.Register("UpdateInterval", typeof(int), typeof(MemoryCounter), new PropertyMetadata(1000, OnUpdateIntervalChanged)); + + private static void OnUpdateIntervalChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) + { + + var sender = ((MemoryCounter)o); + + if (sender != null && sender._timer != null) + sender._timer.Interval = TimeSpan.FromMilliseconds((int)e.NewValue); + } + + public string CurrentMemory + { + get { return (string)GetValue(CurrentMemoryProperty); } + set { SetValue(CurrentMemoryProperty, value); } + } + + public static readonly DependencyProperty CurrentMemoryProperty = + DependencyProperty.Register("CurrentMemory", typeof(string), typeof(MemoryCounter), new PropertyMetadata("0")); + + public string PeakMemory + { + get { return (string)GetValue(PeakMemoryProperty); } + set { SetValue(PeakMemoryProperty, value); } + } + + public static readonly DependencyProperty PeakMemoryProperty = + DependencyProperty.Register("PeakMemory", typeof(string), typeof(MemoryCounter), new PropertyMetadata("0")); + + void TimerTick(object sender, EventArgs e) + { + if ( _threwException) + { + StopAndHide(); + } + + try + { + CurrentMemory = ((DeviceStatus.ApplicationCurrentMemoryUsage) / ByteToMega).ToString("#.00"); + PeakMemory = ((DeviceStatus.ApplicationPeakMemoryUsage) / ByteToMega).ToString("#.00"); + + Debug.WriteLine("CALLING MEM: " + DateTime.Now); + } + catch (Exception) + { + _threwException = true; + _timer.Stop(); + } + } + + private void StopAndHide() + { + if (_timer != null) + _timer.Stop(); + + Visibility = Visibility.Collapsed; + } + + + void ControlLoaded(object sender, RoutedEventArgs e) + { + if (ApplicationSpace.IsDesignMode) + return; + + _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(UpdateInterval) }; + _timer.Tick += TimerTick; + _timer.Start(); + + var rootFrame = ApplicationSpace.RootFrame; + + if (rootFrame == null) + return; + + rootFrame.Navigated -= FrameNavigated; + rootFrame.Navigated += FrameNavigated; + } + + #region control unloaded + void ControlUnloaded(object sender, RoutedEventArgs e) + { + Dispose(); + } + + void FrameNavigated(object sender, NavigationEventArgs e) + { +#if WINDOWS_PHONE + if (e.IsNavigationInitiator) +#endif + { + Dispose(); + } + } + + public void Dispose() + { + var rootFrame = ApplicationSpace.RootFrame; + + if (rootFrame != null) + rootFrame.Navigated -= FrameNavigated; + + if (_timer != null) + { + _timer.Stop(); + _timer.Tick -= TimerTick; + + _timer = null; + } + } + #endregion + + } +} \ No newline at end of file diff --git a/Telegram.Controls/Properties/AssemblyInfo.cs b/Telegram.Controls/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..1d6e0b9 --- /dev/null +++ b/Telegram.Controls/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("Telegram.Controls")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Telegram.Controls")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[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("c1e19589-bd32-4dcf-af58-393ad4d40b4e")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/Telegram.Controls/README_FIRST.txt b/Telegram.Controls/README_FIRST.txt new file mode 100755 index 0000000..d1bb14e --- /dev/null +++ b/Telegram.Controls/README_FIRST.txt @@ -0,0 +1,3 @@ +For the Windows Phone toolkit make sure that you have +marked the icons in the "Toolkit.Content" folder as content. That way they +can be used as the icons for the ApplicationBar control. \ No newline at end of file diff --git a/Telegram.Controls/RangeSlider.cs b/Telegram.Controls/RangeSlider.cs new file mode 100755 index 0000000..0e37595 --- /dev/null +++ b/Telegram.Controls/RangeSlider.cs @@ -0,0 +1,449 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace Telegram.Controls +{ + using System; + using System.Windows; + using System.Windows.Controls; + using System.Windows.Controls.Primitives; + + /// + /// A double headed slider for selecting a range. + /// + public class RangeSlider : Control + { + /// + /// The minimum value dependency protperty. + /// + public static readonly DependencyProperty MinimumProperty = + DependencyProperty.Register("Minimum", typeof(double), typeof(RangeSlider), new PropertyMetadata(0.0, new PropertyChangedCallback(RangeBounds_Changed))); + + /// + /// The maximum value dependency protperty. + /// + public static readonly DependencyProperty MaximumProperty = + DependencyProperty.Register("Maximum", typeof(double), typeof(RangeSlider), new PropertyMetadata(1.0, new PropertyChangedCallback(RangeBounds_Changed))); + + /// + /// The minimum range span dependency protperty. + /// + public static readonly DependencyProperty MinimumRangeSpanProperty = + DependencyProperty.Register("MinimumRangeSpan", typeof(double), typeof(RangeSlider), new PropertyMetadata(0.0)); + + /// + /// The range start dependency property. + /// + public static readonly DependencyProperty RangeStartProperty = + DependencyProperty.Register("RangeStart", typeof(double), typeof(RangeSlider), new PropertyMetadata(0.0, new PropertyChangedCallback(Range_Changed))); + + /// + /// The range end dependency property. + /// + public static readonly DependencyProperty RangeEndProperty = + DependencyProperty.Register("RangeEnd", typeof(double), typeof(RangeSlider), new PropertyMetadata(1.0, new PropertyChangedCallback(Range_Changed))); + + /// + /// The element name for the range start thumb. + /// + private const string ElementRangeStartThumb = "RangeStartThumb"; + + /// + /// The element name for the range center thumb. + /// + private const string ElementRangeCenterThumb = "RangeCenterThumb"; + + /// + /// The element name for the range end thumb. + /// + private const string ElementRangeEndThumb = "RangeEndThumb"; + + /// + /// The element name for the selected range borer. + /// + private const string ElementSelectedRangeBorder = "SelectedRangeBorder"; + + /// + /// The range start thumb. + /// + private Thumb rangeStartThumb; + + /// + /// The range center thumb. + /// + private Thumb rangeCenterThumb; + + /// + /// The range end thumb. + /// + private Thumb rangeEndThumb; + + /// + /// The selected range border. + /// + private Border selectedRangeBorder; + + /// + /// RangeSlider constructor. + /// + public RangeSlider() + { + this.DefaultStyleKey = typeof(RangeSlider); + this.SizeChanged += new SizeChangedEventHandler(this.RangeSlider_SizeChanged); + } + + /// + /// RangeChanged event. + /// + public event EventHandler RangeChanged; + + /// + /// Gets or sets the slider minimum value. + /// + public double Minimum + { + get + { + return (double)GetValue(MinimumProperty); + } + + set + { + SetValue(MinimumProperty, Math.Min(this.Maximum, Math.Max(0, value))); + + if (this.Maximum - this.Minimum < this.MinimumRangeSpan) + { + this.MinimumRangeSpan = this.Maximum - this.Minimum; + } + } + } + + /// + /// Gets or sets the slider maximum value. + /// + public double Maximum + { + get + { + return (double)GetValue(MaximumProperty); + } + + set + { + SetValue(MaximumProperty, Math.Max(this.Minimum, value)); + + if (this.Maximum - this.Minimum < this.MinimumRangeSpan) + { + this.MinimumRangeSpan = this.Maximum - this.Minimum; + } + } + } + + /// + /// Gets or sets the slider minimum range span. + /// + public double MinimumRangeSpan + { + get + { + return (double)GetValue(MinimumRangeSpanProperty); + } + + set + { + SetValue(MinimumRangeSpanProperty, Math.Min(this.Maximum - this.Minimum, value)); + this.UpdateSelectedRangeMinimumWidth(); + this.UpdateRange(false); + } + } + + /// + /// Gets or sets the range start. + /// + public double RangeStart + { + get + { + return (double)GetValue(RangeStartProperty); + } + + set + { + double rangeStart = Math.Max(this.Minimum, value); + SetValue(RangeStartProperty, rangeStart); + } + } + + /// + /// Gets or sets the range end. + /// + public double RangeEnd + { + get + { + return (double)GetValue(RangeEndProperty); + } + + set + { + double rangeEnd = Math.Min(this.Maximum, value); + SetValue(RangeEndProperty, rangeEnd); + } + } + + /// + /// Gets the template parts from the template. + /// + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + this.selectedRangeBorder = this.GetTemplateChild(RangeSlider.ElementSelectedRangeBorder) as Border; + this.rangeStartThumb = this.GetTemplateChild(RangeSlider.ElementRangeStartThumb) as Thumb; + if (this.rangeStartThumb != null) + { + this.rangeStartThumb.DragDelta += new DragDeltaEventHandler(this.RangeStartThumb_DragDelta); + this.rangeStartThumb.SizeChanged += new SizeChangedEventHandler(this.RangeThumb_SizeChanged); + } + + this.rangeCenterThumb = this.GetTemplateChild(RangeSlider.ElementRangeCenterThumb) as Thumb; + if (this.rangeCenterThumb != null) + { + this.rangeCenterThumb.DragDelta += new DragDeltaEventHandler(this.RangeCenterThumb_DragDelta); + } + + this.rangeEndThumb = this.GetTemplateChild(RangeSlider.ElementRangeEndThumb) as Thumb; + if (this.rangeEndThumb != null) + { + this.rangeEndThumb.DragDelta += new DragDeltaEventHandler(this.RangeEndThumb_DragDelta); + this.rangeEndThumb.SizeChanged += new SizeChangedEventHandler(this.RangeThumb_SizeChanged); + } + } + + #region Dependency property events. + /// + /// Updates the slider when the selected range changes. + /// + /// The range slider. + /// Dependency Property Changed Event Args. + private static void Range_Changed(DependencyObject d, DependencyPropertyChangedEventArgs args) + { + RangeSlider rangeSlider = d as RangeSlider; + rangeSlider.UpdateSlider(); + + if (rangeSlider.RangeChanged != null) + { + rangeSlider.RangeChanged(rangeSlider, EventArgs.Empty); + } + } + + /// + /// Updates the range start and end values. + /// + /// The range slider. + /// Dependency Property Changed Event Args. + private static void RangeBounds_Changed(DependencyObject d, DependencyPropertyChangedEventArgs args) + { + (d as RangeSlider).UpdateRange(true); + } + #endregion + + #region Range Slider events + /// + /// Updates the slider UI. + /// + /// The range slider. + /// Size Changed Event Args. + private void RangeSlider_SizeChanged(object sender, SizeChangedEventArgs e) + { + this.UpdateSelectedRangeMinimumWidth(); + this.UpdateSlider(); + } + #endregion + + #region Thumb events + /// + /// Updates the slider's minimum width. + /// + /// The range thumb. + /// Size changed event args. + private void RangeThumb_SizeChanged(object sender, SizeChangedEventArgs e) + { + this.UpdateSelectedRangeMinimumWidth(); + } + + /// + /// Moves the whole range slider. + /// + /// The range cetner thumb. + /// Drag Delta Event Args. + private void RangeCenterThumb_DragDelta(object sender, DragDeltaEventArgs e) + { + if (this.selectedRangeBorder != null) + { + double startMargin = this.selectedRangeBorder.Margin.Left + e.HorizontalChange; + double endMargin = this.selectedRangeBorder.Margin.Right - e.HorizontalChange; + + if (startMargin + e.HorizontalChange <= 0) + { + startMargin = 0; + endMargin = Math.Round(this.ActualWidth - (((this.RangeEnd - this.RangeStart) / (this.Maximum - this.Minimum)) * this.ActualWidth), 0); + } + else if (endMargin - e.HorizontalChange <= 0) + { + endMargin = 0; + startMargin = Math.Round(this.ActualWidth - (((this.RangeEnd - this.RangeStart) / (this.Maximum - this.Minimum)) * this.ActualWidth), 0); + } + + if (!double.IsNaN(startMargin) && !double.IsNaN(endMargin)) + { + this.selectedRangeBorder.Margin = new Thickness( + startMargin, + this.selectedRangeBorder.Margin.Top, + endMargin, + this.selectedRangeBorder.Margin.Bottom); + } + + this.UpdateRange(true); + } + } + + /// + /// Moves the range end thumb. + /// + /// The range end thumb. + /// Drag Delta Event Args. + private void RangeEndThumb_DragDelta(object sender, DragDeltaEventArgs e) + { + if (this.selectedRangeBorder != null) + { + double endMargin = Math.Round(Math.Min(this.ActualWidth - this.selectedRangeBorder.MinWidth, Math.Max(0, this.selectedRangeBorder.Margin.Right - e.HorizontalChange)), 0); + double startMargin = Math.Round(this.selectedRangeBorder.Margin.Left, 0); + + if (this.ActualWidth - startMargin - endMargin < this.selectedRangeBorder.MinWidth) + { + startMargin = Math.Round(this.ActualWidth - endMargin - this.selectedRangeBorder.MinWidth, 0); + } + + this.selectedRangeBorder.Margin = new Thickness( + startMargin, + this.selectedRangeBorder.Margin.Top, + endMargin, + this.selectedRangeBorder.Margin.Bottom); + + this.UpdateRange(true); + } + } + + /// + /// Moves the range start thumb. + /// + /// The range start thumb. + /// Drag Delta Event Args. + private void RangeStartThumb_DragDelta(object sender, DragDeltaEventArgs e) + { + if (this.selectedRangeBorder != null) + { + double startMargin = Math.Round(Math.Min(this.ActualWidth - this.selectedRangeBorder.MinWidth, Math.Max(0, this.selectedRangeBorder.Margin.Left + e.HorizontalChange)), 0); + double endMargin = Math.Round(this.selectedRangeBorder.Margin.Right, 0); + + if (this.ActualWidth - startMargin - endMargin < this.selectedRangeBorder.MinWidth) + { + endMargin = Math.Round(this.ActualWidth - startMargin - this.selectedRangeBorder.MinWidth, 0); + } + + + + this.selectedRangeBorder.Margin = new Thickness( + startMargin, + this.selectedRangeBorder.Margin.Top, + endMargin, + this.selectedRangeBorder.Margin.Bottom); + + this.UpdateRange(true); + } + } + + public void Log(string str) + { + System.Diagnostics.Debug.WriteLine(str); + } + + #endregion + + /// + /// Updates the thumb mimimum width. + /// + private void UpdateSelectedRangeMinimumWidth() + { + if (this.selectedRangeBorder != null && this.rangeStartThumb != null && this.rangeEndThumb != null) + { + this.selectedRangeBorder.MinWidth = Math.Max( + this.rangeStartThumb.ActualWidth + this.rangeEndThumb.ActualWidth, + (this.MinimumRangeSpan / ((this.Maximum - this.Minimum) == 0 ? 1 : (this.Maximum - this.Minimum))) * this.ActualWidth); + } + } + + /// + /// Updates the slider UI. + /// + private void UpdateSlider() + { + if (this.selectedRangeBorder != null) + { + double startMargin = (this.RangeStart / (this.Maximum - this.Minimum)) * this.ActualWidth; + double endMargin = ((this.Maximum - this.RangeEnd) / (this.Maximum - this.Minimum)) * this.ActualWidth; + + if (!double.IsNaN(startMargin) && !double.IsNaN(endMargin)) + { + this.selectedRangeBorder.Margin = new Thickness( + startMargin, + this.selectedRangeBorder.Margin.Top, + endMargin, + this.selectedRangeBorder.Margin.Bottom); + } + } + } + + /// + /// Updates the selected range. + /// + /// Whether the range changed event should fire. + private void UpdateRange(bool raiseEvent) + { + if (this.selectedRangeBorder != null) + { + bool rangeChanged = false; + double rangeStart = Math.Round(((this.Maximum - this.Minimum) * (this.selectedRangeBorder.Margin.Left / this.ActualWidth)) + this.Minimum, 0); + double rangeEnd = Math.Round(this.Maximum - ((this.Maximum - this.Minimum) * (this.selectedRangeBorder.Margin.Right / this.ActualWidth)), 0); + + if (rangeEnd - rangeStart < this.MinimumRangeSpan) + { + if (rangeStart + this.MinimumRangeSpan > this.Maximum) + { + rangeStart = this.Maximum - this.MinimumRangeSpan; + } + + rangeEnd = Math.Min(this.Maximum, rangeStart + this.MinimumRangeSpan); + } + + if (rangeStart != this.RangeStart || rangeEnd != this.RangeEnd) + { + rangeChanged = true; + } + + this.RangeStart = rangeStart; + this.RangeEnd = rangeEnd; + + if (raiseEvent && rangeChanged && this.RangeChanged != null) + { + this.RangeChanged(this, EventArgs.Empty); + } + } + } + } +} diff --git a/Telegram.Controls/ReorderListBox/ReorderListBox.cs b/Telegram.Controls/ReorderListBox/ReorderListBox.cs new file mode 100755 index 0000000..d840708 --- /dev/null +++ b/Telegram.Controls/ReorderListBox/ReorderListBox.cs @@ -0,0 +1,1387 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using Microsoft.Phone.Controls; +using Telegram.Controls; + +namespace ReorderListBox +{ + /// + /// Extends ListBox to enable drag-and-drop reorder within the list. + /// + [TemplatePart(Name = ReorderListBox.ScrollViewerPart, Type = typeof(ScrollViewer))] + [TemplatePart(Name = ReorderListBox.DragIndicatorPart, Type = typeof(Image))] + [TemplatePart(Name = ReorderListBox.DragInterceptorPart, Type = typeof(Canvas))] + [TemplatePart(Name = ReorderListBox.RearrangeCanvasPart, Type = typeof(Canvas))] + public class ReorderListBox : ListBox + { + #region Template part name constants + + public const string ScrollViewerPart = "ScrollViewer"; + public const string DragIndicatorPart = "DragIndicator"; + public const string DragInterceptorPart = "DragInterceptor"; + public const string RearrangeCanvasPart = "RearrangeCanvas"; + + #endregion + + private const string VerticalCompressionGroup = "VerticalCompression"; + private const string HorizontalCompressionGroup = "HorizontalCompression"; + private const string ScrollStatesGroup = "ScrollStates"; + + private const string ScrollViewerScrollingVisualState = "Scrolling"; + private const string ScrollViewerNotScrollingVisualState = "NotScrolling"; + + private const string IsReorderEnabledPropertyName = "IsReorderEnabled"; + + #region Private fields + + private double dragScrollDelta; + private Panel itemsPanel; + private ScrollViewer scrollViewer; + private Canvas dragInterceptor; + private Image dragIndicator; + private object dragItem; + private ReorderListBoxItem dragItemContainer; + private bool isDragItemSelected; + private Rect dragInterceptorRect; + private int dropTargetIndex; + private Canvas rearrangeCanvas; + private Queue> rearrangeQueue; + + #endregion + + /// + /// Creates a new ReorderListBox and sets the default style key. + /// The style key is used to locate the control template in Generic.xaml. + /// + public ReorderListBox() + { + this.DefaultStyleKey = typeof(ReorderListBox); + + ItemContainerGenerator.ItemsChanged += (sender, args) => + { + + }; + } + + public static readonly DependencyProperty HeaderTemplateProperty = DependencyProperty.Register( + "HeaderTemplate", typeof (DataTemplate), typeof (ReorderListBox), new PropertyMetadata(default(DataTemplate))); + + public DataTemplate HeaderTemplate + { + get { return (DataTemplate) GetValue(HeaderTemplateProperty); } + set { SetValue(HeaderTemplateProperty, value); } + } + + public static readonly DependencyProperty FooterTemplateProperty = DependencyProperty.Register( + "FooterTemplate", typeof (DataTemplate), typeof (ReorderListBox), new PropertyMetadata(default(DataTemplate))); + + public DataTemplate FooterTemplate + { + get { return (DataTemplate) GetValue(FooterTemplateProperty); } + set { SetValue(FooterTemplateProperty, value); } + } + + #region IsReorderEnabled DependencyProperty + + public static readonly DependencyProperty IsReorderEnabledProperty = DependencyProperty.Register( + ReorderListBox.IsReorderEnabledPropertyName, typeof(bool), typeof(ReorderListBox), + new PropertyMetadata(false, (d, e) => ((ReorderListBox)d).OnIsReorderEnabledChanged(e))); + + /// + /// Gets or sets a value indicating whether reordering is enabled in the listbox. + /// This also controls the visibility of the reorder drag-handle of each listbox item. + /// + public bool IsReorderEnabled + { + get + { + return (bool)this.GetValue(ReorderListBox.IsReorderEnabledProperty); + } + set + { + this.SetValue(ReorderListBox.IsReorderEnabledProperty, value); + } + } + + protected void OnIsReorderEnabledChanged(DependencyPropertyChangedEventArgs e) + { + if (this.dragInterceptor != null) + { + this.dragInterceptor.Visibility = (bool)e.NewValue ? Visibility.Visible : Visibility.Collapsed; + } + + this.InvalidateArrange(); + } + + #endregion + + #region AutoScrollMargin DependencyProperty + + public static readonly DependencyProperty AutoScrollMarginProperty = DependencyProperty.Register( + "AutoScrollMargin", typeof(int), typeof(ReorderListBox), new PropertyMetadata(32)); + + private PhoneApplicationPage _page; + + /// + /// Gets or sets the size of the region at the top and bottom of the list where dragging will + /// cause the list to automatically scroll. + /// + public double AutoScrollMargin + { + get + { + return (int)this.GetValue(ReorderListBox.AutoScrollMarginProperty); + } + set + { + this.SetValue(ReorderListBox.AutoScrollMarginProperty, value); + } + } + + #endregion + + #region ItemsControl overrides + + /// + /// Applies the control template, gets required template parts, and hooks up the drag events. + /// + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + this.scrollViewer = (ScrollViewer)this.GetTemplateChild(ReorderListBox.ScrollViewerPart); + if (scrollViewer != null) + { + //var verticalGroup = FindVisualState(scrollViewer, VerticalCompressionGroup); + //var horizontalGroup = FindVisualState(scrollViewer, HorizontalCompressionGroup); + var scrollStatesGroup = FindVisualState(scrollViewer, ScrollStatesGroup); + + //if (verticalGroup != null) + // verticalGroup.CurrentStateChanging += VerticalGroup_CurrentStateChanging; + //if (horizontalGroup != null) + // horizontalGroup.CurrentStateChanging += HorizontalGroup_CurrentStateChanging; + if (scrollStatesGroup != null) + scrollStatesGroup.CurrentStateChanging += ScrollStateGroup_CurrentStateChanging; + } + this.dragInterceptor = this.GetTemplateChild(ReorderListBox.DragInterceptorPart) as Canvas; + this.dragIndicator = this.GetTemplateChild(ReorderListBox.DragIndicatorPart) as Image; + this.rearrangeCanvas = this.GetTemplateChild(ReorderListBox.RearrangeCanvasPart) as Canvas; + + if (this.scrollViewer != null && this.dragInterceptor != null && this.dragIndicator != null) + { + this.dragInterceptor.Visibility = this.IsReorderEnabled ? Visibility.Visible : Visibility.Collapsed; + + //AddHandler(ManipulationStartedEvent, new EventHandler(OnReorderListBoxManipulationStarted), true); + //AddHandler(ManipulationDeltaEvent, new EventHandler(dragInterceptor_ManipulationDelta), true); + //AddHandler(ManipulationCompletedEvent, new EventHandler(dragInterceptor_ManipulationCompleted), true); + this.dragInterceptor.ManipulationStarted += this.dragInterceptor_ManipulationStarted; + this.dragInterceptor.ManipulationDelta += this.dragInterceptor_ManipulationDelta; + this.dragInterceptor.ManipulationCompleted += this.dragInterceptor_ManipulationCompleted; + } + } + + private void ScrollStateGroup_CurrentStateChanging(object sender, VisualStateChangedEventArgs e) + { + IsScrolling = (e.NewState.Name == ScrollViewerScrollingVisualState); + } + /// + /// The event people can subscribe to + /// + public event EventHandler ScrollingStateChanged; + + /// + /// DependencyProperty that backs the property + /// + public static readonly DependencyProperty IsScrollingProperty = DependencyProperty.Register( + "IsScrolling", + typeof(bool), + typeof(ReorderListBox), + new PropertyMetadata(false, IsScrollingPropertyChanged)); + + /// + /// Whether the list is currently scrolling or not + /// + public bool IsScrolling + { + get { return (bool)GetValue(IsScrollingProperty); } + set { SetValue(IsScrollingProperty, value); } + } + + /// + /// Handler for when the IsScrolling dependency property changes + /// + /// The object that has the property + /// Args + static void IsScrollingPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) + { + var listbox = source as ReorderListBox; + if (listbox == null) return; + + // Call the virtual notification method for anyone who derives from this class + var scrollingArgs = new ScrollingStateChangedEventArgs((bool)e.OldValue, (bool)e.NewValue); + + // Raise the event, if anyone is listening to it + var handler = listbox.ScrollingStateChanged; + if (handler != null) + handler(listbox, scrollingArgs); + } + + private static VisualStateGroup FindVisualState(FrameworkElement element, string stateName) + { + if (element == null) + return null; + + var groups = VisualStateManager.GetVisualStateGroups(element); + return groups.Cast().FirstOrDefault(group => group.Name == stateName); + } + + //private void OnReorderListBoxManipulationStarted(object sender, ManipulationStartedEventArgs e) + //{ + // scrollViewer.IsHitTestVisible = false; + // dragInterceptor_ManipulationStarted(sender, e); + //} + + protected override DependencyObject GetContainerForItemOverride() + { + return new ReorderListBoxItem(); + } + + protected override bool IsItemItsOwnContainerOverride(object item) + { + return item is ReorderListBoxItem; + } + + /// + /// Ensures that a possibly-recycled item container (ReorderListBoxItem) is ready to display a list item. + /// + protected override void PrepareContainerForItemOverride(DependencyObject element, object item) + { + base.PrepareContainerForItemOverride(element, item); + + ReorderListBoxItem itemContainer = (ReorderListBoxItem)element; + itemContainer.ApplyTemplate(); // Loads visual states. + + // Set this state before binding to avoid showing the visual transition in this case. + string reorderState = this.IsReorderEnabled ? + ReorderListBoxItem.ReorderEnabledState : ReorderListBoxItem.ReorderDisabledState; + VisualStateManager.GoToState(itemContainer, reorderState, false); + + itemContainer.SetBinding(ReorderListBoxItem.IsReorderEnabledProperty, + new Binding(ReorderListBox.IsReorderEnabledPropertyName) { Source = this }); + + if (item == this.dragItem) + { + itemContainer.IsSelected = this.isDragItemSelected; + VisualStateManager.GoToState(itemContainer, ReorderListBoxItem.DraggingState, false); + + if (this.dropTargetIndex >= 0) + { + // The item's dragIndicator is currently being moved, so the item itself is hidden. + itemContainer.Visibility = Visibility.Collapsed; + this.dragItemContainer = itemContainer; + } + else + { + itemContainer.Opacity = 0; + this.Dispatcher.BeginInvoke(() => this.AnimateDrop(itemContainer, "prepareContainer")); + } + } + else + { + VisualStateManager.GoToState(itemContainer, ReorderListBoxItem.NotDraggingState, false); + } + } + + /// + /// Called when an item container (ReorderListBoxItem) is being removed from the list panel. + /// This may be because the item was removed from the list or because the item is now outside + /// the virtualization region (because ListBox uses a VirtualizingStackPanel as its items panel). + /// + protected override void ClearContainerForItemOverride(DependencyObject element, object item) + { + base.ClearContainerForItemOverride(element, item); + + ReorderListBoxItem itemContainer = (ReorderListBoxItem)element; + if (itemContainer == this.dragItemContainer) + { + this.dragItemContainer.Visibility = Visibility.Visible; + this.dragItemContainer = null; + Debug.WriteLine("ClearContainerForItemOverride dragItemContainer=null"); + } + } + + #endregion + + #region Drag & drop reorder + + internal static T GetFirstLogicalChildByType(FrameworkElement parent, bool applyTemplates) + where T : FrameworkElement + { + Debug.Assert(parent != null, "The parent cannot be null."); + + Queue queue = new Queue(); + queue.Enqueue(parent); + + while (queue.Count > 0) + { + FrameworkElement element = queue.Dequeue(); + var elementAsControl = element as Control; + if (applyTemplates && elementAsControl != null) + { + elementAsControl.ApplyTemplate(); + } + + if (element is T && element != parent) + { + return (T)element; + } + + foreach (FrameworkElement visualChild in GetVisualChildren(element).OfType()) + { + queue.Enqueue(visualChild); + } + } + + return null; + } + + public static IEnumerable GetVisualChildren(DependencyObject target) + { + int count = VisualTreeHelper.GetChildrenCount(target); + if (count == 0) + { + } + else + { + for (int i = 0; i < count; i++) + { + yield return VisualTreeHelper.GetChild(target, i); + } + } + yield break; + } + + private bool _isManipulating; + private DateTime? _manipulationTimestamp; + /// + /// Called when the user presses down on the transparent drag-interceptor. Identifies the targed + /// drag handle and list item and prepares for a drag operation. + /// + private void dragInterceptor_ManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + Debug.WriteLine("ManipulationDelta dropTargetIndex=" + dropTargetIndex + " dragItemContainer=" + (dragItemContainer != null ? dragItemContainer.Content : "null") + " dragItem=" + dragItem); + + + _isManipulating = true; + + _manipulationTimestamp = DateTime.Now; + var timestamp = _manipulationTimestamp; + GeneralTransform interceptorTransform; + List targetElements; + var targetItemContainer = InterceptorTransform(e, out targetElements, out interceptorTransform); + ThreadPool.QueueUserWorkItem(state => + { + Thread.Sleep(TimeSpan.FromSeconds(0.5)); + Deployment.Current.Dispatcher.BeginInvoke(() => + { + if (!_isManipulating) return; + if (timestamp != _manipulationTimestamp) return; + + _page = _page ?? GetFirstLogicalChildByType(Application.Current.RootVisual as FrameworkElement, false); + _page.NavigationService.Navigated += OnPageNavigated; + if (this.dragItem != null) + { + return; + } + + if (this.itemsPanel == null) + { + ItemsPresenter scrollItemsPresenter = (ItemsPresenter) GetFirstLogicalChildByType(this.scrollViewer, false); + this.itemsPanel = (Panel)VisualTreeHelper.GetChild(scrollItemsPresenter, 0); + } + + var newTargetItemContainer = InterceptorTransform(e, out targetElements, out interceptorTransform); + if (newTargetItemContainer != targetItemContainer) + { + return; + } + + targetItemContainer = newTargetItemContainer; + if (targetItemContainer != null && targetElements.Contains(targetItemContainer.DragHandle)) + { + VisualStateManager.GoToState(targetItemContainer, ReorderListBoxItem.DraggingState, true); + + GeneralTransform targetItemTransform = targetItemContainer.TransformToVisual(this.dragInterceptor); + Point targetItemOrigin = targetItemTransform.Transform(new Point(0, 0)); + Canvas.SetLeft(this.dragIndicator, targetItemOrigin.X); + Canvas.SetTop(this.dragIndicator, targetItemOrigin.Y); + this.dragIndicator.Width = targetItemContainer.RenderSize.Width; + this.dragIndicator.Height = targetItemContainer.RenderSize.Height; + + this.dragItemContainer = targetItemContainer; + this.dragItem = this.dragItemContainer.Content; + this.isDragItemSelected = this.dragItemContainer.IsSelected; + + dragInterceptorRect = interceptorTransform.TransformBounds(new Rect(new Point(0, 0), this.dragInterceptor.RenderSize)); + + this.dropTargetIndex = -1; + Debug.WriteLine("ManipulationStarted dropTargetIndex=" + dropTargetIndex); + } + }); + }); + + } + + private ReorderListBoxItem InterceptorTransform(ManipulationStartedEventArgs e, out List targetElements, out GeneralTransform interceptorTransform) + { + interceptorTransform = dragInterceptor.TransformToVisual(Application.Current.RootVisual); + + var targetPoint = interceptorTransform.Transform(e.ManipulationOrigin); + targetPoint = GetHostCoordinates(targetPoint); + + targetElements = VisualTreeHelper.FindElementsInHostCoordinates(targetPoint, itemsPanel).ToList(); + + return targetElements.OfType().FirstOrDefault(); + } + + private void OnPageNavigated(object sender, NavigationEventArgs e) + { + _isManipulating = false; + _manipulationTimestamp = null; + + Debug.WriteLine("PageNavigated initiator=" + e.IsNavigationInitiator); + + dragInterceptor_ManipulationCompleted(sender, null); + + _page.NavigationService.Navigated -= OnPageNavigated; + } + + /// + /// Called when the user drags on (or from) the transparent drag-interceptor. + /// Moves the item (actually a rendered snapshot of the item) according to the drag delta. + /// + private void dragInterceptor_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + Debug.WriteLine("ManipulationDelta dropTargetIndex=" + dropTargetIndex + " dragItemContainer=" + (dragItemContainer != null ? dragItemContainer.Content : "null") + " dragItem=" + dragItem); + + + if (e.PinchManipulation != null) + { + dragInterceptor_ManipulationCompleted(sender, null); + + return; + } + + if (this.Items.Count <= 1 || this.dragItem == null) + { + if (_manipulationTimestamp != null) + { + _isManipulating = false; + _manipulationTimestamp = null; + } + + return; + } + + if (this.dropTargetIndex == -1) + { + if (this.dragItemContainer == null) + { + dragItem = null; + return; + } + + // When the drag actually starts, swap out the item for the drag-indicator image of the item. + // This is necessary because the item itself may be removed from the virtualizing panel + // if the drag causes a scroll of considerable distance. + Size dragItemSize = this.dragItemContainer.RenderSize; + WriteableBitmap writeableBitmap = new WriteableBitmap( + (int)dragItemSize.Width, (int)dragItemSize.Height); + + // Swap states to force the transition to complete. + VisualStateManager.GoToState(this.dragItemContainer, ReorderListBoxItem.NotDraggingState, false); + VisualStateManager.GoToState(this.dragItemContainer, ReorderListBoxItem.DraggingState, false); + writeableBitmap.Render(this.dragItemContainer, null); + + writeableBitmap.Invalidate(); + this.dragIndicator.Source = writeableBitmap; + + this.dragIndicator.Visibility = Visibility.Visible; + this.dragItemContainer.Visibility = Visibility.Collapsed; + + if (this.itemsPanel.Children.IndexOf(this.dragItemContainer) < this.itemsPanel.Children.Count - 1) + { + this.UpdateDropTarget(Canvas.GetTop(this.dragIndicator) + this.dragIndicator.Height + 1, false); + } + else + { + this.UpdateDropTarget(Canvas.GetTop(this.dragIndicator) - 1, false); + } + } + + double dragItemHeight = this.dragIndicator.Height; + + TranslateTransform translation = (TranslateTransform)this.dragIndicator.RenderTransform; + double top = Canvas.GetTop(this.dragIndicator); + + // Limit the translation to keep the item within the list area. + // Use different targeting for the top and bottom edges to allow taller items to + // move before or after shorter items at the edges. + double y = top + e.CumulativeManipulation.Translation.Y; + if (y < 0) + { + y = 0; + this.UpdateDropTarget(0, true); + } + else if (y >= this.dragInterceptorRect.Height - dragItemHeight) + { + y = this.dragInterceptorRect.Height - dragItemHeight; + this.UpdateDropTarget(this.dragInterceptorRect.Height - 1, true); + } + else + { + this.UpdateDropTarget(y + dragItemHeight / 2, true); + } + + translation.Y = y - top; + + // Check if we're within the margin where auto-scroll needs to happen. + bool scrolling = (this.dragScrollDelta != 0); + double autoScrollMargin = this.AutoScrollMargin; + if (autoScrollMargin > 0 && y < autoScrollMargin) + { + this.dragScrollDelta = y - autoScrollMargin; + if (!scrolling) + { + VisualStateManager.GoToState(this.scrollViewer, ReorderListBox.ScrollViewerScrollingVisualState, true); + this.Dispatcher.BeginInvoke(() => this.DragScroll()); + return; + } + } + else if (autoScrollMargin > 0 && y + dragItemHeight > this.dragInterceptorRect.Height - autoScrollMargin) + { + this.dragScrollDelta = (y + dragItemHeight - (this.dragInterceptorRect.Height - autoScrollMargin)); + if (!scrolling) + { + VisualStateManager.GoToState(this.scrollViewer, ReorderListBox.ScrollViewerScrollingVisualState, true); + this.Dispatcher.BeginInvoke(() => this.DragScroll()); + return; + } + } + else + { + // We're not within the auto-scroll margin. This ensures any current scrolling is stopped. + this.dragScrollDelta = 0; + } + } + + /// + /// Called when the user releases a drag. Moves the item within the source list and then resets everything. + /// + private void dragInterceptor_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + _isManipulating = false; + _manipulationTimestamp = null; + + + Debug.WriteLine("ManipulationCompleted dropTargetIndex=" + dropTargetIndex + " dragItemContainer=" + (dragItemContainer != null ? dragItemContainer.Content : "null") + " dragItem=" + dragItem); + + if (_page != null) + { + _page.NavigationService.Navigated -= OnPageNavigated; + } + + if (this.dragItem == null) + { + return; + } + + if (this.dropTargetIndex >= 0) + { + this.MoveItem(this.dragItem, this.dropTargetIndex); + } + else + { + + } + + if (this.dragItemContainer != null) + { + this.dragItemContainer.Visibility = Visibility.Visible; + this.dragItemContainer.Opacity = 0; + this.AnimateDrop(this.dragItemContainer, "manipulationCompleted"); + this.dragItemContainer = null; + } + else + { + + } + + this.dragScrollDelta = 0; + this.dropTargetIndex = -1; + //Debug.WriteLine("ManipulationCompleted dropTargetIndex=" + dropTargetIndex); + this.ClearDropTarget(); + + } + + /// + /// Slides the drag indicator (item snapshot) to the location of the dropped item, + /// then performs the visibility swap and removes the dragging visual state. + /// + private void AnimateDrop(ReorderListBoxItem itemContainer, string from) + { + GeneralTransform itemTransform = itemContainer.TransformToVisual(this.dragInterceptor); + + Rect itemRect = itemTransform.TransformBounds(new Rect(new Point(0, 0), itemContainer.RenderSize)); + double delta = Math.Abs(itemRect.Y - Canvas.GetTop(this.dragIndicator) - ((TranslateTransform)this.dragIndicator.RenderTransform).Y); + if (itemRect.Height == 0.0 || (itemContainer.RenderSize.Width == 0.0 && itemContainer.RenderSize.Height == 0.0)) + { + delta = 0.0; + } + if (delta > 0.0) + { + // Adjust the duration based on the distance, so the speed will be constant. + TimeSpan duration = TimeSpan.FromSeconds(0.25 * delta / itemRect.Height); + Debug.WriteLine("Duration=" + duration + " from=" + from + " delta=" + delta + " itemRect.Height=" + itemRect.Height + " dragIndicator.Y=" + ((TranslateTransform)this.dragIndicator.RenderTransform).Y + " itemRect.Y=" + itemRect.Y + " Canvas.GetTop=" + Canvas.GetTop(this.dragIndicator)); + if (duration.TotalSeconds > 1.0) + { + // There was no need for an animation, so do the visibility swap right now. + this.dragItem = null; + itemContainer.Opacity = 1; + this.dragIndicator.Visibility = Visibility.Collapsed; + this.dragIndicator.Source = null; + VisualStateManager.GoToState(itemContainer, ReorderListBoxItem.NotDraggingState, true); + } + else + { + Storyboard dropStoryboard = new Storyboard(); + DoubleAnimation moveToDropAnimation = new DoubleAnimation(); + Storyboard.SetTarget(moveToDropAnimation, this.dragIndicator.RenderTransform); + Storyboard.SetTargetProperty(moveToDropAnimation, new PropertyPath(TranslateTransform.YProperty)); + moveToDropAnimation.To = itemRect.Y - Canvas.GetTop(this.dragIndicator); + moveToDropAnimation.Duration = duration; + dropStoryboard.Children.Add(moveToDropAnimation); + + dropStoryboard.Completed += delegate + { + this.dragItem = null; + itemContainer.Opacity = 1; + this.dragIndicator.Visibility = Visibility.Collapsed; + this.dragIndicator.Source = null; + ((TranslateTransform)this.dragIndicator.RenderTransform).Y = 0; + VisualStateManager.GoToState(itemContainer, ReorderListBoxItem.NotDraggingState, true); + + }; + dropStoryboard.Begin(); + } + } + else + { + // There was no need for an animation, so do the visibility swap right now. + this.dragItem = null; + itemContainer.Opacity = 1; + this.dragIndicator.Visibility = Visibility.Collapsed; + this.dragIndicator.Source = null; + VisualStateManager.GoToState(itemContainer, ReorderListBoxItem.NotDraggingState, true); + } + } + + /// + /// Automatically scrolls for as long as the drag is held within the margin. + /// The speed of the scroll is adjusted based on the depth into the margin. + /// + private void DragScroll() + { + if (this.dragScrollDelta != 0) + { + double scrollRatio = this.scrollViewer.ViewportHeight / this.scrollViewer.RenderSize.Height; + double adjustedDelta = this.dragScrollDelta * scrollRatio; + double newOffset = this.scrollViewer.VerticalOffset + adjustedDelta; + this.scrollViewer.ScrollToVerticalOffset(newOffset); + + this.Dispatcher.BeginInvoke(() => this.DragScroll()); + + double dragItemOffset = Canvas.GetTop(this.dragIndicator) + + ((TranslateTransform)this.dragIndicator.RenderTransform).Y + + this.dragIndicator.Height / 2; + this.UpdateDropTarget(dragItemOffset, true); + } + else + { + VisualStateManager.GoToState(this.scrollViewer, ReorderListBox.ScrollViewerNotScrollingVisualState, true); + } + } + + /// + /// Updates spacing (drop target indicators) surrounding the targeted region. + /// + /// Vertical offset into the items panel where the drag is currently targeting. + /// True if the drop-indicator transitions should be shown. + private void UpdateDropTarget(double dragItemOffset, bool showTransition) + { + Point dragPoint = ReorderListBox.GetHostCoordinates( + new Point(this.dragInterceptorRect.Left, this.dragInterceptorRect.Top + dragItemOffset)); + IEnumerable targetElements = VisualTreeHelper.FindElementsInHostCoordinates(dragPoint, this.itemsPanel); + ReorderListBoxItem targetItem = targetElements.OfType().FirstOrDefault(); + if (targetItem != null) + { + GeneralTransform targetTransform = targetItem.DragHandle.TransformToVisual(this.dragInterceptor); + Rect targetRect = targetTransform.TransformBounds(new Rect(new Point(0, 0), targetItem.DragHandle.RenderSize)); + double targetCenter = (targetRect.Top + targetRect.Bottom) / 2; + + int targetIndex = this.itemsPanel.Children.IndexOf(targetItem); + int childrenCount = this.itemsPanel.Children.Count; + bool after = dragItemOffset > targetCenter; + + ReorderListBoxItem indicatorItem = null; + if (!after && targetIndex > 0) + { + ReorderListBoxItem previousItem = (ReorderListBoxItem)this.itemsPanel.Children[targetIndex - 1]; + if (previousItem.Tag as string == ReorderListBoxItem.DropAfterIndicatorState) + { + indicatorItem = previousItem; + } + } + else if (after && targetIndex < childrenCount - 1) + { + ReorderListBoxItem nextItem = (ReorderListBoxItem)this.itemsPanel.Children[targetIndex + 1]; + if (nextItem.Tag as string == ReorderListBoxItem.DropBeforeIndicatorState) + { + indicatorItem = nextItem; + } + } + if (indicatorItem == null) + { + targetItem.DropIndicatorHeight = this.dragIndicator.Height; + string dropIndicatorState = after ? + ReorderListBoxItem.DropAfterIndicatorState : ReorderListBoxItem.DropBeforeIndicatorState; + VisualStateManager.GoToState(targetItem, dropIndicatorState, showTransition); + targetItem.Tag = dropIndicatorState; + indicatorItem = targetItem; + } + + for (int i = targetIndex - 5; i <= targetIndex + 5; i++) + { + if (i >= 0 && i < childrenCount) + { + ReorderListBoxItem nearbyItem = (ReorderListBoxItem)this.itemsPanel.Children[i]; + if (nearbyItem != indicatorItem) + { + VisualStateManager.GoToState(nearbyItem, ReorderListBoxItem.NoDropIndicatorState, showTransition); + nearbyItem.Tag = ReorderListBoxItem.NoDropIndicatorState; + } + } + } + + this.UpdateDropTargetIndex(targetItem, after); + } + } + + /// + /// Updates the targeted index -- that is the index where the item will be moved to if dropped at this point. + /// + private void UpdateDropTargetIndex(ReorderListBoxItem targetItemContainer, bool after) + { + int dragItemIndex = this.Items.IndexOf(this.dragItem); + int targetItemIndex = this.Items.IndexOf(targetItemContainer.Content); + + int newDropTargetIndex; + if (targetItemIndex == dragItemIndex) + { + newDropTargetIndex = dragItemIndex; + } + else + { + if (dragItemIndex == -1) + { + newDropTargetIndex = targetItemIndex + (after ? 1 : 0); + Debug.WriteLine(" Catched UpdateDropTargetIndex dropTargetIndex=-1 targetItemIndex=" + targetItemIndex + " dragItemIndex=" + dragItemIndex + " after=" + after); + } + else + { + newDropTargetIndex = targetItemIndex + (after ? 1 : 0) - (targetItemIndex >= dragItemIndex ? 1 : 0); + } + } + + if (newDropTargetIndex != this.dropTargetIndex) + { + this.dropTargetIndex = newDropTargetIndex; + if (dropTargetIndex == -1) + { + Debug.WriteLine("UpdateDropTargetIndex dropTargetIndex=-1 targetItemIndex=" + targetItemIndex + " dragItemIndex=" + dragItemIndex + " after=" + after); + } + else + { + Debug.WriteLine("UpdateDropTargetIndex dropTargetIndex=" + dropTargetIndex); + } + } + } + + /// + /// Hides any drop-indicators that are currently visible. + /// + private void ClearDropTarget() + { + foreach (ReorderListBoxItem itemContainer in this.itemsPanel.Children) + { + VisualStateManager.GoToState(itemContainer, ReorderListBoxItem.NoDropIndicatorState, false); + itemContainer.Tag = null; + } + } + + /// + /// Moves an item to a specified index in the source list. + /// + private bool MoveItem(object item, int toIndex) + { + object itemsSource = this.ItemsSource; + + System.Collections.IList sourceList = itemsSource as System.Collections.IList; + if (!(sourceList is System.Collections.Specialized.INotifyCollectionChanged)) + { + // If the source does not implement INotifyCollectionChanged, then there's no point in + // changing the source because changes to it will not be synchronized with the list items. + // So, just change the ListBox's view of the items. + sourceList = this.Items; + } + + int fromIndex = sourceList.IndexOf(item); + if (fromIndex != toIndex) + { + double scrollOffset = this.scrollViewer.VerticalOffset; + + Debug.WriteLine("Move item " + item + " toIndex=" + toIndex + " fromIndex=" + fromIndex); + sourceList.RemoveAt(fromIndex); + sourceList.Insert(toIndex, item); + + if (fromIndex <= scrollOffset && toIndex > scrollOffset) + { + // Correct the scroll offset for the removed item so that the list doesn't appear to jump. + this.scrollViewer.ScrollToVerticalOffset(scrollOffset - 1); + } + return true; + } + else + { + return false; + } + } + + #endregion + + #region View range detection + + /// + /// Gets the indices of the first and last items in the view based on the current scroll position. + /// + /// True to include items that are partially obscured at the top and bottom, + /// false to include only items that are completely in view. + /// Returns the index of the first item in view (or -1 if there are no items). + /// Returns the index of the last item in view (or -1 if there are no items). + public void GetViewIndexRange(bool includePartial, out int firstIndex, out int lastIndex) + { + if (this.Items.Count > 0) + { + firstIndex = 0; + lastIndex = this.Items.Count - 1; + + if (this.scrollViewer != null && this.Items.Count > 1) + { + Thickness scrollViewerPadding = new Thickness( + this.scrollViewer.BorderThickness.Left + this.scrollViewer.Padding.Left, + this.scrollViewer.BorderThickness.Top + this.scrollViewer.Padding.Top, + this.scrollViewer.BorderThickness.Right + this.scrollViewer.Padding.Right, + this.scrollViewer.BorderThickness.Bottom + this.scrollViewer.Padding.Bottom); + + GeneralTransform scrollViewerTransform = this.scrollViewer.TransformToVisual( + Application.Current.RootVisual); + Rect scrollViewerRect = scrollViewerTransform.TransformBounds( + new Rect(new Point(0, 0), this.scrollViewer.RenderSize)); + + Point topPoint = ReorderListBox.GetHostCoordinates(new Point( + scrollViewerRect.Left + scrollViewerPadding.Left, + scrollViewerRect.Top + scrollViewerPadding.Top)); + IEnumerable topElements = VisualTreeHelper.FindElementsInHostCoordinates( + topPoint, this.scrollViewer); + ReorderListBoxItem topItem = topElements.OfType().FirstOrDefault(); + if (topItem != null) + { + GeneralTransform itemTransform = topItem.TransformToVisual(Application.Current.RootVisual); + Rect itemRect = itemTransform.TransformBounds(new Rect(new Point(0, 0), topItem.RenderSize)); + + firstIndex = this.ItemContainerGenerator.IndexFromContainer(topItem); + if (!includePartial && firstIndex < this.Items.Count - 1 && + itemRect.Top < scrollViewerRect.Top && itemRect.Bottom < scrollViewerRect.Bottom) + { + firstIndex++; + } + } + + Point bottomPoint = ReorderListBox.GetHostCoordinates(new Point( + scrollViewerRect.Left + scrollViewerPadding.Left, + scrollViewerRect.Bottom - scrollViewerPadding.Bottom - 1)); + IEnumerable bottomElements = VisualTreeHelper.FindElementsInHostCoordinates( + bottomPoint, this.scrollViewer); + ReorderListBoxItem bottomItem = bottomElements.OfType().FirstOrDefault(); + if (bottomItem != null) + { + GeneralTransform itemTransform = bottomItem.TransformToVisual(Application.Current.RootVisual); + Rect itemRect = itemTransform.TransformBounds( + new Rect(new Point(0, 0), bottomItem.RenderSize)); + + lastIndex = this.ItemContainerGenerator.IndexFromContainer(bottomItem); + if (!includePartial && lastIndex > firstIndex && + itemRect.Bottom > scrollViewerRect.Bottom && itemRect.Top > scrollViewerRect.Top) + { + lastIndex--; + } + } + } + } + else + { + firstIndex = -1; + lastIndex = -1; + } + } + + #endregion + + #region Rearrange + + /// + /// Private helper class for keeping track of each item involved in a rearrange. + /// + private class RearrangeItemInfo + { + public object Item = null; + public int FromIndex = -1; + public int ToIndex = -1; + public double FromY = Double.NaN; + public double ToY = Double.NaN; + public double Height = Double.NaN; + } + + /// + /// Animates movements, insertions, or deletions in the list. + /// + /// Duration of the animation. + /// Performs the actual rearrange on the list source. + /// + /// The animations are as follows: + /// - Inserted items fade in while later items slide down to make space. + /// - Removed items fade out while later items slide up to close the gap. + /// - Moved items slide from their previous location to their new location. + /// - Moved items which move out of or in to the visible area also fade out / fade in while sliding. + /// + /// The rearrange action callback is called in the middle of the rearrange process. That + /// callback may make any number of changes to the list source, in any order. After the rearrange + /// action callback returns, the net result of all changes will be detected and included in a dynamically + /// generated rearrange animation. + /// + /// Multiple calls to this method in quick succession will be automatically queued up and executed in turn + /// to avoid any possibility of conflicts. (If simultaneous rearrange animations are desired, use a single + /// call to AnimateRearrange with a rearrange action callback that does both operations.) + /// + /// + public void AnimateRearrange(Duration animationDuration, Action rearrangeAction) + { + if (rearrangeAction == null) + { + throw new ArgumentNullException("rearrangeAction"); + } + + if (this.rearrangeCanvas == null) + { + throw new InvalidOperationException("ReorderListBox control template is missing " + + "a part required for rearrange: " + ReorderListBox.RearrangeCanvasPart); + } + + if (this.rearrangeQueue == null) + { + this.rearrangeQueue = new Queue>(); + this.scrollViewer.ScrollToVerticalOffset(this.scrollViewer.VerticalOffset); // Stop scrolling. + this.Dispatcher.BeginInvoke(() => + this.AnimateRearrangeInternal(rearrangeAction, animationDuration)); + } + else + { + this.rearrangeQueue.Enqueue(new KeyValuePair(rearrangeAction, animationDuration)); + } + } + + /// + /// Orchestrates the rearrange animation process. + /// + private void AnimateRearrangeInternal(Action rearrangeAction, Duration animationDuration) + { + // Find the indices of items in the view. Animations are optimzed to only include what is visible. + int viewFirstIndex, viewLastIndex; + this.GetViewIndexRange(true, out viewFirstIndex, out viewLastIndex); + + // Collect information about items and their positions before any changes are made. + RearrangeItemInfo[] rearrangeMap = this.BuildRearrangeMap(viewFirstIndex, viewLastIndex); + + // Call the rearrange action callback which actually makes the changes to the source list. + // Assuming the source list is properly bound, the base class will pick up the changes. + rearrangeAction(); + + this.rearrangeCanvas.Visibility = Visibility.Visible; + + // Update the layout (positions of all items) based on the changes that were just made. + this.UpdateLayout(); + + // Find the NEW last-index in view, which may have changed if the items are not constant heights + // or if the view includes the end of the list. + viewLastIndex = this.FindViewLastIndex(viewFirstIndex); + + // Collect information about the NEW items and their NEW positions, linking up to information + // about items which existed before. + RearrangeItemInfo[] rearrangeMap2 = this.BuildRearrangeMap2(rearrangeMap, + viewFirstIndex, viewLastIndex); + + // Find all the movements that need to be animated. + IEnumerable movesWithinView = rearrangeMap + .Where(rii => !Double.IsNaN(rii.FromY) && !Double.IsNaN(rii.ToY)); + IEnumerable movesOutOfView = rearrangeMap + .Where(rii => !Double.IsNaN(rii.FromY) && Double.IsNaN(rii.ToY)); + IEnumerable movesInToView = rearrangeMap2 + .Where(rii => Double.IsNaN(rii.FromY) && !Double.IsNaN(rii.ToY)); + IEnumerable visibleMoves = + movesWithinView.Concat(movesOutOfView).Concat(movesInToView); + + // Set a clip rect so the animations don't go outside the listbox. + this.rearrangeCanvas.Clip = new RectangleGeometry() { Rect = new Rect(new Point(0, 0), this.rearrangeCanvas.RenderSize) }; + + // Create the animation storyboard. + Storyboard rearrangeStoryboard = this.CreateRearrangeStoryboard(visibleMoves, animationDuration); + if (rearrangeStoryboard.Children.Count > 0) + { + // The storyboard uses an overlay canvas with item snapshots. + // While that is playing, hide the real items. + this.scrollViewer.Visibility = Visibility.Collapsed; + + rearrangeStoryboard.Completed += delegate + { + rearrangeStoryboard.Stop(); + this.rearrangeCanvas.Children.Clear(); + this.rearrangeCanvas.Visibility = Visibility.Collapsed; + this.scrollViewer.Visibility = Visibility.Visible; + + this.AnimateNextRearrange(); + }; + + this.Dispatcher.BeginInvoke(() => rearrangeStoryboard.Begin()); + } + else + { + this.rearrangeCanvas.Visibility = Visibility.Collapsed; + this.AnimateNextRearrange(); + } + } + + /// + /// Checks if there's another rearrange action waiting in the queue, and if so executes it next. + /// + private void AnimateNextRearrange() + { + if (this.rearrangeQueue.Count > 0) + { + KeyValuePair nextRearrange = this.rearrangeQueue.Dequeue(); + this.Dispatcher.BeginInvoke(() => + this.AnimateRearrangeInternal(nextRearrange.Key, nextRearrange.Value)); + } + else + { + this.rearrangeQueue = null; + } + } + + /// + /// Collects information about items and their positions before any changes are made. + /// + private RearrangeItemInfo[] BuildRearrangeMap(int viewFirstIndex, int viewLastIndex) + { + RearrangeItemInfo[] map = new RearrangeItemInfo[this.Items.Count]; + + for (int i = 0; i < map.Length; i++) + { + object item = this.Items[i]; + + RearrangeItemInfo info = new RearrangeItemInfo() + { + Item = item, + FromIndex = i, + }; + + // The precise item location is only important if it's within the view. + if (viewFirstIndex <= i && i <= viewLastIndex) + { + ReorderListBoxItem itemContainer = (ReorderListBoxItem) + this.ItemContainerGenerator.ContainerFromIndex(i); + if (itemContainer != null) + { + GeneralTransform itemTransform = itemContainer.TransformToVisual(this.rearrangeCanvas); + Point itemPoint = itemTransform.Transform(new Point(0, 0)); + info.FromY = itemPoint.Y; + info.Height = itemContainer.RenderSize.Height; + } + } + + map[i] = info; + } + + return map; + } + + /// + /// Collects information about the NEW items and their NEW positions after changes were made. + /// + private RearrangeItemInfo[] BuildRearrangeMap2(RearrangeItemInfo[] map, + int viewFirstIndex, int viewLastIndex) + { + RearrangeItemInfo[] map2 = new RearrangeItemInfo[this.Items.Count]; + + for (int i = 0; i < map2.Length; i++) + { + object item = this.Items[i]; + + // Try to find the same item in the pre-rearrange info. + RearrangeItemInfo info = map.FirstOrDefault(rii => rii.ToIndex < 0 && rii.Item == item); + if (info == null) + { + info = new RearrangeItemInfo() + { + Item = item, + }; + } + + info.ToIndex = i; + + // The precise item location is only important if it's within the view. + if (viewFirstIndex <= i && i <= viewLastIndex) + { + ReorderListBoxItem itemContainer = (ReorderListBoxItem) + this.ItemContainerGenerator.ContainerFromIndex(i); + if (itemContainer != null) + { + GeneralTransform itemTransform = itemContainer.TransformToVisual(this.rearrangeCanvas); + Point itemPoint = itemTransform.Transform(new Point(0, 0)); + info.ToY = itemPoint.Y; + info.Height = itemContainer.RenderSize.Height; + } + } + + map2[i] = info; + } + + return map2; + } + + /// + /// Finds the index of the last visible item by starting at the first index and + /// comparing the bounds of each following item to the ScrollViewer bounds. + /// + /// + /// This method is less efficient than the hit-test method used by GetViewIndexRange() above, + /// but it works when the controls haven't actually been rendered yet, while the other doesn't. + /// + private int FindViewLastIndex(int firstIndex) + { + int lastIndex = firstIndex; + + GeneralTransform scrollViewerTransform = this.scrollViewer.TransformToVisual( + Application.Current.RootVisual); + Rect scrollViewerRect = scrollViewerTransform.TransformBounds( + new Rect(new Point(0, 0), this.scrollViewer.RenderSize)); + + while (lastIndex < this.Items.Count - 1) + { + ReorderListBoxItem itemContainer = (ReorderListBoxItem) + this.ItemContainerGenerator.ContainerFromIndex(lastIndex + 1); + if (itemContainer == null) + { + break; + } + + GeneralTransform itemTransform = itemContainer.TransformToVisual( + Application.Current.RootVisual); + Rect itemRect = itemTransform.TransformBounds(new Rect(new Point(0, 0), itemContainer.RenderSize)); + itemRect.Intersect(scrollViewerRect); + if (itemRect == Rect.Empty) + { + break; + } + + lastIndex++; + } + + return lastIndex; + } + + /// + /// Creates a storyboard to animate the visible moves of a rearrange. + /// + private Storyboard CreateRearrangeStoryboard(IEnumerable visibleMoves, + Duration animationDuration) + { + Storyboard storyboard = new Storyboard(); + + ReorderListBoxItem temporaryItemContainer = null; + + foreach (RearrangeItemInfo move in visibleMoves) + { + Size itemSize = new Size(this.rearrangeCanvas.RenderSize.Width, move.Height); + + ReorderListBoxItem itemContainer = null; + if (move.ToIndex >= 0) + { + itemContainer = (ReorderListBoxItem)this.ItemContainerGenerator.ContainerFromIndex(move.ToIndex); + } + if (itemContainer == null) + { + if (temporaryItemContainer == null) + { + temporaryItemContainer = new ReorderListBoxItem(); + } + + itemContainer = temporaryItemContainer; + itemContainer.Width = itemSize.Width; + itemContainer.Height = itemSize.Height; + this.rearrangeCanvas.Children.Add(itemContainer); + this.PrepareContainerForItemOverride(itemContainer, move.Item); + itemContainer.UpdateLayout(); + } + + WriteableBitmap itemSnapshot = new WriteableBitmap((int)itemSize.Width, (int)itemSize.Height); + itemSnapshot.Render(itemContainer, null); + itemSnapshot.Invalidate(); + + Image itemImage = new Image(); + itemImage.Width = itemSize.Width; + itemImage.Height = itemSize.Height; + itemImage.Source = itemSnapshot; + itemImage.RenderTransform = new TranslateTransform(); + this.rearrangeCanvas.Children.Add(itemImage); + + if (itemContainer == temporaryItemContainer) + { + this.rearrangeCanvas.Children.Remove(itemContainer); + } + + if (!Double.IsNaN(move.FromY) && !Double.IsNaN(move.ToY)) + { + Canvas.SetTop(itemImage, move.FromY); + if (move.FromY != move.ToY) + { + DoubleAnimation moveAnimation = new DoubleAnimation(); + moveAnimation.Duration = animationDuration; + Storyboard.SetTarget(moveAnimation, itemImage.RenderTransform); + Storyboard.SetTargetProperty(moveAnimation, new PropertyPath(TranslateTransform.YProperty)); + moveAnimation.To = move.ToY - move.FromY; + storyboard.Children.Add(moveAnimation); + } + } + else if (Double.IsNaN(move.FromY) != Double.IsNaN(move.ToY)) + { + if (move.FromIndex >= 0 && move.ToIndex >= 0) + { + DoubleAnimation moveAnimation = new DoubleAnimation(); + moveAnimation.Duration = animationDuration; + Storyboard.SetTarget(moveAnimation, itemImage.RenderTransform); + Storyboard.SetTargetProperty(moveAnimation, new PropertyPath(TranslateTransform.YProperty)); + + const double animationDistance = 200; + if (!Double.IsNaN(move.FromY)) + { + Canvas.SetTop(itemImage, move.FromY); + if (move.FromIndex < move.ToIndex) + { + moveAnimation.To = animationDistance; + } + else if (move.FromIndex > move.ToIndex) + { + moveAnimation.To = -animationDistance; + } + } + else + { + Canvas.SetTop(itemImage, move.ToY); + if (move.FromIndex < move.ToIndex) + { + moveAnimation.From = -animationDistance; + } + else if (move.FromIndex > move.ToIndex) + { + moveAnimation.From = animationDistance; + } + } + + storyboard.Children.Add(moveAnimation); + } + + DoubleAnimation fadeAnimation = new DoubleAnimation(); + fadeAnimation.Duration = animationDuration; + Storyboard.SetTarget(fadeAnimation, itemImage); + Storyboard.SetTargetProperty(fadeAnimation, new PropertyPath(UIElement.OpacityProperty)); + + if (Double.IsNaN(move.FromY)) + { + itemImage.Opacity = 0.0; + fadeAnimation.To = 1.0; + Canvas.SetTop(itemImage, move.ToY); + } + else + { + itemImage.Opacity = 1.0; + fadeAnimation.To = 0.0; + Canvas.SetTop(itemImage, move.FromY); + } + + storyboard.Children.Add(fadeAnimation); + } + } + + return storyboard; + } + + #endregion + + #region Private utility methods + + /// + /// Gets host coordinates, adjusting for orientation. This is helpful when identifying what + /// controls are under a point. + /// + private static Point GetHostCoordinates(Point point) + { + PhoneApplicationFrame frame = (PhoneApplicationFrame)Application.Current.RootVisual; + switch (frame.Orientation) + { + case PageOrientation.LandscapeLeft: return new Point(frame.RenderSize.Width - point.Y, point.X); + case PageOrientation.LandscapeRight: return new Point(point.Y, frame.RenderSize.Height - point.X); + default: return point; + } + } + + #endregion + } +} diff --git a/Telegram.Controls/ReorderListBox/ReorderListBoxItem.cs b/Telegram.Controls/ReorderListBox/ReorderListBoxItem.cs new file mode 100755 index 0000000..69410e1 --- /dev/null +++ b/Telegram.Controls/ReorderListBox/ReorderListBoxItem.cs @@ -0,0 +1,248 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media.Animation; +using System.Windows.Media; + +namespace ReorderListBox +{ + /// + /// Extends ListBoxItem to support a styleable drag handle, drop-indicator spacing, + /// and visual states and transitions for dragging/dropping and enabling/disabling the reorder capability. + /// + [TemplatePart(Name = ReorderListBoxItem.DragHandlePart, Type = typeof(ContentPresenter))] + [TemplatePart(Name = ReorderListBoxItem.DropBeforeSpacePart, Type = typeof(UIElement))] + [TemplatePart(Name = ReorderListBoxItem.DropAfterSpacePart, Type = typeof(UIElement))] + [TemplateVisualState(Name = ReorderListBoxItem.ReorderDisabledState, GroupName = ReorderListBoxItem.ReorderEnabledStateGroup)] + [TemplateVisualState(Name = ReorderListBoxItem.ReorderEnabledState, GroupName = ReorderListBoxItem.ReorderEnabledStateGroup)] + [TemplateVisualState(Name = ReorderListBoxItem.NotDraggingState, GroupName = ReorderListBoxItem.DraggingStateGroup)] + [TemplateVisualState(Name = ReorderListBoxItem.DraggingState, GroupName = ReorderListBoxItem.DraggingStateGroup)] + [TemplateVisualState(Name = ReorderListBoxItem.NoDropIndicatorState, GroupName = ReorderListBoxItem.DropIndicatorStateGroup)] + [TemplateVisualState(Name = ReorderListBoxItem.DropBeforeIndicatorState, GroupName = ReorderListBoxItem.DropIndicatorStateGroup)] + [TemplateVisualState(Name = ReorderListBoxItem.DropAfterIndicatorState, GroupName = ReorderListBoxItem.DropIndicatorStateGroup)] + public class ReorderListBoxItem : ListBoxItem + { + #region Template part name constants + + public const string DragHandlePart = "DragHandle"; + public const string DropBeforeSpacePart = "DropBeforeSpace"; + public const string DropAfterSpacePart = "DropAfterSpace"; + + #endregion + + #region Visual state name constants + + public const string ReorderEnabledStateGroup = "ReorderEnabledStates"; + public const string ReorderDisabledState = "ReorderDisabled"; + public const string ReorderEnabledState = "ReorderEnabled"; + + public const string DraggingStateGroup = "DraggingStates"; + public const string NotDraggingState = "NotDragging"; + public const string DraggingState = "Dragging"; + + public const string DropIndicatorStateGroup = "DropIndicatorStates"; + public const string NoDropIndicatorState = "NoDropIndicator"; + public const string DropBeforeIndicatorState = "DropBeforeIndicator"; + public const string DropAfterIndicatorState = "DropAfterIndicator"; + + #endregion + + /// + /// Creates a new ReorderListBoxItem and sets the default style key. + /// The style key is used to locate the control template in Generic.xaml. + /// + public ReorderListBoxItem() + { + this.DefaultStyleKey = typeof(ReorderListBoxItem); + } + + #region DropIndicatorHeight DependencyProperty + + public static readonly DependencyProperty DropIndicatorHeightProperty = DependencyProperty.Register( + "DropIndicatorHeight", typeof(double), typeof(ReorderListBoxItem), + new PropertyMetadata(0.0, (d, e) => ((ReorderListBoxItem)d).OnDropIndicatorHeightChanged(e))); + + /// + /// Gets or sets the height of the drop-before and drop-after indicators. + /// The drop-indicator visual states and transitions are automatically updated to use this height. + /// + public double DropIndicatorHeight + { + get + { + return (double)this.GetValue(ReorderListBoxItem.DropIndicatorHeightProperty); + } + set + { + this.SetValue(ReorderListBoxItem.DropIndicatorHeightProperty, value); + } + } + + /// + /// Updates the drop-indicator height value for visual state and transition animations. + /// + /// + /// This is a workaround for the inability of visual states and transitions to do template binding + /// in Silverlight 3. In SL4, they could bind directly to the DropIndicatorHeight property instead. + /// + protected void OnDropIndicatorHeightChanged(DependencyPropertyChangedEventArgs e) + { + Panel rootPanel = (Panel)VisualTreeHelper.GetChild(this, 0); + VisualStateGroup vsg = ReorderListBoxItem.GetVisualStateGroup( + rootPanel, ReorderListBoxItem.DropIndicatorStateGroup); + if (vsg != null) + { + foreach (VisualState vs in vsg.States) + { + foreach (Timeline animation in vs.Storyboard.Children) + { + this.UpdateDropIndicatorAnimationHeight((double)e.NewValue, animation); + } + } + foreach (VisualTransition vt in vsg.Transitions) + { + foreach (Timeline animation in vt.Storyboard.Children) + { + this.UpdateDropIndicatorAnimationHeight((double)e.NewValue, animation); + } + } + } + } + + /// + /// Helper for the UpdateDropIndicatorAnimationHeight method. + /// + private void UpdateDropIndicatorAnimationHeight(double height, Timeline animation) + { + DoubleAnimation da = animation as DoubleAnimation; + if (da != null) + { + string targetName = Storyboard.GetTargetName(da); + PropertyPath targetPath = Storyboard.GetTargetProperty(da); + if ((targetName == ReorderListBoxItem.DropBeforeSpacePart || + targetName == ReorderListBoxItem.DropAfterSpacePart) && + targetPath != null && targetPath.Path == "Height") + { + if (da.From > 0 && da.From != height) + { + da.From = height; + } + if (da.To > 0 && da.To != height) + { + da.To = height; + } + } + } + } + + /// + /// Gets a named VisualStateGroup for a framework element. + /// + private static VisualStateGroup GetVisualStateGroup(FrameworkElement element, string groupName) + { + VisualStateGroup result = null; + System.Collections.IList groups = VisualStateManager.GetVisualStateGroups(element); + if (groups != null) + { + foreach (VisualStateGroup group in groups) + { + if (group.Name == groupName) + { + result = group; + break; + } + } + } + return result; + } + + #endregion + + #region IsReorderEnabled DependencyProperty + + public static readonly DependencyProperty IsReorderEnabledProperty = DependencyProperty.Register( + "IsReorderEnabled", typeof(bool), typeof(ReorderListBoxItem), + new PropertyMetadata(false, (d, e) => ((ReorderListBoxItem)d).OnIsReorderEnabledChanged(e))); + + /// + /// Gets or sets a value indicating whether the drag handle should be shown. + /// + public bool IsReorderEnabled + { + get + { + return (bool)this.GetValue(ReorderListBoxItem.IsReorderEnabledProperty); + } + set + { + this.SetValue(ReorderListBoxItem.IsReorderEnabledProperty, value); + } + } + + protected void OnIsReorderEnabledChanged(DependencyPropertyChangedEventArgs e) + { + string visualState = (bool)e.NewValue ? + ReorderListBoxItem.ReorderEnabledState : ReorderListBoxItem.ReorderDisabledState; + VisualStateManager.GoToState(this, visualState, true); + } + + #endregion + + #region DragHandleTemplate DependencyProperty + + public static readonly DependencyProperty DragHandleTemplateProperty = DependencyProperty.Register( + "DragHandleTemplate", typeof(DataTemplate), typeof(ReorderListBoxItem), null); + + /// + /// Gets or sets the template for the drag handle. + /// + public DataTemplate DragHandleTemplate + { + get + { + return (DataTemplate)this.GetValue(ReorderListBoxItem.DragHandleTemplateProperty); + } + set + { + this.SetValue(ReorderListBoxItem.DragHandleTemplateProperty, value); + } + } + + #endregion + + /// + /// Gets the element (control template part) that serves as a handle for dragging the item. + /// + public ContentPresenter DragHandle + { + get; + private set; + } + + /// + /// Applies the control template, checks for required template parts, and initializes visual states. + /// + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + this.DragHandle = this.GetTemplateChild(ReorderListBoxItem.DragHandlePart) as ContentPresenter; + + if (this.DragHandle == null) + { + throw new InvalidOperationException("ReorderListBoxItem must have a DragHandle ContentPresenter part."); + } + + VisualStateManager.GoToState(this, ReorderListBoxItem.ReorderDisabledState, false); + VisualStateManager.GoToState(this, ReorderListBoxItem.NotDraggingState, false); + VisualStateManager.GoToState(this, ReorderListBoxItem.NoDropIndicatorState, false); + } + } +} \ No newline at end of file diff --git a/Telegram.Controls/ScrollableTextBlock.cs b/Telegram.Controls/ScrollableTextBlock.cs new file mode 100755 index 0000000..f5f5a8b --- /dev/null +++ b/Telegram.Controls/ScrollableTextBlock.cs @@ -0,0 +1,262 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Net; +using System.Text.RegularExpressions; +using System.Windows; +using System.Windows.Controls; +using Microsoft.Phone.Tasks; + +namespace Telegram.Controls +{ + public class ScrollableTextBlock : Control + { + private const int MaxSymbolsChunk = 1024; + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register( + "Text", + typeof (string), + typeof (ScrollableTextBlock), + new PropertyMetadata(OnTextPropertyChanged)); + + private TextBlock _measureText; + + private StackPanel _stackPanel; + + public ScrollableTextBlock() + { + DefaultStyleKey = typeof (ScrollableTextBlock); + } + + public string Text + { + get { return (string) GetValue(TextProperty); } + set { SetValue(TextProperty, value); } + } + + private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((ScrollableTextBlock) d).ParseText((string) e.NewValue); + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + _stackPanel = GetTemplateChild("StackPanel") as StackPanel; + ParseText(Text); + } + + private void ParseText(string value) + { + if (string.IsNullOrEmpty(value) || _stackPanel == null) + return; + _stackPanel.Children.Clear(); + var maxTextSize = GetMaxTextSize(); + if (value.Length < maxTextSize) + { + AddTextChunk(value); + } + else + SplitText(value); + } + + private static readonly Regex HyperlinkRegex = new Regex("(?i)\\b(((?:https?://|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’]))|([a-z0-9.\\-]+(\\.ru|\\.com|\\.net|\\.org|\\.us|\\.it|\\.co\\.uk)(?![a-z0-9]))|([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]*[a-zA-Z0-9-]+))"); + + + private void AddTextChunk(string value) + { + var index = 0; + foreach (Match match in HyperlinkRegex.Matches(value)) + { + string text; + if (match.Index != index) + { + text = value.Substring(index, match.Index - index); + _stackPanel.Children.Add(GetTextElement(text)); + } + + var link = match.Value; + var flag = link.EndsWith(","); + if (flag && link.Length > 1) + link = link.Substring(0, link.Length - 1); + if (!link.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + link = "http://" + link; + + text = match.Value; + _stackPanel.Children.Add(GeHyperlinkElement(text, link)); + + index = match.Index + match.Length; + } + if (index < value.Length) + { + var textElement = GetTextElement(value.Substring(index)); + _stackPanel.Children.Add(textElement); + } + } + + private FrameworkElement GeHyperlinkElement(string text, string uri) + { + var textBlock = GetTextBlock(); + textBlock.Text = text; + textBlock.Tap += (sender, args) => + { + if (textBlock.Text.Contains("@")) + { + var task = new EmailComposeTask(); + task.To = uri.ToLowerInvariant().Replace("http://", string.Empty); + task.Show(); + + } + else + { + var task = new WebBrowserTask(); + task.URL = HttpUtility.UrlEncode(uri); + task.Show(); + } + + }; + textBlock.TextDecorations = TextDecorations.Underline; + var border = GetBackgroundBorder(); + border.Child = textBlock; + + return border; + + //var hyperlink = GetHyperlinkButton(); + //var content = GetTextBlock(); + //content.Text = text; + //hyperlink.Content = content; + //hyperlink.NavigateUri = new Uri(uri, UriKind.Absolute); + //var border = GetBackgroundBorder(); + //border.Child = hyperlink; + + //return border; + } + + private FrameworkElement GetTextElement(string text) + { + var textBlock = GetTextBlock(); + textBlock.Text = text; + var border = GetBackgroundBorder(); + border.Child = textBlock; + + return border; + } + + private static readonly Dictionary Delimiters = new Dictionary + { + {' ', ' '}, + {'.', ' '}, + {',', ' '}, + {'!', ' '}, + {'?', ' '}, + {':', ' '}, + {';', ' '}, + {']', ' '}, + {')', ' '}, + {'}', ' '}, + }; + + private void SplitText(string text) + { + while (true) + { + var symbolsCount = Math.Min(MaxSymbolsChunk, text.Length); + + var stepsBack = 0; + if (symbolsCount != text.Length) + { + if (!Delimiters.ContainsKey(text[symbolsCount - 1])) + { + for (var i = 1; i < 24 && (symbolsCount - 1 - i) >= 0; i++) + { + if (Delimiters.ContainsKey(text[symbolsCount - 1 - i])) + { + stepsBack += i; + break; + } + } + } + } + symbolsCount -= stepsBack; + + var currentChunk = text.Substring(0, symbolsCount); + + AddTextChunk(currentChunk); + + var nextChunk = text.Substring(symbolsCount, text.Length - symbolsCount); + if (nextChunk.Length > 0) + { + text = nextChunk; + continue; + } + break; + } + } + + private Size MeasureString(string text) + { + if (_measureText == null) + _measureText = GetTextBlock(); + _measureText.Text = text; + return new Size(_measureText.ActualWidth, _measureText.ActualHeight); + } + + private int GetMaxTextSize() + { + var size = MeasureString("W"); + return (int) (Width/size.Width)*(int) (2048.0/size.Height)/2; + } + + private TextBlock GetTextBlock() + { + return new TextBlock + { + TextWrapping = TextWrapping.Wrap, + FontSize = FontSize, + FontFamily = FontFamily, + FontWeight = FontWeight, + Foreground = Foreground, + }; + } + + private HyperlinkButton GetHyperlinkButton() + { + //var resources = new generic(); + + //Uri resourceLocater = new Uri("/Telegram.Controls;component/Themes/generic.xaml", UriKind.Relative); + //ResourceDictionary resourceDictionary = (ResourceDictionary)Application.LoadComponent(resourceLocater); + //groupStyle.ContainerStyle = resourceDictionary["GroupHeaderStyle"] as Style; + + return new HyperlinkButton + { + //Style = (Style) resources["HyperlinkButtonWrappingStyle"], + ClickMode = ClickMode.Release, + TargetName = "_blank", + HorizontalAlignment = HorizontalAlignment.Left, + Margin = new Thickness(0.0), + FontSize = FontSize, + FontFamily = FontFamily, + FontWeight = FontWeight, + Foreground = Foreground, + }; + } + + private Border GetBackgroundBorder() + { + return new Border + { + Background = Background, + Margin = new Thickness(0.0, -2.0, 0.0, 0.0), + Padding = new Thickness(Padding.Left, 0.0, Padding.Right, 0.0), + //BorderBrush = new SolidColorBrush(Colors.Blue), + //BorderThickness = new Thickness(1.0) + }; + } + } +} \ No newline at end of file diff --git a/Telegram.Controls/SmoothProgressBar.xaml b/Telegram.Controls/SmoothProgressBar.xaml new file mode 100755 index 0000000..37fa660 --- /dev/null +++ b/Telegram.Controls/SmoothProgressBar.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Telegram.Controls/SmoothProgressBar.xaml.cs b/Telegram.Controls/SmoothProgressBar.xaml.cs new file mode 100755 index 0000000..5a551dd --- /dev/null +++ b/Telegram.Controls/SmoothProgressBar.xaml.cs @@ -0,0 +1,110 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Controls.Primitives; +using System.Windows.Media.Animation; + +namespace Telegram.Controls +{ + public partial class SmoothProgressBar + { + private bool _useAnimations = true; + + public bool UseAnimations + { + get { return _useAnimations; } + set { _useAnimations = value; } + } + + public static readonly DependencyProperty CommandTextProperty = DependencyProperty.Register( + "CommandText", typeof (string), typeof (SmoothProgressBar), new PropertyMetadata(default(string))); + + public string CommandText + { + get { return (string) GetValue(CommandTextProperty); } + set { SetValue(CommandTextProperty, value); } + } + + public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( + "Value", typeof (double), typeof (SmoothProgressBar), new PropertyMetadata(default(double), OnValueChanged)); + + private Storyboard _previousStoryboard; + + private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var smoothProgressBar = (SmoothProgressBar) d; + if ((double) e.NewValue > 0.0) + { + smoothProgressBar.Visibility = Visibility.Visible; + } + + //smoothProgressBar.Progress.Value = (double)e.NewValue; + //if ((double)e.NewValue <= 0.0 || (double)e.NewValue >= 1.0) + //{ + // smoothProgressBar.Visibility = Visibility.Collapsed; + //} + //return; + var newValue = (double)e.NewValue; + if ((double) e.OldValue > 0.0 && newValue == 0.0) + { + newValue = 1.0; + } + + var animation = new DoubleAnimation + { + To = newValue, + Duration = new Duration(TimeSpan.FromSeconds(0.2)), + }; + + if (smoothProgressBar.UseAnimations) + { + Storyboard.SetTarget(animation, smoothProgressBar.Progress); + Storyboard.SetTargetProperty(animation, new PropertyPath(RangeBase.ValueProperty)); + var sb = new Storyboard(); + sb.Children.Add(animation); + if ((double)e.NewValue <= 0.0 || (double)e.NewValue >= 1.0) + { + sb.Completed += (sender, args) => + { + smoothProgressBar.Visibility = Visibility.Collapsed; + }; + } + + if (smoothProgressBar._previousStoryboard != null) + { + smoothProgressBar._previousStoryboard.Stop(); + } + smoothProgressBar._previousStoryboard = sb; + + sb.Begin(); + } + else + { + smoothProgressBar.Value = newValue; + if ((double)e.NewValue <= 0.0 || (double)e.NewValue >= 1.0) + { + smoothProgressBar.Visibility = Visibility.Collapsed; + } + } + } + + public double Value + { + get { return (double) GetValue(ValueProperty); } + set { SetValue(ValueProperty, value); } + } + + public SmoothProgressBar() + { + InitializeComponent(); + + Visibility = Visibility.Collapsed; + } + } +} diff --git a/Telegram.Controls/Telegram.Controls.csproj b/Telegram.Controls/Telegram.Controls.csproj new file mode 100755 index 0000000..cb8ef83 --- /dev/null +++ b/Telegram.Controls/Telegram.Controls.csproj @@ -0,0 +1,174 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {C1E19589-BD32-4DCF-AF58-393AD4D40B4E} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Telegram.Controls + Telegram.Controls + v4.0 + $(TargetFrameworkVersion) + WindowsPhone71 + Silverlight + false + true + true + ..\ + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + bin\Debug Private Beta\ + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + full + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + bin\Release Private Beta\ + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + ..\packages\Coding4Fun.Toolkit.Controls.2.0.7\lib\wp71\Coding4Fun.Toolkit.Controls.dll + + + ..\Libraries\LayoutTransformer.dll + + + + + ..\packages\WPtoolkit.4.2013.08.16\lib\sl4-windowsphone71\Microsoft.Phone.Controls.Toolkit.dll + + + + + + + + + + + + + + + + + FlipCounter.xaml + + + FlipPanel.xaml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SmoothProgressBar.xaml + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Telegram.Controls/Themes/generic.xaml b/Telegram.Controls/Themes/generic.xaml new file mode 100755 index 0000000..77ef371 --- /dev/null +++ b/Telegram.Controls/Themes/generic.xaml @@ -0,0 +1,1036 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Telegram.Controls/Toolkit.Content/ApplicationBar.Add.png b/Telegram.Controls/Toolkit.Content/ApplicationBar.Add.png new file mode 100755 index 0000000..4b524d6 Binary files /dev/null and b/Telegram.Controls/Toolkit.Content/ApplicationBar.Add.png differ diff --git a/Telegram.Controls/Toolkit.Content/ApplicationBar.Cancel.png b/Telegram.Controls/Toolkit.Content/ApplicationBar.Cancel.png new file mode 100755 index 0000000..4dd724f Binary files /dev/null and b/Telegram.Controls/Toolkit.Content/ApplicationBar.Cancel.png differ diff --git a/Telegram.Controls/Toolkit.Content/ApplicationBar.Check.png b/Telegram.Controls/Toolkit.Content/ApplicationBar.Check.png new file mode 100755 index 0000000..7a07466 Binary files /dev/null and b/Telegram.Controls/Toolkit.Content/ApplicationBar.Check.png differ diff --git a/Telegram.Controls/Toolkit.Content/ApplicationBar.Delete.png b/Telegram.Controls/Toolkit.Content/ApplicationBar.Delete.png new file mode 100755 index 0000000..95bb16d Binary files /dev/null and b/Telegram.Controls/Toolkit.Content/ApplicationBar.Delete.png differ diff --git a/Telegram.Controls/Toolkit.Content/ApplicationBar.Select.png b/Telegram.Controls/Toolkit.Content/ApplicationBar.Select.png new file mode 100755 index 0000000..995deaa Binary files /dev/null and b/Telegram.Controls/Toolkit.Content/ApplicationBar.Select.png differ diff --git a/Telegram.Controls/Triggers/CompressionTrigger.cs b/Telegram.Controls/Triggers/CompressionTrigger.cs new file mode 100755 index 0000000..8463d91 --- /dev/null +++ b/Telegram.Controls/Triggers/CompressionTrigger.cs @@ -0,0 +1,96 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Interactivity; + +namespace Telegram.Controls.Triggers +{ + public class CompressionTrigger : TriggerBase + { + public static DependencyProperty IsDisabledProperty = DependencyProperty.Register("IsDisabled", typeof(bool), typeof(CompressionTrigger), null); + + public bool IsDisabled + { + get { return (bool)GetValue(IsDisabledProperty); } + set { SetValue(IsDisabledProperty, value); } + } + + public static DependencyProperty CompressionTypeProperty = DependencyProperty.Register("CompressionType", typeof(CompressionType), typeof(CompressionTrigger), null); + + public CompressionType CompressionType + { + get { return (CompressionType)GetValue(CompressionTypeProperty); } + set { SetValue(CompressionTypeProperty, value); } + } + + protected override void OnAttached() + { + base.OnAttached(); + + AssociatedObject.Compression += AssociatedObject_Compression; + } + + protected override void OnDetaching() + { + AssociatedObject.Compression -= AssociatedObject_Compression; + + base.OnDetaching(); + } + + private void AssociatedObject_Compression(object sender, CompressionEventArgs args) + { + if (!IsDisabled + && args.Type == CompressionType) + { + InvokeActions(null); + } + } + } + + public class CompressionTrigger2 : TriggerBase + { + public static DependencyProperty IsDisabledProperty = DependencyProperty.Register("IsDisabled", typeof(bool), typeof(CompressionTrigger2), null); + + public bool IsDisabled + { + get { return (bool)GetValue(IsDisabledProperty); } + set { SetValue(IsDisabledProperty, value); } + } + + public static DependencyProperty CompressionTypeProperty = DependencyProperty.Register("CompressionType", typeof(CompressionType), typeof(CompressionTrigger2), null); + + public CompressionType CompressionType + { + get { return (CompressionType)GetValue(CompressionTypeProperty); } + set { SetValue(CompressionTypeProperty, value); } + } + + protected override void OnAttached() + { + base.OnAttached(); + + AssociatedObject.Compression += AssociatedObject_Compression; + } + + protected override void OnDetaching() + { + AssociatedObject.Compression -= AssociatedObject_Compression; + + base.OnDetaching(); + } + + private void AssociatedObject_Compression(object sender, CompressionEventArgs args) + { + if (!IsDisabled + && args.Type == CompressionType) + { + InvokeActions(null); + } + } + } +} diff --git a/Telegram.Controls/UnreadCounter.xaml b/Telegram.Controls/UnreadCounter.xaml new file mode 100755 index 0000000..b9b5305 --- /dev/null +++ b/Telegram.Controls/UnreadCounter.xaml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/Telegram.Controls/UnreadCounter.xaml.cs b/Telegram.Controls/UnreadCounter.xaml.cs new file mode 100755 index 0000000..3fa50e3 --- /dev/null +++ b/Telegram.Controls/UnreadCounter.xaml.cs @@ -0,0 +1,73 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Globalization; +using System.Windows; +using System.Windows.Media; + +namespace Telegram.Controls +{ + public partial class UnreadCounter + { + public static readonly DependencyProperty BorderBackgroundProperty = DependencyProperty.Register( + "BorderBackground", typeof (Brush), typeof (UnreadCounter), new PropertyMetadata(default(Brush), OnBorderBackgroundChanged)); + + private static void OnBorderBackgroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var unreadCounter = d as UnreadCounter; + if (unreadCounter != null) + { + unreadCounter.Border.Background = (Brush) e.NewValue; + } + } + + public Brush BorderBackground + { + get { return (Brush) GetValue(BorderBackgroundProperty); } + set { SetValue(BorderBackgroundProperty, value); } + } + + public static readonly DependencyProperty CounterProperty = DependencyProperty.Register( + "Counter", typeof(int), typeof(UnreadCounter), new PropertyMetadata(OnCounterChanged)); + + private static void OnCounterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var unreadCounter = d as UnreadCounter; + if (unreadCounter != null) + { + var counter = (int)e.NewValue; + + unreadCounter.Visibility = counter <= 0 ? Visibility.Collapsed : Visibility.Visible; + if (counter < 1000) + { + unreadCounter.CounterText.Text = counter.ToString(CultureInfo.InvariantCulture); + } + else + { + + unreadCounter.CounterText.Text = counter / 1000 + "K"; + } + } + } + + public int Counter + { + get { return (int)GetValue(CounterProperty); } + set { SetValue(CounterProperty, value); } + } + + public UnreadCounter() + { + InitializeComponent(); + + Background = (Brush) Resources["PhoneAccentBrush"]; + + Visibility = Visibility.Collapsed; + CounterText.Text = null; + } + } +} diff --git a/Telegram.Controls/Utils/Language.cs b/Telegram.Controls/Utils/Language.cs new file mode 100755 index 0000000..5cf5939 --- /dev/null +++ b/Telegram.Controls/Utils/Language.cs @@ -0,0 +1,109 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using System.Text; + +namespace Telegram.Controls.Utils +{ + public static class Language + { + private static readonly Dictionary _ruEnTable = new Dictionary + { + {'а', "a"}, {'б', "b"}, + {'в', "v"}, {'г', "g"}, + {'д', "d"}, {'е', "e"}, + {'ё', "e"}, {'ж', "zh"}, + {'з', "z"}, {'и', "i"}, + {'й', "j"}, {'к', "k"}, + {'л', "l"}, {'м', "m"}, + {'н', "n"}, {'о', "o"}, + {'п', "p"}, {'р', "r"}, + {'с', "s"}, {'т', "t"}, + {'у', "u"}, {'ф', "f"}, + {'х', "kh"}, {'ц', "tc"}, + {'ч', "ch"}, {'ш', "sh"}, + {'щ', "shch"}, {'ъ', ""}, + {'ы', "y"}, {'ь', ""}, + {'э', "e"}, {'ю', "iu"}, + {'я', "ia"} + }; + + private static readonly Dictionary _enRuTable = new Dictionary + { + {'a', "а"}, {'b', "б"}, + {'c', "ц"}, {'d', "д"}, + {'e', "е"}, {'f', "ф"}, + {'g', "г"}, {'h', "х"}, + {'i', "и"}, {'j', "й"}, + {'k', "к"}, {'l', "л"}, + {'m', "м"}, {'n', "н"}, + {'o', "о"}, {'p', "п"}, + {'q', "к"}, {'r', "р"}, + {'s', "с"}, {'t', "т"}, + {'u', "ю"}, {'v', "в"}, + {'w', "в"}, {'x', "х"}, + {'y', "й"}, {'z', "з"} + }; + + public static string Transliterate(string str) + { + var enCount = 0; + var ruCount = 0; + var count = 0; + const int maxCount = 7; + foreach (var alpha in str) + { + if (count > maxCount) break; + if (_enRuTable.ContainsKey(alpha)) + { + enCount++; + } + else if (_ruEnTable.ContainsKey(alpha)) + { + ruCount++; + } + count++; + } + + if (enCount > ruCount) + { + return TransliterateToRussian(str); + } + + return TransliterateToEnglish(str); + } + + public static string TransliterateToRussian(string str) + { + var enStr = new StringBuilder(); + foreach (var alpha in str) + { + if (_enRuTable.ContainsKey(alpha)) + { + enStr.Append(_enRuTable[alpha]); + } + } + + return enStr.ToString(); + } + + public static string TransliterateToEnglish(string str) + { + var enStr = new StringBuilder(); + foreach (var alpha in str) + { + if (_ruEnTable.ContainsKey(alpha)) + { + enStr.Append(_ruEnTable[alpha]); + } + } + + return enStr.ToString(); + } + } +} diff --git a/Telegram.Controls/ValidationTextBox.cs b/Telegram.Controls/ValidationTextBox.cs new file mode 100755 index 0000000..365a08d --- /dev/null +++ b/Telegram.Controls/ValidationTextBox.cs @@ -0,0 +1,42 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeniy Nadymov, 2013-2018. +// +using System.Windows; +using System.Windows.Controls; + +namespace Telegram.Controls +{ + public class ValidationTextBox : TextBox + { + public ValidationTextBox() + { + DefaultStyleKey = typeof(ValidationTextBox); + } + + public static readonly DependencyProperty HasErrorProperty = DependencyProperty.Register( + "HasError", typeof (bool), typeof (ValidationTextBox), new PropertyMetadata(default(bool), OnHasErrorChanged)); + + private static void OnHasErrorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var validationTextBox = (ValidationTextBox)d; + if ((bool)e.NewValue) + { + VisualStateManager.GoToState(validationTextBox, "Invalid", true); + } + else + { + VisualStateManager.GoToState(validationTextBox, "Valid", true); + } + } + + public bool HasError + { + get { return (bool) GetValue(HasErrorProperty); } + set { SetValue(HasErrorProperty, value); } + } + } +} diff --git a/Telegram.Controls/WatermarkTextBox.cs b/Telegram.Controls/WatermarkTextBox.cs new file mode 100755 index 0000000..d6a0fa1 --- /dev/null +++ b/Telegram.Controls/WatermarkTextBox.cs @@ -0,0 +1,194 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using Telegram.Controls.Helpers; + +namespace Telegram.Controls +{ + public class WatermarkedTextBox : TextBox + { + public static readonly DependencyProperty InlineWatermarkProperty = DependencyProperty.Register( + "InlineWatermark", typeof (string), typeof (WatermarkedTextBox), new PropertyMetadata(default(string), OnInlineWatermarkPropertyChanged)); + + private static void OnInlineWatermarkPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var textBox = d as WatermarkedTextBox; + if (textBox != null) + { + SetInlineWatermarkPosition(textBox); + } + } + + private static void SetInlineWatermarkPosition(WatermarkedTextBox textBox) + { + var text = textBox.Text ?? string.Empty; + if (textBox._watermarkInlineContentBorder != null) + { + var measuredText = text; + + var rect = textBox.GetRectFromCharacterIndex(measuredText.Length); +#if DEBUG + //Deployment.Current.Dispatcher.BeginInvoke(() => MessageBox.Show("'" + text + "' " + text.Length + " " + rect)); +#endif + + //textBox._watermarkInlineContentBorder.Margin = new Thickness(textBox.Margin.Left, textBox.Margin.Top, textBox.ActualWidth - rect.X - 15.0, textBox.Margin.Bottom); + //textBox.GetRectFromCharacterIndex(0, ) + var delta = !measuredText.EndsWith(" ") && measuredText.Length > 0 ? rect.X - textBox.GetRectFromCharacterIndex(measuredText.Length - 1).X : 0.0; + textBox._watermarkInlineContentBorder.RenderTransform = new TranslateTransform { X = rect.X + delta, Y = 0.0 }; + } + } + + public string InlineWatermark + { + get { return (string) GetValue(InlineWatermarkProperty); } + set { SetValue(InlineWatermarkProperty, value); } + } + + public static readonly DependencyProperty TextScaleFactorProperty = DependencyProperty.Register( + "TextScaleFactor", typeof(double), typeof(WatermarkedTextBox), new PropertyMetadata(1.0, OnTextScaleFactorChanged)); + + private static void OnTextScaleFactorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var textBox = (WatermarkedTextBox)d; + if (textBox != null && textBox._contentElement != null) + { + var opacity = textBox._watermarkInlineContent.Opacity; + textBox._watermarkInlineContent.Opacity = 0.0; + textBox.FontSize = textBox._defaultFontSize * (double)e.NewValue; + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + textBox._watermarkInlineContent.Opacity = opacity; + SetInlineWatermarkPosition(textBox); + }); + } + } + + private double _defaultFontSize; + + public double TextScaleFactor + { + get { return (double)GetValue(TextScaleFactorProperty); } + set { SetValue(TextScaleFactorProperty, value); } + } + + + private ContentControl _watermarkContent; + + private ContentControl _watermarkInlineContent; + + private ContentControl _contentElement; + + public static readonly DependencyProperty WatermarkForegroundProperty = DependencyProperty.Register( + "WatermarkForeground", typeof (Brush), typeof (WatermarkedTextBox), new PropertyMetadata(default(Brush))); + + public Brush WatermarkForeground + { + get { return (Brush) GetValue(WatermarkForegroundProperty); } + set { SetValue(WatermarkForegroundProperty, value); } + } + + public static readonly DependencyProperty WatermarkProperty = + DependencyProperty.Register("Watermark", typeof(object), typeof(WatermarkedTextBox), new PropertyMetadata(OnWatermarkPropertyChanged)); + + public static readonly DependencyProperty WatermarkStyleProperty = + DependencyProperty.Register("WatermarkStyle", typeof(Style), typeof(WatermarkedTextBox), null); + + public Style WatermarkStyle + { + get { return GetValue(WatermarkStyleProperty) as Style; } + set { SetValue(WatermarkStyleProperty, value); } + } + + public object Watermark + { + get { return GetValue(WatermarkProperty); } + set { SetValue(WatermarkProperty, value); } + } + + private readonly DependencyPropertyChangedListener _listener; + private Border _watermarkInlineContentBorder; + + public WatermarkedTextBox() + { + DefaultStyleKey = typeof(WatermarkedTextBox); + + _listener = DependencyPropertyChangedListener.Create(this, "Text"); + _listener.ValueChanged += OnTextChanged; + } + + private void OnTextChanged(object sender, DependencyPropertyValueChangedEventArgs args) + { + if (_watermarkContent != null) + { + _watermarkContent.Opacity = !string.IsNullOrEmpty(Text) ? 0.0 : 0.5; + } + + if (_watermarkInlineContent != null) + { + _watermarkInlineContent.Opacity = !string.IsNullOrEmpty(Text) ? 0.5 : 0.0; + } + //var text = Text ?? string.Empty; + //if (_watermarkInlineContentBorder != null) + //{ + // var rect = GetRectFromCharacterIndex(text.Length); + // _watermarkInlineContentBorder.RenderTransform = new TranslateTransform { X = rect.X - 12.0, Y = rect.Y - rect.Height / 2.0 - 8.0 }; + //} + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + _defaultFontSize = FontSize; + if (TextScaleFactor > 1.0) + { + FontSize = _defaultFontSize*TextScaleFactor; + } + + _watermarkContent = GetTemplateChild("WatermarkContent") as ContentControl; + _watermarkInlineContent = GetTemplateChild("WatermarkInlineContent") as ContentControl; + _watermarkInlineContentBorder = GetTemplateChild("WatermarkInlineContentBorder") as Border; + _contentElement = GetTemplateChild("ContentElement") as ContentControl; + + if (_watermarkContent != null) + { + DetermineWatermarkContentVisibility(); + } + } + + protected override void OnGotFocus(RoutedEventArgs e) + { + DetermineWatermarkContentVisibility(); + base.OnGotFocus(e); + } + + protected override void OnLostFocus(RoutedEventArgs e) + { + DetermineWatermarkContentVisibility(); + base.OnLostFocus(e); + } + + private static void OnWatermarkPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) + { + var watermarkTextBox = sender as WatermarkedTextBox; + if (watermarkTextBox != null && watermarkTextBox._watermarkContent != null) + { + watermarkTextBox.DetermineWatermarkContentVisibility(); + } + } + + private void DetermineWatermarkContentVisibility() + { + _watermarkContent.Opacity = string.IsNullOrEmpty(Text) ? 0.5 : 0.0; + } + } +} diff --git a/Telegram.Controls/packages.config b/Telegram.Controls/packages.config new file mode 100755 index 0000000..ca3b2b4 --- /dev/null +++ b/Telegram.Controls/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Telegram.EmojiPanel.WP8/Properties/AssemblyInfo.cs b/Telegram.EmojiPanel.WP8/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..fbc34e9 --- /dev/null +++ b/Telegram.EmojiPanel.WP8/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("Telegram.EmojiPanel.WP8")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Telegram.EmojiPanel.WP8")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[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("8223db37-4a07-4e16-91a1-b28e822c9dc0")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/Telegram.EmojiPanel.WP8/Telegram.EmojiPanel.WP8.csproj b/Telegram.EmojiPanel.WP8/Telegram.EmojiPanel.WP8.csproj new file mode 100755 index 0000000..ab853a2 --- /dev/null +++ b/Telegram.EmojiPanel.WP8/Telegram.EmojiPanel.WP8.csproj @@ -0,0 +1,2887 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {8223DB37-4A07-4E16-91A1-B28E822C9DC0} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Telegram.EmojiPanel + Telegram.EmojiPanel + WindowsPhone + v8.0 + $(TargetFrameworkVersion) + false + true + 11.0 + true + ..\ + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\x86\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\x86\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8 + true + true + prompt + 4 + + + true + full + false + Bin\ARM\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8 + true + true + prompt + 4 + + + pdbonly + true + Bin\ARM\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8 + true + true + prompt + 4 + + + + BrowserNavigationService.cs + + + Controls\Emoji\EmojiControl.xaml.cs + EmojiControl.xaml + + + Controls\Emoji\EmojiData.cs + + + Controls\Emoji\EmojiSpriteItem.cs + + + Controls\Utilites\DelayedExecutor.cs + + + Controls\Utilites\Helpers.cs + + + Controls\Utilites\MyListItemBase.cs + + + Controls\Utilites\MyVirtualizingPanel.cs + + + Controls\Utilites\VirtSegment.cs + + + Controls\Utilites\VListItemBase.cs + + + TelegramRichTextBox.cs + + + TestScrollableTextBlock.cs + + + + + + Controls\Emoji\EmojiControl.xaml + MSBuild:Compile + Designer + + + Themes\generic.xaml + MSBuild:Compile + Designer + + + + + Assets\emoji.abc-WXGA.png + + + Assets\emoji.backspace-WXGA.png + + + Assets\emoji.category.1-WXGA.png + + + Assets\emoji.category.2-WXGA.png + + + Assets\emoji.category.3-WXGA.png + + + Assets\emoji.category.4-WXGA.png + + + Assets\emoji.category.5-WXGA.png + + + Assets\emoji.recent-WXGA.png + + + Assets\Emoji\Separated\002320E3.png + + + Assets\Emoji\Separated\003020E3.png + + + Assets\Emoji\Separated\003120E3.png + + + Assets\Emoji\Separated\003220E3.png + + + Assets\Emoji\Separated\003320E3.png + + + Assets\Emoji\Separated\003420E3.png + + + Assets\Emoji\Separated\003520E3.png + + + Assets\Emoji\Separated\003620E3.png + + + Assets\Emoji\Separated\003720E3.png + + + Assets\Emoji\Separated\003820E3.png + + + Assets\Emoji\Separated\003920E3.png + + + Assets\Emoji\Separated\00a9.png + + + Assets\Emoji\Separated\00ae.png + + + Assets\Emoji\Separated\203C.png + + + Assets\Emoji\Separated\2049.png + + + Assets\Emoji\Separated\2122.png + + + Assets\Emoji\Separated\2139.png + + + Assets\Emoji\Separated\2194.png + + + Assets\Emoji\Separated\2195.png + + + Assets\Emoji\Separated\2196.png + + + Assets\Emoji\Separated\2197.png + + + Assets\Emoji\Separated\2198.png + + + Assets\Emoji\Separated\2199.png + + + Assets\Emoji\Separated\21A9.png + + + Assets\Emoji\Separated\21AA.png + + + Assets\Emoji\Separated\231A.png + + + Assets\Emoji\Separated\231B.png + + + Assets\Emoji\Separated\23e9.png + + + Assets\Emoji\Separated\23ea.png + + + Assets\Emoji\Separated\23eb.png + + + Assets\Emoji\Separated\23ec.png + + + Assets\Emoji\Separated\23f0.png + + + Assets\Emoji\Separated\23f3.png + + + Assets\Emoji\Separated\24C2.png + + + Assets\Emoji\Separated\25AA.png + + + Assets\Emoji\Separated\25AB.png + + + Assets\Emoji\Separated\25B6.png + + + Assets\Emoji\Separated\25C0.png + + + Assets\Emoji\Separated\25FB.png + + + Assets\Emoji\Separated\25FC.png + + + Assets\Emoji\Separated\25FD.png + + + Assets\Emoji\Separated\25FE.png + + + Assets\Emoji\Separated\2600.png + + + Assets\Emoji\Separated\2601.png + + + Assets\Emoji\Separated\260E.png + + + Assets\Emoji\Separated\2611.png + + + Assets\Emoji\Separated\2614.png + + + Assets\Emoji\Separated\2615.png + + + Assets\Emoji\Separated\261D.png + + + Assets\Emoji\Separated\263A.png + + + Assets\Emoji\Separated\2648.png + + + Assets\Emoji\Separated\2649.png + + + Assets\Emoji\Separated\264A.png + + + Assets\Emoji\Separated\264B.png + + + Assets\Emoji\Separated\264C.png + + + Assets\Emoji\Separated\264D.png + + + Assets\Emoji\Separated\264E.png + + + Assets\Emoji\Separated\264F.png + + + Assets\Emoji\Separated\2650.png + + + Assets\Emoji\Separated\2651.png + + + Assets\Emoji\Separated\2652.png + + + Assets\Emoji\Separated\2653.png + + + Assets\Emoji\Separated\2660.png + + + Assets\Emoji\Separated\2663.png + + + Assets\Emoji\Separated\2665.png + + + Assets\Emoji\Separated\2666.png + + + Assets\Emoji\Separated\2668.png + + + Assets\Emoji\Separated\267B.png + + + Assets\Emoji\Separated\267F.png + + + Assets\Emoji\Separated\2693.png + + + Assets\Emoji\Separated\26A0.png + + + Assets\Emoji\Separated\26A1.png + + + Assets\Emoji\Separated\26AA.png + + + Assets\Emoji\Separated\26AB.png + + + Assets\Emoji\Separated\26BD.png + + + Assets\Emoji\Separated\26BE.png + + + Assets\Emoji\Separated\26C4.png + + + Assets\Emoji\Separated\26C5.png + + + Assets\Emoji\Separated\26ce.png + + + Assets\Emoji\Separated\26D4.png + + + Assets\Emoji\Separated\26EA.png + + + Assets\Emoji\Separated\26F2.png + + + Assets\Emoji\Separated\26F3.png + + + Assets\Emoji\Separated\26F5.png + + + Assets\Emoji\Separated\26FA.png + + + Assets\Emoji\Separated\26FD.png + + + Assets\Emoji\Separated\2702.png + + + Assets\Emoji\Separated\2705.png + + + Assets\Emoji\Separated\2708.png + + + Assets\Emoji\Separated\2709.png + + + Assets\Emoji\Separated\270a.png + + + Assets\Emoji\Separated\270b.png + + + Assets\Emoji\Separated\270C.png + + + Assets\Emoji\Separated\270F.png + + + Assets\Emoji\Separated\2712.png + + + Assets\Emoji\Separated\2714.png + + + Assets\Emoji\Separated\2716.png + + + Assets\Emoji\Separated\2728.png + + + Assets\Emoji\Separated\2733.png + + + Assets\Emoji\Separated\2734.png + + + Assets\Emoji\Separated\2744.png + + + Assets\Emoji\Separated\2747.png + + + Assets\Emoji\Separated\274c.png + + + Assets\Emoji\Separated\274e.png + + + Assets\Emoji\Separated\2753.png + + + Assets\Emoji\Separated\2754.png + + + Assets\Emoji\Separated\2755.png + + + Assets\Emoji\Separated\2757.png + + + Assets\Emoji\Separated\2764.png + + + Assets\Emoji\Separated\2795.png + + + Assets\Emoji\Separated\2796.png + + + Assets\Emoji\Separated\2797.png + + + Assets\Emoji\Separated\27A1.png + + + Assets\Emoji\Separated\27b0.png + + + Assets\Emoji\Separated\27bf.png + + + Assets\Emoji\Separated\2934.png + + + Assets\Emoji\Separated\2935.png + + + Assets\Emoji\Separated\2B05.png + + + Assets\Emoji\Separated\2B06.png + + + Assets\Emoji\Separated\2B07.png + + + Assets\Emoji\Separated\2B1B.png + + + Assets\Emoji\Separated\2B1C.png + + + Assets\Emoji\Separated\2B50.png + + + Assets\Emoji\Separated\2B55.png + + + Assets\Emoji\Separated\3030.png + + + Assets\Emoji\Separated\303D.png + + + Assets\Emoji\Separated\3297.png + + + Assets\Emoji\Separated\3299.png + + + Assets\Emoji\Separated\D83CDC04.png + + + Assets\Emoji\Separated\D83CDCCF.png + + + Assets\Emoji\Separated\D83CDD70.png + + + Assets\Emoji\Separated\D83CDD71.png + + + Assets\Emoji\Separated\D83CDD7E.png + + + Assets\Emoji\Separated\D83CDD7F.png + + + Assets\Emoji\Separated\D83CDD8E.png + + + Assets\Emoji\Separated\D83CDD91.png + + + Assets\Emoji\Separated\D83CDD92.png + + + Assets\Emoji\Separated\D83CDD93.png + + + Assets\Emoji\Separated\D83CDD94.png + + + Assets\Emoji\Separated\D83CDD95.png + + + Assets\Emoji\Separated\D83CDD96.png + + + Assets\Emoji\Separated\D83CDD97.png + + + Assets\Emoji\Separated\D83CDD98.png + + + Assets\Emoji\Separated\D83CDD99.png + + + Assets\Emoji\Separated\D83CDD9A.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDF3.png + + + Assets\Emoji\Separated\D83CDDE9D83CDDEA.png + + + Assets\Emoji\Separated\D83CDDEAD83CDDF8.png + + + Assets\Emoji\Separated\D83CDDEBD83CDDF7.png + + + Assets\Emoji\Separated\D83CDDECD83CDDE7.png + + + Assets\Emoji\Separated\D83CDDEED83CDDF9.png + + + Assets\Emoji\Separated\D83CDDEFD83CDDF5.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDF7.png + + + Assets\Emoji\Separated\D83CDDF7D83CDDFA.png + + + Assets\Emoji\Separated\D83CDDFAD83CDDF8.png + + + Assets\Emoji\Separated\D83CDE01.png + + + Assets\Emoji\Separated\D83CDE02.png + + + Assets\Emoji\Separated\D83CDE1A.png + + + Assets\Emoji\Separated\D83CDE2F.png + + + Assets\Emoji\Separated\D83CDE32.png + + + Assets\Emoji\Separated\D83CDE33.png + + + Assets\Emoji\Separated\D83CDE34.png + + + Assets\Emoji\Separated\D83CDE35.png + + + Assets\Emoji\Separated\D83CDE36.png + + + Assets\Emoji\Separated\D83CDE37.png + + + Assets\Emoji\Separated\D83CDE38.png + + + Assets\Emoji\Separated\D83CDE39.png + + + Assets\Emoji\Separated\D83CDE3A.png + + + Assets\Emoji\Separated\D83CDE50.png + + + Assets\Emoji\Separated\D83CDE51.png + + + Assets\Emoji\Separated\D83CDF00.png + + + Assets\Emoji\Separated\D83CDF01.png + + + Assets\Emoji\Separated\D83CDF02.png + + + Assets\Emoji\Separated\D83CDF03.png + + + Assets\Emoji\Separated\D83CDF04.png + + + Assets\Emoji\Separated\D83CDF05.png + + + Assets\Emoji\Separated\D83CDF06.png + + + Assets\Emoji\Separated\D83CDF07.png + + + Assets\Emoji\Separated\D83CDF08.png + + + Assets\Emoji\Separated\D83CDF09.png + + + Assets\Emoji\Separated\D83CDF0A.png + + + Assets\Emoji\Separated\D83CDF0B.png + + + Assets\Emoji\Separated\D83CDF0C.png + + + Assets\Emoji\Separated\D83CDF0D.png + + + Assets\Emoji\Separated\D83CDF0E.png + + + Assets\Emoji\Separated\D83CDF0F.png + + + Assets\Emoji\Separated\D83CDF10.png + + + Assets\Emoji\Separated\D83CDF11.png + + + Assets\Emoji\Separated\D83CDF12.png + + + Assets\Emoji\Separated\D83CDF13.png + + + Assets\Emoji\Separated\D83CDF14.png + + + Assets\Emoji\Separated\D83CDF15.png + + + Assets\Emoji\Separated\D83CDF16.png + + + Assets\Emoji\Separated\D83CDF17.png + + + Assets\Emoji\Separated\D83CDF18.png + + + Assets\Emoji\Separated\D83CDF19.png + + + Assets\Emoji\Separated\D83CDF1A.png + + + Assets\Emoji\Separated\D83CDF1B.png + + + Assets\Emoji\Separated\D83CDF1C.png + + + Assets\Emoji\Separated\D83CDF1D.png + + + Assets\Emoji\Separated\D83CDF1E.png + + + Assets\Emoji\Separated\D83CDF1F.png + + + Assets\Emoji\Separated\D83CDF20.png + + + Assets\Emoji\Separated\D83CDF30.png + + + Assets\Emoji\Separated\D83CDF31.png + + + Assets\Emoji\Separated\D83CDF32.png + + + Assets\Emoji\Separated\D83CDF33.png + + + Assets\Emoji\Separated\D83CDF34.png + + + Assets\Emoji\Separated\D83CDF35.png + + + Assets\Emoji\Separated\D83CDF37.png + + + Assets\Emoji\Separated\D83CDF38.png + + + Assets\Emoji\Separated\D83CDF39.png + + + Assets\Emoji\Separated\D83CDF3A.png + + + Assets\Emoji\Separated\D83CDF3B.png + + + Assets\Emoji\Separated\D83CDF3C.png + + + Assets\Emoji\Separated\D83CDF3D.png + + + Assets\Emoji\Separated\D83CDF3E.png + + + Assets\Emoji\Separated\D83CDF3F.png + + + Assets\Emoji\Separated\D83CDF40.png + + + Assets\Emoji\Separated\D83CDF41.png + + + Assets\Emoji\Separated\D83CDF42.png + + + Assets\Emoji\Separated\D83CDF43.png + + + Assets\Emoji\Separated\D83CDF44.png + + + Assets\Emoji\Separated\D83CDF45.png + + + Assets\Emoji\Separated\D83CDF46.png + + + Assets\Emoji\Separated\D83CDF47.png + + + Assets\Emoji\Separated\D83CDF48.png + + + Assets\Emoji\Separated\D83CDF49.png + + + Assets\Emoji\Separated\D83CDF4A.png + + + Assets\Emoji\Separated\D83CDF4B.png + + + Assets\Emoji\Separated\D83CDF4C.png + + + Assets\Emoji\Separated\D83CDF4D.png + + + Assets\Emoji\Separated\D83CDF4E.png + + + Assets\Emoji\Separated\D83CDF4F.png + + + Assets\Emoji\Separated\D83CDF50.png + + + Assets\Emoji\Separated\D83CDF51.png + + + Assets\Emoji\Separated\D83CDF52.png + + + Assets\Emoji\Separated\D83CDF53.png + + + Assets\Emoji\Separated\D83CDF54.png + + + Assets\Emoji\Separated\D83CDF55.png + + + Assets\Emoji\Separated\D83CDF56.png + + + Assets\Emoji\Separated\D83CDF57.png + + + Assets\Emoji\Separated\D83CDF58.png + + + Assets\Emoji\Separated\D83CDF59.png + + + Assets\Emoji\Separated\D83CDF5A.png + + + Assets\Emoji\Separated\D83CDF5B.png + + + Assets\Emoji\Separated\D83CDF5C.png + + + Assets\Emoji\Separated\D83CDF5D.png + + + Assets\Emoji\Separated\D83CDF5E.png + + + Assets\Emoji\Separated\D83CDF5F.png + + + Assets\Emoji\Separated\D83CDF60.png + + + Assets\Emoji\Separated\D83CDF61.png + + + Assets\Emoji\Separated\D83CDF62.png + + + Assets\Emoji\Separated\D83CDF63.png + + + Assets\Emoji\Separated\D83CDF64.png + + + Assets\Emoji\Separated\D83CDF65.png + + + Assets\Emoji\Separated\D83CDF66.png + + + Assets\Emoji\Separated\D83CDF67.png + + + Assets\Emoji\Separated\D83CDF68.png + + + Assets\Emoji\Separated\D83CDF69.png + + + Assets\Emoji\Separated\D83CDF6A.png + + + Assets\Emoji\Separated\D83CDF6B.png + + + Assets\Emoji\Separated\D83CDF6C.png + + + Assets\Emoji\Separated\D83CDF6D.png + + + Assets\Emoji\Separated\D83CDF6E.png + + + Assets\Emoji\Separated\D83CDF6F.png + + + Assets\Emoji\Separated\D83CDF70.png + + + Assets\Emoji\Separated\D83CDF71.png + + + Assets\Emoji\Separated\D83CDF72.png + + + Assets\Emoji\Separated\D83CDF73.png + + + Assets\Emoji\Separated\D83CDF74.png + + + Assets\Emoji\Separated\D83CDF75.png + + + Assets\Emoji\Separated\D83CDF76.png + + + Assets\Emoji\Separated\D83CDF77.png + + + Assets\Emoji\Separated\D83CDF78.png + + + Assets\Emoji\Separated\D83CDF79.png + + + Assets\Emoji\Separated\D83CDF7A.png + + + Assets\Emoji\Separated\D83CDF7B.png + + + Assets\Emoji\Separated\D83CDF7C.png + + + Assets\Emoji\Separated\D83CDF80.png + + + Assets\Emoji\Separated\D83CDF81.png + + + Assets\Emoji\Separated\D83CDF82.png + + + Assets\Emoji\Separated\D83CDF83.png + + + Assets\Emoji\Separated\D83CDF84.png + + + Assets\Emoji\Separated\D83CDF85.png + + + Assets\Emoji\Separated\D83CDF86.png + + + Assets\Emoji\Separated\D83CDF87.png + + + Assets\Emoji\Separated\D83CDF88.png + + + Assets\Emoji\Separated\D83CDF89.png + + + Assets\Emoji\Separated\D83CDF8A.png + + + Assets\Emoji\Separated\D83CDF8B.png + + + Assets\Emoji\Separated\D83CDF8C.png + + + Assets\Emoji\Separated\D83CDF8D.png + + + Assets\Emoji\Separated\D83CDF8E.png + + + Assets\Emoji\Separated\D83CDF8F.png + + + Assets\Emoji\Separated\D83CDF90.png + + + Assets\Emoji\Separated\D83CDF91.png + + + Assets\Emoji\Separated\D83CDF92.png + + + Assets\Emoji\Separated\D83CDF93.png + + + Assets\Emoji\Separated\D83CDFA0.png + + + Assets\Emoji\Separated\D83CDFA1.png + + + Assets\Emoji\Separated\D83CDFA2.png + + + Assets\Emoji\Separated\D83CDFA3.png + + + Assets\Emoji\Separated\D83CDFA4.png + + + Assets\Emoji\Separated\D83CDFA5.png + + + Assets\Emoji\Separated\D83CDFA6.png + + + Assets\Emoji\Separated\D83CDFA7.png + + + Assets\Emoji\Separated\D83CDFA8.png + + + Assets\Emoji\Separated\D83CDFA9.png + + + Assets\Emoji\Separated\D83CDFAA.png + + + Assets\Emoji\Separated\D83CDFAB.png + + + Assets\Emoji\Separated\D83CDFAC.png + + + Assets\Emoji\Separated\D83CDFAD.png + + + Assets\Emoji\Separated\D83CDFAE.png + + + Assets\Emoji\Separated\D83CDFAF.png + + + Assets\Emoji\Separated\D83CDFB0.png + + + Assets\Emoji\Separated\D83CDFB1.png + + + Assets\Emoji\Separated\D83CDFB2.png + + + Assets\Emoji\Separated\D83CDFB3.png + + + Assets\Emoji\Separated\D83CDFB4.png + + + Assets\Emoji\Separated\D83CDFB5.png + + + Assets\Emoji\Separated\D83CDFB6.png + + + Assets\Emoji\Separated\D83CDFB7.png + + + Assets\Emoji\Separated\D83CDFB8.png + + + Assets\Emoji\Separated\D83CDFB9.png + + + Assets\Emoji\Separated\D83CDFBA.png + + + Assets\Emoji\Separated\D83CDFBB.png + + + Assets\Emoji\Separated\D83CDFBC.png + + + Assets\Emoji\Separated\D83CDFBD.png + + + Assets\Emoji\Separated\D83CDFBE.png + + + Assets\Emoji\Separated\D83CDFBF.png + + + Assets\Emoji\Separated\D83CDFC0.png + + + Assets\Emoji\Separated\D83CDFC1.png + + + Assets\Emoji\Separated\D83CDFC2.png + + + Assets\Emoji\Separated\D83CDFC3.png + + + Assets\Emoji\Separated\D83CDFC4.png + + + Assets\Emoji\Separated\D83CDFC6.png + + + Assets\Emoji\Separated\D83CDFC7.png + + + Assets\Emoji\Separated\D83CDFC8.png + + + Assets\Emoji\Separated\D83CDFC9.png + + + Assets\Emoji\Separated\D83CDFCA.png + + + Assets\Emoji\Separated\D83CDFE0.png + + + Assets\Emoji\Separated\D83CDFE1.png + + + Assets\Emoji\Separated\D83CDFE2.png + + + Assets\Emoji\Separated\D83CDFE3.png + + + Assets\Emoji\Separated\D83CDFE4.png + + + Assets\Emoji\Separated\D83CDFE5.png + + + Assets\Emoji\Separated\D83CDFE6.png + + + Assets\Emoji\Separated\D83CDFE7.png + + + Assets\Emoji\Separated\D83CDFE8.png + + + Assets\Emoji\Separated\D83CDFE9.png + + + Assets\Emoji\Separated\D83CDFEA.png + + + Assets\Emoji\Separated\D83CDFEB.png + + + Assets\Emoji\Separated\D83CDFEC.png + + + Assets\Emoji\Separated\D83CDFED.png + + + Assets\Emoji\Separated\D83CDFEE.png + + + Assets\Emoji\Separated\D83CDFEF.png + + + Assets\Emoji\Separated\D83CDFF0.png + + + Assets\Emoji\Separated\D83DDC00.png + + + Assets\Emoji\Separated\D83DDC01.png + + + Assets\Emoji\Separated\D83DDC02.png + + + Assets\Emoji\Separated\D83DDC03.png + + + Assets\Emoji\Separated\D83DDC04.png + + + Assets\Emoji\Separated\D83DDC05.png + + + Assets\Emoji\Separated\D83DDC06.png + + + Assets\Emoji\Separated\D83DDC07.png + + + Assets\Emoji\Separated\D83DDC08.png + + + Assets\Emoji\Separated\D83DDC09.png + + + Assets\Emoji\Separated\D83DDC0A.png + + + Assets\Emoji\Separated\D83DDC0B.png + + + Assets\Emoji\Separated\D83DDC0C.png + + + Assets\Emoji\Separated\D83DDC0D.png + + + Assets\Emoji\Separated\D83DDC0E.png + + + Assets\Emoji\Separated\D83DDC0F.png + + + Assets\Emoji\Separated\D83DDC10.png + + + Assets\Emoji\Separated\D83DDC11.png + + + Assets\Emoji\Separated\D83DDC12.png + + + Assets\Emoji\Separated\D83DDC13.png + + + Assets\Emoji\Separated\D83DDC14.png + + + Assets\Emoji\Separated\D83DDC15.png + + + Assets\Emoji\Separated\D83DDC16.png + + + Assets\Emoji\Separated\D83DDC17.png + + + Assets\Emoji\Separated\D83DDC18.png + + + Assets\Emoji\Separated\D83DDC19.png + + + Assets\Emoji\Separated\D83DDC1A.png + + + Assets\Emoji\Separated\D83DDC1B.png + + + Assets\Emoji\Separated\D83DDC1C.png + + + Assets\Emoji\Separated\D83DDC1D.png + + + Assets\Emoji\Separated\D83DDC1E.png + + + Assets\Emoji\Separated\D83DDC1F.png + + + Assets\Emoji\Separated\D83DDC20.png + + + Assets\Emoji\Separated\D83DDC21.png + + + Assets\Emoji\Separated\D83DDC22.png + + + Assets\Emoji\Separated\D83DDC23.png + + + Assets\Emoji\Separated\D83DDC24.png + + + Assets\Emoji\Separated\D83DDC25.png + + + Assets\Emoji\Separated\D83DDC26.png + + + Assets\Emoji\Separated\D83DDC27.png + + + Assets\Emoji\Separated\D83DDC28.png + + + Assets\Emoji\Separated\D83DDC29.png + + + Assets\Emoji\Separated\D83DDC2A.png + + + Assets\Emoji\Separated\D83DDC2B.png + + + Assets\Emoji\Separated\D83DDC2C.png + + + Assets\Emoji\Separated\D83DDC2D.png + + + Assets\Emoji\Separated\D83DDC2E.png + + + Assets\Emoji\Separated\D83DDC2F.png + + + Assets\Emoji\Separated\D83DDC30.png + + + Assets\Emoji\Separated\D83DDC31.png + + + Assets\Emoji\Separated\D83DDC32.png + + + Assets\Emoji\Separated\D83DDC33.png + + + Assets\Emoji\Separated\D83DDC34.png + + + Assets\Emoji\Separated\D83DDC35.png + + + Assets\Emoji\Separated\D83DDC36.png + + + Assets\Emoji\Separated\D83DDC37.png + + + Assets\Emoji\Separated\D83DDC38.png + + + Assets\Emoji\Separated\D83DDC39.png + + + Assets\Emoji\Separated\D83DDC3A.png + + + Assets\Emoji\Separated\D83DDC3B.png + + + Assets\Emoji\Separated\D83DDC3C.png + + + Assets\Emoji\Separated\D83DDC3D.png + + + Assets\Emoji\Separated\D83DDC3E.png + + + Assets\Emoji\Separated\D83DDC40.png + + + Assets\Emoji\Separated\D83DDC42.png + + + Assets\Emoji\Separated\D83DDC43.png + + + Assets\Emoji\Separated\D83DDC44.png + + + Assets\Emoji\Separated\D83DDC45.png + + + Assets\Emoji\Separated\D83DDC46.png + + + Assets\Emoji\Separated\D83DDC47.png + + + Assets\Emoji\Separated\D83DDC48.png + + + Assets\Emoji\Separated\D83DDC49.png + + + Assets\Emoji\Separated\D83DDC4A.png + + + Assets\Emoji\Separated\D83DDC4B.png + + + Assets\Emoji\Separated\D83DDC4C.png + + + Assets\Emoji\Separated\D83DDC4D.png + + + Assets\Emoji\Separated\D83DDC4E.png + + + Assets\Emoji\Separated\D83DDC4F.png + + + Assets\Emoji\Separated\D83DDC50.png + + + Assets\Emoji\Separated\D83DDC51.png + + + Assets\Emoji\Separated\D83DDC52.png + + + Assets\Emoji\Separated\D83DDC53.png + + + Assets\Emoji\Separated\D83DDC54.png + + + Assets\Emoji\Separated\D83DDC55.png + + + Assets\Emoji\Separated\D83DDC56.png + + + Assets\Emoji\Separated\D83DDC57.png + + + Assets\Emoji\Separated\D83DDC58.png + + + Assets\Emoji\Separated\D83DDC59.png + + + Assets\Emoji\Separated\D83DDC5A.png + + + Assets\Emoji\Separated\D83DDC5B.png + + + Assets\Emoji\Separated\D83DDC5C.png + + + Assets\Emoji\Separated\D83DDC5D.png + + + Assets\Emoji\Separated\D83DDC5E.png + + + Assets\Emoji\Separated\D83DDC5F.png + + + Assets\Emoji\Separated\D83DDC60.png + + + Assets\Emoji\Separated\D83DDC61.png + + + Assets\Emoji\Separated\D83DDC62.png + + + Assets\Emoji\Separated\D83DDC63.png + + + Assets\Emoji\Separated\D83DDC64.png + + + Assets\Emoji\Separated\D83DDC65.png + + + Assets\Emoji\Separated\D83DDC66.png + + + Assets\Emoji\Separated\D83DDC67.png + + + Assets\Emoji\Separated\D83DDC68.png + + + Assets\Emoji\Separated\D83DDC69.png + + + Assets\Emoji\Separated\D83DDC6A.png + + + Assets\Emoji\Separated\D83DDC6B.png + + + Assets\Emoji\Separated\D83DDC6C.png + + + Assets\Emoji\Separated\D83DDC6D.png + + + Assets\Emoji\Separated\D83DDC6E.png + + + Assets\Emoji\Separated\D83DDC6F.png + + + Assets\Emoji\Separated\D83DDC70.png + + + Assets\Emoji\Separated\D83DDC71.png + + + Assets\Emoji\Separated\D83DDC72.png + + + Assets\Emoji\Separated\D83DDC73.png + + + Assets\Emoji\Separated\D83DDC74.png + + + Assets\Emoji\Separated\D83DDC75.png + + + Assets\Emoji\Separated\D83DDC76.png + + + Assets\Emoji\Separated\D83DDC77.png + + + Assets\Emoji\Separated\D83DDC78.png + + + Assets\Emoji\Separated\D83DDC79.png + + + Assets\Emoji\Separated\D83DDC7A.png + + + Assets\Emoji\Separated\D83DDC7B.png + + + Assets\Emoji\Separated\D83DDC7C.png + + + Assets\Emoji\Separated\D83DDC7D.png + + + Assets\Emoji\Separated\D83DDC7E.png + + + Assets\Emoji\Separated\D83DDC7F.png + + + Assets\Emoji\Separated\D83DDC80.png + + + Assets\Emoji\Separated\D83DDC81.png + + + Assets\Emoji\Separated\D83DDC82.png + + + Assets\Emoji\Separated\D83DDC83.png + + + Assets\Emoji\Separated\D83DDC84.png + + + Assets\Emoji\Separated\D83DDC85.png + + + Assets\Emoji\Separated\D83DDC86.png + + + Assets\Emoji\Separated\D83DDC87.png + + + Assets\Emoji\Separated\D83DDC88.png + + + Assets\Emoji\Separated\D83DDC89.png + + + Assets\Emoji\Separated\D83DDC8A.png + + + Assets\Emoji\Separated\D83DDC8B.png + + + Assets\Emoji\Separated\D83DDC8C.png + + + Assets\Emoji\Separated\D83DDC8D.png + + + Assets\Emoji\Separated\D83DDC8E.png + + + Assets\Emoji\Separated\D83DDC8F.png + + + Assets\Emoji\Separated\D83DDC90.png + + + Assets\Emoji\Separated\D83DDC91.png + + + Assets\Emoji\Separated\D83DDC92.png + + + Assets\Emoji\Separated\D83DDC93.png + + + Assets\Emoji\Separated\D83DDC94.png + + + Assets\Emoji\Separated\D83DDC95.png + + + Assets\Emoji\Separated\D83DDC96.png + + + Assets\Emoji\Separated\D83DDC97.png + + + Assets\Emoji\Separated\D83DDC98.png + + + Assets\Emoji\Separated\D83DDC99.png + + + Assets\Emoji\Separated\D83DDC9A.png + + + Assets\Emoji\Separated\D83DDC9B.png + + + Assets\Emoji\Separated\D83DDC9C.png + + + Assets\Emoji\Separated\D83DDC9D.png + + + Assets\Emoji\Separated\D83DDC9E.png + + + Assets\Emoji\Separated\D83DDC9F.png + + + Assets\Emoji\Separated\D83DDCA0.png + + + Assets\Emoji\Separated\D83DDCA1.png + + + Assets\Emoji\Separated\D83DDCA2.png + + + Assets\Emoji\Separated\D83DDCA3.png + + + Assets\Emoji\Separated\D83DDCA4.png + + + Assets\Emoji\Separated\D83DDCA5.png + + + Assets\Emoji\Separated\D83DDCA6.png + + + Assets\Emoji\Separated\D83DDCA7.png + + + Assets\Emoji\Separated\D83DDCA8.png + + + Assets\Emoji\Separated\D83DDCA9.png + + + Assets\Emoji\Separated\D83DDCAA.png + + + Assets\Emoji\Separated\D83DDCAB.png + + + Assets\Emoji\Separated\D83DDCAC.png + + + Assets\Emoji\Separated\D83DDCAD.png + + + Assets\Emoji\Separated\D83DDCAE.png + + + Assets\Emoji\Separated\D83DDCAF.png + + + Assets\Emoji\Separated\D83DDCB0.png + + + Assets\Emoji\Separated\D83DDCB1.png + + + Assets\Emoji\Separated\D83DDCB2.png + + + Assets\Emoji\Separated\D83DDCB3.png + + + Assets\Emoji\Separated\D83DDCB4.png + + + Assets\Emoji\Separated\D83DDCB5.png + + + Assets\Emoji\Separated\D83DDCB6.png + + + Assets\Emoji\Separated\D83DDCB7.png + + + Assets\Emoji\Separated\D83DDCB8.png + + + Assets\Emoji\Separated\D83DDCB9.png + + + Assets\Emoji\Separated\D83DDCBA.png + + + Assets\Emoji\Separated\D83DDCBB.png + + + Assets\Emoji\Separated\D83DDCBC.png + + + Assets\Emoji\Separated\D83DDCBD.png + + + Assets\Emoji\Separated\D83DDCBE.png + + + Assets\Emoji\Separated\D83DDCBF.png + + + Assets\Emoji\Separated\D83DDCC0.png + + + Assets\Emoji\Separated\D83DDCC1.png + + + Assets\Emoji\Separated\D83DDCC2.png + + + Assets\Emoji\Separated\D83DDCC3.png + + + Assets\Emoji\Separated\D83DDCC4.png + + + Assets\Emoji\Separated\D83DDCC5.png + + + Assets\Emoji\Separated\D83DDCC6.png + + + Assets\Emoji\Separated\D83DDCC7.png + + + Assets\Emoji\Separated\D83DDCC8.png + + + Assets\Emoji\Separated\D83DDCC9.png + + + Assets\Emoji\Separated\D83DDCCA.png + + + Assets\Emoji\Separated\D83DDCCB.png + + + Assets\Emoji\Separated\D83DDCCC.png + + + Assets\Emoji\Separated\D83DDCCD.png + + + Assets\Emoji\Separated\D83DDCCE.png + + + Assets\Emoji\Separated\D83DDCCF.png + + + Assets\Emoji\Separated\D83DDCD0.png + + + Assets\Emoji\Separated\D83DDCD1.png + + + Assets\Emoji\Separated\D83DDCD2.png + + + Assets\Emoji\Separated\D83DDCD3.png + + + Assets\Emoji\Separated\D83DDCD4.png + + + Assets\Emoji\Separated\D83DDCD5.png + + + Assets\Emoji\Separated\D83DDCD6.png + + + Assets\Emoji\Separated\D83DDCD7.png + + + Assets\Emoji\Separated\D83DDCD8.png + + + Assets\Emoji\Separated\D83DDCD9.png + + + Assets\Emoji\Separated\D83DDCDA.png + + + Assets\Emoji\Separated\D83DDCDB.png + + + Assets\Emoji\Separated\D83DDCDC.png + + + Assets\Emoji\Separated\D83DDCDD.png + + + Assets\Emoji\Separated\D83DDCDE.png + + + Assets\Emoji\Separated\D83DDCDF.png + + + Assets\Emoji\Separated\D83DDCE0.png + + + Assets\Emoji\Separated\D83DDCE1.png + + + Assets\Emoji\Separated\D83DDCE2.png + + + Assets\Emoji\Separated\D83DDCE3.png + + + Assets\Emoji\Separated\D83DDCE4.png + + + Assets\Emoji\Separated\D83DDCE5.png + + + Assets\Emoji\Separated\D83DDCE6.png + + + Assets\Emoji\Separated\D83DDCE7.png + + + Assets\Emoji\Separated\D83DDCE8.png + + + Assets\Emoji\Separated\D83DDCE9.png + + + Assets\Emoji\Separated\D83DDCEA.png + + + Assets\Emoji\Separated\D83DDCEB.png + + + Assets\Emoji\Separated\D83DDCEC.png + + + Assets\Emoji\Separated\D83DDCED.png + + + Assets\Emoji\Separated\D83DDCEE.png + + + Assets\Emoji\Separated\D83DDCEF.png + + + Assets\Emoji\Separated\D83DDCF0.png + + + Assets\Emoji\Separated\D83DDCF1.png + + + Assets\Emoji\Separated\D83DDCF2.png + + + Assets\Emoji\Separated\D83DDCF3.png + + + Assets\Emoji\Separated\D83DDCF4.png + + + Assets\Emoji\Separated\D83DDCF5.png + + + Assets\Emoji\Separated\D83DDCF6.png + + + Assets\Emoji\Separated\D83DDCF7.png + + + Assets\Emoji\Separated\D83DDCF9.png + + + Assets\Emoji\Separated\D83DDCFA.png + + + Assets\Emoji\Separated\D83DDCFB.png + + + Assets\Emoji\Separated\D83DDCFC.png + + + Assets\Emoji\Separated\D83DDD00.png + + + Assets\Emoji\Separated\D83DDD01.png + + + Assets\Emoji\Separated\D83DDD02.png + + + Assets\Emoji\Separated\D83DDD03.png + + + Assets\Emoji\Separated\D83DDD04.png + + + Assets\Emoji\Separated\D83DDD05.png + + + Assets\Emoji\Separated\D83DDD06.png + + + Assets\Emoji\Separated\D83DDD07.png + + + Assets\Emoji\Separated\D83DDD08.png + + + Assets\Emoji\Separated\D83DDD09.png + + + Assets\Emoji\Separated\D83DDD0A.png + + + Assets\Emoji\Separated\D83DDD0B.png + + + Assets\Emoji\Separated\D83DDD0C.png + + + Assets\Emoji\Separated\D83DDD0D.png + + + Assets\Emoji\Separated\D83DDD0E.png + + + Assets\Emoji\Separated\D83DDD0F.png + + + Assets\Emoji\Separated\D83DDD10.png + + + Assets\Emoji\Separated\D83DDD11.png + + + Assets\Emoji\Separated\D83DDD12.png + + + Assets\Emoji\Separated\D83DDD13.png + + + Assets\Emoji\Separated\D83DDD14.png + + + Assets\Emoji\Separated\D83DDD15.png + + + Assets\Emoji\Separated\D83DDD16.png + + + Assets\Emoji\Separated\D83DDD17.png + + + Assets\Emoji\Separated\D83DDD18.png + + + Assets\Emoji\Separated\D83DDD19.png + + + Assets\Emoji\Separated\D83DDD1A.png + + + Assets\Emoji\Separated\D83DDD1B.png + + + Assets\Emoji\Separated\D83DDD1C.png + + + Assets\Emoji\Separated\D83DDD1D.png + + + Assets\Emoji\Separated\D83DDD1E.png + + + Assets\Emoji\Separated\D83DDD1F.png + + + Assets\Emoji\Separated\D83DDD20.png + + + Assets\Emoji\Separated\D83DDD21.png + + + Assets\Emoji\Separated\D83DDD22.png + + + Assets\Emoji\Separated\D83DDD23.png + + + Assets\Emoji\Separated\D83DDD24.png + + + Assets\Emoji\Separated\D83DDD25.png + + + Assets\Emoji\Separated\D83DDD26.png + + + Assets\Emoji\Separated\D83DDD27.png + + + Assets\Emoji\Separated\D83DDD28.png + + + Assets\Emoji\Separated\D83DDD29.png + + + Assets\Emoji\Separated\D83DDD2A.png + + + Assets\Emoji\Separated\D83DDD2B.png + + + Assets\Emoji\Separated\D83DDD2C.png + + + Assets\Emoji\Separated\D83DDD2D.png + + + Assets\Emoji\Separated\D83DDD2E.png + + + Assets\Emoji\Separated\D83DDD2F.png + + + Assets\Emoji\Separated\D83DDD30.png + + + Assets\Emoji\Separated\D83DDD31.png + + + Assets\Emoji\Separated\D83DDD32.png + + + Assets\Emoji\Separated\D83DDD33.png + + + Assets\Emoji\Separated\D83DDD34.png + + + Assets\Emoji\Separated\D83DDD35.png + + + Assets\Emoji\Separated\D83DDD36.png + + + Assets\Emoji\Separated\D83DDD37.png + + + Assets\Emoji\Separated\D83DDD38.png + + + Assets\Emoji\Separated\D83DDD39.png + + + Assets\Emoji\Separated\D83DDD3A.png + + + Assets\Emoji\Separated\D83DDD3B.png + + + Assets\Emoji\Separated\D83DDD3C.png + + + Assets\Emoji\Separated\D83DDD3D.png + + + Assets\Emoji\Separated\D83DDD50.png + + + Assets\Emoji\Separated\D83DDD51.png + + + Assets\Emoji\Separated\D83DDD52.png + + + Assets\Emoji\Separated\D83DDD53.png + + + Assets\Emoji\Separated\D83DDD54.png + + + Assets\Emoji\Separated\D83DDD55.png + + + Assets\Emoji\Separated\D83DDD56.png + + + Assets\Emoji\Separated\D83DDD57.png + + + Assets\Emoji\Separated\D83DDD58.png + + + Assets\Emoji\Separated\D83DDD59.png + + + Assets\Emoji\Separated\D83DDD5A.png + + + Assets\Emoji\Separated\D83DDD5B.png + + + Assets\Emoji\Separated\D83DDD5C.png + + + Assets\Emoji\Separated\D83DDD5D.png + + + Assets\Emoji\Separated\D83DDD5E.png + + + Assets\Emoji\Separated\D83DDD5F.png + + + Assets\Emoji\Separated\D83DDD60.png + + + Assets\Emoji\Separated\D83DDD61.png + + + Assets\Emoji\Separated\D83DDD62.png + + + Assets\Emoji\Separated\D83DDD63.png + + + Assets\Emoji\Separated\D83DDD64.png + + + Assets\Emoji\Separated\D83DDD65.png + + + Assets\Emoji\Separated\D83DDD66.png + + + Assets\Emoji\Separated\D83DDD67.png + + + Assets\Emoji\Separated\D83DDDFB.png + + + Assets\Emoji\Separated\D83DDDFC.png + + + Assets\Emoji\Separated\D83DDDFD.png + + + Assets\Emoji\Separated\D83DDDFE.png + + + Assets\Emoji\Separated\D83DDDFF.png + + + Assets\Emoji\Separated\D83DDE00.png + + + Assets\Emoji\Separated\D83DDE01.png + + + Assets\Emoji\Separated\D83DDE02.png + + + Assets\Emoji\Separated\D83DDE03.png + + + Assets\Emoji\Separated\D83DDE04.png + + + Assets\Emoji\Separated\D83DDE05.png + + + Assets\Emoji\Separated\D83DDE06.png + + + Assets\Emoji\Separated\D83DDE07.png + + + Assets\Emoji\Separated\D83DDE08.png + + + Assets\Emoji\Separated\D83DDE09.png + + + Assets\Emoji\Separated\D83DDE0A.png + + + Assets\Emoji\Separated\D83DDE0B.png + + + Assets\Emoji\Separated\D83DDE0C.png + + + Assets\Emoji\Separated\D83DDE0D.png + + + Assets\Emoji\Separated\D83DDE0E.png + + + Assets\Emoji\Separated\D83DDE0F.png + + + Assets\Emoji\Separated\D83DDE10.png + + + Assets\Emoji\Separated\D83DDE11.png + + + Assets\Emoji\Separated\D83DDE12.png + + + Assets\Emoji\Separated\D83DDE13.png + + + Assets\Emoji\Separated\D83DDE14.png + + + Assets\Emoji\Separated\D83DDE15.png + + + Assets\Emoji\Separated\D83DDE16.png + + + Assets\Emoji\Separated\D83DDE17.png + + + Assets\Emoji\Separated\D83DDE18.png + + + Assets\Emoji\Separated\D83DDE19.png + + + Assets\Emoji\Separated\D83DDE1A.png + + + Assets\Emoji\Separated\D83DDE1B.png + + + Assets\Emoji\Separated\D83DDE1C.png + + + Assets\Emoji\Separated\D83DDE1D.png + + + Assets\Emoji\Separated\D83DDE1E.png + + + Assets\Emoji\Separated\D83DDE1F.png + + + Assets\Emoji\Separated\D83DDE20.png + + + Assets\Emoji\Separated\D83DDE21.png + + + Assets\Emoji\Separated\D83DDE22.png + + + Assets\Emoji\Separated\D83DDE23.png + + + Assets\Emoji\Separated\D83DDE24.png + + + Assets\Emoji\Separated\D83DDE25.png + + + Assets\Emoji\Separated\D83DDE26.png + + + Assets\Emoji\Separated\D83DDE27.png + + + Assets\Emoji\Separated\D83DDE28.png + + + Assets\Emoji\Separated\D83DDE29.png + + + Assets\Emoji\Separated\D83DDE2A.png + + + Assets\Emoji\Separated\D83DDE2B.png + + + Assets\Emoji\Separated\D83DDE2C.png + + + Assets\Emoji\Separated\D83DDE2D.png + + + Assets\Emoji\Separated\D83DDE2E.png + + + Assets\Emoji\Separated\D83DDE2F.png + + + Assets\Emoji\Separated\D83DDE30.png + + + Assets\Emoji\Separated\D83DDE31.png + + + Assets\Emoji\Separated\D83DDE32.png + + + Assets\Emoji\Separated\D83DDE33.png + + + Assets\Emoji\Separated\D83DDE34.png + + + Assets\Emoji\Separated\D83DDE35.png + + + Assets\Emoji\Separated\D83DDE36.png + + + Assets\Emoji\Separated\D83DDE37.png + + + Assets\Emoji\Separated\D83DDE38.png + + + Assets\Emoji\Separated\D83DDE39.png + + + Assets\Emoji\Separated\D83DDE3A.png + + + Assets\Emoji\Separated\D83DDE3B.png + + + Assets\Emoji\Separated\D83DDE3C.png + + + Assets\Emoji\Separated\D83DDE3D.png + + + Assets\Emoji\Separated\D83DDE3E.png + + + Assets\Emoji\Separated\D83DDE3F.png + + + Assets\Emoji\Separated\D83DDE40.png + + + Assets\Emoji\Separated\D83DDE45.png + + + Assets\Emoji\Separated\D83DDE46.png + + + Assets\Emoji\Separated\D83DDE47.png + + + Assets\Emoji\Separated\D83DDE48.png + + + Assets\Emoji\Separated\D83DDE49.png + + + Assets\Emoji\Separated\D83DDE4A.png + + + Assets\Emoji\Separated\D83DDE4B.png + + + Assets\Emoji\Separated\D83DDE4C.png + + + Assets\Emoji\Separated\D83DDE4D.png + + + Assets\Emoji\Separated\D83DDE4E.png + + + Assets\Emoji\Separated\D83DDE4F.png + + + Assets\Emoji\Separated\D83DDE80.png + + + Assets\Emoji\Separated\D83DDE81.png + + + Assets\Emoji\Separated\D83DDE82.png + + + Assets\Emoji\Separated\D83DDE83.png + + + Assets\Emoji\Separated\D83DDE84.png + + + Assets\Emoji\Separated\D83DDE85.png + + + Assets\Emoji\Separated\D83DDE86.png + + + Assets\Emoji\Separated\D83DDE87.png + + + Assets\Emoji\Separated\D83DDE88.png + + + Assets\Emoji\Separated\D83DDE89.png + + + Assets\Emoji\Separated\D83DDE8A.png + + + Assets\Emoji\Separated\D83DDE8B.png + + + Assets\Emoji\Separated\D83DDE8C.png + + + Assets\Emoji\Separated\D83DDE8D.png + + + Assets\Emoji\Separated\D83DDE8E.png + + + Assets\Emoji\Separated\D83DDE8F.png + + + Assets\Emoji\Separated\D83DDE90.png + + + Assets\Emoji\Separated\D83DDE91.png + + + Assets\Emoji\Separated\D83DDE92.png + + + Assets\Emoji\Separated\D83DDE93.png + + + Assets\Emoji\Separated\D83DDE94.png + + + Assets\Emoji\Separated\D83DDE95.png + + + Assets\Emoji\Separated\D83DDE96.png + + + Assets\Emoji\Separated\D83DDE97.png + + + Assets\Emoji\Separated\D83DDE98.png + + + Assets\Emoji\Separated\D83DDE99.png + + + Assets\Emoji\Separated\D83DDE9A.png + + + Assets\Emoji\Separated\D83DDE9B.png + + + Assets\Emoji\Separated\D83DDE9C.png + + + Assets\Emoji\Separated\D83DDE9D.png + + + Assets\Emoji\Separated\D83DDE9E.png + + + Assets\Emoji\Separated\D83DDE9F.png + + + Assets\Emoji\Separated\D83DDEA0.png + + + Assets\Emoji\Separated\D83DDEA1.png + + + Assets\Emoji\Separated\D83DDEA2.png + + + Assets\Emoji\Separated\D83DDEA3.png + + + Assets\Emoji\Separated\D83DDEA4.png + + + Assets\Emoji\Separated\D83DDEA5.png + + + Assets\Emoji\Separated\D83DDEA6.png + + + Assets\Emoji\Separated\D83DDEA7.png + + + Assets\Emoji\Separated\D83DDEA8.png + + + Assets\Emoji\Separated\D83DDEA9.png + + + Assets\Emoji\Separated\D83DDEAA.png + + + Assets\Emoji\Separated\D83DDEAB.png + + + Assets\Emoji\Separated\D83DDEAC.png + + + Assets\Emoji\Separated\D83DDEAD.png + + + Assets\Emoji\Separated\D83DDEAE.png + + + Assets\Emoji\Separated\D83DDEAF.png + + + Assets\Emoji\Separated\D83DDEB0.png + + + Assets\Emoji\Separated\D83DDEB1.png + + + Assets\Emoji\Separated\D83DDEB2.png + + + Assets\Emoji\Separated\D83DDEB3.png + + + Assets\Emoji\Separated\D83DDEB4.png + + + Assets\Emoji\Separated\D83DDEB5.png + + + Assets\Emoji\Separated\D83DDEB6.png + + + Assets\Emoji\Separated\D83DDEB7.png + + + Assets\Emoji\Separated\D83DDEB8.png + + + Assets\Emoji\Separated\D83DDEB9.png + + + Assets\Emoji\Separated\D83DDEBA.png + + + Assets\Emoji\Separated\D83DDEBB.png + + + Assets\Emoji\Separated\D83DDEBC.png + + + Assets\Emoji\Separated\D83DDEBD.png + + + Assets\Emoji\Separated\D83DDEBE.png + + + Assets\Emoji\Separated\D83DDEBF.png + + + Assets\Emoji\Separated\D83DDEC0.png + + + Assets\Emoji\Separated\D83DDEC1.png + + + Assets\Emoji\Separated\D83DDEC2.png + + + Assets\Emoji\Separated\D83DDEC3.png + + + Assets\Emoji\Separated\D83DDEC4.png + + + Assets\Emoji\Separated\D83DDEC5.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat0_part0.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat0_part1.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat0_part2.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat0_part3.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat1_part0.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat1_part1.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat1_part2.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat2_part0.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat2_part1.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat2_part2.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat2_part3.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat2_part4.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat3_part0.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat3_part1.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat3_part2.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat4_part0.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat4_part1.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat4_part2.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat4_part3.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat4_part4.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part3.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part4.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part5.png + + + Assets\Emoji\SpacedSprites\sprite64_cat1_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat1_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat1_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat1_part3.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part3.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part4.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part5.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part6.png + + + Assets\Emoji\SpacedSprites\sprite64_cat3_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat3_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat3_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part3.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part4.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part5.png + + + Assets\light.emoji.abc-WXGA.png + + + Assets\light.emoji.backspace-WXGA.png + + + Assets\light.emoji.category.1-WXGA.png + + + Assets\light.emoji.category.2-WXGA.png + + + Assets\light.emoji.category.3-WXGA.png + + + Assets\light.emoji.category.4-WXGA.png + + + Assets\light.emoji.category.5-WXGA.png + + + Assets\light.emoji.recent-WXGA.png + + + + + ..\packages\WPtoolkit.4.2013.08.16\lib\wp8\Microsoft.Phone.Controls.Toolkit.dll + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/Telegram.EmojiPanel.WP8/packages.config b/Telegram.EmojiPanel.WP8/packages.config new file mode 100755 index 0000000..4921c47 --- /dev/null +++ b/Telegram.EmojiPanel.WP8/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Telegram.EmojiPanel/Assets/AppBarIcons/appbar.smile.png b/Telegram.EmojiPanel/Assets/AppBarIcons/appbar.smile.png new file mode 100755 index 0000000..a19ddb9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/AppBarIcons/appbar.smile.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/0023-fe0f-20e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/0023-fe0f-20e3.png new file mode 100755 index 0000000..6765d7d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/0023-fe0f-20e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/002320E3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/002320E3.png new file mode 100755 index 0000000..f0ba5b2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/002320E3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/0030-fe0f-20e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/0030-fe0f-20e3.png new file mode 100755 index 0000000..15e7446 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/0030-fe0f-20e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/003020E3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/003020E3.png new file mode 100755 index 0000000..9c6eed2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/003020E3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/0031-fe0f-20e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/0031-fe0f-20e3.png new file mode 100755 index 0000000..2d1f9f8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/0031-fe0f-20e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/003120E3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/003120E3.png new file mode 100755 index 0000000..4e6a4e0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/003120E3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/0032-fe0f-20e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/0032-fe0f-20e3.png new file mode 100755 index 0000000..c191f8a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/0032-fe0f-20e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/003220E3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/003220E3.png new file mode 100755 index 0000000..83c66db Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/003220E3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/0033-fe0f-20e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/0033-fe0f-20e3.png new file mode 100755 index 0000000..55644c9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/0033-fe0f-20e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/003320E3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/003320E3.png new file mode 100755 index 0000000..ebddd85 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/003320E3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/0034-fe0f-20e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/0034-fe0f-20e3.png new file mode 100755 index 0000000..14782ba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/0034-fe0f-20e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/003420E3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/003420E3.png new file mode 100755 index 0000000..bba10d3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/003420E3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/0035-fe0f-20e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/0035-fe0f-20e3.png new file mode 100755 index 0000000..794321a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/0035-fe0f-20e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/003520E3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/003520E3.png new file mode 100755 index 0000000..23f79f4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/003520E3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/0036-fe0f-20e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/0036-fe0f-20e3.png new file mode 100755 index 0000000..5688055 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/0036-fe0f-20e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/003620E3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/003620E3.png new file mode 100755 index 0000000..00e0f77 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/003620E3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/0037-fe0f-20e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/0037-fe0f-20e3.png new file mode 100755 index 0000000..354e89a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/0037-fe0f-20e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/003720E3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/003720E3.png new file mode 100755 index 0000000..9de11bc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/003720E3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/0038-fe0f-20e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/0038-fe0f-20e3.png new file mode 100755 index 0000000..7bdb422 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/0038-fe0f-20e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/003820E3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/003820E3.png new file mode 100755 index 0000000..36c49b4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/003820E3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/0039-fe0f-20e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/0039-fe0f-20e3.png new file mode 100755 index 0000000..8006cc9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/0039-fe0f-20e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/003920E3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/003920E3.png new file mode 100755 index 0000000..6357ad9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/003920E3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/00a9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/00a9.png new file mode 100755 index 0000000..ac44ed6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/00a9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/00ae.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/00ae.png new file mode 100755 index 0000000..3642023 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/00ae.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f004-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f004-fe0f.png new file mode 100755 index 0000000..f51ce65 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f004-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f0cf.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f0cf.png new file mode 100755 index 0000000..4c78f36 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f0cf.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f170.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f170.png new file mode 100755 index 0000000..4908a44 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f170.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f171.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f171.png new file mode 100755 index 0000000..8742b3d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f171.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f17e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f17e.png new file mode 100755 index 0000000..d85f9fb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f17e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f17f-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f17f-fe0f.png new file mode 100755 index 0000000..c24af81 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f17f-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f18e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f18e.png new file mode 100755 index 0000000..2a52220 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f18e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f191.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f191.png new file mode 100755 index 0000000..15ac675 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f191.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f192.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f192.png new file mode 100755 index 0000000..937dcd7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f192.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f193.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f193.png new file mode 100755 index 0000000..c886cf2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f193.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f194.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f194.png new file mode 100755 index 0000000..47437a7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f194.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f195.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f195.png new file mode 100755 index 0000000..28d1570 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f195.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f196.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f196.png new file mode 100755 index 0000000..2ca180a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f196.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f197.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f197.png new file mode 100755 index 0000000..6433d1a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f197.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f198.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f198.png new file mode 100755 index 0000000..e3e16ef Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f198.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f199.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f199.png new file mode 100755 index 0000000..829219a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f199.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f19a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f19a.png new file mode 100755 index 0000000..8636388 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f19a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1e8-1f1f3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1e8-1f1f3.png new file mode 100755 index 0000000..b30dcc5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1e8-1f1f3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1e9-1f1ea.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1e9-1f1ea.png new file mode 100755 index 0000000..16a2854 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1e9-1f1ea.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1ea-1f1f8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1ea-1f1f8.png new file mode 100755 index 0000000..71b30bf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1ea-1f1f8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1eb-1f1f7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1eb-1f1f7.png new file mode 100755 index 0000000..6311c91 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1eb-1f1f7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1ec-1f1e7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1ec-1f1e7.png new file mode 100755 index 0000000..2a62c7a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1ec-1f1e7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1ee-1f1f9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1ee-1f1f9.png new file mode 100755 index 0000000..70bc9f3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1ee-1f1f9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1ef-1f1f5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1ef-1f1f5.png new file mode 100755 index 0000000..b786efb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1ef-1f1f5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1f0-1f1f7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1f0-1f1f7.png new file mode 100755 index 0000000..b4c0c1b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1f0-1f1f7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1f7-1f1fa.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1f7-1f1fa.png new file mode 100755 index 0000000..55fcf35 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1f7-1f1fa.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1fa-1f1f8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1fa-1f1f8.png new file mode 100755 index 0000000..3813766 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f1fa-1f1f8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f201.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f201.png new file mode 100755 index 0000000..3bef28c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f201.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f202.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f202.png new file mode 100755 index 0000000..387f098 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f202.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f21a-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f21a-fe0f.png new file mode 100755 index 0000000..25f694e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f21a-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f22f-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f22f-fe0f.png new file mode 100755 index 0000000..6557f56 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f22f-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f232.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f232.png new file mode 100755 index 0000000..f550a57 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f232.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f233.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f233.png new file mode 100755 index 0000000..c05f5cf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f233.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f234.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f234.png new file mode 100755 index 0000000..03ab0d8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f234.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f235.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f235.png new file mode 100755 index 0000000..5df1cb8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f235.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f236.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f236.png new file mode 100755 index 0000000..cd8fb3f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f236.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f237.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f237.png new file mode 100755 index 0000000..e4dfe5a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f237.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f238.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f238.png new file mode 100755 index 0000000..fc4a990 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f238.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f239.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f239.png new file mode 100755 index 0000000..2148253 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f239.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f23a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f23a.png new file mode 100755 index 0000000..ba946d3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f23a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f250.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f250.png new file mode 100755 index 0000000..e79af78 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f250.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f251.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f251.png new file mode 100755 index 0000000..2d20090 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f251.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f300.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f300.png new file mode 100755 index 0000000..6c49f64 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f300.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f301.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f301.png new file mode 100755 index 0000000..3c7b8b0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f301.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f302.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f302.png new file mode 100755 index 0000000..072c5c2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f302.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f303.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f303.png new file mode 100755 index 0000000..d4de585 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f303.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f304.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f304.png new file mode 100755 index 0000000..ebc3db1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f304.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f305.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f305.png new file mode 100755 index 0000000..ec58dcc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f305.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f306.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f306.png new file mode 100755 index 0000000..7cb178a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f306.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f307.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f307.png new file mode 100755 index 0000000..91ca2a4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f307.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f308.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f308.png new file mode 100755 index 0000000..6b1faa0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f308.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f309.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f309.png new file mode 100755 index 0000000..495b06c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f309.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30a.png new file mode 100755 index 0000000..f8d520c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30b.png new file mode 100755 index 0000000..9b43453 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30c.png new file mode 100755 index 0000000..901090a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30d.png new file mode 100755 index 0000000..44ce5ec Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30e.png new file mode 100755 index 0000000..97d7176 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30f.png new file mode 100755 index 0000000..95ec357 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f30f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f310.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f310.png new file mode 100755 index 0000000..b198646 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f310.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f311.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f311.png new file mode 100755 index 0000000..540239b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f311.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f312.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f312.png new file mode 100755 index 0000000..c8f13dd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f312.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f313.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f313.png new file mode 100755 index 0000000..f38c236 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f313.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f314.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f314.png new file mode 100755 index 0000000..dd8c484 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f314.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f315.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f315.png new file mode 100755 index 0000000..8ff657a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f315.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f316.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f316.png new file mode 100755 index 0000000..8e324ec Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f316.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f317.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f317.png new file mode 100755 index 0000000..355e3c3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f317.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f318.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f318.png new file mode 100755 index 0000000..3038778 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f318.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f319.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f319.png new file mode 100755 index 0000000..afdb450 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f319.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31a.png new file mode 100755 index 0000000..b9aff7a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31b.png new file mode 100755 index 0000000..85ae2ce Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31c.png new file mode 100755 index 0000000..9ece82d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31d.png new file mode 100755 index 0000000..94395a4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31e.png new file mode 100755 index 0000000..ee27663 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31f.png new file mode 100755 index 0000000..8b40ff4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f31f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f320.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f320.png new file mode 100755 index 0000000..097a842 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f320.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f330.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f330.png new file mode 100755 index 0000000..066fb6b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f330.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f331.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f331.png new file mode 100755 index 0000000..f0eb5a6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f331.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f332.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f332.png new file mode 100755 index 0000000..ae8ad10 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f332.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f333.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f333.png new file mode 100755 index 0000000..9bb16bd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f333.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f334.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f334.png new file mode 100755 index 0000000..d534785 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f334.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f335.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f335.png new file mode 100755 index 0000000..5a2c3cc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f335.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f337.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f337.png new file mode 100755 index 0000000..b3ee110 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f337.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f338.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f338.png new file mode 100755 index 0000000..e031554 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f338.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f339.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f339.png new file mode 100755 index 0000000..3479fbc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f339.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33a.png new file mode 100755 index 0000000..32a3774 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33b.png new file mode 100755 index 0000000..d9bad19 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33c.png new file mode 100755 index 0000000..55a9735 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33d.png new file mode 100755 index 0000000..fe5d8b1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33e.png new file mode 100755 index 0000000..a9bba5c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33f.png new file mode 100755 index 0000000..de1ff1b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f33f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f340.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f340.png new file mode 100755 index 0000000..f2014be Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f340.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f341.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f341.png new file mode 100755 index 0000000..4e9b472 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f341.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f342.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f342.png new file mode 100755 index 0000000..d49f9c1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f342.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f343.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f343.png new file mode 100755 index 0000000..801e578 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f343.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f344.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f344.png new file mode 100755 index 0000000..5eeed8e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f344.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f345.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f345.png new file mode 100755 index 0000000..a129700 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f345.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f346.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f346.png new file mode 100755 index 0000000..566d6a8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f346.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f347.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f347.png new file mode 100755 index 0000000..0f9f007 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f347.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f348.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f348.png new file mode 100755 index 0000000..11c13cb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f348.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f349.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f349.png new file mode 100755 index 0000000..fc212be Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f349.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34a.png new file mode 100755 index 0000000..fc9d4f8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34b.png new file mode 100755 index 0000000..9814dc9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34c.png new file mode 100755 index 0000000..a0563af Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34d.png new file mode 100755 index 0000000..d6f8e28 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34e.png new file mode 100755 index 0000000..08aa17b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34f.png new file mode 100755 index 0000000..337205c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f34f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f350.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f350.png new file mode 100755 index 0000000..f24aca8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f350.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f351.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f351.png new file mode 100755 index 0000000..ee2139e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f351.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f352.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f352.png new file mode 100755 index 0000000..8d3e044 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f352.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f353.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f353.png new file mode 100755 index 0000000..13eb827 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f353.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f354.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f354.png new file mode 100755 index 0000000..9f1a3fd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f354.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f355.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f355.png new file mode 100755 index 0000000..460367d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f355.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f356.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f356.png new file mode 100755 index 0000000..d6b311b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f356.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f357.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f357.png new file mode 100755 index 0000000..43ad859 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f357.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f358.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f358.png new file mode 100755 index 0000000..954c901 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f358.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f359.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f359.png new file mode 100755 index 0000000..04f8a88 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f359.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35a.png new file mode 100755 index 0000000..f4773ed Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35b.png new file mode 100755 index 0000000..7983c70 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35c.png new file mode 100755 index 0000000..78dc7d5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35d.png new file mode 100755 index 0000000..08de243 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35e.png new file mode 100755 index 0000000..7e7c637 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35f.png new file mode 100755 index 0000000..cfef669 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f35f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f360.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f360.png new file mode 100755 index 0000000..32117fa Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f360.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f361.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f361.png new file mode 100755 index 0000000..2d042ae Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f361.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f362.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f362.png new file mode 100755 index 0000000..73add1c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f362.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f363.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f363.png new file mode 100755 index 0000000..0d179bd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f363.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f364.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f364.png new file mode 100755 index 0000000..c8c284b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f364.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f365.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f365.png new file mode 100755 index 0000000..a8f2261 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f365.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f366.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f366.png new file mode 100755 index 0000000..871ce09 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f366.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f367.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f367.png new file mode 100755 index 0000000..0d0b382 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f367.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f368.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f368.png new file mode 100755 index 0000000..190be01 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f368.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f369.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f369.png new file mode 100755 index 0000000..ccf8691 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f369.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36a.png new file mode 100755 index 0000000..653edb2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36b.png new file mode 100755 index 0000000..c7ec19d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36c.png new file mode 100755 index 0000000..33722f2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36d.png new file mode 100755 index 0000000..ba55e70 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36e.png new file mode 100755 index 0000000..9f843b4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36f.png new file mode 100755 index 0000000..7327889 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f36f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f370.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f370.png new file mode 100755 index 0000000..efeb9b4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f370.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f371.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f371.png new file mode 100755 index 0000000..c6d99e8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f371.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f372.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f372.png new file mode 100755 index 0000000..6e80b4a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f372.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f373.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f373.png new file mode 100755 index 0000000..c3de6ae Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f373.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f374.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f374.png new file mode 100755 index 0000000..8ba4bc6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f374.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f375.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f375.png new file mode 100755 index 0000000..3ece0b7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f375.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f376.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f376.png new file mode 100755 index 0000000..1f69907 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f376.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f377.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f377.png new file mode 100755 index 0000000..82b0f00 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f377.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f378.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f378.png new file mode 100755 index 0000000..28b45ea Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f378.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f379.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f379.png new file mode 100755 index 0000000..55ca9ee Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f379.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f37a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f37a.png new file mode 100755 index 0000000..cd78bed Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f37a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f37b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f37b.png new file mode 100755 index 0000000..cc5e4ab Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f37b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f37c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f37c.png new file mode 100755 index 0000000..1b2cfe5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f37c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f380.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f380.png new file mode 100755 index 0000000..63ee5ba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f380.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f381.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f381.png new file mode 100755 index 0000000..552cfdc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f381.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f382.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f382.png new file mode 100755 index 0000000..36e8edc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f382.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f383.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f383.png new file mode 100755 index 0000000..1f7667e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f383.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f384.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f384.png new file mode 100755 index 0000000..d813b95 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f384.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f385.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f385.png new file mode 100755 index 0000000..a2240c0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f385.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f386.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f386.png new file mode 100755 index 0000000..b4eccd5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f386.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f387.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f387.png new file mode 100755 index 0000000..4aabd7e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f387.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f388.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f388.png new file mode 100755 index 0000000..a4d3207 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f388.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f389.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f389.png new file mode 100755 index 0000000..7411b52 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f389.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38a.png new file mode 100755 index 0000000..bd293e3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38b.png new file mode 100755 index 0000000..4733464 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38c.png new file mode 100755 index 0000000..2ffbb26 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38d.png new file mode 100755 index 0000000..fc858d0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38e.png new file mode 100755 index 0000000..47ce339 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38f.png new file mode 100755 index 0000000..540164e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f38f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f390.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f390.png new file mode 100755 index 0000000..efacf5d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f390.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f391.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f391.png new file mode 100755 index 0000000..1436198 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f391.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f392.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f392.png new file mode 100755 index 0000000..edfb19a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f392.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f393.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f393.png new file mode 100755 index 0000000..2e811b0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f393.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a0.png new file mode 100755 index 0000000..765d2c0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a1.png new file mode 100755 index 0000000..54a1dcf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a2.png new file mode 100755 index 0000000..9180b98 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a3.png new file mode 100755 index 0000000..d84609c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a4.png new file mode 100755 index 0000000..ce19a2b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a5.png new file mode 100755 index 0000000..9c14384 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a6.png new file mode 100755 index 0000000..a990ccf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a7.png new file mode 100755 index 0000000..ad83000 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a8.png new file mode 100755 index 0000000..d45212b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a9.png new file mode 100755 index 0000000..7d27134 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3a9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3aa.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3aa.png new file mode 100755 index 0000000..4af8719 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3aa.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ab.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ab.png new file mode 100755 index 0000000..cdacf1a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ab.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ac.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ac.png new file mode 100755 index 0000000..4e1dc11 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ac.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ad.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ad.png new file mode 100755 index 0000000..899fbe5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ad.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ae.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ae.png new file mode 100755 index 0000000..59d45ba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ae.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3af.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3af.png new file mode 100755 index 0000000..0438fe5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3af.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b0.png new file mode 100755 index 0000000..26f1148 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b1.png new file mode 100755 index 0000000..c2c710d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b2.png new file mode 100755 index 0000000..4136e78 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b3.png new file mode 100755 index 0000000..13d8ece Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b4.png new file mode 100755 index 0000000..cc46a6a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b5.png new file mode 100755 index 0000000..68b261b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b6.png new file mode 100755 index 0000000..a13147f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b7.png new file mode 100755 index 0000000..011559a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b8.png new file mode 100755 index 0000000..2b7fa43 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b9.png new file mode 100755 index 0000000..93647a4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3b9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ba.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ba.png new file mode 100755 index 0000000..8d4703f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ba.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3bb.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3bb.png new file mode 100755 index 0000000..0dba5ba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3bb.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3bc.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3bc.png new file mode 100755 index 0000000..0c927d3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3bc.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3bd.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3bd.png new file mode 100755 index 0000000..0d68bba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3bd.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3be.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3be.png new file mode 100755 index 0000000..278d904 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3be.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3bf.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3bf.png new file mode 100755 index 0000000..c97de3e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3bf.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c0.png new file mode 100755 index 0000000..ef694be Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c1.png new file mode 100755 index 0000000..ead4a68 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c2.png new file mode 100755 index 0000000..aeda5c8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c3.png new file mode 100755 index 0000000..1ecfd90 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c4.png new file mode 100755 index 0000000..b067e8c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c6.png new file mode 100755 index 0000000..95d3b63 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c7.png new file mode 100755 index 0000000..e3bbaec Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c8.png new file mode 100755 index 0000000..0e4e168 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c9.png new file mode 100755 index 0000000..f8db67d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3c9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ca.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ca.png new file mode 100755 index 0000000..d3878a0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ca.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e0.png new file mode 100755 index 0000000..95b9ee0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e1.png new file mode 100755 index 0000000..eccbfe9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e2.png new file mode 100755 index 0000000..3f20b56 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e3.png new file mode 100755 index 0000000..43b59e3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e4.png new file mode 100755 index 0000000..0f65b14 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e5.png new file mode 100755 index 0000000..c05c493 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e6.png new file mode 100755 index 0000000..1faa877 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e7.png new file mode 100755 index 0000000..c2846e7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e8.png new file mode 100755 index 0000000..d29f276 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e9.png new file mode 100755 index 0000000..44d7db8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3e9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ea.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ea.png new file mode 100755 index 0000000..671696c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ea.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3eb.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3eb.png new file mode 100755 index 0000000..afd922b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3eb.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ec.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ec.png new file mode 100755 index 0000000..68d959c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ec.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ed.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ed.png new file mode 100755 index 0000000..6404634 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ed.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ee.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ee.png new file mode 100755 index 0000000..18730ad Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ee.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ef.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ef.png new file mode 100755 index 0000000..f225ab2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3ef.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3f0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3f0.png new file mode 100755 index 0000000..8229b8a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f3f0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f400.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f400.png new file mode 100755 index 0000000..1c463df Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f400.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f401.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f401.png new file mode 100755 index 0000000..2d777e5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f401.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f402.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f402.png new file mode 100755 index 0000000..f766980 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f402.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f403.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f403.png new file mode 100755 index 0000000..3bcde3e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f403.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f404.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f404.png new file mode 100755 index 0000000..594c921 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f404.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f405.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f405.png new file mode 100755 index 0000000..b0c7d8d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f405.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f406.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f406.png new file mode 100755 index 0000000..8abfc4a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f406.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f407.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f407.png new file mode 100755 index 0000000..5bc993e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f407.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f408.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f408.png new file mode 100755 index 0000000..977c992 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f408.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f409.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f409.png new file mode 100755 index 0000000..e399d60 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f409.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40a.png new file mode 100755 index 0000000..7435d5a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40b.png new file mode 100755 index 0000000..4af657b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40c.png new file mode 100755 index 0000000..e75e69a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40d.png new file mode 100755 index 0000000..ef58933 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40e.png new file mode 100755 index 0000000..4d09c64 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40f.png new file mode 100755 index 0000000..5ea7bfb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f40f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f410.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f410.png new file mode 100755 index 0000000..4be9cf3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f410.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f411.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f411.png new file mode 100755 index 0000000..c7277d2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f411.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f412.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f412.png new file mode 100755 index 0000000..6407035 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f412.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f413.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f413.png new file mode 100755 index 0000000..fab23ad Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f413.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f414.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f414.png new file mode 100755 index 0000000..6d25c0e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f414.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f415.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f415.png new file mode 100755 index 0000000..c7f6a24 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f415.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f416.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f416.png new file mode 100755 index 0000000..fec3374 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f416.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f417.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f417.png new file mode 100755 index 0000000..8196ad4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f417.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f418.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f418.png new file mode 100755 index 0000000..5ca0457 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f418.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f419.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f419.png new file mode 100755 index 0000000..52ce64b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f419.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41a.png new file mode 100755 index 0000000..3145b56 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41b.png new file mode 100755 index 0000000..c2eaf7a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41c.png new file mode 100755 index 0000000..b92d1cc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41d.png new file mode 100755 index 0000000..f537339 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41e.png new file mode 100755 index 0000000..222577c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41f.png new file mode 100755 index 0000000..dc2a3f5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f41f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f420.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f420.png new file mode 100755 index 0000000..a6d7349 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f420.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f421.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f421.png new file mode 100755 index 0000000..a1d47cb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f421.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f422.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f422.png new file mode 100755 index 0000000..04d1d96 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f422.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f423.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f423.png new file mode 100755 index 0000000..005a555 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f423.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f424.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f424.png new file mode 100755 index 0000000..9be8d29 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f424.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f425.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f425.png new file mode 100755 index 0000000..39c25bc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f425.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f426.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f426.png new file mode 100755 index 0000000..e6be8c0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f426.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f427.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f427.png new file mode 100755 index 0000000..d8edbcb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f427.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f428.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f428.png new file mode 100755 index 0000000..e17bd3c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f428.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f429.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f429.png new file mode 100755 index 0000000..adac80b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f429.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42a.png new file mode 100755 index 0000000..c8c7b9f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42b.png new file mode 100755 index 0000000..496c186 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42c.png new file mode 100755 index 0000000..9326077 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42d.png new file mode 100755 index 0000000..8ff162e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42e.png new file mode 100755 index 0000000..12e1ab6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42f.png new file mode 100755 index 0000000..d6cc84a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f42f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f430.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f430.png new file mode 100755 index 0000000..5cb3ef6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f430.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f431.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f431.png new file mode 100755 index 0000000..09b9ef7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f431.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f432.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f432.png new file mode 100755 index 0000000..e5e556b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f432.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f433.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f433.png new file mode 100755 index 0000000..5bb113e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f433.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f434.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f434.png new file mode 100755 index 0000000..78d580a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f434.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f435.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f435.png new file mode 100755 index 0000000..6964cf4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f435.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f436.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f436.png new file mode 100755 index 0000000..389a02b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f436.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f437.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f437.png new file mode 100755 index 0000000..f7f273c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f437.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f438.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f438.png new file mode 100755 index 0000000..cfe11b1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f438.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f439.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f439.png new file mode 100755 index 0000000..ada9c31 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f439.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43a.png new file mode 100755 index 0000000..c60c968 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43b.png new file mode 100755 index 0000000..f5afe92 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43c.png new file mode 100755 index 0000000..a794fb1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43d.png new file mode 100755 index 0000000..38d6124 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43e.png new file mode 100755 index 0000000..89b9fec Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f43e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f440.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f440.png new file mode 100755 index 0000000..dc2216f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f440.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f442.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f442.png new file mode 100755 index 0000000..2bbbf10 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f442.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f443.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f443.png new file mode 100755 index 0000000..ad17c16 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f443.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f444.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f444.png new file mode 100755 index 0000000..826ed11 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f444.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f445.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f445.png new file mode 100755 index 0000000..b0bab12 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f445.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f446.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f446.png new file mode 100755 index 0000000..196d109 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f446.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f447.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f447.png new file mode 100755 index 0000000..658c6d9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f447.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f448.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f448.png new file mode 100755 index 0000000..fee9cac Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f448.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f449.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f449.png new file mode 100755 index 0000000..b04e284 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f449.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44a.png new file mode 100755 index 0000000..2d41fd3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44b.png new file mode 100755 index 0000000..e78402e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44c.png new file mode 100755 index 0000000..3177439 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44d.png new file mode 100755 index 0000000..3a43eca Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44e.png new file mode 100755 index 0000000..e44c042 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44f.png new file mode 100755 index 0000000..d01c982 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f44f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f450.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f450.png new file mode 100755 index 0000000..2cc25bd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f450.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f451.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f451.png new file mode 100755 index 0000000..39da1d5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f451.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f452.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f452.png new file mode 100755 index 0000000..4cb2e6a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f452.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f453.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f453.png new file mode 100755 index 0000000..a3cf75a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f453.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f454.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f454.png new file mode 100755 index 0000000..80461c6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f454.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f455.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f455.png new file mode 100755 index 0000000..297a6d6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f455.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f456.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f456.png new file mode 100755 index 0000000..d721cea Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f456.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f457.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f457.png new file mode 100755 index 0000000..6434e2e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f457.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f458.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f458.png new file mode 100755 index 0000000..34ffe13 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f458.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f459.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f459.png new file mode 100755 index 0000000..4ff63b4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f459.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45a.png new file mode 100755 index 0000000..aa297c7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45b.png new file mode 100755 index 0000000..8f06a2b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45c.png new file mode 100755 index 0000000..d7adf04 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45d.png new file mode 100755 index 0000000..0bc5879 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45e.png new file mode 100755 index 0000000..ecba9ba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45f.png new file mode 100755 index 0000000..45b82e6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f45f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f460.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f460.png new file mode 100755 index 0000000..525b6a0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f460.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f461.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f461.png new file mode 100755 index 0000000..aa62cca Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f461.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f462.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f462.png new file mode 100755 index 0000000..58d0fdb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f462.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f463.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f463.png new file mode 100755 index 0000000..d7a2561 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f463.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f464.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f464.png new file mode 100755 index 0000000..d131398 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f464.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f465.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f465.png new file mode 100755 index 0000000..1f3aabc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f465.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f466.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f466.png new file mode 100755 index 0000000..f79f1f2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f466.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f467.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f467.png new file mode 100755 index 0000000..ea41269 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f467.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f468.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f468.png new file mode 100755 index 0000000..d9bfa26 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f468.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f469.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f469.png new file mode 100755 index 0000000..6bf0d2b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f469.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46a.png new file mode 100755 index 0000000..b4b365f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46b.png new file mode 100755 index 0000000..9e51f40 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46c.png new file mode 100755 index 0000000..d1099f2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46d.png new file mode 100755 index 0000000..619646c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46e.png new file mode 100755 index 0000000..43a5a84 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46f.png new file mode 100755 index 0000000..2dfb451 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f46f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f470.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f470.png new file mode 100755 index 0000000..dd0b0cf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f470.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f471.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f471.png new file mode 100755 index 0000000..c144301 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f471.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f472.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f472.png new file mode 100755 index 0000000..7aad74b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f472.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f473.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f473.png new file mode 100755 index 0000000..036604c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f473.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f474.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f474.png new file mode 100755 index 0000000..149f0cf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f474.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f475.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f475.png new file mode 100755 index 0000000..f839565 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f475.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f476.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f476.png new file mode 100755 index 0000000..3b29da4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f476.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f477.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f477.png new file mode 100755 index 0000000..4d64860 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f477.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f478.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f478.png new file mode 100755 index 0000000..1ebb2ce Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f478.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f479.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f479.png new file mode 100755 index 0000000..e9f5471 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f479.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47a.png new file mode 100755 index 0000000..bd21b18 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47b.png new file mode 100755 index 0000000..671dd0c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47c.png new file mode 100755 index 0000000..da52c31 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47d.png new file mode 100755 index 0000000..e3fd76a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47e.png new file mode 100755 index 0000000..3840491 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47f.png new file mode 100755 index 0000000..48e5701 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f47f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f480.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f480.png new file mode 100755 index 0000000..bd4ee38 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f480.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f481.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f481.png new file mode 100755 index 0000000..52c0a50 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f481.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f482.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f482.png new file mode 100755 index 0000000..b67b335 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f482.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f483.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f483.png new file mode 100755 index 0000000..6885a0b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f483.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f484.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f484.png new file mode 100755 index 0000000..82f990c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f484.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f485.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f485.png new file mode 100755 index 0000000..6a66e63 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f485.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f486.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f486.png new file mode 100755 index 0000000..dd30d15 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f486.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f487.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f487.png new file mode 100755 index 0000000..902d273 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f487.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f488.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f488.png new file mode 100755 index 0000000..a10cb23 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f488.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f489.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f489.png new file mode 100755 index 0000000..e7e7ab6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f489.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48a.png new file mode 100755 index 0000000..cd84a78 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48b.png new file mode 100755 index 0000000..4ae2c2b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48c.png new file mode 100755 index 0000000..e29981f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48d.png new file mode 100755 index 0000000..8a57fd6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48e.png new file mode 100755 index 0000000..8a5d8da Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48f.png new file mode 100755 index 0000000..d027908 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f48f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f490.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f490.png new file mode 100755 index 0000000..ce63783 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f490.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f491.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f491.png new file mode 100755 index 0000000..c503f40 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f491.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f492.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f492.png new file mode 100755 index 0000000..ead19d5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f492.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f493.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f493.png new file mode 100755 index 0000000..b6628f6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f493.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f494.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f494.png new file mode 100755 index 0000000..a1bc850 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f494.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f495.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f495.png new file mode 100755 index 0000000..b189e9a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f495.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f496.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f496.png new file mode 100755 index 0000000..0826bbc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f496.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f497.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f497.png new file mode 100755 index 0000000..a7491cb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f497.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f498.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f498.png new file mode 100755 index 0000000..4987284 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f498.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f499.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f499.png new file mode 100755 index 0000000..baa29b3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f499.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49a.png new file mode 100755 index 0000000..7289cb8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49b.png new file mode 100755 index 0000000..fa41ce7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49c.png new file mode 100755 index 0000000..d5f8750 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49d.png new file mode 100755 index 0000000..f31c26a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49e.png new file mode 100755 index 0000000..ea3317c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49f.png new file mode 100755 index 0000000..b40a486 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f49f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a0.png new file mode 100755 index 0000000..dfd1098 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a1.png new file mode 100755 index 0000000..23afca1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a2.png new file mode 100755 index 0000000..6fb4dca Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a3.png new file mode 100755 index 0000000..3289787 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a4.png new file mode 100755 index 0000000..30be046 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a5.png new file mode 100755 index 0000000..bddeb8f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a6.png new file mode 100755 index 0000000..a83b3e9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a7.png new file mode 100755 index 0000000..9eff463 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a8.png new file mode 100755 index 0000000..dc2c0a8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a9.png new file mode 100755 index 0000000..73a4dc8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4a9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4aa.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4aa.png new file mode 100755 index 0000000..19f92ef Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4aa.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ab.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ab.png new file mode 100755 index 0000000..55213d2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ab.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ac.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ac.png new file mode 100755 index 0000000..2896c27 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ac.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ad.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ad.png new file mode 100755 index 0000000..701bdf0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ad.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ae.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ae.png new file mode 100755 index 0000000..c0929d0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ae.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4af.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4af.png new file mode 100755 index 0000000..bce9ab1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4af.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b0.png new file mode 100755 index 0000000..5546c04 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b1.png new file mode 100755 index 0000000..d5ee21f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b2.png new file mode 100755 index 0000000..361e26a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b3.png new file mode 100755 index 0000000..be1c1dd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b4.png new file mode 100755 index 0000000..139bc93 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b5.png new file mode 100755 index 0000000..63de884 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b6.png new file mode 100755 index 0000000..1c5904b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b7.png new file mode 100755 index 0000000..f8be91d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b8.png new file mode 100755 index 0000000..135e398 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b9.png new file mode 100755 index 0000000..ac2c4bb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4b9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ba.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ba.png new file mode 100755 index 0000000..d1cb864 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ba.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4bb.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4bb.png new file mode 100755 index 0000000..d4d2687 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4bb.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4bc.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4bc.png new file mode 100755 index 0000000..46e82b0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4bc.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4bd.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4bd.png new file mode 100755 index 0000000..e19cc5d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4bd.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4be.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4be.png new file mode 100755 index 0000000..4ad5631 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4be.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4bf.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4bf.png new file mode 100755 index 0000000..baff835 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4bf.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c0.png new file mode 100755 index 0000000..363c83d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c1.png new file mode 100755 index 0000000..4d8bebf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c2.png new file mode 100755 index 0000000..2bbbbf5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c3.png new file mode 100755 index 0000000..bf8f979 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c4.png new file mode 100755 index 0000000..64cd2e1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c5.png new file mode 100755 index 0000000..6ad2efa Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c6.png new file mode 100755 index 0000000..900b868 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c7.png new file mode 100755 index 0000000..374e94e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c8.png new file mode 100755 index 0000000..de3e9ba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c9.png new file mode 100755 index 0000000..65b82f0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4c9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ca.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ca.png new file mode 100755 index 0000000..7871cc6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ca.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4cb.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4cb.png new file mode 100755 index 0000000..e2c74e6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4cb.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4cc.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4cc.png new file mode 100755 index 0000000..540c4ec Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4cc.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4cd.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4cd.png new file mode 100755 index 0000000..e498e92 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4cd.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ce.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ce.png new file mode 100755 index 0000000..774412d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ce.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4cf.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4cf.png new file mode 100755 index 0000000..af8cb4b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4cf.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d0.png new file mode 100755 index 0000000..383677c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d1.png new file mode 100755 index 0000000..0c4e3bf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d2.png new file mode 100755 index 0000000..e4f72ac Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d3.png new file mode 100755 index 0000000..07ea608 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d4.png new file mode 100755 index 0000000..4f3b14c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d5.png new file mode 100755 index 0000000..484029c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d6.png new file mode 100755 index 0000000..8b69841 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d7.png new file mode 100755 index 0000000..e86651e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d8.png new file mode 100755 index 0000000..e2b9e8c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d9.png new file mode 100755 index 0000000..49650d5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4d9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4da.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4da.png new file mode 100755 index 0000000..dca06a1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4da.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4db.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4db.png new file mode 100755 index 0000000..2b712dc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4db.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4dc.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4dc.png new file mode 100755 index 0000000..c5a10e6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4dc.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4dd.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4dd.png new file mode 100755 index 0000000..fc97ddb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4dd.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4de.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4de.png new file mode 100755 index 0000000..36e21e0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4de.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4df.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4df.png new file mode 100755 index 0000000..e3e1fc4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4df.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e0.png new file mode 100755 index 0000000..62be2c9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e1.png new file mode 100755 index 0000000..3481cc2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e2.png new file mode 100755 index 0000000..752385e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e3.png new file mode 100755 index 0000000..5d9319e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e4.png new file mode 100755 index 0000000..7ad15e6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e5.png new file mode 100755 index 0000000..e2df0f8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e6.png new file mode 100755 index 0000000..26602af Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e7.png new file mode 100755 index 0000000..176a8e1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e8.png new file mode 100755 index 0000000..afc8271 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e9.png new file mode 100755 index 0000000..0e01fd5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4e9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ea.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ea.png new file mode 100755 index 0000000..a5982b6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ea.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4eb.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4eb.png new file mode 100755 index 0000000..8351e70 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4eb.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ec.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ec.png new file mode 100755 index 0000000..dae3459 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ec.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ed.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ed.png new file mode 100755 index 0000000..59f15c5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ed.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ee.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ee.png new file mode 100755 index 0000000..ce04b70 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ee.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ef.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ef.png new file mode 100755 index 0000000..e9b713b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4ef.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f0.png new file mode 100755 index 0000000..d171394 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f1.png new file mode 100755 index 0000000..df00710 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f2.png new file mode 100755 index 0000000..837897f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f3.png new file mode 100755 index 0000000..a716e96 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f4.png new file mode 100755 index 0000000..fa16c76 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f5.png new file mode 100755 index 0000000..41df57c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f6.png new file mode 100755 index 0000000..a4bd23e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f7.png new file mode 100755 index 0000000..397d03b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f9.png new file mode 100755 index 0000000..274cecd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4f9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4fa.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4fa.png new file mode 100755 index 0000000..803dc3d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4fa.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4fb.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4fb.png new file mode 100755 index 0000000..ea589ef Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4fb.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4fc.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4fc.png new file mode 100755 index 0000000..881081c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f4fc.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f500.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f500.png new file mode 100755 index 0000000..25cde18 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f500.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f501.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f501.png new file mode 100755 index 0000000..80113b6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f501.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f502.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f502.png new file mode 100755 index 0000000..3c47bcc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f502.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f503.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f503.png new file mode 100755 index 0000000..5f84d7e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f503.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f504.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f504.png new file mode 100755 index 0000000..1933ae1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f504.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f505.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f505.png new file mode 100755 index 0000000..ea15bde Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f505.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f506.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f506.png new file mode 100755 index 0000000..ba9de7d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f506.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f507.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f507.png new file mode 100755 index 0000000..4cf67c3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f507.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f508.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f508.png new file mode 100755 index 0000000..c884bd4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f508.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f509.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f509.png new file mode 100755 index 0000000..6aa4dbf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f509.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50a.png new file mode 100755 index 0000000..f63e814 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50b.png new file mode 100755 index 0000000..aa7eedc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50c.png new file mode 100755 index 0000000..7a3d6ce Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50d.png new file mode 100755 index 0000000..aa5b1d7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50e.png new file mode 100755 index 0000000..6e6cf11 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50f.png new file mode 100755 index 0000000..375e67e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f50f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f510.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f510.png new file mode 100755 index 0000000..e6fdf6c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f510.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f511.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f511.png new file mode 100755 index 0000000..3467321 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f511.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f512.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f512.png new file mode 100755 index 0000000..4892b02 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f512.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f513.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f513.png new file mode 100755 index 0000000..22b429c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f513.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f514.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f514.png new file mode 100755 index 0000000..69acceb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f514.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f515.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f515.png new file mode 100755 index 0000000..613b81c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f515.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f516.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f516.png new file mode 100755 index 0000000..dbee45c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f516.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f517.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f517.png new file mode 100755 index 0000000..ffb8f62 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f517.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f518.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f518.png new file mode 100755 index 0000000..63755ee Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f518.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f519.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f519.png new file mode 100755 index 0000000..0cde628 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f519.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51a.png new file mode 100755 index 0000000..edb0bda Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51b.png new file mode 100755 index 0000000..3595387 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51c.png new file mode 100755 index 0000000..9386615 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51d.png new file mode 100755 index 0000000..5aa4dd4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51e.png new file mode 100755 index 0000000..a789b3c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51f.png new file mode 100755 index 0000000..71dac1c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f51f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f520.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f520.png new file mode 100755 index 0000000..ffc0cba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f520.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f521.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f521.png new file mode 100755 index 0000000..5218470 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f521.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f522.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f522.png new file mode 100755 index 0000000..c47c2e1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f522.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f523.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f523.png new file mode 100755 index 0000000..16bc1da Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f523.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f524.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f524.png new file mode 100755 index 0000000..505d40a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f524.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f525.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f525.png new file mode 100755 index 0000000..f2a3149 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f525.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f526.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f526.png new file mode 100755 index 0000000..215940a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f526.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f527.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f527.png new file mode 100755 index 0000000..a87072a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f527.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f528.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f528.png new file mode 100755 index 0000000..6b75bc3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f528.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f529.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f529.png new file mode 100755 index 0000000..bddfa72 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f529.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52a.png new file mode 100755 index 0000000..18eade0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52b.png new file mode 100755 index 0000000..c49dc52 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52c.png new file mode 100755 index 0000000..f11d54c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52d.png new file mode 100755 index 0000000..51fd8a0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52e.png new file mode 100755 index 0000000..6d2c6c4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52f.png new file mode 100755 index 0000000..010f8f5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f52f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f530.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f530.png new file mode 100755 index 0000000..1f022d1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f530.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f531.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f531.png new file mode 100755 index 0000000..d79a7b4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f531.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f532.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f532.png new file mode 100755 index 0000000..7332e39 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f532.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f533.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f533.png new file mode 100755 index 0000000..63c7a3e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f533.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f534.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f534.png new file mode 100755 index 0000000..b391289 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f534.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f535.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f535.png new file mode 100755 index 0000000..a5b4ad4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f535.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f536.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f536.png new file mode 100755 index 0000000..46d52e5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f536.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f537.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f537.png new file mode 100755 index 0000000..f4598ec Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f537.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f538.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f538.png new file mode 100755 index 0000000..04941d3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f538.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f539.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f539.png new file mode 100755 index 0000000..5a7b5d5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f539.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f53a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f53a.png new file mode 100755 index 0000000..8c4428d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f53a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f53b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f53b.png new file mode 100755 index 0000000..94832f0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f53b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f53c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f53c.png new file mode 100755 index 0000000..1217331 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f53c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f53d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f53d.png new file mode 100755 index 0000000..f7f2d51 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f53d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f550.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f550.png new file mode 100755 index 0000000..ca34e89 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f550.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f551.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f551.png new file mode 100755 index 0000000..1a12524 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f551.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f552.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f552.png new file mode 100755 index 0000000..cd99bb1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f552.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f553.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f553.png new file mode 100755 index 0000000..7274e8b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f553.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f554.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f554.png new file mode 100755 index 0000000..3ed5a81 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f554.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f555.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f555.png new file mode 100755 index 0000000..ac38cb9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f555.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f556.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f556.png new file mode 100755 index 0000000..6a138df Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f556.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f557.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f557.png new file mode 100755 index 0000000..6690cd7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f557.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f558.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f558.png new file mode 100755 index 0000000..c4ad746 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f558.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f559.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f559.png new file mode 100755 index 0000000..f710bef Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f559.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55a.png new file mode 100755 index 0000000..fbc165b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55b.png new file mode 100755 index 0000000..c1ca82f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55c.png new file mode 100755 index 0000000..df93920 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55d.png new file mode 100755 index 0000000..f12c691 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55e.png new file mode 100755 index 0000000..1dc9628 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55f.png new file mode 100755 index 0000000..7726aae Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f55f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f560.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f560.png new file mode 100755 index 0000000..e08d4ad Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f560.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f561.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f561.png new file mode 100755 index 0000000..46f0681 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f561.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f562.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f562.png new file mode 100755 index 0000000..18aab22 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f562.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f563.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f563.png new file mode 100755 index 0000000..ec3e382 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f563.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f564.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f564.png new file mode 100755 index 0000000..fd35221 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f564.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f565.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f565.png new file mode 100755 index 0000000..84a3bc8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f565.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f566.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f566.png new file mode 100755 index 0000000..415999e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f566.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f567.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f567.png new file mode 100755 index 0000000..a652715 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f567.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5fb.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5fb.png new file mode 100755 index 0000000..4c313e5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5fb.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5fc.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5fc.png new file mode 100755 index 0000000..e1cbd7a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5fc.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5fd.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5fd.png new file mode 100755 index 0000000..9ad9028 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5fd.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5fe.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5fe.png new file mode 100755 index 0000000..4593280 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5fe.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5ff.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5ff.png new file mode 100755 index 0000000..61a1a9c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f5ff.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f600.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f600.png new file mode 100755 index 0000000..0ef00d7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f600.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f601.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f601.png new file mode 100755 index 0000000..591cfce Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f601.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f602.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f602.png new file mode 100755 index 0000000..47df693 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f602.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f603.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f603.png new file mode 100755 index 0000000..77b581d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f603.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f604.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f604.png new file mode 100755 index 0000000..81a8396 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f604.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f605.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f605.png new file mode 100755 index 0000000..3903f71 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f605.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f606.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f606.png new file mode 100755 index 0000000..11c91eb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f606.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f607.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f607.png new file mode 100755 index 0000000..503b614 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f607.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f608.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f608.png new file mode 100755 index 0000000..d904049 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f608.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f609.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f609.png new file mode 100755 index 0000000..756766d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f609.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60a.png new file mode 100755 index 0000000..1e9021c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60b.png new file mode 100755 index 0000000..fc39637 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60c.png new file mode 100755 index 0000000..820cf31 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60d.png new file mode 100755 index 0000000..0e57942 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60e.png new file mode 100755 index 0000000..1c468a1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60f.png new file mode 100755 index 0000000..bc6e508 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f60f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f610.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f610.png new file mode 100755 index 0000000..682a1ba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f610.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f611.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f611.png new file mode 100755 index 0000000..1798f24 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f611.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f612.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f612.png new file mode 100755 index 0000000..3722e6f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f612.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f613.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f613.png new file mode 100755 index 0000000..e894b76 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f613.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f614.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f614.png new file mode 100755 index 0000000..2f3bad9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f614.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f615.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f615.png new file mode 100755 index 0000000..18ff760 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f615.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f616.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f616.png new file mode 100755 index 0000000..a5877a0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f616.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f617.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f617.png new file mode 100755 index 0000000..eb049c8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f617.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f618.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f618.png new file mode 100755 index 0000000..af9a80b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f618.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f619.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f619.png new file mode 100755 index 0000000..d85706e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f619.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61a.png new file mode 100755 index 0000000..449de19 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61b.png new file mode 100755 index 0000000..53c4143 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61c.png new file mode 100755 index 0000000..6ae9d49 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61d.png new file mode 100755 index 0000000..333716e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61e.png new file mode 100755 index 0000000..8255200 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61f.png new file mode 100755 index 0000000..afd9283 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f61f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f620.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f620.png new file mode 100755 index 0000000..34174f5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f620.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f621.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f621.png new file mode 100755 index 0000000..c65ddff Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f621.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f622.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f622.png new file mode 100755 index 0000000..6d0d9af Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f622.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f623.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f623.png new file mode 100755 index 0000000..c7e433e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f623.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f624.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f624.png new file mode 100755 index 0000000..92f93bd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f624.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f625.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f625.png new file mode 100755 index 0000000..fa5f9e7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f625.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f626.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f626.png new file mode 100755 index 0000000..7f8b6c7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f626.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f627.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f627.png new file mode 100755 index 0000000..c2edad7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f627.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f628.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f628.png new file mode 100755 index 0000000..513fce4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f628.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f629.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f629.png new file mode 100755 index 0000000..0c54754 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f629.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62a.png new file mode 100755 index 0000000..df4f55e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62b.png new file mode 100755 index 0000000..3a8eefe Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62c.png new file mode 100755 index 0000000..f78e940 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62d.png new file mode 100755 index 0000000..7d43318 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62e.png new file mode 100755 index 0000000..e528358 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62f.png new file mode 100755 index 0000000..afa3f66 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f62f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f630.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f630.png new file mode 100755 index 0000000..b9e39bc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f630.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f631.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f631.png new file mode 100755 index 0000000..76bfc6b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f631.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f632.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f632.png new file mode 100755 index 0000000..858a834 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f632.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f633.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f633.png new file mode 100755 index 0000000..9b49410 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f633.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f634.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f634.png new file mode 100755 index 0000000..a2f3bf7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f634.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f635.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f635.png new file mode 100755 index 0000000..8001d6f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f635.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f636.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f636.png new file mode 100755 index 0000000..d9ec7ca Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f636.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f637.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f637.png new file mode 100755 index 0000000..05887e9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f637.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f638.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f638.png new file mode 100755 index 0000000..ad333ba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f638.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f639.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f639.png new file mode 100755 index 0000000..6c60cb0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f639.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63a.png new file mode 100755 index 0000000..dbf1b02 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63b.png new file mode 100755 index 0000000..eeba240 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63c.png new file mode 100755 index 0000000..351565e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63d.png new file mode 100755 index 0000000..adc62fb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63e.png new file mode 100755 index 0000000..4325fd4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63f.png new file mode 100755 index 0000000..42d4c27 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f63f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f640.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f640.png new file mode 100755 index 0000000..d94cd34 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f640.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f645.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f645.png new file mode 100755 index 0000000..d459a35 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f645.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f646.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f646.png new file mode 100755 index 0000000..e8b9819 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f646.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f647.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f647.png new file mode 100755 index 0000000..024cb61 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f647.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f648.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f648.png new file mode 100755 index 0000000..0890a62 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f648.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f649.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f649.png new file mode 100755 index 0000000..f97a1f9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f649.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64a.png new file mode 100755 index 0000000..87944c4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64b.png new file mode 100755 index 0000000..e1741a4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64c.png new file mode 100755 index 0000000..e03142b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64d.png new file mode 100755 index 0000000..6f34d5e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64e.png new file mode 100755 index 0000000..c4a95c3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64f.png new file mode 100755 index 0000000..f86c992 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f64f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f680.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f680.png new file mode 100755 index 0000000..783078d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f680.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f681.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f681.png new file mode 100755 index 0000000..8e82a0d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f681.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f682.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f682.png new file mode 100755 index 0000000..5495077 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f682.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f683.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f683.png new file mode 100755 index 0000000..2236115 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f683.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f684.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f684.png new file mode 100755 index 0000000..8eca368 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f684.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f685.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f685.png new file mode 100755 index 0000000..16651ac Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f685.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f686.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f686.png new file mode 100755 index 0000000..9c0d3ab Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f686.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f687.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f687.png new file mode 100755 index 0000000..7f34f6b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f687.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f688.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f688.png new file mode 100755 index 0000000..bcfe801 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f688.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f689.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f689.png new file mode 100755 index 0000000..e77daa8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f689.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68a.png new file mode 100755 index 0000000..5eb29fb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68b.png new file mode 100755 index 0000000..0a8ea52 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68c.png new file mode 100755 index 0000000..823aa39 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68d.png new file mode 100755 index 0000000..3695f76 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68e.png new file mode 100755 index 0000000..b9740a5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68f.png new file mode 100755 index 0000000..99af232 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f68f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f690.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f690.png new file mode 100755 index 0000000..c52cef2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f690.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f691.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f691.png new file mode 100755 index 0000000..b740f45 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f691.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f692.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f692.png new file mode 100755 index 0000000..9e6c59c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f692.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f693.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f693.png new file mode 100755 index 0000000..b8f1727 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f693.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f694.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f694.png new file mode 100755 index 0000000..af20e7e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f694.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f695.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f695.png new file mode 100755 index 0000000..60a50d3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f695.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f696.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f696.png new file mode 100755 index 0000000..f78cf31 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f696.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f697.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f697.png new file mode 100755 index 0000000..d70a2f0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f697.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f698.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f698.png new file mode 100755 index 0000000..cb46de2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f698.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f699.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f699.png new file mode 100755 index 0000000..978291e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f699.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69a.png new file mode 100755 index 0000000..3f25ba1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69b.png new file mode 100755 index 0000000..81ec1f9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69c.png new file mode 100755 index 0000000..058fd3e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69d.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69d.png new file mode 100755 index 0000000..913d300 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69d.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69e.png new file mode 100755 index 0000000..1f3d1aa Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69f.png new file mode 100755 index 0000000..aaa45f6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f69f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a0.png new file mode 100755 index 0000000..5688bb2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a1.png new file mode 100755 index 0000000..38f6dfe Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a2.png new file mode 100755 index 0000000..5d2d8b6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a3.png new file mode 100755 index 0000000..fe8ae3e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a4.png new file mode 100755 index 0000000..da6689b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a5.png new file mode 100755 index 0000000..42eaf70 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a6.png new file mode 100755 index 0000000..7a5ba35 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a7.png new file mode 100755 index 0000000..523e9f1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a8.png new file mode 100755 index 0000000..6cf4a77 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a9.png new file mode 100755 index 0000000..f9a3f32 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6a9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6aa.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6aa.png new file mode 100755 index 0000000..83c819a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6aa.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ab.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ab.png new file mode 100755 index 0000000..a8444d1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ab.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ac.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ac.png new file mode 100755 index 0000000..4aad6cb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ac.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ad.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ad.png new file mode 100755 index 0000000..eb11d79 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ad.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ae.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ae.png new file mode 100755 index 0000000..c2e350c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ae.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6af.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6af.png new file mode 100755 index 0000000..38c7ae7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6af.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b0.png new file mode 100755 index 0000000..e9fd560 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b1.png new file mode 100755 index 0000000..1b29d35 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b2.png new file mode 100755 index 0000000..6573860 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b3.png new file mode 100755 index 0000000..4b26216 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b4.png new file mode 100755 index 0000000..4e3e054 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b5.png new file mode 100755 index 0000000..b698897 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b6.png new file mode 100755 index 0000000..7a2bfac Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b7.png new file mode 100755 index 0000000..c35f530 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b8.png new file mode 100755 index 0000000..b0302ae Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b9.png new file mode 100755 index 0000000..abccfc9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6b9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ba.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ba.png new file mode 100755 index 0000000..518b76a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6ba.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6bb.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6bb.png new file mode 100755 index 0000000..312ca3d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6bb.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6bc.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6bc.png new file mode 100755 index 0000000..2e58725 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6bc.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6bd.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6bd.png new file mode 100755 index 0000000..e5cc411 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6bd.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6be.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6be.png new file mode 100755 index 0000000..dfe84d2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6be.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6bf.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6bf.png new file mode 100755 index 0000000..94f82aa Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6bf.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c0.png new file mode 100755 index 0000000..8f75d1d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c1.png new file mode 100755 index 0000000..1c3f844 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c2.png new file mode 100755 index 0000000..675b76d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c3.png new file mode 100755 index 0000000..92691e3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c4.png new file mode 100755 index 0000000..59ae044 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c5.png new file mode 100755 index 0000000..1c08b46 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/1f6c5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/203C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/203C.png new file mode 100755 index 0000000..6ab2a05 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/203C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/203c-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/203c-fe0f.png new file mode 100755 index 0000000..7270f0a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/203c-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2049-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2049-fe0f.png new file mode 100755 index 0000000..64304b9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2049-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2049.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2049.png new file mode 100755 index 0000000..d58c6ab Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2049.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2122.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2122.png new file mode 100755 index 0000000..fbd208a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2122.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2139-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2139-fe0f.png new file mode 100755 index 0000000..9cb8b09 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2139-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2139.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2139.png new file mode 100755 index 0000000..029c0a2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2139.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2194-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2194-fe0f.png new file mode 100755 index 0000000..b9fd11c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2194-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2194.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2194.png new file mode 100755 index 0000000..115e466 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2194.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2195-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2195-fe0f.png new file mode 100755 index 0000000..b718c21 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2195-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2195.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2195.png new file mode 100755 index 0000000..55dba8b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2195.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2196-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2196-fe0f.png new file mode 100755 index 0000000..12aebd9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2196-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2196.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2196.png new file mode 100755 index 0000000..6130c34 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2196.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2197-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2197-fe0f.png new file mode 100755 index 0000000..0daf4e9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2197-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2197.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2197.png new file mode 100755 index 0000000..ddf8a27 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2197.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2198-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2198-fe0f.png new file mode 100755 index 0000000..2a15cc7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2198-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2198.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2198.png new file mode 100755 index 0000000..91c1cc7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2198.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2199-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2199-fe0f.png new file mode 100755 index 0000000..a4438cb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2199-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2199.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2199.png new file mode 100755 index 0000000..10bc558 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2199.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/21A9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/21A9.png new file mode 100755 index 0000000..df60fa6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/21A9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/21AA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/21AA.png new file mode 100755 index 0000000..98da42e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/21AA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/21a9-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/21a9-fe0f.png new file mode 100755 index 0000000..bc45dfe Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/21a9-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/21aa-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/21aa-fe0f.png new file mode 100755 index 0000000..8b4ea6e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/21aa-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/231A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/231A.png new file mode 100755 index 0000000..111cb8e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/231A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/231B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/231B.png new file mode 100755 index 0000000..d6a1dcb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/231B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/231a-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/231a-fe0f.png new file mode 100755 index 0000000..d503bb8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/231a-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/231b-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/231b-fe0f.png new file mode 100755 index 0000000..405aab4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/231b-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/23e9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/23e9.png new file mode 100755 index 0000000..3a57fb8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/23e9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/23ea.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/23ea.png new file mode 100755 index 0000000..b9974e5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/23ea.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/23eb.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/23eb.png new file mode 100755 index 0000000..80da4bc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/23eb.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/23ec.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/23ec.png new file mode 100755 index 0000000..d5674ac Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/23ec.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/23f0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/23f0.png new file mode 100755 index 0000000..44425d8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/23f0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/23f3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/23f3.png new file mode 100755 index 0000000..363c811 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/23f3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/24C2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/24C2.png new file mode 100755 index 0000000..1a85a21 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/24C2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/24c2-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/24c2-fe0f.png new file mode 100755 index 0000000..7424665 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/24c2-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25AA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25AA.png new file mode 100755 index 0000000..401fc00 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25AA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25AB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25AB.png new file mode 100755 index 0000000..15db128 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25AB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25B6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25B6.png new file mode 100755 index 0000000..8c045a6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25B6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25C0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25C0.png new file mode 100755 index 0000000..d6c7d81 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25C0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25FB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25FB.png new file mode 100755 index 0000000..29a5bea Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25FB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25FC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25FC.png new file mode 100755 index 0000000..fcc2349 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25FC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25FD.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25FD.png new file mode 100755 index 0000000..ce4ddcd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25FD.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25FE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25FE.png new file mode 100755 index 0000000..9d65c14 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25FE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25aa-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25aa-fe0f.png new file mode 100755 index 0000000..a247751 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25aa-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25ab-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25ab-fe0f.png new file mode 100755 index 0000000..24ba879 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25ab-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25b6-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25b6-fe0f.png new file mode 100755 index 0000000..fbfe711 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25b6-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25c0-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25c0-fe0f.png new file mode 100755 index 0000000..2be422b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25c0-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25fb-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25fb-fe0f.png new file mode 100755 index 0000000..199808b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25fb-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25fc-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25fc-fe0f.png new file mode 100755 index 0000000..204cce1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25fc-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25fd-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25fd-fe0f.png new file mode 100755 index 0000000..a115cdc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25fd-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/25fe-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/25fe-fe0f.png new file mode 100755 index 0000000..25bfe9c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/25fe-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2600-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2600-fe0f.png new file mode 100755 index 0000000..d23c095 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2600-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2600.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2600.png new file mode 100755 index 0000000..f342fc3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2600.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2601-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2601-fe0f.png new file mode 100755 index 0000000..b31c08c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2601-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2601.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2601.png new file mode 100755 index 0000000..bfe5046 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2601.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/260E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/260E.png new file mode 100755 index 0000000..e5e49ed Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/260E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/260e-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/260e-fe0f.png new file mode 100755 index 0000000..87d2559 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/260e-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2611-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2611-fe0f.png new file mode 100755 index 0000000..f07a466 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2611-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2611.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2611.png new file mode 100755 index 0000000..0410683 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2611.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2614-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2614-fe0f.png new file mode 100755 index 0000000..1db722f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2614-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2614.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2614.png new file mode 100755 index 0000000..59a81af Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2614.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2615-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2615-fe0f.png new file mode 100755 index 0000000..57e1adc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2615-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2615.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2615.png new file mode 100755 index 0000000..bdb77c7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2615.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/261D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/261D.png new file mode 100755 index 0000000..a1abfc8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/261D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/261d-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/261d-fe0f.png new file mode 100755 index 0000000..01896e2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/261d-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/263A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/263A.png new file mode 100755 index 0000000..56045d0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/263A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/263a-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/263a-fe0f.png new file mode 100755 index 0000000..bbab82d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/263a-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2648-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2648-fe0f.png new file mode 100755 index 0000000..d676fd3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2648-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2648.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2648.png new file mode 100755 index 0000000..53f1b53 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2648.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2649-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2649-fe0f.png new file mode 100755 index 0000000..6af582f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2649-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2649.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2649.png new file mode 100755 index 0000000..2bd3264 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2649.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/264A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/264A.png new file mode 100755 index 0000000..234ebc2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/264A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/264B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/264B.png new file mode 100755 index 0000000..3751615 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/264B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/264C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/264C.png new file mode 100755 index 0000000..5a22a66 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/264C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/264D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/264D.png new file mode 100755 index 0000000..411a8d6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/264D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/264E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/264E.png new file mode 100755 index 0000000..e6e2d45 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/264E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/264F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/264F.png new file mode 100755 index 0000000..a1d26ac Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/264F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/264a-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/264a-fe0f.png new file mode 100755 index 0000000..d926f6e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/264a-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/264b-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/264b-fe0f.png new file mode 100755 index 0000000..ea43a4a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/264b-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/264c-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/264c-fe0f.png new file mode 100755 index 0000000..e025933 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/264c-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/264d-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/264d-fe0f.png new file mode 100755 index 0000000..72e1763 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/264d-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/264e-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/264e-fe0f.png new file mode 100755 index 0000000..c9062dd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/264e-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/264f-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/264f-fe0f.png new file mode 100755 index 0000000..67fcea1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/264f-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2650-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2650-fe0f.png new file mode 100755 index 0000000..8b5435b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2650-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2650.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2650.png new file mode 100755 index 0000000..d4652ec Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2650.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2651-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2651-fe0f.png new file mode 100755 index 0000000..f2044e7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2651-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2651.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2651.png new file mode 100755 index 0000000..821e17b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2651.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2652-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2652-fe0f.png new file mode 100755 index 0000000..cbff66e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2652-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2652.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2652.png new file mode 100755 index 0000000..a00ef85 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2652.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2653-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2653-fe0f.png new file mode 100755 index 0000000..5a2da0a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2653-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2653.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2653.png new file mode 100755 index 0000000..2543912 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2653.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2660-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2660-fe0f.png new file mode 100755 index 0000000..133a1ab Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2660-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2660.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2660.png new file mode 100755 index 0000000..42d5c07 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2660.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2663-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2663-fe0f.png new file mode 100755 index 0000000..bfab536 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2663-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2663.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2663.png new file mode 100755 index 0000000..99e9747 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2663.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2665-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2665-fe0f.png new file mode 100755 index 0000000..e894715 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2665-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2665.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2665.png new file mode 100755 index 0000000..135ed7f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2665.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2666-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2666-fe0f.png new file mode 100755 index 0000000..fe08277 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2666-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2666.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2666.png new file mode 100755 index 0000000..57afaa6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2666.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2668-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2668-fe0f.png new file mode 100755 index 0000000..a0bc9d7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2668-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2668.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2668.png new file mode 100755 index 0000000..043b7ad Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2668.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/267B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/267B.png new file mode 100755 index 0000000..4b1e16f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/267B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/267F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/267F.png new file mode 100755 index 0000000..4651b8e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/267F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/267b-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/267b-fe0f.png new file mode 100755 index 0000000..99104c0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/267b-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/267f-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/267f-fe0f.png new file mode 100755 index 0000000..eddcdd7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/267f-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2693-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2693-fe0f.png new file mode 100755 index 0000000..0c5192e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2693-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2693.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2693.png new file mode 100755 index 0000000..297d8d4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2693.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26A0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26A0.png new file mode 100755 index 0000000..6e871ea Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26A0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26A1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26A1.png new file mode 100755 index 0000000..460411f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26A1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26AA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26AA.png new file mode 100755 index 0000000..a71dbc2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26AA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26AB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26AB.png new file mode 100755 index 0000000..ef4c5d5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26AB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26BD.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26BD.png new file mode 100755 index 0000000..a2c564d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26BD.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26BE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26BE.png new file mode 100755 index 0000000..1b56212 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26BE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26C4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26C4.png new file mode 100755 index 0000000..48bb9cf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26C4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26C5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26C5.png new file mode 100755 index 0000000..a7df8f5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26C5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26D4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26D4.png new file mode 100755 index 0000000..4febe76 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26D4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26EA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26EA.png new file mode 100755 index 0000000..458b91c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26EA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26F2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26F2.png new file mode 100755 index 0000000..b7f3eb7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26F2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26F3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26F3.png new file mode 100755 index 0000000..6aeafde Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26F3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26F5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26F5.png new file mode 100755 index 0000000..51031ef Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26F5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26FA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26FA.png new file mode 100755 index 0000000..048eb51 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26FA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26FD.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26FD.png new file mode 100755 index 0000000..3aff027 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26FD.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26a0-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26a0-fe0f.png new file mode 100755 index 0000000..466658d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26a0-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26a1-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26a1-fe0f.png new file mode 100755 index 0000000..260c531 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26a1-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26aa-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26aa-fe0f.png new file mode 100755 index 0000000..da782ae Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26aa-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26ab-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26ab-fe0f.png new file mode 100755 index 0000000..e46f9df Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26ab-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26bd-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26bd-fe0f.png new file mode 100755 index 0000000..1e118b5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26bd-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26be-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26be-fe0f.png new file mode 100755 index 0000000..da004e2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26be-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26c4-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26c4-fe0f.png new file mode 100755 index 0000000..a97902e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26c4-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26c5-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26c5-fe0f.png new file mode 100755 index 0000000..020dd5f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26c5-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26ce.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26ce.png new file mode 100755 index 0000000..931da0c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26ce.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26d4-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26d4-fe0f.png new file mode 100755 index 0000000..cf2086a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26d4-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26ea-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26ea-fe0f.png new file mode 100755 index 0000000..4c07c6b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26ea-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26f2-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26f2-fe0f.png new file mode 100755 index 0000000..da126e6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26f2-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26f3-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26f3-fe0f.png new file mode 100755 index 0000000..cba2116 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26f3-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26f5-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26f5-fe0f.png new file mode 100755 index 0000000..ff656dc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26f5-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26fa-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26fa-fe0f.png new file mode 100755 index 0000000..5c0d20e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26fa-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/26fd-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/26fd-fe0f.png new file mode 100755 index 0000000..54c29ae Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/26fd-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2702-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2702-fe0f.png new file mode 100755 index 0000000..020e052 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2702-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2702.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2702.png new file mode 100755 index 0000000..638071a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2702.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2705.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2705.png new file mode 100755 index 0000000..860af08 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2705.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2708-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2708-fe0f.png new file mode 100755 index 0000000..8407cb6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2708-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2708.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2708.png new file mode 100755 index 0000000..4b09f24 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2708.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2709-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2709-fe0f.png new file mode 100755 index 0000000..3631861 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2709-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2709.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2709.png new file mode 100755 index 0000000..e4a7cb3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2709.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/270C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/270C.png new file mode 100755 index 0000000..77d49b2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/270C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/270F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/270F.png new file mode 100755 index 0000000..73cbd2b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/270F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/270a.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/270a.png new file mode 100755 index 0000000..f77bf87 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/270a.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/270b.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/270b.png new file mode 100755 index 0000000..425a301 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/270b.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/270c-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/270c-fe0f.png new file mode 100755 index 0000000..f61267c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/270c-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/270f-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/270f-fe0f.png new file mode 100755 index 0000000..e624373 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/270f-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2712-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2712-fe0f.png new file mode 100755 index 0000000..29f6994 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2712-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2712.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2712.png new file mode 100755 index 0000000..1cdcad6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2712.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2714-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2714-fe0f.png new file mode 100755 index 0000000..336d262 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2714-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2714.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2714.png new file mode 100755 index 0000000..1d6691b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2714.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2716-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2716-fe0f.png new file mode 100755 index 0000000..13d6660 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2716-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2716.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2716.png new file mode 100755 index 0000000..28766e3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2716.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2728.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2728.png new file mode 100755 index 0000000..f1f9a4f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2728.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2733-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2733-fe0f.png new file mode 100755 index 0000000..946a203 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2733-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2733.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2733.png new file mode 100755 index 0000000..72304cb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2733.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2734-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2734-fe0f.png new file mode 100755 index 0000000..73dc6a0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2734-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2734.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2734.png new file mode 100755 index 0000000..40bfc30 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2734.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2744-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2744-fe0f.png new file mode 100755 index 0000000..54b68ff Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2744-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2744.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2744.png new file mode 100755 index 0000000..a162423 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2744.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2747-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2747-fe0f.png new file mode 100755 index 0000000..23a68ce Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2747-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2747.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2747.png new file mode 100755 index 0000000..6dac01e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2747.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/274c.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/274c.png new file mode 100755 index 0000000..3de8a64 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/274c.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/274e.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/274e.png new file mode 100755 index 0000000..fe8c23b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/274e.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2753.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2753.png new file mode 100755 index 0000000..57f9154 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2753.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2754.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2754.png new file mode 100755 index 0000000..eb944d1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2754.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2755.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2755.png new file mode 100755 index 0000000..33306e9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2755.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2757-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2757-fe0f.png new file mode 100755 index 0000000..4c560f5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2757-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2757.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2757.png new file mode 100755 index 0000000..a23cde9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2757.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2764-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2764-fe0f.png new file mode 100755 index 0000000..7d7790c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2764-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2764.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2764.png new file mode 100755 index 0000000..1d7bc3f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2764.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2795.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2795.png new file mode 100755 index 0000000..90d83a2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2795.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2796.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2796.png new file mode 100755 index 0000000..7ed4d0f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2796.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2797.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2797.png new file mode 100755 index 0000000..4d12104 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2797.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/27A1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/27A1.png new file mode 100755 index 0000000..2e514a3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/27A1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/27a1-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/27a1-fe0f.png new file mode 100755 index 0000000..e5cca85 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/27a1-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/27b0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/27b0.png new file mode 100755 index 0000000..888dcd9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/27b0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/27bf.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/27bf.png new file mode 100755 index 0000000..56b57ee Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/27bf.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2934-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2934-fe0f.png new file mode 100755 index 0000000..c8f670a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2934-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2934.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2934.png new file mode 100755 index 0000000..cec7b7c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2934.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2935-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2935-fe0f.png new file mode 100755 index 0000000..56dd3b9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2935-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2935.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2935.png new file mode 100755 index 0000000..eb5758d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2935.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2B05.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B05.png new file mode 100755 index 0000000..727b973 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B05.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2B06.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B06.png new file mode 100755 index 0000000..df62e5e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B06.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2B07.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B07.png new file mode 100755 index 0000000..a43839e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B07.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2B1B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B1B.png new file mode 100755 index 0000000..fcc2349 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B1B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2B1C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B1C.png new file mode 100755 index 0000000..aff37be Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B1C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2B50.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B50.png new file mode 100755 index 0000000..8512608 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B50.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2B55.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B55.png new file mode 100755 index 0000000..4dc70bb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2B55.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2b05-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b05-fe0f.png new file mode 100755 index 0000000..9d7d1b5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b05-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2b06-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b06-fe0f.png new file mode 100755 index 0000000..565ce29 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b06-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2b07-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b07-fe0f.png new file mode 100755 index 0000000..3956eb3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b07-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2b1b-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b1b-fe0f.png new file mode 100755 index 0000000..71da10d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b1b-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2b1c-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b1c-fe0f.png new file mode 100755 index 0000000..60cb19a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b1c-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2b50-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b50-fe0f.png new file mode 100755 index 0000000..1bfddc8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b50-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/2b55-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b55-fe0f.png new file mode 100755 index 0000000..0ededeb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/2b55-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/3030.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/3030.png new file mode 100755 index 0000000..df8c6ac Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/3030.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/303D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/303D.png new file mode 100755 index 0000000..9903c75 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/303D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/303d-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/303d-fe0f.png new file mode 100755 index 0000000..45dc9b8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/303d-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/3297-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/3297-fe0f.png new file mode 100755 index 0000000..dcbb1d2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/3297-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/3297.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/3297.png new file mode 100755 index 0000000..92c41ba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/3297.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/3299-fe0f.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/3299-fe0f.png new file mode 100755 index 0000000..82e383a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/3299-fe0f.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/3299.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/3299.png new file mode 100755 index 0000000..7a0aad5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/3299.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDC04.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDC04.png new file mode 100755 index 0000000..1c9c85d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDC04.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDCCF.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDCCF.png new file mode 100755 index 0000000..138887a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDCCF.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD70.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD70.png new file mode 100755 index 0000000..7d802f8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD70.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD71.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD71.png new file mode 100755 index 0000000..a0e1e70 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD71.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD7E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD7E.png new file mode 100755 index 0000000..dc45267 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD7E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD7F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD7F.png new file mode 100755 index 0000000..465cf7b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD7F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD8E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD8E.png new file mode 100755 index 0000000..8f31178 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD8E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD91.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD91.png new file mode 100755 index 0000000..3992b05 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD91.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD92.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD92.png new file mode 100755 index 0000000..ed3ab35 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD92.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD93.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD93.png new file mode 100755 index 0000000..474dcca Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD93.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD94.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD94.png new file mode 100755 index 0000000..e427af4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD94.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD95.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD95.png new file mode 100755 index 0000000..a72f7e2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD95.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD96.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD96.png new file mode 100755 index 0000000..6a51bed Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD96.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD97.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD97.png new file mode 100755 index 0000000..3c50e19 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD97.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD98.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD98.png new file mode 100755 index 0000000..6ea7f4a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD98.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD99.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD99.png new file mode 100755 index 0000000..71b8c59 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD99.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD9A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD9A.png new file mode 100755 index 0000000..f832378 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDD9A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDE8D83CDDF3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDE8D83CDDF3.png new file mode 100755 index 0000000..06be9e9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDE8D83CDDF3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDE9D83CDDEA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDE9D83CDDEA.png new file mode 100755 index 0000000..04afaa6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDE9D83CDDEA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDEAD83CDDF8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDEAD83CDDF8.png new file mode 100755 index 0000000..06a58f1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDEAD83CDDF8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDEBD83CDDF7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDEBD83CDDF7.png new file mode 100755 index 0000000..5c68187 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDEBD83CDDF7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDECD83CDDE7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDECD83CDDE7.png new file mode 100755 index 0000000..ccf786e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDECD83CDDE7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDEED83CDDF9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDEED83CDDF9.png new file mode 100755 index 0000000..d32ec57 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDEED83CDDF9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDEFD83CDDF5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDEFD83CDDF5.png new file mode 100755 index 0000000..ee52121 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDEFD83CDDF5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDF0D83CDDF7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDF0D83CDDF7.png new file mode 100755 index 0000000..79e7cf2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDF0D83CDDF7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDF7D83CDDFA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDF7D83CDDFA.png new file mode 100755 index 0000000..a8ee8fb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDF7D83CDDFA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDFAD83CDDF8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDFAD83CDDF8.png new file mode 100755 index 0000000..2bab340 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDDFAD83CDDF8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE01.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE01.png new file mode 100755 index 0000000..ece31a1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE01.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE02.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE02.png new file mode 100755 index 0000000..d9d54c2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE02.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE1A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE1A.png new file mode 100755 index 0000000..0775f01 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE1A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE2F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE2F.png new file mode 100755 index 0000000..917944b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE2F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE32.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE32.png new file mode 100755 index 0000000..63beabb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE32.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE33.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE33.png new file mode 100755 index 0000000..9f8d0ca Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE33.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE34.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE34.png new file mode 100755 index 0000000..28d40b6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE34.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE35.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE35.png new file mode 100755 index 0000000..3fef789 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE35.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE36.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE36.png new file mode 100755 index 0000000..a665804 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE36.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE37.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE37.png new file mode 100755 index 0000000..6504629 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE37.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE38.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE38.png new file mode 100755 index 0000000..50dc1ca Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE38.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE39.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE39.png new file mode 100755 index 0000000..31d1a8c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE39.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE3A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE3A.png new file mode 100755 index 0000000..5553bd6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE3A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE50.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE50.png new file mode 100755 index 0000000..6f9abf6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE50.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE51.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE51.png new file mode 100755 index 0000000..fbadf51 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDE51.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF00.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF00.png new file mode 100755 index 0000000..204752f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF00.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF01.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF01.png new file mode 100755 index 0000000..3ab8f18 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF01.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF02.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF02.png new file mode 100755 index 0000000..31acd56 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF02.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF03.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF03.png new file mode 100755 index 0000000..b162df6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF03.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF04.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF04.png new file mode 100755 index 0000000..6f1011c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF04.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF05.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF05.png new file mode 100755 index 0000000..432ca54 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF05.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF06.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF06.png new file mode 100755 index 0000000..d79d607 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF06.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF07.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF07.png new file mode 100755 index 0000000..06bb22e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF07.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF08.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF08.png new file mode 100755 index 0000000..52530c0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF08.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF09.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF09.png new file mode 100755 index 0000000..e755fd3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF09.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0A.png new file mode 100755 index 0000000..12e558a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0B.png new file mode 100755 index 0000000..3812e81 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0C.png new file mode 100755 index 0000000..e00ce31 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0D.png new file mode 100755 index 0000000..e82eb63 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0E.png new file mode 100755 index 0000000..9694a04 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0F.png new file mode 100755 index 0000000..419dfc8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF0F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF10.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF10.png new file mode 100755 index 0000000..d03e9de Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF10.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF11.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF11.png new file mode 100755 index 0000000..f2d4f33 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF11.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF12.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF12.png new file mode 100755 index 0000000..ef84f8a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF12.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF13.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF13.png new file mode 100755 index 0000000..570d26f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF13.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF14.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF14.png new file mode 100755 index 0000000..637f731 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF14.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF15.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF15.png new file mode 100755 index 0000000..567bc2b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF15.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF16.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF16.png new file mode 100755 index 0000000..ee45092 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF16.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF17.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF17.png new file mode 100755 index 0000000..501b182 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF17.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF18.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF18.png new file mode 100755 index 0000000..4c0bfb1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF18.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF19.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF19.png new file mode 100755 index 0000000..3733d1a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF19.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1A.png new file mode 100755 index 0000000..f77a021 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1B.png new file mode 100755 index 0000000..b3cf2c3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1C.png new file mode 100755 index 0000000..9ec356b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1D.png new file mode 100755 index 0000000..4e32cc9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1E.png new file mode 100755 index 0000000..aa2596a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1F.png new file mode 100755 index 0000000..4cbd749 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF1F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF20.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF20.png new file mode 100755 index 0000000..69d77a5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF20.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF30.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF30.png new file mode 100755 index 0000000..c3b2ca7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF30.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF31.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF31.png new file mode 100755 index 0000000..e20f1ed Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF31.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF32.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF32.png new file mode 100755 index 0000000..04be1cb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF32.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF33.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF33.png new file mode 100755 index 0000000..acca04c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF33.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF34.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF34.png new file mode 100755 index 0000000..26f9111 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF34.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF35.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF35.png new file mode 100755 index 0000000..d815bfc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF35.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF37.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF37.png new file mode 100755 index 0000000..47f26d1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF37.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF38.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF38.png new file mode 100755 index 0000000..3133130 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF38.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF39.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF39.png new file mode 100755 index 0000000..4d8d57d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF39.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3A.png new file mode 100755 index 0000000..d90e92c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3B.png new file mode 100755 index 0000000..38790bf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3C.png new file mode 100755 index 0000000..12c260c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3D.png new file mode 100755 index 0000000..1b15d9e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3E.png new file mode 100755 index 0000000..36ab468 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3F.png new file mode 100755 index 0000000..8023f11 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF3F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF40.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF40.png new file mode 100755 index 0000000..63a7c51 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF40.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF41.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF41.png new file mode 100755 index 0000000..ef11f48 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF41.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF42.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF42.png new file mode 100755 index 0000000..12ba5a4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF42.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF43.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF43.png new file mode 100755 index 0000000..278c01a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF43.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF44.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF44.png new file mode 100755 index 0000000..ed1ac2e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF44.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF45.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF45.png new file mode 100755 index 0000000..7e42c8e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF45.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF46.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF46.png new file mode 100755 index 0000000..80098f6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF46.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF47.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF47.png new file mode 100755 index 0000000..8fa025e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF47.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF48.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF48.png new file mode 100755 index 0000000..9e48dc8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF48.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF49.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF49.png new file mode 100755 index 0000000..b5da36e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF49.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4A.png new file mode 100755 index 0000000..42b41f5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4B.png new file mode 100755 index 0000000..1aeca64 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4C.png new file mode 100755 index 0000000..3a82ebe Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4D.png new file mode 100755 index 0000000..c4855db Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4E.png new file mode 100755 index 0000000..ae1e17d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4F.png new file mode 100755 index 0000000..c8b997d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF4F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF50.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF50.png new file mode 100755 index 0000000..8917af8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF50.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF51.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF51.png new file mode 100755 index 0000000..c2ddbab Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF51.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF52.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF52.png new file mode 100755 index 0000000..dde2234 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF52.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF53.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF53.png new file mode 100755 index 0000000..c3df5ef Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF53.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF54.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF54.png new file mode 100755 index 0000000..b1bcb15 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF54.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF55.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF55.png new file mode 100755 index 0000000..8ba7363 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF55.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF56.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF56.png new file mode 100755 index 0000000..369487d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF56.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF57.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF57.png new file mode 100755 index 0000000..fcb81d8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF57.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF58.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF58.png new file mode 100755 index 0000000..4149ca5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF58.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF59.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF59.png new file mode 100755 index 0000000..1cb373c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF59.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5A.png new file mode 100755 index 0000000..3e30a98 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5B.png new file mode 100755 index 0000000..2a33787 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5C.png new file mode 100755 index 0000000..710ab85 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5D.png new file mode 100755 index 0000000..9544ec5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5E.png new file mode 100755 index 0000000..4118d08 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5F.png new file mode 100755 index 0000000..d2d8972 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF5F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF60.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF60.png new file mode 100755 index 0000000..9f7c9f8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF60.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF61.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF61.png new file mode 100755 index 0000000..f1ac201 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF61.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF62.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF62.png new file mode 100755 index 0000000..904464f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF62.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF63.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF63.png new file mode 100755 index 0000000..f693b92 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF63.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF64.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF64.png new file mode 100755 index 0000000..a6089b2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF64.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF65.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF65.png new file mode 100755 index 0000000..1279d5e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF65.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF66.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF66.png new file mode 100755 index 0000000..bceef5a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF66.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF67.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF67.png new file mode 100755 index 0000000..198c11e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF67.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF68.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF68.png new file mode 100755 index 0000000..188c74d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF68.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF69.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF69.png new file mode 100755 index 0000000..34c4540 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF69.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6A.png new file mode 100755 index 0000000..f24b47e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6B.png new file mode 100755 index 0000000..d0e6dff Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6C.png new file mode 100755 index 0000000..6daf9be Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6D.png new file mode 100755 index 0000000..ee60e38 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6E.png new file mode 100755 index 0000000..6d89010 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6F.png new file mode 100755 index 0000000..9e63d6a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF6F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF70.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF70.png new file mode 100755 index 0000000..9e2cb93 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF70.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF71.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF71.png new file mode 100755 index 0000000..3219777 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF71.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF72.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF72.png new file mode 100755 index 0000000..a474adc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF72.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF73.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF73.png new file mode 100755 index 0000000..aef1a17 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF73.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF74.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF74.png new file mode 100755 index 0000000..5ebdb77 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF74.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF75.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF75.png new file mode 100755 index 0000000..63ae40d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF75.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF76.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF76.png new file mode 100755 index 0000000..34f05fc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF76.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF77.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF77.png new file mode 100755 index 0000000..e0b426b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF77.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF78.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF78.png new file mode 100755 index 0000000..5684d05 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF78.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF79.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF79.png new file mode 100755 index 0000000..ea8180f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF79.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF7A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF7A.png new file mode 100755 index 0000000..c990d3b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF7A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF7B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF7B.png new file mode 100755 index 0000000..b936fbb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF7B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF7C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF7C.png new file mode 100755 index 0000000..cedf373 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF7C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF80.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF80.png new file mode 100755 index 0000000..f78ad9a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF80.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF81.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF81.png new file mode 100755 index 0000000..12b4ca9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF81.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF82.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF82.png new file mode 100755 index 0000000..ae156d9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF82.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF83.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF83.png new file mode 100755 index 0000000..16e51f2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF83.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF84.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF84.png new file mode 100755 index 0000000..6393694 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF84.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF85.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF85.png new file mode 100755 index 0000000..8797bf8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF85.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF86.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF86.png new file mode 100755 index 0000000..e3b2d86 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF86.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF87.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF87.png new file mode 100755 index 0000000..c31f63f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF87.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF88.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF88.png new file mode 100755 index 0000000..c53d0e7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF88.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF89.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF89.png new file mode 100755 index 0000000..300c490 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF89.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8A.png new file mode 100755 index 0000000..992076b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8B.png new file mode 100755 index 0000000..43959f2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8C.png new file mode 100755 index 0000000..12e67fe Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8D.png new file mode 100755 index 0000000..193a378 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8E.png new file mode 100755 index 0000000..617f79e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8F.png new file mode 100755 index 0000000..b9909e8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF8F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF90.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF90.png new file mode 100755 index 0000000..74176c5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF90.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF91.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF91.png new file mode 100755 index 0000000..8128c77 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF91.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF92.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF92.png new file mode 100755 index 0000000..f87534e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF92.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF93.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF93.png new file mode 100755 index 0000000..74e85dd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDF93.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA0.png new file mode 100755 index 0000000..ecc5e70 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA1.png new file mode 100755 index 0000000..b7da0a1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA2.png new file mode 100755 index 0000000..9c6bcc9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA3.png new file mode 100755 index 0000000..cee41c3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA4.png new file mode 100755 index 0000000..4ab7756 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA5.png new file mode 100755 index 0000000..33f6e7b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA6.png new file mode 100755 index 0000000..688f5c5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA7.png new file mode 100755 index 0000000..f91a3b5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA8.png new file mode 100755 index 0000000..0a96057 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA9.png new file mode 100755 index 0000000..efd0998 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFA9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAA.png new file mode 100755 index 0000000..6ddcd50 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAB.png new file mode 100755 index 0000000..5efb912 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAC.png new file mode 100755 index 0000000..95bb9f4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAD.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAD.png new file mode 100755 index 0000000..4be3699 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAD.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAE.png new file mode 100755 index 0000000..feabd5a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAF.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAF.png new file mode 100755 index 0000000..5e11b5a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFAF.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB0.png new file mode 100755 index 0000000..5f87c62 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB1.png new file mode 100755 index 0000000..f73ca94 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB2.png new file mode 100755 index 0000000..1af3771 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB3.png new file mode 100755 index 0000000..716662c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB4.png new file mode 100755 index 0000000..1d1761e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB5.png new file mode 100755 index 0000000..5229e90 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB6.png new file mode 100755 index 0000000..6879d22 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB7.png new file mode 100755 index 0000000..d249e93 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB8.png new file mode 100755 index 0000000..37ae8fb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB9.png new file mode 100755 index 0000000..6c76d36 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFB9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBA.png new file mode 100755 index 0000000..f5222e8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBB.png new file mode 100755 index 0000000..5d57645 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBC.png new file mode 100755 index 0000000..b702cf6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBD.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBD.png new file mode 100755 index 0000000..d260ed5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBD.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBE.png new file mode 100755 index 0000000..32251b1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBF.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBF.png new file mode 100755 index 0000000..2ca51de Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFBF.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC0.png new file mode 100755 index 0000000..ed70324 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC1.png new file mode 100755 index 0000000..1ec0708 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC2.png new file mode 100755 index 0000000..4fe4a7d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC3.png new file mode 100755 index 0000000..5883c57 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC4.png new file mode 100755 index 0000000..3f0a5f3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC6.png new file mode 100755 index 0000000..945fd7d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC7.png new file mode 100755 index 0000000..b1404bd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC8.png new file mode 100755 index 0000000..cd170c0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC9.png new file mode 100755 index 0000000..9622c6e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFC9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFCA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFCA.png new file mode 100755 index 0000000..2274404 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFCA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE0.png new file mode 100755 index 0000000..c764c55 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE1.png new file mode 100755 index 0000000..fab3034 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE2.png new file mode 100755 index 0000000..d1ae2a6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE3.png new file mode 100755 index 0000000..05e06b8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE4.png new file mode 100755 index 0000000..f71c304 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE5.png new file mode 100755 index 0000000..b3d0e4f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE6.png new file mode 100755 index 0000000..28af3b4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE7.png new file mode 100755 index 0000000..54f4f09 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE8.png new file mode 100755 index 0000000..f0705fe Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE9.png new file mode 100755 index 0000000..4b1326d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFE9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEA.png new file mode 100755 index 0000000..7b17b66 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEB.png new file mode 100755 index 0000000..5196a8d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEC.png new file mode 100755 index 0000000..ec84fba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFED.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFED.png new file mode 100755 index 0000000..8a73573 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFED.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEE.png new file mode 100755 index 0000000..1f0acb7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEF.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEF.png new file mode 100755 index 0000000..366ff92 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFEF.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFF0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFF0.png new file mode 100755 index 0000000..cde8089 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83CDFF0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC00.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC00.png new file mode 100755 index 0000000..3ae7424 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC00.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC01.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC01.png new file mode 100755 index 0000000..0443d1e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC01.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC02.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC02.png new file mode 100755 index 0000000..f96a029 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC02.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC03.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC03.png new file mode 100755 index 0000000..9f6e4f0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC03.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC04.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC04.png new file mode 100755 index 0000000..5dd9cb2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC04.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC05.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC05.png new file mode 100755 index 0000000..06045ac Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC05.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC06.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC06.png new file mode 100755 index 0000000..7a06947 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC06.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC07.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC07.png new file mode 100755 index 0000000..594c4ea Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC07.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC08.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC08.png new file mode 100755 index 0000000..e9e9b4a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC08.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC09.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC09.png new file mode 100755 index 0000000..7044958 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC09.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0A.png new file mode 100755 index 0000000..49a0d38 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0B.png new file mode 100755 index 0000000..c0c2bc6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0C.png new file mode 100755 index 0000000..bb3b6b1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0D.png new file mode 100755 index 0000000..d9c07d1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0E.png new file mode 100755 index 0000000..dc89a78 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0F.png new file mode 100755 index 0000000..ae41652 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC0F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC10.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC10.png new file mode 100755 index 0000000..cea4670 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC10.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC11.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC11.png new file mode 100755 index 0000000..1f023da Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC11.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC12.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC12.png new file mode 100755 index 0000000..300cff2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC12.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC13.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC13.png new file mode 100755 index 0000000..8bdf1c1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC13.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC14.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC14.png new file mode 100755 index 0000000..fcc184c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC14.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC15.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC15.png new file mode 100755 index 0000000..177500f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC15.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC16.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC16.png new file mode 100755 index 0000000..4c18bf1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC16.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC17.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC17.png new file mode 100755 index 0000000..a5309f9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC17.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC18.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC18.png new file mode 100755 index 0000000..0fbbf8b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC18.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC19.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC19.png new file mode 100755 index 0000000..0941d86 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC19.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1A.png new file mode 100755 index 0000000..fcc75f7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1B.png new file mode 100755 index 0000000..6a32d29 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1C.png new file mode 100755 index 0000000..8c3954d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1D.png new file mode 100755 index 0000000..689302f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1E.png new file mode 100755 index 0000000..c4cf165 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1F.png new file mode 100755 index 0000000..c265f8a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC1F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC20.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC20.png new file mode 100755 index 0000000..0fef342 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC20.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC21.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC21.png new file mode 100755 index 0000000..018e13f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC21.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC22.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC22.png new file mode 100755 index 0000000..5aa7636 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC22.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC23.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC23.png new file mode 100755 index 0000000..520f4f6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC23.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC24.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC24.png new file mode 100755 index 0000000..f3e813a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC24.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC25.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC25.png new file mode 100755 index 0000000..577036a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC25.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC26.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC26.png new file mode 100755 index 0000000..933234c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC26.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC27.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC27.png new file mode 100755 index 0000000..5460254 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC27.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC28.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC28.png new file mode 100755 index 0000000..4707b9a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC28.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC29.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC29.png new file mode 100755 index 0000000..a945f8d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC29.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2A.png new file mode 100755 index 0000000..49b736f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2B.png new file mode 100755 index 0000000..aff3436 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2C.png new file mode 100755 index 0000000..13029d5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2D.png new file mode 100755 index 0000000..33a259f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2E.png new file mode 100755 index 0000000..1b52b89 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2F.png new file mode 100755 index 0000000..153fcf5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC2F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC30.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC30.png new file mode 100755 index 0000000..b1cdbd3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC30.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC31.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC31.png new file mode 100755 index 0000000..da9acba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC31.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC32.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC32.png new file mode 100755 index 0000000..d269874 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC32.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC33.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC33.png new file mode 100755 index 0000000..d9e0acd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC33.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC34.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC34.png new file mode 100755 index 0000000..faa4a04 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC34.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC35.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC35.png new file mode 100755 index 0000000..5a82028 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC35.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC36.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC36.png new file mode 100755 index 0000000..6ee913c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC36.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC37.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC37.png new file mode 100755 index 0000000..1da0fbc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC37.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC38.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC38.png new file mode 100755 index 0000000..0ac13e1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC38.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC39.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC39.png new file mode 100755 index 0000000..7872d81 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC39.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3A.png new file mode 100755 index 0000000..0162338 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3B.png new file mode 100755 index 0000000..f8a3eec Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3C.png new file mode 100755 index 0000000..710b710 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3D.png new file mode 100755 index 0000000..16deab0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3E.png new file mode 100755 index 0000000..14ecc51 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC3E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC40.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC40.png new file mode 100755 index 0000000..4dada77 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC40.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC42.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC42.png new file mode 100755 index 0000000..f808446 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC42.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC43.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC43.png new file mode 100755 index 0000000..61f703a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC43.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC44.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC44.png new file mode 100755 index 0000000..b14206e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC44.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC45.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC45.png new file mode 100755 index 0000000..c3d404a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC45.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC46.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC46.png new file mode 100755 index 0000000..5ba1a6a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC46.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC47.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC47.png new file mode 100755 index 0000000..ca2087e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC47.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC48.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC48.png new file mode 100755 index 0000000..db1b865 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC48.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC49.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC49.png new file mode 100755 index 0000000..72d57f6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC49.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4A.png new file mode 100755 index 0000000..222d47b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4B.png new file mode 100755 index 0000000..46f6db9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4C.png new file mode 100755 index 0000000..b4166d8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4D.png new file mode 100755 index 0000000..597100d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4E.png new file mode 100755 index 0000000..f1c698b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4F.png new file mode 100755 index 0000000..ee5debc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC4F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC50.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC50.png new file mode 100755 index 0000000..2be1c4e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC50.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC51.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC51.png new file mode 100755 index 0000000..491c58d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC51.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC52.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC52.png new file mode 100755 index 0000000..7bda9bd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC52.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC53.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC53.png new file mode 100755 index 0000000..4f56e52 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC53.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC54.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC54.png new file mode 100755 index 0000000..bc9156d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC54.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC55.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC55.png new file mode 100755 index 0000000..92b0ee7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC55.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC56.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC56.png new file mode 100755 index 0000000..9cddc85 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC56.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC57.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC57.png new file mode 100755 index 0000000..c7d5b28 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC57.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC58.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC58.png new file mode 100755 index 0000000..d3389c8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC58.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC59.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC59.png new file mode 100755 index 0000000..f45fe2e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC59.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5A.png new file mode 100755 index 0000000..f93271d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5B.png new file mode 100755 index 0000000..12ebad2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5C.png new file mode 100755 index 0000000..a5df091 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5D.png new file mode 100755 index 0000000..caff85c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5E.png new file mode 100755 index 0000000..2be8949 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5F.png new file mode 100755 index 0000000..9d1e72c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC5F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC60.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC60.png new file mode 100755 index 0000000..d64189c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC60.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC61.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC61.png new file mode 100755 index 0000000..5c6e187 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC61.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC62.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC62.png new file mode 100755 index 0000000..439a657 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC62.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC63.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC63.png new file mode 100755 index 0000000..f703451 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC63.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC64.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC64.png new file mode 100755 index 0000000..c2e3ebe Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC64.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC65.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC65.png new file mode 100755 index 0000000..2e6ba31 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC65.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC66.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC66.png new file mode 100755 index 0000000..7ce804d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC66.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC67.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC67.png new file mode 100755 index 0000000..c2530ef Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC67.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC68.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC68.png new file mode 100755 index 0000000..a8f56de Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC68.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC69.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC69.png new file mode 100755 index 0000000..ca660a3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC69.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6A.png new file mode 100755 index 0000000..2b073ec Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6B.png new file mode 100755 index 0000000..89d02c1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6C.png new file mode 100755 index 0000000..2118fec Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6D.png new file mode 100755 index 0000000..f3c2d76 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6E.png new file mode 100755 index 0000000..1671cea Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6F.png new file mode 100755 index 0000000..c6e9ddf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC6F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC70.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC70.png new file mode 100755 index 0000000..298b7b0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC70.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC71.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC71.png new file mode 100755 index 0000000..6b28a96 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC71.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC72.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC72.png new file mode 100755 index 0000000..fb66e78 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC72.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC73.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC73.png new file mode 100755 index 0000000..c96ec5a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC73.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC74.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC74.png new file mode 100755 index 0000000..99d6b1b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC74.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC75.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC75.png new file mode 100755 index 0000000..69f2c13 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC75.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC76.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC76.png new file mode 100755 index 0000000..d39019f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC76.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC77.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC77.png new file mode 100755 index 0000000..adf3fc2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC77.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC78.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC78.png new file mode 100755 index 0000000..cce93a8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC78.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC79.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC79.png new file mode 100755 index 0000000..1658637 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC79.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7A.png new file mode 100755 index 0000000..c06384d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7B.png new file mode 100755 index 0000000..4286fa0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7C.png new file mode 100755 index 0000000..9e4c6a8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7D.png new file mode 100755 index 0000000..9f0a1b9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7E.png new file mode 100755 index 0000000..c8296a8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7F.png new file mode 100755 index 0000000..f1cbd14 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC7F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC80.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC80.png new file mode 100755 index 0000000..4740aa7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC80.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC81.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC81.png new file mode 100755 index 0000000..5b8c874 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC81.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC82.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC82.png new file mode 100755 index 0000000..199914f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC82.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC83.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC83.png new file mode 100755 index 0000000..6e13967 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC83.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC84.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC84.png new file mode 100755 index 0000000..bddd072 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC84.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC85.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC85.png new file mode 100755 index 0000000..35d2641 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC85.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC86.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC86.png new file mode 100755 index 0000000..5cae4ae Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC86.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC87.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC87.png new file mode 100755 index 0000000..df26bf9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC87.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC88.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC88.png new file mode 100755 index 0000000..535580b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC88.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC89.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC89.png new file mode 100755 index 0000000..1a8d2c2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC89.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8A.png new file mode 100755 index 0000000..5c90ed9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8B.png new file mode 100755 index 0000000..26bb805 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8C.png new file mode 100755 index 0000000..0a1cd46 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8D.png new file mode 100755 index 0000000..9a027a3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8E.png new file mode 100755 index 0000000..5eed81f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8F.png new file mode 100755 index 0000000..01a8b24 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC8F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC90.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC90.png new file mode 100755 index 0000000..8b9d557 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC90.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC91.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC91.png new file mode 100755 index 0000000..392037d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC91.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC92.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC92.png new file mode 100755 index 0000000..92db5aa Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC92.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC93.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC93.png new file mode 100755 index 0000000..50cc4d5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC93.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC94.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC94.png new file mode 100755 index 0000000..804e87a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC94.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC95.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC95.png new file mode 100755 index 0000000..179f49c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC95.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC96.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC96.png new file mode 100755 index 0000000..3e494b6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC96.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC97.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC97.png new file mode 100755 index 0000000..c9dd168 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC97.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC98.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC98.png new file mode 100755 index 0000000..be6814d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC98.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC99.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC99.png new file mode 100755 index 0000000..6272460 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC99.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9A.png new file mode 100755 index 0000000..23004f5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9B.png new file mode 100755 index 0000000..b006d65 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9C.png new file mode 100755 index 0000000..818fcc1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9D.png new file mode 100755 index 0000000..2bd506a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9E.png new file mode 100755 index 0000000..457e39e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9F.png new file mode 100755 index 0000000..b0a9df3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDC9F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA0.png new file mode 100755 index 0000000..a9f26e3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA1.png new file mode 100755 index 0000000..799d052 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA2.png new file mode 100755 index 0000000..d37c258 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA3.png new file mode 100755 index 0000000..771b2cc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA4.png new file mode 100755 index 0000000..a90a588 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA5.png new file mode 100755 index 0000000..1027e55 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA6.png new file mode 100755 index 0000000..508a704 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA7.png new file mode 100755 index 0000000..df72d59 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA8.png new file mode 100755 index 0000000..99ae0b5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA9.png new file mode 100755 index 0000000..e8b068f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCA9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAA.png new file mode 100755 index 0000000..6813f36 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAB.png new file mode 100755 index 0000000..c641ada Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAC.png new file mode 100755 index 0000000..663aed9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAD.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAD.png new file mode 100755 index 0000000..c12bc19 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAD.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAE.png new file mode 100755 index 0000000..80c5174 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAF.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAF.png new file mode 100755 index 0000000..b531734 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCAF.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB0.png new file mode 100755 index 0000000..da5f0b2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB1.png new file mode 100755 index 0000000..2429662 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB2.png new file mode 100755 index 0000000..9e5e9a9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB3.png new file mode 100755 index 0000000..18855d9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB4.png new file mode 100755 index 0000000..9daee64 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB5.png new file mode 100755 index 0000000..9d4f456 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB6.png new file mode 100755 index 0000000..2350508 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB7.png new file mode 100755 index 0000000..21f2d2d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB8.png new file mode 100755 index 0000000..e9f43ca Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB9.png new file mode 100755 index 0000000..0ed8365 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCB9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBA.png new file mode 100755 index 0000000..9b190c9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBB.png new file mode 100755 index 0000000..32ab538 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBC.png new file mode 100755 index 0000000..3666441 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBD.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBD.png new file mode 100755 index 0000000..de6b444 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBD.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBE.png new file mode 100755 index 0000000..ced68a0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBF.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBF.png new file mode 100755 index 0000000..24dcb78 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCBF.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC0.png new file mode 100755 index 0000000..db8d296 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC1.png new file mode 100755 index 0000000..2aeaeae Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC2.png new file mode 100755 index 0000000..787498a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC3.png new file mode 100755 index 0000000..e39b6db Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC4.png new file mode 100755 index 0000000..08e1e91 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC5.png new file mode 100755 index 0000000..d67fe6f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC6.png new file mode 100755 index 0000000..a731095 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC7.png new file mode 100755 index 0000000..b3fa2bc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC8.png new file mode 100755 index 0000000..9fbe311 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC9.png new file mode 100755 index 0000000..f35a251 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCC9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCA.png new file mode 100755 index 0000000..a57e3f6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCB.png new file mode 100755 index 0000000..74a74c1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCC.png new file mode 100755 index 0000000..10a4cca Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCD.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCD.png new file mode 100755 index 0000000..9242f23 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCD.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCE.png new file mode 100755 index 0000000..b520988 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCF.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCF.png new file mode 100755 index 0000000..6566811 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCCF.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD0.png new file mode 100755 index 0000000..918fcc5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD1.png new file mode 100755 index 0000000..bf10e1a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD2.png new file mode 100755 index 0000000..761d5ce Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD3.png new file mode 100755 index 0000000..4ec7d75 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD4.png new file mode 100755 index 0000000..017c07b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD5.png new file mode 100755 index 0000000..1df0ffc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD6.png new file mode 100755 index 0000000..6f2916a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD7.png new file mode 100755 index 0000000..087e9ca Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD8.png new file mode 100755 index 0000000..a547ffe Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD9.png new file mode 100755 index 0000000..05363c9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCD9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDA.png new file mode 100755 index 0000000..626aa21 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDB.png new file mode 100755 index 0000000..6d10bc0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDC.png new file mode 100755 index 0000000..9599673 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDD.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDD.png new file mode 100755 index 0000000..b319076 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDD.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDE.png new file mode 100755 index 0000000..0f15c22 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDF.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDF.png new file mode 100755 index 0000000..091fc4d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCDF.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE0.png new file mode 100755 index 0000000..f110dbb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE1.png new file mode 100755 index 0000000..c6a5ad9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE2.png new file mode 100755 index 0000000..a16d5bd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE3.png new file mode 100755 index 0000000..522209a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE4.png new file mode 100755 index 0000000..c57fe86 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE5.png new file mode 100755 index 0000000..3593bd4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE6.png new file mode 100755 index 0000000..6ae5c59 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE7.png new file mode 100755 index 0000000..59cb5cc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE8.png new file mode 100755 index 0000000..77af85c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE9.png new file mode 100755 index 0000000..18141f1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCE9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEA.png new file mode 100755 index 0000000..6a78f62 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEB.png new file mode 100755 index 0000000..62fd492 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEC.png new file mode 100755 index 0000000..705ba4e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCED.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCED.png new file mode 100755 index 0000000..eaa49eb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCED.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEE.png new file mode 100755 index 0000000..a901f60 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEF.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEF.png new file mode 100755 index 0000000..20c5247 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCEF.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF0.png new file mode 100755 index 0000000..f394584 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF1.png new file mode 100755 index 0000000..045f0af Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF2.png new file mode 100755 index 0000000..c70a83c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF3.png new file mode 100755 index 0000000..03ea438 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF4.png new file mode 100755 index 0000000..f6ca6c5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF5.png new file mode 100755 index 0000000..8c4bde6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF6.png new file mode 100755 index 0000000..359b411 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF7.png new file mode 100755 index 0000000..834b0ea Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF9.png new file mode 100755 index 0000000..8e6250d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCF9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCFA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCFA.png new file mode 100755 index 0000000..105423e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCFA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCFB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCFB.png new file mode 100755 index 0000000..e3feff8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCFB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCFC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCFC.png new file mode 100755 index 0000000..8d547c2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDCFC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD00.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD00.png new file mode 100755 index 0000000..408a7d0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD00.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD01.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD01.png new file mode 100755 index 0000000..272c153 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD01.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD02.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD02.png new file mode 100755 index 0000000..71e320a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD02.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD03.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD03.png new file mode 100755 index 0000000..87878aa Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD03.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD04.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD04.png new file mode 100755 index 0000000..255d4e5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD04.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD05.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD05.png new file mode 100755 index 0000000..bad4b74 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD05.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD06.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD06.png new file mode 100755 index 0000000..eda6396 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD06.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD07.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD07.png new file mode 100755 index 0000000..0253a7b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD07.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD08.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD08.png new file mode 100755 index 0000000..71b0719 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD08.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD09.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD09.png new file mode 100755 index 0000000..933e618 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD09.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0A.png new file mode 100755 index 0000000..3f4be47 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0B.png new file mode 100755 index 0000000..c1a9fdc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0C.png new file mode 100755 index 0000000..ec8a53d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0D.png new file mode 100755 index 0000000..27a221b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0E.png new file mode 100755 index 0000000..97e85ef Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0F.png new file mode 100755 index 0000000..84f22f3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD0F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD10.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD10.png new file mode 100755 index 0000000..df908be Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD10.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD11.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD11.png new file mode 100755 index 0000000..7a0d0f3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD11.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD12.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD12.png new file mode 100755 index 0000000..9d16e09 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD12.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD13.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD13.png new file mode 100755 index 0000000..f5c18f8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD13.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD14.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD14.png new file mode 100755 index 0000000..1e2f551 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD14.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD15.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD15.png new file mode 100755 index 0000000..e3065f9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD15.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD16.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD16.png new file mode 100755 index 0000000..ee67935 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD16.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD17.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD17.png new file mode 100755 index 0000000..0ec7763 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD17.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD18.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD18.png new file mode 100755 index 0000000..ec467e6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD18.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD19.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD19.png new file mode 100755 index 0000000..5995de6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD19.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1A.png new file mode 100755 index 0000000..e25c1ac Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1B.png new file mode 100755 index 0000000..4ce62a0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1C.png new file mode 100755 index 0000000..e8bc538 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1D.png new file mode 100755 index 0000000..fc68ddd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1E.png new file mode 100755 index 0000000..dcd12b9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1F.png new file mode 100755 index 0000000..c528a8b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD1F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD20.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD20.png new file mode 100755 index 0000000..b6d78d9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD20.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD21.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD21.png new file mode 100755 index 0000000..1e0f014 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD21.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD22.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD22.png new file mode 100755 index 0000000..f7af5e5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD22.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD23.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD23.png new file mode 100755 index 0000000..a44953a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD23.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD24.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD24.png new file mode 100755 index 0000000..2cdbdb6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD24.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD25.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD25.png new file mode 100755 index 0000000..85cead8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD25.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD26.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD26.png new file mode 100755 index 0000000..10ec684 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD26.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD27.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD27.png new file mode 100755 index 0000000..c132493 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD27.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD28.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD28.png new file mode 100755 index 0000000..7bbf667 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD28.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD29.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD29.png new file mode 100755 index 0000000..50933b2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD29.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2A.png new file mode 100755 index 0000000..bb615cb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2B.png new file mode 100755 index 0000000..c602c06 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2C.png new file mode 100755 index 0000000..d459c25 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2D.png new file mode 100755 index 0000000..58ffaf6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2E.png new file mode 100755 index 0000000..0326133 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2F.png new file mode 100755 index 0000000..96b7e0a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD2F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD30.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD30.png new file mode 100755 index 0000000..cf0bc4a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD30.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD31.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD31.png new file mode 100755 index 0000000..c14ab3c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD31.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD32.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD32.png new file mode 100755 index 0000000..fa13730 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD32.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD33.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD33.png new file mode 100755 index 0000000..3a28436 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD33.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD34.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD34.png new file mode 100755 index 0000000..5a61654 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD34.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD35.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD35.png new file mode 100755 index 0000000..c98fb9d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD35.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD36.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD36.png new file mode 100755 index 0000000..f05460a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD36.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD37.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD37.png new file mode 100755 index 0000000..d616edb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD37.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD38.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD38.png new file mode 100755 index 0000000..737c230 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD38.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD39.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD39.png new file mode 100755 index 0000000..5b1ef17 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD39.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD3A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD3A.png new file mode 100755 index 0000000..28d2d28 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD3A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD3B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD3B.png new file mode 100755 index 0000000..f02f0be Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD3B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD3C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD3C.png new file mode 100755 index 0000000..34f2b2d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD3C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD3D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD3D.png new file mode 100755 index 0000000..6bc3e5a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD3D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD50.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD50.png new file mode 100755 index 0000000..c28e59b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD50.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD51.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD51.png new file mode 100755 index 0000000..a88df13 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD51.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD52.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD52.png new file mode 100755 index 0000000..3fe42c6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD52.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD53.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD53.png new file mode 100755 index 0000000..55a514a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD53.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD54.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD54.png new file mode 100755 index 0000000..0201d19 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD54.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD55.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD55.png new file mode 100755 index 0000000..f147f51 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD55.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD56.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD56.png new file mode 100755 index 0000000..3500cd4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD56.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD57.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD57.png new file mode 100755 index 0000000..094cd86 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD57.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD58.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD58.png new file mode 100755 index 0000000..027b28c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD58.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD59.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD59.png new file mode 100755 index 0000000..0fcbafe Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD59.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5A.png new file mode 100755 index 0000000..49e7149 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5B.png new file mode 100755 index 0000000..7fe0834 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5C.png new file mode 100755 index 0000000..903922f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5D.png new file mode 100755 index 0000000..5caf1a7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5E.png new file mode 100755 index 0000000..937c8ac Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5F.png new file mode 100755 index 0000000..18d450f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD5F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD60.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD60.png new file mode 100755 index 0000000..423bf2b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD60.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD61.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD61.png new file mode 100755 index 0000000..ba61456 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD61.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD62.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD62.png new file mode 100755 index 0000000..8cd3ec6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD62.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD63.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD63.png new file mode 100755 index 0000000..43988d4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD63.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD64.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD64.png new file mode 100755 index 0000000..5b4d059 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD64.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD65.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD65.png new file mode 100755 index 0000000..52364c8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD65.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD66.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD66.png new file mode 100755 index 0000000..7a04dcc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD66.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD67.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD67.png new file mode 100755 index 0000000..d0fb5db Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDD67.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFB.png new file mode 100755 index 0000000..58896cb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFC.png new file mode 100755 index 0000000..a3b14c3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFD.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFD.png new file mode 100755 index 0000000..3b6154a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFD.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFE.png new file mode 100755 index 0000000..5ab1a38 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFF.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFF.png new file mode 100755 index 0000000..735699a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDDFF.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE00.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE00.png new file mode 100755 index 0000000..00bc4ce Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE00.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE01.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE01.png new file mode 100755 index 0000000..bccafc9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE01.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE02.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE02.png new file mode 100755 index 0000000..4895bd2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE02.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE03.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE03.png new file mode 100755 index 0000000..99e234f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE03.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE04.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE04.png new file mode 100755 index 0000000..e538839 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE04.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE05.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE05.png new file mode 100755 index 0000000..8f80beb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE05.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE06.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE06.png new file mode 100755 index 0000000..988cae3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE06.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE07.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE07.png new file mode 100755 index 0000000..65f182f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE07.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE08.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE08.png new file mode 100755 index 0000000..9d5d9a3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE08.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE09.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE09.png new file mode 100755 index 0000000..ee8a067 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE09.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0A.png new file mode 100755 index 0000000..3fb8486 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0B.png new file mode 100755 index 0000000..85be02f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0C.png new file mode 100755 index 0000000..7d9f7b9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0D.png new file mode 100755 index 0000000..f83b772 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0E.png new file mode 100755 index 0000000..c90c380 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0F.png new file mode 100755 index 0000000..d4d5044 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE0F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE10.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE10.png new file mode 100755 index 0000000..681dba8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE10.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE11.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE11.png new file mode 100755 index 0000000..7e900d6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE11.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE12.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE12.png new file mode 100755 index 0000000..5125120 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE12.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE13.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE13.png new file mode 100755 index 0000000..1104999 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE13.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE14.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE14.png new file mode 100755 index 0000000..fd3c3fd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE14.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE15.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE15.png new file mode 100755 index 0000000..7837195 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE15.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE16.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE16.png new file mode 100755 index 0000000..18f0a7e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE16.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE17.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE17.png new file mode 100755 index 0000000..87377d1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE17.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE18.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE18.png new file mode 100755 index 0000000..a308368 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE18.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE19.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE19.png new file mode 100755 index 0000000..0447be6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE19.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1A.png new file mode 100755 index 0000000..2a07a0b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1B.png new file mode 100755 index 0000000..22bee05 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1C.png new file mode 100755 index 0000000..b3e511f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1D.png new file mode 100755 index 0000000..e992d7c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1E.png new file mode 100755 index 0000000..f13f55a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1F.png new file mode 100755 index 0000000..38a3a0c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE1F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE20.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE20.png new file mode 100755 index 0000000..146b9bc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE20.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE21.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE21.png new file mode 100755 index 0000000..e4b35ed Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE21.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE22.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE22.png new file mode 100755 index 0000000..ef6c98f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE22.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE23.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE23.png new file mode 100755 index 0000000..8653634 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE23.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE24.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE24.png new file mode 100755 index 0000000..d6654b5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE24.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE25.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE25.png new file mode 100755 index 0000000..089e385 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE25.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE26.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE26.png new file mode 100755 index 0000000..1f949a9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE26.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE27.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE27.png new file mode 100755 index 0000000..76ada45 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE27.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE28.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE28.png new file mode 100755 index 0000000..7a8680f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE28.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE29.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE29.png new file mode 100755 index 0000000..4dc965e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE29.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2A.png new file mode 100755 index 0000000..661d0fb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2B.png new file mode 100755 index 0000000..26b66c0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2C.png new file mode 100755 index 0000000..658d130 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2D.png new file mode 100755 index 0000000..63b4135 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2E.png new file mode 100755 index 0000000..0f29410 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2F.png new file mode 100755 index 0000000..a4044b7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE2F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE30.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE30.png new file mode 100755 index 0000000..764eed3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE30.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE31.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE31.png new file mode 100755 index 0000000..48e70cf Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE31.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE32.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE32.png new file mode 100755 index 0000000..46d6fd5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE32.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE33.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE33.png new file mode 100755 index 0000000..f3ccb6e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE33.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE34.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE34.png new file mode 100755 index 0000000..2d419d6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE34.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE35.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE35.png new file mode 100755 index 0000000..aeb0b13 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE35.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE36.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE36.png new file mode 100755 index 0000000..2a4d408 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE36.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE37.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE37.png new file mode 100755 index 0000000..da3adaa Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE37.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE38.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE38.png new file mode 100755 index 0000000..f2bb885 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE38.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE39.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE39.png new file mode 100755 index 0000000..acfe474 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE39.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3A.png new file mode 100755 index 0000000..543f7a9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3B.png new file mode 100755 index 0000000..210f495 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3C.png new file mode 100755 index 0000000..af89325 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3D.png new file mode 100755 index 0000000..0ef846b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3E.png new file mode 100755 index 0000000..72ee99a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3F.png new file mode 100755 index 0000000..e5a9d70 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE3F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE40.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE40.png new file mode 100755 index 0000000..1cf3564 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE40.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE45.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE45.png new file mode 100755 index 0000000..82df796 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE45.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE46.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE46.png new file mode 100755 index 0000000..a1654ba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE46.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE47.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE47.png new file mode 100755 index 0000000..0128039 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE47.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE48.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE48.png new file mode 100755 index 0000000..c0e888e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE48.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE49.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE49.png new file mode 100755 index 0000000..e09b972 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE49.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4A.png new file mode 100755 index 0000000..4782ae0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4B.png new file mode 100755 index 0000000..9d83a70 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4C.png new file mode 100755 index 0000000..f8c959e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4D.png new file mode 100755 index 0000000..5644681 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4E.png new file mode 100755 index 0000000..0d93df4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4F.png new file mode 100755 index 0000000..a3c5c5e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE4F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE80.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE80.png new file mode 100755 index 0000000..1e544bd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE80.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE81.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE81.png new file mode 100755 index 0000000..1a1f267 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE81.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE82.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE82.png new file mode 100755 index 0000000..5623b50 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE82.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE83.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE83.png new file mode 100755 index 0000000..415a0b2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE83.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE84.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE84.png new file mode 100755 index 0000000..5dcce61 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE84.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE85.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE85.png new file mode 100755 index 0000000..86e4082 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE85.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE86.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE86.png new file mode 100755 index 0000000..d403359 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE86.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE87.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE87.png new file mode 100755 index 0000000..a4f7444 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE87.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE88.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE88.png new file mode 100755 index 0000000..89764c6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE88.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE89.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE89.png new file mode 100755 index 0000000..b304c57 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE89.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8A.png new file mode 100755 index 0000000..2f587af Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8B.png new file mode 100755 index 0000000..b8700ba Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8C.png new file mode 100755 index 0000000..362c3d6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8D.png new file mode 100755 index 0000000..b859f71 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8E.png new file mode 100755 index 0000000..2300925 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8F.png new file mode 100755 index 0000000..4982086 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE8F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE90.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE90.png new file mode 100755 index 0000000..0b940d9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE90.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE91.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE91.png new file mode 100755 index 0000000..72662b5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE91.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE92.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE92.png new file mode 100755 index 0000000..3103d25 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE92.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE93.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE93.png new file mode 100755 index 0000000..aaa3a7c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE93.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE94.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE94.png new file mode 100755 index 0000000..ed53117 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE94.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE95.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE95.png new file mode 100755 index 0000000..1442f44 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE95.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE96.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE96.png new file mode 100755 index 0000000..79dd002 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE96.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE97.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE97.png new file mode 100755 index 0000000..f6f3dc2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE97.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE98.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE98.png new file mode 100755 index 0000000..bf34145 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE98.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE99.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE99.png new file mode 100755 index 0000000..d252166 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE99.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9A.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9A.png new file mode 100755 index 0000000..6cac5a7 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9A.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9B.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9B.png new file mode 100755 index 0000000..73e7bb3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9B.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9C.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9C.png new file mode 100755 index 0000000..2c64b49 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9C.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9D.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9D.png new file mode 100755 index 0000000..ca0dea4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9D.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9E.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9E.png new file mode 100755 index 0000000..b64cfed Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9E.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9F.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9F.png new file mode 100755 index 0000000..1493ea3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDE9F.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA0.png new file mode 100755 index 0000000..a19b257 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA1.png new file mode 100755 index 0000000..2722430 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA2.png new file mode 100755 index 0000000..9d0cf64 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA3.png new file mode 100755 index 0000000..962910c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA4.png new file mode 100755 index 0000000..c552ed6 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA5.png new file mode 100755 index 0000000..1717d3f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA6.png new file mode 100755 index 0000000..eaacd68 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA7.png new file mode 100755 index 0000000..467b3f3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA8.png new file mode 100755 index 0000000..0efd4fb Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA9.png new file mode 100755 index 0000000..52779f0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEA9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAA.png new file mode 100755 index 0000000..c5ce573 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAB.png new file mode 100755 index 0000000..a6b81fa Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAC.png new file mode 100755 index 0000000..ec5cfbc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAD.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAD.png new file mode 100755 index 0000000..26533ea Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAD.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAE.png new file mode 100755 index 0000000..0b7636c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAF.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAF.png new file mode 100755 index 0000000..5636e7f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEAF.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB0.png new file mode 100755 index 0000000..d1107b5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB1.png new file mode 100755 index 0000000..dee702a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB2.png new file mode 100755 index 0000000..4a80ff4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB3.png new file mode 100755 index 0000000..37fe320 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB4.png new file mode 100755 index 0000000..9bebad5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB5.png new file mode 100755 index 0000000..33e25c0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB6.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB6.png new file mode 100755 index 0000000..dffa038 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB7.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB7.png new file mode 100755 index 0000000..571f43c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB7.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB8.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB8.png new file mode 100755 index 0000000..07de47e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB8.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB9.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB9.png new file mode 100755 index 0000000..753471c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEB9.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBA.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBA.png new file mode 100755 index 0000000..d6a6791 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBA.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBB.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBB.png new file mode 100755 index 0000000..aea50a3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBB.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBC.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBC.png new file mode 100755 index 0000000..ac6872d Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBC.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBD.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBD.png new file mode 100755 index 0000000..b855598 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBD.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBE.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBE.png new file mode 100755 index 0000000..da6a8fe Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBE.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBF.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBF.png new file mode 100755 index 0000000..42ed525 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEBF.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC0.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC0.png new file mode 100755 index 0000000..141f95a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC1.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC1.png new file mode 100755 index 0000000..39ac988 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC2.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC2.png new file mode 100755 index 0000000..1bc3914 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC3.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC3.png new file mode 100755 index 0000000..c0e621a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC4.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC4.png new file mode 100755 index 0000000..96f6f0c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC5.png b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC5.png new file mode 100755 index 0000000..ae2c85c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/Separated/D83DDEC5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part0.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part0.png new file mode 100755 index 0000000..89ac8ac Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part1.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part1.png new file mode 100755 index 0000000..28bce47 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part2.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part2.png new file mode 100755 index 0000000..ec21682 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part3.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part3.png new file mode 100755 index 0000000..b0a67f3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part4.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part4.png new file mode 100755 index 0000000..61c5437 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part5.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part5.png new file mode 100755 index 0000000..16ddf15 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat0_part5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part0.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part0.png new file mode 100755 index 0000000..5e5e4cd Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part1.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part1.png new file mode 100755 index 0000000..87b7425 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part2.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part2.png new file mode 100755 index 0000000..a06ef4e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part3.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part3.png new file mode 100755 index 0000000..1ce74a4 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat1_part3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part0.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part0.png new file mode 100755 index 0000000..665bb59 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part1.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part1.png new file mode 100755 index 0000000..6addd30 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part2.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part2.png new file mode 100755 index 0000000..f581833 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part3.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part3.png new file mode 100755 index 0000000..bc7e5d1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part4.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part4.png new file mode 100755 index 0000000..ddaa1e9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part5.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part5.png new file mode 100755 index 0000000..2b494ae Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part6.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part6.png new file mode 100755 index 0000000..a06875b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat2_part6.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part0.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part0.png new file mode 100755 index 0000000..c506439 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part1.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part1.png new file mode 100755 index 0000000..6b2aac1 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part2.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part2.png new file mode 100755 index 0000000..3e2c0c5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat3_part2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part0.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part0.png new file mode 100755 index 0000000..36f31a3 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part1.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part1.png new file mode 100755 index 0000000..1bc77a8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part2.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part2.png new file mode 100755 index 0000000..c9ea9d5 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part3.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part3.png new file mode 100755 index 0000000..da0064b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part4.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part4.png new file mode 100755 index 0000000..04531d0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part5.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part5.png new file mode 100755 index 0000000..e5b3a88 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSprites/sprite64_cat4_part5.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part0.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part0.png new file mode 100755 index 0000000..a1aab42 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part1.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part1.png new file mode 100755 index 0000000..e3b9d22 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part2.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part2.png new file mode 100755 index 0000000..36b2727 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part3.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part3.png new file mode 100755 index 0000000..dd4ca7b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat0_part3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part0.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part0.png new file mode 100755 index 0000000..53daf0e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part1.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part1.png new file mode 100755 index 0000000..7eb3b0c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part2.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part2.png new file mode 100755 index 0000000..37ec77c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat1_part2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part0.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part0.png new file mode 100755 index 0000000..c0b216b Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part1.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part1.png new file mode 100755 index 0000000..082786c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part2.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part2.png new file mode 100755 index 0000000..bdf3a94 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part3.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part3.png new file mode 100755 index 0000000..96a1804 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part4.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part4.png new file mode 100755 index 0000000..539ae11 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat2_part4.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part0.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part0.png new file mode 100755 index 0000000..7e80868 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part1.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part1.png new file mode 100755 index 0000000..7c72d23 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part2.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part2.png new file mode 100755 index 0000000..b8ab291 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat3_part2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part0.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part0.png new file mode 100755 index 0000000..ed22b18 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part0.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part1.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part1.png new file mode 100755 index 0000000..38840e9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part1.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part2.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part2.png new file mode 100755 index 0000000..f07b4a8 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part2.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part3.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part3.png new file mode 100755 index 0000000..8bbe910 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part3.png differ diff --git a/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part4.png b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part4.png new file mode 100755 index 0000000..7a630f9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Emoji/SpacedSpritesLandscape/sprite64_landscape_cat4_part4.png differ diff --git a/Telegram.EmojiPanel/Assets/Sounds/KbdFunction.wav b/Telegram.EmojiPanel/Assets/Sounds/KbdFunction.wav new file mode 100755 index 0000000..bf68554 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Sounds/KbdFunction.wav differ diff --git a/Telegram.EmojiPanel/Assets/Sounds/KbdKeyTap.wav b/Telegram.EmojiPanel/Assets/Sounds/KbdKeyTap.wav new file mode 100755 index 0000000..e67780f Binary files /dev/null and b/Telegram.EmojiPanel/Assets/Sounds/KbdKeyTap.wav differ diff --git a/Telegram.EmojiPanel/Assets/emoji.abc-WXGA.png b/Telegram.EmojiPanel/Assets/emoji.abc-WXGA.png new file mode 100755 index 0000000..51b5d34 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/emoji.abc-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/emoji.backspace-WXGA.png b/Telegram.EmojiPanel/Assets/emoji.backspace-WXGA.png new file mode 100755 index 0000000..849473c Binary files /dev/null and b/Telegram.EmojiPanel/Assets/emoji.backspace-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/emoji.category.1-WXGA.png b/Telegram.EmojiPanel/Assets/emoji.category.1-WXGA.png new file mode 100755 index 0000000..6a87e8a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/emoji.category.1-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/emoji.category.2-WXGA.png b/Telegram.EmojiPanel/Assets/emoji.category.2-WXGA.png new file mode 100755 index 0000000..3015a13 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/emoji.category.2-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/emoji.category.3-WXGA.png b/Telegram.EmojiPanel/Assets/emoji.category.3-WXGA.png new file mode 100755 index 0000000..1d446d0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/emoji.category.3-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/emoji.category.4-WXGA.png b/Telegram.EmojiPanel/Assets/emoji.category.4-WXGA.png new file mode 100755 index 0000000..97cfc53 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/emoji.category.4-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/emoji.category.5-WXGA.png b/Telegram.EmojiPanel/Assets/emoji.category.5-WXGA.png new file mode 100755 index 0000000..6ca64ed Binary files /dev/null and b/Telegram.EmojiPanel/Assets/emoji.category.5-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/emoji.recent-WXGA.png b/Telegram.EmojiPanel/Assets/emoji.recent-WXGA.png new file mode 100755 index 0000000..0680b5e Binary files /dev/null and b/Telegram.EmojiPanel/Assets/emoji.recent-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/light.emoji.abc-WXGA.png b/Telegram.EmojiPanel/Assets/light.emoji.abc-WXGA.png new file mode 100755 index 0000000..4a500b2 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/light.emoji.abc-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/light.emoji.backspace-WXGA.png b/Telegram.EmojiPanel/Assets/light.emoji.backspace-WXGA.png new file mode 100755 index 0000000..32ac45a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/light.emoji.backspace-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/light.emoji.category.1-WXGA.png b/Telegram.EmojiPanel/Assets/light.emoji.category.1-WXGA.png new file mode 100755 index 0000000..09d08a0 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/light.emoji.category.1-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/light.emoji.category.2-WXGA.png b/Telegram.EmojiPanel/Assets/light.emoji.category.2-WXGA.png new file mode 100755 index 0000000..a838126 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/light.emoji.category.2-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/light.emoji.category.3-WXGA.png b/Telegram.EmojiPanel/Assets/light.emoji.category.3-WXGA.png new file mode 100755 index 0000000..76c0226 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/light.emoji.category.3-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/light.emoji.category.4-WXGA.png b/Telegram.EmojiPanel/Assets/light.emoji.category.4-WXGA.png new file mode 100755 index 0000000..b91b6dc Binary files /dev/null and b/Telegram.EmojiPanel/Assets/light.emoji.category.4-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/light.emoji.category.5-WXGA.png b/Telegram.EmojiPanel/Assets/light.emoji.category.5-WXGA.png new file mode 100755 index 0000000..091213a Binary files /dev/null and b/Telegram.EmojiPanel/Assets/light.emoji.category.5-WXGA.png differ diff --git a/Telegram.EmojiPanel/Assets/light.emoji.recent-WXGA.png b/Telegram.EmojiPanel/Assets/light.emoji.recent-WXGA.png new file mode 100755 index 0000000..f89e9c9 Binary files /dev/null and b/Telegram.EmojiPanel/Assets/light.emoji.recent-WXGA.png differ diff --git a/Telegram.EmojiPanel/BrowserNavigationService.cs b/Telegram.EmojiPanel/BrowserNavigationService.cs new file mode 100755 index 0000000..12a8208 --- /dev/null +++ b/Telegram.EmojiPanel/BrowserNavigationService.cs @@ -0,0 +1,1306 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Microsoft.Phone.Tasks; +using Telegram.EmojiPanel.Controls.Emoji; + +namespace Telegram.EmojiPanel +{ + + public static class Emoji + { + private static Dictionary _dict; + + public static Dictionary Dict + { + get + { + if (_dict == null) + { + _dict = new Dictionary(); + + InitializeDict(); + } + + return _dict; + } + } + + private static void InitializeDict() + { + _dict["002320E3"] = "002320E3"; + _dict["003020E3"] = "003020E3"; + _dict["003120E3"] = "003120E3"; + _dict["003220E3"] = "003220E3"; + _dict["003320E3"] = "003320E3"; + _dict["003420E3"] = "003420E3"; + _dict["003520E3"] = "003520E3"; + _dict["003620E3"] = "003620E3"; + _dict["003720E3"] = "003720E3"; + _dict["003820E3"] = "003820E3"; + _dict["003920E3"] = "003920E3"; + _dict["00A9"] = "00A9"; + _dict["00AE"] = "00AE"; + _dict["203C"] = "203C"; + _dict["2049"] = "2049"; + _dict["2122"] = "2122"; + _dict["2139"] = "2139"; + _dict["2194"] = "2194"; + _dict["2195"] = "2195"; + _dict["2196"] = "2196"; + _dict["2197"] = "2197"; + _dict["2198"] = "2198"; + _dict["2199"] = "2199"; + _dict["21A9"] = "21A9"; + _dict["21AA"] = "21AA"; + _dict["231A"] = "231A"; + _dict["231B"] = "231B"; + _dict["23E9"] = "23E9"; + _dict["23EA"] = "23EA"; + _dict["23EB"] = "23EB"; + _dict["23EC"] = "23EC"; + _dict["23F0"] = "23F0"; + _dict["23F3"] = "23F3"; + _dict["24C2"] = "24C2"; + _dict["25AA"] = "25AA"; + _dict["25AB"] = "25AB"; + _dict["25B6"] = "25B6"; + _dict["25C0"] = "25C0"; + _dict["25FB"] = "25FB"; + _dict["25FC"] = "25FC"; + _dict["25FD"] = "25FD"; + _dict["25FE"] = "25FE"; + _dict["2600"] = "2600"; + _dict["2601"] = "2601"; + _dict["260E"] = "260E"; + _dict["2611"] = "2611"; + _dict["2614"] = "2614"; + _dict["2615"] = "2615"; + _dict["261D"] = "261D"; + _dict["263A"] = "263A"; + _dict["2648"] = "2648"; + _dict["2649"] = "2649"; + _dict["264A"] = "264A"; + _dict["264B"] = "264B"; + _dict["264C"] = "264C"; + _dict["264D"] = "264D"; + _dict["264E"] = "264E"; + _dict["264F"] = "264F"; + _dict["2650"] = "2650"; + _dict["2651"] = "2651"; + _dict["2652"] = "2652"; + _dict["2653"] = "2653"; + _dict["2660"] = "2660"; + _dict["2663"] = "2663"; + _dict["2665"] = "2665"; + _dict["2666"] = "2666"; + _dict["2668"] = "2668"; + _dict["267B"] = "267B"; + _dict["267F"] = "267F"; + _dict["2693"] = "2693"; + _dict["26A0"] = "26A0"; + _dict["26A1"] = "26A1"; + _dict["26AA"] = "26AA"; + _dict["26AB"] = "26AB"; + _dict["26BD"] = "26BD"; + _dict["26BE"] = "26BE"; + _dict["26C4"] = "26C4"; + _dict["26C5"] = "26C5"; + _dict["26CE"] = "26CE"; + _dict["26D4"] = "26D4"; + _dict["26EA"] = "26EA"; + _dict["26F2"] = "26F2"; + _dict["26F3"] = "26F3"; + _dict["26F5"] = "26F5"; + _dict["26FA"] = "26FA"; + _dict["26FD"] = "26FD"; + _dict["2702"] = "2702"; + _dict["2705"] = "2705"; + _dict["2708"] = "2708"; + _dict["2709"] = "2709"; + _dict["270A"] = "270A"; + _dict["270B"] = "270B"; + _dict["270C"] = "270C"; + _dict["270F"] = "270F"; + _dict["2712"] = "2712"; + _dict["2714"] = "2714"; + _dict["2716"] = "2716"; + _dict["2728"] = "2728"; + _dict["2733"] = "2733"; + _dict["2734"] = "2734"; + _dict["2744"] = "2744"; + _dict["2747"] = "2747"; + _dict["274C"] = "274C"; + _dict["274E"] = "274E"; + _dict["2753"] = "2753"; + _dict["2754"] = "2754"; + _dict["2755"] = "2755"; + _dict["2757"] = "2757"; + _dict["2764"] = "2764"; + _dict["2795"] = "2795"; + _dict["2796"] = "2796"; + _dict["2797"] = "2797"; + _dict["27A1"] = "27A1"; + _dict["27B0"] = "27B0"; + _dict["27BF"] = "27BF"; + _dict["2934"] = "2934"; + _dict["2935"] = "2935"; + _dict["2B05"] = "2B05"; + _dict["2B06"] = "2B06"; + _dict["2B07"] = "2B07"; + _dict["2B1B"] = "2B1B"; + _dict["2B1C"] = "2B1C"; + _dict["2B50"] = "2B50"; + _dict["2B55"] = "2B55"; + _dict["3030"] = "3030"; + _dict["303D"] = "303D"; + _dict["3297"] = "3297"; + _dict["3299"] = "3299"; + _dict["D83CDC04"] = "D83CDC04"; + _dict["D83CDCCF"] = "D83CDCCF"; + _dict["D83CDD70"] = "D83CDD70"; + _dict["D83CDD71"] = "D83CDD71"; + _dict["D83CDD7E"] = "D83CDD7E"; + _dict["D83CDD7F"] = "D83CDD7F"; + _dict["D83CDD8E"] = "D83CDD8E"; + _dict["D83CDD91"] = "D83CDD91"; + _dict["D83CDD92"] = "D83CDD92"; + _dict["D83CDD93"] = "D83CDD93"; + _dict["D83CDD94"] = "D83CDD94"; + _dict["D83CDD95"] = "D83CDD95"; + _dict["D83CDD96"] = "D83CDD96"; + _dict["D83CDD97"] = "D83CDD97"; + _dict["D83CDD98"] = "D83CDD98"; + _dict["D83CDD99"] = "D83CDD99"; + _dict["D83CDD9A"] = "D83CDD9A"; + _dict["D83CDDE8D83CDDF3"] = "D83CDDE8D83CDDF3"; + _dict["D83CDDE9D83CDDEA"] = "D83CDDE9D83CDDEA"; + _dict["D83CDDEAD83CDDF8"] = "D83CDDEAD83CDDF8"; + _dict["D83CDDEBD83CDDF7"] = "D83CDDEBD83CDDF7"; + _dict["D83CDDECD83CDDE7"] = "D83CDDECD83CDDE7"; + _dict["D83CDDEED83CDDF9"] = "D83CDDEED83CDDF9"; + _dict["D83CDDEFD83CDDF5"] = "D83CDDEFD83CDDF5"; + _dict["D83CDDF0D83CDDF7"] = "D83CDDF0D83CDDF7"; + _dict["D83CDDF7D83CDDFA"] = "D83CDDF7D83CDDFA"; + _dict["D83CDDFAD83CDDF8"] = "D83CDDFAD83CDDF8"; + _dict["D83CDE01"] = "D83CDE01"; + _dict["D83CDE02"] = "D83CDE02"; + _dict["D83CDE1A"] = "D83CDE1A"; + _dict["D83CDE2F"] = "D83CDE2F"; + _dict["D83CDE32"] = "D83CDE32"; + _dict["D83CDE33"] = "D83CDE33"; + _dict["D83CDE34"] = "D83CDE34"; + _dict["D83CDE35"] = "D83CDE35"; + _dict["D83CDE36"] = "D83CDE36"; + _dict["D83CDE37"] = "D83CDE37"; + _dict["D83CDE38"] = "D83CDE38"; + _dict["D83CDE39"] = "D83CDE39"; + _dict["D83CDE3A"] = "D83CDE3A"; + _dict["D83CDE50"] = "D83CDE50"; + _dict["D83CDE51"] = "D83CDE51"; + _dict["D83CDF00"] = "D83CDF00"; + _dict["D83CDF01"] = "D83CDF01"; + _dict["D83CDF02"] = "D83CDF02"; + _dict["D83CDF03"] = "D83CDF03"; + _dict["D83CDF04"] = "D83CDF04"; + _dict["D83CDF05"] = "D83CDF05"; + _dict["D83CDF06"] = "D83CDF06"; + _dict["D83CDF07"] = "D83CDF07"; + _dict["D83CDF08"] = "D83CDF08"; + _dict["D83CDF09"] = "D83CDF09"; + _dict["D83CDF0A"] = "D83CDF0A"; + _dict["D83CDF0B"] = "D83CDF0B"; + _dict["D83CDF0C"] = "D83CDF0C"; + _dict["D83CDF0D"] = "D83CDF0D"; + _dict["D83CDF0E"] = "D83CDF0E"; + _dict["D83CDF0F"] = "D83CDF0F"; + _dict["D83CDF10"] = "D83CDF10"; + _dict["D83CDF11"] = "D83CDF11"; + _dict["D83CDF12"] = "D83CDF12"; + _dict["D83CDF13"] = "D83CDF13"; + _dict["D83CDF14"] = "D83CDF14"; + _dict["D83CDF15"] = "D83CDF15"; + _dict["D83CDF16"] = "D83CDF16"; + _dict["D83CDF17"] = "D83CDF17"; + _dict["D83CDF18"] = "D83CDF18"; + _dict["D83CDF19"] = "D83CDF19"; + _dict["D83CDF1A"] = "D83CDF1A"; + _dict["D83CDF1B"] = "D83CDF1B"; + _dict["D83CDF1C"] = "D83CDF1C"; + _dict["D83CDF1D"] = "D83CDF1D"; + _dict["D83CDF1E"] = "D83CDF1E"; + _dict["D83CDF1F"] = "D83CDF1F"; + _dict["D83CDF20"] = "D83CDF20"; + _dict["D83CDF30"] = "D83CDF30"; + _dict["D83CDF31"] = "D83CDF31"; + _dict["D83CDF32"] = "D83CDF32"; + _dict["D83CDF33"] = "D83CDF33"; + _dict["D83CDF34"] = "D83CDF34"; + _dict["D83CDF35"] = "D83CDF35"; + _dict["D83CDF37"] = "D83CDF37"; + _dict["D83CDF38"] = "D83CDF38"; + _dict["D83CDF39"] = "D83CDF39"; + _dict["D83CDF3A"] = "D83CDF3A"; + _dict["D83CDF3B"] = "D83CDF3B"; + _dict["D83CDF3C"] = "D83CDF3C"; + _dict["D83CDF3D"] = "D83CDF3D"; + _dict["D83CDF3E"] = "D83CDF3E"; + _dict["D83CDF3F"] = "D83CDF3F"; + _dict["D83CDF40"] = "D83CDF40"; + _dict["D83CDF41"] = "D83CDF41"; + _dict["D83CDF42"] = "D83CDF42"; + _dict["D83CDF43"] = "D83CDF43"; + _dict["D83CDF44"] = "D83CDF44"; + _dict["D83CDF45"] = "D83CDF45"; + _dict["D83CDF46"] = "D83CDF46"; + _dict["D83CDF47"] = "D83CDF47"; + _dict["D83CDF48"] = "D83CDF48"; + _dict["D83CDF49"] = "D83CDF49"; + _dict["D83CDF4A"] = "D83CDF4A"; + _dict["D83CDF4B"] = "D83CDF4B"; + _dict["D83CDF4C"] = "D83CDF4C"; + _dict["D83CDF4D"] = "D83CDF4D"; + _dict["D83CDF4E"] = "D83CDF4E"; + _dict["D83CDF4F"] = "D83CDF4F"; + _dict["D83CDF50"] = "D83CDF50"; + _dict["D83CDF51"] = "D83CDF51"; + _dict["D83CDF52"] = "D83CDF52"; + _dict["D83CDF53"] = "D83CDF53"; + _dict["D83CDF54"] = "D83CDF54"; + _dict["D83CDF55"] = "D83CDF55"; + _dict["D83CDF56"] = "D83CDF56"; + _dict["D83CDF57"] = "D83CDF57"; + _dict["D83CDF58"] = "D83CDF58"; + _dict["D83CDF59"] = "D83CDF59"; + _dict["D83CDF5A"] = "D83CDF5A"; + _dict["D83CDF5B"] = "D83CDF5B"; + _dict["D83CDF5C"] = "D83CDF5C"; + _dict["D83CDF5D"] = "D83CDF5D"; + _dict["D83CDF5E"] = "D83CDF5E"; + _dict["D83CDF5F"] = "D83CDF5F"; + _dict["D83CDF60"] = "D83CDF60"; + _dict["D83CDF61"] = "D83CDF61"; + _dict["D83CDF62"] = "D83CDF62"; + _dict["D83CDF63"] = "D83CDF63"; + _dict["D83CDF64"] = "D83CDF64"; + _dict["D83CDF65"] = "D83CDF65"; + _dict["D83CDF66"] = "D83CDF66"; + _dict["D83CDF67"] = "D83CDF67"; + _dict["D83CDF68"] = "D83CDF68"; + _dict["D83CDF69"] = "D83CDF69"; + _dict["D83CDF6A"] = "D83CDF6A"; + _dict["D83CDF6B"] = "D83CDF6B"; + _dict["D83CDF6C"] = "D83CDF6C"; + _dict["D83CDF6D"] = "D83CDF6D"; + _dict["D83CDF6E"] = "D83CDF6E"; + _dict["D83CDF6F"] = "D83CDF6F"; + _dict["D83CDF70"] = "D83CDF70"; + _dict["D83CDF71"] = "D83CDF71"; + _dict["D83CDF72"] = "D83CDF72"; + _dict["D83CDF73"] = "D83CDF73"; + _dict["D83CDF74"] = "D83CDF74"; + _dict["D83CDF75"] = "D83CDF75"; + _dict["D83CDF76"] = "D83CDF76"; + _dict["D83CDF77"] = "D83CDF77"; + _dict["D83CDF78"] = "D83CDF78"; + _dict["D83CDF79"] = "D83CDF79"; + _dict["D83CDF7A"] = "D83CDF7A"; + _dict["D83CDF7B"] = "D83CDF7B"; + _dict["D83CDF7C"] = "D83CDF7C"; + _dict["D83CDF80"] = "D83CDF80"; + _dict["D83CDF81"] = "D83CDF81"; + _dict["D83CDF82"] = "D83CDF82"; + _dict["D83CDF83"] = "D83CDF83"; + _dict["D83CDF84"] = "D83CDF84"; + _dict["D83CDF85"] = "D83CDF85"; + _dict["D83CDF86"] = "D83CDF86"; + _dict["D83CDF87"] = "D83CDF87"; + _dict["D83CDF88"] = "D83CDF88"; + _dict["D83CDF89"] = "D83CDF89"; + _dict["D83CDF8A"] = "D83CDF8A"; + _dict["D83CDF8B"] = "D83CDF8B"; + _dict["D83CDF8C"] = "D83CDF8C"; + _dict["D83CDF8D"] = "D83CDF8D"; + _dict["D83CDF8E"] = "D83CDF8E"; + _dict["D83CDF8F"] = "D83CDF8F"; + _dict["D83CDF90"] = "D83CDF90"; + _dict["D83CDF91"] = "D83CDF91"; + _dict["D83CDF92"] = "D83CDF92"; + _dict["D83CDF93"] = "D83CDF93"; + _dict["D83CDFA0"] = "D83CDFA0"; + _dict["D83CDFA1"] = "D83CDFA1"; + _dict["D83CDFA2"] = "D83CDFA2"; + _dict["D83CDFA3"] = "D83CDFA3"; + _dict["D83CDFA4"] = "D83CDFA4"; + _dict["D83CDFA5"] = "D83CDFA5"; + _dict["D83CDFA6"] = "D83CDFA6"; + _dict["D83CDFA7"] = "D83CDFA7"; + _dict["D83CDFA8"] = "D83CDFA8"; + _dict["D83CDFA9"] = "D83CDFA9"; + _dict["D83CDFAA"] = "D83CDFAA"; + _dict["D83CDFAB"] = "D83CDFAB"; + _dict["D83CDFAC"] = "D83CDFAC"; + _dict["D83CDFAD"] = "D83CDFAD"; + _dict["D83CDFAE"] = "D83CDFAE"; + _dict["D83CDFAF"] = "D83CDFAF"; + _dict["D83CDFB0"] = "D83CDFB0"; + _dict["D83CDFB1"] = "D83CDFB1"; + _dict["D83CDFB2"] = "D83CDFB2"; + _dict["D83CDFB3"] = "D83CDFB3"; + _dict["D83CDFB4"] = "D83CDFB4"; + _dict["D83CDFB5"] = "D83CDFB5"; + _dict["D83CDFB6"] = "D83CDFB6"; + _dict["D83CDFB7"] = "D83CDFB7"; + _dict["D83CDFB8"] = "D83CDFB8"; + _dict["D83CDFB9"] = "D83CDFB9"; + _dict["D83CDFBA"] = "D83CDFBA"; + _dict["D83CDFBB"] = "D83CDFBB"; + _dict["D83CDFBC"] = "D83CDFBC"; + _dict["D83CDFBD"] = "D83CDFBD"; + _dict["D83CDFBE"] = "D83CDFBE"; + _dict["D83CDFBF"] = "D83CDFBF"; + _dict["D83CDFC0"] = "D83CDFC0"; + _dict["D83CDFC1"] = "D83CDFC1"; + _dict["D83CDFC2"] = "D83CDFC2"; + _dict["D83CDFC3"] = "D83CDFC3"; + _dict["D83CDFC4"] = "D83CDFC4"; + _dict["D83CDFC6"] = "D83CDFC6"; + _dict["D83CDFC7"] = "D83CDFC7"; + _dict["D83CDFC8"] = "D83CDFC8"; + _dict["D83CDFC9"] = "D83CDFC9"; + _dict["D83CDFCA"] = "D83CDFCA"; + _dict["D83CDFE0"] = "D83CDFE0"; + _dict["D83CDFE1"] = "D83CDFE1"; + _dict["D83CDFE2"] = "D83CDFE2"; + _dict["D83CDFE3"] = "D83CDFE3"; + _dict["D83CDFE4"] = "D83CDFE4"; + _dict["D83CDFE5"] = "D83CDFE5"; + _dict["D83CDFE6"] = "D83CDFE6"; + _dict["D83CDFE7"] = "D83CDFE7"; + _dict["D83CDFE8"] = "D83CDFE8"; + _dict["D83CDFE9"] = "D83CDFE9"; + _dict["D83CDFEA"] = "D83CDFEA"; + _dict["D83CDFEB"] = "D83CDFEB"; + _dict["D83CDFEC"] = "D83CDFEC"; + _dict["D83CDFED"] = "D83CDFED"; + _dict["D83CDFEE"] = "D83CDFEE"; + _dict["D83CDFEF"] = "D83CDFEF"; + _dict["D83CDFF0"] = "D83CDFF0"; + _dict["D83DDC00"] = "D83DDC00"; + _dict["D83DDC01"] = "D83DDC01"; + _dict["D83DDC02"] = "D83DDC02"; + _dict["D83DDC03"] = "D83DDC03"; + _dict["D83DDC04"] = "D83DDC04"; + _dict["D83DDC05"] = "D83DDC05"; + _dict["D83DDC06"] = "D83DDC06"; + _dict["D83DDC07"] = "D83DDC07"; + _dict["D83DDC08"] = "D83DDC08"; + _dict["D83DDC09"] = "D83DDC09"; + _dict["D83DDC0A"] = "D83DDC0A"; + _dict["D83DDC0B"] = "D83DDC0B"; + _dict["D83DDC0C"] = "D83DDC0C"; + _dict["D83DDC0D"] = "D83DDC0D"; + _dict["D83DDC0E"] = "D83DDC0E"; + _dict["D83DDC0F"] = "D83DDC0F"; + _dict["D83DDC10"] = "D83DDC10"; + _dict["D83DDC11"] = "D83DDC11"; + _dict["D83DDC12"] = "D83DDC12"; + _dict["D83DDC13"] = "D83DDC13"; + _dict["D83DDC14"] = "D83DDC14"; + _dict["D83DDC15"] = "D83DDC15"; + _dict["D83DDC16"] = "D83DDC16"; + _dict["D83DDC17"] = "D83DDC17"; + _dict["D83DDC18"] = "D83DDC18"; + _dict["D83DDC19"] = "D83DDC19"; + _dict["D83DDC1A"] = "D83DDC1A"; + _dict["D83DDC1B"] = "D83DDC1B"; + _dict["D83DDC1C"] = "D83DDC1C"; + _dict["D83DDC1D"] = "D83DDC1D"; + _dict["D83DDC1E"] = "D83DDC1E"; + _dict["D83DDC1F"] = "D83DDC1F"; + _dict["D83DDC20"] = "D83DDC20"; + _dict["D83DDC21"] = "D83DDC21"; + _dict["D83DDC22"] = "D83DDC22"; + _dict["D83DDC23"] = "D83DDC23"; + _dict["D83DDC24"] = "D83DDC24"; + _dict["D83DDC25"] = "D83DDC25"; + _dict["D83DDC26"] = "D83DDC26"; + _dict["D83DDC27"] = "D83DDC27"; + _dict["D83DDC28"] = "D83DDC28"; + _dict["D83DDC29"] = "D83DDC29"; + _dict["D83DDC2A"] = "D83DDC2A"; + _dict["D83DDC2B"] = "D83DDC2B"; + _dict["D83DDC2C"] = "D83DDC2C"; + _dict["D83DDC2D"] = "D83DDC2D"; + _dict["D83DDC2E"] = "D83DDC2E"; + _dict["D83DDC2F"] = "D83DDC2F"; + _dict["D83DDC30"] = "D83DDC30"; + _dict["D83DDC31"] = "D83DDC31"; + _dict["D83DDC32"] = "D83DDC32"; + _dict["D83DDC33"] = "D83DDC33"; + _dict["D83DDC34"] = "D83DDC34"; + _dict["D83DDC35"] = "D83DDC35"; + _dict["D83DDC36"] = "D83DDC36"; + _dict["D83DDC37"] = "D83DDC37"; + _dict["D83DDC38"] = "D83DDC38"; + _dict["D83DDC39"] = "D83DDC39"; + _dict["D83DDC3A"] = "D83DDC3A"; + _dict["D83DDC3B"] = "D83DDC3B"; + _dict["D83DDC3C"] = "D83DDC3C"; + _dict["D83DDC3D"] = "D83DDC3D"; + _dict["D83DDC3E"] = "D83DDC3E"; + _dict["D83DDC40"] = "D83DDC40"; + _dict["D83DDC42"] = "D83DDC42"; + _dict["D83DDC43"] = "D83DDC43"; + _dict["D83DDC44"] = "D83DDC44"; + _dict["D83DDC45"] = "D83DDC45"; + _dict["D83DDC46"] = "D83DDC46"; + _dict["D83DDC47"] = "D83DDC47"; + _dict["D83DDC48"] = "D83DDC48"; + _dict["D83DDC49"] = "D83DDC49"; + _dict["D83DDC4A"] = "D83DDC4A"; + _dict["D83DDC4B"] = "D83DDC4B"; + _dict["D83DDC4C"] = "D83DDC4C"; + _dict["D83DDC4D"] = "D83DDC4D"; + _dict["D83DDC4E"] = "D83DDC4E"; + _dict["D83DDC4F"] = "D83DDC4F"; + _dict["D83DDC50"] = "D83DDC50"; + _dict["D83DDC51"] = "D83DDC51"; + _dict["D83DDC52"] = "D83DDC52"; + _dict["D83DDC53"] = "D83DDC53"; + _dict["D83DDC54"] = "D83DDC54"; + _dict["D83DDC55"] = "D83DDC55"; + _dict["D83DDC56"] = "D83DDC56"; + _dict["D83DDC57"] = "D83DDC57"; + _dict["D83DDC58"] = "D83DDC58"; + _dict["D83DDC59"] = "D83DDC59"; + _dict["D83DDC5A"] = "D83DDC5A"; + _dict["D83DDC5B"] = "D83DDC5B"; + _dict["D83DDC5C"] = "D83DDC5C"; + _dict["D83DDC5D"] = "D83DDC5D"; + _dict["D83DDC5E"] = "D83DDC5E"; + _dict["D83DDC5F"] = "D83DDC5F"; + _dict["D83DDC60"] = "D83DDC60"; + _dict["D83DDC61"] = "D83DDC61"; + _dict["D83DDC62"] = "D83DDC62"; + _dict["D83DDC63"] = "D83DDC63"; + _dict["D83DDC64"] = "D83DDC64"; + _dict["D83DDC65"] = "D83DDC65"; + _dict["D83DDC66"] = "D83DDC66"; + _dict["D83DDC67"] = "D83DDC67"; + _dict["D83DDC68"] = "D83DDC68"; + _dict["D83DDC69"] = "D83DDC69"; + _dict["D83DDC6A"] = "D83DDC6A"; + _dict["D83DDC6B"] = "D83DDC6B"; + _dict["D83DDC6C"] = "D83DDC6C"; + _dict["D83DDC6D"] = "D83DDC6D"; + _dict["D83DDC6E"] = "D83DDC6E"; + _dict["D83DDC6F"] = "D83DDC6F"; + _dict["D83DDC70"] = "D83DDC70"; + _dict["D83DDC71"] = "D83DDC71"; + _dict["D83DDC72"] = "D83DDC72"; + _dict["D83DDC73"] = "D83DDC73"; + _dict["D83DDC74"] = "D83DDC74"; + _dict["D83DDC75"] = "D83DDC75"; + _dict["D83DDC76"] = "D83DDC76"; + _dict["D83DDC77"] = "D83DDC77"; + _dict["D83DDC78"] = "D83DDC78"; + _dict["D83DDC79"] = "D83DDC79"; + _dict["D83DDC7A"] = "D83DDC7A"; + _dict["D83DDC7B"] = "D83DDC7B"; + _dict["D83DDC7C"] = "D83DDC7C"; + _dict["D83DDC7D"] = "D83DDC7D"; + _dict["D83DDC7E"] = "D83DDC7E"; + _dict["D83DDC7F"] = "D83DDC7F"; + _dict["D83DDC80"] = "D83DDC80"; + _dict["D83DDC81"] = "D83DDC81"; + _dict["D83DDC82"] = "D83DDC82"; + _dict["D83DDC83"] = "D83DDC83"; + _dict["D83DDC84"] = "D83DDC84"; + _dict["D83DDC85"] = "D83DDC85"; + _dict["D83DDC86"] = "D83DDC86"; + _dict["D83DDC87"] = "D83DDC87"; + _dict["D83DDC88"] = "D83DDC88"; + _dict["D83DDC89"] = "D83DDC89"; + _dict["D83DDC8A"] = "D83DDC8A"; + _dict["D83DDC8B"] = "D83DDC8B"; + _dict["D83DDC8C"] = "D83DDC8C"; + _dict["D83DDC8D"] = "D83DDC8D"; + _dict["D83DDC8E"] = "D83DDC8E"; + _dict["D83DDC8F"] = "D83DDC8F"; + _dict["D83DDC90"] = "D83DDC90"; + _dict["D83DDC91"] = "D83DDC91"; + _dict["D83DDC92"] = "D83DDC92"; + _dict["D83DDC93"] = "D83DDC93"; + _dict["D83DDC94"] = "D83DDC94"; + _dict["D83DDC95"] = "D83DDC95"; + _dict["D83DDC96"] = "D83DDC96"; + _dict["D83DDC97"] = "D83DDC97"; + _dict["D83DDC98"] = "D83DDC98"; + _dict["D83DDC99"] = "D83DDC99"; + _dict["D83DDC9A"] = "D83DDC9A"; + _dict["D83DDC9B"] = "D83DDC9B"; + _dict["D83DDC9C"] = "D83DDC9C"; + _dict["D83DDC9D"] = "D83DDC9D"; + _dict["D83DDC9E"] = "D83DDC9E"; + _dict["D83DDC9F"] = "D83DDC9F"; + _dict["D83DDCA0"] = "D83DDCA0"; + _dict["D83DDCA1"] = "D83DDCA1"; + _dict["D83DDCA2"] = "D83DDCA2"; + _dict["D83DDCA3"] = "D83DDCA3"; + _dict["D83DDCA4"] = "D83DDCA4"; + _dict["D83DDCA5"] = "D83DDCA5"; + _dict["D83DDCA6"] = "D83DDCA6"; + _dict["D83DDCA7"] = "D83DDCA7"; + _dict["D83DDCA8"] = "D83DDCA8"; + _dict["D83DDCA9"] = "D83DDCA9"; + _dict["D83DDCAA"] = "D83DDCAA"; + _dict["D83DDCAB"] = "D83DDCAB"; + _dict["D83DDCAC"] = "D83DDCAC"; + _dict["D83DDCAD"] = "D83DDCAD"; + _dict["D83DDCAE"] = "D83DDCAE"; + _dict["D83DDCAF"] = "D83DDCAF"; + _dict["D83DDCB0"] = "D83DDCB0"; + _dict["D83DDCB1"] = "D83DDCB1"; + _dict["D83DDCB2"] = "D83DDCB2"; + _dict["D83DDCB3"] = "D83DDCB3"; + _dict["D83DDCB4"] = "D83DDCB4"; + _dict["D83DDCB5"] = "D83DDCB5"; + _dict["D83DDCB6"] = "D83DDCB6"; + _dict["D83DDCB7"] = "D83DDCB7"; + _dict["D83DDCB8"] = "D83DDCB8"; + _dict["D83DDCB9"] = "D83DDCB9"; + _dict["D83DDCBA"] = "D83DDCBA"; + _dict["D83DDCBB"] = "D83DDCBB"; + _dict["D83DDCBC"] = "D83DDCBC"; + _dict["D83DDCBD"] = "D83DDCBD"; + _dict["D83DDCBE"] = "D83DDCBE"; + _dict["D83DDCBF"] = "D83DDCBF"; + _dict["D83DDCC0"] = "D83DDCC0"; + _dict["D83DDCC1"] = "D83DDCC1"; + _dict["D83DDCC2"] = "D83DDCC2"; + _dict["D83DDCC3"] = "D83DDCC3"; + _dict["D83DDCC4"] = "D83DDCC4"; + _dict["D83DDCC5"] = "D83DDCC5"; + _dict["D83DDCC6"] = "D83DDCC6"; + _dict["D83DDCC7"] = "D83DDCC7"; + _dict["D83DDCC8"] = "D83DDCC8"; + _dict["D83DDCC9"] = "D83DDCC9"; + _dict["D83DDCCA"] = "D83DDCCA"; + _dict["D83DDCCB"] = "D83DDCCB"; + _dict["D83DDCCC"] = "D83DDCCC"; + _dict["D83DDCCD"] = "D83DDCCD"; + _dict["D83DDCCE"] = "D83DDCCE"; + _dict["D83DDCCF"] = "D83DDCCF"; + _dict["D83DDCD0"] = "D83DDCD0"; + _dict["D83DDCD1"] = "D83DDCD1"; + _dict["D83DDCD2"] = "D83DDCD2"; + _dict["D83DDCD3"] = "D83DDCD3"; + _dict["D83DDCD4"] = "D83DDCD4"; + _dict["D83DDCD5"] = "D83DDCD5"; + _dict["D83DDCD6"] = "D83DDCD6"; + _dict["D83DDCD7"] = "D83DDCD7"; + _dict["D83DDCD8"] = "D83DDCD8"; + _dict["D83DDCD9"] = "D83DDCD9"; + _dict["D83DDCDA"] = "D83DDCDA"; + _dict["D83DDCDB"] = "D83DDCDB"; + _dict["D83DDCDC"] = "D83DDCDC"; + _dict["D83DDCDD"] = "D83DDCDD"; + _dict["D83DDCDE"] = "D83DDCDE"; + _dict["D83DDCDF"] = "D83DDCDF"; + _dict["D83DDCE0"] = "D83DDCE0"; + _dict["D83DDCE1"] = "D83DDCE1"; + _dict["D83DDCE2"] = "D83DDCE2"; + _dict["D83DDCE3"] = "D83DDCE3"; + _dict["D83DDCE4"] = "D83DDCE4"; + _dict["D83DDCE5"] = "D83DDCE5"; + _dict["D83DDCE6"] = "D83DDCE6"; + _dict["D83DDCE7"] = "D83DDCE7"; + _dict["D83DDCE8"] = "D83DDCE8"; + _dict["D83DDCE9"] = "D83DDCE9"; + _dict["D83DDCEA"] = "D83DDCEA"; + _dict["D83DDCEB"] = "D83DDCEB"; + _dict["D83DDCEC"] = "D83DDCEC"; + _dict["D83DDCED"] = "D83DDCED"; + _dict["D83DDCEE"] = "D83DDCEE"; + _dict["D83DDCEF"] = "D83DDCEF"; + _dict["D83DDCF0"] = "D83DDCF0"; + _dict["D83DDCF1"] = "D83DDCF1"; + _dict["D83DDCF2"] = "D83DDCF2"; + _dict["D83DDCF3"] = "D83DDCF3"; + _dict["D83DDCF4"] = "D83DDCF4"; + _dict["D83DDCF5"] = "D83DDCF5"; + _dict["D83DDCF6"] = "D83DDCF6"; + _dict["D83DDCF7"] = "D83DDCF7"; + _dict["D83DDCF9"] = "D83DDCF9"; + _dict["D83DDCFA"] = "D83DDCFA"; + _dict["D83DDCFB"] = "D83DDCFB"; + _dict["D83DDCFC"] = "D83DDCFC"; + _dict["D83DDD00"] = "D83DDD00"; + _dict["D83DDD01"] = "D83DDD01"; + _dict["D83DDD02"] = "D83DDD02"; + _dict["D83DDD03"] = "D83DDD03"; + _dict["D83DDD04"] = "D83DDD04"; + _dict["D83DDD05"] = "D83DDD05"; + _dict["D83DDD06"] = "D83DDD06"; + _dict["D83DDD07"] = "D83DDD07"; + _dict["D83DDD08"] = "D83DDD08"; + _dict["D83DDD09"] = "D83DDD09"; + _dict["D83DDD0A"] = "D83DDD0A"; + _dict["D83DDD0B"] = "D83DDD0B"; + _dict["D83DDD0C"] = "D83DDD0C"; + _dict["D83DDD0D"] = "D83DDD0D"; + _dict["D83DDD0E"] = "D83DDD0E"; + _dict["D83DDD0F"] = "D83DDD0F"; + _dict["D83DDD10"] = "D83DDD10"; + _dict["D83DDD11"] = "D83DDD11"; + _dict["D83DDD12"] = "D83DDD12"; + _dict["D83DDD13"] = "D83DDD13"; + _dict["D83DDD14"] = "D83DDD14"; + _dict["D83DDD15"] = "D83DDD15"; + _dict["D83DDD16"] = "D83DDD16"; + _dict["D83DDD17"] = "D83DDD17"; + _dict["D83DDD18"] = "D83DDD18"; + _dict["D83DDD19"] = "D83DDD19"; + _dict["D83DDD1A"] = "D83DDD1A"; + _dict["D83DDD1B"] = "D83DDD1B"; + _dict["D83DDD1C"] = "D83DDD1C"; + _dict["D83DDD1D"] = "D83DDD1D"; + _dict["D83DDD1E"] = "D83DDD1E"; + _dict["D83DDD1F"] = "D83DDD1F"; + _dict["D83DDD20"] = "D83DDD20"; + _dict["D83DDD21"] = "D83DDD21"; + _dict["D83DDD22"] = "D83DDD22"; + _dict["D83DDD23"] = "D83DDD23"; + _dict["D83DDD24"] = "D83DDD24"; + _dict["D83DDD25"] = "D83DDD25"; + _dict["D83DDD26"] = "D83DDD26"; + _dict["D83DDD27"] = "D83DDD27"; + _dict["D83DDD28"] = "D83DDD28"; + _dict["D83DDD29"] = "D83DDD29"; + _dict["D83DDD2A"] = "D83DDD2A"; + _dict["D83DDD2B"] = "D83DDD2B"; + _dict["D83DDD2C"] = "D83DDD2C"; + _dict["D83DDD2D"] = "D83DDD2D"; + _dict["D83DDD2E"] = "D83DDD2E"; + _dict["D83DDD2F"] = "D83DDD2F"; + _dict["D83DDD30"] = "D83DDD30"; + _dict["D83DDD31"] = "D83DDD31"; + _dict["D83DDD32"] = "D83DDD32"; + _dict["D83DDD33"] = "D83DDD33"; + _dict["D83DDD34"] = "D83DDD34"; + _dict["D83DDD35"] = "D83DDD35"; + _dict["D83DDD36"] = "D83DDD36"; + _dict["D83DDD37"] = "D83DDD37"; + _dict["D83DDD38"] = "D83DDD38"; + _dict["D83DDD39"] = "D83DDD39"; + _dict["D83DDD3A"] = "D83DDD3A"; + _dict["D83DDD3B"] = "D83DDD3B"; + _dict["D83DDD3C"] = "D83DDD3C"; + _dict["D83DDD3D"] = "D83DDD3D"; + _dict["D83DDD50"] = "D83DDD50"; + _dict["D83DDD51"] = "D83DDD51"; + _dict["D83DDD52"] = "D83DDD52"; + _dict["D83DDD53"] = "D83DDD53"; + _dict["D83DDD54"] = "D83DDD54"; + _dict["D83DDD55"] = "D83DDD55"; + _dict["D83DDD56"] = "D83DDD56"; + _dict["D83DDD57"] = "D83DDD57"; + _dict["D83DDD58"] = "D83DDD58"; + _dict["D83DDD59"] = "D83DDD59"; + _dict["D83DDD5A"] = "D83DDD5A"; + _dict["D83DDD5B"] = "D83DDD5B"; + _dict["D83DDD5C"] = "D83DDD5C"; + _dict["D83DDD5D"] = "D83DDD5D"; + _dict["D83DDD5E"] = "D83DDD5E"; + _dict["D83DDD5F"] = "D83DDD5F"; + _dict["D83DDD60"] = "D83DDD60"; + _dict["D83DDD61"] = "D83DDD61"; + _dict["D83DDD62"] = "D83DDD62"; + _dict["D83DDD63"] = "D83DDD63"; + _dict["D83DDD64"] = "D83DDD64"; + _dict["D83DDD65"] = "D83DDD65"; + _dict["D83DDD66"] = "D83DDD66"; + _dict["D83DDD67"] = "D83DDD67"; + _dict["D83DDDFB"] = "D83DDDFB"; + _dict["D83DDDFC"] = "D83DDDFC"; + _dict["D83DDDFD"] = "D83DDDFD"; + _dict["D83DDDFE"] = "D83DDDFE"; + _dict["D83DDDFF"] = "D83DDDFF"; + _dict["D83DDE00"] = "D83DDE00"; + _dict["D83DDE01"] = "D83DDE01"; + _dict["D83DDE02"] = "D83DDE02"; + _dict["D83DDE03"] = "D83DDE03"; + _dict["D83DDE04"] = "D83DDE04"; + _dict["D83DDE05"] = "D83DDE05"; + _dict["D83DDE06"] = "D83DDE06"; + _dict["D83DDE07"] = "D83DDE07"; + _dict["D83DDE08"] = "D83DDE08"; + _dict["D83DDE09"] = "D83DDE09"; + _dict["D83DDE0A"] = "D83DDE0A"; + _dict["D83DDE0B"] = "D83DDE0B"; + _dict["D83DDE0C"] = "D83DDE0C"; + _dict["D83DDE0D"] = "D83DDE0D"; + _dict["D83DDE0E"] = "D83DDE0E"; + _dict["D83DDE0F"] = "D83DDE0F"; + _dict["D83DDE10"] = "D83DDE10"; + _dict["D83DDE11"] = "D83DDE11"; + _dict["D83DDE12"] = "D83DDE12"; + _dict["D83DDE13"] = "D83DDE13"; + _dict["D83DDE14"] = "D83DDE14"; + _dict["D83DDE15"] = "D83DDE15"; + _dict["D83DDE16"] = "D83DDE16"; + _dict["D83DDE17"] = "D83DDE17"; + _dict["D83DDE18"] = "D83DDE18"; + _dict["D83DDE19"] = "D83DDE19"; + _dict["D83DDE1A"] = "D83DDE1A"; + _dict["D83DDE1B"] = "D83DDE1B"; + _dict["D83DDE1C"] = "D83DDE1C"; + _dict["D83DDE1D"] = "D83DDE1D"; + _dict["D83DDE1E"] = "D83DDE1E"; + _dict["D83DDE1F"] = "D83DDE1F"; + _dict["D83DDE20"] = "D83DDE20"; + _dict["D83DDE21"] = "D83DDE21"; + _dict["D83DDE22"] = "D83DDE22"; + _dict["D83DDE23"] = "D83DDE23"; + _dict["D83DDE24"] = "D83DDE24"; + _dict["D83DDE25"] = "D83DDE25"; + _dict["D83DDE26"] = "D83DDE26"; + _dict["D83DDE27"] = "D83DDE27"; + _dict["D83DDE28"] = "D83DDE28"; + _dict["D83DDE29"] = "D83DDE29"; + _dict["D83DDE2A"] = "D83DDE2A"; + _dict["D83DDE2B"] = "D83DDE2B"; + _dict["D83DDE2C"] = "D83DDE2C"; + _dict["D83DDE2D"] = "D83DDE2D"; + _dict["D83DDE2E"] = "D83DDE2E"; + _dict["D83DDE2F"] = "D83DDE2F"; + _dict["D83DDE30"] = "D83DDE30"; + _dict["D83DDE31"] = "D83DDE31"; + _dict["D83DDE32"] = "D83DDE32"; + _dict["D83DDE33"] = "D83DDE33"; + _dict["D83DDE34"] = "D83DDE34"; + _dict["D83DDE35"] = "D83DDE35"; + _dict["D83DDE36"] = "D83DDE36"; + _dict["D83DDE37"] = "D83DDE37"; + _dict["D83DDE38"] = "D83DDE38"; + _dict["D83DDE39"] = "D83DDE39"; + _dict["D83DDE3A"] = "D83DDE3A"; + _dict["D83DDE3B"] = "D83DDE3B"; + _dict["D83DDE3C"] = "D83DDE3C"; + _dict["D83DDE3D"] = "D83DDE3D"; + _dict["D83DDE3E"] = "D83DDE3E"; + _dict["D83DDE3F"] = "D83DDE3F"; + _dict["D83DDE40"] = "D83DDE40"; + _dict["D83DDE45"] = "D83DDE45"; + _dict["D83DDE46"] = "D83DDE46"; + _dict["D83DDE47"] = "D83DDE47"; + _dict["D83DDE48"] = "D83DDE48"; + _dict["D83DDE49"] = "D83DDE49"; + _dict["D83DDE4A"] = "D83DDE4A"; + _dict["D83DDE4B"] = "D83DDE4B"; + _dict["D83DDE4C"] = "D83DDE4C"; + _dict["D83DDE4D"] = "D83DDE4D"; + _dict["D83DDE4E"] = "D83DDE4E"; + _dict["D83DDE4F"] = "D83DDE4F"; + _dict["D83DDE80"] = "D83DDE80"; + _dict["D83DDE81"] = "D83DDE81"; + _dict["D83DDE82"] = "D83DDE82"; + _dict["D83DDE83"] = "D83DDE83"; + _dict["D83DDE84"] = "D83DDE84"; + _dict["D83DDE85"] = "D83DDE85"; + _dict["D83DDE86"] = "D83DDE86"; + _dict["D83DDE87"] = "D83DDE87"; + _dict["D83DDE88"] = "D83DDE88"; + _dict["D83DDE89"] = "D83DDE89"; + _dict["D83DDE8A"] = "D83DDE8A"; + _dict["D83DDE8B"] = "D83DDE8B"; + _dict["D83DDE8C"] = "D83DDE8C"; + _dict["D83DDE8D"] = "D83DDE8D"; + _dict["D83DDE8E"] = "D83DDE8E"; + _dict["D83DDE8F"] = "D83DDE8F"; + _dict["D83DDE90"] = "D83DDE90"; + _dict["D83DDE91"] = "D83DDE91"; + _dict["D83DDE92"] = "D83DDE92"; + _dict["D83DDE93"] = "D83DDE93"; + _dict["D83DDE94"] = "D83DDE94"; + _dict["D83DDE95"] = "D83DDE95"; + _dict["D83DDE96"] = "D83DDE96"; + _dict["D83DDE97"] = "D83DDE97"; + _dict["D83DDE98"] = "D83DDE98"; + _dict["D83DDE99"] = "D83DDE99"; + _dict["D83DDE9A"] = "D83DDE9A"; + _dict["D83DDE9B"] = "D83DDE9B"; + _dict["D83DDE9C"] = "D83DDE9C"; + _dict["D83DDE9D"] = "D83DDE9D"; + _dict["D83DDE9E"] = "D83DDE9E"; + _dict["D83DDE9F"] = "D83DDE9F"; + _dict["D83DDEA0"] = "D83DDEA0"; + _dict["D83DDEA1"] = "D83DDEA1"; + _dict["D83DDEA2"] = "D83DDEA2"; + _dict["D83DDEA3"] = "D83DDEA3"; + _dict["D83DDEA4"] = "D83DDEA4"; + _dict["D83DDEA5"] = "D83DDEA5"; + _dict["D83DDEA6"] = "D83DDEA6"; + _dict["D83DDEA7"] = "D83DDEA7"; + _dict["D83DDEA8"] = "D83DDEA8"; + _dict["D83DDEA9"] = "D83DDEA9"; + _dict["D83DDEAA"] = "D83DDEAA"; + _dict["D83DDEAB"] = "D83DDEAB"; + _dict["D83DDEAC"] = "D83DDEAC"; + _dict["D83DDEAD"] = "D83DDEAD"; + _dict["D83DDEAE"] = "D83DDEAE"; + _dict["D83DDEAF"] = "D83DDEAF"; + _dict["D83DDEB0"] = "D83DDEB0"; + _dict["D83DDEB1"] = "D83DDEB1"; + _dict["D83DDEB2"] = "D83DDEB2"; + _dict["D83DDEB3"] = "D83DDEB3"; + _dict["D83DDEB4"] = "D83DDEB4"; + _dict["D83DDEB5"] = "D83DDEB5"; + _dict["D83DDEB6"] = "D83DDEB6"; + _dict["D83DDEB7"] = "D83DDEB7"; + _dict["D83DDEB8"] = "D83DDEB8"; + _dict["D83DDEB9"] = "D83DDEB9"; + _dict["D83DDEBA"] = "D83DDEBA"; + _dict["D83DDEBB"] = "D83DDEBB"; + _dict["D83DDEBC"] = "D83DDEBC"; + _dict["D83DDEBD"] = "D83DDEBD"; + _dict["D83DDEBE"] = "D83DDEBE"; + _dict["D83DDEBF"] = "D83DDEBF"; + _dict["D83DDEC0"] = "D83DDEC0"; + _dict["D83DDEC1"] = "D83DDEC1"; + _dict["D83DDEC2"] = "D83DDEC2"; + _dict["D83DDEC3"] = "D83DDEC3"; + _dict["D83DDEC4"] = "D83DDEC4"; + _dict["D83DDEC5"] = "D83DDEC5"; + } + } + + public static class BrowserNavigationService + { + private static double _fontScaleFactor = 1.0; + + public static double FontScaleFactor + { + get { return _fontScaleFactor; } + set { _fontScaleFactor = value; } + } + + // http://daringfireball.net/2010/07/improved_regex_for_matching_urls + private static readonly Regex RE_URL = new Regex(@"(?i)\b(((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'"".,<>?«»“”‘’]))|([a-z0-9.\-]+(\.ru|\.com|\.net|\.org|\.us|\.it|\.co\.uk)(?![a-z0-9]))|([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]*[a-zA-Z0-9-]+))"); + + public static readonly Regex UserMentionRegex = new Regex(@"\[id\d+.*?\|.*?\]"); + public static readonly Regex GroupMentionRegex = new Regex(@"\[club\d+.*?\|.*?\]"); + + + public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached( + "Text", + typeof(string), + typeof(BrowserNavigationService), + new PropertyMetadata(null, OnTextChanged) + ); + + public static string GetText(DependencyObject d) + { return d.GetValue(TextProperty) as string; } + + public static void SetText(DependencyObject d, string value) + { d.SetValue(TextProperty, value); } + + // Fetch run with PhoneTextNormalStyle + public static Run GetRunWithStyle(string text, RichTextBox richTextBox) + { + var run = new Run(); + + run.FontFamily = richTextBox.FontFamily; + //run.FontSize = richTextBox.FontSize * TextScaleFactor; + run.Foreground = richTextBox.Foreground;// (Brush)Application.Current.Resources["PhoneForegroundBrush"]; + run.Text = text; + + return run; + } + + public static event EventHandler ResolveUsername; + + private static void RaiseTelegramNavigated(TelegramEventArgs e) + { + var handler = ResolveUsername; + if (handler != null) handler(null, e); + } + + public static event EventHandler SearchHashtag; + + private static void RaiseSearchHashtag(TelegramHashtagEventArgs e) + { + var handler = SearchHashtag; + if (handler != null) handler(null, e); + } + + public static event EventHandler MentionNavigated; + + private static void RaiseMentionNavigated(TelegramMentionEventArgs e) + { + var handler = MentionNavigated; + if (handler != null) handler(null, e); + } + + public static Hyperlink GetHyperlink(string text, string link, Action action, Brush foreground) + { + var hyperlink = new Hyperlink(); + hyperlink.Inlines.Add(new Run { Text = text, Foreground = foreground }); + hyperlink.NavigateUri = new Uri(link, UriKind.RelativeOrAbsolute); + hyperlink.Click += (sender, args) => action(hyperlink, link); + return hyperlink; + } + + private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var text_block = d as RichTextBox; + if (text_block == null) + return; + + text_block.Blocks.Clear(); + Paragraph par = new Paragraph(); + + + var new_text = (string)e.NewValue; + + + if (string.IsNullOrEmpty(new_text)) + return; + + //new_text = PreprocessTextForGroupBoardMentions(new_text); + + var splitData = ParseText(new_text); + + foreach (var splStr in splitData) + { + var innerSplit = splStr.Split('\b'); + + if (innerSplit.Length == 1) + { + AddRawText(text_block, par, innerSplit[0]); + } + else if (innerSplit.Length > 1) + { + var hyp = GetHyperlink( + innerSplit[1], + innerSplit[0], + (h, navstr) => + { + NavigateOnHyperlink(navstr); + }, + text_block.Foreground); + + par.Inlines.Add(hyp); + } + } + //var dateRun = new Run {Text = "1:23 1.07.2014"}; + //dateRun. + //par.Inlines.Add(dateRun); + + text_block.Blocks.Add(par); + } + + private static void AddRawText(RichTextBox text_block, Paragraph par, string raw_text) + { + + var textEnumerator = StringInfo.GetTextElementEnumerator(raw_text); + bool cont = false; + + + // DebugWriteUnicode(raw_text); + + StringBuilder sb = new StringBuilder(); + + // Note: Begins at element -1 (none). + cont = textEnumerator.MoveNext(); + while (cont) + { + var text = textEnumerator.GetTextElement(); + + var bytes = Encoding.BigEndianUnicode.GetBytes(text); + + var bytesStr = ConvertToHexString(bytes); + + if (_flagsPrefixes.Contains(bytesStr) && textEnumerator.MoveNext()) + { + var text2 = textEnumerator.GetTextElement(); + + var bytes2 = Encoding.BigEndianUnicode.GetBytes(text2); + + var bytesStr2 = ConvertToHexString(bytes2); + + bytesStr += bytesStr2; + + text += text2; + } + + if (Emoji.Dict.ContainsKey(bytesStr)) + { + var sbStr = sb.ToString(); + sb = sb.Clear(); + if (sbStr != string.Empty) + { + par.Inlines.Add(GetRunWithStyle(sbStr, text_block)); + } + + par.Inlines.Add(GetImage(bytesStr)); + } + + else + { + sb = sb.Append(text); + } + + cont = textEnumerator.MoveNext(); + + } + + var sbStrLast = sb.ToString(); + + if (sbStrLast != string.Empty) + { + par.Inlines.Add(GetRunWithStyle(sbStrLast, text_block)); + } + } + + private static List _flagsPrefixes = + new List{"D83CDDE8", + "D83CDDE9", + "D83CDDEA", + "D83CDDEB", + "D83CDDEC", + "D83CDDEE", + "D83CDDEF", + "D83CDDF0", + "D83CDDF7", + "D83CDDFA"}; + + + + + + + + + + + + + + + + + //public static void DebugWriteUnicode(string input) + //{ + // var res = ""; + // for (var i = 0; i < input.Length; i += char.IsSurrogatePair(input, i) ? 2 : 1) + // { + // var codepoint = char.ConvertToUtf32(input, i); + + // res += string.Format("U+{0:X4}", codepoint); + // } + + // Debug.WriteLine(res); + //} + private static string ConvertToHexString(byte[] bytes) + { + var sb = new StringBuilder(); + for (int i = 0; i < bytes.Length; i++) + { + sb = sb.Append(Convert.ToString(bytes[i], 16).PadLeft(2, '0')); + } + + return sb.ToString().ToUpperInvariant(); + } + + private static InlineUIContainer GetImage(string name) + { + var image = new Image(); + image.Source = new BitmapImage(new Uri(string.Format("/Assets/Emoji/Separated/{0}.png", name), UriKind.RelativeOrAbsolute)); + image.Height = 27 * FontScaleFactor; + image.Width = 27 * FontScaleFactor; + image.Margin = new Thickness(0, 5, 0, -5); + var container = new InlineUIContainer(); + + container.Child = image; + + return container; + } + + private static void NavigateOnHyperlink(string navstr) + { + if (string.IsNullOrEmpty(navstr)) return; + + if (navstr.StartsWith("tlg://?action=mention")) + { + var mentionIndex = navstr.IndexOf('@'); + + if (mentionIndex != -1) + { + var mention = navstr.Substring(mentionIndex); + + RaiseMentionNavigated(new TelegramMentionEventArgs { Mention = mention }); + } + } + else if (navstr.StartsWith("tlg://?action=search")) + { + var hashtagIndex = navstr.IndexOf('#'); + + if (hashtagIndex != -1) + { + var hashtag = navstr.Substring(hashtagIndex); + + RaiseSearchHashtag(new TelegramHashtagEventArgs{ Hashtag = hashtag }); + } + } + else if (!navstr.Contains("@")) + { + if (navstr.ToLowerInvariant().Contains("telegram.me")) + { + RaiseTelegramNavigated(new TelegramEventArgs{Uri = navstr}); + } + else + { + var task = new WebBrowserTask(); + task.URL = navstr; + task.Show(); + } + } + else + { + EmailComposeTask emailComposeTask = new EmailComposeTask(); + + if (navstr.StartsWith("http://")) + { + navstr = navstr.Remove(0, 7); + } + + emailComposeTask.To = navstr; + + emailComposeTask.Show(); + } + } + + + public static string PreprocessTextForGroupBoardMentions(string s) + { + s = Regex.Replace(s, @"\[(id|club)(\d+):bp\-(\d+)_(\d+)\|([^\]]+)\]", "[$1$2|$5]"); + return s; + } + + private static bool IsValidUsernameSymbol(char symbol) + { + if ((symbol >= 'a' && symbol <= 'z') + || (symbol >= 'A' && symbol <= 'Z') + || (symbol >= '0' && symbol <= '9') + || symbol == '_') + { + return true; + } + + return false; + } + + private static bool IsValidUsername(string username) + { + if (username.Length <= 5) + { + return false; + } + + if (username.Length > 32) + { + return false; + } + + if (username[0] != '@') + { + return false; + } + + for (var i = 1; i < username.Length; i++) + { + if (!IsValidUsernameSymbol(username[i])) + { + return false; + } + } + + return true; + } + + public static List ParseText(string html) + { + html = html.Replace("\n", " \n "); + var rx = new Regex("(https?:\\/\\/)?(([A-Za-zА-Яа-яЁё0-9@][A-Za-zА-Яа-яЁё0-9@\\-_\\.]*[A-Za-zА-Яа-яЁё0-9@])(\\/([A-Za-zА-Яа-я0-9@\\-_#%&?+\\/\\.=;:~]*[^\\.\\,;\\(\\)\\?<\\&\\s:])?)?)", RegexOptions.IgnoreCase); + html = rx.Replace(html, delegate(Match m) + { + var full = m.Value; + + if (full.IndexOf('@') == 0 && IsValidUsername(full)) + return string.Format("\atlg://?action=mention&q={0}\b{1}\a", full, full); + + var protocol = (m.Groups.Count > 1) ? m.Groups[1].Value : "http://"; + if (protocol == string.Empty) protocol = "http://"; + var url = (m.Groups.Count > 2) ? m.Groups[2].Value : string.Empty; + var domain = (m.Groups.Count > 3) ? m.Groups[3].Value : string.Empty; + if (domain.IndexOf(".") == -1 || domain.IndexOf("..") != -1) return full; + var topDomain = domain.Split('.').LastOrDefault(); + if (topDomain.Length > 5 || + !("guru,info,name,aero,arpa,coop,museum,mobi,travel,xxx,asia,biz,com,net,org,gov,mil,edu,int,tel,ac,ad,ae,af,ag,ai,al,am,an,ao,aq,ar,as,at,au,aw,az,ba,bb,bd,be,bf,bg,bh,bi,bj,bm,bn,bo,br,bs,bt,bv,bw,by,bz,ca,cc,cd,cf,cg,ch,ci,ck,cl,cm,cn,co,cr,cu,cv,cx,cy,cz,de,dj,dk,dm,do,dz,ec,ee,eg,eh,er,es,et,eu,fi,fj,fk,fm,fo,fr,ga,gd,ge,gf,gg,gh,gi,gl,gm,gn,gp,gq,gr,gs,gt,gu,gw,gy,hk,hm,hn,hr,ht,hu,id,ie,il,im,in,io,iq,ir,is,it,je,jm,jo,jp,ke,kg,kh,ki,km,kn,kp,kr,kw,ky,kz,la,lb,lc,li,lk,lr,ls,lt,lu,lv,ly,ma,mc,md,me,mg,mh,mk,ml,mm,mn,mo,mp,mq,mr,ms,mt,mu,mv,mw,mx,my,mz,na,nc,ne,nf,ng,ni,nl,no,np,nr,nu,nz,om,pa,pe,pf,pg,ph,pk,pl,pm,pn,pr,ps,pt,pw,py,qa,re,ro,ru,rw,sa,sb,sc,sd,se,sg,sh,si,sj,sk,sl,sm,sn,so,sr,st,su,sv,sy,sz,tc,td,tf,tg,th,tj,tk,tl,tm,tn,to,tp,tr,tt,tv,tw,tz,ua,ug,uk,um,us,uy,uz,va,vc,ve,vg,vi,vn,vu,wf,ws,ye,yt,yu,za,zm,zw,рф,cat,pro" + .Split(',').Contains(topDomain))) return full; + if (full.IndexOf('@') != -1) return "\amailto:" + full + "\b" + full + "\a"; + + + full = HttpUtility.UrlDecode(full); + if (full.Length > 55) full = full.Substring(0, 53) + ".."; + + return string.Format("\a{0}\b{1}\a", (protocol + url), full); + }).ReplaceByRegex("(^|\\s)#[\\w@\\.]+", " \atlg://?action=search&q=$0\b$0\a"); ; + html = html.Replace("\n ", "\n").Replace(" \n", "\n"); + + if (html.StartsWith(" ")) html = html.Remove(0, 1); + var blocks = html.Split('\a'); + return blocks.ToList(); + } + + } + + public static class StringExtensions + { + public static string ReplaceByRegex(this string str, string regexStr, string replace) + { + var regex = new Regex(regexStr); + + var result = regex.Replace(str, replace); + + return result; + } + } + + public class TelegramEventArgs : EventArgs + { + public string Uri { get; set; } + } + + public class TelegramHashtagEventArgs : EventArgs + { + public string Hashtag { get; set; } + } + + public class TelegramMentionEventArgs : EventArgs + { + public string Mention { get; set; } + } +} diff --git a/Telegram.EmojiPanel/Controls/Emoji/EmojiControl.xaml b/Telegram.EmojiPanel/Controls/Emoji/EmojiControl.xaml new file mode 100755 index 0000000..9c9eede --- /dev/null +++ b/Telegram.EmojiPanel/Controls/Emoji/EmojiControl.xaml @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Telegram.EmojiPanel/Controls/Emoji/EmojiControl.xaml.cs b/Telegram.EmojiPanel/Controls/Emoji/EmojiControl.xaml.cs new file mode 100755 index 0000000..62a5aa9 --- /dev/null +++ b/Telegram.EmojiPanel/Controls/Emoji/EmojiControl.xaml.cs @@ -0,0 +1,840 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Net; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Info; +using Microsoft.Phone.Shell; +using Telegram.Controls.VirtualizedView; +using Telegram.EmojiPanel.Controls.Utilites; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace Telegram.EmojiPanel.Controls.Emoji +{ + public class IsOpenedEventArgs : EventArgs + { + public bool IsOpened { get; set; } + } + + public partial class EmojiControl + { + + private List _category1Sprites; + private List _category2Sprites; + private List _category3Sprites; + private List _category4Sprites; + private List _category5Sprites; + + public event EventHandler IsOpenedChanged; + + private void RaiseIsOpenedChanged(bool isOpened) + { + var eventHandler = IsOpenedChanged; + + if (eventHandler != null) + { + eventHandler(this, new IsOpenedEventArgs { IsOpened = isOpened }); + } + } + + public TextBox TextBoxTarget { get; set; } + + private const int AlbumOrientationHeight = 328; + + public const int PortraitOrientationHeight100 = 408; + + public const int PortraitOrientationHeight112 = 408; + + public const int PortraitOrientationHeight112Software = 400; + + public const int PortraitOrientationHeight150 = 408; + + public const int PortraitOrientationHeight150Software = 400; + + public const int PortraitOrientationHeight160 = 408; + + public const int PortraitOrientationHeight225 = 332; + + public static int PortraitOrientationHeight + { + get + { +#if WP8 + var appBar = new ApplicationBar(); + switch (Application.Current.Host.Content.ScaleFactor) + { + case 100: //Lumia 820 WVGA 480x800 + return PortraitOrientationHeight100; + break; + case 112: //Lumia 535 qHD 540x960 + // Software buttons //Lumia 535 + if (appBar.DefaultSize == 67.0) + { + return PortraitOrientationHeight112Software; + } + + return PortraitOrientationHeight112; + break; + case 150: //HTC 8X, 730, 830 720p 720x1280 + //Software buttons //Lumia 730 + if (appBar.DefaultSize == 67.0) + { + return PortraitOrientationHeight150Software; + } + + return PortraitOrientationHeight150; + break; + case 160: //Lumia 925, 1020 WXGA 768x1280 + return PortraitOrientationHeight160; + break; + case 225: // Lumia 1520, 930 1020p 1080x1920 + + var deviceName = DeviceStatus.DeviceName; + if (!string.IsNullOrEmpty(deviceName)) + { + deviceName = deviceName.Replace("-", string.Empty).ToLowerInvariant(); + + //Lumia 1520 6 inch 1020p + if (deviceName.StartsWith("rm937") + || deviceName.StartsWith("rm938") + || deviceName.StartsWith("rm939") + || deviceName.StartsWith("rm940")) + { + return PortraitOrientationHeight225; + } + } + + //Lumia 930 other 1020p + return PortraitOrientationHeight100; + break; + } +#endif + + return PortraitOrientationHeight100; + } + } + + private bool _isOpen; + private bool _isPortrait = true; + private bool _isTextBoxTargetFocused; + private bool _isBlocked; // Block IsOpen during animation + private int _currentCategory; + private bool _wasRendered; + private readonly TranslateTransform _frameTransform; + private static EmojiControl _instance; + + public static EmojiControl GetInstance() + { + return _instance ?? (_instance = new EmojiControl()); + } + + public static readonly DependencyProperty RootFrameTransformProperty = DependencyProperty.Register( + "RootFrameTransform", + typeof(double), + typeof(EmojiControl), + new PropertyMetadata(OnRootFrameTransformChanged)); + + public EmojiControl() + { + InitializeComponent(); + + //var frame = (Frame)Application.Current.RootVisual; + //_frameTransform = ((TranslateTransform)((TransformGroup)frame.RenderTransform).Children[0]); + //var binding = new Binding("Y") + //{ + // Source = _frameTransform + //}; + //SetBinding(RootFrameTransformProperty, binding); + + VirtPanel.InitializeWithScrollViewer(CSV); + VirtPanel.ScrollPositionChanged += VirtPanelOnScrollPositionChanged; + //SizeChanged += OnSizeChanged; + OnSizeChanged(null, null); + + LoadButtons(); + CurrentCategory = 0; + } + + public void BindTextBox(TextBox textBox) + { + TextBoxTarget = textBox; + textBox.GotFocus += TextBoxOnGotFocus; + textBox.LostFocus += TextBoxOnLostFocus; + } + + public void UnbindTextBox() + { + TextBoxTarget.GotFocus -= TextBoxOnGotFocus; + TextBoxTarget.LostFocus -= TextBoxOnLostFocus; + TextBoxTarget = null; + } + + public bool IsOpen + { + get + { + return !_isTextBoxTargetFocused && _isOpen; + } + set + { + // Dont hide EmojiControl when keyboard is shown (or to be shown) + if (!_isTextBoxTargetFocused && _isOpen == value || _isBlocked) return; + + if (value) + { + Open(); + } + else + { + Hide(); + } + + + RaiseIsOpenedChanged(value); + } + } + + private void Open() + { + _isOpen = true; + + TextBoxTarget.Dispatcher.BeginInvoke(() => VisualStateManager.GoToState(TextBoxTarget, "Focused", false)); + + + + //var frame = (PhoneApplicationFrame)Application.Current.RootVisual; + EmojiContainer.Visibility = Visibility.Visible; + Deployment.Current.Dispatcher.BeginInvoke(() => LoadCategory(0)); + + //frame.BackKeyPress += OnBackKeyPress; + + //if (!(EmojiContainer.RenderTransform is TranslateTransform)) + // EmojiContainer.RenderTransform = new TranslateTransform(); + //var transform = (TranslateTransform)EmojiContainer.RenderTransform; + + var offset = _isPortrait ? PortraitOrientationHeight : AlbumOrientationHeight; + EmojiContainer.Height = offset; + + //var from = 0; + + //if (_frameTransform.Y < 0) // Keyboard is in view + //{ + // from = (int)_frameTransform.Y; + // //_frameTransform.Y = -offset; + // //transform.Y = offset;// -72; + //} + //transform.Y = offset;// -72 + + //if (from == offset) return; + + //frame.IsHitTestVisible = false; + //_isBlocked = true; + + //var storyboard = new Storyboard(); + //var doubleTransformFrame = new DoubleAnimation + //{ + // From = from, + // To = -offset, + // Duration = TimeSpan.FromMilliseconds(440), + // EasingFunction = new ExponentialEase + // { + // EasingMode = EasingMode.EaseOut, + // Exponent = 6 + // } + //}; + //storyboard.Children.Add(doubleTransformFrame); + //Storyboard.SetTarget(doubleTransformFrame, _frameTransform); + //Storyboard.SetTargetProperty(doubleTransformFrame, new PropertyPath("Y")); + + //EmojiContainer.Dispatcher.BeginInvoke(async () => + //{ + // storyboard.Begin(); + + // if (_frameTransform.Y < 0) // Keyboard is in view + // { + // Focus(); + // TextBoxTarget.Dispatcher.BeginInvoke(() // no effect without dispatcher + // => VisualStateManager.GoToState(TextBoxTarget, "Focused", false)); + // } + + // if (_wasRendered) return; + // await Task.Delay(50); + // LoadCategory(0); + //}); + + //storyboard.Completed += (sender, args) => + //{ + // frame.IsHitTestVisible = true; + // _isBlocked = false; + //}; + } + + private void Hide() + { + _isOpen = false; + + VisualStateManager.GoToState(TextBoxTarget, "Unfocused", false); + EmojiContainer.Visibility = Visibility.Collapsed; + + + //var frame = (PhoneApplicationFrame)Application.Current.RootVisual; + //frame.BackKeyPress -= OnBackKeyPress; + + //if (_isTextBoxTargetFocused) + //{ + // _frameTransform.Y = 0; + + // EmojiContainer.Visibility = Visibility.Collapsed; + + // return; + //} + + //VisualStateManager.GoToState(TextBoxTarget, "Unfocused", false); + + //frame.IsHitTestVisible = false; + //_isBlocked = true; + + //var transform = (TranslateTransform)EmojiContainer.RenderTransform; + + //var storyboard = new Storyboard(); + //var doubleTransformFrame = new DoubleAnimation + //{ + // From = -transform.Y, + // To = 0, + // Duration = TimeSpan.FromMilliseconds(440), + // EasingFunction = new ExponentialEase + // { + // EasingMode = EasingMode.EaseOut, + // Exponent = 6 + // } + //}; + //storyboard.Children.Add(doubleTransformFrame); + //Storyboard.SetTarget(doubleTransformFrame, _frameTransform); + //Storyboard.SetTargetProperty(doubleTransformFrame, new PropertyPath("Y")); + //storyboard.Begin(); + + //storyboard.Completed += (sender, args) => + //{ + // EmojiContainer.Visibility = Visibility.Collapsed; + + // frame.IsHitTestVisible = true; + // _isBlocked = false; + // transform.Y = 0; + //}; + + } + + #region _isTextBoxTargetFocused listeners + private void TextBoxOnGotFocus(object sender, RoutedEventArgs routedEventArgs) + { + _isTextBoxTargetFocused = true; + } + private void TextBoxOnLostFocus(object sender, RoutedEventArgs routedEventArgs) + { + _isTextBoxTargetFocused = false; + } + #endregion + + /// + /// Hide instance on pressing hardware Back button. Fires only when instance is opened. + /// + private void OnBackKeyPress(object sender, CancelEventArgs cancelEventArgs) + { + IsOpen = false; + cancelEventArgs.Cancel = true; + } + + /// + /// Clear current highlight on scroll + /// + private static void VirtPanelOnScrollPositionChanged(object sender, MyVirtualizingPanel.ScrollPositionChangedEventAgrs scrollPositionChangedEventAgrs) + { + EmojiSpriteItem.ClearCurrentHighlight(); + } + + /// + /// Changes tabs in UI and _currentCategory property + /// + public int CurrentCategory + { + get { return _currentCategory; } + set + { + var previousCategory = GetCategoryButtonByIndex(_currentCategory); + var nextCategory = GetCategoryButtonByIndex(value); + + if (previousCategory != null) + previousCategory.Background = ButtonBackground; + + nextCategory.Background = (Brush)Application.Current.Resources["PhoneAccentBrush"]; + _currentCategory = value; + } + } + + public void LoadCategory(int index) + { + VirtPanel.ClearItems(); + + if (_currentCategory == RecentsCategoryIndex) + UnloadRecents(); + + if (index == RecentsCategoryIndex) + { + LoadRecents(); + return; + } + + List sprites = null; + + switch (index) + { + case 0: + sprites = _category1Sprites; + break; + case 1: + sprites = _category2Sprites; + break; + case 2: + sprites = _category3Sprites; + break; + case 3: + sprites = _category4Sprites; + break; + case 4: + sprites = _category5Sprites; + break; + } + + if (sprites == null) + { + sprites = new List(); + + for (var i = 0; i < EmojiData.SpritesByCategory[index].Length; i++) + { + //var item = new EmojiSpriteItem(index, i); + var item = new EmojiSpriteItem(EmojiData.SpritesByCategory[index][i], index, i); + item.EmojiSelected += OnEmojiSelected; + sprites.Add(item); + } + + switch (index) + { + case 0: + _category1Sprites = sprites; + break; + case 1: + _category2Sprites = sprites; + break; + case 2: + _category3Sprites = sprites; + break; + case 3: + _category4Sprites = sprites; + break; + case 4: + _category5Sprites = sprites; + break; + } + } + + CurrentCategory = index; + + VirtPanel.AddItems(new List { sprites[0] }); + CreateButtonsBackgrounds(index); + + if (!_wasRendered) + { + // Display LoadingProgressBar only once + LoadingProgressBar.Visibility = Visibility.Collapsed; + _wasRendered = true; + } + + // Delayed rendering of the rest parts - speeds up initial load + ThreadPool.QueueUserWorkItem(state => + { + Thread.Sleep(100); + Deployment.Current.Dispatcher.BeginInvoke(() => + { + if (_currentCategory != index) + return; + + var listList = sprites.ToList(); + listList.RemoveAt(0); + VirtPanel.AddItems(listList); + }); + }); + } + + public static void OnRootFrameTransformChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) + { + ((EmojiControl)source).OnRootFrameTransformChanged(); + } + + public void OnRootFrameTransformChanged() + { + if (!_isOpen) return; + + var offset = _isPortrait ? -PortraitOrientationHeight : -AlbumOrientationHeight; + _frameTransform.Y = offset; + } + + #region Recents + + public static readonly DependencyProperty RecentItemsProperty = DependencyProperty.Register( + "RecentItems", typeof (IList), typeof (EmojiControl), new PropertyMetadata(default(IList))); + + public IList RecentItems + { + get { return (IList) GetValue(RecentItemsProperty); } + set { SetValue(RecentItemsProperty, value); } + } + + public void LoadRecents() + { + CurrentCategory = RecentsCategoryIndex; + + if (EmojiData.Recents == null) + { + EmojiData.LoadRecents(); + } + + RecentItems = new ObservableCollection(EmojiData.Recents ?? new List()); + + CSV.IsHitTestVisible = false; + Recents.Visibility = Visibility.Visible; + } + + public void UnloadRecents() + { + CSV.IsHitTestVisible = true; + Recents.Visibility = Visibility.Collapsed; + } + + #endregion Recents + + private void OnEmojiSelected(object sender, EmojiSelectedEventArgs args) + { + TextBoxTarget.Dispatcher.BeginInvoke(() => + { + var selectionStart = TextBoxTarget.SelectionStart; + TextBoxTarget.Text = TextBoxTarget.Text.Insert(selectionStart, args.DataItem.String); + TextBoxTarget.Select(selectionStart + args.DataItem.String.Length, 0); + }); + + if (_currentCategory == RecentsCategoryIndex) return; + + var that = args.DataItem; + ThreadPool.QueueUserWorkItem(state => EmojiData.AddToRecents(that)); + } + + + /// + /// Emoji control backspace button logic + /// + private void BackspaceButtonOnClick(object sender, RoutedEventArgs routedEventArgs) + { + var text = TextBoxTarget.Text; + var selectionStart = TextBoxTarget.SelectionStart; + + if (text.Length <= 0) return; + if (selectionStart == 0) return; + + int toSubstring; + + if (text.Length > 1) + { + var prevSymbol = text[selectionStart - 2]; + var prevBytes = BitConverter.GetBytes(prevSymbol); + + var curSymbol = text[selectionStart - 1]; + var curBytes = BitConverter.GetBytes(curSymbol); + + if (prevBytes[1] == 0xD8 && (prevBytes[0] == 0x3D || prevBytes[0] == 0x3C)) + toSubstring = 2; + else if (curBytes[1] == 0x20 && curBytes[0] == 0xE3) + toSubstring = 2; + else + toSubstring = 1; + } + else + { + toSubstring = 1; + } + + TextBoxTarget.Text = text.Remove(selectionStart - toSubstring, toSubstring); + TextBoxTarget.SelectionStart = selectionStart - toSubstring; + } + + #region User Interface + + private readonly Button _abcButton = new Button { ClickMode = ClickMode.Release }; + private readonly Button _recentsButton = new Button { ClickMode = ClickMode.Press }; + private readonly Button _cat0Button = new Button { ClickMode = ClickMode.Press }; + private readonly Button _cat1Button = new Button { ClickMode = ClickMode.Press }; + private readonly Button _cat2Button = new Button { ClickMode = ClickMode.Press }; + private readonly Button _cat3Button = new Button { ClickMode = ClickMode.Press }; + private readonly Button _cat4Button = new Button { ClickMode = ClickMode.Press }; + private readonly RepeatButton _backspaceButton = new RepeatButton { ClickMode = ClickMode.Release, Interval = 100 }; + public const int RecentsCategoryIndex = 5; + + private Button GetCategoryButtonByIndex(int index) + { + switch (index) + { + case 0: + return _cat0Button; + case 1: + return _cat1Button; + case 2: + return _cat2Button; + case 3: + return _cat3Button; + case 4: + return _cat4Button; + case RecentsCategoryIndex: + return _recentsButton; + default: + return null; + } + } + + public Brush ButtonBackground + { + get + { + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + + return isLightTheme + ? new SolidColorBrush(Colors.White) + : new SolidColorBrush(Color.FromArgb(255, 71, 71, 71)); + } + } + + public void LoadButtons() + { + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + + var buttonStyleResourceKey = isLightTheme ? "CategoryButtonLightThemeStyle" : "CategoryButtonDarkThemeStyle"; + var buttonStyle = (Style)Resources[buttonStyleResourceKey]; + _abcButton.Style = buttonStyle; + _recentsButton.Style = buttonStyle; + _cat0Button.Style = buttonStyle; + _cat1Button.Style = buttonStyle; + _cat2Button.Style = buttonStyle; + _cat3Button.Style = buttonStyle; + _cat4Button.Style = buttonStyle; + + var repeatButtonStyleResourceKey = isLightTheme ? "RepeatButtonLightThemeStyle" : "RepeatButtonDarkThemeStyle"; + _backspaceButton.Style = (Style)Resources[repeatButtonStyleResourceKey]; + + var prefix = isLightTheme ? "light." : string.Empty; + _abcButton.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri(prefix + "emoji.abc")), + Width = 34, + Height = 32 + }; + _recentsButton.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri(prefix + "emoji.recent")), + Width = 34, + Height = 32 + }; + _cat0Button.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri(prefix + "emoji.category.1")), + Width = 34, + Height = 32 + }; + _cat1Button.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri(prefix + "emoji.category.2")), + Width = 34, + Height = 32 + }; + _cat2Button.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri(prefix + "emoji.category.3")), + Width = 34, + Height = 32 + }; + _cat3Button.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri(prefix + "emoji.category.4")), + Width = 34, + Height = 32 + }; + _cat4Button.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri(prefix + "emoji.category.5")), + Width = 34, + Height = 32 + }; + _backspaceButton.Content = new Image + { + Source = new BitmapImage(Helpers.GetAssetUri(prefix + "emoji.backspace")), + Width = 34, + Height = 32 + }; + + Grid.SetColumn(_abcButton, 0); + Grid.SetColumn(_recentsButton, 1); + Grid.SetColumn(_cat0Button, 2); + Grid.SetColumn(_cat1Button, 3); + Grid.SetColumn(_cat2Button, 4); + Grid.SetColumn(_cat3Button, 5); + Grid.SetColumn(_cat4Button, 6); + Grid.SetColumn(_backspaceButton, 7); + + ButtonsGrid.Children.Add(_abcButton); + ButtonsGrid.Children.Add(_recentsButton); + ButtonsGrid.Children.Add(_cat0Button); + ButtonsGrid.Children.Add(_cat1Button); + ButtonsGrid.Children.Add(_cat2Button); + ButtonsGrid.Children.Add(_cat3Button); + ButtonsGrid.Children.Add(_cat4Button); + ButtonsGrid.Children.Add(_backspaceButton); + + _abcButton.Click += AbcButtonOnClick; + _cat0Button.Click += CategoryButtonClick; + _cat1Button.Click += CategoryButtonClick; + _cat2Button.Click += CategoryButtonClick; + _cat3Button.Click += CategoryButtonClick; + _cat4Button.Click += CategoryButtonClick; + _recentsButton.Click += CategoryButtonClick; + _backspaceButton.Click += BackspaceButtonOnClick; + } + + private void AbcButtonOnClick(object sender, RoutedEventArgs routedEventArgs) + { + TextBoxTarget.Focus(); + } + + private void CategoryButtonClick(object sender, RoutedEventArgs routedEventArgs) + { + if (sender == _cat0Button) + LoadCategory(0); + else if (sender == _cat1Button) + LoadCategory(1); + else if (sender == _cat2Button) + LoadCategory(2); + else if (sender == _cat3Button) + LoadCategory(3); + else if (sender == _cat4Button) + LoadCategory(4); + else if (sender == _recentsButton) + LoadCategory(RecentsCategoryIndex); + } + + private void CreateButtonsBackgrounds(int categoryIndex) + { + var sprites = EmojiData.SpriteRowsCountByCategory[categoryIndex]; + var buttonBackgroundColor = ButtonBackground; + for (var i = 0; i < sprites.Length; i++) + { + var rowsCount = sprites[i]; + + var block = new Rectangle + { + Width = EmojiSpriteItem.SpriteWidth, + Height = EmojiSpriteItem.RowHeight * rowsCount, + Fill = buttonBackgroundColor, + Margin = new Thickness(4, 0, 4, 0) + }; + Canvas.SetTop(block, (EmojiSpriteItem.SpriteHeight) * i); + VirtPanel.Children.Insert(0, block); + } + } + + private void InitializeOrientation(Orientation orientation) + { + switch (orientation) + { + case Orientation.Vertical: + ButtonsGrid.Height = 78; + ButtonsGrid.Margin = new Thickness(0, 6, 0, 0); + EmojiContainer.Height = PortraitOrientationHeight; + //_frameTransform.Y = -PortraitOrientationHeight; + break; + + case Orientation.Horizontal: + ButtonsGrid.Height = 58; + ButtonsGrid.Margin = new Thickness(0, 6, 0, 3); + EmojiContainer.Height = AlbumOrientationHeight; + //_frameTransform.Y = -AlbumOrientationHeight; + break; + } + } + + #endregion User Interface + + + /// + /// Orientation change handler + /// + private void OnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs) + { + var currentOrientation = ((PhoneApplicationFrame)Application.Current.RootVisual).Orientation; + var isPortrait = currentOrientation == PageOrientation.PortraitUp || + currentOrientation == PageOrientation.PortraitDown || + currentOrientation == PageOrientation.Portrait; + + if (_isPortrait == isPortrait && _wasRendered) return; + + _isPortrait = isPortrait; + InitializeOrientation(isPortrait ? Orientation.Vertical : Orientation.Horizontal); + } + + private void UIElement_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + + ((Border)sender).Background = (Brush)Application.Current.Resources["PhoneAccentBrush"]; + } + + private void UIElement_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + ((Border) sender).Background = ButtonBackground; + } + + private void UIElement_OnMouseLeave(object sender, MouseEventArgs e) + { + ((Border) sender).Background = ButtonBackground; + } + + private void EmojiButton_OnTap(object sender, GestureEventArgs e) + { + var button = (FrameworkElement)sender; + var emojiItem = (EmojiDataItem)button.DataContext; + + OnEmojiSelected(sender, new EmojiSelectedEventArgs{DataItem = emojiItem}); + + ////RaiseEmojiAdded(new EmojiAddedEventArgs { Emoji = emojiItem.String }); + + //if (_currentCategory != RecentsCategoryIndex) + //{ + // var prevItem = RecentItems.FirstOrDefault(x => x.Code == emojiItem.Code); + // if (prevItem != null) + // { + // RecentItems.Remove(prevItem); + // RecentItems.Insert(0, prevItem); + // } + // else + // { + // RecentItems.Insert(0, emojiItem); + // RecentItems = RecentItems.Take(30).ToList(); + // } + //} + } + } +} diff --git a/Telegram.EmojiPanel/Controls/Emoji/EmojiData.cs b/Telegram.EmojiPanel/Controls/Emoji/EmojiData.cs new file mode 100755 index 0000000..85389a5 --- /dev/null +++ b/Telegram.EmojiPanel/Controls/Emoji/EmojiData.cs @@ -0,0 +1,408 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.IsolatedStorage; +using System.Linq; + +namespace Telegram.EmojiPanel.Controls.Emoji +{ + public class EmojiDataItem + { + public EmojiDataItem() { } + + public EmojiDataItem(string string2, ulong code) + { + String = string2; + Code = code; + } + + public string String { get; set; } + public ulong Code { get; set; } + public Uri Uri { get; set; } + + public static string BuildString(ulong code) + { + var bytes = BitConverter.GetBytes(code); + + var char1 = BitConverter.ToChar(bytes, 6); + var char2 = BitConverter.ToChar(bytes, 4); + var char3 = BitConverter.ToChar(bytes, 2); + var char4 = BitConverter.ToChar(bytes, 0); + + string text; + + if (char1 != 0) + { + text = new string(new [] { char1, char2, char3, char4 }); + } + else if (char3 != 0) + { + text = new string(new [] { char3, char4 }); + } + else + { + text = char4.ToString(); + } + + return text; + } + + public static Uri BuildUri(string string2) + { + //var string3 = BitConverter.ToString(bytes.Take(4).Reverse().ToArray()) + var string3 = string.Format("{0:X}", (Int16) string2[0]); + + switch (string2.Length) + { + case 2: + { + uint emoji = 0; + emoji |= (uint) string2[0] << 16; + emoji |= (uint) string2[1]; + + return new Uri(string.Format("/Assets/Emoji/Separated/{0:X8}.png", emoji), UriKind.Relative); + } + case 4: + { + uint emoji1 = 0; + emoji1 |= (uint) string2[0] << 16; + emoji1 |= (uint) string2[1]; + + ulong emoji2 = 0; + emoji2 |= (uint) string2[2] << 16; + emoji2 |= (uint) string2[3]; + + return new Uri(string.Format("/Assets/Emoji/Separated/{0:X}{1:X}.png", emoji1, emoji2), UriKind.Relative); + } + default: + return new Uri(string.Format("/Assets/Emoji/Separated/{0:X}.png", (Int16) string2[0]), UriKind.Relative); + } + } + + public static EmojiDataItem GetByIndex(int categoryIndex, int spriteIndex, int itemIndex) + { + + var category = EmojiData.CodesByCategory[categoryIndex]; + var emojiIndex = spriteIndex * EmojiData.ItemsInSprite + itemIndex; + + if (category.Length <= emojiIndex) return null; // out of bounds + + ulong code = category[emojiIndex]; + + var result = new EmojiDataItem + { + Code = code, + String = BuildString(code) + }; + result.Uri = BuildUri(result.String); + + return result; + } + } + + public static class EmojiData + { + public static List Recents; + + public static void AddToRecents(EmojiDataItem emojiDataItem) + { + if (Recents == null) + { + LoadRecents(); + if (Recents == null) + { + Recents = new List(); + } + } + + var prevItem = Recents.FirstOrDefault(x => x.Code == emojiDataItem.Code); + if (prevItem != null) + { + Recents.Remove(prevItem); + Recents.Insert(0, prevItem); + } + else + { + Recents.Insert(0, emojiDataItem); + Recents = Recents.Take(42).ToList(); + } + + SaveRecents(); + } + + public static void LoadRecents() + { + + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (!store.FileExists("EmojiRecents")) return; + using (var stream = new IsolatedStorageFileStream("EmojiRecents", FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite, store)) + { + if (stream.Length <= 0) return; + + using (var br = new BinaryReader(stream)) + { + var count = br.ReadInt32(); + + Recents = new List(); + + for (var i = 0; i < count; i++) + { + var emoji = new EmojiDataItem(br.ReadString(), br.ReadUInt64()); + emoji.Uri = EmojiDataItem.BuildUri(emoji.String); + Recents.Add(emoji); + } + } + } + } + } + + public static IList LoadDefaultRecents() + { + return new List + { + new EmojiDataItem{Code = 1, String = "😂"}, + new EmojiDataItem{Code = 1, String = "😘"}, + new EmojiDataItem{Code = 1, String = "❤"}, + new EmojiDataItem{Code = 1, String = "😍"}, + new EmojiDataItem{Code = 1, String = "😊"}, + new EmojiDataItem{Code = 1, String = "😁"}, + new EmojiDataItem{Code = 1, String = "👍"}, + new EmojiDataItem{Code = 1, String = "☺"}, + new EmojiDataItem{Code = 1, String = "😔"}, + //new EmojiDataItem{Code = 1, String = "😂 😘 ❤ 😍 😊 😁 👍 ☺ 😔 😄 😭 💋 😒 😳 😜 🙈 😉 😃 😢 😝 😱 😡 😏 😞 😅 😚 🙊 😌 😀 😋 😆 👌 😐 😕"}, + }; + } + + public static void SaveRecents() + { + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + using (var stream = new IsolatedStorageFileStream("EmojiRecents", FileMode.Create, FileAccess.Write, FileShare.ReadWrite, store)) + { + using (var bw = new BinaryWriter(stream)) + { + var emojies = Recents.ToList(); + + bw.Write(emojies.Count); + + foreach (var item in emojies) + { + bw.Write(item.String); + bw.Write(item.Code); + } + } + } + } + } + + public const int ItemsInRow = 6; + public const int ItemsInSprite = 36; + + /// + /// Custom spaced sprites by category + /// + public static Uri[][] SpritesByCategory = + { + new[] + { + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat0_part0.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat0_part1.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat0_part2.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat0_part3.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat0_part4.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat0_part5.png", UriKind.Relative), + }, + new[] + { + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat1_part0.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat1_part1.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat1_part2.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat1_part3.png", UriKind.Relative), + }, + new[] + { + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part0.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part1.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part2.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part3.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part4.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part5.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat2_part6.png", UriKind.Relative), + }, + new[] + { + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat3_part0.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat3_part1.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat3_part2.png", UriKind.Relative), + }, + new[] + { + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat4_part0.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat4_part1.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat4_part2.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat4_part3.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat4_part4.png", UriKind.Relative), + new Uri("/Assets/Emoji/SpacedSprites/sprite64_cat4_part5.png", UriKind.Relative), + }, + }; + + /// + /// Config of rows count for sprites in categories + /// + public static int[][] SpriteRowsCountByCategory = + { + new [] { 6, 6, 6, 6, 6, 2 }, + new [] { 6, 6, 6, 2 }, + new [] { 6, 6, 6, 6, 6, 6, 3 }, + new [] { 6, 6, 5 }, + new [] { 6, 6, 6, 6, 6, 5 } + }; + + /// + /// Config of missing cells in last row for each last category's sprite + /// + public static int[] SpriteMissingCellsByCategory = + { + 3, 4, 4, 1, 1 + }; + + /// + /// Emoji codes combined into the groups corresponding to the categories in the interface + /// + public static ulong[][] CodesByCategory = { + new ulong[]{ + 0x00000000D83DDE04L, 0x00000000D83DDE03L, 0x00000000D83DDE00L, 0x00000000D83DDE0AL, 0x000000000000263AL, 0x00000000D83DDE09L, 0x00000000D83DDE0DL, + 0x00000000D83DDE18L, 0x00000000D83DDE1AL, 0x00000000D83DDE17L, 0x00000000D83DDE19L, 0x00000000D83DDE1CL, 0x00000000D83DDE1DL, 0x00000000D83DDE1BL, + 0x00000000D83DDE33L, 0x00000000D83DDE01L, 0x00000000D83DDE14L, 0x00000000D83DDE0CL, 0x00000000D83DDE12L, 0x00000000D83DDE1EL, 0x00000000D83DDE23L, + 0x00000000D83DDE22L, 0x00000000D83DDE02L, 0x00000000D83DDE2DL, 0x00000000D83DDE2AL, 0x00000000D83DDE25L, 0x00000000D83DDE30L, 0x00000000D83DDE05L, + 0x00000000D83DDE13L, 0x00000000D83DDE29L, 0x00000000D83DDE2BL, 0x00000000D83DDE28L, 0x00000000D83DDE31L, 0x00000000D83DDE20L, 0x00000000D83DDE21L, + 0x00000000D83DDE24L, 0x00000000D83DDE16L, 0x00000000D83DDE06L, 0x00000000D83DDE0BL, 0x00000000D83DDE37L, 0x00000000D83DDE0EL, 0x00000000D83DDE34L, + 0x00000000D83DDE35L, 0x00000000D83DDE32L, 0x00000000D83DDE1FL, 0x00000000D83DDE26L, 0x00000000D83DDE27L, 0x00000000D83DDE08L, 0x00000000D83DDC7FL, + 0x00000000D83DDE2EL, 0x00000000D83DDE2CL, 0x00000000D83DDE10L, 0x00000000D83DDE15L, 0x00000000D83DDE2FL, 0x00000000D83DDE36L, 0x00000000D83DDE07L, + 0x00000000D83DDE0FL, 0x00000000D83DDE11L, 0x00000000D83DDC72L, 0x00000000D83DDC73L, 0x00000000D83DDC6EL, 0x00000000D83DDC77L, 0x00000000D83DDC82L, + 0x00000000D83DDC76L, 0x00000000D83DDC66L, 0x00000000D83DDC67L, 0x00000000D83DDC68L, 0x00000000D83DDC69L, 0x00000000D83DDC74L, 0x00000000D83DDC75L, + 0x00000000D83DDC71L, 0x00000000D83DDC7CL, 0x00000000D83DDC78L, 0x00000000D83DDE3AL, 0x00000000D83DDE38L, 0x00000000D83DDE3BL, 0x00000000D83DDE3DL, + 0x00000000D83DDE3CL, 0x00000000D83DDE40L, 0x00000000D83DDE3FL, 0x00000000D83DDE39L, 0x00000000D83DDE3EL, 0x00000000D83DDC79L, 0x00000000D83DDC7AL, + 0x00000000D83DDE48L, 0x00000000D83DDE49L, 0x00000000D83DDE4AL, 0x00000000D83DDC80L, 0x00000000D83DDC7DL, 0x00000000D83DDCA9L, 0x00000000D83DDD25L, + 0x0000000000002728L, 0x00000000D83CDF1FL, 0x00000000D83DDCABL, 0x00000000D83DDCA5L, 0x00000000D83DDCA2L, 0x00000000D83DDCA6L, 0x00000000D83DDCA7L, + 0x00000000D83DDCA4L, 0x00000000D83DDCA8L, 0x00000000D83DDC42L, 0x00000000D83DDC40L, 0x00000000D83DDC43L, 0x00000000D83DDC45L, 0x00000000D83DDC44L, + 0x00000000D83DDC4DL, 0x00000000D83DDC4EL, 0x00000000D83DDC4CL, 0x00000000D83DDC4AL, 0x000000000000270AL, 0x000000000000270CL, 0x00000000D83DDC4BL, + 0x000000000000270BL, 0x00000000D83DDC50L, 0x00000000D83DDC46L, 0x00000000D83DDC47L, 0x00000000D83DDC49L, 0x00000000D83DDC48L, 0x00000000D83DDE4CL, + 0x00000000D83DDE4FL, 0x000000000000261DL, 0x00000000D83DDC4FL, 0x00000000D83DDCAAL, 0x00000000D83DDEB6L, 0x00000000D83CDFC3L, 0x00000000D83DDC83L, + 0x00000000D83DDC6BL, 0x00000000D83DDC6AL, 0x00000000D83DDC6CL, 0x00000000D83DDC6DL, 0x00000000D83DDC8FL, 0x00000000D83DDC91L, 0x00000000D83DDC6FL, + 0x00000000D83DDE46L, 0x00000000D83DDE45L, 0x00000000D83DDC81L, 0x00000000D83DDE4BL, 0x00000000D83DDC86L, 0x00000000D83DDC87L, 0x00000000D83DDC85L, + 0x00000000D83DDC70L, 0x00000000D83DDE4EL, 0x00000000D83DDE4DL, 0x00000000D83DDE47L, 0x00000000D83CDFA9L, 0x00000000D83DDC51L, 0x00000000D83DDC52L, + 0x00000000D83DDC5FL, 0x00000000D83DDC5EL, 0x00000000D83DDC61L, 0x00000000D83DDC60L, 0x00000000D83DDC62L, 0x00000000D83DDC55L, 0x00000000D83DDC54L, + 0x00000000D83DDC5AL, 0x00000000D83DDC57L, 0x00000000D83CDFBDL, 0x00000000D83DDC56L, 0x00000000D83DDC58L, 0x00000000D83DDC59L, 0x00000000D83DDCBCL, + 0x00000000D83DDC5CL, 0x00000000D83DDC5DL, 0x00000000D83DDC5BL, 0x00000000D83DDC53L, 0x00000000D83CDF80L, 0x00000000D83CDF02L, 0x00000000D83DDC84L, + 0x00000000D83DDC9BL, 0x00000000D83DDC99L, 0x00000000D83DDC9CL, 0x00000000D83DDC9AL, 0x0000000000002764L, 0x00000000D83DDC94L, 0x00000000D83DDC97L, + 0x00000000D83DDC93L, 0x00000000D83DDC95L, 0x00000000D83DDC96L, 0x00000000D83DDC9EL, 0x00000000D83DDC98L, 0x00000000D83DDC8CL, 0x00000000D83DDC8BL, + 0x00000000D83DDC8DL, 0x00000000D83DDC8EL, 0x00000000D83DDC64L, 0x00000000D83DDC65L, 0x00000000D83DDCACL, 0x00000000D83DDC63L, 0x00000000D83DDCADL}, + new ulong[]{ + 0x00000000D83DDC36L, 0x00000000D83DDC3AL, 0x00000000D83DDC31L, 0x00000000D83DDC2DL, 0x00000000D83DDC39L, 0x00000000D83DDC30L, 0x00000000D83DDC38L, 0x00000000D83DDC2FL, + 0x00000000D83DDC28L, 0x00000000D83DDC3BL, 0x00000000D83DDC37L, 0x00000000D83DDC3DL, 0x00000000D83DDC2EL, 0x00000000D83DDC17L, 0x00000000D83DDC35L, + 0x00000000D83DDC12L, 0x00000000D83DDC34L, 0x00000000D83DDC11L, 0x00000000D83DDC18L, 0x00000000D83DDC3CL, 0x00000000D83DDC27L, 0x00000000D83DDC26L, + 0x00000000D83DDC24L, 0x00000000D83DDC25L, 0x00000000D83DDC23L, 0x00000000D83DDC14L, 0x00000000D83DDC0DL, 0x00000000D83DDC22L, 0x00000000D83DDC1BL, + 0x00000000D83DDC1DL, 0x00000000D83DDC1CL, 0x00000000D83DDC1EL, 0x00000000D83DDC0CL, 0x00000000D83DDC19L, 0x00000000D83DDC1AL, 0x00000000D83DDC20L, + 0x00000000D83DDC1FL, 0x00000000D83DDC2CL, 0x00000000D83DDC33L, 0x00000000D83DDC0BL, 0x00000000D83DDC04L, 0x00000000D83DDC0FL, 0x00000000D83DDC00L, + 0x00000000D83DDC03L, 0x00000000D83DDC05L, 0x00000000D83DDC07L, 0x00000000D83DDC09L, 0x00000000D83DDC0EL, 0x00000000D83DDC10L, 0x00000000D83DDC13L, + 0x00000000D83DDC15L, 0x00000000D83DDC16L, 0x00000000D83DDC01L, 0x00000000D83DDC02L, 0x00000000D83DDC32L, 0x00000000D83DDC21L, 0x00000000D83DDC0AL, + 0x00000000D83DDC2BL, 0x00000000D83DDC2AL, 0x00000000D83DDC06L, 0x00000000D83DDC08L, 0x00000000D83DDC29L, 0x00000000D83DDC3EL, 0x00000000D83DDC90L, + 0x00000000D83CDF38L, 0x00000000D83CDF37L, 0x00000000D83CDF40L, 0x00000000D83CDF39L, 0x00000000D83CDF3BL, 0x00000000D83CDF3AL, 0x00000000D83CDF41L, + 0x00000000D83CDF43L, 0x00000000D83CDF42L, 0x00000000D83CDF3FL, 0x00000000D83CDF3EL, 0x00000000D83CDF44L, 0x00000000D83CDF35L, 0x00000000D83CDF34L, + 0x00000000D83CDF32L, 0x00000000D83CDF33L, 0x00000000D83CDF30L, 0x00000000D83CDF31L, 0x00000000D83CDF3CL, 0x00000000D83CDF10L, 0x00000000D83CDF1EL, + 0x00000000D83CDF1DL, 0x00000000D83CDF1AL, 0x00000000D83CDF11L, 0x00000000D83CDF12L, 0x00000000D83CDF13L, 0x00000000D83CDF14L, 0x00000000D83CDF15L, + 0x00000000D83CDF16L, 0x00000000D83CDF17L, 0x00000000D83CDF18L, 0x00000000D83CDF1CL, 0x00000000D83CDF1BL, 0x00000000D83CDF19L, 0x00000000D83CDF0DL, + 0x00000000D83CDF0EL, 0x00000000D83CDF0FL, 0x00000000D83CDF0BL, 0x00000000D83CDF0CL, 0x00000000D83CDF20L, 0x0000000000002B50L, 0x0000000000002600L, + 0x00000000000026C5L, 0x0000000000002601L, 0x00000000000026A1L, 0x0000000000002614L, 0x0000000000002744L, 0x00000000000026C4L, 0x00000000D83CDF00L, + 0x00000000D83CDF01L, 0x00000000D83CDF08L, 0x00000000D83CDF0AL}, + new ulong[]{ + 0x00000000D83CDF8DL, 0x00000000D83DDC9DL, 0x00000000D83CDF8EL, 0x00000000D83CDF92L, 0x00000000D83CDF93L, 0x00000000D83CDF8FL, 0x00000000D83CDF86L, 0x00000000D83CDF87L, + 0x00000000D83CDF90L, 0x00000000D83CDF91L, 0x00000000D83CDF83L, 0x00000000D83DDC7BL, 0x00000000D83CDF85L, 0x00000000D83CDF84L, 0x00000000D83CDF81L, + 0x00000000D83CDF8BL, 0x00000000D83CDF89L, 0x00000000D83CDF8AL, 0x00000000D83CDF88L, 0x00000000D83CDF8CL, 0x00000000D83DDD2EL, 0x00000000D83CDFA5L, + 0x00000000D83DDCF7L, 0x00000000D83DDCF9L, 0x00000000D83DDCFCL, 0x00000000D83DDCBFL, 0x00000000D83DDCC0L, 0x00000000D83DDCBDL, 0x00000000D83DDCBEL, + 0x00000000D83DDCBBL, 0x00000000D83DDCF1L, 0x000000000000260EL, 0x00000000D83DDCDEL, 0x00000000D83DDCDFL, 0x00000000D83DDCE0L, 0x00000000D83DDCE1L, + 0x00000000D83DDCFAL, 0x00000000D83DDCFBL, 0x00000000D83DDD0AL, 0x00000000D83DDD09L, 0x00000000D83DDD08L, 0x00000000D83DDD07L, 0x00000000D83DDD14L, + 0x00000000D83DDD14L, 0x00000000D83DDCE2L, 0x00000000D83DDCE3L, 0x00000000000023F3L, 0x000000000000231BL, 0x00000000000023F0L, 0x000000000000231AL, + 0x00000000D83DDD13L, 0x00000000D83DDD12L, 0x00000000D83DDD0FL, 0x00000000D83DDD10L, 0x00000000D83DDD11L, 0x00000000D83DDD0EL, 0x00000000D83DDCA1L, + 0x00000000D83DDD26L, 0x00000000D83DDD06L, 0x00000000D83DDD05L, 0x00000000D83DDD0CL, 0x00000000D83DDD0BL, 0x00000000D83DDD0DL, 0x00000000D83DDEC1L /* was missing */, 0x00000000D83DDEC0L, + 0x00000000D83DDEBFL, 0x00000000D83DDEBDL, 0x00000000D83DDD27L, 0x00000000D83DDD29L, 0x00000000D83DDD28L, 0x00000000D83DDEAAL, 0x00000000D83DDEACL, + 0x00000000D83DDCA3L, 0x00000000D83DDD2BL, 0x00000000D83DDD2AL, 0x00000000D83DDC8AL, 0x00000000D83DDC89L, 0x00000000D83DDCB0L, 0x00000000D83DDCB4L, + 0x00000000D83DDCB5L, 0x00000000D83DDCB7L, 0x00000000D83DDCB6L, 0x00000000D83DDCB3L, 0x00000000D83DDCB8L, 0x00000000D83DDCF2L, 0x00000000D83DDCE7L, + 0x00000000D83DDCE5L, 0x00000000D83DDCE4L, 0x0000000000002709L, 0x00000000D83DDCE9L, 0x00000000D83DDCE8L, 0x00000000D83DDCEFL, 0x00000000D83DDCEBL, + 0x00000000D83DDCEAL, 0x00000000D83DDCECL, 0x00000000D83DDCEDL, 0x00000000D83DDCEEL, 0x00000000D83DDCE6L, 0x00000000D83DDCDDL, 0x00000000D83DDCC4L, + 0x00000000D83DDCC3L, 0x00000000D83DDCD1L, 0x00000000D83DDCCAL, 0x00000000D83DDCC8L, 0x00000000D83DDCC9L, 0x00000000D83DDCDCL, 0x00000000D83DDCCBL, + 0x00000000D83DDCC5L, 0x00000000D83DDCC6L, 0x00000000D83DDCC7L, 0x00000000D83DDCC1L, 0x00000000D83DDCC2L, 0x0000000000002702L, 0x00000000D83DDCCCL, + 0x00000000D83DDCCEL, 0x0000000000002712L, 0x000000000000270FL, 0x00000000D83DDCCFL, 0x00000000D83DDCD0L, 0x00000000D83DDCD5L, 0x00000000D83DDCD7L, + 0x00000000D83DDCD8L, 0x00000000D83DDCD9L, 0x00000000D83DDCD3L, 0x00000000D83DDCD4L, 0x00000000D83DDCD2L, 0x00000000D83DDCDAL, 0x00000000D83DDCD6L, + 0x00000000D83DDD16L, 0x00000000D83DDCDBL, 0x00000000D83DDD2CL, 0x00000000D83DDD2DL, 0x00000000D83DDCF0L, 0x00000000D83CDFA8L, 0x00000000D83CDFACL, + 0x00000000D83CDFA4L, 0x00000000D83CDFA7L, 0x00000000D83CDFBCL, 0x00000000D83CDFB5L, 0x00000000D83CDFB6L, 0x00000000D83CDFB9L, 0x00000000D83CDFBBL, + 0x00000000D83CDFBAL, 0x00000000D83CDFB7L, 0x00000000D83CDFB8L, 0x00000000D83DDC7EL, 0x00000000D83CDFAEL, 0x00000000D83CDCCFL, 0x00000000D83CDFB4L, + 0x00000000D83CDC04L, 0x00000000D83CDFB2L, 0x00000000D83CDFAFL, 0x00000000D83CDFC8L, 0x00000000D83CDFC0L, 0x00000000000026BDL, 0x00000000000026BEL, + 0x00000000D83CDFBEL, 0x00000000D83CDFB1L, 0x00000000D83CDFC9L, 0x00000000D83CDFB3L, 0x00000000000026F3L, 0x00000000D83DDEB5L, 0x00000000D83DDEB4L, + 0x00000000D83CDFC1L, 0x00000000D83CDFC7L, 0x00000000D83CDFC6L, 0x00000000D83CDFBFL, 0x00000000D83CDFC2L, 0x00000000D83CDFCAL, 0x00000000D83CDFC4L, + 0x00000000D83CDFA3L, 0x0000000000002615L, 0x00000000D83CDF75L, 0x00000000D83CDF76L, 0x00000000D83CDF7CL, 0x00000000D83CDF7AL, 0x00000000D83CDF7BL, + 0x00000000D83CDF78L, 0x00000000D83CDF79L, 0x00000000D83CDF77L, 0x00000000D83CDF74L, 0x00000000D83CDF55L, 0x00000000D83CDF54L, 0x00000000D83CDF5FL, + 0x00000000D83CDF57L, 0x00000000D83CDF56L, 0x00000000D83CDF5DL, 0x00000000D83CDF5BL, 0x00000000D83CDF64L, 0x00000000D83CDF71L, 0x00000000D83CDF63L, + 0x00000000D83CDF65L, 0x00000000D83CDF59L, 0x00000000D83CDF58L, 0x00000000D83CDF5AL, 0x00000000D83CDF5CL, 0x00000000D83CDF72L, 0x00000000D83CDF62L, + 0x00000000D83CDF61L, 0x00000000D83CDF73L, 0x00000000D83CDF5EL, 0x00000000D83CDF69L, 0x00000000D83CDF6EL, 0x00000000D83CDF66L, 0x00000000D83CDF68L, + 0x00000000D83CDF67L, 0x00000000D83CDF82L, 0x00000000D83CDF70L, 0x00000000D83CDF6AL, 0x00000000D83CDF6BL, 0x00000000D83CDF6CL, 0x00000000D83CDF6DL, + 0x00000000D83CDF6FL, 0x00000000D83CDF4EL, 0x00000000D83CDF4FL, 0x00000000D83CDF4AL, 0x00000000D83CDF4BL, 0x00000000D83CDF52L, 0x00000000D83CDF47L, + 0x00000000D83CDF49L, 0x00000000D83CDF53L, 0x00000000D83CDF51L, 0x00000000D83CDF48L, 0x00000000D83CDF4CL, 0x00000000D83CDF50L, 0x00000000D83CDF4DL, + 0x00000000D83CDF60L, 0x00000000D83CDF46L, 0x00000000D83CDF45L, 0x00000000D83CDF3DL}, + new ulong[]{ + 0x00000000D83CDFE0L, 0x00000000D83CDFE1L, 0x00000000D83CDFEBL, 0x00000000D83CDFE2L, 0x00000000D83CDFE3L, 0x00000000D83CDFE5L, 0x00000000D83CDFE6L, 0x00000000D83CDFEAL, + 0x00000000D83CDFE9L, 0x00000000D83CDFE8L, 0x00000000D83DDC92L, 0x00000000000026EAL, 0x00000000D83CDFECL, 0x00000000D83CDFE4L, 0x00000000D83CDF07L, + 0x00000000D83CDF06L, 0x00000000D83CDFEFL, 0x00000000D83CDFF0L, 0x00000000000026FAL, 0x00000000D83CDFEDL, 0x00000000D83DDDFCL, 0x00000000D83DDDFEL, + 0x00000000D83DDDFBL, 0x00000000D83CDF04L, 0x00000000D83CDF05L, 0x00000000D83CDF03L, 0x00000000D83DDDFDL, 0x00000000D83CDF09L, 0x00000000D83CDFA0L, + 0x00000000D83CDFA1L, 0x00000000000026F2L, 0x00000000D83CDFA2L, 0x00000000D83DDEA2L, 0x00000000000026F5L, 0x00000000D83DDEA4L, 0x00000000D83DDEA3L, + 0x0000000000002693L, 0x00000000D83DDE80L, 0x0000000000002708L, 0x00000000D83DDCBAL, 0x00000000D83DDE81L, 0x00000000D83DDE82L, 0x00000000D83DDE8AL, + 0x00000000D83DDE89L, 0x00000000D83DDE9EL, 0x00000000D83DDE86L, 0x00000000D83DDE84L, 0x00000000D83DDE85L, 0x00000000D83DDE88L, 0x00000000D83DDE87L, + 0x00000000D83DDE9DL, 0x00000000D83DDE8BL, 0x00000000D83DDE83L, 0x00000000D83DDE8EL, 0x00000000D83DDE8CL, 0x00000000D83DDE8DL, 0x00000000D83DDE99L, + 0x00000000D83DDE98L, 0x00000000D83DDE97L, 0x00000000D83DDE95L, 0x00000000D83DDE96L, 0x00000000D83DDE9BL, 0x00000000D83DDE9AL, 0x00000000D83DDEA8L, + 0x00000000D83DDE93L, 0x00000000D83DDE94L, 0x00000000D83DDE92L, 0x00000000D83DDE91L, 0x00000000D83DDE90L, 0x00000000D83DDEB2L, 0x00000000D83DDEA1L, + 0x00000000D83DDE9FL, 0x00000000D83DDEA0L, 0x00000000D83DDE9CL, 0x00000000D83DDC88L, 0x00000000D83DDE8FL, 0x00000000D83CDFABL, 0x00000000D83DDEA6L, + 0x00000000D83DDEA5L, 0x00000000000026A0L, 0x00000000D83DDEA7L, 0x00000000D83DDD30L, 0x00000000000026FDL, 0x00000000D83CDFEEL, 0x00000000D83CDFB0L, + 0x0000000000002668L, 0x00000000D83DDDFFL, 0x00000000D83CDFAAL, 0x00000000D83CDFADL, 0x00000000D83DDCCDL, 0x00000000D83DDEA9L, 0xD83CDDEFD83CDDF5L, + 0xD83CDDF0D83CDDF7L, 0xD83CDDE9D83CDDEAL, 0xD83CDDE8D83CDDF3L, 0xD83CDDFAD83CDDF8L, 0xD83CDDEBD83CDDF7L, 0xD83CDDEAD83CDDF8L, 0xD83CDDEED83CDDF9L, + 0xD83CDDF7D83CDDFAL, 0xD83CDDECD83CDDE7L}, + new ulong[]{ + 0x00000000003120E3L, 0x00000000003220E3L, 0x00000000003320E3L, 0x00000000003420E3L, 0x00000000003520E3L, 0x00000000003620E3L, 0x00000000003720E3L, 0x00000000003820E3L, + 0x00000000003920E3L, 0x00000000003020E3L, 0x00000000D83DDD1FL, 0x00000000D83DDD22L, 0x00000000002320E3L, 0x00000000D83DDD23L, 0x0000000000002B06L, + 0x0000000000002B07L, 0x0000000000002B05L, 0x00000000000027A1L, 0x00000000D83DDD20L, 0x00000000D83DDD21L, 0x00000000D83DDD24L, 0x0000000000002197L, + 0x0000000000002196L, 0x0000000000002198L, 0x0000000000002199L, 0x0000000000002194L, 0x0000000000002195L, 0x00000000D83DDD04L, 0x00000000000025C0L, + 0x00000000000025B6L, 0x00000000D83DDD3CL, 0x00000000D83DDD3DL, 0x00000000000021A9L, 0x00000000000021AAL, 0x0000000000002139L, 0x00000000000023EAL, + 0x00000000000023E9L, 0x00000000000023EBL, 0x00000000000023ECL, 0x0000000000002935L, 0x0000000000002934L, 0x00000000D83CDD97L, 0x00000000D83DDD00L, + 0x00000000D83DDD01L, 0x00000000D83DDD02L, 0x00000000D83CDD95L, 0x00000000D83CDD99L, 0x00000000D83CDD92L, 0x00000000D83CDD93L, 0x00000000D83CDD96L, + 0x00000000D83DDCF6L, 0x00000000D83CDFA6L, 0x00000000D83CDE01L, 0x00000000D83CDE2FL, 0x00000000D83CDE33L, 0x00000000D83CDE35L, 0x00000000D83CDE34L /* was missing */, 0x00000000D83CDE32L, + 0x00000000D83CDE50L /* //34 was wrong */, 0x00000000D83CDE39L /* //32 was duplicate */, /* removed 3 */ 0x00000000D83CDE3AL, 0x00000000D83CDE36L, 0x00000000D83CDE1AL, + 0x00000000D83DDEBBL, 0x00000000D83DDEB9L, 0x00000000D83DDEBAL, 0x00000000D83DDEBCL, 0x00000000D83DDEBEL, 0x00000000D83DDEB0L, 0x00000000D83DDEAEL, + 0x00000000D83CDD7FL, 0x000000000000267FL, 0x00000000D83DDEADL, 0x00000000D83CDE37L, 0x00000000D83CDE38L, 0x00000000D83CDE02L, 0x00000000000024C2L, + /* missing 4 unicodes */ + 0x00000000D83DDEC2L, 0x00000000D83DDEC4L, 0x00000000D83DDEC5L, 0x00000000D83DDEC3L, + 0x00000000D83CDE51L, 0x0000000000003299L, 0x0000000000003297L, 0x00000000D83CDD91L, 0x00000000D83CDD98L, 0x00000000D83CDD94L, 0x00000000D83DDEABL, + 0x00000000D83DDD1EL, 0x00000000D83DDCF5L, 0x00000000D83DDEAFL, 0x00000000D83DDEB1L, 0x00000000D83DDEB3L, 0x00000000D83DDEB7L, 0x00000000D83DDEB8L, + 0x00000000000026D4L, 0x0000000000002733L, 0x0000000000002747L, 0x000000000000274EL, 0x0000000000002705L, 0x0000000000002734L, 0x00000000D83DDC9FL, + 0x00000000D83CDD9AL, 0x00000000D83DDCF3L, 0x00000000D83DDCF4L, 0x00000000D83CDD70L, 0x00000000D83CDD71L, 0x00000000D83CDD8EL, 0x00000000D83CDD7EL, + 0x00000000D83DDCA0L, 0x00000000000027BFL, 0x000000000000267BL, 0x0000000000002648L, 0x0000000000002649L, 0x000000000000264AL, 0x000000000000264BL, + 0x000000000000264CL, 0x000000000000264DL, 0x000000000000264EL, 0x000000000000264FL, 0x0000000000002650L, 0x0000000000002651L, 0x0000000000002652L, + 0x0000000000002653L, 0x00000000000026CEL, 0x00000000D83DDD2FL, 0x00000000D83CDFE7L, 0x00000000D83DDCB9L, 0x00000000D83DDCB2L, 0x00000000D83DDCB1L, + 0x00000000000000A9L, 0x00000000000000AEL, 0x0000000000002122L /* TM */, + /* was mixed, missing 2-3 */ + 0x000000000000274CL, 0x000000000000203CL, 0x0000000000002049L, 0x0000000000002757L, 0x0000000000002753L, 0x0000000000002755L, 0x0000000000002754L, 0x0000000000002B55L, + 0x00000000D83DDD1DL, 0x00000000D83DDD1AL, + 0x00000000D83DDD19L, 0x00000000D83DDD1BL, 0x00000000D83DDD1CL, + 0x00000000D83DDD03L, 0x00000000D83DDD5BL, 0x00000000D83DDD67L, 0x00000000D83DDD50L, 0x00000000D83DDD5CL, + 0x00000000D83DDD51L, 0x00000000D83DDD5DL, 0x00000000D83DDD52L, 0x00000000D83DDD5EL, 0x00000000D83DDD53L, 0x00000000D83DDD5FL, 0x00000000D83DDD54L, + 0x00000000D83DDD60L, 0x00000000D83DDD55L, 0x00000000D83DDD56L, 0x00000000D83DDD57L, 0x00000000D83DDD58L, 0x00000000D83DDD59L, 0x00000000D83DDD5AL, + 0x00000000D83DDD61L, 0x00000000D83DDD62L, 0x00000000D83DDD63L, 0x00000000D83DDD64L, 0x00000000D83DDD65L, 0x00000000D83DDD66L, 0x0000000000002716L, + 0x0000000000002795L, 0x0000000000002796L, 0x0000000000002797L, 0x0000000000002660L, 0x0000000000002665L, 0x0000000000002663L, 0x0000000000002666L, + 0x00000000D83DDCAEL, 0x00000000D83DDCAFL, 0x0000000000002714L, 0x0000000000002611L, 0x00000000D83DDD18L, 0x00000000D83DDD17L, 0x00000000000027B0L, + 0x0000000000003030L, 0x000000000000303DL, 0x00000000D83DDD31L, + 0x00000000000025FCL, 0x00000000000025FBL, 0x00000000000025FEL, 0x00000000000025FDL, + 0x00000000000025AAL, 0x00000000000025ABL, + 0x00000000D83DDD3AL, 0x00000000D83DDD32L, 0x00000000D83DDD33L, 0x00000000000026ABL, 0x00000000000026AAL, + 0x00000000D83DDD34L, 0x00000000D83DDD35L, 0x00000000D83DDD3BL, 0x0000000000002B1CL, 0x0000000000002B1BL, 0x00000000D83DDD36L, 0x00000000D83DDD37L, 0x00000000D83DDD38L, 0x00000000D83DDD39L}}; + } +} diff --git a/Telegram.EmojiPanel/Controls/Emoji/EmojiSpriteItem.cs b/Telegram.EmojiPanel/Controls/Emoji/EmojiSpriteItem.cs new file mode 100755 index 0000000..20355d8 --- /dev/null +++ b/Telegram.EmojiPanel/Controls/Emoji/EmojiSpriteItem.cs @@ -0,0 +1,245 @@ +using System; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using Telegram.Controls.VirtualizedView; + +namespace Telegram.EmojiPanel.Controls.Emoji +{ + public class EmojiSelectedEventArgs : EventArgs + { + public EmojiDataItem DataItem { get; set; } + } + + public class EmojiSpriteItem : VListItemBase + { + public int CategoryIndex; + public int SpriteOffset; + public int Rows; + + public EventHandler EmojiSelected = delegate { }; + + public EmojiSpriteItem(int categoryIndex, int spriteOffset) + { + CategoryIndex = categoryIndex; + SpriteOffset = spriteOffset; + Rows = EmojiData.SpriteRowsCountByCategory[categoryIndex][spriteOffset]; + + var emojiInCategory = EmojiData.CodesByCategory[categoryIndex]; + ulong[] emojis = null; + emojis = spriteOffset != 0 ? + emojiInCategory.Skip(spriteOffset*EmojiData.ItemsInSprite).Take(EmojiData.ItemsInSprite).ToArray() : + emojiInCategory.Take(EmojiData.ItemsInSprite).ToArray(); + + View.Width = SpriteWidth + 8; + var decodePixelWidth = SpriteWidth; + //switch (Application.Current.Host.Content.ScaleFactor) + //{ + // case 100: + // break; + // case 150: + // decodePixelWidth = 711; + // break; + // case 160: + // decodePixelWidth = 758; + // break; + //} + + var image = new Image + { + Width = SpriteWidth, + Source = new BitmapImage + { + //DecodePixelWidth = decodePixelWidth, + //DecodePixelType = DecodePixelType.Physical + //UriSource = spriteUri + }, + Margin = new Thickness(4, 1, 4, 1), + VerticalAlignment = VerticalAlignment.Top + }; + Children.Add(image); + + View.MouseLeftButtonDown += ViewOnMouseLeftButtonDown; + View.LostMouseCapture += ViewOnLostMouseCapture; + View.MouseLeftButtonUp += ViewOnLostMouseCapture; + View.MouseLeave += ViewOnLostMouseCapture; + View.Tap += ViewOnTap; + + CreateBorders(); + } + + public EmojiSpriteItem(Uri spriteUri, int categoryIndex, int spriteOffset) + { + CategoryIndex = categoryIndex; + SpriteOffset = spriteOffset; + Rows = EmojiData.SpriteRowsCountByCategory[categoryIndex][spriteOffset]; + + View.Width = SpriteWidth + 8; + var decodePixelWidth = SpriteWidth; + //switch (Application.Current.Host.Content.ScaleFactor) + //{ + // case 100: + // break; + // case 150: + // decodePixelWidth = 711; + // break; + // case 160: + // decodePixelWidth = 758; + // break; + //} + + var image = new Image + { + Width = SpriteWidth, + Source = new BitmapImage + { + //DecodePixelWidth = decodePixelWidth, + //DecodePixelType = DecodePixelType.Physical, + UriSource = spriteUri + }, + Margin = new Thickness(4, 1, 4, 1), + VerticalAlignment = VerticalAlignment.Top + }; + Children.Add(image); + + View.MouseLeftButtonDown += ViewOnMouseLeftButtonDown; + View.LostMouseCapture += ViewOnLostMouseCapture; + View.MouseLeftButtonUp += ViewOnLostMouseCapture; + View.MouseLeave += ViewOnLostMouseCapture; + View.Tap += ViewOnTap; + + CreateBorders(); + } + + private static void ViewOnLostMouseCapture(object sender, MouseEventArgs mouseEventArgs) + { + ClearCurrentHighlight(); + } + + public static void ClearCurrentHighlight() + { + if (_currentHighlight == null) return; + + var parent = _currentHighlight.Parent as Grid; + if (parent != null) + parent.Children.Remove(_currentHighlight); + + _currentHighlight = null; + } + + private void ViewOnMouseLeftButtonDown(object sender, MouseButtonEventArgs args) + { + var point = args.GetPosition(View); + var column = (int) Math.Ceiling(point.X / ColumnWidth); + var row = (int) Math.Ceiling(point.Y / RowHeight); + + if (column <= 0 || row <= 0) return; + if (Rows < MaxRowsInSprite && row == Rows) + { + if (EmojiData.ItemsInRow - EmojiData.SpriteMissingCellsByCategory[CategoryIndex] < column) + return; + } + + var emojiHoverBackground = new Rectangle + { + Width = ColumnWidth - 2, //width without 2px border + Height = RowHeight, + Fill = (Brush) Application.Current.Resources["PhoneAccentBrush"], + Margin = new Thickness((column - 1) * 79 + 4, (row - 1) * 70 + 2, 0, 0), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top + }; + View.Children.Insert(0, emojiHoverBackground); + + ClearCurrentHighlight(); + _currentHighlight = emojiHoverBackground; + } + + private void ViewOnTap(object sender, GestureEventArgs args) + { + var point = args.GetPosition(View); + var column = (int) Math.Ceiling(point.X / 79); + var row = (int) Math.Ceiling(point.Y / 70); + + if (column <= 0 || row <= 0) return; + + //Debug.WriteLine("{0}-{1}", column, row); + + var itemIndex = (row - 1) * EmojiData.ItemsInRow + (column - 1); + + var emoji = EmojiDataItem.GetByIndex(CategoryIndex, SpriteOffset, itemIndex); + if (emoji != null) + EmojiSelected(this, new EmojiSelectedEventArgs{DataItem = emoji}); + } + + private static Rectangle _currentHighlight; + + private void CreateBorders() + { + for (int i = 0; i < Rows + 1; i++) + { + var line = new Rectangle + { + Width = SpriteWidth + 4, + Height = 2, + Fill = (Brush) Application.Current.Resources["PhoneChromeBrush"], + Margin = new Thickness(0, i * RowHeight, 0, 0), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top + }; + Children.Add(line); + } + + for (int i = 0; i < 5; i++) + { + var line = new Rectangle + { + Width = 2, + Height = RowHeight * Rows, + Fill = (Brush) Application.Current.Resources["PhoneChromeBrush"], + Margin = new Thickness((i + 1) * ColumnWidth + 2, 0, 0, 0), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top + }; + Children.Add(line); + } + + if (Rows < MaxRowsInSprite) + { + var missingRows = EmojiData.SpriteMissingCellsByCategory[CategoryIndex]; + var startIndex = EmojiData.ItemsInRow - missingRows; + + var width = missingRows * ColumnWidth; + var horizontalOffset = startIndex * ColumnWidth + 4; + + var rect = new Rectangle + { + Fill = (Brush) Application.Current.Resources["PhoneChromeBrush"], + Width = width, + Height = RowHeight, + Margin = new Thickness(horizontalOffset, (Rows - 1) * RowHeight, 0, 0), + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top + }; + Children.Add(rect); + } + } + + public const int SpriteWidth = 472; + public const int SpriteHeight = 420; + public const int ColumnWidth = 79; + public const int RowHeight = 70; // 105 in pixel logic + + public const int MaxRowsInSprite = 6; + + public override double FixedHeight + { + get { return RowHeight * Rows; } + set { } + } + } +} diff --git a/Telegram.EmojiPanel/Controls/Emoji/StickerSpriteItem.cs b/Telegram.EmojiPanel/Controls/Emoji/StickerSpriteItem.cs new file mode 100755 index 0000000..d05f25c --- /dev/null +++ b/Telegram.EmojiPanel/Controls/Emoji/StickerSpriteItem.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.IO.IsolatedStorage; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Input; +using System.Windows.Media; +using Telegram.Api.Services.FileManager; +using Telegram.Api.TL; +using Telegram.Controls.VirtualizedView; + +namespace Telegram.EmojiPanel.Controls.Emoji +{ + //class StickerToImageSourceConverter : IValueConverter + //{ + + // private static ImageSource ReturnOrEnqueueSticker(TLDocument22 document, TLStickerItem sticker) + // { + // if (document == null) return null; + + // var documentLocalFileName = document.GetFileName(); + + // using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + // { + // if (!store.FileExists(documentLocalFileName)) + // { + // TLObject owner = document; + // if (sticker != null) + // { + // owner = sticker; + // } + + // // 1. download full size + // IoC.Get().DownloadFileAsync(document.FileName, document.DCId, document.ToInputFileLocation(), owner, document.Size, progress => { }); + + // // 2. download preview + // var thumbCachedSize = document.Thumb as TLPhotoCachedSize; + // if (thumbCachedSize != null) + // { + // var fileName = "cached" + document.GetFileName(); + // var buffer = thumbCachedSize.Bytes.Data; + // if (buffer == null) return null; + + // return DecodeWebPImage(fileName, buffer, () => { }); + // } + + // var thumbPhotoSize = document.Thumb as TLPhotoSize; + // if (thumbPhotoSize != null) + // { + // var location = thumbPhotoSize.Location as TLFileLocation; + // if (location != null) + // { + // return ReturnOrEnqueueStickerPreview(location, sticker, thumbPhotoSize.Size); + // } + // } + // } + // else + // { + // if (document.DocumentSize > 0 + // && document.DocumentSize < Telegram.Api.Constants.StickerMaxSize) + // { + // byte[] buffer; + // using (var file = store.OpenFile(documentLocalFileName, FileMode.Open)) + // { + // buffer = new byte[file.Length]; + // file.Read(buffer, 0, buffer.Length); + // } + + // return DecodeWebPImage(documentLocalFileName, buffer, + // () => + // { + // using (var localStore = IsolatedStorageFile.GetUserStoreForApplication()) + // { + // localStore.DeleteFile(documentLocalFileName); + // } + // }); + // } + // } + // } + + // return null; + // } + + // public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + // { + // var document = value as TLDocument22; + // if (document == null) return null; + + // document. + // } + + // public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + // { + // throw new NotImplementedException(); + // } + //} + + //class StickerSpriteItem : VListItemBase + //{ + // public override double FixedHeight + // { + // get { return 180.0; } + // set { } + // } + + // public double StickerWidth + // { + // get { return 120.0; } + // } + + // public double StickerHeight + // { + // get { return 180.0; } + // } + + // public StickerSpriteItem(IList stickers) + // { + // var stackPanel = new StackPanel(); + + // for (var i = 0; i < stickers.Count; i++) + // { + // var binding = new Binding(); + // binding.Source = stickers[i]; + // //binding.Path = new PropertyPath(""); + // binding.Mode = BindingMode.OneWay; + // binding.Converter = new StickerToImageSourceConverter(); + + // var image = new Image + // { + // Width = StickerWidth, + // Height = StickerHeight, + // //Source = new BitmapImage + // //{ + // // //DecodePixelWidth = decodePixelWidth, + // // //DecodePixelType = DecodePixelType.Physical + // // //UriSource = spriteUri + // //}, + // Margin = new Thickness(0, 0, 0, 0), + // VerticalAlignment = VerticalAlignment.Top + // }; + // image.SetBinding(Image.SourceProperty, binding); + // image.Tap += Sticker_OnTap; + + // stackPanel.Children.Add(image); + // } + + // Children.Add(stackPanel); + // } + + // private void Sticker_OnTap(object sender, GestureEventArgs e) + // { + + // } + //} +} diff --git a/Telegram.EmojiPanel/Controls/Utilites/DelayedExecutor.cs b/Telegram.EmojiPanel/Controls/Utilites/DelayedExecutor.cs new file mode 100755 index 0000000..9a3a54f --- /dev/null +++ b/Telegram.EmojiPanel/Controls/Utilites/DelayedExecutor.cs @@ -0,0 +1,87 @@ +using System; +using System.Diagnostics; +using System.Threading; + +namespace Telegram.EmojiPanel.Controls.Utilites +{ + public class DelayedExecutor + { + class ExecutionInfo + { + public Action Action { get; set; } + public DateTime Timestamp { get; set; } + } + + ExecutionInfo m_executionInfo; + Timer m_timer; + int m_delay; + bool m_timerIsActive; + object m_lockObj = new object(); + + public DelayedExecutor(int delay) // TO DO : add IDateTimeProvider dependency to remove dependency on DateTime + { + m_delay = delay; + m_timer = new Timer(TimerCallback); + } + + public void AddToDelayedExecution(Action action) + { + lock (m_lockObj) + { + m_executionInfo = new ExecutionInfo() { Action = action, Timestamp = DateTime.Now }; + } + + ChangeTimer(true); + } + + private void TimerCallback(object state) + { + Action executeAction = null; + + lock (m_lockObj) + { + if (m_executionInfo != null) + { + if (DateTime.Now - m_executionInfo.Timestamp >= TimeSpan.FromMilliseconds(m_delay)) + { + Debug.WriteLine("Action is set to be executed."); + executeAction = m_executionInfo.Action; + m_executionInfo = null; + ChangeTimer(false); + } + } + } + if (executeAction != null) + { + try + { + executeAction(); + } + catch (Exception exc) + { + //Logger.Instance.Error("Exeption during delayed execution", exc); + } + } + } + + private void ChangeTimer(bool activate) + { + if (activate && !m_timerIsActive) + { + lock (m_timer) + { + m_timerIsActive = true; + m_timer.Change(m_delay, m_delay); + } + } + else if (!activate && m_timerIsActive) + { + lock (m_timer) + { + m_timerIsActive = false; + m_timer.Change(Timeout.Infinite, 0); + } + } + } + } +} diff --git a/Telegram.EmojiPanel/Controls/Utilites/Helpers.cs b/Telegram.EmojiPanel/Controls/Utilites/Helpers.cs new file mode 100755 index 0000000..dbb3d8b --- /dev/null +++ b/Telegram.EmojiPanel/Controls/Utilites/Helpers.cs @@ -0,0 +1,24 @@ +using System; + +namespace Telegram.EmojiPanel.Controls.Utilites +{ + public static class Helpers + { + public static Uri GetAssetUri(string assetName) + { + return new Uri(String.Format("/Assets/{0}-WXGA.png", assetName), UriKind.Relative); + + //switch (Application.Current.Host.Content.ScaleFactor) + //{ + // case 100: + // return new Uri(String.Format("/Assets/{0}-WVGA.png", assetName), UriKind.Relative); + // case 160: + // return new Uri(String.Format("/Assets/{0}-WXGA.png", assetName), UriKind.Relative); + // case 150: + // return new Uri(String.Format("/Assets/{0}-720p.png", assetName), UriKind.Relative); + // default: + // return new Uri(String.Format("/Assets/{0}-WVGA.png", assetName), UriKind.Relative); + //} + } + } +} diff --git a/Telegram.EmojiPanel/Controls/Utilites/MyListItemBase.cs b/Telegram.EmojiPanel/Controls/Utilites/MyListItemBase.cs new file mode 100755 index 0000000..9837035 --- /dev/null +++ b/Telegram.EmojiPanel/Controls/Utilites/MyListItemBase.cs @@ -0,0 +1,24 @@ +using System.Windows.Controls; +using Telegram.Controls.VirtualizedView; + +namespace Telegram.EmojiPanel.Controls.Utilites +{ + public class MyListItemBase : Grid + { + //private Panel _contentPanel; + //public Panel ContentPanel + //{ + // get + // { + // return _contentPanel; + // } + // set + // { + // _contentPanel = value; + // Content = _contentPanel; + // } + //} + + public VListItemBase VirtSource { get; set; } + } +} diff --git a/Telegram.EmojiPanel/Controls/Utilites/MyVirtualizingPanel.cs b/Telegram.EmojiPanel/Controls/Utilites/MyVirtualizingPanel.cs new file mode 100755 index 0000000..91f2d3f --- /dev/null +++ b/Telegram.EmojiPanel/Controls/Utilites/MyVirtualizingPanel.cs @@ -0,0 +1,586 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Media; +using Telegram.Controls.VirtualizedView; + +namespace Telegram.EmojiPanel.Controls.Utilites +{ + public class MyVirtualizingPanel : Canvas + { + private const bool IsLogEnabled = false; + + private static void Log(string str) + { + if (IsLogEnabled) + { + Debug.WriteLine(str); + } + } + + + private const double LoadUnloadThreshold = 500; + private const double LoadedHeightUpwards = 300; + private const double LoadedHeightDownwards = 900; + private const double LoadedHeightDownwardsNotScrolling = 800; + + private bool _changingVerticalOffset = false; + + readonly DependencyProperty _listVerticalOffsetProperty = DependencyProperty.Register( + "ListVerticalOffset", + typeof(double), + typeof(MyVirtualizingPanel), + new PropertyMetadata(new PropertyChangedCallback(OnListVerticalOffsetChanged))); + + public double ListVerticalOffset + { + get { return (double) this.GetValue(_listVerticalOffsetProperty); } + set { this.SetValue(_listVerticalOffsetProperty, value); } + } + + private static void OnListVerticalOffsetChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) + { + var control = (MyVirtualizingPanel) obj; + control.OnListVerticalOffsetChanged(); + } + + private ScrollViewer _scrollViewer; + bool _isScrolling = false; + + public ScrollViewer ScrollViewer + { + get { return _scrollViewer; } + } + + public void InitializeWithScrollViewer(ScrollViewer scrollViewer) + { + _scrollViewer = scrollViewer; + EnsureBoundToScrollViewer(); + } + + protected void EnsureBoundToScrollViewer() + { + Binding binding = new Binding + { + Source = _scrollViewer, + Path = new PropertyPath("VerticalOffset"), + Mode = BindingMode.OneWay + }; + this.SetBinding(_listVerticalOffsetProperty, binding); + + + } + + bool _notReactToScroll = false; + private double _savedDelta; + //private DelayedExecutor _de = new DelayedExecutor(300); + //internal void PrepareForScrollToBottom() + //{ + // _notReactToScroll = true; + // _savedDelta = DeltaOffset; + // // load in the end + // DeltaOffset = _scrollViewer.ExtentHeight - _scrollViewer.ViewportHeight - _scrollViewer.VerticalOffset; + // Debug.WriteLine("PrepareForScrollToBottom"); + // PerformLoadUnload2(VirtualizableState.LoadedPartially, false); + // _de.AddToDelayedExecution(() => + // { + // Execute.ExecuteOnUIThread(() => ScrollToBottomCompleted()); + // }); + //} + + //internal void ScrollToBottomCompleted() + //{ + // _notReactToScroll = false; + // DeltaOffset = _savedDelta; + // PerformLoadUnload(VirtualizableState.LoadedFully); + // Debug.WriteLine("ScrolltoBottomCompleted"); + //} + + private void group_CurrentStateChanging(object sender, VisualStateChangedEventArgs e) + { + if (e.NewState.Name == "Scrolling") + { + _isScrolling = true; + } + else + { + _isScrolling = false; + PerformLoadUnload(true); + } + } + + private static VisualStateGroup FindVisualState(FrameworkElement element, string name) + { + if (element == null) + return null; + + IList groups = VisualStateManager.GetVisualStateGroups(element); + foreach (VisualStateGroup group in groups) + if (group.Name == name) + return group; + + return null; + } + + public class ScrollPositionChangedEventAgrs : EventArgs + { + public double CurrentPosition { get; private set; } + public double ScrollHeight { get; private set; } + + public ScrollPositionChangedEventAgrs(double currentPosition, + double scrollHeight) + { + CurrentPosition = currentPosition; + ScrollHeight = scrollHeight; + } + } + + public event EventHandler ScrollPositionChanged; + + private double _previousScrollOffset = 0; + private DateTime _previousScrollOffsetChangedTime = DateTime.MinValue; + private const double PixelsPerSecondThreshold = 200; + + private void OnListVerticalOffsetChanged() + { + if (_notReactToScroll) return; + + if (!_changingVerticalOffset) + { + + var w = new Stopwatch(); + w.Start(); + PerformLoadUnload(true); + w.Stop(); + + Log("LOADUNLOAD performed in " + w.ElapsedMilliseconds); + + if (ScrollPositionChanged != null) + { + ScrollPositionChanged(this, new ScrollPositionChangedEventAgrs( + _scrollViewer.VerticalOffset, + Height)); + } + + Log("Reported Offset: " + _scrollViewer.VerticalOffset); + } + } + + private bool DetermineIfScrollingIsFast() + { + var now = DateTime.Now; + var result = false; + if (_previousScrollOffsetChangedTime != DateTime.Now) + { + var scrolledPixels = Math.Abs(_scrollViewer.VerticalOffset - _previousScrollOffset); + var timeInSeconds = (now - _previousScrollOffsetChangedTime).TotalSeconds; + + if (scrolledPixels != 0) + { + var speedPixelsPerSecond = scrolledPixels / timeInSeconds; + Log(String.Format("Speed of scroll {0} ", speedPixelsPerSecond)); + + if (speedPixelsPerSecond > PixelsPerSecondThreshold) + { + result = true; + } + } + } + + _previousScrollOffsetChangedTime = now; + _previousScrollOffset = _scrollViewer.VerticalOffset; + return result; + } + + private readonly List _virtItems = new List(); + + // indexes of loaded items + private Segment _loadedSegment = new Segment(); + + // maps a point to its index in _virtItems + // covers only points 0, LoadUnloadThreshold, 2*LoadUnloadThreshold, etc + private readonly Dictionary _thresholdPointIndexes = new Dictionary(); + + + // do not change through this property + public List VirtItems + { + get { return _virtItems; } + } + + public MyVirtualizingPanel() + { + Loaded += MyVirtualizingPanel_Loaded; + } + + void MyVirtualizingPanel_Loaded(object sender, RoutedEventArgs e) + { + if (!DesignerProperties.GetIsInDesignMode(this)) + { + // Visual States are always on the first child of the control template + FrameworkElement element = VisualTreeHelper.GetChild(_scrollViewer, 0) as FrameworkElement; + if (element != null) + { + VisualStateGroup group = FindVisualState(element, "ScrollStates"); + if (group != null) + { + group.CurrentStateChanging += group_CurrentStateChanging; + } + } + } + } + + public void AddItems(IEnumerable _itemsToBeAdded) + { + var sw = new Stopwatch(); + sw.Start(); + + double topMargin = 0; + + if (_virtItems.Count > 0) + { + topMargin = _virtItems.Sum(vi => vi.FixedHeight); + } + + foreach (var itemToBeAdded in _itemsToBeAdded) + { + itemToBeAdded.View.Margin = new Thickness(itemToBeAdded.Margin.Left, itemToBeAdded.Margin.Top + topMargin, itemToBeAdded.Margin.Right, itemToBeAdded.Margin.Bottom); + + _virtItems.Add(itemToBeAdded); + + var itemHeightIncludingMargin = itemToBeAdded.FixedHeight; + + List coveredPoints = GetCoveredPoints(topMargin, topMargin + itemHeightIncludingMargin); + + foreach (var coveredPoint in coveredPoints) + { + _thresholdPointIndexes[coveredPoint] = _virtItems.Count - 1; // index of the last + } + + topMargin += itemHeightIncludingMargin; + } + + PerformLoadUnload(true); + + Height = topMargin; + + sw.Stop(); + + Log(String.Format("MyVirtualizingPanel.AddItems {0}", sw.ElapsedMilliseconds)); + } + + + public void InsertRemoveItems(int index, List itemsToInsert, bool keepItemsBelowIndexFixed = false, VListItemBase itemToRemove = null) + { + bool needToAdjustScrollPositionAfterInsertion = false; + + if (keepItemsBelowIndexFixed) + { + double totalHeightOfAllItemsBeforeIndex = 0; + + for (int i = 0; i < index; i++) + { + totalHeightOfAllItemsBeforeIndex += VirtItems[i].FixedHeight + VirtItems[i].Margin.Top + VirtItems[i].Margin.Bottom; + } + + if (totalHeightOfAllItemsBeforeIndex < _scrollViewer.VerticalOffset + _scrollViewer.ViewportHeight) + { + needToAdjustScrollPositionAfterInsertion = true; + } + } + + // UnloadItemsInSegment(_loadedSegment); + _loadedSegment = new Segment(); + + var totalHeight = itemsToInsert.Sum(i => i.FixedHeight + i.Margin.Top + i.Margin.Bottom); + + _virtItems.InsertRange(index, itemsToInsert); + + if (itemToRemove != null) + { + itemToRemove.IsVLoaded = false; + totalHeight -= itemToRemove.FixedHeight + itemToRemove.Margin.Top + itemToRemove.Margin.Bottom; + _virtItems.Remove(itemToRemove); + } + + + RearrangeAllItems(); + + + if (needToAdjustScrollPositionAfterInsertion) + { + _changingVerticalOffset = true; + //Debug.WriteLine("SCROLLING TO " + _scrollViewer.VerticalOffset + totalHeight + " scroll height : " + _scrollViewer.ExtentHeight); + _scrollViewer.ScrollToVerticalOffset(_scrollViewer.VerticalOffset + totalHeight); + _changingVerticalOffset = false; + } + + PerformLoadUnload(false); + } + + public void RemoveItem(VListItemBase itemToBeRemoved) + { + itemToBeRemoved.IsVLoaded = false; + + + _virtItems.Remove(itemToBeRemoved); + _loadedSegment = new Segment(); + RearrangeAllItems(); + + PerformLoadUnload(true); + } + + private void RearrangeAllItems() + { + double topMargin = 0; + _thresholdPointIndexes.Clear(); + int ind = 0; + foreach (var item in _virtItems) + { + item.View.Margin = new Thickness(item.Margin.Left, item.Margin.Top + topMargin, item.Margin.Right, item.Margin.Bottom); + + var itemHeightIncludingMargin = item.FixedHeight + item.Margin.Top + item.Margin.Bottom; + + List coveredPoints = GetCoveredPoints(topMargin, topMargin + itemHeightIncludingMargin); + + foreach (var coveredPoint in coveredPoints) + { + _thresholdPointIndexes[coveredPoint] = ind; // index of the last + } + + topMargin += itemHeightIncludingMargin; + ind++; + } + + Height = topMargin; + _scrollViewer.UpdateLayout(); + } + + private void PerformLoadUnload2(bool isToLoad, bool bypassUnload = false) + { + if (_virtItems.Count == 0) + return; + + double currentOffset = GetRealOffset(); + + int lowestLoadedInd = 0; + int upperInd = 0; + + bool triggerLoading = false; + + if (isToLoad || _loadedSegment.IsEmpty) + { + triggerLoading = true; + } + else + { + lowestLoadedInd = _loadedSegment.LowerBound; + upperInd = _loadedSegment.UpperBound; + + double topPoint = _virtItems[lowestLoadedInd].View.Margin.Top; + double bottomPoint = _virtItems[upperInd].View.Margin.Top + _virtItems[upperInd].FixedHeight; + + if (currentOffset - topPoint < 500 || + bottomPoint - currentOffset < 1500) + { + triggerLoading = true; + } + } + + if (triggerLoading) + { + if (_scrollViewer.ExtentHeight < 3000 && _isScrolling) + { + //Debug.WriteLine("Detected short scroll; loading all items"); + // otherwise there are glitches in scrolling + lowestLoadedInd = 0; + upperInd = VirtItems.Count - 1; + isToLoad = true; + } + else + { + var threshold = (int) Math.Floor((currentOffset - (currentOffset % LoadUnloadThreshold))); + + int indexOfBaseItem = _thresholdPointIndexes.ContainsKey(threshold) ? _thresholdPointIndexes[threshold] : -1; + + lowestLoadedInd = upperInd = indexOfBaseItem < 0 ? 0 : indexOfBaseItem; + + double loadUpwards = LoadedHeightUpwards; + double loadDownwards = _isScrolling ? LoadedHeightDownwards : LoadedHeightDownwardsNotScrolling; + + //if (_isScrolling) + //{ + // loadUpwards = LoadUpwardsWhenScrolling; + // loadDownwards = LoadDownwardsWhenScrolling; + //} + + // count up from the lower point on view + while (lowestLoadedInd > 0 && currentOffset - _virtItems[lowestLoadedInd].View.Margin.Top < loadUpwards) + { + lowestLoadedInd--; + } + + while (upperInd < _virtItems.Count - 1 && _virtItems[upperInd].View.Margin.Top - currentOffset < loadDownwards) + { + upperInd++; + } + + } + + SetLoadedBounds(lowestLoadedInd, upperInd, isToLoad, bypassUnload); + + + if (IsLogEnabled) + { + string loadedIndexes = "Loaded indexes : "; + for (int i = 0; i < _virtItems.Count; i++) + { + if (_virtItems[i].IsVLoaded) + { + loadedIndexes += i + ","; + } + } + + Log(loadedIndexes); + } + } + + } + + public double DeltaOffset + { + get; + set; + } + + private double GetRealOffset() + { + //// it might throw exception + //try + //{ + // GeneralTransform childTransform = this.TransformToVisual(_listScrollViewer); + + // var p = childTransform.Transform(new Point(0, 0)); + + // var delta = p.Y; + // Debug.WriteLine("DELTA offset =" + delta + "; VerticalOffset=" + _listScrollViewer.VerticalOffset); + + // return -delta; + //} + //catch (Exception exc) + //{ + // return _listScrollViewer.VerticalOffset; + //} + + return _scrollViewer.VerticalOffset + DeltaOffset; + } + + private void PerformLoadUnload(bool isToLoad) + { + PerformLoadUnload2(isToLoad); + } + + private void SetLoadedBounds(int lowerBoundInd, int upperBoundInd, bool isToLoad, bool bypassUnload = false) + { + var newLoadedSegment = new Segment(lowerBoundInd, upperBoundInd); + + Segment newMinusLoaded1; + Segment newMinusLoaded2; + Segment intersection; + Segment loadedMinusNew1; + Segment loadedMinusNew2; + + newLoadedSegment.CompareToSegment(_loadedSegment, + out newMinusLoaded1, + out newMinusLoaded2, + out intersection, + out loadedMinusNew1, + out loadedMinusNew2); + + + Log(String.Format("LoadedSegment:{0}, NewSegment:{1}, NewMinusLoaded1:{2}, NewMinusLoaded2:{3}, loadedMinusNew1:{4}, loadedMinusNew2:{5}", + _loadedSegment, + newLoadedSegment, + newMinusLoaded1, + newMinusLoaded2, + loadedMinusNew1, + loadedMinusNew2)); + + if (isToLoad) + { + // ensure items are loaded fully for the whole segment + LoadItemsInSegment(newLoadedSegment); + } + + if (!bypassUnload) + { + UnloadItemsInSegment(loadedMinusNew1); + UnloadItemsInSegment(loadedMinusNew2); + } + _loadedSegment = newLoadedSegment; + + } + + private void UnloadItemsInSegment(Segment segment) + { + for (int i = segment.LowerBound; i <= segment.UpperBound; i++) + { + var item = _virtItems[i]; + + Children.Remove(item.View); + + item.IsVLoaded = false; + } + } + + private void LoadItemsInSegment(Segment segment) + { + for (int i = segment.LowerBound; i <= segment.UpperBound; i++) + { + var item = _virtItems[i]; + + item.IsVLoaded = true; + + if (!Children.Contains(item.View)) + { + Children.Add(item.View); + } + } + } + + private List GetCoveredPoints(double from, double to) + { + + var result = new List(); + + var candidate = from - (from % LoadUnloadThreshold); + + while (candidate <= to) + { + if (candidate >= from) + { + result.Add((int) Math.Floor(candidate)); + } + candidate += LoadUnloadThreshold; + } + + return result; + } + + public void ClearItems() + { + _virtItems.Clear(); + Children.Clear(); + _loadedSegment = new Segment(); + _thresholdPointIndexes.Clear(); + _scrollViewer.ScrollToVerticalOffset(0); + Height = 0; + } + } +} diff --git a/Telegram.EmojiPanel/Controls/Utilites/VListItemBase.cs b/Telegram.EmojiPanel/Controls/Utilites/VListItemBase.cs new file mode 100755 index 0000000..cdd6f83 --- /dev/null +++ b/Telegram.EmojiPanel/Controls/Utilites/VListItemBase.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using System.Windows; +using Telegram.EmojiPanel.Controls.Utilites; +using Rectangle = System.Windows.Shapes.Rectangle; + +namespace Telegram.Controls.VirtualizedView +{ + public abstract class VListItemBase + { + private readonly List _children = new List(); + + public MyListItemBase View { get; private set; } + + public List Children + { + get { return _children; } + } + + protected VListItemBase() + { + View = new MyListItemBase + { + VirtSource = this, + Width = 440 + }; + } + public abstract double FixedHeight { get; set; } + + public Thickness Margin = new Thickness(); + + public virtual object ItemSource { get; set; } + + private bool _isVLoaded; + + public bool IsVLoaded + { + get { return _isVLoaded; } + set + { + if (value != IsVLoaded) + { + if (value) Load(); + else Unload(); + } + _isVLoaded = value; + } + } + + public virtual void Load() + { + if (View.Children.Count == 0) + foreach (var child in _children) + View.Children.Add(child); + } + + public virtual void Unload() + { + View.Children.Clear(); + } + } +} diff --git a/Telegram.EmojiPanel/Controls/Utilites/VirtSegment.cs b/Telegram.EmojiPanel/Controls/Utilites/VirtSegment.cs new file mode 100755 index 0000000..8796fc9 --- /dev/null +++ b/Telegram.EmojiPanel/Controls/Utilites/VirtSegment.cs @@ -0,0 +1,98 @@ +using System; + +namespace Telegram.EmojiPanel.Controls.Utilites +{ + public class Segment + { + public int LowerBound { get; private set; } + public int UpperBound { get; private set; } + + public bool IsEmpty { get { return UpperBound < LowerBound; } } + + public Segment(int lowerBound, int upperBound) + { + LowerBound = lowerBound; + UpperBound = upperBound; + } + + public Segment() + : this(0, -1) + { + } + + public override string ToString() + { + if (IsEmpty) return "[]"; + return String.Format("[{0},{1}]", LowerBound, UpperBound); + } + + public void CompareToSegment( + Segment otherSegment, + out Segment thisMinusOther1, + out Segment thisMinusOther2, + out Segment intersection, + out Segment otherMinusThis1, + out Segment otherMinusThis2) + { + + thisMinusOther1 = new Segment(); + thisMinusOther2 = new Segment(); + intersection = new Segment(); + otherMinusThis1 = new Segment(); + otherMinusThis2 = new Segment(); + + + if (this.IsEmpty) + { + otherMinusThis1 = otherSegment; + return; + } + + if (otherSegment.IsEmpty) + { + thisMinusOther1 = this; + return; + } + + if (this.UpperBound < otherSegment.LowerBound) + { + + // do not intersect + + thisMinusOther1 = this; + + otherMinusThis1 = otherSegment; + + return; + } + + + if (this.LowerBound < otherSegment.LowerBound && + this.UpperBound >= otherSegment.LowerBound && + this.UpperBound <= otherSegment.UpperBound) + { + thisMinusOther1 = new Segment(this.LowerBound, otherSegment.LowerBound - 1); + intersection = new Segment(otherSegment.LowerBound, this.UpperBound); + otherMinusThis1 = new Segment(this.UpperBound + 1, otherSegment.UpperBound); + return; + } + + if (this.LowerBound >= otherSegment.LowerBound && + this.UpperBound <= otherSegment.UpperBound) + { + intersection = this; + otherMinusThis1 = new Segment(otherSegment.LowerBound, this.LowerBound - 1); + otherMinusThis2 = new Segment(this.UpperBound + 1, otherSegment.UpperBound); + return; + } + + otherSegment.CompareToSegment(this, + out otherMinusThis1, + out otherMinusThis2, + out intersection, + out thisMinusOther1, + out thisMinusOther2); + + } + } +} diff --git a/Telegram.EmojiPanel/Properties/AssemblyInfo.cs b/Telegram.EmojiPanel/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..a1d0c17 --- /dev/null +++ b/Telegram.EmojiPanel/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("Telegram.EmojiPanel")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Telegram.EmojiPanel")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[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("755e1785-f75a-4a86-b0e1-ef202e134f1c")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] + diff --git a/Telegram.EmojiPanel/Telegram.EmojiPanel.csproj b/Telegram.EmojiPanel/Telegram.EmojiPanel.csproj new file mode 100755 index 0000000..78bf32e --- /dev/null +++ b/Telegram.EmojiPanel/Telegram.EmojiPanel.csproj @@ -0,0 +1,2822 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {755E1785-F75A-4A86-B0E1-EF202E134F1C} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Telegram.EmojiPanel + Telegram.EmojiPanel + v4.0 + $(TargetFrameworkVersion) + WindowsPhone71 + Silverlight + false + true + true + ..\ + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + + ..\packages\WPtoolkit.4.2013.08.16\lib\sl4-windowsphone71\Microsoft.Phone.Controls.Toolkit.dll + + + + + + + + + + + + + + + EmojiControl.xaml + + + + + + + + + + + + + + + + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + + + + + + + + + + + + + {0C2F1B61-A8FE-45FB-8538-AA6925A415B6} + Telegram.Api + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/Telegram.EmojiPanel/TelegramRichTextBox.cs b/Telegram.EmojiPanel/TelegramRichTextBox.cs new file mode 100755 index 0000000..aef626f --- /dev/null +++ b/Telegram.EmojiPanel/TelegramRichTextBox.cs @@ -0,0 +1,298 @@ +using System; +using System.Text.RegularExpressions; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace Telegram.EmojiPanel +{ + public class TelegramRichTextBox : Control + { + public static readonly DependencyProperty MoreElementProperty = DependencyProperty.Register( + "MoreElement", typeof (FrameworkElement), typeof (TelegramRichTextBox), new PropertyMetadata(default(FrameworkElement), OnMoreElementChanged)); + + private static void OnMoreElementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var telegramRichTextBox = (TelegramRichTextBox) d; + telegramRichTextBox.OnSizeChanged(null, null); + } + + public FrameworkElement MoreElement + { + get { return (FrameworkElement) GetValue(MoreElementProperty); } + set { SetValue(MoreElementProperty, value); } + } + + public static readonly DependencyProperty TextScaleFactorProperty = DependencyProperty.Register( + "TextScaleFactor", typeof (double), typeof (TelegramRichTextBox), new PropertyMetadata(1.0, OnFontScaleFactorChanged)); + + private static void OnFontScaleFactorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var textBox = (TelegramRichTextBox)d; + if (textBox != null && textBox._stackPanel != null) + { + foreach (var child in textBox._stackPanel.Children) + { + var richTextBox = child as RichTextBox; + if (richTextBox != null) + { + richTextBox.FontSize = textBox._defaultFontSize*(double) e.NewValue; + foreach (var block in richTextBox.Blocks) + { + var paragraph = block as Paragraph; + if (paragraph != null) + { + foreach (var inline in paragraph.Inlines) + { + var uiContainer = inline as InlineUIContainer; + if (uiContainer != null) + { + var image = uiContainer.Child as Image; + if (image != null) + { + var size = 27.0 * (double)e.NewValue; + image.Height = size; + image.Width = size; + } + } + } + } + } + } + } + } + } + + private double _defaultFontSize; + + public double TextScaleFactor + { + get { return (double) GetValue(TextScaleFactorProperty); } + set { SetValue(TextScaleFactorProperty, value); } + } + + private StackPanel _stackPanel; + private TextBlock measureTxt; + + public TelegramRichTextBox() + { + DefaultStyleKey = typeof(TelegramRichTextBox); + + SizeChanged += OnSizeChanged; + } + + private void OnSizeChanged(object sender, SizeChangedEventArgs e) + { + if (MoreElement != null) + { + if (ActualHeight > 0.0 && MaxHeight > 0.0 && ActualHeight >= MaxHeight) + { + MoreElement.Visibility = Visibility.Visible; + } + else + { + MoreElement.Visibility = Visibility.Collapsed; + } + } + } + + public static readonly DependencyProperty TextProperty = + DependencyProperty.Register( + "Text", + typeof(string), + typeof(TelegramRichTextBox), + new PropertyMetadata("", OnTextPropertyChanged)); + + public string Text + { + get + { + return (string)GetValue(TextProperty); + } + set + { + SetValue(TextProperty, value); + } + } + + public static readonly DependencyProperty DateTextProperty = DependencyProperty.Register( + "DateText", typeof (string), typeof (TelegramRichTextBox), new PropertyMetadata(default(string))); + + public string DateText + { + get { return (string) GetValue(DateTextProperty); } + set { SetValue(DateTextProperty, value); } + } + + private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + TelegramRichTextBox source = (TelegramRichTextBox)d; + string value = (string)e.NewValue; + source.ParseText(value); + } + + + public override void OnApplyTemplate() + { + _defaultFontSize = FontSize; + _stackPanel = GetTemplateChild("StackPanel") as StackPanel; + ParseText(Text); + + base.OnApplyTemplate(); + + } + + private void ParseText(string value) + { + if (value == null) + { + value = ""; + } + + if (_stackPanel == null) + { + return; + } + // Clear previous TextBlocks + _stackPanel.Children.Clear(); + + + bool fitIn2000Pixels = CheckFitInMaxRenderHeight(value); + + if (fitIn2000Pixels) + { + var textBlock = GetTextBlock(); + BrowserNavigationService.SetText(textBlock, value); + _stackPanel.Children.Add(textBlock); + } + else + { + ParseLineExtended(value); + } + } + + private readonly int MAX_STR_LENGTH = 1100; + + private void ParseLineExtended(string allText) + { + if (string.IsNullOrEmpty(allText)) + return; + + + int cutIndex = MAX_STR_LENGTH; + if (cutIndex >= allText.Length) + cutIndex = allText.Length - 1; + + var endOfSentenceIndAfterCut = allText.IndexOf(".", cutIndex); + + if (endOfSentenceIndAfterCut >= 0 && endOfSentenceIndAfterCut - cutIndex < 200) + { + cutIndex = endOfSentenceIndAfterCut; + } + else + { + var whiteSpaceIndAfterCut = allText.IndexOf(' ', cutIndex); + + if (whiteSpaceIndAfterCut >= 0 && whiteSpaceIndAfterCut - cutIndex < 100) + { + cutIndex = whiteSpaceIndAfterCut; + } + } + + // add all whitespaces before cut + while (cutIndex + 1 < allText.Length && + allText[cutIndex + 1] == ' ') + { + cutIndex++; + } + + string leftSide = allText.Substring(0, cutIndex + 1); + RichTextBox textBlock = this.GetTextBlock(); + BrowserNavigationService.SetText(textBlock, leftSide); + this._stackPanel.Children.Add(textBlock); + + allText = allText.Substring(cutIndex + 1); + + if (allText.Length > 0) + { + ParseLineExtended(allText); + } + } + + private bool CheckFitInMaxRenderHeight(string value) + { + return value.Length <= MAX_STR_LENGTH; + } + + private RichTextBox GetTextBlock() + { + var textBlock = new RichTextBox(); + + textBlock.TextWrapping = TextWrapping.Wrap; + textBlock.IsReadOnly = true; + textBlock.FontSize = FontSize * TextScaleFactor; + textBlock.FontFamily = FontFamily; + textBlock.HorizontalContentAlignment = HorizontalContentAlignment; + textBlock.Foreground = Foreground; + textBlock.Padding = new Thickness(0, 0, 0, 0); + + return textBlock; + } + + } + + public class Utils + { + public static readonly Regex HyperlinkRegex = new Regex("(?i)\\b(((?:https?://|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’]))|([a-z0-9.\\-]+(\\.ru|\\.com|\\.net|\\.org|\\.us|\\.it|\\.co\\.uk)(?![a-z0-9]))|([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]*[a-zA-Z0-9-]+))"); + + public static string GetFormattedLink(string link) + { + var flag = link.EndsWith(","); + if (flag && link.Length > 1) + link = link.Substring(0, link.Length - 1); + if (!link.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + link = "http://" + link; + + return link; + } + + public static Inline GetTextBlock(string text) + { + return new Run { Text = text }; + } + + public static Inline GetHyperlinkBlock(string text, string link) + { + var hyperlink = new Hyperlink(); + hyperlink.Inlines.Add(text); + hyperlink.NavigateUri = new Uri(link, UriKind.Absolute); + + return hyperlink; + } + + public static Inline GetEmojiBlock(string emoji) + { + var uiContainer = new InlineUIContainer(); + uiContainer.Child = new Image { Source = GetEmojiSource(emoji), Width = 30, Height = 30 }; + + return uiContainer; + } + + public static ImageSource GetEmojiSource(string emoji) + { + return new BitmapImage(new Uri(emoji)); + } + + public static Regex GetRegex(bool supportEmoji) + { + if (supportEmoji) + { + return HyperlinkRegex; + } + + return HyperlinkRegex; + } + } +} diff --git a/Telegram.EmojiPanel/TestScrollableTextBlock.cs b/Telegram.EmojiPanel/TestScrollableTextBlock.cs new file mode 100755 index 0000000..c5c8b2d --- /dev/null +++ b/Telegram.EmojiPanel/TestScrollableTextBlock.cs @@ -0,0 +1,156 @@ +using System.Windows; +using System.Windows.Controls; + +namespace Telegram.EmojiPanel +{ + public class TestScrollableTextBlock : Control + { + private StackPanel stackPanel; + private TextBlock measureTxt; + + public TestScrollableTextBlock() + { + DefaultStyleKey = typeof(TestScrollableTextBlock); + } + + public static readonly DependencyProperty TextProperty = + DependencyProperty.Register( + "Text", + typeof(string), + typeof(TestScrollableTextBlock), + new PropertyMetadata("", OnTextPropertyChanged)); + + + public static readonly DependencyProperty LineHeightProperty + = DependencyProperty.Register( + "LineHeight", + typeof(double), + typeof(TestScrollableTextBlock), null); + + public string Text + { + get + { + return (string)GetValue(TextProperty); + } + set + { + SetValue(TextProperty, value); + } + } + + private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + //TestScrollableTextBlock source = (TestScrollableTextBlock)d; + //string value = (string)e.NewValue; + //source.ParseText(value); + } + + + public override void OnApplyTemplate() + { + stackPanel = GetTemplateChild("StackPanel") as StackPanel; + ParseText(Text); + + base.OnApplyTemplate(); + + } + + private void ParseText(string value) + { + if (value == null) + { + value = ""; + } + + if (this.stackPanel == null) + { + return; + } + // Clear previous TextBlocks + this.stackPanel.Children.Clear(); + + + bool fitIn2000Pixels = CheckFitInMaxRenderHeight(value); + + if (fitIn2000Pixels) + { + RichTextBox textBlock = this.GetTextBlock(); + BrowserNavigationService.SetText(textBlock, value); + this.stackPanel.Children.Add(textBlock); + } + else + { + ParseLineExtended(value); + } + } + + private readonly int MAX_STR_LENGTH = 1100; + + private void ParseLineExtended(string allText) + { + if (string.IsNullOrEmpty(allText)) + return; + + + int cutIndex = MAX_STR_LENGTH; + if (cutIndex >= allText.Length) + cutIndex = allText.Length - 1; + + var endOfSentenceIndAfterCut = allText.IndexOf(".", cutIndex); + + if (endOfSentenceIndAfterCut >= 0 && endOfSentenceIndAfterCut - cutIndex < 200) + { + cutIndex = endOfSentenceIndAfterCut; + } + else + { + var whiteSpaceIndAfterCut = allText.IndexOf(' ', cutIndex); + + if (whiteSpaceIndAfterCut >= 0 && whiteSpaceIndAfterCut - cutIndex < 100) + { + cutIndex = whiteSpaceIndAfterCut; + } + } + + // add all whitespaces before cut + while (cutIndex + 1 < allText.Length && + allText[cutIndex + 1] == ' ') + { + cutIndex++; + } + + string leftSide = allText.Substring(0, cutIndex + 1); + RichTextBox textBlock = this.GetTextBlock(); + BrowserNavigationService.SetText(textBlock, leftSide); + this.stackPanel.Children.Add(textBlock); + + allText = allText.Substring(cutIndex + 1); + + if (allText.Length > 0) + { + ParseLineExtended(allText); + } + } + + private bool CheckFitInMaxRenderHeight(string value) + { + return value.Length <= MAX_STR_LENGTH; + } + + private RichTextBox GetTextBlock() + { + RichTextBox textBlock = new RichTextBox(); + textBlock.TextWrapping = TextWrapping.Wrap; + + textBlock.IsReadOnly = true; + textBlock.FontSize = this.FontSize; + textBlock.FontFamily = this.FontFamily; + textBlock.HorizontalContentAlignment = this.HorizontalContentAlignment; + textBlock.Foreground = Foreground; + textBlock.Padding = new Thickness(-12, 0, 0, 0); + + return textBlock; + } + } +} diff --git a/Telegram.EmojiPanel/Themes/generic.xaml b/Telegram.EmojiPanel/Themes/generic.xaml new file mode 100755 index 0000000..a43436c --- /dev/null +++ b/Telegram.EmojiPanel/Themes/generic.xaml @@ -0,0 +1,37 @@ + + + + + + \ No newline at end of file diff --git a/Telegram.EmojiPanel/packages.config b/Telegram.EmojiPanel/packages.config new file mode 100755 index 0000000..62ebfb3 --- /dev/null +++ b/Telegram.EmojiPanel/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/TelegramClient.Native/ConnectionSocket.cpp b/TelegramClient.Native/ConnectionSocket.cpp new file mode 100755 index 0000000..47cd260 --- /dev/null +++ b/TelegramClient.Native/ConnectionSocket.cpp @@ -0,0 +1,95 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#include "pch.h" +//#define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include + +#include "ConnectionSocket.h" + +#pragma comment(lib,"WS2_32") + +using namespace TelegramClient_Native; + +void ConnectionSocket::SendPacket(Platform::String^ caption, const Platform::Array^ data) +{ + +} + +void ConnectionSocket::Close() +{ + int err = closesocket(_socket); + if (err < 0) + { + printf("closesocket failed with error: %d\n", err); + return; + } +} + +ConnectionSocket::ConnectionSocket(Platform::String^ host, int port) +{ + WORD wVersionRequested; + WSADATA wsaData; + int err; + + /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */ + wVersionRequested = MAKEWORD(2, 2); + + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + /* Tell the user that we could not find a usable */ + /* Winsock DLL. */ + printf("WSAStartup failed with error: %d\n", err); + return; + } + + _socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + sockaddr_in serverAddr; + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = inet_addr("149.154.175.50"); + serverAddr.sin_port = htons(443); + + err = connect(_socket, (sockaddr*)&serverAddr, sizeof(serverAddr)); + if (err < 0) + { + printf("connect failed with error: %d\n", err); + return; + } + + /*err = closesocket(_socket); + if (err < 0) + { + printf("closesocket failed with error: %d\n", err); + return; + }*/ + //int sockbufsize = 0, size = sizeof(int); + //err = getsockopt(skt, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size); + + //WSACleanup(); +} + +int ConnectionSocket::GetReceiveBufferSize() +{ + int sockbufsize = 0, size = sizeof(int); + int err = getsockopt(_socket, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size); + + return sockbufsize; +} + +int ConnectionSocket::GetSendBufferSize() +{ + int sockbufsize = 0, size = sizeof(int); + int err = getsockopt(_socket, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size); + + return sockbufsize; +} diff --git a/TelegramClient.Native/ConnectionSocket.h b/TelegramClient.Native/ConnectionSocket.h new file mode 100755 index 0000000..1d593e0 --- /dev/null +++ b/TelegramClient.Native/ConnectionSocket.h @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once + +namespace TelegramClient_Native +{ + ref class ConnectionSocket; + public delegate void PacketReceivedEventHandler(ConnectionSocket^ sender, const Platform::Array^ s); + + public ref class ConnectionSocket sealed + { + private: + SOCKET _socket; + + public: + ConnectionSocket(Platform::String^ host, int port); + + event PacketReceivedEventHandler^ PacketReceived; + void SendPacket(Platform::String^ caption, const Platform::Array^ data); + void Close(); + + int GetReceiveBufferSize(); + + int GetSendBufferSize(); + }; +} + diff --git a/TelegramClient.Native/EmojiSuggestion.cpp b/TelegramClient.Native/EmojiSuggestion.cpp new file mode 100755 index 0000000..d94b91f --- /dev/null +++ b/TelegramClient.Native/EmojiSuggestion.cpp @@ -0,0 +1,46 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#include "pch.h" +#include "EmojiSuggestion.h" +#include "emoji_suggestions.h" + +using namespace TelegramClient_Native; +using namespace Platform; +using namespace Ui::Emoji; + +int EmojiSuggestion::GetSuggestionMaxLength() +{ + return Ui::Emoji::GetSuggestionMaxLength(); +} + +EmojiSuggestion::EmojiSuggestion(Suggestion suggestion) +{ + auto emoji = reinterpret_cast(suggestion.emoji().data()); + m_emoji = ref new String(emoji, suggestion.emoji().size()); + + auto label = reinterpret_cast(suggestion.label().data()); + m_label = ref new String(label, suggestion.label().size()); + + auto replacement = reinterpret_cast(suggestion.replacement().data()); + m_replacement = ref new String(replacement, suggestion.replacement().size()); +} + +Array^ EmojiSuggestion::GetSuggestions(String^ query) +{ + auto data = reinterpret_cast(query->Data()); + auto results = Ui::Emoji::GetSuggestions(utf16string(data, query->Length())); + + std::vector suggestions; + + for (auto &item : results) + { + suggestions.push_back(ref new EmojiSuggestion(item)); + } + + return ref new Array(suggestions.data(), suggestions.size()); +} diff --git a/TelegramClient.Native/EmojiSuggestion.h b/TelegramClient.Native/EmojiSuggestion.h new file mode 100755 index 0000000..8d33280 --- /dev/null +++ b/TelegramClient.Native/EmojiSuggestion.h @@ -0,0 +1,47 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once + +#include "emoji_suggestions.h" + +using namespace Platform; +using namespace Ui::Emoji; + +namespace TelegramClient_Native +{ + public ref class EmojiSuggestion sealed + { + public: + static Array^ GetSuggestions(String^ query); + static int GetSuggestionMaxLength(); + + + property String^ Emoji + { + String^ get() { return m_emoji; } + } + + property String^ Label + { + String^ get() { return m_label; } + } + + property String^ Replacement + { + String^ get() { return m_replacement; } + } + + + private: + EmojiSuggestion(Suggestion suggestion); + + String^ m_emoji; + String^ m_label; + String^ m_replacement; + }; +} diff --git a/TelegramClient.Native/TelegramClient.Native.vcxproj b/TelegramClient.Native/TelegramClient.Native.vcxproj new file mode 100755 index 0000000..915bf27 --- /dev/null +++ b/TelegramClient.Native/TelegramClient.Native.vcxproj @@ -0,0 +1,156 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + ARM + + + Release + ARM + + + + {b51dd8c5-335d-4a2d-b429-6d0f41ed0281} + Win32Proj + TelegramClient.Native + TelegramClient_Native + en-US + 12.0 + true + Windows Phone Silverlight + 8.1 + + + + DynamicLibrary + true + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + true + v120 + + + DynamicLibrary + false + true + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + NotUsing + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + /bigobj %(AdditionalOptions) + true + + + Console + false + + + + + NotUsing + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + /bigobj %(AdditionalOptions) + true + + + Console + false + + + + + NotUsing + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + /bigobj %(AdditionalOptions) + true + + + Console + false + + + + + NotUsing + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + /bigobj %(AdditionalOptions) + true + + + Console + false + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/TelegramClient.Native/TelegramClient.Native.vcxproj.filters b/TelegramClient.Native/TelegramClient.Native.vcxproj.filters new file mode 100755 index 0000000..08df544 --- /dev/null +++ b/TelegramClient.Native/TelegramClient.Native.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + b168f0cb-dc50-4df4-9161-ce6c9e6f26e7 + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.Native/emoji_suggestions.cpp b/TelegramClient.Native/emoji_suggestions.cpp new file mode 100755 index 0000000..8cb2e46 --- /dev/null +++ b/TelegramClient.Native/emoji_suggestions.cpp @@ -0,0 +1,432 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "emoji_suggestions.h" + +#include +#include "emoji_suggestions_data.h" + +#ifndef Expects +#include +#define Expects(condition) assert(condition) +#endif // Expects + +namespace Ui { +namespace Emoji { +namespace internal { +namespace { + +checksum Crc32Table[256]; +class Crc32Initializer { +public: + Crc32Initializer() { + checksum poly = 0x04C11DB7U; + for (auto i = 0; i != 256; ++i) { + Crc32Table[i] = reflect(i, 8) << 24; + for (auto j = 0; j != 8; ++j) { + Crc32Table[i] = (Crc32Table[i] << 1) ^ (Crc32Table[i] & (1 << 31) ? poly : 0); + } + Crc32Table[i] = reflect(Crc32Table[i], 32); + } + } + +private: + checksum reflect(checksum val, char ch) { + checksum result = 0; + for (int i = 1; i < (ch + 1); ++i) { + if (val & 1) { + result |= 1 << (ch - i); + } + val >>= 1; + } + return result; + } + +}; + +} // namespace + +checksum countChecksum(const void *data, std::size_t size) { + static Crc32Initializer InitTable; + + auto buffer = static_cast(data); + auto result = checksum(0xFFFFFFFFU); + for (auto i = std::size_t(0); i != size; ++i) { + result = (result >> 8) ^ Crc32Table[(result & 0xFFU) ^ buffer[i]]; + } + return (result ^ 0xFFFFFFFFU); +} + +} // namespace internal + +namespace { + +class string_span { +public: + string_span() = default; + string_span(const utf16string *data, std::size_t size) : begin_(data), size_(size) { + } + string_span(const std::vector &data) : begin_(data.data()), size_(data.size()) { + } + string_span(const string_span &other) = default; + string_span &operator=(const string_span &other) = default; + + const utf16string *begin() const { + return begin_; + } + const utf16string *end() const { + return begin_ + size_; + } + std::size_t size() const { + return size_; + } + + string_span subspan(std::size_t offset, std::size_t size) { + return string_span(begin_ + offset, size); + } + +private: + const utf16string *begin_ = nullptr; + std::size_t size_ = 0; + +}; + +bool IsNumber(utf16char ch) { + return (ch >= '0' && ch <= '9'); +} + +bool IsLetterOrNumber(utf16char ch) { + return (ch >= 'a' && ch <= 'z') || IsNumber(ch); +} + +using Replacement = internal::Replacement; + +class Completer { +public: + Completer(utf16string query); + + std::vector resolve(); + +private: + struct Result { + const Replacement *replacement; + int wordsUsed; + }; + + static std::vector NormalizeQuery(utf16string query); + void addResult(const Replacement *replacement); + bool isDuplicateOfLastResult(const Replacement *replacement) const; + bool isBetterThanLastResult(const Replacement *replacement) const; + void processInitialList(); + void filterInitialList(); + void initWordsTracking(); + bool matchQueryForCurrentItem(); + bool matchQueryTailStartingFrom(int position); + string_span findWordsStartingWith(utf16char ch); + int findEqualCharsCount(int position, const utf16string *word); + std::vector prepareResult(); + bool startsWithQuery(utf16string word); + bool isExactMatch(utf16string replacement); + + std::vector _result; + + utf16string _initialQuery; + const std::vector _query; + const utf16char *_queryBegin = nullptr; + int _querySize = 0; + + const std::vector *_initialList = nullptr; + + string_span _currentItemWords; + int _currentItemWordsUsedCount = 0; + + class UsedWordGuard { + public: + UsedWordGuard(std::vector &map, int index); + UsedWordGuard(const UsedWordGuard &other) = delete; + UsedWordGuard(UsedWordGuard &&other); + UsedWordGuard &operator=(const UsedWordGuard &other) = delete; + UsedWordGuard &operator=(UsedWordGuard &&other) = delete; + explicit operator bool() const; + ~UsedWordGuard(); + + private: + std::vector &_map; + int _index = 0; + bool _guarded = false; + + }; + std::vector _currentItemWordsUsedMap; + +}; + +Completer::UsedWordGuard::UsedWordGuard(std::vector &map, int index) : _map(map), _index(index) { + Expects(_map.size() > _index); + if (!_map[_index]) { + _guarded = _map[_index] = 1; + } +} + +Completer::UsedWordGuard::UsedWordGuard(UsedWordGuard &&other) : _map(other._map), _index(other._index), _guarded(other._guarded) { + other._guarded = 0; +} + +Completer::UsedWordGuard::operator bool() const { + return _guarded; +} + +Completer::UsedWordGuard::~UsedWordGuard() { + if (_guarded) { + _map[_index] = 0; + } +} + +Completer::Completer(utf16string query) : _initialQuery(query), _query(NormalizeQuery(query)) { +} + +// Remove all non-letters-or-numbers. +// Leave '-' and '+' only if they're followed by a number or +// at the end of the query (so it is possibly followed by a number). +std::vector Completer::NormalizeQuery(utf16string query) { + auto result = std::vector(); + result.reserve(query.size()); + auto copyFrom = query.data(); + auto e = copyFrom + query.size(); + auto copyTo = result.data(); + for (auto i = query.data(); i != e; ++i) { + if (IsLetterOrNumber(*i)) { + continue; + } else if (*i == '-' || *i == '+') { + if (i + 1 == e || IsNumber(*(i + 1))) { + continue; + } + } + if (i > copyFrom) { + result.resize(result.size() + (i - copyFrom)); + memcpy(copyTo, copyFrom, (i - copyFrom) * sizeof(utf16char)); + copyTo += (i - copyFrom); + } + copyFrom = i + 1; + } + if (e > copyFrom) { + result.resize(result.size() + (e - copyFrom)); + memcpy(copyTo, copyFrom, (e - copyFrom) * sizeof(utf16char)); + copyTo += (e - copyFrom); + } + return result; +} + +std::vector Completer::resolve() { + _queryBegin = _query.data(); + _querySize = _query.size(); + if (!_querySize) { + return std::vector(); + } + _initialList = Ui::Emoji::internal::GetReplacements(*_queryBegin); + if (!_initialList) { + return std::vector(); + } + _result.reserve(_initialList->size()); + processInitialList(); + return prepareResult(); +} + +bool Completer::isDuplicateOfLastResult(const Replacement *item) const { + if (_result.empty()) { + return false; + } + return (_result.back().replacement->emoji == item->emoji); +} + +bool Completer::isBetterThanLastResult(const Replacement *item) const { + Expects(!_result.empty()); + auto &last = _result.back(); + if (_currentItemWordsUsedCount < last.wordsUsed) { + return true; + } + + auto firstCharOfQuery = _query[0]; + auto firstCharAfterColonLast = last.replacement->replacement[1]; + auto firstCharAfterColonCurrent = item->replacement[1]; + auto goodLast = (firstCharAfterColonLast == firstCharOfQuery); + auto goodCurrent = (firstCharAfterColonCurrent == firstCharOfQuery); + return !goodLast && goodCurrent; +} + +void Completer::addResult(const Replacement *item) { + if (!isDuplicateOfLastResult(item)) { + _result.push_back({ item, _currentItemWordsUsedCount }); + } else if (isBetterThanLastResult(item)) { + _result.back() = { item, _currentItemWordsUsedCount }; + } +} + +void Completer::processInitialList() { + if (_querySize > 1) { + filterInitialList(); + } else { + _currentItemWordsUsedCount = 1; + for (auto item : *_initialList) { + addResult(item); + } + } +} + +void Completer::initWordsTracking() { + auto maxWordsCount = 0; + for (auto item : *_initialList) { + auto wordsCount = item->words.size(); + if (maxWordsCount < wordsCount) { + maxWordsCount = wordsCount; + } + } + _currentItemWordsUsedMap = std::vector(maxWordsCount, 0); +} + +void Completer::filterInitialList() { + initWordsTracking(); + for (auto item : *_initialList) { + _currentItemWords = string_span(item->words); + _currentItemWordsUsedCount = 1; + if (matchQueryForCurrentItem()) { + addResult(item); + } + _currentItemWordsUsedCount = 0; + } +} + +bool Completer::matchQueryForCurrentItem() { + Expects(_currentItemWords.size() != 0); + if (_currentItemWords.size() < 2) { + return startsWithQuery(*_currentItemWords.begin()); + } + return matchQueryTailStartingFrom(0); +} + +bool Completer::startsWithQuery(utf16string word) { + if (word.size() < _query.size()) { + return false; + } + for (auto i = std::size_t(0), size = _query.size(); i != size; ++i) { + if (word[i] != _query[i]) { + return false; + } + } + return true; +} + +bool Completer::isExactMatch(utf16string replacement) { + if (replacement.size() != _initialQuery.size() + 1) { + return false; + } + for (auto i = std::size_t(0), size = _initialQuery.size(); i != size; ++i) { + if (replacement[i] != _initialQuery[i]) { + return false; + } + } + return true; +} + +bool Completer::matchQueryTailStartingFrom(int position) { + auto charsLeftToMatch = (_querySize - position); + if (!charsLeftToMatch) { + return true; + } + + auto firstCharToMatch = *(_queryBegin + position); + auto foundWords = findWordsStartingWith(firstCharToMatch); + + for (auto word = foundWords.begin(), foundWordsEnd = word + foundWords.size(); word != foundWordsEnd; ++word) { + auto wordIndex = word - _currentItemWords.begin(); + if (auto guard = UsedWordGuard(_currentItemWordsUsedMap, wordIndex)) { + ++_currentItemWordsUsedCount; + auto equalCharsCount = findEqualCharsCount(position, word); + for (auto check = equalCharsCount; check != 0; --check) { + if (matchQueryTailStartingFrom(position + check)) { + return true; + } + } + --_currentItemWordsUsedCount; + } + } + return false; +} + +int Completer::findEqualCharsCount(int position, const utf16string *word) { + auto charsLeft = (_querySize - position); + auto wordBegin = word->data(); + auto wordSize = word->size(); + auto possibleEqualCharsCount = (charsLeft > wordSize ? wordSize : charsLeft); + for (auto equalTill = 1; equalTill != possibleEqualCharsCount; ++equalTill) { + auto wordCh = *(wordBegin + equalTill); + auto queryCh = *(_queryBegin + position + equalTill); + if (wordCh != queryCh) { + return equalTill; + } + } + return possibleEqualCharsCount; +} + +std::vector Completer::prepareResult() { + auto firstCharOfQuery = _query[0]; + std::stable_partition(_result.begin(), _result.end(), [firstCharOfQuery](Result &result) { + auto firstCharAfterColon = result.replacement->replacement[1]; + return (firstCharAfterColon == firstCharOfQuery); + }); + std::stable_partition(_result.begin(), _result.end(), [](Result &result) { + return (result.wordsUsed < 2); + }); + std::stable_partition(_result.begin(), _result.end(), [](Result &result) { + return (result.wordsUsed < 3); + }); + std::stable_partition(_result.begin(), _result.end(), [this](Result &result) { + return isExactMatch(result.replacement->replacement); + }); + + auto result = std::vector(); + result.reserve(_result.size()); + for (auto &item : _result) { + result.emplace_back(item.replacement->emoji, item.replacement->replacement, item.replacement->replacement); + } + return result; +} + +string_span Completer::findWordsStartingWith(utf16char ch) { + auto begin = std::lower_bound(_currentItemWords.begin(), _currentItemWords.end(), ch, [](utf16string word, utf16char ch) { + return word[0] < ch; + }); + auto end = std::upper_bound(_currentItemWords.begin(), _currentItemWords.end(), ch, [](utf16char ch, utf16string word) { + return ch < word[0]; + }); + return _currentItemWords.subspan(begin - _currentItemWords.begin(), end - begin); +} + +} // namespace + +std::vector GetSuggestions(utf16string query) { + return Completer(query).resolve(); +} + +int GetSuggestionMaxLength() { + return internal::kReplacementMaxLength; +} + +} // namespace Emoji +} // namespace Ui diff --git a/TelegramClient.Native/emoji_suggestions.h b/TelegramClient.Native/emoji_suggestions.h new file mode 100755 index 0000000..7e2d577 --- /dev/null +++ b/TelegramClient.Native/emoji_suggestions.h @@ -0,0 +1,107 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include + +namespace Ui { +namespace Emoji { + +using small = unsigned char; +using medium = unsigned short; +using utf16char = unsigned short; + +static_assert(sizeof(utf16char) == 2, "Bad UTF-16 character size."); + +class utf16string { +public: + utf16string() = default; + utf16string(const utf16char *data, std::size_t size) : data_(data), size_(size) { + } + utf16string(const utf16string &other) = default; + utf16string &operator=(const utf16string &other) = default; + + const utf16char *data() const { + return data_; + } + std::size_t size() const { + return size_; + } + + utf16char operator[](int index) const { + return data_[index]; + } + +private: + const utf16char *data_ = nullptr; + std::size_t size_ = 0; + +}; + +inline bool operator==(utf16string a, utf16string b) { + return (a.size() == b.size()) && (!a.size() || !memcmp(a.data(), b.data(), a.size() * sizeof(utf16char))); +} + +namespace internal { + +using checksum = unsigned int; +checksum countChecksum(const void *data, std::size_t size); + +utf16string GetReplacementEmoji(utf16string replacement); + +} // namespace internal + +class Suggestion { +public: + Suggestion() = default; + Suggestion(utf16string emoji, utf16string label, utf16string replacement) : emoji_(emoji), label_(label), replacement_(replacement) { + } + Suggestion(const Suggestion &other) = default; + Suggestion &operator=(const Suggestion &other) = default; + + utf16string emoji() const { + return emoji_; + } + utf16string label() const { + return label_; + } + utf16string replacement() const { + return replacement_; + } + +private: + utf16string emoji_; + utf16string label_; + utf16string replacement_; + +}; + +std::vector GetSuggestions(utf16string query); + +inline utf16string GetSuggestionEmoji(utf16string replacement) { + return internal::GetReplacementEmoji(replacement); +} + +int GetSuggestionMaxLength(); + + +} // namespace Emoji +} // namespace Ui diff --git a/TelegramClient.Native/emoji_suggestions_data.cpp b/TelegramClient.Native/emoji_suggestions_data.cpp new file mode 100755 index 0000000..e0ddd49 --- /dev/null +++ b/TelegramClient.Native/emoji_suggestions_data.cpp @@ -0,0 +1,6367 @@ +/* +WARNING! All changes made in this file will be lost! +Created from 'empty' by 'codegen_emoji' + +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#include "emoji_suggestions_data.h" + +#include + +namespace Ui { +namespace Emoji { +namespace internal { +namespace { + +struct ReplacementStruct { + small emojiSize; + small replacementSize; + small wordsCount; +}; + +const utf16char ReplacementData[] = { +0xd83d, 0xde00, 0x3a, 0x67, 0x72, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x3a, +0x67, 0x72, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0xd83d, 0xde03, 0x3a, 0x73, +0x6d, 0x69, 0x6c, 0x65, 0x79, 0x3a, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x79, +0xd83d, 0xde04, 0x3a, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x3a, 0x73, 0x6d, 0x69, +0x6c, 0x65, 0xd83d, 0xde01, 0x3a, 0x67, 0x72, 0x69, 0x6e, 0x3a, 0x67, 0x72, +0x69, 0x6e, 0xd83d, 0xde06, 0x3a, 0x73, 0x61, 0x74, 0x69, 0x73, 0x66, 0x69, +0x65, 0x64, 0x3a, 0x73, 0x61, 0x74, 0x69, 0x73, 0x66, 0x69, 0x65, 0x64, +0xd83d, 0xde06, 0x3a, 0x6c, 0x61, 0x75, 0x67, 0x68, 0x69, 0x6e, 0x67, 0x3a, +0x6c, 0x61, 0x75, 0x67, 0x68, 0x69, 0x6e, 0x67, 0xd83d, 0xde05, 0x3a, 0x73, +0x77, 0x65, 0x61, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x3a, 0x73, +0x6d, 0x69, 0x6c, 0x65, 0x73, 0x77, 0x65, 0x61, 0x74, 0xd83d, 0xde02, 0x3a, +0x6a, 0x6f, 0x79, 0x3a, 0x6a, 0x6f, 0x79, 0xd83e, 0xdd23, 0x3a, 0x72, 0x6f, +0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x6e, 0x5f, 0x74, 0x68, 0x65, +0x5f, 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x5f, 0x6c, 0x61, 0x75, 0x67, 0x68, +0x69, 0x6e, 0x67, 0x3a, 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x6c, 0x61, 0x75, +0x67, 0x68, 0x69, 0x6e, 0x67, 0x6f, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x69, +0x6e, 0x67, 0x74, 0x68, 0x65, 0xd83e, 0xdd23, 0x3a, 0x72, 0x6f, 0x66, 0x6c, +0x3a, 0x72, 0x6f, 0x66, 0x6c, 0x263a, 0xfe0f, 0x3a, 0x72, 0x65, 0x6c, 0x61, +0x78, 0x65, 0x64, 0x3a, 0x72, 0x65, 0x6c, 0x61, 0x78, 0x65, 0x64, 0xd83d, +0xde0a, 0x3a, 0x62, 0x6c, 0x75, 0x73, 0x68, 0x3a, 0x62, 0x6c, 0x75, 0x73, +0x68, 0xd83d, 0xde07, 0x3a, 0x69, 0x6e, 0x6e, 0x6f, 0x63, 0x65, 0x6e, 0x74, +0x3a, 0x69, 0x6e, 0x6e, 0x6f, 0x63, 0x65, 0x6e, 0x74, 0xd83d, 0xde42, 0x3a, +0x73, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6c, 0x79, 0x5f, 0x73, 0x6d, 0x69, +0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, +0x63, 0x65, 0x73, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6c, 0x79, 0x73, 0x6d, +0x69, 0x6c, 0x69, 0x6e, 0x67, 0xd83d, 0xde42, 0x3a, 0x73, 0x6c, 0x69, 0x67, +0x68, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x3a, 0x73, 0x6c, 0x69, +0x67, 0x68, 0x74, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0xd83d, 0xde43, 0x3a, 0x75, +0x70, 0x73, 0x69, 0x64, 0x65, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x66, +0x61, 0x63, 0x65, 0x3a, 0x64, 0x6f, 0x77, 0x6e, 0x66, 0x61, 0x63, 0x65, +0x75, 0x70, 0x73, 0x69, 0x64, 0x65, 0xd83d, 0xde43, 0x3a, 0x75, 0x70, 0x73, +0x69, 0x64, 0x65, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x64, 0x6f, 0x77, +0x6e, 0x75, 0x70, 0x73, 0x69, 0x64, 0x65, 0xd83d, 0xde09, 0x3a, 0x77, 0x69, +0x6e, 0x6b, 0x3a, 0x77, 0x69, 0x6e, 0x6b, 0xd83d, 0xde0c, 0x3a, 0x72, 0x65, +0x6c, 0x69, 0x65, 0x76, 0x65, 0x64, 0x3a, 0x72, 0x65, 0x6c, 0x69, 0x65, +0x76, 0x65, 0x64, 0xd83d, 0xde0d, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x5f, +0x65, 0x79, 0x65, 0x73, 0x3a, 0x65, 0x79, 0x65, 0x73, 0x68, 0x65, 0x61, +0x72, 0x74, 0xd83d, 0xde18, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, +0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, +0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0xd83d, 0xde17, 0x3a, 0x6b, 0x69, +0x73, 0x73, 0x69, 0x6e, 0x67, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, +0x67, 0xd83d, 0xde19, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, +0x73, 0x6d, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x79, 0x65, 0x73, +0x3a, 0x65, 0x79, 0x65, 0x73, 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, +0x73, 0x6d, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0xd83d, 0xde1a, 0x3a, 0x6b, 0x69, +0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, +0x5f, 0x65, 0x79, 0x65, 0x73, 0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, +0x65, 0x79, 0x65, 0x73, 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0xd83d, +0xde0b, 0x3a, 0x79, 0x75, 0x6d, 0x3a, 0x79, 0x75, 0x6d, 0xd83d, 0xde1c, 0x3a, +0x73, 0x74, 0x75, 0x63, 0x6b, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x74, 0x6f, +0x6e, 0x67, 0x75, 0x65, 0x5f, 0x77, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, +0x5f, 0x65, 0x79, 0x65, 0x3a, 0x65, 0x79, 0x65, 0x6f, 0x75, 0x74, 0x73, +0x74, 0x75, 0x63, 0x6b, 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x77, 0x69, +0x6e, 0x6b, 0x69, 0x6e, 0x67, 0xd83d, 0xde1d, 0x3a, 0x73, 0x74, 0x75, 0x63, +0x6b, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, +0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x65, 0x79, 0x65, 0x73, +0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x65, 0x79, 0x65, 0x73, 0x6f, +0x75, 0x74, 0x73, 0x74, 0x75, 0x63, 0x6b, 0x74, 0x6f, 0x6e, 0x67, 0x75, +0x65, 0xd83d, 0xde1b, 0x3a, 0x73, 0x74, 0x75, 0x63, 0x6b, 0x5f, 0x6f, 0x75, +0x74, 0x5f, 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x3a, 0x6f, 0x75, 0x74, +0x73, 0x74, 0x75, 0x63, 0x6b, 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0xd83e, +0xdd11, 0x3a, 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x75, 0x74, +0x68, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x6d, +0x6f, 0x6e, 0x65, 0x79, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0xd83e, 0xdd11, 0x3a, +0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x3a, +0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0xd83e, 0xdd17, +0x3a, 0x68, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, +0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x68, 0x75, 0x67, 0x67, 0x69, 0x6e, +0x67, 0xd83e, 0xdd17, 0x3a, 0x68, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x3a, +0x68, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0xd83e, 0xdd13, 0x3a, 0x6e, 0x65, +0x72, 0x64, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, +0x6e, 0x65, 0x72, 0x64, 0xd83e, 0xdd13, 0x3a, 0x6e, 0x65, 0x72, 0x64, 0x3a, +0x6e, 0x65, 0x72, 0x64, 0xd83d, 0xde0e, 0x3a, 0x73, 0x75, 0x6e, 0x67, 0x6c, +0x61, 0x73, 0x73, 0x65, 0x73, 0x3a, 0x73, 0x75, 0x6e, 0x67, 0x6c, 0x61, +0x73, 0x73, 0x65, 0x73, 0xd83e, 0xdd21, 0x3a, 0x63, 0x6c, 0x6f, 0x77, 0x6e, +0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x63, 0x6c, 0x6f, 0x77, 0x6e, 0x66, +0x61, 0x63, 0x65, 0xd83e, 0xdd21, 0x3a, 0x63, 0x6c, 0x6f, 0x77, 0x6e, 0x3a, +0x63, 0x6c, 0x6f, 0x77, 0x6e, 0xd83e, 0xdd20, 0x3a, 0x66, 0x61, 0x63, 0x65, +0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63, 0x6f, 0x77, 0x62, 0x6f, 0x79, +0x5f, 0x68, 0x61, 0x74, 0x3a, 0x63, 0x6f, 0x77, 0x62, 0x6f, 0x79, 0x66, +0x61, 0x63, 0x65, 0x68, 0x61, 0x74, 0x77, 0x69, 0x74, 0x68, 0xd83e, 0xdd20, +0x3a, 0x63, 0x6f, 0x77, 0x62, 0x6f, 0x79, 0x3a, 0x63, 0x6f, 0x77, 0x62, +0x6f, 0x79, 0xd83d, 0xde0f, 0x3a, 0x73, 0x6d, 0x69, 0x72, 0x6b, 0x3a, 0x73, +0x6d, 0x69, 0x72, 0x6b, 0xd83d, 0xde12, 0x3a, 0x75, 0x6e, 0x61, 0x6d, 0x75, +0x73, 0x65, 0x64, 0x3a, 0x75, 0x6e, 0x61, 0x6d, 0x75, 0x73, 0x65, 0x64, +0xd83d, 0xde1e, 0x3a, 0x64, 0x69, 0x73, 0x61, 0x70, 0x70, 0x6f, 0x69, 0x6e, +0x74, 0x65, 0x64, 0x3a, 0x64, 0x69, 0x73, 0x61, 0x70, 0x70, 0x6f, 0x69, +0x6e, 0x74, 0x65, 0x64, 0xd83d, 0xde14, 0x3a, 0x70, 0x65, 0x6e, 0x73, 0x69, +0x76, 0x65, 0x3a, 0x70, 0x65, 0x6e, 0x73, 0x69, 0x76, 0x65, 0xd83d, 0xde1f, +0x3a, 0x77, 0x6f, 0x72, 0x72, 0x69, 0x65, 0x64, 0x3a, 0x77, 0x6f, 0x72, +0x72, 0x69, 0x65, 0x64, 0xd83d, 0xde15, 0x3a, 0x63, 0x6f, 0x6e, 0x66, 0x75, +0x73, 0x65, 0x64, 0x3a, 0x63, 0x6f, 0x6e, 0x66, 0x75, 0x73, 0x65, 0x64, +0xd83d, 0xde41, 0x3a, 0x73, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6c, 0x79, 0x5f, +0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, +0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, +0x6e, 0x67, 0x73, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6c, 0x79, 0xd83d, 0xde41, +0x3a, 0x73, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x66, 0x72, 0x6f, 0x77, +0x6e, 0x3a, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x73, 0x6c, 0x69, 0x67, 0x68, +0x74, 0x2639, 0xfe0f, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x66, 0x72, +0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, +0x66, 0x61, 0x63, 0x65, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, +0x77, 0x68, 0x69, 0x74, 0x65, 0x2639, 0xfe0f, 0x3a, 0x66, 0x72, 0x6f, 0x77, +0x6e, 0x69, 0x6e, 0x67, 0x32, 0x3a, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, +0x6e, 0x67, 0x32, 0xd83d, 0xde23, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x65, 0x76, +0x65, 0x72, 0x65, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x65, 0x76, 0x65, 0x72, +0x65, 0xd83d, 0xde16, 0x3a, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x75, 0x6e, 0x64, +0x65, 0x64, 0x3a, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x65, +0x64, 0xd83d, 0xde2b, 0x3a, 0x74, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x66, 0x61, +0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x74, 0x69, 0x72, 0x65, 0x64, +0xd83d, 0xde29, 0x3a, 0x77, 0x65, 0x61, 0x72, 0x79, 0x3a, 0x77, 0x65, 0x61, +0x72, 0x79, 0xd83d, 0xde24, 0x3a, 0x74, 0x72, 0x69, 0x75, 0x6d, 0x70, 0x68, +0x3a, 0x74, 0x72, 0x69, 0x75, 0x6d, 0x70, 0x68, 0xd83d, 0xde20, 0x3a, 0x61, +0x6e, 0x67, 0x72, 0x79, 0x3a, 0x61, 0x6e, 0x67, 0x72, 0x79, 0xd83d, 0xde21, +0x3a, 0x72, 0x61, 0x67, 0x65, 0x3a, 0x72, 0x61, 0x67, 0x65, 0xd83d, 0xde36, +0x3a, 0x6e, 0x6f, 0x5f, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x3a, 0x6d, 0x6f, +0x75, 0x74, 0x68, 0x6e, 0x6f, 0xd83d, 0xde10, 0x3a, 0x6e, 0x65, 0x75, 0x74, +0x72, 0x61, 0x6c, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, +0x65, 0x6e, 0x65, 0x75, 0x74, 0x72, 0x61, 0x6c, 0xd83d, 0xde11, 0x3a, 0x65, +0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x6c, 0x65, 0x73, +0x73, 0x3a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, +0x6c, 0x65, 0x73, 0x73, 0xd83d, 0xde2f, 0x3a, 0x68, 0x75, 0x73, 0x68, 0x65, +0x64, 0x3a, 0x68, 0x75, 0x73, 0x68, 0x65, 0x64, 0xd83d, 0xde26, 0x3a, 0x66, +0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x66, 0x72, 0x6f, 0x77, +0x6e, 0x69, 0x6e, 0x67, 0xd83d, 0xde27, 0x3a, 0x61, 0x6e, 0x67, 0x75, 0x69, +0x73, 0x68, 0x65, 0x64, 0x3a, 0x61, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, +0x65, 0x64, 0xd83d, 0xde2e, 0x3a, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x6d, 0x6f, +0x75, 0x74, 0x68, 0x3a, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x6f, 0x70, 0x65, +0x6e, 0xd83d, 0xde32, 0x3a, 0x61, 0x73, 0x74, 0x6f, 0x6e, 0x69, 0x73, 0x68, +0x65, 0x64, 0x3a, 0x61, 0x73, 0x74, 0x6f, 0x6e, 0x69, 0x73, 0x68, 0x65, +0x64, 0xd83d, 0xde35, 0x3a, 0x64, 0x69, 0x7a, 0x7a, 0x79, 0x5f, 0x66, 0x61, +0x63, 0x65, 0x3a, 0x64, 0x69, 0x7a, 0x7a, 0x79, 0x66, 0x61, 0x63, 0x65, +0xd83d, 0xde33, 0x3a, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x65, 0x64, 0x3a, 0x66, +0x6c, 0x75, 0x73, 0x68, 0x65, 0x64, 0xd83d, 0xde31, 0x3a, 0x73, 0x63, 0x72, +0x65, 0x61, 0x6d, 0x3a, 0x73, 0x63, 0x72, 0x65, 0x61, 0x6d, 0xd83d, 0xde28, +0x3a, 0x66, 0x65, 0x61, 0x72, 0x66, 0x75, 0x6c, 0x3a, 0x66, 0x65, 0x61, +0x72, 0x66, 0x75, 0x6c, 0xd83d, 0xde30, 0x3a, 0x63, 0x6f, 0x6c, 0x64, 0x5f, +0x73, 0x77, 0x65, 0x61, 0x74, 0x3a, 0x63, 0x6f, 0x6c, 0x64, 0x73, 0x77, +0x65, 0x61, 0x74, 0xd83d, 0xde22, 0x3a, 0x63, 0x72, 0x79, 0x3a, 0x63, 0x72, +0x79, 0xd83d, 0xde25, 0x3a, 0x64, 0x69, 0x73, 0x61, 0x70, 0x70, 0x6f, 0x69, +0x6e, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x6c, 0x69, 0x65, 0x76, 0x65, +0x64, 0x3a, 0x64, 0x69, 0x73, 0x61, 0x70, 0x70, 0x6f, 0x69, 0x6e, 0x74, +0x65, 0x64, 0x72, 0x65, 0x6c, 0x69, 0x65, 0x76, 0x65, 0x64, 0xd83e, 0xdd24, +0x3a, 0x64, 0x72, 0x6f, 0x6f, 0x6c, 0x3a, 0x64, 0x72, 0x6f, 0x6f, 0x6c, +0xd83e, 0xdd24, 0x3a, 0x64, 0x72, 0x6f, 0x6f, 0x6c, 0x69, 0x6e, 0x67, 0x5f, +0x66, 0x61, 0x63, 0x65, 0x3a, 0x64, 0x72, 0x6f, 0x6f, 0x6c, 0x69, 0x6e, +0x67, 0x66, 0x61, 0x63, 0x65, 0xd83d, 0xde2d, 0x3a, 0x73, 0x6f, 0x62, 0x3a, +0x73, 0x6f, 0x62, 0xd83d, 0xde13, 0x3a, 0x73, 0x77, 0x65, 0x61, 0x74, 0x3a, +0x73, 0x77, 0x65, 0x61, 0x74, 0xd83d, 0xde2a, 0x3a, 0x73, 0x6c, 0x65, 0x65, +0x70, 0x79, 0x3a, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x79, 0xd83d, 0xde34, 0x3a, +0x73, 0x6c, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x3a, 0x73, 0x6c, 0x65, +0x65, 0x70, 0x69, 0x6e, 0x67, 0xd83d, 0xde44, 0x3a, 0x66, 0x61, 0x63, 0x65, +0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x72, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, +0x67, 0x5f, 0x65, 0x79, 0x65, 0x73, 0x3a, 0x65, 0x79, 0x65, 0x73, 0x66, +0x61, 0x63, 0x65, 0x72, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x77, 0x69, +0x74, 0x68, 0xd83d, 0xde44, 0x3a, 0x72, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, +0x5f, 0x65, 0x79, 0x65, 0x73, 0x3a, 0x65, 0x79, 0x65, 0x73, 0x72, 0x6f, +0x6c, 0x6c, 0x69, 0x6e, 0x67, 0xd83e, 0xdd14, 0x3a, 0x68, 0x6d, 0x6d, 0x3a, +0x68, 0x6d, 0x6d, 0xd83e, 0xdd14, 0x3a, 0x74, 0x68, 0x69, 0x6e, 0x6b, 0x69, +0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, +0x74, 0x68, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0xd83e, 0xdd14, 0x3a, 0x74, +0x68, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x74, 0x68, 0x69, 0x6e, +0x6b, 0x69, 0x6e, 0x67, 0xd83e, 0xdd25, 0x3a, 0x6c, 0x69, 0x61, 0x72, 0x3a, +0x6c, 0x69, 0x61, 0x72, 0xd83e, 0xdd25, 0x3a, 0x6c, 0x79, 0x69, 0x6e, 0x67, +0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x6c, 0x79, +0x69, 0x6e, 0x67, 0xd83d, 0xde2c, 0x3a, 0x67, 0x72, 0x69, 0x6d, 0x61, 0x63, +0x69, 0x6e, 0x67, 0x3a, 0x67, 0x72, 0x69, 0x6d, 0x61, 0x63, 0x69, 0x6e, +0x67, 0xd83e, 0xdd10, 0x3a, 0x7a, 0x69, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x6d, +0x6f, 0x75, 0x74, 0x68, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, +0x63, 0x65, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x7a, 0x69, 0x70, 0x70, 0x65, +0x72, 0xd83e, 0xdd10, 0x3a, 0x7a, 0x69, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x6d, +0x6f, 0x75, 0x74, 0x68, 0x3a, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x7a, 0x69, +0x70, 0x70, 0x65, 0x72, 0xd83e, 0xdd22, 0x3a, 0x73, 0x69, 0x63, 0x6b, 0x3a, +0x73, 0x69, 0x63, 0x6b, 0xd83e, 0xdd22, 0x3a, 0x6e, 0x61, 0x75, 0x73, 0x65, +0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, +0x63, 0x65, 0x6e, 0x61, 0x75, 0x73, 0x65, 0x61, 0x74, 0x65, 0x64, 0xd83e, +0xdd27, 0x3a, 0x73, 0x6e, 0x65, 0x65, 0x7a, 0x65, 0x3a, 0x73, 0x6e, 0x65, +0x65, 0x7a, 0x65, 0xd83e, 0xdd27, 0x3a, 0x73, 0x6e, 0x65, 0x65, 0x7a, 0x69, +0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, +0x73, 0x6e, 0x65, 0x65, 0x7a, 0x69, 0x6e, 0x67, 0xd83d, 0xde37, 0x3a, 0x6d, +0x61, 0x73, 0x6b, 0x3a, 0x6d, 0x61, 0x73, 0x6b, 0xd83e, 0xdd12, 0x3a, 0x66, +0x61, 0x63, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x74, 0x68, 0x65, +0x72, 0x6d, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x3a, 0x66, 0x61, 0x63, +0x65, 0x74, 0x68, 0x65, 0x72, 0x6d, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, +0x77, 0x69, 0x74, 0x68, 0xd83e, 0xdd12, 0x3a, 0x74, 0x68, 0x65, 0x72, 0x6d, +0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, +0x66, 0x61, 0x63, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6d, 0x6f, 0x6d, 0x65, +0x74, 0x65, 0x72, 0xd83e, 0xdd15, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x77, +0x69, 0x74, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x61, 0x6e, +0x64, 0x61, 0x67, 0x65, 0x3a, 0x62, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x65, +0x66, 0x61, 0x63, 0x65, 0x68, 0x65, 0x61, 0x64, 0x77, 0x69, 0x74, 0x68, +0xd83e, 0xdd15, 0x3a, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x61, 0x6e, 0x64, +0x61, 0x67, 0x65, 0x3a, 0x62, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x65, 0x68, +0x65, 0x61, 0x64, 0xd83d, 0xde08, 0x3a, 0x73, 0x6d, 0x69, 0x6c, 0x69, 0x6e, +0x67, 0x5f, 0x69, 0x6d, 0x70, 0x3a, 0x69, 0x6d, 0x70, 0x73, 0x6d, 0x69, +0x6c, 0x69, 0x6e, 0x67, 0xd83d, 0xdc7f, 0x3a, 0x69, 0x6d, 0x70, 0x3a, 0x69, +0x6d, 0x70, 0xd83d, 0xdc79, 0x3a, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x65, 0x73, +0x65, 0x5f, 0x6f, 0x67, 0x72, 0x65, 0x3a, 0x6a, 0x61, 0x70, 0x61, 0x6e, +0x65, 0x73, 0x65, 0x6f, 0x67, 0x72, 0x65, 0xd83d, 0xdc7a, 0x3a, 0x6a, 0x61, +0x70, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x62, 0x6c, 0x69, +0x6e, 0x3a, 0x67, 0x6f, 0x62, 0x6c, 0x69, 0x6e, 0x6a, 0x61, 0x70, 0x61, +0x6e, 0x65, 0x73, 0x65, 0xd83d, 0xdca9, 0x3a, 0x70, 0x6f, 0x6f, 0x3a, 0x70, +0x6f, 0x6f, 0xd83d, 0xdca9, 0x3a, 0x68, 0x61, 0x6e, 0x6b, 0x65, 0x79, 0x3a, +0x68, 0x61, 0x6e, 0x6b, 0x65, 0x79, 0xd83d, 0xdca9, 0x3a, 0x73, 0x68, 0x69, +0x74, 0x3a, 0x73, 0x68, 0x69, 0x74, 0xd83d, 0xdca9, 0x3a, 0x70, 0x6f, 0x6f, +0x70, 0x3a, 0x70, 0x6f, 0x6f, 0x70, 0xd83d, 0xdc7b, 0x3a, 0x67, 0x68, 0x6f, +0x73, 0x74, 0x3a, 0x67, 0x68, 0x6f, 0x73, 0x74, 0xd83d, 0xdc80, 0x3a, 0x73, +0x6b, 0x65, 0x6c, 0x65, 0x74, 0x6f, 0x6e, 0x3a, 0x73, 0x6b, 0x65, 0x6c, +0x65, 0x74, 0x6f, 0x6e, 0xd83d, 0xdc80, 0x3a, 0x73, 0x6b, 0x75, 0x6c, 0x6c, +0x3a, 0x73, 0x6b, 0x75, 0x6c, 0x6c, 0x2620, 0xfe0f, 0x3a, 0x73, 0x6b, 0x75, +0x6c, 0x6c, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, +0x62, 0x6f, 0x6e, 0x65, 0x73, 0x3a, 0x61, 0x6e, 0x64, 0x63, 0x72, 0x6f, +0x73, 0x73, 0x62, 0x6f, 0x6e, 0x65, 0x73, 0x73, 0x6b, 0x75, 0x6c, 0x6c, +0x2620, 0xfe0f, 0x3a, 0x73, 0x6b, 0x75, 0x6c, 0x6c, 0x5f, 0x63, 0x72, 0x6f, +0x73, 0x73, 0x62, 0x6f, 0x6e, 0x65, 0x73, 0x3a, 0x63, 0x72, 0x6f, 0x73, +0x73, 0x62, 0x6f, 0x6e, 0x65, 0x73, 0x73, 0x6b, 0x75, 0x6c, 0x6c, 0xd83d, +0xdc7d, 0x3a, 0x61, 0x6c, 0x69, 0x65, 0x6e, 0x3a, 0x61, 0x6c, 0x69, 0x65, +0x6e, 0xd83d, 0xdc7e, 0x3a, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x6e, +0x76, 0x61, 0x64, 0x65, 0x72, 0x3a, 0x69, 0x6e, 0x76, 0x61, 0x64, 0x65, +0x72, 0x73, 0x70, 0x61, 0x63, 0x65, 0xd83e, 0xdd16, 0x3a, 0x72, 0x6f, 0x62, +0x6f, 0x74, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, +0x72, 0x6f, 0x62, 0x6f, 0x74, 0xd83e, 0xdd16, 0x3a, 0x72, 0x6f, 0x62, 0x6f, +0x74, 0x3a, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0xd83c, 0xdf83, 0x3a, 0x6a, 0x61, +0x63, 0x6b, 0x5f, 0x6f, 0x5f, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x72, 0x6e, +0x3a, 0x6a, 0x61, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x72, 0x6e, +0x6f, 0xd83d, 0xde3a, 0x3a, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x79, 0x5f, 0x63, +0x61, 0x74, 0x3a, 0x63, 0x61, 0x74, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x79, +0xd83d, 0xde38, 0x3a, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x74, +0x3a, 0x63, 0x61, 0x74, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0xd83d, 0xde39, 0x3a, +0x6a, 0x6f, 0x79, 0x5f, 0x63, 0x61, 0x74, 0x3a, 0x63, 0x61, 0x74, 0x6a, +0x6f, 0x79, 0xd83d, 0xde3b, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x5f, 0x65, +0x79, 0x65, 0x73, 0x5f, 0x63, 0x61, 0x74, 0x3a, 0x63, 0x61, 0x74, 0x65, +0x79, 0x65, 0x73, 0x68, 0x65, 0x61, 0x72, 0x74, 0xd83d, 0xde3c, 0x3a, 0x73, +0x6d, 0x69, 0x72, 0x6b, 0x5f, 0x63, 0x61, 0x74, 0x3a, 0x63, 0x61, 0x74, +0x73, 0x6d, 0x69, 0x72, 0x6b, 0xd83d, 0xde3d, 0x3a, 0x6b, 0x69, 0x73, 0x73, +0x69, 0x6e, 0x67, 0x5f, 0x63, 0x61, 0x74, 0x3a, 0x63, 0x61, 0x74, 0x6b, +0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0xd83d, 0xde40, 0x3a, 0x73, 0x63, 0x72, +0x65, 0x61, 0x6d, 0x5f, 0x63, 0x61, 0x74, 0x3a, 0x63, 0x61, 0x74, 0x73, +0x63, 0x72, 0x65, 0x61, 0x6d, 0xd83d, 0xde3f, 0x3a, 0x63, 0x72, 0x79, 0x69, +0x6e, 0x67, 0x5f, 0x63, 0x61, 0x74, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, +0x63, 0x61, 0x74, 0x63, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x66, 0x61, 0x63, +0x65, 0xd83d, 0xde3e, 0x3a, 0x70, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, +0x63, 0x61, 0x74, 0x3a, 0x63, 0x61, 0x74, 0x70, 0x6f, 0x75, 0x74, 0x69, +0x6e, 0x67, 0xd83d, 0xdc50, 0x3a, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x68, 0x61, +0x6e, 0x64, 0x73, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x6f, 0x70, 0x65, +0x6e, 0xd83d, 0xde4c, 0x3a, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x68, +0x61, 0x6e, 0x64, 0x73, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x72, 0x61, +0x69, 0x73, 0x65, 0x64, 0xd83d, 0xdc4f, 0x3a, 0x63, 0x6c, 0x61, 0x70, 0x3a, +0x63, 0x6c, 0x61, 0x70, 0xd83d, 0xde4f, 0x3a, 0x70, 0x72, 0x61, 0x79, 0x3a, +0x70, 0x72, 0x61, 0x79, 0xd83e, 0xdd1d, 0x3a, 0x73, 0x68, 0x61, 0x6b, 0x69, +0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x3a, 0x68, 0x61, 0x6e, +0x64, 0x73, 0x73, 0x68, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0xd83e, 0xdd1d, 0x3a, +0x68, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x3a, 0x68, 0x61, +0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0xd83d, 0xdc4d, 0x3a, 0x6c, 0x69, +0x6b, 0x65, 0x3a, 0x6c, 0x69, 0x6b, 0x65, 0xd83d, 0xdc4d, 0x3a, 0x74, 0x68, +0x75, 0x6d, 0x62, 0x75, 0x70, 0x3a, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x75, +0x70, 0xd83d, 0xdc4d, 0x3a, 0x2b, 0x31, 0x3a, 0x2b, 0x31, 0xd83d, 0xdc4d, 0x3a, +0x74, 0x68, 0x75, 0x6d, 0x62, 0x73, 0x75, 0x70, 0x3a, 0x74, 0x68, 0x75, +0x6d, 0x62, 0x73, 0x75, 0x70, 0xd83d, 0xdc4e, 0x3a, 0x64, 0x69, 0x73, 0x6c, +0x69, 0x6b, 0x65, 0x3a, 0x64, 0x69, 0x73, 0x6c, 0x69, 0x6b, 0x65, 0xd83d, +0xdc4e, 0x3a, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x64, 0x6f, 0x77, 0x6e, 0x3a, +0x74, 0x68, 0x75, 0x6d, 0x62, 0x64, 0x6f, 0x77, 0x6e, 0xd83d, 0xdc4e, 0x3a, +0x2d, 0x31, 0x3a, 0x2d, 0x31, 0xd83d, 0xdc4e, 0x3a, 0x74, 0x68, 0x75, 0x6d, +0x62, 0x73, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x74, 0x68, 0x75, 0x6d, 0x62, +0x73, 0x64, 0x6f, 0x77, 0x6e, 0xd83d, 0xdc4a, 0x3a, 0x70, 0x75, 0x6e, 0x63, +0x68, 0x3a, 0x70, 0x75, 0x6e, 0x63, 0x68, 0x270a, 0xfe0f, 0x3a, 0x66, 0x69, +0x73, 0x74, 0x3a, 0x66, 0x69, 0x73, 0x74, 0xd83e, 0xdd1b, 0x3a, 0x6c, 0x65, +0x66, 0x74, 0x5f, 0x66, 0x69, 0x73, 0x74, 0x3a, 0x66, 0x69, 0x73, 0x74, +0x6c, 0x65, 0x66, 0x74, 0xd83e, 0xdd1b, 0x3a, 0x6c, 0x65, 0x66, 0x74, 0x5f, +0x66, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x73, 0x74, 0x3a, +0x66, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x66, 0x69, 0x73, 0x74, 0x6c, 0x65, +0x66, 0x74, 0xd83e, 0xdd1c, 0x3a, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x66, +0x69, 0x73, 0x74, 0x3a, 0x66, 0x69, 0x73, 0x74, 0x72, 0x69, 0x67, 0x68, +0x74, 0xd83e, 0xdd1c, 0x3a, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x66, 0x61, +0x63, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x73, 0x74, 0x3a, 0x66, 0x61, +0x63, 0x69, 0x6e, 0x67, 0x66, 0x69, 0x73, 0x74, 0x72, 0x69, 0x67, 0x68, +0x74, 0xd83e, 0xdd1e, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x5f, 0x77, 0x69, 0x74, +0x68, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x61, 0x6e, 0x64, 0x5f, +0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, +0x72, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x64, 0x3a, 0x61, 0x6e, +0x64, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x64, 0x66, 0x69, 0x6e, 0x67, +0x65, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x6d, +0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x69, 0x74, 0x68, 0xd83e, 0xdd1e, 0x3a, +0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x5f, 0x63, 0x72, 0x6f, 0x73, +0x73, 0x65, 0x64, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x64, 0x66, +0x69, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x270c, 0xfe0f, 0x3a, 0x76, 0x3a, 0x76, +0xd83e, 0xdd18, 0x3a, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x6f, 0x66, 0x5f, 0x74, +0x68, 0x65, 0x5f, 0x68, 0x6f, 0x72, 0x6e, 0x73, 0x3a, 0x68, 0x6f, 0x72, +0x6e, 0x73, 0x6f, 0x66, 0x73, 0x69, 0x67, 0x6e, 0x74, 0x68, 0x65, 0xd83e, +0xdd18, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3a, 0x6d, 0x65, 0x74, 0x61, +0x6c, 0xd83d, 0xdc4c, 0x3a, 0x6f, 0x6b, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x3a, +0x68, 0x61, 0x6e, 0x64, 0x6f, 0x6b, 0xd83d, 0xdc48, 0x3a, 0x70, 0x6f, 0x69, +0x6e, 0x74, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x6c, 0x65, 0x66, 0x74, +0x70, 0x6f, 0x69, 0x6e, 0x74, 0xd83d, 0xdc49, 0x3a, 0x70, 0x6f, 0x69, 0x6e, +0x74, 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x70, 0x6f, 0x69, 0x6e, +0x74, 0x72, 0x69, 0x67, 0x68, 0x74, 0xd83d, 0xdc46, 0x3a, 0x70, 0x6f, 0x69, +0x6e, 0x74, 0x5f, 0x75, 0x70, 0x5f, 0x32, 0x3a, 0x32, 0x70, 0x6f, 0x69, +0x6e, 0x74, 0x75, 0x70, 0xd83d, 0xdc47, 0x3a, 0x70, 0x6f, 0x69, 0x6e, 0x74, +0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x64, 0x6f, 0x77, 0x6e, 0x70, 0x6f, +0x69, 0x6e, 0x74, 0x261d, 0xfe0f, 0x3a, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, +0x75, 0x70, 0x3a, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x75, 0x70, 0x270b, 0xfe0f, +0x3a, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x68, 0x61, 0x6e, 0x64, +0x3a, 0x68, 0x61, 0x6e, 0x64, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0xd83e, +0xdd1a, 0x3a, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x6f, 0x66, 0x5f, 0x68, 0x61, +0x6e, 0x64, 0x3a, 0x62, 0x61, 0x63, 0x6b, 0x68, 0x61, 0x6e, 0x64, 0x6f, +0x66, 0xd83e, 0xdd1a, 0x3a, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x62, +0x61, 0x63, 0x6b, 0x5f, 0x6f, 0x66, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x3a, +0x62, 0x61, 0x63, 0x6b, 0x68, 0x61, 0x6e, 0x64, 0x6f, 0x66, 0x72, 0x61, +0x69, 0x73, 0x65, 0x64, 0xd83d, 0xdd90, 0x3a, 0x72, 0x61, 0x69, 0x73, 0x65, +0x64, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, +0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x5f, 0x73, 0x70, 0x6c, 0x61, +0x79, 0x65, 0x64, 0x3a, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x68, +0x61, 0x6e, 0x64, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x73, 0x70, 0x6c, +0x61, 0x79, 0x65, 0x64, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdd90, 0x3a, 0x68, +0x61, 0x6e, 0x64, 0x5f, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, 0x3a, +0x68, 0x61, 0x6e, 0x64, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, 0xd83d, +0xdd96, 0x3a, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x68, 0x61, 0x6e, +0x64, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x5f, +0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x5f, 0x6d, 0x69, 0x64, 0x64, +0x6c, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, +0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x3a, 0x61, 0x6e, 0x64, 0x62, +0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, +0x73, 0x68, 0x61, 0x6e, 0x64, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x70, +0x61, 0x72, 0x74, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x72, 0x69, 0x6e, +0x67, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdd96, 0x3a, 0x76, 0x75, 0x6c, 0x63, +0x61, 0x6e, 0x3a, 0x76, 0x75, 0x6c, 0x63, 0x61, 0x6e, 0xd83d, 0xdc4b, 0x3a, +0x77, 0x61, 0x76, 0x65, 0x3a, 0x77, 0x61, 0x76, 0x65, 0xd83e, 0xdd19, 0x3a, +0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x6e, 0x64, +0x3a, 0x63, 0x61, 0x6c, 0x6c, 0x68, 0x61, 0x6e, 0x64, 0x6d, 0x65, 0xd83e, +0xdd19, 0x3a, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x3a, 0x63, 0x61, +0x6c, 0x6c, 0x6d, 0x65, 0xd83d, 0xdcaa, 0x3a, 0x6d, 0x75, 0x73, 0x63, 0x6c, +0x65, 0x3a, 0x6d, 0x75, 0x73, 0x63, 0x6c, 0x65, 0xd83d, 0xdd95, 0x3a, 0x72, +0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x64, 0x5f, 0x68, 0x61, 0x6e, 0x64, +0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, +0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x65, 0x78, 0x74, 0x65, +0x6e, 0x64, 0x65, 0x64, 0x3a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, +0x64, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x6d, +0x69, 0x64, 0x64, 0x6c, 0x65, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, +0x64, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdd95, 0x3a, 0x6d, 0x69, 0x64, 0x64, +0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x3a, 0x66, 0x69, +0x6e, 0x67, 0x65, 0x72, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x270d, 0xfe0f, +0x3a, 0x77, 0x72, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, +0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x77, 0x72, 0x69, 0x74, 0x69, 0x6e, +0x67, 0xd83e, 0xdd33, 0x3a, 0x73, 0x65, 0x6c, 0x66, 0x69, 0x65, 0x3a, 0x73, +0x65, 0x6c, 0x66, 0x69, 0x65, 0xd83d, 0xdc85, 0x3a, 0x6e, 0x61, 0x69, 0x6c, +0x5f, 0x63, 0x61, 0x72, 0x65, 0x3a, 0x63, 0x61, 0x72, 0x65, 0x6e, 0x61, +0x69, 0x6c, 0xd83d, 0xdc8d, 0x3a, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x72, 0x69, +0x6e, 0x67, 0xd83d, 0xdc84, 0x3a, 0x6c, 0x69, 0x70, 0x73, 0x74, 0x69, 0x63, +0x6b, 0x3a, 0x6c, 0x69, 0x70, 0x73, 0x74, 0x69, 0x63, 0x6b, 0xd83d, 0xdc8b, +0x3a, 0x6b, 0x69, 0x73, 0x73, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0xd83d, 0xdc44, +0x3a, 0x6c, 0x69, 0x70, 0x73, 0x3a, 0x6c, 0x69, 0x70, 0x73, 0xd83d, 0xdc45, +0x3a, 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x3a, 0x74, 0x6f, 0x6e, 0x67, +0x75, 0x65, 0xd83d, 0xdc42, 0x3a, 0x65, 0x61, 0x72, 0x3a, 0x65, 0x61, 0x72, +0xd83d, 0xdc43, 0x3a, 0x6e, 0x6f, 0x73, 0x65, 0x3a, 0x6e, 0x6f, 0x73, 0x65, +0xd83d, 0xdc63, 0x3a, 0x66, 0x6f, 0x6f, 0x74, 0x70, 0x72, 0x69, 0x6e, 0x74, +0x73, 0x3a, 0x66, 0x6f, 0x6f, 0x74, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, +0xd83d, 0xdc41, 0x3a, 0x65, 0x79, 0x65, 0x3a, 0x65, 0x79, 0x65, 0xd83d, 0xdc40, +0x3a, 0x65, 0x79, 0x65, 0x73, 0x3a, 0x65, 0x79, 0x65, 0x73, 0xd83d, 0xdde3, +0x3a, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, +0x61, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x6c, 0x68, 0x6f, 0x75, +0x65, 0x74, 0x74, 0x65, 0x3a, 0x68, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x73, +0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x70, 0x65, +0x61, 0x6b, 0x69, 0x6e, 0x67, 0xd83d, 0xdde3, 0x3a, 0x73, 0x70, 0x65, 0x61, +0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x3a, 0x68, 0x65, +0x61, 0x64, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0xd83d, 0xdc64, +0x3a, 0x62, 0x75, 0x73, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x6c, +0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x3a, 0x62, 0x75, 0x73, 0x74, +0x69, 0x6e, 0x73, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, +0xd83d, 0xdc65, 0x3a, 0x62, 0x75, 0x73, 0x74, 0x73, 0x5f, 0x69, 0x6e, 0x5f, +0x73, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x3a, 0x62, +0x75, 0x73, 0x74, 0x73, 0x69, 0x6e, 0x73, 0x69, 0x6c, 0x68, 0x6f, 0x75, +0x65, 0x74, 0x74, 0x65, 0xd83d, 0xdc76, 0x3a, 0x62, 0x61, 0x62, 0x79, 0x3a, +0x62, 0x61, 0x62, 0x79, 0xd83d, 0xdc66, 0x3a, 0x62, 0x6f, 0x79, 0x3a, 0x62, +0x6f, 0x79, 0xd83d, 0xdc67, 0x3a, 0x67, 0x69, 0x72, 0x6c, 0x3a, 0x67, 0x69, +0x72, 0x6c, 0xd83d, 0xdc68, 0x3a, 0x6d, 0x61, 0x6e, 0x3a, 0x6d, 0x61, 0x6e, +0xd83d, 0xdc69, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x3a, 0x77, 0x6f, 0x6d, +0x61, 0x6e, 0xd83d, 0xdc71, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x62, 0x6c, 0x6f, 0x6e, +0x64, 0x2d, 0x68, 0x61, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x77, 0x6f, 0x6d, +0x61, 0x6e, 0x3a, 0x62, 0x6c, 0x6f, 0x6e, 0x64, 0x68, 0x61, 0x69, 0x72, +0x65, 0x64, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc71, 0x3a, 0x62, 0x6c, +0x6f, 0x6e, 0x64, 0x2d, 0x68, 0x61, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x6d, +0x61, 0x6e, 0x3a, 0x62, 0x6c, 0x6f, 0x6e, 0x64, 0x68, 0x61, 0x69, 0x72, +0x65, 0x64, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc71, 0x3a, 0x70, 0x65, 0x72, 0x73, +0x6f, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x62, 0x6c, 0x6f, 0x6e, +0x64, 0x5f, 0x68, 0x61, 0x69, 0x72, 0x3a, 0x62, 0x6c, 0x6f, 0x6e, 0x64, +0x68, 0x61, 0x69, 0x72, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x77, 0x69, +0x74, 0x68, 0xd83d, 0xdc71, 0x3a, 0x62, 0x6c, 0x6f, 0x6e, 0x64, 0x5f, 0x68, +0x61, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, +0x3a, 0x62, 0x6c, 0x6f, 0x6e, 0x64, 0x68, 0x61, 0x69, 0x72, 0x65, 0x64, +0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83d, 0xdc74, 0x3a, 0x6f, 0x6c, 0x64, +0x65, 0x72, 0x5f, 0x6d, 0x61, 0x6e, 0x3a, 0x6d, 0x61, 0x6e, 0x6f, 0x6c, +0x64, 0x65, 0x72, 0xd83d, 0xdc75, 0x3a, 0x67, 0x72, 0x61, 0x6e, 0x64, 0x6d, +0x61, 0x3a, 0x67, 0x72, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0xd83d, 0xdc75, 0x3a, +0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x3a, +0x6f, 0x6c, 0x64, 0x65, 0x72, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc72, +0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x67, 0x75, +0x61, 0x5f, 0x70, 0x69, 0x5f, 0x6d, 0x61, 0x6f, 0x3a, 0x67, 0x75, 0x61, +0x6d, 0x61, 0x6e, 0x6d, 0x61, 0x6f, 0x70, 0x69, 0x77, 0x69, 0x74, 0x68, +0xd83d, 0xdc72, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, +0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x65, 0x5f, 0x63, 0x61, 0x70, 0x3a, +0x63, 0x61, 0x70, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x65, 0x6d, 0x61, +0x6e, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdc73, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x77, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, +0x5f, 0x74, 0x75, 0x72, 0x62, 0x61, 0x6e, 0x3a, 0x74, 0x75, 0x72, 0x62, +0x61, 0x6e, 0x77, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, +0x61, 0x6e, 0xd83d, 0xdc73, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x77, 0x65, 0x61, +0x72, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x75, 0x72, 0x62, 0x61, 0x6e, 0x3a, +0x6d, 0x61, 0x6e, 0x74, 0x75, 0x72, 0x62, 0x61, 0x6e, 0x77, 0x65, 0x61, +0x72, 0x69, 0x6e, 0x67, 0xd83d, 0xdc73, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x77, +0x69, 0x74, 0x68, 0x5f, 0x74, 0x75, 0x72, 0x62, 0x61, 0x6e, 0x3a, 0x6d, +0x61, 0x6e, 0x74, 0x75, 0x72, 0x62, 0x61, 0x6e, 0x77, 0x69, 0x74, 0x68, +0xd83d, 0xdc73, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x77, 0x65, +0x61, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x75, 0x72, 0x62, 0x61, 0x6e, +0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x74, 0x75, 0x72, 0x62, 0x61, +0x6e, 0x77, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0xd83d, 0xdc6e, 0x200d, 0x2640, +0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x69, +0x63, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x72, 0x3a, 0x6f, +0x66, 0x66, 0x69, 0x63, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x65, +0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc6e, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, +0x70, 0x6f, 0x6c, 0x69, 0x63, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x69, 0x63, +0x65, 0x72, 0x3a, 0x6d, 0x61, 0x6e, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, +0x72, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x65, 0xd83d, 0xdc6e, 0x3a, 0x63, 0x6f, +0x70, 0x3a, 0x63, 0x6f, 0x70, 0xd83d, 0xdc6e, 0x3a, 0x70, 0x6f, 0x6c, 0x69, +0x63, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x72, 0x3a, 0x6f, +0x66, 0x66, 0x69, 0x63, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x65, +0xd83d, 0xdc77, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, +0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, +0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x3a, 0x63, 0x6f, 0x6e, 0x73, +0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc77, 0x3a, 0x6d, 0x61, +0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, +0x6f, 0x6e, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x3a, 0x63, 0x6f, +0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x61, +0x6e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc77, 0x3a, 0x63, 0x6f, +0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, +0x6f, 0x72, 0x6b, 0x65, 0x72, 0x3a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, +0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, +0xd83d, 0xdc82, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, +0x67, 0x75, 0x61, 0x72, 0x64, 0x3a, 0x67, 0x75, 0x61, 0x72, 0x64, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc82, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x67, +0x75, 0x61, 0x72, 0x64, 0x3a, 0x67, 0x75, 0x61, 0x72, 0x64, 0x6d, 0x61, +0x6e, 0xd83d, 0xdc82, 0x3a, 0x67, 0x75, 0x61, 0x72, 0x64, 0x73, 0x6d, 0x61, +0x6e, 0x3a, 0x67, 0x75, 0x61, 0x72, 0x64, 0x73, 0x6d, 0x61, 0x6e, 0xd83d, +0xdc82, 0x3a, 0x67, 0x75, 0x61, 0x72, 0x64, 0x3a, 0x67, 0x75, 0x61, 0x72, +0x64, 0xd83d, 0xdd75, 0xfe0f, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x3a, +0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x77, 0x6f, 0x6d, +0x61, 0x6e, 0xd83d, 0xdd75, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x64, 0x65, +0x74, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x3a, 0x64, 0x65, 0x74, 0x65, +0x63, 0x74, 0x69, 0x76, 0x65, 0x6d, 0x61, 0x6e, 0xd83d, 0xdd75, 0xfe0f, 0x3a, +0x73, 0x6c, 0x65, 0x75, 0x74, 0x68, 0x5f, 0x6f, 0x72, 0x5f, 0x73, 0x70, +0x79, 0x3a, 0x6f, 0x72, 0x73, 0x6c, 0x65, 0x75, 0x74, 0x68, 0x73, 0x70, +0x79, 0xd83d, 0xdd75, 0xfe0f, 0x3a, 0x73, 0x70, 0x79, 0x3a, 0x73, 0x70, 0x79, +0xd83d, 0xdd75, 0xfe0f, 0x3a, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x76, +0x65, 0x3a, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0xd83d, +0xdc69, 0x200d, 0x2695, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x68, +0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, +0x3a, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x77, 0x6f, 0x6d, 0x61, 0x6e, +0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc68, 0x200d, 0x2695, 0xfe0f, 0x3a, +0x6d, 0x61, 0x6e, 0x5f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x77, +0x6f, 0x72, 0x6b, 0x65, 0x72, 0x3a, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, +0x6d, 0x61, 0x6e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc69, 0x200d, +0xd83c, 0xdf3e, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x61, 0x72, +0x6d, 0x65, 0x72, 0x3a, 0x66, 0x61, 0x72, 0x6d, 0x65, 0x72, 0x77, 0x6f, +0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83c, 0xdf3e, 0x3a, 0x6d, 0x61, 0x6e, +0x5f, 0x66, 0x61, 0x72, 0x6d, 0x65, 0x72, 0x3a, 0x66, 0x61, 0x72, 0x6d, +0x65, 0x72, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0xd83c, 0xdf73, 0x3a, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x3a, 0x63, 0x6f, +0x6f, 0x6b, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83c, 0xdf73, +0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x3a, 0x63, 0x6f, +0x6f, 0x6b, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0xd83c, 0xdf93, 0x3a, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, +0x3a, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83c, 0xdf93, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x73, +0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x3a, 0x6d, 0x61, 0x6e, 0x73, 0x74, +0x75, 0x64, 0x65, 0x6e, 0x74, 0xd83d, 0xdc69, 0x200d, 0xd83c, 0xdfa4, 0x3a, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x3a, +0x73, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, +0xdc68, 0x200d, 0xd83c, 0xdfa4, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x69, 0x6e, +0x67, 0x65, 0x72, 0x3a, 0x6d, 0x61, 0x6e, 0x73, 0x69, 0x6e, 0x67, 0x65, +0x72, 0xd83d, 0xdc69, 0x200d, 0xd83c, 0xdfeb, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, +0x5f, 0x74, 0x65, 0x61, 0x63, 0x68, 0x65, 0x72, 0x3a, 0x74, 0x65, 0x61, +0x63, 0x68, 0x65, 0x72, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, +0xd83c, 0xdfeb, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x74, 0x65, 0x61, 0x63, 0x68, +0x65, 0x72, 0x3a, 0x6d, 0x61, 0x6e, 0x74, 0x65, 0x61, 0x63, 0x68, 0x65, +0x72, 0xd83d, 0xdc69, 0x200d, 0xd83c, 0xdfed, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, +0x5f, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x77, 0x6f, 0x72, +0x6b, 0x65, 0x72, 0x3a, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc68, +0x200d, 0xd83c, 0xdfed, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x61, 0x63, 0x74, +0x6f, 0x72, 0x79, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x3a, 0x66, +0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x6d, 0x61, 0x6e, 0x77, 0x6f, 0x72, +0x6b, 0x65, 0x72, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdcbb, 0x3a, 0x77, 0x6f, 0x6d, +0x61, 0x6e, 0x5f, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, +0x69, 0x73, 0x74, 0x3a, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, +0x67, 0x69, 0x73, 0x74, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, +0xd83d, 0xdcbb, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x74, 0x65, 0x63, 0x68, 0x6e, +0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x73, 0x74, 0x3a, 0x6d, 0x61, 0x6e, 0x74, +0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x73, 0x74, 0xd83d, +0xdc69, 0x200d, 0xd83d, 0xdcbc, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x6f, +0x66, 0x66, 0x69, 0x63, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, +0x3a, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x77, 0x6f, 0x6d, 0x61, 0x6e, +0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdcbc, 0x3a, +0x6d, 0x61, 0x6e, 0x5f, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x5f, 0x77, +0x6f, 0x72, 0x6b, 0x65, 0x72, 0x3a, 0x6d, 0x61, 0x6e, 0x6f, 0x66, 0x66, +0x69, 0x63, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc69, 0x200d, +0xd83d, 0xdd27, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x6d, 0x65, 0x63, +0x68, 0x61, 0x6e, 0x69, 0x63, 0x3a, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, +0x69, 0x63, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdd27, +0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, +0x63, 0x3a, 0x6d, 0x61, 0x6e, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, +0x63, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdd2c, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, +0x5f, 0x73, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x73, 0x74, 0x3a, 0x73, +0x63, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x73, 0x74, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdd2c, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x73, +0x63, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x73, 0x74, 0x3a, 0x6d, 0x61, 0x6e, +0x73, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x73, 0x74, 0xd83d, 0xdc69, 0x200d, +0xd83c, 0xdfa8, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x61, 0x72, 0x74, +0x69, 0x73, 0x74, 0x3a, 0x61, 0x72, 0x74, 0x69, 0x73, 0x74, 0x77, 0x6f, +0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83c, 0xdfa8, 0x3a, 0x6d, 0x61, 0x6e, +0x5f, 0x61, 0x72, 0x74, 0x69, 0x73, 0x74, 0x3a, 0x61, 0x72, 0x74, 0x69, +0x73, 0x74, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xde92, 0x3a, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x69, 0x72, 0x65, 0x66, 0x69, 0x67, +0x68, 0x74, 0x65, 0x72, 0x3a, 0x66, 0x69, 0x72, 0x65, 0x66, 0x69, 0x67, +0x68, 0x74, 0x65, 0x72, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, +0xd83d, 0xde92, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x69, 0x72, 0x65, 0x66, +0x69, 0x67, 0x68, 0x74, 0x65, 0x72, 0x3a, 0x66, 0x69, 0x72, 0x65, 0x66, +0x69, 0x67, 0x68, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, +0x2708, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x70, 0x69, 0x6c, +0x6f, 0x74, 0x3a, 0x70, 0x69, 0x6c, 0x6f, 0x74, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0xd83d, 0xdc68, 0x200d, 0x2708, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x70, +0x69, 0x6c, 0x6f, 0x74, 0x3a, 0x6d, 0x61, 0x6e, 0x70, 0x69, 0x6c, 0x6f, +0x74, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xde80, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, +0x5f, 0x61, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x61, 0x75, 0x74, 0x3a, 0x61, +0x73, 0x74, 0x72, 0x6f, 0x6e, 0x61, 0x75, 0x74, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xde80, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x61, +0x73, 0x74, 0x72, 0x6f, 0x6e, 0x61, 0x75, 0x74, 0x3a, 0x61, 0x73, 0x74, +0x72, 0x6f, 0x6e, 0x61, 0x75, 0x74, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, +0x2696, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x6a, 0x75, 0x64, +0x67, 0x65, 0x3a, 0x6a, 0x75, 0x64, 0x67, 0x65, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0xd83d, 0xdc68, 0x200d, 0x2696, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x6a, +0x75, 0x64, 0x67, 0x65, 0x3a, 0x6a, 0x75, 0x64, 0x67, 0x65, 0x6d, 0x61, +0x6e, 0xd83e, 0xdd36, 0x3a, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x63, +0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x3a, 0x63, 0x68, 0x72, +0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, +0xd83e, 0xdd36, 0x3a, 0x6d, 0x72, 0x73, 0x5f, 0x63, 0x6c, 0x61, 0x75, 0x73, +0x3a, 0x63, 0x6c, 0x61, 0x75, 0x73, 0x6d, 0x72, 0x73, 0xd83c, 0xdf85, 0x3a, +0x73, 0x61, 0x6e, 0x74, 0x61, 0x3a, 0x73, 0x61, 0x6e, 0x74, 0x61, 0xd83d, +0xdc78, 0x3a, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x73, 0x3a, 0x70, +0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x73, 0xd83e, 0xdd34, 0x3a, 0x70, 0x72, +0x69, 0x6e, 0x63, 0x65, 0x3a, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x65, 0xd83d, +0xdc70, 0x3a, 0x62, 0x72, 0x69, 0x64, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, +0x5f, 0x76, 0x65, 0x69, 0x6c, 0x3a, 0x62, 0x72, 0x69, 0x64, 0x65, 0x76, +0x65, 0x69, 0x6c, 0x77, 0x69, 0x74, 0x68, 0xd83e, 0xdd35, 0x3a, 0x6d, 0x61, +0x6e, 0x5f, 0x69, 0x6e, 0x5f, 0x74, 0x75, 0x78, 0x65, 0x64, 0x6f, 0x3a, +0x69, 0x6e, 0x6d, 0x61, 0x6e, 0x74, 0x75, 0x78, 0x65, 0x64, 0x6f, 0xd83d, +0xdc7c, 0x3a, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x3a, 0x61, 0x6e, 0x67, 0x65, +0x6c, 0xd83e, 0xdd30, 0x3a, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6e, +0x67, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x3a, 0x65, 0x78, 0x70, 0x65, +0x63, 0x74, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd30, +0x3a, 0x70, 0x72, 0x65, 0x67, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x77, 0x6f, +0x6d, 0x61, 0x6e, 0x3a, 0x70, 0x72, 0x65, 0x67, 0x6e, 0x61, 0x6e, 0x74, +0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xde47, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x62, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, +0x62, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, +0xde47, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x62, 0x6f, 0x77, 0x69, 0x6e, 0x67, +0x3a, 0x62, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0xd83d, 0xde47, +0x3a, 0x62, 0x6f, 0x77, 0x3a, 0x62, 0x6f, 0x77, 0xd83d, 0xde47, 0x3a, 0x70, +0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x62, 0x6f, 0x77, 0x69, 0x6e, 0x67, +0x3a, 0x62, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, +0x6e, 0xd83d, 0xdc81, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x74, 0x69, +0x70, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x3a, 0x68, +0x61, 0x6e, 0x64, 0x74, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x77, 0x6f, +0x6d, 0x61, 0x6e, 0xd83d, 0xdc81, 0x3a, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, +0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x73, 0x6b, 0x5f, 0x70, +0x65, 0x72, 0x73, 0x6f, 0x6e, 0x3a, 0x64, 0x65, 0x73, 0x6b, 0x69, 0x6e, +0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x70, 0x65, 0x72, +0x73, 0x6f, 0x6e, 0xd83d, 0xdc81, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, +0x5f, 0x74, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, +0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, +0x74, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xd83d, 0xdc81, 0x200d, 0x2642, 0xfe0f, +0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x74, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, +0x5f, 0x68, 0x61, 0x6e, 0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x6d, 0x61, +0x6e, 0x74, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xd83d, 0xde45, 0x3a, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, +0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x3a, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, +0x69, 0x6e, 0x67, 0x6e, 0x6f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xde45, +0x3a, 0x6e, 0x6f, 0x5f, 0x67, 0x6f, 0x6f, 0x64, 0x3a, 0x67, 0x6f, 0x6f, +0x64, 0x6e, 0x6f, 0xd83d, 0xde45, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, +0x5f, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6e, +0x6f, 0x3a, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x6e, +0x6f, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83d, 0xde45, 0x200d, 0x2642, 0xfe0f, +0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, +0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x3a, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, +0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0x6e, 0x6f, 0xd83d, 0xde46, 0x3a, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, +0x6e, 0x67, 0x5f, 0x6f, 0x6b, 0x3a, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, +0x69, 0x6e, 0x67, 0x6f, 0x6b, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xde46, +0x3a, 0x6f, 0x6b, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x3a, 0x6f, 0x6b, +0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xde46, 0x3a, 0x70, 0x65, 0x72, 0x73, +0x6f, 0x6e, 0x5f, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67, +0x5f, 0x6f, 0x6b, 0x3a, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, +0x67, 0x6f, 0x6b, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83d, 0xde46, 0x200d, +0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x73, 0x74, 0x75, +0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x6b, 0x3a, 0x67, 0x65, 0x73, 0x74, +0x75, 0x72, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0x6f, 0x6b, 0xd83d, 0xde4b, +0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x72, 0x61, 0x69, 0x73, 0x69, +0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, +0x72, 0x61, 0x69, 0x73, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, +0xd83d, 0xde4b, 0x3a, 0x72, 0x61, 0x69, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x68, +0x61, 0x6e, 0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x72, 0x61, 0x69, 0x73, +0x69, 0x6e, 0x67, 0xd83d, 0xde4b, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, +0x5f, 0x72, 0x61, 0x69, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, +0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, +0x72, 0x61, 0x69, 0x73, 0x69, 0x6e, 0x67, 0xd83d, 0xde4b, 0x200d, 0x2642, 0xfe0f, +0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x72, 0x61, 0x69, 0x73, 0x69, 0x6e, 0x67, +0x5f, 0x68, 0x61, 0x6e, 0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x6d, 0x61, +0x6e, 0x72, 0x61, 0x69, 0x73, 0x69, 0x6e, 0x67, 0xd83e, 0xdd26, 0x200d, 0x2640, +0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x61, 0x63, 0x65, +0x70, 0x61, 0x6c, 0x6d, 0x69, 0x6e, 0x67, 0x3a, 0x66, 0x61, 0x63, 0x65, +0x70, 0x61, 0x6c, 0x6d, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, +0xd83e, 0xdd26, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x61, +0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, 0x69, 0x6e, 0x67, 0x3a, 0x66, 0x61, +0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, +0xd83e, 0xdd26, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x70, 0x61, +0x6c, 0x6d, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, 0xd83e, +0xdd26, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x70, 0x61, +0x6c, 0x6d, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, 0xd83e, +0xdd26, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, +0x66, 0x61, 0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, 0x69, 0x6e, 0x67, 0x3a, +0x66, 0x61, 0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, 0x69, 0x6e, 0x67, 0x70, +0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83e, 0xdd37, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x68, 0x72, 0x75, 0x67, 0x67, 0x69, +0x6e, 0x67, 0x3a, 0x73, 0x68, 0x72, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, +0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd37, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x73, +0x68, 0x72, 0x75, 0x67, 0x3a, 0x73, 0x68, 0x72, 0x75, 0x67, 0xd83e, 0xdd37, +0x200d, 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x73, +0x68, 0x72, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x3a, 0x70, 0x65, 0x72, +0x73, 0x6f, 0x6e, 0x73, 0x68, 0x72, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, +0xd83e, 0xdd37, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x68, +0x72, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x3a, 0x6d, 0x61, 0x6e, 0x73, +0x68, 0x72, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0xd83d, 0xde4e, 0x3a, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, +0x3a, 0x70, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0xd83d, 0xde4e, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x77, +0x69, 0x74, 0x68, 0x5f, 0x70, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x5f, +0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x70, 0x65, 0x72, +0x73, 0x6f, 0x6e, 0x70, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x77, 0x69, +0x74, 0x68, 0xd83d, 0xde4e, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, +0x70, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x3a, 0x70, 0x65, 0x72, 0x73, +0x6f, 0x6e, 0x70, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0xd83d, 0xde4e, 0x200d, +0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x75, 0x74, 0x69, +0x6e, 0x67, 0x3a, 0x6d, 0x61, 0x6e, 0x70, 0x6f, 0x75, 0x74, 0x69, 0x6e, +0x67, 0xd83d, 0xde4d, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x72, +0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x66, 0x72, 0x6f, 0x77, 0x6e, +0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xde4d, 0x3a, 0x70, +0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, +0x6e, 0x67, 0x3a, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x70, +0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83d, 0xde4d, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, +0x61, 0x6e, 0x5f, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x3a, +0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0xd83d, +0xdc87, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x74, 0x74, +0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x69, 0x72, 0x63, 0x75, 0x74, 0x3a, +0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x72, 0x63, +0x75, 0x74, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc87, 0x3a, 0x68, 0x61, +0x69, 0x72, 0x63, 0x75, 0x74, 0x3a, 0x68, 0x61, 0x69, 0x72, 0x63, 0x75, +0x74, 0xd83d, 0xdc87, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x67, +0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x69, 0x72, 0x63, +0x75, 0x74, 0x3a, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x68, 0x61, +0x69, 0x72, 0x63, 0x75, 0x74, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83d, +0xdc87, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x74, +0x74, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x69, 0x72, 0x63, 0x75, 0x74, +0x3a, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x72, +0x63, 0x75, 0x74, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc86, 0x3a, 0x77, 0x6f, 0x6d, +0x61, 0x6e, 0x5f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x66, +0x61, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, +0x66, 0x61, 0x63, 0x65, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x6d, +0x61, 0x73, 0x73, 0x61, 0x67, 0x65, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, +0xdc86, 0x3a, 0x6d, 0x61, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x6d, 0x61, +0x73, 0x73, 0x61, 0x67, 0x65, 0xd83d, 0xdc86, 0x3a, 0x70, 0x65, 0x72, 0x73, +0x6f, 0x6e, 0x5f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6d, +0x61, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x67, 0x65, 0x74, 0x74, 0x69, +0x6e, 0x67, 0x6d, 0x61, 0x73, 0x73, 0x61, 0x67, 0x65, 0x70, 0x65, 0x72, +0x73, 0x6f, 0x6e, 0xd83d, 0xdc86, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, +0x5f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, +0x65, 0x5f, 0x6d, 0x61, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x66, 0x61, +0x63, 0x65, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, +0x6d, 0x61, 0x73, 0x73, 0x61, 0x67, 0x65, 0xd83d, 0xdd74, 0x3a, 0x6d, 0x61, +0x6e, 0x5f, 0x69, 0x6e, 0x5f, 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, +0x73, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x5f, 0x6c, 0x65, 0x76, 0x69, 0x74, +0x61, 0x74, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, +0x73, 0x73, 0x69, 0x6e, 0x6c, 0x65, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, +0x6e, 0x67, 0x6d, 0x61, 0x6e, 0x73, 0x75, 0x69, 0x74, 0xd83d, 0xdc83, 0x3a, +0x64, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x3a, 0x64, 0x61, 0x6e, 0x63, 0x65, +0x72, 0xd83d, 0xdd7a, 0x3a, 0x6d, 0x61, 0x6c, 0x65, 0x5f, 0x64, 0x61, 0x6e, +0x63, 0x65, 0x72, 0x3a, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x6d, 0x61, +0x6c, 0x65, 0xd83d, 0xdd7a, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x64, 0x61, 0x6e, +0x63, 0x69, 0x6e, 0x67, 0x3a, 0x64, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, +0x6d, 0x61, 0x6e, 0xd83d, 0xdc6f, 0x3a, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x5f, +0x77, 0x69, 0x74, 0x68, 0x5f, 0x62, 0x75, 0x6e, 0x6e, 0x79, 0x5f, 0x65, +0x61, 0x72, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x69, 0x6e, 0x67, +0x3a, 0x62, 0x75, 0x6e, 0x6e, 0x79, 0x65, 0x61, 0x72, 0x73, 0x70, 0x61, +0x72, 0x74, 0x79, 0x69, 0x6e, 0x67, 0x77, 0x69, 0x74, 0x68, 0x77, 0x6f, +0x6d, 0x65, 0x6e, 0xd83d, 0xdc6f, 0x3a, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x72, +0x73, 0x3a, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x73, 0xd83d, 0xdc6f, 0x3a, +0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, +0x62, 0x75, 0x6e, 0x6e, 0x79, 0x5f, 0x65, 0x61, 0x72, 0x73, 0x5f, 0x70, +0x61, 0x72, 0x74, 0x79, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x75, 0x6e, 0x6e, +0x79, 0x65, 0x61, 0x72, 0x73, 0x70, 0x61, 0x72, 0x74, 0x79, 0x69, 0x6e, +0x67, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x77, 0x69, 0x74, 0x68, 0xd83d, +0xdc6f, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x65, 0x6e, 0x5f, 0x77, 0x69, 0x74, +0x68, 0x5f, 0x62, 0x75, 0x6e, 0x6e, 0x79, 0x5f, 0x65, 0x61, 0x72, 0x73, +0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x75, +0x6e, 0x6e, 0x79, 0x65, 0x61, 0x72, 0x73, 0x6d, 0x65, 0x6e, 0x70, 0x61, +0x72, 0x74, 0x79, 0x69, 0x6e, 0x67, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdeb6, +0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x77, 0x61, +0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, +0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdeb6, 0x3a, 0x6d, 0x61, 0x6e, +0x5f, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x6d, 0x61, 0x6e, +0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0xd83d, 0xdeb6, 0x3a, 0x77, 0x61, +0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, +0x67, 0xd83d, 0xdeb6, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x77, +0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, +0x6e, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0xd83c, 0xdfc3, 0x200d, 0x2640, +0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x72, 0x75, 0x6e, 0x6e, +0x69, 0x6e, 0x67, 0x3a, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0xd83c, 0xdfc3, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x72, +0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x6d, 0x61, 0x6e, 0x72, 0x75, +0x6e, 0x6e, 0x69, 0x6e, 0x67, 0xd83c, 0xdfc3, 0x3a, 0x72, 0x75, 0x6e, 0x6e, +0x65, 0x72, 0x3a, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0xd83c, 0xdfc3, 0x3a, +0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, +0x6e, 0x67, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x72, 0x75, 0x6e, +0x6e, 0x69, 0x6e, 0x67, 0xd83d, 0xdc6b, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, +0x65, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0xd83d, 0xdc6d, 0x3a, 0x74, +0x77, 0x6f, 0x5f, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x5f, 0x68, 0x6f, 0x6c, +0x64, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x3a, 0x68, +0x61, 0x6e, 0x64, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x74, +0x77, 0x6f, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0xd83d, 0xdc6c, 0x3a, 0x74, 0x77, +0x6f, 0x5f, 0x6d, 0x65, 0x6e, 0x5f, 0x68, 0x6f, 0x6c, 0x64, 0x69, 0x6e, +0x67, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x3a, 0x68, 0x61, 0x6e, 0x64, +0x73, 0x68, 0x6f, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x6d, 0x65, 0x6e, 0x74, +0x77, 0x6f, 0xd83d, 0xdc91, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x5f, +0x77, 0x69, 0x74, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3a, 0x63, +0x6f, 0x75, 0x70, 0x6c, 0x65, 0x68, 0x65, 0x61, 0x72, 0x74, 0x77, 0x69, +0x74, 0x68, 0xd83d, 0xdc91, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x5f, +0x77, 0x69, 0x74, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x5f, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x6d, 0x61, 0x6e, 0x3a, 0x63, 0x6f, 0x75, +0x70, 0x6c, 0x65, 0x68, 0x65, 0x61, 0x72, 0x74, 0x6d, 0x61, 0x6e, 0x77, +0x69, 0x74, 0x68, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0x2764, +0xfe0f, 0x200d, 0xd83d, 0xdc69, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x5f, +0x77, 0x69, 0x74, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x5f, 0x77, +0x77, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x68, 0x65, 0x61, 0x72, +0x74, 0x77, 0x69, 0x74, 0x68, 0x77, 0x77, 0xd83d, 0xdc69, 0x200d, 0x2764, 0xfe0f, +0x200d, 0xd83d, 0xdc69, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x5f, 0x77, +0x77, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x77, 0x77, 0xd83d, 0xdc68, +0x200d, 0x2764, 0xfe0f, 0x200d, 0xd83d, 0xdc68, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, +0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, +0x5f, 0x6d, 0x6d, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x68, 0x65, +0x61, 0x72, 0x74, 0x6d, 0x6d, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdc68, 0x200d, +0x2764, 0xfe0f, 0x200d, 0xd83d, 0xdc68, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, +0x5f, 0x6d, 0x6d, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x6d, 0x6d, +0xd83d, 0xdc8f, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x6b, 0x69, 0x73, +0x73, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x6b, 0x69, 0x73, 0x73, +0xd83d, 0xdc8f, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x5f, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0x5f, 0x6d, 0x61, 0x6e, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x6d, 0x61, +0x6e, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0x2764, 0xfe0f, 0x200d, +0xd83d, 0xdc8b, 0x200d, 0xd83d, 0xdc69, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, +0x6b, 0x69, 0x73, 0x73, 0x5f, 0x77, 0x77, 0x3a, 0x63, 0x6f, 0x75, 0x70, +0x6c, 0x65, 0x6b, 0x69, 0x73, 0x73, 0x77, 0x77, 0xd83d, 0xdc69, 0x200d, 0x2764, +0xfe0f, 0x200d, 0xd83d, 0xdc8b, 0x200d, 0xd83d, 0xdc69, 0x3a, 0x6b, 0x69, 0x73, 0x73, +0x5f, 0x77, 0x77, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x77, 0x77, 0xd83d, 0xdc68, +0x200d, 0x2764, 0xfe0f, 0x200d, 0xd83d, 0xdc8b, 0x200d, 0xd83d, 0xdc68, 0x3a, 0x63, 0x6f, +0x75, 0x70, 0x6c, 0x65, 0x6b, 0x69, 0x73, 0x73, 0x5f, 0x6d, 0x6d, 0x3a, +0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x6b, 0x69, 0x73, 0x73, 0x6d, 0x6d, +0xd83d, 0xdc68, 0x200d, 0x2764, 0xfe0f, 0x200d, 0xd83d, 0xdc8b, 0x200d, 0xd83d, 0xdc68, 0x3a, +0x6b, 0x69, 0x73, 0x73, 0x5f, 0x6d, 0x6d, 0x3a, 0x6b, 0x69, 0x73, 0x73, +0x6d, 0x6d, 0xd83d, 0xdc6a, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, +0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0xd83d, 0xdc6a, 0x3a, 0x66, 0x61, 0x6d, +0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x5f, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0x5f, 0x62, 0x6f, 0x79, 0x3a, 0x62, 0x6f, 0x79, 0x66, 0x61, 0x6d, +0x69, 0x6c, 0x79, 0x6d, 0x61, 0x6e, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, +0xdc68, 0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, +0x6c, 0x79, 0x5f, 0x6d, 0x77, 0x67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, +0x79, 0x6d, 0x77, 0x67, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc67, +0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, +0x77, 0x67, 0x62, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x77, +0x67, 0x62, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc66, 0x200d, 0xd83d, +0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x77, 0x62, +0x62, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x77, 0x62, 0x62, +0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc67, 0x3a, +0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x77, 0x67, 0x67, 0x3a, +0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x77, 0x67, 0x67, 0xd83d, 0xdc69, +0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, +0x79, 0x5f, 0x77, 0x77, 0x62, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, +0x77, 0x77, 0x62, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc67, 0x3a, +0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x77, 0x77, 0x67, 0x3a, 0x66, +0x61, 0x6d, 0x69, 0x6c, 0x79, 0x77, 0x77, 0x67, 0xd83d, 0xdc69, 0x200d, 0xd83d, +0xdc69, 0x200d, 0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, +0x6c, 0x79, 0x5f, 0x77, 0x77, 0x67, 0x62, 0x3a, 0x66, 0x61, 0x6d, 0x69, +0x6c, 0x79, 0x77, 0x77, 0x67, 0x62, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc69, 0x200d, +0xd83d, 0xdc66, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, +0x5f, 0x77, 0x77, 0x62, 0x62, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, +0x77, 0x77, 0x62, 0x62, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc67, +0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x77, +0x77, 0x67, 0x67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x77, 0x77, +0x67, 0x67, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, +0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x6d, 0x62, 0x3a, 0x66, 0x61, +0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x6d, 0x62, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc68, +0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, +0x6d, 0x67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x6d, 0x67, +0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc66, 0x3a, +0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x6d, 0x67, 0x62, 0x3a, +0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x6d, 0x67, 0x62, 0xd83d, 0xdc68, +0x200d, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc66, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, +0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x6d, 0x62, 0x62, 0x3a, 0x66, 0x61, +0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x6d, 0x62, 0x62, 0xd83d, 0xdc68, 0x200d, 0xd83d, +0xdc68, 0x200d, 0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, +0x6c, 0x79, 0x5f, 0x6d, 0x6d, 0x67, 0x67, 0x3a, 0x66, 0x61, 0x6d, 0x69, +0x6c, 0x79, 0x6d, 0x6d, 0x67, 0x67, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc66, 0x3a, +0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, +0x5f, 0x62, 0x6f, 0x79, 0x3a, 0x62, 0x6f, 0x79, 0x66, 0x61, 0x6d, 0x69, +0x6c, 0x79, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc67, +0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0x5f, 0x67, 0x69, 0x72, 0x6c, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, +0x79, 0x67, 0x69, 0x72, 0x6c, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, +0x200d, 0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, +0x79, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x69, 0x72, 0x6c, +0x5f, 0x62, 0x6f, 0x79, 0x3a, 0x62, 0x6f, 0x79, 0x66, 0x61, 0x6d, 0x69, +0x6c, 0x79, 0x67, 0x69, 0x72, 0x6c, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, +0xdc69, 0x200d, 0xd83d, 0xdc66, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, +0x6c, 0x79, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x62, 0x6f, 0x79, +0x5f, 0x62, 0x6f, 0x79, 0x3a, 0x62, 0x6f, 0x79, 0x62, 0x6f, 0x79, 0x66, +0x61, 0x6d, 0x69, 0x6c, 0x79, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, +0x200d, 0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, +0x79, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x69, 0x72, 0x6c, +0x5f, 0x67, 0x69, 0x72, 0x6c, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, +0x67, 0x69, 0x72, 0x6c, 0x67, 0x69, 0x72, 0x6c, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, +0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x5f, 0x62, 0x6f, 0x79, 0x3a, 0x62, 0x6f, +0x79, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, +0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, +0x61, 0x6e, 0x5f, 0x67, 0x69, 0x72, 0x6c, 0x3a, 0x66, 0x61, 0x6d, 0x69, +0x6c, 0x79, 0x67, 0x69, 0x72, 0x6c, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, +0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, +0x5f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x69, 0x72, 0x6c, 0x5f, 0x62, 0x6f, +0x79, 0x3a, 0x62, 0x6f, 0x79, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x67, +0x69, 0x72, 0x6c, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc66, 0x200d, +0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x61, +0x6e, 0x5f, 0x62, 0x6f, 0x79, 0x5f, 0x62, 0x6f, 0x79, 0x3a, 0x62, 0x6f, +0x79, 0x62, 0x6f, 0x79, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x61, +0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, +0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x69, 0x72, +0x6c, 0x5f, 0x67, 0x69, 0x72, 0x6c, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, +0x79, 0x67, 0x69, 0x72, 0x6c, 0x67, 0x69, 0x72, 0x6c, 0x6d, 0x61, 0x6e, +0xd83d, 0xdc5a, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x73, 0x5f, 0x63, 0x6c, +0x6f, 0x74, 0x68, 0x65, 0x73, 0x3a, 0x63, 0x6c, 0x6f, 0x74, 0x68, 0x65, +0x73, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x73, 0xd83d, 0xdc55, 0x3a, 0x73, 0x68, +0x69, 0x72, 0x74, 0x3a, 0x73, 0x68, 0x69, 0x72, 0x74, 0xd83d, 0xdc56, 0x3a, +0x6a, 0x65, 0x61, 0x6e, 0x73, 0x3a, 0x6a, 0x65, 0x61, 0x6e, 0x73, 0xd83d, +0xdc54, 0x3a, 0x6e, 0x65, 0x63, 0x6b, 0x74, 0x69, 0x65, 0x3a, 0x6e, 0x65, +0x63, 0x6b, 0x74, 0x69, 0x65, 0xd83d, 0xdc57, 0x3a, 0x64, 0x72, 0x65, 0x73, +0x73, 0x3a, 0x64, 0x72, 0x65, 0x73, 0x73, 0xd83d, 0xdc59, 0x3a, 0x62, 0x69, +0x6b, 0x69, 0x6e, 0x69, 0x3a, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x69, 0xd83d, +0xdc58, 0x3a, 0x6b, 0x69, 0x6d, 0x6f, 0x6e, 0x6f, 0x3a, 0x6b, 0x69, 0x6d, +0x6f, 0x6e, 0x6f, 0xd83d, 0xdc60, 0x3a, 0x68, 0x69, 0x67, 0x68, 0x5f, 0x68, +0x65, 0x65, 0x6c, 0x3a, 0x68, 0x65, 0x65, 0x6c, 0x68, 0x69, 0x67, 0x68, +0xd83d, 0xdc61, 0x3a, 0x73, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x3a, 0x73, 0x61, +0x6e, 0x64, 0x61, 0x6c, 0xd83d, 0xdc62, 0x3a, 0x62, 0x6f, 0x6f, 0x74, 0x3a, +0x62, 0x6f, 0x6f, 0x74, 0xd83d, 0xdc5e, 0x3a, 0x6d, 0x61, 0x6e, 0x73, 0x5f, +0x73, 0x68, 0x6f, 0x65, 0x3a, 0x6d, 0x61, 0x6e, 0x73, 0x73, 0x68, 0x6f, +0x65, 0xd83d, 0xdc5f, 0x3a, 0x61, 0x74, 0x68, 0x6c, 0x65, 0x74, 0x69, 0x63, +0x5f, 0x73, 0x68, 0x6f, 0x65, 0x3a, 0x61, 0x74, 0x68, 0x6c, 0x65, 0x74, +0x69, 0x63, 0x73, 0x68, 0x6f, 0x65, 0xd83d, 0xdc52, 0x3a, 0x77, 0x6f, 0x6d, +0x61, 0x6e, 0x73, 0x5f, 0x68, 0x61, 0x74, 0x3a, 0x68, 0x61, 0x74, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0x73, 0xd83c, 0xdfa9, 0x3a, 0x74, 0x6f, 0x70, 0x68, +0x61, 0x74, 0x3a, 0x74, 0x6f, 0x70, 0x68, 0x61, 0x74, 0xd83c, 0xdf93, 0x3a, +0x6d, 0x6f, 0x72, 0x74, 0x61, 0x72, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, +0x3a, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x6d, 0x6f, 0x72, 0x74, 0x61, 0x72, +0xd83d, 0xdc51, 0x3a, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x3a, 0x63, 0x72, 0x6f, +0x77, 0x6e, 0x26d1, 0x3a, 0x68, 0x65, 0x6c, 0x6d, 0x65, 0x74, 0x5f, 0x77, +0x69, 0x74, 0x68, 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x72, +0x6f, 0x73, 0x73, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x68, 0x65, 0x6c, +0x6d, 0x65, 0x74, 0x77, 0x68, 0x69, 0x74, 0x65, 0x77, 0x69, 0x74, 0x68, +0x26d1, 0x3a, 0x68, 0x65, 0x6c, 0x6d, 0x65, 0x74, 0x5f, 0x77, 0x69, 0x74, +0x68, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x3a, 0x63, 0x72, 0x6f, 0x73, +0x73, 0x68, 0x65, 0x6c, 0x6d, 0x65, 0x74, 0x77, 0x69, 0x74, 0x68, 0xd83c, +0xdf92, 0x3a, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x5f, 0x73, 0x61, 0x74, +0x63, 0x68, 0x65, 0x6c, 0x3a, 0x73, 0x61, 0x74, 0x63, 0x68, 0x65, 0x6c, +0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0xd83d, 0xdc5d, 0x3a, 0x70, 0x6f, 0x75, +0x63, 0x68, 0x3a, 0x70, 0x6f, 0x75, 0x63, 0x68, 0xd83d, 0xdc5b, 0x3a, 0x70, +0x75, 0x72, 0x73, 0x65, 0x3a, 0x70, 0x75, 0x72, 0x73, 0x65, 0xd83d, 0xdc5c, +0x3a, 0x68, 0x61, 0x6e, 0x64, 0x62, 0x61, 0x67, 0x3a, 0x68, 0x61, 0x6e, +0x64, 0x62, 0x61, 0x67, 0xd83d, 0xdcbc, 0x3a, 0x62, 0x72, 0x69, 0x65, 0x66, +0x63, 0x61, 0x73, 0x65, 0x3a, 0x62, 0x72, 0x69, 0x65, 0x66, 0x63, 0x61, +0x73, 0x65, 0xd83d, 0xdc53, 0x3a, 0x65, 0x79, 0x65, 0x67, 0x6c, 0x61, 0x73, +0x73, 0x65, 0x73, 0x3a, 0x65, 0x79, 0x65, 0x67, 0x6c, 0x61, 0x73, 0x73, +0x65, 0x73, 0xd83d, 0xdd76, 0x3a, 0x64, 0x61, 0x72, 0x6b, 0x5f, 0x73, 0x75, +0x6e, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0x3a, 0x64, 0x61, 0x72, +0x6b, 0x73, 0x75, 0x6e, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0xd83c, +0xdf02, 0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x75, 0x6d, 0x62, +0x72, 0x65, 0x6c, 0x6c, 0x61, 0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, +0x75, 0x6d, 0x62, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x2602, 0xfe0f, 0x3a, 0x75, +0x6d, 0x62, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x32, 0x3a, 0x75, 0x6d, 0x62, +0x72, 0x65, 0x6c, 0x6c, 0x61, 0x32, 0xd83d, 0xdc36, 0x3a, 0x64, 0x6f, 0x67, +0x3a, 0x64, 0x6f, 0x67, 0xd83d, 0xdc31, 0x3a, 0x63, 0x61, 0x74, 0x3a, 0x63, +0x61, 0x74, 0xd83d, 0xdc2d, 0x3a, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x3a, 0x6d, +0x6f, 0x75, 0x73, 0x65, 0xd83d, 0xdc39, 0x3a, 0x68, 0x61, 0x6d, 0x73, 0x74, +0x65, 0x72, 0x3a, 0x68, 0x61, 0x6d, 0x73, 0x74, 0x65, 0x72, 0xd83d, 0xdc30, +0x3a, 0x72, 0x61, 0x62, 0x62, 0x69, 0x74, 0x3a, 0x72, 0x61, 0x62, 0x62, +0x69, 0x74, 0xd83e, 0xdd8a, 0x3a, 0x66, 0x6f, 0x78, 0x5f, 0x66, 0x61, 0x63, +0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x66, 0x6f, 0x78, 0xd83e, 0xdd8a, 0x3a, +0x66, 0x6f, 0x78, 0x3a, 0x66, 0x6f, 0x78, 0xd83d, 0xdc3b, 0x3a, 0x62, 0x65, +0x61, 0x72, 0x3a, 0x62, 0x65, 0x61, 0x72, 0xd83d, 0xdc3c, 0x3a, 0x70, 0x61, +0x6e, 0x64, 0x61, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, +0x65, 0x70, 0x61, 0x6e, 0x64, 0x61, 0xd83d, 0xdc28, 0x3a, 0x6b, 0x6f, 0x61, +0x6c, 0x61, 0x3a, 0x6b, 0x6f, 0x61, 0x6c, 0x61, 0xd83d, 0xdc2f, 0x3a, 0x74, +0x69, 0x67, 0x65, 0x72, 0x3a, 0x74, 0x69, 0x67, 0x65, 0x72, 0xd83e, 0xdd81, +0x3a, 0x6c, 0x69, 0x6f, 0x6e, 0x3a, 0x6c, 0x69, 0x6f, 0x6e, 0xd83e, 0xdd81, +0x3a, 0x6c, 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, +0x61, 0x63, 0x65, 0x6c, 0x69, 0x6f, 0x6e, 0xd83d, 0xdc2e, 0x3a, 0x63, 0x6f, +0x77, 0x3a, 0x63, 0x6f, 0x77, 0xd83d, 0xdc37, 0x3a, 0x70, 0x69, 0x67, 0x3a, +0x70, 0x69, 0x67, 0xd83d, 0xdc3d, 0x3a, 0x70, 0x69, 0x67, 0x5f, 0x6e, 0x6f, +0x73, 0x65, 0x3a, 0x6e, 0x6f, 0x73, 0x65, 0x70, 0x69, 0x67, 0xd83d, 0xdc38, +0x3a, 0x66, 0x72, 0x6f, 0x67, 0x3a, 0x66, 0x72, 0x6f, 0x67, 0xd83d, 0xdc35, +0x3a, 0x6d, 0x6f, 0x6e, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x61, 0x63, 0x65, +0x3a, 0x66, 0x61, 0x63, 0x65, 0x6d, 0x6f, 0x6e, 0x6b, 0x65, 0x79, 0xd83d, +0xde48, 0x3a, 0x73, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x5f, 0x65, 0x76, 0x69, +0x6c, 0x3a, 0x65, 0x76, 0x69, 0x6c, 0x6e, 0x6f, 0x73, 0x65, 0x65, 0xd83d, +0xde49, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x5f, 0x6e, 0x6f, 0x5f, 0x65, 0x76, +0x69, 0x6c, 0x3a, 0x65, 0x76, 0x69, 0x6c, 0x68, 0x65, 0x61, 0x72, 0x6e, +0x6f, 0xd83d, 0xde4a, 0x3a, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x5f, 0x6e, 0x6f, +0x5f, 0x65, 0x76, 0x69, 0x6c, 0x3a, 0x65, 0x76, 0x69, 0x6c, 0x6e, 0x6f, +0x73, 0x70, 0x65, 0x61, 0x6b, 0xd83d, 0xdc12, 0x3a, 0x6d, 0x6f, 0x6e, 0x6b, +0x65, 0x79, 0x3a, 0x6d, 0x6f, 0x6e, 0x6b, 0x65, 0x79, 0xd83d, 0xdc14, 0x3a, +0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x3a, 0x63, 0x68, 0x69, 0x63, +0x6b, 0x65, 0x6e, 0xd83d, 0xdc27, 0x3a, 0x70, 0x65, 0x6e, 0x67, 0x75, 0x69, +0x6e, 0x3a, 0x70, 0x65, 0x6e, 0x67, 0x75, 0x69, 0x6e, 0xd83d, 0xdc26, 0x3a, +0x62, 0x69, 0x72, 0x64, 0x3a, 0x62, 0x69, 0x72, 0x64, 0xd83d, 0xdc24, 0x3a, +0x62, 0x61, 0x62, 0x79, 0x5f, 0x63, 0x68, 0x69, 0x63, 0x6b, 0x3a, 0x62, +0x61, 0x62, 0x79, 0x63, 0x68, 0x69, 0x63, 0x6b, 0xd83d, 0xdc23, 0x3a, 0x68, +0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x69, 0x63, +0x6b, 0x3a, 0x63, 0x68, 0x69, 0x63, 0x6b, 0x68, 0x61, 0x74, 0x63, 0x68, +0x69, 0x6e, 0x67, 0xd83d, 0xdc25, 0x3a, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, +0x64, 0x5f, 0x63, 0x68, 0x69, 0x63, 0x6b, 0x3a, 0x63, 0x68, 0x69, 0x63, +0x6b, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0xd83e, 0xdd86, 0x3a, 0x64, +0x75, 0x63, 0x6b, 0x3a, 0x64, 0x75, 0x63, 0x6b, 0xd83e, 0xdd85, 0x3a, 0x65, +0x61, 0x67, 0x6c, 0x65, 0x3a, 0x65, 0x61, 0x67, 0x6c, 0x65, 0xd83e, 0xdd89, +0x3a, 0x6f, 0x77, 0x6c, 0x3a, 0x6f, 0x77, 0x6c, 0xd83e, 0xdd87, 0x3a, 0x62, +0x61, 0x74, 0x3a, 0x62, 0x61, 0x74, 0xd83d, 0xdc3a, 0x3a, 0x77, 0x6f, 0x6c, +0x66, 0x3a, 0x77, 0x6f, 0x6c, 0x66, 0xd83d, 0xdc17, 0x3a, 0x62, 0x6f, 0x61, +0x72, 0x3a, 0x62, 0x6f, 0x61, 0x72, 0xd83d, 0xdc34, 0x3a, 0x68, 0x6f, 0x72, +0x73, 0x65, 0x3a, 0x68, 0x6f, 0x72, 0x73, 0x65, 0xd83e, 0xdd84, 0x3a, 0x75, +0x6e, 0x69, 0x63, 0x6f, 0x72, 0x6e, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, +0x66, 0x61, 0x63, 0x65, 0x75, 0x6e, 0x69, 0x63, 0x6f, 0x72, 0x6e, 0xd83e, +0xdd84, 0x3a, 0x75, 0x6e, 0x69, 0x63, 0x6f, 0x72, 0x6e, 0x3a, 0x75, 0x6e, +0x69, 0x63, 0x6f, 0x72, 0x6e, 0xd83d, 0xdc1d, 0x3a, 0x62, 0x65, 0x65, 0x3a, +0x62, 0x65, 0x65, 0xd83d, 0xdc1b, 0x3a, 0x62, 0x75, 0x67, 0x3a, 0x62, 0x75, +0x67, 0xd83e, 0xdd8b, 0x3a, 0x62, 0x75, 0x74, 0x74, 0x65, 0x72, 0x66, 0x6c, +0x79, 0x3a, 0x62, 0x75, 0x74, 0x74, 0x65, 0x72, 0x66, 0x6c, 0x79, 0xd83d, +0xdc0c, 0x3a, 0x73, 0x6e, 0x61, 0x69, 0x6c, 0x3a, 0x73, 0x6e, 0x61, 0x69, +0x6c, 0xd83d, 0xdc1a, 0x3a, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x3a, 0x73, 0x68, +0x65, 0x6c, 0x6c, 0xd83d, 0xdc1e, 0x3a, 0x62, 0x65, 0x65, 0x74, 0x6c, 0x65, +0x3a, 0x62, 0x65, 0x65, 0x74, 0x6c, 0x65, 0xd83d, 0xdc1c, 0x3a, 0x61, 0x6e, +0x74, 0x3a, 0x61, 0x6e, 0x74, 0xd83d, 0xdd77, 0x3a, 0x73, 0x70, 0x69, 0x64, +0x65, 0x72, 0x3a, 0x73, 0x70, 0x69, 0x64, 0x65, 0x72, 0xd83d, 0xdd78, 0x3a, +0x73, 0x70, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x77, 0x65, 0x62, 0x3a, 0x73, +0x70, 0x69, 0x64, 0x65, 0x72, 0x77, 0x65, 0x62, 0xd83d, 0xdc22, 0x3a, 0x74, +0x75, 0x72, 0x74, 0x6c, 0x65, 0x3a, 0x74, 0x75, 0x72, 0x74, 0x6c, 0x65, +0xd83d, 0xdc0d, 0x3a, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x3a, 0x73, 0x6e, 0x61, +0x6b, 0x65, 0xd83e, 0xdd8e, 0x3a, 0x6c, 0x69, 0x7a, 0x61, 0x72, 0x64, 0x3a, +0x6c, 0x69, 0x7a, 0x61, 0x72, 0x64, 0xd83e, 0xdd82, 0x3a, 0x73, 0x63, 0x6f, +0x72, 0x70, 0x69, 0x6f, 0x6e, 0x3a, 0x73, 0x63, 0x6f, 0x72, 0x70, 0x69, +0x6f, 0x6e, 0xd83e, 0xdd80, 0x3a, 0x63, 0x72, 0x61, 0x62, 0x3a, 0x63, 0x72, +0x61, 0x62, 0xd83e, 0xdd91, 0x3a, 0x73, 0x71, 0x75, 0x69, 0x64, 0x3a, 0x73, +0x71, 0x75, 0x69, 0x64, 0xd83d, 0xdc19, 0x3a, 0x6f, 0x63, 0x74, 0x6f, 0x70, +0x75, 0x73, 0x3a, 0x6f, 0x63, 0x74, 0x6f, 0x70, 0x75, 0x73, 0xd83e, 0xdd90, +0x3a, 0x73, 0x68, 0x72, 0x69, 0x6d, 0x70, 0x3a, 0x73, 0x68, 0x72, 0x69, +0x6d, 0x70, 0xd83d, 0xdc20, 0x3a, 0x74, 0x72, 0x6f, 0x70, 0x69, 0x63, 0x61, +0x6c, 0x5f, 0x66, 0x69, 0x73, 0x68, 0x3a, 0x66, 0x69, 0x73, 0x68, 0x74, +0x72, 0x6f, 0x70, 0x69, 0x63, 0x61, 0x6c, 0xd83d, 0xdc1f, 0x3a, 0x66, 0x69, +0x73, 0x68, 0x3a, 0x66, 0x69, 0x73, 0x68, 0xd83d, 0xdc21, 0x3a, 0x62, 0x6c, +0x6f, 0x77, 0x66, 0x69, 0x73, 0x68, 0x3a, 0x62, 0x6c, 0x6f, 0x77, 0x66, +0x69, 0x73, 0x68, 0xd83d, 0xdc2c, 0x3a, 0x64, 0x6f, 0x6c, 0x70, 0x68, 0x69, +0x6e, 0x3a, 0x64, 0x6f, 0x6c, 0x70, 0x68, 0x69, 0x6e, 0xd83e, 0xdd88, 0x3a, +0x73, 0x68, 0x61, 0x72, 0x6b, 0x3a, 0x73, 0x68, 0x61, 0x72, 0x6b, 0xd83d, +0xdc33, 0x3a, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x3a, 0x77, 0x68, 0x61, 0x6c, +0x65, 0xd83d, 0xdc0b, 0x3a, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x32, 0x3a, 0x77, +0x68, 0x61, 0x6c, 0x65, 0x32, 0xd83d, 0xdc0a, 0x3a, 0x63, 0x72, 0x6f, 0x63, +0x6f, 0x64, 0x69, 0x6c, 0x65, 0x3a, 0x63, 0x72, 0x6f, 0x63, 0x6f, 0x64, +0x69, 0x6c, 0x65, 0xd83d, 0xdc06, 0x3a, 0x6c, 0x65, 0x6f, 0x70, 0x61, 0x72, +0x64, 0x3a, 0x6c, 0x65, 0x6f, 0x70, 0x61, 0x72, 0x64, 0xd83d, 0xdc05, 0x3a, +0x74, 0x69, 0x67, 0x65, 0x72, 0x32, 0x3a, 0x74, 0x69, 0x67, 0x65, 0x72, +0x32, 0xd83d, 0xdc03, 0x3a, 0x77, 0x61, 0x74, 0x65, 0x72, 0x5f, 0x62, 0x75, +0x66, 0x66, 0x61, 0x6c, 0x6f, 0x3a, 0x62, 0x75, 0x66, 0x66, 0x61, 0x6c, +0x6f, 0x77, 0x61, 0x74, 0x65, 0x72, 0xd83d, 0xdc02, 0x3a, 0x6f, 0x78, 0x3a, +0x6f, 0x78, 0xd83d, 0xdc04, 0x3a, 0x63, 0x6f, 0x77, 0x32, 0x3a, 0x63, 0x6f, +0x77, 0x32, 0xd83e, 0xdd8c, 0x3a, 0x64, 0x65, 0x65, 0x72, 0x3a, 0x64, 0x65, +0x65, 0x72, 0xd83d, 0xdc2a, 0x3a, 0x64, 0x72, 0x6f, 0x6d, 0x65, 0x64, 0x61, +0x72, 0x79, 0x5f, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x3a, 0x63, 0x61, 0x6d, +0x65, 0x6c, 0x64, 0x72, 0x6f, 0x6d, 0x65, 0x64, 0x61, 0x72, 0x79, 0xd83d, +0xdc2b, 0x3a, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x3a, 0x63, 0x61, 0x6d, 0x65, +0x6c, 0xd83d, 0xdc18, 0x3a, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x61, 0x6e, 0x74, +0x3a, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x61, 0x6e, 0x74, 0xd83e, 0xdd8f, 0x3a, +0x72, 0x68, 0x69, 0x6e, 0x6f, 0x63, 0x65, 0x72, 0x6f, 0x73, 0x3a, 0x72, +0x68, 0x69, 0x6e, 0x6f, 0x63, 0x65, 0x72, 0x6f, 0x73, 0xd83e, 0xdd8f, 0x3a, +0x72, 0x68, 0x69, 0x6e, 0x6f, 0x3a, 0x72, 0x68, 0x69, 0x6e, 0x6f, 0xd83e, +0xdd8d, 0x3a, 0x67, 0x6f, 0x72, 0x69, 0x6c, 0x6c, 0x61, 0x3a, 0x67, 0x6f, +0x72, 0x69, 0x6c, 0x6c, 0x61, 0xd83d, 0xdc0e, 0x3a, 0x72, 0x61, 0x63, 0x65, +0x68, 0x6f, 0x72, 0x73, 0x65, 0x3a, 0x72, 0x61, 0x63, 0x65, 0x68, 0x6f, +0x72, 0x73, 0x65, 0xd83d, 0xdc16, 0x3a, 0x70, 0x69, 0x67, 0x32, 0x3a, 0x70, +0x69, 0x67, 0x32, 0xd83d, 0xdc10, 0x3a, 0x67, 0x6f, 0x61, 0x74, 0x3a, 0x67, +0x6f, 0x61, 0x74, 0xd83d, 0xdc0f, 0x3a, 0x72, 0x61, 0x6d, 0x3a, 0x72, 0x61, +0x6d, 0xd83d, 0xdc11, 0x3a, 0x73, 0x68, 0x65, 0x65, 0x70, 0x3a, 0x73, 0x68, +0x65, 0x65, 0x70, 0xd83d, 0xdc15, 0x3a, 0x64, 0x6f, 0x67, 0x32, 0x3a, 0x64, +0x6f, 0x67, 0x32, 0xd83d, 0xdc29, 0x3a, 0x70, 0x6f, 0x6f, 0x64, 0x6c, 0x65, +0x3a, 0x70, 0x6f, 0x6f, 0x64, 0x6c, 0x65, 0xd83d, 0xdc08, 0x3a, 0x63, 0x61, +0x74, 0x32, 0x3a, 0x63, 0x61, 0x74, 0x32, 0xd83d, 0xdc13, 0x3a, 0x72, 0x6f, +0x6f, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x72, 0x6f, 0x6f, 0x73, 0x74, 0x65, +0x72, 0xd83e, 0xdd83, 0x3a, 0x74, 0x75, 0x72, 0x6b, 0x65, 0x79, 0x3a, 0x74, +0x75, 0x72, 0x6b, 0x65, 0x79, 0xd83d, 0xdd4a, 0x3a, 0x64, 0x6f, 0x76, 0x65, +0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x65, 0x61, 0x63, 0x65, 0x3a, 0x64, 0x6f, +0x76, 0x65, 0x6f, 0x66, 0x70, 0x65, 0x61, 0x63, 0x65, 0xd83d, 0xdd4a, 0x3a, +0x64, 0x6f, 0x76, 0x65, 0x3a, 0x64, 0x6f, 0x76, 0x65, 0xd83d, 0xdc07, 0x3a, +0x72, 0x61, 0x62, 0x62, 0x69, 0x74, 0x32, 0x3a, 0x72, 0x61, 0x62, 0x62, +0x69, 0x74, 0x32, 0xd83d, 0xdc01, 0x3a, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x32, +0x3a, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x32, 0xd83d, 0xdc00, 0x3a, 0x72, 0x61, +0x74, 0x3a, 0x72, 0x61, 0x74, 0xd83d, 0xdc3f, 0x3a, 0x63, 0x68, 0x69, 0x70, +0x6d, 0x75, 0x6e, 0x6b, 0x3a, 0x63, 0x68, 0x69, 0x70, 0x6d, 0x75, 0x6e, +0x6b, 0xd83d, 0xdc3e, 0x3a, 0x70, 0x61, 0x77, 0x5f, 0x70, 0x72, 0x69, 0x6e, +0x74, 0x73, 0x3a, 0x70, 0x61, 0x77, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, +0xd83d, 0xdc3e, 0x3a, 0x66, 0x65, 0x65, 0x74, 0x3a, 0x66, 0x65, 0x65, 0x74, +0xd83d, 0xdc09, 0x3a, 0x64, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x3a, 0x64, 0x72, +0x61, 0x67, 0x6f, 0x6e, 0xd83d, 0xdc32, 0x3a, 0x64, 0x72, 0x61, 0x67, 0x6f, +0x6e, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x64, 0x72, 0x61, 0x67, 0x6f, +0x6e, 0x66, 0x61, 0x63, 0x65, 0xd83c, 0xdf35, 0x3a, 0x63, 0x61, 0x63, 0x74, +0x75, 0x73, 0x3a, 0x63, 0x61, 0x63, 0x74, 0x75, 0x73, 0xd83c, 0xdf84, 0x3a, +0x63, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x5f, 0x74, 0x72, +0x65, 0x65, 0x3a, 0x63, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, +0x74, 0x72, 0x65, 0x65, 0xd83c, 0xdf32, 0x3a, 0x65, 0x76, 0x65, 0x72, 0x67, +0x72, 0x65, 0x65, 0x6e, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x3a, 0x65, 0x76, +0x65, 0x72, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x74, 0x72, 0x65, 0x65, 0xd83c, +0xdf33, 0x3a, 0x64, 0x65, 0x63, 0x69, 0x64, 0x75, 0x6f, 0x75, 0x73, 0x5f, +0x74, 0x72, 0x65, 0x65, 0x3a, 0x64, 0x65, 0x63, 0x69, 0x64, 0x75, 0x6f, +0x75, 0x73, 0x74, 0x72, 0x65, 0x65, 0xd83c, 0xdf34, 0x3a, 0x70, 0x61, 0x6c, +0x6d, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x3a, 0x70, 0x61, 0x6c, 0x6d, 0x74, +0x72, 0x65, 0x65, 0xd83c, 0xdf31, 0x3a, 0x73, 0x65, 0x65, 0x64, 0x6c, 0x69, +0x6e, 0x67, 0x3a, 0x73, 0x65, 0x65, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0xd83c, +0xdf3f, 0x3a, 0x68, 0x65, 0x72, 0x62, 0x3a, 0x68, 0x65, 0x72, 0x62, 0x2618, +0xfe0f, 0x3a, 0x73, 0x68, 0x61, 0x6d, 0x72, 0x6f, 0x63, 0x6b, 0x3a, 0x73, +0x68, 0x61, 0x6d, 0x72, 0x6f, 0x63, 0x6b, 0xd83c, 0xdf40, 0x3a, 0x66, 0x6f, +0x75, 0x72, 0x5f, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x63, 0x6c, 0x6f, 0x76, +0x65, 0x72, 0x3a, 0x63, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6f, 0x75, +0x72, 0x6c, 0x65, 0x61, 0x66, 0xd83c, 0xdf8d, 0x3a, 0x62, 0x61, 0x6d, 0x62, +0x6f, 0x6f, 0x3a, 0x62, 0x61, 0x6d, 0x62, 0x6f, 0x6f, 0xd83c, 0xdf8b, 0x3a, +0x74, 0x61, 0x6e, 0x61, 0x62, 0x61, 0x74, 0x61, 0x5f, 0x74, 0x72, 0x65, +0x65, 0x3a, 0x74, 0x61, 0x6e, 0x61, 0x62, 0x61, 0x74, 0x61, 0x74, 0x72, +0x65, 0x65, 0xd83c, 0xdf43, 0x3a, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x3a, +0x6c, 0x65, 0x61, 0x76, 0x65, 0x73, 0xd83c, 0xdf42, 0x3a, 0x66, 0x61, 0x6c, +0x6c, 0x65, 0x6e, 0x5f, 0x6c, 0x65, 0x61, 0x66, 0x3a, 0x66, 0x61, 0x6c, +0x6c, 0x65, 0x6e, 0x6c, 0x65, 0x61, 0x66, 0xd83c, 0xdf41, 0x3a, 0x6d, 0x61, +0x70, 0x6c, 0x65, 0x5f, 0x6c, 0x65, 0x61, 0x66, 0x3a, 0x6c, 0x65, 0x61, +0x66, 0x6d, 0x61, 0x70, 0x6c, 0x65, 0xd83c, 0xdf44, 0x3a, 0x6d, 0x75, 0x73, +0x68, 0x72, 0x6f, 0x6f, 0x6d, 0x3a, 0x6d, 0x75, 0x73, 0x68, 0x72, 0x6f, +0x6f, 0x6d, 0xd83c, 0xdf3e, 0x3a, 0x65, 0x61, 0x72, 0x5f, 0x6f, 0x66, 0x5f, +0x72, 0x69, 0x63, 0x65, 0x3a, 0x65, 0x61, 0x72, 0x6f, 0x66, 0x72, 0x69, +0x63, 0x65, 0xd83d, 0xdc90, 0x3a, 0x62, 0x6f, 0x75, 0x71, 0x75, 0x65, 0x74, +0x3a, 0x62, 0x6f, 0x75, 0x71, 0x75, 0x65, 0x74, 0xd83c, 0xdf37, 0x3a, 0x74, +0x75, 0x6c, 0x69, 0x70, 0x3a, 0x74, 0x75, 0x6c, 0x69, 0x70, 0xd83c, 0xdf39, +0x3a, 0x72, 0x6f, 0x73, 0x65, 0x3a, 0x72, 0x6f, 0x73, 0x65, 0xd83e, 0xdd40, +0x3a, 0x77, 0x69, 0x6c, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x6c, 0x6f, 0x77, +0x65, 0x72, 0x3a, 0x66, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x77, 0x69, 0x6c, +0x74, 0x65, 0x64, 0xd83e, 0xdd40, 0x3a, 0x77, 0x69, 0x6c, 0x74, 0x65, 0x64, +0x5f, 0x72, 0x6f, 0x73, 0x65, 0x3a, 0x72, 0x6f, 0x73, 0x65, 0x77, 0x69, +0x6c, 0x74, 0x65, 0x64, 0xd83c, 0xdf3b, 0x3a, 0x73, 0x75, 0x6e, 0x66, 0x6c, +0x6f, 0x77, 0x65, 0x72, 0x3a, 0x73, 0x75, 0x6e, 0x66, 0x6c, 0x6f, 0x77, +0x65, 0x72, 0xd83c, 0xdf3c, 0x3a, 0x62, 0x6c, 0x6f, 0x73, 0x73, 0x6f, 0x6d, +0x3a, 0x62, 0x6c, 0x6f, 0x73, 0x73, 0x6f, 0x6d, 0xd83c, 0xdf38, 0x3a, 0x63, +0x68, 0x65, 0x72, 0x72, 0x79, 0x5f, 0x62, 0x6c, 0x6f, 0x73, 0x73, 0x6f, +0x6d, 0x3a, 0x62, 0x6c, 0x6f, 0x73, 0x73, 0x6f, 0x6d, 0x63, 0x68, 0x65, +0x72, 0x72, 0x79, 0xd83c, 0xdf3a, 0x3a, 0x68, 0x69, 0x62, 0x69, 0x73, 0x63, +0x75, 0x73, 0x3a, 0x68, 0x69, 0x62, 0x69, 0x73, 0x63, 0x75, 0x73, 0xd83c, +0xdf0e, 0x3a, 0x65, 0x61, 0x72, 0x74, 0x68, 0x5f, 0x61, 0x6d, 0x65, 0x72, +0x69, 0x63, 0x61, 0x73, 0x3a, 0x61, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x73, 0x65, 0x61, 0x72, 0x74, 0x68, 0xd83c, 0xdf0d, 0x3a, 0x65, 0x61, 0x72, +0x74, 0x68, 0x5f, 0x61, 0x66, 0x72, 0x69, 0x63, 0x61, 0x3a, 0x61, 0x66, +0x72, 0x69, 0x63, 0x61, 0x65, 0x61, 0x72, 0x74, 0x68, 0xd83c, 0xdf0f, 0x3a, +0x65, 0x61, 0x72, 0x74, 0x68, 0x5f, 0x61, 0x73, 0x69, 0x61, 0x3a, 0x61, +0x73, 0x69, 0x61, 0x65, 0x61, 0x72, 0x74, 0x68, 0xd83c, 0xdf15, 0x3a, 0x66, +0x75, 0x6c, 0x6c, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x3a, 0x66, 0x75, 0x6c, +0x6c, 0x6d, 0x6f, 0x6f, 0x6e, 0xd83c, 0xdf16, 0x3a, 0x77, 0x61, 0x6e, 0x69, +0x6e, 0x67, 0x5f, 0x67, 0x69, 0x62, 0x62, 0x6f, 0x75, 0x73, 0x5f, 0x6d, +0x6f, 0x6f, 0x6e, 0x3a, 0x67, 0x69, 0x62, 0x62, 0x6f, 0x75, 0x73, 0x6d, +0x6f, 0x6f, 0x6e, 0x77, 0x61, 0x6e, 0x69, 0x6e, 0x67, 0xd83c, 0xdf17, 0x3a, +0x6c, 0x61, 0x73, 0x74, 0x5f, 0x71, 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, +0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x3a, 0x6c, 0x61, 0x73, 0x74, 0x6d, 0x6f, +0x6f, 0x6e, 0x71, 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, 0xd83c, 0xdf18, 0x3a, +0x77, 0x61, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x72, 0x65, 0x73, 0x63, +0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x3a, 0x63, 0x72, 0x65, +0x73, 0x63, 0x65, 0x6e, 0x74, 0x6d, 0x6f, 0x6f, 0x6e, 0x77, 0x61, 0x6e, +0x69, 0x6e, 0x67, 0xd83c, 0xdf11, 0x3a, 0x6e, 0x65, 0x77, 0x5f, 0x6d, 0x6f, +0x6f, 0x6e, 0x3a, 0x6d, 0x6f, 0x6f, 0x6e, 0x6e, 0x65, 0x77, 0xd83c, 0xdf12, +0x3a, 0x77, 0x61, 0x78, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x72, 0x65, 0x73, +0x63, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x3a, 0x63, 0x72, +0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x6d, 0x6f, 0x6f, 0x6e, 0x77, 0x61, +0x78, 0x69, 0x6e, 0x67, 0xd83c, 0xdf13, 0x3a, 0x66, 0x69, 0x72, 0x73, 0x74, +0x5f, 0x71, 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x6f, +0x6e, 0x3a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x6d, 0x6f, 0x6f, 0x6e, 0x71, +0x75, 0x61, 0x72, 0x74, 0x65, 0x72, 0xd83c, 0xdf14, 0x3a, 0x77, 0x61, 0x78, +0x69, 0x6e, 0x67, 0x5f, 0x67, 0x69, 0x62, 0x62, 0x6f, 0x75, 0x73, 0x5f, +0x6d, 0x6f, 0x6f, 0x6e, 0x3a, 0x67, 0x69, 0x62, 0x62, 0x6f, 0x75, 0x73, +0x6d, 0x6f, 0x6f, 0x6e, 0x77, 0x61, 0x78, 0x69, 0x6e, 0x67, 0xd83c, 0xdf1a, +0x3a, 0x6e, 0x65, 0x77, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x5f, 0x77, 0x69, +0x74, 0x68, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, +0x6d, 0x6f, 0x6f, 0x6e, 0x6e, 0x65, 0x77, 0x77, 0x69, 0x74, 0x68, 0xd83c, +0xdf1d, 0x3a, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x5f, +0x77, 0x69, 0x74, 0x68, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, +0x63, 0x65, 0x66, 0x75, 0x6c, 0x6c, 0x6d, 0x6f, 0x6f, 0x6e, 0x77, 0x69, +0x74, 0x68, 0xd83c, 0xdf1e, 0x3a, 0x73, 0x75, 0x6e, 0x5f, 0x77, 0x69, 0x74, +0x68, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x73, +0x75, 0x6e, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf1b, 0x3a, 0x66, 0x69, 0x72, +0x73, 0x74, 0x5f, 0x71, 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6d, +0x6f, 0x6f, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x66, 0x61, 0x63, +0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x66, 0x69, 0x72, 0x73, 0x74, 0x6d, +0x6f, 0x6f, 0x6e, 0x71, 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, 0x77, 0x69, +0x74, 0x68, 0xd83c, 0xdf1c, 0x3a, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x71, 0x75, +0x61, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x5f, 0x77, +0x69, 0x74, 0x68, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, +0x65, 0x6c, 0x61, 0x73, 0x74, 0x6d, 0x6f, 0x6f, 0x6e, 0x71, 0x75, 0x61, +0x72, 0x74, 0x65, 0x72, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf19, 0x3a, 0x63, +0x72, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, +0x3a, 0x63, 0x72, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x6d, 0x6f, 0x6f, +0x6e, 0xd83d, 0xdcab, 0x3a, 0x64, 0x69, 0x7a, 0x7a, 0x79, 0x3a, 0x64, 0x69, +0x7a, 0x7a, 0x79, 0x2b50, 0xfe0f, 0x3a, 0x73, 0x74, 0x61, 0x72, 0x3a, 0x73, +0x74, 0x61, 0x72, 0xd83c, 0xdf1f, 0x3a, 0x73, 0x74, 0x61, 0x72, 0x32, 0x3a, +0x73, 0x74, 0x61, 0x72, 0x32, 0x2728, 0x3a, 0x73, 0x70, 0x61, 0x72, 0x6b, +0x6c, 0x65, 0x73, 0x3a, 0x73, 0x70, 0x61, 0x72, 0x6b, 0x6c, 0x65, 0x73, +0x26a1, 0xfe0f, 0x3a, 0x7a, 0x61, 0x70, 0x3a, 0x7a, 0x61, 0x70, 0xd83d, 0xdd25, +0x3a, 0x66, 0x6c, 0x61, 0x6d, 0x65, 0x3a, 0x66, 0x6c, 0x61, 0x6d, 0x65, +0xd83d, 0xdd25, 0x3a, 0x66, 0x69, 0x72, 0x65, 0x3a, 0x66, 0x69, 0x72, 0x65, +0xd83d, 0xdca5, 0x3a, 0x62, 0x6f, 0x6f, 0x6d, 0x3a, 0x62, 0x6f, 0x6f, 0x6d, +0x2604, 0xfe0f, 0x3a, 0x63, 0x6f, 0x6d, 0x65, 0x74, 0x3a, 0x63, 0x6f, 0x6d, +0x65, 0x74, 0x2600, 0xfe0f, 0x3a, 0x73, 0x75, 0x6e, 0x6e, 0x79, 0x3a, 0x73, +0x75, 0x6e, 0x6e, 0x79, 0xd83c, 0xdf24, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, +0x5f, 0x73, 0x75, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x73, 0x6d, +0x61, 0x6c, 0x6c, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3a, 0x63, 0x6c, +0x6f, 0x75, 0x64, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x73, 0x75, 0x6e, 0x77, +0x68, 0x69, 0x74, 0x65, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf24, 0x3a, 0x77, +0x68, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6e, 0x5f, 0x73, 0x6d, 0x61, +0x6c, 0x6c, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3a, 0x63, 0x6c, 0x6f, +0x75, 0x64, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x73, 0x75, 0x6e, 0x77, 0x68, +0x69, 0x74, 0x65, 0x26c5, 0xfe0f, 0x3a, 0x70, 0x61, 0x72, 0x74, 0x6c, 0x79, +0x5f, 0x73, 0x75, 0x6e, 0x6e, 0x79, 0x3a, 0x70, 0x61, 0x72, 0x74, 0x6c, +0x79, 0x73, 0x75, 0x6e, 0x6e, 0x79, 0xd83c, 0xdf25, 0x3a, 0x77, 0x68, 0x69, +0x74, 0x65, 0x5f, 0x73, 0x75, 0x6e, 0x5f, 0x62, 0x65, 0x68, 0x69, 0x6e, +0x64, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3a, 0x62, 0x65, 0x68, 0x69, +0x6e, 0x64, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x75, 0x6e, 0x77, 0x68, +0x69, 0x74, 0x65, 0xd83c, 0xdf25, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, +0x73, 0x75, 0x6e, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3a, 0x63, 0x6c, +0x6f, 0x75, 0x64, 0x73, 0x75, 0x6e, 0x77, 0x68, 0x69, 0x74, 0x65, 0xd83c, +0xdf26, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6e, 0x5f, +0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, +0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x3a, 0x62, +0x65, 0x68, 0x69, 0x6e, 0x64, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x72, 0x61, +0x69, 0x6e, 0x73, 0x75, 0x6e, 0x77, 0x68, 0x69, 0x74, 0x65, 0x77, 0x69, +0x74, 0x68, 0xd83c, 0xdf26, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x73, +0x75, 0x6e, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x63, 0x6c, 0x6f, 0x75, +0x64, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x72, 0x61, 0x69, 0x6e, 0x73, +0x75, 0x6e, 0x77, 0x68, 0x69, 0x74, 0x65, 0xd83c, 0xdf08, 0x3a, 0x72, 0x61, +0x69, 0x6e, 0x62, 0x6f, 0x77, 0x3a, 0x72, 0x61, 0x69, 0x6e, 0x62, 0x6f, +0x77, 0x2601, 0xfe0f, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3a, 0x63, 0x6c, +0x6f, 0x75, 0x64, 0xd83c, 0xdf27, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, +0x77, 0x69, 0x74, 0x68, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x3a, 0x63, 0x6c, +0x6f, 0x75, 0x64, 0x72, 0x61, 0x69, 0x6e, 0x77, 0x69, 0x74, 0x68, 0xd83c, +0xdf27, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x72, 0x61, 0x69, 0x6e, +0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x72, 0x61, 0x69, 0x6e, 0x26c8, 0x3a, +0x74, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x6f, 0x75, +0x64, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x3a, 0x61, +0x6e, 0x64, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x72, 0x61, 0x69, 0x6e, 0x74, +0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x26c8, 0x3a, 0x74, 0x68, 0x75, 0x6e, +0x64, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x72, 0x61, +0x69, 0x6e, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x72, 0x61, 0x69, 0x6e, +0x74, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0xd83c, 0xdf29, 0x3a, 0x63, 0x6c, +0x6f, 0x75, 0x64, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6c, 0x69, 0x67, +0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, +0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x77, 0x69, 0x74, +0x68, 0xd83c, 0xdf29, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x6c, 0x69, +0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x63, 0x6c, 0x6f, 0x75, +0x64, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0xd83c, 0xdf28, +0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, +0x73, 0x6e, 0x6f, 0x77, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x6e, +0x6f, 0x77, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf28, 0x3a, 0x63, 0x6c, 0x6f, +0x75, 0x64, 0x5f, 0x73, 0x6e, 0x6f, 0x77, 0x3a, 0x63, 0x6c, 0x6f, 0x75, +0x64, 0x73, 0x6e, 0x6f, 0x77, 0x2603, 0xfe0f, 0x3a, 0x73, 0x6e, 0x6f, 0x77, +0x6d, 0x61, 0x6e, 0x32, 0x3a, 0x73, 0x6e, 0x6f, 0x77, 0x6d, 0x61, 0x6e, +0x32, 0x26c4, 0xfe0f, 0x3a, 0x73, 0x6e, 0x6f, 0x77, 0x6d, 0x61, 0x6e, 0x3a, +0x73, 0x6e, 0x6f, 0x77, 0x6d, 0x61, 0x6e, 0x2744, 0xfe0f, 0x3a, 0x73, 0x6e, +0x6f, 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x3a, 0x73, 0x6e, 0x6f, 0x77, +0x66, 0x6c, 0x61, 0x6b, 0x65, 0xd83c, 0xdf2c, 0x3a, 0x77, 0x69, 0x6e, 0x64, +0x5f, 0x62, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, +0x65, 0x3a, 0x62, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x66, 0x61, 0x63, +0x65, 0x77, 0x69, 0x6e, 0x64, 0xd83d, 0xdca8, 0x3a, 0x64, 0x61, 0x73, 0x68, +0x3a, 0x64, 0x61, 0x73, 0x68, 0xd83c, 0xdf2a, 0x3a, 0x63, 0x6c, 0x6f, 0x75, +0x64, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x74, 0x6f, 0x72, 0x6e, 0x61, +0x64, 0x6f, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x74, 0x6f, 0x72, 0x6e, +0x61, 0x64, 0x6f, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf2a, 0x3a, 0x63, 0x6c, +0x6f, 0x75, 0x64, 0x5f, 0x74, 0x6f, 0x72, 0x6e, 0x61, 0x64, 0x6f, 0x3a, +0x63, 0x6c, 0x6f, 0x75, 0x64, 0x74, 0x6f, 0x72, 0x6e, 0x61, 0x64, 0x6f, +0xd83c, 0xdf2b, 0x3a, 0x66, 0x6f, 0x67, 0x3a, 0x66, 0x6f, 0x67, 0xd83c, 0xdf0a, +0x3a, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x3a, 0x6f, 0x63, 0x65, 0x61, 0x6e, +0xd83d, 0xdca7, 0x3a, 0x64, 0x72, 0x6f, 0x70, 0x6c, 0x65, 0x74, 0x3a, 0x64, +0x72, 0x6f, 0x70, 0x6c, 0x65, 0x74, 0xd83d, 0xdca6, 0x3a, 0x73, 0x77, 0x65, +0x61, 0x74, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x73, 0x3a, 0x64, 0x72, 0x6f, +0x70, 0x73, 0x73, 0x77, 0x65, 0x61, 0x74, 0x2614, 0xfe0f, 0x3a, 0x75, 0x6d, +0x62, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x3a, 0x75, 0x6d, 0x62, 0x72, 0x65, +0x6c, 0x6c, 0x61, 0xd83c, 0xdf4f, 0x3a, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x5f, +0x61, 0x70, 0x70, 0x6c, 0x65, 0x3a, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x67, +0x72, 0x65, 0x65, 0x6e, 0xd83c, 0xdf4e, 0x3a, 0x61, 0x70, 0x70, 0x6c, 0x65, +0x3a, 0x61, 0x70, 0x70, 0x6c, 0x65, 0xd83c, 0xdf50, 0x3a, 0x70, 0x65, 0x61, +0x72, 0x3a, 0x70, 0x65, 0x61, 0x72, 0xd83c, 0xdf4a, 0x3a, 0x74, 0x61, 0x6e, +0x67, 0x65, 0x72, 0x69, 0x6e, 0x65, 0x3a, 0x74, 0x61, 0x6e, 0x67, 0x65, +0x72, 0x69, 0x6e, 0x65, 0xd83c, 0xdf4b, 0x3a, 0x6c, 0x65, 0x6d, 0x6f, 0x6e, +0x3a, 0x6c, 0x65, 0x6d, 0x6f, 0x6e, 0xd83c, 0xdf4c, 0x3a, 0x62, 0x61, 0x6e, +0x61, 0x6e, 0x61, 0x3a, 0x62, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0xd83c, 0xdf49, +0x3a, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x6c, 0x6f, 0x6e, 0x3a, +0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x6c, 0x6f, 0x6e, 0xd83c, 0xdf47, +0x3a, 0x67, 0x72, 0x61, 0x70, 0x65, 0x73, 0x3a, 0x67, 0x72, 0x61, 0x70, +0x65, 0x73, 0xd83c, 0xdf53, 0x3a, 0x73, 0x74, 0x72, 0x61, 0x77, 0x62, 0x65, +0x72, 0x72, 0x79, 0x3a, 0x73, 0x74, 0x72, 0x61, 0x77, 0x62, 0x65, 0x72, +0x72, 0x79, 0xd83c, 0xdf48, 0x3a, 0x6d, 0x65, 0x6c, 0x6f, 0x6e, 0x3a, 0x6d, +0x65, 0x6c, 0x6f, 0x6e, 0xd83c, 0xdf52, 0x3a, 0x63, 0x68, 0x65, 0x72, 0x72, +0x69, 0x65, 0x73, 0x3a, 0x63, 0x68, 0x65, 0x72, 0x72, 0x69, 0x65, 0x73, +0xd83c, 0xdf51, 0x3a, 0x70, 0x65, 0x61, 0x63, 0x68, 0x3a, 0x70, 0x65, 0x61, +0x63, 0x68, 0xd83c, 0xdf4d, 0x3a, 0x70, 0x69, 0x6e, 0x65, 0x61, 0x70, 0x70, +0x6c, 0x65, 0x3a, 0x70, 0x69, 0x6e, 0x65, 0x61, 0x70, 0x70, 0x6c, 0x65, +0xd83e, 0xdd5d, 0x3a, 0x6b, 0x69, 0x77, 0x69, 0x66, 0x72, 0x75, 0x69, 0x74, +0x3a, 0x6b, 0x69, 0x77, 0x69, 0x66, 0x72, 0x75, 0x69, 0x74, 0xd83e, 0xdd5d, +0x3a, 0x6b, 0x69, 0x77, 0x69, 0x3a, 0x6b, 0x69, 0x77, 0x69, 0xd83e, 0xdd51, +0x3a, 0x61, 0x76, 0x6f, 0x63, 0x61, 0x64, 0x6f, 0x3a, 0x61, 0x76, 0x6f, +0x63, 0x61, 0x64, 0x6f, 0xd83c, 0xdf45, 0x3a, 0x74, 0x6f, 0x6d, 0x61, 0x74, +0x6f, 0x3a, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x6f, 0xd83c, 0xdf46, 0x3a, 0x65, +0x67, 0x67, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x3a, 0x65, 0x67, 0x67, 0x70, +0x6c, 0x61, 0x6e, 0x74, 0xd83e, 0xdd52, 0x3a, 0x63, 0x75, 0x63, 0x75, 0x6d, +0x62, 0x65, 0x72, 0x3a, 0x63, 0x75, 0x63, 0x75, 0x6d, 0x62, 0x65, 0x72, +0xd83e, 0xdd55, 0x3a, 0x63, 0x61, 0x72, 0x72, 0x6f, 0x74, 0x3a, 0x63, 0x61, +0x72, 0x72, 0x6f, 0x74, 0xd83c, 0xdf3d, 0x3a, 0x63, 0x6f, 0x72, 0x6e, 0x3a, +0x63, 0x6f, 0x72, 0x6e, 0xd83c, 0xdf36, 0x3a, 0x68, 0x6f, 0x74, 0x5f, 0x70, +0x65, 0x70, 0x70, 0x65, 0x72, 0x3a, 0x68, 0x6f, 0x74, 0x70, 0x65, 0x70, +0x70, 0x65, 0x72, 0xd83e, 0xdd54, 0x3a, 0x70, 0x6f, 0x74, 0x61, 0x74, 0x6f, +0x3a, 0x70, 0x6f, 0x74, 0x61, 0x74, 0x6f, 0xd83c, 0xdf60, 0x3a, 0x73, 0x77, +0x65, 0x65, 0x74, 0x5f, 0x70, 0x6f, 0x74, 0x61, 0x74, 0x6f, 0x3a, 0x70, +0x6f, 0x74, 0x61, 0x74, 0x6f, 0x73, 0x77, 0x65, 0x65, 0x74, 0xd83c, 0xdf30, +0x3a, 0x63, 0x68, 0x65, 0x73, 0x74, 0x6e, 0x75, 0x74, 0x3a, 0x63, 0x68, +0x65, 0x73, 0x74, 0x6e, 0x75, 0x74, 0xd83e, 0xdd5c, 0x3a, 0x73, 0x68, 0x65, +0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x61, 0x6e, 0x75, 0x74, 0x3a, +0x70, 0x65, 0x61, 0x6e, 0x75, 0x74, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x65, +0x64, 0xd83e, 0xdd5c, 0x3a, 0x70, 0x65, 0x61, 0x6e, 0x75, 0x74, 0x73, 0x3a, +0x70, 0x65, 0x61, 0x6e, 0x75, 0x74, 0x73, 0xd83c, 0xdf6f, 0x3a, 0x68, 0x6f, +0x6e, 0x65, 0x79, 0x5f, 0x70, 0x6f, 0x74, 0x3a, 0x68, 0x6f, 0x6e, 0x65, +0x79, 0x70, 0x6f, 0x74, 0xd83e, 0xdd50, 0x3a, 0x63, 0x72, 0x6f, 0x69, 0x73, +0x73, 0x61, 0x6e, 0x74, 0x3a, 0x63, 0x72, 0x6f, 0x69, 0x73, 0x73, 0x61, +0x6e, 0x74, 0xd83c, 0xdf5e, 0x3a, 0x62, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x62, +0x72, 0x65, 0x61, 0x64, 0xd83e, 0xdd56, 0x3a, 0x62, 0x61, 0x67, 0x75, 0x65, +0x74, 0x74, 0x65, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x62, 0x61, +0x67, 0x75, 0x65, 0x74, 0x74, 0x65, 0x62, 0x72, 0x65, 0x61, 0x64, 0xd83e, +0xdd56, 0x3a, 0x66, 0x72, 0x65, 0x6e, 0x63, 0x68, 0x5f, 0x62, 0x72, 0x65, +0x61, 0x64, 0x3a, 0x62, 0x72, 0x65, 0x61, 0x64, 0x66, 0x72, 0x65, 0x6e, +0x63, 0x68, 0xd83e, 0xddc0, 0x3a, 0x63, 0x68, 0x65, 0x65, 0x73, 0x65, 0x5f, +0x77, 0x65, 0x64, 0x67, 0x65, 0x3a, 0x63, 0x68, 0x65, 0x65, 0x73, 0x65, +0x77, 0x65, 0x64, 0x67, 0x65, 0xd83e, 0xddc0, 0x3a, 0x63, 0x68, 0x65, 0x65, +0x73, 0x65, 0x3a, 0x63, 0x68, 0x65, 0x65, 0x73, 0x65, 0xd83e, 0xdd5a, 0x3a, +0x65, 0x67, 0x67, 0x3a, 0x65, 0x67, 0x67, 0xd83c, 0xdf73, 0x3a, 0x63, 0x6f, +0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x6e, +0x67, 0xd83e, 0xdd53, 0x3a, 0x62, 0x61, 0x63, 0x6f, 0x6e, 0x3a, 0x62, 0x61, +0x63, 0x6f, 0x6e, 0xd83e, 0xdd5e, 0x3a, 0x70, 0x61, 0x6e, 0x63, 0x61, 0x6b, +0x65, 0x73, 0x3a, 0x70, 0x61, 0x6e, 0x63, 0x61, 0x6b, 0x65, 0x73, 0xd83c, +0xdf64, 0x3a, 0x66, 0x72, 0x69, 0x65, 0x64, 0x5f, 0x73, 0x68, 0x72, 0x69, +0x6d, 0x70, 0x3a, 0x66, 0x72, 0x69, 0x65, 0x64, 0x73, 0x68, 0x72, 0x69, +0x6d, 0x70, 0xd83c, 0xdf57, 0x3a, 0x70, 0x6f, 0x75, 0x6c, 0x74, 0x72, 0x79, +0x5f, 0x6c, 0x65, 0x67, 0x3a, 0x6c, 0x65, 0x67, 0x70, 0x6f, 0x75, 0x6c, +0x74, 0x72, 0x79, 0xd83c, 0xdf56, 0x3a, 0x6d, 0x65, 0x61, 0x74, 0x5f, 0x6f, +0x6e, 0x5f, 0x62, 0x6f, 0x6e, 0x65, 0x3a, 0x62, 0x6f, 0x6e, 0x65, 0x6d, +0x65, 0x61, 0x74, 0x6f, 0x6e, 0xd83c, 0xdf55, 0x3a, 0x70, 0x69, 0x7a, 0x7a, +0x61, 0x3a, 0x70, 0x69, 0x7a, 0x7a, 0x61, 0xd83c, 0xdf2d, 0x3a, 0x68, 0x6f, +0x74, 0x5f, 0x64, 0x6f, 0x67, 0x3a, 0x64, 0x6f, 0x67, 0x68, 0x6f, 0x74, +0xd83c, 0xdf2d, 0x3a, 0x68, 0x6f, 0x74, 0x64, 0x6f, 0x67, 0x3a, 0x68, 0x6f, +0x74, 0x64, 0x6f, 0x67, 0xd83c, 0xdf54, 0x3a, 0x68, 0x61, 0x6d, 0x62, 0x75, +0x72, 0x67, 0x65, 0x72, 0x3a, 0x68, 0x61, 0x6d, 0x62, 0x75, 0x72, 0x67, +0x65, 0x72, 0xd83c, 0xdf5f, 0x3a, 0x66, 0x72, 0x69, 0x65, 0x73, 0x3a, 0x66, +0x72, 0x69, 0x65, 0x73, 0xd83e, 0xdd59, 0x3a, 0x73, 0x74, 0x75, 0x66, 0x66, +0x65, 0x64, 0x5f, 0x70, 0x69, 0x74, 0x61, 0x3a, 0x70, 0x69, 0x74, 0x61, +0x73, 0x74, 0x75, 0x66, 0x66, 0x65, 0x64, 0xd83e, 0xdd59, 0x3a, 0x73, 0x74, +0x75, 0x66, 0x66, 0x65, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x74, 0x62, 0x72, +0x65, 0x61, 0x64, 0x3a, 0x66, 0x6c, 0x61, 0x74, 0x62, 0x72, 0x65, 0x61, +0x64, 0x73, 0x74, 0x75, 0x66, 0x66, 0x65, 0x64, 0xd83c, 0xdf2e, 0x3a, 0x74, +0x61, 0x63, 0x6f, 0x3a, 0x74, 0x61, 0x63, 0x6f, 0xd83c, 0xdf2f, 0x3a, 0x62, +0x75, 0x72, 0x72, 0x69, 0x74, 0x6f, 0x3a, 0x62, 0x75, 0x72, 0x72, 0x69, +0x74, 0x6f, 0xd83e, 0xdd57, 0x3a, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x5f, 0x73, +0x61, 0x6c, 0x61, 0x64, 0x3a, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x61, +0x6c, 0x61, 0x64, 0xd83e, 0xdd57, 0x3a, 0x73, 0x61, 0x6c, 0x61, 0x64, 0x3a, +0x73, 0x61, 0x6c, 0x61, 0x64, 0xd83e, 0xdd58, 0x3a, 0x70, 0x61, 0x65, 0x6c, +0x6c, 0x61, 0x3a, 0x70, 0x61, 0x65, 0x6c, 0x6c, 0x61, 0xd83e, 0xdd58, 0x3a, +0x73, 0x68, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x70, 0x61, 0x6e, 0x5f, +0x6f, 0x66, 0x5f, 0x66, 0x6f, 0x6f, 0x64, 0x3a, 0x66, 0x6f, 0x6f, 0x64, +0x6f, 0x66, 0x70, 0x61, 0x6e, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x6f, 0x77, +0xd83c, 0xdf5d, 0x3a, 0x73, 0x70, 0x61, 0x67, 0x68, 0x65, 0x74, 0x74, 0x69, +0x3a, 0x73, 0x70, 0x61, 0x67, 0x68, 0x65, 0x74, 0x74, 0x69, 0xd83c, 0xdf5c, +0x3a, 0x72, 0x61, 0x6d, 0x65, 0x6e, 0x3a, 0x72, 0x61, 0x6d, 0x65, 0x6e, +0xd83c, 0xdf72, 0x3a, 0x73, 0x74, 0x65, 0x77, 0x3a, 0x73, 0x74, 0x65, 0x77, +0xd83c, 0xdf65, 0x3a, 0x66, 0x69, 0x73, 0x68, 0x5f, 0x63, 0x61, 0x6b, 0x65, +0x3a, 0x63, 0x61, 0x6b, 0x65, 0x66, 0x69, 0x73, 0x68, 0xd83c, 0xdf63, 0x3a, +0x73, 0x75, 0x73, 0x68, 0x69, 0x3a, 0x73, 0x75, 0x73, 0x68, 0x69, 0xd83c, +0xdf71, 0x3a, 0x62, 0x65, 0x6e, 0x74, 0x6f, 0x3a, 0x62, 0x65, 0x6e, 0x74, +0x6f, 0xd83c, 0xdf5b, 0x3a, 0x63, 0x75, 0x72, 0x72, 0x79, 0x3a, 0x63, 0x75, +0x72, 0x72, 0x79, 0xd83c, 0xdf59, 0x3a, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x62, +0x61, 0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x72, 0x69, 0x63, 0x65, +0xd83c, 0xdf5a, 0x3a, 0x72, 0x69, 0x63, 0x65, 0x3a, 0x72, 0x69, 0x63, 0x65, +0xd83c, 0xdf58, 0x3a, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x72, 0x61, 0x63, +0x6b, 0x65, 0x72, 0x3a, 0x63, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x72, +0x69, 0x63, 0x65, 0xd83c, 0xdf62, 0x3a, 0x6f, 0x64, 0x65, 0x6e, 0x3a, 0x6f, +0x64, 0x65, 0x6e, 0xd83c, 0xdf61, 0x3a, 0x64, 0x61, 0x6e, 0x67, 0x6f, 0x3a, +0x64, 0x61, 0x6e, 0x67, 0x6f, 0xd83c, 0xdf67, 0x3a, 0x73, 0x68, 0x61, 0x76, +0x65, 0x64, 0x5f, 0x69, 0x63, 0x65, 0x3a, 0x69, 0x63, 0x65, 0x73, 0x68, +0x61, 0x76, 0x65, 0x64, 0xd83c, 0xdf68, 0x3a, 0x69, 0x63, 0x65, 0x5f, 0x63, +0x72, 0x65, 0x61, 0x6d, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x63, +0x65, 0xd83c, 0xdf66, 0x3a, 0x69, 0x63, 0x65, 0x63, 0x72, 0x65, 0x61, 0x6d, +0x3a, 0x69, 0x63, 0x65, 0x63, 0x72, 0x65, 0x61, 0x6d, 0xd83c, 0xdf70, 0x3a, +0x63, 0x61, 0x6b, 0x65, 0x3a, 0x63, 0x61, 0x6b, 0x65, 0xd83c, 0xdf82, 0x3a, +0x62, 0x69, 0x72, 0x74, 0x68, 0x64, 0x61, 0x79, 0x3a, 0x62, 0x69, 0x72, +0x74, 0x68, 0x64, 0x61, 0x79, 0xd83c, 0xdf6e, 0x3a, 0x66, 0x6c, 0x61, 0x6e, +0x3a, 0x66, 0x6c, 0x61, 0x6e, 0xd83c, 0xdf6e, 0x3a, 0x70, 0x75, 0x64, 0x64, +0x69, 0x6e, 0x67, 0x3a, 0x70, 0x75, 0x64, 0x64, 0x69, 0x6e, 0x67, 0xd83c, +0xdf6e, 0x3a, 0x63, 0x75, 0x73, 0x74, 0x61, 0x72, 0x64, 0x3a, 0x63, 0x75, +0x73, 0x74, 0x61, 0x72, 0x64, 0xd83c, 0xdf6d, 0x3a, 0x6c, 0x6f, 0x6c, 0x6c, +0x69, 0x70, 0x6f, 0x70, 0x3a, 0x6c, 0x6f, 0x6c, 0x6c, 0x69, 0x70, 0x6f, +0x70, 0xd83c, 0xdf6c, 0x3a, 0x63, 0x61, 0x6e, 0x64, 0x79, 0x3a, 0x63, 0x61, +0x6e, 0x64, 0x79, 0xd83c, 0xdf6b, 0x3a, 0x63, 0x68, 0x6f, 0x63, 0x6f, 0x6c, +0x61, 0x74, 0x65, 0x5f, 0x62, 0x61, 0x72, 0x3a, 0x62, 0x61, 0x72, 0x63, +0x68, 0x6f, 0x63, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0xd83c, 0xdf7f, 0x3a, 0x70, +0x6f, 0x70, 0x63, 0x6f, 0x72, 0x6e, 0x3a, 0x70, 0x6f, 0x70, 0x63, 0x6f, +0x72, 0x6e, 0xd83c, 0xdf69, 0x3a, 0x64, 0x6f, 0x75, 0x67, 0x68, 0x6e, 0x75, +0x74, 0x3a, 0x64, 0x6f, 0x75, 0x67, 0x68, 0x6e, 0x75, 0x74, 0xd83c, 0xdf6a, +0x3a, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x3a, 0x63, 0x6f, 0x6f, 0x6b, +0x69, 0x65, 0xd83e, 0xdd5b, 0x3a, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x6f, +0x66, 0x5f, 0x6d, 0x69, 0x6c, 0x6b, 0x3a, 0x67, 0x6c, 0x61, 0x73, 0x73, +0x6d, 0x69, 0x6c, 0x6b, 0x6f, 0x66, 0xd83e, 0xdd5b, 0x3a, 0x6d, 0x69, 0x6c, +0x6b, 0x3a, 0x6d, 0x69, 0x6c, 0x6b, 0xd83c, 0xdf7c, 0x3a, 0x62, 0x61, 0x62, +0x79, 0x5f, 0x62, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x3a, 0x62, 0x61, 0x62, +0x79, 0x62, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x2615, 0xfe0f, 0x3a, 0x63, 0x6f, +0x66, 0x66, 0x65, 0x65, 0x3a, 0x63, 0x6f, 0x66, 0x66, 0x65, 0x65, 0xd83c, +0xdf75, 0x3a, 0x74, 0x65, 0x61, 0x3a, 0x74, 0x65, 0x61, 0xd83c, 0xdf76, 0x3a, +0x73, 0x61, 0x6b, 0x65, 0x3a, 0x73, 0x61, 0x6b, 0x65, 0xd83c, 0xdf7a, 0x3a, +0x62, 0x65, 0x65, 0x72, 0x3a, 0x62, 0x65, 0x65, 0x72, 0xd83c, 0xdf7b, 0x3a, +0x62, 0x65, 0x65, 0x72, 0x73, 0x3a, 0x62, 0x65, 0x65, 0x72, 0x73, 0xd83e, +0xdd42, 0x3a, 0x63, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x67, +0x6c, 0x61, 0x73, 0x73, 0x3a, 0x63, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, +0x67, 0x67, 0x6c, 0x61, 0x73, 0x73, 0xd83e, 0xdd42, 0x3a, 0x63, 0x68, 0x61, +0x6d, 0x70, 0x61, 0x67, 0x6e, 0x65, 0x5f, 0x67, 0x6c, 0x61, 0x73, 0x73, +0x3a, 0x63, 0x68, 0x61, 0x6d, 0x70, 0x61, 0x67, 0x6e, 0x65, 0x67, 0x6c, +0x61, 0x73, 0x73, 0xd83c, 0xdf77, 0x3a, 0x77, 0x69, 0x6e, 0x65, 0x5f, 0x67, +0x6c, 0x61, 0x73, 0x73, 0x3a, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x77, 0x69, +0x6e, 0x65, 0xd83e, 0xdd43, 0x3a, 0x77, 0x68, 0x69, 0x73, 0x6b, 0x79, 0x3a, +0x77, 0x68, 0x69, 0x73, 0x6b, 0x79, 0xd83e, 0xdd43, 0x3a, 0x74, 0x75, 0x6d, +0x62, 0x6c, 0x65, 0x72, 0x5f, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x3a, 0x67, +0x6c, 0x61, 0x73, 0x73, 0x74, 0x75, 0x6d, 0x62, 0x6c, 0x65, 0x72, 0xd83c, +0xdf78, 0x3a, 0x63, 0x6f, 0x63, 0x6b, 0x74, 0x61, 0x69, 0x6c, 0x3a, 0x63, +0x6f, 0x63, 0x6b, 0x74, 0x61, 0x69, 0x6c, 0xd83c, 0xdf79, 0x3a, 0x74, 0x72, +0x6f, 0x70, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x64, 0x72, 0x69, 0x6e, 0x6b, +0x3a, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x74, 0x72, 0x6f, 0x70, 0x69, 0x63, +0x61, 0x6c, 0xd83c, 0xdf7e, 0x3a, 0x62, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x5f, +0x77, 0x69, 0x74, 0x68, 0x5f, 0x70, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, +0x5f, 0x63, 0x6f, 0x72, 0x6b, 0x3a, 0x62, 0x6f, 0x74, 0x74, 0x6c, 0x65, +0x63, 0x6f, 0x72, 0x6b, 0x70, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x77, +0x69, 0x74, 0x68, 0xd83c, 0xdf7e, 0x3a, 0x63, 0x68, 0x61, 0x6d, 0x70, 0x61, +0x67, 0x6e, 0x65, 0x3a, 0x63, 0x68, 0x61, 0x6d, 0x70, 0x61, 0x67, 0x6e, +0x65, 0xd83e, 0xdd44, 0x3a, 0x73, 0x70, 0x6f, 0x6f, 0x6e, 0x3a, 0x73, 0x70, +0x6f, 0x6f, 0x6e, 0xd83c, 0xdf74, 0x3a, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x61, +0x6e, 0x64, 0x5f, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x3a, 0x61, 0x6e, 0x64, +0x66, 0x6f, 0x72, 0x6b, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0xd83c, 0xdf7d, 0x3a, +0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x6b, 0x6e, 0x69, +0x66, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x70, 0x6c, 0x61, 0x74, +0x65, 0x3a, 0x61, 0x6e, 0x64, 0x66, 0x6f, 0x72, 0x6b, 0x6b, 0x6e, 0x69, +0x66, 0x65, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x77, 0x69, 0x74, 0x68, 0xd83c, +0xdf7d, 0x3a, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x6b, 0x6e, 0x69, 0x66, 0x65, +0x5f, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3a, 0x66, 0x6f, 0x72, 0x6b, 0x6b, +0x6e, 0x69, 0x66, 0x65, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x26bd, 0xfe0f, 0x3a, +0x73, 0x6f, 0x63, 0x63, 0x65, 0x72, 0x3a, 0x73, 0x6f, 0x63, 0x63, 0x65, +0x72, 0xd83c, 0xdfc0, 0x3a, 0x62, 0x61, 0x73, 0x6b, 0x65, 0x74, 0x62, 0x61, +0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x73, 0x6b, 0x65, 0x74, 0x62, 0x61, 0x6c, +0x6c, 0xd83c, 0xdfc8, 0x3a, 0x66, 0x6f, 0x6f, 0x74, 0x62, 0x61, 0x6c, 0x6c, +0x3a, 0x66, 0x6f, 0x6f, 0x74, 0x62, 0x61, 0x6c, 0x6c, 0x26be, 0xfe0f, 0x3a, +0x62, 0x61, 0x73, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x73, +0x65, 0x62, 0x61, 0x6c, 0x6c, 0xd83c, 0xdfbe, 0x3a, 0x74, 0x65, 0x6e, 0x6e, +0x69, 0x73, 0x3a, 0x74, 0x65, 0x6e, 0x6e, 0x69, 0x73, 0xd83c, 0xdfd0, 0x3a, +0x76, 0x6f, 0x6c, 0x6c, 0x65, 0x79, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x76, +0x6f, 0x6c, 0x6c, 0x65, 0x79, 0x62, 0x61, 0x6c, 0x6c, 0xd83c, 0xdfc9, 0x3a, +0x72, 0x75, 0x67, 0x62, 0x79, 0x5f, 0x66, 0x6f, 0x6f, 0x74, 0x62, 0x61, +0x6c, 0x6c, 0x3a, 0x66, 0x6f, 0x6f, 0x74, 0x62, 0x61, 0x6c, 0x6c, 0x72, +0x75, 0x67, 0x62, 0x79, 0xd83c, 0xdfb1, 0x3a, 0x38, 0x62, 0x61, 0x6c, 0x6c, +0x3a, 0x38, 0x62, 0x61, 0x6c, 0x6c, 0xd83c, 0xdfd3, 0x3a, 0x74, 0x61, 0x62, +0x6c, 0x65, 0x5f, 0x74, 0x65, 0x6e, 0x6e, 0x69, 0x73, 0x3a, 0x74, 0x61, +0x62, 0x6c, 0x65, 0x74, 0x65, 0x6e, 0x6e, 0x69, 0x73, 0xd83c, 0xdfd3, 0x3a, +0x70, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x6f, 0x6e, 0x67, 0x3a, 0x70, 0x69, +0x6e, 0x67, 0x70, 0x6f, 0x6e, 0x67, 0xd83c, 0xdff8, 0x3a, 0x62, 0x61, 0x64, +0x6d, 0x69, 0x6e, 0x74, 0x6f, 0x6e, 0x3a, 0x62, 0x61, 0x64, 0x6d, 0x69, +0x6e, 0x74, 0x6f, 0x6e, 0xd83e, 0xdd45, 0x3a, 0x67, 0x6f, 0x61, 0x6c, 0x5f, +0x6e, 0x65, 0x74, 0x3a, 0x67, 0x6f, 0x61, 0x6c, 0x6e, 0x65, 0x74, 0xd83e, +0xdd45, 0x3a, 0x67, 0x6f, 0x61, 0x6c, 0x3a, 0x67, 0x6f, 0x61, 0x6c, 0xd83c, +0xdfd2, 0x3a, 0x68, 0x6f, 0x63, 0x6b, 0x65, 0x79, 0x3a, 0x68, 0x6f, 0x63, +0x6b, 0x65, 0x79, 0xd83c, 0xdfd1, 0x3a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, +0x68, 0x6f, 0x63, 0x6b, 0x65, 0x79, 0x3a, 0x66, 0x69, 0x65, 0x6c, 0x64, +0x68, 0x6f, 0x63, 0x6b, 0x65, 0x79, 0xd83c, 0xdfcf, 0x3a, 0x63, 0x72, 0x69, +0x63, 0x6b, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x74, 0x5f, 0x62, 0x61, 0x6c, +0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x74, 0x63, 0x72, 0x69, +0x63, 0x6b, 0x65, 0x74, 0xd83c, 0xdfcf, 0x3a, 0x63, 0x72, 0x69, 0x63, 0x6b, +0x65, 0x74, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x3a, 0x63, 0x72, 0x69, 0x63, +0x6b, 0x65, 0x74, 0x67, 0x61, 0x6d, 0x65, 0x26f3, 0xfe0f, 0x3a, 0x67, 0x6f, +0x6c, 0x66, 0x3a, 0x67, 0x6f, 0x6c, 0x66, 0xd83c, 0xdff9, 0x3a, 0x61, 0x72, +0x63, 0x68, 0x65, 0x72, 0x79, 0x3a, 0x61, 0x72, 0x63, 0x68, 0x65, 0x72, +0x79, 0xd83c, 0xdff9, 0x3a, 0x62, 0x6f, 0x77, 0x5f, 0x61, 0x6e, 0x64, 0x5f, +0x61, 0x72, 0x72, 0x6f, 0x77, 0x3a, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x72, +0x6f, 0x77, 0x62, 0x6f, 0x77, 0xd83c, 0xdfa3, 0x3a, 0x66, 0x69, 0x73, 0x68, +0x69, 0x6e, 0x67, 0x5f, 0x70, 0x6f, 0x6c, 0x65, 0x5f, 0x61, 0x6e, 0x64, +0x5f, 0x66, 0x69, 0x73, 0x68, 0x3a, 0x61, 0x6e, 0x64, 0x66, 0x69, 0x73, +0x68, 0x66, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x6c, 0x65, +0xd83e, 0xdd4a, 0x3a, 0x62, 0x6f, 0x78, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x6c, +0x6f, 0x76, 0x65, 0x73, 0x3a, 0x62, 0x6f, 0x78, 0x69, 0x6e, 0x67, 0x67, +0x6c, 0x6f, 0x76, 0x65, 0x73, 0xd83e, 0xdd4a, 0x3a, 0x62, 0x6f, 0x78, 0x69, +0x6e, 0x67, 0x5f, 0x67, 0x6c, 0x6f, 0x76, 0x65, 0x3a, 0x62, 0x6f, 0x78, +0x69, 0x6e, 0x67, 0x67, 0x6c, 0x6f, 0x76, 0x65, 0xd83e, 0xdd4b, 0x3a, 0x6b, +0x61, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, +0x6d, 0x3a, 0x6b, 0x61, 0x72, 0x61, 0x74, 0x65, 0x75, 0x6e, 0x69, 0x66, +0x6f, 0x72, 0x6d, 0xd83e, 0xdd4b, 0x3a, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x61, +0x6c, 0x5f, 0x61, 0x72, 0x74, 0x73, 0x5f, 0x75, 0x6e, 0x69, 0x66, 0x6f, +0x72, 0x6d, 0x3a, 0x61, 0x72, 0x74, 0x73, 0x6d, 0x61, 0x72, 0x74, 0x69, +0x61, 0x6c, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x26f8, 0x3a, 0x69, +0x63, 0x65, 0x5f, 0x73, 0x6b, 0x61, 0x74, 0x65, 0x3a, 0x69, 0x63, 0x65, +0x73, 0x6b, 0x61, 0x74, 0x65, 0xd83c, 0xdfbf, 0x3a, 0x73, 0x6b, 0x69, 0x3a, +0x73, 0x6b, 0x69, 0x26f7, 0x3a, 0x73, 0x6b, 0x69, 0x65, 0x72, 0x3a, 0x73, +0x6b, 0x69, 0x65, 0x72, 0xd83c, 0xdfc2, 0x3a, 0x73, 0x6e, 0x6f, 0x77, 0x62, +0x6f, 0x61, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x73, 0x6e, 0x6f, 0x77, 0x62, +0x6f, 0x61, 0x72, 0x64, 0x65, 0x72, 0xd83c, 0xdfcb, 0xfe0f, 0x200d, 0x2640, 0xfe0f, +0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x6c, 0x69, 0x66, 0x74, 0x69, +0x6e, 0x67, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3a, 0x6c, +0x69, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, +0x73, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83c, 0xdfcb, 0xfe0f, 0x3a, 0x6d, 0x61, +0x6e, 0x5f, 0x6c, 0x69, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x77, 0x65, +0x69, 0x67, 0x68, 0x74, 0x73, 0x3a, 0x6c, 0x69, 0x66, 0x74, 0x69, 0x6e, +0x67, 0x6d, 0x61, 0x6e, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0xd83c, +0xdfcb, 0xfe0f, 0x3a, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x6c, 0x69, +0x66, 0x74, 0x65, 0x72, 0x3a, 0x6c, 0x69, 0x66, 0x74, 0x65, 0x72, 0x77, +0x65, 0x69, 0x67, 0x68, 0x74, 0xd83c, 0xdfcb, 0xfe0f, 0x3a, 0x6c, 0x69, 0x66, +0x74, 0x65, 0x72, 0x3a, 0x6c, 0x69, 0x66, 0x74, 0x65, 0x72, 0xd83c, 0xdfcb, +0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x6c, 0x69, 0x66, +0x74, 0x69, 0x6e, 0x67, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, +0x3a, 0x6c, 0x69, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, +0x6f, 0x6e, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0xd83e, 0xdd3a, 0x3a, +0x66, 0x65, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x3a, 0x66, 0x65, 0x6e, 0x63, +0x69, 0x6e, 0x67, 0xd83e, 0xdd3a, 0x3a, 0x66, 0x65, 0x6e, 0x63, 0x65, 0x72, +0x3a, 0x66, 0x65, 0x6e, 0x63, 0x65, 0x72, 0xd83e, 0xdd3a, 0x3a, 0x70, 0x65, +0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x65, 0x6e, 0x63, 0x69, 0x6e, 0x67, +0x3a, 0x66, 0x65, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, +0x6f, 0x6e, 0xd83e, 0xdd3c, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x65, +0x6e, 0x5f, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0x3a, +0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, +0x6e, 0x67, 0xd83e, 0xdd3c, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x65, 0x6e, 0x5f, +0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x6d, 0x65, +0x6e, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0xd83e, 0xdd3c, +0x200d, 0x2642, 0xfe0f, 0x3a, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6e, +0x67, 0x3a, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0xd83e, +0xdd3c, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x65, +0x72, 0x73, 0x3a, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x65, 0x72, 0x73, +0xd83e, 0xdd3c, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, +0x5f, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x70, +0x65, 0x6f, 0x70, 0x6c, 0x65, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, +0x6e, 0x67, 0xd83e, 0xdd38, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0x5f, 0x63, 0x61, 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x69, +0x6e, 0x67, 0x3a, 0x63, 0x61, 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, 0x6c, +0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd38, 0x200d, 0x2642, +0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x63, 0x61, 0x72, 0x74, 0x77, 0x68, +0x65, 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x63, 0x61, 0x72, 0x74, 0x77, +0x68, 0x65, 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd38, +0x200d, 0x2642, 0xfe0f, 0x3a, 0x63, 0x61, 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, +0x6c, 0x3a, 0x63, 0x61, 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, 0x6c, 0xd83e, +0xdd38, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, +0x64, 0x6f, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x61, 0x72, 0x74, 0x77, 0x68, +0x65, 0x65, 0x6c, 0x3a, 0x63, 0x61, 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, +0x6c, 0x64, 0x6f, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, +0x26f9, 0xfe0f, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, +0x62, 0x6f, 0x75, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x61, 0x6c, +0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x62, 0x6f, 0x75, 0x6e, 0x63, 0x69, +0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x26f9, 0xfe0f, 0x3a, 0x6d, 0x61, +0x6e, 0x5f, 0x62, 0x6f, 0x75, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x62, +0x61, 0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x62, 0x6f, 0x75, 0x6e, +0x63, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0x26f9, 0xfe0f, 0x3a, 0x70, 0x65, +0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x62, 0x61, +0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x70, 0x65, 0x72, 0x73, 0x6f, +0x6e, 0x77, 0x69, 0x74, 0x68, 0x26f9, 0xfe0f, 0x3a, 0x62, 0x61, 0x73, 0x6b, +0x65, 0x74, 0x62, 0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x65, +0x72, 0x3a, 0x62, 0x61, 0x73, 0x6b, 0x65, 0x74, 0x62, 0x61, 0x6c, 0x6c, +0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x26f9, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, +0x73, 0x6f, 0x6e, 0x5f, 0x62, 0x6f, 0x75, 0x6e, 0x63, 0x69, 0x6e, 0x67, +0x5f, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x62, 0x6f, +0x75, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, +0xd83e, 0xdd3e, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, +0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, 0x64, +0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x62, 0x61, 0x6c, +0x6c, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, +0x6e, 0xd83e, 0xdd3e, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x62, +0x61, 0x6c, 0x6c, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x62, 0x61, 0x6c, 0x6c, +0xd83e, 0xdd3e, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, +0x5f, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, +0x64, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x62, 0x61, +0x6c, 0x6c, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x70, 0x6c, 0x61, 0x79, +0x69, 0x6e, 0x67, 0xd83e, 0xdd3e, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, +0x5f, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, +0x64, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x62, 0x61, +0x6c, 0x6c, 0x6d, 0x61, 0x6e, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, +0xd83c, 0xdfcc, 0xfe0f, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, +0x5f, 0x67, 0x6f, 0x6c, 0x66, 0x69, 0x6e, 0x67, 0x3a, 0x67, 0x6f, 0x6c, +0x66, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83c, 0xdfcc, 0xfe0f, +0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x6f, 0x6c, 0x66, 0x69, 0x6e, 0x67, +0x3a, 0x67, 0x6f, 0x6c, 0x66, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0xd83c, +0xdfcc, 0xfe0f, 0x3a, 0x67, 0x6f, 0x6c, 0x66, 0x65, 0x72, 0x3a, 0x67, 0x6f, +0x6c, 0x66, 0x65, 0x72, 0xd83c, 0xdfcc, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, +0x6f, 0x6e, 0x5f, 0x67, 0x6f, 0x6c, 0x66, 0x69, 0x6e, 0x67, 0x3a, 0x67, +0x6f, 0x6c, 0x66, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, +0xd83c, 0xdfc4, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, +0x73, 0x75, 0x72, 0x66, 0x69, 0x6e, 0x67, 0x3a, 0x73, 0x75, 0x72, 0x66, +0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83c, 0xdfc4, 0x3a, 0x6d, +0x61, 0x6e, 0x5f, 0x73, 0x75, 0x72, 0x66, 0x69, 0x6e, 0x67, 0x3a, 0x6d, +0x61, 0x6e, 0x73, 0x75, 0x72, 0x66, 0x69, 0x6e, 0x67, 0xd83c, 0xdfc4, 0x3a, +0x73, 0x75, 0x72, 0x66, 0x65, 0x72, 0x3a, 0x73, 0x75, 0x72, 0x66, 0x65, +0x72, 0xd83c, 0xdfc4, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x73, +0x75, 0x72, 0x66, 0x69, 0x6e, 0x67, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, +0x6e, 0x73, 0x75, 0x72, 0x66, 0x69, 0x6e, 0x67, 0xd83c, 0xdfca, 0x200d, 0x2640, +0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x77, 0x69, 0x6d, +0x6d, 0x69, 0x6e, 0x67, 0x3a, 0x73, 0x77, 0x69, 0x6d, 0x6d, 0x69, 0x6e, +0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83c, 0xdfca, 0x3a, 0x6d, 0x61, 0x6e, +0x5f, 0x73, 0x77, 0x69, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x3a, 0x6d, 0x61, +0x6e, 0x73, 0x77, 0x69, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0xd83c, 0xdfca, 0x3a, +0x73, 0x77, 0x69, 0x6d, 0x6d, 0x65, 0x72, 0x3a, 0x73, 0x77, 0x69, 0x6d, +0x6d, 0x65, 0x72, 0xd83c, 0xdfca, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, +0x5f, 0x73, 0x77, 0x69, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x3a, 0x70, 0x65, +0x72, 0x73, 0x6f, 0x6e, 0x73, 0x77, 0x69, 0x6d, 0x6d, 0x69, 0x6e, 0x67, +0xd83e, 0xdd3d, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, +0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x77, 0x61, 0x74, 0x65, +0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x6f, 0x3a, 0x70, 0x6c, 0x61, 0x79, 0x69, +0x6e, 0x67, 0x70, 0x6f, 0x6c, 0x6f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd3d, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, +0x6e, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x77, 0x61, +0x74, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x6f, 0x3a, 0x6d, 0x61, 0x6e, +0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x6c, 0x6f, 0x77, +0x61, 0x74, 0x65, 0x72, 0xd83e, 0xdd3d, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x77, 0x61, +0x74, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x6f, 0x3a, 0x70, 0x6f, 0x6c, +0x6f, 0x77, 0x61, 0x74, 0x65, 0x72, 0xd83e, 0xdd3d, 0x200d, 0x2642, 0xfe0f, 0x3a, +0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x69, +0x6e, 0x67, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x6c, +0x6f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x70, 0x6c, 0x61, 0x79, +0x69, 0x6e, 0x67, 0x70, 0x6f, 0x6c, 0x6f, 0x77, 0x61, 0x74, 0x65, 0x72, +0xd83d, 0xdea3, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, +0x72, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x6f, 0x61, 0x74, 0x3a, +0x62, 0x6f, 0x61, 0x74, 0x72, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x77, 0x6f, +0x6d, 0x61, 0x6e, 0xd83d, 0xdea3, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x72, 0x6f, +0x77, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x6f, 0x61, 0x74, 0x3a, 0x62, 0x6f, +0x61, 0x74, 0x6d, 0x61, 0x6e, 0x72, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0xd83d, +0xdea3, 0x3a, 0x72, 0x6f, 0x77, 0x62, 0x6f, 0x61, 0x74, 0x3a, 0x72, 0x6f, +0x77, 0x62, 0x6f, 0x61, 0x74, 0xd83d, 0xdea3, 0x3a, 0x70, 0x65, 0x72, 0x73, +0x6f, 0x6e, 0x5f, 0x72, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x6f, +0x61, 0x74, 0x3a, 0x62, 0x6f, 0x61, 0x74, 0x70, 0x65, 0x72, 0x73, 0x6f, +0x6e, 0x72, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0xd83c, 0xdfc7, 0x3a, 0x68, 0x6f, +0x72, 0x73, 0x65, 0x5f, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3a, 0x68, +0x6f, 0x72, 0x73, 0x65, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0xd83d, 0xdeb4, +0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x62, 0x69, +0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, 0x77, +0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdeb4, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x62, +0x69, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, +0x6d, 0x61, 0x6e, 0xd83d, 0xdeb4, 0x3a, 0x62, 0x69, 0x63, 0x79, 0x63, 0x6c, +0x69, 0x73, 0x74, 0x3a, 0x62, 0x69, 0x63, 0x79, 0x63, 0x6c, 0x69, 0x73, +0x74, 0xd83d, 0xdeb4, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x62, +0x69, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, +0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83d, 0xdeb5, 0x200d, 0x2640, 0xfe0f, 0x3a, +0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, +0x69, 0x6e, 0x5f, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x69, +0x6b, 0x69, 0x6e, 0x67, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, +0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdeb5, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, +0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x62, 0x69, 0x6b, +0x69, 0x6e, 0x67, 0x3a, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, 0x6d, 0x61, +0x6e, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0xd83d, 0xdeb5, 0x3a, +0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x62, 0x69, 0x63, +0x79, 0x63, 0x6c, 0x69, 0x73, 0x74, 0x3a, 0x62, 0x69, 0x63, 0x79, 0x63, +0x6c, 0x69, 0x73, 0x74, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, +0xd83d, 0xdeb5, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x6f, +0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x62, 0x69, 0x6b, 0x69, 0x6e, +0x67, 0x3a, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, 0x6d, 0x6f, 0x75, 0x6e, +0x74, 0x61, 0x69, 0x6e, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83c, 0xdfbd, +0x3a, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x68, 0x69, +0x72, 0x74, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x73, 0x61, 0x73, 0x68, +0x3a, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x61, 0x73, 0x68, +0x73, 0x68, 0x69, 0x72, 0x74, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdfc5, 0x3a, +0x73, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x5f, 0x6d, 0x65, 0x64, 0x61, 0x6c, +0x3a, 0x6d, 0x65, 0x64, 0x61, 0x6c, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x73, +0xd83c, 0xdfc5, 0x3a, 0x6d, 0x65, 0x64, 0x61, 0x6c, 0x3a, 0x6d, 0x65, 0x64, +0x61, 0x6c, 0xd83c, 0xdf96, 0x3a, 0x6d, 0x69, 0x6c, 0x69, 0x74, 0x61, 0x72, +0x79, 0x5f, 0x6d, 0x65, 0x64, 0x61, 0x6c, 0x3a, 0x6d, 0x65, 0x64, 0x61, +0x6c, 0x6d, 0x69, 0x6c, 0x69, 0x74, 0x61, 0x72, 0x79, 0xd83e, 0xdd47, 0x3a, +0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, +0x6d, 0x65, 0x64, 0x61, 0x6c, 0x3a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x6d, +0x65, 0x64, 0x61, 0x6c, 0x70, 0x6c, 0x61, 0x63, 0x65, 0xd83e, 0xdd47, 0x3a, +0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x3a, +0x66, 0x69, 0x72, 0x73, 0x74, 0x70, 0x6c, 0x61, 0x63, 0x65, 0xd83e, 0xdd48, +0x3a, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x5f, 0x70, 0x6c, 0x61, 0x63, +0x65, 0x5f, 0x6d, 0x65, 0x64, 0x61, 0x6c, 0x3a, 0x6d, 0x65, 0x64, 0x61, +0x6c, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, +0xd83e, 0xdd48, 0x3a, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x5f, 0x70, 0x6c, +0x61, 0x63, 0x65, 0x3a, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x65, 0x63, +0x6f, 0x6e, 0x64, 0xd83e, 0xdd49, 0x3a, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, +0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x64, 0x61, 0x6c, 0x3a, +0x6d, 0x65, 0x64, 0x61, 0x6c, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x74, 0x68, +0x69, 0x72, 0x64, 0xd83e, 0xdd49, 0x3a, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, +0x70, 0x6c, 0x61, 0x63, 0x65, 0x3a, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x74, +0x68, 0x69, 0x72, 0x64, 0xd83c, 0xdfc6, 0x3a, 0x74, 0x72, 0x6f, 0x70, 0x68, +0x79, 0x3a, 0x74, 0x72, 0x6f, 0x70, 0x68, 0x79, 0xd83c, 0xdff5, 0x3a, 0x72, +0x6f, 0x73, 0x65, 0x74, 0x74, 0x65, 0x3a, 0x72, 0x6f, 0x73, 0x65, 0x74, +0x74, 0x65, 0xd83c, 0xdf97, 0x3a, 0x72, 0x65, 0x6d, 0x69, 0x6e, 0x64, 0x65, +0x72, 0x5f, 0x72, 0x69, 0x62, 0x62, 0x6f, 0x6e, 0x3a, 0x72, 0x65, 0x6d, +0x69, 0x6e, 0x64, 0x65, 0x72, 0x72, 0x69, 0x62, 0x62, 0x6f, 0x6e, 0xd83c, +0xdfab, 0x3a, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x3a, 0x74, 0x69, 0x63, +0x6b, 0x65, 0x74, 0xd83c, 0xdf9f, 0x3a, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, +0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x3a, +0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x74, 0x69, 0x63, +0x6b, 0x65, 0x74, 0x73, 0xd83c, 0xdf9f, 0x3a, 0x74, 0x69, 0x63, 0x6b, 0x65, +0x74, 0x73, 0x3a, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x73, 0xd83c, 0xdfaa, +0x3a, 0x63, 0x69, 0x72, 0x63, 0x75, 0x73, 0x5f, 0x74, 0x65, 0x6e, 0x74, +0x3a, 0x63, 0x69, 0x72, 0x63, 0x75, 0x73, 0x74, 0x65, 0x6e, 0x74, 0xd83e, +0xdd39, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x6a, +0x75, 0x67, 0x67, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x6a, 0x75, 0x67, 0x67, +0x6c, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd39, 0x200d, +0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x6a, 0x75, 0x67, 0x67, 0x6c, +0x69, 0x6e, 0x67, 0x3a, 0x6a, 0x75, 0x67, 0x67, 0x6c, 0x69, 0x6e, 0x67, +0x6d, 0x61, 0x6e, 0xd83e, 0xdd39, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6a, 0x75, 0x67, +0x67, 0x6c, 0x65, 0x72, 0x3a, 0x6a, 0x75, 0x67, 0x67, 0x6c, 0x65, 0x72, +0xd83e, 0xdd39, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6a, 0x75, 0x67, 0x67, 0x6c, 0x69, +0x6e, 0x67, 0x3a, 0x6a, 0x75, 0x67, 0x67, 0x6c, 0x69, 0x6e, 0x67, 0xd83e, +0xdd39, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, +0x6a, 0x75, 0x67, 0x67, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x6a, 0x75, 0x67, +0x67, 0x6c, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83c, +0xdfad, 0x3a, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x6e, 0x67, +0x5f, 0x61, 0x72, 0x74, 0x73, 0x3a, 0x61, 0x72, 0x74, 0x73, 0x70, 0x65, +0x72, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x6e, 0x67, 0xd83c, 0xdfa8, 0x3a, 0x61, +0x72, 0x74, 0x3a, 0x61, 0x72, 0x74, 0xd83c, 0xdfac, 0x3a, 0x63, 0x6c, 0x61, +0x70, 0x70, 0x65, 0x72, 0x3a, 0x63, 0x6c, 0x61, 0x70, 0x70, 0x65, 0x72, +0xd83c, 0xdfa4, 0x3a, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x70, 0x68, 0x6f, 0x6e, +0x65, 0x3a, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x70, 0x68, 0x6f, 0x6e, 0x65, +0xd83c, 0xdfa7, 0x3a, 0x68, 0x65, 0x61, 0x64, 0x70, 0x68, 0x6f, 0x6e, 0x65, +0x73, 0x3a, 0x68, 0x65, 0x61, 0x64, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x73, +0xd83c, 0xdfbc, 0x3a, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x73, +0x63, 0x6f, 0x72, 0x65, 0x3a, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x61, 0x6c, +0x73, 0x63, 0x6f, 0x72, 0x65, 0xd83c, 0xdfb9, 0x3a, 0x6d, 0x75, 0x73, 0x69, +0x63, 0x61, 0x6c, 0x5f, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, +0x3a, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x6d, 0x75, 0x73, +0x69, 0x63, 0x61, 0x6c, 0xd83e, 0xdd41, 0x3a, 0x64, 0x72, 0x75, 0x6d, 0x5f, +0x77, 0x69, 0x74, 0x68, 0x5f, 0x64, 0x72, 0x75, 0x6d, 0x73, 0x74, 0x69, +0x63, 0x6b, 0x73, 0x3a, 0x64, 0x72, 0x75, 0x6d, 0x64, 0x72, 0x75, 0x6d, +0x73, 0x74, 0x69, 0x63, 0x6b, 0x73, 0x77, 0x69, 0x74, 0x68, 0xd83e, 0xdd41, +0x3a, 0x64, 0x72, 0x75, 0x6d, 0x3a, 0x64, 0x72, 0x75, 0x6d, 0xd83c, 0xdfb7, +0x3a, 0x73, 0x61, 0x78, 0x6f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x3a, 0x73, +0x61, 0x78, 0x6f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0xd83c, 0xdfba, 0x3a, 0x74, +0x72, 0x75, 0x6d, 0x70, 0x65, 0x74, 0x3a, 0x74, 0x72, 0x75, 0x6d, 0x70, +0x65, 0x74, 0xd83c, 0xdfb8, 0x3a, 0x67, 0x75, 0x69, 0x74, 0x61, 0x72, 0x3a, +0x67, 0x75, 0x69, 0x74, 0x61, 0x72, 0xd83c, 0xdfbb, 0x3a, 0x76, 0x69, 0x6f, +0x6c, 0x69, 0x6e, 0x3a, 0x76, 0x69, 0x6f, 0x6c, 0x69, 0x6e, 0xd83c, 0xdfb2, +0x3a, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x64, 0x69, 0x65, 0x3a, 0x64, 0x69, +0x65, 0x67, 0x61, 0x6d, 0x65, 0xd83c, 0xdfaf, 0x3a, 0x64, 0x61, 0x72, 0x74, +0x3a, 0x64, 0x61, 0x72, 0x74, 0xd83c, 0xdfb3, 0x3a, 0x62, 0x6f, 0x77, 0x6c, +0x69, 0x6e, 0x67, 0x3a, 0x62, 0x6f, 0x77, 0x6c, 0x69, 0x6e, 0x67, 0xd83c, +0xdfae, 0x3a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x5f, 0x67, 0x61, 0x6d, 0x65, +0x3a, 0x67, 0x61, 0x6d, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0xd83c, 0xdfb0, +0x3a, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, +0x65, 0x3a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x6c, 0x6f, +0x74, 0xd83d, 0xde97, 0x3a, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x61, 0x72, 0x3a, +0x63, 0x61, 0x72, 0x72, 0x65, 0x64, 0xd83d, 0xde95, 0x3a, 0x74, 0x61, 0x78, +0x69, 0x3a, 0x74, 0x61, 0x78, 0x69, 0xd83d, 0xde99, 0x3a, 0x62, 0x6c, 0x75, +0x65, 0x5f, 0x63, 0x61, 0x72, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x63, 0x61, +0x72, 0xd83d, 0xde8c, 0x3a, 0x62, 0x75, 0x73, 0x3a, 0x62, 0x75, 0x73, 0xd83d, +0xde8e, 0x3a, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x79, 0x62, 0x75, 0x73, +0x3a, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x79, 0x62, 0x75, 0x73, 0xd83c, +0xdfce, 0x3a, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x61, 0x72, +0x3a, 0x63, 0x61, 0x72, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0xd83c, 0xdfce, +0x3a, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x63, 0x61, 0x72, 0x3a, 0x63, 0x61, +0x72, 0x72, 0x61, 0x63, 0x65, 0xd83d, 0xde93, 0x3a, 0x70, 0x6f, 0x6c, 0x69, +0x63, 0x65, 0x5f, 0x63, 0x61, 0x72, 0x3a, 0x63, 0x61, 0x72, 0x70, 0x6f, +0x6c, 0x69, 0x63, 0x65, 0xd83d, 0xde91, 0x3a, 0x61, 0x6d, 0x62, 0x75, 0x6c, +0x61, 0x6e, 0x63, 0x65, 0x3a, 0x61, 0x6d, 0x62, 0x75, 0x6c, 0x61, 0x6e, +0x63, 0x65, 0xd83d, 0xde92, 0x3a, 0x66, 0x69, 0x72, 0x65, 0x5f, 0x65, 0x6e, +0x67, 0x69, 0x6e, 0x65, 0x3a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x66, +0x69, 0x72, 0x65, 0xd83d, 0xde90, 0x3a, 0x6d, 0x69, 0x6e, 0x69, 0x62, 0x75, +0x73, 0x3a, 0x6d, 0x69, 0x6e, 0x69, 0x62, 0x75, 0x73, 0xd83d, 0xde9a, 0x3a, +0x74, 0x72, 0x75, 0x63, 0x6b, 0x3a, 0x74, 0x72, 0x75, 0x63, 0x6b, 0xd83d, +0xde9b, 0x3a, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, +0x64, 0x5f, 0x6c, 0x6f, 0x72, 0x72, 0x79, 0x3a, 0x61, 0x72, 0x74, 0x69, +0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x6c, 0x6f, 0x72, 0x72, 0x79, +0xd83d, 0xde9c, 0x3a, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x3a, 0x74, +0x72, 0x61, 0x63, 0x74, 0x6f, 0x72, 0xd83d, 0xdef4, 0x3a, 0x73, 0x63, 0x6f, +0x6f, 0x74, 0x65, 0x72, 0x3a, 0x73, 0x63, 0x6f, 0x6f, 0x74, 0x65, 0x72, +0xd83d, 0xdeb2, 0x3a, 0x62, 0x69, 0x6b, 0x65, 0x3a, 0x62, 0x69, 0x6b, 0x65, +0xd83d, 0xdef5, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x62, 0x69, 0x6b, 0x65, +0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x62, 0x69, 0x6b, 0x65, 0xd83d, 0xdef5, +0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x63, 0x6f, 0x6f, 0x74, +0x65, 0x72, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x73, 0x63, 0x6f, 0x6f, +0x74, 0x65, 0x72, 0xd83c, 0xdfcd, 0x3a, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, +0x5f, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x3a, +0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x72, 0x61, +0x63, 0x69, 0x6e, 0x67, 0xd83c, 0xdfcd, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, +0x63, 0x79, 0x63, 0x6c, 0x65, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x63, +0x79, 0x63, 0x6c, 0x65, 0xd83d, 0xdea8, 0x3a, 0x72, 0x6f, 0x74, 0x61, 0x74, +0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x6c, 0x69, +0x67, 0x68, 0x74, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, 0xd83d, +0xde94, 0x3a, 0x6f, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x70, +0x6f, 0x6c, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x61, 0x72, 0x3a, 0x63, 0x61, +0x72, 0x6f, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x6c, +0x69, 0x63, 0x65, 0xd83d, 0xde8d, 0x3a, 0x6f, 0x6e, 0x63, 0x6f, 0x6d, 0x69, +0x6e, 0x67, 0x5f, 0x62, 0x75, 0x73, 0x3a, 0x62, 0x75, 0x73, 0x6f, 0x6e, +0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0xd83d, 0xde98, 0x3a, 0x6f, 0x6e, 0x63, +0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x6f, +0x62, 0x69, 0x6c, 0x65, 0x3a, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x6f, 0x62, +0x69, 0x6c, 0x65, 0x6f, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0xd83d, +0xde96, 0x3a, 0x6f, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x74, +0x61, 0x78, 0x69, 0x3a, 0x6f, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, +0x74, 0x61, 0x78, 0x69, 0xd83d, 0xdea1, 0x3a, 0x61, 0x65, 0x72, 0x69, 0x61, +0x6c, 0x5f, 0x74, 0x72, 0x61, 0x6d, 0x77, 0x61, 0x79, 0x3a, 0x61, 0x65, +0x72, 0x69, 0x61, 0x6c, 0x74, 0x72, 0x61, 0x6d, 0x77, 0x61, 0x79, 0xd83d, +0xdea0, 0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x63, +0x61, 0x62, 0x6c, 0x65, 0x77, 0x61, 0x79, 0x3a, 0x63, 0x61, 0x62, 0x6c, +0x65, 0x77, 0x61, 0x79, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, +0xd83d, 0xde9f, 0x3a, 0x73, 0x75, 0x73, 0x70, 0x65, 0x6e, 0x73, 0x69, 0x6f, +0x6e, 0x5f, 0x72, 0x61, 0x69, 0x6c, 0x77, 0x61, 0x79, 0x3a, 0x72, 0x61, +0x69, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x75, 0x73, 0x70, 0x65, 0x6e, 0x73, +0x69, 0x6f, 0x6e, 0xd83d, 0xde83, 0x3a, 0x72, 0x61, 0x69, 0x6c, 0x77, 0x61, +0x79, 0x5f, 0x63, 0x61, 0x72, 0x3a, 0x63, 0x61, 0x72, 0x72, 0x61, 0x69, +0x6c, 0x77, 0x61, 0x79, 0xd83d, 0xde8b, 0x3a, 0x74, 0x72, 0x61, 0x69, 0x6e, +0x3a, 0x74, 0x72, 0x61, 0x69, 0x6e, 0xd83d, 0xde9e, 0x3a, 0x6d, 0x6f, 0x75, +0x6e, 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x72, 0x61, 0x69, 0x6c, 0x77, 0x61, +0x79, 0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x72, 0x61, +0x69, 0x6c, 0x77, 0x61, 0x79, 0xd83d, 0xde9d, 0x3a, 0x6d, 0x6f, 0x6e, 0x6f, +0x72, 0x61, 0x69, 0x6c, 0x3a, 0x6d, 0x6f, 0x6e, 0x6f, 0x72, 0x61, 0x69, +0x6c, 0xd83d, 0xde84, 0x3a, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x74, 0x72, +0x61, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x3a, 0x62, 0x75, 0x6c, +0x6c, 0x65, 0x74, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, +0xd83d, 0xde85, 0x3a, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x74, 0x72, 0x61, +0x69, 0x6e, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x3a, 0x62, 0x75, 0x6c, +0x6c, 0x65, 0x74, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x66, 0x72, 0x6f, 0x6e, +0x74, 0xd83d, 0xde88, 0x3a, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x72, 0x61, +0x69, 0x6c, 0x3a, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x72, 0x61, 0x69, 0x6c, +0xd83d, 0xde82, 0x3a, 0x73, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x6c, 0x6f, 0x63, +0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x76, 0x65, 0x3a, 0x6c, 0x6f, 0x63, 0x6f, +0x6d, 0x6f, 0x74, 0x69, 0x76, 0x65, 0x73, 0x74, 0x65, 0x61, 0x6d, 0xd83d, +0xde86, 0x3a, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x32, 0x3a, 0x74, 0x72, 0x61, +0x69, 0x6e, 0x32, 0xd83d, 0xde87, 0x3a, 0x6d, 0x65, 0x74, 0x72, 0x6f, 0x3a, +0x6d, 0x65, 0x74, 0x72, 0x6f, 0xd83d, 0xde8a, 0x3a, 0x74, 0x72, 0x61, 0x6d, +0x3a, 0x74, 0x72, 0x61, 0x6d, 0xd83d, 0xde89, 0x3a, 0x73, 0x74, 0x61, 0x74, +0x69, 0x6f, 0x6e, 0x3a, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xd83d, +0xde81, 0x3a, 0x68, 0x65, 0x6c, 0x69, 0x63, 0x6f, 0x70, 0x74, 0x65, 0x72, +0x3a, 0x68, 0x65, 0x6c, 0x69, 0x63, 0x6f, 0x70, 0x74, 0x65, 0x72, 0xd83d, +0xdee9, 0x3a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x61, 0x69, 0x72, 0x70, +0x6c, 0x61, 0x6e, 0x65, 0x3a, 0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, +0x65, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0xd83d, 0xdee9, 0x3a, 0x61, 0x69, 0x72, +0x70, 0x6c, 0x61, 0x6e, 0x65, 0x5f, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x3a, +0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x73, 0x6d, 0x61, 0x6c, +0x6c, 0x2708, 0xfe0f, 0x3a, 0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, 0x65, +0x3a, 0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xd83d, 0xdeeb, 0x3a, +0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x70, +0x61, 0x72, 0x74, 0x75, 0x72, 0x65, 0x3a, 0x61, 0x69, 0x72, 0x70, 0x6c, +0x61, 0x6e, 0x65, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x75, 0x72, 0x65, +0xd83d, 0xdeec, 0x3a, 0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x5f, +0x61, 0x72, 0x72, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x3a, 0x61, 0x69, 0x72, +0x70, 0x6c, 0x61, 0x6e, 0x65, 0x61, 0x72, 0x72, 0x69, 0x76, 0x69, 0x6e, +0x67, 0xd83d, 0xde80, 0x3a, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x3a, 0x72, +0x6f, 0x63, 0x6b, 0x65, 0x74, 0xd83d, 0xdef0, 0x3a, 0x73, 0x61, 0x74, 0x65, +0x6c, 0x6c, 0x69, 0x74, 0x65, 0x5f, 0x6f, 0x72, 0x62, 0x69, 0x74, 0x61, +0x6c, 0x3a, 0x6f, 0x72, 0x62, 0x69, 0x74, 0x61, 0x6c, 0x73, 0x61, 0x74, +0x65, 0x6c, 0x6c, 0x69, 0x74, 0x65, 0xd83d, 0xdcba, 0x3a, 0x73, 0x65, 0x61, +0x74, 0x3a, 0x73, 0x65, 0x61, 0x74, 0xd83d, 0xdef6, 0x3a, 0x6b, 0x61, 0x79, +0x61, 0x6b, 0x3a, 0x6b, 0x61, 0x79, 0x61, 0x6b, 0xd83d, 0xdef6, 0x3a, 0x63, +0x61, 0x6e, 0x6f, 0x65, 0x3a, 0x63, 0x61, 0x6e, 0x6f, 0x65, 0x26f5, 0xfe0f, +0x3a, 0x73, 0x61, 0x69, 0x6c, 0x62, 0x6f, 0x61, 0x74, 0x3a, 0x73, 0x61, +0x69, 0x6c, 0x62, 0x6f, 0x61, 0x74, 0xd83d, 0xdee5, 0x3a, 0x6d, 0x6f, 0x74, +0x6f, 0x72, 0x62, 0x6f, 0x61, 0x74, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, +0x62, 0x6f, 0x61, 0x74, 0xd83d, 0xdea4, 0x3a, 0x73, 0x70, 0x65, 0x65, 0x64, +0x62, 0x6f, 0x61, 0x74, 0x3a, 0x73, 0x70, 0x65, 0x65, 0x64, 0x62, 0x6f, +0x61, 0x74, 0xd83d, 0xdef3, 0x3a, 0x70, 0x61, 0x73, 0x73, 0x65, 0x6e, 0x67, +0x65, 0x72, 0x5f, 0x73, 0x68, 0x69, 0x70, 0x3a, 0x70, 0x61, 0x73, 0x73, +0x65, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0xd83d, 0xdef3, 0x3a, +0x63, 0x72, 0x75, 0x69, 0x73, 0x65, 0x5f, 0x73, 0x68, 0x69, 0x70, 0x3a, +0x63, 0x72, 0x75, 0x69, 0x73, 0x65, 0x73, 0x68, 0x69, 0x70, 0x26f4, 0x3a, +0x66, 0x65, 0x72, 0x72, 0x79, 0x3a, 0x66, 0x65, 0x72, 0x72, 0x79, 0xd83d, +0xdea2, 0x3a, 0x73, 0x68, 0x69, 0x70, 0x3a, 0x73, 0x68, 0x69, 0x70, 0x2693, +0xfe0f, 0x3a, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x3a, 0x61, 0x6e, 0x63, +0x68, 0x6f, 0x72, 0xd83d, 0xdea7, 0x3a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, +0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x63, 0x6f, 0x6e, 0x73, 0x74, +0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x26fd, 0xfe0f, 0x3a, 0x66, 0x75, +0x65, 0x6c, 0x70, 0x75, 0x6d, 0x70, 0x3a, 0x66, 0x75, 0x65, 0x6c, 0x70, +0x75, 0x6d, 0x70, 0xd83d, 0xde8f, 0x3a, 0x62, 0x75, 0x73, 0x73, 0x74, 0x6f, +0x70, 0x3a, 0x62, 0x75, 0x73, 0x73, 0x74, 0x6f, 0x70, 0xd83d, 0xdea6, 0x3a, +0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x74, 0x72, 0x61, +0x66, 0x66, 0x69, 0x63, 0x5f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x6c, +0x69, 0x67, 0x68, 0x74, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x76, +0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0xd83d, 0xdea5, 0x3a, 0x74, 0x72, +0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x3a, +0x6c, 0x69, 0x67, 0x68, 0x74, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, +0xd83d, 0xddfa, 0x3a, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x70, +0x3a, 0x6d, 0x61, 0x70, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0xd83d, 0xddfa, 0x3a, +0x6d, 0x61, 0x70, 0x3a, 0x6d, 0x61, 0x70, 0xd83d, 0xddff, 0x3a, 0x6d, 0x6f, +0x79, 0x61, 0x69, 0x3a, 0x6d, 0x6f, 0x79, 0x61, 0x69, 0xd83d, 0xddfd, 0x3a, +0x73, 0x74, 0x61, 0x74, 0x75, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x6c, 0x69, +0x62, 0x65, 0x72, 0x74, 0x79, 0x3a, 0x6c, 0x69, 0x62, 0x65, 0x72, 0x74, +0x79, 0x6f, 0x66, 0x73, 0x74, 0x61, 0x74, 0x75, 0x65, 0x26f2, 0xfe0f, 0x3a, +0x66, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x3a, 0x66, 0x6f, 0x75, +0x6e, 0x74, 0x61, 0x69, 0x6e, 0xd83d, 0xddfc, 0x3a, 0x74, 0x6f, 0x6b, 0x79, +0x6f, 0x5f, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x3a, 0x74, 0x6f, 0x6b, 0x79, +0x6f, 0x74, 0x6f, 0x77, 0x65, 0x72, 0xd83c, 0xdff0, 0x3a, 0x65, 0x75, 0x72, +0x6f, 0x70, 0x65, 0x61, 0x6e, 0x5f, 0x63, 0x61, 0x73, 0x74, 0x6c, 0x65, +0x3a, 0x63, 0x61, 0x73, 0x74, 0x6c, 0x65, 0x65, 0x75, 0x72, 0x6f, 0x70, +0x65, 0x61, 0x6e, 0xd83c, 0xdfef, 0x3a, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x65, +0x73, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x74, 0x6c, 0x65, 0x3a, 0x63, 0x61, +0x73, 0x74, 0x6c, 0x65, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x65, 0x73, 0x65, +0xd83c, 0xdfdf, 0x3a, 0x73, 0x74, 0x61, 0x64, 0x69, 0x75, 0x6d, 0x3a, 0x73, +0x74, 0x61, 0x64, 0x69, 0x75, 0x6d, 0xd83c, 0xdfa1, 0x3a, 0x66, 0x65, 0x72, +0x72, 0x69, 0x73, 0x5f, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x3a, 0x66, 0x65, +0x72, 0x72, 0x69, 0x73, 0x77, 0x68, 0x65, 0x65, 0x6c, 0xd83c, 0xdfa2, 0x3a, +0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x61, 0x73, 0x74, +0x65, 0x72, 0x3a, 0x63, 0x6f, 0x61, 0x73, 0x74, 0x65, 0x72, 0x72, 0x6f, +0x6c, 0x6c, 0x65, 0x72, 0xd83c, 0xdfa0, 0x3a, 0x63, 0x61, 0x72, 0x6f, 0x75, +0x73, 0x65, 0x6c, 0x5f, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x3a, 0x63, 0x61, +0x72, 0x6f, 0x75, 0x73, 0x65, 0x6c, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x26f1, +0x3a, 0x75, 0x6d, 0x62, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x5f, 0x6f, 0x6e, +0x5f, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x67, 0x72, 0x6f, 0x75, +0x6e, 0x64, 0x6f, 0x6e, 0x75, 0x6d, 0x62, 0x72, 0x65, 0x6c, 0x6c, 0x61, +0x26f1, 0x3a, 0x62, 0x65, 0x61, 0x63, 0x68, 0x5f, 0x75, 0x6d, 0x62, 0x72, +0x65, 0x6c, 0x6c, 0x61, 0x3a, 0x62, 0x65, 0x61, 0x63, 0x68, 0x75, 0x6d, +0x62, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0xd83c, 0xdfd6, 0x3a, 0x62, 0x65, 0x61, +0x63, 0x68, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x75, 0x6d, 0x62, 0x72, +0x65, 0x6c, 0x6c, 0x61, 0x3a, 0x62, 0x65, 0x61, 0x63, 0x68, 0x75, 0x6d, +0x62, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdfd6, +0x3a, 0x62, 0x65, 0x61, 0x63, 0x68, 0x3a, 0x62, 0x65, 0x61, 0x63, 0x68, +0xd83c, 0xdfdd, 0x3a, 0x64, 0x65, 0x73, 0x65, 0x72, 0x74, 0x5f, 0x69, 0x73, +0x6c, 0x61, 0x6e, 0x64, 0x3a, 0x64, 0x65, 0x73, 0x65, 0x72, 0x74, 0x69, +0x73, 0x6c, 0x61, 0x6e, 0x64, 0xd83c, 0xdfdd, 0x3a, 0x69, 0x73, 0x6c, 0x61, +0x6e, 0x64, 0x3a, 0x69, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x26f0, 0x3a, 0x6d, +0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x3a, 0x6d, 0x6f, 0x75, 0x6e, +0x74, 0x61, 0x69, 0x6e, 0xd83c, 0xdfd4, 0x3a, 0x73, 0x6e, 0x6f, 0x77, 0x5f, +0x63, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, +0x61, 0x69, 0x6e, 0x3a, 0x63, 0x61, 0x70, 0x70, 0x65, 0x64, 0x6d, 0x6f, +0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x6e, 0x6f, 0x77, 0xd83c, 0xdfd4, +0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x6e, +0x6f, 0x77, 0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, +0x6e, 0x6f, 0x77, 0xd83d, 0xddfb, 0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, +0x66, 0x75, 0x6a, 0x69, 0x3a, 0x66, 0x75, 0x6a, 0x69, 0x6d, 0x6f, 0x75, +0x6e, 0x74, 0xd83c, 0xdf0b, 0x3a, 0x76, 0x6f, 0x6c, 0x63, 0x61, 0x6e, 0x6f, +0x3a, 0x76, 0x6f, 0x6c, 0x63, 0x61, 0x6e, 0x6f, 0xd83c, 0xdfdc, 0x3a, 0x64, +0x65, 0x73, 0x65, 0x72, 0x74, 0x3a, 0x64, 0x65, 0x73, 0x65, 0x72, 0x74, +0xd83c, 0xdfd5, 0x3a, 0x63, 0x61, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x3a, 0x63, +0x61, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x26fa, 0xfe0f, 0x3a, 0x74, 0x65, 0x6e, +0x74, 0x3a, 0x74, 0x65, 0x6e, 0x74, 0xd83d, 0xdee4, 0x3a, 0x72, 0x61, 0x69, +0x6c, 0x72, 0x6f, 0x61, 0x64, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x3a, +0x72, 0x61, 0x69, 0x6c, 0x72, 0x6f, 0x61, 0x64, 0x74, 0x72, 0x61, 0x63, +0x6b, 0xd83d, 0xdee4, 0x3a, 0x72, 0x61, 0x69, 0x6c, 0x77, 0x61, 0x79, 0x5f, +0x74, 0x72, 0x61, 0x63, 0x6b, 0x3a, 0x72, 0x61, 0x69, 0x6c, 0x77, 0x61, +0x79, 0x74, 0x72, 0x61, 0x63, 0x6b, 0xd83d, 0xdee3, 0x3a, 0x6d, 0x6f, 0x74, +0x6f, 0x72, 0x77, 0x61, 0x79, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x77, +0x61, 0x79, 0xd83c, 0xdfd7, 0x3a, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, +0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, +0x6f, 0x6e, 0x3a, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x63, +0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0xd83c, +0xdfd7, 0x3a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, +0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x74, 0x65, 0x3a, 0x63, 0x6f, 0x6e, 0x73, +0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x69, 0x74, 0x65, +0xd83c, 0xdfed, 0x3a, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x3a, 0x66, +0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0xd83c, 0xdfe0, 0x3a, 0x68, 0x6f, 0x75, +0x73, 0x65, 0x3a, 0x68, 0x6f, 0x75, 0x73, 0x65, 0xd83c, 0xdfe1, 0x3a, 0x68, +0x6f, 0x75, 0x73, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x67, 0x61, +0x72, 0x64, 0x65, 0x6e, 0x3a, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x68, +0x6f, 0x75, 0x73, 0x65, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdfd8, 0x3a, 0x68, +0x6f, 0x75, 0x73, 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, +0x67, 0x73, 0x3a, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x73, +0x68, 0x6f, 0x75, 0x73, 0x65, 0xd83c, 0xdfd8, 0x3a, 0x68, 0x6f, 0x6d, 0x65, +0x73, 0x3a, 0x68, 0x6f, 0x6d, 0x65, 0x73, 0xd83c, 0xdfda, 0x3a, 0x64, 0x65, +0x72, 0x65, 0x6c, 0x69, 0x63, 0x74, 0x5f, 0x68, 0x6f, 0x75, 0x73, 0x65, +0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x75, +0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x64, 0x65, 0x72, 0x65, 0x6c, 0x69, +0x63, 0x74, 0x68, 0x6f, 0x75, 0x73, 0x65, 0xd83c, 0xdfda, 0x3a, 0x68, 0x6f, +0x75, 0x73, 0x65, 0x5f, 0x61, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x65, +0x64, 0x3a, 0x61, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x64, 0x68, +0x6f, 0x75, 0x73, 0x65, 0xd83c, 0xdfe2, 0x3a, 0x6f, 0x66, 0x66, 0x69, 0x63, +0x65, 0x3a, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0xd83c, 0xdfec, 0x3a, 0x64, +0x65, 0x70, 0x61, 0x72, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, +0x6f, 0x72, 0x65, 0x3a, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x6d, 0x65, +0x6e, 0x74, 0x73, 0x74, 0x6f, 0x72, 0x65, 0xd83c, 0xdfe3, 0x3a, 0x70, 0x6f, +0x73, 0x74, 0x5f, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x3a, 0x6f, 0x66, +0x66, 0x69, 0x63, 0x65, 0x70, 0x6f, 0x73, 0x74, 0xd83c, 0xdfe4, 0x3a, 0x65, +0x75, 0x72, 0x6f, 0x70, 0x65, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x73, 0x74, +0x5f, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x3a, 0x65, 0x75, 0x72, 0x6f, +0x70, 0x65, 0x61, 0x6e, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x70, 0x6f, +0x73, 0x74, 0xd83c, 0xdfe5, 0x3a, 0x68, 0x6f, 0x73, 0x70, 0x69, 0x74, 0x61, +0x6c, 0x3a, 0x68, 0x6f, 0x73, 0x70, 0x69, 0x74, 0x61, 0x6c, 0xd83c, 0xdfe6, +0x3a, 0x62, 0x61, 0x6e, 0x6b, 0x3a, 0x62, 0x61, 0x6e, 0x6b, 0xd83c, 0xdfe8, +0x3a, 0x68, 0x6f, 0x74, 0x65, 0x6c, 0x3a, 0x68, 0x6f, 0x74, 0x65, 0x6c, +0xd83c, 0xdfea, 0x3a, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x6e, 0x69, 0x65, 0x6e, +0x63, 0x65, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x63, 0x6f, 0x6e, +0x76, 0x65, 0x6e, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, +0x65, 0xd83c, 0xdfeb, 0x3a, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x3a, 0x73, +0x63, 0x68, 0x6f, 0x6f, 0x6c, 0xd83c, 0xdfe9, 0x3a, 0x6c, 0x6f, 0x76, 0x65, +0x5f, 0x68, 0x6f, 0x74, 0x65, 0x6c, 0x3a, 0x68, 0x6f, 0x74, 0x65, 0x6c, +0x6c, 0x6f, 0x76, 0x65, 0xd83d, 0xdc92, 0x3a, 0x77, 0x65, 0x64, 0x64, 0x69, +0x6e, 0x67, 0x3a, 0x77, 0x65, 0x64, 0x64, 0x69, 0x6e, 0x67, 0xd83c, 0xdfdb, +0x3a, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x62, +0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x75, 0x69, 0x6c, +0x64, 0x69, 0x6e, 0x67, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x63, 0x61, +0x6c, 0x26ea, 0xfe0f, 0x3a, 0x63, 0x68, 0x75, 0x72, 0x63, 0x68, 0x3a, 0x63, +0x68, 0x75, 0x72, 0x63, 0x68, 0xd83d, 0xdd4c, 0x3a, 0x6d, 0x6f, 0x73, 0x71, +0x75, 0x65, 0x3a, 0x6d, 0x6f, 0x73, 0x71, 0x75, 0x65, 0xd83d, 0xdd4d, 0x3a, +0x73, 0x79, 0x6e, 0x61, 0x67, 0x6f, 0x67, 0x75, 0x65, 0x3a, 0x73, 0x79, +0x6e, 0x61, 0x67, 0x6f, 0x67, 0x75, 0x65, 0xd83d, 0xdd4b, 0x3a, 0x6b, 0x61, +0x61, 0x62, 0x61, 0x3a, 0x6b, 0x61, 0x61, 0x62, 0x61, 0x26e9, 0x3a, 0x73, +0x68, 0x69, 0x6e, 0x74, 0x6f, 0x5f, 0x73, 0x68, 0x72, 0x69, 0x6e, 0x65, +0x3a, 0x73, 0x68, 0x69, 0x6e, 0x74, 0x6f, 0x73, 0x68, 0x72, 0x69, 0x6e, +0x65, 0xd83d, 0xddfe, 0x3a, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x3a, 0x6a, 0x61, +0x70, 0x61, 0x6e, 0xd83c, 0xdf91, 0x3a, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x73, +0x63, 0x65, 0x6e, 0x65, 0x3a, 0x72, 0x69, 0x63, 0x65, 0x73, 0x63, 0x65, +0x6e, 0x65, 0xd83c, 0xdfde, 0x3a, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, +0x6c, 0x5f, 0x70, 0x61, 0x72, 0x6b, 0x3a, 0x6e, 0x61, 0x74, 0x69, 0x6f, +0x6e, 0x61, 0x6c, 0x70, 0x61, 0x72, 0x6b, 0xd83c, 0xdfde, 0x3a, 0x70, 0x61, +0x72, 0x6b, 0x3a, 0x70, 0x61, 0x72, 0x6b, 0xd83c, 0xdf05, 0x3a, 0x73, 0x75, +0x6e, 0x72, 0x69, 0x73, 0x65, 0x3a, 0x73, 0x75, 0x6e, 0x72, 0x69, 0x73, +0x65, 0xd83c, 0xdf04, 0x3a, 0x73, 0x75, 0x6e, 0x72, 0x69, 0x73, 0x65, 0x5f, +0x6f, 0x76, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, +0x6e, 0x73, 0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, +0x6f, 0x76, 0x65, 0x72, 0x73, 0x75, 0x6e, 0x72, 0x69, 0x73, 0x65, 0xd83c, +0xdf20, 0x3a, 0x73, 0x74, 0x61, 0x72, 0x73, 0x3a, 0x73, 0x74, 0x61, 0x72, +0x73, 0xd83c, 0xdf87, 0x3a, 0x73, 0x70, 0x61, 0x72, 0x6b, 0x6c, 0x65, 0x72, +0x3a, 0x73, 0x70, 0x61, 0x72, 0x6b, 0x6c, 0x65, 0x72, 0xd83c, 0xdf86, 0x3a, +0x66, 0x69, 0x72, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x3a, 0x66, 0x69, +0x72, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0xd83c, 0xdf07, 0x3a, 0x63, 0x69, +0x74, 0x79, 0x5f, 0x73, 0x75, 0x6e, 0x72, 0x69, 0x73, 0x65, 0x3a, 0x63, +0x69, 0x74, 0x79, 0x73, 0x75, 0x6e, 0x72, 0x69, 0x73, 0x65, 0xd83c, 0xdf07, +0x3a, 0x63, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x75, 0x6e, 0x73, 0x65, 0x74, +0x3a, 0x63, 0x69, 0x74, 0x79, 0x73, 0x75, 0x6e, 0x73, 0x65, 0x74, 0xd83c, +0xdf06, 0x3a, 0x63, 0x69, 0x74, 0x79, 0x5f, 0x64, 0x75, 0x73, 0x6b, 0x3a, +0x63, 0x69, 0x74, 0x79, 0x64, 0x75, 0x73, 0x6b, 0xd83c, 0xdfd9, 0x3a, 0x63, +0x69, 0x74, 0x79, 0x73, 0x63, 0x61, 0x70, 0x65, 0x3a, 0x63, 0x69, 0x74, +0x79, 0x73, 0x63, 0x61, 0x70, 0x65, 0xd83c, 0xdf03, 0x3a, 0x6e, 0x69, 0x67, +0x68, 0x74, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x73, 0x74, 0x61, 0x72, +0x73, 0x3a, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x73, 0x74, 0x61, 0x72, 0x73, +0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf0c, 0x3a, 0x6d, 0x69, 0x6c, 0x6b, 0x79, +0x5f, 0x77, 0x61, 0x79, 0x3a, 0x6d, 0x69, 0x6c, 0x6b, 0x79, 0x77, 0x61, +0x79, 0xd83c, 0xdf09, 0x3a, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x61, +0x74, 0x5f, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x61, 0x74, 0x62, 0x72, +0x69, 0x64, 0x67, 0x65, 0x6e, 0x69, 0x67, 0x68, 0x74, 0xd83c, 0xdf01, 0x3a, +0x66, 0x6f, 0x67, 0x67, 0x79, 0x3a, 0x66, 0x6f, 0x67, 0x67, 0x79, 0x231a, +0xfe0f, 0x3a, 0x77, 0x61, 0x74, 0x63, 0x68, 0x3a, 0x77, 0x61, 0x74, 0x63, +0x68, 0xd83d, 0xdcf1, 0x3a, 0x69, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x3a, 0x69, +0x70, 0x68, 0x6f, 0x6e, 0x65, 0xd83d, 0xdcf2, 0x3a, 0x63, 0x61, 0x6c, 0x6c, +0x69, 0x6e, 0x67, 0x3a, 0x63, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0xd83d, +0xdcbb, 0x3a, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x3a, 0x63, +0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x2328, 0xfe0f, 0x3a, 0x6b, 0x65, +0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x3a, 0x6b, 0x65, 0x79, 0x62, 0x6f, +0x61, 0x72, 0x64, 0xd83d, 0xdda5, 0x3a, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, +0x70, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x3a, 0x63, +0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x64, 0x65, 0x73, 0x6b, 0x74, +0x6f, 0x70, 0xd83d, 0xdda5, 0x3a, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, +0x3a, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0xd83d, 0xdda8, 0x3a, 0x70, +0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x3a, 0x70, 0x72, 0x69, 0x6e, 0x74, +0x65, 0x72, 0xd83d, 0xddb1, 0x3a, 0x74, 0x68, 0x72, 0x65, 0x65, 0x5f, 0x62, +0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5f, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x3a, +0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x74, +0x68, 0x72, 0x65, 0x65, 0xd83d, 0xddb1, 0x3a, 0x6d, 0x6f, 0x75, 0x73, 0x65, +0x5f, 0x74, 0x68, 0x72, 0x65, 0x65, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, +0x6e, 0x3a, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x6d, 0x6f, 0x75, 0x73, +0x65, 0x74, 0x68, 0x72, 0x65, 0x65, 0xd83d, 0xddb2, 0x3a, 0x74, 0x72, 0x61, +0x63, 0x6b, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x74, 0x72, 0x61, 0x63, 0x6b, +0x62, 0x61, 0x6c, 0x6c, 0xd83d, 0xdd79, 0x3a, 0x6a, 0x6f, 0x79, 0x73, 0x74, +0x69, 0x63, 0x6b, 0x3a, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, +0xd83d, 0xdddc, 0x3a, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, +0x6f, 0x6e, 0x3a, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, +0x6f, 0x6e, 0xd83d, 0xdcbd, 0x3a, 0x6d, 0x69, 0x6e, 0x69, 0x64, 0x69, 0x73, +0x63, 0x3a, 0x6d, 0x69, 0x6e, 0x69, 0x64, 0x69, 0x73, 0x63, 0xd83d, 0xdcbe, +0x3a, 0x66, 0x6c, 0x6f, 0x70, 0x70, 0x79, 0x5f, 0x64, 0x69, 0x73, 0x6b, +0x3a, 0x64, 0x69, 0x73, 0x6b, 0x66, 0x6c, 0x6f, 0x70, 0x70, 0x79, 0xd83d, +0xdcbf, 0x3a, 0x63, 0x64, 0x3a, 0x63, 0x64, 0xd83d, 0xdcc0, 0x3a, 0x64, 0x76, +0x64, 0x3a, 0x64, 0x76, 0x64, 0xd83d, 0xdcfc, 0x3a, 0x76, 0x68, 0x73, 0x3a, +0x76, 0x68, 0x73, 0xd83d, 0xdcf7, 0x3a, 0x63, 0x61, 0x6d, 0x65, 0x72, 0x61, +0x3a, 0x63, 0x61, 0x6d, 0x65, 0x72, 0x61, 0xd83d, 0xdcf8, 0x3a, 0x63, 0x61, +0x6d, 0x65, 0x72, 0x61, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x66, 0x6c, +0x61, 0x73, 0x68, 0x3a, 0x63, 0x61, 0x6d, 0x65, 0x72, 0x61, 0x66, 0x6c, +0x61, 0x73, 0x68, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdcf9, 0x3a, 0x76, 0x69, +0x64, 0x65, 0x6f, 0x5f, 0x63, 0x61, 0x6d, 0x65, 0x72, 0x61, 0x3a, 0x63, +0x61, 0x6d, 0x65, 0x72, 0x61, 0x76, 0x69, 0x64, 0x65, 0x6f, 0xd83c, 0xdfa5, +0x3a, 0x6d, 0x6f, 0x76, 0x69, 0x65, 0x5f, 0x63, 0x61, 0x6d, 0x65, 0x72, +0x61, 0x3a, 0x63, 0x61, 0x6d, 0x65, 0x72, 0x61, 0x6d, 0x6f, 0x76, 0x69, +0x65, 0xd83d, 0xdcfd, 0x3a, 0x66, 0x69, 0x6c, 0x6d, 0x5f, 0x70, 0x72, 0x6f, +0x6a, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x3a, 0x66, 0x69, 0x6c, 0x6d, 0x70, +0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x6f, 0x72, 0xd83d, 0xdcfd, 0x3a, 0x70, +0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x3a, 0x70, 0x72, 0x6f, +0x6a, 0x65, 0x63, 0x74, 0x6f, 0x72, 0xd83c, 0xdf9e, 0x3a, 0x66, 0x69, 0x6c, +0x6d, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3a, 0x66, 0x69, 0x6c, +0x6d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0xd83d, 0xdcde, 0x3a, 0x74, 0x65, +0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x65, +0x69, 0x76, 0x65, 0x72, 0x3a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, +0x72, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x260e, 0xfe0f, +0x3a, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x3a, 0x74, +0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0xd83d, 0xdcdf, 0x3a, 0x70, +0x61, 0x67, 0x65, 0x72, 0x3a, 0x70, 0x61, 0x67, 0x65, 0x72, 0xd83d, 0xdce0, +0x3a, 0x66, 0x61, 0x78, 0x3a, 0x66, 0x61, 0x78, 0xd83d, 0xdcfa, 0x3a, 0x74, +0x76, 0x3a, 0x74, 0x76, 0xd83d, 0xdcfb, 0x3a, 0x72, 0x61, 0x64, 0x69, 0x6f, +0x3a, 0x72, 0x61, 0x64, 0x69, 0x6f, 0xd83c, 0xdf99, 0x3a, 0x73, 0x74, 0x75, +0x64, 0x69, 0x6f, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x70, 0x68, 0x6f, +0x6e, 0x65, 0x3a, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x70, 0x68, 0x6f, 0x6e, +0x65, 0x73, 0x74, 0x75, 0x64, 0x69, 0x6f, 0xd83c, 0xdf99, 0x3a, 0x6d, 0x69, +0x63, 0x72, 0x6f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x32, 0x3a, 0x6d, 0x69, +0x63, 0x72, 0x6f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x32, 0xd83c, 0xdf9a, 0x3a, +0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x72, +0x3a, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x72, +0xd83c, 0xdf9b, 0x3a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x6b, +0x6e, 0x6f, 0x62, 0x73, 0x3a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, +0x6b, 0x6e, 0x6f, 0x62, 0x73, 0x23f1, 0x3a, 0x73, 0x74, 0x6f, 0x70, 0x77, +0x61, 0x74, 0x63, 0x68, 0x3a, 0x73, 0x74, 0x6f, 0x70, 0x77, 0x61, 0x74, +0x63, 0x68, 0x23f2, 0x3a, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x5f, 0x63, 0x6c, +0x6f, 0x63, 0x6b, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x74, 0x69, 0x6d, +0x65, 0x72, 0x23f2, 0x3a, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x3a, 0x74, 0x69, +0x6d, 0x65, 0x72, 0x23f0, 0x3a, 0x61, 0x6c, 0x61, 0x72, 0x6d, 0x5f, 0x63, +0x6c, 0x6f, 0x63, 0x6b, 0x3a, 0x61, 0x6c, 0x61, 0x72, 0x6d, 0x63, 0x6c, +0x6f, 0x63, 0x6b, 0xd83d, 0xdd70, 0x3a, 0x6d, 0x61, 0x6e, 0x74, 0x6c, 0x65, +0x70, 0x69, 0x65, 0x63, 0x65, 0x5f, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x3a, +0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x6d, 0x61, 0x6e, 0x74, 0x6c, 0x65, 0x70, +0x69, 0x65, 0x63, 0x65, 0xd83d, 0xdd70, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, +0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x231b, 0xfe0f, 0x3a, 0x68, 0x6f, 0x75, +0x72, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x3a, 0x68, 0x6f, 0x75, 0x72, 0x67, +0x6c, 0x61, 0x73, 0x73, 0x23f3, 0x3a, 0x68, 0x6f, 0x75, 0x72, 0x67, 0x6c, +0x61, 0x73, 0x73, 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x5f, +0x73, 0x61, 0x6e, 0x64, 0x3a, 0x66, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, +0x68, 0x6f, 0x75, 0x72, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x73, 0x61, 0x6e, +0x64, 0xd83d, 0xdce1, 0x3a, 0x73, 0x61, 0x74, 0x65, 0x6c, 0x6c, 0x69, 0x74, +0x65, 0x3a, 0x73, 0x61, 0x74, 0x65, 0x6c, 0x6c, 0x69, 0x74, 0x65, 0xd83d, +0xdd0b, 0x3a, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x3a, 0x62, 0x61, +0x74, 0x74, 0x65, 0x72, 0x79, 0xd83d, 0xdd0c, 0x3a, 0x65, 0x6c, 0x65, 0x63, +0x74, 0x72, 0x69, 0x63, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x3a, 0x65, 0x6c, +0x65, 0x63, 0x74, 0x72, 0x69, 0x63, 0x70, 0x6c, 0x75, 0x67, 0xd83d, 0xdca1, +0x3a, 0x62, 0x75, 0x6c, 0x62, 0x3a, 0x62, 0x75, 0x6c, 0x62, 0xd83d, 0xdd26, +0x3a, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x3a, +0x66, 0x6c, 0x61, 0x73, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0xd83d, 0xdd6f, +0x3a, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x3a, 0x63, 0x61, 0x6e, 0x64, +0x6c, 0x65, 0xd83d, 0xddd1, 0x3a, 0x77, 0x61, 0x73, 0x74, 0x65, 0x62, 0x61, +0x73, 0x6b, 0x65, 0x74, 0x3a, 0x77, 0x61, 0x73, 0x74, 0x65, 0x62, 0x61, +0x73, 0x6b, 0x65, 0x74, 0xd83d, 0xdee2, 0x3a, 0x6f, 0x69, 0x6c, 0x5f, 0x64, +0x72, 0x75, 0x6d, 0x3a, 0x64, 0x72, 0x75, 0x6d, 0x6f, 0x69, 0x6c, 0xd83d, +0xdee2, 0x3a, 0x6f, 0x69, 0x6c, 0x3a, 0x6f, 0x69, 0x6c, 0xd83d, 0xdcb8, 0x3a, +0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x77, +0x69, 0x6e, 0x67, 0x73, 0x3a, 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x77, 0x69, +0x6e, 0x67, 0x73, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdcb5, 0x3a, 0x64, 0x6f, +0x6c, 0x6c, 0x61, 0x72, 0x3a, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0xd83d, +0xdcb4, 0x3a, 0x79, 0x65, 0x6e, 0x3a, 0x79, 0x65, 0x6e, 0xd83d, 0xdcb6, 0x3a, +0x65, 0x75, 0x72, 0x6f, 0x3a, 0x65, 0x75, 0x72, 0x6f, 0xd83d, 0xdcb7, 0x3a, +0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0xd83d, +0xdcb0, 0x3a, 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x62, 0x61, 0x67, 0x3a, 0x6d, +0x6f, 0x6e, 0x65, 0x79, 0x62, 0x61, 0x67, 0xd83d, 0xdcb3, 0x3a, 0x63, 0x72, +0x65, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x61, 0x72, 0x64, 0x3a, 0x63, 0x61, +0x72, 0x64, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0xd83d, 0xdc8e, 0x3a, 0x67, +0x65, 0x6d, 0x3a, 0x67, 0x65, 0x6d, 0x2696, 0xfe0f, 0x3a, 0x73, 0x63, 0x61, +0x6c, 0x65, 0x73, 0x3a, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x73, 0xd83d, 0xdd27, +0x3a, 0x77, 0x72, 0x65, 0x6e, 0x63, 0x68, 0x3a, 0x77, 0x72, 0x65, 0x6e, +0x63, 0x68, 0xd83d, 0xdd28, 0x3a, 0x68, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x3a, +0x68, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x2692, 0x3a, 0x68, 0x61, 0x6d, 0x6d, +0x65, 0x72, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x69, 0x63, 0x6b, 0x3a, +0x61, 0x6e, 0x64, 0x68, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x70, 0x69, 0x63, +0x6b, 0x2692, 0x3a, 0x68, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x5f, 0x70, 0x69, +0x63, 0x6b, 0x3a, 0x68, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x70, 0x69, 0x63, +0x6b, 0xd83d, 0xdee0, 0x3a, 0x68, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x5f, 0x61, +0x6e, 0x64, 0x5f, 0x77, 0x72, 0x65, 0x6e, 0x63, 0x68, 0x3a, 0x61, 0x6e, +0x64, 0x68, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x77, 0x72, 0x65, 0x6e, 0x63, +0x68, 0xd83d, 0xdee0, 0x3a, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x3a, 0x74, 0x6f, +0x6f, 0x6c, 0x73, 0x26cf, 0x3a, 0x70, 0x69, 0x63, 0x6b, 0x3a, 0x70, 0x69, +0x63, 0x6b, 0xd83d, 0xdd29, 0x3a, 0x6e, 0x75, 0x74, 0x5f, 0x61, 0x6e, 0x64, +0x5f, 0x62, 0x6f, 0x6c, 0x74, 0x3a, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x6c, +0x74, 0x6e, 0x75, 0x74, 0x2699, 0xfe0f, 0x3a, 0x67, 0x65, 0x61, 0x72, 0x3a, +0x67, 0x65, 0x61, 0x72, 0x26d3, 0x3a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, +0x3a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0xd83d, 0xdd2b, 0x3a, 0x67, 0x75, +0x6e, 0x3a, 0x67, 0x75, 0x6e, 0xd83d, 0xdca3, 0x3a, 0x62, 0x6f, 0x6d, 0x62, +0x3a, 0x62, 0x6f, 0x6d, 0x62, 0xd83d, 0xdd2a, 0x3a, 0x6b, 0x6e, 0x69, 0x66, +0x65, 0x3a, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0xd83d, 0xdde1, 0x3a, 0x64, 0x61, +0x67, 0x67, 0x65, 0x72, 0x5f, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x3a, 0x64, +0x61, 0x67, 0x67, 0x65, 0x72, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0xd83d, 0xdde1, +0x3a, 0x64, 0x61, 0x67, 0x67, 0x65, 0x72, 0x3a, 0x64, 0x61, 0x67, 0x67, +0x65, 0x72, 0x2694, 0xfe0f, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x64, +0x5f, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x3a, 0x63, 0x72, 0x6f, 0x73, +0x73, 0x65, 0x64, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0xd83d, 0xdee1, 0x3a, +0x73, 0x68, 0x69, 0x65, 0x6c, 0x64, 0x3a, 0x73, 0x68, 0x69, 0x65, 0x6c, +0x64, 0xd83d, 0xdeac, 0x3a, 0x73, 0x6d, 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x3a, +0x73, 0x6d, 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x26b0, 0xfe0f, 0x3a, 0x63, 0x6f, +0x66, 0x66, 0x69, 0x6e, 0x3a, 0x63, 0x6f, 0x66, 0x66, 0x69, 0x6e, 0x26b1, +0xfe0f, 0x3a, 0x66, 0x75, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x75, 0x72, +0x6e, 0x3a, 0x66, 0x75, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x75, 0x72, 0x6e, +0x26b1, 0xfe0f, 0x3a, 0x75, 0x72, 0x6e, 0x3a, 0x75, 0x72, 0x6e, 0xd83c, 0xdffa, +0x3a, 0x61, 0x6d, 0x70, 0x68, 0x6f, 0x72, 0x61, 0x3a, 0x61, 0x6d, 0x70, +0x68, 0x6f, 0x72, 0x61, 0xd83d, 0xdd2e, 0x3a, 0x63, 0x72, 0x79, 0x73, 0x74, +0x61, 0x6c, 0x5f, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, +0x63, 0x72, 0x79, 0x73, 0x74, 0x61, 0x6c, 0xd83d, 0xdcff, 0x3a, 0x70, 0x72, +0x61, 0x79, 0x65, 0x72, 0x5f, 0x62, 0x65, 0x61, 0x64, 0x73, 0x3a, 0x62, +0x65, 0x61, 0x64, 0x73, 0x70, 0x72, 0x61, 0x79, 0x65, 0x72, 0xd83d, 0xdc88, +0x3a, 0x62, 0x61, 0x72, 0x62, 0x65, 0x72, 0x3a, 0x62, 0x61, 0x72, 0x62, +0x65, 0x72, 0x2697, 0xfe0f, 0x3a, 0x61, 0x6c, 0x65, 0x6d, 0x62, 0x69, 0x63, +0x3a, 0x61, 0x6c, 0x65, 0x6d, 0x62, 0x69, 0x63, 0xd83d, 0xdd2d, 0x3a, 0x74, +0x65, 0x6c, 0x65, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x3a, 0x74, 0x65, 0x6c, +0x65, 0x73, 0x63, 0x6f, 0x70, 0x65, 0xd83d, 0xdd2c, 0x3a, 0x6d, 0x69, 0x63, +0x72, 0x6f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x3a, 0x6d, 0x69, 0x63, 0x72, +0x6f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0xd83d, 0xdd73, 0x3a, 0x68, 0x6f, 0x6c, +0x65, 0x3a, 0x68, 0x6f, 0x6c, 0x65, 0xd83d, 0xdc8a, 0x3a, 0x70, 0x69, 0x6c, +0x6c, 0x3a, 0x70, 0x69, 0x6c, 0x6c, 0xd83d, 0xdc89, 0x3a, 0x73, 0x79, 0x72, +0x69, 0x6e, 0x67, 0x65, 0x3a, 0x73, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x65, +0xd83c, 0xdf21, 0x3a, 0x74, 0x68, 0x65, 0x72, 0x6d, 0x6f, 0x6d, 0x65, 0x74, +0x65, 0x72, 0x3a, 0x74, 0x68, 0x65, 0x72, 0x6d, 0x6f, 0x6d, 0x65, 0x74, +0x65, 0x72, 0xd83d, 0xdebd, 0x3a, 0x74, 0x6f, 0x69, 0x6c, 0x65, 0x74, 0x3a, +0x74, 0x6f, 0x69, 0x6c, 0x65, 0x74, 0xd83d, 0xdeb0, 0x3a, 0x70, 0x6f, 0x74, +0x61, 0x62, 0x6c, 0x65, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x3a, 0x70, +0x6f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x77, 0x61, 0x74, 0x65, 0x72, 0xd83d, +0xdebf, 0x3a, 0x73, 0x68, 0x6f, 0x77, 0x65, 0x72, 0x3a, 0x73, 0x68, 0x6f, +0x77, 0x65, 0x72, 0xd83d, 0xdec1, 0x3a, 0x62, 0x61, 0x74, 0x68, 0x74, 0x75, +0x62, 0x3a, 0x62, 0x61, 0x74, 0x68, 0x74, 0x75, 0x62, 0xd83d, 0xdec0, 0x3a, +0x62, 0x61, 0x74, 0x68, 0x3a, 0x62, 0x61, 0x74, 0x68, 0xd83d, 0xdece, 0x3a, +0x62, 0x65, 0x6c, 0x6c, 0x68, 0x6f, 0x70, 0x5f, 0x62, 0x65, 0x6c, 0x6c, +0x3a, 0x62, 0x65, 0x6c, 0x6c, 0x62, 0x65, 0x6c, 0x6c, 0x68, 0x6f, 0x70, +0xd83d, 0xdece, 0x3a, 0x62, 0x65, 0x6c, 0x6c, 0x68, 0x6f, 0x70, 0x3a, 0x62, +0x65, 0x6c, 0x6c, 0x68, 0x6f, 0x70, 0xd83d, 0xdd11, 0x3a, 0x6b, 0x65, 0x79, +0x3a, 0x6b, 0x65, 0x79, 0xd83d, 0xdddd, 0x3a, 0x6f, 0x6c, 0x64, 0x5f, 0x6b, +0x65, 0x79, 0x3a, 0x6b, 0x65, 0x79, 0x6f, 0x6c, 0x64, 0xd83d, 0xdddd, 0x3a, +0x6b, 0x65, 0x79, 0x32, 0x3a, 0x6b, 0x65, 0x79, 0x32, 0xd83d, 0xdeaa, 0x3a, +0x64, 0x6f, 0x6f, 0x72, 0x3a, 0x64, 0x6f, 0x6f, 0x72, 0xd83d, 0xdecb, 0x3a, +0x63, 0x6f, 0x75, 0x63, 0x68, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x6c, 0x61, +0x6d, 0x70, 0x3a, 0x61, 0x6e, 0x64, 0x63, 0x6f, 0x75, 0x63, 0x68, 0x6c, +0x61, 0x6d, 0x70, 0xd83d, 0xdecb, 0x3a, 0x63, 0x6f, 0x75, 0x63, 0x68, 0x3a, +0x63, 0x6f, 0x75, 0x63, 0x68, 0xd83d, 0xdecf, 0x3a, 0x62, 0x65, 0x64, 0x3a, +0x62, 0x65, 0x64, 0xd83d, 0xdecc, 0x3a, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x69, +0x6e, 0x67, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x61, +0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, +0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x69, +0x6e, 0x67, 0xd83d, 0xddbc, 0x3a, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x77, +0x69, 0x74, 0x68, 0x5f, 0x70, 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, 0x3a, +0x66, 0x72, 0x61, 0x6d, 0x65, 0x70, 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, +0x77, 0x69, 0x74, 0x68, 0xd83d, 0xddbc, 0x3a, 0x66, 0x72, 0x61, 0x6d, 0x65, +0x5f, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x3a, 0x66, 0x72, 0x61, 0x6d, 0x65, +0x70, 0x68, 0x6f, 0x74, 0x6f, 0xd83d, 0xdecd, 0x3a, 0x73, 0x68, 0x6f, 0x70, +0x70, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x61, 0x67, 0x73, 0x3a, 0x62, 0x61, +0x67, 0x73, 0x73, 0x68, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xd83d, 0xded2, +0x3a, 0x73, 0x68, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, +0x6f, 0x6c, 0x6c, 0x65, 0x79, 0x3a, 0x73, 0x68, 0x6f, 0x70, 0x70, 0x69, +0x6e, 0x67, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x79, 0xd83d, 0xded2, 0x3a, +0x73, 0x68, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x61, 0x72, +0x74, 0x3a, 0x63, 0x61, 0x72, 0x74, 0x73, 0x68, 0x6f, 0x70, 0x70, 0x69, +0x6e, 0x67, 0xd83c, 0xdf81, 0x3a, 0x67, 0x69, 0x66, 0x74, 0x3a, 0x67, 0x69, +0x66, 0x74, 0xd83c, 0xdf88, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x6f, 0x6e, +0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x6f, 0x6e, 0xd83c, 0xdf8f, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0xd83c, 0xdf80, +0x3a, 0x72, 0x69, 0x62, 0x62, 0x6f, 0x6e, 0x3a, 0x72, 0x69, 0x62, 0x62, +0x6f, 0x6e, 0xd83c, 0xdf8a, 0x3a, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x74, 0x74, +0x69, 0x5f, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x63, +0x6f, 0x6e, 0x66, 0x65, 0x74, 0x74, 0x69, 0xd83c, 0xdf89, 0x3a, 0x74, 0x61, +0x64, 0x61, 0x3a, 0x74, 0x61, 0x64, 0x61, 0xd83c, 0xdf8e, 0x3a, 0x64, 0x6f, +0x6c, 0x6c, 0x73, 0x3a, 0x64, 0x6f, 0x6c, 0x6c, 0x73, 0xd83c, 0xdfee, 0x3a, +0x69, 0x7a, 0x61, 0x6b, 0x61, 0x79, 0x61, 0x5f, 0x6c, 0x61, 0x6e, 0x74, +0x65, 0x72, 0x6e, 0x3a, 0x69, 0x7a, 0x61, 0x6b, 0x61, 0x79, 0x61, 0x6c, +0x61, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0xd83c, 0xdf90, 0x3a, 0x77, 0x69, 0x6e, +0x64, 0x5f, 0x63, 0x68, 0x69, 0x6d, 0x65, 0x3a, 0x63, 0x68, 0x69, 0x6d, +0x65, 0x77, 0x69, 0x6e, 0x64, 0x2709, 0xfe0f, 0x3a, 0x65, 0x6e, 0x76, 0x65, +0x6c, 0x6f, 0x70, 0x65, 0x3a, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, +0x65, 0xd83d, 0xdce9, 0x3a, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, +0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x3a, +0x61, 0x72, 0x72, 0x6f, 0x77, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, +0x65, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdce8, 0x3a, 0x69, 0x6e, 0x63, 0x6f, +0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, +0x65, 0x3a, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x69, 0x6e, +0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0xd83d, 0xdce7, 0x3a, 0x65, 0x6d, 0x61, +0x69, 0x6c, 0x3a, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0xd83d, 0xdce7, 0x3a, 0x65, +0x2d, 0x6d, 0x61, 0x69, 0x6c, 0x3a, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0xd83d, +0xdc8c, 0x3a, 0x6c, 0x6f, 0x76, 0x65, 0x5f, 0x6c, 0x65, 0x74, 0x74, 0x65, +0x72, 0x3a, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x6c, 0x6f, 0x76, 0x65, +0xd83d, 0xdce5, 0x3a, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x74, 0x72, 0x61, +0x79, 0x3a, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x74, 0x72, 0x61, 0x79, 0xd83d, +0xdce4, 0x3a, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x78, 0x5f, 0x74, 0x72, 0x61, +0x79, 0x3a, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x78, 0x74, 0x72, 0x61, 0x79, +0xd83d, 0xdce6, 0x3a, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x3a, 0x70, +0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0xd83c, 0xdff7, 0x3a, 0x6c, 0x61, 0x62, +0x65, 0x6c, 0x3a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0xd83d, 0xdcea, 0x3a, 0x6d, +0x61, 0x69, 0x6c, 0x62, 0x6f, 0x78, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, +0x64, 0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x6d, 0x61, 0x69, 0x6c, +0x62, 0x6f, 0x78, 0xd83d, 0xdceb, 0x3a, 0x6d, 0x61, 0x69, 0x6c, 0x62, 0x6f, +0x78, 0x3a, 0x6d, 0x61, 0x69, 0x6c, 0x62, 0x6f, 0x78, 0xd83d, 0xdcec, 0x3a, +0x6d, 0x61, 0x69, 0x6c, 0x62, 0x6f, 0x78, 0x5f, 0x77, 0x69, 0x74, 0x68, +0x5f, 0x6d, 0x61, 0x69, 0x6c, 0x3a, 0x6d, 0x61, 0x69, 0x6c, 0x6d, 0x61, +0x69, 0x6c, 0x62, 0x6f, 0x78, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdced, 0x3a, +0x6d, 0x61, 0x69, 0x6c, 0x62, 0x6f, 0x78, 0x5f, 0x77, 0x69, 0x74, 0x68, +0x5f, 0x6e, 0x6f, 0x5f, 0x6d, 0x61, 0x69, 0x6c, 0x3a, 0x6d, 0x61, 0x69, +0x6c, 0x6d, 0x61, 0x69, 0x6c, 0x62, 0x6f, 0x78, 0x6e, 0x6f, 0x77, 0x69, +0x74, 0x68, 0xd83d, 0xdcee, 0x3a, 0x70, 0x6f, 0x73, 0x74, 0x62, 0x6f, 0x78, +0x3a, 0x70, 0x6f, 0x73, 0x74, 0x62, 0x6f, 0x78, 0xd83d, 0xdcef, 0x3a, 0x70, +0x6f, 0x73, 0x74, 0x61, 0x6c, 0x5f, 0x68, 0x6f, 0x72, 0x6e, 0x3a, 0x68, +0x6f, 0x72, 0x6e, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0xd83d, 0xdcdc, 0x3a, +0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x73, 0x63, 0x72, 0x6f, 0x6c, +0x6c, 0xd83d, 0xdcc3, 0x3a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x77, 0x69, 0x74, +0x68, 0x5f, 0x63, 0x75, 0x72, 0x6c, 0x3a, 0x63, 0x75, 0x72, 0x6c, 0x70, +0x61, 0x67, 0x65, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdcc4, 0x3a, 0x70, 0x61, +0x67, 0x65, 0x5f, 0x66, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x70, +0x3a, 0x66, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x70, 0x61, 0x67, 0x65, 0x75, +0x70, 0xd83d, 0xdcd1, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x72, 0x6b, +0x5f, 0x74, 0x61, 0x62, 0x73, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, +0x72, 0x6b, 0x74, 0x61, 0x62, 0x73, 0xd83d, 0xdcca, 0x3a, 0x62, 0x61, 0x72, +0x5f, 0x63, 0x68, 0x61, 0x72, 0x74, 0x3a, 0x62, 0x61, 0x72, 0x63, 0x68, +0x61, 0x72, 0x74, 0xd83d, 0xdcc8, 0x3a, 0x63, 0x68, 0x61, 0x72, 0x74, 0x5f, +0x77, 0x69, 0x74, 0x68, 0x5f, 0x75, 0x70, 0x77, 0x61, 0x72, 0x64, 0x73, +0x5f, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x3a, 0x63, 0x68, 0x61, 0x72, 0x74, +0x74, 0x72, 0x65, 0x6e, 0x64, 0x75, 0x70, 0x77, 0x61, 0x72, 0x64, 0x73, +0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdcc9, 0x3a, 0x63, 0x68, 0x61, 0x72, 0x74, +0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x77, 0x61, +0x72, 0x64, 0x73, 0x5f, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x3a, 0x63, 0x68, +0x61, 0x72, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x77, 0x61, 0x72, 0x64, 0x73, +0x74, 0x72, 0x65, 0x6e, 0x64, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xddd2, 0x3a, +0x73, 0x70, 0x69, 0x72, 0x61, 0x6c, 0x5f, 0x6e, 0x6f, 0x74, 0x65, 0x5f, +0x70, 0x61, 0x64, 0x3a, 0x6e, 0x6f, 0x74, 0x65, 0x70, 0x61, 0x64, 0x73, +0x70, 0x69, 0x72, 0x61, 0x6c, 0xd83d, 0xddd2, 0x3a, 0x6e, 0x6f, 0x74, 0x65, +0x70, 0x61, 0x64, 0x5f, 0x73, 0x70, 0x69, 0x72, 0x61, 0x6c, 0x3a, 0x6e, +0x6f, 0x74, 0x65, 0x70, 0x61, 0x64, 0x73, 0x70, 0x69, 0x72, 0x61, 0x6c, +0xd83d, 0xddd3, 0x3a, 0x73, 0x70, 0x69, 0x72, 0x61, 0x6c, 0x5f, 0x63, 0x61, +0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x5f, 0x70, 0x61, 0x64, 0x3a, 0x63, +0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x70, 0x61, 0x64, 0x73, 0x70, +0x69, 0x72, 0x61, 0x6c, 0xd83d, 0xddd3, 0x3a, 0x63, 0x61, 0x6c, 0x65, 0x6e, +0x64, 0x61, 0x72, 0x5f, 0x73, 0x70, 0x69, 0x72, 0x61, 0x6c, 0x3a, 0x63, +0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x73, 0x70, 0x69, 0x72, 0x61, +0x6c, 0xd83d, 0xdcc6, 0x3a, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, +0x3a, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0xd83d, 0xdcc5, 0x3a, +0x64, 0x61, 0x74, 0x65, 0x3a, 0x64, 0x61, 0x74, 0x65, 0xd83d, 0xdcc7, 0x3a, +0x63, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x63, +0x61, 0x72, 0x64, 0x69, 0x6e, 0x64, 0x65, 0x78, 0xd83d, 0xddc3, 0x3a, 0x63, +0x61, 0x72, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x62, 0x6f, 0x78, +0x3a, 0x62, 0x6f, 0x78, 0x63, 0x61, 0x72, 0x64, 0x66, 0x69, 0x6c, 0x65, +0xd83d, 0xddc3, 0x3a, 0x63, 0x61, 0x72, 0x64, 0x5f, 0x62, 0x6f, 0x78, 0x3a, +0x62, 0x6f, 0x78, 0x63, 0x61, 0x72, 0x64, 0xd83d, 0xddf3, 0x3a, 0x62, 0x61, +0x6c, 0x6c, 0x6f, 0x74, 0x5f, 0x62, 0x6f, 0x78, 0x5f, 0x77, 0x69, 0x74, +0x68, 0x5f, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x3a, 0x62, 0x61, 0x6c, +0x6c, 0x6f, 0x74, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x62, 0x6f, 0x78, +0x77, 0x69, 0x74, 0x68, 0xd83d, 0xddf3, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x6f, +0x74, 0x5f, 0x62, 0x6f, 0x78, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x74, +0x62, 0x6f, 0x78, 0xd83d, 0xddc4, 0x3a, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, +0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x3a, 0x63, 0x61, 0x62, 0x69, 0x6e, +0x65, 0x74, 0x66, 0x69, 0x6c, 0x65, 0xd83d, 0xdccb, 0x3a, 0x63, 0x6c, 0x69, +0x70, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x3a, 0x63, 0x6c, 0x69, 0x70, 0x62, +0x6f, 0x61, 0x72, 0x64, 0xd83d, 0xdcc1, 0x3a, 0x66, 0x69, 0x6c, 0x65, 0x5f, +0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x3a, 0x66, 0x69, 0x6c, 0x65, 0x66, +0x6f, 0x6c, 0x64, 0x65, 0x72, 0xd83d, 0xdcc2, 0x3a, 0x6f, 0x70, 0x65, 0x6e, +0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, +0x3a, 0x66, 0x69, 0x6c, 0x65, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x6f, +0x70, 0x65, 0x6e, 0xd83d, 0xddc2, 0x3a, 0x63, 0x61, 0x72, 0x64, 0x5f, 0x69, +0x6e, 0x64, 0x65, 0x78, 0x5f, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x72, +0x73, 0x3a, 0x63, 0x61, 0x72, 0x64, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, +0x72, 0x73, 0x69, 0x6e, 0x64, 0x65, 0x78, 0xd83d, 0xddc2, 0x3a, 0x64, 0x69, +0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x3a, 0x64, 0x69, 0x76, 0x69, 0x64, +0x65, 0x72, 0x73, 0xd83d, 0xddde, 0x3a, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, +0x5f, 0x75, 0x70, 0x5f, 0x6e, 0x65, 0x77, 0x73, 0x70, 0x61, 0x70, 0x65, +0x72, 0x3a, 0x6e, 0x65, 0x77, 0x73, 0x70, 0x61, 0x70, 0x65, 0x72, 0x72, +0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x75, 0x70, 0xd83d, 0xddde, 0x3a, 0x6e, 0x65, +0x77, 0x73, 0x70, 0x61, 0x70, 0x65, 0x72, 0x32, 0x3a, 0x6e, 0x65, 0x77, +0x73, 0x70, 0x61, 0x70, 0x65, 0x72, 0x32, 0xd83d, 0xdcf0, 0x3a, 0x6e, 0x65, +0x77, 0x73, 0x70, 0x61, 0x70, 0x65, 0x72, 0x3a, 0x6e, 0x65, 0x77, 0x73, +0x70, 0x61, 0x70, 0x65, 0x72, 0xd83d, 0xdcd3, 0x3a, 0x6e, 0x6f, 0x74, 0x65, +0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, +0x6b, 0xd83d, 0xdcd4, 0x3a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, +0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, +0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x63, +0x6f, 0x76, 0x65, 0x72, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, +0x76, 0x65, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x77, 0x69, +0x74, 0x68, 0xd83d, 0xdcd2, 0x3a, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x3a, +0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0xd83d, 0xdcd5, 0x3a, 0x63, 0x6c, 0x6f, +0x73, 0x65, 0x64, 0x5f, 0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x62, 0x6f, 0x6f, +0x6b, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0xd83d, 0xdcd7, 0x3a, 0x67, 0x72, +0x65, 0x65, 0x6e, 0x5f, 0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x62, 0x6f, 0x6f, +0x6b, 0x67, 0x72, 0x65, 0x65, 0x6e, 0xd83d, 0xdcd8, 0x3a, 0x62, 0x6c, 0x75, +0x65, 0x5f, 0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x62, +0x6f, 0x6f, 0x6b, 0xd83d, 0xdcd9, 0x3a, 0x6f, 0x72, 0x61, 0x6e, 0x67, 0x65, +0x5f, 0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x6f, 0x72, +0x61, 0x6e, 0x67, 0x65, 0xd83d, 0xdcda, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x73, +0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0xd83d, 0xdcd6, 0x3a, 0x62, 0x6f, 0x6f, +0x6b, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0xd83d, 0xdd16, 0x3a, 0x62, 0x6f, 0x6f, +0x6b, 0x6d, 0x61, 0x72, 0x6b, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, +0x72, 0x6b, 0xd83d, 0xdd17, 0x3a, 0x6c, 0x69, 0x6e, 0x6b, 0x3a, 0x6c, 0x69, +0x6e, 0x6b, 0xd83d, 0xdcce, 0x3a, 0x70, 0x61, 0x70, 0x65, 0x72, 0x63, 0x6c, +0x69, 0x70, 0x3a, 0x70, 0x61, 0x70, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x70, +0xd83d, 0xdd87, 0x3a, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x5f, 0x70, 0x61, +0x70, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x70, 0x73, 0x3a, 0x6c, 0x69, 0x6e, +0x6b, 0x65, 0x64, 0x70, 0x61, 0x70, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x70, +0x73, 0xd83d, 0xdd87, 0x3a, 0x70, 0x61, 0x70, 0x65, 0x72, 0x63, 0x6c, 0x69, +0x70, 0x73, 0x3a, 0x70, 0x61, 0x70, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x70, +0x73, 0xd83d, 0xdcd0, 0x3a, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x75, 0x6c, +0x61, 0x72, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x72, 0x3a, 0x72, 0x75, 0x6c, +0x65, 0x72, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x72, +0xd83d, 0xdccf, 0x3a, 0x73, 0x74, 0x72, 0x61, 0x69, 0x67, 0x68, 0x74, 0x5f, +0x72, 0x75, 0x6c, 0x65, 0x72, 0x3a, 0x72, 0x75, 0x6c, 0x65, 0x72, 0x73, +0x74, 0x72, 0x61, 0x69, 0x67, 0x68, 0x74, 0xd83d, 0xdccc, 0x3a, 0x70, 0x75, +0x73, 0x68, 0x70, 0x69, 0x6e, 0x3a, 0x70, 0x75, 0x73, 0x68, 0x70, 0x69, +0x6e, 0xd83d, 0xdccd, 0x3a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x70, 0x75, +0x73, 0x68, 0x70, 0x69, 0x6e, 0x3a, 0x70, 0x75, 0x73, 0x68, 0x70, 0x69, +0x6e, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2702, 0xfe0f, 0x3a, 0x73, 0x63, 0x69, +0x73, 0x73, 0x6f, 0x72, 0x73, 0x3a, 0x73, 0x63, 0x69, 0x73, 0x73, 0x6f, +0x72, 0x73, 0xd83d, 0xdd8a, 0x3a, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x6c, +0x65, 0x66, 0x74, 0x5f, 0x62, 0x61, 0x6c, 0x6c, 0x70, 0x6f, 0x69, 0x6e, +0x74, 0x5f, 0x70, 0x65, 0x6e, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x70, 0x6f, +0x69, 0x6e, 0x74, 0x6c, 0x65, 0x66, 0x74, 0x6c, 0x6f, 0x77, 0x65, 0x72, +0x70, 0x65, 0x6e, 0xd83d, 0xdd8a, 0x3a, 0x70, 0x65, 0x6e, 0x5f, 0x62, 0x61, +0x6c, 0x6c, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x3a, 0x62, 0x61, 0x6c, 0x6c, +0x70, 0x6f, 0x69, 0x6e, 0x74, 0x70, 0x65, 0x6e, 0xd83d, 0xdd8b, 0x3a, 0x6c, +0x6f, 0x77, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x66, 0x6f, +0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x65, 0x6e, 0x3a, 0x66, +0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x6c, 0x65, 0x66, 0x74, 0x6c, +0x6f, 0x77, 0x65, 0x72, 0x70, 0x65, 0x6e, 0xd83d, 0xdd8b, 0x3a, 0x70, 0x65, +0x6e, 0x5f, 0x66, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x3a, 0x66, +0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x70, 0x65, 0x6e, 0x2712, 0xfe0f, +0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x6e, 0x69, 0x62, 0x3a, 0x62, +0x6c, 0x61, 0x63, 0x6b, 0x6e, 0x69, 0x62, 0xd83d, 0xdd8c, 0x3a, 0x6c, 0x6f, +0x77, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x70, 0x61, 0x69, +0x6e, 0x74, 0x62, 0x72, 0x75, 0x73, 0x68, 0x3a, 0x6c, 0x65, 0x66, 0x74, +0x6c, 0x6f, 0x77, 0x65, 0x72, 0x70, 0x61, 0x69, 0x6e, 0x74, 0x62, 0x72, +0x75, 0x73, 0x68, 0xd83d, 0xdd8c, 0x3a, 0x70, 0x61, 0x69, 0x6e, 0x74, 0x62, +0x72, 0x75, 0x73, 0x68, 0x3a, 0x70, 0x61, 0x69, 0x6e, 0x74, 0x62, 0x72, +0x75, 0x73, 0x68, 0xd83d, 0xdd8d, 0x3a, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, +0x6c, 0x65, 0x66, 0x74, 0x5f, 0x63, 0x72, 0x61, 0x79, 0x6f, 0x6e, 0x3a, +0x63, 0x72, 0x61, 0x79, 0x6f, 0x6e, 0x6c, 0x65, 0x66, 0x74, 0x6c, 0x6f, +0x77, 0x65, 0x72, 0xd83d, 0xdd8d, 0x3a, 0x63, 0x72, 0x61, 0x79, 0x6f, 0x6e, +0x3a, 0x63, 0x72, 0x61, 0x79, 0x6f, 0x6e, 0xd83d, 0xdcdd, 0x3a, 0x6d, 0x65, +0x6d, 0x6f, 0x3a, 0x6d, 0x65, 0x6d, 0x6f, 0xd83d, 0xdcdd, 0x3a, 0x70, 0x65, +0x6e, 0x63, 0x69, 0x6c, 0x3a, 0x70, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x270f, +0xfe0f, 0x3a, 0x70, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x32, 0x3a, 0x70, 0x65, +0x6e, 0x63, 0x69, 0x6c, 0x32, 0xd83d, 0xdd0d, 0x3a, 0x6d, 0x61, 0x67, 0x3a, +0x6d, 0x61, 0x67, 0xd83d, 0xdd0e, 0x3a, 0x6d, 0x61, 0x67, 0x5f, 0x72, 0x69, +0x67, 0x68, 0x74, 0x3a, 0x6d, 0x61, 0x67, 0x72, 0x69, 0x67, 0x68, 0x74, +0xd83d, 0xdd0f, 0x3a, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x77, 0x69, 0x74, 0x68, +0x5f, 0x69, 0x6e, 0x6b, 0x5f, 0x70, 0x65, 0x6e, 0x3a, 0x69, 0x6e, 0x6b, +0x6c, 0x6f, 0x63, 0x6b, 0x70, 0x65, 0x6e, 0x77, 0x69, 0x74, 0x68, 0xd83d, +0xdd10, 0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x6c, 0x6f, 0x63, +0x6b, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x3a, 0x63, +0x6c, 0x6f, 0x73, 0x65, 0x64, 0x6b, 0x65, 0x79, 0x6c, 0x6f, 0x63, 0x6b, +0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdd12, 0x3a, 0x6c, 0x6f, 0x63, 0x6b, 0x3a, +0x6c, 0x6f, 0x63, 0x6b, 0xd83d, 0xdd13, 0x3a, 0x75, 0x6e, 0x6c, 0x6f, 0x63, +0x6b, 0x3a, 0x75, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x2764, 0xfe0f, 0x3a, 0x68, +0x65, 0x61, 0x72, 0x74, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0xd83d, 0xdc9b, +0x3a, 0x79, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x68, 0x65, 0x61, 0x72, +0x74, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x79, 0x65, 0x6c, 0x6c, 0x6f, +0x77, 0xd83d, 0xdc9a, 0x3a, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x5f, 0x68, 0x65, +0x61, 0x72, 0x74, 0x3a, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x68, 0x65, 0x61, +0x72, 0x74, 0xd83d, 0xdc99, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x5f, 0x68, 0x65, +0x61, 0x72, 0x74, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x68, 0x65, 0x61, 0x72, +0x74, 0xd83d, 0xdc9c, 0x3a, 0x70, 0x75, 0x72, 0x70, 0x6c, 0x65, 0x5f, 0x68, +0x65, 0x61, 0x72, 0x74, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x70, 0x75, +0x72, 0x70, 0x6c, 0x65, 0xd83d, 0xdda4, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, +0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, +0x68, 0x65, 0x61, 0x72, 0x74, 0xd83d, 0xdc94, 0x3a, 0x62, 0x72, 0x6f, 0x6b, +0x65, 0x6e, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3a, 0x62, 0x72, 0x6f, +0x6b, 0x65, 0x6e, 0x68, 0x65, 0x61, 0x72, 0x74, 0x2763, 0xfe0f, 0x3a, 0x68, +0x65, 0x61, 0x76, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x5f, 0x65, +0x78, 0x63, 0x6c, 0x61, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, +0x61, 0x72, 0x6b, 0x5f, 0x6f, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x6e, 0x74, +0x3a, 0x65, 0x78, 0x63, 0x6c, 0x61, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, +0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x65, 0x61, 0x76, 0x79, 0x6d, 0x61, +0x72, 0x6b, 0x6f, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x2763, 0xfe0f, +0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x5f, 0x65, 0x78, 0x63, 0x6c, 0x61, +0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x65, 0x78, 0x63, 0x6c, 0x61, +0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x68, 0x65, 0x61, 0x72, 0x74, 0xd83d, +0xdc95, 0x3a, 0x74, 0x77, 0x6f, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x73, +0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x73, 0x74, 0x77, 0x6f, 0xd83d, 0xdc9e, +0x3a, 0x72, 0x65, 0x76, 0x6f, 0x6c, 0x76, 0x69, 0x6e, 0x67, 0x5f, 0x68, +0x65, 0x61, 0x72, 0x74, 0x73, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x73, +0x72, 0x65, 0x76, 0x6f, 0x6c, 0x76, 0x69, 0x6e, 0x67, 0xd83d, 0xdc93, 0x3a, +0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x3a, 0x68, 0x65, +0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0xd83d, 0xdc97, 0x3a, 0x68, 0x65, +0x61, 0x72, 0x74, 0x70, 0x75, 0x6c, 0x73, 0x65, 0x3a, 0x68, 0x65, 0x61, +0x72, 0x74, 0x70, 0x75, 0x6c, 0x73, 0x65, 0xd83d, 0xdc96, 0x3a, 0x73, 0x70, +0x61, 0x72, 0x6b, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x61, 0x72, +0x74, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x73, 0x70, 0x61, 0x72, 0x6b, +0x6c, 0x69, 0x6e, 0x67, 0xd83d, 0xdc98, 0x3a, 0x63, 0x75, 0x70, 0x69, 0x64, +0x3a, 0x63, 0x75, 0x70, 0x69, 0x64, 0xd83d, 0xdc9d, 0x3a, 0x67, 0x69, 0x66, +0x74, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3a, 0x67, 0x69, 0x66, 0x74, +0x68, 0x65, 0x61, 0x72, 0x74, 0xd83d, 0xdc9f, 0x3a, 0x68, 0x65, 0x61, 0x72, +0x74, 0x5f, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, +0x3a, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x68, +0x65, 0x61, 0x72, 0x74, 0x262e, 0xfe0f, 0x3a, 0x70, 0x65, 0x61, 0x63, 0x65, +0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x3a, 0x70, 0x65, 0x61, 0x63, +0x65, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x262e, 0xfe0f, 0x3a, 0x70, 0x65, +0x61, 0x63, 0x65, 0x3a, 0x70, 0x65, 0x61, 0x63, 0x65, 0x271d, 0xfe0f, 0x3a, +0x6c, 0x61, 0x74, 0x69, 0x6e, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x3a, +0x63, 0x72, 0x6f, 0x73, 0x73, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x271d, 0xfe0f, +0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, +0x262a, 0xfe0f, 0x3a, 0x73, 0x74, 0x61, 0x72, 0x5f, 0x61, 0x6e, 0x64, 0x5f, +0x63, 0x72, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x3a, 0x61, 0x6e, 0x64, +0x63, 0x72, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x73, 0x74, 0x61, 0x72, +0xd83d, 0xdd49, 0x3a, 0x6f, 0x6d, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, +0x3a, 0x6f, 0x6d, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x2638, 0xfe0f, 0x3a, +0x77, 0x68, 0x65, 0x65, 0x6c, 0x5f, 0x6f, 0x66, 0x5f, 0x64, 0x68, 0x61, +0x72, 0x6d, 0x61, 0x3a, 0x64, 0x68, 0x61, 0x72, 0x6d, 0x61, 0x6f, 0x66, +0x77, 0x68, 0x65, 0x65, 0x6c, 0x2721, 0xfe0f, 0x3a, 0x73, 0x74, 0x61, 0x72, +0x5f, 0x6f, 0x66, 0x5f, 0x64, 0x61, 0x76, 0x69, 0x64, 0x3a, 0x64, 0x61, +0x76, 0x69, 0x64, 0x6f, 0x66, 0x73, 0x74, 0x61, 0x72, 0xd83d, 0xdd2f, 0x3a, +0x73, 0x69, 0x78, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x5f, +0x73, 0x74, 0x61, 0x72, 0x3a, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, +0x73, 0x69, 0x78, 0x73, 0x74, 0x61, 0x72, 0xd83d, 0xdd4e, 0x3a, 0x6d, 0x65, +0x6e, 0x6f, 0x72, 0x61, 0x68, 0x3a, 0x6d, 0x65, 0x6e, 0x6f, 0x72, 0x61, +0x68, 0x262f, 0xfe0f, 0x3a, 0x79, 0x69, 0x6e, 0x5f, 0x79, 0x61, 0x6e, 0x67, +0x3a, 0x79, 0x61, 0x6e, 0x67, 0x79, 0x69, 0x6e, 0x2626, 0xfe0f, 0x3a, 0x6f, +0x72, 0x74, 0x68, 0x6f, 0x64, 0x6f, 0x78, 0x5f, 0x63, 0x72, 0x6f, 0x73, +0x73, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x6f, 0x72, 0x74, 0x68, 0x6f, +0x64, 0x6f, 0x78, 0xd83d, 0xded0, 0x3a, 0x77, 0x6f, 0x72, 0x73, 0x68, 0x69, +0x70, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x3a, 0x73, 0x79, 0x6d, +0x62, 0x6f, 0x6c, 0x77, 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, 0xd83d, 0xded0, +0x3a, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x77, 0x6f, +0x72, 0x73, 0x68, 0x69, 0x70, 0x3a, 0x6f, 0x66, 0x70, 0x6c, 0x61, 0x63, +0x65, 0x77, 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, 0x26ce, 0x3a, 0x6f, 0x70, +0x68, 0x69, 0x75, 0x63, 0x68, 0x75, 0x73, 0x3a, 0x6f, 0x70, 0x68, 0x69, +0x75, 0x63, 0x68, 0x75, 0x73, 0x2648, 0xfe0f, 0x3a, 0x61, 0x72, 0x69, 0x65, +0x73, 0x3a, 0x61, 0x72, 0x69, 0x65, 0x73, 0x2649, 0xfe0f, 0x3a, 0x74, 0x61, +0x75, 0x72, 0x75, 0x73, 0x3a, 0x74, 0x61, 0x75, 0x72, 0x75, 0x73, 0x264a, +0xfe0f, 0x3a, 0x67, 0x65, 0x6d, 0x69, 0x6e, 0x69, 0x3a, 0x67, 0x65, 0x6d, +0x69, 0x6e, 0x69, 0x264b, 0xfe0f, 0x3a, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x72, +0x3a, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x264c, 0xfe0f, 0x3a, 0x6c, 0x65, +0x6f, 0x3a, 0x6c, 0x65, 0x6f, 0x264d, 0xfe0f, 0x3a, 0x76, 0x69, 0x72, 0x67, +0x6f, 0x3a, 0x76, 0x69, 0x72, 0x67, 0x6f, 0x264e, 0xfe0f, 0x3a, 0x6c, 0x69, +0x62, 0x72, 0x61, 0x3a, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x264f, 0xfe0f, 0x3a, +0x73, 0x63, 0x6f, 0x72, 0x70, 0x69, 0x75, 0x73, 0x3a, 0x73, 0x63, 0x6f, +0x72, 0x70, 0x69, 0x75, 0x73, 0x2650, 0xfe0f, 0x3a, 0x73, 0x61, 0x67, 0x69, +0x74, 0x74, 0x61, 0x72, 0x69, 0x75, 0x73, 0x3a, 0x73, 0x61, 0x67, 0x69, +0x74, 0x74, 0x61, 0x72, 0x69, 0x75, 0x73, 0x2651, 0xfe0f, 0x3a, 0x63, 0x61, +0x70, 0x72, 0x69, 0x63, 0x6f, 0x72, 0x6e, 0x3a, 0x63, 0x61, 0x70, 0x72, +0x69, 0x63, 0x6f, 0x72, 0x6e, 0x2652, 0xfe0f, 0x3a, 0x61, 0x71, 0x75, 0x61, +0x72, 0x69, 0x75, 0x73, 0x3a, 0x61, 0x71, 0x75, 0x61, 0x72, 0x69, 0x75, +0x73, 0x2653, 0xfe0f, 0x3a, 0x70, 0x69, 0x73, 0x63, 0x65, 0x73, 0x3a, 0x70, +0x69, 0x73, 0x63, 0x65, 0x73, 0xd83c, 0xdd94, 0x3a, 0x69, 0x64, 0x3a, 0x69, +0x64, 0x269b, 0xfe0f, 0x3a, 0x61, 0x74, 0x6f, 0x6d, 0x5f, 0x73, 0x79, 0x6d, +0x62, 0x6f, 0x6c, 0x3a, 0x61, 0x74, 0x6f, 0x6d, 0x73, 0x79, 0x6d, 0x62, +0x6f, 0x6c, 0x269b, 0xfe0f, 0x3a, 0x61, 0x74, 0x6f, 0x6d, 0x3a, 0x61, 0x74, +0x6f, 0x6d, 0xd83c, 0xde51, 0x3a, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, +0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2622, 0xfe0f, 0x3a, 0x72, 0x61, 0x64, +0x69, 0x6f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x69, 0x67, +0x6e, 0x3a, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x61, 0x63, 0x74, 0x69, 0x76, +0x65, 0x73, 0x69, 0x67, 0x6e, 0x2622, 0xfe0f, 0x3a, 0x72, 0x61, 0x64, 0x69, +0x6f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x3a, 0x72, 0x61, 0x64, 0x69, +0x6f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2623, 0xfe0f, 0x3a, 0x62, 0x69, +0x6f, 0x68, 0x61, 0x7a, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x6e, +0x3a, 0x62, 0x69, 0x6f, 0x68, 0x61, 0x7a, 0x61, 0x72, 0x64, 0x73, 0x69, +0x67, 0x6e, 0x2623, 0xfe0f, 0x3a, 0x62, 0x69, 0x6f, 0x68, 0x61, 0x7a, 0x61, +0x72, 0x64, 0x3a, 0x62, 0x69, 0x6f, 0x68, 0x61, 0x7a, 0x61, 0x72, 0x64, +0xd83d, 0xdcf4, 0x3a, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x68, +0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x3a, 0x6d, 0x6f, 0x62, 0x69, +0x6c, 0x65, 0x6f, 0x66, 0x66, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0xd83d, 0xdcf3, +0x3a, 0x76, 0x69, 0x62, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, +0x6f, 0x64, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x65, 0x76, 0x69, 0x62, 0x72, +0x61, 0x74, 0x69, 0x6f, 0x6e, 0xd83c, 0xde36, 0x3a, 0x75, 0x36, 0x37, 0x30, +0x39, 0x3a, 0x75, 0x36, 0x37, 0x30, 0x39, 0xd83c, 0xde1a, 0xfe0f, 0x3a, 0x75, +0x37, 0x31, 0x32, 0x31, 0x3a, 0x75, 0x37, 0x31, 0x32, 0x31, 0xd83c, 0xde38, +0x3a, 0x75, 0x37, 0x35, 0x33, 0x33, 0x3a, 0x75, 0x37, 0x35, 0x33, 0x33, +0xd83c, 0xde3a, 0x3a, 0x75, 0x35, 0x35, 0x62, 0x36, 0x3a, 0x75, 0x35, 0x35, +0x62, 0x36, 0xd83c, 0xde37, 0x3a, 0x75, 0x36, 0x37, 0x30, 0x38, 0x3a, 0x75, +0x36, 0x37, 0x30, 0x38, 0x2734, 0xfe0f, 0x3a, 0x65, 0x69, 0x67, 0x68, 0x74, +0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x61, +0x63, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x3a, 0x62, 0x6c, 0x61, 0x63, +0x6b, 0x65, 0x69, 0x67, 0x68, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, +0x64, 0x73, 0x74, 0x61, 0x72, 0xd83c, 0xdd9a, 0x3a, 0x76, 0x73, 0x3a, 0x76, +0x73, 0xd83d, 0xdcae, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x66, 0x6c, +0x6f, 0x77, 0x65, 0x72, 0x3a, 0x66, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x77, +0x68, 0x69, 0x74, 0x65, 0xd83c, 0xde50, 0x3a, 0x69, 0x64, 0x65, 0x6f, 0x67, +0x72, 0x61, 0x70, 0x68, 0x5f, 0x61, 0x64, 0x76, 0x61, 0x6e, 0x74, 0x61, +0x67, 0x65, 0x3a, 0x61, 0x64, 0x76, 0x61, 0x6e, 0x74, 0x61, 0x67, 0x65, +0x69, 0x64, 0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x3299, 0xfe0f, 0x3a, +0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x3a, 0x73, 0x65, 0x63, 0x72, 0x65, +0x74, 0x3297, 0xfe0f, 0x3a, 0x63, 0x6f, 0x6e, 0x67, 0x72, 0x61, 0x74, 0x75, +0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x63, 0x6f, 0x6e, 0x67, +0x72, 0x61, 0x74, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xd83c, +0xde34, 0x3a, 0x75, 0x35, 0x34, 0x30, 0x38, 0x3a, 0x75, 0x35, 0x34, 0x30, +0x38, 0xd83c, 0xde35, 0x3a, 0x75, 0x36, 0x65, 0x38, 0x30, 0x3a, 0x75, 0x36, +0x65, 0x38, 0x30, 0xd83c, 0xde39, 0x3a, 0x75, 0x35, 0x32, 0x37, 0x32, 0x3a, +0x75, 0x35, 0x32, 0x37, 0x32, 0xd83c, 0xde32, 0x3a, 0x75, 0x37, 0x39, 0x38, +0x31, 0x3a, 0x75, 0x37, 0x39, 0x38, 0x31, 0xd83c, 0xdd70, 0xfe0f, 0x3a, 0x61, +0x3a, 0x61, 0xd83c, 0xdd71, 0xfe0f, 0x3a, 0x62, 0x3a, 0x62, 0xd83c, 0xdd8e, 0x3a, +0x61, 0x62, 0x3a, 0x61, 0x62, 0xd83c, 0xdd91, 0x3a, 0x63, 0x6c, 0x3a, 0x63, +0x6c, 0xd83c, 0xdd7e, 0xfe0f, 0x3a, 0x6f, 0x32, 0x3a, 0x6f, 0x32, 0xd83c, 0xdd98, +0x3a, 0x73, 0x6f, 0x73, 0x3a, 0x73, 0x6f, 0x73, 0x274c, 0x3a, 0x78, 0x3a, +0x78, 0x2b55, 0xfe0f, 0x3a, 0x6f, 0x3a, 0x6f, 0xd83d, 0xded1, 0x3a, 0x73, 0x74, +0x6f, 0x70, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x3a, 0x73, 0x69, 0x67, 0x6e, +0x73, 0x74, 0x6f, 0x70, 0xd83d, 0xded1, 0x3a, 0x6f, 0x63, 0x74, 0x61, 0x67, +0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x3a, 0x6f, 0x63, +0x74, 0x61, 0x67, 0x6f, 0x6e, 0x61, 0x6c, 0x73, 0x69, 0x67, 0x6e, 0x26d4, +0xfe0f, 0x3a, 0x6e, 0x6f, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x3a, 0x65, +0x6e, 0x74, 0x72, 0x79, 0x6e, 0x6f, 0xd83d, 0xdcdb, 0x3a, 0x6e, 0x61, 0x6d, +0x65, 0x5f, 0x62, 0x61, 0x64, 0x67, 0x65, 0x3a, 0x62, 0x61, 0x64, 0x67, +0x65, 0x6e, 0x61, 0x6d, 0x65, 0xd83d, 0xdeab, 0x3a, 0x6e, 0x6f, 0x5f, 0x65, +0x6e, 0x74, 0x72, 0x79, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x3a, 0x65, 0x6e, +0x74, 0x72, 0x79, 0x6e, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0xd83d, 0xdcaf, 0x3a, +0x31, 0x30, 0x30, 0x3a, 0x31, 0x30, 0x30, 0xd83d, 0xdca2, 0x3a, 0x61, 0x6e, +0x67, 0x65, 0x72, 0x3a, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x2668, 0xfe0f, 0x3a, +0x68, 0x6f, 0x74, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x68, +0x6f, 0x74, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x73, 0xd83d, 0xdeb7, 0x3a, +0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x64, 0x65, 0x73, 0x74, 0x72, 0x69, 0x61, +0x6e, 0x73, 0x3a, 0x6e, 0x6f, 0x70, 0x65, 0x64, 0x65, 0x73, 0x74, 0x72, +0x69, 0x61, 0x6e, 0x73, 0xd83d, 0xdeaf, 0x3a, 0x64, 0x6f, 0x5f, 0x6e, 0x6f, +0x74, 0x5f, 0x6c, 0x69, 0x74, 0x74, 0x65, 0x72, 0x3a, 0x64, 0x6f, 0x6c, +0x69, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x6f, 0x74, 0xd83d, 0xdeb3, 0x3a, 0x6e, +0x6f, 0x5f, 0x62, 0x69, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x3a, 0x62, +0x69, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x6e, 0x6f, 0xd83d, 0xdeb1, 0x3a, +0x6e, 0x6f, 0x6e, 0x2d, 0x70, 0x6f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, +0x77, 0x61, 0x74, 0x65, 0x72, 0x3a, 0x6e, 0x6f, 0x6e, 0x70, 0x6f, 0x74, +0x61, 0x62, 0x6c, 0x65, 0x77, 0x61, 0x74, 0x65, 0x72, 0xd83d, 0xdd1e, 0x3a, +0x75, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x67, 0x65, 0x3a, 0x75, 0x6e, 0x64, +0x65, 0x72, 0x61, 0x67, 0x65, 0xd83d, 0xdcf5, 0x3a, 0x6e, 0x6f, 0x5f, 0x6d, +0x6f, 0x62, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x73, +0x3a, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x70, 0x68, 0x6f, +0x6e, 0x65, 0x73, 0xd83d, 0xdead, 0x3a, 0x6e, 0x6f, 0x5f, 0x73, 0x6d, 0x6f, +0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x6e, 0x6f, 0x73, 0x6d, 0x6f, 0x6b, 0x69, +0x6e, 0x67, 0x2757, 0xfe0f, 0x3a, 0x65, 0x78, 0x63, 0x6c, 0x61, 0x6d, 0x61, +0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x65, 0x78, 0x63, 0x6c, 0x61, 0x6d, 0x61, +0x74, 0x69, 0x6f, 0x6e, 0x2755, 0x3a, 0x67, 0x72, 0x65, 0x79, 0x5f, 0x65, +0x78, 0x63, 0x6c, 0x61, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x65, +0x78, 0x63, 0x6c, 0x61, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x67, 0x72, +0x65, 0x79, 0x2753, 0x3a, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, +0x3a, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x2754, 0x3a, 0x67, +0x72, 0x65, 0x79, 0x5f, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, +0x3a, 0x67, 0x72, 0x65, 0x79, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, +0x6e, 0x203c, 0xfe0f, 0x3a, 0x62, 0x61, 0x6e, 0x67, 0x62, 0x61, 0x6e, 0x67, +0x3a, 0x62, 0x61, 0x6e, 0x67, 0x62, 0x61, 0x6e, 0x67, 0x2049, 0xfe0f, 0x3a, +0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x6f, 0x62, 0x61, 0x6e, 0x67, 0x3a, +0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x6f, 0x62, 0x61, 0x6e, 0x67, 0xd83d, +0xdd05, 0x3a, 0x6c, 0x6f, 0x77, 0x5f, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, +0x6e, 0x65, 0x73, 0x73, 0x3a, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6e, +0x65, 0x73, 0x73, 0x6c, 0x6f, 0x77, 0xd83d, 0xdd06, 0x3a, 0x68, 0x69, 0x67, +0x68, 0x5f, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x65, 0x73, 0x73, +0x3a, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x68, +0x69, 0x67, 0x68, 0x303d, 0xfe0f, 0x3a, 0x70, 0x61, 0x72, 0x74, 0x5f, 0x61, +0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, +0x61, 0x72, 0x6b, 0x3a, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, +0x69, 0x6f, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x70, 0x61, 0x72, 0x74, 0x26a0, +0xfe0f, 0x3a, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x77, 0x61, +0x72, 0x6e, 0x69, 0x6e, 0x67, 0xd83d, 0xdeb8, 0x3a, 0x63, 0x68, 0x69, 0x6c, +0x64, 0x72, 0x65, 0x6e, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x69, 0x6e, +0x67, 0x3a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x63, 0x72, +0x6f, 0x73, 0x73, 0x69, 0x6e, 0x67, 0xd83d, 0xdd31, 0x3a, 0x74, 0x72, 0x69, +0x64, 0x65, 0x6e, 0x74, 0x3a, 0x74, 0x72, 0x69, 0x64, 0x65, 0x6e, 0x74, +0x269c, 0xfe0f, 0x3a, 0x66, 0x6c, 0x65, 0x75, 0x72, 0x2d, 0x64, 0x65, 0x2d, +0x6c, 0x69, 0x73, 0x3a, 0x64, 0x65, 0x66, 0x6c, 0x65, 0x75, 0x72, 0x6c, +0x69, 0x73, 0xd83d, 0xdd30, 0x3a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x6e, 0x65, +0x72, 0x3a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x267b, 0xfe0f, +0x3a, 0x72, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x3a, 0x72, 0x65, 0x63, +0x79, 0x63, 0x6c, 0x65, 0x2705, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, +0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x3a, 0x63, +0x68, 0x65, 0x63, 0x6b, 0x6d, 0x61, 0x72, 0x6b, 0x77, 0x68, 0x69, 0x74, +0x65, 0xd83c, 0xde2f, 0xfe0f, 0x3a, 0x75, 0x36, 0x33, 0x30, 0x37, 0x3a, 0x75, +0x36, 0x33, 0x30, 0x37, 0xd83d, 0xdcb9, 0x3a, 0x63, 0x68, 0x61, 0x72, 0x74, +0x3a, 0x63, 0x68, 0x61, 0x72, 0x74, 0x2747, 0xfe0f, 0x3a, 0x73, 0x70, 0x61, +0x72, 0x6b, 0x6c, 0x65, 0x3a, 0x73, 0x70, 0x61, 0x72, 0x6b, 0x6c, 0x65, +0x2733, 0xfe0f, 0x3a, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x73, 0x70, 0x6f, +0x6b, 0x65, 0x64, 0x5f, 0x61, 0x73, 0x74, 0x65, 0x72, 0x69, 0x73, 0x6b, +0x3a, 0x61, 0x73, 0x74, 0x65, 0x72, 0x69, 0x73, 0x6b, 0x65, 0x69, 0x67, +0x68, 0x74, 0x73, 0x70, 0x6f, 0x6b, 0x65, 0x64, 0x274e, 0x3a, 0x6e, 0x65, +0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, +0x65, 0x64, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x5f, 0x6d, 0x61, 0x72, +0x6b, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x6d, 0x61, 0x72, 0x6b, 0x6e, +0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x73, 0x71, 0x75, 0x61, 0x72, +0x65, 0x64, 0xd83c, 0xdf10, 0x3a, 0x67, 0x6c, 0x6f, 0x62, 0x65, 0x5f, 0x77, +0x69, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x72, 0x69, 0x64, 0x69, 0x61, 0x6e, +0x73, 0x3a, 0x67, 0x6c, 0x6f, 0x62, 0x65, 0x6d, 0x65, 0x72, 0x69, 0x64, +0x69, 0x61, 0x6e, 0x73, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdca0, 0x3a, 0x64, +0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, +0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x61, 0x5f, 0x64, 0x6f, 0x74, 0x5f, +0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x3a, 0x61, 0x64, 0x69, 0x61, 0x6d, +0x6f, 0x6e, 0x64, 0x64, 0x6f, 0x74, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, +0x73, 0x68, 0x61, 0x70, 0x65, 0x77, 0x69, 0x74, 0x68, 0x24c2, 0xfe0f, 0x3a, +0x6d, 0x3a, 0x6d, 0xd83c, 0xdf00, 0x3a, 0x63, 0x79, 0x63, 0x6c, 0x6f, 0x6e, +0x65, 0x3a, 0x63, 0x79, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0xd83d, 0xdca4, 0x3a, +0x7a, 0x7a, 0x7a, 0x3a, 0x7a, 0x7a, 0x7a, 0xd83c, 0xdfe7, 0x3a, 0x61, 0x74, +0x6d, 0x3a, 0x61, 0x74, 0x6d, 0xd83d, 0xdebe, 0x3a, 0x77, 0x63, 0x3a, 0x77, +0x63, 0x267f, 0xfe0f, 0x3a, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x63, 0x68, 0x61, +0x69, 0x72, 0x3a, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x63, 0x68, 0x61, 0x69, +0x72, 0xd83c, 0xdd7f, 0xfe0f, 0x3a, 0x70, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, +0x3a, 0x70, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0xd83c, 0xde33, 0x3a, 0x75, +0x37, 0x61, 0x37, 0x61, 0x3a, 0x75, 0x37, 0x61, 0x37, 0x61, 0xd83c, 0xde02, +0x3a, 0x73, 0x61, 0x3a, 0x73, 0x61, 0xd83d, 0xdec2, 0x3a, 0x70, 0x61, 0x73, +0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, +0x6c, 0x3a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x61, 0x73, +0x73, 0x70, 0x6f, 0x72, 0x74, 0xd83d, 0xdec3, 0x3a, 0x63, 0x75, 0x73, 0x74, +0x6f, 0x6d, 0x73, 0x3a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x73, 0xd83d, +0xdec4, 0x3a, 0x62, 0x61, 0x67, 0x67, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c, +0x61, 0x69, 0x6d, 0x3a, 0x62, 0x61, 0x67, 0x67, 0x61, 0x67, 0x65, 0x63, +0x6c, 0x61, 0x69, 0x6d, 0xd83d, 0xdec5, 0x3a, 0x6c, 0x65, 0x66, 0x74, 0x5f, +0x6c, 0x75, 0x67, 0x67, 0x61, 0x67, 0x65, 0x3a, 0x6c, 0x65, 0x66, 0x74, +0x6c, 0x75, 0x67, 0x67, 0x61, 0x67, 0x65, 0xd83d, 0xdeb9, 0x3a, 0x6d, 0x65, +0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x6e, 0x73, 0xd83d, 0xdeba, 0x3a, 0x77, 0x6f, +0x6d, 0x65, 0x6e, 0x73, 0x3a, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x73, 0xd83d, +0xdebc, 0x3a, 0x62, 0x61, 0x62, 0x79, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, +0x6c, 0x3a, 0x62, 0x61, 0x62, 0x79, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, +0xd83d, 0xdebb, 0x3a, 0x72, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x6f, 0x6d, 0x3a, +0x72, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x6f, 0x6d, 0xd83d, 0xdeae, 0x3a, 0x70, +0x75, 0x74, 0x5f, 0x6c, 0x69, 0x74, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, +0x5f, 0x69, 0x74, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x3a, 0x69, +0x6e, 0x69, 0x74, 0x73, 0x6c, 0x69, 0x74, 0x74, 0x65, 0x72, 0x70, 0x6c, +0x61, 0x63, 0x65, 0x70, 0x75, 0x74, 0xd83c, 0xdfa6, 0x3a, 0x63, 0x69, 0x6e, +0x65, 0x6d, 0x61, 0x3a, 0x63, 0x69, 0x6e, 0x65, 0x6d, 0x61, 0xd83d, 0xdcf6, +0x3a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x72, 0x65, +0x6e, 0x67, 0x74, 0x68, 0x3a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73, +0x74, 0x72, 0x65, 0x6e, 0x67, 0x74, 0x68, 0xd83c, 0xde01, 0x3a, 0x6b, 0x6f, +0x6b, 0x6f, 0x3a, 0x6b, 0x6f, 0x6b, 0x6f, 0xd83d, 0xdd23, 0x3a, 0x73, 0x79, +0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x3a, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, +0x73, 0x2139, 0xfe0f, 0x3a, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, +0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x3a, 0x69, +0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x6f, +0x75, 0x72, 0x63, 0x65, 0xd83d, 0xdd24, 0x3a, 0x61, 0x62, 0x63, 0x3a, 0x61, +0x62, 0x63, 0xd83d, 0xdd21, 0x3a, 0x61, 0x62, 0x63, 0x64, 0x3a, 0x61, 0x62, +0x63, 0x64, 0xd83d, 0xdd20, 0x3a, 0x63, 0x61, 0x70, 0x69, 0x74, 0x61, 0x6c, +0x5f, 0x61, 0x62, 0x63, 0x64, 0x3a, 0x61, 0x62, 0x63, 0x64, 0x63, 0x61, +0x70, 0x69, 0x74, 0x61, 0x6c, 0xd83c, 0xdd96, 0x3a, 0x6e, 0x67, 0x3a, 0x6e, +0x67, 0xd83c, 0xdd97, 0x3a, 0x6f, 0x6b, 0x3a, 0x6f, 0x6b, 0xd83c, 0xdd99, 0x3a, +0x75, 0x70, 0x3a, 0x75, 0x70, 0xd83c, 0xdd92, 0x3a, 0x63, 0x6f, 0x6f, 0x6c, +0x3a, 0x63, 0x6f, 0x6f, 0x6c, 0xd83c, 0xdd95, 0x3a, 0x6e, 0x65, 0x77, 0x3a, +0x6e, 0x65, 0x77, 0xd83c, 0xdd93, 0x3a, 0x66, 0x72, 0x65, 0x65, 0x3a, 0x66, +0x72, 0x65, 0x65, 0x30, 0xfe0f, 0x20e3, 0x3a, 0x7a, 0x65, 0x72, 0x6f, 0x3a, +0x7a, 0x65, 0x72, 0x6f, 0x31, 0xfe0f, 0x20e3, 0x3a, 0x6f, 0x6e, 0x65, 0x3a, +0x6f, 0x6e, 0x65, 0x32, 0xfe0f, 0x20e3, 0x3a, 0x74, 0x77, 0x6f, 0x3a, 0x74, +0x77, 0x6f, 0x33, 0xfe0f, 0x20e3, 0x3a, 0x74, 0x68, 0x72, 0x65, 0x65, 0x3a, +0x74, 0x68, 0x72, 0x65, 0x65, 0x34, 0xfe0f, 0x20e3, 0x3a, 0x66, 0x6f, 0x75, +0x72, 0x3a, 0x66, 0x6f, 0x75, 0x72, 0x35, 0xfe0f, 0x20e3, 0x3a, 0x66, 0x69, +0x76, 0x65, 0x3a, 0x66, 0x69, 0x76, 0x65, 0x36, 0xfe0f, 0x20e3, 0x3a, 0x73, +0x69, 0x78, 0x3a, 0x73, 0x69, 0x78, 0x37, 0xfe0f, 0x20e3, 0x3a, 0x73, 0x65, +0x76, 0x65, 0x6e, 0x3a, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x38, 0xfe0f, 0x20e3, +0x3a, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x65, 0x69, 0x67, 0x68, 0x74, +0x39, 0xfe0f, 0x20e3, 0x3a, 0x6e, 0x69, 0x6e, 0x65, 0x3a, 0x6e, 0x69, 0x6e, +0x65, 0xd83d, 0xdd1f, 0x3a, 0x6b, 0x65, 0x79, 0x63, 0x61, 0x70, 0x5f, 0x74, +0x65, 0x6e, 0x3a, 0x6b, 0x65, 0x79, 0x63, 0x61, 0x70, 0x74, 0x65, 0x6e, +0xd83d, 0xdd22, 0x3a, 0x31, 0x32, 0x33, 0x34, 0x3a, 0x31, 0x32, 0x33, 0x34, +0x23, 0xfe0f, 0x20e3, 0x3a, 0x68, 0x61, 0x73, 0x68, 0x3a, 0x68, 0x61, 0x73, +0x68, 0x2a, 0xfe0f, 0x20e3, 0x3a, 0x6b, 0x65, 0x79, 0x63, 0x61, 0x70, 0x5f, +0x61, 0x73, 0x74, 0x65, 0x72, 0x69, 0x73, 0x6b, 0x3a, 0x61, 0x73, 0x74, +0x65, 0x72, 0x69, 0x73, 0x6b, 0x6b, 0x65, 0x79, 0x63, 0x61, 0x70, 0x2a, +0xfe0f, 0x20e3, 0x3a, 0x61, 0x73, 0x74, 0x65, 0x72, 0x69, 0x73, 0x6b, 0x3a, +0x61, 0x73, 0x74, 0x65, 0x72, 0x69, 0x73, 0x6b, 0x25b6, 0xfe0f, 0x3a, 0x61, +0x72, 0x72, 0x6f, 0x77, 0x5f, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, +0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, +0x64, 0x23f8, 0x3a, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x65, +0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x62, 0x61, 0x72, 0x3a, 0x62, +0x61, 0x72, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x76, 0x65, 0x72, 0x74, +0x69, 0x63, 0x61, 0x6c, 0x23f8, 0x3a, 0x70, 0x61, 0x75, 0x73, 0x65, 0x5f, +0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x62, 0x75, 0x74, 0x74, 0x6f, +0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x23ef, 0x3a, 0x70, 0x6c, 0x61, 0x79, +0x5f, 0x70, 0x61, 0x75, 0x73, 0x65, 0x3a, 0x70, 0x61, 0x75, 0x73, 0x65, +0x70, 0x6c, 0x61, 0x79, 0x23f9, 0x3a, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x62, +0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, +0x73, 0x74, 0x6f, 0x70, 0x23fa, 0x3a, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, +0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x62, 0x75, 0x74, 0x74, +0x6f, 0x6e, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x23ed, 0x3a, 0x6e, 0x65, +0x78, 0x74, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x3a, 0x6e, 0x65, 0x78, +0x74, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x23ed, 0x3a, 0x74, 0x72, 0x61, 0x63, +0x6b, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x3a, 0x6e, 0x65, 0x78, 0x74, 0x74, +0x72, 0x61, 0x63, 0x6b, 0x23ee, 0x3a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, +0x75, 0x73, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x3a, 0x70, 0x72, 0x65, +0x76, 0x69, 0x6f, 0x75, 0x73, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x23ee, 0x3a, +0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, +0x75, 0x73, 0x3a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x74, +0x72, 0x61, 0x63, 0x6b, 0x23e9, 0x3a, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x66, +0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x3a, 0x66, 0x61, 0x73, 0x74, 0x66, +0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x23ea, 0x3a, 0x72, 0x65, 0x77, 0x69, +0x6e, 0x64, 0x3a, 0x72, 0x65, 0x77, 0x69, 0x6e, 0x64, 0x23eb, 0x3a, 0x61, +0x72, 0x72, 0x6f, 0x77, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, +0x75, 0x70, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x64, 0x6f, 0x75, 0x62, +0x6c, 0x65, 0x75, 0x70, 0x23ec, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, +0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x3a, +0x61, 0x72, 0x72, 0x6f, 0x77, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x64, +0x6f, 0x77, 0x6e, 0x25c0, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, +0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, 0x64, 0x3a, 0x61, 0x72, 0x72, +0x6f, 0x77, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, 0x64, 0xd83d, 0xdd3c, +0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x75, 0x70, 0x5f, 0x73, 0x6d, +0x61, 0x6c, 0x6c, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x73, 0x6d, 0x61, +0x6c, 0x6c, 0x75, 0x70, 0xd83d, 0xdd3d, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, +0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x3a, +0x61, 0x72, 0x72, 0x6f, 0x77, 0x64, 0x6f, 0x77, 0x6e, 0x73, 0x6d, 0x61, +0x6c, 0x6c, 0x27a1, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x72, +0x69, 0x67, 0x68, 0x74, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x72, 0x69, +0x67, 0x68, 0x74, 0x2b05, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, +0x6c, 0x65, 0x66, 0x74, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x6c, 0x65, +0x66, 0x74, 0x2b06, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x75, +0x70, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x75, 0x70, 0x2b07, 0xfe0f, 0x3a, +0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x61, +0x72, 0x72, 0x6f, 0x77, 0x64, 0x6f, 0x77, 0x6e, 0x2197, 0xfe0f, 0x3a, 0x61, +0x72, 0x72, 0x6f, 0x77, 0x5f, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x72, +0x69, 0x67, 0x68, 0x74, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x72, 0x69, +0x67, 0x68, 0x74, 0x75, 0x70, 0x70, 0x65, 0x72, 0x2198, 0xfe0f, 0x3a, 0x61, +0x72, 0x72, 0x6f, 0x77, 0x5f, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x72, +0x69, 0x67, 0x68, 0x74, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x6c, 0x6f, +0x77, 0x65, 0x72, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2199, 0xfe0f, 0x3a, 0x61, +0x72, 0x72, 0x6f, 0x77, 0x5f, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x6c, +0x65, 0x66, 0x74, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x6c, 0x65, 0x66, +0x74, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x2196, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, +0x6f, 0x77, 0x5f, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x66, +0x74, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x6c, 0x65, 0x66, 0x74, 0x75, +0x70, 0x70, 0x65, 0x72, 0x2195, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, +0x5f, 0x75, 0x70, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x61, 0x72, 0x72, +0x6f, 0x77, 0x64, 0x6f, 0x77, 0x6e, 0x75, 0x70, 0x2194, 0xfe0f, 0x3a, 0x6c, +0x65, 0x66, 0x74, 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x61, 0x72, +0x72, 0x6f, 0x77, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x6c, 0x65, 0x66, +0x74, 0x72, 0x69, 0x67, 0x68, 0x74, 0x21aa, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, +0x6f, 0x77, 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x68, 0x6f, 0x6f, +0x6b, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x68, 0x6f, 0x6f, 0x6b, 0x72, +0x69, 0x67, 0x68, 0x74, 0x21a9, 0xfe0f, 0x3a, 0x6c, 0x65, 0x66, 0x74, 0x77, +0x61, 0x72, 0x64, 0x73, 0x5f, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x77, +0x69, 0x74, 0x68, 0x5f, 0x68, 0x6f, 0x6f, 0x6b, 0x3a, 0x61, 0x72, 0x72, +0x6f, 0x77, 0x68, 0x6f, 0x6f, 0x6b, 0x6c, 0x65, 0x66, 0x74, 0x77, 0x61, +0x72, 0x64, 0x73, 0x77, 0x69, 0x74, 0x68, 0x2934, 0xfe0f, 0x3a, 0x61, 0x72, +0x72, 0x6f, 0x77, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, +0x75, 0x70, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x68, 0x65, 0x61, 0x64, +0x69, 0x6e, 0x67, 0x75, 0x70, 0x2935, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, +0x77, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x6f, +0x77, 0x6e, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x64, 0x6f, 0x77, 0x6e, +0x68, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0xd83d, 0xdd00, 0x3a, 0x74, 0x77, +0x69, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x77, +0x61, 0x72, 0x64, 0x73, 0x5f, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x73, 0x3a, +0x61, 0x72, 0x72, 0x6f, 0x77, 0x73, 0x72, 0x69, 0x67, 0x68, 0x74, 0x77, +0x61, 0x72, 0x64, 0x73, 0x74, 0x77, 0x69, 0x73, 0x74, 0x65, 0x64, 0xd83d, +0xdd01, 0x3a, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3a, 0x72, 0x65, 0x70, +0x65, 0x61, 0x74, 0xd83d, 0xdd02, 0x3a, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, +0x5f, 0x6f, 0x6e, 0x65, 0x3a, 0x6f, 0x6e, 0x65, 0x72, 0x65, 0x70, 0x65, +0x61, 0x74, 0xd83d, 0xdd04, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x73, 0x5f, +0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x6c, 0x6f, 0x63, 0x6b, +0x77, 0x69, 0x73, 0x65, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x73, 0x63, +0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x77, +0x69, 0x73, 0x65, 0xd83d, 0xdd03, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x73, +0x5f, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x77, 0x69, 0x73, 0x65, 0x3a, 0x61, +0x72, 0x72, 0x6f, 0x77, 0x73, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x77, 0x69, +0x73, 0x65, 0xd83c, 0xdfb5, 0x3a, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x61, 0x6c, +0x5f, 0x6e, 0x6f, 0x74, 0x65, 0x3a, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x61, +0x6c, 0x6e, 0x6f, 0x74, 0x65, 0xd83c, 0xdfb6, 0x3a, 0x6e, 0x6f, 0x74, 0x65, +0x73, 0x3a, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x2795, 0x3a, 0x68, 0x65, 0x61, +0x76, 0x79, 0x5f, 0x70, 0x6c, 0x75, 0x73, 0x5f, 0x73, 0x69, 0x67, 0x6e, +0x3a, 0x68, 0x65, 0x61, 0x76, 0x79, 0x70, 0x6c, 0x75, 0x73, 0x73, 0x69, +0x67, 0x6e, 0x2796, 0x3a, 0x68, 0x65, 0x61, 0x76, 0x79, 0x5f, 0x6d, 0x69, +0x6e, 0x75, 0x73, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x3a, 0x68, 0x65, 0x61, +0x76, 0x79, 0x6d, 0x69, 0x6e, 0x75, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x2797, +0x3a, 0x68, 0x65, 0x61, 0x76, 0x79, 0x5f, 0x64, 0x69, 0x76, 0x69, 0x73, +0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x3a, 0x64, 0x69, 0x76, +0x69, 0x73, 0x69, 0x6f, 0x6e, 0x68, 0x65, 0x61, 0x76, 0x79, 0x73, 0x69, +0x67, 0x6e, 0x2716, 0xfe0f, 0x3a, 0x68, 0x65, 0x61, 0x76, 0x79, 0x5f, 0x6d, +0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, +0x6e, 0x5f, 0x78, 0x3a, 0x68, 0x65, 0x61, 0x76, 0x79, 0x6d, 0x75, 0x6c, +0x74, 0x69, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x78, +0xd83d, 0xdcb2, 0x3a, 0x68, 0x65, 0x61, 0x76, 0x79, 0x5f, 0x64, 0x6f, 0x6c, +0x6c, 0x61, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x3a, 0x64, 0x6f, 0x6c, +0x6c, 0x61, 0x72, 0x68, 0x65, 0x61, 0x76, 0x79, 0x73, 0x69, 0x67, 0x6e, +0xd83d, 0xdcb1, 0x3a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, +0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x3a, 0x63, 0x75, 0x72, +0x72, 0x65, 0x6e, 0x63, 0x79, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, +0x65, 0x2122, 0x3a, 0x74, 0x6d, 0x3a, 0x74, 0x6d, 0xa9, 0x3a, 0x63, 0x6f, +0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x63, 0x6f, 0x70, 0x79, +0x72, 0x69, 0x67, 0x68, 0x74, 0xae, 0x3a, 0x72, 0x65, 0x67, 0x69, 0x73, +0x74, 0x65, 0x72, 0x65, 0x64, 0x3a, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, +0x65, 0x72, 0x65, 0x64, 0x3030, 0x3a, 0x77, 0x61, 0x76, 0x79, 0x5f, 0x64, +0x61, 0x73, 0x68, 0x3a, 0x64, 0x61, 0x73, 0x68, 0x77, 0x61, 0x76, 0x79, +0x27b0, 0x3a, 0x63, 0x75, 0x72, 0x6c, 0x79, 0x5f, 0x6c, 0x6f, 0x6f, 0x70, +0x3a, 0x63, 0x75, 0x72, 0x6c, 0x79, 0x6c, 0x6f, 0x6f, 0x70, 0x27bf, 0x3a, +0x6c, 0x6f, 0x6f, 0x70, 0x3a, 0x6c, 0x6f, 0x6f, 0x70, 0xd83d, 0xdd1a, 0x3a, +0x65, 0x6e, 0x64, 0x3a, 0x65, 0x6e, 0x64, 0xd83d, 0xdd19, 0x3a, 0x62, 0x61, +0x63, 0x6b, 0x3a, 0x62, 0x61, 0x63, 0x6b, 0xd83d, 0xdd1b, 0x3a, 0x6f, 0x6e, +0x3a, 0x6f, 0x6e, 0xd83d, 0xdd1d, 0x3a, 0x74, 0x6f, 0x70, 0x3a, 0x74, 0x6f, +0x70, 0xd83d, 0xdd1c, 0x3a, 0x73, 0x6f, 0x6f, 0x6e, 0x3a, 0x73, 0x6f, 0x6f, +0x6e, 0x2714, 0xfe0f, 0x3a, 0x68, 0x65, 0x61, 0x76, 0x79, 0x5f, 0x63, 0x68, +0x65, 0x63, 0x6b, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x3a, 0x63, 0x68, 0x65, +0x63, 0x6b, 0x68, 0x65, 0x61, 0x76, 0x79, 0x6d, 0x61, 0x72, 0x6b, 0x2611, +0xfe0f, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x5f, 0x62, 0x6f, 0x78, +0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x3a, +0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x62, 0x6f, 0x78, 0x63, 0x68, 0x65, +0x63, 0x6b, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdd18, 0x3a, 0x72, 0x61, 0x64, +0x69, 0x6f, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x62, 0x75, +0x74, 0x74, 0x6f, 0x6e, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x26aa, 0xfe0f, 0x3a, +0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, +0x3a, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x77, 0x68, 0x69, 0x74, 0x65, +0x26ab, 0xfe0f, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x69, 0x72, +0x63, 0x6c, 0x65, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x63, 0x69, 0x72, +0x63, 0x6c, 0x65, 0xd83d, 0xdd34, 0x3a, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x69, +0x72, 0x63, 0x6c, 0x65, 0x3a, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x72, +0x65, 0x64, 0xd83d, 0xdd35, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x5f, 0x63, 0x69, +0x72, 0x63, 0x6c, 0x65, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x63, 0x69, 0x72, +0x63, 0x6c, 0x65, 0xd83d, 0xdd3a, 0x3a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, +0x72, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x6c, 0x65, +0x3a, 0x72, 0x65, 0x64, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x74, 0x72, 0x69, +0x61, 0x6e, 0x67, 0x6c, 0x65, 0xd83d, 0xdd3b, 0x3a, 0x73, 0x6d, 0x61, 0x6c, +0x6c, 0x5f, 0x72, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, +0x6c, 0x65, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x64, 0x6f, 0x77, 0x6e, +0x72, 0x65, 0x64, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x74, 0x72, 0x69, 0x61, +0x6e, 0x67, 0x6c, 0x65, 0xd83d, 0xdd38, 0x3a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, +0x5f, 0x6f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x64, 0x69, 0x61, 0x6d, +0x6f, 0x6e, 0x64, 0x3a, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x6f, +0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0xd83d, 0xdd39, +0x3a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x62, 0x6c, 0x75, 0x65, 0x5f, +0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x3a, 0x62, 0x6c, 0x75, 0x65, +0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x73, 0x6d, 0x61, 0x6c, 0x6c, +0xd83d, 0xdd36, 0x3a, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x6f, 0x72, 0x61, +0x6e, 0x67, 0x65, 0x5f, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x3a, +0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x6c, 0x61, 0x72, 0x67, 0x65, +0x6f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0xd83d, 0xdd37, 0x3a, 0x6c, 0x61, 0x72, +0x67, 0x65, 0x5f, 0x62, 0x6c, 0x75, 0x65, 0x5f, 0x64, 0x69, 0x61, 0x6d, +0x6f, 0x6e, 0x64, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x64, 0x69, 0x61, 0x6d, +0x6f, 0x6e, 0x64, 0x6c, 0x61, 0x72, 0x67, 0x65, 0xd83d, 0xdd33, 0x3a, 0x77, +0x68, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x5f, +0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x62, 0x75, 0x74, 0x74, 0x6f, +0x6e, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x77, 0x68, 0x69, 0x74, 0x65, +0xd83d, 0xdd32, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x71, 0x75, +0x61, 0x72, 0x65, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x62, +0x6c, 0x61, 0x63, 0x6b, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x71, +0x75, 0x61, 0x72, 0x65, 0x25aa, 0xfe0f, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, +0x5f, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, +0x65, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x73, 0x6d, 0x61, 0x6c, 0x6c, +0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x25ab, 0xfe0f, 0x3a, 0x77, 0x68, 0x69, +0x74, 0x65, 0x5f, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x71, 0x75, +0x61, 0x72, 0x65, 0x3a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x73, 0x71, 0x75, +0x61, 0x72, 0x65, 0x77, 0x68, 0x69, 0x74, 0x65, 0x25fe, 0xfe0f, 0x3a, 0x62, +0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x5f, +0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, +0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, +0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x25fd, +0xfe0f, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x6d, 0x65, 0x64, 0x69, +0x75, 0x6d, 0x5f, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x71, 0x75, +0x61, 0x72, 0x65, 0x3a, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x73, 0x6d, +0x61, 0x6c, 0x6c, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x77, 0x68, 0x69, +0x74, 0x65, 0x25fc, 0xfe0f, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x6d, +0x65, 0x64, 0x69, 0x75, 0x6d, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, +0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, +0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x25fb, 0xfe0f, 0x3a, 0x77, 0x68, 0x69, +0x74, 0x65, 0x5f, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x5f, 0x73, 0x71, +0x75, 0x61, 0x72, 0x65, 0x3a, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x73, +0x71, 0x75, 0x61, 0x72, 0x65, 0x77, 0x68, 0x69, 0x74, 0x65, 0x2b1b, 0xfe0f, +0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x6c, 0x61, 0x72, 0x67, 0x65, +0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x3a, 0x62, 0x6c, 0x61, 0x63, +0x6b, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, +0x2b1c, 0xfe0f, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x6c, 0x61, 0x72, +0x67, 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x3a, 0x6c, 0x61, +0x72, 0x67, 0x65, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x77, 0x68, 0x69, +0x74, 0x65, 0xd83d, 0xdd08, 0x3a, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x65, 0x72, +0x3a, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x65, 0x72, 0xd83d, 0xdd07, 0x3a, 0x6d, +0x75, 0x74, 0x65, 0x3a, 0x6d, 0x75, 0x74, 0x65, 0xd83d, 0xdd09, 0x3a, 0x73, +0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0xd83d, 0xdd0a, +0x3a, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x3a, +0x6c, 0x6f, 0x75, 0x64, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0xd83d, 0xdd14, 0x3a, +0x62, 0x65, 0x6c, 0x6c, 0x3a, 0x62, 0x65, 0x6c, 0x6c, 0xd83d, 0xdd15, 0x3a, +0x6e, 0x6f, 0x5f, 0x62, 0x65, 0x6c, 0x6c, 0x3a, 0x62, 0x65, 0x6c, 0x6c, +0x6e, 0x6f, 0xd83d, 0xdce3, 0x3a, 0x6d, 0x65, 0x67, 0x61, 0x3a, 0x6d, 0x65, +0x67, 0x61, 0xd83d, 0xdce2, 0x3a, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x70, 0x65, +0x61, 0x6b, 0x65, 0x72, 0x3a, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x70, 0x65, +0x61, 0x6b, 0x65, 0x72, 0xd83d, 0xdde8, 0x3a, 0x6c, 0x65, 0x66, 0x74, 0x5f, +0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0x5f, 0x62, 0x75, 0x62, 0x62, 0x6c, +0x65, 0x3a, 0x62, 0x75, 0x62, 0x62, 0x6c, 0x65, 0x6c, 0x65, 0x66, 0x74, +0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0xd83d, 0xdde8, 0x3a, 0x73, 0x70, 0x65, +0x65, 0x63, 0x68, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x6c, 0x65, 0x66, +0x74, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0xd83d, 0xdc41, 0x200d, 0xd83d, 0xdde8, +0x3a, 0x65, 0x79, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x65, +0x63, 0x68, 0x5f, 0x62, 0x75, 0x62, 0x62, 0x6c, 0x65, 0x3a, 0x62, 0x75, +0x62, 0x62, 0x6c, 0x65, 0x65, 0x79, 0x65, 0x69, 0x6e, 0x73, 0x70, 0x65, +0x65, 0x63, 0x68, 0xd83d, 0xdcac, 0x3a, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, +0x5f, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x6f, 0x6e, 0x3a, 0x62, 0x61, 0x6c, +0x6c, 0x6f, 0x6f, 0x6e, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0xd83d, 0xdcad, +0x3a, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x5f, 0x62, 0x61, 0x6c, +0x6c, 0x6f, 0x6f, 0x6e, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x6f, 0x6e, +0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x74, 0xd83d, 0xddef, 0x3a, 0x72, 0x69, +0x67, 0x68, 0x74, 0x5f, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x62, 0x75, +0x62, 0x62, 0x6c, 0x65, 0x3a, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x62, 0x75, +0x62, 0x62, 0x6c, 0x65, 0x72, 0x69, 0x67, 0x68, 0x74, 0xd83d, 0xddef, 0x3a, +0x61, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, +0x61, 0x6e, 0x67, 0x65, 0x72, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2660, 0xfe0f, +0x3a, 0x73, 0x70, 0x61, 0x64, 0x65, 0x73, 0x3a, 0x73, 0x70, 0x61, 0x64, +0x65, 0x73, 0x2663, 0xfe0f, 0x3a, 0x63, 0x6c, 0x75, 0x62, 0x73, 0x3a, 0x63, +0x6c, 0x75, 0x62, 0x73, 0x2665, 0xfe0f, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, +0x73, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x73, 0x2666, 0xfe0f, 0x3a, 0x64, +0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x73, 0x3a, 0x64, 0x69, 0x61, 0x6d, +0x6f, 0x6e, 0x64, 0x73, 0xd83c, 0xdccf, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, +0x5f, 0x6a, 0x6f, 0x6b, 0x65, 0x72, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, +0x6a, 0x6f, 0x6b, 0x65, 0x72, 0xd83c, 0xdfb4, 0x3a, 0x66, 0x6c, 0x6f, 0x77, +0x65, 0x72, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x63, +0x61, 0x72, 0x64, 0x73, 0x3a, 0x63, 0x61, 0x72, 0x64, 0x73, 0x66, 0x6c, +0x6f, 0x77, 0x65, 0x72, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0xd83c, +0xdc04, 0xfe0f, 0x3a, 0x6d, 0x61, 0x68, 0x6a, 0x6f, 0x6e, 0x67, 0x3a, 0x6d, +0x61, 0x68, 0x6a, 0x6f, 0x6e, 0x67, 0xd83d, 0xdd50, 0x3a, 0x63, 0x6c, 0x6f, +0x63, 0x6b, 0x31, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0xd83d, 0xdd51, +0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x32, 0x3a, 0x63, 0x6c, 0x6f, 0x63, +0x6b, 0x32, 0xd83d, 0xdd52, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x33, 0x3a, +0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x33, 0xd83d, 0xdd53, 0x3a, 0x63, 0x6c, 0x6f, +0x63, 0x6b, 0x34, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x34, 0xd83d, 0xdd54, +0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x35, 0x3a, 0x63, 0x6c, 0x6f, 0x63, +0x6b, 0x35, 0xd83d, 0xdd55, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x36, 0x3a, +0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x36, 0xd83d, 0xdd56, 0x3a, 0x63, 0x6c, 0x6f, +0x63, 0x6b, 0x37, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x37, 0xd83d, 0xdd57, +0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x38, 0x3a, 0x63, 0x6c, 0x6f, 0x63, +0x6b, 0x38, 0xd83d, 0xdd58, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x39, 0x3a, +0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x39, 0xd83d, 0xdd59, 0x3a, 0x63, 0x6c, 0x6f, +0x63, 0x6b, 0x31, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x30, +0xd83d, 0xdd5a, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x31, 0x3a, 0x63, +0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x31, 0xd83d, 0xdd5b, 0x3a, 0x63, 0x6c, 0x6f, +0x63, 0x6b, 0x31, 0x32, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x32, +0xd83d, 0xdd5c, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x33, 0x30, 0x3a, +0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x33, 0x30, 0xd83d, 0xdd5d, 0x3a, 0x63, +0x6c, 0x6f, 0x63, 0x6b, 0x32, 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, +0x6b, 0x32, 0x33, 0x30, 0xd83d, 0xdd5e, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, +0x33, 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x33, 0x33, 0x30, +0xd83d, 0xdd5f, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x34, 0x33, 0x30, 0x3a, +0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x34, 0x33, 0x30, 0xd83d, 0xdd60, 0x3a, 0x63, +0x6c, 0x6f, 0x63, 0x6b, 0x35, 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, +0x6b, 0x35, 0x33, 0x30, 0xd83d, 0xdd61, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, +0x36, 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x36, 0x33, 0x30, +0xd83d, 0xdd62, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x37, 0x33, 0x30, 0x3a, +0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x37, 0x33, 0x30, 0xd83d, 0xdd63, 0x3a, 0x63, +0x6c, 0x6f, 0x63, 0x6b, 0x38, 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, +0x6b, 0x38, 0x33, 0x30, 0xd83d, 0xdd64, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, +0x39, 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x39, 0x33, 0x30, +0xd83d, 0xdd65, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x30, 0x33, 0x30, +0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x30, 0x33, 0x30, 0xd83d, 0xdd66, +0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x31, 0x33, 0x30, 0x3a, 0x63, +0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x31, 0x33, 0x30, 0xd83d, 0xdd67, 0x3a, 0x63, +0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x32, 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, +0x63, 0x6b, 0x31, 0x32, 0x33, 0x30, 0xd83c, 0xdff3, 0x3a, 0x77, 0x61, 0x76, +0x69, 0x6e, 0x67, 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x66, 0x6c, +0x61, 0x67, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x77, 0x61, 0x76, 0x69, 0x6e, +0x67, 0x77, 0x68, 0x69, 0x74, 0x65, 0xd83c, 0xdff3, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x77, 0x68, 0x69, 0x74, 0x65, 0xd83c, 0xdff4, 0x3a, 0x77, 0x61, 0x76, 0x69, +0x6e, 0x67, 0x5f, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x66, 0x6c, 0x61, +0x67, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x66, 0x6c, 0x61, 0x67, 0x77, +0x61, 0x76, 0x69, 0x6e, 0x67, 0xd83c, 0xdff4, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, +0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdfc1, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b, +0x65, 0x72, 0x65, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x3a, 0x63, 0x68, +0x65, 0x63, 0x6b, 0x65, 0x72, 0x65, 0x64, 0x66, 0x6c, 0x61, 0x67, 0xd83d, +0xdea9, 0x3a, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x72, +0x5f, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x73, +0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6f, 0x6e, 0x70, 0x6f, 0x73, 0x74, +0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x72, 0xd83c, 0xdff3, +0xfe0f, 0x200d, 0xd83c, 0xdf08, 0x3a, 0x67, 0x61, 0x79, 0x5f, 0x70, 0x72, 0x69, +0x64, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x67, 0x61, 0x79, 0x70, 0x72, 0x69, 0x64, 0x65, 0xd83c, 0xdff3, 0xfe0f, 0x200d, +0xd83c, 0xdf08, 0x3a, 0x72, 0x61, 0x69, 0x6e, 0x62, 0x6f, 0x77, 0x5f, 0x66, +0x6c, 0x61, 0x67, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x72, 0x61, 0x69, 0x6e, +0x62, 0x6f, 0x77, 0xd83c, 0xdde6, 0xd83c, 0xddeb, 0x3a, 0x61, 0x66, 0x3a, 0x61, +0x66, 0xd83c, 0xdde6, 0xd83c, 0xddeb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, +0x66, 0x3a, 0x61, 0x66, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddfd, +0x3a, 0x61, 0x78, 0x3a, 0x61, 0x78, 0xd83c, 0xdde6, 0xd83c, 0xddfd, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x61, 0x78, 0x3a, 0x61, 0x78, 0x66, 0x6c, 0x61, +0x67, 0xd83c, 0xdde6, 0xd83c, 0xddf1, 0x3a, 0x61, 0x6c, 0x3a, 0x61, 0x6c, 0xd83c, +0xdde6, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x6c, 0x3a, +0x61, 0x6c, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde9, 0xd83c, 0xddff, 0x3a, 0x64, +0x7a, 0x3a, 0x64, 0x7a, 0xd83c, 0xdde9, 0xd83c, 0xddff, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x64, 0x7a, 0x3a, 0x64, 0x7a, 0x66, 0x6c, 0x61, 0x67, 0xd83c, +0xdde6, 0xd83c, 0xddf8, 0x3a, 0x61, 0x73, 0x3a, 0x61, 0x73, 0xd83c, 0xdde6, 0xd83c, +0xddf8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x73, 0x3a, 0x61, 0x73, +0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xdde9, 0x3a, 0x61, 0x64, 0x3a, +0x61, 0x64, 0xd83c, 0xdde6, 0xd83c, 0xdde9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x61, 0x64, 0x3a, 0x61, 0x64, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, +0xddf4, 0x3a, 0x61, 0x6f, 0x3a, 0x61, 0x6f, 0xd83c, 0xdde6, 0xd83c, 0xddf4, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x6f, 0x3a, 0x61, 0x6f, 0x66, 0x6c, +0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddee, 0x3a, 0x61, 0x69, 0x3a, 0x61, 0x69, +0xd83c, 0xdde6, 0xd83c, 0xddee, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x69, +0x3a, 0x61, 0x69, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddf6, 0x3a, +0x61, 0x71, 0x3a, 0x61, 0x71, 0xd83c, 0xdde6, 0xd83c, 0xddf6, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x61, 0x71, 0x3a, 0x61, 0x71, 0x66, 0x6c, 0x61, 0x67, +0xd83c, 0xdde6, 0xd83c, 0xddec, 0x3a, 0x61, 0x67, 0x3a, 0x61, 0x67, 0xd83c, 0xdde6, +0xd83c, 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x67, 0x3a, 0x61, +0x67, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddf7, 0x3a, 0x61, 0x72, +0x3a, 0x61, 0x72, 0xd83c, 0xdde6, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x61, 0x72, 0x3a, 0x61, 0x72, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, +0xd83c, 0xddf2, 0x3a, 0x61, 0x6d, 0x3a, 0x61, 0x6d, 0xd83c, 0xdde6, 0xd83c, 0xddf2, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x6d, 0x3a, 0x61, 0x6d, 0x66, +0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddfc, 0x3a, 0x61, 0x77, 0x3a, 0x61, +0x77, 0xd83c, 0xdde6, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, +0x77, 0x3a, 0x61, 0x77, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddfa, +0x3a, 0x68, 0x6d, 0x3a, 0x68, 0x6d, 0xd83c, 0xdde6, 0xd83c, 0xddfa, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x68, 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x68, +0x6d, 0xd83c, 0xdde6, 0xd83c, 0xddfa, 0x3a, 0x61, 0x75, 0x3a, 0x61, 0x75, 0xd83c, +0xdde6, 0xd83c, 0xddfa, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x75, 0x3a, +0x61, 0x75, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddf9, 0x3a, 0x61, +0x74, 0x3a, 0x61, 0x74, 0xd83c, 0xdde6, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x61, 0x74, 0x3a, 0x61, 0x74, 0x66, 0x6c, 0x61, 0x67, 0xd83c, +0xdde6, 0xd83c, 0xddff, 0x3a, 0x61, 0x7a, 0x3a, 0x61, 0x7a, 0xd83c, 0xdde6, 0xd83c, +0xddff, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x7a, 0x3a, 0x61, 0x7a, +0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddf8, 0x3a, 0x62, 0x73, 0x3a, +0x62, 0x73, 0xd83c, 0xdde7, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x62, 0x73, 0x3a, 0x62, 0x73, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, +0xdded, 0x3a, 0x62, 0x68, 0x3a, 0x62, 0x68, 0xd83c, 0xdde7, 0xd83c, 0xdded, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x68, 0x3a, 0x62, 0x68, 0x66, 0x6c, +0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xdde9, 0x3a, 0x62, 0x64, 0x3a, 0x62, 0x64, +0xd83c, 0xdde7, 0xd83c, 0xdde9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x64, +0x3a, 0x62, 0x64, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xdde7, 0x3a, +0x62, 0x62, 0x3a, 0x62, 0x62, 0xd83c, 0xdde7, 0xd83c, 0xdde7, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x62, 0x62, 0x3a, 0x62, 0x62, 0x66, 0x6c, 0x61, 0x67, +0xd83c, 0xdde7, 0xd83c, 0xddfe, 0x3a, 0x62, 0x79, 0x3a, 0x62, 0x79, 0xd83c, 0xdde7, +0xd83c, 0xddfe, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x79, 0x3a, 0x62, +0x79, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddea, 0x3a, 0x62, 0x65, +0x3a, 0x62, 0x65, 0xd83c, 0xdde7, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x62, 0x65, 0x3a, 0x62, 0x65, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, +0xd83c, 0xddff, 0x3a, 0x62, 0x7a, 0x3a, 0x62, 0x7a, 0xd83c, 0xdde7, 0xd83c, 0xddff, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x7a, 0x3a, 0x62, 0x7a, 0x66, +0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddef, 0x3a, 0x62, 0x6a, 0x3a, 0x62, +0x6a, 0xd83c, 0xdde7, 0xd83c, 0xddef, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, +0x6a, 0x3a, 0x62, 0x6a, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddf2, +0x3a, 0x62, 0x6d, 0x3a, 0x62, 0x6d, 0xd83c, 0xdde7, 0xd83c, 0xddf2, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x62, 0x6d, 0x3a, 0x62, 0x6d, 0x66, 0x6c, 0x61, +0x67, 0xd83c, 0xdde7, 0xd83c, 0xddf9, 0x3a, 0x62, 0x74, 0x3a, 0x62, 0x74, 0xd83c, +0xdde7, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x74, 0x3a, +0x62, 0x74, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddf4, 0x3a, 0x62, +0x6f, 0x3a, 0x62, 0x6f, 0xd83c, 0xdde7, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x62, 0x6f, 0x3a, 0x62, 0x6f, 0x66, 0x6c, 0x61, 0x67, 0xd83c, +0xdde7, 0xd83c, 0xdde6, 0x3a, 0x62, 0x61, 0x3a, 0x62, 0x61, 0xd83c, 0xdde7, 0xd83c, +0xdde6, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x61, 0x3a, 0x62, 0x61, +0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddfc, 0x3a, 0x62, 0x77, 0x3a, +0x62, 0x77, 0xd83c, 0xdde7, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x62, 0x77, 0x3a, 0x62, 0x77, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, +0xddf7, 0x3a, 0x62, 0x72, 0x3a, 0x62, 0x72, 0xd83c, 0xdde7, 0xd83c, 0xddf7, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x72, 0x3a, 0x62, 0x72, 0x66, 0x6c, +0x61, 0x67, 0xd83c, 0xddee, 0xd83c, 0xddf4, 0x3a, 0x69, 0x6f, 0x3a, 0x69, 0x6f, +0xd83c, 0xddee, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, 0x6f, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, 0x6f, 0xd83c, 0xddee, 0xd83c, 0xddf4, 0x3a, +0x64, 0x67, 0x3a, 0x64, 0x67, 0xd83c, 0xddee, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x64, 0x67, 0x3a, 0x64, 0x67, 0x66, 0x6c, 0x61, 0x67, +0xd83c, 0xddfb, 0xd83c, 0xddec, 0x3a, 0x76, 0x67, 0x3a, 0x76, 0x67, 0xd83c, 0xddfb, +0xd83c, 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76, 0x67, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x76, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddf3, 0x3a, 0x62, 0x6e, +0x3a, 0x62, 0x6e, 0xd83c, 0xdde7, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x62, 0x6e, 0x3a, 0x62, 0x6e, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, +0xd83c, 0xddec, 0x3a, 0x62, 0x67, 0x3a, 0x62, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddec, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x67, 0x3a, 0x62, 0x67, 0x66, +0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddeb, 0x3a, 0x62, 0x66, 0x3a, 0x62, +0x66, 0xd83c, 0xdde7, 0xd83c, 0xddeb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, +0x66, 0x3a, 0x62, 0x66, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddee, +0x3a, 0x62, 0x69, 0x3a, 0x62, 0x69, 0xd83c, 0xdde7, 0xd83c, 0xddee, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x62, 0x69, 0x3a, 0x62, 0x69, 0x66, 0x6c, 0x61, +0x67, 0xd83c, 0xddf0, 0xd83c, 0xdded, 0x3a, 0x6b, 0x68, 0x3a, 0x6b, 0x68, 0xd83c, +0xddf0, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x68, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x6b, 0x68, 0xd83c, 0xdde8, 0xd83c, 0xddf2, 0x3a, 0x63, +0x6d, 0x3a, 0x63, 0x6d, 0xd83c, 0xdde8, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x63, 0x6d, 0x3a, 0x63, 0x6d, 0x66, 0x6c, 0x61, 0x67, 0xd83c, +0xdde8, 0xd83c, 0xdde6, 0x3a, 0x63, 0x61, 0x3a, 0x63, 0x61, 0xd83c, 0xdde8, 0xd83c, +0xdde6, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x61, 0x3a, 0x63, 0x61, +0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddee, 0xd83c, 0xdde8, 0x3a, 0x69, 0x63, 0x3a, +0x69, 0x63, 0xd83c, 0xddee, 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x69, 0x63, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, 0x63, 0xd83c, 0xdde8, 0xd83c, +0xddfb, 0x3a, 0x63, 0x76, 0x3a, 0x63, 0x76, 0xd83c, 0xdde8, 0xd83c, 0xddfb, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x76, 0x3a, 0x63, 0x76, 0x66, 0x6c, +0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddf6, 0x3a, 0x62, 0x71, 0x3a, 0x62, 0x71, +0xd83c, 0xdde7, 0xd83c, 0xddf6, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x71, +0x3a, 0x62, 0x71, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddf0, 0xd83c, 0xddfe, 0x3a, +0x6b, 0x79, 0x3a, 0x6b, 0x79, 0xd83c, 0xddf0, 0xd83c, 0xddfe, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x6b, 0x79, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6b, 0x79, +0xd83c, 0xdde8, 0xd83c, 0xddeb, 0x3a, 0x63, 0x66, 0x3a, 0x63, 0x66, 0xd83c, 0xdde8, +0xd83c, 0xddeb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x66, 0x3a, 0x63, +0x66, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddf9, 0xd83c, 0xdde9, 0x3a, 0x74, 0x64, +0x3a, 0x74, 0x64, 0xd83c, 0xddf9, 0xd83c, 0xdde9, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x74, 0x64, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x64, 0xd83c, 0xdde8, +0xd83c, 0xddf1, 0x3a, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x3a, 0x63, 0x68, 0x69, +0x6c, 0x65, 0xd83c, 0xdde8, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x63, 0x6c, 0x3a, 0x63, 0x6c, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, +0xddf3, 0x3a, 0x63, 0x6e, 0x3a, 0x63, 0x6e, 0xd83c, 0xdde8, 0xd83c, 0xddf3, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x6e, 0x3a, 0x63, 0x6e, 0x66, 0x6c, +0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xddfd, 0x3a, 0x63, 0x78, 0x3a, 0x63, 0x78, +0xd83c, 0xdde8, 0xd83c, 0xddfd, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x78, +0x3a, 0x63, 0x78, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xdde8, 0x3a, +0x63, 0x63, 0x3a, 0x63, 0x63, 0xd83c, 0xdde8, 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x63, 0x63, 0x3a, 0x63, 0x63, 0x66, 0x6c, 0x61, 0x67, +0xd83c, 0xdde8, 0xd83c, 0xddf4, 0x3a, 0x63, 0x6f, 0x3a, 0x63, 0x6f, 0xd83c, 0xdde8, +0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x6f, 0x3a, 0x63, +0x6f, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddf0, 0xd83c, 0xddf2, 0x3a, 0x6b, 0x6d, +0x3a, 0x6b, 0x6d, 0xd83c, 0xddf0, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x6b, 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6b, 0x6d, 0xd83c, 0xdde8, +0xd83c, 0xddec, 0x3a, 0x63, 0x67, 0x3a, 0x63, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xddec, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x67, 0x3a, 0x63, 0x67, 0x66, +0x6c, 0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xdde9, 0x3a, 0x63, 0x6f, 0x6e, 0x67, +0x6f, 0x3a, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0xd83c, 0xdde8, 0xd83c, 0xdde9, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x64, 0x3a, 0x63, 0x64, 0x66, 0x6c, +0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xddf0, 0x3a, 0x63, 0x6b, 0x3a, 0x63, 0x6b, +0xd83c, 0xdde8, 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x6b, +0x3a, 0x63, 0x6b, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xddf7, 0x3a, +0x63, 0x72, 0x3a, 0x63, 0x72, 0xd83c, 0xdde8, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x63, 0x72, 0x3a, 0x63, 0x72, 0x66, 0x6c, 0x61, 0x67, +0xd83c, 0xdde8, 0xd83c, 0xddee, 0x3a, 0x63, 0x69, 0x3a, 0x63, 0x69, 0xd83c, 0xdde8, +0xd83c, 0xddee, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x69, 0x3a, 0x63, +0x69, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdded, 0xd83c, 0xddf7, 0x3a, 0x68, 0x72, +0x3a, 0x68, 0x72, 0xd83c, 0xdded, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x68, 0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x68, 0x72, 0xd83c, 0xdde8, +0xd83c, 0xddfa, 0x3a, 0x63, 0x75, 0x3a, 0x63, 0x75, 0xd83c, 0xdde8, 0xd83c, 0xddfa, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x75, 0x3a, 0x63, 0x75, 0x66, +0x6c, 0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xddfc, 0x3a, 0x63, 0x77, 0x3a, 0x63, +0x77, 0xd83c, 0xdde8, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, +0x77, 0x3a, 0x63, 0x77, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xddfe, +0x3a, 0x63, 0x79, 0x3a, 0x63, 0x79, 0xd83c, 0xdde8, 0xd83c, 0xddfe, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x63, 0x79, 0x3a, 0x63, 0x79, 0x66, 0x6c, 0x61, +0x67, 0xd83c, 0xdde8, 0xd83c, 0xddff, 0x3a, 0x63, 0x7a, 0x3a, 0x63, 0x7a, 0xd83c, +0xdde8, 0xd83c, 0xddff, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x7a, 0x3a, +0x63, 0x7a, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde9, 0xd83c, 0xddf0, 0x3a, 0x64, +0x6b, 0x3a, 0x64, 0x6b, 0xd83c, 0xdde9, 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x64, 0x6b, 0x3a, 0x64, 0x6b, 0x66, 0x6c, 0x61, 0x67, 0xd83c, +0xdde9, 0xd83c, 0xddef, 0x3a, 0x64, 0x6a, 0x3a, 0x64, 0x6a, 0xd83c, 0xdde9, 0xd83c, +0xddef, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64, 0x6a, 0x3a, 0x64, 0x6a, +0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde9, 0xd83c, 0xddf2, 0x3a, 0x64, 0x6d, 0x3a, +0x64, 0x6d, 0xd83c, 0xdde9, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x64, 0x6d, 0x3a, 0x64, 0x6d, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde9, 0xd83c, +0xddf4, 0x3a, 0x64, 0x6f, 0x3a, 0x64, 0x6f, 0xd83c, 0xdde9, 0xd83c, 0xddf4, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64, 0x6f, 0x3a, 0x64, 0x6f, 0x66, 0x6c, +0x61, 0x67, 0xd83c, 0xddea, 0xd83c, 0xdde8, 0x3a, 0x65, 0x63, 0x3a, 0x65, 0x63, +0xd83c, 0xddea, 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x65, 0x63, +0x3a, 0x65, 0x63, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddea, 0xd83c, 0xddec, 0x3a, +0x65, 0x67, 0x3a, 0x65, 0x67, 0xd83c, 0xddea, 0xd83c, 0xddec, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x65, 0x67, 0x3a, 0x65, 0x67, 0x66, 0x6c, 0x61, 0x67, +0xd83c, 0xddf8, 0xd83c, 0xddfb, 0x3a, 0x73, 0x76, 0x3a, 0x73, 0x76, 0xd83c, 0xddf8, +0xd83c, 0xddfb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x76, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x73, 0x76, 0xd83c, 0xddec, 0xd83c, 0xddf6, 0x3a, 0x67, 0x71, +0x3a, 0x67, 0x71, 0xd83c, 0xddec, 0xd83c, 0xddf6, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x67, 0x71, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x71, 0xd83c, 0xddea, +0xd83c, 0xddf7, 0x3a, 0x65, 0x72, 0x3a, 0x65, 0x72, 0xd83c, 0xddea, 0xd83c, 0xddf7, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x65, 0x72, 0x3a, 0x65, 0x72, 0x66, +0x6c, 0x61, 0x67, 0xd83c, 0xddea, 0xd83c, 0xddea, 0x3a, 0x65, 0x65, 0x3a, 0x65, +0x65, 0xd83c, 0xddea, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x65, +0x65, 0x3a, 0x65, 0x65, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddea, 0xd83c, 0xddf9, +0x3a, 0x65, 0x74, 0x3a, 0x65, 0x74, 0xd83c, 0xddea, 0xd83c, 0xddf9, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x65, 0x74, 0x3a, 0x65, 0x74, 0x66, 0x6c, 0x61, +0x67, 0xd83c, 0xddea, 0xd83c, 0xddfa, 0x3a, 0x65, 0x75, 0x3a, 0x65, 0x75, 0xd83c, +0xddea, 0xd83c, 0xddfa, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x65, 0x75, 0x3a, +0x65, 0x75, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddeb, 0xd83c, 0xddf0, 0x3a, 0x66, +0x6b, 0x3a, 0x66, 0x6b, 0xd83c, 0xddeb, 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x66, 0x6b, 0x3a, 0x66, 0x6b, 0x66, 0x6c, 0x61, 0x67, 0xd83c, +0xddeb, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6f, 0x3a, 0x66, 0x6f, 0xd83c, 0xddeb, 0xd83c, +0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x66, 0x6f, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x66, 0x6f, 0xd83c, 0xddeb, 0xd83c, 0xddef, 0x3a, 0x66, 0x6a, 0x3a, +0x66, 0x6a, 0xd83c, 0xddeb, 0xd83c, 0xddef, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x66, 0x6a, 0x3a, 0x66, 0x6a, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddeb, 0xd83c, +0xddee, 0x3a, 0x66, 0x69, 0x3a, 0x66, 0x69, 0xd83c, 0xddeb, 0xd83c, 0xddee, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x66, 0x69, 0x3a, 0x66, 0x69, 0x66, 0x6c, +0x61, 0x67, 0xd83c, 0xddeb, 0xd83c, 0xddf7, 0x3a, 0x6d, 0x66, 0x3a, 0x6d, 0x66, +0xd83c, 0xddeb, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x66, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x66, 0xd83c, 0xddeb, 0xd83c, 0xddf7, 0x3a, +0x66, 0x72, 0x3a, 0x66, 0x72, 0xd83c, 0xddeb, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x66, 0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x66, 0x72, +0xd83c, 0xddeb, 0xd83c, 0xddf7, 0x3a, 0x63, 0x70, 0x3a, 0x63, 0x70, 0xd83c, 0xddeb, +0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x70, 0x3a, 0x63, +0x70, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddec, 0xd83c, 0xddeb, 0x3a, 0x67, 0x66, +0x3a, 0x67, 0x66, 0xd83c, 0xddec, 0xd83c, 0xddeb, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x67, 0x66, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x66, 0xd83c, 0xddf5, +0xd83c, 0xddeb, 0x3a, 0x70, 0x66, 0x3a, 0x70, 0x66, 0xd83c, 0xddf5, 0xd83c, 0xddeb, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x66, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x70, 0x66, 0xd83c, 0xddf9, 0xd83c, 0xddeb, 0x3a, 0x74, 0x66, 0x3a, 0x74, +0x66, 0xd83c, 0xddf9, 0xd83c, 0xddeb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, +0x66, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x66, 0xd83c, 0xddec, 0xd83c, 0xdde6, +0x3a, 0x67, 0x61, 0x3a, 0x67, 0x61, 0xd83c, 0xddec, 0xd83c, 0xdde6, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x67, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, +0x61, 0xd83c, 0xddec, 0xd83c, 0xddf2, 0x3a, 0x67, 0x6d, 0x3a, 0x67, 0x6d, 0xd83c, +0xddec, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x6d, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x67, 0x6d, 0xd83c, 0xddec, 0xd83c, 0xddea, 0x3a, 0x67, +0x65, 0x3a, 0x67, 0x65, 0xd83c, 0xddec, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x67, 0x65, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x65, 0xd83c, +0xdde9, 0xd83c, 0xddea, 0x3a, 0x64, 0x65, 0x3a, 0x64, 0x65, 0xd83c, 0xdde9, 0xd83c, +0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64, 0x65, 0x3a, 0x64, 0x65, +0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddec, 0xd83c, 0xdded, 0x3a, 0x67, 0x68, 0x3a, +0x67, 0x68, 0xd83c, 0xddec, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x67, 0x68, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x68, 0xd83c, 0xddec, 0xd83c, +0xddee, 0x3a, 0x67, 0x69, 0x3a, 0x67, 0x69, 0xd83c, 0xddec, 0xd83c, 0xddee, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x69, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x67, 0x69, 0xd83c, 0xddec, 0xd83c, 0xddf7, 0x3a, 0x67, 0x72, 0x3a, 0x67, 0x72, +0xd83c, 0xddec, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x72, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x72, 0xd83c, 0xddec, 0xd83c, 0xddf1, 0x3a, +0x67, 0x6c, 0x3a, 0x67, 0x6c, 0xd83c, 0xddec, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x67, 0x6c, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x6c, +0xd83c, 0xddec, 0xd83c, 0xdde9, 0x3a, 0x67, 0x64, 0x3a, 0x67, 0x64, 0xd83c, 0xddec, +0xd83c, 0xdde9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x64, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x67, 0x64, 0xd83c, 0xddec, 0xd83c, 0xddf5, 0x3a, 0x67, 0x70, +0x3a, 0x67, 0x70, 0xd83c, 0xddec, 0xd83c, 0xddf5, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x67, 0x70, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x70, 0xd83c, 0xddec, +0xd83c, 0xddfa, 0x3a, 0x67, 0x75, 0x3a, 0x67, 0x75, 0xd83c, 0xddec, 0xd83c, 0xddfa, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x75, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x67, 0x75, 0xd83c, 0xddec, 0xd83c, 0xddf9, 0x3a, 0x67, 0x74, 0x3a, 0x67, +0x74, 0xd83c, 0xddec, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, +0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x74, 0xd83c, 0xddec, 0xd83c, 0xddec, +0x3a, 0x67, 0x67, 0x3a, 0x67, 0x67, 0xd83c, 0xddec, 0xd83c, 0xddec, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x67, 0x67, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, +0x67, 0xd83c, 0xddec, 0xd83c, 0xddf3, 0x3a, 0x67, 0x6e, 0x3a, 0x67, 0x6e, 0xd83c, +0xddec, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x6e, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x67, 0x6e, 0xd83c, 0xddec, 0xd83c, 0xddfc, 0x3a, 0x67, +0x77, 0x3a, 0x67, 0x77, 0xd83c, 0xddec, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x67, 0x77, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x77, 0xd83c, +0xddec, 0xd83c, 0xddfe, 0x3a, 0x67, 0x79, 0x3a, 0x67, 0x79, 0xd83c, 0xddec, 0xd83c, +0xddfe, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x79, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x67, 0x79, 0xd83c, 0xdded, 0xd83c, 0xddf9, 0x3a, 0x68, 0x74, 0x3a, +0x68, 0x74, 0xd83c, 0xdded, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x68, 0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x68, 0x74, 0xd83c, 0xdded, 0xd83c, +0xddf3, 0x3a, 0x68, 0x6e, 0x3a, 0x68, 0x6e, 0xd83c, 0xdded, 0xd83c, 0xddf3, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x68, 0x6e, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x68, 0x6e, 0xd83c, 0xdded, 0xd83c, 0xddf0, 0x3a, 0x68, 0x6b, 0x3a, 0x68, 0x6b, +0xd83c, 0xdded, 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x68, 0x6b, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x68, 0x6b, 0xd83c, 0xdded, 0xd83c, 0xddfa, 0x3a, +0x68, 0x75, 0x3a, 0x68, 0x75, 0xd83c, 0xdded, 0xd83c, 0xddfa, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x68, 0x75, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x68, 0x75, +0xd83c, 0xddee, 0xd83c, 0xddf8, 0x3a, 0x69, 0x73, 0x3a, 0x69, 0x73, 0xd83c, 0xddee, +0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, 0x73, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x69, 0x73, 0xd83c, 0xddee, 0xd83c, 0xddf3, 0x3a, 0x69, 0x6e, +0x3a, 0x69, 0x6e, 0xd83c, 0xddee, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x69, 0x6e, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, 0x6e, 0xd83c, 0xddee, +0xd83c, 0xdde9, 0x3a, 0x69, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, +0x3a, 0x69, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0xd83c, 0xddee, +0xd83c, 0xdde9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, 0x64, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x69, 0x64, 0xd83c, 0xddee, 0xd83c, 0xddf7, 0x3a, 0x69, 0x72, +0x3a, 0x69, 0x72, 0xd83c, 0xddee, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x69, 0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, 0x72, 0xd83c, 0xddee, +0xd83c, 0xddf6, 0x3a, 0x69, 0x71, 0x3a, 0x69, 0x71, 0xd83c, 0xddee, 0xd83c, 0xddf6, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, 0x71, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x69, 0x71, 0xd83c, 0xddee, 0xd83c, 0xddea, 0x3a, 0x69, 0x65, 0x3a, 0x69, +0x65, 0xd83c, 0xddee, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, +0x65, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, 0x65, 0xd83c, 0xddee, 0xd83c, 0xddf2, +0x3a, 0x69, 0x6d, 0x3a, 0x69, 0x6d, 0xd83c, 0xddee, 0xd83c, 0xddf2, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x69, 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, +0x6d, 0xd83c, 0xddee, 0xd83c, 0xddf1, 0x3a, 0x69, 0x6c, 0x3a, 0x69, 0x6c, 0xd83c, +0xddee, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, 0x6c, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x69, 0x6c, 0xd83c, 0xddee, 0xd83c, 0xddf9, 0x3a, 0x69, +0x74, 0x3a, 0x69, 0x74, 0xd83c, 0xddee, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x69, 0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, 0x74, 0xd83c, +0xddef, 0xd83c, 0xddf2, 0x3a, 0x6a, 0x6d, 0x3a, 0x6a, 0x6d, 0xd83c, 0xddef, 0xd83c, +0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6a, 0x6d, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x6a, 0x6d, 0xd83c, 0xddef, 0xd83c, 0xddf5, 0x3a, 0x6a, 0x70, 0x3a, +0x6a, 0x70, 0xd83c, 0xddef, 0xd83c, 0xddf5, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x6a, 0x70, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6a, 0x70, 0xd83c, 0xdf8c, 0x3a, +0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, +0x73, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x64, 0x66, 0x6c, 0x61, +0x67, 0x73, 0xd83c, 0xddef, 0xd83c, 0xddea, 0x3a, 0x6a, 0x65, 0x3a, 0x6a, 0x65, +0xd83c, 0xddef, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6a, 0x65, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6a, 0x65, 0xd83c, 0xddef, 0xd83c, 0xddf4, 0x3a, +0x6a, 0x6f, 0x3a, 0x6a, 0x6f, 0xd83c, 0xddef, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x6a, 0x6f, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6a, 0x6f, +0xd83c, 0xddf0, 0xd83c, 0xddff, 0x3a, 0x6b, 0x7a, 0x3a, 0x6b, 0x7a, 0xd83c, 0xddf0, +0xd83c, 0xddff, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x7a, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x6b, 0x7a, 0xd83c, 0xddf0, 0xd83c, 0xddea, 0x3a, 0x6b, 0x65, +0x3a, 0x6b, 0x65, 0xd83c, 0xddf0, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x6b, 0x65, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6b, 0x65, 0xd83c, 0xddf0, +0xd83c, 0xddee, 0x3a, 0x6b, 0x69, 0x3a, 0x6b, 0x69, 0xd83c, 0xddf0, 0xd83c, 0xddee, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x69, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x6b, 0x69, 0xd83c, 0xddfd, 0xd83c, 0xddf0, 0x3a, 0x78, 0x6b, 0x3a, 0x78, +0x6b, 0xd83c, 0xddfd, 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x78, +0x6b, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x78, 0x6b, 0xd83c, 0xddf0, 0xd83c, 0xddfc, +0x3a, 0x6b, 0x77, 0x3a, 0x6b, 0x77, 0xd83c, 0xddf0, 0xd83c, 0xddfc, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x77, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6b, +0x77, 0xd83c, 0xddf0, 0xd83c, 0xddec, 0x3a, 0x6b, 0x67, 0x3a, 0x6b, 0x67, 0xd83c, +0xddf0, 0xd83c, 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x67, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x6b, 0x67, 0xd83c, 0xddf1, 0xd83c, 0xdde6, 0x3a, 0x6c, +0x61, 0x3a, 0x6c, 0x61, 0xd83c, 0xddf1, 0xd83c, 0xdde6, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x6c, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, 0x61, 0xd83c, +0xddf1, 0xd83c, 0xddfb, 0x3a, 0x6c, 0x76, 0x3a, 0x6c, 0x76, 0xd83c, 0xddf1, 0xd83c, +0xddfb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6c, 0x76, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x6c, 0x76, 0xd83c, 0xddf1, 0xd83c, 0xdde7, 0x3a, 0x6c, 0x62, 0x3a, +0x6c, 0x62, 0xd83c, 0xddf1, 0xd83c, 0xdde7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x6c, 0x62, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, 0x62, 0xd83c, 0xddf1, 0xd83c, +0xddf8, 0x3a, 0x6c, 0x73, 0x3a, 0x6c, 0x73, 0xd83c, 0xddf1, 0xd83c, 0xddf8, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6c, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x6c, 0x73, 0xd83c, 0xddf1, 0xd83c, 0xddf7, 0x3a, 0x6c, 0x72, 0x3a, 0x6c, 0x72, +0xd83c, 0xddf1, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6c, 0x72, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, 0x72, 0xd83c, 0xddf1, 0xd83c, 0xddfe, 0x3a, +0x6c, 0x79, 0x3a, 0x6c, 0x79, 0xd83c, 0xddf1, 0xd83c, 0xddfe, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x6c, 0x79, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, 0x79, +0xd83c, 0xddf1, 0xd83c, 0xddee, 0x3a, 0x6c, 0x69, 0x3a, 0x6c, 0x69, 0xd83c, 0xddf1, +0xd83c, 0xddee, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6c, 0x69, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x6c, 0x69, 0xd83c, 0xddf1, 0xd83c, 0xddf9, 0x3a, 0x6c, 0x74, +0x3a, 0x6c, 0x74, 0xd83c, 0xddf1, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x6c, 0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, 0x74, 0xd83c, 0xddf1, +0xd83c, 0xddfa, 0x3a, 0x6c, 0x75, 0x3a, 0x6c, 0x75, 0xd83c, 0xddf1, 0xd83c, 0xddfa, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6c, 0x75, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x6c, 0x75, 0xd83c, 0xddf2, 0xd83c, 0xddf4, 0x3a, 0x6d, 0x6f, 0x3a, 0x6d, +0x6f, 0xd83c, 0xddf2, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, +0x6f, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x6f, 0xd83c, 0xddf2, 0xd83c, 0xddf0, +0x3a, 0x6d, 0x6b, 0x3a, 0x6d, 0x6b, 0xd83c, 0xddf2, 0xd83c, 0xddf0, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x6b, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, +0x6b, 0xd83c, 0xddf2, 0xd83c, 0xddec, 0x3a, 0x6d, 0x67, 0x3a, 0x6d, 0x67, 0xd83c, +0xddf2, 0xd83c, 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x67, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x6d, 0x67, 0xd83c, 0xddf2, 0xd83c, 0xddfc, 0x3a, 0x6d, +0x77, 0x3a, 0x6d, 0x77, 0xd83c, 0xddf2, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x6d, 0x77, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x77, 0xd83c, +0xddf2, 0xd83c, 0xddfe, 0x3a, 0x6d, 0x79, 0x3a, 0x6d, 0x79, 0xd83c, 0xddf2, 0xd83c, +0xddfe, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x79, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x6d, 0x79, 0xd83c, 0xddf2, 0xd83c, 0xddfb, 0x3a, 0x6d, 0x76, 0x3a, +0x6d, 0x76, 0xd83c, 0xddf2, 0xd83c, 0xddfb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x6d, 0x76, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x76, 0xd83c, 0xddf2, 0xd83c, +0xddf1, 0x3a, 0x6d, 0x6c, 0x3a, 0x6d, 0x6c, 0xd83c, 0xddf2, 0xd83c, 0xddf1, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x6c, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x6d, 0x6c, 0xd83c, 0xddf2, 0xd83c, 0xddf9, 0x3a, 0x6d, 0x74, 0x3a, 0x6d, 0x74, +0xd83c, 0xddf2, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x74, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x74, 0xd83c, 0xddf2, 0xd83c, 0xdded, 0x3a, +0x6d, 0x68, 0x3a, 0x6d, 0x68, 0xd83c, 0xddf2, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x6d, 0x68, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x68, +0xd83c, 0xddf2, 0xd83c, 0xddf6, 0x3a, 0x6d, 0x71, 0x3a, 0x6d, 0x71, 0xd83c, 0xddf2, +0xd83c, 0xddf6, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x71, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x6d, 0x71, 0xd83c, 0xddf2, 0xd83c, 0xddf7, 0x3a, 0x6d, 0x72, +0x3a, 0x6d, 0x72, 0xd83c, 0xddf2, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x6d, 0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x72, 0xd83c, 0xddf2, +0xd83c, 0xddfa, 0x3a, 0x6d, 0x75, 0x3a, 0x6d, 0x75, 0xd83c, 0xddf2, 0xd83c, 0xddfa, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x75, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x6d, 0x75, 0xd83c, 0xddfe, 0xd83c, 0xddf9, 0x3a, 0x79, 0x74, 0x3a, 0x79, +0x74, 0xd83c, 0xddfe, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x79, +0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x79, 0x74, 0xd83c, 0xddf2, 0xd83c, 0xddfd, +0x3a, 0x6d, 0x78, 0x3a, 0x6d, 0x78, 0xd83c, 0xddf2, 0xd83c, 0xddfd, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x78, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, +0x78, 0xd83c, 0xddeb, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6d, 0x3a, 0x66, 0x6d, 0xd83c, +0xddeb, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x66, 0x6d, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x66, 0x6d, 0xd83c, 0xddf2, 0xd83c, 0xdde9, 0x3a, 0x6d, +0x64, 0x3a, 0x6d, 0x64, 0xd83c, 0xddf2, 0xd83c, 0xdde9, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x6d, 0x64, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x64, 0xd83c, +0xddf2, 0xd83c, 0xdde8, 0x3a, 0x6d, 0x63, 0x3a, 0x6d, 0x63, 0xd83c, 0xddf2, 0xd83c, +0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x63, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x6d, 0x63, 0xd83c, 0xddf2, 0xd83c, 0xddf3, 0x3a, 0x6d, 0x6e, 0x3a, +0x6d, 0x6e, 0xd83c, 0xddf2, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x6d, 0x6e, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x6e, 0xd83c, 0xddf2, 0xd83c, +0xddea, 0x3a, 0x6d, 0x65, 0x3a, 0x6d, 0x65, 0xd83c, 0xddf2, 0xd83c, 0xddea, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x65, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x6d, 0x65, 0xd83c, 0xddf2, 0xd83c, 0xddf8, 0x3a, 0x6d, 0x73, 0x3a, 0x6d, 0x73, +0xd83c, 0xddf2, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x73, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x73, 0xd83c, 0xddf2, 0xd83c, 0xdde6, 0x3a, +0x6d, 0x61, 0x3a, 0x6d, 0x61, 0xd83c, 0xddf2, 0xd83c, 0xdde6, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x6d, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x61, +0xd83c, 0xddf2, 0xd83c, 0xddff, 0x3a, 0x6d, 0x7a, 0x3a, 0x6d, 0x7a, 0xd83c, 0xddf2, +0xd83c, 0xddff, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x7a, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x6d, 0x7a, 0xd83c, 0xddf2, 0xd83c, 0xddf2, 0x3a, 0x6d, 0x6d, +0x3a, 0x6d, 0x6d, 0xd83c, 0xddf2, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x6d, 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x6d, 0xd83c, 0xddf3, +0xd83c, 0xdde6, 0x3a, 0x6e, 0x61, 0x3a, 0x6e, 0x61, 0xd83c, 0xddf3, 0xd83c, 0xdde6, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x61, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x6e, 0x61, 0xd83c, 0xddf3, 0xd83c, 0xddf7, 0x3a, 0x6e, 0x72, 0x3a, 0x6e, +0x72, 0xd83c, 0xddf3, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, +0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, 0x72, 0xd83c, 0xddf3, 0xd83c, 0xddf5, +0x3a, 0x6e, 0x70, 0x3a, 0x6e, 0x70, 0xd83c, 0xddf3, 0xd83c, 0xddf5, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x70, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, +0x70, 0xd83c, 0xddf3, 0xd83c, 0xddf1, 0x3a, 0x6e, 0x6c, 0x3a, 0x6e, 0x6c, 0xd83c, +0xddf3, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x6c, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x6e, 0x6c, 0xd83c, 0xddf3, 0xd83c, 0xdde8, 0x3a, 0x6e, +0x63, 0x3a, 0x6e, 0x63, 0xd83c, 0xddf3, 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x6e, 0x63, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, 0x63, 0xd83c, +0xddf3, 0xd83c, 0xddff, 0x3a, 0x6e, 0x7a, 0x3a, 0x6e, 0x7a, 0xd83c, 0xddf3, 0xd83c, +0xddff, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x7a, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x6e, 0x7a, 0xd83c, 0xddf3, 0xd83c, 0xddee, 0x3a, 0x6e, 0x69, 0x3a, +0x6e, 0x69, 0xd83c, 0xddf3, 0xd83c, 0xddee, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x6e, 0x69, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, 0x69, 0xd83c, 0xddf3, 0xd83c, +0xddea, 0x3a, 0x6e, 0x65, 0x3a, 0x6e, 0x65, 0xd83c, 0xddf3, 0xd83c, 0xddea, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x65, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x6e, 0x65, 0xd83c, 0xddf3, 0xd83c, 0xddec, 0x3a, 0x6e, 0x69, 0x67, 0x65, 0x72, +0x69, 0x61, 0x3a, 0x6e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0xd83c, 0xddf3, +0xd83c, 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x67, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x6e, 0x67, 0xd83c, 0xddf3, 0xd83c, 0xddfa, 0x3a, 0x6e, 0x75, +0x3a, 0x6e, 0x75, 0xd83c, 0xddf3, 0xd83c, 0xddfa, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x6e, 0x75, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, 0x75, 0xd83c, 0xddf3, +0xd83c, 0xddeb, 0x3a, 0x6e, 0x66, 0x3a, 0x6e, 0x66, 0xd83c, 0xddf3, 0xd83c, 0xddeb, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x66, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x6e, 0x66, 0xd83c, 0xddf0, 0xd83c, 0xddf5, 0x3a, 0x6b, 0x70, 0x3a, 0x6b, +0x70, 0xd83c, 0xddf0, 0xd83c, 0xddf5, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, +0x70, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6b, 0x70, 0xd83c, 0xddf2, 0xd83c, 0xddf5, +0x3a, 0x6d, 0x70, 0x3a, 0x6d, 0x70, 0xd83c, 0xddf2, 0xd83c, 0xddf5, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x70, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, +0x70, 0xd83c, 0xddf3, 0xd83c, 0xddf4, 0x3a, 0x73, 0x6a, 0x3a, 0x73, 0x6a, 0xd83c, +0xddf3, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x6a, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x73, 0x6a, 0xd83c, 0xddf3, 0xd83c, 0xddf4, 0x3a, 0x6e, +0x6f, 0x3a, 0x6e, 0x6f, 0xd83c, 0xddf3, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x6e, 0x6f, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, 0x6f, 0xd83c, +0xddf3, 0xd83c, 0xddf4, 0x3a, 0x62, 0x76, 0x3a, 0x62, 0x76, 0xd83c, 0xddf3, 0xd83c, +0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x76, 0x3a, 0x62, 0x76, +0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddf4, 0xd83c, 0xddf2, 0x3a, 0x6f, 0x6d, 0x3a, +0x6f, 0x6d, 0xd83c, 0xddf4, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x6f, 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6f, 0x6d, 0xd83c, 0xddf5, 0xd83c, +0xddf0, 0x3a, 0x70, 0x6b, 0x3a, 0x70, 0x6b, 0xd83c, 0xddf5, 0xd83c, 0xddf0, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x6b, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x70, 0x6b, 0xd83c, 0xddf5, 0xd83c, 0xddfc, 0x3a, 0x70, 0x77, 0x3a, 0x70, 0x77, +0xd83c, 0xddf5, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x77, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, 0x77, 0xd83c, 0xddf5, 0xd83c, 0xddf8, 0x3a, +0x70, 0x73, 0x3a, 0x70, 0x73, 0xd83c, 0xddf5, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x70, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, 0x73, +0xd83c, 0xddf5, 0xd83c, 0xdde6, 0x3a, 0x70, 0x61, 0x3a, 0x70, 0x61, 0xd83c, 0xddf5, +0xd83c, 0xdde6, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x61, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x70, 0x61, 0xd83c, 0xddf5, 0xd83c, 0xddec, 0x3a, 0x70, 0x67, +0x3a, 0x70, 0x67, 0xd83c, 0xddf5, 0xd83c, 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x70, 0x67, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, 0x67, 0xd83c, 0xddf5, +0xd83c, 0xddfe, 0x3a, 0x70, 0x79, 0x3a, 0x70, 0x79, 0xd83c, 0xddf5, 0xd83c, 0xddfe, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x79, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x70, 0x79, 0xd83c, 0xddf5, 0xd83c, 0xddea, 0x3a, 0x70, 0x65, 0x3a, 0x70, +0x65, 0xd83c, 0xddf5, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, +0x65, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, 0x65, 0xd83c, 0xddf5, 0xd83c, 0xdded, +0x3a, 0x70, 0x68, 0x3a, 0x70, 0x68, 0xd83c, 0xddf5, 0xd83c, 0xdded, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x70, 0x68, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, +0x68, 0xd83c, 0xddf5, 0xd83c, 0xddf3, 0x3a, 0x70, 0x6e, 0x3a, 0x70, 0x6e, 0xd83c, +0xddf5, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x6e, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x70, 0x6e, 0xd83c, 0xddf5, 0xd83c, 0xddf1, 0x3a, 0x70, +0x6c, 0x3a, 0x70, 0x6c, 0xd83c, 0xddf5, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x70, 0x6c, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, 0x6c, 0xd83c, +0xddf5, 0xd83c, 0xddf9, 0x3a, 0x70, 0x74, 0x3a, 0x70, 0x74, 0xd83c, 0xddf5, 0xd83c, +0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x74, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x70, 0x74, 0xd83c, 0xddf5, 0xd83c, 0xddf7, 0x3a, 0x70, 0x72, 0x3a, +0x70, 0x72, 0xd83c, 0xddf5, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x70, 0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, 0x72, 0xd83c, 0xddf6, 0xd83c, +0xdde6, 0x3a, 0x71, 0x61, 0x3a, 0x71, 0x61, 0xd83c, 0xddf6, 0xd83c, 0xdde6, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x71, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x71, 0x61, 0xd83c, 0xddf7, 0xd83c, 0xddea, 0x3a, 0x72, 0x65, 0x3a, 0x72, 0x65, +0xd83c, 0xddf7, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x72, 0x65, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x72, 0x65, 0xd83c, 0xddf7, 0xd83c, 0xddf4, 0x3a, +0x72, 0x6f, 0x3a, 0x72, 0x6f, 0xd83c, 0xddf7, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x72, 0x6f, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x72, 0x6f, +0xd83c, 0xddf7, 0xd83c, 0xddfa, 0x3a, 0x72, 0x75, 0x3a, 0x72, 0x75, 0xd83c, 0xddf7, +0xd83c, 0xddfa, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x72, 0x75, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x72, 0x75, 0xd83c, 0xddf7, 0xd83c, 0xddfc, 0x3a, 0x72, 0x77, +0x3a, 0x72, 0x77, 0xd83c, 0xddf7, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x72, 0x77, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x72, 0x77, 0xd83c, 0xddfc, +0xd83c, 0xddf8, 0x3a, 0x77, 0x73, 0x3a, 0x77, 0x73, 0xd83c, 0xddfc, 0xd83c, 0xddf8, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x77, 0x73, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x77, 0x73, 0xd83c, 0xddf8, 0xd83c, 0xddf2, 0x3a, 0x73, 0x6d, 0x3a, 0x73, +0x6d, 0xd83c, 0xddf8, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, +0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x6d, 0xd83c, 0xddf8, 0xd83c, 0xddf9, +0x3a, 0x73, 0x74, 0x3a, 0x73, 0x74, 0xd83c, 0xddf8, 0xd83c, 0xddf9, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x73, 0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, +0x74, 0xd83c, 0xddf8, 0xd83c, 0xdde6, 0x3a, 0x73, 0x61, 0x75, 0x64, 0x69, 0x3a, +0x73, 0x61, 0x75, 0x64, 0x69, 0xd83c, 0xddf8, 0xd83c, 0xdde6, 0x3a, 0x73, 0x61, +0x75, 0x64, 0x69, 0x61, 0x72, 0x61, 0x62, 0x69, 0x61, 0x3a, 0x73, 0x61, +0x75, 0x64, 0x69, 0x61, 0x72, 0x61, 0x62, 0x69, 0x61, 0xd83c, 0xddf8, 0xd83c, +0xdde6, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x61, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x73, 0x61, 0xd83c, 0xddf8, 0xd83c, 0xddf3, 0x3a, 0x73, 0x6e, 0x3a, +0x73, 0x6e, 0xd83c, 0xddf8, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x73, 0x6e, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x6e, 0xd83c, 0xddf7, 0xd83c, +0xddf8, 0x3a, 0x72, 0x73, 0x3a, 0x72, 0x73, 0xd83c, 0xddf7, 0xd83c, 0xddf8, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x72, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x72, 0x73, 0xd83c, 0xddf8, 0xd83c, 0xdde8, 0x3a, 0x73, 0x63, 0x3a, 0x73, 0x63, +0xd83c, 0xddf8, 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x63, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x63, 0xd83c, 0xddf8, 0xd83c, 0xddf1, 0x3a, +0x73, 0x6c, 0x3a, 0x73, 0x6c, 0xd83c, 0xddf8, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x73, 0x6c, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x6c, +0xd83c, 0xddf8, 0xd83c, 0xddec, 0x3a, 0x73, 0x67, 0x3a, 0x73, 0x67, 0xd83c, 0xddf8, +0xd83c, 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x67, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x73, 0x67, 0xd83c, 0xddf8, 0xd83c, 0xddfd, 0x3a, 0x73, 0x78, +0x3a, 0x73, 0x78, 0xd83c, 0xddf8, 0xd83c, 0xddfd, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x73, 0x78, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x78, 0xd83c, 0xddf8, +0xd83c, 0xddf0, 0x3a, 0x73, 0x6b, 0x3a, 0x73, 0x6b, 0xd83c, 0xddf8, 0xd83c, 0xddf0, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x6b, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x73, 0x6b, 0xd83c, 0xddf8, 0xd83c, 0xddee, 0x3a, 0x73, 0x69, 0x3a, 0x73, +0x69, 0xd83c, 0xddf8, 0xd83c, 0xddee, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, +0x69, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x69, 0xd83c, 0xddec, 0xd83c, 0xddf8, +0x3a, 0x67, 0x73, 0x3a, 0x67, 0x73, 0xd83c, 0xddec, 0xd83c, 0xddf8, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x67, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, +0x73, 0xd83c, 0xddf8, 0xd83c, 0xdde7, 0x3a, 0x73, 0x62, 0x3a, 0x73, 0x62, 0xd83c, +0xddf8, 0xd83c, 0xdde7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x62, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x73, 0x62, 0xd83c, 0xddf8, 0xd83c, 0xddf4, 0x3a, 0x73, +0x6f, 0x3a, 0x73, 0x6f, 0xd83c, 0xddf8, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x73, 0x6f, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x6f, 0xd83c, +0xddff, 0xd83c, 0xdde6, 0x3a, 0x7a, 0x61, 0x3a, 0x7a, 0x61, 0xd83c, 0xddff, 0xd83c, +0xdde6, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x7a, 0x61, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x7a, 0x61, 0xd83c, 0xddf0, 0xd83c, 0xddf7, 0x3a, 0x6b, 0x72, 0x3a, +0x6b, 0x72, 0xd83c, 0xddf0, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x6b, 0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6b, 0x72, 0xd83c, 0xddf8, 0xd83c, +0xddf8, 0x3a, 0x73, 0x73, 0x3a, 0x73, 0x73, 0xd83c, 0xddf8, 0xd83c, 0xddf8, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x73, 0x73, 0xd83c, 0xddea, 0xd83c, 0xddf8, 0x3a, 0x65, 0x73, 0x3a, 0x65, 0x73, +0xd83c, 0xddea, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x65, 0x73, +0x3a, 0x65, 0x73, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddea, 0xd83c, 0xddf8, 0x3a, +0x65, 0x61, 0x3a, 0x65, 0x61, 0xd83c, 0xddea, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x65, 0x61, 0x3a, 0x65, 0x61, 0x66, 0x6c, 0x61, 0x67, +0xd83c, 0xddf1, 0xd83c, 0xddf0, 0x3a, 0x6c, 0x6b, 0x3a, 0x6c, 0x6b, 0xd83c, 0xddf1, +0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6c, 0x6b, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x6c, 0x6b, 0xd83c, 0xdde7, 0xd83c, 0xddf1, 0x3a, 0x62, 0x6c, +0x3a, 0x62, 0x6c, 0xd83c, 0xdde7, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x62, 0x6c, 0x3a, 0x62, 0x6c, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddf8, +0xd83c, 0xdded, 0x3a, 0x74, 0x61, 0x3a, 0x74, 0x61, 0xd83c, 0xddf8, 0xd83c, 0xdded, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x61, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x74, 0x61, 0xd83c, 0xddf8, 0xd83c, 0xdded, 0x3a, 0x73, 0x68, 0x3a, 0x73, +0x68, 0xd83c, 0xddf8, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, +0x68, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x68, 0xd83c, 0xddf8, 0xd83c, 0xdded, +0x3a, 0x61, 0x63, 0x3a, 0x61, 0x63, 0xd83c, 0xddf8, 0xd83c, 0xdded, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x61, 0x63, 0x3a, 0x61, 0x63, 0x66, 0x6c, 0x61, +0x67, 0xd83c, 0xddf0, 0xd83c, 0xddf3, 0x3a, 0x6b, 0x6e, 0x3a, 0x6b, 0x6e, 0xd83c, +0xddf0, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x6e, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x6b, 0x6e, 0xd83c, 0xddf1, 0xd83c, 0xdde8, 0x3a, 0x6c, +0x63, 0x3a, 0x6c, 0x63, 0xd83c, 0xddf1, 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x6c, 0x63, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, 0x63, 0xd83c, +0xddf5, 0xd83c, 0xddf2, 0x3a, 0x70, 0x6d, 0x3a, 0x70, 0x6d, 0xd83c, 0xddf5, 0xd83c, +0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x6d, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x70, 0x6d, 0xd83c, 0xddfb, 0xd83c, 0xdde8, 0x3a, 0x76, 0x63, 0x3a, +0x76, 0x63, 0xd83c, 0xddfb, 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x76, 0x63, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x76, 0x63, 0xd83c, 0xddf8, 0xd83c, +0xdde9, 0x3a, 0x73, 0x64, 0x3a, 0x73, 0x64, 0xd83c, 0xddf8, 0xd83c, 0xdde9, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x64, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x73, 0x64, 0xd83c, 0xddf8, 0xd83c, 0xddf7, 0x3a, 0x73, 0x72, 0x3a, 0x73, 0x72, +0xd83c, 0xddf8, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x72, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x72, 0xd83c, 0xddf8, 0xd83c, 0xddff, 0x3a, +0x73, 0x7a, 0x3a, 0x73, 0x7a, 0xd83c, 0xddf8, 0xd83c, 0xddff, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x73, 0x7a, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x7a, +0xd83c, 0xddf8, 0xd83c, 0xddea, 0x3a, 0x73, 0x65, 0x3a, 0x73, 0x65, 0xd83c, 0xddf8, +0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x65, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x73, 0x65, 0xd83c, 0xdde8, 0xd83c, 0xdded, 0x3a, 0x63, 0x68, +0x3a, 0x63, 0x68, 0xd83c, 0xdde8, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x63, 0x68, 0x3a, 0x63, 0x68, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddf8, +0xd83c, 0xddfe, 0x3a, 0x73, 0x79, 0x3a, 0x73, 0x79, 0xd83c, 0xddf8, 0xd83c, 0xddfe, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x79, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x73, 0x79, 0xd83c, 0xddf9, 0xd83c, 0xddfc, 0x3a, 0x74, 0x77, 0x3a, 0x74, +0x77, 0xd83c, 0xddf9, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, +0x77, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x77, 0xd83c, 0xddf9, 0xd83c, 0xddef, +0x3a, 0x74, 0x6a, 0x3a, 0x74, 0x6a, 0xd83c, 0xddf9, 0xd83c, 0xddef, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x74, 0x6a, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, +0x6a, 0xd83c, 0xddf9, 0xd83c, 0xddff, 0x3a, 0x74, 0x7a, 0x3a, 0x74, 0x7a, 0xd83c, +0xddf9, 0xd83c, 0xddff, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x7a, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x74, 0x7a, 0xd83c, 0xddf9, 0xd83c, 0xdded, 0x3a, 0x74, +0x68, 0x3a, 0x74, 0x68, 0xd83c, 0xddf9, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x74, 0x68, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x68, 0xd83c, +0xddf9, 0xd83c, 0xddf1, 0x3a, 0x74, 0x6c, 0x3a, 0x74, 0x6c, 0xd83c, 0xddf9, 0xd83c, +0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x6c, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x74, 0x6c, 0xd83c, 0xddf9, 0xd83c, 0xddec, 0x3a, 0x74, 0x67, 0x3a, +0x74, 0x67, 0xd83c, 0xddf9, 0xd83c, 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x74, 0x67, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x67, 0xd83c, 0xddf9, 0xd83c, +0xddf0, 0x3a, 0x74, 0x6b, 0x3a, 0x74, 0x6b, 0xd83c, 0xddf9, 0xd83c, 0xddf0, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x6b, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x74, 0x6b, 0xd83c, 0xddf9, 0xd83c, 0xddf4, 0x3a, 0x74, 0x6f, 0x3a, 0x74, 0x6f, +0xd83c, 0xddf9, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x6f, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x6f, 0xd83c, 0xddf9, 0xd83c, 0xddf9, 0x3a, +0x74, 0x74, 0x3a, 0x74, 0x74, 0xd83c, 0xddf9, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x74, 0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x74, +0xd83c, 0xddf9, 0xd83c, 0xddf3, 0x3a, 0x74, 0x6e, 0x3a, 0x74, 0x6e, 0xd83c, 0xddf9, +0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x6e, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x74, 0x6e, 0xd83c, 0xddf9, 0xd83c, 0xddf7, 0x3a, 0x74, 0x72, +0x3a, 0x74, 0x72, 0xd83c, 0xddf9, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x74, 0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x72, 0xd83c, 0xddf9, +0xd83c, 0xddf2, 0x3a, 0x74, 0x75, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x69, 0x73, +0x74, 0x61, 0x6e, 0x3a, 0x74, 0x75, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x69, +0x73, 0x74, 0x61, 0x6e, 0xd83c, 0xddf9, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x74, 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x6d, 0xd83c, +0xddf9, 0xd83c, 0xdde8, 0x3a, 0x74, 0x63, 0x3a, 0x74, 0x63, 0xd83c, 0xddf9, 0xd83c, +0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x63, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x74, 0x63, 0xd83c, 0xddf9, 0xd83c, 0xddfb, 0x3a, 0x74, 0x75, 0x76, +0x61, 0x6c, 0x75, 0x3a, 0x74, 0x75, 0x76, 0x61, 0x6c, 0x75, 0xd83c, 0xddf9, +0xd83c, 0xddfb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x76, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x74, 0x76, 0xd83c, 0xddfb, 0xd83c, 0xddee, 0x3a, 0x76, 0x69, +0x3a, 0x76, 0x69, 0xd83c, 0xddfb, 0xd83c, 0xddee, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x76, 0x69, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x76, 0x69, 0xd83c, 0xddfa, +0xd83c, 0xddec, 0x3a, 0x75, 0x67, 0x3a, 0x75, 0x67, 0xd83c, 0xddfa, 0xd83c, 0xddec, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x75, 0x67, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x75, 0x67, 0xd83c, 0xddfa, 0xd83c, 0xdde6, 0x3a, 0x75, 0x61, 0x3a, 0x75, +0x61, 0xd83c, 0xddfa, 0xd83c, 0xdde6, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x75, +0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x75, 0x61, 0xd83c, 0xdde6, 0xd83c, 0xddea, +0x3a, 0x61, 0x65, 0x3a, 0x61, 0x65, 0xd83c, 0xdde6, 0xd83c, 0xddea, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x61, 0x65, 0x3a, 0x61, 0x65, 0x66, 0x6c, 0x61, +0x67, 0xd83c, 0xddec, 0xd83c, 0xdde7, 0x3a, 0x67, 0x62, 0x3a, 0x67, 0x62, 0xd83c, +0xddec, 0xd83c, 0xdde7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x62, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x67, 0x62, 0xd83c, 0xddfa, 0xd83c, 0xddf8, 0x3a, 0x75, +0x73, 0x3a, 0x75, 0x73, 0xd83c, 0xddfa, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x75, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x75, 0x73, 0xd83c, +0xddfa, 0xd83c, 0xddf8, 0x3a, 0x75, 0x6d, 0x3a, 0x75, 0x6d, 0xd83c, 0xddfa, 0xd83c, +0xddf8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x75, 0x6d, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x75, 0x6d, 0xd83c, 0xddfa, 0xd83c, 0xddfe, 0x3a, 0x75, 0x79, 0x3a, +0x75, 0x79, 0xd83c, 0xddfa, 0xd83c, 0xddfe, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, +0x75, 0x79, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x75, 0x79, 0xd83c, 0xddfa, 0xd83c, +0xddff, 0x3a, 0x75, 0x7a, 0x3a, 0x75, 0x7a, 0xd83c, 0xddfa, 0xd83c, 0xddff, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x5f, 0x75, 0x7a, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x75, 0x7a, 0xd83c, 0xddfb, 0xd83c, 0xddfa, 0x3a, 0x76, 0x75, 0x3a, 0x76, 0x75, +0xd83c, 0xddfb, 0xd83c, 0xddfa, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76, 0x75, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x76, 0x75, 0xd83c, 0xddfb, 0xd83c, 0xdde6, 0x3a, +0x76, 0x61, 0x3a, 0x76, 0x61, 0xd83c, 0xddfb, 0xd83c, 0xdde6, 0x3a, 0x66, 0x6c, +0x61, 0x67, 0x5f, 0x76, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x76, 0x61, +0xd83c, 0xddfb, 0xd83c, 0xddea, 0x3a, 0x76, 0x65, 0x3a, 0x76, 0x65, 0xd83c, 0xddfb, +0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76, 0x65, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x76, 0x65, 0xd83c, 0xddfb, 0xd83c, 0xddf3, 0x3a, 0x76, 0x6e, +0x3a, 0x76, 0x6e, 0xd83c, 0xddfb, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, +0x5f, 0x76, 0x6e, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x76, 0x6e, 0xd83c, 0xddfc, +0xd83c, 0xddeb, 0x3a, 0x77, 0x66, 0x3a, 0x77, 0x66, 0xd83c, 0xddfc, 0xd83c, 0xddeb, +0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x77, 0x66, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x77, 0x66, 0xd83c, 0xddea, 0xd83c, 0xdded, 0x3a, 0x65, 0x68, 0x3a, 0x65, +0x68, 0xd83c, 0xddea, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x65, +0x68, 0x3a, 0x65, 0x68, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddfe, 0xd83c, 0xddea, +0x3a, 0x79, 0x65, 0x3a, 0x79, 0x65, 0xd83c, 0xddfe, 0xd83c, 0xddea, 0x3a, 0x66, +0x6c, 0x61, 0x67, 0x5f, 0x79, 0x65, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x79, +0x65, 0xd83c, 0xddff, 0xd83c, 0xddf2, 0x3a, 0x7a, 0x6d, 0x3a, 0x7a, 0x6d, 0xd83c, +0xddff, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x7a, 0x6d, 0x3a, +0x66, 0x6c, 0x61, 0x67, 0x7a, 0x6d, 0xd83c, 0xddff, 0xd83c, 0xddfc, 0x3a, 0x7a, +0x77, 0x3a, 0x7a, 0x77, 0xd83c, 0xddff, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, +0x67, 0x5f, 0x7a, 0x77, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x7a, 0x77 }; + +const small ReplacementWordLengths[] = { +8, 6, 5, 4, 9, 8, 5, 5, 3, 5, 8, 2, +7, 3, 4, 7, 5, 8, 4, 8, 7, 6, 5, 4, +4, 6, 4, 6, 4, 8, 4, 5, 5, 7, 7, 4, +7, 7, 6, 4, 7, 3, 3, 3, 5, 6, 7, 6, +4, 3, 5, 6, 3, 5, 6, 4, 5, 5, 5, 5, +4, 7, 7, 4, 4, 4, 10, 5, 4, 5, 6, 4, +3, 4, 6, 5, 8, 12, 7, 7, 8, 4, 8, 8, +5, 6, 4, 8, 5, 9, 9, 10, 4, 5, 5, 7, +5, 4, 5, 2, 4, 7, 14, 6, 8, 9, 5, 4, +10, 5, 4, 7, 6, 7, 4, 5, 3, 12, 8, 5, +8, 4, 3, 5, 6, 8, 4, 4, 7, 4, 4, 7, +3, 4, 8, 8, 4, 4, 5, 9, 4, 5, 6, 5, +6, 4, 4, 9, 6, 4, 8, 4, 4, 11, 4, 4, +11, 7, 4, 4, 4, 7, 4, 3, 7, 3, 8, 4, +6, 8, 3, 6, 4, 4, 5, 8, 5, 3, 10, 5, +10, 5, 5, 7, 5, 4, 5, 5, 4, 7, 1, 3, +6, 3, 5, 3, 3, 3, 4, 5, 3, 5, 3, 7, +3, 6, 3, 6, 4, 3, 7, 5, 4, 5, 6, 4, +4, 5, 7, 9, 4, 7, 2, 8, 7, 9, 2, 10, +5, 4, 4, 4, 6, 4, 4, 4, 5, 6, 4, 5, +3, 7, 6, 4, 5, 6, 4, 7, 7, 1, 5, 2, +4, 3, 5, 4, 2, 4, 5, 5, 5, 1, 5, 2, +4, 5, 5, 2, 4, 6, 4, 4, 2, 4, 4, 2, +6, 7, 4, 6, 7, 4, 4, 7, 3, 7, 7, 4, +6, 4, 6, 4, 4, 6, 4, 4, 4, 2, 4, 2, +6, 8, 6, 4, 6, 8, 4, 6, 6, 4, 7, 6, +4, 4, 4, 8, 4, 4, 6, 3, 4, 10, 3, 4, +4, 2, 10, 8, 4, 8, 4, 2, 10, 5, 2, 10, +4, 3, 4, 3, 5, 5, 6, 5, 5, 6, 3, 5, +4, 6, 4, 5, 6, 6, 3, 5, 7, 5, 5, 3, +3, 3, 2, 4, 3, 7, 3, 4, 6, 7, 5, 3, +6, 7, 3, 6, 4, 6, 6, 7, 7, 6, 5, 3, +7, 6, 3, 7, 6, 12, 5, 6, 12, 3, 6, 12, +6, 5, 5, 5, 3, 9, 5, 9, 5, 9, 3, 2, +6, 3, 3, 9, 6, 5, 6, 6, 3, 6, 6, 5, +6, 3, 4, 5, 4, 3, 7, 5, 3, 7, 6, 5, +3, 6, 7, 5, 3, 7, 7, 5, 6, 7, 3, 6, +12, 5, 3, 12, 6, 5, 6, 3, 6, 6, 8, 5, +3, 8, 9, 5, 3, 9, 6, 5, 6, 3, 11, 5, +11, 3, 5, 5, 3, 5, 9, 5, 9, 3, 5, 5, +5, 3, 9, 6, 5, 3, 5, 8, 6, 5, 4, 4, +2, 3, 6, 5, 9, 5, 8, 5, 6, 5, 6, 3, +3, 6, 6, 4, 7, 5, 4, 11, 6, 4, 6, 7, +4, 3, 7, 9, 2, 5, 4, 2, 9, 2, 6, 9, +3, 2, 9, 2, 5, 2, 5, 9, 2, 6, 9, 3, +2, 4, 7, 5, 4, 7, 4, 6, 7, 4, 3, 7, +11, 5, 11, 3, 8, 4, 4, 11, 6, 9, 5, 5, +6, 9, 3, 9, 7, 5, 4, 6, 7, 4, 6, 7, +3, 7, 8, 5, 8, 6, 8, 3, 7, 7, 5, 7, +7, 7, 6, 7, 7, 3, 4, 7, 7, 5, 7, 7, +7, 6, 4, 7, 3, 7, 8, 2, 10, 3, 4, 6, +6, 4, 7, 3, 5, 4, 8, 4, 5, 7, 5, 4, +8, 6, 4, 5, 4, 3, 8, 4, 7, 5, 3, 7, +7, 6, 7, 7, 5, 3, 7, 6, 6, 7, 6, 5, +7, 3, 5, 5, 7, 3, 3, 6, 5, 4, 6, 5, +3, 4, 5, 6, 5, 4, 2, 6, 2, 6, 5, 2, +4, 6, 2, 10, 4, 3, 5, 10, 2, 4, 2, 10, +2, 4, 2, 6, 3, 6, 3, 5, 6, 3, 6, 4, +6, 4, 6, 4, 6, 3, 6, 3, 6, 4, 6, 4, +6, 4, 6, 3, 6, 3, 6, 4, 6, 4, 6, 4, +3, 6, 5, 6, 4, 5, 3, 6, 4, 5, 3, 3, +6, 5, 6, 4, 4, 5, 3, 6, 3, 6, 4, 3, +3, 6, 4, 3, 3, 3, 6, 3, 6, 4, 4, 3, +7, 6, 5, 5, 7, 5, 6, 6, 4, 4, 6, 4, +4, 4, 8, 4, 3, 6, 6, 5, 6, 5, 5, 6, +5, 4, 5, 6, 4, 7, 6, 5, 5, 7, 9, 10, +4, 10, 6, 8, 9, 3, 3, 5, 7, 6, 4, 3, +3, 4, 4, 5, 5, 5, 4, 4, 4, 3, 3, 4, +3, 4, 4, 6, 4, 2, 3, 4, 4, 2, 4, 2, +5, 6, 7, 7, 4, 4, 5, 5, 8, 5, 7, 4, +5, 3, 3, 4, 4, 5, 4, 7, 7, 3, 3, 9, +5, 5, 6, 3, 6, 6, 3, 6, 5, 6, 8, 4, +5, 7, 6, 4, 8, 4, 8, 7, 5, 5, 6, 9, +7, 6, 7, 5, 2, 4, 4, 5, 9, 5, 8, 10, +5, 7, 9, 4, 4, 3, 5, 4, 6, 4, 7, 6, +4, 2, 5, 4, 7, 6, 3, 8, 3, 6, 4, 6, +6, 4, 6, 9, 4, 9, 4, 9, 4, 4, 4, 8, +4, 8, 6, 4, 4, 6, 8, 4, 6, 6, 4, 4, +5, 8, 3, 2, 4, 7, 5, 4, 6, 6, 4, 6, +9, 7, 7, 6, 8, 8, 5, 6, 5, 4, 5, 4, +4, 7, 4, 6, 4, 4, 7, 8, 4, 6, 4, 3, +8, 4, 6, 5, 4, 7, 7, 4, 6, 4, 4, 3, +4, 4, 4, 4, 4, 4, 3, 4, 4, 5, 4, 7, +4, 4, 4, 4, 7, 4, 8, 4, 5, 4, 5, 8, +3, 5, 4, 4, 5, 5, 5, 5, 3, 5, 4, 5, +5, 3, 5, 6, 5, 6, 5, 3, 5, 5, 3, 5, +6, 5, 4, 3, 5, 4, 5, 4, 3, 5, 7, 5, +5, 4, 4, 5, 4, 3, 5, 4, 7, 5, 4, 7, +5, 9, 4, 5, 9, 5, 4, 4, 5, 4, 8, 7, +9, 7, 4, 4, 4, 5, 7, 4, 5, 7, 3, 5, +7, 5, 5, 8, 5, 5, 5, 4, 9, 5, 6, 10, +6, 10, 5, 8, 5, 9, 9, 4, 7, 6, 8, 8, +6, 4, 3, 6, 6, 6, 5, 8, 6, 7, 7, 5, +3, 9, 5, 8, 5, 5, 6, 6, 5, 6, 3, 7, +5, 8, 5, 6, 3, 7, 4, 4, 2, 5, 3, 3, +6, 9, 5, 4, 7, 9, 7, 4, 7, 5, 5, 5, +6, 4, 2, 3, 7, 9, 5, 4, 4, 4, 5, 5, +5, 4, 4, 4, 7, 4, 4, 5, 3, 6, 5, 3, +8, 4, 8, 4, 7, 7, 8, 5, 3, 9, 7, 8, +6, 5, 4, 2, 4, 4, 6, 6, 3, 4, 4, 5, +8, 5, 9, 5, 5, 4, 6, 5, 7, 8, 5, 8, +6, 4, 7, 4, 9, 5, 3, 4, 5, 3, 4, 5, +5, 4, 4, 5, 5, 6, 10, 8, 8, 6, 10, 8, +5, 5, 5, 6, 4, 4, 9, 4, 3, 4, 6, 5, +6, 4, 3, 7, 7, 4, 4, 7, 3, 5, 3, 3, +4, 7, 4, 6, 6, 6, 5, 6, 7, 4, 7, 7, +3, 5, 3, 5, 11, 7, 7, 5, 7, 3, 7, 6, +6, 6, 7, 6, 7, 7, 6, 7, 6, 5, 9, 3, +9, 9, 9, 6, 9, 12, 5, 12, 3, 9, 9, 5, +6, 4, 8, 5, 4, 8, 3, 4, 6, 4, 10, 6, +4, 8, 6, 8, 7, 5, 8, 8, 6, 7, 8, 3, +7, 7, 5, 7, 3, 6, 7, 6, 7, 5, 3, 7, +6, 6, 7, 8, 5, 3, 8, 7, 6, 8, 7, 4, +5, 5, 3, 7, 4, 5, 4, 5, 6, 7, 4, 5, +4, 6, 5, 4, 3, 6, 7, 4, 6, 6, 5, 6, +6, 5, 6, 3, 9, 6, 6, 6, 8, 5, 6, 3, +8, 9, 8, 6, 8, 6, 7, 4, 5, 4, 5, 6, +5, 5, 8, 5, 5, 5, 5, 5, 5, 5, 6, 5, +6, 5, 5, 5, 5, 5, 6, 7, 8, 6, 6, 9, +7, 7, 6, 4, 8, 5, 8, 3, 7, 8, 8, 6, +4, 10, 3, 7, 10, 10, 7, 5, 8, 7, 4, 10, +4, 4, 9, 7, 6, 6, 3, 4, 4, 7, 4, 5, +7, 4, 3, 3, 4, 4, 3, 3, 10, 3, 6, 3, +4, 3, 6, 9, 6, 4, 7, 5, 11, 5, 7, 7, +4, 9, 5, 7, 10, 6, 10, 5, 8, 3, 8, 6, +3, 8, 10, 8, 8, 4, 6, 7, 8, 8, 7, 10, +3, 7, 5, 8, 7, 8, 11, 4, 11, 5, 5, 4, +10, 5, 6, 5, 4, 7, 10, 8, 5, 8, 5, 8, +8, 9, 8, 8, 6, 7, 9, 4, 5, 5, 8, 9, +9, 9, 4, 6, 4, 5, 4, 6, 12, 8, 7, 5, +7, 8, 5, 7, 3, 5, 3, 5, 7, 2, 6, 8, +5, 5, 6, 8, 6, 8, 7, 6, 5, 7, 6, 8, +5, 6, 2, 8, 5, 8, 5, 8, 4, 5, 6, 6, +6, 8, 6, 8, 4, 8, 4, 4, 5, 7, 6, 7, +4, 8, 5, 7, 5, 8, 8, 12, 12, 4, 7, 5, +6, 5, 4, 9, 5, 5, 8, 8, 5, 9, 5, 6, +10, 5, 6, 4, 8, 6, 4, 8, 4, 5, 11, 5, +6, 5, 4, 7, 8, 9, 6, 6, 9, 5, 6, 6, +5, 4, 5, 8, 4, 4, 7, 9, 4, 7, 5, 8, +9, 4, 7, 4, 6, 4, 4, 9, 5, 5, 4, 5, +3, 2, 6, 5, 5, 5, 6, 7, 8, 8, 8, 7, +7, 7, 6, 5, 5, 6, 5, 5, 9, 8, 11, 8, +4, 6, 2, 3, 3, 6, 6, 5, 4, 6, 5, 6, +5, 4, 9, 9, 4, 6, 8, 9, 9, 5, 3, 2, +5, 10, 6, 11, 5, 6, 7, 5, 9, 5, 5, 5, +5, 5, 5, 11, 5, 9, 7, 9, 4, 9, 7, 8, +4, 4, 10, 6, 11, 4, 3, 3, 5, 5, 4, 6, +3, 4, 5, 8, 4, 6, 3, 6, 6, 6, 3, 6, +4, 6, 4, 3, 6, 6, 5, 4, 3, 4, 3, 4, +6, 3, 4, 5, 6, 5, 6, 7, 6, 6, 7, 6, +7, 3, 3, 7, 4, 7, 5, 6, 6, 7, 9, 10, +4, 4, 7, 11, 6, 7, 5, 6, 7, 4, 4, 7, +7, 3, 3, 3, 4, 4, 3, 5, 4, 5, 3, 13, +8, 5, 7, 4, 5, 5, 4, 8, 8, 7, 4, 8, +4, 7, 5, 6, 4, 8, 4, 5, 7, 7, 5, 4, +8, 5, 8, 4, 8, 8, 5, 1, 4, 6, 4, 5, +4, 6, 4, 7, 5, 6, 7, 7, 4, 7, 4, 4, +7, 2, 4, 7, 4, 6, 6, 4, 4, 4, 6, 4, +2, 8, 4, 3, 5, 5, 5, 7, 4, 5, 9, 5, +4, 4, 3, 6, 7, 6, 8, 3, 6, 8, 6, 8, +4, 4, 5, 3, 4, 4, 3, 4, 6, 6, 3, 4, +6, 3, 7, 4, 9, 4, 6, 4, 6, 4, 4, 8, +5, 8, 9, 6, 2, 10, 9, 8, 5, 10, 8, 4, +6, 4, 6, 4, 5, 4, 4, 4, 6, 5, 4, 8, +4, 9, 6, 10, 10, 5, 10, 5, 8, 7, 7, 5, +8, 9, 4, 5, 3, 9, 3, 8, 4, 5, 3, 8, +3, 5, 3, 4, 5, 10, 10, 6, 4, 5, 6, 4, +6, 7, 3, 3, 5, 3, 4, 3, 4, 6, 3, 4, +4, 4, 6, 5, 5, 6, 5, 5, 4, 5, 5, 6, +5, 5, 6, 5, 11, 5, 5, 4, 8, 11, 5, 6, +3, 6, 9, 9, 10, 5, 9, 5, 4, 5, 10, 5, +5, 6, 5, 5, 5, 5, 3, 8, 4, 2, 6, 6, +2, 5, 5, 2, 4, 7, 3, 4, 7, 4, 3, 5, +8, 6, 7, 2, 5, 7, 9, 5, 6, 6, 6, 3, +5, 5, 8, 11, 9, 8, 6, 2, 4, 6, 4, 6, +11, 4, 11, 9, 4, 9, 6, 3, 5, 4, 9, 5, +5, 5, 5, 5, 5, 5, 7, 4, 2, 6, 5, 9, +9, 6, 15, 5, 5, 5, 5, 1, 1, 2, 2, 2, +3, 1, 1, 4, 4, 9, 4, 5, 2, 5, 4, 5, +2, 4, 3, 5, 10, 2, 11, 2, 6, 3, 8, 2, +3, 7, 5, 8, 6, 2, 6, 2, 7, 11, 11, 4, +8, 4, 8, 8, 11, 10, 3, 10, 4, 11, 4, 4, +7, 8, 8, 7, 2, 5, 3, 8, 7, 5, 4, 5, +5, 5, 7, 8, 5, 6, 5, 4, 8, 7, 5, 9, +4, 1, 7, 3, 6, 5, 4, 1, 7, 3, 3, 2, +10, 7, 5, 2, 7, 8, 7, 7, 5, 4, 7, 4, +6, 4, 6, 8, 2, 3, 6, 5, 3, 6, 6, 8, +4, 7, 11, 6, 3, 4, 4, 7, 2, 2, 2, 4, +3, 4, 4, 3, 3, 5, 4, 4, 3, 5, 5, 4, +6, 3, 4, 4, 8, 6, 8, 5, 7, 3, 6, 8, +6, 5, 5, 4, 6, 4, 6, 6, 4, 5, 4, 5, +8, 5, 8, 5, 4, 7, 6, 5, 6, 2, 5, 6, +4, 5, 8, 5, 5, 2, 5, 4, 5, 5, 5, 5, +4, 5, 2, 5, 4, 5, 5, 5, 5, 5, 5, 5, +4, 5, 5, 4, 5, 5, 4, 2, 5, 4, 5, 5, +4, 5, 5, 4, 9, 4, 5, 7, 2, 5, 4, 7, +6, 10, 7, 6, 3, 6, 6, 16, 6, 9, 7, 4, +5, 5, 4, 4, 5, 5, 4, 8, 5, 4, 5, 14, +1, 6, 5, 4, 8, 8, 2, 9, 10, 4, 4, 5, +4, 4, 3, 4, 2, 3, 4, 5, 5, 4, 6, 3, +5, 4, 6, 5, 6, 5, 5, 6, 6, 3, 4, 6, +3, 5, 8, 4, 3, 5, 8, 7, 6, 5, 4, 7, +5, 7, 5, 6, 4, 7, 5, 6, 6, 5, 5, 6, +6, 5, 5, 6, 5, 6, 5, 5, 6, 5, 6, 6, +5, 6, 5, 5, 6, 6, 6, 6, 5, 5, 5, 6, +5, 6, 5, 7, 4, 5, 4, 5, 4, 4, 2, 4, +11, 6, 4, 6, 4, 6, 6, 3, 2, 6, 7, 6, +7, 7, 5, 6, 5, 5, 5, 6, 5, 6, 8, 5, +5, 5, 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, +6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, +8, 8, 9, 9, 9, 4, 6, 5, 4, 5, 5, 4, +6, 5, 4, 9, 4, 4, 2, 4, 10, 4, 3, 5, +4, 7, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, +2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, +2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, +2, 4, 2, 2, 4, 2, 4, 2, 2, 2, 4, 2, +2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, +2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, +2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, +2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, +4, 2, 2, 2, 4, 2, 4, 2, 2, 2, 4, 2, +2, 4, 2, 2, 4, 2, 2, 4, 2, 4, 2, 2, +2, 4, 2, 2, 4, 2, 4, 2, 2, 2, 4, 2, +2, 4, 2, 4, 2, 2, 2, 4, 2, 4, 2, 5, +2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, +2, 4, 2, 4, 2, 2, 2, 4, 5, 2, 4, 2, +2, 4, 2, 2, 4, 2, 2, 4, 2, 4, 2, 2, +2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, +2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, +2, 4, 2, 2, 4, 2, 4, 2, 2, 4, 2, 2, +2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, +2, 4, 2, 4, 2, 2, 2, 4, 2, 2, 4, 2, +4, 2, 2, 4, 2, 2, 2, 4, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 2, 4, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 9, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 7, 5, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 7, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 2, 4, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, +2, 2, 4, 2, 2, 4, 2, 5, 11, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 2, 4, 2, 2, 4, 2, +4, 2, 2, 2, 4, 2, 4, 2, 2, 4, 2, 2, +2, 4, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 2, 4, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 12, 4, 2, 2, 4, 2, 6, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +2, 4, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, +4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 4, 2, +4, 2, 2, 4, 2, 2, 4, 2 }; + +const ReplacementStruct ReplacementInitData[] = { + { small(2), small(10), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(31), small(5) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(23), small(3) }, + { small(2), small(14), small(2) }, + { small(2), small(18), small(3) }, + { small(2), small(13), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(15), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(22), small(3) }, + { small(2), small(21), small(3) }, + { small(2), small(5), small(1) }, + { small(2), small(30), small(5) }, + { small(2), small(30), small(5) }, + { small(2), small(18), small(3) }, + { small(2), small(18), small(3) }, + { small(2), small(13), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(11), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(22), small(4) }, + { small(2), small(8), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(14), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(24), small(3) }, + { small(2), small(14), small(2) }, + { small(2), small(21), small(3) }, + { small(2), small(11), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(10), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(16), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(12), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(23), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(24), small(4) }, + { small(2), small(14), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(19), small(3) }, + { small(2), small(14), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(23), small(3) }, + { small(2), small(18), small(2) }, + { small(2), small(24), small(4) }, + { small(2), small(14), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(17), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(22), small(3) }, + { small(2), small(18), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(16), small(3) }, + { small(2), small(12), small(2) }, + { small(2), small(11), small(2) }, + { small(2), small(9), small(2) }, + { small(2), small(16), small(3) }, + { small(2), small(11), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(17), small(3) }, + { small(2), small(13), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(4), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(4), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(11), small(2) }, + { small(2), small(18), small(3) }, + { small(2), small(12), small(2) }, + { small(2), small(19), small(3) }, + { small(2), small(43), small(7) }, + { small(2), small(17), small(2) }, + { small(2), small(3), small(1) }, + { small(2), small(19), small(4) }, + { small(2), small(7), small(1) }, + { small(2), small(9), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(12), small(3) }, + { small(2), small(12), small(2) }, + { small(2), small(10), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(14), small(3) }, + { small(2), small(21), small(4) }, + { small(2), small(34), small(5) }, + { small(2), small(14), small(2) }, + { small(2), small(55), small(9) }, + { small(2), small(8), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(14), small(3) }, + { small(2), small(9), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(43), small(6) }, + { small(2), small(15), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(11), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(29), small(4) }, + { small(2), small(15), small(2) }, + { small(2), small(20), small(3) }, + { small(2), small(21), small(3) }, + { small(2), small(6), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(7), small(1) }, + { small(5), small(20), small(3) }, + { small(2), small(18), small(3) }, + { small(2), small(24), small(4) }, + { small(2), small(21), small(3) }, + { small(2), small(11), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(21), small(5) }, + { small(2), small(22), small(4) }, + { small(5), small(22), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(17), small(3) }, + { small(2), small(23), small(3) }, + { small(5), small(22), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(5), small(1) }, + { small(2), small(16), small(2) }, + { small(5), small(27), small(3) }, + { small(2), small(25), small(3) }, + { small(2), small(21), small(2) }, + { small(5), small(13), small(2) }, + { small(2), small(11), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(7), small(1) }, + { small(6), small(17), small(2) }, + { small(3), small(15), small(2) }, + { small(3), small(15), small(3) }, + { small(3), small(5), small(1) }, + { small(3), small(11), small(1) }, + { small(5), small(21), small(3) }, + { small(5), small(19), small(3) }, + { small(5), small(14), small(2) }, + { small(5), small(12), small(2) }, + { small(5), small(12), small(2) }, + { small(5), small(10), small(2) }, + { small(5), small(15), small(2) }, + { small(5), small(13), small(2) }, + { small(5), small(14), small(2) }, + { small(5), small(12), small(2) }, + { small(5), small(15), small(2) }, + { small(5), small(13), small(2) }, + { small(5), small(22), small(3) }, + { small(5), small(20), small(3) }, + { small(5), small(20), small(2) }, + { small(5), small(18), small(2) }, + { small(5), small(21), small(3) }, + { small(5), small(19), small(3) }, + { small(5), small(16), small(2) }, + { small(5), small(14), small(2) }, + { small(5), small(17), small(2) }, + { small(5), small(15), small(2) }, + { small(5), small(14), small(2) }, + { small(5), small(12), small(2) }, + { small(5), small(19), small(2) }, + { small(5), small(17), small(2) }, + { small(5), small(13), small(2) }, + { small(5), small(11), small(2) }, + { small(5), small(17), small(2) }, + { small(5), small(15), small(2) }, + { small(5), small(13), small(2) }, + { small(5), small(11), small(2) }, + { small(2), small(18), small(2) }, + { small(2), small(11), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(17), small(3) }, + { small(2), small(15), small(3) }, + { small(2), small(7), small(1) }, + { small(2), small(17), small(2) }, + { small(2), small(16), small(2) }, + { small(5), small(14), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(20), small(3) }, + { small(2), small(25), small(3) }, + { small(2), small(21), small(3) }, + { small(5), small(18), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(9), small(2) }, + { small(2), small(21), small(3) }, + { small(5), small(18), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(10), small(2) }, + { small(2), small(21), small(3) }, + { small(5), small(18), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(14), small(2) }, + { small(2), small(21), small(3) }, + { small(5), small(18), small(3) }, + { small(5), small(19), small(2) }, + { small(5), small(17), small(2) }, + { small(5), small(10), small(1) }, + { small(5), small(11), small(2) }, + { small(5), small(20), small(2) }, + { small(5), small(17), small(2) }, + { small(5), small(7), small(1) }, + { small(5), small(18), small(2) }, + { small(5), small(15), small(2) }, + { small(2), small(15), small(2) }, + { small(2), small(26), small(4) }, + { small(2), small(16), small(2) }, + { small(5), small(13), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(17), small(2) }, + { small(5), small(14), small(2) }, + { small(2), small(23), small(3) }, + { small(2), small(9), small(1) }, + { small(2), small(24), small(3) }, + { small(5), small(21), small(3) }, + { small(2), small(28), small(4) }, + { small(2), small(9), small(1) }, + { small(2), small(24), small(3) }, + { small(5), small(26), small(4) }, + { small(2), small(33), small(5) }, + { small(2), small(8), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(32), small(5) }, + { small(2), small(9), small(1) }, + { small(2), small(33), small(5) }, + { small(5), small(30), small(5) }, + { small(5), small(15), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(16), small(2) }, + { small(5), small(15), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(25), small(4) }, + { small(2), small(23), small(4) }, + { small(2), small(19), small(3) }, + { small(2), small(29), small(5) }, + { small(8), small(22), small(4) }, + { small(8), small(11), small(2) }, + { small(8), small(22), small(4) }, + { small(8), small(11), small(2) }, + { small(2), small(12), small(1) }, + { small(2), small(16), small(3) }, + { small(11), small(15), small(2) }, + { small(11), small(9), small(2) }, + { small(11), small(15), small(2) }, + { small(11), small(9), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(22), small(4) }, + { small(8), small(12), small(2) }, + { small(11), small(13), small(2) }, + { small(11), small(13), small(2) }, + { small(11), small(13), small(2) }, + { small(8), small(12), small(2) }, + { small(8), small(12), small(2) }, + { small(11), small(13), small(2) }, + { small(11), small(13), small(2) }, + { small(11), small(13), small(2) }, + { small(8), small(12), small(2) }, + { small(8), small(12), small(2) }, + { small(11), small(13), small(2) }, + { small(11), small(13), small(2) }, + { small(11), small(13), small(2) }, + { small(5), small(18), small(3) }, + { small(5), small(19), small(3) }, + { small(8), small(23), small(4) }, + { small(8), small(22), small(4) }, + { small(8), small(24), small(4) }, + { small(5), small(16), small(3) }, + { small(5), small(17), small(3) }, + { small(8), small(21), small(4) }, + { small(8), small(20), small(4) }, + { small(8), small(22), small(4) }, + { small(2), small(16), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(11), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(11), small(2) }, + { small(2), small(15), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(7), small(1) }, + { small(1), small(25), small(4) }, + { small(1), small(19), small(3) }, + { small(2), small(16), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(17), small(2) }, + { small(2), small(17), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(10), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(11), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(10), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(13), small(3) }, + { small(2), small(14), small(3) }, + { small(2), small(15), small(3) }, + { small(2), small(8), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(15), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(4), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(17), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(15), small(3) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(11), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(18), small(3) }, + { small(2), small(8), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(13), small(3) }, + { small(2), small(9), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(11), small(2) }, + { small(2), small(21), small(3) }, + { small(2), small(19), small(3) }, + { small(2), small(22), small(3) }, + { small(2), small(10), small(2) }, + { small(2), small(22), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(21), small(3) }, + { small(2), small(20), small(4) }, + { small(2), small(21), small(4) }, + { small(2), small(15), small(3) }, + { small(2), small(30), small(5) }, + { small(2), small(29), small(5) }, + { small(2), small(15), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(1), small(10), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(28), small(5) }, + { small(2), small(23), small(4) }, + { small(2), small(14), small(2) }, + { small(2), small(24), small(4) }, + { small(2), small(17), small(3) }, + { small(2), small(34), small(6) }, + { small(2), small(22), small(4) }, + { small(2), small(9), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(17), small(3) }, + { small(2), small(12), small(2) }, + { small(1), small(24), small(4) }, + { small(1), small(20), small(3) }, + { small(2), small(22), small(3) }, + { small(2), small(17), small(2) }, + { small(2), small(17), small(3) }, + { small(2), small(12), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(19), small(3) }, + { small(2), small(6), small(1) }, + { small(2), small(20), small(3) }, + { small(2), small(15), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(11), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(14), small(3) }, + { small(2), small(7), small(1) }, + { small(2), small(9), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(19), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(21), small(4) }, + { small(2), small(11), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(11), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(11), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(11), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(15), small(3) }, + { small(2), small(6), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(17), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(26), small(4) }, + { small(2), small(11), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(16), small(3) }, + { small(2), small(27), small(5) }, + { small(2), small(18), small(3) }, + { small(2), small(8), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(11), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(10), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(18), small(3) }, + { small(2), small(14), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(15), small(3) }, + { small(2), small(23), small(4) }, + { small(2), small(15), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(22), small(3) }, + { small(1), small(11), small(2) }, + { small(2), small(5), small(1) }, + { small(1), small(7), small(1) }, + { small(2), small(13), small(1) }, + { small(6), small(23), small(3) }, + { small(3), small(21), small(3) }, + { small(3), small(15), small(2) }, + { small(3), small(8), small(1) }, + { small(3), small(24), small(3) }, + { small(2), small(9), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(16), small(2) }, + { small(5), small(17), small(2) }, + { small(5), small(15), small(2) }, + { small(5), small(11), small(1) }, + { small(5), small(11), small(1) }, + { small(5), small(18), small(2) }, + { small(5), small(20), small(2) }, + { small(5), small(18), small(2) }, + { small(5), small(11), small(1) }, + { small(5), small(24), small(3) }, + { small(5), small(21), small(3) }, + { small(2), small(19), small(3) }, + { small(2), small(18), small(3) }, + { small(2), small(19), small(2) }, + { small(2), small(22), small(3) }, + { small(5), small(24), small(3) }, + { small(5), small(10), small(1) }, + { small(5), small(25), small(3) }, + { small(5), small(22), small(3) }, + { small(6), small(15), small(2) }, + { small(3), small(13), small(2) }, + { small(3), small(8), small(1) }, + { small(3), small(16), small(2) }, + { small(5), small(15), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(16), small(2) }, + { small(5), small(16), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(17), small(2) }, + { small(5), small(26), small(4) }, + { small(5), small(24), small(4) }, + { small(5), small(12), small(2) }, + { small(5), small(27), small(4) }, + { small(5), small(19), small(3) }, + { small(2), small(17), small(3) }, + { small(2), small(9), small(1) }, + { small(2), small(20), small(3) }, + { small(2), small(14), small(2) }, + { small(5), small(14), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(15), small(2) }, + { small(5), small(23), small(3) }, + { small(2), small(21), small(3) }, + { small(2), small(20), small(2) }, + { small(2), small(24), small(3) }, + { small(2), small(25), small(4) }, + { small(2), small(14), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(19), small(3) }, + { small(2), small(13), small(2) }, + { small(2), small(20), small(3) }, + { small(2), small(14), small(2) }, + { small(2), small(19), small(3) }, + { small(2), small(13), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(17), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(19), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(13), small(2) }, + { small(5), small(16), small(2) }, + { small(5), small(14), small(2) }, + { small(5), small(9), small(1) }, + { small(5), small(10), small(1) }, + { small(5), small(17), small(2) }, + { small(2), small(17), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(18), small(2) }, + { small(2), small(22), small(3) }, + { small(2), small(6), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(10), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(9), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(10), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(10), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(19), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(19), small(2) }, + { small(2), small(12), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(21), small(3) }, + { small(2), small(14), small(2) }, + { small(2), small(21), small(2) }, + { small(2), small(15), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(19), small(2) }, + { small(2), small(20), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(18), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(18), small(2) }, + { small(2), small(19), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(18), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(20), small(2) }, + { small(2), small(19), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(19), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(13), small(2) }, + { small(1), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(14), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(24), small(3) }, + { small(2), small(15), small(2) }, + { small(2), small(11), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(19), small(3) }, + { small(2), small(10), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(17), small(2) }, + { small(2), small(17), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(16), small(2) }, + { small(1), small(20), small(3) }, + { small(1), small(16), small(2) }, + { small(2), small(21), small(3) }, + { small(2), small(7), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(8), small(1) }, + { small(1), small(10), small(1) }, + { small(2), small(22), small(3) }, + { small(2), small(15), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(15), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(23), small(2) }, + { small(2), small(19), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(19), small(3) }, + { small(2), small(17), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(25), small(3) }, + { small(2), small(17), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(18), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(22), small(3) }, + { small(2), small(10), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(19), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(20), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(7), small(1) }, + { small(1), small(15), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(15), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(24), small(3) }, + { small(2), small(7), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(11), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(18), small(3) }, + { small(2), small(11), small(2) }, + { small(2), small(17), small(3) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(18), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(20), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(11), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(13), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(4), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(19), small(3) }, + { small(2), small(14), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(20), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(4), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(19), small(2) }, + { small(2), small(13), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(15), small(2) }, + { small(1), small(11), small(1) }, + { small(1), small(13), small(2) }, + { small(1), small(7), small(1) }, + { small(1), small(13), small(2) }, + { small(2), small(19), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(11), small(1) }, + { small(1), small(24), small(3) }, + { small(2), small(11), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(13), small(1) }, + { small(2), small(10), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(18), small(3) }, + { small(2), small(8), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(1), small(17), small(3) }, + { small(1), small(13), small(2) }, + { small(2), small(19), small(3) }, + { small(2), small(7), small(1) }, + { small(1), small(6), small(1) }, + { small(2), small(14), small(3) }, + { small(2), small(6), small(1) }, + { small(1), small(8), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(13), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(9), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(16), small(3) }, + { small(2), small(7), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(24), small(2) }, + { small(2), small(20), small(3) }, + { small(2), small(13), small(2) }, + { small(2), small(15), small(2) }, + { small(2), small(18), small(2) }, + { small(2), small(15), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(17), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(21), small(3) }, + { small(2), small(19), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(8), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(19), small(3) }, + { small(2), small(22), small(4) }, + { small(2), small(9), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(16), small(3) }, + { small(2), small(16), small(3) }, + { small(2), small(15), small(2) }, + { small(2), small(11), small(2) }, + { small(2), small(26), small(4) }, + { small(2), small(28), small(4) }, + { small(2), small(17), small(3) }, + { small(2), small(16), small(2) }, + { small(2), small(21), small(3) }, + { small(2), small(17), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(15), small(3) }, + { small(2), small(10), small(2) }, + { small(2), small(24), small(4) }, + { small(2), small(12), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(18), small(3) }, + { small(2), small(21), small(3) }, + { small(2), small(10), small(1) }, + { small(2), small(21), small(3) }, + { small(2), small(12), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(32), small(4) }, + { small(2), small(8), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(11), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(19), small(2) }, + { small(2), small(12), small(1) }, + { small(2), small(18), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(26), small(4) }, + { small(2), small(15), small(2) }, + { small(2), small(25), small(4) }, + { small(2), small(14), small(2) }, + { small(2), small(11), small(2) }, + { small(2), small(23), small(3) }, + { small(2), small(12), small(1) }, + { small(2), small(19), small(3) }, + { small(2), small(8), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(11), small(2) }, + { small(2), small(19), small(4) }, + { small(2), small(22), small(4) }, + { small(2), small(6), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(39), small(5) }, + { small(2), small(19), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(18), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(17), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(18), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(7), small(1) }, + { small(2), small(19), small(3) }, + { small(2), small(11), small(2) }, + { small(2), small(17), small(3) }, + { small(2), small(15), small(3) }, + { small(2), small(18), small(3) }, + { small(2), small(9), small(1) }, + { small(2), small(10), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(18), small(3) }, + { small(1), small(11), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(13), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(4), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(18), small(2) }, + { small(2), small(13), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(11), small(1) }, + { small(2), small(18), small(3) }, + { small(2), small(16), small(2) }, + { small(2), small(7), small(1) }, + { small(3), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(26), small(4) }, + { small(2), small(4), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(21), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(17), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(3), small(3), small(1) }, + { small(3), small(3), small(1) }, + { small(2), small(4), small(1) }, + { small(2), small(4), small(1) }, + { small(3), small(4), small(1) }, + { small(2), small(5), small(1) }, + { small(1), small(3), small(1) }, + { small(2), small(3), small(1) }, + { small(2), small(11), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(10), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(15), small(3) }, + { small(2), small(5), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(12), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(15), small(3) }, + { small(2), small(13), small(2) }, + { small(2), small(19), small(3) }, + { small(2), small(10), small(1) }, + { small(2), small(18), small(3) }, + { small(2), small(12), small(2) }, + { small(2), small(13), small(1) }, + { small(1), small(18), small(2) }, + { small(1), small(10), small(1) }, + { small(1), small(15), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(13), small(1) }, + { small(2), small(16), small(2) }, + { small(2), small(17), small(2) }, + { small(2), small(23), small(3) }, + { small(2), small(9), small(1) }, + { small(2), small(19), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(14), small(3) }, + { small(2), small(10), small(1) }, + { small(2), small(9), small(1) }, + { small(1), small(18), small(3) }, + { small(3), small(7), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(23), small(3) }, + { small(1), small(29), small(4) }, + { small(2), small(22), small(3) }, + { small(2), small(33), small(6) }, + { small(2), small(3), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(4), small(1) }, + { small(2), small(12), small(1) }, + { small(3), small(9), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(4), small(1) }, + { small(2), small(18), small(2) }, + { small(2), small(9), small(1) }, + { small(2), small(15), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(10), small(1) }, + { small(2), small(25), small(5) }, + { small(2), small(8), small(1) }, + { small(2), small(17), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(20), small(2) }, + { small(2), small(5), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(14), small(2) }, + { small(2), small(4), small(1) }, + { small(2), small(4), small(1) }, + { small(2), small(4), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(6), small(1) }, + { small(3), small(6), small(1) }, + { small(3), small(5), small(1) }, + { small(3), small(5), small(1) }, + { small(3), small(7), small(1) }, + { small(3), small(6), small(1) }, + { small(3), small(6), small(1) }, + { small(3), small(5), small(1) }, + { small(3), small(7), small(1) }, + { small(3), small(7), small(1) }, + { small(3), small(6), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(6), small(1) }, + { small(3), small(6), small(1) }, + { small(3), small(17), small(2) }, + { small(3), small(10), small(1) }, + { small(2), small(15), small(2) }, + { small(1), small(21), small(3) }, + { small(1), small(14), small(2) }, + { small(1), small(12), small(2) }, + { small(1), small(13), small(2) }, + { small(1), small(15), small(2) }, + { small(1), small(12), small(2) }, + { small(1), small(12), small(2) }, + { small(1), small(16), small(2) }, + { small(1), small(16), small(2) }, + { small(1), small(14), small(2) }, + { small(1), small(8), small(1) }, + { small(1), small(17), small(3) }, + { small(1), small(19), small(3) }, + { small(2), small(16), small(2) }, + { small(2), small(16), small(3) }, + { small(2), small(18), small(3) }, + { small(2), small(13), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(10), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(19), small(3) }, + { small(2), small(19), small(3) }, + { small(2), small(18), small(3) }, + { small(2), small(18), small(3) }, + { small(2), small(15), small(3) }, + { small(2), small(18), small(3) }, + { small(2), small(18), small(3) }, + { small(2), small(27), small(4) }, + { small(2), small(18), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(27), small(3) }, + { small(2), small(8), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(25), small(2) }, + { small(2), small(18), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(7), small(1) }, + { small(1), small(17), small(3) }, + { small(1), small(18), small(3) }, + { small(1), small(21), small(3) }, + { small(2), small(24), small(3) }, + { small(2), small(19), small(3) }, + { small(2), small(19), small(2) }, + { small(1), small(4), small(1) }, + { small(1), small(11), small(1) }, + { small(1), small(12), small(1) }, + { small(1), small(11), small(2) }, + { small(1), small(12), small(2) }, + { small(1), small(6), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(4), small(1) }, + { small(2), small(5), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(18), small(3) }, + { small(2), small(23), small(4) }, + { small(2), small(14), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(14), small(2) }, + { small(2), small(12), small(2) }, + { small(2), small(13), small(2) }, + { small(2), small(20), small(3) }, + { small(2), small(25), small(4) }, + { small(2), small(22), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(22), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(21), small(3) }, + { small(2), small(21), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(27), small(4) }, + { small(2), small(27), small(4) }, + { small(2), small(21), small(3) }, + { small(2), small(21), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(20), small(3) }, + { small(2), small(9), small(1) }, + { small(2), small(6), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(12), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(9), small(2) }, + { small(2), small(6), small(1) }, + { small(2), small(13), small(1) }, + { small(2), small(20), small(3) }, + { small(2), small(13), small(2) }, + { small(5), small(22), small(4) }, + { small(2), small(16), small(2) }, + { small(2), small(17), small(2) }, + { small(2), small(20), small(3) }, + { small(2), small(13), small(2) }, + { small(2), small(8), small(1) }, + { small(2), small(7), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(13), small(2) }, + { small(2), small(22), small(3) }, + { small(3), small(9), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(8), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(9), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(10), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(11), small(1) }, + { small(2), small(19), small(3) }, + { small(2), small(12), small(2) }, + { small(2), small(19), small(3) }, + { small(2), small(12), small(2) }, + { small(2), small(16), small(2) }, + { small(2), small(25), small(4) }, + { small(6), small(16), small(3) }, + { small(6), small(14), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(7), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(7), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(11), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(2), small(15), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(9), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(7), small(1) }, + { small(4), small(13), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(14), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(8), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, + { small(4), small(4), small(1) }, + { small(4), small(9), small(2) }, +}; + +const medium ReplacementIndices[] = { +131, 135, 1208, 1284, 151, 671, 54, 61, 63, 107, 109, 143, +159, 240, 241, 246, 247, 257, 372, 431, 507, 508, 509, 545, +563, 564, 578, 661, 662, 682, 683, 684, 688, 762, 770, 771, +796, 800, 811, 813, 829, 830, 831, 832, 833, 846, 889, 922, +962, 987, 989, 992, 1006, 1010, 1028, 1031, 1047, 1147, 1158, 1168, +1171, 1172, 1173, 1188, 1195, 1197, 1209, 1226, 1237, 1240, 1244, 1264, +1265, 1266, 1286, 1287, 1288, 1300, 1301, 1302, 1303, 1304, 1305, 1306, +1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, +1319, 1322, 1323, 1379, 1380, 1420, 1421, 1422, 1423, 1424, 1425, 1428, +1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, +1441, 1442, 1443, 1444, 1445, 1448, 1449, 1450, 1451, 1452, 1453, 1850, +1851, 1906, 1907, 11, 94, 95, 155, 156, 159, 182, 183, 184, +185, 189, 190, 191, 192, 255, 260, 261, 262, 263, 304, 308, +310, 311, 336, 351, 353, 354, 356, 358, 359, 366, 370, 375, +383, 395, 412, 413, 419, 421, 425, 426, 427, 430, 444, 452, +491, 498, 504, 505, 531, 537, 539, 554, 568, 592, 593, 594, +599, 603, 612, 622, 624, 633, 639, 645, 649, 650, 658, 665, +667, 674, 679, 683, 685, 686, 710, 711, 712, 713, 714, 735, +736, 738, 740, 741, 742, 743, 744, 745, 746, 747, 785, 790, +791, 803, 810, 820, 821, 849, 865, 866, 867, 881, 886, 888, +895, 901, 922, 932, 933, 968, 970, 992, 996, 1007, 1008, 1009, +1020, 1021, 1022, 1023, 1030, 1034, 1038, 1041, 1065, 1066, 1076, 1077, +1078, 1079, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1108, 1109, 1112, +1129, 1131, 1132, 1176, 1177, 1185, 1196, 1206, 1213, 1222, 1224, 1225, +1231, 1252, 1256, 1289, 1290, 1292, 1293, 1302, 1339, 1344, 1345, 1347, +1349, 1353, 1355, 1356, 1357, 1358, 1360, 1362, 1364, 1370, 1371, 1374, +1376, 1377, 1378, 1379, 1385, 1414, 1415, 1454, 1455, 1456, 1457, 1458, +1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, +1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1488, +1489, 1490, 1491, 1492, 1493, 1494, 1495, 1506, 1507, 1763, 1764, 1844, +1845, 23, 26, 35, 36, 37, 38, 44, 50, 68, 69, 107, +108, 114, 115, 116, 117, 118, 119, 120, 121, 122, 125, 143, +144, 162, 163, 169, 197, 204, 206, 207, 208, 222, 223, 250, +251, 320, 323, 324, 325, 326, 327, 328, 329, 331, 333, 361, +376, 377, 378, 386, 389, 401, 410, 413, 414, 415, 438, 449, +454, 456, 457, 469, 477, 482, 483, 490, 505, 513, 515, 523, +532, 534, 535, 537, 538, 539, 540, 542, 543, 544, 545, 546, +547, 548, 549, 550, 556, 557, 573, 581, 582, 583, 587, 591, +595, 596, 598, 620, 623, 626, 630, 632, 636, 638, 639, 642, +646, 651, 652, 656, 658, 659, 679, 680, 706, 707, 708, 709, +764, 772, 788, 790, 793, 794, 795, 809, 814, 816, 838, 843, +847, 858, 859, 862, 863, 871, 876, 881, 882, 897, 901, 902, +916, 917, 918, 919, 926, 927, 929, 936, 939, 942, 943, 944, +945, 958, 960, 962, 963, 964, 972, 982, 994, 1000, 1003, 1007, +1028, 1029, 1036, 1041, 1045, 1056, 1063, 1066, 1067, 1068, 1071, 1072, +1073, 1075, 1076, 1077, 1080, 1081, 1084, 1090, 1092, 1115, 1116, 1123, +1140, 1145, 1146, 1147, 1154, 1161, 1167, 1190, 1198, 1228, 1233, 1235, +1238, 1242, 1250, 1251, 1252, 1259, 1266, 1270, 1322, 1323, 1331, 1333, +1336, 1343, 1344, 1346, 1347, 1348, 1349, 1382, 1386, 1388, 1389, 1390, +1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, +1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1416, 1498, 1499, +1500, 1501, 1504, 1505, 1510, 1511, 1514, 1515, 1516, 1517, 1518, 1519, +1520, 1521, 1522, 1523, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, +1534, 1535, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1582, 1583, +1652, 1868, 1869, 15, 16, 41, 64, 70, 71, 72, 133, 152, +213, 214, 217, 265, 305, 306, 307, 309, 365, 385, 388, 416, +445, 455, 456, 467, 472, 473, 480, 481, 485, 524, 555, 560, +561, 605, 628, 641, 657, 709, 777, 778, 783, 784, 832, 868, +875, 888, 891, 918, 929, 930, 938, 940, 974, 977, 998, 999, +1027, 1043, 1068, 1074, 1084, 1085, 1090, 1142, 1149, 1150, 1212, 1230, +1240, 1289, 1300, 1301, 1304, 1308, 1313, 1318, 1328, 1330, 1335, 1351, +1352, 1353, 1354, 1355, 1384, 1426, 1427, 1484, 1485, 1546, 1547, 1548, +1549, 1550, 1551, 1552, 1553, 1596, 1597, 19, 22, 23, 25, 26, +58, 77, 78, 117, 165, 175, 178, 179, 258, 308, 310, 311, +384, 406, 407, 408, 417, 458, 484, 497, 507, 508, 509, 580, +597, 797, 858, 893, 969, 979, 1046, 1047, 1048, 1049, 1050, 1133, +1134, 1185, 1205, 1207, 1218, 1219, 1237, 1281, 1331, 1338, 1376, 1554, +1555, 1556, 1557, 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1838, +1839, 1840, 1841, 1928, 1929, 8, 13, 15, 28, 30, 32, 35, +37, 45, 46, 47, 48, 51, 57, 60, 64, 65, 67, 72, +77, 80, 83, 85, 88, 90, 92, 93, 94, 111, 121, 138, +139, 140, 141, 142, 143, 144, 157, 159, 165, 166, 177, 220, +221, 230, 231, 242, 243, 280, 281, 282, 283, 284, 290, 293, +294, 295, 300, 303, 335, 336, 337, 338, 339, 340, 341, 342, +343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, +355, 356, 357, 358, 359, 360, 393, 394, 396, 400, 404, 405, +423, 442, 443, 479, 481, 490, 494, 501, 510, 516, 518, 519, +520, 521, 522, 529, 530, 554, 558, 594, 601, 608, 610, 616, +620, 634, 661, 662, 663, 666, 670, 678, 684, 698, 699, 700, +752, 753, 797, 821, 844, 848, 856, 861, 873, 883, 915, 923, +938, 943, 946, 948, 952, 966, 971, 1004, 1032, 1033, 1039, 1064, +1076, 1080, 1082, 1083, 1110, 1111, 1187, 1230, 1272, 1277, 1278, 1288, +1298, 1386, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1421, 1423, +1425, 1427, 1429, 1431, 1433, 1435, 1437, 1439, 1441, 1443, 1445, 1447, +1449, 1451, 1453, 1455, 1457, 1459, 1461, 1463, 1465, 1467, 1469, 1471, +1473, 1475, 1477, 1479, 1481, 1483, 1485, 1487, 1489, 1491, 1493, 1495, +1497, 1499, 1501, 1503, 1505, 1507, 1509, 1511, 1513, 1515, 1517, 1519, +1521, 1523, 1525, 1527, 1529, 1531, 1533, 1535, 1537, 1539, 1541, 1543, +1545, 1547, 1549, 1551, 1553, 1555, 1557, 1559, 1561, 1563, 1565, 1567, +1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1579, 1580, 1581, +1583, 1585, 1587, 1589, 1591, 1593, 1595, 1597, 1599, 1601, 1603, 1605, +1607, 1609, 1611, 1613, 1615, 1617, 1619, 1621, 1623, 1625, 1627, 1629, +1631, 1633, 1635, 1637, 1639, 1641, 1643, 1645, 1647, 1649, 1651, 1652, +1654, 1656, 1658, 1660, 1662, 1664, 1666, 1668, 1670, 1672, 1674, 1676, +1678, 1680, 1682, 1684, 1686, 1688, 1690, 1692, 1694, 1696, 1698, 1700, +1702, 1704, 1706, 1708, 1710, 1712, 1714, 1715, 1716, 1718, 1720, 1722, +1724, 1726, 1728, 1730, 1732, 1734, 1736, 1738, 1740, 1742, 1744, 1746, +1748, 1750, 1752, 1754, 1756, 1758, 1760, 1762, 1764, 1766, 1768, 1770, +1772, 1774, 1776, 1778, 1780, 1782, 1784, 1786, 1788, 1790, 1792, 1794, +1796, 1798, 1800, 1802, 1804, 1806, 1809, 1811, 1813, 1815, 1817, 1819, +1821, 1823, 1825, 1827, 1829, 1831, 1833, 1835, 1837, 1839, 1841, 1843, +1845, 1847, 1849, 1851, 1853, 1855, 1857, 1859, 1861, 1863, 1865, 1867, +1869, 1871, 1873, 1875, 1877, 1879, 1881, 1883, 1885, 1887, 1889, 1891, +1893, 1895, 1897, 1899, 1901, 1903, 1905, 1907, 1909, 1911, 1913, 1915, +1917, 1919, 1921, 1923, 1925, 1927, 1929, 1931, 1933, 1935, 0, 3, +84, 99, 104, 186, 194, 196, 209, 210, 211, 212, 268, 269, +270, 271, 272, 274, 275, 296, 298, 299, 300, 302, 303, 352, +353, 355, 357, 358, 360, 461, 464, 511, 517, 563, 570, 613, +643, 651, 652, 653, 655, 675, 676, 680, 681, 685, 686, 719, +720, 721, 722, 781, 783, 786, 864, 885, 983, 993, 995, 1037, +1093, 1128, 1141, 1160, 1219, 1221, 1239, 1418, 1560, 1561, 1584, 1585, +1590, 1591, 1592, 1593, 1594, 1595, 1598, 1599, 1600, 1601, 1602, 1603, +1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, +1616, 1617, 1618, 1619, 1620, 1621, 1826, 1827, 1908, 1909, 19, 20, +30, 31, 37, 59, 79, 94, 95, 101, 117, 123, 124, 127, +128, 143, 146, 148, 154, 155, 156, 157, 158, 159, 162, 165, +167, 180, 181, 189, 190, 191, 192, 218, 219, 264, 266, 267, +276, 277, 278, 279, 296, 297, 298, 299, 321, 322, 323, 324, +325, 327, 368, 373, 377, 378, 382, 391, 407, 414, 415, 422, +488, 506, 584, 590, 605, 606, 607, 677, 678, 715, 716, 717, +718, 739, 774, 828, 863, 884, 885, 886, 887, 888, 889, 894, +896, 899, 965, 966, 986, 987, 988, 989, 1013, 1061, 1126, 1127, +1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, +1141, 1142, 1210, 1225, 1285, 1315, 1316, 1317, 1318, 1326, 1327, 1328, +1329, 1330, 1343, 1383, 1446, 1447, 1536, 1537, 1622, 1623, 1624, 1625, +1626, 1627, 1628, 1629, 12, 96, 97, 110, 143, 180, 182, 183, +256, 265, 304, 629, 630, 631, 689, 868, 869, 925, 1044, 1048, +1052, 1075, 1084, 1122, 1170, 1188, 1223, 1240, 1258, 1263, 1376, 1482, +1483, 1502, 1503, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, +1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 7, 98, 99, +113, 116, 248, 249, 363, 765, 766, 767, 768, 769, 859, 907, +935, 1385, 1648, 1649, 1650, 1651, 1653, 1654, 1655, 1656, 20, 21, +22, 23, 119, 172, 330, 332, 334, 367, 397, 576, 577, 661, +662, 663, 687, 776, 837, 905, 928, 958, 997, 998, 1024, 1025, +1026, 1123, 1261, 1283, 1286, 1496, 1497, 1508, 1509, 1524, 1525, 1657, +1658, 1659, 1660, 1661, 1662, 1665, 1666, 1667, 1668, 1755, 1756, 1834, +1835, 1852, 1853, 5, 8, 82, 83, 113, 129, 139, 140, 149, +171, 173, 304, 399, 400, 436, 450, 490, 493, 494, 495, 512, +522, 547, 548, 567, 602, 637, 693, 694, 695, 696, 697, 800, +808, 822, 823, 850, 851, 855, 899, 957, 1028, 1044, 1051, 1055, +1091, 1099, 1101, 1108, 1110, 1113, 1115, 1122, 1123, 1124, 1145, 1162, +1164, 1212, 1224, 1230, 1253, 1258, 1306, 1310, 1311, 1312, 1314, 1316, +1336, 1337, 1354, 1355, 1364, 1365, 1369, 1373, 1374, 1375, 1669, 1670, +1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, +1683, 1684, 1685, 1686, 1842, 1843, 1854, 1855, 28, 29, 56, 62, +85, 86, 91, 143, 147, 159, 162, 163, 164, 165, 166, 187, +190, 193, 196, 197, 199, 200, 203, 207, 210, 214, 219, 221, +223, 225, 227, 229, 231, 233, 235, 236, 237, 239, 241, 243, +245, 247, 249, 250, 251, 256, 261, 267, 271, 275, 279, 281, +288, 292, 295, 299, 300, 301, 302, 303, 304, 306, 307, 311, +313, 317, 322, 324, 327, 328, 330, 333, 334, 336, 337, 338, +339, 340, 346, 347, 348, 349, 350, 356, 357, 358, 359, 360, +371, 375, 390, 405, 409, 475, 495, 496, 510, 511, 512, 513, +514, 515, 516, 517, 518, 519, 521, 522, 523, 572, 603, 643, +644, 688, 694, 702, 707, 711, 718, 720, 724, 728, 732, 736, +741, 744, 745, 746, 747, 749, 750, 751, 752, 754, 756, 766, +773, 775, 776, 787, 798, 804, 805, 806, 807, 814, 818, 819, +825, 840, 852, 853, 854, 870, 871, 872, 873, 880, 903, 912, +921, 932, 933, 937, 945, 955, 956, 963, 976, 981, 1012, 1050, +1056, 1057, 1058, 1059, 1117, 1120, 1121, 1133, 1152, 1178, 1179, 1216, +1226, 1233, 1238, 1239, 1241, 1254, 1324, 1327, 1329, 1343, 1360, 1361, +1362, 1363, 1367, 1372, 1387, 1578, 1579, 1687, 1688, 1689, 1690, 1691, +1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, +1704, 1705, 1706, 1707, 1708, 1709, 1710, 1713, 1714, 1717, 1718, 1719, +1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, +1732, 1757, 1758, 32, 33, 56, 57, 88, 169, 176, 268, 269, +270, 271, 364, 403, 406, 407, 408, 514, 518, 675, 909, 920, +922, 992, 1059, 1069, 1070, 1086, 1087, 1088, 1089, 1090, 1112, 1205, +1206, 1207, 1211, 1212, 1213, 1214, 1216, 1217, 1238, 1267, 1271, 1282, +1294, 1295, 1324, 1325, 1371, 1733, 1734, 1735, 1736, 1737, 1738, 1739, +1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, +1752, 1753, 1754, 1761, 1762, 8, 25, 26, 27, 62, 98, 113, +123, 146, 148, 155, 156, 193, 195, 202, 203, 205, 215, 234, +235, 272, 273, 274, 275, 418, 440, 453, 472, 497, 559, 603, +616, 627, 643, 809, 810, 811, 812, 835, 855, 864, 890, 892, +893, 912, 974, 975, 1025, 1053, 1083, 1095, 1133, 1148, 1149, 1150, +1154, 1156, 1157, 1178, 1199, 1202, 1204, 1268, 1274, 1321, 1340, 1352, +1354, 1417, 1765, 1766, 42, 49, 100, 103, 122, 126, 137, 149, +150, 151, 152, 153, 159, 191, 192, 196, 201, 202, 203, 205, +244, 245, 253, 254, 259, 263, 265, 266, 270, 274, 278, 283, +284, 287, 289, 290, 291, 292, 294, 298, 302, 308, 310, 311, +315, 319, 380, 381, 396, 402, 403, 411, 463, 468, 472, 478, +486, 536, 565, 574, 575, 584, 585, 586, 588, 589, 590, 600, +602, 604, 609, 615, 616, 635, 640, 658, 662, 663, 673, 684, +697, 700, 705, 709, 712, 713, 714, 715, 717, 718, 722, 726, +730, 731, 732, 733, 734, 738, 743, 747, 752, 753, 754, 755, +756, 757, 769, 770, 795, 809, 842, 892, 893, 909, 910, 931, +946, 947, 951, 969, 980, 987, 988, 991, 1008, 1014, 1018, 1032, +1033, 1054, 1060, 1061, 1063, 1064, 1069, 1071, 1100, 1101, 1102, 1105, +1106, 1108, 1109, 1110, 1111, 1113, 1114, 1118, 1119, 1122, 1130, 1143, +1144, 1151, 1156, 1169, 1178, 1185, 1211, 1214, 1216, 1226, 1247, 1250, +1258, 1290, 1291, 1296, 1297, 1326, 1386, 1417, 1418, 1586, 1587, 1767, +1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, +1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1856, +1857, 512, 516, 521, 522, 1220, 1221, 1791, 1792, 8, 9, 10, +18, 55, 70, 77, 78, 111, 112, 124, 141, 142, 150, 154, +156, 157, 159, 165, 170, 276, 277, 278, 279, 316, 317, 318, +319, 392, 459, 460, 462, 465, 470, 474, 476, 497, 500, 502, +539, 540, 541, 543, 544, 545, 546, 618, 624, 625, 626, 670, +735, 736, 737, 738, 739, 748, 759, 760, 788, 793, 794, 806, +808, 815, 816, 818, 822, 834, 862, 878, 879, 908, 949, 954, +1040, 1086, 1103, 1104, 1106, 1121, 1136, 1174, 1175, 1232, 1257, 1293, +1299, 1305, 1309, 1310, 1314, 1315, 1319, 1320, 1321, 1334, 1345, 1348, +1350, 1351, 1379, 1380, 1419, 1793, 1794, 1795, 1796, 1797, 1798, 1799, +1800, 1812, 1813, 1, 2, 4, 6, 13, 14, 22, 25, 26, +27, 34, 39, 45, 46, 66, 68, 73, 74, 75, 76, 87, +89, 90, 96, 102, 105, 106, 107, 108, 110, 114, 115, 118, +120, 127, 146, 157, 158, 168, 180, 181, 182, 183, 215, 216, +224, 225, 226, 227, 238, 239, 252, 285, 286, 287, 288, 304, +362, 369, 371, 372, 379, 385, 406, 408, 428, 429, 432, 433, +435, 437, 439, 441, 446, 466, 487, 489, 503, 520, 525, 526, +527, 533, 534, 535, 536, 537, 538, 539, 540, 549, 550, 551, +552, 553, 561, 571, 586, 588, 601, 609, 610, 613, 614, 616, +617, 619, 621, 629, 648, 660, 664, 689, 690, 691, 692, 723, +724, 725, 726, 727, 728, 729, 730, 748, 749, 754, 755, 775, +779, 787, 802, 805, 815, 820, 823, 827, 829, 830, 835, 836, +839, 841, 842, 843, 845, 855, 860, 871, 872, 882, 891, 897, +898, 904, 906, 908, 911, 912, 913, 914, 916, 917, 920, 955, +957, 959, 966, 967, 984, 1000, 1001, 1002, 1015, 1019, 1031, 1034, +1035, 1036, 1062, 1069, 1070, 1071, 1072, 1104, 1107, 1139, 1143, 1147, +1148, 1150, 1151, 1155, 1165, 1166, 1171, 1174, 1176, 1185, 1189, 1200, +1203, 1204, 1207, 1217, 1236, 1237, 1238, 1240, 1249, 1256, 1260, 1262, +1263, 1279, 1280, 1292, 1303, 1304, 1326, 1327, 1328, 1330, 1342, 1350, +1351, 1352, 1353, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, +1365, 1366, 1368, 1369, 1374, 1375, 1376, 1377, 1381, 1558, 1559, 1759, +1760, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1814, 1815, +1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1828, 1829, +1830, 1831, 1836, 1837, 1848, 1849, 1860, 1861, 1862, 1863, 1864, 1865, +1866, 1867, 1870, 1871, 8, 25, 26, 27, 51, 53, 80, 81, +92, 93, 130, 132, 134, 136, 146, 174, 198, 199, 200, 201, +228, 229, 232, 233, 256, 264, 266, 267, 321, 322, 374, 398, +434, 442, 451, 471, 483, 484, 485, 486, 492, 499, 545, 546, +556, 557, 566, 579, 611, 647, 655, 657, 668, 672, 756, 757, +758, 761, 762, 763, 764, 780, 789, 792, 799, 801, 812, 813, +817, 824, 826, 850, 851, 857, 877, 878, 879, 932, 933, 934, +949, 950, 953, 960, 961, 990, 1011, 1016, 1017, 1035, 1042, 1052, +1053, 1065, 1067, 1068, 1103, 1135, 1159, 1229, 1275, 1276, 1283, 1294, +1295, 1296, 1297, 1319, 1332, 1341, 1350, 1351, 1378, 1417, 1512, 1513, +1588, 1589, 1846, 1847, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, +1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, +1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 15, 16, 40, 151, +153, 386, 387, 423, 424, 562, 687, 688, 864, 865, 866, 1004, +1005, 1064, 1067, 1086, 1125, 1180, 1181, 1182, 1183, 1184, 1191, 1192, +1193, 1194, 1215, 1234, 1248, 1269, 1300, 1303, 1307, 1309, 1312, 1313, +1317, 1902, 1903, 1904, 1905, 1910, 1911, 1912, 1913, 1914, 1915, 1916, +1917, 145, 160, 255, 669, 782, 786, 850, 874, 941, 944, 1163, +1179, 1186, 1289, 1486, 1487, 1858, 1859, 1900, 1901, 1918, 1919, 1920, +1921, 1922, 1923, 1924, 1925, 17, 25, 37, 43, 47, 52, 77, +92, 94, 143, 157, 159, 161, 165, 167, 188, 189, 191, 195, +196, 197, 198, 199, 200, 201, 202, 206, 207, 208, 209, 213, +218, 219, 220, 222, 224, 226, 228, 230, 231, 232, 234, 235, +236, 238, 240, 242, 244, 246, 248, 255, 258, 259, 260, 264, +268, 272, 273, 276, 280, 285, 289, 290, 293, 296, 300, 308, +310, 311, 312, 313, 314, 315, 316, 321, 323, 324, 325, 326, +327, 330, 331, 332, 336, 341, 342, 343, 344, 345, 351, 352, +353, 354, 355, 361, 373, 377, 378, 420, 433, 447, 448, 452, +501, 502, 511, 513, 515, 517, 518, 519, 520, 521, 522, 534, +535, 537, 538, 539, 540, 543, 547, 549, 554, 556, 569, 595, +653, 654, 658, 662, 693, 694, 695, 697, 701, 702, 703, 704, +705, 706, 710, 712, 715, 719, 723, 727, 731, 732, 733, 734, +735, 740, 744, 748, 765, 777, 852, 861, 866, 885, 900, 920, +921, 924, 943, 973, 976, 985, 989, 1018, 1032, 1045, 1047, 1058, +1059, 1063, 1067, 1068, 1078, 1090, 1122, 1123, 1149, 1155, 1156, 1187, +1214, 1227, 1233, 1239, 1240, 1245, 1246, 1255, 1316, 1335, 1344, 1346, +1356, 1359, 1361, 1363, 1365, 1412, 1413, 1414, 1801, 1802, 1926, 1927, +1201, 1329, 1663, 1664, 24, 978, 1127, 1153, 1711, 1712, 1930, 1931, +85, 86, 528, 1243, 1273, 1832, 1833, 1932, 1933, 1934, 1935 }; + +struct ReplacementIndexStruct { + utf16char ch; + medium count; +}; + +const internal::checksum ReplacementChecksums[] = { + +0xAE1DAB16U, 0x8F27A2AU, 0x465496D5U, 0x892E9135U, 0xD621DD31U, 0x40D5B583U, 0x23598B8CU, 0x174C4A14U, 0x9739B1DAU, 0xF448853DU, 0xF3DF7DF2U, 0x15D5108FU, +0xE8A0D4E8U, 0x8FBCAF62U, 0x95F9E2A9U, 0x47CEA738U, 0x839E1EBCU, 0xA58AFD2AU, 0xAAA850BDU, 0xBBEE1755U, 0x4F9A8CDDU, 0x77C2915FU, 0x42B9AA72U, 0xABB65511U, +0x984E9DE9U, 0x229620B8U, 0x11744AD7U, 0xDEA4DF8BU, 0x3DDDF327U, 0xC9016AA9U, 0xDD058F8EU, 0x33167FFDU, 0xCF4EB7B4U, 0x5E990F1U, 0xB6610B6U, 0xF3DA224AU, +0xDDF16CC9U, 0x26FBBFD8U, 0xF0D58D6U, 0x9F57820DU, 0xCAEFB5CCU, 0x868C5775U, 0x36F0B13EU, 0xC2104FC3U, 0x635ED438U, 0xFE76A6BFU, 0xAF98DEFEU, 0xC4A1CE0BU, +0x24A144DU, 0xA07F4113U, 0xA1B56E69U, 0x7AC6D4C1U, 0xA6737D27U, 0x3841C7E7U, 0x7BD9C74BU, 0x57960B20U, 0xA3016C3FU, 0x47DE3B8DU, 0x347522B4U, 0x3DD97630U, +0x283C812CU, 0x62FCCC72U, 0x2A8707F7U, 0x4CAAF872U, 0x7DE5251FU, 0xA1CE4738U, 0x65284ADEU, 0x3CAC3D83U, 0xBBB37EE8U, 0xB74B407AU, 0xBB721077U, 0xD5827C60U, +0xE79C25ACU, 0xF3A0B08AU, 0x754CB19FU, 0xC53F5EC8U, 0x2FB36C45U, 0x8A111CA0U, 0x16625752U, 0xC7DA2CAAU, 0x50A359D4U, 0x9E85659AU, 0xA6832DF5U, 0x7F7A32B5U, +0x349608E1U, 0x3CA5EFD1U, 0xBEEDA352U, 0x10FF4E8EU, 0x5A37598EU, 0x92500B16U, 0xD5E5CEF4U, 0xF9ABE6FBU, 0xEF0313FDU, 0x5D682C8AU, 0xD1D48498U, 0x4DA7CF6AU, +0x2B17F5C6U, 0xA903A376U, 0xCA823961U, 0x829E9619U, 0x8F456FB4U, 0xCC6B224AU, 0x75B42ABFU, 0xCD7DECEFU, 0x73290221U, 0xDF8E5CD8U, 0x1D568D7CU, 0x7F2FCD63U, +0x539DB28DU, 0xB9BB5841U, 0x88EB5D8DU, 0x30B6C9CCU, 0xEA5F5485U, 0xF282B417U, 0x46508060U, 0x8C9D5E3EU, 0xBC04162BU, 0xFA329E5DU, 0xC885E4CCU, 0xDCBF9DCAU, +0x4715B337U, 0x2FDC1366U, 0x3E3BBA50U, 0x9F2BF2CU, 0x73F18BAU, 0xB561B097U, 0x6DC1E6EFU, 0x9000A7E8U, 0xEE613496U, 0xCAD661B5U, 0xADEFBC1EU, 0x717A2494U, +0x10ED817CU, 0xD5497538U, 0xC264618U, 0xA723C789U, 0x365CA2E0U, 0xC4AE628U, 0xDAD44170U, 0x69B2A699U, 0xFA94A82BU, 0x9500E45FU, 0x641EDBEU, 0xBBC0F4D2U, +0xE21AA1F5U, 0x7FDEA451U, 0x5F8E4A17U, 0x9682906DU, 0x41B84148U, 0x6659DDC9U, 0xBA4A5BADU, 0x14B31920U, 0x1360E730U, 0x590C5708U, 0xF019A4AAU, 0x5089CA96U, +0xF0B0E775U, 0xFDD90E49U, 0x1BF1824BU, 0xE13025FCU, 0xEF137B9DU, 0x7935115AU, 0x718BD26AU, 0xF09E5811U, 0x7BA332A6U, 0xA7615393U, 0x73FAF11U, 0x55936B7CU, +0x141AF304U, 0x65E071DDU, 0x97589D6U, 0x73A15F22U, 0xB2FDF279U, 0xD6B59BAEU, 0x27ABA3E6U, 0x2367BEC9U, 0xE7C938F9U, 0x560FEC09U, 0x12C5119U, 0x5001267U, +0x85080CCDU, 0xA3B79EC5U, 0x960F8445U, 0xF895CC46U, 0x3A3AF35CU, 0xC4A951A1U, 0x6BE7869BU, 0xEA4D4D5BU, 0xAE72E7B2U, 0x4282D2C1U, 0x33ECB6EBU, 0x4415ADC3U, +0xC78A4A6EU, 0xA58D62B2U, 0xF3E3048EU, 0x1B8D6392U, 0x147A0701U, 0xE63DAAF0U, 0x8DDD9273U, 0xF5A4B231U, 0x9FF25F7FU, 0xDDEA0DB3U, 0x5CEB285U, 0x7DB792C7U, +0x750B1EB5U, 0x57AE509CU, 0xC8F777C2U, 0xBCD1360BU, 0x632D2CA8U, 0xBC462336U, 0x602E733DU, 0x2194100DU, 0x2FB69E71U, 0x58D9C98U, 0xD3907616U, 0x40B025B8U, +0x8638D05AU, 0xE4433DD5U, 0xB399E080U, 0xEB05158DU, 0x21E41D29U, 0xA97B497EU, 0x7DF9E406U, 0x2B2DDA74U, 0xBA0D8072U, 0x23F15693U, 0x69AB4478U, 0xE134102FU, +0x8522D229U, 0x1CDE04C8U, 0x1021B3B1U, 0x685893F3U, 0x548FAB48U, 0x3926C75EU, 0xCD7FFCC1U, 0x95E309CCU, 0x70DCC40DU, 0x5809E8BDU, 0xC3D9F1CBU, 0x15C41B45U, +0x461F4802U, 0xCE801C55U, 0x39156F0DU, 0x3AE08EU, 0x8D001528U, 0x51684523U, 0x85F53FF7U, 0x53E8D579U, 0x81AED8F1U, 0x5DC688FAU, 0x88B16330U, 0x43104043U, +0x364A68E3U, 0xA3F2B218U, 0x84AC213BU, 0x752D5FFCU, 0xA15A7026U, 0x2CD52C5U, 0x8C136450U, 0x1A32A58U, 0xBE1AD3FCU, 0x368587ABU, 0x24762692U, 0xDB6866FU, +0xDBFE03C1U, 0x32805E0BU, 0xBDB344CU, 0xB6576FD7U, 0xCE602BD5U, 0xD9A1C5D8U, 0x1E451C58U, 0xA3C947C3U, 0x8A5E6F27U, 0xA76375AEU, 0x5A7B58AAU, 0xE7F70331U, +0x9E18A785U, 0x5E2B2BB3U, 0x4E3D9008U, 0xF3B1CB93U, 0xFE1D8CFCU, 0xC732037FU, 0xE5F2028FU, 0x922F93ECU, 0x3B1CD1U, 0x489442A4U, 0xF7CEB34U, 0xE3308006U, +0x9E89A82AU, 0x88E25FD7U, 0xBA9183F8U, 0xC98F90D9U, 0x111E8936U, 0xAB056753U, 0x3E5DD491U, 0x83D04BE3U, 0x7419BEF7U, 0xDEC343D9U, 0xDF53B75BU, 0x8D38CBC1U, +0x9E65B31DU, 0x49E9647BU, 0x487990F9U, 0x8586DA3AU, 0x8D4BA4A5U, 0xE27A2FD3U, 0xCF0F75B3U, 0x506B7DCCU, 0x7729EE20U, 0x83A892CEU, 0x1724B686U, 0x1D5443E6U, +0xF994FF2AU, 0x606829CBU, 0x4F6BD1AEU, 0xB8F93024U, 0xF6C1C490U, 0x6F3D1271U, 0xE8119B5BU, 0xB7AC0B9EU, 0xA93D2434U, 0x9CBC7723U, 0x5384167CU, 0x6CC02C32U, +0xE3AEFA3BU, 0x96ACCCB8U, 0x93EDFEB5U, 0xB455ABEU, 0xE0468B3U, 0xD2638E77U, 0x85F33C85U, 0x53C0FE60U, 0x40A0CF69U, 0xCE296866U, 0xDD49596FU, 0x89ED9A7CU, +0xB2168218U, 0x2A16FE9FU, 0xC6158813U, 0x96D819A0U, 0xF1CB7821U, 0xF0B3234EU, 0xC76DD37CU, 0xF6999932U, 0xA6540881U, 0xC1476900U, 0xBF852F50U, 0x885BDF62U, +0x2B6EA5F0U, 0x7BA33443U, 0x1CB055C2U, 0x406B945CU, 0x21FBAB96U, 0x25A9EEF7U, 0x29D0280DU, 0xDCD83354U, 0x95D847CAU, 0x193AD0D7U, 0x65149603U, 0x875F1D51U, +0xF2D6AE5EU, 0x9E89C614U, 0x71040E80U, 0x2F6DB3B1U, 0x4FBD2D4DU, 0x382CE581U, 0x8682E54AU, 0xC6CE3C16U, 0xD0CDB310U, 0xC097D2DCU, 0x61442A6DU, 0x803FC77EU, +0xBFABF3D6U, 0x2AB83F69U, 0xB70E7066U, 0x1BED886U, 0xE496DD92U, 0x125067C1U, 0xF2BDF6E8U, 0xA1E56DA4U, 0x1D17DA74U, 0xD6E2180AU, 0x96AAE39BU, 0x9E79ED3CU, +0xFE814EF2U, 0x55E387B6U, 0x38A8B47FU, 0x1BD7ADCCU, 0xB200788AU, 0xC063E892U, 0x7E1CEC20U, 0x62C476EDU, 0xF83527BEU, 0xCB64655U, 0xF85F383EU, 0xEFE50809U, +0xA32D4B9DU, 0x14325108U, 0xC46CF3FCU, 0x8646A4A2U, 0x24231E6EU, 0xE8DC260CU, 0x9CA8A446U, 0x4A5517EBU, 0xCDBD569CU, 0xB4C0F066U, 0xF1C615D9U, 0x14C9784FU, +0xC35ACFA4U, 0xA1F99F39U, 0xDB5D327U, 0x16208387U, 0x487A6530U, 0x8B83FB15U, 0x47AA297BU, 0xA6838556U, 0xFE99F07BU, 0xAAC72C75U, 0xD7EE632BU, 0xCC9E80CU, +0xDC478D7BU, 0x7E2514C1U, 0xEC7A9229U, 0x7EFF1AE2U, 0xDA58F332U, 0x7FFD9AE0U, 0xD62250F0U, 0x36FF2FD3U, 0x5343E85AU, 0x8ADA0754U, 0x7DE1A231U, 0x73105D3AU, +0x9EA10A8CU, 0x454632DU, 0x2AFBA286U, 0x638306DBU, 0xD0EE5B94U, 0xBDBA49B8U, 0x26400C9AU, 0xB8A32501U, 0xED50973AU, 0x96A4B4A6U, 0x532A2EC9U, 0xC01BA957U, +0x11CDDFF8U, 0x38F60BF1U, 0xAA9B52FCU, 0x709E7D5BU, 0xD63F1DE9U, 0xE5D7E3BU, 0xF7AF95C2U, 0x3D792D12U, 0x77418D32U, 0x3AF7B59U, 0xDF7CC644U, 0x796A3A58U, +0x2A0F1115U, 0x8E3D8B1FU, 0x3EE734ECU, 0xA157B457U, 0x19AD5091U, 0xA348A4DCU, 0x4F107817U, 0xD65CF7B3U, 0xBD678059U, 0x5D63C132U, 0xB71ABEBBU, 0x3E76DFA6U, +0x7B931373U, 0x4C62A6D8U, 0x57F03940U, 0xB2A038EEU, 0x5FDF9A23U, 0xA0263983U, 0x7E882A01U, 0x9DFC1084U, 0x7072D927U, 0xD8FDE69FU, 0xE0E7157BU, 0x58F4B5B9U, +0x57E98EE9U, 0x2B7F17D5U, 0xBF5D536FU, 0x19B4B8DDU, 0x670EE546U, 0x759F5B56U, 0x521D3385U, 0x54FF4F92U, 0x2D9CBF6AU, 0xD0F0ACFBU, 0x41F4137CU, 0x3ECD73DCU, +0xD98F534U, 0xAFC9093DU, 0x11EB63E2U, 0x69341E0FU, 0x45C58EDBU, 0xDFF71D29U, 0xBACC8D3CU, 0x795F863CU, 0xDA5B599FU, 0x756A6CFCU, 0x492FD69AU, 0x29F01476U, +0x6E924FB3U, 0xE8B85ECU, 0x2AC4EC3FU, 0xF77C2327U, 0x4D7BA0B7U, 0xC9C38BCEU, 0xC46345A2U, 0xA8C65A6U, 0x1A0CBBA0U, 0xC6B953FBU, 0xF469483CU, 0xE8DBA058U, +0x55E1E9EDU, 0x220DF006U, 0x752BEE8CU, 0xFBB8B0D5U, 0x16F0C1B5U, 0x6F47CA15U, 0xE7DF0A66U, 0x93AA672CU, 0xA4B0DB5U, 0x9798D36AU, 0x210C73B2U, 0x2D884E0BU, +0x2CF555C5U, 0x2594AF17U, 0xF92DA22FU, 0x4C553278U, 0x559C4DCU, 0x2FEF17FCU, 0xF479A777U, 0x13EC6D08U, 0x507AFB0FU, 0x3DBD6B73U, 0xD3DAA910U, 0x56D07CCDU, +0x76F544DDU, 0x8D972880U, 0xFF842DA6U, 0xAB51C2E8U, 0xFE925847U, 0x1266FB35U, 0x9951A06U, 0xD3FF1DF6U, 0x51D302CEU, 0x66FB4072U, 0x3338DADDU, 0x67610EA3U, +0x8FD669ECU, 0xE3411213U, 0xA28A9DA9U, 0x170B62DFU, 0x46D9B7D7U, 0x3BAA86EEU, 0xF0257FF7U, 0x6DBF878BU, 0x520CEC4CU, 0x4A7596BEU, 0x732E55FDU, 0x36069DA1U, +0x17D3C5EEU, 0xCCBE59DCU, 0xF17154B8U, 0xFED05FF9U, 0x70F66BAAU, 0x668A255FU, 0x5E1E3F24U, 0xC6AA9101U, 0xA9DF1308U, 0x1CE8989FU, 0xF2C4756CU, 0x606CB509U, +0x2394B2A6U, 0x16C80794U, 0x2A219240U, 0xAE1222A3U, 0x8CB97B86U, 0x4CACE737U, 0x8EC4A97AU, 0xE6AE7EDU, 0xB911D42CU, 0x6C05079AU, 0x2A97030AU, 0x1E97978CU, +0xA9209129U, 0x859AA93BU, 0xC97EF510U, 0x66821408U, 0x54C18CD7U, 0x66B85367U, 0x5C604485U, 0x3A9FAE2U, 0x3CD0C352U, 0x92F9FA79U, 0xC17824C7U, 0xB803EAFU, +0x538FB0D3U, 0x948FC967U, 0x41D70FEBU, 0x8F21EB7FU, 0x90F8A446U, 0xD768A2BEU, 0xDDABF113U, 0xD17178C2U, 0x56378FD7U, 0xBED2C72U, 0x93D47BEAU, 0xAEA4D915U, +0xF5601C83U, 0x317F54CBU, 0x10AA0C84U, 0xD907DC46U, 0xE342A78AU, 0xBD65E28U, 0xB389E207U, 0x3BD7614EU, 0xC08B5199U, 0x4E118784U, 0x48C31E39U, 0x7CF71C84U, +0xB0B24B2CU, 0x1FE25283U, 0x629F7C2DU, 0x57EF2916U, 0x2B576B96U, 0xCE051BEAU, 0xEC16C919U, 0xBFF3A0CBU, 0xE838218DU, 0xEE352A21U, 0xE38E5B7FU, 0x3A8BB7DFU, +0x1F0ECE93U, 0x5385D9B7U, 0xAC29F8F4U, 0x575DB2ADU, 0xACBF183FU, 0x567EEE14U, 0xE8AD89DBU, 0xE3E9CEBBU, 0xD8CE4D00U, 0xBA789F5AU, 0xF87F77BBU, 0x4A4B351BU, +0xCF96A065U, 0x74744A1FU, 0xD93F0955U, 0x4F6722B3U, 0xFDCD24EEU, 0xE6A9F921U, 0x166CC0D6U, 0xB92186A0U, 0x29211071U, 0xD978BCDDU, 0xB14992FCU, 0x19854E77U, +0x3FE60A5U, 0x58FC1E58U, 0x10475664U, 0xDAFCA3E6U, 0xFDCAE1D1U, 0x82D2915DU, 0xE3DFF22AU, 0x130FDF55U, 0xD3B59A0FU, 0xD5F60290U, 0x6CCD0385U, 0x58438A99U, +0xDE26F199U, 0x3E40DEB9U, 0x706B5E46U, 0x3B8DBFD5U, 0x28CAFF29U, 0xD0A47AE4U, 0x3AA9B57AU, 0x8504AFF7U, 0x5E28BCA3U, 0xFBE90C93U, 0xEAD04C12U, 0xCB24B726U, +0xF6C65A18U, 0x2A34D380U, 0x62E270A6U, 0x6E546C36U, 0x31006A54U, 0x29503BFAU, 0xBF30759DU, 0xA18BD87CU, 0xA2D5259U, 0x34D4508EU, 0xCDF525B8U, 0xD28710F0U, +0xB2863FDDU, 0x9F9E5922U, 0xE1642FD1U, 0x12D001U, 0x16F6CE5BU, 0x70B1EF12U, 0xA6AC059CU, 0xBBEBD881U, 0x472BCFE6U, 0xE62890CU, 0xA80B1464U, 0xC5A27872U, +0x3BEA65ABU, 0xA8392847U, 0x279F356AU, 0x7F03C067U, 0x7D764E6CU, 0xA208B04BU, 0x110FA646U, 0xFC591AA1U, 0x4B671A82U, 0x8737FAAAU, 0x552AF746U, 0x21D61F84U, +0xB82AC965U, 0x3B3F074FU, 0x60BBD08AU, 0x426CB588U, 0xDB906369U, 0x9B6900FEU, 0x3017A86U, 0xEEDF7292U, 0xC60A5E22U, 0x19DDB430U, 0x7B87C150U, 0x49FFE8C2U, +0x875E3C9U, 0xEFB8D540U, 0xBB551FEU, 0x485E57B1U, 0x7171D832U, 0xAA37823U, 0xB678C79CU, 0x9AD6EC38U, 0x6CB5177AU, 0xE42A432DU, 0xA711D2F5U, 0xDF1942E9U, +0x92D028AU, 0xF00C77BCU, 0x7049BC1CU, 0xA2670B26U, 0x20B4D99EU, 0x8BEAF43BU, 0xEA39A146U, 0x14F38D7U, 0x3A72453FU, 0x464E138BU, 0xC1B90DE8U, 0x9EAD10B7U, +0x1E4CB9E4U, 0x2CF77C5BU, 0x8927E59AU, 0x7116D68AU, 0xBB545FEBU, 0x81B4AA98U, 0xD01859CAU, 0xDF71061U, 0x479A64C4U, 0x71B1C5DBU, 0x5964E96BU, 0xF1560394U, +0xF28823A4U, 0xE4E97619U, 0x1295A088U, 0x7049FDAU, 0xE592D573U, 0x3535BE69U, 0x1619B844U, 0xD727F3DEU, 0x13232E2BU, 0x51338796U, 0x4B84738U, 0xF482392DU, +0xAB40F973U, 0x9E36BDD6U, 0x3845F022U, 0xA2F40E8BU, 0xC698595DU, 0x87D8352DU, 0xEEB9CC7FU, 0xC644164DU, 0x4CDBDEAFU, 0xE2DE7491U, 0x31F7EB3DU, 0x9599038U, +0x9D918DA1U, 0x65E89B01U, 0x886E82A6U, 0xFFFE534AU, 0xE151673CU, 0x2026F087U, 0x6D682B4EU, 0xDEF444BDU, 0xF1416D33U, 0xBA2D6D03U, 0xEEFF589AU, 0xD41F5106U, +0xDE088E4CU, 0x999A79F6U, 0xE8AEA3D0U, 0xE93324AEU, 0xAD49F7U, 0x5FE7A23DU, 0xC1728CACU, 0x60B9C80EU, 0xE3F2AFEBU, 0x95F0722U, 0xA039D72EU, 0xD6262CCFU, +0x76C373F8U, 0xB040A838U, 0xCF9DD85FU, 0x89EE399BU, 0x4280BC28U, 0xFC69FC63U, 0x3D05B634U, 0x49B5C357U, 0x6E56C308U, 0x1754FB6U, 0xBB51865DU, 0x8715888CU, +0x1D1552DU, 0xB7351D91U, 0x4537E08EU, 0xAD2738D0U, 0xAE6891D3U, 0x3D480692U, 0x964B44CEU, 0x7F89BA71U, 0x2E2BD03U, 0x7686B89FU, 0xDC21E010U, 0xC76B9756U, +0x51599457U, 0x9E6B1EDU, 0x9A6FBFC1U, 0xBBC871A0U, 0xC3FAEA7CU, 0xFAD6BDE8U, 0x1D426A4FU, 0x54E93201U, 0x23516287U, 0x7D2AAB9U, 0x3D14944U, 0x20F91670U, +0x7A1502CDU, 0x5A8B6DF7U, 0x2D7BE547U, 0xC7686672U, 0x6101B9D7U, 0x6D9E58AFU, 0xEB0B3F26U, 0x92FD1CE6U, 0x10438777U, 0xB9A6DF98U, 0x8F21D6D6U, 0xA5DC42D9U, +0xAA8A7A11U, 0x97ABDF97U, 0xF820B371U, 0x12E7060FU, 0x7898B7E6U, 0xECC6032BU, 0x9CD6CAB9U, 0x3BC2405BU, 0x16974E59U, 0xB1168D81U, 0x2F1E6611U, 0xCEFB7A8CU, +0x399695C7U, 0x116814AFU, 0x588FA645U, 0xC9B298CDU, 0xC2BC200U, 0x264CB5CEU, 0x9C43107EU, 0xA1A8D07EU, 0xE6BF9B30U, 0xDAAEEB22U, 0x9AE019F0U, 0xE91C586BU, +0x2C799952U, 0xE5A1E7CEU, 0x405A2DB6U, 0x804346D2U, 0xBE708250U, 0x67B107D0U, 0xC596A1FBU, 0xB7E8AC33U, 0x829235A2U, 0xA0D9823DU, 0x46D24122U, 0x2B9EA93U, +0xA1C073C6U, 0xC4EAFBEU, 0x9CBCA0CEU, 0x87CB523EU, 0x93F53F24U, 0x30F100CBU, 0xC76E5C71U, 0xC5B21FE9U, 0xEEEE5BF8U, 0xBB647D0EU, 0xE0A73F06U, 0xC685C32DU, +0x1C5C9B9BU, 0x2A44CEAU, 0x9534296EU, 0x5A5EC350U, 0xB3780B29U, 0xE8A4B00U, 0xF8327784U, 0x996FC0C8U, 0xD67C8539U, 0x621659DDU, 0x1FD6996U, 0xB398D6D2U, +0xBBEC03D6U, 0x3F8504F6U, 0x9FA1B8CEU, 0x83ADB8A5U, 0x9004789FU, 0x99ED15F4U, 0x6883E2DU, 0x3C75FFACU, 0xD2391F74U, 0x66EE73F1U, 0x8FA89A21U, 0x801A7503U, +0x522E1784U, 0x36392E2EU, 0x19DF8128U, 0x6EA25305U, 0x846C8437U, 0x4EE0BEACU, 0xF690FDC5U, 0xF6832E1EU, 0xA48C9379U, 0x5F8921B0U, 0xFE3D1F9CU, 0x4B6BADFEU, +0x2DDBBD52U, 0xFA227036U, 0xFE4FE03AU, 0xD4BD8877U, 0xC255594EU, 0x8A61FE32U, 0x63B85E32U, 0xC24637DFU, 0x39229F39U, 0xF9B405A4U, 0x3EBF9329U, 0xF28B6E98U, +0x81DAA8C9U, 0x55ACEF34U, 0x296DE97FU, 0x5953C3AU, 0x7268DC76U, 0x49C2BAAAU, 0x1FD82E79U, 0xE54C1803U, 0x9CD98442U, 0x4C57DE89U, 0x7FD97D63U, 0x5B3CB6F5U, +0x67B3B2E4U, 0x3F4D318AU, 0x3EC0ABB7U, 0xEE3200C0U, 0x3FA3D082U, 0x4D0F7C4AU, 0x892D309CU, 0x56B3DD2CU, 0xEB5F7612U, 0x2EE42882U, 0xCF07E495U, 0xF2A9BC6BU, +0x9DA909A4U, 0x937B3A8U, 0x363217CFU, 0x9AED0006U, 0x60362015U, 0x5226B280U, 0x8524AEA3U, 0xFBC8F58DU, 0x7B172312U, 0x9CCC34DU, 0xA8AE6F61U, 0xE3CA111EU, +0x59FE8325U, 0x6EC95B2U, 0xF676DCD9U, 0x9A250AE3U, 0x99E585E7U, 0xA62C89BU, 0xC631DEF4U, 0x58BC30C1U, 0x470412E1U, 0xC05117F0U, 0xA51D983CU, 0x1E629C01U, +0x541C0E33U, 0xEB80059DU, 0x129D07E0U, 0x48EDAAD6U, 0x8397F485U, 0x1857F8F0U, 0x97497FE1U, 0xA8AEC1F6U, 0xC8027F76U, 0x736E96A8U, 0x1A578E1AU, 0x6B9FD701U, +0x8B4734B7U, 0x7102220U, 0x13FE645BU, 0xE25D1A59U, 0x7A7D69ECU, 0x9295838AU, 0x6761FB08U, 0x493105F6U, 0x13BF90E3U, 0x6691E578U, 0xC741FD85U, 0x62E01643U, +0xE782CAB0U, 0x3223B5F4U, 0xB36E1464U, 0x2C04AA45U, 0x9260D4CBU, 0x660DB966U, 0x41F2BCF7U, 0xF17D8432U, 0x17C405A6U, 0x87274585U, 0x537E9E9EU, 0x7B344BCU, +0x1E023531U, 0xDD6783A8U, 0xFA37738DU, 0xD7D7F72CU, 0xEAADB26BU, 0x5B511B45U, 0x240A687DU, 0x44E66B55U, 0xD0808C97U, 0xF31BFF35U, 0x9EE5345CU, 0x258906C2U, +0x9860CC4AU, 0xB9CCB14FU, 0x5580726EU, 0x26B182EU, 0x4F6C5C89U, 0x5D26775DU, 0xF0CA22ADU, 0x2DD7CAC5U, 0xD0EDAF27U, 0x8C09D6DU, 0xDCFB88F2U, 0x71C63BCFU, +0xAEC8C854U, 0xC3ADC8F6U, 0xE93C7B65U, 0xC698C893U, 0x8E574092U, 0x92FF3CB6U, 0xF8648ABAU, 0xB5BC2991U, 0x5E05BD9DU, 0xB09A78A0U, 0x15AB67C0U, 0x3FADF7CEU, +0x2927A3FDU, 0x445BA5DBU, 0xFA3008B2U, 0x2891DB6BU, 0xDBB845FU, 0x573B85ECU, 0x18F54327U, 0x74F4356BU, 0x95971E70U, 0x4470A211U, 0xB905173DU, 0x414D94A9U, +0xE929B3ADU, 0xAE3B8A7AU, 0xFF18EB1U, 0xEE383B0CU, 0x7B04D607U, 0x693E6DA4U, 0xC3FB577EU, 0x7AC48735U, 0x1A99C4ADU, 0x45B0C657U, 0x5CC05A5U, 0xE24AE587U, +0x884FA08EU, 0x5BCE0610U, 0xCCBADA00U, 0xEEBE62E2U, 0x1BED96D4U, 0xFF9731C4U, 0x5644B2A0U, 0x9119ABCAU, 0x28FC1FE4U, 0x983CF251U, 0xF92F5A3BU, 0xDC9DC061U, +0x5B150730U, 0xCB5F1CBDU, 0x5966470CU, 0xE5C92630U, 0x974502D1U, 0x2047F98CU, 0x444D6B88U, 0xFB8235EU, 0x359D6CU, 0xC34153C2U, 0x2A95D777U, 0x5B6E4E6FU, +0xB408F38U, 0x2423E46EU, 0x4C85DCE9U, 0xBBEEC84BU, 0xE9D46305U, 0x30187C97U, 0x181599U, 0xF4F90026U, 0x952F111CU, 0x5B9D9750U, 0x624304BEU, 0xCE566F2EU, +0xF5B066E3U, 0xC84AEDC4U, 0x26984E70U, 0xD637245CU, 0xAEADB1U, 0x7F65D377U, 0xDD7410C6U, 0xE156A6E8U, 0x2BDB808BU, 0x3107D6E5U, 0xA654151FU, 0x5DBD1349U, +0x29676B1CU, 0xD9B9A12BU, 0x559571C7U, 0x17D9B1EFU, 0x8EBB69EAU, 0x6E834FD7U, 0x22AF6658U, 0x50FD3DEBU, 0xA35B6E1U, 0x87B78513U, 0x5CA68B6U, 0xF3B77C65U, +0xDAE7ACC8U, 0xBD84E707U, 0xC0B1F2EEU, 0x7C5B280BU, 0x3C82C2A7U, 0xF1848767U, 0xCF397063U, 0x11293CECU, 0x86B3A406U, 0xCF0391E2U, 0xCAE6F488U, 0xA2130914U, +0x80443800U, 0x75A52C98U, 0x255D3BC5U, 0x70B8141FU, 0x52A6D7E8U, 0xF3773CB5U, 0x16682961U, 0xE291D23CU, 0xEA1AB08DU, 0x3AF6AC29U, 0xF077AF0BU, 0xDB42975FU, +0xE4B5A5C3U, 0x828767D9U, 0xCE511DFDU, 0x8FA20C6DU, 0xD4FEEEB4U, 0x3B75D536U, 0x81090466U, 0xB210CB77U, 0xA0A56499U, 0x601ADD2U, 0xAB167BEAU, 0xF706C300U, +0x1B058070U, 0x9F01D362U, 0x52CFBC44U, 0x96A9AB7BU, 0x966588D6U, 0xB899A286U, 0x5EE0407AU, 0x681CEAFFU, 0x4C40811U, 0xB20B7269U, 0x367237BFU, 0x428A0B94U, +0xD691C645U, 0xB12CFF27U, 0x9E6383BEU, 0x6176461EU, 0xFDB47228U, 0x51A94E60U, 0xFBD6A3E0U, 0xF187D05EU, 0x4DA143CFU, 0x49C7CCE6U, 0xB4B52BF7U, 0x3BA3A346U, +0xA803AAFEU, 0x9FC8C67BU, 0xA639766CU, 0x4C6B2408U, 0xED09AD3DU, 0xDBBD48U, 0xE0E2196DU, 0xE9FFEE62U, 0xB50384FU, 0xDFE188A2U, 0x3633AE21U, 0xAEF9F8C9U, +0x80178502U, 0xED42BC9CU, 0x85653DDDU, 0x394C79C4U, 0x71477B3DU, 0xF8C674CFU, 0xD4B8C4E9U, 0x2A5947F9U, 0xFC4C64D2U, 0x6B322B31U, 0xB9B20DFBU, 0x57BB1739U, +0x3D915162U, 0x5AAAA1ACU, 0x91EB2A66U, 0x35CA03C9U, 0xDE6D0202U, 0xCB2E089FU, 0x57048634U, 0xEEBBC058U, 0x3813A5F6U, 0x722CE848U, 0x8479A8A6U, 0xE92B8076U, +0x1B1F3F83U, 0x81D8932FU, 0xFDDDB092U, 0x30D5B4C9U, 0xC91CF267U, 0x36AD135BU, 0x71F52515U, 0xC089EF35U, 0x41038328U, 0x6456724BU, 0x1B2B3E23U, 0xD24210BBU, +0xC62FBD71U, 0xFCAD3662U, 0x8E3F7FF2U, 0xE48AE1B8U, 0xD23BC8ABU, 0xEF89F436U, 0x62BCE039U, 0x1A5DE46CU, 0x16236FU, 0xCA241E6DU, 0x9EEE203BU, 0x3D3879E4U, +0x1D1C6180U, 0xD378251U, 0xE2BA4A87U, 0x66DFA1A0U, 0x7418FB2CU, 0x6CB7295CU, 0x9F7002F9U, 0x1F7DE611U, 0x5FA0D6B3U, 0xA466F742U, 0x8E097065U, 0x7F7B3458U, +0x25360EB8U, 0xE8ADA4B0U, 0x18B1FE00U, 0x2AC22D1CU, 0x4186B027U, 0x959C76EAU, 0x8872FA1EU, 0x486317D3U, 0xED35E29BU, 0xB17E878U, 0x8F6CC5FCU, 0x2E8831DBU, +0xFA55FF05U, 0x6FEFF36U, 0xBE942D00U, 0x36B6480EU, 0x4C5D91EFU, 0xEB2C7AC2U, 0xEA33683AU, 0xB8A51C5EU, 0x8BF2227BU, 0xF37E24F6U, 0x864012FU, 0x5DE7786U, +0x3EFEC660U, 0xE2761ACU, 0x54A6C4ABU, 0x4047D505U, 0x37FBD45CU, 0x65D5D78BU, 0xBE3CF030U, 0x4A150EFBU, 0x2F283083U, 0xCB47C04DU, 0x973EDABU, 0xD6BC301FU, +0xD792EACU, 0xEEA55E7U, 0xAB40BD74U, 0x2CAC2CA8U, 0x9B8691CAU, 0xF0EF8D89U, 0xA743045FU, 0xB76BFEDU, 0x76DD731AU, 0x3752687U, 0x968C7740U, 0x770D8687U, +0xF6DE8D96U, 0x91B3A983U, 0x7228545U, 0xA8134914U, 0xFD9A01E6U, 0x72386ADDU, 0x845A80A6U, 0x10675D75U, 0x31032835U, 0xB6510D2AU, 0x67E9C2D9U, 0x8C073B5FU, +0x348F2BA5U, 0xE4DF38ECU, 0x535EDE00U, 0xE31FD2EFU, 0xAA5BD7DCU, 0x9D963F06U, 0x8D26D2E9U, 0x5D76C1A0U, 0x95131597U, 0x25521978U, 0xA549BA78U, 0xFC809EA1U, +0x9CC1A4E2U, 0x58043720U, 0xE3BD3B7BU, 0xED684815U, 0x8A1B48E8U, 0x9C5BFCA1U, 0x1C5A009AU, 0x7485B1C1U, 0xCA86F28AU, 0x32FA853AU, 0xB3626483U, 0x972DA82DU, +0xE492749AU, 0x35CA2D1DU, 0xC1E25D40U, 0xFAA559E2U, 0x27472E18U, 0xEA8FB72AU, 0x5D846824U, 0x77540CDAU, 0x45717960U, 0x57C4D68EU, 0xEF78B1EBU, 0x72AF8952U, +0xCA13EE37U, 0xD8A641D9U, 0x601A26BCU, 0x387936EAU, 0x80C5518FU, 0x47E9CBACU, 0xFF55ACC9U, 0xEDE00327U, 0x835DF178U, 0xDD2F69BU, 0xC178F605U, 0xCBBDFF1CU, +0x717FF82U, 0x8998F861U, 0x4532F8FFU, 0x9C12EA53U, 0x50B8EACDU, 0x2E8AEB86U, 0xE220EB18U, 0x6CAFECFBU, 0x6D9D258CU, 0xBC42E87CU, 0x61A4E33U, 0xCFB8C4FU, +0x81664E1AU, 0x13BBA529U, 0x5BFB8755U, 0x5B9E60F1U, 0x89633A85U, 0x3E0560D0U, 0x39A51A29U, 0x8EC3407CU, 0xE6DEDAE1U, 0x51B880B4U, 0xC3614311U, 0x74071944U, +0xEEA49D28U, 0x59C2C77DU, 0x236AF20EU, 0x940CA85BU, 0xF46B750FU, 0x430D2F5AU, 0xD1002AD3U, 0x66667086U, 0x44AD55A3U, 0xF3CB0FF6U, 0x31DF5DE0U, 0x86B907B5U, +0x5618FA4DU, 0xE17EA018U, 0x5E62BD84U, 0xE904E7D1U, 0x61C60A7FU, 0xD6A0502AU, 0x796DEC4CU, 0xCE0BB619U, 0xCBCFC2F4U, 0x7CA998A1U, 0x7373A591U, 0xC415FFC4U, +0x93ACD2A2U, 0x24CA88F7U, 0x6830EF86U, 0xDF56B5D3U, 0xEF283F18U, 0x584E654DU, 0xA5FE80A0U, 0x1298DAF5U, 0x8095DF7CU, 0x37F38529U, 0x78D0FE2U, 0xB0EB55B7U, +0x1D42E7C5U, 0xAA24BD90U, 0x1538A00CU, 0xA25EFA59U, 0x4521F793U, 0xF247ADC6U, 0xD8F6CF2AU, 0x6F90957FU, 0xF5E7D73FU, 0x42818D6AU, 0x72FF07A1U, 0xC5995DF4U, +0x92207092U, 0x25462AC7U, 0xE75278D1U, 0x50342284U, 0xD08C88E3U, 0x67EAD2B6U, 0x1838F762U, 0xAF5EAD37U, 0x6112CC53U, 0xD6749606U, 0x2F0C6FC3U, 0x986A3596U, +0xCA4360C4U, 0x7D253A91U, 0xB74B2F4EU, 0x2D751BU, 0xFF7482BU, 0xB891127EU, 0x5794587DU, 0xE0F20228U, 0xC8276ED0U, 0x7F413485U, 0x13AA1C8FU, 0xA4CC46DAU, +0x597CA337U, 0xEE1AF962U, 0x52EE48DAU, 0xE588128FU, 0x94B2CC11U, 0x23D49644U, 0xC239270DU, 0x755F7D58U, 0x20825E2AU, 0x97E4047FU, 0xC4AB9B8EU, 0x73CDC1DBU, +0x70716126U, 0xC7173B73U, 0xAC65B06DU, 0x1C7021BFU, 0x11FB361U, 0xB679E934U, 0x746DBB22U, 0xC30BE177U, 0xF3756BBCU, 0x441331E9U, 0xB9A3D404U, 0xEC58E51U, +0xFFF99EE2U, 0x489FC4B7U, 0x7C17FCEBU, 0xCB71A6BEU, 0x4106B2AAU, 0xD9C40950U, 0x36C14353U, 0x81A71906U, 0x1BD05B46U, 0xACB60113U, 0x9CC88BD8U, 0x2BAED18DU, +0x7117AB85U, 0xC671F1D0U, 0x860763FFU, 0x316139AAU, 0x2C0EAB74U, 0x9B68F121U, 0xCCD1DC47U, 0x7BB78612U, 0xDE6473A9U, 0x690229FCU, 0x2BC473EBU, 0x9CA229BEU, +0x9378148EU, 0x241E4EDBU, 0xEAF2C37U, 0xB9C97662U, 0xA4A6E4BCU, 0x13C0BEE9U, 0x252C88A1U, 0x924AD2F4U, 0xAA4E1FF6U, 0x1D2845A3U, 0x9764CE8AU, 0x200294DFU, +0x92F4B6BEU, 0x2592ECEBU, 0xCD89B85BU, 0x7AEFE20EU, 0x47D77DU, 0xB7218D28U, 0xE8E2E787U, 0x5F84BDD2U, 0x505E80E2U, 0xE738DAB7U, 0x660CD2E0U, 0xD16A88B5U, +0xE96E45B7U, 0x5E081FE2U, 0xDEB0B585U, 0x69D6EFD0U, 0xCC051A6BU, 0x7B63403EU, 0xFEA1FAFEU, 0x49C7A0ABU, 0x4B1DCAF5U, 0xFC7B90A0U, 0xB1D993CDU, 0x6BFC998U, +0x5F3AD998U, 0xE85C83CDU, 0x41E9EBBBU, 0xF68FB1EEU, 0xDA78A9ADU, 0x6D1EF3F8U, 0xC2EDE121U, 0x758BBB74U, 0x883B5E99U, 0x3F5D04CCU, 0x4D8F7676U, 0xFAE92C23U, +0xCB1B04D8U, 0x7C7D5E8DU, 0xBFE5AEABU, 0x883F4FEU, 0x759C9CEU, 0xB03F939BU, 0x80411950U, 0x37274305U, 0x308739FCU, 0x87E163A9U, 0xF5331113U, 0x42554B46U, +0x2A48D1DBU, 0x9D2E8B8EU, 0x1D9621E9U, 0xAAF07BBCU, 0xA52A468CU, 0x124C1CD9U, 0xE786BEFDU, 0x50E0E4A8U, 0x9A8EF177U, 0x2DE8AB22U, 0xB79FE962U, 0xF9B337U, +0x57409E51U, 0xE026C404U, 0x547CF459U, 0xE31AAE0CU, 0x6BD843A2U, 0xDCBE19F7U, 0x5C06B390U, 0xEB60E9C5U, 0xECC0933CU, 0x5BA6C969U, 0x2F71F45U, 0xB5914510U, +0xA0849007U, 0x17E2CA52U, 0x5D8F4DD1U, 0x785F2A36U, 0xBA4B7820U, 0xD2D2275U, 0xA8FED7CEU, 0x1F988D9BU, 0x77851706U, 0xC0E34D53U, 0xB2313FE9U, 0x55765BCU, +0xA8D588CU, 0xBDEB02D9U, 0x9F2027FCU, 0x28467DA9U, 0x34A54D47U, 0x83C31712U, 0x96D6C205U, 0x21B09850U, 0x335DBD17U, 0xF11165A8U, 0x46773FFDU, 0x9EAC85CCU, +0x29CADF99U, 0x3237F1C4U, 0x8551AB91U, 0x3A4DB60DU, 0x8D2BEC58U, 0x709B09B5U, 0xC7FD53E0U, 0x5FD0B10BU, 0xE8B6EB5EU, 0xC05D2919U, 0x773B734CU, 0x90447E86U, +0x272224D3U, 0xA82A11E2U, 0x1F4C4BB7U, 0x65E47EC4U, 0xD2822491U, 0xBA9FBE0CU, 0xDF9E459U, 0x523A8EF6U, 0xE55CD4A3U, 0xEA86E993U, 0x5DE0B3C6U, 0x3D876E92U, +0x8AE134C7U, 0x6D9E390DU, 0xDAF86358U, 0xCFEDB64FU, 0x788BEC1AU, 0x7751D12AU, 0xC0378B7FU, 0x83A9B574U, 0x34CFEF21U, 0xCCB2223U, 0xBBAD7876U, 0x461D9D9BU, +0xF17BC7CEU, 0x1604CA04U, 0xA1629051U, 0xF6DBBD37U, 0x41BDE762U, 0xAEB8AD61U, 0x19DEF734U, 0x911C1A9AU, 0x267A40CFU, 0x4B165EAU, 0xB3D73FBFU, 0x1E7E8DCDU, +0xA918D798U, 0x336F95D8U, 0x8409CF8DU, 0x21DA3A36U, 0x96BC6063U, 0xBC0D028FU, 0xB6B58DAU, 0x9CF62567U, 0x2B907F32U, 0x4E67DA52U, 0xF9018007U, 0x43678D3CU, +0xF401D769U, 0x54A83275U, 0xE3CE6820U, 0xC97F0ACCU, 0x7E195099U, 0x3B15D211U, 0x8C738844U, 0xEC145510U, 0x5B720F45U, 0x99665D53U, 0x2E000706U, 0x6376C247U, +0xD4109812U, 0xE46E12D9U, 0x5308488CU, 0x29A07DFFU, 0x9EC627AAU, 0xE5E2B0E9U, 0x5284EABCU, 0xA74E4898U, 0x102812CDU, 0xD478013U, 0xBA21DA46U, 0x17886834U, +0xA0EE3261U, 0x4FEB7862U, 0xF88D2237U, 0x62FA6077U, 0xD59C3A22U, 0x20569806U, 0x9730C253U, 0x6A8027BEU, 0xDDE67DEBU, 0x318A297CU, 0x77EFB560U, 0x3A997021U, +0x8DFF2A74U, 0x78358850U, 0xCF53D205U, 0x5D8A11A0U, 0xEAEC4BF5U, 0x8BD3F2BDU, 0x3CB5A8E8U, 0x8DAB26ADU, 0x3ACD7CF8U, 0x53DC7DAU, 0xB25B9D8FU, 0x5FEE1FB4U, +0xE88845E1U, 0x6468DCF4U, 0xD30E86A1U, 0xB3833366U, 0x4E56933U, 0xA94CDB41U, 0x1E2A8114U, 0x262E4C16U, 0x91481643U, 0xDC3ED302U, 0x6B588957U, 0xF9558CDEU, +0x4E33D68BU, 0x4993AC72U, 0xFEF5F627U, 0x535C4455U, 0xE43A1E00U, 0xA1369C88U, 0x1650C6DDU, 0x845DC354U, 0x333B9901U, 0x2E540BDFU, 0x9932518AU, 0xBBF974AFU, +0xC9F2EFAU, 0x9E922B73U, 0x29F47126U, 0x176200A7U, 0xA0045AF2U, 0x1E94E55EU, 0xA9F2BF0BU, 0x7129053AU, 0xC64F5F6FU, 0x4E8DB2C1U, 0xF9EBE894U, 0xE4847A4AU, +0x53E2201FU, 0x3B2B7CAEU, 0x8C4D26FBU, 0x107C1E14U, 0xA71A4441U, 0x3D6D0601U, 0x8A0B5C54U, 0xD1F96FEAU, 0x701F8A2FU, 0xEDCCFBF9U, 0x2C9B1FAU, 0xB5AFEBAFU, +0x6BE6ED1DU, 0xDC80B748U, 0xF0A36927U, 0x47C53372U, 0xA8C07971U, 0x1FA62324U, 0x7FC1FE70U, 0xC8A7A425U, 0x77BBB9B9U, 0xC0DDE3ECU, 0x351741C8U, 0x82711B9DU, +0x9F1E8943U, 0x2878D316U, 0x38FD7E35U, 0x8F9B2460U, 0x481F0E42U, 0xFF795417U, 0xBA75D69FU, 0xD138CCAU, 0x7DA5F064U, 0xCAC3AA31U, 0xF783D92BU, 0x40E5837EU, +0xA0BA3EB8U, 0x17DC64EDU, 0x7535DF3EU, 0xC253856BU, 0x8F25402AU, 0x38431A7FU, 0xC797F186U, 0x70F1ABD3U, 0x604AA84FU, 0xD72CF21AU, 0x47AF9114U, 0xF0C9CB41U, +0x27A2EE26U, 0x90C4B473U, 0xBEBDCAB7U, 0x9DB90E2U, 0xED4C310CU, 0x5A2A6B59U, 0x223D969U, 0xB545833CU, 0x96E86CBAU, 0x218E36EFU, 0xA06EF894U, 0x1708A2C1U, +0x6D74519EU, 0xDA120BCBU, 0x180659DDU, 0xAF600388U, 0xDDB27132U, 0x6AD42B67U, 0xD5C836FBU, 0x62AE6CAEU, 0x2474ECBDU, 0x9312B6E8U, 0xCF07DEDCU, 0x78618489U, +0x32DD9957U, 0x85BBC302U, 0x90AE1615U, 0x27C84C40U, 0xC0B7418AU, 0x77D11BDFU, 0x3AA7DE9EU, 0x8DC184CBU, 0xB5C549C9U, 0x2A3139CU, 0x62C4CEC8U, 0xD5A2949DU, +0x28127170U, 0x9F742B25U, 0xA770E627U, 0x1016BC72U, 0x206836B9U, 0x970E6CECU, 0x1FCC8142U, 0xA8AADB17U, 0x5036965U, 0xB2653330U, 0x52862C08U, 0xBA1F74F9U, +0xEDA6599FU, 0x5AC003CAU, 0x47526A2CU, 0x3D07A467U, 0xCFD318F0U, 0x78B542A5U, 0xA9981D6DU, 0x1EFE4738U, 0x8CF342B1U, 0x3B9518E4U, 0x9BD6956BU, 0x2CB0CF3EU, +0xD0584ECFU, 0x673E149AU, 0x76E3DDA5U, 0xC18587F0U, 0xC625FD09U, 0x7143A75CU, 0x195E3DC1U, 0xAE386794U, 0xBEB922FU, 0xBC8DC87AU, 0xD51CF0D7U, 0x627AAA82U, +0xA67301FU, 0xBD016A4AU, 0x8505A748U, 0x3263FD1DU, 0x52042049U, 0xE5627A1CU, 0x5CECDB03U, 0xEB8A8156U, 0xF22D0FA0U, 0x454B55F5U, 0x7453159DU, 0xC3354FC8U, +0x37734FDCU, 0x80151589U, 0x8D7F827U, 0xBFB1A272U }; + +const ReplacementIndexStruct ReplacementIndexData[] = { + { utf16char(43), medium(1) }, + { utf16char(45), medium(1) }, + { utf16char(49), medium(2) }, + { utf16char(50), medium(1) }, + { utf16char(56), medium(1) }, + { utf16char(97), medium(129) }, + { utf16char(98), medium(226) }, + { utf16char(99), medium(290) }, + { utf16char(100), medium(100) }, + { utf16char(101), medium(70) }, + { utf16char(102), medium(437) }, + { utf16char(103), medium(108) }, + { utf16char(104), medium(138) }, + { utf16char(105), medium(53) }, + { utf16char(106), medium(25) }, + { utf16char(107), medium(53) }, + { utf16char(108), medium(101) }, + { utf16char(109), medium(247) }, + { utf16char(110), medium(74) }, + { utf16char(111), medium(71) }, + { utf16char(112), medium(201) }, + { utf16char(113), medium(8) }, + { utf16char(114), medium(114) }, + { utf16char(115), medium(289) }, + { utf16char(116), medium(148) }, + { utf16char(117), medium(53) }, + { utf16char(118), medium(28) }, + { utf16char(119), medium(211) }, + { utf16char(120), medium(4) }, + { utf16char(121), medium(8) }, + { utf16char(122), medium(11) }, +}; + +std::vector Replacements; +std::map> ReplacementsMap; +std::map ReplacementsHash; + +} // namespace + +void InitReplacements() { + if (!Replacements.empty()) { + return; + } + auto data = ReplacementData; + auto takeString = [&data](int size) { + auto result = utf16string(data, size); + data += size; + return result; + }; + auto wordSize = ReplacementWordLengths; + + Replacements.reserve(1936); + for (auto item : ReplacementInitData) { + auto emoji = takeString(item.emojiSize); + auto replacement = takeString(item.replacementSize); + auto words = std::vector(); + words.reserve(item.wordsCount); + for (auto i = 0; i != item.wordsCount; ++i) { + words.push_back(takeString(*wordSize++)); + } + Replacements.push_back({ std::move(emoji), std::move(replacement), std::move(words) }); + } + + auto indices = ReplacementIndices; + auto items = &Replacements[0]; + for (auto item : ReplacementIndexData) { + auto index = std::vector(); + index.reserve(item.count); + for (auto i = 0; i != item.count; ++i) { + index.push_back(items + (*indices++)); + } + ReplacementsMap.emplace(item.ch, std::move(index)); + } + + for (auto checksum : ReplacementChecksums) { + ReplacementsHash.emplace(checksum, items++); + } +} + +const std::vector *GetReplacements(utf16char first) { + if (ReplacementsMap.empty()) { + InitReplacements(); + } + auto it = ReplacementsMap.find(first); + return (it == ReplacementsMap.cend()) ? nullptr : &it->second; +} + +utf16string GetReplacementEmoji(utf16string replacement) { + auto code = internal::countChecksum(replacement.data(), replacement.size() * sizeof(utf16char)); + auto it = ReplacementsHash.find(code); + return (it == ReplacementsHash.cend()) ? utf16string() : it->second->emoji; +} + +} // namespace internal +} // namespace Emoji +} // namespace Ui diff --git a/TelegramClient.Native/emoji_suggestions_data.h b/TelegramClient.Native/emoji_suggestions_data.h new file mode 100755 index 0000000..29598a1 --- /dev/null +++ b/TelegramClient.Native/emoji_suggestions_data.h @@ -0,0 +1,46 @@ +/* +WARNING! All changes made in this file will be lost! +Created from 'empty' by 'codegen_emoji' + +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "emoji_suggestions.h" + +namespace Ui { +namespace Emoji { +namespace internal { + +struct Replacement { + utf16string emoji; + utf16string replacement; + std::vector words; +}; + +const int kReplacementMaxLength = 55; + +void InitReplacements(); +const std::vector *GetReplacements(utf16char first); +utf16string GetReplacementEmoji(utf16string replacement); + +} // namespace internal +} // namespace Emoji +} // namespace Ui diff --git a/TelegramClient.Native/pch.cpp b/TelegramClient.Native/pch.cpp new file mode 100755 index 0000000..ac95590 --- /dev/null +++ b/TelegramClient.Native/pch.cpp @@ -0,0 +1,8 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#include "pch.h" diff --git a/TelegramClient.Native/pch.h b/TelegramClient.Native/pch.h new file mode 100755 index 0000000..c16b9a4 --- /dev/null +++ b/TelegramClient.Native/pch.h @@ -0,0 +1,8 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once diff --git a/TelegramClient.Opus/COpusCodec.cpp b/TelegramClient.Opus/COpusCodec.cpp new file mode 100755 index 0000000..de27a18 --- /dev/null +++ b/TelegramClient.Opus/COpusCodec.cpp @@ -0,0 +1,166 @@ +//// (c) Seth Heeren 2013 +//// +//// Based on src/opus_demo.c in opus-1.0.2 +//// License see http://www.opus-codec.org/license/ +//#include "COpusCodec.h" +//#include +//#include +//#include +//#include +//#include +// +//#include "opus.h" +// +//#define MAX_PACKET 1500 +// +//const char* OpusErrorException::what() +//{ +// return opus_strerror(code); +//} +// +//// I'd suggest reading with boost::spirit::big_dword or similar +//static uint32_t char_to_int(char ch[4]) +//{ +// return static_cast(static_cast(ch[0])<<24) | +// static_cast(static_cast(ch[1])<<16) | +// static_cast(static_cast(ch[2])<< 8) | +// static_cast(static_cast(ch[3])<< 0); +//} +// +//struct COpusCodec::Impl +//{ +// Impl(int32_t sampling_rate = 48000, int channels = 1) +// : +// _channels(channels), +// _decoder(nullptr, &opus_decoder_destroy), +// _state(_max_frame_size, MAX_PACKET, channels) +// { +// int err = OPUS_OK; +// auto raw = opus_decoder_create(sampling_rate, _channels, &err); +// _decoder.reset(err == OPUS_OK? raw : throw OpusErrorException(err) ); +// } +// +// bool decode_frame(std::ifstream& fin, std::ofstream& fout) +// { +// char ch[4] = {0}; +// +// if (!fin.read(ch, 4) && fin.eof()) +// return false; +// +// uint32_t len = char_to_int(ch); +// +// if(len>_state.data.size()) +// throw std::runtime_error("Invalid payload length"); +// +// fin.read(ch, 4); +// const uint32_t enc_final_range = char_to_int(ch); +// const auto data = reinterpret_cast(&_state.data.front()); +// +// size_t read = 0ul; +// for (auto append_position = data; fin && read0) +// { +// for(int i=0; i<(output_samples)*_channels; i++) +// { +// short s; +// s=_state.out[i]; +// _state.fbytes[2*i] = s&0xFF; +// _state.fbytes[2*i+1] = (s>>8)&0xFF; +// } +// if(!fout.write(reinterpret_cast(_state.fbytes.data()), sizeof(short)* _channels * output_samples)) +// throw std::runtime_error("Error writing"); +// } +// else +// { +// throw OpusErrorException(output_samples); // negative return is error code +// } +// +// uint32_t dec_final_range; +// opus_decoder_ctl(_decoder.get(), OPUS_GET_FINAL_RANGE(&dec_final_range)); +// +// /* compare final range encoder rng values of encoder and decoder */ +// if(enc_final_range!=0 +// && !lost && !_state.lost_prev +// && dec_final_range != enc_final_range) +// { +// std::ostringstream oss; +// oss << "Error: Range coder state mismatch between encoder and decoder in frame " << _state.frameno << ": " << +// "0x" << std::setw(8) << std::setfill('0') << std::hex << (unsigned long)enc_final_range << +// "0x" << std::setw(8) << std::setfill('0') << std::hex << (unsigned long)dec_final_range; +// +// throw std::runtime_error(oss.str()); +// } +// +// _state.lost_prev = lost; +// _state.frameno++; +// +// return true; +// } +//private: +// const int _channels; +// const int _max_frame_size = 5760;// 960*6; +// std::unique_ptr _decoder; +// +// struct State +// { +// State(int max_frame_size, int max_payload_bytes, int channels) : +// out (max_frame_size*channels), +// fbytes(max_frame_size*channels*sizeof(decltype(out)::value_type)), +// data (max_payload_bytes) +// { } +// +// std::vector out; +// std::vector fbytes, data; +// int32_t frameno = 0; +// bool lost_prev = true; +// }; +// State _state; +//}; +// +//COpusCodec::COpusCodec(int32_t sampling_rate, int channels) +// : _pimpl(std::unique_ptr(new Impl(sampling_rate, channels))) +//{ +// // +//} +// +//COpusCodec::~COpusCodec() +//{ +// // this instantiates the pimpl deletor code on the, now-complete, pimpl class +//} +// +//bool COpusCodec::decode_frame( +// std::ifstream& fin, +// std::ofstream& fout) +//{ +// return _pimpl->decode_frame(fin, fout); +//} \ No newline at end of file diff --git a/TelegramClient.Opus/COpusCodec.h b/TelegramClient.Opus/COpusCodec.h new file mode 100755 index 0000000..aed1e6f --- /dev/null +++ b/TelegramClient.Opus/COpusCodec.h @@ -0,0 +1,21 @@ +//#include +//#include +// +//struct OpusErrorException : public virtual std::exception +//{ +// OpusErrorException(int code) : code(code) {} +// const char* what(); +//private: +// const int code; +//}; +// +//struct COpusCodec +//{ +// COpusCodec(int32_t sampling_rate, int channels); +// ~COpusCodec(); +// +// bool decode_frame(std::ifstream& fin, std::ofstream& fout); +// private: +// struct Impl; +// std::unique_ptr _pimpl; +//}; \ No newline at end of file diff --git a/TelegramClient.Opus/TelegramClient.Opus.cpp b/TelegramClient.Opus/TelegramClient.Opus.cpp new file mode 100755 index 0000000..8f6216e --- /dev/null +++ b/TelegramClient.Opus/TelegramClient.Opus.cpp @@ -0,0 +1,982 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#include "opus_defines.h" +#include "opus_types.h" + + +#include +#include +#include +#include +#include +#include +#include "opusfile.h" +#include "stdint.h" +#include "stdio.h" + +#include "windows.h" + + +#include "pch.h" +#include "audio.c" +#include "TelegramClient.Opus.h" +#include + +using namespace TelegramClient_Opus; +using namespace Platform; +//using namespace Windows::Storage; + +//--------------- + + +typedef struct { + int version; + int channels; /* Number of channels: 1..255 */ + int preskip; + ogg_uint32_t input_sample_rate; + int gain; /* in dB S7.8 should be zero whenever possible */ + int channel_mapping; + /* The rest is only used if channel_mapping != 0 */ + int nb_streams; + int nb_coupled; + unsigned char stream_map[255]; +} OpusHeader; + +typedef struct { + unsigned char *data; + int maxlen; + int pos; +} Packet; + +typedef struct { + const unsigned char *data; + int maxlen; + int pos; +} ROPacket; + +typedef struct { + void *readdata; + opus_int64 total_samples_per_channel; + int rawmode; + int channels; + long rate; + int gain; + int samplesize; + int endianness; + char *infilename; + int ignorelength; + int skip; + int extraout; + char *comments; + int comments_length; + int copy_comments; +} oe_enc_opt; + +static int write_uint32(Packet *p, ogg_uint32_t val) { + if (p->pos > p->maxlen - 4) { + return 0; + } + p->data[p->pos ] = (val ) & 0xFF; + p->data[p->pos+1] = (val>> 8) & 0xFF; + p->data[p->pos+2] = (val>>16) & 0xFF; + p->data[p->pos+3] = (val>>24) & 0xFF; + p->pos += 4; + return 1; +} + +static int write_uint16(Packet *p, ogg_uint16_t val) { + if (p->pos > p->maxlen-2) { + return 0; + } + p->data[p->pos ] = (val ) & 0xFF; + p->data[p->pos+1] = (val>> 8) & 0xFF; + p->pos += 2; + return 1; +} + +static int write_chars(Packet *p, const unsigned char *str, int nb_chars) +{ + int i; + if (p->pos>p->maxlen-nb_chars) + return 0; + for (i=0;idata[p->pos++] = str[i]; + return 1; +} + +static int read_uint32(ROPacket *p, ogg_uint32_t *val) +{ + if (p->pos>p->maxlen-4) + return 0; + *val = (ogg_uint32_t)p->data[p->pos ]; + *val |= (ogg_uint32_t)p->data[p->pos+1]<< 8; + *val |= (ogg_uint32_t)p->data[p->pos+2]<<16; + *val |= (ogg_uint32_t)p->data[p->pos+3]<<24; + p->pos += 4; + return 1; +} + +static int read_uint16(ROPacket *p, ogg_uint16_t *val) +{ + if (p->pos>p->maxlen-2) + return 0; + *val = (ogg_uint16_t)p->data[p->pos ]; + *val |= (ogg_uint16_t)p->data[p->pos+1]<<8; + p->pos += 2; + return 1; +} + +static int read_chars(ROPacket *p, unsigned char *str, int nb_chars) +{ + int i; + if (p->pos>p->maxlen-nb_chars) + return 0; + for (i=0;idata[p->pos++]; + return 1; +} + +int opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int len) { + int i; + Packet p; + unsigned char ch; + + p.data = packet; + p.maxlen = len; + p.pos = 0; + if (len < 19) { + return 0; + } + if (!write_chars(&p, (const unsigned char *)"OpusHead", 8)) { + return 0; + } + + ch = 1; + if (!write_chars(&p, &ch, 1)) { + return 0; + } + + ch = h->channels; + if (!write_chars(&p, &ch, 1)) { + return 0; + } + + if (!write_uint16(&p, h->preskip)) { + return 0; + } + + if (!write_uint32(&p, h->input_sample_rate)) { + return 0; + } + + if (!write_uint16(&p, h->gain)) { + return 0; + } + + ch = h->channel_mapping; + if (!write_chars(&p, &ch, 1)) { + return 0; + } + + if (h->channel_mapping != 0) { + ch = h->nb_streams; + if (!write_chars(&p, &ch, 1)) { + return 0; + } + + ch = h->nb_coupled; + if (!write_chars(&p, &ch, 1)) { + return 0; + } + + /* Multi-stream support */ + for (i = 0; i < h->channels; i++) { + if (!write_chars(&p, &h->stream_map[i], 1)) { + return 0; + } + } + } + + return p.pos; +} + +#define writeint(buf, base, val) do { buf[base + 3] = ((val) >> 24) & 0xff; \ +buf[base + 2]=((val) >> 16) & 0xff; \ +buf[base + 1]=((val) >> 8) & 0xff; \ +buf[base] = (val) & 0xff; \ +} while(0) + +static void comment_init(char **comments, int *length, const char *vendor_string) { + // The 'vendor' field should be the actual encoding library used + int vendor_length = strlen(vendor_string); + int user_comment_list_length = 0; + int len = 8 + 4 + vendor_length + 4; + char *p = (char *)malloc(len); + memcpy(p, "OpusTags", 8); + writeint(p, 8, vendor_length); + memcpy(p + 12, vendor_string, vendor_length); + writeint(p, 12 + vendor_length, user_comment_list_length); + *length = len; + *comments = p; +} + +static void comment_pad(char **comments, int* length, int amount) { + char* p; + int newlen; + int i; + if (amount > 0) { + p = *comments; + // Make sure there is at least amount worth of padding free, and round up to the maximum that fits in the current ogg segments + newlen = (*length + amount + 255) / 255 * 255 - 1; + p = (char*)realloc(p, newlen); + for (i = *length; i < newlen; i++) { + p[i] = 0; + } + *comments = p; + *length = newlen; + } +} + +static int writeOggPage(ogg_page *page, FILE *os) { + int written = fwrite(page->header, sizeof(unsigned char), page->header_len, os); + written += fwrite(page->body, sizeof(unsigned char), page->body_len, os); + return written; +} + +const opus_int32 bitrate = 16000; +const opus_int32 rate = 16000; +const opus_int32 frame_size = 960; +const int with_cvbr = 1; +const int max_ogg_delay = 0; +const int comment_padding = 512; + +opus_int32 coding_rate = 16000; +ogg_int32_t _packetId; +OpusEncoder *_encoder = 0; +uint8_t *_packet = 0; +ogg_stream_state os; +FILE *_fileOs = 0; +oe_enc_opt inopt; +OpusHeader header; +opus_int32 min_bytes; +int max_frame_bytes; +ogg_packet op; +ogg_page og; +opus_int64 bytes_written; +opus_int64 pages_out; +opus_int64 total_samples; +ogg_int64_t enc_granulepos; +ogg_int64_t last_granulepos; +int size_segments; +int last_segments; + +void cleanupRecorder() { + + ogg_stream_flush(&os, &og); + + if (_encoder) { + opus_encoder_destroy(_encoder); + _encoder = 0; + } + + ogg_stream_clear(&os); + + if (_packet) { + free(_packet); + _packet = 0; + } + + if (_fileOs) { + fclose(_fileOs); + _fileOs = 0; + } + + _packetId = -1; + bytes_written = 0; + pages_out = 0; + total_samples = 0; + enc_granulepos = 0; + size_segments = 0; + last_segments = 0; + last_granulepos = 0; + memset(&os, 0, sizeof(ogg_stream_state)); + memset(&inopt, 0, sizeof(oe_enc_opt)); + memset(&header, 0, sizeof(OpusHeader)); + memset(&op, 0, sizeof(ogg_packet)); + memset(&og, 0, sizeof(ogg_page)); +} + +int initRecorder(const char *path) { + cleanupRecorder(); + + if (!path) { + return 0; + } + + _fileOs = fopen(path, "wb"); + if (!_fileOs) { + return 0; + } + + inopt.rate = rate; + inopt.gain = 0; + inopt.endianness = 0; + inopt.copy_comments = 0; + inopt.rawmode = 1; + inopt.ignorelength = 1; + inopt.samplesize = 16; + inopt.channels = 1; + inopt.skip = 0; + + comment_init(&inopt.comments, &inopt.comments_length, opus_get_version_string()); + + if (rate > 24000) { + coding_rate = 48000; + } else if (rate > 16000) { + coding_rate = 24000; + } else if (rate > 12000) { + coding_rate = 16000; + } else if (rate > 8000) { + coding_rate = 12000; + } else { + coding_rate = 8000; + } + + if (rate != coding_rate) { + //LOGE("Invalid rate"); + return 0; + } + + header.channels = 1; + header.channel_mapping = 0; + header.input_sample_rate = rate; + header.gain = inopt.gain; + header.nb_streams = 1; + + int result = OPUS_OK; + _encoder = opus_encoder_create(coding_rate, 1, OPUS_APPLICATION_AUDIO, &result); + if (result != OPUS_OK) { + //LOGE("Error cannot create encoder: %s", opus_strerror(result)); + return 0; + } + + min_bytes = max_frame_bytes = (1275 * 3 + 7) * header.nb_streams; + _packet = (uint8_t*)malloc(max_frame_bytes); + + result = opus_encoder_ctl(_encoder, OPUS_SET_BITRATE(bitrate)); + if (result != OPUS_OK) { + //LOGE("Error OPUS_SET_BITRATE returned: %s", opus_strerror(result)); + return 0; + } + +#ifdef OPUS_SET_LSB_DEPTH + result = opus_encoder_ctl(_encoder, OPUS_SET_LSB_DEPTH(max(8, min(24, inopt.samplesize)))); + if (result != OPUS_OK) { + //LOGE("Warning OPUS_SET_LSB_DEPTH returned: %s", opus_strerror(result)); + } +#endif + + opus_int32 lookahead; + result = opus_encoder_ctl(_encoder, OPUS_GET_LOOKAHEAD(&lookahead)); + if (result != OPUS_OK) { + //LOGE("Error OPUS_GET_LOOKAHEAD returned: %s", opus_strerror(result)); + return 0; + } + + inopt.skip += lookahead; + header.preskip = (int)(inopt.skip * (48000.0 / coding_rate)); + inopt.extraout = (int)(header.preskip * (rate / 48000.0)); + + if (ogg_stream_init(&os, rand()) == -1) { + //LOGE("Error: stream init failed"); + return 0; + } + + unsigned char header_data[100]; + int packet_size = opus_header_to_packet(&header, header_data, 100); + op.packet = header_data; + op.bytes = packet_size; + op.b_o_s = 1; + op.e_o_s = 0; + op.granulepos = 0; + op.packetno = 0; + ogg_stream_packetin(&os, &op); + + while ((result = ogg_stream_flush(&os, &og))) { + if (!result) { + break; + } + + int pageBytesWritten = writeOggPage(&og, _fileOs); + if (pageBytesWritten != og.header_len + og.body_len) { + //LOGE("Error: failed writing header to output stream"); + return 0; + } + bytes_written += pageBytesWritten; + pages_out++; + } + + comment_pad(&inopt.comments, &inopt.comments_length, comment_padding); + op.packet = (unsigned char *)inopt.comments; + op.bytes = inopt.comments_length; + op.b_o_s = 0; + op.e_o_s = 0; + op.granulepos = 0; + op.packetno = 1; + ogg_stream_packetin(&os, &op); + + while ((result = ogg_stream_flush(&os, &og))) { + if (result == 0) { + break; + } + + int writtenPageBytes = writeOggPage(&og, _fileOs); + if (writtenPageBytes != og.header_len + og.body_len) { + //LOGE("Error: failed writing header to output stream"); + return 0; + } + + bytes_written += writtenPageBytes; + pages_out++; + } + + free(inopt.comments); + + return 1; +} + +int writeFrame(uint8_t *framePcmBytes, unsigned int frameByteCount) { + int cur_frame_size = frame_size; + _packetId++; + + opus_int32 nb_samples = frameByteCount / 2; + total_samples += nb_samples; + if (nb_samples < frame_size) { + op.e_o_s = 1; + } else { + op.e_o_s = 0; + } + + int nbBytes = 0; + + if (nb_samples != 0) { + uint8_t *paddedFrameBytes = framePcmBytes; + int freePaddedFrameBytes = 0; + + if (nb_samples < cur_frame_size) { + paddedFrameBytes = (uint8_t*)malloc(cur_frame_size * 2); + freePaddedFrameBytes = 1; + memcpy(paddedFrameBytes, framePcmBytes, frameByteCount); + memset(paddedFrameBytes + nb_samples * 2, 0, cur_frame_size * 2 - nb_samples * 2); + } + + nbBytes = opus_encode(_encoder, (opus_int16 *)paddedFrameBytes, cur_frame_size, _packet, max_frame_bytes / 10); + if (freePaddedFrameBytes) { + free(paddedFrameBytes); + paddedFrameBytes = NULL; + } + + if (nbBytes < 0) { + //LOGE("Encoding failed: %s. Aborting.", opus_strerror(nbBytes)); + return 0; + } + + enc_granulepos += cur_frame_size * 48000 / coding_rate; + size_segments = (nbBytes + 255) / 255; + min_bytes = min(nbBytes, min_bytes); + } + + while ((((size_segments <= 255) && (last_segments + size_segments > 255)) || (enc_granulepos - last_granulepos > max_ogg_delay)) && ogg_stream_flush_fill(&os, &og, 255 * 255)) { + if (ogg_page_packets(&og) != 0) { + last_granulepos = ogg_page_granulepos(&og); + } + + last_segments -= og.header[26]; + int writtenPageBytes = writeOggPage(&og, _fileOs); + if (writtenPageBytes != og.header_len + og.body_len) { + //LOGE("Error: failed writing data to output stream"); + return 0; + } + bytes_written += writtenPageBytes; + pages_out++; + } + + op.packet = (unsigned char *)_packet; + op.bytes = nbBytes; + op.b_o_s = 0; + op.granulepos = enc_granulepos; + if (op.e_o_s) { + op.granulepos = ((total_samples * 48000 + rate - 1) / rate) + header.preskip; + } + op.packetno = 2 + _packetId; + ogg_stream_packetin(&os, &op); + last_segments += size_segments; + + while ((op.e_o_s || (enc_granulepos + (frame_size * 48000 / coding_rate) - last_granulepos > max_ogg_delay) || (last_segments >= 255)) ? ogg_stream_flush_fill(&os, &og, 255 * 255) : ogg_stream_pageout_fill(&os, &og, 255 * 255)) { + if (ogg_page_packets(&og) != 0) { + last_granulepos = ogg_page_granulepos(&og); + } + last_segments -= og.header[26]; + int writtenPageBytes = writeOggPage(&og, _fileOs); + if (writtenPageBytes != og.header_len + og.body_len) { + //LOGE("Error: failed writing data to output stream"); + return 0; + } + bytes_written += writtenPageBytes; + pages_out++; + } + + return 1; +} + +//player +OggOpusFile *_opusFile; +int _isSeekable = 0; +long _totalPcmDuration = 0; +long _currentPcmOffset = 0; +int _finished = 0; +static const int playerBuffersCount = 3; +static const int playerSampleRate = 48000; + +void cleanupPlayer() { + if (_opusFile) { + op_free(_opusFile); + _opusFile = 0; + } + _isSeekable = 0; + _totalPcmDuration = 0; + _currentPcmOffset = 0; + _finished = 0; +} + +int seekPlayer(float position) { + int result; + ogg_int64_t pcmPosition; + + if (!_opusFile || !_isSeekable || position < 0) { + return 0; + } + result = op_pcm_seek(_opusFile, (ogg_int64_t)(position * _totalPcmDuration)); + if (result != OPUS_OK) { + //LOGE("op_pcm_seek failed: %d", result); + } + pcmPosition = op_pcm_tell(_opusFile); + _currentPcmOffset = pcmPosition; + return result == OPUS_OK; +} + +int initPlayer(const char *path) { + int openError = OPUS_OK; + cleanupPlayer(); + + _opusFile = op_open_file(path, &openError); + if (!_opusFile || openError != OPUS_OK) { + //LOGE("op_open_file failed: %d", openError); + cleanupPlayer(); + return 0; + } + + _isSeekable = op_seekable(_opusFile); + _totalPcmDuration = op_pcm_total(_opusFile, -1); + + return 1; +} + +void fillBuffer(uint8_t *buffer, int capacity, int *args) { + if (_opusFile) { + args[1] = max((ogg_int64_t)0, op_pcm_tell(_opusFile)); + + if (_finished) { + args[0] = 0; + args[1] = 0; + args[2] = 1; + return; + } else { + int writtenOutputBytes = 0; + int endOfFileReached = 0; + + while (writtenOutputBytes < capacity) { + int readSamples = op_read(_opusFile, (opus_int16 *)(buffer + writtenOutputBytes), (capacity - writtenOutputBytes) / 2, NULL); + + if (readSamples > 0) { + writtenOutputBytes += readSamples * 2; + } else { + if (readSamples < 0) { + //LOGE("op_read failed: %d", readSamples); + } + endOfFileReached = 1; + break; + } + } + + args[0] = writtenOutputBytes; + + if (endOfFileReached || args[1] + args[0] == _totalPcmDuration) { + _finished = 1; + args[2] = 1; + } else { + args[2] = 0; + } + } + } else { + memset(buffer, 0, capacity); + args[0] = capacity; + args[1] = _totalPcmDuration; + } +} + +//-------------------------------------------- + +int startRecord(char* pathStr) { + int result = initRecorder(pathStr); + + return result; +} + +void stopRecord() { + cleanupRecorder(); +} + +long getTotalPcmDuration() { + return _totalPcmDuration; +} + +void readOpusFile(uint8_t* bufferBytes, int capacity, int* args) { + fillBuffer(bufferBytes, capacity, args); +} + +int seekOpusFile(float position) { + return seekPlayer(position); +} + +int openOpusFile(char* pathStr) { + + int result = initPlayer(pathStr); + + return result; +} + +void closeOpusFile() { + cleanupPlayer(); +} + +int isOpusFile(char* pathStr) { + int result = 0; + + int error = OPUS_OK; + OggOpusFile *file = op_test_file(pathStr, &error); + if (file != NULL) { + int error = op_test_open(file); + op_free(file); + + result = error == OPUS_OK; + } + + return result; +} +//--------------- + +WindowsPhoneRuntimeComponent::WindowsPhoneRuntimeComponent() +{ + +} + +const char* StringToCharArray(Platform::String^ str){ + std::wstring fooW(str->Begin()); + std::string fooA(fooW.begin(), fooW.end()); + return fooA.c_str(); +} + +int WindowsPhoneRuntimeComponent::Sum(int a, int b) +{ + auto local = Windows::Storage::ApplicationData::Current->LocalFolder; + auto localFileNamePlatformString = local->Path + "\\game.sav"; + return a + b; +} + +int64 WindowsPhoneRuntimeComponent::GetTotalPcmDuration(){ + return getTotalPcmDuration(); +} + +int WindowsPhoneRuntimeComponent::InitPlayer(Platform::String^ path){ + std::wstring fooW(path->Begin()); + std::string fooA(fooW.begin(), fooW.end()); + const char* pathStr = fooA.c_str(); + int result = initPlayer(pathStr); + //delete[] pathStr; + + return result; +} + +void WindowsPhoneRuntimeComponent::CleanupPlayer(){ + cleanupPlayer(); +} + +void WindowsPhoneRuntimeComponent::FillBuffer(Platform::WriteOnlyArray^ buffer, int capacity, Platform::WriteOnlyArray^ args){ + uint8_t* buf = new uint8_t[capacity]; + int* bufArgs = new int[3]; + + fillBuffer(buf, capacity, bufArgs); + + for (int i = 0; i < capacity; i++){ + buffer->set(i, buf[i]); + } + + args->set(0, bufArgs[0]); + args->set(1, bufArgs[1]); + args->set(2, bufArgs[2]); + + delete[] buf; + delete[] bufArgs; +} + +bool WindowsPhoneRuntimeComponent::IsOpusFile(Platform::String^ path) { + Platform::String^ fooRT = path; + std::wstring fooW(fooRT->Begin()); + std::string fooA(fooW.begin(), fooW.end()); + const char* charStr = fooA.c_str(); + + //const char *pathStr = (*env)->GetStringUTFChars(env, path, 0); + + int error = OPUS_OK; + bool result = false; + OggOpusFile *file = op_test_file(charStr, &error); + if (file != NULL) { + int error = op_test_open(file); + op_free(file); + + result = error == OPUS_OK; + } + + + /*if (pathStr != 0) { + (*env)->ReleaseStringUTFChars(env, path, pathStr); + }*/ + + return result; +} + +int WindowsPhoneRuntimeComponent::StartRecord(Platform::String^ path) { + Platform::String^ fooRT = path; + std::wstring fooW(fooRT->Begin()); + std::string fooA(fooW.begin(), fooW.end()); + const char* charStr = fooA.c_str(); + + int result = initRecorder(charStr); + + /*if (pathStr != 0) { + (*env)->ReleaseStringUTFChars(env, path, pathStr); + }*/ + + return result; +} + +int WindowsPhoneRuntimeComponent::WriteFrame(const Platform::Array^ buffer, int length) { + return writeFrame(buffer->begin(), length); +} + +void WindowsPhoneRuntimeComponent::StopRecord() { + cleanupRecorder(); +} + +static inline void set_bits(uint8_t *bytes, int32_t bitOffset, int32_t numBits, int32_t value) { + numBits = (unsigned int)(2 << (numBits - 1)) - 1; + bytes += bitOffset / 8; + bitOffset %= 8; + *((int32_t *)bytes) |= (value << bitOffset); +} + +Platform::Array^ WindowsPhoneRuntimeComponent::GetWaveform(Platform::String^ path) { + Platform::String^ fooRT = path; + std::wstring fooW(fooRT->Begin()); + std::string fooA(fooW.begin(), fooW.end()); + const char* pathStr = fooA.c_str(); + + Platform::Array^ result = ref new Platform::Array(0);// ref new Platform::Array(retData, retDataLength); + //jbyteArray result = 0; + + int error = OPUS_OK; + OggOpusFile *opusFile = op_open_file(pathStr, &error); + if (opusFile != NULL && error == OPUS_OK) { + int64_t totalSamples = op_pcm_total(opusFile, -1); + int32_t resultSamples = 100; + int32_t sampleRate = (int32_t)max(1, totalSamples / resultSamples); + + uint16_t *samples = new uint16_t[100]; + + int bufferSize = 1024 * 128; + int16_t *sampleBuffer = new int16_t[bufferSize]; + uint64_t sampleIndex = 0; + uint16_t peakSample = 0; + + int index = 0; + + while (1) { + int readSamples = op_read(opusFile, sampleBuffer, bufferSize / 2, NULL); + for (int i = 0; i < readSamples; i++) { + uint16_t sample = (uint16_t) abs(sampleBuffer[i]); + if (sample > peakSample) { + peakSample = sample; + } + if (sampleIndex++ % sampleRate == 0) { + if (index < resultSamples) { + samples[index++] = peakSample; + } + peakSample = 0; + } + } + if (readSamples == 0) { + break; + } + } + + /*uint16_t peak = 0; + for (int i = 0; i < resultSamples; i++) { + if (peak < samples[i]){ + peak = samples[i]; + } + } + + delete[] sampleBuffer; + op_free(opusFile); + + uint32_t bitstreamLength = (resultSamples * 5) / 8 + (((resultSamples * 5) % 8) == 0 ? 0 : 1); + + result = ref new Platform::Array(resultSamples); + + uint8_t* bytes = new uint8_t[bitstreamLength]; + + for (int i = 0; i < resultSamples; i++) { + int32_t value = min(31, abs((int32_t)samples[i]) * 31 / peak); + + result[i] = value & 31; + set_bits(bytes, i * 5, 5, value & 31); + } + + delete[] bytes; + delete[] samples;*/ + + int64_t sumSamples = 0; + for (int i = 0; i < resultSamples; i++) { + sumSamples += samples[i]; + } + uint16_t peak = (uint16_t) (sumSamples * 1.8f / resultSamples); + if (peak < 7500) { + peak = 7500; + } + + for (int i = 0; i < resultSamples; i++) { + uint16_t sample = samples[i];//(uint16_t) ((int64_t) samples[i]); + if (sample > peak) { + samples[i] = peak; + } + } + + delete[] sampleBuffer; + op_free(opusFile); + + uint32_t bitstreamLength = (resultSamples * 5) / 8 + (((resultSamples * 5) % 8) == 0 ? 0 : 1); + + result = ref new Platform::Array(resultSamples); + //result = ref new Platform::Array(bitstreamLength); + + uint8_t* bytes = new uint8_t[bitstreamLength]; + + for (int i = 0; i < resultSamples; i++) { + int32_t value = min(31, abs((int32_t)samples[i]) * 31 / peak); + + result[i] = value & 31; + set_bits(bytes, i * 5, 5, value & 31); + } + + + /*for (int i = 0; i < bitstreamLength; i++) { + result[i] = bytes[i]; + }*/ + + + delete[] bytes; + delete[] samples; + } + + return result; +} + + + + +//void WindowsPhoneRuntimeComponent::WriteFile( String^ strFile, String^ strContent ) +//{ +// auto folder = ApplicationData::Current->LocalFolder; + //task getFileTask(folder->CreateFileAsync( strFile, CreationCollisionOption::ReplaceExisting)); + + //// Create a local to allow the DataReader to be passed between lambdas. + //auto writer = std::make_shared(nullptr); + + //getFileTask.then([](StorageFile^ file) + //{ + // return file->OpenAsync(FileAccessMode::ReadWrite); + //}).then([this, writer, strContent](Streams::IRandomAccessStream^ stream) + //{ + // Streams::DataWriter^ state = ref new Streams::DataWriter(stream); + // *writer = state; + + // unsigned int codeUnits = state->MeasureString(strContent); + // state->WriteUInt32(codeUnits); + // state->WriteString(strContent); + + // return state->StoreAsync(); + //}).then([writer](uint32 count) + //{ + // return (*writer)->FlushAsync(); + //}).then([this, writer](bool flushed) + //{ + // delete (*writer); + //}); +//} + +//void WindowsPhoneRuntimeComponent::LoadFile(String^ strFile) +//{ + // auto folder = ApplicationData::Current->LocalFolder; + //task getFileTask(folder->GetFileAsync(strFile)); + + //// Create a local to allow the DataReader to be passed between lambdas. + //auto reader = std::make_shared(nullptr); + //getFileTask.then([this, reader](task fileTask) + //{ + // try + // { + // StorageFile^ file = fileTask.get(); + + // task (file->OpenReadAsync()).then([reader](Streams::IRandomAccessStreamWithContentType^ stream) + // { + // *reader = ref new Streams::DataReader(stream); + // return (*reader)->LoadAsync(static_cast(stream->Size)); + // }).then([this, reader](uint32 bytesRead) + // { + + // Streams::DataReader^ state = (*reader); + // try + // { + // unsigned int codeUnits = state->ReadUInt32(); + // Platform::String^ strContent = state->ReadString(codeUnits); + + // } + // catch (Platform::Exception^ e) + // { + // // Do nothing. + // } + // });; + // } + // catch (Platform::Exception^ e) + // { + + // } + //}); +//} + diff --git a/TelegramClient.Opus/TelegramClient.Opus.h b/TelegramClient.Opus/TelegramClient.Opus.h new file mode 100755 index 0000000..ab37ef5 --- /dev/null +++ b/TelegramClient.Opus/TelegramClient.Opus.h @@ -0,0 +1,46 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#pragma once + + + +namespace TelegramClient_Opus +{ + //public ref class TestClass sealed{ + //public: + // //property int IntValue; + // //property String^ StringValue; + //}; + + public ref class WindowsPhoneRuntimeComponent sealed + { + + public: + //property int IntField; + //property TestClass ClassField; + //TestClass ClassField; + WindowsPhoneRuntimeComponent(); + int Sum(int a, int b); + int InitPlayer(Platform::String^ path); + void CleanupPlayer(); + void FillBuffer(Platform::WriteOnlyArray^ buffer, int capacity, Platform::WriteOnlyArray^ args); + int64 GetTotalPcmDuration(); + + int StartRecord(Platform::String^ path); + int WriteFrame(const Platform::Array^ buffer, int length); + void StopRecord(); + + bool IsOpusFile(Platform::String^ path); + + Platform::Array^ GetWaveform(Platform::String^ path); + + //void WriteFile( String^ strFile, String^ strContent ); + //void LoadFile(String^ strFile); + }; + +} \ No newline at end of file diff --git a/TelegramClient.Opus/TelegramClient.Opus.vcxproj b/TelegramClient.Opus/TelegramClient.Opus.vcxproj new file mode 100755 index 0000000..7eba93c --- /dev/null +++ b/TelegramClient.Opus/TelegramClient.Opus.vcxproj @@ -0,0 +1,363 @@ + + + + + Debug + Win32 + + + Debug + ARM + + + Release + Win32 + + + Release + ARM + + + + {5e327850-e16e-4642-957a-fd52bf8d3d02} + TelegramClient_Opus + en-US + 12.0 + true + Windows Phone + 8.1 + + + + DynamicLibrary + true + v120_wp81 + + + DynamicLibrary + true + v120_wp81 + + + DynamicLibrary + false + true + v120_wp81 + + + DynamicLibrary + false + true + v120_wp81 + + + + + + + + false + + + + _WINRT_DLL;OPUS_EXPORT=__declspec(dllexport);OPUS_BUILD;FIXED_POINT;USE_ALLOCA;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + NotUsing + pch.h + $(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories) + false + .\opus\opusfile;.\opus\silk\fixed;.\opus\ogg;.\opus\;.\opus\silk;.\opus\celt;.\opus\include;%(AdditionalIncludeDirectories) + + + Console + false + ole32.lib;%(IgnoreSpecificDefaultLibraries) + true + + + + + _WINRT_DLL;OPUS_EXPORT=__declspec(dllexport);NDEBUG;OPUS_BUILD;FIXED_POINT;USE_ALLOCA;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + NotUsing + pch.h + $(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories) + false + .\opus\opusfile;.\opus\silk\fixed;.\opus\ogg;.\opus\;.\opus\silk;.\opus\celt;.\opus\include;%(AdditionalIncludeDirectories) + + + Console + false + ole32.lib;%(IgnoreSpecificDefaultLibraries) + true + + + + + _WINRT_DLL;OPUS_EXPORT=__declspec(dllexport);OPUS_BUILD;FIXED_POINT;HAVE_LRINTF;HAVE_LRINT;USE_ALLOCA;DISABLE_FLOAT_API;OP_FIXED_POINT;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + NotUsing + pch.h + $(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories) + false + .\opus\opusfile;.\opus\silk\fixed;.\opus\ogg;.\opus\;.\opus\silk;.\opus\celt;.\opus\include;%(AdditionalIncludeDirectories) + MaxSpeed + Default + + + Console + false + ole32.lib;%(IgnoreSpecificDefaultLibraries) + true + + + + + _WINRT_DLL;OPUS_EXPORT=__declspec(dllexport);NDEBUG;OPUS_BUILD;FIXED_POINT;USE_ALLOCA;HAVE_LRINTF;HAVE_LRINT;DISABLE_FLOAT_API;OP_FIXED_POINT;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + NotUsing + pch.h + $(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories) + false + .\opus\opusfile;.\opus\silk\fixed;.\opus\ogg;.\opus\;.\opus\silk;.\opus\celt;.\opus\include;%(AdditionalIncludeDirectories) + + + Console + false + ole32.lib;%(IgnoreSpecificDefaultLibraries) + true + + + + + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + true + true + + + + + + + \ No newline at end of file diff --git a/TelegramClient.Opus/TelegramClient.Opus.vcxproj.filters b/TelegramClient.Opus/TelegramClient.Opus.vcxproj.filters new file mode 100755 index 0000000..c00864c --- /dev/null +++ b/TelegramClient.Opus/TelegramClient.Opus.vcxproj.filters @@ -0,0 +1,667 @@ + + + + + 5fd0e509-b6ae-4f29-bd2a-4d2cc10f3aa0 + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {53ba44f6-1989-4e6f-9e7c-4a6c8e85c1f6} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/TelegramClient.Opus/audio.c b/TelegramClient.Opus/audio.c new file mode 100755 index 0000000..b28b04f --- /dev/null +++ b/TelegramClient.Opus/audio.c @@ -0,0 +1,3 @@ + + + diff --git a/TelegramClient.Opus/opus/celt/_kiss_fft_guts.h b/TelegramClient.Opus/opus/celt/_kiss_fft_guts.h new file mode 100755 index 0000000..aefe490 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/_kiss_fft_guts.h @@ -0,0 +1,183 @@ +/*Copyright (c) 2003-2004, Mark Borgerding + + 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. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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.*/ + +#ifndef KISS_FFT_GUTS_H +#define KISS_FFT_GUTS_H + +#define MIN(a,b) ((a)<(b) ? (a):(b)) +#define MAX(a,b) ((a)>(b) ? (a):(b)) + +/* kiss_fft.h + defines kiss_fft_scalar as either short or a float type + and defines + typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ +#include "kiss_fft.h" + +/* + Explanation of macros dealing with complex math: + + C_MUL(m,a,b) : m = a*b + C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise + C_SUB( res, a,b) : res = a - b + C_SUBFROM( res , a) : res -= a + C_ADDTO( res , a) : res += a + * */ +#ifdef FIXED_POINT +#include "arch.h" + + +#define SAMP_MAX 2147483647 +#define TWID_MAX 32767 +#define TRIG_UPSCALE 1 + +#define SAMP_MIN -SAMP_MAX + + +# define S_MUL(a,b) MULT16_32_Q15(b, a) + +# define C_MUL(m,a,b) \ + do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ + (m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0) + +# define C_MULC(m,a,b) \ + do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ + (m).i = SUB32(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0) + +# define C_MUL4(m,a,b) \ + do{ (m).r = SHR32(SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)),2); \ + (m).i = SHR32(ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)),2); }while(0) + +# define C_MULBYSCALAR( c, s ) \ + do{ (c).r = S_MUL( (c).r , s ) ;\ + (c).i = S_MUL( (c).i , s ) ; }while(0) + +# define DIVSCALAR(x,k) \ + (x) = S_MUL( x, (TWID_MAX-((k)>>1))/(k)+1 ) + +# define C_FIXDIV(c,div) \ + do { DIVSCALAR( (c).r , div); \ + DIVSCALAR( (c).i , div); }while (0) + +#define C_ADD( res, a,b)\ + do {(res).r=ADD32((a).r,(b).r); (res).i=ADD32((a).i,(b).i); \ + }while(0) +#define C_SUB( res, a,b)\ + do {(res).r=SUB32((a).r,(b).r); (res).i=SUB32((a).i,(b).i); \ + }while(0) +#define C_ADDTO( res , a)\ + do {(res).r = ADD32((res).r, (a).r); (res).i = ADD32((res).i,(a).i);\ + }while(0) + +#define C_SUBFROM( res , a)\ + do {(res).r = ADD32((res).r,(a).r); (res).i = SUB32((res).i,(a).i); \ + }while(0) + +#if defined(OPUS_ARM_INLINE_ASM) +#include "arm/kiss_fft_armv4.h" +#endif + +#if defined(OPUS_ARM_INLINE_EDSP) +#include "arm/kiss_fft_armv5e.h" +#endif + +#else /* not FIXED_POINT*/ + +# define S_MUL(a,b) ( (a)*(b) ) +#define C_MUL(m,a,b) \ + do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ + (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) +#define C_MULC(m,a,b) \ + do{ (m).r = (a).r*(b).r + (a).i*(b).i;\ + (m).i = (a).i*(b).r - (a).r*(b).i; }while(0) + +#define C_MUL4(m,a,b) C_MUL(m,a,b) + +# define C_FIXDIV(c,div) /* NOOP */ +# define C_MULBYSCALAR( c, s ) \ + do{ (c).r *= (s);\ + (c).i *= (s); }while(0) +#endif + +#ifndef CHECK_OVERFLOW_OP +# define CHECK_OVERFLOW_OP(a,op,b) /* noop */ +#endif + +#ifndef C_ADD +#define C_ADD( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,+,(b).r)\ + CHECK_OVERFLOW_OP((a).i,+,(b).i)\ + (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ + }while(0) +#define C_SUB( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,-,(b).r)\ + CHECK_OVERFLOW_OP((a).i,-,(b).i)\ + (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ + }while(0) +#define C_ADDTO( res , a)\ + do { \ + CHECK_OVERFLOW_OP((res).r,+,(a).r)\ + CHECK_OVERFLOW_OP((res).i,+,(a).i)\ + (res).r += (a).r; (res).i += (a).i;\ + }while(0) + +#define C_SUBFROM( res , a)\ + do {\ + CHECK_OVERFLOW_OP((res).r,-,(a).r)\ + CHECK_OVERFLOW_OP((res).i,-,(a).i)\ + (res).r -= (a).r; (res).i -= (a).i; \ + }while(0) +#endif /* C_ADD defined */ + +#ifdef FIXED_POINT +/*# define KISS_FFT_COS(phase) TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase)))) +# define KISS_FFT_SIN(phase) TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase))))*/ +# define KISS_FFT_COS(phase) floor(.5+TWID_MAX*cos (phase)) +# define KISS_FFT_SIN(phase) floor(.5+TWID_MAX*sin (phase)) +# define HALF_OF(x) ((x)>>1) +#elif defined(USE_SIMD) +# define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) ) +# define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) ) +# define HALF_OF(x) ((x)*_mm_set1_ps(.5f)) +#else +# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase) +# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase) +# define HALF_OF(x) ((x)*.5f) +#endif + +#define kf_cexp(x,phase) \ + do{ \ + (x)->r = KISS_FFT_COS(phase);\ + (x)->i = KISS_FFT_SIN(phase);\ + }while(0) + +#define kf_cexp2(x,phase) \ + do{ \ + (x)->r = TRIG_UPSCALE*celt_cos_norm((phase));\ + (x)->i = TRIG_UPSCALE*celt_cos_norm((phase)-32768);\ +}while(0) + +#endif /* KISS_FFT_GUTS_H */ diff --git a/TelegramClient.Opus/opus/celt/arch.h b/TelegramClient.Opus/opus/celt/arch.h new file mode 100755 index 0000000..3bbcd36 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/arch.h @@ -0,0 +1,214 @@ +/* Copyright (c) 2003-2008 Jean-Marc Valin + Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/** + @file arch.h + @brief Various architecture definitions for CELT +*/ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef ARCH_H +#define ARCH_H + +#include "opus_types.h" +#include "opus_defines.h" + +# if !defined(__GNUC_PREREQ) +# if defined(__GNUC__)&&defined(__GNUC_MINOR__) +# define __GNUC_PREREQ(_maj,_min) \ + ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) +# else +# define __GNUC_PREREQ(_maj,_min) 0 +# endif +# endif + +#define CELT_SIG_SCALE 32768.f + +#define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__); +#ifdef ENABLE_ASSERTIONS +#include +#include +#ifdef __GNUC__ +__attribute__((noreturn)) +#endif +static OPUS_INLINE void _celt_fatal(const char *str, const char *file, int line) +{ + fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str); + abort(); +} +#define celt_assert(cond) {if (!(cond)) {celt_fatal("assertion failed: " #cond);}} +#define celt_assert2(cond, message) {if (!(cond)) {celt_fatal("assertion failed: " #cond "\n" message);}} +#else +#define celt_assert(cond) +#define celt_assert2(cond, message) +#endif + +#define IMUL32(a,b) ((a)*(b)) + +#define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */ +#define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */ +#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 16-bit value. */ +#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */ +#define ABS32(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 32-bit value. */ +#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 32-bit value. */ +#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */ +#define IMIN(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum int value. */ +#define IMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum int value. */ +#define UADD32(a,b) ((a)+(b)) +#define USUB32(a,b) ((a)-(b)) + +#define PRINT_MIPS(file) + +#ifdef FIXED_POINT + +typedef opus_int16 opus_val16; +typedef opus_int32 opus_val32; + +typedef opus_val32 celt_sig; +typedef opus_val16 celt_norm; +typedef opus_val32 celt_ener; + +#define Q15ONE 32767 + +#define SIG_SHIFT 12 + +#define NORM_SCALING 16384 + +#define DB_SHIFT 10 + +#define EPSILON 1 +#define VERY_SMALL 0 +#define VERY_LARGE16 ((opus_val16)32767) +#define Q15_ONE ((opus_val16)32767) + +#define SCALEIN(a) (a) +#define SCALEOUT(a) (a) + +#ifdef FIXED_DEBUG +#include "fixed_debug.h" +#else + +#include "fixed_generic.h" + +#ifdef OPUS_ARM_INLINE_EDSP +#include "arm/fixed_armv5e.h" +#elif defined (OPUS_ARM_INLINE_ASM) +#include "arm/fixed_armv4.h" +#elif defined (BFIN_ASM) +#include "fixed_bfin.h" +#elif defined (TI_C5X_ASM) +#include "fixed_c5x.h" +#elif defined (TI_C6X_ASM) +#include "fixed_c6x.h" +#endif + +#endif + +#else /* FIXED_POINT */ + +typedef float opus_val16; +typedef float opus_val32; + +typedef float celt_sig; +typedef float celt_norm; +typedef float celt_ener; + +#define Q15ONE 1.0f + +#define NORM_SCALING 1.f + +#define EPSILON 1e-15f +#define VERY_SMALL 1e-30f +#define VERY_LARGE16 1e15f +#define Q15_ONE ((opus_val16)1.f) + +#define QCONST16(x,bits) (x) +#define QCONST32(x,bits) (x) + +#define NEG16(x) (-(x)) +#define NEG32(x) (-(x)) +#define EXTRACT16(x) (x) +#define EXTEND32(x) (x) +#define SHR16(a,shift) (a) +#define SHL16(a,shift) (a) +#define SHR32(a,shift) (a) +#define SHL32(a,shift) (a) +#define PSHR32(a,shift) (a) +#define VSHR32(a,shift) (a) + +#define PSHR(a,shift) (a) +#define SHR(a,shift) (a) +#define SHL(a,shift) (a) +#define SATURATE(x,a) (x) +#define SATURATE16(x) (x) + +#define ROUND16(a,shift) (a) +#define HALF16(x) (.5f*(x)) +#define HALF32(x) (.5f*(x)) + +#define ADD16(a,b) ((a)+(b)) +#define SUB16(a,b) ((a)-(b)) +#define ADD32(a,b) ((a)+(b)) +#define SUB32(a,b) ((a)-(b)) +#define MULT16_16_16(a,b) ((a)*(b)) +#define MULT16_16(a,b) ((opus_val32)(a)*(opus_val32)(b)) +#define MAC16_16(c,a,b) ((c)+(opus_val32)(a)*(opus_val32)(b)) + +#define MULT16_32_Q15(a,b) ((a)*(b)) +#define MULT16_32_Q16(a,b) ((a)*(b)) + +#define MULT32_32_Q31(a,b) ((a)*(b)) + +#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b)) + +#define MULT16_16_Q11_32(a,b) ((a)*(b)) +#define MULT16_16_Q11(a,b) ((a)*(b)) +#define MULT16_16_Q13(a,b) ((a)*(b)) +#define MULT16_16_Q14(a,b) ((a)*(b)) +#define MULT16_16_Q15(a,b) ((a)*(b)) +#define MULT16_16_P15(a,b) ((a)*(b)) +#define MULT16_16_P13(a,b) ((a)*(b)) +#define MULT16_16_P14(a,b) ((a)*(b)) +#define MULT16_32_P16(a,b) ((a)*(b)) + +#define DIV32_16(a,b) (((opus_val32)(a))/(opus_val16)(b)) +#define DIV32(a,b) (((opus_val32)(a))/(opus_val32)(b)) + +#define SCALEIN(a) ((a)*CELT_SIG_SCALE) +#define SCALEOUT(a) ((a)*(1/CELT_SIG_SCALE)) + +#endif /* !FIXED_POINT */ + +#ifndef GLOBAL_STACK_SIZE +#ifdef FIXED_POINT +#define GLOBAL_STACK_SIZE 100000 +#else +#define GLOBAL_STACK_SIZE 100000 +#endif +#endif + +#endif /* ARCH_H */ diff --git a/TelegramClient.Opus/opus/celt/arm/arm_celt_map.c b/TelegramClient.Opus/opus/celt/arm/arm_celt_map.c new file mode 100755 index 0000000..547a84d --- /dev/null +++ b/TelegramClient.Opus/opus/celt/arm/arm_celt_map.c @@ -0,0 +1,49 @@ +/* Copyright (c) 2010 Xiph.Org Foundation + * Copyright (c) 2013 Parrot */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pitch.h" + +#if defined(OPUS_HAVE_RTCD) + +# if defined(FIXED_POINT) +opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *, + const opus_val16 *, opus_val32 *, int , int) = { + celt_pitch_xcorr_c, /* ARMv4 */ + MAY_HAVE_EDSP(celt_pitch_xcorr), /* EDSP */ + MAY_HAVE_MEDIA(celt_pitch_xcorr), /* Media */ + MAY_HAVE_NEON(celt_pitch_xcorr) /* NEON */ +}; +# else +# error "Floating-point implementation is not supported by ARM asm yet." \ + "Reconfigure with --disable-rtcd or send patches." +# endif + +#endif diff --git a/TelegramClient.Opus/opus/celt/arm/armcpu.c b/TelegramClient.Opus/opus/celt/arm/armcpu.c new file mode 100755 index 0000000..1768525 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/arm/armcpu.c @@ -0,0 +1,174 @@ +/* Copyright (c) 2010 Xiph.Org Foundation + * Copyright (c) 2013 Parrot */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +/* Original code from libtheora modified to suit to Opus */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef OPUS_HAVE_RTCD + +#include "armcpu.h" +#include "cpu_support.h" +#include "os_support.h" +#include "opus_types.h" + +#define OPUS_CPU_ARM_V4 (1) +#define OPUS_CPU_ARM_EDSP (1<<1) +#define OPUS_CPU_ARM_MEDIA (1<<2) +#define OPUS_CPU_ARM_NEON (1<<3) + +#if defined(_MSC_VER) +/*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/ +# define WIN32_LEAN_AND_MEAN +# define WIN32_EXTRA_LEAN +# include + +static OPUS_INLINE opus_uint32 opus_cpu_capabilities(void){ + opus_uint32 flags; + flags=0; + /* MSVC has no OPUS_INLINE __asm support for ARM, but it does let you __emit + * instructions via their assembled hex code. + * All of these instructions should be essentially nops. */ +# if defined(OPUS_ARM_MAY_HAVE_EDSP) + __try{ + /*PLD [r13]*/ + __emit(0xF5DDF000); + flags|=OPUS_CPU_ARM_EDSP; + } + __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){ + /*Ignore exception.*/ + } +# if defined(OPUS_ARM_MAY_HAVE_MEDIA) + __try{ + /*SHADD8 r3,r3,r3*/ + __emit(0xE6333F93); + flags|=OPUS_CPU_ARM_MEDIA; + } + __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){ + /*Ignore exception.*/ + } +# if defined(OPUS_ARM_MAY_HAVE_NEON) + __try{ + /*VORR q0,q0,q0*/ + __emit(0xF2200150); + flags|=OPUS_CPU_ARM_NEON; + } + __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){ + /*Ignore exception.*/ + } +# endif +# endif +# endif + return flags; +} + +#elif defined(__linux__) +/* Linux based */ +opus_uint32 opus_cpu_capabilities(void) +{ + opus_uint32 flags = 0; + FILE *cpuinfo; + + /* Reading /proc/self/auxv would be easier, but that doesn't work reliably on + * Android */ + cpuinfo = fopen("/proc/cpuinfo", "r"); + + if(cpuinfo != NULL) + { + /* 512 should be enough for anybody (it's even enough for all the flags that + * x86 has accumulated... so far). */ + char buf[512]; + + while(fgets(buf, 512, cpuinfo) != NULL) + { +# if defined(OPUS_ARM_MAY_HAVE_EDSP) || defined(OPUS_ARM_MAY_HAVE_NEON) + /* Search for edsp and neon flag */ + if(memcmp(buf, "Features", 8) == 0) + { + char *p; +# if defined(OPUS_ARM_MAY_HAVE_EDSP) + p = strstr(buf, " edsp"); + if(p != NULL && (p[5] == ' ' || p[5] == '\n')) + flags |= OPUS_CPU_ARM_EDSP; +# endif + +# if defined(OPUS_ARM_MAY_HAVE_NEON) + p = strstr(buf, " neon"); + if(p != NULL && (p[5] == ' ' || p[5] == '\n')) + flags |= OPUS_CPU_ARM_NEON; +# endif + } +# endif + +# if defined(OPUS_ARM_MAY_HAVE_MEDIA) + /* Search for media capabilities (>= ARMv6) */ + if(memcmp(buf, "CPU architecture:", 17) == 0) + { + int version; + version = atoi(buf+17); + + if(version >= 6) + flags |= OPUS_CPU_ARM_MEDIA; + } +# endif + } + + fclose(cpuinfo); + } + return flags; +} +#else +/* The feature registers which can tell us what the processor supports are + * accessible in priveleged modes only, so we can't have a general user-space + * detection method like on x86.*/ +# error "Configured to use ARM asm but no CPU detection method available for " \ + "your platform. Reconfigure with --disable-rtcd (or send patches)." +#endif + +int opus_select_arch(void) +{ + opus_uint32 flags = opus_cpu_capabilities(); + int arch = 0; + + if(!(flags & OPUS_CPU_ARM_EDSP)) + return arch; + arch++; + + if(!(flags & OPUS_CPU_ARM_MEDIA)) + return arch; + arch++; + + if(!(flags & OPUS_CPU_ARM_NEON)) + return arch; + arch++; + + return arch; +} + +#endif diff --git a/TelegramClient.Opus/opus/celt/arm/armcpu.h b/TelegramClient.Opus/opus/celt/arm/armcpu.h new file mode 100755 index 0000000..ac57446 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/arm/armcpu.h @@ -0,0 +1,71 @@ +/* Copyright (c) 2010 Xiph.Org Foundation + * Copyright (c) 2013 Parrot */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#if !defined(ARMCPU_H) +# define ARMCPU_H + +# if defined(OPUS_ARM_MAY_HAVE_EDSP) +# define MAY_HAVE_EDSP(name) name ## _edsp +# else +# define MAY_HAVE_EDSP(name) name ## _c +# endif + +# if defined(OPUS_ARM_MAY_HAVE_MEDIA) +# define MAY_HAVE_MEDIA(name) name ## _media +# else +# define MAY_HAVE_MEDIA(name) MAY_HAVE_EDSP(name) +# endif + +# if defined(OPUS_ARM_MAY_HAVE_NEON) +# define MAY_HAVE_NEON(name) name ## _neon +# else +# define MAY_HAVE_NEON(name) MAY_HAVE_MEDIA(name) +# endif + +# if defined(OPUS_ARM_PRESUME_EDSP) +# define PRESUME_EDSP(name) name ## _edsp +# else +# define PRESUME_EDSP(name) name ## _c +# endif + +# if defined(OPUS_ARM_PRESUME_MEDIA) +# define PRESUME_MEDIA(name) name ## _media +# else +# define PRESUME_MEDIA(name) PRESUME_EDSP(name) +# endif + +# if defined(OPUS_ARM_PRESUME_NEON) +# define PRESUME_NEON(name) name ## _neon +# else +# define PRESUME_NEON(name) PRESUME_MEDIA(name) +# endif + +# if defined(OPUS_HAVE_RTCD) +int opus_select_arch(void); +# endif + +#endif diff --git a/TelegramClient.Opus/opus/celt/arm/fixed_armv4.h b/TelegramClient.Opus/opus/celt/arm/fixed_armv4.h new file mode 100755 index 0000000..b690bc8 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/arm/fixed_armv4.h @@ -0,0 +1,76 @@ +/* Copyright (C) 2013 Xiph.Org Foundation and contributors */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef FIXED_ARMv4_H +#define FIXED_ARMv4_H + +/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */ +#undef MULT16_32_Q16 +static OPUS_INLINE opus_val32 MULT16_32_Q16_armv4(opus_val16 a, opus_val32 b) +{ + unsigned rd_lo; + int rd_hi; + __asm__( + "#MULT16_32_Q16\n\t" + "smull %0, %1, %2, %3\n\t" + : "=&r"(rd_lo), "=&r"(rd_hi) + : "%r"(b),"r"(a<<16) + ); + return rd_hi; +} +#define MULT16_32_Q16(a, b) (MULT16_32_Q16_armv4(a, b)) + + +/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */ +#undef MULT16_32_Q15 +static OPUS_INLINE opus_val32 MULT16_32_Q15_armv4(opus_val16 a, opus_val32 b) +{ + unsigned rd_lo; + int rd_hi; + __asm__( + "#MULT16_32_Q15\n\t" + "smull %0, %1, %2, %3\n\t" + : "=&r"(rd_lo), "=&r"(rd_hi) + : "%r"(b), "r"(a<<16) + ); + /*We intentionally don't OR in the high bit of rd_lo for speed.*/ + return rd_hi<<1; +} +#define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv4(a, b)) + + +/** 16x32 multiply, followed by a 15-bit shift right and 32-bit add. + b must fit in 31 bits. + Result fits in 32 bits. */ +#undef MAC16_32_Q15 +#define MAC16_32_Q15(c, a, b) ADD32(c, MULT16_32_Q15(a, b)) + + +/** 32x32 multiplication, followed by a 31-bit shift right. Results fits in 32 bits */ +#undef MULT32_32_Q31 +#define MULT32_32_Q31(a,b) (opus_val32)((((opus_int64)(a)) * ((opus_int64)(b)))>>31) + +#endif diff --git a/TelegramClient.Opus/opus/celt/arm/fixed_armv5e.h b/TelegramClient.Opus/opus/celt/arm/fixed_armv5e.h new file mode 100755 index 0000000..1194a7d --- /dev/null +++ b/TelegramClient.Opus/opus/celt/arm/fixed_armv5e.h @@ -0,0 +1,116 @@ +/* Copyright (C) 2007-2009 Xiph.Org Foundation + Copyright (C) 2003-2008 Jean-Marc Valin + Copyright (C) 2007-2008 CSIRO + Copyright (C) 2013 Parrot */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef FIXED_ARMv5E_H +#define FIXED_ARMv5E_H + +#include "fixed_armv4.h" + +/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */ +#undef MULT16_32_Q16 +static OPUS_INLINE opus_val32 MULT16_32_Q16_armv5e(opus_val16 a, opus_val32 b) +{ + int res; + __asm__( + "#MULT16_32_Q16\n\t" + "smulwb %0, %1, %2\n\t" + : "=r"(res) + : "r"(b),"r"(a) + ); + return res; +} +#define MULT16_32_Q16(a, b) (MULT16_32_Q16_armv5e(a, b)) + + +/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */ +#undef MULT16_32_Q15 +static OPUS_INLINE opus_val32 MULT16_32_Q15_armv5e(opus_val16 a, opus_val32 b) +{ + int res; + __asm__( + "#MULT16_32_Q15\n\t" + "smulwb %0, %1, %2\n\t" + : "=r"(res) + : "r"(b), "r"(a) + ); + return res<<1; +} +#define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv5e(a, b)) + + +/** 16x32 multiply, followed by a 15-bit shift right and 32-bit add. + b must fit in 31 bits. + Result fits in 32 bits. */ +#undef MAC16_32_Q15 +static OPUS_INLINE opus_val32 MAC16_32_Q15_armv5e(opus_val32 c, opus_val16 a, + opus_val32 b) +{ + int res; + __asm__( + "#MAC16_32_Q15\n\t" + "smlawb %0, %1, %2, %3;\n" + : "=r"(res) + : "r"(b<<1), "r"(a), "r"(c) + ); + return res; +} +#define MAC16_32_Q15(c, a, b) (MAC16_32_Q15_armv5e(c, a, b)) + +/** 16x16 multiply-add where the result fits in 32 bits */ +#undef MAC16_16 +static OPUS_INLINE opus_val32 MAC16_16_armv5e(opus_val32 c, opus_val16 a, + opus_val16 b) +{ + int res; + __asm__( + "#MAC16_16\n\t" + "smlabb %0, %1, %2, %3;\n" + : "=r"(res) + : "r"(a), "r"(b), "r"(c) + ); + return res; +} +#define MAC16_16(c, a, b) (MAC16_16_armv5e(c, a, b)) + +/** 16x16 multiplication where the result fits in 32 bits */ +#undef MULT16_16 +static OPUS_INLINE opus_val32 MULT16_16_armv5e(opus_val16 a, opus_val16 b) +{ + int res; + __asm__( + "#MULT16_16\n\t" + "smulbb %0, %1, %2;\n" + : "=r"(res) + : "r"(a), "r"(b) + ); + return res; +} +#define MULT16_16(a, b) (MULT16_16_armv5e(a, b)) + +#endif diff --git a/TelegramClient.Opus/opus/celt/arm/kiss_fft_armv4.h b/TelegramClient.Opus/opus/celt/arm/kiss_fft_armv4.h new file mode 100755 index 0000000..e4faad6 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/arm/kiss_fft_armv4.h @@ -0,0 +1,121 @@ +/*Copyright (c) 2013, Xiph.Org Foundation and contributors. + + 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. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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.*/ + +#ifndef KISS_FFT_ARMv4_H +#define KISS_FFT_ARMv4_H + +#if !defined(KISS_FFT_GUTS_H) +#error "This file should only be included from _kiss_fft_guts.h" +#endif + +#ifdef FIXED_POINT + +#undef C_MUL +#define C_MUL(m,a,b) \ + do{ \ + int br__; \ + int bi__; \ + int tt__; \ + __asm__ __volatile__( \ + "#C_MUL\n\t" \ + "ldrsh %[br], [%[bp], #0]\n\t" \ + "ldm %[ap], {r0,r1}\n\t" \ + "ldrsh %[bi], [%[bp], #2]\n\t" \ + "smull %[tt], %[mi], r1, %[br]\n\t" \ + "smlal %[tt], %[mi], r0, %[bi]\n\t" \ + "rsb %[bi], %[bi], #0\n\t" \ + "smull %[br], %[mr], r0, %[br]\n\t" \ + "mov %[tt], %[tt], lsr #15\n\t" \ + "smlal %[br], %[mr], r1, %[bi]\n\t" \ + "orr %[mi], %[tt], %[mi], lsl #17\n\t" \ + "mov %[br], %[br], lsr #15\n\t" \ + "orr %[mr], %[br], %[mr], lsl #17\n\t" \ + : [mr]"=r"((m).r), [mi]"=r"((m).i), \ + [br]"=&r"(br__), [bi]"=r"(bi__), [tt]"=r"(tt__) \ + : [ap]"r"(&(a)), [bp]"r"(&(b)) \ + : "r0", "r1" \ + ); \ + } \ + while(0) + +#undef C_MUL4 +#define C_MUL4(m,a,b) \ + do{ \ + int br__; \ + int bi__; \ + int tt__; \ + __asm__ __volatile__( \ + "#C_MUL4\n\t" \ + "ldrsh %[br], [%[bp], #0]\n\t" \ + "ldm %[ap], {r0,r1}\n\t" \ + "ldrsh %[bi], [%[bp], #2]\n\t" \ + "smull %[tt], %[mi], r1, %[br]\n\t" \ + "smlal %[tt], %[mi], r0, %[bi]\n\t" \ + "rsb %[bi], %[bi], #0\n\t" \ + "smull %[br], %[mr], r0, %[br]\n\t" \ + "mov %[tt], %[tt], lsr #17\n\t" \ + "smlal %[br], %[mr], r1, %[bi]\n\t" \ + "orr %[mi], %[tt], %[mi], lsl #15\n\t" \ + "mov %[br], %[br], lsr #17\n\t" \ + "orr %[mr], %[br], %[mr], lsl #15\n\t" \ + : [mr]"=r"((m).r), [mi]"=r"((m).i), \ + [br]"=&r"(br__), [bi]"=r"(bi__), [tt]"=r"(tt__) \ + : [ap]"r"(&(a)), [bp]"r"(&(b)) \ + : "r0", "r1" \ + ); \ + } \ + while(0) + +#undef C_MULC +#define C_MULC(m,a,b) \ + do{ \ + int br__; \ + int bi__; \ + int tt__; \ + __asm__ __volatile__( \ + "#C_MULC\n\t" \ + "ldrsh %[br], [%[bp], #0]\n\t" \ + "ldm %[ap], {r0,r1}\n\t" \ + "ldrsh %[bi], [%[bp], #2]\n\t" \ + "smull %[tt], %[mr], r0, %[br]\n\t" \ + "smlal %[tt], %[mr], r1, %[bi]\n\t" \ + "rsb %[bi], %[bi], #0\n\t" \ + "smull %[br], %[mi], r1, %[br]\n\t" \ + "mov %[tt], %[tt], lsr #15\n\t" \ + "smlal %[br], %[mi], r0, %[bi]\n\t" \ + "orr %[mr], %[tt], %[mr], lsl #17\n\t" \ + "mov %[br], %[br], lsr #15\n\t" \ + "orr %[mi], %[br], %[mi], lsl #17\n\t" \ + : [mr]"=r"((m).r), [mi]"=r"((m).i), \ + [br]"=&r"(br__), [bi]"=r"(bi__), [tt]"=r"(tt__) \ + : [ap]"r"(&(a)), [bp]"r"(&(b)) \ + : "r0", "r1" \ + ); \ + } \ + while(0) + +#endif /* FIXED_POINT */ + +#endif /* KISS_FFT_ARMv4_H */ diff --git a/TelegramClient.Opus/opus/celt/arm/kiss_fft_armv5e.h b/TelegramClient.Opus/opus/celt/arm/kiss_fft_armv5e.h new file mode 100755 index 0000000..9eca183 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/arm/kiss_fft_armv5e.h @@ -0,0 +1,118 @@ +/*Copyright (c) 2013, Xiph.Org Foundation and contributors. + + 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. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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.*/ + +#ifndef KISS_FFT_ARMv5E_H +#define KISS_FFT_ARMv5E_H + +#if !defined(KISS_FFT_GUTS_H) +#error "This file should only be included from _kiss_fft_guts.h" +#endif + +#ifdef FIXED_POINT + +#if defined(__thumb__)||defined(__thumb2__) +#define LDRD_CONS "Q" +#else +#define LDRD_CONS "Uq" +#endif + +#undef C_MUL +#define C_MUL(m,a,b) \ + do{ \ + int mr1__; \ + int mr2__; \ + int mi__; \ + long long aval__; \ + int bval__; \ + __asm__( \ + "#C_MUL\n\t" \ + "ldrd %[aval], %H[aval], %[ap]\n\t" \ + "ldr %[bval], %[bp]\n\t" \ + "smulwb %[mi], %H[aval], %[bval]\n\t" \ + "smulwb %[mr1], %[aval], %[bval]\n\t" \ + "smulwt %[mr2], %H[aval], %[bval]\n\t" \ + "smlawt %[mi], %[aval], %[bval], %[mi]\n\t" \ + : [mr1]"=r"(mr1__), [mr2]"=r"(mr2__), [mi]"=r"(mi__), \ + [aval]"=&r"(aval__), [bval]"=r"(bval__) \ + : [ap]LDRD_CONS(a), [bp]"m"(b) \ + ); \ + (m).r = SHL32(SUB32(mr1__, mr2__), 1); \ + (m).i = SHL32(mi__, 1); \ + } \ + while(0) + +#undef C_MUL4 +#define C_MUL4(m,a,b) \ + do{ \ + int mr1__; \ + int mr2__; \ + int mi__; \ + long long aval__; \ + int bval__; \ + __asm__( \ + "#C_MUL4\n\t" \ + "ldrd %[aval], %H[aval], %[ap]\n\t" \ + "ldr %[bval], %[bp]\n\t" \ + "smulwb %[mi], %H[aval], %[bval]\n\t" \ + "smulwb %[mr1], %[aval], %[bval]\n\t" \ + "smulwt %[mr2], %H[aval], %[bval]\n\t" \ + "smlawt %[mi], %[aval], %[bval], %[mi]\n\t" \ + : [mr1]"=r"(mr1__), [mr2]"=r"(mr2__), [mi]"=r"(mi__), \ + [aval]"=&r"(aval__), [bval]"=r"(bval__) \ + : [ap]LDRD_CONS(a), [bp]"m"(b) \ + ); \ + (m).r = SHR32(SUB32(mr1__, mr2__), 1); \ + (m).i = SHR32(mi__, 1); \ + } \ + while(0) + +#undef C_MULC +#define C_MULC(m,a,b) \ + do{ \ + int mr__; \ + int mi1__; \ + int mi2__; \ + long long aval__; \ + int bval__; \ + __asm__( \ + "#C_MULC\n\t" \ + "ldrd %[aval], %H[aval], %[ap]\n\t" \ + "ldr %[bval], %[bp]\n\t" \ + "smulwb %[mr], %[aval], %[bval]\n\t" \ + "smulwb %[mi1], %H[aval], %[bval]\n\t" \ + "smulwt %[mi2], %[aval], %[bval]\n\t" \ + "smlawt %[mr], %H[aval], %[bval], %[mr]\n\t" \ + : [mr]"=r"(mr__), [mi1]"=r"(mi1__), [mi2]"=r"(mi2__), \ + [aval]"=&r"(aval__), [bval]"=r"(bval__) \ + : [ap]LDRD_CONS(a), [bp]"m"(b) \ + ); \ + (m).r = SHL32(mr__, 1); \ + (m).i = SHL32(SUB32(mi1__, mi2__), 1); \ + } \ + while(0) + +#endif /* FIXED_POINT */ + +#endif /* KISS_FFT_GUTS_H */ diff --git a/TelegramClient.Opus/opus/celt/arm/pitch_arm.h b/TelegramClient.Opus/opus/celt/arm/pitch_arm.h new file mode 100755 index 0000000..a07f8ac --- /dev/null +++ b/TelegramClient.Opus/opus/celt/arm/pitch_arm.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2010 Xiph.Org Foundation + * Copyright (c) 2013 Parrot */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#if !defined(PITCH_ARM_H) +# define PITCH_ARM_H + +# include "armcpu.h" + +# if defined(FIXED_POINT) + +# if defined(OPUS_ARM_MAY_HAVE_NEON) +opus_val32 celt_pitch_xcorr_neon(const opus_val16 *_x, const opus_val16 *_y, + opus_val32 *xcorr, int len, int max_pitch); +# endif + +# if defined(OPUS_ARM_MAY_HAVE_MEDIA) +# define celt_pitch_xcorr_media MAY_HAVE_EDSP(celt_pitch_xcorr) +# endif + +# if defined(OPUS_ARM_MAY_HAVE_EDSP) +opus_val32 celt_pitch_xcorr_edsp(const opus_val16 *_x, const opus_val16 *_y, + opus_val32 *xcorr, int len, int max_pitch); +# endif + +# if !defined(OPUS_HAVE_RTCD) +# define OVERRIDE_PITCH_XCORR (1) +# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ + ((void)(arch),PRESUME_NEON(celt_pitch_xcorr)(_x, _y, xcorr, len, max_pitch)) +# endif + +# endif + +#endif diff --git a/TelegramClient.Opus/opus/celt/bands.c b/TelegramClient.Opus/opus/celt/bands.c new file mode 100755 index 0000000..cce56e2 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/bands.c @@ -0,0 +1,1518 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Copyright (c) 2008-2009 Gregory Maxwell + Written by Jean-Marc Valin and Gregory Maxwell */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "bands.h" +#include "modes.h" +#include "vq.h" +#include "cwrs.h" +#include "stack_alloc.h" +#include "os_support.h" +#include "mathops.h" +#include "rate.h" +#include "quant_bands.h" +#include "pitch.h" + +int hysteresis_decision(opus_val16 val, const opus_val16 *thresholds, const opus_val16 *hysteresis, int N, int prev) +{ + int i; + for (i=0;iprev && val < thresholds[prev]+hysteresis[prev]) + i=prev; + if (i thresholds[prev-1]-hysteresis[prev-1]) + i=prev; + return i; +} + +opus_uint32 celt_lcg_rand(opus_uint32 seed) +{ + return 1664525 * seed + 1013904223; +} + +/* This is a cos() approximation designed to be bit-exact on any platform. Bit exactness + with this approximation is important because it has an impact on the bit allocation */ +static opus_int16 bitexact_cos(opus_int16 x) +{ + opus_int32 tmp; + opus_int16 x2; + tmp = (4096+((opus_int32)(x)*(x)))>>13; + celt_assert(tmp<=32767); + x2 = tmp; + x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2))))); + celt_assert(x2<=32766); + return 1+x2; +} + +static int bitexact_log2tan(int isin,int icos) +{ + int lc; + int ls; + lc=EC_ILOG(icos); + ls=EC_ILOG(isin); + icos<<=15-lc; + isin<<=15-ls; + return (ls-lc)*(1<<11) + +FRAC_MUL16(isin, FRAC_MUL16(isin, -2597) + 7932) + -FRAC_MUL16(icos, FRAC_MUL16(icos, -2597) + 7932); +} + +#ifdef FIXED_POINT +/* Compute the amplitude (sqrt energy) in each of the bands */ +void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int M) +{ + int i, c, N; + const opus_int16 *eBands = m->eBands; + N = M*m->shortMdctSize; + c=0; do { + for (i=0;i 0) + { + int shift = celt_ilog2(maxval)-10; + j=M*eBands[i]; do { + sum = MAC16_16(sum, EXTRACT16(VSHR32(X[j+c*N],shift)), + EXTRACT16(VSHR32(X[j+c*N],shift))); + } while (++jnbEBands] = EPSILON+VSHR32(EXTEND32(celt_sqrt(sum)),-shift); + } else { + bandE[i+c*m->nbEBands] = EPSILON; + } + /*printf ("%f ", bandE[i+c*m->nbEBands]);*/ + } + } while (++ceBands; + N = M*m->shortMdctSize; + c=0; do { + i=0; do { + opus_val16 g; + int j,shift; + opus_val16 E; + shift = celt_zlog2(bandE[i+c*m->nbEBands])-13; + E = VSHR32(bandE[i+c*m->nbEBands], shift); + g = EXTRACT16(celt_rcp(SHL32(E,3))); + j=M*eBands[i]; do { + X[j+c*N] = MULT16_16_Q15(VSHR32(freq[j+c*N],shift-1),g); + } while (++jeBands; + N = M*m->shortMdctSize; + c=0; do { + for (i=0;inbEBands] = celt_sqrt(sum); + /*printf ("%f ", bandE[i+c*m->nbEBands]);*/ + } + } while (++ceBands; + N = M*m->shortMdctSize; + c=0; do { + for (i=0;inbEBands]); + for (j=M*eBands[i];jeBands; + N = M*m->shortMdctSize; + celt_assert2(C<=2, "denormalise_bands() not implemented for >2 channels"); + c=0; do { + celt_sig * OPUS_RESTRICT f; + const celt_norm * OPUS_RESTRICT x; + f = freq+c*N; + x = X+c*N+M*eBands[start]; + for (i=0;inbEBands], SHL16((opus_val16)eMeans[i],6)); +#ifndef FIXED_POINT + g = celt_exp2(lg); +#else + /* Handle the integer part of the log energy */ + shift = 16-(lg>>DB_SHIFT); + if (shift>31) + { + shift=0; + g=0; + } else { + /* Handle the fractional part. */ + g = celt_exp2_frac(lg&((1<eBands[i+1]-m->eBands[i]; + /* depth in 1/8 bits */ + depth = (1+pulses[i])/((m->eBands[i+1]-m->eBands[i])<>1; + t = SHL32(t, (7-shift)<<1); + sqrt_1 = celt_rsqrt_norm(t); + } +#else + thresh = .5f*celt_exp2(-.125f*depth); + sqrt_1 = celt_rsqrt(N0<nbEBands+i]; + prev2 = prev2logE[c*m->nbEBands+i]; + if (C==1) + { + prev1 = MAX16(prev1,prev1logE[m->nbEBands+i]); + prev2 = MAX16(prev2,prev2logE[m->nbEBands+i]); + } + Ediff = EXTEND32(logE[c*m->nbEBands+i])-EXTEND32(MIN16(prev1,prev2)); + Ediff = MAX32(0, Ediff); + +#ifdef FIXED_POINT + if (Ediff < 16384) + { + opus_val32 r32 = SHR32(celt_exp2(-EXTRACT16(Ediff)),1); + r = 2*MIN16(16383,r32); + } else { + r = 0; + } + if (LM==3) + r = MULT16_16_Q14(23170, MIN32(23169, r)); + r = SHR16(MIN16(thresh, r),1); + r = SHR32(MULT16_16_Q15(sqrt_1, r),shift); +#else + /* r needs to be multiplied by 2 or 2*sqrt(2) depending on LM because + short blocks don't have the same energy as long */ + r = 2.f*celt_exp2(-Ediff); + if (LM==3) + r *= 1.41421356f; + r = MIN16(thresh, r); + r = r*sqrt_1; +#endif + X = X_+c*size+(m->eBands[i]<nbEBands]))-13; +#endif + left = VSHR32(bandE[i],shift); + right = VSHR32(bandE[i+m->nbEBands],shift); + norm = EPSILON + celt_sqrt(EPSILON+MULT16_16(left,left)+MULT16_16(right,right)); + a1 = DIV32_16(SHL32(EXTEND32(left),14),norm); + a2 = DIV32_16(SHL32(EXTEND32(right),14),norm); + for (j=0;j>1; + kr = celt_ilog2(Er)>>1; +#endif + t = VSHR32(El, (kl-7)<<1); + lgain = celt_rsqrt_norm(t); + t = VSHR32(Er, (kr-7)<<1); + rgain = celt_rsqrt_norm(t); + +#ifdef FIXED_POINT + if (kl < 7) + kl = 7; + if (kr < 7) + kr = 7; +#endif + + for (j=0;jeBands; + int decision; + int hf_sum=0; + + celt_assert(end>0); + + N0 = M*m->shortMdctSize; + + if (M*(eBands[end]-eBands[end-1]) <= 8) + return SPREAD_NONE; + c=0; do { + for (i=0;im->nbEBands-4) + hf_sum += 32*(tcount[1]+tcount[0])/N; + tmp = (2*tcount[2] >= N) + (2*tcount[1] >= N) + (2*tcount[0] >= N); + sum += tmp*256; + nbBands++; + } + } while (++cnbEBands+end); + *hf_average = (*hf_average+hf_sum)>>1; + hf_sum = *hf_average; + if (*tapset_decision==2) + hf_sum += 4; + else if (*tapset_decision==0) + hf_sum -= 4; + if (hf_sum > 22) + *tapset_decision=2; + else if (hf_sum > 18) + *tapset_decision=1; + else + *tapset_decision=0; + } + /*printf("%d %d %d\n", hf_sum, *hf_average, *tapset_decision);*/ + celt_assert(nbBands>0); /* end has to be non-zero */ + sum /= nbBands; + /* Recursive averaging */ + sum = (sum+*average)>>1; + *average = sum; + /* Hysteresis */ + sum = (3*sum + (((3-last_decision)<<7) + 64) + 2)>>2; + if (sum < 80) + { + decision = SPREAD_AGGRESSIVE; + } else if (sum < 256) + { + decision = SPREAD_NORMAL; + } else if (sum < 384) + { + decision = SPREAD_LIGHT; + } else { + decision = SPREAD_NONE; + } +#ifdef FUZZING + decision = rand()&0x3; + *tapset_decision=rand()%3; +#endif + return decision; +} + +/* Indexing table for converting from natural Hadamard to ordery Hadamard + This is essentially a bit-reversed Gray, on top of which we've added + an inversion of the order because we want the DC at the end rather than + the beginning. The lines are for N=2, 4, 8, 16 */ +static const int ordery_table[] = { + 1, 0, + 3, 0, 2, 1, + 7, 0, 4, 3, 6, 1, 5, 2, + 15, 0, 8, 7, 12, 3, 11, 4, 14, 1, 9, 6, 13, 2, 10, 5, +}; + +static void deinterleave_hadamard(celt_norm *X, int N0, int stride, int hadamard) +{ + int i,j; + VARDECL(celt_norm, tmp); + int N; + SAVE_STACK; + N = N0*stride; + ALLOC(tmp, N, celt_norm); + celt_assert(stride>0); + if (hadamard) + { + const int *ordery = ordery_table+stride-2; + for (i=0;i>= 1; + for (i=0;i>1)) { + qn = 1; + } else { + qn = exp2_table8[qb&0x7]>>(14-(qb>>BITRES)); + qn = (qn+1)>>1<<1; + } + celt_assert(qn <= 256); + return qn; +} + +struct band_ctx { + int encode; + const CELTMode *m; + int i; + int intensity; + int spread; + int tf_change; + ec_ctx *ec; + opus_int32 remaining_bits; + const celt_ener *bandE; + opus_uint32 seed; +}; + +struct split_ctx { + int inv; + int imid; + int iside; + int delta; + int itheta; + int qalloc; +}; + +static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx, + celt_norm *X, celt_norm *Y, int N, int *b, int B, int B0, + int LM, + int stereo, int *fill) +{ + int qn; + int itheta=0; + int delta; + int imid, iside; + int qalloc; + int pulse_cap; + int offset; + opus_int32 tell; + int inv=0; + int encode; + const CELTMode *m; + int i; + int intensity; + ec_ctx *ec; + const celt_ener *bandE; + + encode = ctx->encode; + m = ctx->m; + i = ctx->i; + intensity = ctx->intensity; + ec = ctx->ec; + bandE = ctx->bandE; + + /* Decide on the resolution to give to the split parameter theta */ + pulse_cap = m->logN[i]+LM*(1<>1) - (stereo&&N==2 ? QTHETA_OFFSET_TWOPHASE : QTHETA_OFFSET); + qn = compute_qn(N, *b, offset, pulse_cap, stereo); + if (stereo && i>=intensity) + qn = 1; + if (encode) + { + /* theta is the atan() of the ratio between the (normalized) + side and mid. With just that parameter, we can re-scale both + mid and side because we know that 1) they have unit norm and + 2) they are orthogonal. */ + itheta = stereo_itheta(X, Y, stereo, N); + } + tell = ec_tell_frac(ec); + if (qn!=1) + { + if (encode) + itheta = (itheta*qn+8192)>>14; + + /* Entropy coding of the angle. We use a uniform pdf for the + time split, a step for stereo, and a triangular one for the rest. */ + if (stereo && N>2) + { + int p0 = 3; + int x = itheta; + int x0 = qn/2; + int ft = p0*(x0+1) + x0; + /* Use a probability of p0 up to itheta=8192 and then use 1 after */ + if (encode) + { + ec_encode(ec,x<=x0?p0*x:(x-1-x0)+(x0+1)*p0,x<=x0?p0*(x+1):(x-x0)+(x0+1)*p0,ft); + } else { + int fs; + fs=ec_decode(ec,ft); + if (fs<(x0+1)*p0) + x=fs/p0; + else + x=x0+1+(fs-(x0+1)*p0); + ec_dec_update(ec,x<=x0?p0*x:(x-1-x0)+(x0+1)*p0,x<=x0?p0*(x+1):(x-x0)+(x0+1)*p0,ft); + itheta = x; + } + } else if (B0>1 || stereo) { + /* Uniform pdf */ + if (encode) + ec_enc_uint(ec, itheta, qn+1); + else + itheta = ec_dec_uint(ec, qn+1); + } else { + int fs=1, ft; + ft = ((qn>>1)+1)*((qn>>1)+1); + if (encode) + { + int fl; + + fs = itheta <= (qn>>1) ? itheta + 1 : qn + 1 - itheta; + fl = itheta <= (qn>>1) ? itheta*(itheta + 1)>>1 : + ft - ((qn + 1 - itheta)*(qn + 2 - itheta)>>1); + + ec_encode(ec, fl, fl+fs, ft); + } else { + /* Triangular pdf */ + int fl=0; + int fm; + fm = ec_decode(ec, ft); + + if (fm < ((qn>>1)*((qn>>1) + 1)>>1)) + { + itheta = (isqrt32(8*(opus_uint32)fm + 1) - 1)>>1; + fs = itheta + 1; + fl = itheta*(itheta + 1)>>1; + } + else + { + itheta = (2*(qn + 1) + - isqrt32(8*(opus_uint32)(ft - fm - 1) + 1))>>1; + fs = qn + 1 - itheta; + fl = ft - ((qn + 1 - itheta)*(qn + 2 - itheta)>>1); + } + + ec_dec_update(ec, fl, fl+fs, ft); + } + } + itheta = (opus_int32)itheta*16384/qn; + if (encode && stereo) + { + if (itheta==0) + intensity_stereo(m, X, Y, bandE, i, N); + else + stereo_split(X, Y, N); + } + /* NOTE: Renormalising X and Y *may* help fixed-point a bit at very high rate. + Let's do that at higher complexity */ + } else if (stereo) { + if (encode) + { + inv = itheta > 8192; + if (inv) + { + int j; + for (j=0;j2<remaining_bits > 2<inv = inv; + sctx->imid = imid; + sctx->iside = iside; + sctx->delta = delta; + sctx->itheta = itheta; + sctx->qalloc = qalloc; +} +static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y, int b, + celt_norm *lowband_out) +{ +#ifdef RESYNTH + int resynth = 1; +#else + int resynth = !ctx->encode; +#endif + int c; + int stereo; + celt_norm *x = X; + int encode; + ec_ctx *ec; + + encode = ctx->encode; + ec = ctx->ec; + + stereo = Y != NULL; + c=0; do { + int sign=0; + if (ctx->remaining_bits>=1<remaining_bits -= 1<encode; +#endif + celt_norm *Y=NULL; + int encode; + const CELTMode *m; + int i; + int spread; + ec_ctx *ec; + + encode = ctx->encode; + m = ctx->m; + i = ctx->i; + spread = ctx->spread; + ec = ctx->ec; + + /* If we need 1.5 more bit than we can produce, split the band in two. */ + cache = m->cache.bits + m->cache.index[(LM+1)*m->nbEBands+i]; + if (LM != -1 && b > cache[cache[0]]+12 && N>2) + { + int mbits, sbits, delta; + int itheta; + int qalloc; + struct split_ctx sctx; + celt_norm *next_lowband2=NULL; + opus_int32 rebalance; + + N >>= 1; + Y = X+N; + LM -= 1; + if (B==1) + fill = (fill&1)|(fill<<1); + B = (B+1)>>1; + + compute_theta(ctx, &sctx, X, Y, N, &b, B, B0, + LM, 0, &fill); + imid = sctx.imid; + iside = sctx.iside; + delta = sctx.delta; + itheta = sctx.itheta; + qalloc = sctx.qalloc; +#ifdef FIXED_POINT + mid = imid; + side = iside; +#else + mid = (1.f/32768)*imid; + side = (1.f/32768)*iside; +#endif + + /* Give more bits to low-energy MDCTs than they would otherwise deserve */ + if (B0>1 && (itheta&0x3fff)) + { + if (itheta > 8192) + /* Rough approximation for pre-echo masking */ + delta -= delta>>(4-LM); + else + /* Corresponds to a forward-masking slope of 1.5 dB per 10 ms */ + delta = IMIN(0, delta + (N<>(5-LM))); + } + mbits = IMAX(0, IMIN(b, (b-delta)/2)); + sbits = b-mbits; + ctx->remaining_bits -= qalloc; + + if (lowband) + next_lowband2 = lowband+N; /* >32-bit split case */ + + rebalance = ctx->remaining_bits; + if (mbits >= sbits) + { + cm = quant_partition(ctx, X, N, mbits, B, + lowband, LM, + MULT16_16_P15(gain,mid), fill); + rebalance = mbits - (rebalance-ctx->remaining_bits); + if (rebalance > 3<>B)<<(B0>>1); + } else { + cm = quant_partition(ctx, Y, N, sbits, B, + next_lowband2, LM, + MULT16_16_P15(gain,side), fill>>B)<<(B0>>1); + rebalance = sbits - (rebalance-ctx->remaining_bits); + if (rebalance > 3<remaining_bits -= curr_bits; + + /* Ensures we can never bust the budget */ + while (ctx->remaining_bits < 0 && q > 0) + { + ctx->remaining_bits += curr_bits; + q--; + curr_bits = pulses2bits(m, i, LM, q); + ctx->remaining_bits -= curr_bits; + } + + if (q!=0) + { + int K = get_pulses(q); + + /* Finally do the actual quantization */ + if (encode) + { + cm = alg_quant(X, N, K, spread, B, ec +#ifdef RESYNTH + , gain +#endif + ); + } else { + cm = alg_unquant(X, N, K, spread, B, ec, gain); + } + } else { + /* If there's no pulse, fill the band anyway */ + int j; + if (resynth) + { + unsigned cm_mask; + /* B can be as large as 16, so this shift might overflow an int on a + 16-bit platform; use a long to get defined behavior.*/ + cm_mask = (unsigned)(1UL<seed = celt_lcg_rand(ctx->seed); + X[j] = (celt_norm)((opus_int32)ctx->seed>>20); + } + cm = cm_mask; + } else { + /* Folded spectrum */ + for (j=0;jseed = celt_lcg_rand(ctx->seed); + /* About 48 dB below the "normal" folding level */ + tmp = QCONST16(1.0f/256, 10); + tmp = (ctx->seed)&0x8000 ? tmp : -tmp; + X[j] = lowband[j]+tmp; + } + cm = fill; + } + renormalise_vector(X, N, gain); + } + } + } + } + + return cm; +} + + +/* This function is responsible for encoding and decoding a band for the mono case. */ +static unsigned quant_band(struct band_ctx *ctx, celt_norm *X, + int N, int b, int B, celt_norm *lowband, + int LM, celt_norm *lowband_out, + opus_val16 gain, celt_norm *lowband_scratch, int fill) +{ + int N0=N; + int N_B=N; + int N_B0; + int B0=B; + int time_divide=0; + int recombine=0; + int longBlocks; + unsigned cm=0; +#ifdef RESYNTH + int resynth = 1; +#else + int resynth = !ctx->encode; +#endif + int k; + int encode; + int tf_change; + + encode = ctx->encode; + tf_change = ctx->tf_change; + + longBlocks = B0==1; + + N_B /= B; + + /* Special case for one sample */ + if (N==1) + { + return quant_band_n1(ctx, X, NULL, b, lowband_out); + } + + if (tf_change>0) + recombine = tf_change; + /* Band recombining to increase frequency resolution */ + + if (lowband_scratch && lowband && (recombine || ((N_B&1) == 0 && tf_change<0) || B0>1)) + { + int j; + for (j=0;j>k, 1<>k, 1<>4]<<2; + } + B>>=recombine; + N_B<<=recombine; + + /* Increasing the time resolution */ + while ((N_B&1) == 0 && tf_change<0) + { + if (encode) + haar1(X, N_B, B); + if (lowband) + haar1(lowband, N_B, B); + fill |= fill<>= 1; + time_divide++; + tf_change++; + } + B0=B; + N_B0 = N_B; + + /* Reorganize the samples in time order instead of frequency order */ + if (B0>1) + { + if (encode) + deinterleave_hadamard(X, N_B>>recombine, B0<>recombine, B0<1) + interleave_hadamard(X, N_B>>recombine, B0<>= 1; + N_B <<= 1; + cm |= cm>>B; + haar1(X, N_B, B); + } + + for (k=0;k>k, 1<encode; +#endif + int mbits, sbits, delta; + int itheta; + int qalloc; + struct split_ctx sctx; + int orig_fill; + int encode; + ec_ctx *ec; + + encode = ctx->encode; + ec = ctx->ec; + + /* Special case for one sample */ + if (N==1) + { + return quant_band_n1(ctx, X, Y, b, lowband_out); + } + + orig_fill = fill; + + compute_theta(ctx, &sctx, X, Y, N, &b, B, B, + LM, 1, &fill); + inv = sctx.inv; + imid = sctx.imid; + iside = sctx.iside; + delta = sctx.delta; + itheta = sctx.itheta; + qalloc = sctx.qalloc; +#ifdef FIXED_POINT + mid = imid; + side = iside; +#else + mid = (1.f/32768)*imid; + side = (1.f/32768)*iside; +#endif + + /* This is a special case for N=2 that only works for stereo and takes + advantage of the fact that mid and side are orthogonal to encode + the side with just one bit. */ + if (N==2) + { + int c; + int sign=0; + celt_norm *x2, *y2; + mbits = b; + sbits = 0; + /* Only need one bit for the side. */ + if (itheta != 0 && itheta != 16384) + sbits = 1< 8192; + ctx->remaining_bits -= qalloc+sbits; + + x2 = c ? Y : X; + y2 = c ? X : Y; + if (sbits) + { + if (encode) + { + /* Here we only need to encode a sign for the side. */ + sign = x2[0]*y2[1] - x2[1]*y2[0] < 0; + ec_enc_bits(ec, sign, 1); + } else { + sign = ec_dec_bits(ec, 1); + } + } + sign = 1-2*sign; + /* We use orig_fill here because we want to fold the side, but if + itheta==16384, we'll have cleared the low bits of fill. */ + cm = quant_band(ctx, x2, N, mbits, B, lowband, + LM, lowband_out, Q15ONE, lowband_scratch, orig_fill); + /* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse), + and there's no need to worry about mixing with the other channel. */ + y2[0] = -sign*x2[1]; + y2[1] = sign*x2[0]; + if (resynth) + { + celt_norm tmp; + X[0] = MULT16_16_Q15(mid, X[0]); + X[1] = MULT16_16_Q15(mid, X[1]); + Y[0] = MULT16_16_Q15(side, Y[0]); + Y[1] = MULT16_16_Q15(side, Y[1]); + tmp = X[0]; + X[0] = SUB16(tmp,Y[0]); + Y[0] = ADD16(tmp,Y[0]); + tmp = X[1]; + X[1] = SUB16(tmp,Y[1]); + Y[1] = ADD16(tmp,Y[1]); + } + } else { + /* "Normal" split code */ + opus_int32 rebalance; + + mbits = IMAX(0, IMIN(b, (b-delta)/2)); + sbits = b-mbits; + ctx->remaining_bits -= qalloc; + + rebalance = ctx->remaining_bits; + if (mbits >= sbits) + { + /* In stereo mode, we do not apply a scaling to the mid because we need the normalized + mid for folding later. */ + cm = quant_band(ctx, X, N, mbits, B, + lowband, LM, lowband_out, + Q15ONE, lowband_scratch, fill); + rebalance = mbits - (rebalance-ctx->remaining_bits); + if (rebalance > 3<>B); + } else { + /* For a stereo split, the high bits of fill are always zero, so no + folding will be done to the side. */ + cm = quant_band(ctx, Y, N, sbits, B, + NULL, LM, NULL, + side, NULL, fill>>B); + rebalance = sbits - (rebalance-ctx->remaining_bits); + if (rebalance > 3<eBands; + celt_norm * OPUS_RESTRICT norm, * OPUS_RESTRICT norm2; + VARDECL(celt_norm, _norm); + celt_norm *lowband_scratch; + int B; + int M; + int lowband_offset; + int update_lowband = 1; + int C = Y_ != NULL ? 2 : 1; + int norm_offset; +#ifdef RESYNTH + int resynth = 1; +#else + int resynth = !encode; +#endif + struct band_ctx ctx; + SAVE_STACK; + + M = 1<nbEBands-1]-norm_offset), celt_norm); + norm = _norm; + norm2 = norm + M*eBands[m->nbEBands-1]-norm_offset; + /* We can use the last band as scratch space because we don't need that + scratch space for the last band. */ + lowband_scratch = X_+M*eBands[m->nbEBands-1]; + + lowband_offset = 0; + ctx.bandE = bandE; + ctx.ec = ec; + ctx.encode = encode; + ctx.intensity = intensity; + ctx.m = m; + ctx.seed = *seed; + ctx.spread = spread; + for (i=start;i= M*eBands[start] && (update_lowband || lowband_offset==0)) + lowband_offset = i; + + tf_change = tf_res[i]; + ctx.tf_change = tf_change; + if (i>=m->effEBands) + { + X=norm; + if (Y_!=NULL) + Y = norm; + lowband_scratch = NULL; + } + if (i==end-1) + lowband_scratch = NULL; + + /* Get a conservative estimate of the collapse_mask's for the bands we're + going to be folding from. */ + if (lowband_offset != 0 && (spread!=SPREAD_AGGRESSIVE || B>1 || tf_change<0)) + { + int fold_start; + int fold_end; + int fold_i; + /* This ensures we never repeat spectral content within one band */ + effective_lowband = IMAX(0, M*eBands[lowband_offset]-norm_offset-N); + fold_start = lowband_offset; + while(M*eBands[--fold_start] > effective_lowband+norm_offset); + fold_end = lowband_offset-1; + while(M*eBands[++fold_end] < effective_lowband+norm_offset+N); + x_cm = y_cm = 0; + fold_i = fold_start; do { + x_cm |= collapse_masks[fold_i*C+0]; + y_cm |= collapse_masks[fold_i*C+C-1]; + } while (++fold_i(N< +#include "celt.h" +#include "pitch.h" +#include "bands.h" +#include "modes.h" +#include "entcode.h" +#include "quant_bands.h" +#include "rate.h" +#include "stack_alloc.h" +#include "mathops.h" +#include "float_cast.h" +#include +#include "celt_lpc.h" +#include "vq.h" + +#ifndef PACKAGE_VERSION +#define PACKAGE_VERSION "unknown" +#endif + + +int resampling_factor(opus_int32 rate) +{ + int ret; + switch (rate) + { + case 48000: + ret = 1; + break; + case 24000: + ret = 2; + break; + case 16000: + ret = 3; + break; + case 12000: + ret = 4; + break; + case 8000: + ret = 6; + break; + default: +#ifndef CUSTOM_MODES + celt_assert(0); +#endif + ret = 0; + break; + } + return ret; +} + +#ifndef OVERRIDE_COMB_FILTER_CONST +static void comb_filter_const(opus_val32 *y, opus_val32 *x, int T, int N, + opus_val16 g10, opus_val16 g11, opus_val16 g12) +{ + opus_val32 x0, x1, x2, x3, x4; + int i; + x4 = x[-T-2]; + x3 = x[-T-1]; + x2 = x[-T]; + x1 = x[-T+1]; + for (i=0;inbEBands;i++) + { + int N; + N=(m->eBands[i+1]-m->eBands[i])<cache.caps[m->nbEBands*(2*LM+C-1)+i]+64)*C*N>>2; + } +} + + + +const char *opus_strerror(int error) +{ + static const char * const error_strings[8] = { + "success", + "invalid argument", + "buffer too small", + "internal error", + "corrupted stream", + "request not implemented", + "invalid state", + "memory allocation failed" + }; + if (error > 0 || error < -7) + return "unknown error"; + else + return error_strings[-error]; +} + +const char *opus_get_version_string(void) +{ + return "libopus " PACKAGE_VERSION +#ifdef FIXED_POINT + "-fixed" +#endif +#ifdef FUZZING + "-fuzzing" +#endif + ; +} diff --git a/TelegramClient.Opus/opus/celt/celt.h b/TelegramClient.Opus/opus/celt/celt.h new file mode 100755 index 0000000..5deea1f --- /dev/null +++ b/TelegramClient.Opus/opus/celt/celt.h @@ -0,0 +1,218 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Copyright (c) 2008 Gregory Maxwell + Written by Jean-Marc Valin and Gregory Maxwell */ +/** + @file celt.h + @brief Contains all the functions for encoding and decoding audio + */ + +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef CELT_H +#define CELT_H + +#include "opus_types.h" +#include "opus_defines.h" +#include "opus_custom.h" +#include "entenc.h" +#include "entdec.h" +#include "arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define CELTEncoder OpusCustomEncoder +#define CELTDecoder OpusCustomDecoder +#define CELTMode OpusCustomMode + +typedef struct { + int valid; + float tonality; + float tonality_slope; + float noisiness; + float activity; + float music_prob; + int bandwidth; +}AnalysisInfo; + +#define __celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr))) + +#define __celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr))) + +/* Encoder/decoder Requests */ + +/* Expose this option again when variable framesize actually works */ +#define OPUS_FRAMESIZE_VARIABLE 5010 /**< Optimize the frame size dynamically */ + + +#define CELT_SET_PREDICTION_REQUEST 10002 +/** Controls the use of interframe prediction. + 0=Independent frames + 1=Short term interframe prediction allowed + 2=Long term prediction allowed + */ +#define CELT_SET_PREDICTION(x) CELT_SET_PREDICTION_REQUEST, __opus_check_int(x) + +#define CELT_SET_INPUT_CLIPPING_REQUEST 10004 +#define CELT_SET_INPUT_CLIPPING(x) CELT_SET_INPUT_CLIPPING_REQUEST, __opus_check_int(x) + +#define CELT_GET_AND_CLEAR_ERROR_REQUEST 10007 +#define CELT_GET_AND_CLEAR_ERROR(x) CELT_GET_AND_CLEAR_ERROR_REQUEST, __opus_check_int_ptr(x) + +#define CELT_SET_CHANNELS_REQUEST 10008 +#define CELT_SET_CHANNELS(x) CELT_SET_CHANNELS_REQUEST, __opus_check_int(x) + + +/* Internal */ +#define CELT_SET_START_BAND_REQUEST 10010 +#define CELT_SET_START_BAND(x) CELT_SET_START_BAND_REQUEST, __opus_check_int(x) + +#define CELT_SET_END_BAND_REQUEST 10012 +#define CELT_SET_END_BAND(x) CELT_SET_END_BAND_REQUEST, __opus_check_int(x) + +#define CELT_GET_MODE_REQUEST 10015 +/** Get the CELTMode used by an encoder or decoder */ +#define CELT_GET_MODE(x) CELT_GET_MODE_REQUEST, __celt_check_mode_ptr_ptr(x) + +#define CELT_SET_SIGNALLING_REQUEST 10016 +#define CELT_SET_SIGNALLING(x) CELT_SET_SIGNALLING_REQUEST, __opus_check_int(x) + +#define CELT_SET_TONALITY_REQUEST 10018 +#define CELT_SET_TONALITY(x) CELT_SET_TONALITY_REQUEST, __opus_check_int(x) +#define CELT_SET_TONALITY_SLOPE_REQUEST 10020 +#define CELT_SET_TONALITY_SLOPE(x) CELT_SET_TONALITY_SLOPE_REQUEST, __opus_check_int(x) + +#define CELT_SET_ANALYSIS_REQUEST 10022 +#define CELT_SET_ANALYSIS(x) CELT_SET_ANALYSIS_REQUEST, __celt_check_analysis_ptr(x) + +#define OPUS_SET_LFE_REQUEST 10024 +#define OPUS_SET_LFE(x) OPUS_SET_LFE_REQUEST, __opus_check_int(x) + +#define OPUS_SET_ENERGY_MASK_REQUEST 10026 +#define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __opus_check_val16_ptr(x) + +/* Encoder stuff */ + +int celt_encoder_get_size(int channels); + +int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc); + +int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels, + int arch); + + + +/* Decoder stuff */ + +int celt_decoder_get_size(int channels); + + +int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels); + +int celt_decode_with_ec(OpusCustomDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec); + +#define celt_encoder_ctl opus_custom_encoder_ctl +#define celt_decoder_ctl opus_custom_decoder_ctl + + +#ifdef CUSTOM_MODES +#define OPUS_CUSTOM_NOSTATIC +#else +#define OPUS_CUSTOM_NOSTATIC static OPUS_INLINE +#endif + +static const unsigned char trim_icdf[11] = {126, 124, 119, 109, 87, 41, 19, 9, 4, 2, 0}; +/* Probs: NONE: 21.875%, LIGHT: 6.25%, NORMAL: 65.625%, AGGRESSIVE: 6.25% */ +static const unsigned char spread_icdf[4] = {25, 23, 2, 0}; + +static const unsigned char tapset_icdf[3]={2,1,0}; + +#ifdef CUSTOM_MODES +static const unsigned char toOpusTable[20] = { + 0xE0, 0xE8, 0xF0, 0xF8, + 0xC0, 0xC8, 0xD0, 0xD8, + 0xA0, 0xA8, 0xB0, 0xB8, + 0x00, 0x00, 0x00, 0x00, + 0x80, 0x88, 0x90, 0x98, +}; + +static const unsigned char fromOpusTable[16] = { + 0x80, 0x88, 0x90, 0x98, + 0x40, 0x48, 0x50, 0x58, + 0x20, 0x28, 0x30, 0x38, + 0x00, 0x08, 0x10, 0x18 +}; + +static OPUS_INLINE int toOpus(unsigned char c) +{ + int ret=0; + if (c<0xA0) + ret = toOpusTable[c>>3]; + if (ret == 0) + return -1; + else + return ret|(c&0x7); +} + +static OPUS_INLINE int fromOpus(unsigned char c) +{ + if (c<0x80) + return -1; + else + return fromOpusTable[(c>>3)-16] | (c&0x7); +} +#endif /* CUSTOM_MODES */ + +#define COMBFILTER_MAXPERIOD 1024 +#define COMBFILTER_MINPERIOD 15 + +extern const signed char tf_select_table[4][8]; + +int resampling_factor(opus_int32 rate); + +void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp, + int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip); + +void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N, + opus_val16 g0, opus_val16 g1, int tapset0, int tapset1, + const opus_val16 *window, int overlap); + +void init_caps(const CELTMode *m,int *cap,int LM,int C); + +#ifdef RESYNTH +void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem, celt_sig * OPUS_RESTRICT scratch); + +void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig *X, + celt_sig * OPUS_RESTRICT out_mem[], int C, int LM); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* CELT_H */ diff --git a/TelegramClient.Opus/opus/celt/celt_decoder.c b/TelegramClient.Opus/opus/celt/celt_decoder.c new file mode 100755 index 0000000..830398e --- /dev/null +++ b/TelegramClient.Opus/opus/celt/celt_decoder.c @@ -0,0 +1,1195 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2010 Xiph.Org Foundation + Copyright (c) 2008 Gregory Maxwell + Written by Jean-Marc Valin and Gregory Maxwell */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define CELT_DECODER_C + +#include "cpu_support.h" +#include "os_support.h" +#include "mdct.h" +#include +#include "celt.h" +#include "pitch.h" +#include "bands.h" +#include "modes.h" +#include "entcode.h" +#include "quant_bands.h" +#include "rate.h" +#include "stack_alloc.h" +#include "mathops.h" +#include "float_cast.h" +#include +#include "celt_lpc.h" +#include "vq.h" + +/**********************************************************************/ +/* */ +/* DECODER */ +/* */ +/**********************************************************************/ +#define DECODE_BUFFER_SIZE 2048 + +/** Decoder state + @brief Decoder state + */ +struct OpusCustomDecoder { + const OpusCustomMode *mode; + int overlap; + int channels; + int stream_channels; + + int downsample; + int start, end; + int signalling; + int arch; + + /* Everything beyond this point gets cleared on a reset */ +#define DECODER_RESET_START rng + + opus_uint32 rng; + int error; + int last_pitch_index; + int loss_count; + int postfilter_period; + int postfilter_period_old; + opus_val16 postfilter_gain; + opus_val16 postfilter_gain_old; + int postfilter_tapset; + int postfilter_tapset_old; + + celt_sig preemph_memD[2]; + + celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */ + /* opus_val16 lpc[], Size = channels*LPC_ORDER */ + /* opus_val16 oldEBands[], Size = 2*mode->nbEBands */ + /* opus_val16 oldLogE[], Size = 2*mode->nbEBands */ + /* opus_val16 oldLogE2[], Size = 2*mode->nbEBands */ + /* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */ +}; + +int celt_decoder_get_size(int channels) +{ + const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL); + return opus_custom_decoder_get_size(mode, channels); +} + +OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int channels) +{ + int size = sizeof(struct CELTDecoder) + + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig) + + channels*LPC_ORDER*sizeof(opus_val16) + + 4*2*mode->nbEBands*sizeof(opus_val16); + return size; +} + +#ifdef CUSTOM_MODES +CELTDecoder *opus_custom_decoder_create(const CELTMode *mode, int channels, int *error) +{ + int ret; + CELTDecoder *st = (CELTDecoder *)opus_alloc(opus_custom_decoder_get_size(mode, channels)); + ret = opus_custom_decoder_init(st, mode, channels); + if (ret != OPUS_OK) + { + opus_custom_decoder_destroy(st); + st = NULL; + } + if (error) + *error = ret; + return st; +} +#endif /* CUSTOM_MODES */ + +int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels) +{ + int ret; + ret = opus_custom_decoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels); + if (ret != OPUS_OK) + return ret; + st->downsample = resampling_factor(sampling_rate); + if (st->downsample==0) + return OPUS_BAD_ARG; + else + return OPUS_OK; +} + +OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels) +{ + if (channels < 0 || channels > 2) + return OPUS_BAD_ARG; + + if (st==NULL) + return OPUS_ALLOC_FAIL; + + OPUS_CLEAR((char*)st, opus_custom_decoder_get_size(mode, channels)); + + st->mode = mode; + st->overlap = mode->overlap; + st->stream_channels = st->channels = channels; + + st->downsample = 1; + st->start = 0; + st->end = st->mode->effEBands; + st->signalling = 1; + st->arch = opus_select_arch(); + + st->loss_count = 0; + + opus_custom_decoder_ctl(st, OPUS_RESET_STATE); + + return OPUS_OK; +} + +#ifdef CUSTOM_MODES +void opus_custom_decoder_destroy(CELTDecoder *st) +{ + opus_free(st); +} +#endif /* CUSTOM_MODES */ + +static OPUS_INLINE opus_val16 SIG2WORD16(celt_sig x) +{ +#ifdef FIXED_POINT + x = PSHR32(x, SIG_SHIFT); + x = MAX32(x, -32768); + x = MIN32(x, 32767); + return EXTRACT16(x); +#else + return (opus_val16)x; +#endif +} + +#ifndef RESYNTH +static +#endif +void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem, celt_sig * OPUS_RESTRICT scratch) +{ + int c; + int Nd; + int apply_downsampling=0; + opus_val16 coef0; + + coef0 = coef[0]; + Nd = N/downsample; + c=0; do { + int j; + celt_sig * OPUS_RESTRICT x; + opus_val16 * OPUS_RESTRICT y; + celt_sig m = mem[c]; + x =in[c]; + y = pcm+c; +#ifdef CUSTOM_MODES + if (coef[1] != 0) + { + opus_val16 coef1 = coef[1]; + opus_val16 coef3 = coef[3]; + for (j=0;j1) + { + /* Shortcut for the standard (non-custom modes) case */ + for (j=0;jshortMdctSize; + shift = mode->maxLM; + } else { + B = 1; + N = mode->shortMdctSize<maxLM-LM; + } + c=0; do { + /* IMDCT on the interleaved the sub-frames, overlap-add is performed by the IMDCT */ + for (b=0;bmdct, &X[b+c*N*B], out_mem[c]+N*b, mode->window, overlap, shift, B); + } while (++cstorage*8; + tell = ec_tell(dec); + logp = isTransient ? 2 : 4; + tf_select_rsv = LM>0 && tell+logp+1<=budget; + budget -= tf_select_rsv; + tf_changed = curr = 0; + for (i=start;ichannels; + celt_sig *decode_mem[2]; + celt_sig *out_syn[2]; + opus_val16 *lpc; + opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE; + const OpusCustomMode *mode; + int nbEBands; + int overlap; + int start; + int downsample; + int loss_count; + int noise_based; + const opus_int16 *eBands; + VARDECL(celt_sig, scratch); + SAVE_STACK; + + mode = st->mode; + nbEBands = mode->nbEBands; + overlap = mode->overlap; + eBands = mode->eBands; + + c=0; do { + decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+overlap); + out_syn[c] = decode_mem[c]+DECODE_BUFFER_SIZE-N; + } while (++c_decode_mem+(DECODE_BUFFER_SIZE+overlap)*C); + oldBandE = lpc+C*LPC_ORDER; + oldLogE = oldBandE + 2*nbEBands; + oldLogE2 = oldLogE + 2*nbEBands; + backgroundLogE = oldLogE2 + 2*nbEBands; + + loss_count = st->loss_count; + start = st->start; + downsample = st->downsample; + noise_based = loss_count >= 5 || start != 0; + ALLOC(scratch, noise_based?N*C:N, celt_sig); + if (noise_based) + { + /* Noise-based PLC/CNG */ + celt_sig *freq; + VARDECL(celt_norm, X); + opus_uint32 seed; + opus_val16 *plcLogE; + int end; + int effEnd; + + end = st->end; + effEnd = IMAX(start, IMIN(end, mode->effEBands)); + + /* Share the interleaved signal MDCT coefficient buffer with the + deemphasis scratch buffer. */ + freq = scratch; + ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ + + if (loss_count >= 5) + plcLogE = backgroundLogE; + else { + /* Energy decay */ + opus_val16 decay = loss_count==0 ? + QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT); + c=0; do + { + for (i=start;irng; + for (c=0;c>20); + } + renormalise_vector(X+boffs, blen, Q15ONE); + } + } + st->rng = seed; + + denormalise_bands(mode, X, freq, plcLogE, start, effEnd, C, 1<>1)); + } while (++c>1, opus_val16 ); + pitch_downsample(decode_mem, lp_pitch_buf, + DECODE_BUFFER_SIZE, C, st->arch); + pitch_search(lp_pitch_buf+(PLC_PITCH_LAG_MAX>>1), lp_pitch_buf, + DECODE_BUFFER_SIZE-PLC_PITCH_LAG_MAX, + PLC_PITCH_LAG_MAX-PLC_PITCH_LAG_MIN, &pitch_index, st->arch); + pitch_index = PLC_PITCH_LAG_MAX-pitch_index; + st->last_pitch_index = pitch_index; + } else { + pitch_index = st->last_pitch_index; + fade = QCONST16(.8f,15); + } + + ALLOC(etmp, overlap, opus_val32); + ALLOC(exc, MAX_PERIOD, opus_val16); + window = mode->window; + c=0; do { + opus_val16 decay; + opus_val16 attenuation; + opus_val32 S1=0; + celt_sig *buf; + int extrapolation_offset; + int extrapolation_len; + int exc_length; + int j; + + buf = decode_mem[c]; + for (i=0;iarch); + /* Add a noise floor of -40 dB. */ +#ifdef FIXED_POINT + ac[0] += SHR32(ac[0],13); +#else + ac[0] *= 1.0001f; +#endif + /* Use lag windowing to stabilize the Levinson-Durbin recursion. */ + for (i=1;i<=LPC_ORDER;i++) + { + /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/ +#ifdef FIXED_POINT + ac[i] -= MULT16_32_Q15(2*i*i, ac[i]); +#else + ac[i] -= ac[i]*(0.008f*0.008f)*i*i; +#endif + } + _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER); + } + /* We want the excitation for 2 pitch periods in order to look for a + decaying signal, but we can't get more than MAX_PERIOD. */ + exc_length = IMIN(2*pitch_index, MAX_PERIOD); + /* Initialize the LPC history with the samples just before the start + of the region for which we're computing the excitation. */ + { + opus_val16 lpc_mem[LPC_ORDER]; + for (i=0;i>1; + for (i=0;i= pitch_index) { + j -= pitch_index; + attenuation = MULT16_16_Q15(attenuation, decay); + } + buf[DECODE_BUFFER_SIZE-N+i] = + SHL32(EXTEND32(MULT16_16_Q15(attenuation, + exc[extrapolation_offset+j])), SIG_SHIFT); + /* Compute the energy of the previously decoded signal whose + excitation we're copying. */ + tmp = ROUND16( + buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j], + SIG_SHIFT); + S1 += SHR32(MULT16_16(tmp, tmp), 8); + } + + { + opus_val16 lpc_mem[LPC_ORDER]; + /* Copy the last decoded samples (prior to the overlap region) to + synthesis filter memory so we can have a continuous signal. */ + for (i=0;i SHR32(S2,2))) +#else + /* The float test is written this way to catch NaNs in the output + of the IIR filter at the same time. */ + if (!(S1 > 0.2f*S2)) +#endif + { + for (i=0;ipostfilter_period, st->postfilter_period, overlap, + -st->postfilter_gain, -st->postfilter_gain, + st->postfilter_tapset, st->postfilter_tapset, NULL, 0); + + /* Simulate TDAC on the concealed audio so that it blends with the + MDCT of the next frame. */ + for (i=0;ipreemph, st->preemph_memD, scratch); + + st->loss_count = loss_count+1; + + RESTORE_STACK; +} + +int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec) +{ + int c, i, N; + int spread_decision; + opus_int32 bits; + ec_dec _dec; + VARDECL(celt_sig, freq); + VARDECL(celt_norm, X); + VARDECL(int, fine_quant); + VARDECL(int, pulses); + VARDECL(int, cap); + VARDECL(int, offsets); + VARDECL(int, fine_priority); + VARDECL(int, tf_res); + VARDECL(unsigned char, collapse_masks); + celt_sig *decode_mem[2]; + celt_sig *out_syn[2]; + opus_val16 *lpc; + opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE; + + int shortBlocks; + int isTransient; + int intra_ener; + const int CC = st->channels; + int LM, M; + int effEnd; + int codedBands; + int alloc_trim; + int postfilter_pitch; + opus_val16 postfilter_gain; + int intensity=0; + int dual_stereo=0; + opus_int32 total_bits; + opus_int32 balance; + opus_int32 tell; + int dynalloc_logp; + int postfilter_tapset; + int anti_collapse_rsv; + int anti_collapse_on=0; + int silence; + int C = st->stream_channels; + const OpusCustomMode *mode; + int nbEBands; + int overlap; + const opus_int16 *eBands; + ALLOC_STACK; + + mode = st->mode; + nbEBands = mode->nbEBands; + overlap = mode->overlap; + eBands = mode->eBands; + frame_size *= st->downsample; + + c=0; do { + decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+overlap); + } while (++c_decode_mem+(DECODE_BUFFER_SIZE+overlap)*CC); + oldBandE = lpc+CC*LPC_ORDER; + oldLogE = oldBandE + 2*nbEBands; + oldLogE2 = oldLogE + 2*nbEBands; + backgroundLogE = oldLogE2 + 2*nbEBands; + +#ifdef CUSTOM_MODES + if (st->signalling && data!=NULL) + { + int data0=data[0]; + /* Convert "standard mode" to Opus header */ + if (mode->Fs==48000 && mode->shortMdctSize==120) + { + data0 = fromOpus(data0); + if (data0<0) + return OPUS_INVALID_PACKET; + } + st->end = IMAX(1, mode->effEBands-2*(data0>>5)); + LM = (data0>>3)&0x3; + C = 1 + ((data0>>2)&0x1); + data++; + len--; + if (LM>mode->maxLM) + return OPUS_INVALID_PACKET; + if (frame_size < mode->shortMdctSize<shortMdctSize<maxLM;LM++) + if (mode->shortMdctSize<mode->maxLM) + return OPUS_BAD_ARG; + } + M=1<1275 || pcm==NULL) + return OPUS_BAD_ARG; + + N = M*mode->shortMdctSize; + + effEnd = st->end; + if (effEnd > mode->effEBands) + effEnd = mode->effEBands; + + if (data == NULL || len<=1) + { + celt_decode_lost(st, pcm, N, LM); + RESTORE_STACK; + return frame_size/st->downsample; + } + + if (dec == NULL) + { + ec_dec_init(&_dec,(unsigned char*)data,len); + dec = &_dec; + } + + if (C==1) + { + for (i=0;i= total_bits) + silence = 1; + else if (tell==1) + silence = ec_dec_bit_logp(dec, 15); + else + silence = 0; + if (silence) + { + /* Pretend we've read all the remaining bits */ + tell = len*8; + dec->nbits_total+=tell-ec_tell(dec); + } + + postfilter_gain = 0; + postfilter_pitch = 0; + postfilter_tapset = 0; + if (st->start==0 && tell+16 <= total_bits) + { + if(ec_dec_bit_logp(dec, 1)) + { + int qg, octave; + octave = ec_dec_uint(dec, 6); + postfilter_pitch = (16< 0 && tell+3 <= total_bits) + { + isTransient = ec_dec_bit_logp(dec, 3); + tell = ec_tell(dec); + } + else + isTransient = 0; + + if (isTransient) + shortBlocks = M; + else + shortBlocks = 0; + + /* Decode the global flags (first symbols in the stream) */ + intra_ener = tell+3<=total_bits ? ec_dec_bit_logp(dec, 3) : 0; + /* Get band energies */ + unquant_coarse_energy(mode, st->start, st->end, oldBandE, + intra_ener, dec, C, LM); + + ALLOC(tf_res, nbEBands, int); + tf_decode(st->start, st->end, isTransient, tf_res, LM, dec); + + tell = ec_tell(dec); + spread_decision = SPREAD_NORMAL; + if (tell+4 <= total_bits) + spread_decision = ec_dec_icdf(dec, spread_icdf, 5); + + ALLOC(cap, nbEBands, int); + + init_caps(mode,cap,LM,C); + + ALLOC(offsets, nbEBands, int); + + dynalloc_logp = 6; + total_bits<<=BITRES; + tell = ec_tell_frac(dec); + for (i=st->start;iend;i++) + { + int width, quanta; + int dynalloc_loop_logp; + int boost; + width = C*(eBands[i+1]-eBands[i])<0) + dynalloc_logp = IMAX(2, dynalloc_logp-1); + } + + ALLOC(fine_quant, nbEBands, int); + alloc_trim = tell+(6<=2&&bits>=((LM+2)<start, st->end, offsets, cap, + alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses, + fine_quant, fine_priority, C, LM, dec, 0, 0, 0); + + unquant_fine_energy(mode, st->start, st->end, oldBandE, fine_quant, dec, C); + + /* Decode fixed codebook */ + ALLOC(collapse_masks, C*nbEBands, unsigned char); + ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ + + quant_all_bands(0, mode, st->start, st->end, X, C==2 ? X+N : NULL, collapse_masks, + NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res, + len*(8<rng); + + if (anti_collapse_rsv > 0) + { + anti_collapse_on = ec_dec_bits(dec, 1); + } + + unquant_energy_finalise(mode, st->start, st->end, oldBandE, + fine_quant, fine_priority, len*8-ec_tell(dec), dec, C); + + if (anti_collapse_on) + anti_collapse(mode, X, collapse_masks, LM, C, N, + st->start, st->end, oldBandE, oldLogE, oldLogE2, pulses, st->rng); + + ALLOC(freq, IMAX(CC,C)*N, celt_sig); /**< Interleaved signal MDCTs */ + + if (silence) + { + for (i=0;istart, effEnd, C, M); + } + c=0; do { + OPUS_MOVE(decode_mem[c], decode_mem[c]+N, DECODE_BUFFER_SIZE-N+overlap/2); + } while (++cdownsample!=1) + bound = IMIN(bound, N/st->downsample); + for (i=bound;ipostfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD); + st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD); + comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, mode->shortMdctSize, + st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset, + mode->window, overlap); + if (LM!=0) + comb_filter(out_syn[c]+mode->shortMdctSize, out_syn[c]+mode->shortMdctSize, st->postfilter_period, postfilter_pitch, N-mode->shortMdctSize, + st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset, + mode->window, overlap); + + } while (++cpostfilter_period_old = st->postfilter_period; + st->postfilter_gain_old = st->postfilter_gain; + st->postfilter_tapset_old = st->postfilter_tapset; + st->postfilter_period = postfilter_pitch; + st->postfilter_gain = postfilter_gain; + st->postfilter_tapset = postfilter_tapset; + if (LM!=0) + { + st->postfilter_period_old = st->postfilter_period; + st->postfilter_gain_old = st->postfilter_gain; + st->postfilter_tapset_old = st->postfilter_tapset; + } + + if (C==1) { + for (i=0;istart;i++) + { + oldBandE[c*nbEBands+i]=0; + oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT); + } + for (i=st->end;irng = dec->rng; + + /* We reuse freq[] as scratch space for the de-emphasis */ + deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, freq); + st->loss_count = 0; + RESTORE_STACK; + if (ec_tell(dec) > 8*len) + return OPUS_INTERNAL_ERROR; + if(ec_get_error(dec)) + st->error = 1; + return frame_size/st->downsample; +} + + +#ifdef CUSTOM_MODES + +#ifdef FIXED_POINT +int opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size) +{ + return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL); +} + +#ifndef DISABLE_FLOAT_API +int opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size) +{ + int j, ret, C, N; + VARDECL(opus_int16, out); + ALLOC_STACK; + + if (pcm==NULL) + return OPUS_BAD_ARG; + + C = st->channels; + N = frame_size; + + ALLOC(out, C*N, opus_int16); + ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL); + if (ret>0) + for (j=0;jchannels; + N = frame_size; + ALLOC(out, C*N, celt_sig); + + ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL); + + if (ret>0) + for (j=0;j=st->mode->nbEBands) + goto bad_arg; + st->start = value; + } + break; + case CELT_SET_END_BAND_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<1 || value>st->mode->nbEBands) + goto bad_arg; + st->end = value; + } + break; + case CELT_SET_CHANNELS_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<1 || value>2) + goto bad_arg; + st->stream_channels = value; + } + break; + case CELT_GET_AND_CLEAR_ERROR_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (value==NULL) + goto bad_arg; + *value=st->error; + st->error = 0; + } + break; + case OPUS_GET_LOOKAHEAD_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (value==NULL) + goto bad_arg; + *value = st->overlap/st->downsample; + } + break; + case OPUS_RESET_STATE: + { + int i; + opus_val16 *lpc, *oldBandE, *oldLogE, *oldLogE2; + lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*st->channels); + oldBandE = lpc+st->channels*LPC_ORDER; + oldLogE = oldBandE + 2*st->mode->nbEBands; + oldLogE2 = oldLogE + 2*st->mode->nbEBands; + OPUS_CLEAR((char*)&st->DECODER_RESET_START, + opus_custom_decoder_get_size(st->mode, st->channels)- + ((char*)&st->DECODER_RESET_START - (char*)st)); + for (i=0;i<2*st->mode->nbEBands;i++) + oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT); + } + break; + case OPUS_GET_PITCH_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (value==NULL) + goto bad_arg; + *value = st->postfilter_period; + } + break; + case CELT_GET_MODE_REQUEST: + { + const CELTMode ** value = va_arg(ap, const CELTMode**); + if (value==0) + goto bad_arg; + *value=st->mode; + } + break; + case CELT_SET_SIGNALLING_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->signalling = value; + } + break; + case OPUS_GET_FINAL_RANGE_REQUEST: + { + opus_uint32 * value = va_arg(ap, opus_uint32 *); + if (value==0) + goto bad_arg; + *value=st->rng; + } + break; + default: + goto bad_request; + } + va_end(ap); + return OPUS_OK; +bad_arg: + va_end(ap); + return OPUS_BAD_ARG; +bad_request: + va_end(ap); + return OPUS_UNIMPLEMENTED; +} diff --git a/TelegramClient.Opus/opus/celt/celt_encoder.c b/TelegramClient.Opus/opus/celt/celt_encoder.c new file mode 100755 index 0000000..ffff077 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/celt_encoder.c @@ -0,0 +1,2353 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2010 Xiph.Org Foundation + Copyright (c) 2008 Gregory Maxwell + Written by Jean-Marc Valin and Gregory Maxwell */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define CELT_ENCODER_C + +#include "cpu_support.h" +#include "os_support.h" +#include "mdct.h" +#include +#include "celt.h" +#include "pitch.h" +#include "bands.h" +#include "modes.h" +#include "entcode.h" +#include "quant_bands.h" +#include "rate.h" +#include "stack_alloc.h" +#include "mathops.h" +#include "float_cast.h" +#include +#include "celt_lpc.h" +#include "vq.h" + + +/** Encoder state + @brief Encoder state + */ +struct OpusCustomEncoder { + const OpusCustomMode *mode; /**< Mode used by the encoder */ + int overlap; + int channels; + int stream_channels; + + int force_intra; + int clip; + int disable_pf; + int complexity; + int upsample; + int start, end; + + opus_int32 bitrate; + int vbr; + int signalling; + int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */ + int loss_rate; + int lsb_depth; + int variable_duration; + int lfe; + int arch; + + /* Everything beyond this point gets cleared on a reset */ +#define ENCODER_RESET_START rng + + opus_uint32 rng; + int spread_decision; + opus_val32 delayedIntra; + int tonal_average; + int lastCodedBands; + int hf_average; + int tapset_decision; + + int prefilter_period; + opus_val16 prefilter_gain; + int prefilter_tapset; +#ifdef RESYNTH + int prefilter_period_old; + opus_val16 prefilter_gain_old; + int prefilter_tapset_old; +#endif + int consec_transient; + AnalysisInfo analysis; + + opus_val32 preemph_memE[2]; + opus_val32 preemph_memD[2]; + + /* VBR-related parameters */ + opus_int32 vbr_reservoir; + opus_int32 vbr_drift; + opus_int32 vbr_offset; + opus_int32 vbr_count; + opus_val32 overlap_max; + opus_val16 stereo_saving; + int intensity; + opus_val16 *energy_mask; + opus_val16 spec_avg; + +#ifdef RESYNTH + /* +MAX_PERIOD/2 to make space for overlap */ + celt_sig syn_mem[2][2*MAX_PERIOD+MAX_PERIOD/2]; +#endif + + celt_sig in_mem[1]; /* Size = channels*mode->overlap */ + /* celt_sig prefilter_mem[], Size = channels*COMBFILTER_MAXPERIOD */ + /* opus_val16 oldBandE[], Size = channels*mode->nbEBands */ + /* opus_val16 oldLogE[], Size = channels*mode->nbEBands */ + /* opus_val16 oldLogE2[], Size = channels*mode->nbEBands */ +}; + +int celt_encoder_get_size(int channels) +{ + CELTMode *mode = opus_custom_mode_create(48000, 960, NULL); + return opus_custom_encoder_get_size(mode, channels); +} + +OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_get_size(const CELTMode *mode, int channels) +{ + int size = sizeof(struct CELTEncoder) + + (channels*mode->overlap-1)*sizeof(celt_sig) /* celt_sig in_mem[channels*mode->overlap]; */ + + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) /* celt_sig prefilter_mem[channels*COMBFILTER_MAXPERIOD]; */ + + 3*channels*mode->nbEBands*sizeof(opus_val16); /* opus_val16 oldBandE[channels*mode->nbEBands]; */ + /* opus_val16 oldLogE[channels*mode->nbEBands]; */ + /* opus_val16 oldLogE2[channels*mode->nbEBands]; */ + return size; +} + +#ifdef CUSTOM_MODES +CELTEncoder *opus_custom_encoder_create(const CELTMode *mode, int channels, int *error) +{ + int ret; + CELTEncoder *st = (CELTEncoder *)opus_alloc(opus_custom_encoder_get_size(mode, channels)); + /* init will handle the NULL case */ + ret = opus_custom_encoder_init(st, mode, channels); + if (ret != OPUS_OK) + { + opus_custom_encoder_destroy(st); + st = NULL; + } + if (error) + *error = ret; + return st; +} +#endif /* CUSTOM_MODES */ + +static int opus_custom_encoder_init_arch(CELTEncoder *st, const CELTMode *mode, + int channels, int arch) +{ + if (channels < 0 || channels > 2) + return OPUS_BAD_ARG; + + if (st==NULL || mode==NULL) + return OPUS_ALLOC_FAIL; + + OPUS_CLEAR((char*)st, opus_custom_encoder_get_size(mode, channels)); + + st->mode = mode; + st->overlap = mode->overlap; + st->stream_channels = st->channels = channels; + + st->upsample = 1; + st->start = 0; + st->end = st->mode->effEBands; + st->signalling = 1; + + st->arch = arch; + + st->constrained_vbr = 1; + st->clip = 1; + + st->bitrate = OPUS_BITRATE_MAX; + st->vbr = 0; + st->force_intra = 0; + st->complexity = 5; + st->lsb_depth=24; + + opus_custom_encoder_ctl(st, OPUS_RESET_STATE); + + return OPUS_OK; +} + +#ifdef CUSTOM_MODES +int opus_custom_encoder_init(CELTEncoder *st, const CELTMode *mode, int channels) +{ + return opus_custom_encoder_init_arch(st, mode, channels, opus_select_arch()); +} +#endif + +int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels, + int arch) +{ + int ret; + ret = opus_custom_encoder_init_arch(st, + opus_custom_mode_create(48000, 960, NULL), channels, arch); + if (ret != OPUS_OK) + return ret; + st->upsample = resampling_factor(sampling_rate); + return OPUS_OK; +} + +#ifdef CUSTOM_MODES +void opus_custom_encoder_destroy(CELTEncoder *st) +{ + opus_free(st); +} +#endif /* CUSTOM_MODES */ + + +static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int C, + opus_val16 *tf_estimate, int *tf_chan) +{ + int i; + VARDECL(opus_val16, tmp); + opus_val32 mem0,mem1; + int is_transient = 0; + opus_int32 mask_metric = 0; + int c; + opus_val16 tf_max; + int len2; + /* Table of 6*64/x, trained on real data to minimize the average error */ + static const unsigned char inv_table[128] = { + 255,255,156,110, 86, 70, 59, 51, 45, 40, 37, 33, 31, 28, 26, 25, + 23, 22, 21, 20, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12, + 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 9, 9, 9, 8, 8, + 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + }; + SAVE_STACK; + ALLOC(tmp, len, opus_val16); + + len2=len/2; + for (c=0;c=0;i--) + { +#ifdef FIXED_POINT + /* FIXME: Use PSHR16() instead */ + tmp[i] = mem0 + PSHR32(tmp[i]-mem0,3); +#else + tmp[i] = mem0 + MULT16_16_P15(QCONST16(0.125f,15),tmp[i]-mem0); +#endif + mem0 = tmp[i]; + maxE = MAX16(maxE, mem0); + } + /*for (i=0;i>1))); +#else + mean = celt_sqrt(mean * maxE*.5*len2); +#endif + /* Inverse of the mean energy in Q15+6 */ + norm = SHL32(EXTEND32(len2),6+14)/ADD32(EPSILON,SHR32(mean,1)); + /* Compute harmonic mean discarding the unreliable boundaries + The data is smooth, so we only take 1/4th of the samples */ + unmask=0; + for (i=12;imask_metric) + { + *tf_chan = c; + mask_metric = unmask; + } + } + is_transient = mask_metric>200; + + /* Arbitrary metric for VBR boost */ + tf_max = MAX16(0,celt_sqrt(27*mask_metric)-42); + /* *tf_estimate = 1 + MIN16(1, sqrt(MAX16(0, tf_max-30))/20); */ + *tf_estimate = celt_sqrt(MAX16(0, SHL32(MULT16_16(QCONST16(0.0069,14),MIN16(163,tf_max)),14)-QCONST32(0.139,28))); + /*printf("%d %f\n", tf_max, mask_metric);*/ + RESTORE_STACK; +#ifdef FUZZING + is_transient = rand()&0x1; +#endif + /*printf("%d %f %d\n", is_transient, (float)*tf_estimate, tf_max);*/ + return is_transient; +} + +/* Looks for sudden increases of energy to decide whether we need to patch + the transient decision */ +int patch_transient_decision(opus_val16 *newE, opus_val16 *oldE, int nbEBands, + int end, int C) +{ + int i, c; + opus_val32 mean_diff=0; + opus_val16 spread_old[26]; + /* Apply an aggressive (-6 dB/Bark) spreading function to the old frame to + avoid false detection caused by irrelevant bands */ + if (C==1) + { + spread_old[0] = oldE[0]; + for (i=1;i=0;i--) + spread_old[i] = MAX16(spread_old[i], spread_old[i+1]-QCONST16(1.0f, DB_SHIFT)); + /* Compute mean increase */ + c=0; do { + for (i=2;i QCONST16(1.f, DB_SHIFT); +} + +/** Apply window and compute the MDCT for all sub-frames and + all channels in a frame */ +static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * OPUS_RESTRICT in, + celt_sig * OPUS_RESTRICT out, int C, int CC, int LM, int upsample) +{ + const int overlap = OVERLAP(mode); + int N; + int B; + int shift; + int i, b, c; + if (shortBlocks) + { + B = shortBlocks; + N = mode->shortMdctSize; + shift = mode->maxLM; + } else { + B = 1; + N = mode->shortMdctSize<maxLM-LM; + } + c=0; do { + for (b=0;bmdct, in+c*(B*N+overlap)+b*N, &out[b+c*N*B], mode->window, overlap, shift, B); + } + } while (++ceBands[len]-m->eBands[len-1])<eBands[len]-m->eBands[len-1])<eBands[i+1]-m->eBands[i])<eBands[i+1]-m->eBands[i])==1; + for (j=0;jeBands[i]<eBands[i]<>LM, 1<>k, 1<=0;i--) + { + if (tf_res[i+1] == 1) + tf_res[i] = path1[i+1]; + else + tf_res[i] = path0[i+1]; + } + /*printf("%d %f\n", *tf_sum, tf_estimate);*/ + RESTORE_STACK; +#ifdef FUZZING + tf_select = rand()&0x1; + tf_res[0] = rand()&0x1; + for (i=1;istorage*8; + tell = ec_tell(enc); + logp = isTransient ? 2 : 4; + /* Reserve space to code the tf_select decision. */ + tf_select_rsv = LM>0 && tell+logp+1 <= budget; + budget -= tf_select_rsv; + curr = tf_changed = 0; + for (i=start;ieBands[i]<eBands[i+1]<eBands[i]<eBands[i+1]< QCONST16(.995f,10)) + trim_index-=4; + else if (sum > QCONST16(.92f,10)) + trim_index-=3; + else if (sum > QCONST16(.85f,10)) + trim_index-=2; + else if (sum > QCONST16(.8f,10)) + trim_index-=1; + /* mid-side savings estimations based on the LF average*/ + logXC = celt_log2(QCONST32(1.001f, 20)-MULT16_16(sum, sum)); + /* mid-side savings estimations based on min correlation */ + logXC2 = MAX16(HALF16(logXC), celt_log2(QCONST32(1.001f, 20)-MULT16_16(minXC, minXC))); +#ifdef FIXED_POINT + /* Compensate for Q20 vs Q14 input and convert output to Q8 */ + logXC = PSHR32(logXC-QCONST16(6.f, DB_SHIFT),DB_SHIFT-8); + logXC2 = PSHR32(logXC2-QCONST16(6.f, DB_SHIFT),DB_SHIFT-8); +#endif + + trim += MAX16(-QCONST16(4.f, 8), MULT16_16_Q15(QCONST16(.75f,15),logXC)); + *stereo_saving = MIN16(*stereo_saving + QCONST16(0.25f, 8), -HALF16(logXC2)); + } + + /* Estimate spectral tilt */ + c=0; do { + for (i=0;inbEBands]*(opus_int32)(2+2*i-end); + } + } while (++c QCONST16(2.f, DB_SHIFT)) + trim_index--; + if (diff > QCONST16(8.f, DB_SHIFT)) + trim_index--; + if (diff < -QCONST16(4.f, DB_SHIFT)) + trim_index++; + if (diff < -QCONST16(10.f, DB_SHIFT)) + trim_index++; + trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), SHR16(diff+QCONST16(1.f, DB_SHIFT),DB_SHIFT-8)/6 )); + trim -= SHR16(surround_trim, DB_SHIFT-8); + trim -= 2*SHR16(tf_estimate, 14-8); +#ifndef DISABLE_FLOAT_API + if (analysis->valid) + { + trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), + (opus_val16)(QCONST16(2.f, 8)*(analysis->tonality_slope+.05f)))); + } +#endif + +#ifdef FIXED_POINT + trim_index = PSHR32(trim, 8); +#else + trim_index = (int)floor(.5f+trim); +#endif + if (trim_index<0) + trim_index = 0; + if (trim_index>10) + trim_index = 10; + /*printf("%d\n", trim_index);*/ +#ifdef FUZZING + trim_index = rand()%11; +#endif + return trim_index; +} + +static int stereo_analysis(const CELTMode *m, const celt_norm *X, + int LM, int N0) +{ + int i; + int thetas; + opus_val32 sumLR = EPSILON, sumMS = EPSILON; + + /* Use the L1 norm to model the entropy of the L/R signal vs the M/S signal */ + for (i=0;i<13;i++) + { + int j; + for (j=m->eBands[i]<eBands[i+1]<eBands[13]<<(LM+1))+thetas, sumMS) + > MULT16_32_Q15(m->eBands[13]<<(LM+1), sumLR); +} + +static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16 *bandLogE2, + int nbEBands, int start, int end, int C, int *offsets, int lsb_depth, const opus_int16 *logN, + int isTransient, int vbr, int constrained_vbr, const opus_int16 *eBands, int LM, + int effectiveBytes, opus_int32 *tot_boost_, int lfe, opus_val16 *surround_dynalloc) +{ + int i, c; + opus_int32 tot_boost=0; + opus_val16 maxDepth; + VARDECL(opus_val16, follower); + VARDECL(opus_val16, noise_floor); + SAVE_STACK; + ALLOC(follower, C*nbEBands, opus_val16); + ALLOC(noise_floor, C*nbEBands, opus_val16); + for (i=0;i 50 && LM>=1 && !lfe) + { + int last=0; + c=0;do + { + follower[c*nbEBands] = bandLogE2[c*nbEBands]; + for (i=1;i bandLogE2[c*nbEBands+i-1]+QCONST16(.5f,DB_SHIFT)) + last=i; + follower[c*nbEBands+i] = MIN16(follower[c*nbEBands+i-1]+QCONST16(1.5f,DB_SHIFT), bandLogE2[c*nbEBands+i]); + } + for (i=last-1;i>=0;i--) + follower[c*nbEBands+i] = MIN16(follower[c*nbEBands+i], MIN16(follower[c*nbEBands+i+1]+QCONST16(2.f,DB_SHIFT), bandLogE2[c*nbEBands+i])); + for (i=0;i=12) + follower[i] = HALF16(follower[i]); + follower[i] = MIN16(follower[i], QCONST16(4, DB_SHIFT)); + + width = C*(eBands[i+1]-eBands[i])< 48) { + boost = (int)SHR32(EXTEND32(follower[i])*8,DB_SHIFT); + boost_bits = (boost*width<>BITRES>>3 > effectiveBytes/4) + { + opus_int32 cap = ((effectiveBytes/4)<mode; + ALLOC(_pre, CC*(N+COMBFILTER_MAXPERIOD), celt_sig); + + pre[0] = _pre; + pre[1] = _pre + (N+COMBFILTER_MAXPERIOD); + + + c=0; do { + OPUS_COPY(pre[c], prefilter_mem+c*COMBFILTER_MAXPERIOD, COMBFILTER_MAXPERIOD); + OPUS_COPY(pre[c]+COMBFILTER_MAXPERIOD, in+c*(N+st->overlap)+st->overlap, N); + } while (++c>1, opus_val16); + + pitch_downsample(pre, pitch_buf, COMBFILTER_MAXPERIOD+N, CC, st->arch); + /* Don't search for the fir last 1.5 octave of the range because + there's too many false-positives due to short-term correlation */ + pitch_search(pitch_buf+(COMBFILTER_MAXPERIOD>>1), pitch_buf, N, + COMBFILTER_MAXPERIOD-3*COMBFILTER_MINPERIOD, &pitch_index, + st->arch); + pitch_index = COMBFILTER_MAXPERIOD-pitch_index; + + gain1 = remove_doubling(pitch_buf, COMBFILTER_MAXPERIOD, COMBFILTER_MINPERIOD, + N, &pitch_index, st->prefilter_period, st->prefilter_gain); + if (pitch_index > COMBFILTER_MAXPERIOD-2) + pitch_index = COMBFILTER_MAXPERIOD-2; + gain1 = MULT16_16_Q15(QCONST16(.7f,15),gain1); + /*printf("%d %d %f %f\n", pitch_change, pitch_index, gain1, st->analysis.tonality);*/ + if (st->loss_rate>2) + gain1 = HALF32(gain1); + if (st->loss_rate>4) + gain1 = HALF32(gain1); + if (st->loss_rate>8) + gain1 = 0; + } else { + gain1 = 0; + pitch_index = COMBFILTER_MINPERIOD; + } + + /* Gain threshold for enabling the prefilter/postfilter */ + pf_threshold = QCONST16(.2f,15); + + /* Adjusting the threshold based on rate and continuity */ + if (abs(pitch_index-st->prefilter_period)*10>pitch_index) + pf_threshold += QCONST16(.2f,15); + if (nbAvailableBytes<25) + pf_threshold += QCONST16(.1f,15); + if (nbAvailableBytes<35) + pf_threshold += QCONST16(.1f,15); + if (st->prefilter_gain > QCONST16(.4f,15)) + pf_threshold -= QCONST16(.1f,15); + if (st->prefilter_gain > QCONST16(.55f,15)) + pf_threshold -= QCONST16(.1f,15); + + /* Hard threshold at 0.2 */ + pf_threshold = MAX16(pf_threshold, QCONST16(.2f,15)); + if (gain1prefilter_gain)prefilter_gain; + +#ifdef FIXED_POINT + qg = ((gain1+1536)>>10)/3-1; +#else + qg = (int)floor(.5f+gain1*32/3)-1; +#endif + qg = IMAX(0, IMIN(7, qg)); + gain1 = QCONST16(0.09375f,15)*(qg+1); + pf_on = 1; + } + /*printf("%d %f\n", pitch_index, gain1);*/ + + c=0; do { + int offset = mode->shortMdctSize-st->overlap; + st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD); + OPUS_COPY(in+c*(N+st->overlap), st->in_mem+c*(st->overlap), st->overlap); + if (offset) + comb_filter(in+c*(N+st->overlap)+st->overlap, pre[c]+COMBFILTER_MAXPERIOD, + st->prefilter_period, st->prefilter_period, offset, -st->prefilter_gain, -st->prefilter_gain, + st->prefilter_tapset, st->prefilter_tapset, NULL, 0); + + comb_filter(in+c*(N+st->overlap)+st->overlap+offset, pre[c]+COMBFILTER_MAXPERIOD+offset, + st->prefilter_period, pitch_index, N-offset, -st->prefilter_gain, -gain1, + st->prefilter_tapset, prefilter_tapset, mode->window, st->overlap); + OPUS_COPY(st->in_mem+c*(st->overlap), in+c*(N+st->overlap)+N, st->overlap); + + if (N>COMBFILTER_MAXPERIOD) + { + OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, pre[c]+N, COMBFILTER_MAXPERIOD); + } else { + OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, prefilter_mem+c*COMBFILTER_MAXPERIOD+N, COMBFILTER_MAXPERIOD-N); + OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD+COMBFILTER_MAXPERIOD-N, pre[c]+COMBFILTER_MAXPERIOD, N); + } + } while (++cnbEBands; + eBands = mode->eBands; + + coded_bands = lastCodedBands ? lastCodedBands : nbEBands; + coded_bins = eBands[coded_bands]<analysis.activity, st->analysis.tonality, tf_estimate, st->stereo_saving, tot_boost, coded_bands);*/ +#ifndef DISABLE_FLOAT_API + if (analysis->valid && analysis->activity<.4) + target -= (opus_int32)((coded_bins<activity)); +#endif + /* Stereo savings */ + if (C==2) + { + int coded_stereo_bands; + int coded_stereo_dof; + opus_val16 max_frac; + coded_stereo_bands = IMIN(intensity, coded_bands); + coded_stereo_dof = (eBands[coded_stereo_bands]<valid && !lfe) + { + opus_int32 tonal_target; + float tonal; + + /* Tonality boost (compensating for the average). */ + tonal = MAX16(0.f,analysis->tonality-.15f)-0.09f; + tonal_target = target + (opus_int32)((coded_bins<tonality, tonal);*/ + target = tonal_target; + } +#endif + + if (has_surround_mask&&!lfe) + { + opus_int32 surround_target = target + (opus_int32)SHR32(MULT16_16(surround_masking,coded_bins<end, st->intensity, surround_target, target, st->bitrate);*/ + target = IMAX(target/4, surround_target); + } + + { + opus_int32 floor_depth; + int bins; + bins = eBands[nbEBands-2]<>2); + target = IMIN(target, floor_depth); + /*printf("%f %d\n", maxDepth, floor_depth);*/ + } + + if ((!has_surround_mask||lfe) && (constrained_vbr || bitrate<64000)) + { + opus_val16 rate_factor; +#ifdef FIXED_POINT + rate_factor = MAX16(0,(bitrate-32000)); +#else + rate_factor = MAX16(0,(1.f/32768)*(bitrate-32000)); +#endif + if (constrained_vbr) + rate_factor = MIN16(rate_factor, QCONST16(0.67f, 15)); + target = base_target + (opus_int32)MULT16_32_Q15(rate_factor, target-base_target); + + } + + if (!has_surround_mask && tf_estimate < QCONST16(.2f, 14)) + { + opus_val16 amount; + opus_val16 tvbr_factor; + amount = MULT16_16_Q15(QCONST16(.0000031f, 30), IMAX(0, IMIN(32000, 96000-bitrate))); + tvbr_factor = SHR32(MULT16_16(temporal_vbr, amount), DB_SHIFT); + target += (opus_int32)MULT16_32_Q15(tvbr_factor, target); + } + + /* Don't allow more than doubling the rate */ + target = IMIN(2*base_target, target); + + return target; +} + +int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc) +{ + int i, c, N; + opus_int32 bits; + ec_enc _enc; + VARDECL(celt_sig, in); + VARDECL(celt_sig, freq); + VARDECL(celt_norm, X); + VARDECL(celt_ener, bandE); + VARDECL(opus_val16, bandLogE); + VARDECL(opus_val16, bandLogE2); + VARDECL(int, fine_quant); + VARDECL(opus_val16, error); + VARDECL(int, pulses); + VARDECL(int, cap); + VARDECL(int, offsets); + VARDECL(int, fine_priority); + VARDECL(int, tf_res); + VARDECL(unsigned char, collapse_masks); + celt_sig *prefilter_mem; + opus_val16 *oldBandE, *oldLogE, *oldLogE2; + int shortBlocks=0; + int isTransient=0; + const int CC = st->channels; + const int C = st->stream_channels; + int LM, M; + int tf_select; + int nbFilledBytes, nbAvailableBytes; + int effEnd; + int codedBands; + int tf_sum; + int alloc_trim; + int pitch_index=COMBFILTER_MINPERIOD; + opus_val16 gain1 = 0; + int dual_stereo=0; + int effectiveBytes; + int dynalloc_logp; + opus_int32 vbr_rate; + opus_int32 total_bits; + opus_int32 total_boost; + opus_int32 balance; + opus_int32 tell; + int prefilter_tapset=0; + int pf_on; + int anti_collapse_rsv; + int anti_collapse_on=0; + int silence=0; + int tf_chan = 0; + opus_val16 tf_estimate; + int pitch_change=0; + opus_int32 tot_boost; + opus_val32 sample_max; + opus_val16 maxDepth; + const OpusCustomMode *mode; + int nbEBands; + int overlap; + const opus_int16 *eBands; + int secondMdct; + int signalBandwidth; + int transient_got_disabled=0; + opus_val16 surround_masking=0; + opus_val16 temporal_vbr=0; + opus_val16 surround_trim = 0; + opus_int32 equiv_rate = 510000; + VARDECL(opus_val16, surround_dynalloc); + ALLOC_STACK; + + mode = st->mode; + nbEBands = mode->nbEBands; + overlap = mode->overlap; + eBands = mode->eBands; + tf_estimate = 0; + if (nbCompressedBytes<2 || pcm==NULL) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + + frame_size *= st->upsample; + for (LM=0;LM<=mode->maxLM;LM++) + if (mode->shortMdctSize<mode->maxLM) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + M=1<shortMdctSize; + + prefilter_mem = st->in_mem+CC*(st->overlap); + oldBandE = (opus_val16*)(st->in_mem+CC*(st->overlap+COMBFILTER_MAXPERIOD)); + oldLogE = oldBandE + CC*nbEBands; + oldLogE2 = oldLogE + CC*nbEBands; + + if (enc==NULL) + { + tell=1; + nbFilledBytes=0; + } else { + tell=ec_tell(enc); + nbFilledBytes=(tell+4)>>3; + } + +#ifdef CUSTOM_MODES + if (st->signalling && enc==NULL) + { + int tmp = (mode->effEBands-st->end)>>1; + st->end = IMAX(1, mode->effEBands-tmp); + compressed[0] = tmp<<5; + compressed[0] |= LM<<3; + compressed[0] |= (C==2)<<2; + /* Convert "standard mode" to Opus header */ + if (mode->Fs==48000 && mode->shortMdctSize==120) + { + int c0 = toOpus(compressed[0]); + if (c0<0) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + compressed[0] = c0; + } + compressed++; + nbCompressedBytes--; + } +#else + celt_assert(st->signalling==0); +#endif + + /* Can't produce more than 1275 output bytes */ + nbCompressedBytes = IMIN(nbCompressedBytes,1275); + nbAvailableBytes = nbCompressedBytes - nbFilledBytes; + + if (st->vbr && st->bitrate!=OPUS_BITRATE_MAX) + { + opus_int32 den=mode->Fs>>BITRES; + vbr_rate=(st->bitrate*frame_size+(den>>1))/den; +#ifdef CUSTOM_MODES + if (st->signalling) + vbr_rate -= 8<>(3+BITRES); + } else { + opus_int32 tmp; + vbr_rate = 0; + tmp = st->bitrate*frame_size; + if (tell>1) + tmp += tell; + if (st->bitrate!=OPUS_BITRATE_MAX) + nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes, + (tmp+4*mode->Fs)/(8*mode->Fs)-!!st->signalling)); + effectiveBytes = nbCompressedBytes; + } + if (st->bitrate != OPUS_BITRATE_MAX) + equiv_rate = st->bitrate - (40*C+20)*((400>>LM) - 50); + + if (enc==NULL) + { + ec_enc_init(&_enc, compressed, nbCompressedBytes); + enc = &_enc; + } + + if (vbr_rate>0) + { + /* Computes the max bit-rate allowed in VBR mode to avoid violating the + target rate and buffering. + We must do this up front so that bust-prevention logic triggers + correctly if we don't have enough bits. */ + if (st->constrained_vbr) + { + opus_int32 vbr_bound; + opus_int32 max_allowed; + /* We could use any multiple of vbr_rate as bound (depending on the + delay). + This is clamped to ensure we use at least two bytes if the encoder + was entirely empty, but to allow 0 in hybrid mode. */ + vbr_bound = vbr_rate; + max_allowed = IMIN(IMAX(tell==1?2:0, + (vbr_rate+vbr_bound-st->vbr_reservoir)>>(BITRES+3)), + nbAvailableBytes); + if(max_allowed < nbAvailableBytes) + { + nbCompressedBytes = nbFilledBytes+max_allowed; + nbAvailableBytes = max_allowed; + ec_enc_shrink(enc, nbCompressedBytes); + } + } + } + total_bits = nbCompressedBytes*8; + + effEnd = st->end; + if (effEnd > mode->effEBands) + effEnd = mode->effEBands; + + ALLOC(in, CC*(N+st->overlap), celt_sig); + + sample_max=MAX32(st->overlap_max, celt_maxabs16(pcm, C*(N-overlap)/st->upsample)); + st->overlap_max=celt_maxabs16(pcm+C*(N-overlap)/st->upsample, C*overlap/st->upsample); + sample_max=MAX32(sample_max, st->overlap_max); +#ifdef FIXED_POINT + silence = (sample_max==0); +#else + silence = (sample_max <= (opus_val16)1/(1<lsb_depth)); +#endif +#ifdef FUZZING + if ((rand()&0x3F)==0) + silence = 1; +#endif + if (tell==1) + ec_enc_bit_logp(enc, silence, 15); + else + silence=0; + if (silence) + { + /*In VBR mode there is no need to send more than the minimum. */ + if (vbr_rate>0) + { + effectiveBytes=nbCompressedBytes=IMIN(nbCompressedBytes, nbFilledBytes+2); + total_bits=nbCompressedBytes*8; + nbAvailableBytes=2; + ec_enc_shrink(enc, nbCompressedBytes); + } + /* Pretend we've filled all the remaining bits with zeros + (that's what the initialiser did anyway) */ + tell = nbCompressedBytes*8; + enc->nbits_total+=tell-ec_tell(enc); + } + c=0; do { + celt_preemphasis(pcm+c, in+c*(N+st->overlap)+st->overlap, N, CC, st->upsample, + mode->preemph, st->preemph_memE+c, st->clip); + } while (++clfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && st->start==0 && !silence && !st->disable_pf + && st->complexity >= 5 && !(st->consec_transient && LM!=3 && st->variable_duration==OPUS_FRAMESIZE_VARIABLE); + + prefilter_tapset = st->tapset_decision; + pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes); + if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && (!st->analysis.valid || st->analysis.tonality > .3) + && (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period)) + pitch_change = 1; + if (pf_on==0) + { + if(st->start==0 && tell+16<=total_bits) + ec_enc_bit_logp(enc, 0, 1); + } else { + /*This block is not gated by a total bits check only because + of the nbAvailableBytes check above.*/ + int octave; + ec_enc_bit_logp(enc, 1, 1); + pitch_index += 1; + octave = EC_ILOG(pitch_index)-5; + ec_enc_uint(enc, octave, 6); + ec_enc_bits(enc, pitch_index-(16<complexity >= 1 && !st->lfe) + { + isTransient = transient_analysis(in, N+st->overlap, CC, + &tf_estimate, &tf_chan); + } + if (LM>0 && ec_tell(enc)+3<=total_bits) + { + if (isTransient) + shortBlocks = M; + } else { + isTransient = 0; + transient_got_disabled=1; + } + + ALLOC(freq, CC*N, celt_sig); /**< Interleaved signal MDCTs */ + ALLOC(bandE,nbEBands*CC, celt_ener); + ALLOC(bandLogE,nbEBands*CC, opus_val16); + + secondMdct = shortBlocks && st->complexity>=8; + ALLOC(bandLogE2, C*nbEBands, opus_val16); + if (secondMdct) + { + compute_mdcts(mode, 0, in, freq, C, CC, LM, st->upsample); + compute_band_energies(mode, freq, bandE, effEnd, C, M); + amp2Log2(mode, effEnd, st->end, bandE, bandLogE2, C); + for (i=0;iupsample); + if (CC==2&&C==1) + tf_chan = 0; + compute_band_energies(mode, freq, bandE, effEnd, C, M); + + if (st->lfe) + { + for (i=2;iend;i++) + { + bandE[i] = IMIN(bandE[i], MULT16_32_Q15(QCONST16(1e-4f,15),bandE[0])); + bandE[i] = MAX32(bandE[i], EPSILON); + } + } + amp2Log2(mode, effEnd, st->end, bandE, bandLogE, C); + + ALLOC(surround_dynalloc, C*nbEBands, opus_val16); + for(i=0;iend;i++) + surround_dynalloc[i] = 0; + /* This computes how much masking takes place between surround channels */ + if (st->start==0&&st->energy_mask&&!st->lfe) + { + int mask_end; + int midband; + int count_dynalloc; + opus_val32 mask_avg=0; + opus_val32 diff=0; + int count=0; + mask_end = IMAX(2,st->lastCodedBands); + for (c=0;cenergy_mask[nbEBands*c+i], + QCONST16(.25f, DB_SHIFT)), -QCONST16(2.0f, DB_SHIFT)); + if (mask > 0) + mask = HALF16(mask); + mask_avg += MULT16_16(mask, eBands[i+1]-eBands[i]); + count += eBands[i+1]-eBands[i]; + diff += MULT16_16(mask, 1+2*i-mask_end); + } + } + mask_avg = DIV32_16(mask_avg,count); + mask_avg += QCONST16(.2f, DB_SHIFT); + diff = diff*6/(C*(mask_end-1)*(mask_end+1)*mask_end); + /* Again, being conservative */ + diff = HALF32(diff); + diff = MAX32(MIN32(diff, QCONST32(.031f, DB_SHIFT)), -QCONST32(.031f, DB_SHIFT)); + /* Find the band that's in the middle of the coded spectrum */ + for (midband=0;eBands[midband+1] < eBands[mask_end]/2;midband++); + count_dynalloc=0; + for(i=0;ienergy_mask[i], st->energy_mask[nbEBands+i]); + else + unmask = st->energy_mask[i]; + unmask = MIN16(unmask, QCONST16(.0f, DB_SHIFT)); + unmask -= lin; + if (unmask > QCONST16(.25f, DB_SHIFT)) + { + surround_dynalloc[i] = unmask - QCONST16(.25f, DB_SHIFT); + count_dynalloc++; + } + } + if (count_dynalloc>=3) + { + /* If we need dynalloc in many bands, it's probably because our + initial masking rate was too low. */ + mask_avg += QCONST16(.25f, DB_SHIFT); + if (mask_avg>0) + { + /* Something went really wrong in the original calculations, + disabling masking. */ + mask_avg = 0; + diff = 0; + for(i=0;ilfe) + { + opus_val16 follow=-QCONST16(10.0f,DB_SHIFT); + opus_val32 frame_avg=0; + opus_val16 offset = shortBlocks?HALF16(SHL16(LM, DB_SHIFT)):0; + for(i=st->start;iend;i++) + { + follow = MAX16(follow-QCONST16(1.f, DB_SHIFT), bandLogE[i]-offset); + if (C==2) + follow = MAX16(follow, bandLogE[i+nbEBands]-offset); + frame_avg += follow; + } + frame_avg /= (st->end-st->start); + temporal_vbr = SUB16(frame_avg,st->spec_avg); + temporal_vbr = MIN16(QCONST16(3.f, DB_SHIFT), MAX16(-QCONST16(1.5f, DB_SHIFT), temporal_vbr)); + st->spec_avg += MULT16_16_Q15(QCONST16(.02f, 15), temporal_vbr); + } + /*for (i=0;i<21;i++) + printf("%f ", bandLogE[i]); + printf("\n");*/ + + if (!secondMdct) + { + for (i=0;i0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe) + { + if (patch_transient_decision(bandLogE, oldBandE, nbEBands, st->end, C)) + { + isTransient = 1; + shortBlocks = M; + compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample); + compute_band_energies(mode, freq, bandE, effEnd, C, M); + amp2Log2(mode, effEnd, st->end, bandE, bandLogE, C); + /* Compensate for the scaling of short vs long mdcts */ + for (i=0;i0 && ec_tell(enc)+3<=total_bits) + ec_enc_bit_logp(enc, isTransient, 3); + + ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ + + /* Band normalisation */ + normalise_bands(mode, freq, X, bandE, effEnd, C, M); + + ALLOC(tf_res, nbEBands, int); + /* Disable variable tf resolution for hybrid and at very low bitrate */ + if (effectiveBytes>=15*C && st->start==0 && st->complexity>=2 && !st->lfe) + { + int lambda; + if (effectiveBytes<40) + lambda = 12; + else if (effectiveBytes<60) + lambda = 6; + else if (effectiveBytes<100) + lambda = 4; + else + lambda = 3; + lambda*=2; + tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, &tf_sum, tf_estimate, tf_chan); + for (i=effEnd;iend;i++) + tf_res[i] = tf_res[effEnd-1]; + } else { + tf_sum = 0; + for (i=0;iend;i++) + tf_res[i] = isTransient; + tf_select=0; + } + + ALLOC(error, C*nbEBands, opus_val16); + quant_coarse_energy(mode, st->start, st->end, effEnd, bandLogE, + oldBandE, total_bits, error, enc, + C, LM, nbAvailableBytes, st->force_intra, + &st->delayedIntra, st->complexity >= 4, st->loss_rate, st->lfe); + + tf_encode(st->start, st->end, isTransient, tf_res, LM, tf_select, enc); + + if (ec_tell(enc)+4<=total_bits) + { + if (st->lfe) + { + st->tapset_decision = 0; + st->spread_decision = SPREAD_NORMAL; + } else if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C || st->start != 0) + { + if (st->complexity == 0) + st->spread_decision = SPREAD_NONE; + else + st->spread_decision = SPREAD_NORMAL; + } else { + /* Disable new spreading+tapset estimator until we can show it works + better than the old one. So far it seems like spreading_decision() + works best. */ +#if 0 + if (st->analysis.valid) + { + static const opus_val16 spread_thresholds[3] = {-QCONST16(.6f, 15), -QCONST16(.2f, 15), -QCONST16(.07f, 15)}; + static const opus_val16 spread_histeresis[3] = {QCONST16(.15f, 15), QCONST16(.07f, 15), QCONST16(.02f, 15)}; + static const opus_val16 tapset_thresholds[2] = {QCONST16(.0f, 15), QCONST16(.15f, 15)}; + static const opus_val16 tapset_histeresis[2] = {QCONST16(.1f, 15), QCONST16(.05f, 15)}; + st->spread_decision = hysteresis_decision(-st->analysis.tonality, spread_thresholds, spread_histeresis, 3, st->spread_decision); + st->tapset_decision = hysteresis_decision(st->analysis.tonality_slope, tapset_thresholds, tapset_histeresis, 2, st->tapset_decision); + } else +#endif + { + st->spread_decision = spreading_decision(mode, X, + &st->tonal_average, st->spread_decision, &st->hf_average, + &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M); + } + /*printf("%d %d\n", st->tapset_decision, st->spread_decision);*/ + /*printf("%f %d %f %d\n\n", st->analysis.tonality, st->spread_decision, st->analysis.tonality_slope, st->tapset_decision);*/ + } + ec_enc_icdf(enc, st->spread_decision, spread_icdf, 5); + } + + ALLOC(offsets, nbEBands, int); + + maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, st->start, st->end, C, offsets, + st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr, + eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc); + /* For LFE, everything interesting is in the first band */ + if (st->lfe) + offsets[0] = IMIN(8, effectiveBytes/3); + ALLOC(cap, nbEBands, int); + init_caps(mode,cap,LM,C); + + dynalloc_logp = 6; + total_bits<<=BITRES; + total_boost = 0; + tell = ec_tell_frac(enc); + for (i=st->start;iend;i++) + { + int width, quanta; + int dynalloc_loop_logp; + int boost; + int j; + width = C*(eBands[i+1]-eBands[i])<intensity = hysteresis_decision((opus_val16)(equiv_rate/1000), + intensity_thresholds, intensity_histeresis, 21, st->intensity); + st->intensity = IMIN(st->end,IMAX(st->start, st->intensity)); + } + + alloc_trim = 5; + if (tell+(6<lfe) + alloc_trim = 5; + else + alloc_trim = alloc_trim_analysis(mode, X, bandLogE, + st->end, LM, C, N, &st->analysis, &st->stereo_saving, tf_estimate, st->intensity, surround_trim); + ec_enc_icdf(enc, alloc_trim, trim_icdf, 7); + tell = ec_tell_frac(enc); + } + + /* Variable bitrate */ + if (vbr_rate>0) + { + opus_val16 alpha; + opus_int32 delta; + /* The target rate in 8th bits per frame */ + opus_int32 target, base_target; + opus_int32 min_allowed; + int lm_diff = mode->maxLM - LM; + + /* Don't attempt to use more than 510 kb/s, even for frames smaller than 20 ms. + The CELT allocator will just not be able to use more than that anyway. */ + nbCompressedBytes = IMIN(nbCompressedBytes,1275>>(3-LM)); + base_target = vbr_rate - ((40*C+20)<constrained_vbr) + base_target += (st->vbr_offset>>lm_diff); + + target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate, + st->lastCodedBands, C, st->intensity, st->constrained_vbr, + st->stereo_saving, tot_boost, tf_estimate, pitch_change, maxDepth, + st->variable_duration, st->lfe, st->energy_mask!=NULL, surround_masking, + temporal_vbr); + + /* The current offset is removed from the target and the space used + so far is added*/ + target=target+tell; + /* In VBR mode the frame size must not be reduced so much that it would + result in the encoder running out of bits. + The margin of 2 bytes ensures that none of the bust-prevention logic + in the decoder will have triggered so far. */ + min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2 - nbFilledBytes; + + nbAvailableBytes = (target+(1<<(BITRES+2)))>>(BITRES+3); + nbAvailableBytes = IMAX(min_allowed,nbAvailableBytes); + nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes) - nbFilledBytes; + + /* By how much did we "miss" the target on that frame */ + delta = target - vbr_rate; + + target=nbAvailableBytes<<(BITRES+3); + + /*If the frame is silent we don't adjust our drift, otherwise + the encoder will shoot to very high rates after hitting a + span of silence, but we do allow the bitres to refill. + This means that we'll undershoot our target in CVBR/VBR modes + on files with lots of silence. */ + if(silence) + { + nbAvailableBytes = 2; + target = 2*8<vbr_count < 970) + { + st->vbr_count++; + alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+20),16)); + } else + alpha = QCONST16(.001f,15); + /* How many bits have we used in excess of what we're allowed */ + if (st->constrained_vbr) + st->vbr_reservoir += target - vbr_rate; + /*printf ("%d\n", st->vbr_reservoir);*/ + + /* Compute the offset we need to apply in order to reach the target */ + if (st->constrained_vbr) + { + st->vbr_drift += (opus_int32)MULT16_32_Q15(alpha,(delta*(1<vbr_offset-st->vbr_drift); + st->vbr_offset = -st->vbr_drift; + } + /*printf ("%d\n", st->vbr_drift);*/ + + if (st->constrained_vbr && st->vbr_reservoir < 0) + { + /* We're under the min value -- increase rate */ + int adjust = (-st->vbr_reservoir)/(8<vbr_reservoir = 0; + /*printf ("+%d\n", adjust);*/ + } + nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes); + /*printf("%d\n", nbCompressedBytes*50*8);*/ + /* This moves the raw bits to take into account the new compressed size */ + ec_enc_shrink(enc, nbCompressedBytes); + } + + /* Bit allocation */ + ALLOC(fine_quant, nbEBands, int); + ALLOC(pulses, nbEBands, int); + ALLOC(fine_priority, nbEBands, int); + + /* bits = packet size - where we are - safety*/ + bits = (((opus_int32)nbCompressedBytes*8)<=2&&bits>=((LM+2)<end-1; +#ifndef DISABLE_FLOAT_API + if (st->analysis.valid) + { + int min_bandwidth; + if (equiv_rate < (opus_int32)32000*C) + min_bandwidth = 13; + else if (equiv_rate < (opus_int32)48000*C) + min_bandwidth = 16; + else if (equiv_rate < (opus_int32)60000*C) + min_bandwidth = 18; + else if (equiv_rate < (opus_int32)80000*C) + min_bandwidth = 19; + else + min_bandwidth = 20; + signalBandwidth = IMAX(st->analysis.bandwidth, min_bandwidth); + } +#endif + if (st->lfe) + signalBandwidth = 1; + codedBands = compute_allocation(mode, st->start, st->end, offsets, cap, + alloc_trim, &st->intensity, &dual_stereo, bits, &balance, pulses, + fine_quant, fine_priority, C, LM, enc, 1, st->lastCodedBands, signalBandwidth); + if (st->lastCodedBands) + st->lastCodedBands = IMIN(st->lastCodedBands+1,IMAX(st->lastCodedBands-1,codedBands)); + else + st->lastCodedBands = codedBands; + + quant_fine_energy(mode, st->start, st->end, oldBandE, error, fine_quant, enc, C); + + /* Residual quantisation */ + ALLOC(collapse_masks, C*nbEBands, unsigned char); + quant_all_bands(1, mode, st->start, st->end, X, C==2 ? X+N : NULL, collapse_masks, + bandE, pulses, shortBlocks, st->spread_decision, dual_stereo, st->intensity, tf_res, + nbCompressedBytes*(8<rng); + + if (anti_collapse_rsv > 0) + { + anti_collapse_on = st->consec_transient<2; +#ifdef FUZZING + anti_collapse_on = rand()&0x1; +#endif + ec_enc_bits(enc, anti_collapse_on, 1); + } + quant_energy_finalise(mode, st->start, st->end, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_tell(enc), enc, C); + + if (silence) + { + for (i=0;istart, st->end, oldBandE, oldLogE, oldLogE2, pulses, st->rng); + } + + if (silence) + { + for (i=0;istart, effEnd, C, M); + } + + c=0; do { + OPUS_MOVE(st->syn_mem[c], st->syn_mem[c]+N, 2*MAX_PERIOD-N+overlap/2); + } while (++csyn_mem[c]+2*MAX_PERIOD-N; + } while (++cprefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD); + st->prefilter_period_old=IMAX(st->prefilter_period_old, COMBFILTER_MINPERIOD); + comb_filter(out_mem[c], out_mem[c], st->prefilter_period_old, st->prefilter_period, mode->shortMdctSize, + st->prefilter_gain_old, st->prefilter_gain, st->prefilter_tapset_old, st->prefilter_tapset, + mode->window, st->overlap); + if (LM!=0) + comb_filter(out_mem[c]+mode->shortMdctSize, out_mem[c]+mode->shortMdctSize, st->prefilter_period, pitch_index, N-mode->shortMdctSize, + st->prefilter_gain, gain1, st->prefilter_tapset, prefilter_tapset, + mode->window, overlap); + } while (++cupsample, mode->preemph, st->preemph_memD, freq); + st->prefilter_period_old = st->prefilter_period; + st->prefilter_gain_old = st->prefilter_gain; + st->prefilter_tapset_old = st->prefilter_tapset; + } +#endif + + st->prefilter_period = pitch_index; + st->prefilter_gain = gain1; + st->prefilter_tapset = prefilter_tapset; +#ifdef RESYNTH + if (LM!=0) + { + st->prefilter_period_old = st->prefilter_period; + st->prefilter_gain_old = st->prefilter_gain; + st->prefilter_tapset_old = st->prefilter_tapset; + } +#endif + + if (CC==2&&C==1) { + for (i=0;istart;i++) + { + oldBandE[c*nbEBands+i]=0; + oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT); + } + for (i=st->end;iconsec_transient++; + else + st->consec_transient=0; + st->rng = enc->rng; + + /* If there's any room left (can only happen for very high rates), + it's already filled with zeros */ + ec_enc_done(enc); + +#ifdef CUSTOM_MODES + if (st->signalling) + nbCompressedBytes++; +#endif + + RESTORE_STACK; + if (ec_get_error(enc)) + return OPUS_INTERNAL_ERROR; + else + return nbCompressedBytes; +} + + +#ifdef CUSTOM_MODES + +#ifdef FIXED_POINT +int opus_custom_encode(CELTEncoder * OPUS_RESTRICT st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) +{ + return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL); +} + +#ifndef DISABLE_FLOAT_API +int opus_custom_encode_float(CELTEncoder * OPUS_RESTRICT st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) +{ + int j, ret, C, N; + VARDECL(opus_int16, in); + ALLOC_STACK; + + if (pcm==NULL) + return OPUS_BAD_ARG; + + C = st->channels; + N = frame_size; + ALLOC(in, C*N, opus_int16); + + for (j=0;jchannels; + N=frame_size; + ALLOC(in, C*N, celt_sig); + for (j=0;j10) + goto bad_arg; + st->complexity = value; + } + break; + case CELT_SET_START_BAND_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<0 || value>=st->mode->nbEBands) + goto bad_arg; + st->start = value; + } + break; + case CELT_SET_END_BAND_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<1 || value>st->mode->nbEBands) + goto bad_arg; + st->end = value; + } + break; + case CELT_SET_PREDICTION_REQUEST: + { + int value = va_arg(ap, opus_int32); + if (value<0 || value>2) + goto bad_arg; + st->disable_pf = value<=1; + st->force_intra = value==0; + } + break; + case OPUS_SET_PACKET_LOSS_PERC_REQUEST: + { + int value = va_arg(ap, opus_int32); + if (value<0 || value>100) + goto bad_arg; + st->loss_rate = value; + } + break; + case OPUS_SET_VBR_CONSTRAINT_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->constrained_vbr = value; + } + break; + case OPUS_SET_VBR_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->vbr = value; + } + break; + case OPUS_SET_BITRATE_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<=500 && value!=OPUS_BITRATE_MAX) + goto bad_arg; + value = IMIN(value, 260000*st->channels); + st->bitrate = value; + } + break; + case CELT_SET_CHANNELS_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<1 || value>2) + goto bad_arg; + st->stream_channels = value; + } + break; + case OPUS_SET_LSB_DEPTH_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<8 || value>24) + goto bad_arg; + st->lsb_depth=value; + } + break; + case OPUS_GET_LSB_DEPTH_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + *value=st->lsb_depth; + } + break; + case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->variable_duration = value; + } + break; + case OPUS_RESET_STATE: + { + int i; + opus_val16 *oldBandE, *oldLogE, *oldLogE2; + oldBandE = (opus_val16*)(st->in_mem+st->channels*(st->overlap+COMBFILTER_MAXPERIOD)); + oldLogE = oldBandE + st->channels*st->mode->nbEBands; + oldLogE2 = oldLogE + st->channels*st->mode->nbEBands; + OPUS_CLEAR((char*)&st->ENCODER_RESET_START, + opus_custom_encoder_get_size(st->mode, st->channels)- + ((char*)&st->ENCODER_RESET_START - (char*)st)); + for (i=0;ichannels*st->mode->nbEBands;i++) + oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT); + st->vbr_offset = 0; + st->delayedIntra = 1; + st->spread_decision = SPREAD_NORMAL; + st->tonal_average = 256; + st->hf_average = 0; + st->tapset_decision = 0; + } + break; +#ifdef CUSTOM_MODES + case CELT_SET_INPUT_CLIPPING_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->clip = value; + } + break; +#endif + case CELT_SET_SIGNALLING_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->signalling = value; + } + break; + case CELT_SET_ANALYSIS_REQUEST: + { + AnalysisInfo *info = va_arg(ap, AnalysisInfo *); + if (info) + OPUS_COPY(&st->analysis, info, 1); + } + break; + case CELT_GET_MODE_REQUEST: + { + const CELTMode ** value = va_arg(ap, const CELTMode**); + if (value==0) + goto bad_arg; + *value=st->mode; + } + break; + case OPUS_GET_FINAL_RANGE_REQUEST: + { + opus_uint32 * value = va_arg(ap, opus_uint32 *); + if (value==0) + goto bad_arg; + *value=st->rng; + } + break; + case OPUS_SET_LFE_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->lfe = value; + } + break; + case OPUS_SET_ENERGY_MASK_REQUEST: + { + opus_val16 *value = va_arg(ap, opus_val16*); + st->energy_mask = value; + } + break; + default: + goto bad_request; + } + va_end(ap); + return OPUS_OK; +bad_arg: + va_end(ap); + return OPUS_BAD_ARG; +bad_request: + va_end(ap); + return OPUS_UNIMPLEMENTED; +} diff --git a/TelegramClient.Opus/opus/celt/celt_lpc.c b/TelegramClient.Opus/opus/celt/celt_lpc.c new file mode 100755 index 0000000..fa29d62 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/celt_lpc.c @@ -0,0 +1,309 @@ +/* Copyright (c) 2009-2010 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "celt_lpc.h" +#include "stack_alloc.h" +#include "mathops.h" +#include "pitch.h" + +void _celt_lpc( + opus_val16 *_lpc, /* out: [0...p-1] LPC coefficients */ +const opus_val32 *ac, /* in: [0...p] autocorrelation values */ +int p +) +{ + int i, j; + opus_val32 r; + opus_val32 error = ac[0]; +#ifdef FIXED_POINT + opus_val32 lpc[LPC_ORDER]; +#else + float *lpc = _lpc; +#endif + + for (i = 0; i < p; i++) + lpc[i] = 0; + if (ac[0] != 0) + { + for (i = 0; i < p; i++) { + /* Sum up this iteration's reflection coefficient */ + opus_val32 rr = 0; + for (j = 0; j < i; j++) + rr += MULT32_32_Q31(lpc[j],ac[i - j]); + rr += SHR32(ac[i + 1],3); + r = -frac_div32(SHL32(rr,3), error); + /* Update LPC coefficients and total error */ + lpc[i] = SHR32(r,3); + for (j = 0; j < (i+1)>>1; j++) + { + opus_val32 tmp1, tmp2; + tmp1 = lpc[j]; + tmp2 = lpc[i-1-j]; + lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2); + lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1); + } + + error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error); + /* Bail out once we get 30 dB gain */ +#ifdef FIXED_POINT + if (error=1;j--) + { + mem[j]=mem[j-1]; + } + mem[0] = ROUND16(sum,SIG_SHIFT); + _y[i] = sum; + } +#else + int i,j; + VARDECL(opus_val16, rden); + VARDECL(opus_val16, y); + SAVE_STACK; + + celt_assert((ord&3)==0); + ALLOC(rden, ord, opus_val16); + ALLOC(y, N+ord, opus_val16); + for(i=0;i0); + celt_assert(overlap>=0); + if (overlap == 0) + { + xptr = x; + } else { + for (i=0;i0) + { + for(i=0;i= 536870912) + { + int shift2=1; + if (ac[0] >= 1073741824) + shift2++; + for (i=0;i<=lag;i++) + ac[i] = SHR32(ac[i], shift2); + shift += shift2; + } +#endif + + RESTORE_STACK; + return shift; +} diff --git a/TelegramClient.Opus/opus/celt/celt_lpc.h b/TelegramClient.Opus/opus/celt/celt_lpc.h new file mode 100755 index 0000000..dc2a0a3 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/celt_lpc.h @@ -0,0 +1,54 @@ +/* Copyright (c) 2009-2010 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef PLC_H +#define PLC_H + +#include "arch.h" + +#define LPC_ORDER 24 + +void _celt_lpc(opus_val16 *_lpc, const opus_val32 *ac, int p); + +void celt_fir(const opus_val16 *x, + const opus_val16 *num, + opus_val16 *y, + int N, + int ord, + opus_val16 *mem); + +void celt_iir(const opus_val32 *x, + const opus_val16 *den, + opus_val32 *y, + int N, + int ord, + opus_val16 *mem); + +int _celt_autocorr(const opus_val16 *x, opus_val32 *ac, + const opus_val16 *window, int overlap, int lag, int n, int arch); + +#endif /* PLC_H */ diff --git a/TelegramClient.Opus/opus/celt/cpu_support.h b/TelegramClient.Opus/opus/celt/cpu_support.h new file mode 100755 index 0000000..d68dbe6 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/cpu_support.h @@ -0,0 +1,54 @@ +/* Copyright (c) 2010 Xiph.Org Foundation + * Copyright (c) 2013 Parrot */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef CPU_SUPPORT_H +#define CPU_SUPPORT_H + +#include "opus_types.h" +#include "opus_defines.h" + +#if defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_ASM) +#include "arm/armcpu.h" + +/* We currently support 4 ARM variants: + * arch[0] -> ARMv4 + * arch[1] -> ARMv5E + * arch[2] -> ARMv6 + * arch[3] -> NEON + */ +#define OPUS_ARCHMASK 3 + +#else +#define OPUS_ARCHMASK 0 + +static OPUS_INLINE int opus_select_arch(void) +{ + return 0; +} +#endif + +#endif diff --git a/TelegramClient.Opus/opus/celt/cwrs.c b/TelegramClient.Opus/opus/celt/cwrs.c new file mode 100755 index 0000000..ad980cc --- /dev/null +++ b/TelegramClient.Opus/opus/celt/cwrs.c @@ -0,0 +1,697 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Copyright (c) 2007-2009 Timothy B. Terriberry + Written by Timothy B. Terriberry and Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "os_support.h" +#include "cwrs.h" +#include "mathops.h" +#include "arch.h" + +#ifdef CUSTOM_MODES + +/*Guaranteed to return a conservatively large estimate of the binary logarithm + with frac bits of fractional precision. + Tested for all possible 32-bit inputs with frac=4, where the maximum + overestimation is 0.06254243 bits.*/ +int log2_frac(opus_uint32 val, int frac) +{ + int l; + l=EC_ILOG(val); + if(val&(val-1)){ + /*This is (val>>l-16), but guaranteed to round up, even if adding a bias + before the shift would cause overflow (e.g., for 0xFFFFxxxx). + Doesn't work for val=0, but that case fails the test above.*/ + if(l>16)val=((val-1)>>(l-16))+1; + else val<<=16-l; + l=(l-1)<>16); + l+=b<>b; + val=(val*val+0x7FFF)>>15; + } + while(frac-->0); + /*If val is not exactly 0x8000, then we have to round up the remainder.*/ + return l+(val>0x8000); + } + /*Exact powers of two require no rounding.*/ + else return (l-1)<0 ? sum(k=1...K,2**k*choose(N,k)*choose(K-1,k-1)) : 1, + where choose() is the binomial function. + A table of values for N<10 and K<10 looks like: + V[10][10] = { + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 2, 2, 2, 2, 2, 2, 2, 2, 2}, + {1, 4, 8, 12, 16, 20, 24, 28, 32, 36}, + {1, 6, 18, 38, 66, 102, 146, 198, 258, 326}, + {1, 8, 32, 88, 192, 360, 608, 952, 1408, 1992}, + {1, 10, 50, 170, 450, 1002, 1970, 3530, 5890, 9290}, + {1, 12, 72, 292, 912, 2364, 5336, 10836, 20256, 35436}, + {1, 14, 98, 462, 1666, 4942, 12642, 28814, 59906, 115598}, + {1, 16, 128, 688, 2816, 9424, 27008, 68464, 157184, 332688}, + {1, 18, 162, 978, 4482, 16722, 53154, 148626, 374274, 864146} + }; + + U(N,K) = the number of such combinations wherein N-1 objects are taken at + most K-1 at a time. + This is given by + U(N,K) = sum(k=0...K-1,V(N-1,k)) + = K>0 ? (V(N-1,K-1) + V(N,K-1))/2 : 0. + The latter expression also makes clear that U(N,K) is half the number of such + combinations wherein the first object is taken at least once. + Although it may not be clear from either of these definitions, U(N,K) is the + natural function to work with when enumerating the pulse vector codebooks, + not V(N,K). + U(N,K) is not well-defined for N=0, but with the extension + U(0,K) = K>0 ? 0 : 1, + the function becomes symmetric: U(N,K) = U(K,N), with a similar table: + U[10][10] = { + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {0, 1, 3, 5, 7, 9, 11, 13, 15, 17}, + {0, 1, 5, 13, 25, 41, 61, 85, 113, 145}, + {0, 1, 7, 25, 63, 129, 231, 377, 575, 833}, + {0, 1, 9, 41, 129, 321, 681, 1289, 2241, 3649}, + {0, 1, 11, 61, 231, 681, 1683, 3653, 7183, 13073}, + {0, 1, 13, 85, 377, 1289, 3653, 8989, 19825, 40081}, + {0, 1, 15, 113, 575, 2241, 7183, 19825, 48639, 108545}, + {0, 1, 17, 145, 833, 3649, 13073, 40081, 108545, 265729} + }; + + With this extension, V(N,K) may be written in terms of U(N,K): + V(N,K) = U(N,K) + U(N,K+1) + for all N>=0, K>=0. + Thus U(N,K+1) represents the number of combinations where the first element + is positive or zero, and U(N,K) represents the number of combinations where + it is negative. + With a large enough table of U(N,K) values, we could write O(N) encoding + and O(min(N*log(K),N+K)) decoding routines, but such a table would be + prohibitively large for small embedded devices (K may be as large as 32767 + for small N, and N may be as large as 200). + + Both functions obey the same recurrence relation: + V(N,K) = V(N-1,K) + V(N,K-1) + V(N-1,K-1), + U(N,K) = U(N-1,K) + U(N,K-1) + U(N-1,K-1), + for all N>0, K>0, with different initial conditions at N=0 or K=0. + This allows us to construct a row of one of the tables above given the + previous row or the next row. + Thus we can derive O(NK) encoding and decoding routines with O(K) memory + using only addition and subtraction. + + When encoding, we build up from the U(2,K) row and work our way forwards. + When decoding, we need to start at the U(N,K) row and work our way backwards, + which requires a means of computing U(N,K). + U(N,K) may be computed from two previous values with the same N: + U(N,K) = ((2*N-1)*U(N,K-1) - U(N,K-2))/(K-1) + U(N,K-2) + for all N>1, and since U(N,K) is symmetric, a similar relation holds for two + previous values with the same K: + U(N,K>1) = ((2*K-1)*U(N-1,K) - U(N-2,K))/(N-1) + U(N-2,K) + for all K>1. + This allows us to construct an arbitrary row of the U(N,K) table by starting + with the first two values, which are constants. + This saves roughly 2/3 the work in our O(NK) decoding routine, but costs O(K) + multiplications. + Similar relations can be derived for V(N,K), but are not used here. + + For N>0 and K>0, U(N,K) and V(N,K) take on the form of an (N-1)-degree + polynomial for fixed N. + The first few are + U(1,K) = 1, + U(2,K) = 2*K-1, + U(3,K) = (2*K-2)*K+1, + U(4,K) = (((4*K-6)*K+8)*K-3)/3, + U(5,K) = ((((2*K-4)*K+10)*K-8)*K+3)/3, + and + V(1,K) = 2, + V(2,K) = 4*K, + V(3,K) = 4*K*K+2, + V(4,K) = 8*(K*K+2)*K/3, + V(5,K) = ((4*K*K+20)*K*K+6)/3, + for all K>0. + This allows us to derive O(N) encoding and O(N*log(K)) decoding routines for + small N (and indeed decoding is also O(N) for N<3). + + @ARTICLE{Fis86, + author="Thomas R. Fischer", + title="A Pyramid Vector Quantizer", + journal="IEEE Transactions on Information Theory", + volume="IT-32", + number=4, + pages="568--583", + month=Jul, + year=1986 + }*/ + +#if !defined(SMALL_FOOTPRINT) + +/*U(N,K) = U(K,N) := N>0?K>0?U(N-1,K)+U(N,K-1)+U(N-1,K-1):0:K>0?1:0*/ +# define CELT_PVQ_U(_n,_k) (CELT_PVQ_U_ROW[IMIN(_n,_k)][IMAX(_n,_k)]) +/*V(N,K) := U(N,K)+U(N,K+1) = the number of PVQ codewords for a band of size N + with K pulses allocated to it.*/ +# define CELT_PVQ_V(_n,_k) (CELT_PVQ_U(_n,_k)+CELT_PVQ_U(_n,(_k)+1)) + +/*For each V(N,K) supported, we will access element U(min(N,K+1),max(N,K+1)). + Thus, the number of entries in row I is the larger of the maximum number of + pulses we will ever allocate for a given N=I (K=128, or however many fit in + 32 bits, whichever is smaller), plus one, and the maximum N for which + K=I-1 pulses fit in 32 bits. + The largest band size in an Opus Custom mode is 208. + Otherwise, we can limit things to the set of N which can be achieved by + splitting a band from a standard Opus mode: 176, 144, 96, 88, 72, 64, 48, + 44, 36, 32, 24, 22, 18, 16, 8, 4, 2).*/ +#if defined(CUSTOM_MODES) +static const opus_uint32 CELT_PVQ_U_DATA[1488]={ +#else +static const opus_uint32 CELT_PVQ_U_DATA[1272]={ +#endif + /*N=0, K=0...176:*/ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +#if defined(CUSTOM_MODES) + /*...208:*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, +#endif + /*N=1, K=1...176:*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +#if defined(CUSTOM_MODES) + /*...208:*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, +#endif + /*N=2, K=2...176:*/ + 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, + 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, + 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, + 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, + 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, + 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, + 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, + 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263, + 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, + 295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323, + 325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, +#if defined(CUSTOM_MODES) + /*...208:*/ + 353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381, + 383, 385, 387, 389, 391, 393, 395, 397, 399, 401, 403, 405, 407, 409, 411, + 413, 415, +#endif + /*N=3, K=3...176:*/ + 13, 25, 41, 61, 85, 113, 145, 181, 221, 265, 313, 365, 421, 481, 545, 613, + 685, 761, 841, 925, 1013, 1105, 1201, 1301, 1405, 1513, 1625, 1741, 1861, + 1985, 2113, 2245, 2381, 2521, 2665, 2813, 2965, 3121, 3281, 3445, 3613, 3785, + 3961, 4141, 4325, 4513, 4705, 4901, 5101, 5305, 5513, 5725, 5941, 6161, 6385, + 6613, 6845, 7081, 7321, 7565, 7813, 8065, 8321, 8581, 8845, 9113, 9385, 9661, + 9941, 10225, 10513, 10805, 11101, 11401, 11705, 12013, 12325, 12641, 12961, + 13285, 13613, 13945, 14281, 14621, 14965, 15313, 15665, 16021, 16381, 16745, + 17113, 17485, 17861, 18241, 18625, 19013, 19405, 19801, 20201, 20605, 21013, + 21425, 21841, 22261, 22685, 23113, 23545, 23981, 24421, 24865, 25313, 25765, + 26221, 26681, 27145, 27613, 28085, 28561, 29041, 29525, 30013, 30505, 31001, + 31501, 32005, 32513, 33025, 33541, 34061, 34585, 35113, 35645, 36181, 36721, + 37265, 37813, 38365, 38921, 39481, 40045, 40613, 41185, 41761, 42341, 42925, + 43513, 44105, 44701, 45301, 45905, 46513, 47125, 47741, 48361, 48985, 49613, + 50245, 50881, 51521, 52165, 52813, 53465, 54121, 54781, 55445, 56113, 56785, + 57461, 58141, 58825, 59513, 60205, 60901, 61601, +#if defined(CUSTOM_MODES) + /*...208:*/ + 62305, 63013, 63725, 64441, 65161, 65885, 66613, 67345, 68081, 68821, 69565, + 70313, 71065, 71821, 72581, 73345, 74113, 74885, 75661, 76441, 77225, 78013, + 78805, 79601, 80401, 81205, 82013, 82825, 83641, 84461, 85285, 86113, +#endif + /*N=4, K=4...176:*/ + 63, 129, 231, 377, 575, 833, 1159, 1561, 2047, 2625, 3303, 4089, 4991, 6017, + 7175, 8473, 9919, 11521, 13287, 15225, 17343, 19649, 22151, 24857, 27775, + 30913, 34279, 37881, 41727, 45825, 50183, 54809, 59711, 64897, 70375, 76153, + 82239, 88641, 95367, 102425, 109823, 117569, 125671, 134137, 142975, 152193, + 161799, 171801, 182207, 193025, 204263, 215929, 228031, 240577, 253575, + 267033, 280959, 295361, 310247, 325625, 341503, 357889, 374791, 392217, + 410175, 428673, 447719, 467321, 487487, 508225, 529543, 551449, 573951, + 597057, 620775, 645113, 670079, 695681, 721927, 748825, 776383, 804609, + 833511, 863097, 893375, 924353, 956039, 988441, 1021567, 1055425, 1090023, + 1125369, 1161471, 1198337, 1235975, 1274393, 1313599, 1353601, 1394407, + 1436025, 1478463, 1521729, 1565831, 1610777, 1656575, 1703233, 1750759, + 1799161, 1848447, 1898625, 1949703, 2001689, 2054591, 2108417, 2163175, + 2218873, 2275519, 2333121, 2391687, 2451225, 2511743, 2573249, 2635751, + 2699257, 2763775, 2829313, 2895879, 2963481, 3032127, 3101825, 3172583, + 3244409, 3317311, 3391297, 3466375, 3542553, 3619839, 3698241, 3777767, + 3858425, 3940223, 4023169, 4107271, 4192537, 4278975, 4366593, 4455399, + 4545401, 4636607, 4729025, 4822663, 4917529, 5013631, 5110977, 5209575, + 5309433, 5410559, 5512961, 5616647, 5721625, 5827903, 5935489, 6044391, + 6154617, 6266175, 6379073, 6493319, 6608921, 6725887, 6844225, 6963943, + 7085049, 7207551, +#if defined(CUSTOM_MODES) + /*...208:*/ + 7331457, 7456775, 7583513, 7711679, 7841281, 7972327, 8104825, 8238783, + 8374209, 8511111, 8649497, 8789375, 8930753, 9073639, 9218041, 9363967, + 9511425, 9660423, 9810969, 9963071, 10116737, 10271975, 10428793, 10587199, + 10747201, 10908807, 11072025, 11236863, 11403329, 11571431, 11741177, + 11912575, +#endif + /*N=5, K=5...176:*/ + 321, 681, 1289, 2241, 3649, 5641, 8361, 11969, 16641, 22569, 29961, 39041, + 50049, 63241, 78889, 97281, 118721, 143529, 172041, 204609, 241601, 283401, + 330409, 383041, 441729, 506921, 579081, 658689, 746241, 842249, 947241, + 1061761, 1186369, 1321641, 1468169, 1626561, 1797441, 1981449, 2179241, + 2391489, 2618881, 2862121, 3121929, 3399041, 3694209, 4008201, 4341801, + 4695809, 5071041, 5468329, 5888521, 6332481, 6801089, 7295241, 7815849, + 8363841, 8940161, 9545769, 10181641, 10848769, 11548161, 12280841, 13047849, + 13850241, 14689089, 15565481, 16480521, 17435329, 18431041, 19468809, + 20549801, 21675201, 22846209, 24064041, 25329929, 26645121, 28010881, + 29428489, 30899241, 32424449, 34005441, 35643561, 37340169, 39096641, + 40914369, 42794761, 44739241, 46749249, 48826241, 50971689, 53187081, + 55473921, 57833729, 60268041, 62778409, 65366401, 68033601, 70781609, + 73612041, 76526529, 79526721, 82614281, 85790889, 89058241, 92418049, + 95872041, 99421961, 103069569, 106816641, 110664969, 114616361, 118672641, + 122835649, 127107241, 131489289, 135983681, 140592321, 145317129, 150160041, + 155123009, 160208001, 165417001, 170752009, 176215041, 181808129, 187533321, + 193392681, 199388289, 205522241, 211796649, 218213641, 224775361, 231483969, + 238341641, 245350569, 252512961, 259831041, 267307049, 274943241, 282741889, + 290705281, 298835721, 307135529, 315607041, 324252609, 333074601, 342075401, + 351257409, 360623041, 370174729, 379914921, 389846081, 399970689, 410291241, + 420810249, 431530241, 442453761, 453583369, 464921641, 476471169, 488234561, + 500214441, 512413449, 524834241, 537479489, 550351881, 563454121, 576788929, + 590359041, 604167209, 618216201, 632508801, +#if defined(CUSTOM_MODES) + /*...208:*/ + 647047809, 661836041, 676876329, 692171521, 707724481, 723538089, 739615241, + 755958849, 772571841, 789457161, 806617769, 824056641, 841776769, 859781161, + 878072841, 896654849, 915530241, 934702089, 954173481, 973947521, 994027329, + 1014416041, 1035116809, 1056132801, 1077467201, 1099123209, 1121104041, + 1143412929, 1166053121, 1189027881, 1212340489, 1235994241, +#endif + /*N=6, K=6...96:*/ + 1683, 3653, 7183, 13073, 22363, 36365, 56695, 85305, 124515, 177045, 246047, + 335137, 448427, 590557, 766727, 982729, 1244979, 1560549, 1937199, 2383409, + 2908411, 3522221, 4235671, 5060441, 6009091, 7095093, 8332863, 9737793, + 11326283, 13115773, 15124775, 17372905, 19880915, 22670725, 25765455, + 29189457, 32968347, 37129037, 41699767, 46710137, 52191139, 58175189, + 64696159, 71789409, 79491819, 87841821, 96879431, 106646281, 117185651, + 128542501, 140763503, 153897073, 167993403, 183104493, 199284183, 216588185, + 235074115, 254801525, 275831935, 298228865, 322057867, 347386557, 374284647, + 402823977, 433078547, 465124549, 499040399, 534906769, 572806619, 612825229, + 655050231, 699571641, 746481891, 795875861, 847850911, 902506913, 959946283, + 1020274013, 1083597703, 1150027593, 1219676595, 1292660325, 1369097135, + 1449108145, 1532817275, 1620351277, 1711839767, 1807415257, 1907213187, + 2011371957, 2120032959, +#if defined(CUSTOM_MODES) + /*...109:*/ + 2233340609U, 2351442379U, 2474488829U, 2602633639U, 2736033641U, 2874848851U, + 3019242501U, 3169381071U, 3325434321U, 3487575323U, 3655980493U, 3830829623U, + 4012305913U, +#endif + /*N=7, K=7...54*/ + 8989, 19825, 40081, 75517, 134245, 227305, 369305, 579125, 880685, 1303777, + 1884961, 2668525, 3707509, 5064793, 6814249, 9041957, 11847485, 15345233, + 19665841, 24957661, 31388293, 39146185, 48442297, 59511829, 72616013, + 88043969, 106114625, 127178701, 151620757, 179861305, 212358985, 249612805, + 292164445, 340600625, 395555537, 457713341, 527810725, 606639529, 695049433, + 793950709, 904317037, 1027188385, 1163673953, 1314955181, 1482288821, + 1667010073, 1870535785, 2094367717, +#if defined(CUSTOM_MODES) + /*...60:*/ + 2340095869U, 2609401873U, 2904062449U, 3225952925U, 3577050821U, 3959439497U, +#endif + /*N=8, K=8...37*/ + 48639, 108545, 224143, 433905, 795455, 1392065, 2340495, 3800305, 5984767, + 9173505, 13726991, 20103025, 28875327, 40754369, 56610575, 77500017, + 104692735, 139703809, 184327311, 240673265, 311207743, 398796225, 506750351, + 638878193, 799538175, 993696769, 1226990095, 1505789553, 1837271615, + 2229491905U, +#if defined(CUSTOM_MODES) + /*...40:*/ + 2691463695U, 3233240945U, 3866006015U, +#endif + /*N=9, K=9...28:*/ + 265729, 598417, 1256465, 2485825, 4673345, 8405905, 14546705, 24331777, + 39490049, 62390545, 96220561, 145198913, 214828609, 312193553, 446304145, + 628496897, 872893441, 1196924561, 1621925137, 2173806145U, +#if defined(CUSTOM_MODES) + /*...29:*/ + 2883810113U, +#endif + /*N=10, K=10...24:*/ + 1462563, 3317445, 7059735, 14218905, 27298155, 50250765, 89129247, 152951073, + 254831667, 413442773, 654862247, 1014889769, 1541911931, 2300409629U, + 3375210671U, + /*N=11, K=11...19:*/ + 8097453, 18474633, 39753273, 81270333, 158819253, 298199265, 540279585, + 948062325, 1616336765, +#if defined(CUSTOM_MODES) + /*...20:*/ + 2684641785U, +#endif + /*N=12, K=12...18:*/ + 45046719, 103274625, 224298231, 464387817, 921406335, 1759885185, + 3248227095U, + /*N=13, K=13...16:*/ + 251595969, 579168825, 1267854873, 2653649025U, + /*N=14, K=14:*/ + 1409933619 +}; + +#if defined(CUSTOM_MODES) +static const opus_uint32 *const CELT_PVQ_U_ROW[15]={ + CELT_PVQ_U_DATA+ 0,CELT_PVQ_U_DATA+ 208,CELT_PVQ_U_DATA+ 415, + CELT_PVQ_U_DATA+ 621,CELT_PVQ_U_DATA+ 826,CELT_PVQ_U_DATA+1030, + CELT_PVQ_U_DATA+1233,CELT_PVQ_U_DATA+1336,CELT_PVQ_U_DATA+1389, + CELT_PVQ_U_DATA+1421,CELT_PVQ_U_DATA+1441,CELT_PVQ_U_DATA+1455, + CELT_PVQ_U_DATA+1464,CELT_PVQ_U_DATA+1470,CELT_PVQ_U_DATA+1473 +}; +#else +static const opus_uint32 *const CELT_PVQ_U_ROW[15]={ + CELT_PVQ_U_DATA+ 0,CELT_PVQ_U_DATA+ 176,CELT_PVQ_U_DATA+ 351, + CELT_PVQ_U_DATA+ 525,CELT_PVQ_U_DATA+ 698,CELT_PVQ_U_DATA+ 870, + CELT_PVQ_U_DATA+1041,CELT_PVQ_U_DATA+1131,CELT_PVQ_U_DATA+1178, + CELT_PVQ_U_DATA+1207,CELT_PVQ_U_DATA+1226,CELT_PVQ_U_DATA+1240, + CELT_PVQ_U_DATA+1248,CELT_PVQ_U_DATA+1254,CELT_PVQ_U_DATA+1257 +}; +#endif + +#if defined(CUSTOM_MODES) +void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){ + int k; + /*_maxk==0 => there's nothing to do.*/ + celt_assert(_maxk>0); + _bits[0]=0; + for(k=1;k<=_maxk;k++)_bits[k]=log2_frac(CELT_PVQ_V(_n,k),_frac); +} +#endif + +static opus_uint32 icwrs(int _n,const int *_y){ + opus_uint32 i; + int j; + int k; + celt_assert(_n>=2); + j=_n-1; + i=_y[j]<0; + k=abs(_y[j]); + do{ + j--; + i+=CELT_PVQ_U(_n-j,k); + k+=abs(_y[j]); + if(_y[j]<0)i+=CELT_PVQ_U(_n-j,k+1); + } + while(j>0); + return i; +} + +void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){ + celt_assert(_k>0); + ec_enc_uint(_enc,icwrs(_n,_y),CELT_PVQ_V(_n,_k)); +} + +static void cwrsi(int _n,int _k,opus_uint32 _i,int *_y){ + opus_uint32 p; + int s; + int k0; + celt_assert(_k>0); + celt_assert(_n>1); + while(_n>2){ + opus_uint32 q; + /*Lots of pulses case:*/ + if(_k>=_n){ + const opus_uint32 *row; + row=CELT_PVQ_U_ROW[_n]; + /*Are the pulses in this dimension negative?*/ + p=row[_k+1]; + s=-(_i>=p); + _i-=p&s; + /*Count how many pulses were placed in this dimension.*/ + k0=_k; + q=row[_n]; + if(q>_i){ + celt_assert(p>q); + _k=_n; + do p=CELT_PVQ_U_ROW[--_k][_n]; + while(p>_i); + } + else for(p=row[_k];p>_i;p=row[_k])_k--; + _i-=p; + *_y++=(k0-_k+s)^s; + } + /*Lots of dimensions case:*/ + else{ + /*Are there any pulses in this dimension at all?*/ + p=CELT_PVQ_U_ROW[_k][_n]; + q=CELT_PVQ_U_ROW[_k+1][_n]; + if(p<=_i&&_i=q); + _i-=q&s; + /*Count how many pulses were placed in this dimension.*/ + k0=_k; + do p=CELT_PVQ_U_ROW[--_k][_n]; + while(p>_i); + _i-=p; + *_y++=(k0-_k+s)^s; + } + } + _n--; + } + /*_n==2*/ + p=2*_k+1; + s=-(_i>=p); + _i-=p&s; + k0=_k; + _k=(_i+1)>>1; + if(_k)_i-=2*_k-1; + *_y++=(k0-_k+s)^s; + /*_n==1*/ + s=-(int)_i; + *_y=(_k+s)^s; +} + +void decode_pulses(int *_y,int _n,int _k,ec_dec *_dec){ + cwrsi(_n,_k,ec_dec_uint(_dec,CELT_PVQ_V(_n,_k)),_y); +} + +#else /* SMALL_FOOTPRINT */ + +/*Computes the next row/column of any recurrence that obeys the relation + u[i][j]=u[i-1][j]+u[i][j-1]+u[i-1][j-1]. + _ui0 is the base case for the new row/column.*/ +static OPUS_INLINE void unext(opus_uint32 *_ui,unsigned _len,opus_uint32 _ui0){ + opus_uint32 ui1; + unsigned j; + /*This do-while will overrun the array if we don't have storage for at least + 2 values.*/ + j=1; do { + ui1=UADD32(UADD32(_ui[j],_ui[j-1]),_ui0); + _ui[j-1]=_ui0; + _ui0=ui1; + } while (++j<_len); + _ui[j-1]=_ui0; +} + +/*Computes the previous row/column of any recurrence that obeys the relation + u[i-1][j]=u[i][j]-u[i][j-1]-u[i-1][j-1]. + _ui0 is the base case for the new row/column.*/ +static OPUS_INLINE void uprev(opus_uint32 *_ui,unsigned _n,opus_uint32 _ui0){ + opus_uint32 ui1; + unsigned j; + /*This do-while will overrun the array if we don't have storage for at least + 2 values.*/ + j=1; do { + ui1=USUB32(USUB32(_ui[j],_ui[j-1]),_ui0); + _ui[j-1]=_ui0; + _ui0=ui1; + } while (++j<_n); + _ui[j-1]=_ui0; +} + +/*Compute V(_n,_k), as well as U(_n,0..._k+1). + _u: On exit, _u[i] contains U(_n,i) for i in [0..._k+1].*/ +static opus_uint32 ncwrs_urow(unsigned _n,unsigned _k,opus_uint32 *_u){ + opus_uint32 um2; + unsigned len; + unsigned k; + len=_k+2; + /*We require storage at least 3 values (e.g., _k>0).*/ + celt_assert(len>=3); + _u[0]=0; + _u[1]=um2=1; + /*If _n==0, _u[0] should be 1 and the rest should be 0.*/ + /*If _n==1, _u[i] should be 1 for i>1.*/ + celt_assert(_n>=2); + /*If _k==0, the following do-while loop will overflow the buffer.*/ + celt_assert(_k>0); + k=2; + do _u[k]=(k<<1)-1; + while(++k0); + j=0; + do{ + opus_uint32 p; + int s; + int yj; + p=_u[_k+1]; + s=-(_i>=p); + _i-=p&s; + yj=_k; + p=_u[_k]; + while(p>_i)p=_u[--_k]; + _i-=p; + yj-=_k; + _y[j]=(yj+s)^s; + uprev(_u,_k+2,0); + } + while(++j<_n); +} + +/*Returns the index of the given combination of K elements chosen from a set + of size 1 with associated sign bits. + _y: The vector of pulses, whose sum of absolute values is K. + _k: Returns K.*/ +static OPUS_INLINE opus_uint32 icwrs1(const int *_y,int *_k){ + *_k=abs(_y[0]); + return _y[0]<0; +} + +/*Returns the index of the given combination of K elements chosen from a set + of size _n with associated sign bits. + _y: The vector of pulses, whose sum of absolute values must be _k. + _nc: Returns V(_n,_k).*/ +static OPUS_INLINE opus_uint32 icwrs(int _n,int _k,opus_uint32 *_nc,const int *_y, + opus_uint32 *_u){ + opus_uint32 i; + int j; + int k; + /*We can't unroll the first two iterations of the loop unless _n>=2.*/ + celt_assert(_n>=2); + _u[0]=0; + for(k=1;k<=_k+1;k++)_u[k]=(k<<1)-1; + i=icwrs1(_y+_n-1,&k); + j=_n-2; + i+=_u[k]; + k+=abs(_y[j]); + if(_y[j]<0)i+=_u[k+1]; + while(j-->0){ + unext(_u,_k+2,0); + i+=_u[k]; + k+=abs(_y[j]); + if(_y[j]<0)i+=_u[k+1]; + } + *_nc=_u[k]+_u[k+1]; + return i; +} + +#ifdef CUSTOM_MODES +void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){ + int k; + /*_maxk==0 => there's nothing to do.*/ + celt_assert(_maxk>0); + _bits[0]=0; + if (_n==1) + { + for (k=1;k<=_maxk;k++) + _bits[k] = 1<<_frac; + } + else { + VARDECL(opus_uint32,u); + SAVE_STACK; + ALLOC(u,_maxk+2U,opus_uint32); + ncwrs_urow(_n,_maxk,u); + for(k=1;k<=_maxk;k++) + _bits[k]=log2_frac(u[k]+u[k+1],_frac); + RESTORE_STACK; + } +} +#endif /* CUSTOM_MODES */ + +void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){ + opus_uint32 i; + VARDECL(opus_uint32,u); + opus_uint32 nc; + SAVE_STACK; + celt_assert(_k>0); + ALLOC(u,_k+2U,opus_uint32); + i=icwrs(_n,_k,&nc,_y,u); + ec_enc_uint(_enc,i,nc); + RESTORE_STACK; +} + +void decode_pulses(int *_y,int _n,int _k,ec_dec *_dec){ + VARDECL(opus_uint32,u); + SAVE_STACK; + celt_assert(_k>0); + ALLOC(u,_k+2U,opus_uint32); + cwrsi(_n,_k,ec_dec_uint(_dec,ncwrs_urow(_n,_k,u)),_y,u); + RESTORE_STACK; +} + +#endif /* SMALL_FOOTPRINT */ diff --git a/TelegramClient.Opus/opus/celt/cwrs.h b/TelegramClient.Opus/opus/celt/cwrs.h new file mode 100755 index 0000000..7dfbd07 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/cwrs.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Copyright (c) 2007-2009 Timothy B. Terriberry + Written by Timothy B. Terriberry and Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef CWRS_H +#define CWRS_H + +#include "arch.h" +#include "stack_alloc.h" +#include "entenc.h" +#include "entdec.h" + +#ifdef CUSTOM_MODES +int log2_frac(opus_uint32 val, int frac); +#endif + +void get_required_bits(opus_int16 *bits, int N, int K, int frac); + +void encode_pulses(const int *_y, int N, int K, ec_enc *enc); + +void decode_pulses(int *_y, int N, int K, ec_dec *dec); + +#endif /* CWRS_H */ diff --git a/TelegramClient.Opus/opus/celt/ecintrin.h b/TelegramClient.Opus/opus/celt/ecintrin.h new file mode 100755 index 0000000..2263cff --- /dev/null +++ b/TelegramClient.Opus/opus/celt/ecintrin.h @@ -0,0 +1,87 @@ +/* Copyright (c) 2003-2008 Timothy B. Terriberry + Copyright (c) 2008 Xiph.Org Foundation */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +/*Some common macros for potential platform-specific optimization.*/ +#include "opus_types.h" +#include +#include +#include "arch.h" +#if !defined(_ecintrin_H) +# define _ecintrin_H (1) + +/*Some specific platforms may have optimized intrinsic or OPUS_INLINE assembly + versions of these functions which can substantially improve performance. + We define macros for them to allow easy incorporation of these non-ANSI + features.*/ + +/*Modern gcc (4.x) can compile the naive versions of min and max with cmov if + given an appropriate architecture, but the branchless bit-twiddling versions + are just as fast, and do not require any special target architecture. + Earlier gcc versions (3.x) compiled both code to the same assembly + instructions, because of the way they represented ((_b)>(_a)) internally.*/ +# define EC_MINI(_a,_b) ((_a)+(((_b)-(_a))&-((_b)<(_a)))) + +/*Count leading zeros. + This macro should only be used for implementing ec_ilog(), if it is defined. + All other code should use EC_ILOG() instead.*/ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +# include +/*In _DEBUG mode this is not an intrinsic by default.*/ +# pragma intrinsic(_BitScanReverse) + +static __inline int ec_bsr(unsigned long _x){ + unsigned long ret; + _BitScanReverse(&ret,_x); + return (int)ret; +} +# define EC_CLZ0 (1) +# define EC_CLZ(_x) (-ec_bsr(_x)) +#elif defined(ENABLE_TI_DSPLIB) +# include "dsplib.h" +# define EC_CLZ0 (31) +# define EC_CLZ(_x) (_lnorm(_x)) +#elif __GNUC_PREREQ(3,4) +# if INT_MAX>=2147483647 +# define EC_CLZ0 ((int)sizeof(unsigned)*CHAR_BIT) +# define EC_CLZ(_x) (__builtin_clz(_x)) +# elif LONG_MAX>=2147483647L +# define EC_CLZ0 ((int)sizeof(unsigned long)*CHAR_BIT) +# define EC_CLZ(_x) (__builtin_clzl(_x)) +# endif +#endif + +#if defined(EC_CLZ) +/*Note that __builtin_clz is not defined when _x==0, according to the gcc + documentation (and that of the BSR instruction that implements it on x86). + The majority of the time we can never pass it zero. + When we need to, it can be special cased.*/ +# define EC_ILOG(_x) (EC_CLZ0-EC_CLZ(_x)) +#else +int ec_ilog(opus_uint32 _v); +# define EC_ILOG(_x) (ec_ilog(_x)) +#endif +#endif diff --git a/TelegramClient.Opus/opus/celt/entcode.c b/TelegramClient.Opus/opus/celt/entcode.c new file mode 100755 index 0000000..fa5d7c7 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/entcode.c @@ -0,0 +1,93 @@ +/* Copyright (c) 2001-2011 Timothy B. Terriberry +*/ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "entcode.h" +#include "arch.h" + +#if !defined(EC_CLZ) +/*This is a fallback for systems where we don't know how to access + a BSR or CLZ instruction (see ecintrin.h). + If you are optimizing Opus on a new platform and it has a native CLZ or + BZR (e.g. cell, MIPS, x86, etc) then making it available to Opus will be + an easy performance win.*/ +int ec_ilog(opus_uint32 _v){ + /*On a Pentium M, this branchless version tested as the fastest on + 1,000,000,000 random 32-bit integers, edging out a similar version with + branches, and a 256-entry LUT version.*/ + int ret; + int m; + ret=!!_v; + m=!!(_v&0xFFFF0000)<<4; + _v>>=m; + ret|=m; + m=!!(_v&0xFF00)<<3; + _v>>=m; + ret|=m; + m=!!(_v&0xF0)<<2; + _v>>=m; + ret|=m; + m=!!(_v&0xC)<<1; + _v>>=m; + ret|=m; + ret+=!!(_v&0x2); + return ret; +} +#endif + +opus_uint32 ec_tell_frac(ec_ctx *_this){ + opus_uint32 nbits; + opus_uint32 r; + int l; + int i; + /*To handle the non-integral number of bits still left in the encoder/decoder + state, we compute the worst-case number of bits of val that must be + encoded to ensure that the value is inside the range for any possible + subsequent bits. + The computation here is independent of val itself (the decoder does not + even track that value), even though the real number of bits used after + ec_enc_done() may be 1 smaller if rng is a power of two and the + corresponding trailing bits of val are all zeros. + If we did try to track that special case, then coding a value with a + probability of 1/(1<nbits_total<rng); + r=_this->rng>>(l-16); + for(i=BITRES;i-->0;){ + int b; + r=r*r>>15; + b=(int)(r>>16); + l=l<<1|b; + r>>=b; + } + return nbits-l; +} diff --git a/TelegramClient.Opus/opus/celt/entcode.h b/TelegramClient.Opus/opus/celt/entcode.h new file mode 100755 index 0000000..dd13e49 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/entcode.h @@ -0,0 +1,117 @@ +/* Copyright (c) 2001-2011 Timothy B. Terriberry + Copyright (c) 2008-2009 Xiph.Org Foundation */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#include "opus_types.h" +#include "opus_defines.h" + +#if !defined(_entcode_H) +# define _entcode_H (1) +# include +# include +# include "ecintrin.h" + +/*OPT: ec_window must be at least 32 bits, but if you have fast arithmetic on a + larger type, you can speed up the decoder by using it here.*/ +typedef opus_uint32 ec_window; +typedef struct ec_ctx ec_ctx; +typedef struct ec_ctx ec_enc; +typedef struct ec_ctx ec_dec; + +# define EC_WINDOW_SIZE ((int)sizeof(ec_window)*CHAR_BIT) + +/*The number of bits to use for the range-coded part of unsigned integers.*/ +# define EC_UINT_BITS (8) + +/*The resolution of fractional-precision bit usage measurements, i.e., + 3 => 1/8th bits.*/ +# define BITRES 3 + +/*The entropy encoder/decoder context. + We use the same structure for both, so that common functions like ec_tell() + can be used on either one.*/ +struct ec_ctx{ + /*Buffered input/output.*/ + unsigned char *buf; + /*The size of the buffer.*/ + opus_uint32 storage; + /*The offset at which the last byte containing raw bits was read/written.*/ + opus_uint32 end_offs; + /*Bits that will be read from/written at the end.*/ + ec_window end_window; + /*Number of valid bits in end_window.*/ + int nend_bits; + /*The total number of whole bits read/written. + This does not include partial bits currently in the range coder.*/ + int nbits_total; + /*The offset at which the next range coder byte will be read/written.*/ + opus_uint32 offs; + /*The number of values in the current range.*/ + opus_uint32 rng; + /*In the decoder: the difference between the top of the current range and + the input value, minus one. + In the encoder: the low end of the current range.*/ + opus_uint32 val; + /*In the decoder: the saved normalization factor from ec_decode(). + In the encoder: the number of oustanding carry propagating symbols.*/ + opus_uint32 ext; + /*A buffered input/output symbol, awaiting carry propagation.*/ + int rem; + /*Nonzero if an error occurred.*/ + int error; +}; + +static OPUS_INLINE opus_uint32 ec_range_bytes(ec_ctx *_this){ + return _this->offs; +} + +static OPUS_INLINE unsigned char *ec_get_buffer(ec_ctx *_this){ + return _this->buf; +} + +static OPUS_INLINE int ec_get_error(ec_ctx *_this){ + return _this->error; +} + +/*Returns the number of bits "used" by the encoded or decoded symbols so far. + This same number can be computed in either the encoder or the decoder, and is + suitable for making coding decisions. + Return: The number of bits. + This will always be slightly larger than the exact value (e.g., all + rounding error is in the positive direction).*/ +static OPUS_INLINE int ec_tell(ec_ctx *_this){ + return _this->nbits_total-EC_ILOG(_this->rng); +} + +/*Returns the number of bits "used" by the encoded or decoded symbols so far. + This same number can be computed in either the encoder or the decoder, and is + suitable for making coding decisions. + Return: The number of bits scaled by 2**BITRES. + This will always be slightly larger than the exact value (e.g., all + rounding error is in the positive direction).*/ +opus_uint32 ec_tell_frac(ec_ctx *_this); + +#endif diff --git a/TelegramClient.Opus/opus/celt/entdec.c b/TelegramClient.Opus/opus/celt/entdec.c new file mode 100755 index 0000000..3c26468 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/entdec.c @@ -0,0 +1,245 @@ +/* Copyright (c) 2001-2011 Timothy B. Terriberry + Copyright (c) 2008-2009 Xiph.Org Foundation */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "os_support.h" +#include "arch.h" +#include "entdec.h" +#include "mfrngcod.h" + +/*A range decoder. + This is an entropy decoder based upon \cite{Mar79}, which is itself a + rediscovery of the FIFO arithmetic code introduced by \cite{Pas76}. + It is very similar to arithmetic encoding, except that encoding is done with + digits in any base, instead of with bits, and so it is faster when using + larger bases (i.e.: a byte). + The author claims an average waste of $\frac{1}{2}\log_b(2b)$ bits, where $b$ + is the base, longer than the theoretical optimum, but to my knowledge there + is no published justification for this claim. + This only seems true when using near-infinite precision arithmetic so that + the process is carried out with no rounding errors. + + An excellent description of implementation details is available at + http://www.arturocampos.com/ac_range.html + A recent work \cite{MNW98} which proposes several changes to arithmetic + encoding for efficiency actually re-discovers many of the principles + behind range encoding, and presents a good theoretical analysis of them. + + End of stream is handled by writing out the smallest number of bits that + ensures that the stream will be correctly decoded regardless of the value of + any subsequent bits. + ec_tell() can be used to determine how many bits were needed to decode + all the symbols thus far; other data can be packed in the remaining bits of + the input buffer. + @PHDTHESIS{Pas76, + author="Richard Clark Pasco", + title="Source coding algorithms for fast data compression", + school="Dept. of Electrical Engineering, Stanford University", + address="Stanford, CA", + month=May, + year=1976 + } + @INPROCEEDINGS{Mar79, + author="Martin, G.N.N.", + title="Range encoding: an algorithm for removing redundancy from a digitised + message", + booktitle="Video & Data Recording Conference", + year=1979, + address="Southampton", + month=Jul + } + @ARTICLE{MNW98, + author="Alistair Moffat and Radford Neal and Ian H. Witten", + title="Arithmetic Coding Revisited", + journal="{ACM} Transactions on Information Systems", + year=1998, + volume=16, + number=3, + pages="256--294", + month=Jul, + URL="http://www.stanford.edu/class/ee398a/handouts/papers/Moffat98ArithmCoding.pdf" + }*/ + +static int ec_read_byte(ec_dec *_this){ + return _this->offs<_this->storage?_this->buf[_this->offs++]:0; +} + +static int ec_read_byte_from_end(ec_dec *_this){ + return _this->end_offs<_this->storage? + _this->buf[_this->storage-++(_this->end_offs)]:0; +} + +/*Normalizes the contents of val and rng so that rng lies entirely in the + high-order symbol.*/ +static void ec_dec_normalize(ec_dec *_this){ + /*If the range is too small, rescale it and input some bits.*/ + while(_this->rng<=EC_CODE_BOT){ + int sym; + _this->nbits_total+=EC_SYM_BITS; + _this->rng<<=EC_SYM_BITS; + /*Use up the remaining bits from our last symbol.*/ + sym=_this->rem; + /*Read the next value from the input.*/ + _this->rem=ec_read_byte(_this); + /*Take the rest of the bits we need from this new symbol.*/ + sym=(sym<rem)>>(EC_SYM_BITS-EC_CODE_EXTRA); + /*And subtract them from val, capped to be less than EC_CODE_TOP.*/ + _this->val=((_this->val<buf=_buf; + _this->storage=_storage; + _this->end_offs=0; + _this->end_window=0; + _this->nend_bits=0; + /*This is the offset from which ec_tell() will subtract partial bits. + The final value after the ec_dec_normalize() call will be the same as in + the encoder, but we have to compensate for the bits that are added there.*/ + _this->nbits_total=EC_CODE_BITS+1 + -((EC_CODE_BITS-EC_CODE_EXTRA)/EC_SYM_BITS)*EC_SYM_BITS; + _this->offs=0; + _this->rng=1U<rem=ec_read_byte(_this); + _this->val=_this->rng-1-(_this->rem>>(EC_SYM_BITS-EC_CODE_EXTRA)); + _this->error=0; + /*Normalize the interval.*/ + ec_dec_normalize(_this); +} + +unsigned ec_decode(ec_dec *_this,unsigned _ft){ + unsigned s; + _this->ext=_this->rng/_ft; + s=(unsigned)(_this->val/_this->ext); + return _ft-EC_MINI(s+1,_ft); +} + +unsigned ec_decode_bin(ec_dec *_this,unsigned _bits){ + unsigned s; + _this->ext=_this->rng>>_bits; + s=(unsigned)(_this->val/_this->ext); + return (1U<<_bits)-EC_MINI(s+1U,1U<<_bits); +} + +void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft){ + opus_uint32 s; + s=IMUL32(_this->ext,_ft-_fh); + _this->val-=s; + _this->rng=_fl>0?IMUL32(_this->ext,_fh-_fl):_this->rng-s; + ec_dec_normalize(_this); +} + +/*The probability of having a "one" is 1/(1<<_logp).*/ +int ec_dec_bit_logp(ec_dec *_this,unsigned _logp){ + opus_uint32 r; + opus_uint32 d; + opus_uint32 s; + int ret; + r=_this->rng; + d=_this->val; + s=r>>_logp; + ret=dval=d-s; + _this->rng=ret?s:r-s; + ec_dec_normalize(_this); + return ret; +} + +int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb){ + opus_uint32 r; + opus_uint32 d; + opus_uint32 s; + opus_uint32 t; + int ret; + s=_this->rng; + d=_this->val; + r=s>>_ftb; + ret=-1; + do{ + t=s; + s=IMUL32(r,_icdf[++ret]); + } + while(dval=d-s; + _this->rng=t-s; + ec_dec_normalize(_this); + return ret; +} + +opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft){ + unsigned ft; + unsigned s; + int ftb; + /*In order to optimize EC_ILOG(), it is undefined for the value 0.*/ + celt_assert(_ft>1); + _ft--; + ftb=EC_ILOG(_ft); + if(ftb>EC_UINT_BITS){ + opus_uint32 t; + ftb-=EC_UINT_BITS; + ft=(unsigned)(_ft>>ftb)+1; + s=ec_decode(_this,ft); + ec_dec_update(_this,s,s+1,ft); + t=(opus_uint32)s<error=1; + return _ft; + } + else{ + _ft++; + s=ec_decode(_this,(unsigned)_ft); + ec_dec_update(_this,s,s+1,(unsigned)_ft); + return s; + } +} + +opus_uint32 ec_dec_bits(ec_dec *_this,unsigned _bits){ + ec_window window; + int available; + opus_uint32 ret; + window=_this->end_window; + available=_this->nend_bits; + if((unsigned)available<_bits){ + do{ + window|=(ec_window)ec_read_byte_from_end(_this)<>=_bits; + available-=_bits; + _this->end_window=window; + _this->nend_bits=available; + _this->nbits_total+=_bits; + return ret; +} diff --git a/TelegramClient.Opus/opus/celt/entdec.h b/TelegramClient.Opus/opus/celt/entdec.h new file mode 100755 index 0000000..d8ab318 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/entdec.h @@ -0,0 +1,100 @@ +/* Copyright (c) 2001-2011 Timothy B. Terriberry + Copyright (c) 2008-2009 Xiph.Org Foundation */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#if !defined(_entdec_H) +# define _entdec_H (1) +# include +# include "entcode.h" + +/*Initializes the decoder. + _buf: The input buffer to use. + Return: 0 on success, or a negative value on error.*/ +void ec_dec_init(ec_dec *_this,unsigned char *_buf,opus_uint32 _storage); + +/*Calculates the cumulative frequency for the next symbol. + This can then be fed into the probability model to determine what that + symbol is, and the additional frequency information required to advance to + the next symbol. + This function cannot be called more than once without a corresponding call to + ec_dec_update(), or decoding will not proceed correctly. + _ft: The total frequency of the symbols in the alphabet the next symbol was + encoded with. + Return: A cumulative frequency representing the encoded symbol. + If the cumulative frequency of all the symbols before the one that + was encoded was fl, and the cumulative frequency of all the symbols + up to and including the one encoded is fh, then the returned value + will fall in the range [fl,fh).*/ +unsigned ec_decode(ec_dec *_this,unsigned _ft); + +/*Equivalent to ec_decode() with _ft==1<<_bits.*/ +unsigned ec_decode_bin(ec_dec *_this,unsigned _bits); + +/*Advance the decoder past the next symbol using the frequency information the + symbol was encoded with. + Exactly one call to ec_decode() must have been made so that all necessary + intermediate calculations are performed. + _fl: The cumulative frequency of all symbols that come before the symbol + decoded. + _fh: The cumulative frequency of all symbols up to and including the symbol + decoded. + Together with _fl, this defines the range [_fl,_fh) in which the value + returned above must fall. + _ft: The total frequency of the symbols in the alphabet the symbol decoded + was encoded in. + This must be the same as passed to the preceding call to ec_decode().*/ +void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft); + +/* Decode a bit that has a 1/(1<<_logp) probability of being a one */ +int ec_dec_bit_logp(ec_dec *_this,unsigned _logp); + +/*Decodes a symbol given an "inverse" CDF table. + No call to ec_dec_update() is necessary after this call. + _icdf: The "inverse" CDF, such that symbol s falls in the range + [s>0?ft-_icdf[s-1]:0,ft-_icdf[s]), where ft=1<<_ftb. + The values must be monotonically non-increasing, and the last value + must be 0. + _ftb: The number of bits of precision in the cumulative distribution. + Return: The decoded symbol s.*/ +int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb); + +/*Extracts a raw unsigned integer with a non-power-of-2 range from the stream. + The bits must have been encoded with ec_enc_uint(). + No call to ec_dec_update() is necessary after this call. + _ft: The number of integers that can be decoded (one more than the max). + This must be at least one, and no more than 2**32-1. + Return: The decoded bits.*/ +opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft); + +/*Extracts a sequence of raw bits from the stream. + The bits must have been encoded with ec_enc_bits(). + No call to ec_dec_update() is necessary after this call. + _ftb: The number of bits to extract. + This must be between 0 and 25, inclusive. + Return: The decoded bits.*/ +opus_uint32 ec_dec_bits(ec_dec *_this,unsigned _ftb); + +#endif diff --git a/TelegramClient.Opus/opus/celt/entenc.c b/TelegramClient.Opus/opus/celt/entenc.c new file mode 100755 index 0000000..a7e34ec --- /dev/null +++ b/TelegramClient.Opus/opus/celt/entenc.c @@ -0,0 +1,294 @@ +/* Copyright (c) 2001-2011 Timothy B. Terriberry + Copyright (c) 2008-2009 Xiph.Org Foundation */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif +#include "os_support.h" +#include "arch.h" +#include "entenc.h" +#include "mfrngcod.h" + +/*A range encoder. + See entdec.c and the references for implementation details \cite{Mar79,MNW98}. + + @INPROCEEDINGS{Mar79, + author="Martin, G.N.N.", + title="Range encoding: an algorithm for removing redundancy from a digitised + message", + booktitle="Video \& Data Recording Conference", + year=1979, + address="Southampton", + month=Jul + } + @ARTICLE{MNW98, + author="Alistair Moffat and Radford Neal and Ian H. Witten", + title="Arithmetic Coding Revisited", + journal="{ACM} Transactions on Information Systems", + year=1998, + volume=16, + number=3, + pages="256--294", + month=Jul, + URL="http://www.stanford.edu/class/ee398/handouts/papers/Moffat98ArithmCoding.pdf" + }*/ + +static int ec_write_byte(ec_enc *_this,unsigned _value){ + if(_this->offs+_this->end_offs>=_this->storage)return -1; + _this->buf[_this->offs++]=(unsigned char)_value; + return 0; +} + +static int ec_write_byte_at_end(ec_enc *_this,unsigned _value){ + if(_this->offs+_this->end_offs>=_this->storage)return -1; + _this->buf[_this->storage-++(_this->end_offs)]=(unsigned char)_value; + return 0; +} + +/*Outputs a symbol, with a carry bit. + If there is a potential to propagate a carry over several symbols, they are + buffered until it can be determined whether or not an actual carry will + occur. + If the counter for the buffered symbols overflows, then the stream becomes + undecodable. + This gives a theoretical limit of a few billion symbols in a single packet on + 32-bit systems. + The alternative is to truncate the range in order to force a carry, but + requires similar carry tracking in the decoder, needlessly slowing it down.*/ +static void ec_enc_carry_out(ec_enc *_this,int _c){ + if(_c!=EC_SYM_MAX){ + /*No further carry propagation possible, flush buffer.*/ + int carry; + carry=_c>>EC_SYM_BITS; + /*Don't output a byte on the first write. + This compare should be taken care of by branch-prediction thereafter.*/ + if(_this->rem>=0)_this->error|=ec_write_byte(_this,_this->rem+carry); + if(_this->ext>0){ + unsigned sym; + sym=(EC_SYM_MAX+carry)&EC_SYM_MAX; + do _this->error|=ec_write_byte(_this,sym); + while(--(_this->ext)>0); + } + _this->rem=_c&EC_SYM_MAX; + } + else _this->ext++; +} + +static void ec_enc_normalize(ec_enc *_this){ + /*If the range is too small, output some bits and rescale it.*/ + while(_this->rng<=EC_CODE_BOT){ + ec_enc_carry_out(_this,(int)(_this->val>>EC_CODE_SHIFT)); + /*Move the next-to-high-order symbol into the high-order position.*/ + _this->val=(_this->val<rng<<=EC_SYM_BITS; + _this->nbits_total+=EC_SYM_BITS; + } +} + +void ec_enc_init(ec_enc *_this,unsigned char *_buf,opus_uint32 _size){ + _this->buf=_buf; + _this->end_offs=0; + _this->end_window=0; + _this->nend_bits=0; + /*This is the offset from which ec_tell() will subtract partial bits.*/ + _this->nbits_total=EC_CODE_BITS+1; + _this->offs=0; + _this->rng=EC_CODE_TOP; + _this->rem=-1; + _this->val=0; + _this->ext=0; + _this->storage=_size; + _this->error=0; +} + +void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){ + opus_uint32 r; + r=_this->rng/_ft; + if(_fl>0){ + _this->val+=_this->rng-IMUL32(r,(_ft-_fl)); + _this->rng=IMUL32(r,(_fh-_fl)); + } + else _this->rng-=IMUL32(r,(_ft-_fh)); + ec_enc_normalize(_this); +} + +void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _bits){ + opus_uint32 r; + r=_this->rng>>_bits; + if(_fl>0){ + _this->val+=_this->rng-IMUL32(r,((1U<<_bits)-_fl)); + _this->rng=IMUL32(r,(_fh-_fl)); + } + else _this->rng-=IMUL32(r,((1U<<_bits)-_fh)); + ec_enc_normalize(_this); +} + +/*The probability of having a "one" is 1/(1<<_logp).*/ +void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp){ + opus_uint32 r; + opus_uint32 s; + opus_uint32 l; + r=_this->rng; + l=_this->val; + s=r>>_logp; + r-=s; + if(_val)_this->val=l+r; + _this->rng=_val?s:r; + ec_enc_normalize(_this); +} + +void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb){ + opus_uint32 r; + r=_this->rng>>_ftb; + if(_s>0){ + _this->val+=_this->rng-IMUL32(r,_icdf[_s-1]); + _this->rng=IMUL32(r,_icdf[_s-1]-_icdf[_s]); + } + else _this->rng-=IMUL32(r,_icdf[_s]); + ec_enc_normalize(_this); +} + +void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft){ + unsigned ft; + unsigned fl; + int ftb; + /*In order to optimize EC_ILOG(), it is undefined for the value 0.*/ + celt_assert(_ft>1); + _ft--; + ftb=EC_ILOG(_ft); + if(ftb>EC_UINT_BITS){ + ftb-=EC_UINT_BITS; + ft=(_ft>>ftb)+1; + fl=(unsigned)(_fl>>ftb); + ec_encode(_this,fl,fl+1,ft); + ec_enc_bits(_this,_fl&(((opus_uint32)1<end_window; + used=_this->nend_bits; + celt_assert(_bits>0); + if(used+_bits>EC_WINDOW_SIZE){ + do{ + _this->error|=ec_write_byte_at_end(_this,(unsigned)window&EC_SYM_MAX); + window>>=EC_SYM_BITS; + used-=EC_SYM_BITS; + } + while(used>=EC_SYM_BITS); + } + window|=(ec_window)_fl<end_window=window; + _this->nend_bits=used; + _this->nbits_total+=_bits; +} + +void ec_enc_patch_initial_bits(ec_enc *_this,unsigned _val,unsigned _nbits){ + int shift; + unsigned mask; + celt_assert(_nbits<=EC_SYM_BITS); + shift=EC_SYM_BITS-_nbits; + mask=((1<<_nbits)-1)<offs>0){ + /*The first byte has been finalized.*/ + _this->buf[0]=(unsigned char)((_this->buf[0]&~mask)|_val<rem>=0){ + /*The first byte is still awaiting carry propagation.*/ + _this->rem=(_this->rem&~mask)|_val<rng<=(EC_CODE_TOP>>_nbits)){ + /*The renormalization loop has never been run.*/ + _this->val=(_this->val&~((opus_uint32)mask<error=-1; +} + +void ec_enc_shrink(ec_enc *_this,opus_uint32 _size){ + celt_assert(_this->offs+_this->end_offs<=_size); + OPUS_MOVE(_this->buf+_size-_this->end_offs, + _this->buf+_this->storage-_this->end_offs,_this->end_offs); + _this->storage=_size; +} + +void ec_enc_done(ec_enc *_this){ + ec_window window; + int used; + opus_uint32 msk; + opus_uint32 end; + int l; + /*We output the minimum number of bits that ensures that the symbols encoded + thus far will be decoded correctly regardless of the bits that follow.*/ + l=EC_CODE_BITS-EC_ILOG(_this->rng); + msk=(EC_CODE_TOP-1)>>l; + end=(_this->val+msk)&~msk; + if((end|msk)>=_this->val+_this->rng){ + l++; + msk>>=1; + end=(_this->val+msk)&~msk; + } + while(l>0){ + ec_enc_carry_out(_this,(int)(end>>EC_CODE_SHIFT)); + end=(end<rem>=0||_this->ext>0)ec_enc_carry_out(_this,0); + /*If we have buffered extra bits, flush them as well.*/ + window=_this->end_window; + used=_this->nend_bits; + while(used>=EC_SYM_BITS){ + _this->error|=ec_write_byte_at_end(_this,(unsigned)window&EC_SYM_MAX); + window>>=EC_SYM_BITS; + used-=EC_SYM_BITS; + } + /*Clear any excess space and add any remaining extra bits to the last byte.*/ + if(!_this->error){ + OPUS_CLEAR(_this->buf+_this->offs, + _this->storage-_this->offs-_this->end_offs); + if(used>0){ + /*If there's no range coder data at all, give up.*/ + if(_this->end_offs>=_this->storage)_this->error=-1; + else{ + l=-l; + /*If we've busted, don't add too many extra bits to the last byte; it + would corrupt the range coder data, and that's more important.*/ + if(_this->offs+_this->end_offs>=_this->storage&&lerror=-1; + } + _this->buf[_this->storage-_this->end_offs-1]|=(unsigned char)window; + } + } + } +} diff --git a/TelegramClient.Opus/opus/celt/entenc.h b/TelegramClient.Opus/opus/celt/entenc.h new file mode 100755 index 0000000..796bc4d --- /dev/null +++ b/TelegramClient.Opus/opus/celt/entenc.h @@ -0,0 +1,110 @@ +/* Copyright (c) 2001-2011 Timothy B. Terriberry + Copyright (c) 2008-2009 Xiph.Org Foundation */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#if !defined(_entenc_H) +# define _entenc_H (1) +# include +# include "entcode.h" + +/*Initializes the encoder. + _buf: The buffer to store output bytes in. + _size: The size of the buffer, in chars.*/ +void ec_enc_init(ec_enc *_this,unsigned char *_buf,opus_uint32 _size); +/*Encodes a symbol given its frequency information. + The frequency information must be discernable by the decoder, assuming it + has read only the previous symbols from the stream. + It is allowable to change the frequency information, or even the entire + source alphabet, so long as the decoder can tell from the context of the + previously encoded information that it is supposed to do so as well. + _fl: The cumulative frequency of all symbols that come before the one to be + encoded. + _fh: The cumulative frequency of all symbols up to and including the one to + be encoded. + Together with _fl, this defines the range [_fl,_fh) in which the + decoded value will fall. + _ft: The sum of the frequencies of all the symbols*/ +void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft); + +/*Equivalent to ec_encode() with _ft==1<<_bits.*/ +void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _bits); + +/* Encode a bit that has a 1/(1<<_logp) probability of being a one */ +void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp); + +/*Encodes a symbol given an "inverse" CDF table. + _s: The index of the symbol to encode. + _icdf: The "inverse" CDF, such that symbol _s falls in the range + [_s>0?ft-_icdf[_s-1]:0,ft-_icdf[_s]), where ft=1<<_ftb. + The values must be monotonically non-increasing, and the last value + must be 0. + _ftb: The number of bits of precision in the cumulative distribution.*/ +void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb); + +/*Encodes a raw unsigned integer in the stream. + _fl: The integer to encode. + _ft: The number of integers that can be encoded (one more than the max). + This must be at least one, and no more than 2**32-1.*/ +void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft); + +/*Encodes a sequence of raw bits in the stream. + _fl: The bits to encode. + _ftb: The number of bits to encode. + This must be between 1 and 25, inclusive.*/ +void ec_enc_bits(ec_enc *_this,opus_uint32 _fl,unsigned _ftb); + +/*Overwrites a few bits at the very start of an existing stream, after they + have already been encoded. + This makes it possible to have a few flags up front, where it is easy for + decoders to access them without parsing the whole stream, even if their + values are not determined until late in the encoding process, without having + to buffer all the intermediate symbols in the encoder. + In order for this to work, at least _nbits bits must have already been + encoded using probabilities that are an exact power of two. + The encoder can verify the number of encoded bits is sufficient, but cannot + check this latter condition. + _val: The bits to encode (in the least _nbits significant bits). + They will be decoded in order from most-significant to least. + _nbits: The number of bits to overwrite. + This must be no more than 8.*/ +void ec_enc_patch_initial_bits(ec_enc *_this,unsigned _val,unsigned _nbits); + +/*Compacts the data to fit in the target size. + This moves up the raw bits at the end of the current buffer so they are at + the end of the new buffer size. + The caller must ensure that the amount of data that's already been written + will fit in the new size. + _size: The number of bytes in the new buffer. + This must be large enough to contain the bits already written, and + must be no larger than the existing size.*/ +void ec_enc_shrink(ec_enc *_this,opus_uint32 _size); + +/*Indicates that there are no more symbols to encode. + All reamining output bytes are flushed to the output buffer. + ec_enc_init() must be called before the encoder can be used again.*/ +void ec_enc_done(ec_enc *_this); + +#endif diff --git a/TelegramClient.Opus/opus/celt/fixed_debug.h b/TelegramClient.Opus/opus/celt/fixed_debug.h new file mode 100755 index 0000000..80bc949 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/fixed_debug.h @@ -0,0 +1,773 @@ +/* Copyright (C) 2003-2008 Jean-Marc Valin + Copyright (C) 2007-2012 Xiph.Org Foundation */ +/** + @file fixed_debug.h + @brief Fixed-point operations with debugging +*/ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef FIXED_DEBUG_H +#define FIXED_DEBUG_H + +#include +#include "opus_defines.h" + +#ifdef CELT_C +OPUS_EXPORT opus_int64 celt_mips=0; +#else +extern opus_int64 celt_mips; +#endif + +#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b)) +#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL32(MULT16_16(SHR32((a),16),SHR((b),16)),1), SHR32(MULT16_16SU(SHR32((a),16),((b)&0x0000ffff)),15)), SHR32(MULT16_16SU(SHR32((b),16),((a)&0x0000ffff)),15)) + +/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */ +#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR32((b),16)), SHR32(MULT16_16SU((a),((b)&0x0000ffff)),16)) + +#define MULT16_32_P16(a,b) MULT16_32_PX(a,b,16) + +#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits)))) +#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val32)1)<<(bits)))) + +#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768) +#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL) +#define VERIFY_UINT(x) ((x)<=(2147483647LLU<<1)) + +#define SHR(a,b) SHR32(a,b) +#define PSHR(a,b) PSHR32(a,b) + +static OPUS_INLINE short NEG16(int x) +{ + int res; + if (!VERIFY_SHORT(x)) + { + fprintf (stderr, "NEG16: input is not short: %d\n", (int)x); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = -x; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "NEG16: output is not short: %d\n", (int)res); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips++; + return res; +} +static OPUS_INLINE int NEG32(opus_int64 x) +{ + opus_int64 res; + if (!VERIFY_INT(x)) + { + fprintf (stderr, "NEG16: input is not int: %d\n", (int)x); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = -x; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "NEG16: output is not int: %d\n", (int)res); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=2; + return res; +} + +#define EXTRACT16(x) EXTRACT16_(x, __FILE__, __LINE__) +static OPUS_INLINE short EXTRACT16_(int x, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(x)) + { + fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = x; + celt_mips++; + return res; +} + +#define EXTEND32(x) EXTEND32_(x, __FILE__, __LINE__) +static OPUS_INLINE int EXTEND32_(int x, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(x)) + { + fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = x; + celt_mips++; + return res; +} + +#define SHR16(a, shift) SHR16_(a, shift, __FILE__, __LINE__) +static OPUS_INLINE short SHR16_(int a, int shift, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift)) + { + fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = a>>shift; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips++; + return res; +} +#define SHL16(a, shift) SHL16_(a, shift, __FILE__, __LINE__) +static OPUS_INLINE short SHL16_(int a, int shift, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift)) + { + fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = a<>shift; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "SHR32: output is not int: %d\n", (int)res); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=2; + return res; +} +#define SHL32(a, shift) SHL32_(a, shift, __FILE__, __LINE__) +static OPUS_INLINE int SHL32_(opus_int64 a, int shift, char *file, int line) +{ + opus_int64 res; + if (!VERIFY_INT(a) || !VERIFY_SHORT(shift)) + { + fprintf (stderr, "SHL32: inputs are not int: %lld %d in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = a<>1))),shift)) +#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) + +#define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a)))) +#define HALF16(x) (SHR16(x,1)) +#define HALF32(x) (SHR32(x,1)) + +//#define SHR(a,shift) ((a) >> (shift)) +//#define SHL(a,shift) ((a) << (shift)) + +#define ADD16(a, b) ADD16_(a, b, __FILE__, __LINE__) +static OPUS_INLINE short ADD16_(int a, int b, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = a+b; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips++; + return res; +} + +#define SUB16(a, b) SUB16_(a, b, __FILE__, __LINE__) +static OPUS_INLINE short SUB16_(int a, int b, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = a-b; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips++; + return res; +} + +#define ADD32(a, b) ADD32_(a, b, __FILE__, __LINE__) +static OPUS_INLINE int ADD32_(opus_int64 a, opus_int64 b, char *file, int line) +{ + opus_int64 res; + if (!VERIFY_INT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = a+b; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=2; + return res; +} + +#define SUB32(a, b) SUB32_(a, b, __FILE__, __LINE__) +static OPUS_INLINE int SUB32_(opus_int64 a, opus_int64 b, char *file, int line) +{ + opus_int64 res; + if (!VERIFY_INT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "SUB32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = a-b; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "SUB32: output is not int: %d in %s: line %d\n", (int)res, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=2; + return res; +} + +#undef UADD32 +#define UADD32(a, b) UADD32_(a, b, __FILE__, __LINE__) +static OPUS_INLINE unsigned int UADD32_(opus_uint64 a, opus_uint64 b, char *file, int line) +{ + opus_uint64 res; + if (!VERIFY_UINT(a) || !VERIFY_UINT(b)) + { + fprintf (stderr, "UADD32: inputs are not uint32: %llu %llu in %s: line %d\n", a, b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = a+b; + if (!VERIFY_UINT(res)) + { + fprintf (stderr, "UADD32: output is not uint32: %llu in %s: line %d\n", res, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=2; + return res; +} + +#undef USUB32 +#define USUB32(a, b) USUB32_(a, b, __FILE__, __LINE__) +static OPUS_INLINE unsigned int USUB32_(opus_uint64 a, opus_uint64 b, char *file, int line) +{ + opus_uint64 res; + if (!VERIFY_UINT(a) || !VERIFY_UINT(b)) + { + fprintf (stderr, "USUB32: inputs are not uint32: %llu %llu in %s: line %d\n", a, b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + if (a=((opus_val32)(1)<<(15+Q))) + { + fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = (((opus_int64)a)*(opus_int64)b) >> Q; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + if (Q==15) + celt_mips+=3; + else + celt_mips+=4; + return res; +} + +#define MULT16_32_PX(a, b, Q) MULT16_32_PX_(a, b, Q, __FILE__, __LINE__) +static OPUS_INLINE int MULT16_32_PX_(int a, opus_int64 b, int Q, char *file, int line) +{ + opus_int64 res; + if (!VERIFY_SHORT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d in %s: line %d\n\n", Q, (int)a, (int)b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + if (ABS32(b)>=((opus_int64)(1)<<(15+Q))) + { + fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n\n", Q, (int)a, (int)b,file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = ((((opus_int64)a)*(opus_int64)b) + (((opus_val32)(1)<>1))>> Q; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d in %s: line %d\n\n", Q, (int)a, (int)b,(int)res, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + if (Q==15) + celt_mips+=4; + else + celt_mips+=5; + return res; +} + +#define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15) +#define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b)))) + +static OPUS_INLINE int SATURATE(int a, int b) +{ + if (a>b) + a=b; + if (a<-b) + a = -b; + celt_mips+=3; + return a; +} + +static OPUS_INLINE opus_int16 SATURATE16(opus_int32 a) +{ + celt_mips+=3; + if (a>32767) + return 32767; + else if (a<-32768) + return -32768; + else return a; +} + +static OPUS_INLINE int MULT16_16_Q11_32(int a, int b) +{ + opus_int64 res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = ((opus_int64)a)*b; + res >>= 11; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=3; + return res; +} +static OPUS_INLINE short MULT16_16_Q13(int a, int b) +{ + opus_int64 res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = ((opus_int64)a)*b; + res >>= 13; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=3; + return res; +} +static OPUS_INLINE short MULT16_16_Q14(int a, int b) +{ + opus_int64 res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = ((opus_int64)a)*b; + res >>= 14; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=3; + return res; +} + +#define MULT16_16_Q15(a, b) MULT16_16_Q15_(a, b, __FILE__, __LINE__) +static OPUS_INLINE short MULT16_16_Q15_(int a, int b, char *file, int line) +{ + opus_int64 res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a, b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = ((opus_int64)a)*b; + res >>= 15; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "MULT16_16_Q15: output is not short: %d in %s: line %d\n", (int)res, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=1; + return res; +} + +static OPUS_INLINE short MULT16_16_P13(int a, int b) +{ + opus_int64 res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = ((opus_int64)a)*b; + res += 4096; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res >>= 13; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=4; + return res; +} +static OPUS_INLINE short MULT16_16_P14(int a, int b) +{ + opus_int64 res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = ((opus_int64)a)*b; + res += 8192; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res >>= 14; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=4; + return res; +} +static OPUS_INLINE short MULT16_16_P15(int a, int b) +{ + opus_int64 res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = ((opus_int64)a)*b; + res += 16384; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res >>= 15; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=2; + return res; +} + +#define DIV32_16(a, b) DIV32_16_(a, b, __FILE__, __LINE__) + +static OPUS_INLINE int DIV32_16_(opus_int64 a, opus_int64 b, char *file, int line) +{ + opus_int64 res; + if (b==0) + { + fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + return 0; + } + if (!VERIFY_INT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = a/b; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line); + if (res>32767) + res = 32767; + if (res<-32768) + res = -32768; +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=35; + return res; +} + +#define DIV32(a, b) DIV32_(a, b, __FILE__, __LINE__) +static OPUS_INLINE int DIV32_(opus_int64 a, opus_int64 b, char *file, int line) +{ + opus_int64 res; + if (b==0) + { + fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + return 0; + } + + if (!VERIFY_INT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + res = a/b; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line); +#ifdef FIXED_DEBUG_ASSERT + celt_assert(0); +#endif + } + celt_mips+=70; + return res; +} + +#undef PRINT_MIPS +#define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", celt_mips);} while (0); + +#endif diff --git a/TelegramClient.Opus/opus/celt/fixed_generic.h b/TelegramClient.Opus/opus/celt/fixed_generic.h new file mode 100755 index 0000000..ecf018a --- /dev/null +++ b/TelegramClient.Opus/opus/celt/fixed_generic.h @@ -0,0 +1,134 @@ +/* Copyright (C) 2007-2009 Xiph.Org Foundation + Copyright (C) 2003-2008 Jean-Marc Valin + Copyright (C) 2007-2008 CSIRO */ +/** + @file fixed_generic.h + @brief Generic fixed-point operations +*/ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef FIXED_GENERIC_H +#define FIXED_GENERIC_H + +/** Multiply a 16-bit signed value by a 16-bit unsigned value. The result is a 32-bit signed value */ +#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b)) + +/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */ +#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16)) + +/** 16x32 multiplication, followed by a 16-bit shift right (round-to-nearest). Results fits in 32 bits */ +#define MULT16_32_P16(a,b) ADD32(MULT16_16((a),SHR((b),16)), PSHR(MULT16_16SU((a),((b)&0x0000ffff)),16)) + +/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */ +#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),((b)&0x0000ffff)),15)) + +/** 32x32 multiplication, followed by a 31-bit shift right. Results fits in 32 bits */ +#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),15)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),15)) + +/** Compile-time conversion of float constant to 16-bit value */ +#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits)))) + +/** Compile-time conversion of float constant to 32-bit value */ +#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val32)1)<<(bits)))) + +/** Negate a 16-bit value */ +#define NEG16(x) (-(x)) +/** Negate a 32-bit value */ +#define NEG32(x) (-(x)) + +/** Change a 32-bit value into a 16-bit value. The value is assumed to fit in 16-bit, otherwise the result is undefined */ +#define EXTRACT16(x) ((opus_val16)(x)) +/** Change a 16-bit value into a 32-bit value */ +#define EXTEND32(x) ((opus_val32)(x)) + +/** Arithmetic shift-right of a 16-bit value */ +#define SHR16(a,shift) ((a) >> (shift)) +/** Arithmetic shift-left of a 16-bit value */ +#define SHL16(a,shift) ((opus_int16)((opus_uint16)(a)<<(shift))) +/** Arithmetic shift-right of a 32-bit value */ +#define SHR32(a,shift) ((a) >> (shift)) +/** Arithmetic shift-left of a 32-bit value */ +#define SHL32(a,shift) ((opus_int32)((opus_uint32)(a)<<(shift))) + +/** 32-bit arithmetic shift right with rounding-to-nearest instead of rounding down */ +#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift)) +/** 32-bit arithmetic shift right where the argument can be negative */ +#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) + +/** "RAW" macros, should not be used outside of this header file */ +#define SHR(a,shift) ((a) >> (shift)) +#define SHL(a,shift) SHL32(a,shift) +#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift)) +#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) + +#define SATURATE16(x) (EXTRACT16((x)>32767 ? 32767 : (x)<-32768 ? -32768 : (x))) + +/** Shift by a and round-to-neareast 32-bit value. Result is a 16-bit value */ +#define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a)))) +/** Divide by two */ +#define HALF16(x) (SHR16(x,1)) +#define HALF32(x) (SHR32(x,1)) + +/** Add two 16-bit values */ +#define ADD16(a,b) ((opus_val16)((opus_val16)(a)+(opus_val16)(b))) +/** Subtract two 16-bit values */ +#define SUB16(a,b) ((opus_val16)(a)-(opus_val16)(b)) +/** Add two 32-bit values */ +#define ADD32(a,b) ((opus_val32)(a)+(opus_val32)(b)) +/** Subtract two 32-bit values */ +#define SUB32(a,b) ((opus_val32)(a)-(opus_val32)(b)) + +/** 16x16 multiplication where the result fits in 16 bits */ +#define MULT16_16_16(a,b) ((((opus_val16)(a))*((opus_val16)(b)))) + +/* (opus_val32)(opus_val16) gives TI compiler a hint that it's 16x16->32 multiply */ +/** 16x16 multiplication where the result fits in 32 bits */ +#define MULT16_16(a,b) (((opus_val32)(opus_val16)(a))*((opus_val32)(opus_val16)(b))) + +/** 16x16 multiply-add where the result fits in 32 bits */ +#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b)))) +/** 16x32 multiply, followed by a 15-bit shift right and 32-bit add. + b must fit in 31 bits. + Result fits in 32 bits. */ +#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))) + +#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11)) +#define MULT16_16_Q11(a,b) (SHR(MULT16_16((a),(b)),11)) +#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13)) +#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14)) +#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15)) + +#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13)) +#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14)) +#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15)) + +/** Divide a 32-bit value by a 16-bit value. Result fits in 16 bits */ +#define DIV32_16(a,b) ((opus_val16)(((opus_val32)(a))/((opus_val16)(b)))) + +/** Divide a 32-bit value by a 32-bit value. Result fits in 32 bits */ +#define DIV32(a,b) (((opus_val32)(a))/((opus_val32)(b))) + +#endif diff --git a/TelegramClient.Opus/opus/celt/float_cast.h b/TelegramClient.Opus/opus/celt/float_cast.h new file mode 100755 index 0000000..ede6574 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/float_cast.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2001 Erik de Castro Lopo */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +/* Version 1.1 */ + +#ifndef FLOAT_CAST_H +#define FLOAT_CAST_H + + +#include "arch.h" + +/*============================================================================ +** On Intel Pentium processors (especially PIII and probably P4), converting +** from float to int is very slow. To meet the C specs, the code produced by +** most C compilers targeting Pentium needs to change the FPU rounding mode +** before the float to int conversion is performed. +** +** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It +** is this flushing of the pipeline which is so slow. +** +** Fortunately the ISO C99 specifications define the functions lrint, lrintf, +** llrint and llrintf which fix this problem as a side effect. +** +** On Unix-like systems, the configure process should have detected the +** presence of these functions. If they weren't found we have to replace them +** here with a standard C cast. +*/ + +/* +** The C99 prototypes for lrint and lrintf are as follows: +** +** long int lrintf (float x) ; +** long int lrint (double x) ; +*/ + +/* The presence of the required functions are detected during the configure +** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in +** the config.h file. +*/ + +#if (HAVE_LRINTF) + +/* These defines enable functionality introduced with the 1999 ISO C +** standard. They must be defined before the inclusion of math.h to +** engage them. If optimisation is enabled, these functions will be +** inlined. With optimisation switched off, you have to link in the +** maths library using -lm. +*/ + +#define _ISOC9X_SOURCE 1 +#define _ISOC99_SOURCE 1 + +#define __USE_ISOC9X 1 +#define __USE_ISOC99 1 + +#include +#define float2int(x) lrintf(x) + +#elif (defined(HAVE_LRINT)) + +#define _ISOC9X_SOURCE 1 +#define _ISOC99_SOURCE 1 + +#define __USE_ISOC9X 1 +#define __USE_ISOC99 1 + +#include +#define float2int(x) lrint(x) + +#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined (WIN64) || defined (_WIN64)) + #include + + __inline long int float2int(float value) + { + return _mm_cvtss_si32(_mm_load_ss(&value)); + } +#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined (WIN32) || defined (_WIN32)) + #include + + /* Win32 doesn't seem to have these functions. + ** Therefore implement OPUS_INLINE versions of these functions here. + */ + + __inline long int + float2int (float flt) + { int intgr; + + _asm + { fld flt + fistp intgr + } ; + + return intgr ; + } + +#else + +#if (defined(__GNUC__) && defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) + /* supported by gcc in C99 mode, but not by all other compilers */ + #warning "Don't have the functions lrint() and lrintf ()." + #warning "Replacing these functions with a standard C cast." +#endif /* __STDC_VERSION__ >= 199901L */ + #include + #define float2int(flt) ((int)(floor(.5+flt))) +#endif + +#ifndef DISABLE_FLOAT_API +static OPUS_INLINE opus_int16 FLOAT2INT16(float x) +{ + x = x*CELT_SIG_SCALE; + x = MAX32(x, -32768); + x = MIN32(x, 32767); + return (opus_int16)float2int(x); +} +#endif /* DISABLE_FLOAT_API */ + +#endif /* FLOAT_CAST_H */ diff --git a/TelegramClient.Opus/opus/celt/kiss_fft.c b/TelegramClient.Opus/opus/celt/kiss_fft.c new file mode 100755 index 0000000..ad706c7 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/kiss_fft.c @@ -0,0 +1,719 @@ +/*Copyright (c) 2003-2004, Mark Borgerding + Lots of modifications by Jean-Marc Valin + Copyright (c) 2005-2007, Xiph.Org Foundation + Copyright (c) 2008, Xiph.Org Foundation, CSIRO + + 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. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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.*/ + +/* This code is originally from Mark Borgerding's KISS-FFT but has been + heavily modified to better suit Opus */ + +#ifndef SKIP_CONFIG_H +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif +#endif + +#include "_kiss_fft_guts.h" +#include "arch.h" +#include "os_support.h" +#include "mathops.h" +#include "stack_alloc.h" + +/* The guts header contains all the multiplication and addition macros that are defined for + complex numbers. It also delares the kf_ internal functions. +*/ + +static void kf_bfly2( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_state *st, + int m, + int N, + int mm + ) +{ + kiss_fft_cpx * Fout2; + const kiss_twiddle_cpx * tw1; + int i,j; + kiss_fft_cpx * Fout_beg = Fout; + for (i=0;itwiddles; + for(j=0;jr = SHR32(Fout->r, 1);Fout->i = SHR32(Fout->i, 1); + Fout2->r = SHR32(Fout2->r, 1);Fout2->i = SHR32(Fout2->i, 1); + C_MUL (t, *Fout2 , *tw1); + tw1 += fstride; + C_SUB( *Fout2 , *Fout , t ); + C_ADDTO( *Fout , t ); + ++Fout2; + ++Fout; + } + } +} + +static void ki_bfly2( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_state *st, + int m, + int N, + int mm + ) +{ + kiss_fft_cpx * Fout2; + const kiss_twiddle_cpx * tw1; + kiss_fft_cpx t; + int i,j; + kiss_fft_cpx * Fout_beg = Fout; + for (i=0;itwiddles; + for(j=0;jtwiddles; + for (j=0;jr = PSHR32(Fout->r, 2); + Fout->i = PSHR32(Fout->i, 2); + C_SUB( scratch[5] , *Fout, scratch[1] ); + C_ADDTO(*Fout, scratch[1]); + C_ADD( scratch[3] , scratch[0] , scratch[2] ); + C_SUB( scratch[4] , scratch[0] , scratch[2] ); + C_SUB( Fout[m2], *Fout, scratch[3] ); + tw1 += fstride; + tw2 += fstride*2; + tw3 += fstride*3; + C_ADDTO( *Fout , scratch[3] ); + + Fout[m].r = scratch[5].r + scratch[4].i; + Fout[m].i = scratch[5].i - scratch[4].r; + Fout[m3].r = scratch[5].r - scratch[4].i; + Fout[m3].i = scratch[5].i + scratch[4].r; + ++Fout; + } + } +} + +static void ki_bfly4( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_state *st, + int m, + int N, + int mm + ) +{ + const kiss_twiddle_cpx *tw1,*tw2,*tw3; + kiss_fft_cpx scratch[6]; + const size_t m2=2*m; + const size_t m3=3*m; + int i, j; + + kiss_fft_cpx * Fout_beg = Fout; + for (i=0;itwiddles; + for (j=0;jtwiddles[fstride*m]; + for (i=0;itwiddles; + k=m; + do { + C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3); + + C_MUL(scratch[1],Fout[m] , *tw1); + C_MUL(scratch[2],Fout[m2] , *tw2); + + C_ADD(scratch[3],scratch[1],scratch[2]); + C_SUB(scratch[0],scratch[1],scratch[2]); + tw1 += fstride; + tw2 += fstride*2; + + Fout[m].r = Fout->r - HALF_OF(scratch[3].r); + Fout[m].i = Fout->i - HALF_OF(scratch[3].i); + + C_MULBYSCALAR( scratch[0] , epi3.i ); + + C_ADDTO(*Fout,scratch[3]); + + Fout[m2].r = Fout[m].r + scratch[0].i; + Fout[m2].i = Fout[m].i - scratch[0].r; + + Fout[m].r -= scratch[0].i; + Fout[m].i += scratch[0].r; + + ++Fout; + } while(--k); + } +} + +static void ki_bfly3( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_state *st, + int m, + int N, + int mm + ) +{ + int i, k; + const size_t m2 = 2*m; + const kiss_twiddle_cpx *tw1,*tw2; + kiss_fft_cpx scratch[5]; + kiss_twiddle_cpx epi3; + + kiss_fft_cpx * Fout_beg = Fout; + epi3 = st->twiddles[fstride*m]; + for (i=0;itwiddles; + k=m; + do{ + + C_MULC(scratch[1],Fout[m] , *tw1); + C_MULC(scratch[2],Fout[m2] , *tw2); + + C_ADD(scratch[3],scratch[1],scratch[2]); + C_SUB(scratch[0],scratch[1],scratch[2]); + tw1 += fstride; + tw2 += fstride*2; + + Fout[m].r = Fout->r - HALF_OF(scratch[3].r); + Fout[m].i = Fout->i - HALF_OF(scratch[3].i); + + C_MULBYSCALAR( scratch[0] , -epi3.i ); + + C_ADDTO(*Fout,scratch[3]); + + Fout[m2].r = Fout[m].r + scratch[0].i; + Fout[m2].i = Fout[m].i - scratch[0].r; + + Fout[m].r -= scratch[0].i; + Fout[m].i += scratch[0].r; + + ++Fout; + }while(--k); + } +} + +static void kf_bfly5( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_state *st, + int m, + int N, + int mm + ) +{ + kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4; + int i, u; + kiss_fft_cpx scratch[13]; + const kiss_twiddle_cpx * twiddles = st->twiddles; + const kiss_twiddle_cpx *tw; + kiss_twiddle_cpx ya,yb; + kiss_fft_cpx * Fout_beg = Fout; + + ya = twiddles[fstride*m]; + yb = twiddles[fstride*2*m]; + tw=st->twiddles; + + for (i=0;ir += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; + + scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r); + scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r); + + scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i); + scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i); + + C_SUB(*Fout1,scratch[5],scratch[6]); + C_ADD(*Fout4,scratch[5],scratch[6]); + + scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r); + scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r); + scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i); + scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i); + + C_ADD(*Fout2,scratch[11],scratch[12]); + C_SUB(*Fout3,scratch[11],scratch[12]); + + ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4; + } + } +} + +static void ki_bfly5( + kiss_fft_cpx * Fout, + const size_t fstride, + const kiss_fft_state *st, + int m, + int N, + int mm + ) +{ + kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4; + int i, u; + kiss_fft_cpx scratch[13]; + const kiss_twiddle_cpx * twiddles = st->twiddles; + const kiss_twiddle_cpx *tw; + kiss_twiddle_cpx ya,yb; + kiss_fft_cpx * Fout_beg = Fout; + + ya = twiddles[fstride*m]; + yb = twiddles[fstride*2*m]; + tw=st->twiddles; + + for (i=0;ir += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; + + scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r); + scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r); + + scratch[6].r = -S_MUL(scratch[10].i,ya.i) - S_MUL(scratch[9].i,yb.i); + scratch[6].i = S_MUL(scratch[10].r,ya.i) + S_MUL(scratch[9].r,yb.i); + + C_SUB(*Fout1,scratch[5],scratch[6]); + C_ADD(*Fout4,scratch[5],scratch[6]); + + scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r); + scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r); + scratch[12].r = S_MUL(scratch[10].i,yb.i) - S_MUL(scratch[9].i,ya.i); + scratch[12].i = -S_MUL(scratch[10].r,yb.i) + S_MUL(scratch[9].r,ya.i); + + C_ADD(*Fout2,scratch[11],scratch[12]); + C_SUB(*Fout3,scratch[11],scratch[12]); + + ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4; + } + } +} + +#endif + + +#ifdef CUSTOM_MODES + +static +void compute_bitrev_table( + int Fout, + opus_int16 *f, + const size_t fstride, + int in_stride, + opus_int16 * factors, + const kiss_fft_state *st + ) +{ + const int p=*factors++; /* the radix */ + const int m=*factors++; /* stage's fft length/p */ + + /*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/ + if (m==1) + { + int j; + for (j=0;j32000 || (opus_int32)p*(opus_int32)p > n) + p = n; /* no more factors, skip to end */ + } + n /= p; +#ifdef RADIX_TWO_ONLY + if (p!=2 && p != 4) +#else + if (p>5) +#endif + { + return 0; + } + *facbuf++ = p; + *facbuf++ = n; + } while (n > 1); + return 1; +} + +static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft) +{ + int i; +#ifdef FIXED_POINT + for (i=0;i= memneeded) + st = (kiss_fft_state*)mem; + *lenmem = memneeded; + } + if (st) { + opus_int16 *bitrev; + kiss_twiddle_cpx *twiddles; + + st->nfft=nfft; +#ifndef FIXED_POINT + st->scale = 1.f/nfft; +#endif + if (base != NULL) + { + st->twiddles = base->twiddles; + st->shift = 0; + while (nfft<shift != base->nfft && st->shift < 32) + st->shift++; + if (st->shift>=32) + goto fail; + } else { + st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft); + compute_twiddles(twiddles, nfft); + st->shift = -1; + } + if (!kf_factor(nfft,st->factors)) + { + goto fail; + } + + /* bitrev */ + st->bitrev = bitrev = (opus_int16*)KISS_FFT_MALLOC(sizeof(opus_int16)*nfft); + if (st->bitrev==NULL) + goto fail; + compute_bitrev_table(0, bitrev, 1,1, st->factors,st); + } + return st; +fail: + opus_fft_free(st); + return NULL; +} + +kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem ) +{ + return opus_fft_alloc_twiddles(nfft, mem, lenmem, NULL); +} + +void opus_fft_free(const kiss_fft_state *cfg) +{ + if (cfg) + { + opus_free((opus_int16*)cfg->bitrev); + if (cfg->shift < 0) + opus_free((kiss_twiddle_cpx*)cfg->twiddles); + opus_free((kiss_fft_state*)cfg); + } +} + +#endif /* CUSTOM_MODES */ + +void opus_fft(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) +{ + int m2, m; + int p; + int L; + int fstride[MAXFACTORS]; + int i; + int shift; + + /* st->shift can be -1 */ + shift = st->shift>0 ? st->shift : 0; + + celt_assert2 (fin != fout, "In-place FFT not supported"); + /* Bit-reverse the input */ + for (i=0;infft;i++) + { + fout[st->bitrev[i]] = fin[i]; +#ifndef FIXED_POINT + fout[st->bitrev[i]].r *= st->scale; + fout[st->bitrev[i]].i *= st->scale; +#endif + } + + fstride[0] = 1; + L=0; + do { + p = st->factors[2*L]; + m = st->factors[2*L+1]; + fstride[L+1] = fstride[L]*p; + L++; + } while(m!=1); + m = st->factors[2*L-1]; + for (i=L-1;i>=0;i--) + { + if (i!=0) + m2 = st->factors[2*i-1]; + else + m2 = 1; + switch (st->factors[2*i]) + { + case 2: + kf_bfly2(fout,fstride[i]<shift can be -1 */ + shift = st->shift>0 ? st->shift : 0; + celt_assert2 (fin != fout, "In-place FFT not supported"); + /* Bit-reverse the input */ + for (i=0;infft;i++) + fout[st->bitrev[i]] = fin[i]; + + fstride[0] = 1; + L=0; + do { + p = st->factors[2*L]; + m = st->factors[2*L+1]; + fstride[L+1] = fstride[L]*p; + L++; + } while(m!=1); + m = st->factors[2*L-1]; + for (i=L-1;i>=0;i--) + { + if (i!=0) + m2 = st->factors[2*i-1]; + else + m2 = 1; + switch (st->factors[2*i]) + { + case 2: + ki_bfly2(fout,fstride[i]< +#include +#include "arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef USE_SIMD +# include +# define kiss_fft_scalar __m128 +#define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes) +#else +#define KISS_FFT_MALLOC opus_alloc +#endif + +#ifdef FIXED_POINT +#include "arch.h" + +# define kiss_fft_scalar opus_int32 +# define kiss_twiddle_scalar opus_int16 + + +#else +# ifndef kiss_fft_scalar +/* default is float */ +# define kiss_fft_scalar float +# define kiss_twiddle_scalar float +# define KF_SUFFIX _celt_single +# endif +#endif + +typedef struct { + kiss_fft_scalar r; + kiss_fft_scalar i; +}kiss_fft_cpx; + +typedef struct { + kiss_twiddle_scalar r; + kiss_twiddle_scalar i; +}kiss_twiddle_cpx; + +#define MAXFACTORS 8 +/* e.g. an fft of length 128 has 4 factors + as far as kissfft is concerned + 4*4*4*2 + */ + +typedef struct kiss_fft_state{ + int nfft; +#ifndef FIXED_POINT + kiss_fft_scalar scale; +#endif + int shift; + opus_int16 factors[2*MAXFACTORS]; + const opus_int16 *bitrev; + const kiss_twiddle_cpx *twiddles; +} kiss_fft_state; + +/*typedef struct kiss_fft_state* kiss_fft_cfg;*/ + +/** + * opus_fft_alloc + * + * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. + * + * typical usage: kiss_fft_cfg mycfg=opus_fft_alloc(1024,0,NULL,NULL); + * + * The return value from fft_alloc is a cfg buffer used internally + * by the fft routine or NULL. + * + * If lenmem is NULL, then opus_fft_alloc will allocate a cfg buffer using malloc. + * The returned value should be free()d when done to avoid memory leaks. + * + * The state can be placed in a user supplied buffer 'mem': + * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, + * then the function places the cfg in mem and the size used in *lenmem + * and returns mem. + * + * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), + * then the function returns NULL and places the minimum cfg + * buffer size in *lenmem. + * */ + +kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base); + +kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem); + +/** + * opus_fft(cfg,in_out_buf) + * + * Perform an FFT on a complex input buffer. + * for a forward FFT, + * fin should be f[0] , f[1] , ... ,f[nfft-1] + * fout will be F[0] , F[1] , ... ,F[nfft-1] + * Note that each element is complex and can be accessed like + f[k].r and f[k].i + * */ +void opus_fft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); +void opus_ifft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); + +void opus_fft_free(const kiss_fft_state *cfg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/TelegramClient.Opus/opus/celt/laplace.c b/TelegramClient.Opus/opus/celt/laplace.c new file mode 100755 index 0000000..a7bca87 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/laplace.c @@ -0,0 +1,134 @@ +/* Copyright (c) 2007 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "laplace.h" +#include "mathops.h" + +/* The minimum probability of an energy delta (out of 32768). */ +#define LAPLACE_LOG_MINP (0) +#define LAPLACE_MINP (1<>15; +} + +void ec_laplace_encode(ec_enc *enc, int *value, unsigned fs, int decay) +{ + unsigned fl; + int val = *value; + fl = 0; + if (val) + { + int s; + int i; + s = -(val<0); + val = (val+s)^s; + fl = fs; + fs = ec_laplace_get_freq1(fs, decay); + /* Search the decaying part of the PDF.*/ + for (i=1; fs > 0 && i < val; i++) + { + fs *= 2; + fl += fs+2*LAPLACE_MINP; + fs = (fs*(opus_int32)decay)>>15; + } + /* Everything beyond that has probability LAPLACE_MINP. */ + if (!fs) + { + int di; + int ndi_max; + ndi_max = (32768-fl+LAPLACE_MINP-1)>>LAPLACE_LOG_MINP; + ndi_max = (ndi_max-s)>>1; + di = IMIN(val - i, ndi_max - 1); + fl += (2*di+1+s)*LAPLACE_MINP; + fs = IMIN(LAPLACE_MINP, 32768-fl); + *value = (i+di+s)^s; + } + else + { + fs += LAPLACE_MINP; + fl += fs&~s; + } + celt_assert(fl+fs<=32768); + celt_assert(fs>0); + } + ec_encode_bin(enc, fl, fl+fs, 15); +} + +int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay) +{ + int val=0; + unsigned fl; + unsigned fm; + fm = ec_decode_bin(dec, 15); + fl = 0; + if (fm >= fs) + { + val++; + fl = fs; + fs = ec_laplace_get_freq1(fs, decay)+LAPLACE_MINP; + /* Search the decaying part of the PDF.*/ + while(fs > LAPLACE_MINP && fm >= fl+2*fs) + { + fs *= 2; + fl += fs; + fs = ((fs-2*LAPLACE_MINP)*(opus_int32)decay)>>15; + fs += LAPLACE_MINP; + val++; + } + /* Everything beyond that has probability LAPLACE_MINP. */ + if (fs <= LAPLACE_MINP) + { + int di; + di = (fm-fl)>>(LAPLACE_LOG_MINP+1); + val += di; + fl += 2*di*LAPLACE_MINP; + } + if (fm < fl+fs) + val = -val; + else + fl += fs; + } + celt_assert(fl<32768); + celt_assert(fs>0); + celt_assert(fl<=fm); + celt_assert(fm>1; + b=1U<>=1; + bshift--; + } + while(bshift>=0); + return g; +} + +#ifdef FIXED_POINT + +opus_val32 frac_div32(opus_val32 a, opus_val32 b) +{ + opus_val16 rcp; + opus_val32 result, rem; + int shift = celt_ilog2(b)-29; + a = VSHR32(a,shift); + b = VSHR32(b,shift); + /* 16-bit reciprocal */ + rcp = ROUND16(celt_rcp(ROUND16(b,16)),3); + result = MULT16_32_Q15(rcp, a); + rem = PSHR32(a,2)-MULT32_32_Q31(result, b); + result = ADD32(result, SHL32(MULT16_32_Q15(rcp, rem),2)); + if (result >= 536870912) /* 2^29 */ + return 2147483647; /* 2^31 - 1 */ + else if (result <= -536870912) /* -2^29 */ + return -2147483647; /* -2^31 */ + else + return SHL32(result, 2); +} + +/** Reciprocal sqrt approximation in the range [0.25,1) (Q16 in, Q14 out) */ +opus_val16 celt_rsqrt_norm(opus_val32 x) +{ + opus_val16 n; + opus_val16 r; + opus_val16 r2; + opus_val16 y; + /* Range of n is [-16384,32767] ([-0.5,1) in Q15). */ + n = x-32768; + /* Get a rough initial guess for the root. + The optimal minimax quadratic approximation (using relative error) is + r = 1.437799046117536+n*(-0.823394375837328+n*0.4096419668459485). + Coefficients here, and the final result r, are Q14.*/ + r = ADD16(23557, MULT16_16_Q15(n, ADD16(-13490, MULT16_16_Q15(n, 6713)))); + /* We want y = x*r*r-1 in Q15, but x is 32-bit Q16 and r is Q14. + We can compute the result from n and r using Q15 multiplies with some + adjustment, carefully done to avoid overflow. + Range of y is [-1564,1594]. */ + r2 = MULT16_16_Q15(r, r); + y = SHL16(SUB16(ADD16(MULT16_16_Q15(r2, n), r2), 16384), 1); + /* Apply a 2nd-order Householder iteration: r += r*y*(y*0.375-0.5). + This yields the Q14 reciprocal square root of the Q16 x, with a maximum + relative error of 1.04956E-4, a (relative) RMSE of 2.80979E-5, and a + peak absolute error of 2.26591/16384. */ + return ADD16(r, MULT16_16_Q15(r, MULT16_16_Q15(y, + SUB16(MULT16_16_Q15(y, 12288), 16384)))); +} + +/** Sqrt approximation (QX input, QX/2 output) */ +opus_val32 celt_sqrt(opus_val32 x) +{ + int k; + opus_val16 n; + opus_val32 rt; + static const opus_val16 C[5] = {23175, 11561, -3011, 1699, -664}; + if (x==0) + return 0; + else if (x>=1073741824) + return 32767; + k = (celt_ilog2(x)>>1)-7; + x = VSHR32(x, 2*k); + n = x-32768; + rt = ADD16(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2], + MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, (C[4]))))))))); + rt = VSHR32(rt,7-k); + return rt; +} + +#define L1 32767 +#define L2 -7651 +#define L3 8277 +#define L4 -626 + +static OPUS_INLINE opus_val16 _celt_cos_pi_2(opus_val16 x) +{ + opus_val16 x2; + + x2 = MULT16_16_P15(x,x); + return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2 + )))))))); +} + +#undef L1 +#undef L2 +#undef L3 +#undef L4 + +opus_val16 celt_cos_norm(opus_val32 x) +{ + x = x&0x0001ffff; + if (x>SHL32(EXTEND32(1), 16)) + x = SUB32(SHL32(EXTEND32(1), 17),x); + if (x&0x00007fff) + { + if (x0, "celt_rcp() only defined for positive values"); + i = celt_ilog2(x); + /* n is Q15 with range [0,1). */ + n = VSHR32(x,i-15)-32768; + /* Start with a linear approximation: + r = 1.8823529411764706-0.9411764705882353*n. + The coefficients and the result are Q14 in the range [15420,30840].*/ + r = ADD16(30840, MULT16_16_Q15(-15420, n)); + /* Perform two Newton iterations: + r -= r*((r*n)-1.Q15) + = r*((r*n)+(r-1.Q15)). */ + r = SUB16(r, MULT16_16_Q15(r, + ADD16(MULT16_16_Q15(r, n), ADD16(r, -32768)))); + /* We subtract an extra 1 in the second iteration to avoid overflow; it also + neatly compensates for truncation error in the rest of the process. */ + r = SUB16(r, ADD16(1, MULT16_16_Q15(r, + ADD16(MULT16_16_Q15(r, n), ADD16(r, -32768))))); + /* r is now the Q15 solution to 2/(n+1), with a maximum relative error + of 7.05346E-5, a (relative) RMSE of 2.14418E-5, and a peak absolute + error of 1.24665/32768. */ + return VSHR32(EXTEND32(r),i-16); +} + +#endif diff --git a/TelegramClient.Opus/opus/celt/mathops.h b/TelegramClient.Opus/opus/celt/mathops.h new file mode 100755 index 0000000..a0525a9 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/mathops.h @@ -0,0 +1,258 @@ +/* Copyright (c) 2002-2008 Jean-Marc Valin + Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/** + @file mathops.h + @brief Various math functions +*/ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef MATHOPS_H +#define MATHOPS_H + +#include "arch.h" +#include "entcode.h" +#include "os_support.h" + +/* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */ +#define FRAC_MUL16(a,b) ((16384+((opus_int32)(opus_int16)(a)*(opus_int16)(b)))>>15) + +unsigned isqrt32(opus_uint32 _val); + +#ifndef OVERRIDE_CELT_MAXABS16 +static OPUS_INLINE opus_val32 celt_maxabs16(const opus_val16 *x, int len) +{ + int i; + opus_val16 maxval = 0; + opus_val16 minval = 0; + for (i=0;i>23)-127; + in.i -= integer<<23; + frac = in.f - 1.5f; + frac = -0.41445418f + frac*(0.95909232f + + frac*(-0.33951290f + frac*0.16541097f)); + return 1+integer+frac; +} + +/** Base-2 exponential approximation (2^x). */ +static OPUS_INLINE float celt_exp2(float x) +{ + int integer; + float frac; + union { + float f; + opus_uint32 i; + } res; + integer = floor(x); + if (integer < -50) + return 0; + frac = x-integer; + /* K0 = 1, K1 = log(2), K2 = 3-4*log(2), K3 = 3*log(2) - 2 */ + res.f = 0.99992522f + frac * (0.69583354f + + frac * (0.22606716f + 0.078024523f*frac)); + res.i = (res.i + (integer<<23)) & 0x7fffffff; + return res.f; +} + +#else +#define celt_log2(x) ((float)(1.442695040888963387*log(x))) +#define celt_exp2(x) ((float)exp(0.6931471805599453094*(x))) +#endif + +#endif + +#ifdef FIXED_POINT + +#include "os_support.h" + +#ifndef OVERRIDE_CELT_ILOG2 +/** Integer log in base2. Undefined for zero and negative numbers */ +static OPUS_INLINE opus_int16 celt_ilog2(opus_int32 x) +{ + celt_assert2(x>0, "celt_ilog2() only defined for strictly positive numbers"); + return EC_ILOG(x)-1; +} +#endif + + +/** Integer log in base2. Defined for zero, but not for negative numbers */ +static OPUS_INLINE opus_int16 celt_zlog2(opus_val32 x) +{ + return x <= 0 ? 0 : celt_ilog2(x); +} + +opus_val16 celt_rsqrt_norm(opus_val32 x); + +opus_val32 celt_sqrt(opus_val32 x); + +opus_val16 celt_cos_norm(opus_val32 x); + +/** Base-2 logarithm approximation (log2(x)). (Q14 input, Q10 output) */ +static OPUS_INLINE opus_val16 celt_log2(opus_val32 x) +{ + int i; + opus_val16 n, frac; + /* -0.41509302963303146, 0.9609890551383969, -0.31836011537636605, + 0.15530808010959576, -0.08556153059057618 */ + static const opus_val16 C[5] = {-6801+(1<<(13-DB_SHIFT)), 15746, -5217, 2545, -1401}; + if (x==0) + return -32767; + i = celt_ilog2(x); + n = VSHR32(x,i-15)-32768-16384; + frac = ADD16(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2], MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, C[4])))))))); + return SHL16(i-13,DB_SHIFT)+SHR16(frac,14-DB_SHIFT); +} + +/* + K0 = 1 + K1 = log(2) + K2 = 3-4*log(2) + K3 = 3*log(2) - 2 +*/ +#define D0 16383 +#define D1 22804 +#define D2 14819 +#define D3 10204 + +static OPUS_INLINE opus_val32 celt_exp2_frac(opus_val16 x) +{ + opus_val16 frac; + frac = SHL16(x, 4); + return ADD16(D0, MULT16_16_Q15(frac, ADD16(D1, MULT16_16_Q15(frac, ADD16(D2 , MULT16_16_Q15(D3,frac)))))); +} +/** Base-2 exponential approximation (2^x). (Q10 input, Q16 output) */ +static OPUS_INLINE opus_val32 celt_exp2(opus_val16 x) +{ + int integer; + opus_val16 frac; + integer = SHR16(x,10); + if (integer>14) + return 0x7f000000; + else if (integer < -15) + return 0; + frac = celt_exp2_frac(x-SHL16(integer,10)); + return VSHR32(EXTEND32(frac), -integer-2); +} + +opus_val32 celt_rcp(opus_val32 x); + +#define celt_div(a,b) MULT32_32_Q31((opus_val32)(a),celt_rcp(b)) + +opus_val32 frac_div32(opus_val32 a, opus_val32 b); + +#define M1 32767 +#define M2 -21 +#define M3 -11943 +#define M4 4936 + +/* Atan approximation using a 4th order polynomial. Input is in Q15 format + and normalized by pi/4. Output is in Q15 format */ +static OPUS_INLINE opus_val16 celt_atan01(opus_val16 x) +{ + return MULT16_16_P15(x, ADD32(M1, MULT16_16_P15(x, ADD32(M2, MULT16_16_P15(x, ADD32(M3, MULT16_16_P15(M4, x))))))); +} + +#undef M1 +#undef M2 +#undef M3 +#undef M4 + +/* atan2() approximation valid for positive input values */ +static OPUS_INLINE opus_val16 celt_atan2p(opus_val16 y, opus_val16 x) +{ + if (y < x) + { + opus_val32 arg; + arg = celt_div(SHL32(EXTEND32(y),15),x); + if (arg >= 32767) + arg = 32767; + return SHR16(celt_atan01(EXTRACT16(arg)),1); + } else { + opus_val32 arg; + arg = celt_div(SHL32(EXTEND32(x),15),y); + if (arg >= 32767) + arg = 32767; + return 25736-SHR16(celt_atan01(EXTRACT16(arg)),1); + } +} + +#endif /* FIXED_POINT */ +#endif /* MATHOPS_H */ diff --git a/TelegramClient.Opus/opus/celt/mdct.c b/TelegramClient.Opus/opus/celt/mdct.c new file mode 100755 index 0000000..90a214a --- /dev/null +++ b/TelegramClient.Opus/opus/celt/mdct.c @@ -0,0 +1,311 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2008 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +/* This is a simple MDCT implementation that uses a N/4 complex FFT + to do most of the work. It should be relatively straightforward to + plug in pretty much and FFT here. + + This replaces the Vorbis FFT (and uses the exact same API), which + was a bit too messy and that was ending up duplicating code + (might as well use the same FFT everywhere). + + The algorithm is similar to (and inspired from) Fabrice Bellard's + MDCT implementation in FFMPEG, but has differences in signs, ordering + and scaling in many places. +*/ + +#ifndef SKIP_CONFIG_H +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#endif + +#include "mdct.h" +#include "kiss_fft.h" +#include "_kiss_fft_guts.h" +#include +#include "os_support.h" +#include "mathops.h" +#include "stack_alloc.h" + +#ifdef CUSTOM_MODES + +int clt_mdct_init(mdct_lookup *l,int N, int maxshift) +{ + int i; + int N4; + kiss_twiddle_scalar *trig; +#if defined(FIXED_POINT) + int N2=N>>1; +#endif + l->n = N; + N4 = N>>2; + l->maxshift = maxshift; + for (i=0;i<=maxshift;i++) + { + if (i==0) + l->kfft[i] = opus_fft_alloc(N>>2>>i, 0, 0); + else + l->kfft[i] = opus_fft_alloc_twiddles(N>>2>>i, 0, 0, l->kfft[0]); +#ifndef ENABLE_TI_DSPLIB55 + if (l->kfft[i]==NULL) + return 0; +#endif + } + l->trig = trig = (kiss_twiddle_scalar*)opus_alloc((N4+1)*sizeof(kiss_twiddle_scalar)); + if (l->trig==NULL) + return 0; + /* We have enough points that sine isn't necessary */ +#if defined(FIXED_POINT) + for (i=0;i<=N4;i++) + trig[i] = TRIG_UPSCALE*celt_cos_norm(DIV32(ADD32(SHL32(EXTEND32(i),17),N2),N)); +#else + for (i=0;i<=N4;i++) + trig[i] = (kiss_twiddle_scalar)cos(2*PI*i/N); +#endif + return 1; +} + +void clt_mdct_clear(mdct_lookup *l) +{ + int i; + for (i=0;i<=l->maxshift;i++) + opus_fft_free(l->kfft[i]); + opus_free((kiss_twiddle_scalar*)l->trig); +} + +#endif /* CUSTOM_MODES */ + +/* Forward MDCT trashes the input array */ +void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, + const opus_val16 *window, int overlap, int shift, int stride) +{ + int i; + int N, N2, N4; + kiss_twiddle_scalar sine; + VARDECL(kiss_fft_scalar, f); + VARDECL(kiss_fft_scalar, f2); + SAVE_STACK; + N = l->n; + N >>= shift; + N2 = N>>1; + N4 = N>>2; + ALLOC(f, N2, kiss_fft_scalar); + ALLOC(f2, N2, kiss_fft_scalar); + /* sin(x) ~= x here */ +#ifdef FIXED_POINT + sine = TRIG_UPSCALE*(QCONST16(0.7853981f, 15)+N2)/N; +#else + sine = (kiss_twiddle_scalar)2*PI*(.125f)/N; +#endif + + /* Consider the input to be composed of four blocks: [a, b, c, d] */ + /* Window, shuffle, fold */ + { + /* Temp pointers to make it really clear to the compiler what we're doing */ + const kiss_fft_scalar * OPUS_RESTRICT xp1 = in+(overlap>>1); + const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+N2-1+(overlap>>1); + kiss_fft_scalar * OPUS_RESTRICT yp = f; + const opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1); + const opus_val16 * OPUS_RESTRICT wp2 = window+(overlap>>1)-1; + for(i=0;i<((overlap+3)>>2);i++) + { + /* Real part arranged as -d-cR, Imag part arranged as -b+aR*/ + *yp++ = MULT16_32_Q15(*wp2, xp1[N2]) + MULT16_32_Q15(*wp1,*xp2); + *yp++ = MULT16_32_Q15(*wp1, *xp1) - MULT16_32_Q15(*wp2, xp2[-N2]); + xp1+=2; + xp2-=2; + wp1+=2; + wp2-=2; + } + wp1 = window; + wp2 = window+overlap-1; + for(;i>2);i++) + { + /* Real part arranged as a-bR, Imag part arranged as -c-dR */ + *yp++ = *xp2; + *yp++ = *xp1; + xp1+=2; + xp2-=2; + } + for(;itrig[0]; + for(i=0;ikfft[shift], (kiss_fft_cpx *)f, (kiss_fft_cpx *)f2); + + /* Post-rotate */ + { + /* Temp pointers to make it really clear to the compiler what we're doing */ + const kiss_fft_scalar * OPUS_RESTRICT fp = f2; + kiss_fft_scalar * OPUS_RESTRICT yp1 = out; + kiss_fft_scalar * OPUS_RESTRICT yp2 = out+stride*(N2-1); + const kiss_twiddle_scalar *t = &l->trig[0]; + /* Temp pointers to make it really clear to the compiler what we're doing */ + for(i=0;in; + N >>= shift; + N2 = N>>1; + N4 = N>>2; + ALLOC(f2, N2, kiss_fft_scalar); + /* sin(x) ~= x here */ +#ifdef FIXED_POINT + sine = TRIG_UPSCALE*(QCONST16(0.7853981f, 15)+N2)/N; +#else + sine = (kiss_twiddle_scalar)2*PI*(.125f)/N; +#endif + + /* Pre-rotate */ + { + /* Temp pointers to make it really clear to the compiler what we're doing */ + const kiss_fft_scalar * OPUS_RESTRICT xp1 = in; + const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+stride*(N2-1); + kiss_fft_scalar * OPUS_RESTRICT yp = f2; + const kiss_twiddle_scalar *t = &l->trig[0]; + for(i=0;ikfft[shift], (kiss_fft_cpx *)f2, (kiss_fft_cpx *)(out+(overlap>>1))); + + /* Post-rotate and de-shuffle from both ends of the buffer at once to make + it in-place. */ + { + kiss_fft_scalar * OPUS_RESTRICT yp0 = out+(overlap>>1); + kiss_fft_scalar * OPUS_RESTRICT yp1 = out+(overlap>>1)+N2-2; + const kiss_twiddle_scalar *t = &l->trig[0]; + /* Loop to (N4+1)>>1 to handle odd N4. When N4 is odd, the + middle pair will be computed twice. */ + for(i=0;i<(N4+1)>>1;i++) + { + kiss_fft_scalar re, im, yr, yi; + kiss_twiddle_scalar t0, t1; + re = yp0[0]; + im = yp0[1]; + t0 = t[i<>EC_SYM_BITS) +/*The number of bits available for the last, partial symbol in the code field.*/ +# define EC_CODE_EXTRA ((EC_CODE_BITS-2)%EC_SYM_BITS+1) +#endif diff --git a/TelegramClient.Opus/opus/celt/modes.c b/TelegramClient.Opus/opus/celt/modes.c new file mode 100755 index 0000000..42e68e1 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/modes.c @@ -0,0 +1,438 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Copyright (c) 2008 Gregory Maxwell + Written by Jean-Marc Valin and Gregory Maxwell */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "celt.h" +#include "modes.h" +#include "rate.h" +#include "os_support.h" +#include "stack_alloc.h" +#include "quant_bands.h" + +static const opus_int16 eband5ms[] = { +/*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 34, 40, 48, 60, 78, 100 +}; + +/* Alternate tuning (partially derived from Vorbis) */ +#define BITALLOC_SIZE 11 +/* Bit allocation table in units of 1/32 bit/sample (0.1875 dB SNR) */ +static const unsigned char band_allocation[] = { +/*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 90, 80, 75, 69, 63, 56, 49, 40, 34, 29, 20, 18, 10, 0, 0, 0, 0, 0, 0, 0, 0, +110,100, 90, 84, 78, 71, 65, 58, 51, 45, 39, 32, 26, 20, 12, 0, 0, 0, 0, 0, 0, +118,110,103, 93, 86, 80, 75, 70, 65, 59, 53, 47, 40, 31, 23, 15, 4, 0, 0, 0, 0, +126,119,112,104, 95, 89, 83, 78, 72, 66, 60, 54, 47, 39, 32, 25, 17, 12, 1, 0, 0, +134,127,120,114,103, 97, 91, 85, 78, 72, 66, 60, 54, 47, 41, 35, 29, 23, 16, 10, 1, +144,137,130,124,113,107,101, 95, 88, 82, 76, 70, 64, 57, 51, 45, 39, 33, 26, 15, 1, +152,145,138,132,123,117,111,105, 98, 92, 86, 80, 74, 67, 61, 55, 49, 43, 36, 20, 1, +162,155,148,142,133,127,121,115,108,102, 96, 90, 84, 77, 71, 65, 59, 53, 46, 30, 1, +172,165,158,152,143,137,131,125,118,112,106,100, 94, 87, 81, 75, 69, 63, 56, 45, 20, +200,200,200,200,200,200,200,200,198,193,188,183,178,173,168,163,158,153,148,129,104, +}; + +#ifndef CUSTOM_MODES_ONLY + #ifdef FIXED_POINT + #include "static_modes_fixed.h" + #else + #include "static_modes_float.h" + #endif +#endif /* CUSTOM_MODES_ONLY */ + +#ifndef M_PI +#define M_PI 3.141592653 +#endif + +#ifdef CUSTOM_MODES + +/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth + Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */ +#define BARK_BANDS 25 +static const opus_int16 bark_freq[BARK_BANDS+1] = { + 0, 100, 200, 300, 400, + 510, 630, 770, 920, 1080, + 1270, 1480, 1720, 2000, 2320, + 2700, 3150, 3700, 4400, 5300, + 6400, 7700, 9500, 12000, 15500, + 20000}; + +static opus_int16 *compute_ebands(opus_int32 Fs, int frame_size, int res, int *nbEBands) +{ + opus_int16 *eBands; + int i, j, lin, low, high, nBark, offset=0; + + /* All modes that have 2.5 ms short blocks use the same definition */ + if (Fs == 400*(opus_int32)frame_size) + { + *nbEBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1; + eBands = opus_alloc(sizeof(opus_int16)*(*nbEBands+1)); + for (i=0;i<*nbEBands+1;i++) + eBands[i] = eband5ms[i]; + return eBands; + } + /* Find the number of critical bands supported by our sampling rate */ + for (nBark=1;nBark= Fs) + break; + + /* Find where the linear part ends (i.e. where the spacing is more than min_width */ + for (lin=0;lin= res) + break; + + low = (bark_freq[lin]+res/2)/res; + high = nBark-lin; + *nbEBands = low+high; + eBands = opus_alloc(sizeof(opus_int16)*(*nbEBands+2)); + + if (eBands==NULL) + return NULL; + + /* Linear spacing (min_width) */ + for (i=0;i0) + offset = eBands[low-1]*res - bark_freq[lin-1]; + /* Spacing follows critical bands */ + for (i=0;i frame_size) + eBands[*nbEBands] = frame_size; + for (i=1;i<*nbEBands-1;i++) + { + if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1]) + { + eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1])/2; + } + } + /* Remove any empty bands. */ + for (i=j=0;i<*nbEBands;i++) + if(eBands[i+1]>eBands[j]) + eBands[++j]=eBands[i+1]; + *nbEBands=j; + + for (i=1;i<*nbEBands;i++) + { + /* Every band must be smaller than the last band. */ + celt_assert(eBands[i]-eBands[i-1]<=eBands[*nbEBands]-eBands[*nbEBands-1]); + /* Each band must be no larger than twice the size of the previous one. */ + celt_assert(eBands[i+1]-eBands[i]<=2*(eBands[i]-eBands[i-1])); + } + + return eBands; +} + +static void compute_allocation_table(CELTMode *mode) +{ + int i, j; + unsigned char *allocVectors; + int maxBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1; + + mode->nbAllocVectors = BITALLOC_SIZE; + allocVectors = opus_alloc(sizeof(unsigned char)*(BITALLOC_SIZE*mode->nbEBands)); + if (allocVectors==NULL) + return; + + /* Check for standard mode */ + if (mode->Fs == 400*(opus_int32)mode->shortMdctSize) + { + for (i=0;inbEBands;i++) + allocVectors[i] = band_allocation[i]; + mode->allocVectors = allocVectors; + return; + } + /* If not the standard mode, interpolate */ + /* Compute per-codec-band allocation from per-critical-band matrix */ + for (i=0;inbEBands;j++) + { + int k; + for (k=0;k mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize) + break; + } + if (k>maxBands-1) + allocVectors[i*mode->nbEBands+j] = band_allocation[i*maxBands + maxBands-1]; + else { + opus_int32 a0, a1; + a1 = mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize - 400*(opus_int32)eband5ms[k-1]; + a0 = 400*(opus_int32)eband5ms[k] - mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize; + allocVectors[i*mode->nbEBands+j] = (a0*band_allocation[i*maxBands+k-1] + + a1*band_allocation[i*maxBands+k])/(a0+a1); + } + } + } + + /*printf ("\n"); + for (i=0;inbEBands;j++) + printf ("%d ", allocVectors[i*mode->nbEBands+j]); + printf ("\n"); + } + exit(0);*/ + + mode->allocVectors = allocVectors; +} + +#endif /* CUSTOM_MODES */ + +CELTMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error) +{ + int i; +#ifdef CUSTOM_MODES + CELTMode *mode=NULL; + int res; + opus_val16 *window; + opus_int16 *logN; + int LM; + ALLOC_STACK; +#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA) + if (global_stack==NULL) + goto failure; +#endif +#endif + +#ifndef CUSTOM_MODES_ONLY + for (i=0;iFs && + (frame_size<shortMdctSize*static_mode_list[i]->nbShortMdcts) + { + if (error) + *error = OPUS_OK; + return (CELTMode*)static_mode_list[i]; + } + } + } +#endif /* CUSTOM_MODES_ONLY */ + +#ifndef CUSTOM_MODES + if (error) + *error = OPUS_BAD_ARG; + return NULL; +#else + + /* The good thing here is that permutation of the arguments will automatically be invalid */ + + if (Fs < 8000 || Fs > 96000) + { + if (error) + *error = OPUS_BAD_ARG; + return NULL; + } + if (frame_size < 40 || frame_size > 1024 || frame_size%2!=0) + { + if (error) + *error = OPUS_BAD_ARG; + return NULL; + } + /* Frames of less than 1ms are not supported. */ + if ((opus_int32)frame_size*1000 < Fs) + { + if (error) + *error = OPUS_BAD_ARG; + return NULL; + } + + if ((opus_int32)frame_size*75 >= Fs && (frame_size%16)==0) + { + LM = 3; + } else if ((opus_int32)frame_size*150 >= Fs && (frame_size%8)==0) + { + LM = 2; + } else if ((opus_int32)frame_size*300 >= Fs && (frame_size%4)==0) + { + LM = 1; + } else + { + LM = 0; + } + + /* Shorts longer than 3.3ms are not supported. */ + if ((opus_int32)(frame_size>>LM)*300 > Fs) + { + if (error) + *error = OPUS_BAD_ARG; + return NULL; + } + + mode = opus_alloc(sizeof(CELTMode)); + if (mode==NULL) + goto failure; + mode->Fs = Fs; + + /* Pre/de-emphasis depends on sampling rate. The "standard" pre-emphasis + is defined as A(z) = 1 - 0.85*z^-1 at 48 kHz. Other rates should + approximate that. */ + if(Fs < 12000) /* 8 kHz */ + { + mode->preemph[0] = QCONST16(0.3500061035f, 15); + mode->preemph[1] = -QCONST16(0.1799926758f, 15); + mode->preemph[2] = QCONST16(0.2719968125f, SIG_SHIFT); /* exact 1/preemph[3] */ + mode->preemph[3] = QCONST16(3.6765136719f, 13); + } else if(Fs < 24000) /* 16 kHz */ + { + mode->preemph[0] = QCONST16(0.6000061035f, 15); + mode->preemph[1] = -QCONST16(0.1799926758f, 15); + mode->preemph[2] = QCONST16(0.4424998650f, SIG_SHIFT); /* exact 1/preemph[3] */ + mode->preemph[3] = QCONST16(2.2598876953f, 13); + } else if(Fs < 40000) /* 32 kHz */ + { + mode->preemph[0] = QCONST16(0.7799987793f, 15); + mode->preemph[1] = -QCONST16(0.1000061035f, 15); + mode->preemph[2] = QCONST16(0.7499771125f, SIG_SHIFT); /* exact 1/preemph[3] */ + mode->preemph[3] = QCONST16(1.3333740234f, 13); + } else /* 48 kHz */ + { + mode->preemph[0] = QCONST16(0.8500061035f, 15); + mode->preemph[1] = QCONST16(0.0f, 15); + mode->preemph[2] = QCONST16(1.f, SIG_SHIFT); + mode->preemph[3] = QCONST16(1.f, 13); + } + + mode->maxLM = LM; + mode->nbShortMdcts = 1<shortMdctSize = frame_size/mode->nbShortMdcts; + res = (mode->Fs+mode->shortMdctSize)/(2*mode->shortMdctSize); + + mode->eBands = compute_ebands(Fs, mode->shortMdctSize, res, &mode->nbEBands); + if (mode->eBands==NULL) + goto failure; +#if !defined(SMALL_FOOTPRINT) + /* Make sure we don't allocate a band larger than our PVQ table. + 208 should be enough, but let's be paranoid. */ + if ((mode->eBands[mode->nbEBands] - mode->eBands[mode->nbEBands-1])< + 208) { + goto failure; + } +#endif + + mode->effEBands = mode->nbEBands; + while (mode->eBands[mode->effEBands] > mode->shortMdctSize) + mode->effEBands--; + + /* Overlap must be divisible by 4 */ + mode->overlap = ((mode->shortMdctSize>>2)<<2); + + compute_allocation_table(mode); + if (mode->allocVectors==NULL) + goto failure; + + window = (opus_val16*)opus_alloc(mode->overlap*sizeof(opus_val16)); + if (window==NULL) + goto failure; + +#ifndef FIXED_POINT + for (i=0;ioverlap;i++) + window[i] = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap)); +#else + for (i=0;ioverlap;i++) + window[i] = MIN32(32767,floor(.5+32768.*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap)))); +#endif + mode->window = window; + + logN = (opus_int16*)opus_alloc(mode->nbEBands*sizeof(opus_int16)); + if (logN==NULL) + goto failure; + + for (i=0;inbEBands;i++) + logN[i] = log2_frac(mode->eBands[i+1]-mode->eBands[i], BITRES); + mode->logN = logN; + + compute_pulse_cache(mode, mode->maxLM); + + if (clt_mdct_init(&mode->mdct, 2*mode->shortMdctSize*mode->nbShortMdcts, + mode->maxLM) == 0) + goto failure; + + if (error) + *error = OPUS_OK; + + return mode; +failure: + if (error) + *error = OPUS_ALLOC_FAIL; + if (mode!=NULL) + opus_custom_mode_destroy(mode); + return NULL; +#endif /* !CUSTOM_MODES */ +} + +#ifdef CUSTOM_MODES +void opus_custom_mode_destroy(CELTMode *mode) +{ + if (mode == NULL) + return; +#ifndef CUSTOM_MODES_ONLY + { + int i; + for (i=0;ieBands); + opus_free((opus_int16*)mode->allocVectors); + + opus_free((opus_val16*)mode->window); + opus_free((opus_int16*)mode->logN); + + opus_free((opus_int16*)mode->cache.index); + opus_free((unsigned char*)mode->cache.bits); + opus_free((unsigned char*)mode->cache.caps); + clt_mdct_clear(&mode->mdct); + + opus_free((CELTMode *)mode); +} +#endif diff --git a/TelegramClient.Opus/opus/celt/modes.h b/TelegramClient.Opus/opus/celt/modes.h new file mode 100755 index 0000000..c8340f9 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/modes.h @@ -0,0 +1,83 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Copyright (c) 2008 Gregory Maxwell + Written by Jean-Marc Valin and Gregory Maxwell */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef MODES_H +#define MODES_H + +#include "opus_types.h" +#include "celt.h" +#include "arch.h" +#include "mdct.h" +#include "entenc.h" +#include "entdec.h" + +#define MAX_PERIOD 1024 + +#ifndef OVERLAP +#define OVERLAP(mode) ((mode)->overlap) +#endif + +#ifndef FRAMESIZE +#define FRAMESIZE(mode) ((mode)->mdctSize) +#endif + +typedef struct { + int size; + const opus_int16 *index; + const unsigned char *bits; + const unsigned char *caps; +} PulseCache; + +/** Mode definition (opaque) + @brief Mode definition + */ +struct OpusCustomMode { + opus_int32 Fs; + int overlap; + + int nbEBands; + int effEBands; + opus_val16 preemph[4]; + const opus_int16 *eBands; /**< Definition for each "pseudo-critical band" */ + + int maxLM; + int nbShortMdcts; + int shortMdctSize; + + int nbAllocVectors; /**< Number of lines in the matrix below */ + const unsigned char *allocVectors; /**< Number of bits in each band for several rates */ + const opus_int16 *logN; + + const opus_val16 *window; + mdct_lookup mdct; + PulseCache cache; +}; + + +#endif diff --git a/TelegramClient.Opus/opus/celt/os_support.h b/TelegramClient.Opus/opus/celt/os_support.h new file mode 100755 index 0000000..5e47e3c --- /dev/null +++ b/TelegramClient.Opus/opus/celt/os_support.h @@ -0,0 +1,92 @@ +/* Copyright (C) 2007 Jean-Marc Valin + + File: os_support.h + This is the (tiny) OS abstraction layer. Aside from math.h, this is the + only place where system headers are allowed. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +*/ + +#ifndef OS_SUPPORT_H +#define OS_SUPPORT_H + +#ifdef CUSTOM_SUPPORT +# include "custom_support.h" +#endif + +#include "opus_types.h" +#include "opus_defines.h" + +#include +#include +#include + +/** Opus wrapper for malloc(). To do your own dynamic allocation, all you need to do is replace this function and opus_free */ +#ifndef OVERRIDE_OPUS_ALLOC +static OPUS_INLINE void *opus_alloc (size_t size) +{ + return malloc(size); +} +#endif + +/** Same as celt_alloc(), except that the area is only needed inside a CELT call (might cause problem with wideband though) */ +#ifndef OVERRIDE_OPUS_ALLOC_SCRATCH +static OPUS_INLINE void *opus_alloc_scratch (size_t size) +{ + /* Scratch space doesn't need to be cleared */ + return opus_alloc(size); +} +#endif + +/** Opus wrapper for free(). To do your own dynamic allocation, all you need to do is replace this function and opus_alloc */ +#ifndef OVERRIDE_OPUS_FREE +static OPUS_INLINE void opus_free (void *ptr) +{ + free(ptr); +} +#endif + +/** Copy n bytes of memory from src to dst. The 0* term provides compile-time type checking */ +#ifndef OVERRIDE_OPUS_COPY +#define OPUS_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) +#endif + +/** Copy n bytes of memory from src to dst, allowing overlapping regions. The 0* term + provides compile-time type checking */ +#ifndef OVERRIDE_OPUS_MOVE +#define OPUS_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) +#endif + +/** Set n elements of dst to zero, starting at address s */ +#ifndef OVERRIDE_OPUS_CLEAR +#define OPUS_CLEAR(dst, n) (memset((dst), 0, (n)*sizeof(*(dst)))) +#endif + +/*#ifdef __GNUC__ +#pragma GCC poison printf sprintf +#pragma GCC poison malloc free realloc calloc +#endif*/ + +#endif /* OS_SUPPORT_H */ + diff --git a/TelegramClient.Opus/opus/celt/pitch.c b/TelegramClient.Opus/opus/celt/pitch.c new file mode 100755 index 0000000..327f055 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/pitch.c @@ -0,0 +1,538 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/** + @file pitch.c + @brief Pitch analysis + */ + +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pitch.h" +#include "os_support.h" +#include "modes.h" +#include "stack_alloc.h" +#include "mathops.h" +#include "celt_lpc.h" + + +static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len, + int max_pitch, int *best_pitch +#ifdef FIXED_POINT + , int yshift, opus_val32 maxcorr +#endif + ) +{ + int i, j; + opus_val32 Syy=1; + opus_val16 best_num[2]; + opus_val32 best_den[2]; +#ifdef FIXED_POINT + int xshift; + + xshift = celt_ilog2(maxcorr)-14; +#endif + + best_num[0] = -1; + best_num[1] = -1; + best_den[0] = 0; + best_den[1] = 0; + best_pitch[0] = 0; + best_pitch[1] = 1; + for (j=0;j0) + { + opus_val16 num; + opus_val32 xcorr16; + xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift)); +#ifndef FIXED_POINT + /* Considering the range of xcorr16, this should avoid both underflows + and overflows (inf) when squaring xcorr16 */ + xcorr16 *= 1e-12f; +#endif + num = MULT16_16_Q15(xcorr16,xcorr16); + if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy)) + { + if (MULT16_32_Q15(num,best_den[0]) > MULT16_32_Q15(best_num[0],Syy)) + { + best_num[1] = best_num[0]; + best_den[1] = best_den[0]; + best_pitch[1] = best_pitch[0]; + best_num[0] = num; + best_den[0] = Syy; + best_pitch[0] = i; + } else { + best_num[1] = num; + best_den[1] = Syy; + best_pitch[1] = i; + } + } + } + Syy += SHR32(MULT16_16(y[i+len],y[i+len]),yshift) - SHR32(MULT16_16(y[i],y[i]),yshift); + Syy = MAX32(1, Syy); + } +} + +static void celt_fir5(const opus_val16 *x, + const opus_val16 *num, + opus_val16 *y, + int N, + opus_val16 *mem) +{ + int i; + opus_val16 num0, num1, num2, num3, num4; + opus_val32 mem0, mem1, mem2, mem3, mem4; + num0=num[0]; + num1=num[1]; + num2=num[2]; + num3=num[3]; + num4=num[4]; + mem0=mem[0]; + mem1=mem[1]; + mem2=mem[2]; + mem3=mem[3]; + mem4=mem[4]; + for (i=0;i>1;i++) + x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), shift); + x_lp[0] = SHR32(HALF32(HALF32(x[0][1])+x[0][0]), shift); + if (C==2) + { + for (i=1;i>1;i++) + x_lp[i] += SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), shift); + x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), shift); + } + + _celt_autocorr(x_lp, ac, NULL, 0, + 4, len>>1, arch); + + /* Noise floor -40 dB */ +#ifdef FIXED_POINT + ac[0] += SHR32(ac[0],13); +#else + ac[0] *= 1.0001f; +#endif + /* Lag windowing */ + for (i=1;i<=4;i++) + { + /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/ +#ifdef FIXED_POINT + ac[i] -= MULT16_32_Q15(2*i*i, ac[i]); +#else + ac[i] -= ac[i]*(.008f*i)*(.008f*i); +#endif + } + + _celt_lpc(lpc, ac, 4); + for (i=0;i<4;i++) + { + tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp); + lpc[i] = MULT16_16_Q15(lpc[i], tmp); + } + /* Add a zero */ + lpc2[0] = lpc[0] + QCONST16(.8f,SIG_SHIFT); + lpc2[1] = lpc[1] + MULT16_16_Q15(c1,lpc[0]); + lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]); + lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]); + lpc2[4] = MULT16_16_Q15(c1,lpc[3]); + celt_fir5(x_lp, lpc2, x_lp, len>>1, mem); +} + +#if 0 /* This is a simple version of the pitch correlation that should work + well on DSPs like Blackfin and TI C5x/C6x */ + +#ifdef FIXED_POINT +opus_val32 +#else +void +#endif +celt_pitch_xcorr(opus_val16 *x, opus_val16 *y, opus_val32 *xcorr, int len, int max_pitch) +{ + int i, j; +#ifdef FIXED_POINT + opus_val32 maxcorr=1; +#endif + for (i=0;i0); + //celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0); +#ifdef FIXED_POINT + opus_val32 maxcorr=1; +#endif + for (i=0;i0); + celt_assert(max_pitch>0); + lag = len+max_pitch; + + ALLOC(x_lp4, len>>2, opus_val16); + ALLOC(y_lp4, lag>>2, opus_val16); + ALLOC(xcorr, max_pitch>>1, opus_val32); + + /* Downsample by 2 again */ + for (j=0;j>2;j++) + x_lp4[j] = x_lp[2*j]; + for (j=0;j>2;j++) + y_lp4[j] = y[2*j]; + +#ifdef FIXED_POINT + xmax = celt_maxabs16(x_lp4, len>>2); + ymax = celt_maxabs16(y_lp4, lag>>2); + shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax)))-11; + if (shift>0) + { + for (j=0;j>2;j++) + x_lp4[j] = SHR16(x_lp4[j], shift); + for (j=0;j>2;j++) + y_lp4[j] = SHR16(y_lp4[j], shift); + /* Use double the shift for a MAC */ + shift *= 2; + } else { + shift = 0; + } +#endif + + /* Coarse search with 4x decimation */ + +#ifdef FIXED_POINT + maxcorr = +#endif + celt_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2, arch); + + find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch +#ifdef FIXED_POINT + , 0, maxcorr +#endif + ); + + /* Finer search with 2x decimation */ +#ifdef FIXED_POINT + maxcorr=1; +#endif + for (i=0;i>1;i++) + { + opus_val32 sum=0; + xcorr[i] = 0; + if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2) + continue; + for (j=0;j>1;j++) + sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift); + xcorr[i] = MAX32(-1, sum); +#ifdef FIXED_POINT + maxcorr = MAX32(maxcorr, sum); +#endif + } + find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch +#ifdef FIXED_POINT + , shift+1, maxcorr +#endif + ); + + /* Refine by pseudo-interpolation */ + if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1) + { + opus_val32 a, b, c; + a = xcorr[best_pitch[0]-1]; + b = xcorr[best_pitch[0]]; + c = xcorr[best_pitch[0]+1]; + if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a)) + offset = 1; + else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c)) + offset = -1; + else + offset = 0; + } else { + offset = 0; + } + *pitch = 2*best_pitch[0]-offset; + + RESTORE_STACK; +} + +static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2}; +opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod, + int N, int *T0_, int prev_period, opus_val16 prev_gain) +{ + int k, i, T, T0; + opus_val16 g, g0; + opus_val16 pg; + opus_val32 xy,xx,yy,xy2; + opus_val32 xcorr[3]; + opus_val32 best_xy, best_yy; + int offset; + int minperiod0; + VARDECL(opus_val32, yy_lookup); + SAVE_STACK; + + minperiod0 = minperiod; + maxperiod /= 2; + minperiod /= 2; + *T0_ /= 2; + prev_period /= 2; + N /= 2; + x += maxperiod; + if (*T0_>=maxperiod) + *T0_=maxperiod-1; + + T = T0 = *T0_; + ALLOC(yy_lookup, maxperiod+1, opus_val32); + dual_inner_prod(x, x, x-T0, N, &xx, &xy); + yy_lookup[0] = xx; + yy=xx; + for (i=1;i<=maxperiod;i++) + { + yy = yy+MULT16_16(x[-i],x[-i])-MULT16_16(x[N-i],x[N-i]); + yy_lookup[i] = MAX32(0, yy); + } + yy = yy_lookup[T0]; + best_xy = xy; + best_yy = yy; +#ifdef FIXED_POINT + { + opus_val32 x2y2; + int sh, t; + x2y2 = 1+HALF32(MULT32_32_Q31(xx,yy)); + sh = celt_ilog2(x2y2)>>1; + t = VSHR32(x2y2, 2*(sh-7)); + g = g0 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1); + } +#else + g = g0 = xy/celt_sqrt(1+xx*yy); +#endif + /* Look for any pitch at T/k */ + for (k=2;k<=15;k++) + { + int T1, T1b; + opus_val16 g1; + opus_val16 cont=0; + opus_val16 thresh; + T1 = (2*T0+k)/(2*k); + if (T1 < minperiod) + break; + /* Look for another strong correlation at T1b */ + if (k==2) + { + if (T1+T0>maxperiod) + T1b = T0; + else + T1b = T0+T1; + } else + { + T1b = (2*second_check[k]*T0+k)/(2*k); + } + dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2); + xy += xy2; + yy = yy_lookup[T1] + yy_lookup[T1b]; +#ifdef FIXED_POINT + { + opus_val32 x2y2; + int sh, t; + x2y2 = 1+MULT32_32_Q31(xx,yy); + sh = celt_ilog2(x2y2)>>1; + t = VSHR32(x2y2, 2*(sh-7)); + g1 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1); + } +#else + g1 = xy/celt_sqrt(1+2.f*xx*1.f*yy); +#endif + if (abs(T1-prev_period)<=1) + cont = prev_gain; + else if (abs(T1-prev_period)<=2 && 5*k*k < T0) + cont = HALF32(prev_gain); + else + cont = 0; + thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont); + /* Bias against very high pitch (very short period) to avoid false-positives + due to short-term correlation */ + if (T1<3*minperiod) + thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont); + else if (T1<2*minperiod) + thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont); + if (g1 > thresh) + { + best_xy = xy; + best_yy = yy; + T = T1; + g = g1; + } + } + best_xy = MAX32(0, best_xy); + if (best_yy <= best_xy) + pg = Q15ONE; + else + pg = SHR32(frac_div32(best_xy,best_yy+1),16); + + for (k=0;k<3;k++) + { + int T1 = T+k-1; + xy = 0; + for (i=0;i MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0])) + offset = 1; + else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2])) + offset = -1; + else + offset = 0; + if (pg > g) + pg = g; + *T0_ = 2*T+offset; + + if (*T0_=3); + y_3=0; /* gcc doesn't realize that y_3 can't be used uninitialized */ + y_0=*y++; + y_1=*y++; + y_2=*y++; + for (j=0;j +#include "os_support.h" +#include "arch.h" +#include "mathops.h" +#include "stack_alloc.h" +#include "rate.h" + +#ifdef FIXED_POINT +/* Mean energy in each band quantized in Q4 */ +const signed char eMeans[25] = { + 103,100, 92, 85, 81, + 77, 72, 70, 78, 75, + 73, 71, 78, 74, 69, + 72, 70, 74, 76, 71, + 60, 60, 60, 60, 60 +}; +#else +/* Mean energy in each band quantized in Q4 and converted back to float */ +const opus_val16 eMeans[25] = { + 6.437500f, 6.250000f, 5.750000f, 5.312500f, 5.062500f, + 4.812500f, 4.500000f, 4.375000f, 4.875000f, 4.687500f, + 4.562500f, 4.437500f, 4.875000f, 4.625000f, 4.312500f, + 4.500000f, 4.375000f, 4.625000f, 4.750000f, 4.437500f, + 3.750000f, 3.750000f, 3.750000f, 3.750000f, 3.750000f +}; +#endif +/* prediction coefficients: 0.9, 0.8, 0.65, 0.5 */ +#ifdef FIXED_POINT +static const opus_val16 pred_coef[4] = {29440, 26112, 21248, 16384}; +static const opus_val16 beta_coef[4] = {30147, 22282, 12124, 6554}; +static const opus_val16 beta_intra = 4915; +#else +static const opus_val16 pred_coef[4] = {29440/32768., 26112/32768., 21248/32768., 16384/32768.}; +static const opus_val16 beta_coef[4] = {30147/32768., 22282/32768., 12124/32768., 6554/32768.}; +static const opus_val16 beta_intra = 4915/32768.; +#endif + +/*Parameters of the Laplace-like probability models used for the coarse energy. + There is one pair of parameters for each frame size, prediction type + (inter/intra), and band number. + The first number of each pair is the probability of 0, and the second is the + decay rate, both in Q8 precision.*/ +static const unsigned char e_prob_model[4][2][42] = { + /*120 sample frames.*/ + { + /*Inter*/ + { + 72, 127, 65, 129, 66, 128, 65, 128, 64, 128, 62, 128, 64, 128, + 64, 128, 92, 78, 92, 79, 92, 78, 90, 79, 116, 41, 115, 40, + 114, 40, 132, 26, 132, 26, 145, 17, 161, 12, 176, 10, 177, 11 + }, + /*Intra*/ + { + 24, 179, 48, 138, 54, 135, 54, 132, 53, 134, 56, 133, 55, 132, + 55, 132, 61, 114, 70, 96, 74, 88, 75, 88, 87, 74, 89, 66, + 91, 67, 100, 59, 108, 50, 120, 40, 122, 37, 97, 43, 78, 50 + } + }, + /*240 sample frames.*/ + { + /*Inter*/ + { + 83, 78, 84, 81, 88, 75, 86, 74, 87, 71, 90, 73, 93, 74, + 93, 74, 109, 40, 114, 36, 117, 34, 117, 34, 143, 17, 145, 18, + 146, 19, 162, 12, 165, 10, 178, 7, 189, 6, 190, 8, 177, 9 + }, + /*Intra*/ + { + 23, 178, 54, 115, 63, 102, 66, 98, 69, 99, 74, 89, 71, 91, + 73, 91, 78, 89, 86, 80, 92, 66, 93, 64, 102, 59, 103, 60, + 104, 60, 117, 52, 123, 44, 138, 35, 133, 31, 97, 38, 77, 45 + } + }, + /*480 sample frames.*/ + { + /*Inter*/ + { + 61, 90, 93, 60, 105, 42, 107, 41, 110, 45, 116, 38, 113, 38, + 112, 38, 124, 26, 132, 27, 136, 19, 140, 20, 155, 14, 159, 16, + 158, 18, 170, 13, 177, 10, 187, 8, 192, 6, 175, 9, 159, 10 + }, + /*Intra*/ + { + 21, 178, 59, 110, 71, 86, 75, 85, 84, 83, 91, 66, 88, 73, + 87, 72, 92, 75, 98, 72, 105, 58, 107, 54, 115, 52, 114, 55, + 112, 56, 129, 51, 132, 40, 150, 33, 140, 29, 98, 35, 77, 42 + } + }, + /*960 sample frames.*/ + { + /*Inter*/ + { + 42, 121, 96, 66, 108, 43, 111, 40, 117, 44, 123, 32, 120, 36, + 119, 33, 127, 33, 134, 34, 139, 21, 147, 23, 152, 20, 158, 25, + 154, 26, 166, 21, 173, 16, 184, 13, 184, 10, 150, 13, 139, 15 + }, + /*Intra*/ + { + 22, 178, 63, 114, 74, 82, 84, 83, 92, 82, 103, 62, 96, 72, + 96, 67, 101, 73, 107, 72, 113, 55, 118, 52, 125, 52, 118, 52, + 117, 55, 135, 49, 137, 39, 157, 32, 145, 29, 97, 33, 77, 40 + } + } +}; + +static const unsigned char small_energy_icdf[3]={2,1,0}; + +static opus_val32 loss_distortion(const opus_val16 *eBands, opus_val16 *oldEBands, int start, int end, int len, int C) +{ + int c, i; + opus_val32 dist = 0; + c=0; do { + for (i=start;inbEBands]; + oldE = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]); +#ifdef FIXED_POINT + f = SHL32(EXTEND32(x),7) - PSHR32(MULT16_16(coef,oldE), 8) - prev[c]; + /* Rounding to nearest integer here is really important! */ + qi = (f+QCONST32(.5f,DB_SHIFT+7))>>(DB_SHIFT+7); + decay_bound = EXTRACT16(MAX32(-QCONST16(28.f,DB_SHIFT), + SUB32((opus_val32)oldEBands[i+c*m->nbEBands],max_decay))); +#else + f = x-coef*oldE-prev[c]; + /* Rounding to nearest integer here is really important! */ + qi = (int)floor(.5f+f); + decay_bound = MAX16(-QCONST16(28.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]) - max_decay; +#endif + /* Prevent the energy from going down too quickly (e.g. for bands + that have just one bin) */ + if (qi < 0 && x < decay_bound) + { + qi += (int)SHR16(SUB16(decay_bound,x), DB_SHIFT); + if (qi > 0) + qi = 0; + } + qi0 = qi; + /* If we don't have enough bits to encode all the energy, just assume + something safe. */ + tell = ec_tell(enc); + bits_left = budget-tell-3*C*(end-i); + if (i!=start && bits_left < 30) + { + if (bits_left < 24) + qi = IMIN(1, qi); + if (bits_left < 16) + qi = IMAX(-1, qi); + } + if (lfe && i>=2) + qi = IMIN(qi, 0); + if (budget-tell >= 15) + { + int pi; + pi = 2*IMIN(i,20); + ec_laplace_encode(enc, &qi, + prob_model[pi]<<7, prob_model[pi+1]<<6); + } + else if(budget-tell >= 2) + { + qi = IMAX(-1, IMIN(qi, 1)); + ec_enc_icdf(enc, 2*qi^-(qi<0), small_energy_icdf, 2); + } + else if(budget-tell >= 1) + { + qi = IMIN(0, qi); + ec_enc_bit_logp(enc, -qi, 1); + } + else + qi = -1; + error[i+c*m->nbEBands] = PSHR32(f,7) - SHL16(qi,DB_SHIFT); + badness += abs(qi0-qi); + q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT); + + tmp = PSHR32(MULT16_16(coef,oldE),8) + prev[c] + SHL32(q,7); +#ifdef FIXED_POINT + tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp); +#endif + oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7); + prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8)); + } while (++c < C); + } + return lfe ? 0 : badness; +} + +void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, + const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget, + opus_val16 *error, ec_enc *enc, int C, int LM, int nbAvailableBytes, + int force_intra, opus_val32 *delayedIntra, int two_pass, int loss_rate, int lfe) +{ + int intra; + opus_val16 max_decay; + VARDECL(opus_val16, oldEBands_intra); + VARDECL(opus_val16, error_intra); + ec_enc enc_start_state; + opus_uint32 tell; + int badness1=0; + opus_int32 intra_bias; + opus_val32 new_distortion; + SAVE_STACK; + + intra = force_intra || (!two_pass && *delayedIntra>2*C*(end-start) && nbAvailableBytes > (end-start)*C); + intra_bias = (opus_int32)((budget**delayedIntra*loss_rate)/(C*512)); + new_distortion = loss_distortion(eBands, oldEBands, start, effEnd, m->nbEBands, C); + + tell = ec_tell(enc); + if (tell+3 > budget) + two_pass = intra = 0; + + max_decay = QCONST16(16.f,DB_SHIFT); + if (end-start>10) + { +#ifdef FIXED_POINT + max_decay = MIN32(max_decay, SHL32(EXTEND32(nbAvailableBytes),DB_SHIFT-3)); +#else + max_decay = MIN32(max_decay, .125f*nbAvailableBytes); +#endif + } + if (lfe) + max_decay=3; + enc_start_state = *enc; + + ALLOC(oldEBands_intra, C*m->nbEBands, opus_val16); + ALLOC(error_intra, C*m->nbEBands, opus_val16); + OPUS_COPY(oldEBands_intra, oldEBands, C*m->nbEBands); + + if (two_pass || intra) + { + badness1 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands_intra, budget, + tell, e_prob_model[LM][1], error_intra, enc, C, LM, 1, max_decay, lfe); + } + + if (!intra) + { + unsigned char *intra_buf; + ec_enc enc_intra_state; + opus_int32 tell_intra; + opus_uint32 nstart_bytes; + opus_uint32 nintra_bytes; + opus_uint32 save_bytes; + int badness2; + VARDECL(unsigned char, intra_bits); + + tell_intra = ec_tell_frac(enc); + + enc_intra_state = *enc; + + nstart_bytes = ec_range_bytes(&enc_start_state); + nintra_bytes = ec_range_bytes(&enc_intra_state); + intra_buf = ec_get_buffer(&enc_intra_state) + nstart_bytes; + save_bytes = nintra_bytes-nstart_bytes; + if (save_bytes == 0) + save_bytes = ALLOC_NONE; + ALLOC(intra_bits, save_bytes, unsigned char); + /* Copy bits from intra bit-stream */ + OPUS_COPY(intra_bits, intra_buf, nintra_bytes - nstart_bytes); + + *enc = enc_start_state; + + badness2 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands, budget, + tell, e_prob_model[LM][intra], error, enc, C, LM, 0, max_decay, lfe); + + if (two_pass && (badness1 < badness2 || (badness1 == badness2 && ((opus_int32)ec_tell_frac(enc))+intra_bias > tell_intra))) + { + *enc = enc_intra_state; + /* Copy intra bits to bit-stream */ + OPUS_COPY(intra_buf, intra_bits, nintra_bytes - nstart_bytes); + OPUS_COPY(oldEBands, oldEBands_intra, C*m->nbEBands); + OPUS_COPY(error, error_intra, C*m->nbEBands); + intra = 1; + } + } else { + OPUS_COPY(oldEBands, oldEBands_intra, C*m->nbEBands); + OPUS_COPY(error, error_intra, C*m->nbEBands); + } + + if (intra) + *delayedIntra = new_distortion; + else + *delayedIntra = ADD32(MULT16_32_Q15(MULT16_16_Q15(pred_coef[LM], pred_coef[LM]),*delayedIntra), + new_distortion); + + RESTORE_STACK; +} + +void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C) +{ + int i, c; + + /* Encode finer resolution */ + for (i=start;inbEBands]+QCONST16(.5f,DB_SHIFT))>>(DB_SHIFT-fine_quant[i]); +#else + q2 = (int)floor((error[i+c*m->nbEBands]+.5f)*frac); +#endif + if (q2 > frac-1) + q2 = frac-1; + if (q2<0) + q2 = 0; + ec_enc_bits(enc, q2, fine_quant[i]); +#ifdef FIXED_POINT + offset = SUB16(SHR32(SHL32(EXTEND32(q2),DB_SHIFT)+QCONST16(.5f,DB_SHIFT),fine_quant[i]),QCONST16(.5f,DB_SHIFT)); +#else + offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f; +#endif + oldEBands[i+c*m->nbEBands] += offset; + error[i+c*m->nbEBands] -= offset; + /*printf ("%f ", error[i] - offset);*/ + } while (++c < C); + } +} + +void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C) +{ + int i, prio, c; + + /* Use up the remaining bits */ + for (prio=0;prio<2;prio++) + { + for (i=start;i=C ;i++) + { + if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio) + continue; + c=0; + do { + int q2; + opus_val16 offset; + q2 = error[i+c*m->nbEBands]<0 ? 0 : 1; + ec_enc_bits(enc, q2, 1); +#ifdef FIXED_POINT + offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1); +#else + offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384); +#endif + oldEBands[i+c*m->nbEBands] += offset; + bits_left--; + } while (++c < C); + } + } +} + +void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM) +{ + const unsigned char *prob_model = e_prob_model[LM][intra]; + int i, c; + opus_val32 prev[2] = {0, 0}; + opus_val16 coef; + opus_val16 beta; + opus_int32 budget; + opus_int32 tell; + + if (intra) + { + coef = 0; + beta = beta_intra; + } else { + beta = beta_coef[LM]; + coef = pred_coef[LM]; + } + + budget = dec->storage*8; + + /* Decode at a fixed coarse resolution */ + for (i=start;i=15) + { + int pi; + pi = 2*IMIN(i,20); + qi = ec_laplace_decode(dec, + prob_model[pi]<<7, prob_model[pi+1]<<6); + } + else if(budget-tell>=2) + { + qi = ec_dec_icdf(dec, small_energy_icdf, 2); + qi = (qi>>1)^-(qi&1); + } + else if(budget-tell>=1) + { + qi = -ec_dec_bit_logp(dec, 1); + } + else + qi = -1; + q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT); + + oldEBands[i+c*m->nbEBands] = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]); + tmp = PSHR32(MULT16_16(coef,oldEBands[i+c*m->nbEBands]),8) + prev[c] + SHL32(q,7); +#ifdef FIXED_POINT + tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp); +#endif + oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7); + prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8)); + } while (++c < C); + } +} + +void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, ec_dec *dec, int C) +{ + int i, c; + /* Decode finer resolution */ + for (i=start;inbEBands] += offset; + } while (++c < C); + } +} + +void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C) +{ + int i, prio, c; + + /* Use up the remaining bits */ + for (prio=0;prio<2;prio++) + { + for (i=start;i=C ;i++) + { + if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio) + continue; + c=0; + do { + int q2; + opus_val16 offset; + q2 = ec_dec_bits(dec, 1); +#ifdef FIXED_POINT + offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1); +#else + offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384); +#endif + oldEBands[i+c*m->nbEBands] += offset; + bits_left--; + } while (++c < C); + } + } +} + +void amp2Log2(const CELTMode *m, int effEnd, int end, + celt_ener *bandE, opus_val16 *bandLogE, int C) +{ + int c, i; + c=0; + do { + for (i=0;inbEBands] = + celt_log2(SHL32(bandE[i+c*m->nbEBands],2)) + - SHL16((opus_val16)eMeans[i],6); + for (i=effEnd;inbEBands+i] = -QCONST16(14.f,DB_SHIFT); + } while (++c < C); +} diff --git a/TelegramClient.Opus/opus/celt/quant_bands.h b/TelegramClient.Opus/opus/celt/quant_bands.h new file mode 100755 index 0000000..0490bca --- /dev/null +++ b/TelegramClient.Opus/opus/celt/quant_bands.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef QUANT_BANDS +#define QUANT_BANDS + +#include "arch.h" +#include "modes.h" +#include "entenc.h" +#include "entdec.h" +#include "mathops.h" + +#ifdef FIXED_POINT +extern const signed char eMeans[25]; +#else +extern const opus_val16 eMeans[25]; +#endif + +void amp2Log2(const CELTMode *m, int effEnd, int end, + celt_ener *bandE, opus_val16 *bandLogE, int C); + +void log2Amp(const CELTMode *m, int start, int end, + celt_ener *eBands, const opus_val16 *oldEBands, int C); + +void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, + const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget, + opus_val16 *error, ec_enc *enc, int C, int LM, + int nbAvailableBytes, int force_intra, opus_val32 *delayedIntra, + int two_pass, int loss_rate, int lfe); + +void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C); + +void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C); + +void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM); + +void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, ec_dec *dec, int C); + +void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C); + +#endif /* QUANT_BANDS */ diff --git a/TelegramClient.Opus/opus/celt/rate.c b/TelegramClient.Opus/opus/celt/rate.c new file mode 100755 index 0000000..e13d839 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/rate.c @@ -0,0 +1,638 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "modes.h" +#include "cwrs.h" +#include "arch.h" +#include "os_support.h" + +#include "entcode.h" +#include "rate.h" + +static const unsigned char LOG2_FRAC_TABLE[24]={ + 0, + 8,13, + 16,19,21,23, + 24,26,27,28,29,30,31,32, + 32,33,34,34,35,36,36,37,37 +}; + +#ifdef CUSTOM_MODES + +/*Determines if V(N,K) fits in a 32-bit unsigned integer. + N and K are themselves limited to 15 bits.*/ +static int fits_in32(int _n, int _k) +{ + static const opus_int16 maxN[15] = { + 32767, 32767, 32767, 1476, 283, 109, 60, 40, + 29, 24, 20, 18, 16, 14, 13}; + static const opus_int16 maxK[15] = { + 32767, 32767, 32767, 32767, 1172, 238, 95, 53, + 36, 27, 22, 18, 16, 15, 13}; + if (_n>=14) + { + if (_k>=14) + return 0; + else + return _n <= maxN[_k]; + } else { + return _k <= maxK[_n]; + } +} + +void compute_pulse_cache(CELTMode *m, int LM) +{ + int C; + int i; + int j; + int curr=0; + int nbEntries=0; + int entryN[100], entryK[100], entryI[100]; + const opus_int16 *eBands = m->eBands; + PulseCache *cache = &m->cache; + opus_int16 *cindex; + unsigned char *bits; + unsigned char *cap; + + cindex = (opus_int16 *)opus_alloc(sizeof(cache->index[0])*m->nbEBands*(LM+2)); + cache->index = cindex; + + /* Scan for all unique band sizes */ + for (i=0;i<=LM+1;i++) + { + for (j=0;jnbEBands;j++) + { + int k; + int N = (eBands[j+1]-eBands[j])<>1; + cindex[i*m->nbEBands+j] = -1; + /* Find other bands that have the same size */ + for (k=0;k<=i;k++) + { + int n; + for (n=0;nnbEBands && (k!=i || n>1) + { + cindex[i*m->nbEBands+j] = cindex[k*m->nbEBands+n]; + break; + } + } + } + if (cache->index[i*m->nbEBands+j] == -1 && N!=0) + { + int K; + entryN[nbEntries] = N; + K = 0; + while (fits_in32(N,get_pulses(K+1)) && KnbEBands+j] = curr; + entryI[nbEntries] = curr; + + curr += K+1; + nbEntries++; + } + } + } + bits = (unsigned char *)opus_alloc(sizeof(unsigned char)*curr); + cache->bits = bits; + cache->size = curr; + /* Compute the cache for all unique sizes */ + for (i=0;icaps = cap = (unsigned char *)opus_alloc(sizeof(cache->caps[0])*(LM+1)*2*m->nbEBands); + for (i=0;i<=LM;i++) + { + for (C=1;C<=2;C++) + { + for (j=0;jnbEBands;j++) + { + int N0; + int max_bits; + N0 = m->eBands[j+1]-m->eBands[j]; + /* N=1 bands only have a sign bit and fine bits. */ + if (N0<1 are even, including custom modes.*/ + if (N0 > 2) + { + N0>>=1; + LM0--; + } + /* N0=1 bands can't be split down to N<2. */ + else if (N0 <= 1) + { + LM0=IMIN(i,1); + N0<<=LM0; + } + /* Compute the cost for the lowest-level PVQ of a fully split + band. */ + pcache = bits + cindex[(LM0+1)*m->nbEBands+j]; + max_bits = pcache[pcache[0]]+1; + /* Add in the cost of coding regular splits. */ + N = N0; + for(k=0;klogN[j]+((LM0+k)<>1)-QTHETA_OFFSET; + /* The number of qtheta bits we'll allocate if the remainder + is to be max_bits. + The average measured cost for theta is 0.89701 times qb, + approximated here as 459/512. */ + num=459*(opus_int32)((2*N-1)*offset+max_bits); + den=((opus_int32)(2*N-1)<<9)-459; + qb = IMIN((num+(den>>1))/den, 57); + celt_assert(qb >= 0); + max_bits += qb; + N <<= 1; + } + /* Add in the cost of a stereo split, if necessary. */ + if (C==2) + { + max_bits <<= 1; + offset = ((m->logN[j]+(i<>1)-(N==2?QTHETA_OFFSET_TWOPHASE:QTHETA_OFFSET); + ndof = 2*N-1-(N==2); + /* The average measured cost for theta with the step PDF is + 0.95164 times qb, approximated here as 487/512. */ + num = (N==2?512:487)*(opus_int32)(max_bits+ndof*offset); + den = ((opus_int32)ndof<<9)-(N==2?512:487); + qb = IMIN((num+(den>>1))/den, (N==2?64:61)); + celt_assert(qb >= 0); + max_bits += qb; + } + /* Add the fine bits we'll use. */ + /* Compensate for the extra DoF in stereo */ + ndof = C*N + ((C==2 && N>2) ? 1 : 0); + /* Offset the number of fine bits by log2(N)/2 + FINE_OFFSET + compared to their "fair share" of total/N */ + offset = ((m->logN[j] + (i<>1)-FINE_OFFSET; + /* N=2 is the only point that doesn't match the curve */ + if (N==2) + offset += 1<>2; + /* The number of fine bits we'll allocate if the remainder is + to be max_bits. */ + num = max_bits+ndof*offset; + den = (ndof-1)<>1))/den, MAX_FINE_BITS); + celt_assert(qb >= 0); + max_bits += C*qb<eBands[j+1]-m->eBands[j])<= 0); + celt_assert(max_bits < 256); + *cap++ = (unsigned char)max_bits; + } + } + } +} + +#endif /* CUSTOM_MODES */ + +#define ALLOC_STEPS 6 + +static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end, int skip_start, + const int *bits1, const int *bits2, const int *thresh, const int *cap, opus_int32 total, opus_int32 *_balance, + int skip_rsv, int *intensity, int intensity_rsv, int *dual_stereo, int dual_stereo_rsv, int *bits, + int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth) +{ + opus_int32 psum; + int lo, hi; + int i, j; + int logM; + int stereo; + int codedBands=-1; + int alloc_floor; + opus_int32 left, percoeff; + int done; + opus_int32 balance; + SAVE_STACK; + + alloc_floor = C<1; + + logM = LM<>1; + psum = 0; + done = 0; + for (j=end;j-->start;) + { + int tmp = bits1[j] + (mid*(opus_int32)bits2[j]>>ALLOC_STEPS); + if (tmp >= thresh[j] || done) + { + done = 1; + /* Don't allocate more than we can actually use */ + psum += IMIN(tmp, cap[j]); + } else { + if (tmp >= alloc_floor) + psum += alloc_floor; + } + } + if (psum > total) + hi = mid; + else + lo = mid; + } + psum = 0; + /*printf ("interp bisection gave %d\n", lo);*/ + done = 0; + for (j=end;j-->start;) + { + int tmp = bits1[j] + (lo*bits2[j]>>ALLOC_STEPS); + if (tmp < thresh[j] && !done) + { + if (tmp >= alloc_floor) + tmp = alloc_floor; + else + tmp = 0; + } else + done = 1; + /* Don't allocate more than we can actually use */ + tmp = IMIN(tmp, cap[j]); + bits[j] = tmp; + psum += tmp; + } + + /* Decide which bands to skip, working backwards from the end. */ + for (codedBands=end;;codedBands--) + { + int band_width; + int band_bits; + int rem; + j = codedBands-1; + /* Never skip the first band, nor a band that has been boosted by + dynalloc. + In the first case, we'd be coding a bit to signal we're going to waste + all the other bits. + In the second case, we'd be coding a bit to redistribute all the bits + we just signaled should be cocentrated in this band. */ + if (j<=skip_start) + { + /* Give the bit we reserved to end skipping back. */ + total += skip_rsv; + break; + } + /*Figure out how many left-over bits we would be adding to this band. + This can include bits we've stolen back from higher, skipped bands.*/ + left = total-psum; + percoeff = left/(m->eBands[codedBands]-m->eBands[start]); + left -= (m->eBands[codedBands]-m->eBands[start])*percoeff; + rem = IMAX(left-(m->eBands[j]-m->eBands[start]),0); + band_width = m->eBands[codedBands]-m->eBands[j]; + band_bits = (int)(bits[j] + percoeff*band_width + rem); + /*Only code a skip decision if we're above the threshold for this band. + Otherwise it is force-skipped. + This ensures that we have enough bits to code the skip flag.*/ + if (band_bits >= IMAX(thresh[j], alloc_floor+(1< ((j>4 && j<=signalBandwidth)) +#endif + { + ec_enc_bit_logp(ec, 1, 1); + break; + } + ec_enc_bit_logp(ec, 0, 1); + } else if (ec_dec_bit_logp(ec, 1)) { + break; + } + /*We used a bit to skip this band.*/ + psum += 1< 0) + intensity_rsv = LOG2_FRAC_TABLE[j-start]; + psum += intensity_rsv; + if (band_bits >= alloc_floor) + { + /*If we have enough for a fine energy bit per channel, use it.*/ + psum += alloc_floor; + bits[j] = alloc_floor; + } else { + /*Otherwise this band gets nothing at all.*/ + bits[j] = 0; + } + } + + celt_assert(codedBands > start); + /* Code the intensity and dual stereo parameters. */ + if (intensity_rsv > 0) + { + if (encode) + { + *intensity = IMIN(*intensity, codedBands); + ec_enc_uint(ec, *intensity-start, codedBands+1-start); + } + else + *intensity = start+ec_dec_uint(ec, codedBands+1-start); + } + else + *intensity = 0; + if (*intensity <= start) + { + total += dual_stereo_rsv; + dual_stereo_rsv = 0; + } + if (dual_stereo_rsv > 0) + { + if (encode) + ec_enc_bit_logp(ec, *dual_stereo, 1); + else + *dual_stereo = ec_dec_bit_logp(ec, 1); + } + else + *dual_stereo = 0; + + /* Allocate the remaining bits */ + left = total-psum; + percoeff = left/(m->eBands[codedBands]-m->eBands[start]); + left -= (m->eBands[codedBands]-m->eBands[start])*percoeff; + for (j=start;jeBands[j+1]-m->eBands[j])); + for (j=start;jeBands[j+1]-m->eBands[j]); + bits[j] += tmp; + left -= tmp; + } + /*for (j=0;j= 0); + N0 = m->eBands[j+1]-m->eBands[j]; + N=N0<1) + { + excess = MAX32(bit-cap[j],0); + bits[j] = bit-excess; + + /* Compensate for the extra DoF in stereo */ + den=(C*N+ ((C==2 && N>2 && !*dual_stereo && j<*intensity) ? 1 : 0)); + + NClogN = den*(m->logN[j] + logM); + + /* Offset for the number of fine bits by log2(N)/2 + FINE_OFFSET + compared to their "fair share" of total/N */ + offset = (NClogN>>1)-den*FINE_OFFSET; + + /* N=2 is the only point that doesn't match the curve */ + if (N==2) + offset += den<>2; + + /* Changing the offset for allocating the second and third + fine energy bit */ + if (bits[j] + offset < den*2<>2; + else if (bits[j] + offset < den*3<>3; + + /* Divide with rounding */ + ebits[j] = IMAX(0, (bits[j] + offset + (den<<(BITRES-1))) / (den< (bits[j]>>BITRES)) + ebits[j] = bits[j] >> stereo >> BITRES; + + /* More than that is useless because that's about as far as PVQ can go */ + ebits[j] = IMIN(ebits[j], MAX_FINE_BITS); + + /* If we rounded down or capped this band, make it a candidate for the + final fine energy pass */ + fine_priority[j] = ebits[j]*(den<= bits[j]+offset; + + /* Remove the allocated fine bits; the rest are assigned to PVQ */ + bits[j] -= C*ebits[j]< 0) + { + int extra_fine; + int extra_bits; + extra_fine = IMIN(excess>>(stereo+BITRES),MAX_FINE_BITS-ebits[j]); + ebits[j] += extra_fine; + extra_bits = extra_fine*C<= excess-balance; + excess -= extra_bits; + } + balance = excess; + + celt_assert(bits[j] >= 0); + celt_assert(ebits[j] >= 0); + } + /* Save any remaining bits over the cap for the rebalancing in + quant_all_bands(). */ + *_balance = balance; + + /* The skipped bands use all their bits for fine energy. */ + for (;j> stereo >> BITRES; + celt_assert(C*ebits[j]<nbEBands; + skip_start = start; + /* Reserve a bit to signal the end of manually skipped bands. */ + skip_rsv = total >= 1<total) + intensity_rsv = 0; + else + { + total -= intensity_rsv; + dual_stereo_rsv = total>=1<eBands[j+1]-m->eBands[j])<>4); + /* Tilt of the allocation curve */ + trim_offset[j] = C*(m->eBands[j+1]-m->eBands[j])*(alloc_trim-5-LM)*(end-j-1) + *(1<<(LM+BITRES))>>6; + /* Giving less resolution to single-coefficient bands because they get + more benefit from having one coarse value per coefficient*/ + if ((m->eBands[j+1]-m->eBands[j])<nbAllocVectors - 1; + do + { + int done = 0; + int psum = 0; + int mid = (lo+hi) >> 1; + for (j=end;j-->start;) + { + int bitsj; + int N = m->eBands[j+1]-m->eBands[j]; + bitsj = C*N*m->allocVectors[mid*len+j]<>2; + if (bitsj > 0) + bitsj = IMAX(0, bitsj + trim_offset[j]); + bitsj += offsets[j]; + if (bitsj >= thresh[j] || done) + { + done = 1; + /* Don't allocate more than we can actually use */ + psum += IMIN(bitsj, cap[j]); + } else { + if (bitsj >= C< total) + hi = mid - 1; + else + lo = mid + 1; + /*printf ("lo = %d, hi = %d\n", lo, hi);*/ + } + while (lo <= hi); + hi = lo--; + /*printf ("interp between %d and %d\n", lo, hi);*/ + for (j=start;jeBands[j+1]-m->eBands[j]; + bits1j = C*N*m->allocVectors[lo*len+j]<>2; + bits2j = hi>=m->nbAllocVectors ? + cap[j] : C*N*m->allocVectors[hi*len+j]<>2; + if (bits1j > 0) + bits1j = IMAX(0, bits1j + trim_offset[j]); + if (bits2j > 0) + bits2j = IMAX(0, bits2j + trim_offset[j]); + if (lo > 0) + bits1j += offsets[j]; + bits2j += offsets[j]; + if (offsets[j]>0) + skip_start = j; + bits2j = IMAX(0,bits2j-bits1j); + bits1[j] = bits1j; + bits2[j] = bits2j; + } + codedBands = interp_bits2pulses(m, start, end, skip_start, bits1, bits2, thresh, cap, + total, balance, skip_rsv, intensity, intensity_rsv, dual_stereo, dual_stereo_rsv, + pulses, ebits, fine_priority, C, LM, ec, encode, prev, signalBandwidth); + RESTORE_STACK; + return codedBands; +} + diff --git a/TelegramClient.Opus/opus/celt/rate.h b/TelegramClient.Opus/opus/celt/rate.h new file mode 100755 index 0000000..f1e0661 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/rate.h @@ -0,0 +1,101 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef RATE_H +#define RATE_H + +#define MAX_PSEUDO 40 +#define LOG_MAX_PSEUDO 6 + +#define MAX_PULSES 128 + +#define MAX_FINE_BITS 8 + +#define FINE_OFFSET 21 +#define QTHETA_OFFSET 4 +#define QTHETA_OFFSET_TWOPHASE 16 + +#include "cwrs.h" +#include "modes.h" + +void compute_pulse_cache(CELTMode *m, int LM); + +static OPUS_INLINE int get_pulses(int i) +{ + return i<8 ? i : (8 + (i&7)) << ((i>>3)-1); +} + +static OPUS_INLINE int bits2pulses(const CELTMode *m, int band, int LM, int bits) +{ + int i; + int lo, hi; + const unsigned char *cache; + + LM++; + cache = m->cache.bits + m->cache.index[LM*m->nbEBands+band]; + + lo = 0; + hi = cache[0]; + bits--; + for (i=0;i>1; + /* OPT: Make sure this is implemented with a conditional move */ + if ((int)cache[mid] >= bits) + hi = mid; + else + lo = mid; + } + if (bits- (lo == 0 ? -1 : (int)cache[lo]) <= (int)cache[hi]-bits) + return lo; + else + return hi; +} + +static OPUS_INLINE int pulses2bits(const CELTMode *m, int band, int LM, int pulses) +{ + const unsigned char *cache; + + LM++; + cache = m->cache.bits + m->cache.index[LM*m->nbEBands+band]; + return pulses == 0 ? 0 : cache[pulses]+1; +} + +/** Compute the pulse allocation, i.e. how many pulses will go in each + * band. + @param m mode + @param offsets Requested increase or decrease in the number of bits for + each band + @param total Number of bands + @param pulses Number of pulses per band (returned) + @return Total number of bits allocated +*/ +int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stero, + opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth); + +#endif diff --git a/TelegramClient.Opus/opus/celt/stack_alloc.h b/TelegramClient.Opus/opus/celt/stack_alloc.h new file mode 100755 index 0000000..7a8fa85 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/stack_alloc.h @@ -0,0 +1,178 @@ +/* Copyright (C) 2002-2003 Jean-Marc Valin + Copyright (C) 2007-2009 Xiph.Org Foundation */ +/** + @file stack_alloc.h + @brief Temporary memory allocation on stack +*/ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifndef STACK_ALLOC_H +#define STACK_ALLOC_H + +#include "opus_types.h" +#include "opus_defines.h" + +#if (!defined (VAR_ARRAYS) && !defined (USE_ALLOCA) && !defined (NONTHREADSAFE_PSEUDOSTACK)) +#error "Opus requires one of VAR_ARRAYS, USE_ALLOCA, or NONTHREADSAFE_PSEUDOSTACK be defined to select the temporary allocation mode." +#endif + +#ifdef USE_ALLOCA +# ifdef WIN32 +# include +# else +# ifdef HAVE_ALLOCA_H +# include +# else +# include +# endif +# endif +#endif + +/** + * @def ALIGN(stack, size) + * + * Aligns the stack to a 'size' boundary + * + * @param stack Stack + * @param size New size boundary + */ + +/** + * @def PUSH(stack, size, type) + * + * Allocates 'size' elements of type 'type' on the stack + * + * @param stack Stack + * @param size Number of elements + * @param type Type of element + */ + +/** + * @def VARDECL(var) + * + * Declare variable on stack + * + * @param var Variable to declare + */ + +/** + * @def ALLOC(var, size, type) + * + * Allocate 'size' elements of 'type' on stack + * + * @param var Name of variable to allocate + * @param size Number of elements + * @param type Type of element + */ + +#if defined(VAR_ARRAYS) + +#define VARDECL(type, var) +#define ALLOC(var, size, type) type var[size] +#define SAVE_STACK +#define RESTORE_STACK +#define ALLOC_STACK +/* C99 does not allow VLAs of size zero */ +#define ALLOC_NONE 1 + +#elif defined(USE_ALLOCA) + +#define VARDECL(type, var) type *var + +//# ifdef WIN32 +# define ALLOC(var, size, type) var = ((type*)_alloca(sizeof(type)*(size))) +//# else +//# define ALLOC(var, size, type) var = ((type*)alloca(sizeof(type)*(size))) +//# endif + +#define SAVE_STACK +#define RESTORE_STACK +#define ALLOC_STACK +#define ALLOC_NONE 0 + +#else + +#ifdef CELT_C +char *global_stack=0; +#else +extern char *global_stack; +#endif /* CELT_C */ + +#ifdef ENABLE_VALGRIND + +#include + +#ifdef CELT_C +char *global_stack_top=0; +#else +extern char *global_stack_top; +#endif /* CELT_C */ + +#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) +#define PUSH(stack, size, type) (VALGRIND_MAKE_MEM_NOACCESS(stack, global_stack_top-stack),ALIGN((stack),sizeof(type)/sizeof(char)),VALGRIND_MAKE_MEM_UNDEFINED(stack, ((size)*sizeof(type)/sizeof(char))),(stack)+=(2*(size)*sizeof(type)/sizeof(char)),(type*)((stack)-(2*(size)*sizeof(type)/sizeof(char)))) +#define RESTORE_STACK ((global_stack = _saved_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack)) +#define ALLOC_STACK char *_saved_stack; ((global_stack = (global_stack==0) ? ((global_stack_top=opus_alloc_scratch(GLOBAL_STACK_SIZE*2)+(GLOBAL_STACK_SIZE*2))-(GLOBAL_STACK_SIZE*2)) : global_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack)); _saved_stack = global_stack; + +#else + +#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) +#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)/sizeof(char)),(stack)+=(size)*(sizeof(type)/sizeof(char)),(type*)((stack)-(size)*(sizeof(type)/sizeof(char)))) +#define RESTORE_STACK (global_stack = _saved_stack) +#define ALLOC_STACK char *_saved_stack; (global_stack = (global_stack==0) ? opus_alloc_scratch(GLOBAL_STACK_SIZE) : global_stack); _saved_stack = global_stack; + +#endif /* ENABLE_VALGRIND */ + +#include "os_support.h" +#define VARDECL(type, var) type *var +#define ALLOC(var, size, type) var = PUSH(global_stack, size, type) +#define SAVE_STACK char *_saved_stack = global_stack; +#define ALLOC_NONE 0 + +#endif /* VAR_ARRAYS */ + + +#ifdef ENABLE_VALGRIND + +#include +#define OPUS_CHECK_ARRAY(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr)) +#define OPUS_CHECK_VALUE(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value) +#define OPUS_CHECK_ARRAY_COND(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr)) +#define OPUS_CHECK_VALUE_COND(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value) +#define OPUS_PRINT_INT(value) do {fprintf(stderr, #value " = %d at %s:%d\n", value, __FILE__, __LINE__);}while(0) +#define OPUS_FPRINTF fprintf + +#else + +static OPUS_INLINE int _opus_false(void) {return 0;} +#define OPUS_CHECK_ARRAY(ptr, len) _opus_false() +#define OPUS_CHECK_VALUE(value) _opus_false() +#define OPUS_PRINT_INT(value) do{}while(0) +#define OPUS_FPRINTF (void) + +#endif + + +#endif /* STACK_ALLOC_H */ diff --git a/TelegramClient.Opus/opus/celt/static_modes_fixed.h b/TelegramClient.Opus/opus/celt/static_modes_fixed.h new file mode 100755 index 0000000..216df9e --- /dev/null +++ b/TelegramClient.Opus/opus/celt/static_modes_fixed.h @@ -0,0 +1,595 @@ +/* The contents of this file was automatically generated by dump_modes.c + with arguments: 48000 960 + It contains static definitions for some pre-defined modes. */ +#include "modes.h" +#include "rate.h" + +#ifndef DEF_WINDOW120 +#define DEF_WINDOW120 +static const opus_val16 window120[120] = { +2, 20, 55, 108, 178, +266, 372, 494, 635, 792, +966, 1157, 1365, 1590, 1831, +2089, 2362, 2651, 2956, 3276, +3611, 3961, 4325, 4703, 5094, +5499, 5916, 6346, 6788, 7241, +7705, 8179, 8663, 9156, 9657, +10167, 10684, 11207, 11736, 12271, +12810, 13353, 13899, 14447, 14997, +15547, 16098, 16648, 17197, 17744, +18287, 18827, 19363, 19893, 20418, +20936, 21447, 21950, 22445, 22931, +23407, 23874, 24330, 24774, 25208, +25629, 26039, 26435, 26819, 27190, +27548, 27893, 28224, 28541, 28845, +29135, 29411, 29674, 29924, 30160, +30384, 30594, 30792, 30977, 31151, +31313, 31463, 31602, 31731, 31849, +31958, 32057, 32148, 32229, 32303, +32370, 32429, 32481, 32528, 32568, +32604, 32634, 32661, 32683, 32701, +32717, 32729, 32740, 32748, 32754, +32758, 32762, 32764, 32766, 32767, +32767, 32767, 32767, 32767, 32767, +}; +#endif + +#ifndef DEF_LOGN400 +#define DEF_LOGN400 +static const opus_int16 logN400[21] = { +0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, }; +#endif + +#ifndef DEF_PULSE_CACHE50 +#define DEF_PULSE_CACHE50 +static const opus_int16 cache_index50[105] = { +-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41, +82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41, +41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41, +41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305, +318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240, +305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240, +240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387, +}; +static const unsigned char cache_bits50[392] = { +40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28, +31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50, +51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65, +66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61, +64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92, +94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123, +124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94, +97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139, +142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35, +28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149, +153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225, +229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157, +166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63, +86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250, +25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180, +185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89, +110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41, +74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138, +163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214, +228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49, +90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47, +87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57, +106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187, +224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127, +182, 234, }; +static const unsigned char cache_caps50[168] = { +224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185, +178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240, +240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160, +160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172, +138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207, +204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185, +185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39, +207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201, +188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193, +193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204, +204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175, +140, 66, 40, }; +#endif + +#ifndef FFT_TWIDDLES48000_960 +#define FFT_TWIDDLES48000_960 +static const kiss_twiddle_cpx fft_twiddles48000_960[480] = { +{32767, 0}, {32766, -429}, +{32757, -858}, {32743, -1287}, +{32724, -1715}, {32698, -2143}, +{32667, -2570}, {32631, -2998}, +{32588, -3425}, {32541, -3851}, +{32488, -4277}, {32429, -4701}, +{32364, -5125}, {32295, -5548}, +{32219, -5971}, {32138, -6393}, +{32051, -6813}, {31960, -7231}, +{31863, -7650}, {31760, -8067}, +{31652, -8481}, {31539, -8895}, +{31419, -9306}, {31294, -9716}, +{31165, -10126}, {31030, -10532}, +{30889, -10937}, {30743, -11340}, +{30592, -11741}, {30436, -12141}, +{30274, -12540}, {30107, -12935}, +{29936, -13328}, {29758, -13718}, +{29577, -14107}, {29390, -14493}, +{29197, -14875}, {29000, -15257}, +{28797, -15635}, {28590, -16010}, +{28379, -16384}, {28162, -16753}, +{27940, -17119}, {27714, -17484}, +{27482, -17845}, {27246, -18205}, +{27006, -18560}, {26760, -18911}, +{26510, -19260}, {26257, -19606}, +{25997, -19947}, {25734, -20286}, +{25466, -20621}, {25194, -20952}, +{24918, -21281}, {24637, -21605}, +{24353, -21926}, {24063, -22242}, +{23770, -22555}, {23473, -22865}, +{23171, -23171}, {22866, -23472}, +{22557, -23769}, {22244, -24063}, +{21927, -24352}, {21606, -24636}, +{21282, -24917}, {20954, -25194}, +{20622, -25465}, {20288, -25733}, +{19949, -25997}, {19607, -26255}, +{19261, -26509}, {18914, -26760}, +{18561, -27004}, {18205, -27246}, +{17846, -27481}, {17485, -27713}, +{17122, -27940}, {16755, -28162}, +{16385, -28378}, {16012, -28590}, +{15636, -28797}, {15258, -28999}, +{14878, -29197}, {14494, -29389}, +{14108, -29576}, {13720, -29757}, +{13329, -29934}, {12937, -30107}, +{12540, -30274}, {12142, -30435}, +{11744, -30592}, {11342, -30743}, +{10939, -30889}, {10534, -31030}, +{10127, -31164}, {9718, -31294}, +{9307, -31418}, {8895, -31537}, +{8482, -31652}, {8067, -31759}, +{7650, -31862}, {7233, -31960}, +{6815, -32051}, {6393, -32138}, +{5973, -32219}, {5549, -32294}, +{5127, -32364}, {4703, -32429}, +{4278, -32487}, {3852, -32541}, +{3426, -32588}, {2999, -32630}, +{2572, -32667}, {2144, -32698}, +{1716, -32724}, {1287, -32742}, +{860, -32757}, {430, -32766}, +{0, -32767}, {-429, -32766}, +{-858, -32757}, {-1287, -32743}, +{-1715, -32724}, {-2143, -32698}, +{-2570, -32667}, {-2998, -32631}, +{-3425, -32588}, {-3851, -32541}, +{-4277, -32488}, {-4701, -32429}, +{-5125, -32364}, {-5548, -32295}, +{-5971, -32219}, {-6393, -32138}, +{-6813, -32051}, {-7231, -31960}, +{-7650, -31863}, {-8067, -31760}, +{-8481, -31652}, {-8895, -31539}, +{-9306, -31419}, {-9716, -31294}, +{-10126, -31165}, {-10532, -31030}, +{-10937, -30889}, {-11340, -30743}, +{-11741, -30592}, {-12141, -30436}, +{-12540, -30274}, {-12935, -30107}, +{-13328, -29936}, {-13718, -29758}, +{-14107, -29577}, {-14493, -29390}, +{-14875, -29197}, {-15257, -29000}, +{-15635, -28797}, {-16010, -28590}, +{-16384, -28379}, {-16753, -28162}, +{-17119, -27940}, {-17484, -27714}, +{-17845, -27482}, {-18205, -27246}, +{-18560, -27006}, {-18911, -26760}, +{-19260, -26510}, {-19606, -26257}, +{-19947, -25997}, {-20286, -25734}, +{-20621, -25466}, {-20952, -25194}, +{-21281, -24918}, {-21605, -24637}, +{-21926, -24353}, {-22242, -24063}, +{-22555, -23770}, {-22865, -23473}, +{-23171, -23171}, {-23472, -22866}, +{-23769, -22557}, {-24063, -22244}, +{-24352, -21927}, {-24636, -21606}, +{-24917, -21282}, {-25194, -20954}, +{-25465, -20622}, {-25733, -20288}, +{-25997, -19949}, {-26255, -19607}, +{-26509, -19261}, {-26760, -18914}, +{-27004, -18561}, {-27246, -18205}, +{-27481, -17846}, {-27713, -17485}, +{-27940, -17122}, {-28162, -16755}, +{-28378, -16385}, {-28590, -16012}, +{-28797, -15636}, {-28999, -15258}, +{-29197, -14878}, {-29389, -14494}, +{-29576, -14108}, {-29757, -13720}, +{-29934, -13329}, {-30107, -12937}, +{-30274, -12540}, {-30435, -12142}, +{-30592, -11744}, {-30743, -11342}, +{-30889, -10939}, {-31030, -10534}, +{-31164, -10127}, {-31294, -9718}, +{-31418, -9307}, {-31537, -8895}, +{-31652, -8482}, {-31759, -8067}, +{-31862, -7650}, {-31960, -7233}, +{-32051, -6815}, {-32138, -6393}, +{-32219, -5973}, {-32294, -5549}, +{-32364, -5127}, {-32429, -4703}, +{-32487, -4278}, {-32541, -3852}, +{-32588, -3426}, {-32630, -2999}, +{-32667, -2572}, {-32698, -2144}, +{-32724, -1716}, {-32742, -1287}, +{-32757, -860}, {-32766, -430}, +{-32767, 0}, {-32766, 429}, +{-32757, 858}, {-32743, 1287}, +{-32724, 1715}, {-32698, 2143}, +{-32667, 2570}, {-32631, 2998}, +{-32588, 3425}, {-32541, 3851}, +{-32488, 4277}, {-32429, 4701}, +{-32364, 5125}, {-32295, 5548}, +{-32219, 5971}, {-32138, 6393}, +{-32051, 6813}, {-31960, 7231}, +{-31863, 7650}, {-31760, 8067}, +{-31652, 8481}, {-31539, 8895}, +{-31419, 9306}, {-31294, 9716}, +{-31165, 10126}, {-31030, 10532}, +{-30889, 10937}, {-30743, 11340}, +{-30592, 11741}, {-30436, 12141}, +{-30274, 12540}, {-30107, 12935}, +{-29936, 13328}, {-29758, 13718}, +{-29577, 14107}, {-29390, 14493}, +{-29197, 14875}, {-29000, 15257}, +{-28797, 15635}, {-28590, 16010}, +{-28379, 16384}, {-28162, 16753}, +{-27940, 17119}, {-27714, 17484}, +{-27482, 17845}, {-27246, 18205}, +{-27006, 18560}, {-26760, 18911}, +{-26510, 19260}, {-26257, 19606}, +{-25997, 19947}, {-25734, 20286}, +{-25466, 20621}, {-25194, 20952}, +{-24918, 21281}, {-24637, 21605}, +{-24353, 21926}, {-24063, 22242}, +{-23770, 22555}, {-23473, 22865}, +{-23171, 23171}, {-22866, 23472}, +{-22557, 23769}, {-22244, 24063}, +{-21927, 24352}, {-21606, 24636}, +{-21282, 24917}, {-20954, 25194}, +{-20622, 25465}, {-20288, 25733}, +{-19949, 25997}, {-19607, 26255}, +{-19261, 26509}, {-18914, 26760}, +{-18561, 27004}, {-18205, 27246}, +{-17846, 27481}, {-17485, 27713}, +{-17122, 27940}, {-16755, 28162}, +{-16385, 28378}, {-16012, 28590}, +{-15636, 28797}, {-15258, 28999}, +{-14878, 29197}, {-14494, 29389}, +{-14108, 29576}, {-13720, 29757}, +{-13329, 29934}, {-12937, 30107}, +{-12540, 30274}, {-12142, 30435}, +{-11744, 30592}, {-11342, 30743}, +{-10939, 30889}, {-10534, 31030}, +{-10127, 31164}, {-9718, 31294}, +{-9307, 31418}, {-8895, 31537}, +{-8482, 31652}, {-8067, 31759}, +{-7650, 31862}, {-7233, 31960}, +{-6815, 32051}, {-6393, 32138}, +{-5973, 32219}, {-5549, 32294}, +{-5127, 32364}, {-4703, 32429}, +{-4278, 32487}, {-3852, 32541}, +{-3426, 32588}, {-2999, 32630}, +{-2572, 32667}, {-2144, 32698}, +{-1716, 32724}, {-1287, 32742}, +{-860, 32757}, {-430, 32766}, +{0, 32767}, {429, 32766}, +{858, 32757}, {1287, 32743}, +{1715, 32724}, {2143, 32698}, +{2570, 32667}, {2998, 32631}, +{3425, 32588}, {3851, 32541}, +{4277, 32488}, {4701, 32429}, +{5125, 32364}, {5548, 32295}, +{5971, 32219}, {6393, 32138}, +{6813, 32051}, {7231, 31960}, +{7650, 31863}, {8067, 31760}, +{8481, 31652}, {8895, 31539}, +{9306, 31419}, {9716, 31294}, +{10126, 31165}, {10532, 31030}, +{10937, 30889}, {11340, 30743}, +{11741, 30592}, {12141, 30436}, +{12540, 30274}, {12935, 30107}, +{13328, 29936}, {13718, 29758}, +{14107, 29577}, {14493, 29390}, +{14875, 29197}, {15257, 29000}, +{15635, 28797}, {16010, 28590}, +{16384, 28379}, {16753, 28162}, +{17119, 27940}, {17484, 27714}, +{17845, 27482}, {18205, 27246}, +{18560, 27006}, {18911, 26760}, +{19260, 26510}, {19606, 26257}, +{19947, 25997}, {20286, 25734}, +{20621, 25466}, {20952, 25194}, +{21281, 24918}, {21605, 24637}, +{21926, 24353}, {22242, 24063}, +{22555, 23770}, {22865, 23473}, +{23171, 23171}, {23472, 22866}, +{23769, 22557}, {24063, 22244}, +{24352, 21927}, {24636, 21606}, +{24917, 21282}, {25194, 20954}, +{25465, 20622}, {25733, 20288}, +{25997, 19949}, {26255, 19607}, +{26509, 19261}, {26760, 18914}, +{27004, 18561}, {27246, 18205}, +{27481, 17846}, {27713, 17485}, +{27940, 17122}, {28162, 16755}, +{28378, 16385}, {28590, 16012}, +{28797, 15636}, {28999, 15258}, +{29197, 14878}, {29389, 14494}, +{29576, 14108}, {29757, 13720}, +{29934, 13329}, {30107, 12937}, +{30274, 12540}, {30435, 12142}, +{30592, 11744}, {30743, 11342}, +{30889, 10939}, {31030, 10534}, +{31164, 10127}, {31294, 9718}, +{31418, 9307}, {31537, 8895}, +{31652, 8482}, {31759, 8067}, +{31862, 7650}, {31960, 7233}, +{32051, 6815}, {32138, 6393}, +{32219, 5973}, {32294, 5549}, +{32364, 5127}, {32429, 4703}, +{32487, 4278}, {32541, 3852}, +{32588, 3426}, {32630, 2999}, +{32667, 2572}, {32698, 2144}, +{32724, 1716}, {32742, 1287}, +{32757, 860}, {32766, 430}, +}; +#ifndef FFT_BITREV480 +#define FFT_BITREV480 +static const opus_int16 fft_bitrev480[480] = { +0, 120, 240, 360, 30, 150, 270, 390, 60, 180, 300, 420, 90, 210, 330, +450, 15, 135, 255, 375, 45, 165, 285, 405, 75, 195, 315, 435, 105, 225, +345, 465, 5, 125, 245, 365, 35, 155, 275, 395, 65, 185, 305, 425, 95, +215, 335, 455, 20, 140, 260, 380, 50, 170, 290, 410, 80, 200, 320, 440, +110, 230, 350, 470, 10, 130, 250, 370, 40, 160, 280, 400, 70, 190, 310, +430, 100, 220, 340, 460, 25, 145, 265, 385, 55, 175, 295, 415, 85, 205, +325, 445, 115, 235, 355, 475, 1, 121, 241, 361, 31, 151, 271, 391, 61, +181, 301, 421, 91, 211, 331, 451, 16, 136, 256, 376, 46, 166, 286, 406, +76, 196, 316, 436, 106, 226, 346, 466, 6, 126, 246, 366, 36, 156, 276, +396, 66, 186, 306, 426, 96, 216, 336, 456, 21, 141, 261, 381, 51, 171, +291, 411, 81, 201, 321, 441, 111, 231, 351, 471, 11, 131, 251, 371, 41, +161, 281, 401, 71, 191, 311, 431, 101, 221, 341, 461, 26, 146, 266, 386, +56, 176, 296, 416, 86, 206, 326, 446, 116, 236, 356, 476, 2, 122, 242, +362, 32, 152, 272, 392, 62, 182, 302, 422, 92, 212, 332, 452, 17, 137, +257, 377, 47, 167, 287, 407, 77, 197, 317, 437, 107, 227, 347, 467, 7, +127, 247, 367, 37, 157, 277, 397, 67, 187, 307, 427, 97, 217, 337, 457, +22, 142, 262, 382, 52, 172, 292, 412, 82, 202, 322, 442, 112, 232, 352, +472, 12, 132, 252, 372, 42, 162, 282, 402, 72, 192, 312, 432, 102, 222, +342, 462, 27, 147, 267, 387, 57, 177, 297, 417, 87, 207, 327, 447, 117, +237, 357, 477, 3, 123, 243, 363, 33, 153, 273, 393, 63, 183, 303, 423, +93, 213, 333, 453, 18, 138, 258, 378, 48, 168, 288, 408, 78, 198, 318, +438, 108, 228, 348, 468, 8, 128, 248, 368, 38, 158, 278, 398, 68, 188, +308, 428, 98, 218, 338, 458, 23, 143, 263, 383, 53, 173, 293, 413, 83, +203, 323, 443, 113, 233, 353, 473, 13, 133, 253, 373, 43, 163, 283, 403, +73, 193, 313, 433, 103, 223, 343, 463, 28, 148, 268, 388, 58, 178, 298, +418, 88, 208, 328, 448, 118, 238, 358, 478, 4, 124, 244, 364, 34, 154, +274, 394, 64, 184, 304, 424, 94, 214, 334, 454, 19, 139, 259, 379, 49, +169, 289, 409, 79, 199, 319, 439, 109, 229, 349, 469, 9, 129, 249, 369, +39, 159, 279, 399, 69, 189, 309, 429, 99, 219, 339, 459, 24, 144, 264, +384, 54, 174, 294, 414, 84, 204, 324, 444, 114, 234, 354, 474, 14, 134, +254, 374, 44, 164, 284, 404, 74, 194, 314, 434, 104, 224, 344, 464, 29, +149, 269, 389, 59, 179, 299, 419, 89, 209, 329, 449, 119, 239, 359, 479, +}; +#endif + +#ifndef FFT_BITREV240 +#define FFT_BITREV240 +static const opus_int16 fft_bitrev240[240] = { +0, 60, 120, 180, 15, 75, 135, 195, 30, 90, 150, 210, 45, 105, 165, +225, 5, 65, 125, 185, 20, 80, 140, 200, 35, 95, 155, 215, 50, 110, +170, 230, 10, 70, 130, 190, 25, 85, 145, 205, 40, 100, 160, 220, 55, +115, 175, 235, 1, 61, 121, 181, 16, 76, 136, 196, 31, 91, 151, 211, +46, 106, 166, 226, 6, 66, 126, 186, 21, 81, 141, 201, 36, 96, 156, +216, 51, 111, 171, 231, 11, 71, 131, 191, 26, 86, 146, 206, 41, 101, +161, 221, 56, 116, 176, 236, 2, 62, 122, 182, 17, 77, 137, 197, 32, +92, 152, 212, 47, 107, 167, 227, 7, 67, 127, 187, 22, 82, 142, 202, +37, 97, 157, 217, 52, 112, 172, 232, 12, 72, 132, 192, 27, 87, 147, +207, 42, 102, 162, 222, 57, 117, 177, 237, 3, 63, 123, 183, 18, 78, +138, 198, 33, 93, 153, 213, 48, 108, 168, 228, 8, 68, 128, 188, 23, +83, 143, 203, 38, 98, 158, 218, 53, 113, 173, 233, 13, 73, 133, 193, +28, 88, 148, 208, 43, 103, 163, 223, 58, 118, 178, 238, 4, 64, 124, +184, 19, 79, 139, 199, 34, 94, 154, 214, 49, 109, 169, 229, 9, 69, +129, 189, 24, 84, 144, 204, 39, 99, 159, 219, 54, 114, 174, 234, 14, +74, 134, 194, 29, 89, 149, 209, 44, 104, 164, 224, 59, 119, 179, 239, +}; +#endif + +#ifndef FFT_BITREV120 +#define FFT_BITREV120 +static const opus_int16 fft_bitrev120[120] = { +0, 30, 60, 90, 15, 45, 75, 105, 5, 35, 65, 95, 20, 50, 80, +110, 10, 40, 70, 100, 25, 55, 85, 115, 1, 31, 61, 91, 16, 46, +76, 106, 6, 36, 66, 96, 21, 51, 81, 111, 11, 41, 71, 101, 26, +56, 86, 116, 2, 32, 62, 92, 17, 47, 77, 107, 7, 37, 67, 97, +22, 52, 82, 112, 12, 42, 72, 102, 27, 57, 87, 117, 3, 33, 63, +93, 18, 48, 78, 108, 8, 38, 68, 98, 23, 53, 83, 113, 13, 43, +73, 103, 28, 58, 88, 118, 4, 34, 64, 94, 19, 49, 79, 109, 9, +39, 69, 99, 24, 54, 84, 114, 14, 44, 74, 104, 29, 59, 89, 119, +}; +#endif + +#ifndef FFT_BITREV60 +#define FFT_BITREV60 +static const opus_int16 fft_bitrev60[60] = { +0, 15, 30, 45, 5, 20, 35, 50, 10, 25, 40, 55, 1, 16, 31, +46, 6, 21, 36, 51, 11, 26, 41, 56, 2, 17, 32, 47, 7, 22, +37, 52, 12, 27, 42, 57, 3, 18, 33, 48, 8, 23, 38, 53, 13, +28, 43, 58, 4, 19, 34, 49, 9, 24, 39, 54, 14, 29, 44, 59, +}; +#endif + +#ifndef FFT_STATE48000_960_0 +#define FFT_STATE48000_960_0 +static const kiss_fft_state fft_state48000_960_0 = { +480, /* nfft */ +-1, /* shift */ +{4, 120, 4, 30, 2, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, }, /* factors */ +fft_bitrev480, /* bitrev */ +fft_twiddles48000_960, /* bitrev */ +}; +#endif + +#ifndef FFT_STATE48000_960_1 +#define FFT_STATE48000_960_1 +static const kiss_fft_state fft_state48000_960_1 = { +240, /* nfft */ +1, /* shift */ +{4, 60, 4, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */ +fft_bitrev240, /* bitrev */ +fft_twiddles48000_960, /* bitrev */ +}; +#endif + +#ifndef FFT_STATE48000_960_2 +#define FFT_STATE48000_960_2 +static const kiss_fft_state fft_state48000_960_2 = { +120, /* nfft */ +2, /* shift */ +{4, 30, 2, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */ +fft_bitrev120, /* bitrev */ +fft_twiddles48000_960, /* bitrev */ +}; +#endif + +#ifndef FFT_STATE48000_960_3 +#define FFT_STATE48000_960_3 +static const kiss_fft_state fft_state48000_960_3 = { +60, /* nfft */ +3, /* shift */ +{4, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */ +fft_bitrev60, /* bitrev */ +fft_twiddles48000_960, /* bitrev */ +}; +#endif + +#endif + +#ifndef MDCT_TWIDDLES960 +#define MDCT_TWIDDLES960 +static const opus_val16 mdct_twiddles960[481] = { +32767, 32767, 32767, 32767, 32766, +32763, 32762, 32759, 32757, 32753, +32751, 32747, 32743, 32738, 32733, +32729, 32724, 32717, 32711, 32705, +32698, 32690, 32683, 32676, 32667, +32658, 32650, 32640, 32631, 32620, +32610, 32599, 32588, 32577, 32566, +32554, 32541, 32528, 32515, 32502, +32487, 32474, 32459, 32444, 32429, +32413, 32397, 32381, 32364, 32348, +32331, 32313, 32294, 32277, 32257, +32239, 32219, 32200, 32180, 32159, +32138, 32118, 32096, 32074, 32051, +32029, 32006, 31984, 31960, 31936, +31912, 31888, 31863, 31837, 31812, +31786, 31760, 31734, 31707, 31679, +31652, 31624, 31596, 31567, 31539, +31508, 31479, 31450, 31419, 31388, +31357, 31326, 31294, 31262, 31230, +31198, 31164, 31131, 31097, 31063, +31030, 30994, 30959, 30924, 30889, +30853, 30816, 30779, 30743, 30705, +30668, 30629, 30592, 30553, 30515, +30475, 30435, 30396, 30356, 30315, +30274, 30233, 30191, 30149, 30107, +30065, 30022, 29979, 29936, 29891, +29847, 29803, 29758, 29713, 29668, +29622, 29577, 29529, 29483, 29436, +29390, 29341, 29293, 29246, 29197, +29148, 29098, 29050, 29000, 28949, +28899, 28848, 28797, 28746, 28694, +28642, 28590, 28537, 28485, 28432, +28378, 28324, 28271, 28217, 28162, +28106, 28051, 27995, 27940, 27884, +27827, 27770, 27713, 27657, 27598, +27540, 27481, 27423, 27365, 27305, +27246, 27187, 27126, 27066, 27006, +26945, 26883, 26822, 26760, 26698, +26636, 26574, 26510, 26448, 26383, +26320, 26257, 26191, 26127, 26062, +25997, 25931, 25866, 25800, 25734, +25667, 25601, 25533, 25466, 25398, +25330, 25262, 25194, 25125, 25056, +24987, 24917, 24848, 24778, 24707, +24636, 24566, 24495, 24424, 24352, +24280, 24208, 24135, 24063, 23990, +23917, 23842, 23769, 23695, 23622, +23546, 23472, 23398, 23322, 23246, +23171, 23095, 23018, 22942, 22866, +22788, 22711, 22634, 22557, 22478, +22400, 22322, 22244, 22165, 22085, +22006, 21927, 21846, 21766, 21687, +21606, 21524, 21443, 21363, 21282, +21199, 21118, 21035, 20954, 20870, +20788, 20705, 20621, 20538, 20455, +20371, 20286, 20202, 20118, 20034, +19947, 19863, 19777, 19692, 19606, +19520, 19434, 19347, 19260, 19174, +19088, 18999, 18911, 18825, 18737, +18648, 18560, 18472, 18384, 18294, +18205, 18116, 18025, 17936, 17846, +17757, 17666, 17576, 17485, 17395, +17303, 17212, 17122, 17030, 16937, +16846, 16755, 16662, 16569, 16477, +16385, 16291, 16198, 16105, 16012, +15917, 15824, 15730, 15636, 15541, +15447, 15352, 15257, 15162, 15067, +14973, 14875, 14781, 14685, 14589, +14493, 14396, 14300, 14204, 14107, +14010, 13914, 13815, 13718, 13621, +13524, 13425, 13328, 13230, 13133, +13033, 12935, 12836, 12738, 12638, +12540, 12441, 12341, 12241, 12142, +12044, 11943, 11843, 11744, 11643, +11542, 11442, 11342, 11241, 11139, +11039, 10939, 10836, 10736, 10635, +10534, 10431, 10330, 10228, 10127, +10024, 9921, 9820, 9718, 9614, +9512, 9410, 9306, 9204, 9101, +8998, 8895, 8791, 8689, 8585, +8481, 8377, 8274, 8171, 8067, +7962, 7858, 7753, 7650, 7545, +7441, 7336, 7231, 7129, 7023, +6917, 6813, 6709, 6604, 6498, +6393, 6288, 6182, 6077, 5973, +5867, 5760, 5656, 5549, 5445, +5339, 5232, 5127, 5022, 4914, +4809, 4703, 4596, 4490, 4384, +4278, 4171, 4065, 3958, 3852, +3745, 3640, 3532, 3426, 3318, +3212, 3106, 2998, 2891, 2786, +2679, 2570, 2465, 2358, 2251, +2143, 2037, 1929, 1823, 1715, +1609, 1501, 1393, 1287, 1180, +1073, 964, 858, 751, 644, +535, 429, 322, 214, 107, +0, }; +#endif + +static const CELTMode mode48000_960_120 = { +48000, /* Fs */ +120, /* overlap */ +21, /* nbEBands */ +21, /* effEBands */ +{27853, 0, 4096, 8192, }, /* preemph */ +eband5ms, /* eBands */ +3, /* maxLM */ +8, /* nbShortMdcts */ +120, /* shortMdctSize */ +11, /* nbAllocVectors */ +band_allocation, /* allocVectors */ +logN400, /* logN */ +window120, /* window */ +{1920, 3, {&fft_state48000_960_0, &fft_state48000_960_1, &fft_state48000_960_2, &fft_state48000_960_3, }, mdct_twiddles960}, /* mdct */ +{392, cache_index50, cache_bits50, cache_caps50}, /* cache */ +}; + +/* List of all the available modes */ +#define TOTAL_MODES 1 +static const CELTMode * const static_mode_list[TOTAL_MODES] = { +&mode48000_960_120, +}; diff --git a/TelegramClient.Opus/opus/celt/static_modes_float.h b/TelegramClient.Opus/opus/celt/static_modes_float.h new file mode 100755 index 0000000..5d7e7b8 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/static_modes_float.h @@ -0,0 +1,599 @@ +/* The contents of this file was automatically generated by dump_modes.c + with arguments: 48000 960 + It contains static definitions for some pre-defined modes. */ +#include "modes.h" +#include "rate.h" + +#ifndef DEF_WINDOW120 +#define DEF_WINDOW120 +static const opus_val16 window120[120] = { +6.7286966e-05f, 0.00060551348f, 0.0016815970f, 0.0032947962f, 0.0054439943f, +0.0081276923f, 0.011344001f, 0.015090633f, 0.019364886f, 0.024163635f, +0.029483315f, 0.035319905f, 0.041668911f, 0.048525347f, 0.055883718f, +0.063737999f, 0.072081616f, 0.080907428f, 0.090207705f, 0.099974111f, +0.11019769f, 0.12086883f, 0.13197729f, 0.14351214f, 0.15546177f, +0.16781389f, 0.18055550f, 0.19367290f, 0.20715171f, 0.22097682f, +0.23513243f, 0.24960208f, 0.26436860f, 0.27941419f, 0.29472040f, +0.31026818f, 0.32603788f, 0.34200931f, 0.35816177f, 0.37447407f, +0.39092462f, 0.40749142f, 0.42415215f, 0.44088423f, 0.45766484f, +0.47447104f, 0.49127978f, 0.50806798f, 0.52481261f, 0.54149077f, +0.55807973f, 0.57455701f, 0.59090049f, 0.60708841f, 0.62309951f, +0.63891306f, 0.65450896f, 0.66986776f, 0.68497077f, 0.69980010f, +0.71433873f, 0.72857055f, 0.74248043f, 0.75605424f, 0.76927895f, +0.78214257f, 0.79463430f, 0.80674445f, 0.81846456f, 0.82978733f, +0.84070669f, 0.85121779f, 0.86131698f, 0.87100183f, 0.88027111f, +0.88912479f, 0.89756398f, 0.90559094f, 0.91320904f, 0.92042270f, +0.92723738f, 0.93365955f, 0.93969656f, 0.94535671f, 0.95064907f, +0.95558353f, 0.96017067f, 0.96442171f, 0.96834849f, 0.97196334f, +0.97527906f, 0.97830883f, 0.98106616f, 0.98356480f, 0.98581869f, +0.98784191f, 0.98964856f, 0.99125274f, 0.99266849f, 0.99390969f, +0.99499004f, 0.99592297f, 0.99672162f, 0.99739874f, 0.99796667f, +0.99843728f, 0.99882195f, 0.99913147f, 0.99937606f, 0.99956527f, +0.99970802f, 0.99981248f, 0.99988613f, 0.99993565f, 0.99996697f, +0.99998518f, 0.99999457f, 0.99999859f, 0.99999982f, 1.0000000f, +}; +#endif + +#ifndef DEF_LOGN400 +#define DEF_LOGN400 +static const opus_int16 logN400[21] = { +0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, }; +#endif + +#ifndef DEF_PULSE_CACHE50 +#define DEF_PULSE_CACHE50 +static const opus_int16 cache_index50[105] = { +-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41, +82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41, +41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41, +41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305, +318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240, +305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240, +240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387, +}; +static const unsigned char cache_bits50[392] = { +40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28, +31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50, +51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65, +66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61, +64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92, +94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123, +124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94, +97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139, +142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35, +28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149, +153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225, +229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157, +166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63, +86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250, +25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180, +185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89, +110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41, +74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138, +163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214, +228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49, +90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47, +87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57, +106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187, +224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127, +182, 234, }; +static const unsigned char cache_caps50[168] = { +224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185, +178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240, +240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160, +160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172, +138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207, +204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185, +185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39, +207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201, +188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193, +193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204, +204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175, +140, 66, 40, }; +#endif + +#ifndef FFT_TWIDDLES48000_960 +#define FFT_TWIDDLES48000_960 +static const kiss_twiddle_cpx fft_twiddles48000_960[480] = { +{1.0000000f, -0.0000000f}, {0.99991433f, -0.013089596f}, +{0.99965732f, -0.026176948f}, {0.99922904f, -0.039259816f}, +{0.99862953f, -0.052335956f}, {0.99785892f, -0.065403129f}, +{0.99691733f, -0.078459096f}, {0.99580493f, -0.091501619f}, +{0.99452190f, -0.10452846f}, {0.99306846f, -0.11753740f}, +{0.99144486f, -0.13052619f}, {0.98965139f, -0.14349262f}, +{0.98768834f, -0.15643447f}, {0.98555606f, -0.16934950f}, +{0.98325491f, -0.18223553f}, {0.98078528f, -0.19509032f}, +{0.97814760f, -0.20791169f}, {0.97534232f, -0.22069744f}, +{0.97236992f, -0.23344536f}, {0.96923091f, -0.24615329f}, +{0.96592583f, -0.25881905f}, {0.96245524f, -0.27144045f}, +{0.95881973f, -0.28401534f}, {0.95501994f, -0.29654157f}, +{0.95105652f, -0.30901699f}, {0.94693013f, -0.32143947f}, +{0.94264149f, -0.33380686f}, {0.93819134f, -0.34611706f}, +{0.93358043f, -0.35836795f}, {0.92880955f, -0.37055744f}, +{0.92387953f, -0.38268343f}, {0.91879121f, -0.39474386f}, +{0.91354546f, -0.40673664f}, {0.90814317f, -0.41865974f}, +{0.90258528f, -0.43051110f}, {0.89687274f, -0.44228869f}, +{0.89100652f, -0.45399050f}, {0.88498764f, -0.46561452f}, +{0.87881711f, -0.47715876f}, {0.87249601f, -0.48862124f}, +{0.86602540f, -0.50000000f}, {0.85940641f, -0.51129309f}, +{0.85264016f, -0.52249856f}, {0.84572782f, -0.53361452f}, +{0.83867057f, -0.54463904f}, {0.83146961f, -0.55557023f}, +{0.82412619f, -0.56640624f}, {0.81664156f, -0.57714519f}, +{0.80901699f, -0.58778525f}, {0.80125381f, -0.59832460f}, +{0.79335334f, -0.60876143f}, {0.78531693f, -0.61909395f}, +{0.77714596f, -0.62932039f}, {0.76884183f, -0.63943900f}, +{0.76040597f, -0.64944805f}, {0.75183981f, -0.65934582f}, +{0.74314483f, -0.66913061f}, {0.73432251f, -0.67880075f}, +{0.72537437f, -0.68835458f}, {0.71630194f, -0.69779046f}, +{0.70710678f, -0.70710678f}, {0.69779046f, -0.71630194f}, +{0.68835458f, -0.72537437f}, {0.67880075f, -0.73432251f}, +{0.66913061f, -0.74314483f}, {0.65934582f, -0.75183981f}, +{0.64944805f, -0.76040597f}, {0.63943900f, -0.76884183f}, +{0.62932039f, -0.77714596f}, {0.61909395f, -0.78531693f}, +{0.60876143f, -0.79335334f}, {0.59832460f, -0.80125381f}, +{0.58778525f, -0.80901699f}, {0.57714519f, -0.81664156f}, +{0.56640624f, -0.82412619f}, {0.55557023f, -0.83146961f}, +{0.54463904f, -0.83867057f}, {0.53361452f, -0.84572782f}, +{0.52249856f, -0.85264016f}, {0.51129309f, -0.85940641f}, +{0.50000000f, -0.86602540f}, {0.48862124f, -0.87249601f}, +{0.47715876f, -0.87881711f}, {0.46561452f, -0.88498764f}, +{0.45399050f, -0.89100652f}, {0.44228869f, -0.89687274f}, +{0.43051110f, -0.90258528f}, {0.41865974f, -0.90814317f}, +{0.40673664f, -0.91354546f}, {0.39474386f, -0.91879121f}, +{0.38268343f, -0.92387953f}, {0.37055744f, -0.92880955f}, +{0.35836795f, -0.93358043f}, {0.34611706f, -0.93819134f}, +{0.33380686f, -0.94264149f}, {0.32143947f, -0.94693013f}, +{0.30901699f, -0.95105652f}, {0.29654157f, -0.95501994f}, +{0.28401534f, -0.95881973f}, {0.27144045f, -0.96245524f}, +{0.25881905f, -0.96592583f}, {0.24615329f, -0.96923091f}, +{0.23344536f, -0.97236992f}, {0.22069744f, -0.97534232f}, +{0.20791169f, -0.97814760f}, {0.19509032f, -0.98078528f}, +{0.18223553f, -0.98325491f}, {0.16934950f, -0.98555606f}, +{0.15643447f, -0.98768834f}, {0.14349262f, -0.98965139f}, +{0.13052619f, -0.99144486f}, {0.11753740f, -0.99306846f}, +{0.10452846f, -0.99452190f}, {0.091501619f, -0.99580493f}, +{0.078459096f, -0.99691733f}, {0.065403129f, -0.99785892f}, +{0.052335956f, -0.99862953f}, {0.039259816f, -0.99922904f}, +{0.026176948f, -0.99965732f}, {0.013089596f, -0.99991433f}, +{6.1230318e-17f, -1.0000000f}, {-0.013089596f, -0.99991433f}, +{-0.026176948f, -0.99965732f}, {-0.039259816f, -0.99922904f}, +{-0.052335956f, -0.99862953f}, {-0.065403129f, -0.99785892f}, +{-0.078459096f, -0.99691733f}, {-0.091501619f, -0.99580493f}, +{-0.10452846f, -0.99452190f}, {-0.11753740f, -0.99306846f}, +{-0.13052619f, -0.99144486f}, {-0.14349262f, -0.98965139f}, +{-0.15643447f, -0.98768834f}, {-0.16934950f, -0.98555606f}, +{-0.18223553f, -0.98325491f}, {-0.19509032f, -0.98078528f}, +{-0.20791169f, -0.97814760f}, {-0.22069744f, -0.97534232f}, +{-0.23344536f, -0.97236992f}, {-0.24615329f, -0.96923091f}, +{-0.25881905f, -0.96592583f}, {-0.27144045f, -0.96245524f}, +{-0.28401534f, -0.95881973f}, {-0.29654157f, -0.95501994f}, +{-0.30901699f, -0.95105652f}, {-0.32143947f, -0.94693013f}, +{-0.33380686f, -0.94264149f}, {-0.34611706f, -0.93819134f}, +{-0.35836795f, -0.93358043f}, {-0.37055744f, -0.92880955f}, +{-0.38268343f, -0.92387953f}, {-0.39474386f, -0.91879121f}, +{-0.40673664f, -0.91354546f}, {-0.41865974f, -0.90814317f}, +{-0.43051110f, -0.90258528f}, {-0.44228869f, -0.89687274f}, +{-0.45399050f, -0.89100652f}, {-0.46561452f, -0.88498764f}, +{-0.47715876f, -0.87881711f}, {-0.48862124f, -0.87249601f}, +{-0.50000000f, -0.86602540f}, {-0.51129309f, -0.85940641f}, +{-0.52249856f, -0.85264016f}, {-0.53361452f, -0.84572782f}, +{-0.54463904f, -0.83867057f}, {-0.55557023f, -0.83146961f}, +{-0.56640624f, -0.82412619f}, {-0.57714519f, -0.81664156f}, +{-0.58778525f, -0.80901699f}, {-0.59832460f, -0.80125381f}, +{-0.60876143f, -0.79335334f}, {-0.61909395f, -0.78531693f}, +{-0.62932039f, -0.77714596f}, {-0.63943900f, -0.76884183f}, +{-0.64944805f, -0.76040597f}, {-0.65934582f, -0.75183981f}, +{-0.66913061f, -0.74314483f}, {-0.67880075f, -0.73432251f}, +{-0.68835458f, -0.72537437f}, {-0.69779046f, -0.71630194f}, +{-0.70710678f, -0.70710678f}, {-0.71630194f, -0.69779046f}, +{-0.72537437f, -0.68835458f}, {-0.73432251f, -0.67880075f}, +{-0.74314483f, -0.66913061f}, {-0.75183981f, -0.65934582f}, +{-0.76040597f, -0.64944805f}, {-0.76884183f, -0.63943900f}, +{-0.77714596f, -0.62932039f}, {-0.78531693f, -0.61909395f}, +{-0.79335334f, -0.60876143f}, {-0.80125381f, -0.59832460f}, +{-0.80901699f, -0.58778525f}, {-0.81664156f, -0.57714519f}, +{-0.82412619f, -0.56640624f}, {-0.83146961f, -0.55557023f}, +{-0.83867057f, -0.54463904f}, {-0.84572782f, -0.53361452f}, +{-0.85264016f, -0.52249856f}, {-0.85940641f, -0.51129309f}, +{-0.86602540f, -0.50000000f}, {-0.87249601f, -0.48862124f}, +{-0.87881711f, -0.47715876f}, {-0.88498764f, -0.46561452f}, +{-0.89100652f, -0.45399050f}, {-0.89687274f, -0.44228869f}, +{-0.90258528f, -0.43051110f}, {-0.90814317f, -0.41865974f}, +{-0.91354546f, -0.40673664f}, {-0.91879121f, -0.39474386f}, +{-0.92387953f, -0.38268343f}, {-0.92880955f, -0.37055744f}, +{-0.93358043f, -0.35836795f}, {-0.93819134f, -0.34611706f}, +{-0.94264149f, -0.33380686f}, {-0.94693013f, -0.32143947f}, +{-0.95105652f, -0.30901699f}, {-0.95501994f, -0.29654157f}, +{-0.95881973f, -0.28401534f}, {-0.96245524f, -0.27144045f}, +{-0.96592583f, -0.25881905f}, {-0.96923091f, -0.24615329f}, +{-0.97236992f, -0.23344536f}, {-0.97534232f, -0.22069744f}, +{-0.97814760f, -0.20791169f}, {-0.98078528f, -0.19509032f}, +{-0.98325491f, -0.18223553f}, {-0.98555606f, -0.16934950f}, +{-0.98768834f, -0.15643447f}, {-0.98965139f, -0.14349262f}, +{-0.99144486f, -0.13052619f}, {-0.99306846f, -0.11753740f}, +{-0.99452190f, -0.10452846f}, {-0.99580493f, -0.091501619f}, +{-0.99691733f, -0.078459096f}, {-0.99785892f, -0.065403129f}, +{-0.99862953f, -0.052335956f}, {-0.99922904f, -0.039259816f}, +{-0.99965732f, -0.026176948f}, {-0.99991433f, -0.013089596f}, +{-1.0000000f, -1.2246064e-16f}, {-0.99991433f, 0.013089596f}, +{-0.99965732f, 0.026176948f}, {-0.99922904f, 0.039259816f}, +{-0.99862953f, 0.052335956f}, {-0.99785892f, 0.065403129f}, +{-0.99691733f, 0.078459096f}, {-0.99580493f, 0.091501619f}, +{-0.99452190f, 0.10452846f}, {-0.99306846f, 0.11753740f}, +{-0.99144486f, 0.13052619f}, {-0.98965139f, 0.14349262f}, +{-0.98768834f, 0.15643447f}, {-0.98555606f, 0.16934950f}, +{-0.98325491f, 0.18223553f}, {-0.98078528f, 0.19509032f}, +{-0.97814760f, 0.20791169f}, {-0.97534232f, 0.22069744f}, +{-0.97236992f, 0.23344536f}, {-0.96923091f, 0.24615329f}, +{-0.96592583f, 0.25881905f}, {-0.96245524f, 0.27144045f}, +{-0.95881973f, 0.28401534f}, {-0.95501994f, 0.29654157f}, +{-0.95105652f, 0.30901699f}, {-0.94693013f, 0.32143947f}, +{-0.94264149f, 0.33380686f}, {-0.93819134f, 0.34611706f}, +{-0.93358043f, 0.35836795f}, {-0.92880955f, 0.37055744f}, +{-0.92387953f, 0.38268343f}, {-0.91879121f, 0.39474386f}, +{-0.91354546f, 0.40673664f}, {-0.90814317f, 0.41865974f}, +{-0.90258528f, 0.43051110f}, {-0.89687274f, 0.44228869f}, +{-0.89100652f, 0.45399050f}, {-0.88498764f, 0.46561452f}, +{-0.87881711f, 0.47715876f}, {-0.87249601f, 0.48862124f}, +{-0.86602540f, 0.50000000f}, {-0.85940641f, 0.51129309f}, +{-0.85264016f, 0.52249856f}, {-0.84572782f, 0.53361452f}, +{-0.83867057f, 0.54463904f}, {-0.83146961f, 0.55557023f}, +{-0.82412619f, 0.56640624f}, {-0.81664156f, 0.57714519f}, +{-0.80901699f, 0.58778525f}, {-0.80125381f, 0.59832460f}, +{-0.79335334f, 0.60876143f}, {-0.78531693f, 0.61909395f}, +{-0.77714596f, 0.62932039f}, {-0.76884183f, 0.63943900f}, +{-0.76040597f, 0.64944805f}, {-0.75183981f, 0.65934582f}, +{-0.74314483f, 0.66913061f}, {-0.73432251f, 0.67880075f}, +{-0.72537437f, 0.68835458f}, {-0.71630194f, 0.69779046f}, +{-0.70710678f, 0.70710678f}, {-0.69779046f, 0.71630194f}, +{-0.68835458f, 0.72537437f}, {-0.67880075f, 0.73432251f}, +{-0.66913061f, 0.74314483f}, {-0.65934582f, 0.75183981f}, +{-0.64944805f, 0.76040597f}, {-0.63943900f, 0.76884183f}, +{-0.62932039f, 0.77714596f}, {-0.61909395f, 0.78531693f}, +{-0.60876143f, 0.79335334f}, {-0.59832460f, 0.80125381f}, +{-0.58778525f, 0.80901699f}, {-0.57714519f, 0.81664156f}, +{-0.56640624f, 0.82412619f}, {-0.55557023f, 0.83146961f}, +{-0.54463904f, 0.83867057f}, {-0.53361452f, 0.84572782f}, +{-0.52249856f, 0.85264016f}, {-0.51129309f, 0.85940641f}, +{-0.50000000f, 0.86602540f}, {-0.48862124f, 0.87249601f}, +{-0.47715876f, 0.87881711f}, {-0.46561452f, 0.88498764f}, +{-0.45399050f, 0.89100652f}, {-0.44228869f, 0.89687274f}, +{-0.43051110f, 0.90258528f}, {-0.41865974f, 0.90814317f}, +{-0.40673664f, 0.91354546f}, {-0.39474386f, 0.91879121f}, +{-0.38268343f, 0.92387953f}, {-0.37055744f, 0.92880955f}, +{-0.35836795f, 0.93358043f}, {-0.34611706f, 0.93819134f}, +{-0.33380686f, 0.94264149f}, {-0.32143947f, 0.94693013f}, +{-0.30901699f, 0.95105652f}, {-0.29654157f, 0.95501994f}, +{-0.28401534f, 0.95881973f}, {-0.27144045f, 0.96245524f}, +{-0.25881905f, 0.96592583f}, {-0.24615329f, 0.96923091f}, +{-0.23344536f, 0.97236992f}, {-0.22069744f, 0.97534232f}, +{-0.20791169f, 0.97814760f}, {-0.19509032f, 0.98078528f}, +{-0.18223553f, 0.98325491f}, {-0.16934950f, 0.98555606f}, +{-0.15643447f, 0.98768834f}, {-0.14349262f, 0.98965139f}, +{-0.13052619f, 0.99144486f}, {-0.11753740f, 0.99306846f}, +{-0.10452846f, 0.99452190f}, {-0.091501619f, 0.99580493f}, +{-0.078459096f, 0.99691733f}, {-0.065403129f, 0.99785892f}, +{-0.052335956f, 0.99862953f}, {-0.039259816f, 0.99922904f}, +{-0.026176948f, 0.99965732f}, {-0.013089596f, 0.99991433f}, +{-1.8369095e-16f, 1.0000000f}, {0.013089596f, 0.99991433f}, +{0.026176948f, 0.99965732f}, {0.039259816f, 0.99922904f}, +{0.052335956f, 0.99862953f}, {0.065403129f, 0.99785892f}, +{0.078459096f, 0.99691733f}, {0.091501619f, 0.99580493f}, +{0.10452846f, 0.99452190f}, {0.11753740f, 0.99306846f}, +{0.13052619f, 0.99144486f}, {0.14349262f, 0.98965139f}, +{0.15643447f, 0.98768834f}, {0.16934950f, 0.98555606f}, +{0.18223553f, 0.98325491f}, {0.19509032f, 0.98078528f}, +{0.20791169f, 0.97814760f}, {0.22069744f, 0.97534232f}, +{0.23344536f, 0.97236992f}, {0.24615329f, 0.96923091f}, +{0.25881905f, 0.96592583f}, {0.27144045f, 0.96245524f}, +{0.28401534f, 0.95881973f}, {0.29654157f, 0.95501994f}, +{0.30901699f, 0.95105652f}, {0.32143947f, 0.94693013f}, +{0.33380686f, 0.94264149f}, {0.34611706f, 0.93819134f}, +{0.35836795f, 0.93358043f}, {0.37055744f, 0.92880955f}, +{0.38268343f, 0.92387953f}, {0.39474386f, 0.91879121f}, +{0.40673664f, 0.91354546f}, {0.41865974f, 0.90814317f}, +{0.43051110f, 0.90258528f}, {0.44228869f, 0.89687274f}, +{0.45399050f, 0.89100652f}, {0.46561452f, 0.88498764f}, +{0.47715876f, 0.87881711f}, {0.48862124f, 0.87249601f}, +{0.50000000f, 0.86602540f}, {0.51129309f, 0.85940641f}, +{0.52249856f, 0.85264016f}, {0.53361452f, 0.84572782f}, +{0.54463904f, 0.83867057f}, {0.55557023f, 0.83146961f}, +{0.56640624f, 0.82412619f}, {0.57714519f, 0.81664156f}, +{0.58778525f, 0.80901699f}, {0.59832460f, 0.80125381f}, +{0.60876143f, 0.79335334f}, {0.61909395f, 0.78531693f}, +{0.62932039f, 0.77714596f}, {0.63943900f, 0.76884183f}, +{0.64944805f, 0.76040597f}, {0.65934582f, 0.75183981f}, +{0.66913061f, 0.74314483f}, {0.67880075f, 0.73432251f}, +{0.68835458f, 0.72537437f}, {0.69779046f, 0.71630194f}, +{0.70710678f, 0.70710678f}, {0.71630194f, 0.69779046f}, +{0.72537437f, 0.68835458f}, {0.73432251f, 0.67880075f}, +{0.74314483f, 0.66913061f}, {0.75183981f, 0.65934582f}, +{0.76040597f, 0.64944805f}, {0.76884183f, 0.63943900f}, +{0.77714596f, 0.62932039f}, {0.78531693f, 0.61909395f}, +{0.79335334f, 0.60876143f}, {0.80125381f, 0.59832460f}, +{0.80901699f, 0.58778525f}, {0.81664156f, 0.57714519f}, +{0.82412619f, 0.56640624f}, {0.83146961f, 0.55557023f}, +{0.83867057f, 0.54463904f}, {0.84572782f, 0.53361452f}, +{0.85264016f, 0.52249856f}, {0.85940641f, 0.51129309f}, +{0.86602540f, 0.50000000f}, {0.87249601f, 0.48862124f}, +{0.87881711f, 0.47715876f}, {0.88498764f, 0.46561452f}, +{0.89100652f, 0.45399050f}, {0.89687274f, 0.44228869f}, +{0.90258528f, 0.43051110f}, {0.90814317f, 0.41865974f}, +{0.91354546f, 0.40673664f}, {0.91879121f, 0.39474386f}, +{0.92387953f, 0.38268343f}, {0.92880955f, 0.37055744f}, +{0.93358043f, 0.35836795f}, {0.93819134f, 0.34611706f}, +{0.94264149f, 0.33380686f}, {0.94693013f, 0.32143947f}, +{0.95105652f, 0.30901699f}, {0.95501994f, 0.29654157f}, +{0.95881973f, 0.28401534f}, {0.96245524f, 0.27144045f}, +{0.96592583f, 0.25881905f}, {0.96923091f, 0.24615329f}, +{0.97236992f, 0.23344536f}, {0.97534232f, 0.22069744f}, +{0.97814760f, 0.20791169f}, {0.98078528f, 0.19509032f}, +{0.98325491f, 0.18223553f}, {0.98555606f, 0.16934950f}, +{0.98768834f, 0.15643447f}, {0.98965139f, 0.14349262f}, +{0.99144486f, 0.13052619f}, {0.99306846f, 0.11753740f}, +{0.99452190f, 0.10452846f}, {0.99580493f, 0.091501619f}, +{0.99691733f, 0.078459096f}, {0.99785892f, 0.065403129f}, +{0.99862953f, 0.052335956f}, {0.99922904f, 0.039259816f}, +{0.99965732f, 0.026176948f}, {0.99991433f, 0.013089596f}, +}; +#ifndef FFT_BITREV480 +#define FFT_BITREV480 +static const opus_int16 fft_bitrev480[480] = { +0, 120, 240, 360, 30, 150, 270, 390, 60, 180, 300, 420, 90, 210, 330, +450, 15, 135, 255, 375, 45, 165, 285, 405, 75, 195, 315, 435, 105, 225, +345, 465, 5, 125, 245, 365, 35, 155, 275, 395, 65, 185, 305, 425, 95, +215, 335, 455, 20, 140, 260, 380, 50, 170, 290, 410, 80, 200, 320, 440, +110, 230, 350, 470, 10, 130, 250, 370, 40, 160, 280, 400, 70, 190, 310, +430, 100, 220, 340, 460, 25, 145, 265, 385, 55, 175, 295, 415, 85, 205, +325, 445, 115, 235, 355, 475, 1, 121, 241, 361, 31, 151, 271, 391, 61, +181, 301, 421, 91, 211, 331, 451, 16, 136, 256, 376, 46, 166, 286, 406, +76, 196, 316, 436, 106, 226, 346, 466, 6, 126, 246, 366, 36, 156, 276, +396, 66, 186, 306, 426, 96, 216, 336, 456, 21, 141, 261, 381, 51, 171, +291, 411, 81, 201, 321, 441, 111, 231, 351, 471, 11, 131, 251, 371, 41, +161, 281, 401, 71, 191, 311, 431, 101, 221, 341, 461, 26, 146, 266, 386, +56, 176, 296, 416, 86, 206, 326, 446, 116, 236, 356, 476, 2, 122, 242, +362, 32, 152, 272, 392, 62, 182, 302, 422, 92, 212, 332, 452, 17, 137, +257, 377, 47, 167, 287, 407, 77, 197, 317, 437, 107, 227, 347, 467, 7, +127, 247, 367, 37, 157, 277, 397, 67, 187, 307, 427, 97, 217, 337, 457, +22, 142, 262, 382, 52, 172, 292, 412, 82, 202, 322, 442, 112, 232, 352, +472, 12, 132, 252, 372, 42, 162, 282, 402, 72, 192, 312, 432, 102, 222, +342, 462, 27, 147, 267, 387, 57, 177, 297, 417, 87, 207, 327, 447, 117, +237, 357, 477, 3, 123, 243, 363, 33, 153, 273, 393, 63, 183, 303, 423, +93, 213, 333, 453, 18, 138, 258, 378, 48, 168, 288, 408, 78, 198, 318, +438, 108, 228, 348, 468, 8, 128, 248, 368, 38, 158, 278, 398, 68, 188, +308, 428, 98, 218, 338, 458, 23, 143, 263, 383, 53, 173, 293, 413, 83, +203, 323, 443, 113, 233, 353, 473, 13, 133, 253, 373, 43, 163, 283, 403, +73, 193, 313, 433, 103, 223, 343, 463, 28, 148, 268, 388, 58, 178, 298, +418, 88, 208, 328, 448, 118, 238, 358, 478, 4, 124, 244, 364, 34, 154, +274, 394, 64, 184, 304, 424, 94, 214, 334, 454, 19, 139, 259, 379, 49, +169, 289, 409, 79, 199, 319, 439, 109, 229, 349, 469, 9, 129, 249, 369, +39, 159, 279, 399, 69, 189, 309, 429, 99, 219, 339, 459, 24, 144, 264, +384, 54, 174, 294, 414, 84, 204, 324, 444, 114, 234, 354, 474, 14, 134, +254, 374, 44, 164, 284, 404, 74, 194, 314, 434, 104, 224, 344, 464, 29, +149, 269, 389, 59, 179, 299, 419, 89, 209, 329, 449, 119, 239, 359, 479, +}; +#endif + +#ifndef FFT_BITREV240 +#define FFT_BITREV240 +static const opus_int16 fft_bitrev240[240] = { +0, 60, 120, 180, 15, 75, 135, 195, 30, 90, 150, 210, 45, 105, 165, +225, 5, 65, 125, 185, 20, 80, 140, 200, 35, 95, 155, 215, 50, 110, +170, 230, 10, 70, 130, 190, 25, 85, 145, 205, 40, 100, 160, 220, 55, +115, 175, 235, 1, 61, 121, 181, 16, 76, 136, 196, 31, 91, 151, 211, +46, 106, 166, 226, 6, 66, 126, 186, 21, 81, 141, 201, 36, 96, 156, +216, 51, 111, 171, 231, 11, 71, 131, 191, 26, 86, 146, 206, 41, 101, +161, 221, 56, 116, 176, 236, 2, 62, 122, 182, 17, 77, 137, 197, 32, +92, 152, 212, 47, 107, 167, 227, 7, 67, 127, 187, 22, 82, 142, 202, +37, 97, 157, 217, 52, 112, 172, 232, 12, 72, 132, 192, 27, 87, 147, +207, 42, 102, 162, 222, 57, 117, 177, 237, 3, 63, 123, 183, 18, 78, +138, 198, 33, 93, 153, 213, 48, 108, 168, 228, 8, 68, 128, 188, 23, +83, 143, 203, 38, 98, 158, 218, 53, 113, 173, 233, 13, 73, 133, 193, +28, 88, 148, 208, 43, 103, 163, 223, 58, 118, 178, 238, 4, 64, 124, +184, 19, 79, 139, 199, 34, 94, 154, 214, 49, 109, 169, 229, 9, 69, +129, 189, 24, 84, 144, 204, 39, 99, 159, 219, 54, 114, 174, 234, 14, +74, 134, 194, 29, 89, 149, 209, 44, 104, 164, 224, 59, 119, 179, 239, +}; +#endif + +#ifndef FFT_BITREV120 +#define FFT_BITREV120 +static const opus_int16 fft_bitrev120[120] = { +0, 30, 60, 90, 15, 45, 75, 105, 5, 35, 65, 95, 20, 50, 80, +110, 10, 40, 70, 100, 25, 55, 85, 115, 1, 31, 61, 91, 16, 46, +76, 106, 6, 36, 66, 96, 21, 51, 81, 111, 11, 41, 71, 101, 26, +56, 86, 116, 2, 32, 62, 92, 17, 47, 77, 107, 7, 37, 67, 97, +22, 52, 82, 112, 12, 42, 72, 102, 27, 57, 87, 117, 3, 33, 63, +93, 18, 48, 78, 108, 8, 38, 68, 98, 23, 53, 83, 113, 13, 43, +73, 103, 28, 58, 88, 118, 4, 34, 64, 94, 19, 49, 79, 109, 9, +39, 69, 99, 24, 54, 84, 114, 14, 44, 74, 104, 29, 59, 89, 119, +}; +#endif + +#ifndef FFT_BITREV60 +#define FFT_BITREV60 +static const opus_int16 fft_bitrev60[60] = { +0, 15, 30, 45, 5, 20, 35, 50, 10, 25, 40, 55, 1, 16, 31, +46, 6, 21, 36, 51, 11, 26, 41, 56, 2, 17, 32, 47, 7, 22, +37, 52, 12, 27, 42, 57, 3, 18, 33, 48, 8, 23, 38, 53, 13, +28, 43, 58, 4, 19, 34, 49, 9, 24, 39, 54, 14, 29, 44, 59, +}; +#endif + +#ifndef FFT_STATE48000_960_0 +#define FFT_STATE48000_960_0 +static const kiss_fft_state fft_state48000_960_0 = { +480, /* nfft */ +0.002083333f, /* scale */ +-1, /* shift */ +{4, 120, 4, 30, 2, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, }, /* factors */ +fft_bitrev480, /* bitrev */ +fft_twiddles48000_960, /* bitrev */ +}; +#endif + +#ifndef FFT_STATE48000_960_1 +#define FFT_STATE48000_960_1 +static const kiss_fft_state fft_state48000_960_1 = { +240, /* nfft */ +0.004166667f, /* scale */ +1, /* shift */ +{4, 60, 4, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */ +fft_bitrev240, /* bitrev */ +fft_twiddles48000_960, /* bitrev */ +}; +#endif + +#ifndef FFT_STATE48000_960_2 +#define FFT_STATE48000_960_2 +static const kiss_fft_state fft_state48000_960_2 = { +120, /* nfft */ +0.008333333f, /* scale */ +2, /* shift */ +{4, 30, 2, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */ +fft_bitrev120, /* bitrev */ +fft_twiddles48000_960, /* bitrev */ +}; +#endif + +#ifndef FFT_STATE48000_960_3 +#define FFT_STATE48000_960_3 +static const kiss_fft_state fft_state48000_960_3 = { +60, /* nfft */ +0.016666667f, /* scale */ +3, /* shift */ +{4, 15, 3, 5, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */ +fft_bitrev60, /* bitrev */ +fft_twiddles48000_960, /* bitrev */ +}; +#endif + +#endif + +#ifndef MDCT_TWIDDLES960 +#define MDCT_TWIDDLES960 +static const opus_val16 mdct_twiddles960[481] = { +1.0000000f, 0.99999465f, 0.99997858f, 0.99995181f, 0.99991433f, +0.99986614f, 0.99980724f, 0.99973764f, 0.99965732f, 0.99956631f, +0.99946459f, 0.99935216f, 0.99922904f, 0.99909521f, 0.99895068f, +0.99879546f, 0.99862953f, 0.99845292f, 0.99826561f, 0.99806761f, +0.99785892f, 0.99763955f, 0.99740949f, 0.99716875f, 0.99691733f, +0.99665524f, 0.99638247f, 0.99609903f, 0.99580493f, 0.99550016f, +0.99518473f, 0.99485864f, 0.99452190f, 0.99417450f, 0.99381646f, +0.99344778f, 0.99306846f, 0.99267850f, 0.99227791f, 0.99186670f, +0.99144486f, 0.99101241f, 0.99056934f, 0.99011566f, 0.98965139f, +0.98917651f, 0.98869104f, 0.98819498f, 0.98768834f, 0.98717112f, +0.98664333f, 0.98610497f, 0.98555606f, 0.98499659f, 0.98442657f, +0.98384600f, 0.98325491f, 0.98265328f, 0.98204113f, 0.98141846f, +0.98078528f, 0.98014159f, 0.97948742f, 0.97882275f, 0.97814760f, +0.97746197f, 0.97676588f, 0.97605933f, 0.97534232f, 0.97461487f, +0.97387698f, 0.97312866f, 0.97236992f, 0.97160077f, 0.97082121f, +0.97003125f, 0.96923091f, 0.96842019f, 0.96759909f, 0.96676764f, +0.96592582f, 0.96507367f, 0.96421118f, 0.96333837f, 0.96245523f, +0.96156180f, 0.96065806f, 0.95974403f, 0.95881973f, 0.95788517f, +0.95694034f, 0.95598526f, 0.95501995f, 0.95404440f, 0.95305864f, +0.95206267f, 0.95105651f, 0.95004016f, 0.94901364f, 0.94797697f, +0.94693013f, 0.94587315f, 0.94480604f, 0.94372882f, 0.94264149f, +0.94154406f, 0.94043656f, 0.93931897f, 0.93819133f, 0.93705365f, +0.93590592f, 0.93474818f, 0.93358042f, 0.93240268f, 0.93121493f, +0.93001722f, 0.92880955f, 0.92759193f, 0.92636438f, 0.92512690f, +0.92387953f, 0.92262225f, 0.92135509f, 0.92007809f, 0.91879121f, +0.91749449f, 0.91618795f, 0.91487161f, 0.91354545f, 0.91220952f, +0.91086382f, 0.90950836f, 0.90814316f, 0.90676824f, 0.90538363f, +0.90398929f, 0.90258528f, 0.90117161f, 0.89974828f, 0.89831532f, +0.89687273f, 0.89542055f, 0.89395877f, 0.89248742f, 0.89100652f, +0.88951606f, 0.88801610f, 0.88650661f, 0.88498764f, 0.88345918f, +0.88192125f, 0.88037390f, 0.87881711f, 0.87725090f, 0.87567531f, +0.87409035f, 0.87249599f, 0.87089232f, 0.86927933f, 0.86765699f, +0.86602540f, 0.86438453f, 0.86273437f, 0.86107503f, 0.85940641f, +0.85772862f, 0.85604161f, 0.85434547f, 0.85264014f, 0.85092572f, +0.84920218f, 0.84746955f, 0.84572781f, 0.84397704f, 0.84221721f, +0.84044838f, 0.83867056f, 0.83688375f, 0.83508799f, 0.83328325f, +0.83146961f, 0.82964704f, 0.82781562f, 0.82597530f, 0.82412620f, +0.82226820f, 0.82040144f, 0.81852589f, 0.81664154f, 0.81474847f, +0.81284665f, 0.81093620f, 0.80901698f, 0.80708914f, 0.80515262f, +0.80320752f, 0.80125378f, 0.79929149f, 0.79732067f, 0.79534125f, +0.79335335f, 0.79135691f, 0.78935204f, 0.78733867f, 0.78531691f, +0.78328674f, 0.78124818f, 0.77920122f, 0.77714595f, 0.77508232f, +0.77301043f, 0.77093026f, 0.76884183f, 0.76674517f, 0.76464026f, +0.76252720f, 0.76040593f, 0.75827656f, 0.75613907f, 0.75399349f, +0.75183978f, 0.74967807f, 0.74750833f, 0.74533054f, 0.74314481f, +0.74095112f, 0.73874950f, 0.73653993f, 0.73432251f, 0.73209718f, +0.72986405f, 0.72762307f, 0.72537438f, 0.72311787f, 0.72085359f, +0.71858162f, 0.71630192f, 0.71401459f, 0.71171956f, 0.70941701f, +0.70710677f, 0.70478900f, 0.70246363f, 0.70013079f, 0.69779041f, +0.69544260f, 0.69308738f, 0.69072466f, 0.68835458f, 0.68597709f, +0.68359229f, 0.68120013f, 0.67880072f, 0.67639404f, 0.67398011f, +0.67155892f, 0.66913059f, 0.66669509f, 0.66425240f, 0.66180265f, +0.65934581f, 0.65688191f, 0.65441092f, 0.65193298f, 0.64944801f, +0.64695613f, 0.64445727f, 0.64195160f, 0.63943902f, 0.63691954f, +0.63439328f, 0.63186019f, 0.62932037f, 0.62677377f, 0.62422055f, +0.62166055f, 0.61909394f, 0.61652065f, 0.61394081f, 0.61135435f, +0.60876139f, 0.60616195f, 0.60355593f, 0.60094349f, 0.59832457f, +0.59569929f, 0.59306758f, 0.59042957f, 0.58778523f, 0.58513460f, +0.58247766f, 0.57981452f, 0.57714518f, 0.57446961f, 0.57178793f, +0.56910013f, 0.56640624f, 0.56370623f, 0.56100023f, 0.55828818f, +0.55557020f, 0.55284627f, 0.55011641f, 0.54738067f, 0.54463901f, +0.54189157f, 0.53913828f, 0.53637921f, 0.53361450f, 0.53084398f, +0.52806787f, 0.52528601f, 0.52249852f, 0.51970543f, 0.51690688f, +0.51410279f, 0.51129310f, 0.50847793f, 0.50565732f, 0.50283139f, +0.49999997f, 0.49716321f, 0.49432122f, 0.49147383f, 0.48862118f, +0.48576340f, 0.48290042f, 0.48003216f, 0.47715876f, 0.47428025f, +0.47139677f, 0.46850813f, 0.46561448f, 0.46271584f, 0.45981235f, +0.45690383f, 0.45399042f, 0.45107214f, 0.44814915f, 0.44522124f, +0.44228868f, 0.43935137f, 0.43640926f, 0.43346247f, 0.43051104f, +0.42755511f, 0.42459449f, 0.42162932f, 0.41865964f, 0.41568558f, +0.41270697f, 0.40972393f, 0.40673661f, 0.40374494f, 0.40074884f, +0.39774844f, 0.39474390f, 0.39173501f, 0.38872193f, 0.38570469f, +0.38268343f, 0.37965796f, 0.37662842f, 0.37359496f, 0.37055739f, +0.36751585f, 0.36447038f, 0.36142122f, 0.35836797f, 0.35531089f, +0.35225000f, 0.34918544f, 0.34611704f, 0.34304493f, 0.33996926f, +0.33688983f, 0.33380680f, 0.33072019f, 0.32763015f, 0.32453650f, +0.32143936f, 0.31833890f, 0.31523503f, 0.31212767f, 0.30901696f, +0.30590306f, 0.30278577f, 0.29966524f, 0.29654150f, 0.29341470f, +0.29028464f, 0.28715147f, 0.28401522f, 0.28087605f, 0.27773376f, +0.27458861f, 0.27144052f, 0.26828940f, 0.26513541f, 0.26197859f, +0.25881907f, 0.25565666f, 0.25249152f, 0.24932367f, 0.24615327f, +0.24298012f, 0.23980436f, 0.23662604f, 0.23344530f, 0.23026206f, +0.22707623f, 0.22388809f, 0.22069744f, 0.21750443f, 0.21430908f, +0.21111156f, 0.20791165f, 0.20470953f, 0.20150520f, 0.19829884f, +0.19509024f, 0.19187955f, 0.18866692f, 0.18545227f, 0.18223552f, +0.17901681f, 0.17579631f, 0.17257380f, 0.16934945f, 0.16612328f, +0.16289546f, 0.15966577f, 0.15643437f, 0.15320141f, 0.14996669f, +0.14673037f, 0.14349260f, 0.14025329f, 0.13701235f, 0.13376995f, +0.13052612f, 0.12728101f, 0.12403442f, 0.12078650f, 0.11753740f, +0.11428693f, 0.11103523f, 0.10778234f, 0.10452842f, 0.10127326f, +0.098017137f, 0.094759842f, 0.091501652f, 0.088242363f, 0.084982129f, +0.081721103f, 0.078459084f, 0.075196224f, 0.071932560f, 0.068668243f, +0.065403073f, 0.062137201f, 0.058870665f, 0.055603617f, 0.052335974f, +0.049067651f, 0.045798921f, 0.042529582f, 0.039259788f, 0.035989573f, +0.032719092f, 0.029448142f, 0.026176876f, 0.022905329f, 0.019633657f, +0.016361655f, 0.013089478f, 0.0098171604f, 0.0065449764f, 0.0032724839f, +-4.3711390e-08f, }; +#endif + +static const CELTMode mode48000_960_120 = { +48000, /* Fs */ +120, /* overlap */ +21, /* nbEBands */ +21, /* effEBands */ +{0.85000610f, 0.0000000f, 1.0000000f, 1.0000000f, }, /* preemph */ +eband5ms, /* eBands */ +3, /* maxLM */ +8, /* nbShortMdcts */ +120, /* shortMdctSize */ +11, /* nbAllocVectors */ +band_allocation, /* allocVectors */ +logN400, /* logN */ +window120, /* window */ +{1920, 3, {&fft_state48000_960_0, &fft_state48000_960_1, &fft_state48000_960_2, &fft_state48000_960_3, }, mdct_twiddles960}, /* mdct */ +{392, cache_index50, cache_bits50, cache_caps50}, /* cache */ +}; + +/* List of all the available modes */ +#define TOTAL_MODES 1 +static const CELTMode * const static_mode_list[TOTAL_MODES] = { +&mode48000_960_120, +}; diff --git a/TelegramClient.Opus/opus/celt/vq.c b/TelegramClient.Opus/opus/celt/vq.c new file mode 100755 index 0000000..98a0f36 --- /dev/null +++ b/TelegramClient.Opus/opus/celt/vq.c @@ -0,0 +1,415 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mathops.h" +#include "cwrs.h" +#include "vq.h" +#include "arch.h" +#include "os_support.h" +#include "bands.h" +#include "rate.h" + +static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s) +{ + int i; + celt_norm *Xptr; + Xptr = X; + for (i=0;i=0;i--) + { + celt_norm x1, x2; + x1 = Xptr[0]; + x2 = Xptr[stride]; + Xptr[stride] = EXTRACT16(SHR32(MULT16_16(c,x2) + MULT16_16(s,x1), 15)); + *Xptr-- = EXTRACT16(SHR32(MULT16_16(c,x1) - MULT16_16(s,x2), 15)); + } +} + +static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread) +{ + static const int SPREAD_FACTOR[3]={15,10,5}; + int i; + opus_val16 c, s; + opus_val16 gain, theta; + int stride2=0; + int factor; + + if (2*K>=len || spread==SPREAD_NONE) + return; + factor = SPREAD_FACTOR[spread-1]; + + gain = celt_div((opus_val32)MULT16_16(Q15_ONE,len),(opus_val32)(len+factor*K)); + theta = HALF16(MULT16_16_Q15(gain,gain)); + + c = celt_cos_norm(EXTEND32(theta)); + s = celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /* sin(theta) */ + + if (len>=8*stride) + { + stride2 = 1; + /* This is just a simple (equivalent) way of computing sqrt(len/stride) with rounding. + It's basically incrementing long as (stride2+0.5)^2 < len/stride. */ + while ((stride2*stride2+stride2)*stride + (stride>>2) < len) + stride2++; + } + /*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for + extract_collapse_mask().*/ + len /= stride; + for (i=0;i>1; +#endif + t = VSHR32(Ryy, 2*(k-7)); + g = MULT16_16_P15(celt_rsqrt_norm(t),gain); + + i=0; + do + X[i] = EXTRACT16(PSHR32(MULT16_16(g, iy[i]), k+1)); + while (++i < N); +} + +static unsigned extract_collapse_mask(int *iy, int N, int B) +{ + unsigned collapse_mask; + int N0; + int i; + if (B<=1) + return 1; + /*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for + exp_rotation().*/ + N0 = N/B; + collapse_mask = 0; + i=0; do { + int j; + j=0; do { + collapse_mask |= (iy[i*N0+j]!=0)<0, "alg_quant() needs at least one pulse"); + celt_assert2(N>1, "alg_quant() needs at least two dimensions"); + + ALLOC(y, N, celt_norm); + ALLOC(iy, N, int); + ALLOC(signx, N, opus_val16); + + exp_rotation(X, N, 1, B, K, spread); + + /* Get rid of the sign */ + sum = 0; + j=0; do { + if (X[j]>0) + signx[j]=1; + else { + signx[j]=-1; + X[j]=-X[j]; + } + iy[j] = 0; + y[j] = 0; + } while (++j (N>>1)) + { + opus_val16 rcp; + j=0; do { + sum += X[j]; + } while (++j EPSILON && sum < 64)) +#endif + { + X[0] = QCONST16(1.f,14); + j=1; do + X[j]=0; + while (++j=1, "Allocated too many pulses in the quick pass"); + + /* This should never happen, but just in case it does (e.g. on silence) + we fill the first bin with pulses. */ +#ifdef FIXED_POINT_DEBUG + celt_assert2(pulsesLeft<=N+3, "Not enough pulses in the quick pass"); +#endif + if (pulsesLeft > N+3) + { + opus_val16 tmp = (opus_val16)pulsesLeft; + yy = MAC16_16(yy, tmp, tmp); + yy = MAC16_16(yy, tmp, y[0]); + iy[0] += pulsesLeft; + pulsesLeft=0; + } + + s = 1; + for (i=0;i= best_num/best_den, but that way + we can do it without any division */ + /* OPT: Make sure to use conditional moves here */ + if (MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num)) + { + best_den = Ryy; + best_num = Rxy; + best_id = j; + } + } while (++j0, "alg_unquant() needs at least one pulse"); + celt_assert2(N>1, "alg_unquant() needs at least two dimensions"); + ALLOC(iy, N, int); + decode_pulses(iy, N, K, dec); + Ryy = 0; + i=0; + do { + Ryy = MAC16_16(Ryy, iy[i], iy[i]); + } while (++i < N); + normalise_residual(iy, X, N, Ryy, gain); + exp_rotation(X, N, -1, B, K, spread); + collapse_mask = extract_collapse_mask(iy, N, B); + RESTORE_STACK; + return collapse_mask; +} + +void renormalise_vector(celt_norm *X, int N, opus_val16 gain) +{ + int i; +#ifdef FIXED_POINT + int k; +#endif + opus_val32 E = EPSILON; + opus_val16 g; + opus_val32 t; + celt_norm *xptr = X; + for (i=0;i>1; +#endif + t = VSHR32(E, 2*(k-7)); + g = MULT16_16_P15(celt_rsqrt_norm(t),gain); + + xptr = X; + for (i=0;i +#include "arch.h" + +#define OVERRIDE_XCORR_KERNEL +static OPUS_INLINE void xcorr_kernel(const opus_val16 *x, const opus_val16 *y, opus_val32 sum[4], int len) +{ + int j; + __m128 xsum1, xsum2; + xsum1 = _mm_loadu_ps(sum); + xsum2 = _mm_setzero_ps(); + + for (j = 0; j < len-3; j += 4) + { + __m128 x0 = _mm_loadu_ps(x+j); + __m128 yj = _mm_loadu_ps(y+j); + __m128 y3 = _mm_loadu_ps(y+j+3); + + xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0x00),yj)); + xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0x55), + _mm_shuffle_ps(yj,y3,0x49))); + xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0xaa), + _mm_shuffle_ps(yj,y3,0x9e))); + xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0xff),y3)); + } + if (j < len) + { + xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_load1_ps(x+j),_mm_loadu_ps(y+j))); + if (++j < len) + { + xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(_mm_load1_ps(x+j),_mm_loadu_ps(y+j))); + if (++j < len) + { + xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_load1_ps(x+j),_mm_loadu_ps(y+j))); + } + } + } + _mm_storeu_ps(sum,_mm_add_ps(xsum1,xsum2)); +} + +#define OVERRIDE_DUAL_INNER_PROD +static OPUS_INLINE void dual_inner_prod(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02, + int N, opus_val32 *xy1, opus_val32 *xy2) +{ + int i; + __m128 xsum1, xsum2; + xsum1 = _mm_setzero_ps(); + xsum2 = _mm_setzero_ps(); + for (i=0;i + *
  • audio_frame is the audio data in opus_int16 (or float for opus_encode_float())
  • + *
  • frame_size is the duration of the frame in samples (per channel)
  • + *
  • packet is the byte array to which the compressed data is written
  • + *
  • max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended). + * Do not use max_packet to control VBR target bitrate, instead use the #OPUS_SET_BITRATE CTL.
  • + * + * + * opus_encode() and opus_encode_float() return the number of bytes actually written to the packet. + * The return value can be negative, which indicates that an error has occurred. If the return value + * is 1 byte, then the packet does not need to be transmitted (DTX). + * + * Once the encoder state if no longer needed, it can be destroyed with + * + * @code + * opus_encoder_destroy(enc); + * @endcode + * + * If the encoder was created with opus_encoder_init() rather than opus_encoder_create(), + * then no action is required aside from potentially freeing the memory that was manually + * allocated for it (calling free(enc) for the example above) + * + */ + +/** Opus encoder state. + * This contains the complete state of an Opus encoder. + * It is position independent and can be freely copied. + * @see opus_encoder_create,opus_encoder_init + */ +typedef struct OpusEncoder OpusEncoder; + +/** Gets the size of an OpusEncoder structure. + * @param[in] channels int: Number of channels. + * This must be 1 or 2. + * @returns The size in bytes. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels); + +/** + */ + +/** Allocates and initializes an encoder state. + * There are three coding modes: + * + * @ref OPUS_APPLICATION_VOIP gives best quality at a given bitrate for voice + * signals. It enhances the input signal by high-pass filtering and + * emphasizing formants and harmonics. Optionally it includes in-band + * forward error correction to protect against packet loss. Use this + * mode for typical VoIP applications. Because of the enhancement, + * even at high bitrates the output may sound different from the input. + * + * @ref OPUS_APPLICATION_AUDIO gives best quality at a given bitrate for most + * non-voice signals like music. Use this mode for music and mixed + * (music/voice) content, broadcast, and applications requiring less + * than 15 ms of coding delay. + * + * @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY configures low-delay mode that + * disables the speech-optimized mode in exchange for slightly reduced delay. + * This mode can only be set on an newly initialized or freshly reset encoder + * because it changes the codec delay. + * + * This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution). + * @param [in] Fs opus_int32: Sampling rate of input signal (Hz) + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels int: Number of channels (1 or 2) in input signal + * @param [in] application int: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY) + * @param [out] error int*: @ref opus_errorcodes + * @note Regardless of the sampling rate and number channels selected, the Opus encoder + * can switch to a lower audio bandwidth or number of channels if the bitrate + * selected is too low. This also means that it is safe to always use 48 kHz stereo input + * and let the encoder optimize the encoding. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create( + opus_int32 Fs, + int channels, + int application, + int *error +); + +/** Initializes a previously allocated encoder state + * The memory pointed to by st must be at least the size returned by opus_encoder_get_size(). + * This is intended for applications which use their own allocator instead of malloc. + * @see opus_encoder_create(),opus_encoder_get_size() + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @param [in] st OpusEncoder*: Encoder state + * @param [in] Fs opus_int32: Sampling rate of input signal (Hz) + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels int: Number of channels (1 or 2) in input signal + * @param [in] application int: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY) + * @retval #OPUS_OK Success or @ref opus_errorcodes + */ +OPUS_EXPORT int opus_encoder_init( + OpusEncoder *st, + opus_int32 Fs, + int channels, + int application +) OPUS_ARG_NONNULL(1); + +/** Encodes an Opus frame. + * @param [in] st OpusEncoder*: Encoder state + * @param [in] pcm opus_int16*: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16) + * @param [in] frame_size int: Number of samples per channel in the + * input signal. + * This must be an Opus frame size for + * the encoder's sampling rate. + * For example, at 48 kHz the permitted + * values are 120, 240, 480, 960, 1920, + * and 2880. + * Passing in a duration of less than + * 10 ms (480 samples at 48 kHz) will + * prevent the encoder from using the LPC + * or hybrid modes. + * @param [out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode( + OpusEncoder *st, + const opus_int16 *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Encodes an Opus frame from floating point input. + * @param [in] st OpusEncoder*: Encoder state + * @param [in] pcm float*: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0. + * Samples with a range beyond +/-1.0 are supported but will + * be clipped by decoders using the integer API and should + * only be used if it is known that the far end supports + * extended dynamic range. + * length is frame_size*channels*sizeof(float) + * @param [in] frame_size int: Number of samples per channel in the + * input signal. + * This must be an Opus frame size for + * the encoder's sampling rate. + * For example, at 48 kHz the permitted + * values are 120, 240, 480, 960, 1920, + * and 2880. + * Passing in a duration of less than + * 10 ms (480 samples at 48 kHz) will + * prevent the encoder from using the LPC + * or hybrid modes. + * @param [out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float( + OpusEncoder *st, + const float *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Frees an OpusEncoder allocated by opus_encoder_create(). + * @param[in] st OpusEncoder*: State to be freed. + */ +OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st); + +/** Perform a CTL function on an Opus encoder. + * + * Generally the request and subsequent arguments are generated + * by a convenience macro. + * @param st OpusEncoder*: Encoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls or + * @ref opus_encoderctls. + * @see opus_genericctls + * @see opus_encoderctls + */ +OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); +/**@}*/ + +/** @defgroup opus_decoder Opus Decoder + * @{ + * + * @brief This page describes the process and functions used to decode Opus. + * + * The decoding process also starts with creating a decoder + * state. This can be done with: + * @code + * int error; + * OpusDecoder *dec; + * dec = opus_decoder_create(Fs, channels, &error); + * @endcode + * where + * @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000 + * @li channels is the number of channels (1 or 2) + * @li error will hold the error code in case of failure (or #OPUS_OK on success) + * @li the return value is a newly created decoder state to be used for decoding + * + * While opus_decoder_create() allocates memory for the state, it's also possible + * to initialize pre-allocated memory: + * @code + * int size; + * int error; + * OpusDecoder *dec; + * size = opus_decoder_get_size(channels); + * dec = malloc(size); + * error = opus_decoder_init(dec, Fs, channels); + * @endcode + * where opus_decoder_get_size() returns the required size for the decoder state. Note that + * future versions of this code may change the size, so no assuptions should be made about it. + * + * The decoder state is always continuous in memory and only a shallow copy is sufficient + * to copy it (e.g. memcpy()) + * + * To decode a frame, opus_decode() or opus_decode_float() must be called with a packet of compressed audio data: + * @code + * frame_size = opus_decode(dec, packet, len, decoded, max_size, 0); + * @endcode + * where + * + * @li packet is the byte array containing the compressed data + * @li len is the exact number of bytes contained in the packet + * @li decoded is the decoded audio data in opus_int16 (or float for opus_decode_float()) + * @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array + * + * opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet. + * If that value is negative, then an error has occurred. This can occur if the packet is corrupted or if the audio + * buffer is too small to hold the decoded audio. + * + * Opus is a stateful codec with overlapping blocks and as a result Opus + * packets are not coded independently of each other. Packets must be + * passed into the decoder serially and in the correct order for a correct + * decode. Lost packets can be replaced with loss concealment by calling + * the decoder with a null pointer and zero length for the missing packet. + * + * A single codec state may only be accessed from a single thread at + * a time and any required locking must be performed by the caller. Separate + * streams must be decoded with separate decoder states and can be decoded + * in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK + * defined. + * + */ + +/** Opus decoder state. + * This contains the complete state of an Opus decoder. + * It is position independent and can be freely copied. + * @see opus_decoder_create,opus_decoder_init + */ +typedef struct OpusDecoder OpusDecoder; + +/** Gets the size of an OpusDecoder structure. + * @param [in] channels int: Number of channels. + * This must be 1 or 2. + * @returns The size in bytes. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels); + +/** Allocates and initializes a decoder state. + * @param [in] Fs opus_int32: Sample rate to decode at (Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels int: Number of channels (1 or 2) to decode + * @param [out] error int*: #OPUS_OK Success or @ref opus_errorcodes + * + * Internally Opus stores data at 48000 Hz, so that should be the default + * value for Fs. However, the decoder can efficiently decode to buffers + * at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use + * data at the full sample rate, or knows the compressed data doesn't + * use the full frequency range, it can request decoding at a reduced + * rate. Likewise, the decoder is capable of filling in either mono or + * interleaved stereo pcm buffers, at the caller's request. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create( + opus_int32 Fs, + int channels, + int *error +); + +/** Initializes a previously allocated decoder state. + * The state must be at least the size returned by opus_decoder_get_size(). + * This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @param [in] st OpusDecoder*: Decoder state. + * @param [in] Fs opus_int32: Sampling rate to decode to (Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param [in] channels int: Number of channels (1 or 2) to decode + * @retval #OPUS_OK Success or @ref opus_errorcodes + */ +OPUS_EXPORT int opus_decoder_init( + OpusDecoder *st, + opus_int32 Fs, + int channels +) OPUS_ARG_NONNULL(1); + +/** Decode an Opus packet. + * @param [in] st OpusDecoder*: Decoder state + * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss + * @param [in] len opus_int32: Number of bytes in payload* + * @param [out] pcm opus_int16*: Output signal (interleaved if 2 channels). length + * is frame_size*channels*sizeof(opus_int16) + * @param [in] frame_size Number of samples per channel of available space in \a pcm. + * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will + * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1), + * then frame_size needs to be exactly the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and + * FEC cases, frame_size must be a multiple of 2.5 ms. + * @param [in] decode_fec int: Flag (0 or 1) to request that any in-band forward error correction data be + * decoded. If no such data is available, the frame is decoded as if it were lost. + * @returns Number of decoded samples or @ref opus_errorcodes + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode( + OpusDecoder *st, + const unsigned char *data, + opus_int32 len, + opus_int16 *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Decode an Opus packet with floating point output. + * @param [in] st OpusDecoder*: Decoder state + * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss + * @param [in] len opus_int32: Number of bytes in payload + * @param [out] pcm float*: Output signal (interleaved if 2 channels). length + * is frame_size*channels*sizeof(float) + * @param [in] frame_size Number of samples per channel of available space in \a pcm. + * If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will + * not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1), + * then frame_size needs to be exactly the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the next incoming packet. For the PLC and + * FEC cases, frame_size must be a multiple of 2.5 ms. + * @param [in] decode_fec int: Flag (0 or 1) to request that any in-band forward error correction data be + * decoded. If no such data is available the frame is decoded as if it were lost. + * @returns Number of decoded samples or @ref opus_errorcodes + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float( + OpusDecoder *st, + const unsigned char *data, + opus_int32 len, + float *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Perform a CTL function on an Opus decoder. + * + * Generally the request and subsequent arguments are generated + * by a convenience macro. + * @param st OpusDecoder*: Decoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls or + * @ref opus_decoderctls. + * @see opus_genericctls + * @see opus_decoderctls + */ +OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); + +/** Frees an OpusDecoder allocated by opus_decoder_create(). + * @param[in] st OpusDecoder*: State to be freed. + */ +OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st); + +/** Parse an opus packet into one or more frames. + * Opus_decode will perform this operation internally so most applications do + * not need to use this function. + * This function does not copy the frames, the returned pointers are pointers into + * the input packet. + * @param [in] data char*: Opus packet to be parsed + * @param [in] len opus_int32: size of data + * @param [out] out_toc char*: TOC pointer + * @param [out] frames char*[48] encapsulated frames + * @param [out] size opus_int16[48] sizes of the encapsulated frames + * @param [out] payload_offset int*: returns the position of the payload within the packet (in bytes) + * @returns number of frames + */ +OPUS_EXPORT int opus_packet_parse( + const unsigned char *data, + opus_int32 len, + unsigned char *out_toc, + const unsigned char *frames[48], + opus_int16 size[48], + int *payload_offset +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Gets the bandwidth of an Opus packet. + * @param [in] data char*: Opus packet + * @retval OPUS_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass) + * @retval OPUS_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass) + * @retval OPUS_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass) + * @retval OPUS_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass) + * @retval OPUS_BANDWIDTH_FULLBAND Fullband (20kHz bandpass) + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1); + +/** Gets the number of samples per frame from an Opus packet. + * @param [in] data char*: Opus packet. + * This must contain at least one byte of + * data. + * @param [in] Fs opus_int32: Sampling rate in Hz. + * This must be a multiple of 400, or + * inaccurate results will be returned. + * @returns Number of samples per frame. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1); + +/** Gets the number of channels from an Opus packet. + * @param [in] data char*: Opus packet + * @returns Number of channels + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsigned char *data) OPUS_ARG_NONNULL(1); + +/** Gets the number of frames in an Opus packet. + * @param [in] packet char*: Opus packet + * @param [in] len opus_int32: Length of packet + * @returns Number of frames + * @retval OPUS_BAD_ARG Insufficient data was passed to the function + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1); + +/** Gets the number of samples of an Opus packet. + * @param [in] packet char*: Opus packet + * @param [in] len opus_int32: Length of packet + * @param [in] Fs opus_int32: Sampling rate in Hz. + * This must be a multiple of 400, or + * inaccurate results will be returned. + * @returns Number of samples + * @retval OPUS_BAD_ARG Insufficient data was passed to the function + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1); + +/** Gets the number of samples of an Opus packet. + * @param [in] dec OpusDecoder*: Decoder state + * @param [in] packet char*: Opus packet + * @param [in] len opus_int32: Length of packet + * @returns Number of samples + * @retval OPUS_BAD_ARG Insufficient data was passed to the function + * @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); + +/** Applies soft-clipping to bring a float signal within the [-1,1] range. If + * the signal is already in that range, nothing is done. If there are values + * outside of [-1,1], then the signal is clipped as smoothly as possible to + * both fit in the range and avoid creating excessive distortion in the + * process. + * @param [in,out] pcm float*: Input PCM and modified PCM + * @param [in] frame_size int Number of samples per channel to process + * @param [in] channels int: Number of channels + * @param [in,out] softclip_mem float*: State memory for the soft clipping process (one float per channel, initialized to zero) + */ +OPUS_EXPORT void opus_pcm_soft_clip(float *pcm, int frame_size, int channels, float *softclip_mem); + + +/**@}*/ + +/** @defgroup opus_repacketizer Repacketizer + * @{ + * + * The repacketizer can be used to merge multiple Opus packets into a single + * packet or alternatively to split Opus packets that have previously been + * merged. Splitting valid Opus packets is always guaranteed to succeed, + * whereas merging valid packets only succeeds if all frames have the same + * mode, bandwidth, and frame size, and when the total duration of the merged + * packet is no more than 120 ms. + * The repacketizer currently only operates on elementary Opus + * streams. It will not manipualte multistream packets successfully, except in + * the degenerate case where they consist of data from a single stream. + * + * The repacketizing process starts with creating a repacketizer state, either + * by calling opus_repacketizer_create() or by allocating the memory yourself, + * e.g., + * @code + * OpusRepacketizer *rp; + * rp = (OpusRepacketizer*)malloc(opus_repacketizer_get_size()); + * if (rp != NULL) + * opus_repacketizer_init(rp); + * @endcode + * + * Then the application should submit packets with opus_repacketizer_cat(), + * extract new packets with opus_repacketizer_out() or + * opus_repacketizer_out_range(), and then reset the state for the next set of + * input packets via opus_repacketizer_init(). + * + * For example, to split a sequence of packets into individual frames: + * @code + * unsigned char *data; + * int len; + * while (get_next_packet(&data, &len)) + * { + * unsigned char out[1276]; + * opus_int32 out_len; + * int nb_frames; + * int err; + * int i; + * err = opus_repacketizer_cat(rp, data, len); + * if (err != OPUS_OK) + * { + * release_packet(data); + * return err; + * } + * nb_frames = opus_repacketizer_get_nb_frames(rp); + * for (i = 0; i < nb_frames; i++) + * { + * out_len = opus_repacketizer_out_range(rp, i, i+1, out, sizeof(out)); + * if (out_len < 0) + * { + * release_packet(data); + * return (int)out_len; + * } + * output_next_packet(out, out_len); + * } + * opus_repacketizer_init(rp); + * release_packet(data); + * } + * @endcode + * + * Alternatively, to combine a sequence of frames into packets that each + * contain up to TARGET_DURATION_MS milliseconds of data: + * @code + * // The maximum number of packets with duration TARGET_DURATION_MS occurs + * // when the frame size is 2.5 ms, for a total of (TARGET_DURATION_MS*2/5) + * // packets. + * unsigned char *data[(TARGET_DURATION_MS*2/5)+1]; + * opus_int32 len[(TARGET_DURATION_MS*2/5)+1]; + * int nb_packets; + * unsigned char out[1277*(TARGET_DURATION_MS*2/2)]; + * opus_int32 out_len; + * int prev_toc; + * nb_packets = 0; + * while (get_next_packet(data+nb_packets, len+nb_packets)) + * { + * int nb_frames; + * int err; + * nb_frames = opus_packet_get_nb_frames(data[nb_packets], len[nb_packets]); + * if (nb_frames < 1) + * { + * release_packets(data, nb_packets+1); + * return nb_frames; + * } + * nb_frames += opus_repacketizer_get_nb_frames(rp); + * // If adding the next packet would exceed our target, or it has an + * // incompatible TOC sequence, output the packets we already have before + * // submitting it. + * // N.B., The nb_packets > 0 check ensures we've submitted at least one + * // packet since the last call to opus_repacketizer_init(). Otherwise a + * // single packet longer than TARGET_DURATION_MS would cause us to try to + * // output an (invalid) empty packet. It also ensures that prev_toc has + * // been set to a valid value. Additionally, len[nb_packets] > 0 is + * // guaranteed by the call to opus_packet_get_nb_frames() above, so the + * // reference to data[nb_packets][0] should be valid. + * if (nb_packets > 0 && ( + * ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) || + * opus_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames > + * TARGET_DURATION_MS*48)) + * { + * out_len = opus_repacketizer_out(rp, out, sizeof(out)); + * if (out_len < 0) + * { + * release_packets(data, nb_packets+1); + * return (int)out_len; + * } + * output_next_packet(out, out_len); + * opus_repacketizer_init(rp); + * release_packets(data, nb_packets); + * data[0] = data[nb_packets]; + * len[0] = len[nb_packets]; + * nb_packets = 0; + * } + * err = opus_repacketizer_cat(rp, data[nb_packets], len[nb_packets]); + * if (err != OPUS_OK) + * { + * release_packets(data, nb_packets+1); + * return err; + * } + * prev_toc = data[nb_packets][0]; + * nb_packets++; + * } + * // Output the final, partial packet. + * if (nb_packets > 0) + * { + * out_len = opus_repacketizer_out(rp, out, sizeof(out)); + * release_packets(data, nb_packets); + * if (out_len < 0) + * return (int)out_len; + * output_next_packet(out, out_len); + * } + * @endcode + * + * An alternate way of merging packets is to simply call opus_repacketizer_cat() + * unconditionally until it fails. At that point, the merged packet can be + * obtained with opus_repacketizer_out() and the input packet for which + * opus_repacketizer_cat() needs to be re-added to a newly reinitialized + * repacketizer state. + */ + +typedef struct OpusRepacketizer OpusRepacketizer; + +/** Gets the size of an OpusRepacketizer structure. + * @returns The size in bytes. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void); + +/** (Re)initializes a previously allocated repacketizer state. + * The state must be at least the size returned by opus_repacketizer_get_size(). + * This can be used for applications which use their own allocator instead of + * malloc(). + * It must also be called to reset the queue of packets waiting to be + * repacketized, which is necessary if the maximum packet duration of 120 ms + * is reached or if you wish to submit packets with a different Opus + * configuration (coding mode, audio bandwidth, frame size, or channel count). + * Failure to do so will prevent a new packet from being added with + * opus_repacketizer_cat(). + * @see opus_repacketizer_create + * @see opus_repacketizer_get_size + * @see opus_repacketizer_cat + * @param rp OpusRepacketizer*: The repacketizer state to + * (re)initialize. + * @returns A pointer to the same repacketizer state that was passed in. + */ +OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1); + +/** Allocates memory and initializes the new repacketizer with + * opus_repacketizer_init(). + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void); + +/** Frees an OpusRepacketizer allocated by + * opus_repacketizer_create(). + * @param[in] rp OpusRepacketizer*: State to be freed. + */ +OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp); + +/** Add a packet to the current repacketizer state. + * This packet must match the configuration of any packets already submitted + * for repacketization since the last call to opus_repacketizer_init(). + * This means that it must have the same coding mode, audio bandwidth, frame + * size, and channel count. + * This can be checked in advance by examining the top 6 bits of the first + * byte of the packet, and ensuring they match the top 6 bits of the first + * byte of any previously submitted packet. + * The total duration of audio in the repacketizer state also must not exceed + * 120 ms, the maximum duration of a single packet, after adding this packet. + * + * The contents of the current repacketizer state can be extracted into new + * packets using opus_repacketizer_out() or opus_repacketizer_out_range(). + * + * In order to add a packet with a different configuration or to add more + * audio beyond 120 ms, you must clear the repacketizer state by calling + * opus_repacketizer_init(). + * If a packet is too large to add to the current repacketizer state, no part + * of it is added, even if it contains multiple frames, some of which might + * fit. + * If you wish to be able to add parts of such packets, you should first use + * another repacketizer to split the packet into pieces and add them + * individually. + * @see opus_repacketizer_out_range + * @see opus_repacketizer_out + * @see opus_repacketizer_init + * @param rp OpusRepacketizer*: The repacketizer state to which to + * add the packet. + * @param[in] data const unsigned char*: The packet data. + * The application must ensure + * this pointer remains valid + * until the next call to + * opus_repacketizer_init() or + * opus_repacketizer_destroy(). + * @param len opus_int32: The number of bytes in the packet data. + * @returns An error code indicating whether or not the operation succeeded. + * @retval #OPUS_OK The packet's contents have been added to the repacketizer + * state. + * @retval #OPUS_INVALID_PACKET The packet did not have a valid TOC sequence, + * the packet's TOC sequence was not compatible + * with previously submitted packets (because + * the coding mode, audio bandwidth, frame size, + * or channel count did not match), or adding + * this packet would increase the total amount of + * audio stored in the repacketizer state to more + * than 120 ms. + */ +OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); + + +/** Construct a new packet from data previously submitted to the repacketizer + * state via opus_repacketizer_cat(). + * @param rp OpusRepacketizer*: The repacketizer state from which to + * construct the new packet. + * @param begin int: The index of the first frame in the current + * repacketizer state to include in the output. + * @param end int: One past the index of the last frame in the + * current repacketizer state to include in the + * output. + * @param[out] data const unsigned char*: The buffer in which to + * store the output packet. + * @param maxlen opus_int32: The maximum number of bytes to store in + * the output buffer. In order to guarantee + * success, this should be at least + * 1276 for a single frame, + * or for multiple frames, + * 1277*(end-begin). + * However, 1*(end-begin) plus + * the size of all packet data submitted to + * the repacketizer since the last call to + * opus_repacketizer_init() or + * opus_repacketizer_create() is also + * sufficient, and possibly much smaller. + * @returns The total size of the output packet on success, or an error code + * on failure. + * @retval #OPUS_BAD_ARG [begin,end) was an invalid range of + * frames (begin < 0, begin >= end, or end > + * opus_repacketizer_get_nb_frames()). + * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the + * complete output packet. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Return the total number of frames contained in packet data submitted to + * the repacketizer state so far via opus_repacketizer_cat() since the last + * call to opus_repacketizer_init() or opus_repacketizer_create(). + * This defines the valid range of packets that can be extracted with + * opus_repacketizer_out_range() or opus_repacketizer_out(). + * @param rp OpusRepacketizer*: The repacketizer state containing the + * frames. + * @returns The total number of frames contained in the packet data submitted + * to the repacketizer state. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1); + +/** Construct a new packet from data previously submitted to the repacketizer + * state via opus_repacketizer_cat(). + * This is a convenience routine that returns all the data submitted so far + * in a single packet. + * It is equivalent to calling + * @code + * opus_repacketizer_out_range(rp, 0, opus_repacketizer_get_nb_frames(rp), + * data, maxlen) + * @endcode + * @param rp OpusRepacketizer*: The repacketizer state from which to + * construct the new packet. + * @param[out] data const unsigned char*: The buffer in which to + * store the output packet. + * @param maxlen opus_int32: The maximum number of bytes to store in + * the output buffer. In order to guarantee + * success, this should be at least + * 1277*opus_repacketizer_get_nb_frames(rp). + * However, + * 1*opus_repacketizer_get_nb_frames(rp) + * plus the size of all packet data + * submitted to the repacketizer since the + * last call to opus_repacketizer_init() or + * opus_repacketizer_create() is also + * sufficient, and possibly much smaller. + * @returns The total size of the output packet on success, or an error code + * on failure. + * @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the + * complete output packet. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1); + +/** Pads a given Opus packet to a larger size (possibly changing the TOC sequence). + * @param[in,out] data const unsigned char*: The buffer containing the + * packet to pad. + * @param len opus_int32: The size of the packet. + * This must be at least 1. + * @param new_len opus_int32: The desired size of the packet after padding. + * This must be at least as large as len. + * @returns an error code + * @retval #OPUS_OK \a on success. + * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len. + * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet. + */ +OPUS_EXPORT int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len); + +/** Remove all padding from a given Opus packet and rewrite the TOC sequence to + * minimize space usage. + * @param[in,out] data const unsigned char*: The buffer containing the + * packet to strip. + * @param len opus_int32: The size of the packet. + * This must be at least 1. + * @returns The new size of the output packet on success, or an error code + * on failure. + * @retval #OPUS_BAD_ARG \a len was less than 1. + * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len); + +/** Pads a given Opus multi-stream packet to a larger size (possibly changing the TOC sequence). + * @param[in,out] data const unsigned char*: The buffer containing the + * packet to pad. + * @param len opus_int32: The size of the packet. + * This must be at least 1. + * @param new_len opus_int32: The desired size of the packet after padding. + * This must be at least 1. + * @param nb_streams opus_int32: The number of streams (not channels) in the packet. + * This must be at least as large as len. + * @returns an error code + * @retval #OPUS_OK \a on success. + * @retval #OPUS_BAD_ARG \a len was less than 1. + * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet. + */ +OPUS_EXPORT int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams); + +/** Remove all padding from a given Opus multi-stream packet and rewrite the TOC sequence to + * minimize space usage. + * @param[in,out] data const unsigned char*: The buffer containing the + * packet to strip. + * @param len opus_int32: The size of the packet. + * This must be at least 1. + * @param nb_streams opus_int32: The number of streams (not channels) in the packet. + * This must be at least 1. + * @returns The new size of the output packet on success, or an error code + * on failure. + * @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len. + * @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* OPUS_H */ diff --git a/TelegramClient.Opus/opus/include/opus_custom.h b/TelegramClient.Opus/opus/include/opus_custom.h new file mode 100755 index 0000000..41f36bf --- /dev/null +++ b/TelegramClient.Opus/opus/include/opus_custom.h @@ -0,0 +1,342 @@ +/* Copyright (c) 2007-2008 CSIRO + Copyright (c) 2007-2009 Xiph.Org Foundation + Copyright (c) 2008-2012 Gregory Maxwell + Written by Jean-Marc Valin and Gregory Maxwell */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +/** + @file opus_custom.h + @brief Opus-Custom reference implementation API + */ + +#ifndef OPUS_CUSTOM_H +#define OPUS_CUSTOM_H + +#include "opus_defines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CUSTOM_MODES +# define OPUS_CUSTOM_EXPORT OPUS_EXPORT +# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT +#else +# define OPUS_CUSTOM_EXPORT +# ifdef OPUS_BUILD +# define OPUS_CUSTOM_EXPORT_STATIC static OPUS_INLINE +# else +# define OPUS_CUSTOM_EXPORT_STATIC +# endif +#endif + +/** @defgroup opus_custom Opus Custom + * @{ + * Opus Custom is an optional part of the Opus specification and + * reference implementation which uses a distinct API from the regular + * API and supports frame sizes that are not normally supported.\ Use + * of Opus Custom is discouraged for all but very special applications + * for which a frame size different from 2.5, 5, 10, or 20 ms is needed + * (for either complexity or latency reasons) and where interoperability + * is less important. + * + * In addition to the interoperability limitations the use of Opus custom + * disables a substantial chunk of the codec and generally lowers the + * quality available at a given bitrate. Normally when an application needs + * a different frame size from the codec it should buffer to match the + * sizes but this adds a small amount of delay which may be important + * in some very low latency applications. Some transports (especially + * constant rate RF transports) may also work best with frames of + * particular durations. + * + * Libopus only supports custom modes if they are enabled at compile time. + * + * The Opus Custom API is similar to the regular API but the + * @ref opus_encoder_create and @ref opus_decoder_create calls take + * an additional mode parameter which is a structure produced by + * a call to @ref opus_custom_mode_create. Both the encoder and decoder + * must create a mode using the same sample rate (fs) and frame size + * (frame size) so these parameters must either be signaled out of band + * or fixed in a particular implementation. + * + * Similar to regular Opus the custom modes support on the fly frame size + * switching, but the sizes available depend on the particular frame size in + * use. For some initial frame sizes on a single on the fly size is available. + */ + +/** Contains the state of an encoder. One encoder state is needed + for each stream. It is initialized once at the beginning of the + stream. Do *not* re-initialize the state for every frame. + @brief Encoder state + */ +typedef struct OpusCustomEncoder OpusCustomEncoder; + +/** State of the decoder. One decoder state is needed for each stream. + It is initialized once at the beginning of the stream. Do *not* + re-initialize the state for every frame. + @brief Decoder state + */ +typedef struct OpusCustomDecoder OpusCustomDecoder; + +/** The mode contains all the information necessary to create an + encoder. Both the encoder and decoder need to be initialized + with exactly the same mode, otherwise the output will be + corrupted. + @brief Mode configuration + */ +typedef struct OpusCustomMode OpusCustomMode; + +/** Creates a new mode struct. This will be passed to an encoder or + * decoder. The mode MUST NOT BE DESTROYED until the encoders and + * decoders that use it are destroyed as well. + * @param [in] Fs int: Sampling rate (8000 to 96000 Hz) + * @param [in] frame_size int: Number of samples (per channel) to encode in each + * packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes) + * @param [out] error int*: Returned error code (if NULL, no error will be returned) + * @return A newly created mode + */ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error); + +/** Destroys a mode struct. Only call this after all encoders and + * decoders using this mode are destroyed as well. + * @param [in] mode OpusCustomMode*: Mode to be freed. + */ +OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode); + + +#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C) + +/* Encoder */ +/** Gets the size of an OpusCustomEncoder structure. + * @param [in] mode OpusCustomMode *: Mode configuration + * @param [in] channels int: Number of channels + * @returns size + */ +OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size( + const OpusCustomMode *mode, + int channels +) OPUS_ARG_NONNULL(1); + +# ifdef CUSTOM_MODES +/** Initializes a previously allocated encoder state + * The memory pointed to by st must be the size returned by opus_custom_encoder_get_size. + * This is intended for applications which use their own allocator instead of malloc. + * @see opus_custom_encoder_create(),opus_custom_encoder_get_size() + * To reset a previously initialized state use the OPUS_RESET_STATE CTL. + * @param [in] st OpusCustomEncoder*: Encoder state + * @param [in] mode OpusCustomMode *: Contains all the information about the characteristics of + * the stream (must be the same characteristics as used for the + * decoder) + * @param [in] channels int: Number of channels + * @return OPUS_OK Success or @ref opus_errorcodes + */ +OPUS_CUSTOM_EXPORT int opus_custom_encoder_init( + OpusCustomEncoder *st, + const OpusCustomMode *mode, + int channels +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); +# endif +#endif + + +/** Creates a new encoder state. Each stream needs its own encoder + * state (can't be shared across simultaneous streams). + * @param [in] mode OpusCustomMode*: Contains all the information about the characteristics of + * the stream (must be the same characteristics as used for the + * decoder) + * @param [in] channels int: Number of channels + * @param [out] error int*: Returns an error code + * @return Newly created encoder state. +*/ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create( + const OpusCustomMode *mode, + int channels, + int *error +) OPUS_ARG_NONNULL(1); + + +/** Destroys a an encoder state. + * @param[in] st OpusCustomEncoder*: State to be freed. + */ +OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st); + +/** Encodes a frame of audio. + * @param [in] st OpusCustomEncoder*: Encoder state + * @param [in] pcm float*: PCM audio in float format, with a normal range of +/-1.0. + * Samples with a range beyond +/-1.0 are supported but will + * be clipped by decoders using the integer API and should + * only be used if it is known that the far end supports + * extended dynamic range. There must be exactly + * frame_size samples per channel. + * @param [in] frame_size int: Number of samples per frame of input signal + * @param [out] compressed char *: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long. + * @param [in] maxCompressedBytes int: Maximum number of bytes to use for compressing the frame + * (can change from one frame to another) + * @return Number of bytes written to "compressed". + * If negative, an error has occurred (see error codes). It is IMPORTANT that + * the length returned be somehow transmitted to the decoder. Otherwise, no + * decoding is possible. + */ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float( + OpusCustomEncoder *st, + const float *pcm, + int frame_size, + unsigned char *compressed, + int maxCompressedBytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Encodes a frame of audio. + * @param [in] st OpusCustomEncoder*: Encoder state + * @param [in] pcm opus_int16*: PCM audio in signed 16-bit format (native endian). + * There must be exactly frame_size samples per channel. + * @param [in] frame_size int: Number of samples per frame of input signal + * @param [out] compressed char *: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long. + * @param [in] maxCompressedBytes int: Maximum number of bytes to use for compressing the frame + * (can change from one frame to another) + * @return Number of bytes written to "compressed". + * If negative, an error has occurred (see error codes). It is IMPORTANT that + * the length returned be somehow transmitted to the decoder. Otherwise, no + * decoding is possible. + */ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode( + OpusCustomEncoder *st, + const opus_int16 *pcm, + int frame_size, + unsigned char *compressed, + int maxCompressedBytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Perform a CTL function on an Opus custom encoder. + * + * Generally the request and subsequent arguments are generated + * by a convenience macro. + * @see opus_encoderctls + */ +OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1); + + +#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C) +/* Decoder */ + +/** Gets the size of an OpusCustomDecoder structure. + * @param [in] mode OpusCustomMode *: Mode configuration + * @param [in] channels int: Number of channels + * @returns size + */ +OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size( + const OpusCustomMode *mode, + int channels +) OPUS_ARG_NONNULL(1); + +/** Initializes a previously allocated decoder state + * The memory pointed to by st must be the size returned by opus_custom_decoder_get_size. + * This is intended for applications which use their own allocator instead of malloc. + * @see opus_custom_decoder_create(),opus_custom_decoder_get_size() + * To reset a previously initialized state use the OPUS_RESET_STATE CTL. + * @param [in] st OpusCustomDecoder*: Decoder state + * @param [in] mode OpusCustomMode *: Contains all the information about the characteristics of + * the stream (must be the same characteristics as used for the + * encoder) + * @param [in] channels int: Number of channels + * @return OPUS_OK Success or @ref opus_errorcodes + */ +OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init( + OpusCustomDecoder *st, + const OpusCustomMode *mode, + int channels +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); + +#endif + + +/** Creates a new decoder state. Each stream needs its own decoder state (can't + * be shared across simultaneous streams). + * @param [in] mode OpusCustomMode: Contains all the information about the characteristics of the + * stream (must be the same characteristics as used for the encoder) + * @param [in] channels int: Number of channels + * @param [out] error int*: Returns an error code + * @return Newly created decoder state. + */ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create( + const OpusCustomMode *mode, + int channels, + int *error +) OPUS_ARG_NONNULL(1); + +/** Destroys a an decoder state. + * @param[in] st OpusCustomDecoder*: State to be freed. + */ +OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st); + +/** Decode an opus custom frame with floating point output + * @param [in] st OpusCustomDecoder*: Decoder state + * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss + * @param [in] len int: Number of bytes in payload + * @param [out] pcm float*: Output signal (interleaved if 2 channels). length + * is frame_size*channels*sizeof(float) + * @param [in] frame_size Number of samples per channel of available space in *pcm. + * @returns Number of decoded samples or @ref opus_errorcodes + */ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float( + OpusCustomDecoder *st, + const unsigned char *data, + int len, + float *pcm, + int frame_size +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Decode an opus custom frame + * @param [in] st OpusCustomDecoder*: Decoder state + * @param [in] data char*: Input payload. Use a NULL pointer to indicate packet loss + * @param [in] len int: Number of bytes in payload + * @param [out] pcm opus_int16*: Output signal (interleaved if 2 channels). length + * is frame_size*channels*sizeof(opus_int16) + * @param [in] frame_size Number of samples per channel of available space in *pcm. + * @returns Number of decoded samples or @ref opus_errorcodes + */ +OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode( + OpusCustomDecoder *st, + const unsigned char *data, + int len, + opus_int16 *pcm, + int frame_size +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Perform a CTL function on an Opus custom decoder. + * + * Generally the request and subsequent arguments are generated + * by a convenience macro. + * @see opus_genericctls + */ +OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* OPUS_CUSTOM_H */ diff --git a/TelegramClient.Opus/opus/include/opus_defines.h b/TelegramClient.Opus/opus/include/opus_defines.h new file mode 100755 index 0000000..265089f --- /dev/null +++ b/TelegramClient.Opus/opus/include/opus_defines.h @@ -0,0 +1,726 @@ +/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited + Written by Jean-Marc Valin and Koen Vos */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +/** + * @file opus_defines.h + * @brief Opus reference implementation constants + */ + +#ifndef OPUS_DEFINES_H +#define OPUS_DEFINES_H + +#include "opus_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup opus_errorcodes Error codes + * @{ + */ +/** No error @hideinitializer*/ +#define OPUS_OK 0 +/** One or more invalid/out of range arguments @hideinitializer*/ +#define OPUS_BAD_ARG -1 +/** The mode struct passed is invalid @hideinitializer*/ +#define OPUS_BUFFER_TOO_SMALL -2 +/** An internal error was detected @hideinitializer*/ +#define OPUS_INTERNAL_ERROR -3 +/** The compressed data passed is corrupted @hideinitializer*/ +#define OPUS_INVALID_PACKET -4 +/** Invalid/unsupported request number @hideinitializer*/ +#define OPUS_UNIMPLEMENTED -5 +/** An encoder or decoder structure is invalid or already freed @hideinitializer*/ +#define OPUS_INVALID_STATE -6 +/** Memory allocation has failed @hideinitializer*/ +#define OPUS_ALLOC_FAIL -7 +/**@}*/ + +/** @cond OPUS_INTERNAL_DOC */ +/**Export control for opus functions */ + +#ifndef OPUS_EXPORT +# if defined(WIN32) +# ifdef OPUS_BUILD +# define OPUS_EXPORT __declspec(dllexport) +# else +# define OPUS_EXPORT +# endif +# elif defined(__GNUC__) && defined(OPUS_BUILD) +# define OPUS_EXPORT __attribute__ ((visibility ("default"))) +# else +# define OPUS_EXPORT +# endif +#endif + +# if !defined(OPUS_GNUC_PREREQ) +# if defined(__GNUC__)&&defined(__GNUC_MINOR__) +# define OPUS_GNUC_PREREQ(_maj,_min) \ + ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) +# else +# define OPUS_GNUC_PREREQ(_maj,_min) 0 +# endif +# endif + +#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) +# if OPUS_GNUC_PREREQ(3,0) +# define OPUS_RESTRICT __restrict__ +# elif (defined(_MSC_VER) && _MSC_VER >= 1400) +# define OPUS_RESTRICT __restrict +# else +# define OPUS_RESTRICT +# endif +#else +# define OPUS_RESTRICT restrict +#endif + +#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) +# if OPUS_GNUC_PREREQ(2,7) +# define OPUS_INLINE __inline__ +# elif (defined(_MSC_VER)) +# define OPUS_INLINE __inline +# else +# define OPUS_INLINE +# endif +#else +# define OPUS_INLINE inline +#endif + +/**Warning attributes for opus functions + * NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out + * some paranoid null checks. */ +#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4) +# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) +#else +# define OPUS_WARN_UNUSED_RESULT +#endif +#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4) +# define OPUS_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) +#else +# define OPUS_ARG_NONNULL(_x) +#endif + +/** These are the actual Encoder CTL ID numbers. + * They should not be used directly by applications. + * In general, SETs should be even and GETs should be odd.*/ +#define OPUS_SET_APPLICATION_REQUEST 4000 +#define OPUS_GET_APPLICATION_REQUEST 4001 +#define OPUS_SET_BITRATE_REQUEST 4002 +#define OPUS_GET_BITRATE_REQUEST 4003 +#define OPUS_SET_MAX_BANDWIDTH_REQUEST 4004 +#define OPUS_GET_MAX_BANDWIDTH_REQUEST 4005 +#define OPUS_SET_VBR_REQUEST 4006 +#define OPUS_GET_VBR_REQUEST 4007 +#define OPUS_SET_BANDWIDTH_REQUEST 4008 +#define OPUS_GET_BANDWIDTH_REQUEST 4009 +#define OPUS_SET_COMPLEXITY_REQUEST 4010 +#define OPUS_GET_COMPLEXITY_REQUEST 4011 +#define OPUS_SET_INBAND_FEC_REQUEST 4012 +#define OPUS_GET_INBAND_FEC_REQUEST 4013 +#define OPUS_SET_PACKET_LOSS_PERC_REQUEST 4014 +#define OPUS_GET_PACKET_LOSS_PERC_REQUEST 4015 +#define OPUS_SET_DTX_REQUEST 4016 +#define OPUS_GET_DTX_REQUEST 4017 +#define OPUS_SET_VBR_CONSTRAINT_REQUEST 4020 +#define OPUS_GET_VBR_CONSTRAINT_REQUEST 4021 +#define OPUS_SET_FORCE_CHANNELS_REQUEST 4022 +#define OPUS_GET_FORCE_CHANNELS_REQUEST 4023 +#define OPUS_SET_SIGNAL_REQUEST 4024 +#define OPUS_GET_SIGNAL_REQUEST 4025 +#define OPUS_GET_LOOKAHEAD_REQUEST 4027 +/* #define OPUS_RESET_STATE 4028 */ +#define OPUS_GET_SAMPLE_RATE_REQUEST 4029 +#define OPUS_GET_FINAL_RANGE_REQUEST 4031 +#define OPUS_GET_PITCH_REQUEST 4033 +#define OPUS_SET_GAIN_REQUEST 4034 +#define OPUS_GET_GAIN_REQUEST 4045 /* Should have been 4035 */ +#define OPUS_SET_LSB_DEPTH_REQUEST 4036 +#define OPUS_GET_LSB_DEPTH_REQUEST 4037 +#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039 +#define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040 +#define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041 +#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042 +#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043 + +/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */ + +/* Macros to trigger compilation errors when the wrong types are provided to a CTL */ +#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x)) +#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr))) +#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr))) +#define __opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr))) +/** @endcond */ + +/** @defgroup opus_ctlvalues Pre-defined values for CTL interface + * @see opus_genericctls, opus_encoderctls + * @{ + */ +/* Values for the various encoder CTLs */ +#define OPUS_AUTO -1000 /**opus_int32: Allowed values: 0-10, inclusive. + * + * @hideinitializer */ +#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, __opus_check_int(x) +/** Gets the encoder's complexity configuration. + * @see OPUS_SET_COMPLEXITY + * @param[out] x opus_int32 *: Returns a value in the range 0-10, + * inclusive. + * @hideinitializer */ +#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, __opus_check_int_ptr(x) + +/** Configures the bitrate in the encoder. + * Rates from 500 to 512000 bits per second are meaningful, as well as the + * special values #OPUS_AUTO and #OPUS_BITRATE_MAX. + * The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much + * rate as it can, which is useful for controlling the rate by adjusting the + * output buffer size. + * @see OPUS_GET_BITRATE + * @param[in] x opus_int32: Bitrate in bits per second. The default + * is determined based on the number of + * channels and the input sampling rate. + * @hideinitializer */ +#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, __opus_check_int(x) +/** Gets the encoder's bitrate configuration. + * @see OPUS_SET_BITRATE + * @param[out] x opus_int32 *: Returns the bitrate in bits per second. + * The default is determined based on the + * number of channels and the input + * sampling rate. + * @hideinitializer */ +#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, __opus_check_int_ptr(x) + +/** Enables or disables variable bitrate (VBR) in the encoder. + * The configured bitrate may not be met exactly because frames must + * be an integer number of bytes in length. + * @warning Only the MDCT mode of Opus can provide hard CBR behavior. + * @see OPUS_GET_VBR + * @see OPUS_SET_VBR_CONSTRAINT + * @param[in] x opus_int32: Allowed values: + *
    + *
    0
    Hard CBR. For LPC/hybrid modes at very low bit-rate, this can + * cause noticeable quality degradation.
    + *
    1
    VBR (default). The exact type of VBR is controlled by + * #OPUS_SET_VBR_CONSTRAINT.
    + *
    + * @hideinitializer */ +#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, __opus_check_int(x) +/** Determine if variable bitrate (VBR) is enabled in the encoder. + * @see OPUS_SET_VBR + * @see OPUS_GET_VBR_CONSTRAINT + * @param[out] x opus_int32 *: Returns one of the following values: + *
    + *
    0
    Hard CBR.
    + *
    1
    VBR (default). The exact type of VBR may be retrieved via + * #OPUS_GET_VBR_CONSTRAINT.
    + *
    + * @hideinitializer */ +#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, __opus_check_int_ptr(x) + +/** Enables or disables constrained VBR in the encoder. + * This setting is ignored when the encoder is in CBR mode. + * @warning Only the MDCT mode of Opus currently heeds the constraint. + * Speech mode ignores it completely, hybrid mode may fail to obey it + * if the LPC layer uses more bitrate than the constraint would have + * permitted. + * @see OPUS_GET_VBR_CONSTRAINT + * @see OPUS_SET_VBR + * @param[in] x opus_int32: Allowed values: + *
    + *
    0
    Unconstrained VBR.
    + *
    1
    Constrained VBR (default). This creates a maximum of one + * frame of buffering delay assuming a transport with a + * serialization speed of the nominal bitrate.
    + *
    + * @hideinitializer */ +#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, __opus_check_int(x) +/** Determine if constrained VBR is enabled in the encoder. + * @see OPUS_SET_VBR_CONSTRAINT + * @see OPUS_GET_VBR + * @param[out] x opus_int32 *: Returns one of the following values: + *
    + *
    0
    Unconstrained VBR.
    + *
    1
    Constrained VBR (default).
    + *
    + * @hideinitializer */ +#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, __opus_check_int_ptr(x) + +/** Configures mono/stereo forcing in the encoder. + * This can force the encoder to produce packets encoded as either mono or + * stereo, regardless of the format of the input audio. This is useful when + * the caller knows that the input signal is currently a mono source embedded + * in a stereo stream. + * @see OPUS_GET_FORCE_CHANNELS + * @param[in] x opus_int32: Allowed values: + *
    + *
    #OPUS_AUTO
    Not forced (default)
    + *
    1
    Forced mono
    + *
    2
    Forced stereo
    + *
    + * @hideinitializer */ +#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, __opus_check_int(x) +/** Gets the encoder's forced channel configuration. + * @see OPUS_SET_FORCE_CHANNELS + * @param[out] x opus_int32 *: + *
    + *
    #OPUS_AUTO
    Not forced (default)
    + *
    1
    Forced mono
    + *
    2
    Forced stereo
    + *
    + * @hideinitializer */ +#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, __opus_check_int_ptr(x) + +/** Configures the maximum bandpass that the encoder will select automatically. + * Applications should normally use this instead of #OPUS_SET_BANDWIDTH + * (leaving that set to the default, #OPUS_AUTO). This allows the + * application to set an upper bound based on the type of input it is + * providing, but still gives the encoder the freedom to reduce the bandpass + * when the bitrate becomes too low, for better overall quality. + * @see OPUS_GET_MAX_BANDWIDTH + * @param[in] x opus_int32: Allowed values: + *
    + *
    OPUS_BANDWIDTH_NARROWBAND
    4 kHz passband
    + *
    OPUS_BANDWIDTH_MEDIUMBAND
    6 kHz passband
    + *
    OPUS_BANDWIDTH_WIDEBAND
    8 kHz passband
    + *
    OPUS_BANDWIDTH_SUPERWIDEBAND
    12 kHz passband
    + *
    OPUS_BANDWIDTH_FULLBAND
    20 kHz passband (default)
    + *
    + * @hideinitializer */ +#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, __opus_check_int(x) + +/** Gets the encoder's configured maximum allowed bandpass. + * @see OPUS_SET_MAX_BANDWIDTH + * @param[out] x opus_int32 *: Allowed values: + *
    + *
    #OPUS_BANDWIDTH_NARROWBAND
    4 kHz passband
    + *
    #OPUS_BANDWIDTH_MEDIUMBAND
    6 kHz passband
    + *
    #OPUS_BANDWIDTH_WIDEBAND
    8 kHz passband
    + *
    #OPUS_BANDWIDTH_SUPERWIDEBAND
    12 kHz passband
    + *
    #OPUS_BANDWIDTH_FULLBAND
    20 kHz passband (default)
    + *
    + * @hideinitializer */ +#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x) + +/** Sets the encoder's bandpass to a specific value. + * This prevents the encoder from automatically selecting the bandpass based + * on the available bitrate. If an application knows the bandpass of the input + * audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH + * instead, which still gives the encoder the freedom to reduce the bandpass + * when the bitrate becomes too low, for better overall quality. + * @see OPUS_GET_BANDWIDTH + * @param[in] x opus_int32: Allowed values: + *
    + *
    #OPUS_AUTO
    (default)
    + *
    #OPUS_BANDWIDTH_NARROWBAND
    4 kHz passband
    + *
    #OPUS_BANDWIDTH_MEDIUMBAND
    6 kHz passband
    + *
    #OPUS_BANDWIDTH_WIDEBAND
    8 kHz passband
    + *
    #OPUS_BANDWIDTH_SUPERWIDEBAND
    12 kHz passband
    + *
    #OPUS_BANDWIDTH_FULLBAND
    20 kHz passband
    + *
    + * @hideinitializer */ +#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __opus_check_int(x) + +/** Configures the type of signal being encoded. + * This is a hint which helps the encoder's mode selection. + * @see OPUS_GET_SIGNAL + * @param[in] x opus_int32: Allowed values: + *
    + *
    #OPUS_AUTO
    (default)
    + *
    #OPUS_SIGNAL_VOICE
    Bias thresholds towards choosing LPC or Hybrid modes.
    + *
    #OPUS_SIGNAL_MUSIC
    Bias thresholds towards choosing MDCT modes.
    + *
    + * @hideinitializer */ +#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured signal type. + * @see OPUS_SET_SIGNAL + * @param[out] x opus_int32 *: Returns one of the following values: + *
    + *
    #OPUS_AUTO
    (default)
    + *
    #OPUS_SIGNAL_VOICE
    Bias thresholds towards choosing LPC or Hybrid modes.
    + *
    #OPUS_SIGNAL_MUSIC
    Bias thresholds towards choosing MDCT modes.
    + *
    + * @hideinitializer */ +#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __opus_check_int_ptr(x) + + +/** Configures the encoder's intended application. + * The initial value is a mandatory argument to the encoder_create function. + * @see OPUS_GET_APPLICATION + * @param[in] x opus_int32: Returns one of the following values: + *
    + *
    #OPUS_APPLICATION_VOIP
    + *
    Process signal for improved speech intelligibility.
    + *
    #OPUS_APPLICATION_AUDIO
    + *
    Favor faithfulness to the original input.
    + *
    #OPUS_APPLICATION_RESTRICTED_LOWDELAY
    + *
    Configure the minimum possible coding delay by disabling certain modes + * of operation.
    + *
    + * @hideinitializer */ +#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured application. + * @see OPUS_SET_APPLICATION + * @param[out] x opus_int32 *: Returns one of the following values: + *
    + *
    #OPUS_APPLICATION_VOIP
    + *
    Process signal for improved speech intelligibility.
    + *
    #OPUS_APPLICATION_AUDIO
    + *
    Favor faithfulness to the original input.
    + *
    #OPUS_APPLICATION_RESTRICTED_LOWDELAY
    + *
    Configure the minimum possible coding delay by disabling certain modes + * of operation.
    + *
    + * @hideinitializer */ +#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x) + +/** Gets the sampling rate the encoder or decoder was initialized with. + * This simply returns the Fs value passed to opus_encoder_init() + * or opus_decoder_init(). + * @param[out] x opus_int32 *: Sampling rate of encoder or decoder. + * @hideinitializer + */ +#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x) + +/** Gets the total samples of delay added by the entire codec. + * This can be queried by the encoder and then the provided number of samples can be + * skipped on from the start of the decoder's output to provide time aligned input + * and output. From the perspective of a decoding application the real data begins this many + * samples late. + * + * The decoder contribution to this delay is identical for all decoders, but the + * encoder portion of the delay may vary from implementation to implementation, + * version to version, or even depend on the encoder's initial configuration. + * Applications needing delay compensation should call this CTL rather than + * hard-coding a value. + * @param[out] x opus_int32 *: Number of lookahead samples + * @hideinitializer */ +#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x) + +/** Configures the encoder's use of inband forward error correction (FEC). + * @note This is only applicable to the LPC layer + * @see OPUS_GET_INBAND_FEC + * @param[in] x opus_int32: Allowed values: + *
    + *
    0
    Disable inband FEC (default).
    + *
    1
    Enable inband FEC.
    + *
    + * @hideinitializer */ +#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x) +/** Gets encoder's configured use of inband forward error correction. + * @see OPUS_SET_INBAND_FEC + * @param[out] x opus_int32 *: Returns one of the following values: + *
    + *
    0
    Inband FEC disabled (default).
    + *
    1
    Inband FEC enabled.
    + *
    + * @hideinitializer */ +#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x) + +/** Configures the encoder's expected packet loss percentage. + * Higher values with trigger progressively more loss resistant behavior in the encoder + * at the expense of quality at a given bitrate in the lossless case, but greater quality + * under loss. + * @see OPUS_GET_PACKET_LOSS_PERC + * @param[in] x opus_int32: Loss percentage in the range 0-100, inclusive (default: 0). + * @hideinitializer */ +#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured packet loss percentage. + * @see OPUS_SET_PACKET_LOSS_PERC + * @param[out] x opus_int32 *: Returns the configured loss percentage + * in the range 0-100, inclusive (default: 0). + * @hideinitializer */ +#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, __opus_check_int_ptr(x) + +/** Configures the encoder's use of discontinuous transmission (DTX). + * @note This is only applicable to the LPC layer + * @see OPUS_GET_DTX + * @param[in] x opus_int32: Allowed values: + *
    + *
    0
    Disable DTX (default).
    + *
    1
    Enabled DTX.
    + *
    + * @hideinitializer */ +#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, __opus_check_int(x) +/** Gets encoder's configured use of discontinuous transmission. + * @see OPUS_SET_DTX + * @param[out] x opus_int32 *: Returns one of the following values: + *
    + *
    0
    DTX disabled (default).
    + *
    1
    DTX enabled.
    + *
    + * @hideinitializer */ +#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x) +/** Configures the depth of signal being encoded. + * This is a hint which helps the encoder identify silence and near-silence. + * @see OPUS_GET_LSB_DEPTH + * @param[in] x opus_int32: Input precision in bits, between 8 and 24 + * (default: 24). + * @hideinitializer */ +#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured signal depth. + * @see OPUS_SET_LSB_DEPTH + * @param[out] x opus_int32 *: Input precision in bits, between 8 and + * 24 (default: 24). + * @hideinitializer */ +#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x) + +/** Gets the duration (in samples) of the last packet successfully decoded or concealed. + * @param[out] x opus_int32 *: Number of samples (at current sampling rate). + * @hideinitializer */ +#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, __opus_check_int_ptr(x) + +/** Configures the encoder's use of variable duration frames. + * When variable duration is enabled, the encoder is free to use a shorter frame + * size than the one requested in the opus_encode*() call. + * It is then the user's responsibility + * to verify how much audio was encoded by checking the ToC byte of the encoded + * packet. The part of the audio that was not encoded needs to be resent to the + * encoder for the next call. Do not use this option unless you really + * know what you are doing. + * @see OPUS_GET_EXPERT_VARIABLE_DURATION + * @param[in] x opus_int32: Allowed values: + *
    + *
    OPUS_FRAMESIZE_ARG
    Select frame size from the argument (default).
    + *
    OPUS_FRAMESIZE_2_5_MS
    Use 2.5 ms frames.
    + *
    OPUS_FRAMESIZE_5_MS
    Use 2.5 ms frames.
    + *
    OPUS_FRAMESIZE_10_MS
    Use 10 ms frames.
    + *
    OPUS_FRAMESIZE_20_MS
    Use 20 ms frames.
    + *
    OPUS_FRAMESIZE_40_MS
    Use 40 ms frames.
    + *
    OPUS_FRAMESIZE_60_MS
    Use 60 ms frames.
    + *
    OPUS_FRAMESIZE_VARIABLE
    Optimize the frame size dynamically.
    + *
    + * @hideinitializer */ +#define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured use of variable duration frames. + * @see OPUS_SET_EXPERT_VARIABLE_DURATION + * @param[out] x opus_int32 *: Returns one of the following values: + *
    + *
    OPUS_FRAMESIZE_ARG
    Select frame size from the argument (default).
    + *
    OPUS_FRAMESIZE_2_5_MS
    Use 2.5 ms frames.
    + *
    OPUS_FRAMESIZE_5_MS
    Use 2.5 ms frames.
    + *
    OPUS_FRAMESIZE_10_MS
    Use 10 ms frames.
    + *
    OPUS_FRAMESIZE_20_MS
    Use 20 ms frames.
    + *
    OPUS_FRAMESIZE_40_MS
    Use 40 ms frames.
    + *
    OPUS_FRAMESIZE_60_MS
    Use 60 ms frames.
    + *
    OPUS_FRAMESIZE_VARIABLE
    Optimize the frame size dynamically.
    + *
    + * @hideinitializer */ +#define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x) + +/** If set to 1, disables almost all use of prediction, making frames almost + completely independent. This reduces quality. (default : 0) + * @hideinitializer */ +#define OPUS_SET_PREDICTION_DISABLED(x) OPUS_SET_PREDICTION_DISABLED_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured prediction status. + * @hideinitializer */ +#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, __opus_check_int_ptr(x) + +/**@}*/ + +/** @defgroup opus_genericctls Generic CTLs + * + * These macros are used with the \c opus_decoder_ctl and + * \c opus_encoder_ctl calls to generate a particular + * request. + * + * When called on an \c OpusDecoder they apply to that + * particular decoder instance. When called on an + * \c OpusEncoder they apply to the corresponding setting + * on that encoder instance, if present. + * + * Some usage examples: + * + * @code + * int ret; + * opus_int32 pitch; + * ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch)); + * if (ret == OPUS_OK) return ret; + * + * opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE); + * opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE); + * + * opus_int32 enc_bw, dec_bw; + * opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw)); + * opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw)); + * if (enc_bw != dec_bw) { + * printf("packet bandwidth mismatch!\n"); + * } + * @endcode + * + * @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls + * @{ + */ + +/** Resets the codec state to be equivalent to a freshly initialized state. + * This should be called when switching streams in order to prevent + * the back to back decoding from giving different results from + * one at a time decoding. + * @hideinitializer */ +#define OPUS_RESET_STATE 4028 + +/** Gets the final state of the codec's entropy coder. + * This is used for testing purposes, + * The encoder and decoder state should be identical after coding a payload + * (assuming no data corruption or software bugs) + * + * @param[out] x opus_uint32 *: Entropy coder state + * + * @hideinitializer */ +#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x) + +/** Gets the pitch of the last decoded frame, if available. + * This can be used for any post-processing algorithm requiring the use of pitch, + * e.g. time stretching/shortening. If the last frame was not voiced, or if the + * pitch was not coded in the frame, then zero is returned. + * + * This CTL is only implemented for decoder instances. + * + * @param[out] x opus_int32 *: pitch period at 48 kHz (or 0 if not available) + * + * @hideinitializer */ +#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x) + +/** Gets the encoder's configured bandpass or the decoder's last bandpass. + * @see OPUS_SET_BANDWIDTH + * @param[out] x opus_int32 *: Returns one of the following values: + *
    + *
    #OPUS_AUTO
    (default)
    + *
    #OPUS_BANDWIDTH_NARROWBAND
    4 kHz passband
    + *
    #OPUS_BANDWIDTH_MEDIUMBAND
    6 kHz passband
    + *
    #OPUS_BANDWIDTH_WIDEBAND
    8 kHz passband
    + *
    #OPUS_BANDWIDTH_SUPERWIDEBAND
    12 kHz passband
    + *
    #OPUS_BANDWIDTH_FULLBAND
    20 kHz passband
    + *
    + * @hideinitializer */ +#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x) + +/**@}*/ + +/** @defgroup opus_decoderctls Decoder related CTLs + * @see opus_genericctls, opus_encoderctls, opus_decoder + * @{ + */ + +/** Configures decoder gain adjustment. + * Scales the decoded output by a factor specified in Q8 dB units. + * This has a maximum range of -32768 to 32767 inclusive, and returns + * OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment. + * This setting survives decoder reset. + * + * gain = pow(10, x/(20.0*256)) + * + * @param[in] x opus_int32: Amount to scale PCM signal by in Q8 dB units. + * @hideinitializer */ +#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, __opus_check_int(x) +/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN + * + * @param[out] x opus_int32 *: Amount to scale PCM signal by in Q8 dB units. + * @hideinitializer */ +#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, __opus_check_int_ptr(x) + +/**@}*/ + +/** @defgroup opus_libinfo Opus library information functions + * @{ + */ + +/** Converts an opus error code into a human readable string. + * + * @param[in] error int: Error number + * @returns Error string + */ +OPUS_EXPORT const char *opus_strerror(int error); + +/** Gets the libopus version string. + * + * @returns Version string + */ +OPUS_EXPORT const char *opus_get_version_string(void); +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* OPUS_DEFINES_H */ diff --git a/TelegramClient.Opus/opus/include/opus_multistream.h b/TelegramClient.Opus/opus/include/opus_multistream.h new file mode 100755 index 0000000..ae59979 --- /dev/null +++ b/TelegramClient.Opus/opus/include/opus_multistream.h @@ -0,0 +1,660 @@ +/* Copyright (c) 2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +/** + * @file opus_multistream.h + * @brief Opus reference implementation multistream API + */ + +#ifndef OPUS_MULTISTREAM_H +#define OPUS_MULTISTREAM_H + +#include "opus.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond OPUS_INTERNAL_DOC */ + +/** Macros to trigger compilation errors when the wrong types are provided to a + * CTL. */ +/**@{*/ +#define __opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr))) +#define __opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr))) +/**@}*/ + +/** These are the actual encoder and decoder CTL ID numbers. + * They should not be used directly by applications. + * In general, SETs should be even and GETs should be odd.*/ +/**@{*/ +#define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120 +#define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122 +/**@}*/ + +/** @endcond */ + +/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs + * + * These are convenience macros that are specific to the + * opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl() + * interface. + * The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and + * @ref opus_decoderctls may be applied to a multistream encoder or decoder as + * well. + * In addition, you may retrieve the encoder or decoder state for an specific + * stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or + * #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually. + */ +/**@{*/ + +/** Gets the encoder state for an individual stream of a multistream encoder. + * @param[in] x opus_int32: The index of the stream whose encoder you + * wish to retrieve. + * This must be non-negative and less than + * the streams parameter used + * to initialize the encoder. + * @param[out] y OpusEncoder**: Returns a pointer to the given + * encoder state. + * @retval OPUS_BAD_ARG The index of the requested stream was out of range. + * @hideinitializer + */ +#define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, __opus_check_int(x), __opus_check_encstate_ptr(y) + +/** Gets the decoder state for an individual stream of a multistream decoder. + * @param[in] x opus_int32: The index of the stream whose decoder you + * wish to retrieve. + * This must be non-negative and less than + * the streams parameter used + * to initialize the decoder. + * @param[out] y OpusDecoder**: Returns a pointer to the given + * decoder state. + * @retval OPUS_BAD_ARG The index of the requested stream was out of range. + * @hideinitializer + */ +#define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, __opus_check_int(x), __opus_check_decstate_ptr(y) + +/**@}*/ + +/** @defgroup opus_multistream Opus Multistream API + * @{ + * + * The multistream API allows individual Opus streams to be combined into a + * single packet, enabling support for up to 255 channels. Unlike an + * elementary Opus stream, the encoder and decoder must negotiate the channel + * configuration before the decoder can successfully interpret the data in the + * packets produced by the encoder. Some basic information, such as packet + * duration, can be computed without any special negotiation. + * + * The format for multistream Opus packets is defined in the + * Ogg + * encapsulation specification and is based on the self-delimited Opus + * framing described in Appendix B of RFC 6716. + * Normal Opus packets are just a degenerate case of multistream Opus packets, + * and can be encoded or decoded with the multistream API by setting + * streams to 1 when initializing the encoder or + * decoder. + * + * Multistream Opus streams can contain up to 255 elementary Opus streams. + * These may be either "uncoupled" or "coupled", indicating that the decoder + * is configured to decode them to either 1 or 2 channels, respectively. + * The streams are ordered so that all coupled streams appear at the + * beginning. + * + * A mapping table defines which decoded channel i + * should be used for each input/output (I/O) channel j. This table is + * typically provided as an unsigned char array. + * Let i = mapping[j] be the index for I/O channel j. + * If i < 2*coupled_streams, then I/O channel j is + * encoded as the left channel of stream (i/2) if i + * is even, or as the right channel of stream (i/2) if + * i is odd. Otherwise, I/O channel j is encoded as + * mono in stream (i - coupled_streams), unless it has the special + * value 255, in which case it is omitted from the encoding entirely (the + * decoder will reproduce it as silence). Each value i must either + * be the special value 255 or be less than streams + coupled_streams. + * + * The output channels specified by the encoder + * should use the + * Vorbis + * channel ordering. A decoder may wish to apply an additional permutation + * to the mapping the encoder used to achieve a different output channel + * order (e.g. for outputing in WAV order). + * + * Each multistream packet contains an Opus packet for each stream, and all of + * the Opus packets in a single multistream packet must have the same + * duration. Therefore the duration of a multistream packet can be extracted + * from the TOC sequence of the first stream, which is located at the + * beginning of the packet, just like an elementary Opus stream: + * + * @code + * int nb_samples; + * int nb_frames; + * nb_frames = opus_packet_get_nb_frames(data, len); + * if (nb_frames < 1) + * return nb_frames; + * nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames; + * @endcode + * + * The general encoding and decoding process proceeds exactly the same as in + * the normal @ref opus_encoder and @ref opus_decoder APIs. + * See their documentation for an overview of how to use the corresponding + * multistream functions. + */ + +/** Opus multistream encoder state. + * This contains the complete state of a multistream Opus encoder. + * It is position independent and can be freely copied. + * @see opus_multistream_encoder_create + * @see opus_multistream_encoder_init + */ +typedef struct OpusMSEncoder OpusMSEncoder; + +/** Opus multistream decoder state. + * This contains the complete state of a multistream Opus decoder. + * It is position independent and can be freely copied. + * @see opus_multistream_decoder_create + * @see opus_multistream_decoder_init + */ +typedef struct OpusMSDecoder OpusMSDecoder; + +/**\name Multistream encoder functions */ +/**@{*/ + +/** Gets the size of an OpusMSEncoder structure. + * @param streams int: The total number of streams to encode from the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (streams + + * coupled_streams) must be no + * more than 255. + * @returns The size in bytes on success, or a negative error code + * (see @ref opus_errorcodes) on error. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size( + int streams, + int coupled_streams +); + +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_surround_encoder_get_size( + int channels, + int mapping_family +); + + +/** Allocates and initializes a multistream encoder state. + * Call opus_multistream_encoder_destroy() to release + * this object when finished. + * @param Fs opus_int32: Sampling rate of the input signal (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels in the input signal. + * This must be at most 255. + * It may be greater than the number of + * coded channels (streams + + * coupled_streams). + * @param streams int: The total number of streams to encode from the + * input. + * This must be no more than the number of channels. + * @param coupled_streams int: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (streams + + * coupled_streams) must be no + * more than the number of input channels. + * @param[in] mapping const unsigned char[channels]: Mapping from + * encoded channels to input channels, as described in + * @ref opus_multistream. As an extra constraint, the + * multistream encoder does not allow encoding coupled + * streams for which one channel is unused since this + * is never a good idea. + * @param application int: The target encoder application. + * This must be one of the following: + *
    + *
    #OPUS_APPLICATION_VOIP
    + *
    Process signal for improved speech intelligibility.
    + *
    #OPUS_APPLICATION_AUDIO
    + *
    Favor faithfulness to the original input.
    + *
    #OPUS_APPLICATION_RESTRICTED_LOWDELAY
    + *
    Configure the minimum possible coding delay by disabling certain modes + * of operation.
    + *
    + * @param[out] error int *: Returns #OPUS_OK on success, or an error + * code (see @ref opus_errorcodes) on + * failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create( + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application, + int *error +) OPUS_ARG_NONNULL(5); + +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_encoder_create( + opus_int32 Fs, + int channels, + int mapping_family, + int *streams, + int *coupled_streams, + unsigned char *mapping, + int application, + int *error +) OPUS_ARG_NONNULL(5); + +/** Initialize a previously allocated multistream encoder state. + * The memory pointed to by \a st must be at least the size returned by + * opus_multistream_encoder_get_size(). + * This is intended for applications which use their own allocator instead of + * malloc. + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @see opus_multistream_encoder_create + * @see opus_multistream_encoder_get_size + * @param st OpusMSEncoder*: Multistream encoder state to initialize. + * @param Fs opus_int32: Sampling rate of the input signal (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels in the input signal. + * This must be at most 255. + * It may be greater than the number of + * coded channels (streams + + * coupled_streams). + * @param streams int: The total number of streams to encode from the + * input. + * This must be no more than the number of channels. + * @param coupled_streams int: Number of coupled (2 channel) streams + * to encode. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * encoded channels (streams + + * coupled_streams) must be no + * more than the number of input channels. + * @param[in] mapping const unsigned char[channels]: Mapping from + * encoded channels to input channels, as described in + * @ref opus_multistream. As an extra constraint, the + * multistream encoder does not allow encoding coupled + * streams for which one channel is unused since this + * is never a good idea. + * @param application int: The target encoder application. + * This must be one of the following: + *
    + *
    #OPUS_APPLICATION_VOIP
    + *
    Process signal for improved speech intelligibility.
    + *
    #OPUS_APPLICATION_AUDIO
    + *
    Favor faithfulness to the original input.
    + *
    #OPUS_APPLICATION_RESTRICTED_LOWDELAY
    + *
    Configure the minimum possible coding delay by disabling certain modes + * of operation.
    + *
    + * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) + * on failure. + */ +OPUS_EXPORT int opus_multistream_encoder_init( + OpusMSEncoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); + +OPUS_EXPORT int opus_multistream_surround_encoder_init( + OpusMSEncoder *st, + opus_int32 Fs, + int channels, + int mapping_family, + int *streams, + int *coupled_streams, + unsigned char *mapping, + int application +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); + +/** Encodes a multistream Opus frame. + * @param st OpusMSEncoder*: Multistream encoder state. + * @param[in] pcm const opus_int16*: The input signal as interleaved + * samples. + * This must contain + * frame_size*channels + * samples. + * @param frame_size int: Number of samples per channel in the input + * signal. + * This must be an Opus frame size for the + * encoder's sampling rate. + * For example, at 48 kHz the permitted values + * are 120, 240, 480, 960, 1920, and 2880. + * Passing in a duration of less than 10 ms + * (480 samples at 48 kHz) will prevent the + * encoder from using the LPC or hybrid modes. + * @param[out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode( + OpusMSEncoder *st, + const opus_int16 *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Encodes a multistream Opus frame from floating point input. + * @param st OpusMSEncoder*: Multistream encoder state. + * @param[in] pcm const float*: The input signal as interleaved + * samples with a normal range of + * +/-1.0. + * Samples with a range beyond +/-1.0 + * are supported but will be clipped by + * decoders using the integer API and + * should only be used if it is known + * that the far end supports extended + * dynamic range. + * This must contain + * frame_size*channels + * samples. + * @param frame_size int: Number of samples per channel in the input + * signal. + * This must be an Opus frame size for the + * encoder's sampling rate. + * For example, at 48 kHz the permitted values + * are 120, 240, 480, 960, 1920, and 2880. + * Passing in a duration of less than 10 ms + * (480 samples at 48 kHz) will prevent the + * encoder from using the LPC or hybrid modes. + * @param[out] data unsigned char*: Output payload. + * This must contain storage for at + * least \a max_data_bytes. + * @param [in] max_data_bytes opus_int32: Size of the allocated + * memory for the output + * payload. This may be + * used to impose an upper limit on + * the instant bitrate, but should + * not be used as the only bitrate + * control. Use #OPUS_SET_BITRATE to + * control the bitrate. + * @returns The length of the encoded packet (in bytes) on success or a + * negative error code (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float( + OpusMSEncoder *st, + const float *pcm, + int frame_size, + unsigned char *data, + opus_int32 max_data_bytes +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); + +/** Frees an OpusMSEncoder allocated by + * opus_multistream_encoder_create(). + * @param st OpusMSEncoder*: Multistream encoder state to be freed. + */ +OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st); + +/** Perform a CTL function on a multistream Opus encoder. + * + * Generally the request and subsequent arguments are generated by a + * convenience macro. + * @param st OpusMSEncoder*: Multistream encoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls, + * @ref opus_encoderctls, or @ref opus_multistream_ctls. + * @see opus_genericctls + * @see opus_encoderctls + * @see opus_multistream_ctls + */ +OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); + +/**@}*/ + +/**\name Multistream decoder functions */ +/**@{*/ + +/** Gets the size of an OpusMSDecoder structure. + * @param streams int: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (streams + + * coupled_streams) must be no + * more than 255. + * @returns The size in bytes on success, or a negative error code + * (see @ref opus_errorcodes) on error. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size( + int streams, + int coupled_streams +); + +/** Allocates and initializes a multistream decoder state. + * Call opus_multistream_decoder_destroy() to release + * this object when finished. + * @param Fs opus_int32: Sampling rate to decode at (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels to output. + * This must be at most 255. + * It may be different from the number of coded + * channels (streams + + * coupled_streams). + * @param streams int: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number of streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (streams + + * coupled_streams) must be no + * more than 255. + * @param[in] mapping const unsigned char[channels]: Mapping from + * coded channels to output channels, as described in + * @ref opus_multistream. + * @param[out] error int *: Returns #OPUS_OK on success, or an error + * code (see @ref opus_errorcodes) on + * failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create( + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int *error +) OPUS_ARG_NONNULL(5); + +/** Intialize a previously allocated decoder state object. + * The memory pointed to by \a st must be at least the size returned by + * opus_multistream_encoder_get_size(). + * This is intended for applications which use their own allocator instead of + * malloc. + * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL. + * @see opus_multistream_decoder_create + * @see opus_multistream_deocder_get_size + * @param st OpusMSEncoder*: Multistream encoder state to initialize. + * @param Fs opus_int32: Sampling rate to decode at (in Hz). + * This must be one of 8000, 12000, 16000, + * 24000, or 48000. + * @param channels int: Number of channels to output. + * This must be at most 255. + * It may be different from the number of coded + * channels (streams + + * coupled_streams). + * @param streams int: The total number of streams coded in the + * input. + * This must be no more than 255. + * @param coupled_streams int: Number of streams to decode as coupled + * (2 channel) streams. + * This must be no larger than the total + * number of streams. + * Additionally, The total number of + * coded channels (streams + + * coupled_streams) must be no + * more than 255. + * @param[in] mapping const unsigned char[channels]: Mapping from + * coded channels to output channels, as described in + * @ref opus_multistream. + * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) + * on failure. + */ +OPUS_EXPORT int opus_multistream_decoder_init( + OpusMSDecoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); + +/** Decode a multistream Opus packet. + * @param st OpusMSDecoder*: Multistream decoder state. + * @param[in] data const unsigned char*: Input payload. + * Use a NULL + * pointer to indicate packet + * loss. + * @param len opus_int32: Number of bytes in payload. + * @param[out] pcm opus_int16*: Output signal, with interleaved + * samples. + * This must contain room for + * frame_size*channels + * samples. + * @param frame_size int: The number of samples per channel of + * available space in \a pcm. + * If this is less than the maximum packet duration + * (120 ms; 5760 for 48kHz), this function will not be capable + * of decoding some packets. In the case of PLC (data==NULL) + * or FEC (decode_fec=1), then frame_size needs to be exactly + * the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the + * next incoming packet. For the PLC and FEC cases, frame_size + * must be a multiple of 2.5 ms. + * @param decode_fec int: Flag (0 or 1) to request that any in-band + * forward error correction data be decoded. + * If no such data is available, the frame is + * decoded as if it were lost. + * @returns Number of samples decoded on success or a negative error code + * (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode( + OpusMSDecoder *st, + const unsigned char *data, + opus_int32 len, + opus_int16 *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Decode a multistream Opus packet with floating point output. + * @param st OpusMSDecoder*: Multistream decoder state. + * @param[in] data const unsigned char*: Input payload. + * Use a NULL + * pointer to indicate packet + * loss. + * @param len opus_int32: Number of bytes in payload. + * @param[out] pcm opus_int16*: Output signal, with interleaved + * samples. + * This must contain room for + * frame_size*channels + * samples. + * @param frame_size int: The number of samples per channel of + * available space in \a pcm. + * If this is less than the maximum packet duration + * (120 ms; 5760 for 48kHz), this function will not be capable + * of decoding some packets. In the case of PLC (data==NULL) + * or FEC (decode_fec=1), then frame_size needs to be exactly + * the duration of audio that is missing, otherwise the + * decoder will not be in the optimal state to decode the + * next incoming packet. For the PLC and FEC cases, frame_size + * must be a multiple of 2.5 ms. + * @param decode_fec int: Flag (0 or 1) to request that any in-band + * forward error correction data be decoded. + * If no such data is available, the frame is + * decoded as if it were lost. + * @returns Number of samples decoded on success or a negative error code + * (see @ref opus_errorcodes) on failure. + */ +OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float( + OpusMSDecoder *st, + const unsigned char *data, + opus_int32 len, + float *pcm, + int frame_size, + int decode_fec +) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); + +/** Perform a CTL function on a multistream Opus decoder. + * + * Generally the request and subsequent arguments are generated by a + * convenience macro. + * @param st OpusMSDecoder*: Multistream decoder state. + * @param request This and all remaining parameters should be replaced by one + * of the convenience macros in @ref opus_genericctls, + * @ref opus_decoderctls, or @ref opus_multistream_ctls. + * @see opus_genericctls + * @see opus_decoderctls + * @see opus_multistream_ctls + */ +OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); + +/** Frees an OpusMSDecoder allocated by + * opus_multistream_decoder_create(). + * @param st OpusMSDecoder: Multistream decoder state to be freed. + */ +OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st); + +/**@}*/ + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* OPUS_MULTISTREAM_H */ diff --git a/TelegramClient.Opus/opus/include/opus_types.h b/TelegramClient.Opus/opus/include/opus_types.h new file mode 100755 index 0000000..b28e03a --- /dev/null +++ b/TelegramClient.Opus/opus/include/opus_types.h @@ -0,0 +1,159 @@ +/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */ +/* Modified by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ +/* opus_types.h based on ogg_types.h from libogg */ + +/** + @file opus_types.h + @brief Opus reference implementation types +*/ +#ifndef OPUS_TYPES_H +#define OPUS_TYPES_H + +/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */ +#if (defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H)) +#include + + typedef int16_t opus_int16; + typedef uint16_t opus_uint16; + typedef int32_t opus_int32; + typedef uint32_t opus_uint32; +#elif defined(_WIN32) + +# if defined(__CYGWIN__) +# include <_G_config.h> + typedef _G_int32_t opus_int32; + typedef _G_uint32_t opus_uint32; + typedef _G_int16 opus_int16; + typedef _G_uint16 opus_uint16; +# elif defined(__MINGW32__) + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; +# elif defined(__MWERKS__) + typedef int opus_int32; + typedef unsigned int opus_uint32; + typedef short opus_int16; + typedef unsigned short opus_uint16; +# else + /* MSVC/Borland */ + typedef __int32 opus_int32; + typedef unsigned __int32 opus_uint32; + typedef __int16 opus_int16; + typedef unsigned __int16 opus_uint16; +# endif + +#elif defined(__MACOS__) + +# include + typedef SInt16 opus_int16; + typedef UInt16 opus_uint16; + typedef SInt32 opus_int32; + typedef UInt32 opus_uint32; + +#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ + +# include + typedef int16_t opus_int16; + typedef u_int16_t opus_uint16; + typedef int32_t opus_int32; + typedef u_int32_t opus_uint32; + +#elif defined(__BEOS__) + + /* Be */ +# include + typedef int16 opus_int16; + typedef u_int16 opus_uint16; + typedef int32_t opus_int32; + typedef u_int32_t opus_uint32; + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; + +#elif defined (DJGPP) + + /* DJGPP */ + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; + +#elif defined(R5900) + + /* PS2 EE */ + typedef int opus_int32; + typedef unsigned opus_uint32; + typedef short opus_int16; + typedef unsigned short opus_uint16; + +#elif defined(__SYMBIAN32__) + + /* Symbian GCC */ + typedef signed short opus_int16; + typedef unsigned short opus_uint16; + typedef signed int opus_int32; + typedef unsigned int opus_uint32; + +#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) + + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef long opus_int32; + typedef unsigned long opus_uint32; + +#elif defined(CONFIG_TI_C6X) + + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; + +#else + + /* Give up, take a reasonable guess */ + typedef short opus_int16; + typedef unsigned short opus_uint16; + typedef int opus_int32; + typedef unsigned int opus_uint32; + +#endif + +#define opus_int int /* used for counters etc; at least 16 bits */ +#define opus_int64 long long +#define opus_int8 signed char + +#define opus_uint unsigned int /* used for counters etc; at least 16 bits */ +#define opus_uint64 unsigned long long +#define opus_uint8 unsigned char + +#endif /* OPUS_TYPES_H */ diff --git a/TelegramClient.Opus/opus/ogg/bitwise.c b/TelegramClient.Opus/opus/ogg/bitwise.c new file mode 100755 index 0000000..49986af --- /dev/null +++ b/TelegramClient.Opus/opus/ogg/bitwise.c @@ -0,0 +1,857 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: packing variable sized words into an octet stream + last mod: $Id: bitwise.c 18051 2011-08-04 17:56:39Z giles $ + + ********************************************************************/ + +/* We're 'LSb' endian; if we write a word but read individual bits, + then we'll read the lsb first */ + +#include +#include +#include +#include + +#define BUFFER_INCREMENT 256 + +static const unsigned long mask[]= +{0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, + 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, + 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, + 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff, + 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff, + 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, + 0x3fffffff,0x7fffffff,0xffffffff }; + +static const unsigned int mask8B[]= +{0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff}; + +void oggpack_writeinit(oggpack_buffer *b){ + memset(b,0,sizeof(*b)); + b->ptr=b->buffer=_ogg_malloc(BUFFER_INCREMENT); + b->buffer[0]='\0'; + b->storage=BUFFER_INCREMENT; +} + +void oggpackB_writeinit(oggpack_buffer *b){ + oggpack_writeinit(b); +} + +int oggpack_writecheck(oggpack_buffer *b){ + if(!b->ptr || !b->storage)return -1; + return 0; +} + +int oggpackB_writecheck(oggpack_buffer *b){ + return oggpack_writecheck(b); +} + +void oggpack_writetrunc(oggpack_buffer *b,long bits){ + long bytes=bits>>3; + if(b->ptr){ + bits-=bytes*8; + b->ptr=b->buffer+bytes; + b->endbit=bits; + b->endbyte=bytes; + *b->ptr&=mask[bits]; + } +} + +void oggpackB_writetrunc(oggpack_buffer *b,long bits){ + long bytes=bits>>3; + if(b->ptr){ + bits-=bytes*8; + b->ptr=b->buffer+bytes; + b->endbit=bits; + b->endbyte=bytes; + *b->ptr&=mask8B[bits]; + } +} + +/* Takes only up to 32 bits. */ +void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){ + if(bits<0 || bits>32) goto err; + if(b->endbyte>=b->storage-4){ + void *ret; + if(!b->ptr)return; + if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err; + ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); + if(!ret) goto err; + b->buffer=ret; + b->storage+=BUFFER_INCREMENT; + b->ptr=b->buffer+b->endbyte; + } + + value&=mask[bits]; + bits+=b->endbit; + + b->ptr[0]|=value<endbit; + + if(bits>=8){ + b->ptr[1]=(unsigned char)(value>>(8-b->endbit)); + if(bits>=16){ + b->ptr[2]=(unsigned char)(value>>(16-b->endbit)); + if(bits>=24){ + b->ptr[3]=(unsigned char)(value>>(24-b->endbit)); + if(bits>=32){ + if(b->endbit) + b->ptr[4]=(unsigned char)(value>>(32-b->endbit)); + else + b->ptr[4]=0; + } + } + } + } + + b->endbyte+=bits/8; + b->ptr+=bits/8; + b->endbit=bits&7; + return; + err: + oggpack_writeclear(b); +} + +/* Takes only up to 32 bits. */ +void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){ + if(bits<0 || bits>32) goto err; + if(b->endbyte>=b->storage-4){ + void *ret; + if(!b->ptr)return; + if(b->storage>LONG_MAX-BUFFER_INCREMENT) goto err; + ret=_ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT); + if(!ret) goto err; + b->buffer=ret; + b->storage+=BUFFER_INCREMENT; + b->ptr=b->buffer+b->endbyte; + } + + value=(value&mask[bits])<<(32-bits); + bits+=b->endbit; + + b->ptr[0]|=value>>(24+b->endbit); + + if(bits>=8){ + b->ptr[1]=(unsigned char)(value>>(16+b->endbit)); + if(bits>=16){ + b->ptr[2]=(unsigned char)(value>>(8+b->endbit)); + if(bits>=24){ + b->ptr[3]=(unsigned char)(value>>(b->endbit)); + if(bits>=32){ + if(b->endbit) + b->ptr[4]=(unsigned char)(value<<(8-b->endbit)); + else + b->ptr[4]=0; + } + } + } + } + + b->endbyte+=bits/8; + b->ptr+=bits/8; + b->endbit=bits&7; + return; + err: + oggpack_writeclear(b); +} + +void oggpack_writealign(oggpack_buffer *b){ + int bits=8-b->endbit; + if(bits<8) + oggpack_write(b,0,bits); +} + +void oggpackB_writealign(oggpack_buffer *b){ + int bits=8-b->endbit; + if(bits<8) + oggpackB_write(b,0,bits); +} + +static void oggpack_writecopy_helper(oggpack_buffer *b, + void *source, + long bits, + void (*w)(oggpack_buffer *, + unsigned long, + int), + int msb){ + unsigned char *ptr=(unsigned char *)source; + + long bytes=bits/8; + bits-=bytes*8; + + if(b->endbit){ + int i; + /* unaligned copy. Do it the hard way. */ + for(i=0;iendbyte+bytes+1>=b->storage){ + void *ret; + if(!b->ptr) goto err; + if(b->endbyte+bytes+BUFFER_INCREMENT>b->storage) goto err; + b->storage=b->endbyte+bytes+BUFFER_INCREMENT; + ret=_ogg_realloc(b->buffer,b->storage); + if(!ret) goto err; + b->buffer=ret; + b->ptr=b->buffer+b->endbyte; + } + + memmove(b->ptr,source,bytes); + b->ptr+=bytes; + b->endbyte+=bytes; + *b->ptr=0; + + } + if(bits){ + if(msb) + w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits); + else + w(b,(unsigned long)(ptr[bytes]),bits); + } + return; + err: + oggpack_writeclear(b); +} + +void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){ + oggpack_writecopy_helper(b,source,bits,oggpack_write,0); +} + +void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits){ + oggpack_writecopy_helper(b,source,bits,oggpackB_write,1); +} + +void oggpack_reset(oggpack_buffer *b){ + if(!b->ptr)return; + b->ptr=b->buffer; + b->buffer[0]=0; + b->endbit=b->endbyte=0; +} + +void oggpackB_reset(oggpack_buffer *b){ + oggpack_reset(b); +} + +void oggpack_writeclear(oggpack_buffer *b){ + if(b->buffer)_ogg_free(b->buffer); + memset(b,0,sizeof(*b)); +} + +void oggpackB_writeclear(oggpack_buffer *b){ + oggpack_writeclear(b); +} + +void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){ + memset(b,0,sizeof(*b)); + b->buffer=b->ptr=buf; + b->storage=bytes; +} + +void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){ + oggpack_readinit(b,buf,bytes); +} + +/* Read in bits without advancing the bitptr; bits <= 32 */ +long oggpack_look(oggpack_buffer *b,int bits){ + unsigned long ret; + unsigned long m; + + if(bits<0 || bits>32) return -1; + m=mask[bits]; + bits+=b->endbit; + + if(b->endbyte >= b->storage-4){ + /* not the main path */ + if(b->endbyte > b->storage-((bits+7)>>3)) return -1; + /* special case to avoid reading b->ptr[0], which might be past the end of + the buffer; also skips some useless accounting */ + else if(!bits)return(0L); + } + + ret=b->ptr[0]>>b->endbit; + if(bits>8){ + ret|=b->ptr[1]<<(8-b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(16-b->endbit); + if(bits>24){ + ret|=b->ptr[3]<<(24-b->endbit); + if(bits>32 && b->endbit) + ret|=b->ptr[4]<<(32-b->endbit); + } + } + } + return(m&ret); +} + +/* Read in bits without advancing the bitptr; bits <= 32 */ +long oggpackB_look(oggpack_buffer *b,int bits){ + unsigned long ret; + int m=32-bits; + + if(m<0 || m>32) return -1; + bits+=b->endbit; + + if(b->endbyte >= b->storage-4){ + /* not the main path */ + if(b->endbyte > b->storage-((bits+7)>>3)) return -1; + /* special case to avoid reading b->ptr[0], which might be past the end of + the buffer; also skips some useless accounting */ + else if(!bits)return(0L); + } + + ret=b->ptr[0]<<(24+b->endbit); + if(bits>8){ + ret|=b->ptr[1]<<(16+b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(8+b->endbit); + if(bits>24){ + ret|=b->ptr[3]<<(b->endbit); + if(bits>32 && b->endbit) + ret|=b->ptr[4]>>(8-b->endbit); + } + } + } + return ((ret&0xffffffff)>>(m>>1))>>((m+1)>>1); +} + +long oggpack_look1(oggpack_buffer *b){ + if(b->endbyte>=b->storage)return(-1); + return((b->ptr[0]>>b->endbit)&1); +} + +long oggpackB_look1(oggpack_buffer *b){ + if(b->endbyte>=b->storage)return(-1); + return((b->ptr[0]>>(7-b->endbit))&1); +} + +void oggpack_adv(oggpack_buffer *b,int bits){ + bits+=b->endbit; + + if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow; + + b->ptr+=bits/8; + b->endbyte+=bits/8; + b->endbit=bits&7; + return; + + overflow: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; +} + +void oggpackB_adv(oggpack_buffer *b,int bits){ + oggpack_adv(b,bits); +} + +void oggpack_adv1(oggpack_buffer *b){ + if(++(b->endbit)>7){ + b->endbit=0; + b->ptr++; + b->endbyte++; + } +} + +void oggpackB_adv1(oggpack_buffer *b){ + oggpack_adv1(b); +} + +/* bits <= 32 */ +long oggpack_read(oggpack_buffer *b,int bits){ + long ret; + unsigned long m; + + if(bits<0 || bits>32) goto err; + m=mask[bits]; + bits+=b->endbit; + + if(b->endbyte >= b->storage-4){ + /* not the main path */ + if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow; + /* special case to avoid reading b->ptr[0], which might be past the end of + the buffer; also skips some useless accounting */ + else if(!bits)return(0L); + } + + ret=b->ptr[0]>>b->endbit; + if(bits>8){ + ret|=b->ptr[1]<<(8-b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(16-b->endbit); + if(bits>24){ + ret|=b->ptr[3]<<(24-b->endbit); + if(bits>32 && b->endbit){ + ret|=b->ptr[4]<<(32-b->endbit); + } + } + } + } + ret&=m; + b->ptr+=bits/8; + b->endbyte+=bits/8; + b->endbit=bits&7; + return ret; + + overflow: + err: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; + return -1L; +} + +/* bits <= 32 */ +long oggpackB_read(oggpack_buffer *b,int bits){ + long ret; + long m=32-bits; + + if(m<0 || m>32) goto err; + bits+=b->endbit; + + if(b->endbyte+4>=b->storage){ + /* not the main path */ + if(b->endbyte > b->storage-((bits+7)>>3)) goto overflow; + /* special case to avoid reading b->ptr[0], which might be past the end of + the buffer; also skips some useless accounting */ + else if(!bits)return(0L); + } + + ret=b->ptr[0]<<(24+b->endbit); + if(bits>8){ + ret|=b->ptr[1]<<(16+b->endbit); + if(bits>16){ + ret|=b->ptr[2]<<(8+b->endbit); + if(bits>24){ + ret|=b->ptr[3]<<(b->endbit); + if(bits>32 && b->endbit) + ret|=b->ptr[4]>>(8-b->endbit); + } + } + } + ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1); + + b->ptr+=bits/8; + b->endbyte+=bits/8; + b->endbit=bits&7; + return ret; + + overflow: + err: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; + return -1L; +} + +long oggpack_read1(oggpack_buffer *b){ + long ret; + + if(b->endbyte >= b->storage) goto overflow; + ret=(b->ptr[0]>>b->endbit)&1; + + b->endbit++; + if(b->endbit>7){ + b->endbit=0; + b->ptr++; + b->endbyte++; + } + return ret; + + overflow: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; + return -1L; +} + +long oggpackB_read1(oggpack_buffer *b){ + long ret; + + if(b->endbyte >= b->storage) goto overflow; + ret=(b->ptr[0]>>(7-b->endbit))&1; + + b->endbit++; + if(b->endbit>7){ + b->endbit=0; + b->ptr++; + b->endbyte++; + } + return ret; + + overflow: + b->ptr=NULL; + b->endbyte=b->storage; + b->endbit=1; + return -1L; +} + +long oggpack_bytes(oggpack_buffer *b){ + return(b->endbyte+(b->endbit+7)/8); +} + +long oggpack_bits(oggpack_buffer *b){ + return(b->endbyte*8+b->endbit); +} + +long oggpackB_bytes(oggpack_buffer *b){ + return oggpack_bytes(b); +} + +long oggpackB_bits(oggpack_buffer *b){ + return oggpack_bits(b); +} + +unsigned char *oggpack_get_buffer(oggpack_buffer *b){ + return(b->buffer); +} + +unsigned char *oggpackB_get_buffer(oggpack_buffer *b){ + return oggpack_get_buffer(b); +} + +/* Self test of the bitwise routines; everything else is based on + them, so they damned well better be solid. */ + +#ifdef _V_SELFTEST +#include + +static int ilog(unsigned int v){ + int ret=0; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +oggpack_buffer o; +oggpack_buffer r; + +void report(char *in){ + fprintf(stderr,"%s",in); + exit(1); +} + +void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){ + long bytes,i; + unsigned char *buffer; + + oggpack_reset(&o); + for(i=0;i +#include +#include +#include + +/* A complete description of Ogg framing exists in docs/framing.html */ + +int ogg_page_version(const ogg_page *og){ + return((int)(og->header[4])); +} + +int ogg_page_continued(const ogg_page *og){ + return((int)(og->header[5]&0x01)); +} + +int ogg_page_bos(const ogg_page *og){ + return((int)(og->header[5]&0x02)); +} + +int ogg_page_eos(const ogg_page *og){ + return((int)(og->header[5]&0x04)); +} + +ogg_int64_t ogg_page_granulepos(const ogg_page *og){ + unsigned char *page=og->header; + ogg_int64_t granulepos=page[13]&(0xff); + granulepos= (granulepos<<8)|(page[12]&0xff); + granulepos= (granulepos<<8)|(page[11]&0xff); + granulepos= (granulepos<<8)|(page[10]&0xff); + granulepos= (granulepos<<8)|(page[9]&0xff); + granulepos= (granulepos<<8)|(page[8]&0xff); + granulepos= (granulepos<<8)|(page[7]&0xff); + granulepos= (granulepos<<8)|(page[6]&0xff); + return(granulepos); +} + +int ogg_page_serialno(const ogg_page *og){ + return(og->header[14] | + (og->header[15]<<8) | + (og->header[16]<<16) | + (og->header[17]<<24)); +} + +long ogg_page_pageno(const ogg_page *og){ + return(og->header[18] | + (og->header[19]<<8) | + (og->header[20]<<16) | + (og->header[21]<<24)); +} + + + +/* returns the number of packets that are completed on this page (if + the leading packet is begun on a previous page, but ends on this + page, it's counted */ + +/* NOTE: + If a page consists of a packet begun on a previous page, and a new + packet begun (but not completed) on this page, the return will be: + ogg_page_packets(page) ==1, + ogg_page_continued(page) !=0 + + If a page happens to be a single packet that was begun on a + previous page, and spans to the next page (in the case of a three or + more page packet), the return will be: + ogg_page_packets(page) ==0, + ogg_page_continued(page) !=0 +*/ + +int ogg_page_packets(const ogg_page *og){ + int i,n=og->header[26],count=0; + for(i=0;iheader[27+i]<255)count++; + return(count); +} + + +#if 0 +/* helper to initialize lookup for direct-table CRC (illustrative; we + use the static init below) */ + +static ogg_uint32_t _ogg_crc_entry(unsigned long index){ + int i; + unsigned long r; + + r = index << 24; + for (i=0; i<8; i++) + if (r & 0x80000000UL) + r = (r << 1) ^ 0x04c11db7; /* The same as the ethernet generator + polynomial, although we use an + unreflected alg and an init/final + of 0, not 0xffffffff */ + else + r<<=1; + return (r & 0xffffffffUL); +} +#endif + +static const ogg_uint32_t crc_lookup[256]={ + 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9, + 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005, + 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61, + 0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd, + 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9, + 0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75, + 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011, + 0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd, + 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039, + 0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5, + 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81, + 0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d, + 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49, + 0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95, + 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1, + 0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d, + 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae, + 0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072, + 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16, + 0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca, + 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde, + 0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02, + 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066, + 0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba, + 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e, + 0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692, + 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6, + 0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a, + 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e, + 0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2, + 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686, + 0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a, + 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637, + 0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb, + 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f, + 0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53, + 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47, + 0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b, + 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff, + 0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623, + 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7, + 0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b, + 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f, + 0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3, + 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7, + 0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b, + 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f, + 0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3, + 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640, + 0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c, + 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8, + 0x68860bfd,0x6c47164a,0x61043093,0x65c52d24, + 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30, + 0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec, + 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088, + 0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654, + 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0, + 0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c, + 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18, + 0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4, + 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0, + 0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c, + 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668, + 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4}; + +/* init the encode/decode logical stream state */ + +int ogg_stream_init(ogg_stream_state *os,int serialno){ + if(os){ + memset(os,0,sizeof(*os)); + os->body_storage=16*1024; + os->lacing_storage=1024; + + os->body_data=_ogg_malloc(os->body_storage*sizeof(*os->body_data)); + os->lacing_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->lacing_vals)); + os->granule_vals=_ogg_malloc(os->lacing_storage*sizeof(*os->granule_vals)); + + if(!os->body_data || !os->lacing_vals || !os->granule_vals){ + ogg_stream_clear(os); + return -1; + } + + os->serialno=serialno; + + return(0); + } + return(-1); +} + +/* async/delayed error detection for the ogg_stream_state */ +int ogg_stream_check(ogg_stream_state *os){ + if(!os || !os->body_data) return -1; + return 0; +} + +/* _clear does not free os, only the non-flat storage within */ +int ogg_stream_clear(ogg_stream_state *os){ + if(os){ + if(os->body_data)_ogg_free(os->body_data); + if(os->lacing_vals)_ogg_free(os->lacing_vals); + if(os->granule_vals)_ogg_free(os->granule_vals); + + memset(os,0,sizeof(*os)); + } + return(0); +} + +int ogg_stream_destroy(ogg_stream_state *os){ + if(os){ + ogg_stream_clear(os); + _ogg_free(os); + } + return(0); +} + +/* Helpers for ogg_stream_encode; this keeps the structure and + what's happening fairly clear */ + +static int _os_body_expand(ogg_stream_state *os,long needed){ + if(os->body_storage-needed<=os->body_fill){ + long body_storage; + void *ret; + if(os->body_storage>LONG_MAX-needed){ + ogg_stream_clear(os); + return -1; + } + body_storage=os->body_storage+needed; + if(body_storagebody_data,body_storage*sizeof(*os->body_data)); + if(!ret){ + ogg_stream_clear(os); + return -1; + } + os->body_storage=body_storage; + os->body_data=ret; + } + return 0; +} + +static int _os_lacing_expand(ogg_stream_state *os,long needed){ + if(os->lacing_storage-needed<=os->lacing_fill){ + long lacing_storage; + void *ret; + if(os->lacing_storage>LONG_MAX-needed){ + ogg_stream_clear(os); + return -1; + } + lacing_storage=os->lacing_storage+needed; + if(lacing_storagelacing_vals,lacing_storage*sizeof(*os->lacing_vals)); + if(!ret){ + ogg_stream_clear(os); + return -1; + } + os->lacing_vals=ret; + ret=_ogg_realloc(os->granule_vals,lacing_storage* + sizeof(*os->granule_vals)); + if(!ret){ + ogg_stream_clear(os); + return -1; + } + os->granule_vals=ret; + os->lacing_storage=lacing_storage; + } + return 0; +} + +/* checksum the page */ +/* Direct table CRC; note that this will be faster in the future if we + perform the checksum simultaneously with other copies */ + +void ogg_page_checksum_set(ogg_page *og){ + if(og){ + ogg_uint32_t crc_reg=0; + int i; + + /* safety; needed for API behavior, but not framing code */ + og->header[22]=0; + og->header[23]=0; + og->header[24]=0; + og->header[25]=0; + + for(i=0;iheader_len;i++) + crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->header[i]]; + for(i=0;ibody_len;i++) + crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg >> 24)&0xff)^og->body[i]]; + + og->header[22]=(unsigned char)(crc_reg&0xff); + og->header[23]=(unsigned char)((crc_reg>>8)&0xff); + og->header[24]=(unsigned char)((crc_reg>>16)&0xff); + og->header[25]=(unsigned char)((crc_reg>>24)&0xff); + } +} + +/* submit data to the internal buffer of the framing engine */ +int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count, + long e_o_s, ogg_int64_t granulepos){ + + long bytes = 0, lacing_vals; + int i; + + if(ogg_stream_check(os)) return -1; + if(!iov) return 0; + + for (i = 0; i < count; ++i){ + if(iov[i].iov_len>LONG_MAX) return -1; + if(bytes>LONG_MAX-(long)iov[i].iov_len) return -1; + bytes += (long)iov[i].iov_len; + } + lacing_vals=bytes/255+1; + + if(os->body_returned){ + /* advance packet data according to the body_returned pointer. We + had to keep it around to return a pointer into the buffer last + call */ + + os->body_fill-=os->body_returned; + if(os->body_fill) + memmove(os->body_data,os->body_data+os->body_returned, + os->body_fill); + os->body_returned=0; + } + + /* make sure we have the buffer storage */ + if(_os_body_expand(os,bytes) || _os_lacing_expand(os,lacing_vals)) + return -1; + + /* Copy in the submitted packet. Yes, the copy is a waste; this is + the liability of overly clean abstraction for the time being. It + will actually be fairly easy to eliminate the extra copy in the + future */ + + for (i = 0; i < count; ++i) { + memcpy(os->body_data+os->body_fill, iov[i].iov_base, iov[i].iov_len); + os->body_fill += (int)iov[i].iov_len; + } + + /* Store lacing vals for this packet */ + for(i=0;ilacing_vals[os->lacing_fill+i]=255; + os->granule_vals[os->lacing_fill+i]=os->granulepos; + } + os->lacing_vals[os->lacing_fill+i]=bytes%255; + os->granulepos=os->granule_vals[os->lacing_fill+i]=granulepos; + + /* flag the first segment as the beginning of the packet */ + os->lacing_vals[os->lacing_fill]|= 0x100; + + os->lacing_fill+=lacing_vals; + + /* for the sake of completeness */ + os->packetno++; + + if(e_o_s)os->e_o_s=1; + + return(0); +} + +int ogg_stream_packetin(ogg_stream_state *os,ogg_packet *op){ + ogg_iovec_t iov; + iov.iov_base = op->packet; + iov.iov_len = op->bytes; + return ogg_stream_iovecin(os, &iov, 1, op->e_o_s, op->granulepos); +} + +/* Conditionally flush a page; force==0 will only flush nominal-size + pages, force==1 forces us to flush a page regardless of page size + so long as there's any data available at all. */ +static int ogg_stream_flush_i(ogg_stream_state *os,ogg_page *og, int force, int nfill){ + int i; + int vals=0; + int maxvals=(os->lacing_fill>255?255:os->lacing_fill); + int bytes=0; + long acc=0; + ogg_int64_t granule_pos=-1; + + if(ogg_stream_check(os)) return(0); + if(maxvals==0) return(0); + + /* construct a page */ + /* decide how many segments to include */ + + /* If this is the initial header case, the first page must only include + the initial header packet */ + if(os->b_o_s==0){ /* 'initial header page' case */ + granule_pos=0; + for(vals=0;valslacing_vals[vals]&0x0ff)<255){ + vals++; + break; + } + } + }else{ + + /* The extra packets_done, packet_just_done logic here attempts to do two things: + 1) Don't unneccessarily span pages. + 2) Unless necessary, don't flush pages if there are less than four packets on + them; this expands page size to reduce unneccessary overhead if incoming packets + are large. + These are not necessary behaviors, just 'always better than naive flushing' + without requiring an application to explicitly request a specific optimized + behavior. We'll want an explicit behavior setup pathway eventually as well. */ + + int packets_done=0; + int packet_just_done=0; + for(vals=0;valsnfill && packet_just_done>=4){ + force=1; + break; + } + acc+=os->lacing_vals[vals]&0x0ff; + if((os->lacing_vals[vals]&0xff)<255){ + granule_pos=os->granule_vals[vals]; + packet_just_done=++packets_done; + }else + packet_just_done=0; + } + if(vals==255)force=1; + } + + if(!force) return(0); + + /* construct the header in temp storage */ + memcpy(os->header,"OggS",4); + + /* stream structure version */ + os->header[4]=0x00; + + /* continued packet flag? */ + os->header[5]=0x00; + if((os->lacing_vals[0]&0x100)==0)os->header[5]|=0x01; + /* first page flag? */ + if(os->b_o_s==0)os->header[5]|=0x02; + /* last page flag? */ + if(os->e_o_s && os->lacing_fill==vals)os->header[5]|=0x04; + os->b_o_s=1; + + /* 64 bits of PCM position */ + for(i=6;i<14;i++){ + os->header[i]=(unsigned char)(granule_pos&0xff); + granule_pos>>=8; + } + + /* 32 bits of stream serial number */ + { + long serialno=os->serialno; + for(i=14;i<18;i++){ + os->header[i]=(unsigned char)(serialno&0xff); + serialno>>=8; + } + } + + /* 32 bits of page counter (we have both counter and page header + because this val can roll over) */ + if(os->pageno==-1)os->pageno=0; /* because someone called + stream_reset; this would be a + strange thing to do in an + encode stream, but it has + plausible uses */ + { + long pageno=os->pageno++; + for(i=18;i<22;i++){ + os->header[i]=(unsigned char)(pageno&0xff); + pageno>>=8; + } + } + + /* zero for computation; filled in later */ + os->header[22]=0; + os->header[23]=0; + os->header[24]=0; + os->header[25]=0; + + /* segment table */ + os->header[26]=(unsigned char)(vals&0xff); + for(i=0;iheader[i+27]=(unsigned char)(os->lacing_vals[i]&0xff); + + /* set pointers in the ogg_page struct */ + og->header=os->header; + og->header_len=os->header_fill=vals+27; + og->body=os->body_data+os->body_returned; + og->body_len=bytes; + + /* advance the lacing data and set the body_returned pointer */ + + os->lacing_fill-=vals; + memmove(os->lacing_vals,os->lacing_vals+vals,os->lacing_fill*sizeof(*os->lacing_vals)); + memmove(os->granule_vals,os->granule_vals+vals,os->lacing_fill*sizeof(*os->granule_vals)); + os->body_returned+=bytes; + + /* calculate the checksum */ + + ogg_page_checksum_set(og); + + /* done */ + return(1); +} + +/* This will flush remaining packets into a page (returning nonzero), + even if there is not enough data to trigger a flush normally + (undersized page). If there are no packets or partial packets to + flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will + try to flush a normal sized page like ogg_stream_pageout; a call to + ogg_stream_flush does not guarantee that all packets have flushed. + Only a return value of 0 from ogg_stream_flush indicates all packet + data is flushed into pages. + + since ogg_stream_flush will flush the last page in a stream even if + it's undersized, you almost certainly want to use ogg_stream_pageout + (and *not* ogg_stream_flush) unless you specifically need to flush + a page regardless of size in the middle of a stream. */ + +int ogg_stream_flush(ogg_stream_state *os,ogg_page *og){ + return ogg_stream_flush_i(os,og,1,4096); +} + +/* Like the above, but an argument is provided to adjust the nominal + page size for applications which are smart enough to provide their + own delay based flushing */ + +int ogg_stream_flush_fill(ogg_stream_state *os,ogg_page *og, int nfill){ + return ogg_stream_flush_i(os,og,1,nfill); +} + +/* This constructs pages from buffered packet segments. The pointers +returned are to static buffers; do not free. The returned buffers are +good only until the next call (using the same ogg_stream_state) */ + +int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og){ + int force=0; + if(ogg_stream_check(os)) return 0; + + if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */ + (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */ + force=1; + + return(ogg_stream_flush_i(os,og,force,4096)); +} + +/* Like the above, but an argument is provided to adjust the nominal +page size for applications which are smart enough to provide their +own delay based flushing */ + +int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill){ + int force=0; + if(ogg_stream_check(os)) return 0; + + if((os->e_o_s&&os->lacing_fill) || /* 'were done, now flush' case */ + (os->lacing_fill&&!os->b_o_s)) /* 'initial header page' case */ + force=1; + + return(ogg_stream_flush_i(os,og,force,nfill)); +} + +int ogg_stream_eos(ogg_stream_state *os){ + if(ogg_stream_check(os)) return 1; + return os->e_o_s; +} + +/* DECODING PRIMITIVES: packet streaming layer **********************/ + +/* This has two layers to place more of the multi-serialno and paging + control in the application's hands. First, we expose a data buffer + using ogg_sync_buffer(). The app either copies into the + buffer, or passes it directly to read(), etc. We then call + ogg_sync_wrote() to tell how many bytes we just added. + + Pages are returned (pointers into the buffer in ogg_sync_state) + by ogg_sync_pageout(). The page is then submitted to + ogg_stream_pagein() along with the appropriate + ogg_stream_state* (ie, matching serialno). We then get raw + packets out calling ogg_stream_packetout() with a + ogg_stream_state. */ + +/* initialize the struct to a known state */ +int ogg_sync_init(ogg_sync_state *oy){ + if(oy){ + oy->storage = -1; /* used as a readiness flag */ + memset(oy,0,sizeof(*oy)); + } + return(0); +} + +/* clear non-flat storage within */ +int ogg_sync_clear(ogg_sync_state *oy){ + if(oy){ + if(oy->data)_ogg_free(oy->data); + memset(oy,0,sizeof(*oy)); + } + return(0); +} + +int ogg_sync_destroy(ogg_sync_state *oy){ + if(oy){ + ogg_sync_clear(oy); + _ogg_free(oy); + } + return(0); +} + +int ogg_sync_check(ogg_sync_state *oy){ + if(oy->storage<0) return -1; + return 0; +} + +char *ogg_sync_buffer(ogg_sync_state *oy, long size){ + if(ogg_sync_check(oy)) return NULL; + + /* first, clear out any space that has been previously returned */ + if(oy->returned){ + oy->fill-=oy->returned; + if(oy->fill>0) + memmove(oy->data,oy->data+oy->returned,oy->fill); + oy->returned=0; + } + + if(size>oy->storage-oy->fill){ + /* We need to extend the internal buffer */ + long newsize=size+oy->fill+4096; /* an extra page to be nice */ + void *ret; + + if(oy->data) + ret=_ogg_realloc(oy->data,newsize); + else + ret=_ogg_malloc(newsize); + if(!ret){ + ogg_sync_clear(oy); + return NULL; + } + oy->data=ret; + oy->storage=newsize; + } + + /* expose a segment at least as large as requested at the fill mark */ + return((char *)oy->data+oy->fill); +} + +int ogg_sync_wrote(ogg_sync_state *oy, long bytes){ + if(ogg_sync_check(oy))return -1; + if(oy->fill+bytes>oy->storage)return -1; + oy->fill+=bytes; + return(0); +} + +/* sync the stream. This is meant to be useful for finding page + boundaries. + + return values for this: + -n) skipped n bytes + 0) page not ready; more data (no bytes skipped) + n) page synced at current location; page length n bytes + +*/ + +long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ + unsigned char *page=oy->data+oy->returned; + unsigned char *next; + long bytes=oy->fill-oy->returned; + + if(ogg_sync_check(oy))return 0; + + if(oy->headerbytes==0){ + int headerbytes,i; + if(bytes<27)return(0); /* not enough for a header */ + + /* verify capture pattern */ + if(memcmp(page,"OggS",4))goto sync_fail; + + headerbytes=page[26]+27; + if(bytesbodybytes+=page[27+i]; + oy->headerbytes=headerbytes; + } + + if(oy->bodybytes+oy->headerbytes>bytes)return(0); + + /* The whole test page is buffered. Verify the checksum */ + { + /* Grab the checksum bytes, set the header field to zero */ + char chksum[4]; + ogg_page log; + + memcpy(chksum,page+22,4); + memset(page+22,0,4); + + /* set up a temp page struct and recompute the checksum */ + log.header=page; + log.header_len=oy->headerbytes; + log.body=page+oy->headerbytes; + log.body_len=oy->bodybytes; + ogg_page_checksum_set(&log); + + /* Compare */ + if(memcmp(chksum,page+22,4)){ + /* D'oh. Mismatch! Corrupt page (or miscapture and not a page + at all) */ + /* replace the computed checksum with the one actually read in */ + memcpy(page+22,chksum,4); + + /* Bad checksum. Lose sync */ + goto sync_fail; + } + } + + /* yes, have a whole page all ready to go */ + { + unsigned char *page=oy->data+oy->returned; + long bytes; + + if(og){ + og->header=page; + og->header_len=oy->headerbytes; + og->body=page+oy->headerbytes; + og->body_len=oy->bodybytes; + } + + oy->unsynced=0; + oy->returned+=(bytes=oy->headerbytes+oy->bodybytes); + oy->headerbytes=0; + oy->bodybytes=0; + return(bytes); + } + + sync_fail: + + oy->headerbytes=0; + oy->bodybytes=0; + + /* search for possible capture */ + next=memchr(page+1,'O',bytes-1); + if(!next) + next=oy->data+oy->fill; + + oy->returned=(int)(next-oy->data); + return((long)-(next-page)); +} + +/* sync the stream and get a page. Keep trying until we find a page. + Suppress 'sync errors' after reporting the first. + + return values: + -1) recapture (hole in data) + 0) need more data + 1) page returned + + Returns pointers into buffered data; invalidated by next call to + _stream, _clear, _init, or _buffer */ + +int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){ + + if(ogg_sync_check(oy))return 0; + + /* all we need to do is verify a page at the head of the stream + buffer. If it doesn't verify, we look for the next potential + frame */ + + for(;;){ + long ret=ogg_sync_pageseek(oy,og); + if(ret>0){ + /* have a page */ + return(1); + } + if(ret==0){ + /* need more data */ + return(0); + } + + /* head did not start a synced page... skipped some bytes */ + if(!oy->unsynced){ + oy->unsynced=1; + return(-1); + } + + /* loop. keep looking */ + + } +} + +/* add the incoming page to the stream state; we decompose the page + into packet segments here as well. */ + +int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){ + unsigned char *header=og->header; + unsigned char *body=og->body; + long bodysize=og->body_len; + int segptr=0; + + int version=ogg_page_version(og); + int continued=ogg_page_continued(og); + int bos=ogg_page_bos(og); + int eos=ogg_page_eos(og); + ogg_int64_t granulepos=ogg_page_granulepos(og); + int serialno=ogg_page_serialno(og); + long pageno=ogg_page_pageno(og); + int segments=header[26]; + + if(ogg_stream_check(os)) return -1; + + /* clean up 'returned data' */ + { + long lr=os->lacing_returned; + long br=os->body_returned; + + /* body data */ + if(br){ + os->body_fill-=br; + if(os->body_fill) + memmove(os->body_data,os->body_data+br,os->body_fill); + os->body_returned=0; + } + + if(lr){ + /* segment table */ + if(os->lacing_fill-lr){ + memmove(os->lacing_vals,os->lacing_vals+lr, + (os->lacing_fill-lr)*sizeof(*os->lacing_vals)); + memmove(os->granule_vals,os->granule_vals+lr, + (os->lacing_fill-lr)*sizeof(*os->granule_vals)); + } + os->lacing_fill-=lr; + os->lacing_packet-=lr; + os->lacing_returned=0; + } + } + + /* check the serial number */ + if(serialno!=os->serialno)return(-1); + if(version>0)return(-1); + + if(_os_lacing_expand(os,segments+1)) return -1; + + /* are we in sequence? */ + if(pageno!=os->pageno){ + int i; + + /* unroll previous partial packet (if any) */ + for(i=os->lacing_packet;ilacing_fill;i++) + os->body_fill-=os->lacing_vals[i]&0xff; + os->lacing_fill=os->lacing_packet; + + /* make a note of dropped data in segment table */ + if(os->pageno!=-1){ + os->lacing_vals[os->lacing_fill++]=0x400; + os->lacing_packet++; + } + } + + /* are we a 'continued packet' page? If so, we may need to skip + some segments */ + if(continued){ + if(os->lacing_fill<1 || + os->lacing_vals[os->lacing_fill-1]==0x400){ + bos=0; + for(;segptrbody_data+os->body_fill,body,bodysize); + os->body_fill+=bodysize; + } + + { + int saved=-1; + while(segptrlacing_vals[os->lacing_fill]=val; + os->granule_vals[os->lacing_fill]=-1; + + if(bos){ + os->lacing_vals[os->lacing_fill]|=0x100; + bos=0; + } + + if(val<255)saved=os->lacing_fill; + + os->lacing_fill++; + segptr++; + + if(val<255)os->lacing_packet=os->lacing_fill; + } + + /* set the granulepos on the last granuleval of the last full packet */ + if(saved!=-1){ + os->granule_vals[saved]=granulepos; + } + + } + + if(eos){ + os->e_o_s=1; + if(os->lacing_fill>0) + os->lacing_vals[os->lacing_fill-1]|=0x200; + } + + os->pageno=pageno+1; + + return(0); +} + +/* clear things to an initial state. Good to call, eg, before seeking */ +int ogg_sync_reset(ogg_sync_state *oy){ + if(ogg_sync_check(oy))return -1; + + oy->fill=0; + oy->returned=0; + oy->unsynced=0; + oy->headerbytes=0; + oy->bodybytes=0; + return(0); +} + +int ogg_stream_reset(ogg_stream_state *os){ + if(ogg_stream_check(os)) return -1; + + os->body_fill=0; + os->body_returned=0; + + os->lacing_fill=0; + os->lacing_packet=0; + os->lacing_returned=0; + + os->header_fill=0; + + os->e_o_s=0; + os->b_o_s=0; + os->pageno=-1; + os->packetno=0; + os->granulepos=0; + + return(0); +} + +int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){ + if(ogg_stream_check(os)) return -1; + ogg_stream_reset(os); + os->serialno=serialno; + return(0); +} + +static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){ + + /* The last part of decode. We have the stream broken into packet + segments. Now we need to group them into packets (or return the + out of sync markers) */ + + int ptr=os->lacing_returned; + + if(os->lacing_packet<=ptr)return(0); + + if(os->lacing_vals[ptr]&0x400){ + /* we need to tell the codec there's a gap; it might need to + handle previous packet dependencies. */ + os->lacing_returned++; + os->packetno++; + return(-1); + } + + if(!op && !adv)return(1); /* just using peek as an inexpensive way + to ask if there's a whole packet + waiting */ + + /* Gather the whole packet. We'll have no holes or a partial packet */ + { + int size=os->lacing_vals[ptr]&0xff; + long bytes=size; + int eos=os->lacing_vals[ptr]&0x200; /* last packet of the stream? */ + int bos=os->lacing_vals[ptr]&0x100; /* first packet of the stream? */ + + while(size==255){ + int val=os->lacing_vals[++ptr]; + size=val&0xff; + if(val&0x200)eos=0x200; + bytes+=size; + } + + if(op){ + op->e_o_s=eos; + op->b_o_s=bos; + op->packet=os->body_data+os->body_returned; + op->packetno=os->packetno; + op->granulepos=os->granule_vals[ptr]; + op->bytes=bytes; + } + + if(adv){ + os->body_returned+=bytes; + os->lacing_returned=ptr+1; + os->packetno++; + } + } + return(1); +} + +int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op){ + if(ogg_stream_check(os)) return 0; + return _packetout(os,op,1); +} + +int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op){ + if(ogg_stream_check(os)) return 0; + return _packetout(os,op,0); +} + +void ogg_packet_clear(ogg_packet *op) { + _ogg_free(op->packet); + memset(op, 0, sizeof(*op)); +} + +#ifdef _V_SELFTEST +#include + +ogg_stream_state os_en, os_de; +ogg_sync_state oy; + +void checkpacket(ogg_packet *op,long len, int no, long pos){ + long j; + static int sequence=0; + static int lastno=0; + + if(op->bytes!=len){ + fprintf(stderr,"incorrect packet length (%ld != %ld)!\n",op->bytes,len); + exit(1); + } + if(op->granulepos!=pos){ + fprintf(stderr,"incorrect packet granpos (%ld != %ld)!\n",(long)op->granulepos,pos); + exit(1); + } + + /* packet number just follows sequence/gap; adjust the input number + for that */ + if(no==0){ + sequence=0; + }else{ + sequence++; + if(no>lastno+1) + sequence++; + } + lastno=no; + if(op->packetno!=sequence){ + fprintf(stderr,"incorrect packet sequence %ld != %d\n", + (long)(op->packetno),sequence); + exit(1); + } + + /* Test data */ + for(j=0;jbytes;j++) + if(op->packet[j]!=((j+no)&0xff)){ + fprintf(stderr,"body data mismatch (1) at pos %ld: %x!=%lx!\n\n", + j,op->packet[j],(j+no)&0xff); + exit(1); + } +} + +void check_page(unsigned char *data,const int *header,ogg_page *og){ + long j; + /* Test data */ + for(j=0;jbody_len;j++) + if(og->body[j]!=data[j]){ + fprintf(stderr,"body data mismatch (2) at pos %ld: %x!=%x!\n\n", + j,data[j],og->body[j]); + exit(1); + } + + /* Test header */ + for(j=0;jheader_len;j++){ + if(og->header[j]!=header[j]){ + fprintf(stderr,"header content mismatch at pos %ld:\n",j); + for(j=0;jheader[j]); + fprintf(stderr,"\n"); + exit(1); + } + } + if(og->header_len!=header[26]+27){ + fprintf(stderr,"header length incorrect! (%ld!=%d)\n", + og->header_len,header[26]+27); + exit(1); + } +} + +void print_header(ogg_page *og){ + int j; + fprintf(stderr,"\nHEADER:\n"); + fprintf(stderr," capture: %c %c %c %c version: %d flags: %x\n", + og->header[0],og->header[1],og->header[2],og->header[3], + (int)og->header[4],(int)og->header[5]); + + fprintf(stderr," granulepos: %d serialno: %d pageno: %ld\n", + (og->header[9]<<24)|(og->header[8]<<16)| + (og->header[7]<<8)|og->header[6], + (og->header[17]<<24)|(og->header[16]<<16)| + (og->header[15]<<8)|og->header[14], + ((long)(og->header[21])<<24)|(og->header[20]<<16)| + (og->header[19]<<8)|og->header[18]); + + fprintf(stderr," checksum: %02x:%02x:%02x:%02x\n segments: %d (", + (int)og->header[22],(int)og->header[23], + (int)og->header[24],(int)og->header[25], + (int)og->header[26]); + + for(j=27;jheader_len;j++) + fprintf(stderr,"%d ",(int)og->header[j]); + fprintf(stderr,")\n\n"); +} + +void copy_page(ogg_page *og){ + unsigned char *temp=_ogg_malloc(og->header_len); + memcpy(temp,og->header,og->header_len); + og->header=temp; + + temp=_ogg_malloc(og->body_len); + memcpy(temp,og->body,og->body_len); + og->body=temp; +} + +void free_page(ogg_page *og){ + _ogg_free (og->header); + _ogg_free (og->body); +} + +void error(void){ + fprintf(stderr,"error!\n"); + exit(1); +} + +/* 17 only */ +const int head1_0[] = {0x4f,0x67,0x67,0x53,0,0x06, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0x15,0xed,0xec,0x91, + 1, + 17}; + +/* 17, 254, 255, 256, 500, 510, 600 byte, pad */ +const int head1_1[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0x59,0x10,0x6c,0x2c, + 1, + 17}; +const int head2_1[] = {0x4f,0x67,0x67,0x53,0,0x04, + 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x89,0x33,0x85,0xce, + 13, + 254,255,0,255,1,255,245,255,255,0, + 255,255,90}; + +/* nil packets; beginning,middle,end */ +const int head1_2[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; +const int head2_2[] = {0x4f,0x67,0x67,0x53,0,0x04, + 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x5c,0x3f,0x66,0xcb, + 17, + 17,254,255,0,0,255,1,0,255,245,255,255,0, + 255,255,90,0}; + +/* large initial packet */ +const int head1_3[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0x01,0x27,0x31,0xaa, + 18, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,10}; + +const int head2_3[] = {0x4f,0x67,0x67,0x53,0,0x04, + 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x7f,0x4e,0x8a,0xd2, + 4, + 255,4,255,0}; + + +/* continuing packet test */ +const int head1_4[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; + +const int head2_4[] = {0x4f,0x67,0x67,0x53,0,0x00, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0xf8,0x3c,0x19,0x79, + 255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255}; + +const int head3_4[] = {0x4f,0x67,0x67,0x53,0,0x05, + 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0x38,0xe6,0xb6,0x28, + 6, + 255,220,255,4,255,0}; + + +/* spill expansion test */ +const int head1_4b[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; + +const int head2_4b[] = {0x4f,0x67,0x67,0x53,0,0x00, + 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0xce,0x8f,0x17,0x1a, + 23, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,10,255,4,255,0,0}; + + +const int head3_4b[] = {0x4f,0x67,0x67,0x53,0,0x04, + 0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0x9b,0xb2,0x50,0xa1, + 1, + 0}; + +/* page with the 255 segment limit */ +const int head1_5[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; + +const int head2_5[] = {0x4f,0x67,0x67,0x53,0,0x00, + 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0xed,0x2a,0x2e,0xa7, + 255, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10}; + +const int head3_5[] = {0x4f,0x67,0x67,0x53,0,0x04, + 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0x6c,0x3b,0x82,0x3d, + 1, + 50}; + + +/* packet that overspans over an entire page */ +const int head1_6[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; + +const int head2_6[] = {0x4f,0x67,0x67,0x53,0,0x00, + 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x68,0x22,0x7c,0x3d, + 255, + 100, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255}; + +const int head3_6[] = {0x4f,0x67,0x67,0x53,0,0x01, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0xf4,0x87,0xba,0xf3, + 255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255}; + +const int head4_6[] = {0x4f,0x67,0x67,0x53,0,0x05, + 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,3,0,0,0, + 0xf7,0x2f,0x6c,0x60, + 5, + 254,255,4,255,0}; + +/* packet that overspans over an entire page */ +const int head1_7[] = {0x4f,0x67,0x67,0x53,0,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0,0,0,0, + 0xff,0x7b,0x23,0x17, + 1, + 0}; + +const int head2_7[] = {0x4f,0x67,0x67,0x53,0,0x00, + 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,1,0,0,0, + 0x68,0x22,0x7c,0x3d, + 255, + 100, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255, + 255,255,255,255,255,255}; + +const int head3_7[] = {0x4f,0x67,0x67,0x53,0,0x05, + 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,2,0,0,0, + 0xd4,0xe0,0x60,0xe5, + 1, + 0}; + +void test_pack(const int *pl, const int **headers, int byteskip, + int pageskip, int packetskip){ + unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */ + long inptr=0; + long outptr=0; + long deptr=0; + long depacket=0; + long granule_pos=7,pageno=0; + int i,j,packets,pageout=pageskip; + int eosflag=0; + int bosflag=0; + + int byteskipcount=0; + + ogg_stream_reset(&os_en); + ogg_stream_reset(&os_de); + ogg_sync_reset(&oy); + + for(packets=0;packetsbyteskip){ + memcpy(next,og.header,byteskipcount-byteskip); + next+=byteskipcount-byteskip; + byteskipcount=byteskip; + } + + byteskipcount+=og.body_len; + if(byteskipcount>byteskip){ + memcpy(next,og.body,byteskipcount-byteskip); + next+=byteskipcount-byteskip; + byteskipcount=byteskip; + } + + ogg_sync_wrote(&oy,next-buf); + + while(1){ + int ret=ogg_sync_pageout(&oy,&og_de); + if(ret==0)break; + if(ret<0)continue; + /* got a page. Happy happy. Verify that it's good. */ + + fprintf(stderr,"(%d), ",pageout); + + check_page(data+deptr,headers[pageout],&og_de); + deptr+=og_de.body_len; + pageout++; + + /* submit it to deconstitution */ + ogg_stream_pagein(&os_de,&og_de); + + /* packets out? */ + while(ogg_stream_packetpeek(&os_de,&op_de2)>0){ + ogg_stream_packetpeek(&os_de,NULL); + ogg_stream_packetout(&os_de,&op_de); /* just catching them all */ + + /* verify peek and out match */ + if(memcmp(&op_de,&op_de2,sizeof(op_de))){ + fprintf(stderr,"packetout != packetpeek! pos=%ld\n", + depacket); + exit(1); + } + + /* verify the packet! */ + /* check data */ + if(memcmp(data+depacket,op_de.packet,op_de.bytes)){ + fprintf(stderr,"packet data mismatch in decode! pos=%ld\n", + depacket); + exit(1); + } + /* check bos flag */ + if(bosflag==0 && op_de.b_o_s==0){ + fprintf(stderr,"b_o_s flag not set on packet!\n"); + exit(1); + } + if(bosflag && op_de.b_o_s){ + fprintf(stderr,"b_o_s flag incorrectly set on packet!\n"); + exit(1); + } + bosflag=1; + depacket+=op_de.bytes; + + /* check eos flag */ + if(eosflag){ + fprintf(stderr,"Multiple decoded packets with eos flag!\n"); + exit(1); + } + + if(op_de.e_o_s)eosflag=1; + + /* check granulepos flag */ + if(op_de.granulepos!=-1){ + fprintf(stderr," granule:%ld ",(long)op_de.granulepos); + } + } + } + } + } + } + } + _ogg_free(data); + if(headers[pageno]!=NULL){ + fprintf(stderr,"did not write last page!\n"); + exit(1); + } + if(headers[pageout]!=NULL){ + fprintf(stderr,"did not decode last page!\n"); + exit(1); + } + if(inptr!=outptr){ + fprintf(stderr,"encoded page data incomplete!\n"); + exit(1); + } + if(inptr!=deptr){ + fprintf(stderr,"decoded page data incomplete!\n"); + exit(1); + } + if(inptr!=depacket){ + fprintf(stderr,"decoded packet data incomplete!\n"); + exit(1); + } + if(!eosflag){ + fprintf(stderr,"Never got a packet with EOS set!\n"); + exit(1); + } + fprintf(stderr,"ok.\n"); +} + +int main(void){ + + ogg_stream_init(&os_en,0x04030201); + ogg_stream_init(&os_de,0x04030201); + ogg_sync_init(&oy); + + /* Exercise each code path in the framing code. Also verify that + the checksums are working. */ + + { + /* 17 only */ + const int packets[]={17, -1}; + const int *headret[]={head1_0,NULL}; + + fprintf(stderr,"testing single page encoding... "); + test_pack(packets,headret,0,0,0); + } + + { + /* 17, 254, 255, 256, 500, 510, 600 byte, pad */ + const int packets[]={17, 254, 255, 256, 500, 510, 600, -1}; + const int *headret[]={head1_1,head2_1,NULL}; + + fprintf(stderr,"testing basic page encoding... "); + test_pack(packets,headret,0,0,0); + } + + { + /* nil packets; beginning,middle,end */ + const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1}; + const int *headret[]={head1_2,head2_2,NULL}; + + fprintf(stderr,"testing basic nil packets... "); + test_pack(packets,headret,0,0,0); + } + + { + /* large initial packet */ + const int packets[]={4345,259,255,-1}; + const int *headret[]={head1_3,head2_3,NULL}; + + fprintf(stderr,"testing initial-packet lacing > 4k... "); + test_pack(packets,headret,0,0,0); + } + + { + /* continuing packet test; with page spill expansion, we have to + overflow the lacing table. */ + const int packets[]={0,65500,259,255,-1}; + const int *headret[]={head1_4,head2_4,head3_4,NULL}; + + fprintf(stderr,"testing single packet page span... "); + test_pack(packets,headret,0,0,0); + } + + { + /* spill expand packet test */ + const int packets[]={0,4345,259,255,0,0,-1}; + const int *headret[]={head1_4b,head2_4b,head3_4b,NULL}; + + fprintf(stderr,"testing page spill expansion... "); + test_pack(packets,headret,0,0,0); + } + + /* page with the 255 segment limit */ + { + + const int packets[]={0,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,50,-1}; + const int *headret[]={head1_5,head2_5,head3_5,NULL}; + + fprintf(stderr,"testing max packet segments... "); + test_pack(packets,headret,0,0,0); + } + + { + /* packet that overspans over an entire page */ + const int packets[]={0,100,130049,259,255,-1}; + const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL}; + + fprintf(stderr,"testing very large packets... "); + test_pack(packets,headret,0,0,0); + } + + { + /* test for the libogg 1.1.1 resync in large continuation bug + found by Josh Coalson) */ + const int packets[]={0,100,130049,259,255,-1}; + const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL}; + + fprintf(stderr,"testing continuation resync in very large packets... "); + test_pack(packets,headret,100,2,3); + } + + { + /* term only page. why not? */ + const int packets[]={0,100,64770,-1}; + const int *headret[]={head1_7,head2_7,head3_7,NULL}; + + fprintf(stderr,"testing zero data page (1 nil packet)... "); + test_pack(packets,headret,0,0,0); + } + + + + { + /* build a bunch of pages for testing */ + unsigned char *data=_ogg_malloc(1024*1024); + int pl[]={0, 1,1,98,4079, 1,1,2954,2057, 76,34,912,0,234,1000,1000, 1000,300,-1}; + int inptr=0,i,j; + ogg_page og[5]; + + ogg_stream_reset(&os_en); + + for(i=0;pl[i]!=-1;i++){ + ogg_packet op; + int len=pl[i]; + + op.packet=data+inptr; + op.bytes=len; + op.e_o_s=(pl[i+1]<0?1:0); + op.granulepos=(i+1)*1000; + + for(j=0;j0)error(); + + /* Test fractional page inputs: incomplete fixed header */ + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3, + 20); + ogg_sync_wrote(&oy,20); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + /* Test fractional page inputs: incomplete header */ + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23, + 5); + ogg_sync_wrote(&oy,5); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + /* Test fractional page inputs: incomplete body */ + + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28, + og[1].header_len-28); + ogg_sync_wrote(&oy,og[1].header_len-28); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000); + ogg_sync_wrote(&oy,1000); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000, + og[1].body_len-1000); + ogg_sync_wrote(&oy,og[1].body_len-1000); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + + fprintf(stderr,"ok.\n"); + } + + /* Test fractional page inputs: page + incomplete capture */ + { + ogg_page og_de; + fprintf(stderr,"Testing sync on 1+partial inputs... "); + ogg_sync_reset(&oy); + + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + og[1].header_len); + ogg_sync_wrote(&oy,og[1].header_len); + + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); + + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + 20); + ogg_sync_wrote(&oy,20); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20, + og[1].header_len-20); + ogg_sync_wrote(&oy,og[1].header_len-20); + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + + fprintf(stderr,"ok.\n"); + } + + /* Test recapture: garbage + page */ + { + ogg_page og_de; + fprintf(stderr,"Testing search for capture... "); + ogg_sync_reset(&oy); + + /* 'garbage' */ + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); + + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + og[1].header_len); + ogg_sync_wrote(&oy,og[1].header_len); + + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); + + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, + 20); + ogg_sync_wrote(&oy,20); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20, + og[2].header_len-20); + ogg_sync_wrote(&oy,og[2].header_len-20); + memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body, + og[2].body_len); + ogg_sync_wrote(&oy,og[2].body_len); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + + fprintf(stderr,"ok.\n"); + } + + /* Test recapture: page + garbage + page */ + { + ogg_page og_de; + fprintf(stderr,"Testing recapture... "); + ogg_sync_reset(&oy); + + memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header, + og[1].header_len); + ogg_sync_wrote(&oy,og[1].header_len); + + memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body, + og[1].body_len); + ogg_sync_wrote(&oy,og[1].body_len); + + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, + og[2].header_len); + ogg_sync_wrote(&oy,og[2].header_len); + + memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header, + og[2].header_len); + ogg_sync_wrote(&oy,og[2].header_len); + + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + + memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body, + og[2].body_len-5); + ogg_sync_wrote(&oy,og[2].body_len-5); + + memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header, + og[3].header_len); + ogg_sync_wrote(&oy,og[3].header_len); + + memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body, + og[3].body_len); + ogg_sync_wrote(&oy,og[3].body_len); + + if(ogg_sync_pageout(&oy,&og_de)>0)error(); + if(ogg_sync_pageout(&oy,&og_de)<=0)error(); + + fprintf(stderr,"ok.\n"); + } + + /* Free page data that was previously copied */ + { + for(i=0;i<5;i++){ + free_page(&og[i]); + } + } + } + + return(0); +} + +#endif diff --git a/TelegramClient.Opus/opus/ogg/ogg.h b/TelegramClient.Opus/opus/ogg/ogg.h new file mode 100755 index 0000000..000258b --- /dev/null +++ b/TelegramClient.Opus/opus/ogg/ogg.h @@ -0,0 +1,210 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: toplevel libogg include + last mod: $Id: ogg.h 18044 2011-08-01 17:55:20Z gmaxwell $ + + ********************************************************************/ +#ifndef _OGG_H +#define _OGG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +typedef struct { + void *iov_base; + size_t iov_len; +} ogg_iovec_t; + +typedef struct { + long endbyte; + int endbit; + + unsigned char *buffer; + unsigned char *ptr; + long storage; +} oggpack_buffer; + +/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/ + +typedef struct { + unsigned char *header; + long header_len; + unsigned char *body; + long body_len; +} ogg_page; + +/* ogg_stream_state contains the current encode/decode state of a logical + Ogg bitstream **********************************************************/ + +typedef struct { + unsigned char *body_data; /* bytes from packet bodies */ + long body_storage; /* storage elements allocated */ + long body_fill; /* elements stored; fill mark */ + long body_returned; /* elements of fill returned */ + + + int *lacing_vals; /* The values that will go to the segment table */ + ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact + this way, but it is simple coupled to the + lacing fifo */ + long lacing_storage; + long lacing_fill; + long lacing_packet; + long lacing_returned; + + unsigned char header[282]; /* working space for header encode */ + int header_fill; + + int e_o_s; /* set when we have buffered the last packet in the + logical bitstream */ + int b_o_s; /* set after we've written the initial page + of a logical bitstream */ + long serialno; + long pageno; + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a separate abstraction + layer) also knows about the gap */ + ogg_int64_t granulepos; + +} ogg_stream_state; + +/* ogg_packet is used to encapsulate the data and metadata belonging + to a single raw Ogg/Vorbis packet *************************************/ + +typedef struct { + unsigned char *packet; + long bytes; + long b_o_s; + long e_o_s; + + ogg_int64_t granulepos; + + ogg_int64_t packetno; /* sequence number for decode; the framing + knows where there's a hole in the data, + but we need coupling so that the codec + (which is in a separate abstraction + layer) also knows about the gap */ +} ogg_packet; + +typedef struct { + unsigned char *data; + int storage; + int fill; + int returned; + + int unsynced; + int headerbytes; + int bodybytes; +} ogg_sync_state; + +/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ + +extern void oggpack_writeinit(oggpack_buffer *b); +extern int oggpack_writecheck(oggpack_buffer *b); +extern void oggpack_writetrunc(oggpack_buffer *b,long bits); +extern void oggpack_writealign(oggpack_buffer *b); +extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits); +extern void oggpack_reset(oggpack_buffer *b); +extern void oggpack_writeclear(oggpack_buffer *b); +extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); +extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits); +extern long oggpack_look(oggpack_buffer *b,int bits); +extern long oggpack_look1(oggpack_buffer *b); +extern void oggpack_adv(oggpack_buffer *b,int bits); +extern void oggpack_adv1(oggpack_buffer *b); +extern long oggpack_read(oggpack_buffer *b,int bits); +extern long oggpack_read1(oggpack_buffer *b); +extern long oggpack_bytes(oggpack_buffer *b); +extern long oggpack_bits(oggpack_buffer *b); +extern unsigned char *oggpack_get_buffer(oggpack_buffer *b); + +extern void oggpackB_writeinit(oggpack_buffer *b); +extern int oggpackB_writecheck(oggpack_buffer *b); +extern void oggpackB_writetrunc(oggpack_buffer *b,long bits); +extern void oggpackB_writealign(oggpack_buffer *b); +extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits); +extern void oggpackB_reset(oggpack_buffer *b); +extern void oggpackB_writeclear(oggpack_buffer *b); +extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); +extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits); +extern long oggpackB_look(oggpack_buffer *b,int bits); +extern long oggpackB_look1(oggpack_buffer *b); +extern void oggpackB_adv(oggpack_buffer *b,int bits); +extern void oggpackB_adv1(oggpack_buffer *b); +extern long oggpackB_read(oggpack_buffer *b,int bits); +extern long oggpackB_read1(oggpack_buffer *b); +extern long oggpackB_bytes(oggpack_buffer *b); +extern long oggpackB_bits(oggpack_buffer *b); +extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b); + +/* Ogg BITSTREAM PRIMITIVES: encoding **************************/ + +extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op); +extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, + int count, long e_o_s, ogg_int64_t granulepos); +extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill); +extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_flush_fill(ogg_stream_state *os, ogg_page *og, int nfill); + +/* Ogg BITSTREAM PRIMITIVES: decoding **************************/ + +extern int ogg_sync_init(ogg_sync_state *oy); +extern int ogg_sync_clear(ogg_sync_state *oy); +extern int ogg_sync_reset(ogg_sync_state *oy); +extern int ogg_sync_destroy(ogg_sync_state *oy); +extern int ogg_sync_check(ogg_sync_state *oy); + +extern char *ogg_sync_buffer(ogg_sync_state *oy, long size); +extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); +extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); +extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og); +extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); +extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); +extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); + +/* Ogg BITSTREAM PRIMITIVES: general ***************************/ + +extern int ogg_stream_init(ogg_stream_state *os,int serialno); +extern int ogg_stream_clear(ogg_stream_state *os); +extern int ogg_stream_reset(ogg_stream_state *os); +extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); +extern int ogg_stream_destroy(ogg_stream_state *os); +extern int ogg_stream_check(ogg_stream_state *os); +extern int ogg_stream_eos(ogg_stream_state *os); + +extern void ogg_page_checksum_set(ogg_page *og); + +extern int ogg_page_version(const ogg_page *og); +extern int ogg_page_continued(const ogg_page *og); +extern int ogg_page_bos(const ogg_page *og); +extern int ogg_page_eos(const ogg_page *og); +extern ogg_int64_t ogg_page_granulepos(const ogg_page *og); +extern int ogg_page_serialno(const ogg_page *og); +extern long ogg_page_pageno(const ogg_page *og); +extern int ogg_page_packets(const ogg_page *og); + +extern void ogg_packet_clear(ogg_packet *op); + + +#ifdef __cplusplus +} +#endif + +#endif /* _OGG_H */ diff --git a/TelegramClient.Opus/opus/ogg/os_types.h b/TelegramClient.Opus/opus/ogg/os_types.h new file mode 100755 index 0000000..d6691b7 --- /dev/null +++ b/TelegramClient.Opus/opus/ogg/os_types.h @@ -0,0 +1,147 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: #ifdef jail to whip a few platforms into the UNIX ideal. + last mod: $Id: os_types.h 17712 2010-12-03 17:10:02Z xiphmont $ + + ********************************************************************/ +#ifndef _OS_TYPES_H +#define _OS_TYPES_H + +/* make it easy on the folks that want to compile the libs with a + different malloc than stdlib */ +#define _ogg_malloc malloc +#define _ogg_calloc calloc +#define _ogg_realloc realloc +#define _ogg_free free + +#if defined(_WIN32) + +# if defined(__CYGWIN__) +# include + typedef int16_t ogg_int16_t; + typedef uint16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef uint32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + typedef uint64_t ogg_uint64_t; +# elif defined(__MINGW32__) +# include + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + typedef unsigned long long ogg_uint64_t; +# elif defined(__MWERKS__) + typedef long long ogg_int64_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; +# else + /* MSVC/Borland */ + typedef __int64 ogg_int64_t; + typedef __int32 ogg_int32_t; + typedef unsigned __int32 ogg_uint32_t; + typedef __int16 ogg_int16_t; + typedef unsigned __int16 ogg_uint16_t; +# endif + +#elif defined(__MACOS__) + +# include + typedef SInt16 ogg_int16_t; + typedef UInt16 ogg_uint16_t; + typedef SInt32 ogg_int32_t; + typedef UInt32 ogg_uint32_t; + typedef SInt64 ogg_int64_t; + +#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ + +# include + typedef int16_t ogg_int16_t; + typedef uint16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef uint32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + +#elif defined(__HAIKU__) + + /* Haiku */ +# include + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined(__BEOS__) + + /* Be */ +# include + typedef int16_t ogg_int16_t; + typedef uint16_t ogg_uint16_t; + typedef int32_t ogg_int32_t; + typedef uint32_t ogg_uint32_t; + typedef int64_t ogg_int64_t; + +#elif defined (__EMX__) + + /* OS/2 GCC */ + typedef short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined (DJGPP) + + /* DJGPP */ + typedef short ogg_int16_t; + typedef int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long ogg_int64_t; + +#elif defined(R5900) + + /* PS2 EE */ + typedef long ogg_int64_t; + typedef int ogg_int32_t; + typedef unsigned ogg_uint32_t; + typedef short ogg_int16_t; + +#elif defined(__SYMBIAN32__) + + /* Symbian GCC */ + typedef signed short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef signed int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long int ogg_int64_t; + +#elif defined(__TMS320C6X__) + + /* TI C64x compiler */ + typedef signed short ogg_int16_t; + typedef unsigned short ogg_uint16_t; + typedef signed int ogg_int32_t; + typedef unsigned int ogg_uint32_t; + typedef long long int ogg_int64_t; + +#else + +# include + +#endif + +#endif /* _OS_TYPES_H */ diff --git a/TelegramClient.Opus/opus/opusfile/info.c b/TelegramClient.Opus/opus/opusfile/info.c new file mode 100755 index 0000000..6cf9851 --- /dev/null +++ b/TelegramClient.Opus/opus/opusfile/info.c @@ -0,0 +1,683 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ********************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "internal.h" +#include +#include + +static unsigned op_parse_uint16le(const unsigned char *_data){ + return _data[0]|_data[1]<<8; +} + +static int op_parse_int16le(const unsigned char *_data){ + int ret; + ret=_data[0]|_data[1]<<8; + return (ret^0x8000)-0x8000; +} + +static opus_uint32 op_parse_uint32le(const unsigned char *_data){ + return _data[0]|_data[1]<<8|_data[2]<<16|_data[3]<<24; +} + +static opus_uint32 op_parse_uint32be(const unsigned char *_data){ + return _data[3]|_data[2]<<8|_data[1]<<16|_data[0]<<24; +} + +int opus_head_parse(OpusHead *_head,const unsigned char *_data,size_t _len){ + OpusHead head; + if(_len<8)return OP_ENOTFORMAT; + if(memcmp(_data,"OpusHead",8)!=0)return OP_ENOTFORMAT; + if(_len<9)return OP_EBADHEADER; + head.version=_data[8]; + if(head.version>15)return OP_EVERSION; + if(_len<19)return OP_EBADHEADER; + head.channel_count=_data[9]; + head.pre_skip=op_parse_uint16le(_data+10); + head.input_sample_rate=op_parse_uint32le(_data+12); + head.output_gain=op_parse_int16le(_data+16); + head.mapping_family=_data[18]; + if(head.mapping_family==0){ + if(head.channel_count<1||head.channel_count>2)return OP_EBADHEADER; + if(head.version<=1&&_len>19)return OP_EBADHEADER; + head.stream_count=1; + head.coupled_count=head.channel_count-1; + if(_head!=NULL){ + _head->mapping[0]=0; + _head->mapping[1]=1; + } + } + else if(head.mapping_family==1){ + size_t size; + int ci; + if(head.channel_count<1||head.channel_count>8)return OP_EBADHEADER; + size=21+head.channel_count; + if(_lensize)return OP_EBADHEADER; + head.stream_count=_data[19]; + if(head.stream_count<1)return OP_EBADHEADER; + head.coupled_count=_data[20]; + if(head.coupled_count>head.stream_count)return OP_EBADHEADER; + for(ci=0;ci=head.stream_count+head.coupled_count + &&_data[21+ci]!=255){ + return OP_EBADHEADER; + } + } + if(_head!=NULL)memcpy(_head->mapping,_data+21,head.channel_count); + } + /*General purpose players should not attempt to play back content with + channel mapping family 255.*/ + else if(head.mapping_family==255)return OP_EIMPL; + /*No other channel mapping families are currently defined.*/ + else return OP_EBADHEADER; + if(_head!=NULL)memcpy(_head,&head,head.mapping-(unsigned char *)&head); + return 0; +} + +void opus_tags_init(OpusTags *_tags){ + memset(_tags,0,sizeof(*_tags)); +} + +void opus_tags_clear(OpusTags *_tags){ + int ci; + for(ci=_tags->comments;ci-->0;)_ogg_free(_tags->user_comments[ci]); + _ogg_free(_tags->user_comments); + _ogg_free(_tags->comment_lengths); + _ogg_free(_tags->vendor); +} + +/*Ensure there's room for up to _ncomments comments.*/ +static int op_tags_ensure_capacity(OpusTags *_tags,size_t _ncomments){ + char **user_comments; + int *comment_lengths; + size_t size; + if(OP_UNLIKELY(_ncomments>=(size_t)INT_MAX))return OP_EFAULT; + size=sizeof(*_tags->comment_lengths)*(_ncomments+1); + if(size/sizeof(*_tags->comment_lengths)!=_ncomments+1)return OP_EFAULT; + comment_lengths=(int *)_ogg_realloc(_tags->comment_lengths,size); + if(OP_UNLIKELY(comment_lengths==NULL))return OP_EFAULT; + comment_lengths[_ncomments]=0; + _tags->comment_lengths=comment_lengths; + size=sizeof(*_tags->user_comments)*(_ncomments+1); + if(size/sizeof(*_tags->user_comments)!=_ncomments+1)return OP_EFAULT; + user_comments=(char **)_ogg_realloc(_tags->user_comments,size); + if(OP_UNLIKELY(user_comments==NULL))return OP_EFAULT; + user_comments[_ncomments]=NULL; + _tags->user_comments=user_comments; + return 0; +} + +/*Duplicate a (possibly non-NUL terminated) string with a known length.*/ +static char *op_strdup_with_len(const char *_s,size_t _len){ + size_t size; + char *ret; + size=sizeof(*ret)*(_len+1); + if(OP_UNLIKELY(size<_len))return NULL; + ret=(char *)_ogg_malloc(size); + if(OP_LIKELY(ret!=NULL)){ + ret=(char *)memcpy(ret,_s,sizeof(*ret)*_len); + ret[_len]='\0'; + } + return ret; +} + +/*The actual implementation of opus_tags_parse(). + Unlike the public API, this function requires _tags to already be + initialized, modifies its contents before success is guaranteed, and assumes + the caller will clear it on error.*/ +static int opus_tags_parse_impl(OpusTags *_tags, + const unsigned char *_data,size_t _len){ + opus_uint32 count; + size_t len; + int ncomments; + int ci; + len=_len; + if(len<8)return OP_ENOTFORMAT; + if(memcmp(_data,"OpusTags",8)!=0)return OP_ENOTFORMAT; + if(len<16)return OP_EBADHEADER; + _data+=8; + len-=8; + count=op_parse_uint32le(_data); + _data+=4; + len-=4; + if(count>len)return OP_EBADHEADER; + if(_tags!=NULL){ + _tags->vendor=op_strdup_with_len((char *)_data,count); + if(_tags->vendor==NULL)return OP_EFAULT; + } + _data+=count; + len-=count; + if(len<4)return OP_EBADHEADER; + count=op_parse_uint32le(_data); + _data+=4; + len-=4; + /*Check to make sure there's minimally sufficient data left in the packet.*/ + if(count>len>>2)return OP_EBADHEADER; + /*Check for overflow (the API limits this to an int).*/ + if(count>(opus_uint32)INT_MAX-1)return OP_EFAULT; + if(_tags!=NULL){ + int ret; + ret=op_tags_ensure_capacity(_tags,count); + if(ret<0)return ret; + } + ncomments=(int)count; + for(ci=0;cilen>>2)return OP_EBADHEADER; + count=op_parse_uint32le(_data); + _data+=4; + len-=4; + if(count>len)return OP_EBADHEADER; + /*Check for overflow (the API limits this to an int).*/ + if(count>(opus_uint32)INT_MAX)return OP_EFAULT; + if(_tags!=NULL){ + _tags->user_comments[ci]=op_strdup_with_len((char *)_data,count); + if(_tags->user_comments[ci]==NULL)return OP_EFAULT; + _tags->comment_lengths[ci]=(int)count; + _tags->comments=ci+1; + } + _data+=count; + len-=count; + } + return 0; +} + +int opus_tags_parse(OpusTags *_tags,const unsigned char *_data,size_t _len){ + if(_tags!=NULL){ + OpusTags tags; + int ret; + opus_tags_init(&tags); + ret=opus_tags_parse_impl(&tags,_data,_len); + if(ret<0)opus_tags_clear(&tags); + else *_tags=*&tags; + return ret; + } + else return opus_tags_parse_impl(NULL,_data,_len); +} + +/*The actual implementation of opus_tags_copy(). + Unlike the public API, this function requires _dst to already be + initialized, modifies its contents before success is guaranteed, and assumes + the caller will clear it on error.*/ +static int opus_tags_copy_impl(OpusTags *_dst,const OpusTags *_src){ + char *vendor; + int ncomments; + int ret; + int ci; + vendor=_src->vendor; + _dst->vendor=op_strdup_with_len(vendor,strlen(vendor)); + if(OP_UNLIKELY(_dst->vendor==NULL))return OP_EFAULT; + ncomments=_src->comments; + ret=op_tags_ensure_capacity(_dst,ncomments); + if(OP_UNLIKELY(ret<0))return ret; + for(ci=0;cicomment_lengths[ci]; + OP_ASSERT(len>=0); + _dst->user_comments[ci]=op_strdup_with_len(_src->user_comments[ci],len); + if(OP_UNLIKELY(_dst->user_comments[ci]==NULL))return OP_EFAULT; + _dst->comment_lengths[ci]=len; + _dst->comments=ci+1; + } + return 0; +} + +int opus_tags_copy(OpusTags *_dst,const OpusTags *_src){ + OpusTags dst; + int ret; + opus_tags_init(&dst); + ret=opus_tags_copy_impl(&dst,_src); + if(OP_UNLIKELY(ret<0))opus_tags_clear(&dst); + else *_dst=*&dst; + return 0; +} + +int opus_tags_add(OpusTags *_tags,const char *_tag,const char *_value){ + char *comment; + int tag_len; + int value_len; + int ncomments; + int ret; + ncomments=_tags->comments; + ret=op_tags_ensure_capacity(_tags,ncomments+1); + if(OP_UNLIKELY(ret<0))return ret; + tag_len=strlen(_tag); + value_len=strlen(_value); + /*+2 for '=' and '\0'.*/ + _tags->comment_lengths[ncomments]=0; + _tags->user_comments[ncomments]=comment= + (char *)_ogg_malloc(sizeof(*comment)*(tag_len+value_len+2)); + if(OP_UNLIKELY(comment==NULL))return OP_EFAULT; + _tags->comment_lengths[ncomments]=tag_len+value_len+1; + memcpy(comment,_tag,sizeof(*comment)*tag_len); + comment[tag_len]='='; + memcpy(comment+tag_len+1,_value,sizeof(*comment)*(value_len+1)); + return 0; +} + +int opus_tags_add_comment(OpusTags *_tags,const char *_comment){ + int comment_len; + int ncomments; + int ret; + ncomments=_tags->comments; + ret=op_tags_ensure_capacity(_tags,ncomments+1); + if(OP_UNLIKELY(ret<0))return ret; + comment_len=(int)strlen(_comment); + _tags->comment_lengths[ncomments]=0; + _tags->user_comments[ncomments]=op_strdup_with_len(_comment,comment_len); + if(OP_UNLIKELY(_tags->user_comments[ncomments]==NULL))return OP_EFAULT; + _tags->comment_lengths[ncomments]=comment_len; + return 0; +} + +int opus_tagcompare(const char *_tag_name,const char *_comment){ + return opus_tagncompare(_tag_name,strlen(_tag_name),_comment); +} + +int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment){ + int ret; + OP_ASSERT(_tag_len>=0); + ret=op_strncasecmp(_tag_name,_comment,_tag_len); + return ret?ret:'='-_comment[_tag_len]; +} + +const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count){ + char **user_comments; + int tag_len; + int found; + int ncomments; + int ci; + tag_len=strlen(_tag); + ncomments=_tags->comments; + user_comments=_tags->user_comments; + found=0; + for(ci=0;cicomments; + user_comments=_tags->user_comments; + found=0; + for(ci=0;ciuser_comments; + ncomments=_tags->comments; + /*Look for the first valid R128_TRACK_GAIN tag and use that.*/ + for(ci=0;ci='0'&&*p<='9'){ + gain_q8=10*gain_q8+*p-'0'; + if(gain_q8>32767-negative)break; + p++; + } + /*This didn't look like a signed 16-bit decimal integer. + Not a valid R128_TRACK_GAIN tag.*/ + if(*p!='\0')continue; + *_gain_q8=(int)(gain_q8+negative^negative); + return 0; + } + } + return OP_FALSE; +} + +static int op_is_jpeg(const unsigned char *_buf,size_t _buf_sz){ + return _buf_sz>=11&&memcmp(_buf,"\xFF\xD8\xFF\xE0",4)==0 + &&(_buf[4]<<8|_buf[5])>=16&&memcmp(_buf+6,"JFIF",5)==0; +} + +/*Tries to extract the width, height, bits per pixel, and palette size of a + JPEG. + On failure, simply leaves its outputs unmodified.*/ +static void op_extract_jpeg_params(const unsigned char *_buf,size_t _buf_sz, + opus_uint32 *_width,opus_uint32 *_height, + opus_uint32 *_depth,opus_uint32 *_colors,int *_has_palette){ + if(op_is_jpeg(_buf,_buf_sz)){ + size_t offs; + offs=2; + for(;;){ + size_t segment_len; + int marker; + while(offs<_buf_sz&&_buf[offs]!=0xFF)offs++; + while(offs<_buf_sz&&_buf[offs]==0xFF)offs++; + marker=_buf[offs]; + offs++; + /*If we hit EOI* (end of image), or another SOI* (start of image), + or SOS (start of scan), then stop now.*/ + if(offs>=_buf_sz||(marker>=0xD8&&marker<=0xDA))break; + /*RST* (restart markers): skip (no segment length).*/ + else if(marker>=0xD0&&marker<=0xD7)continue; + /*Read the length of the marker segment.*/ + if(_buf_sz-offs<2)break; + segment_len=_buf[offs]<<8|_buf[offs+1]; + if(segment_len<2||_buf_sz-offs0xC0&&marker<0xD0&&(marker&3)!=0)){ + /*Found a SOFn (start of frame) marker segment:*/ + if(segment_len>=8){ + *_height=_buf[offs+3]<<8|_buf[offs+4]; + *_width=_buf[offs+5]<<8|_buf[offs+6]; + *_depth=_buf[offs+2]*_buf[offs+7]; + *_colors=0; + *_has_palette=0; + } + break; + } + /*Other markers: skip the whole marker segment.*/ + offs+=segment_len; + } + } +} + +static int op_is_png(const unsigned char *_buf,size_t _buf_sz){ + return _buf_sz>=8&&memcmp(_buf,"\x89PNG\x0D\x0A\x1A\x0A",8)==0; +} + +/*Tries to extract the width, height, bits per pixel, and palette size of a + PNG. + On failure, simply leaves its outputs unmodified.*/ +static void op_extract_png_params(const unsigned char *_buf,size_t _buf_sz, + opus_uint32 *_width,opus_uint32 *_height, + opus_uint32 *_depth,opus_uint32 *_colors,int *_has_palette){ + if(op_is_png(_buf,_buf_sz)){ + size_t offs; + offs=8; + while(_buf_sz-offs>=12){ + ogg_uint32_t chunk_len; + chunk_len=op_parse_uint32be(_buf+offs); + if(chunk_len>_buf_sz-(offs+12))break; + else if(chunk_len==13&&memcmp(_buf+offs+4,"IHDR",4)==0){ + int color_type; + *_width=op_parse_uint32be(_buf+offs+8); + *_height=op_parse_uint32be(_buf+offs+12); + color_type=_buf[offs+17]; + if(color_type==3){ + *_depth=24; + *_has_palette=1; + } + else{ + int sample_depth; + sample_depth=_buf[offs+16]; + if(color_type==0)*_depth=sample_depth; + else if(color_type==2)*_depth=sample_depth*3; + else if(color_type==4)*_depth=sample_depth*2; + else if(color_type==6)*_depth=sample_depth*4; + *_colors=0; + *_has_palette=0; + break; + } + } + else if(*_has_palette>0&&memcmp(_buf+offs+4,"PLTE",4)==0){ + *_colors=chunk_len/3; + break; + } + offs+=12+chunk_len; + } + } +} + +static int op_is_gif(const unsigned char *_buf,size_t _buf_sz){ + return _buf_sz>=6&&(memcmp(_buf,"GIF87a",6)==0||memcmp(_buf,"GIF89a",6)==0); +} + +/*Tries to extract the width, height, bits per pixel, and palette size of a + GIF. + On failure, simply leaves its outputs unmodified.*/ +static void op_extract_gif_params(const unsigned char *_buf,size_t _buf_sz, + opus_uint32 *_width,opus_uint32 *_height, + opus_uint32 *_depth,opus_uint32 *_colors,int *_has_palette){ + if(op_is_gif(_buf,_buf_sz)&&_buf_sz>=14){ + *_width=_buf[6]|_buf[7]<<8; + *_height=_buf[8]|_buf[9]<<8; + /*libFLAC hard-codes the depth to 24.*/ + *_depth=24; + *_colors=1<<((_buf[10]&7)+1); + *_has_palette=1; + } +} + +/*The actual implementation of opus_picture_tag_parse(). + Unlike the public API, this function requires _pic to already be + initialized, modifies its contents before success is guaranteed, and assumes + the caller will clear it on error.*/ +static int opus_picture_tag_parse_impl(OpusPictureTag *_pic,const char *_tag, + unsigned char *_buf,size_t _buf_sz,size_t _base64_sz){ + opus_int32 picture_type; + opus_uint32 mime_type_length; + char *mime_type; + opus_uint32 description_length; + char *description; + opus_uint32 width; + opus_uint32 height; + opus_uint32 depth; + opus_uint32 colors; + opus_uint32 data_length; + opus_uint32 file_width; + opus_uint32 file_height; + opus_uint32 file_depth; + opus_uint32 file_colors; + int format; + int has_palette; + int colors_set; + size_t i; + /*Decode the BASE64 data.*/ + for(i=0;i<_base64_sz;i++){ + opus_uint32 value; + int j; + value=0; + for(j=0;j<4;j++){ + unsigned c; + unsigned d; + c=(unsigned char)_tag[4*i+j]; + if(c=='+')d=62; + else if(c=='/')d=63; + else if(c>='0'&&c<='9')d=52+c-'0'; + else if(c>='a'&&c<='z')d=26+c-'a'; + else if(c>='A'&&c<='Z')d=c-'A'; + else if(c=='='&&3*i+j>_buf_sz)d=0; + else return OP_ENOTFORMAT; + value=value<<6|d; + } + _buf[3*i]=(unsigned char)(value>>16); + if(3*i+1<_buf_sz){ + _buf[3*i+1]=(unsigned char)(value>>8); + if(3*i+2<_buf_sz)_buf[3*i+2]=(unsigned char)value; + } + } + i=0; + picture_type=op_parse_uint32be(_buf+i); + i+=4; + /*Extract the MIME type.*/ + mime_type_length=op_parse_uint32be(_buf+i); + i+=4; + if(mime_type_length>_buf_sz-32)return OP_ENOTFORMAT; + mime_type=(char *)_ogg_malloc(sizeof(*_pic->mime_type)*(mime_type_length+1)); + if(mime_type==NULL)return OP_EFAULT; + memcpy(mime_type,_buf+i,sizeof(*mime_type)*mime_type_length); + mime_type[mime_type_length]='\0'; + _pic->mime_type=mime_type; + i+=mime_type_length; + /*Extract the description string.*/ + description_length=op_parse_uint32be(_buf+i); + i+=4; + if(description_length>_buf_sz-mime_type_length-32)return OP_ENOTFORMAT; + description= + (char *)_ogg_malloc(sizeof(*_pic->mime_type)*(description_length+1)); + if(description==NULL)return OP_EFAULT; + memcpy(description,_buf+i,sizeof(*description)*description_length); + description[description_length]='\0'; + _pic->description=description; + i+=description_length; + /*Extract the remaining fields.*/ + width=op_parse_uint32be(_buf+i); + i+=4; + height=op_parse_uint32be(_buf+i); + i+=4; + depth=op_parse_uint32be(_buf+i); + i+=4; + colors=op_parse_uint32be(_buf+i); + i+=4; + /*If one of these is set, they all must be, but colors==0 is a valid value.*/ + colors_set=width!=0||height!=0||depth!=0||colors!=0; + if(width==0||height==0||depth==0&&colors_set)return OP_ENOTFORMAT; + data_length=op_parse_uint32be(_buf+i); + i+=4; + if(data_length>_buf_sz-i)return OP_ENOTFORMAT; + /*Trim extraneous data so we don't copy it below.*/ + _buf_sz=i+data_length; + /*Attempt to determine the image format.*/ + format=OP_PIC_FORMAT_UNKNOWN; + if(mime_type_length==3&&strcmp(mime_type,"-->")==0){ + format=OP_PIC_FORMAT_URL; + /*Picture type 1 must be a 32x32 PNG.*/ + if(picture_type==1&&(width!=0||height!=0)&&(width!=32||height!=32)){ + return OP_ENOTFORMAT; + } + /*Append a terminating NUL for the convenience of our callers.*/ + _buf[_buf_sz++]='\0'; + } + else{ + if(mime_type_length==10 + &&op_strncasecmp(mime_type,"image/jpeg",mime_type_length)==0){ + if(op_is_jpeg(_buf+i,data_length))format=OP_PIC_FORMAT_JPEG; + } + else if(mime_type_length==9 + &&op_strncasecmp(mime_type,"image/png",mime_type_length)==0){ + if(op_is_png(_buf+i,data_length))format=OP_PIC_FORMAT_PNG; + } + else if(mime_type_length==9 + &&op_strncasecmp(mime_type,"image/gif",mime_type_length)==0){ + if(op_is_gif(_buf+i,data_length))format=OP_PIC_FORMAT_GIF; + } + else if(mime_type_length==0||(mime_type_length==6 + &&op_strncasecmp(mime_type,"image/",mime_type_length)==0)){ + if(op_is_jpeg(_buf+i,data_length))format=OP_PIC_FORMAT_JPEG; + else if(op_is_png(_buf+i,data_length))format=OP_PIC_FORMAT_PNG; + else if(op_is_gif(_buf+i,data_length))format=OP_PIC_FORMAT_GIF; + } + file_width=file_height=file_depth=file_colors=0; + has_palette=-1; + switch(format){ + case OP_PIC_FORMAT_JPEG:{ + op_extract_jpeg_params(_buf+i,data_length, + &file_width,&file_height,&file_depth,&file_colors,&has_palette); + }break; + case OP_PIC_FORMAT_PNG:{ + op_extract_png_params(_buf+i,data_length, + &file_width,&file_height,&file_depth,&file_colors,&has_palette); + }break; + case OP_PIC_FORMAT_GIF:{ + op_extract_gif_params(_buf+i,data_length, + &file_width,&file_height,&file_depth,&file_colors,&has_palette); + }break; + } + if(has_palette>=0){ + /*If we successfully extracted these parameters from the image, override + any declared values.*/ + width=file_width; + height=file_height; + depth=file_depth; + colors=file_colors; + } + /*Picture type 1 must be a 32x32 PNG.*/ + if(picture_type==1&&(format!=OP_PIC_FORMAT_PNG||width!=32||height!=32)){ + return OP_ENOTFORMAT; + } + } + /*Adjust _buf_sz instead of using data_length to capture the terminating NUL + for URLs.*/ + _buf_sz-=i; + memmove(_buf,_buf+i,sizeof(*_buf)*_buf_sz); + _buf=(unsigned char *)_ogg_realloc(_buf,_buf_sz); + if(_buf_sz>0&&_buf==NULL)return OP_EFAULT; + _pic->type=picture_type; + _pic->width=width; + _pic->height=height; + _pic->depth=depth; + _pic->colors=colors; + _pic->data_length=data_length; + _pic->data=_buf; + _pic->format=format; + return 0; +} + +int opus_picture_tag_parse(OpusPictureTag *_pic,const char *_tag){ + OpusPictureTag pic; + unsigned char *buf; + size_t base64_sz; + size_t buf_sz; + size_t tag_length; + int ret; + if(opus_tagncompare("METADATA_BLOCK_PICTURE",22,_tag)==0)_tag+=23; + /*Figure out how much BASE64-encoded data we have.*/ + tag_length=strlen(_tag); + if(tag_length&3)return OP_ENOTFORMAT; + base64_sz=tag_length>>2; + buf_sz=3*base64_sz; + if(buf_sz<32)return OP_ENOTFORMAT; + if(_tag[tag_length-1]=='=')buf_sz--; + if(_tag[tag_length-2]=='=')buf_sz--; + if(buf_sz<32)return OP_ENOTFORMAT; + /*Allocate an extra byte to allow appending a terminating NUL to URL data.*/ + buf=(unsigned char *)_ogg_malloc(sizeof(*buf)*(buf_sz+1)); + if(buf==NULL)return OP_EFAULT; + opus_picture_tag_init(&pic); + ret=opus_picture_tag_parse_impl(&pic,_tag,buf,buf_sz,base64_sz); + if(ret<0){ + opus_picture_tag_clear(&pic); + _ogg_free(buf); + } + else *_pic=*&pic; + return ret; +} + +void opus_picture_tag_init(OpusPictureTag *_pic){ + memset(_pic,0,sizeof(*_pic)); +} + +void opus_picture_tag_clear(OpusPictureTag *_pic){ + _ogg_free(_pic->description); + _ogg_free(_pic->mime_type); + _ogg_free(_pic->data); +} diff --git a/TelegramClient.Opus/opus/opusfile/internal.c b/TelegramClient.Opus/opus/opusfile/internal.c new file mode 100755 index 0000000..96c80de --- /dev/null +++ b/TelegramClient.Opus/opus/opusfile/internal.c @@ -0,0 +1,42 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ********************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "internal.h" + +#if defined(OP_ENABLE_ASSERTIONS) +void op_fatal_impl(const char *_str,const char *_file,int _line){ + fprintf(stderr,"Fatal (internal) error in %s, line %i: %s\n", + _file,_line,_str); + abort(); +} +#endif + +/*A version of strncasecmp() that is guaranteed to only ignore the case of + ASCII characters.*/ +int op_strncasecmp(const char *_a,const char *_b,int _n){ + int i; + for(i=0;i<_n;i++){ + int a; + int b; + int d; + a=_a[i]; + b=_b[i]; + if(a>='a'&&a<='z')a-='a'-'A'; + if(b>='a'&&b<='z')b-='a'-'A'; + d=a-b; + if(d)return d; + } + return 0; +} diff --git a/TelegramClient.Opus/opus/opusfile/internal.h b/TelegramClient.Opus/opus/opusfile/internal.h new file mode 100755 index 0000000..b1109de --- /dev/null +++ b/TelegramClient.Opus/opus/opusfile/internal.h @@ -0,0 +1,249 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ********************************************************************/ +#if !defined(_opusfile_internal_h) +# define _opusfile_internal_h (1) + +# if !defined(_REENTRANT) +# define _REENTRANT +# endif +# if !defined(_GNU_SOURCE) +# define _GNU_SOURCE +# endif +# if !defined(_LARGEFILE_SOURCE) +# define _LARGEFILE_SOURCE +# endif +# if !defined(_LARGEFILE64_SOURCE) +# define _LARGEFILE64_SOURCE +# endif +# if !defined(_FILE_OFFSET_BITS) +# define _FILE_OFFSET_BITS 64 +# endif + +# include +# include "opusfile.h" + +typedef struct OggOpusLink OggOpusLink; + +# if defined(OP_FIXED_POINT) + +typedef opus_int16 op_sample; + +# else + +typedef float op_sample; + +/*We're using this define to test for libopus 1.1 or later until libopus + provides a better mechanism.*/ +# if defined(OPUS_GET_EXPERT_FRAME_DURATION_REQUEST) +/*Enable soft clipping prevention in 16-bit decodes.*/ +# define OP_SOFT_CLIP (1) +# endif + +# endif + +# if OP_GNUC_PREREQ(4,2) +/*Disable excessive warnings about the order of operations.*/ +# pragma GCC diagnostic ignored "-Wparentheses" +# elif defined(_MSC_VER) +/*Disable excessive warnings about the order of operations.*/ +# pragma warning(disable:4554) +/*Disable warnings about "deprecated" POSIX functions.*/ +# pragma warning(disable:4996) +# endif + +# if OP_GNUC_PREREQ(3,0) +/*Another alternative is + (__builtin_constant_p(_x)?!!(_x):__builtin_expect(!!(_x),1)) + but that evaluates _x multiple times, which may be bad.*/ +# define OP_LIKELY(_x) (__builtin_expect(!!(_x),1)) +# define OP_UNLIKELY(_x) (__builtin_expect(!!(_x),0)) +# else +# define OP_LIKELY(_x) (!!(_x)) +# define OP_UNLIKELY(_x) (!!(_x)) +# endif + +# if defined(OP_ENABLE_ASSERTIONS) +# if OP_GNUC_PREREQ(2,5)||__SUNPRO_C>=0x590 +__attribute__((noreturn)) +# endif +void op_fatal_impl(const char *_str,const char *_file,int _line); + +# define OP_FATAL(_str) (op_fatal_impl(_str,__FILE__,__LINE__)) + +# define OP_ASSERT(_cond) \ + do{ \ + if(OP_UNLIKELY(!(_cond)))OP_FATAL("assertion failed: " #_cond); \ + } \ + while(0) +# define OP_ALWAYS_TRUE(_cond) OP_ASSERT(_cond) + +# else +# define OP_FATAL(_str) abort() +# define OP_ASSERT(_cond) +# define OP_ALWAYS_TRUE(_cond) ((void)(_cond)) +# endif + +# define OP_INT64_MAX (2*(((ogg_int64_t)1<<62)-1)|1) +# define OP_INT64_MIN (-OP_INT64_MAX-1) +# define OP_INT32_MAX (2*(((ogg_int32_t)1<<30)-1)|1) +# define OP_INT32_MIN (-OP_INT32_MAX-1) + +# define OP_MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) +# define OP_MAX(_a,_b) ((_a)>(_b)?(_a):(_b)) +# define OP_CLAMP(_lo,_x,_hi) (OP_MAX(_lo,OP_MIN(_x,_hi))) + +/*Advance a file offset by the given amount, clamping against OP_INT64_MAX. + This is used to advance a known offset by things like OP_CHUNK_SIZE or + OP_PAGE_SIZE_MAX, while making sure to avoid signed overflow. + It assumes that both _offset and _amount are non-negative.*/ +#define OP_ADV_OFFSET(_offset,_amount) \ + (OP_MIN(_offset,OP_INT64_MAX-(_amount))+(_amount)) + +/*The maximum channel count for any mapping we'll actually decode.*/ +# define OP_NCHANNELS_MAX (8) + +/*Initial state.*/ +# define OP_NOTOPEN (0) +/*We've found the first Opus stream in the first link.*/ +# define OP_PARTOPEN (1) +# define OP_OPENED (2) +/*We've found the first Opus stream in the current link.*/ +# define OP_STREAMSET (3) +/*We've initialized the decoder for the chosen Opus stream in the current + link.*/ +# define OP_INITSET (4) + +/*Information cached for a single link in a chained Ogg Opus file. + We choose the first Opus stream encountered in each link to play back (and + require at least one).*/ +struct OggOpusLink{ + /*The byte offset of the first header page in this link.*/ + opus_int64 offset; + /*The byte offset of the first data page from the chosen Opus stream in this + link (after the headers).*/ + opus_int64 data_offset; + /*The byte offset of the last page from the chosen Opus stream in this link. + This is used when seeking to ensure we find a page before the last one, so + that end-trimming calculations work properly. + This is only valid for seekable sources.*/ + opus_int64 end_offset; + /*The granule position of the last sample. + This is only valid for seekable sources.*/ + ogg_int64_t pcm_end; + /*The granule position before the first sample.*/ + ogg_int64_t pcm_start; + /*The serial number.*/ + ogg_uint32_t serialno; + /*The contents of the info header.*/ + OpusHead head; + /*The contents of the comment header.*/ + OpusTags tags; +}; + +struct OggOpusFile{ + /*The callbacks used to access the data source.*/ + OpusFileCallbacks callbacks; + /*A FILE *, memory bufer, etc.*/ + void *source; + /*Whether or not we can seek with this data source.*/ + int seekable; + /*The number of links in this chained Ogg Opus file.*/ + int nlinks; + /*The cached information from each link in a chained Ogg Opus file. + If source isn't seekable (e.g., it's a pipe), only the current link + appears.*/ + OggOpusLink *links; + /*The number of serial numbers from a single link.*/ + int nserialnos; + /*The capacity of the list of serial numbers from a single link.*/ + int cserialnos; + /*Storage for the list of serial numbers from a single link.*/ + ogg_uint32_t *serialnos; + /*This is the current offset of the data processed by the ogg_sync_state. + After a seek, this should be set to the target offset so that we can track + the byte offsets of subsequent pages. + After a call to op_get_next_page(), this will point to the first byte after + that page.*/ + opus_int64 offset; + /*The total size of this data source, or -1 if it's unseekable.*/ + opus_int64 end; + /*Used to locate pages in the data source.*/ + ogg_sync_state oy; + /*One of OP_NOTOPEN, OP_PARTOPEN, OP_OPENED, OP_STREAMSET, OP_INITSET.*/ + int ready_state; + /*The current link being played back.*/ + int cur_link; + /*The number of decoded samples to discard from the start of decoding.*/ + opus_int32 cur_discard_count; + /*The granule position of the previous packet (current packet start time).*/ + ogg_int64_t prev_packet_gp; + /*The number of bytes read since the last bitrate query, including framing.*/ + opus_int64 bytes_tracked; + /*The number of samples decoded since the last bitrate query.*/ + ogg_int64_t samples_tracked; + /*Takes physical pages and welds them into a logical stream of packets.*/ + ogg_stream_state os; + /*Re-timestamped packets from a single page. + Buffering these relies on the undocumented libogg behavior that ogg_packet + pointers remain valid until the next page is submitted to the + ogg_stream_state they came from.*/ + ogg_packet op[255]; + /*The index of the next packet to return.*/ + int op_pos; + /*The total number of packets available.*/ + int op_count; + /*Central working state for the packet-to-PCM decoder.*/ + OpusMSDecoder *od; + /*The application-provided packet decode callback.*/ + op_decode_cb_func decode_cb; + /*The application-provided packet decode callback context.*/ + void *decode_cb_ctx; + /*The stream count used to initialize the decoder.*/ + int od_stream_count; + /*The coupled stream count used to initialize the decoder.*/ + int od_coupled_count; + /*The channel count used to initialize the decoder.*/ + int od_channel_count; + /*The channel mapping used to initialize the decoder.*/ + unsigned char od_mapping[OP_NCHANNELS_MAX]; + /*The buffered data for one decoded packet.*/ + op_sample *od_buffer; + /*The current position in the decoded buffer.*/ + int od_buffer_pos; + /*The number of valid samples in the decoded buffer.*/ + int od_buffer_size; + /*The type of gain offset to apply. + One of OP_HEADER_GAIN, OP_TRACK_GAIN, or OP_ABSOLUTE_GAIN.*/ + int gain_type; + /*The offset to apply to the gain.*/ + opus_int32 gain_offset_q8; + /*Internal state for soft clipping and dithering float->short output.*/ +#if !defined(OP_FIXED_POINT) +# if defined(OP_SOFT_CLIP) + float clip_state[OP_NCHANNELS_MAX]; +# endif + float dither_a[OP_NCHANNELS_MAX*4]; + float dither_b[OP_NCHANNELS_MAX*4]; + opus_uint32 dither_seed; + int dither_mute; + int dither_disabled; + /*The number of channels represented by the internal state. + This gets set to 0 whenever anything that would prevent state propagation + occurs (switching between the float/short APIs, or between the + stereo/multistream APIs).*/ + int state_channel_count; +#endif +}; + +int op_strncasecmp(const char *_a,const char *_b,int _n); + +#endif diff --git a/TelegramClient.Opus/opus/opusfile/opusfile.c b/TelegramClient.Opus/opus/opusfile/opusfile.c new file mode 100755 index 0000000..392ddb2 --- /dev/null +++ b/TelegramClient.Opus/opus/opusfile/opusfile.c @@ -0,0 +1,3163 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: stdio-based convenience library for opening/seeking/decoding + last mod: $Id: vorbisfile.c 17573 2010-10-27 14:53:59Z xiphmont $ + + ********************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "internal.h" +#include +#include +#include +#include +#include +#include + +#include "opusfile.h" + +/*This implementation is largely based off of libvorbisfile. + All of the Ogg bits work roughly the same, though I have made some + "improvements" that have not been folded back there, yet.*/ + +/*A 'chained bitstream' is an Ogg Opus bitstream that contains more than one + logical bitstream arranged end to end (the only form of Ogg multiplexing + supported by this library. + Grouping (parallel multiplexing) is not supported, except to the extent that + if there are multiple logical Ogg streams in a single link of the chain, we + will ignore all but the first Opus stream we find.*/ + +/*An Ogg Opus file can be played beginning to end (streamed) without worrying + ahead of time about chaining (see opusdec from the opus-tools package). + If we have the whole file, however, and want random access + (seeking/scrubbing) or desire to know the total length/time of a file, we + need to account for the possibility of chaining.*/ + +/*We can handle things a number of ways. + We can determine the entire bitstream structure right off the bat, or find + pieces on demand. + This library determines and caches structure for the entire bitstream, but + builds a virtual decoder on the fly when moving between links in the chain.*/ + +/*There are also different ways to implement seeking. + Enough information exists in an Ogg bitstream to seek to sample-granularity + positions in the output. + Or, one can seek by picking some portion of the stream roughly in the desired + area if we only want coarse navigation through the stream. + We implement and expose both strategies.*/ + +/*The maximum number of bytes in a page (including the page headers).*/ +#define OP_PAGE_SIZE_MAX (65307) +/*The default amount to seek backwards per step when trying to find the + previous page. + This must be at least as large as the maximum size of a page.*/ +#define OP_CHUNK_SIZE (65536) +/*The maximum amount to seek backwards per step when trying to find the + previous page.*/ +#define OP_CHUNK_SIZE_MAX (1024*(opus_int32)1024) +/*A smaller read size is needed for low-rate streaming.*/ +#define OP_READ_SIZE (2048) + +int op_test(OpusHead *_head, + const unsigned char *_initial_data,size_t _initial_bytes){ + ogg_sync_state oy; + char *data; + int err; + /*The first page of a normal Opus file will be at most 57 bytes (27 Ogg + page header bytes + 1 lacing value + 21 Opus header bytes + 8 channel + mapping bytes). + It will be at least 47 bytes (27 Ogg page header bytes + 1 lacing value + + 19 Opus header bytes using channel mapping family 0). + If we don't have at least that much data, give up now.*/ + if(_initial_bytes<47)return OP_FALSE; + /*Only proceed if we start with the magic OggS string. + This is to prevent us spending a lot of time allocating memory and looking + for Ogg pages in non-Ogg files.*/ + if(memcmp(_initial_data,"OggS",4)!=0)return OP_ENOTFORMAT; + ogg_sync_init(&oy); + data=ogg_sync_buffer(&oy,_initial_bytes); + if(data!=NULL){ + ogg_stream_state os; + ogg_page og; + int ret; + memcpy(data,_initial_data,_initial_bytes); + ogg_sync_wrote(&oy,_initial_bytes); + ogg_stream_init(&os,-1); + err=OP_FALSE; + do{ + ogg_packet op; + ret=ogg_sync_pageout(&oy,&og); + /*Ignore holes.*/ + if(ret<0)continue; + /*Stop if we run out of data.*/ + if(!ret)break; + ogg_stream_reset_serialno(&os,ogg_page_serialno(&og)); + ogg_stream_pagein(&os,&og); + /*Only process the first packet on this page (if it's a BOS packet, + it's required to be the only one).*/ + if(ogg_stream_packetout(&os,&op)==1){ + if(op.b_o_s){ + ret=opus_head_parse(_head,op.packet,op.bytes); + /*If this didn't look like Opus, keep going.*/ + if(ret==OP_ENOTFORMAT)continue; + /*Otherwise we're done, one way or another.*/ + err=ret; + } + /*We finished parsing the headers. + There is no Opus to be found.*/ + else err=OP_ENOTFORMAT; + } + } + while(err==OP_FALSE); + ogg_stream_clear(&os); + } + else err=OP_EFAULT; + ogg_sync_clear(&oy); + return err; +} + +/*Many, many internal helpers. + The intention is not to be confusing. + Rampant duplication and monolithic function implementation (though we do have + some large, omnibus functions still) would be harder to understand anyway. + The high level functions are last. + Begin grokking near the end of the file if you prefer to read things + top-down.*/ + +/*The read/seek functions track absolute position within the stream.*/ + +/*Read a little more data from the file/pipe into the ogg_sync framer. + _nbytes: The maximum number of bytes to read. + Return: A positive number of bytes read on success, 0 on end-of-file, or a + negative value on failure.*/ +static int op_get_data(OggOpusFile *_of,int _nbytes){ + unsigned char *buffer; + int nbytes; + OP_ASSERT(_nbytes>0); + buffer=(unsigned char *)ogg_sync_buffer(&_of->oy,_nbytes); + nbytes=(int)(*_of->callbacks.read)(_of->source,buffer,_nbytes); + OP_ASSERT(nbytes<=_nbytes); + if(OP_LIKELY(nbytes>0))ogg_sync_wrote(&_of->oy,nbytes); + return nbytes; +} + +/*Save a tiny smidge of verbosity to make the code more readable.*/ +static int op_seek_helper(OggOpusFile *_of,opus_int64 _offset){ + if(_offset==_of->offset)return 0; + if(_of->callbacks.seek==NULL|| + (*_of->callbacks.seek)(_of->source,_offset,SEEK_SET)){ + return OP_EREAD; + } + _of->offset=_offset; + ogg_sync_reset(&_of->oy); + return 0; +} + +/*Get the current position indicator of the underlying source. + This should be the same as the value reported by tell().*/ +static opus_int64 op_position(const OggOpusFile *_of){ + /*The current position indicator is _not_ simply offset. + We may also have unprocessed, buffered data in the sync state.*/ + return _of->offset+_of->oy.fill-_of->oy.returned; +} + +/*From the head of the stream, get the next page. + _boundary specifies if the function is allowed to fetch more data from the + stream (and how much) or only use internally buffered data. + _boundary: -1: Unbounded search. + 0: Read no additional data. + Use only cached data. + n: Search for the start of a new page up to file position n. + Return: n>=0: Found a page at absolute offset n. + OP_FALSE: Hit the _boundary limit. + OP_EREAD: An underlying read operation failed. + OP_BADLINK: We hit end-of-file before reaching _boundary.*/ +static opus_int64 op_get_next_page(OggOpusFile *_of,ogg_page *_og, + opus_int64 _boundary){ + while(_boundary<=0||_of->offset<_boundary){ + int more; + more=ogg_sync_pageseek(&_of->oy,_og); + /*Skipped (-more) bytes.*/ + if(OP_UNLIKELY(more<0))_of->offset-=more; + else if(more==0){ + int read_nbytes; + int ret; + /*Send more paramedics.*/ + if(!_boundary)return OP_FALSE; + if(_boundary<0)read_nbytes=OP_READ_SIZE; + else{ + opus_int64 position; + position=op_position(_of); + if(position>=_boundary)return OP_FALSE; + read_nbytes=(int)OP_MIN(_boundary-position,OP_READ_SIZE); + } + ret=op_get_data(_of,read_nbytes); + if(OP_UNLIKELY(ret<0))return OP_EREAD; + if(OP_UNLIKELY(ret==0)){ + /*Only fail cleanly on EOF if we didn't have a known boundary. + Otherwise, we should have been able to reach that boundary, and this + is a fatal error.*/ + return OP_UNLIKELY(_boundary<0)?OP_FALSE:OP_EBADLINK; + } + } + else{ + /*Got a page. + Return the page start offset and advance the internal offset past the + page end.*/ + opus_int64 page_offset; + page_offset=_of->offset; + _of->offset+=more; + OP_ASSERT(page_offset>=0); + return page_offset; + } + } + return OP_FALSE; +} + +static int op_add_serialno(const ogg_page *_og, + ogg_uint32_t **_serialnos,int *_nserialnos,int *_cserialnos){ + ogg_uint32_t *serialnos; + int nserialnos; + int cserialnos; + ogg_uint32_t s; + s=ogg_page_serialno(_og); + serialnos=*_serialnos; + nserialnos=*_nserialnos; + cserialnos=*_cserialnos; + if(OP_UNLIKELY(nserialnos>=cserialnos)){ + if(OP_UNLIKELY(cserialnos>INT_MAX-1>>1))return OP_EFAULT; + cserialnos=2*cserialnos+1; + OP_ASSERT(nserialnos=OP_PAGE_SIZE_MAX); + begin=OP_MAX(begin-chunk_size,0); + ret=op_seek_helper(_of,begin); + if(OP_UNLIKELY(ret<0))return ret; + search_start=begin; + while(_of->offsetsearch_start=search_start; + _sr->offset=_offset=llret; + _sr->serialno=serialno; + OP_ASSERT(_of->offset-_offset>=0); + OP_ASSERT(_of->offset-_offset<=OP_PAGE_SIZE_MAX); + _sr->size=(opus_int32)(_of->offset-_offset); + _sr->gp=ogg_page_granulepos(&og); + /*If this page is from the stream we're looking for, remember it.*/ + if(serialno==_serialno){ + preferred_found=1; + *&preferred_sr=*_sr; + } + if(!op_lookup_serialno(serialno,_serialnos,_nserialnos)){ + /*We fell off the end of the link, which means we seeked back too far + and shouldn't have been looking in that link to begin with. + If we found the preferred serial number, forget that we saw it.*/ + preferred_found=0; + } + search_start=llret+1; + } + /*We started from the beginning of the stream and found nothing. + This should be impossible unless the contents of the source changed out + from under us after we read from it.*/ + if(OP_UNLIKELY(!begin)&&OP_UNLIKELY(_offset<0))return OP_EBADLINK; + /*Bump up the chunk size. + This is mildly helpful when seeks are very expensive (http).*/ + chunk_size=OP_MIN(2*chunk_size,OP_CHUNK_SIZE_MAX); + /*Avoid quadratic complexity if we hit an invalid patch of the file.*/ + end=OP_MIN(begin+OP_PAGE_SIZE_MAX-1,original_end); + } + while(_offset<0); + if(preferred_found)*_sr=*&preferred_sr; + return 0; +} + +/*Find the last page beginning before _offset with the given serial number and + a valid granule position. + Unlike the above search, this continues until it finds such a page, but does + not stray outside the current link. + We could implement it (inefficiently) by calling op_get_prev_page_serial() + repeatedly until it returned a page that had both our preferred serial + number and a valid granule position, but doing it with a separate function + allows us to avoid repeatedly re-scanning valid pages from other streams as + we seek-back-and-read-forward. + [out] _gp: Returns the granule position of the page that was found on + success. + _offset: The _offset before which to find a page. + Any page returned will consist of data entirely before _offset. + _serialno: The target serial number. + _serialnos: The list of serial numbers in the link that contains the + preferred serial number. + _nserialnos: The number of serial numbers in the current link. + Return: The offset of the page on success, or a negative value on failure. + OP_EREAD: Failed to read more data (error or EOF). + OP_EBADLINK: We couldn't find a page even after seeking back past the + beginning of the link.*/ +static opus_int64 op_get_last_page(OggOpusFile *_of,ogg_int64_t *_gp, + opus_int64 _offset,ogg_uint32_t _serialno, + const ogg_uint32_t *_serialnos,int _nserialnos){ + ogg_page og; + ogg_int64_t gp; + opus_int64 begin; + opus_int64 end; + opus_int64 original_end; + opus_int32 chunk_size; + /*The target serial number must belong to the current link.*/ + OP_ASSERT(op_lookup_serialno(_serialno,_serialnos,_nserialnos)); + original_end=end=begin=_offset; + _offset=-1; + /*We shouldn't have to initialize gp, but gcc is too dumb to figure out that + ret>=0 implies we entered the if(page_gp!=-1) block at least once.*/ + gp=-1; + chunk_size=OP_CHUNK_SIZE; + do{ + int left_link; + int ret; + OP_ASSERT(chunk_size>=OP_PAGE_SIZE_MAX); + begin=OP_MAX(begin-chunk_size,0); + ret=op_seek_helper(_of,begin); + if(OP_UNLIKELY(ret<0))return ret; + left_link=0; + while(_of->offsetready_stateos,ogg_page_serialno(_og)); + ogg_stream_pagein(&_of->os,_og); + if(OP_LIKELY(ogg_stream_packetout(&_of->os,&op)>0)){ + ret=opus_head_parse(_head,op.packet,op.bytes); + /*If it's just a stream type we don't recognize, ignore it.*/ + if(ret==OP_ENOTFORMAT)continue; + /*Everything else is fatal.*/ + if(OP_UNLIKELY(ret<0))return ret; + /*Found a valid Opus header. + Continue setup.*/ + _of->ready_state=OP_STREAMSET; + } + } + /*Get the next page. + No need to clamp the boundary offset against _of->end, as all errors + become OP_ENOTFORMAT.*/ + if(OP_UNLIKELY(op_get_next_page(_of,_og, + OP_ADV_OFFSET(_of->offset,OP_CHUNK_SIZE))<0)){ + return OP_ENOTFORMAT; + } + /*If this page also belongs to our Opus stream, submit it and break.*/ + if(_of->ready_state==OP_STREAMSET + &&_of->os.serialno==ogg_page_serialno(_og)){ + ogg_stream_pagein(&_of->os,_og); + break; + } + } + if(OP_UNLIKELY(_of->ready_state!=OP_STREAMSET))return OP_ENOTFORMAT; + /*Loop getting packets.*/ + for(;;){ + switch(ogg_stream_packetout(&_of->os,&op)){ + case 0:{ + /*Loop getting pages.*/ + for(;;){ + /*No need to clamp the boundary offset against _of->end, as all + errors become OP_EBADHEADER.*/ + if(OP_UNLIKELY(op_get_next_page(_of,_og, + OP_ADV_OFFSET(_of->offset,OP_CHUNK_SIZE))<0)){ + return OP_EBADHEADER; + } + /*If this page belongs to the correct stream, go parse it.*/ + if(_of->os.serialno==ogg_page_serialno(_og)){ + ogg_stream_pagein(&_of->os,_og); + break; + } + /*If the link ends before we see the Opus comment header, abort.*/ + if(OP_UNLIKELY(ogg_page_bos(_og)))return OP_EBADHEADER; + /*Otherwise, keep looking.*/ + } + }break; + /*We shouldn't get a hole in the headers!*/ + case -1:return OP_EBADHEADER; + default:{ + /*Got a packet. + It should be the comment header.*/ + ret=opus_tags_parse(_tags,op.packet,op.bytes); + if(OP_UNLIKELY(ret<0))return ret; + /*Make sure the page terminated at the end of the comment header. + If there is another packet on the page, or part of a packet, then + reject the stream. + Otherwise seekable sources won't be able to seek back to the start + properly.*/ + ret=ogg_stream_packetout(&_of->os,&op); + if(OP_UNLIKELY(ret!=0) + ||OP_UNLIKELY(_og->header[_og->header_len-1]==255)){ + /*If we fail, the caller assumes our tags are uninitialized.*/ + opus_tags_clear(_tags); + return OP_EBADHEADER; + } + return 0; + } + } + } +} + +static int op_fetch_headers(OggOpusFile *_of,OpusHead *_head, + OpusTags *_tags,ogg_uint32_t **_serialnos,int *_nserialnos, + int *_cserialnos,ogg_page *_og){ + ogg_page og; + int ret; + if(!_og){ + /*No need to clamp the boundary offset against _of->end, as all errors + become OP_ENOTFORMAT.*/ + if(OP_UNLIKELY(op_get_next_page(_of,&og, + OP_ADV_OFFSET(_of->offset,OP_CHUNK_SIZE))<0)){ + return OP_ENOTFORMAT; + } + _og=&og; + } + _of->ready_state=OP_OPENED; + ret=op_fetch_headers_impl(_of,_head,_tags,_serialnos,_nserialnos, + _cserialnos,_og); + /*Revert back from OP_STREAMSET to OP_OPENED on failure, to prevent + double-free of the tags in an unseekable stream.*/ + if(OP_UNLIKELY(ret<0))_of->ready_state=OP_OPENED; + return ret; +} + +/*Granule position manipulation routines. + A granule position is defined to be an unsigned 64-bit integer, with the + special value -1 in two's complement indicating an unset or invalid granule + position. + We are not guaranteed to have an unsigned 64-bit type, so we construct the + following routines that + a) Properly order negative numbers as larger than positive numbers, and + b) Check for underflow or overflow past the special -1 value. + This lets us operate on the full, valid range of granule positions in a + consistent and safe manner. + This full range is organized into distinct regions: + [ -1 (invalid) ][ 0 ... OP_INT64_MAX ][ OP_INT64_MIN ... -2 ][-1 (invalid) ] + + No one should actually use granule positions so large that they're negative, + even if they are technically valid, as very little software handles them + correctly (including most of Xiph.Org's). + This library also refuses to support durations so large they won't fit in a + signed 64-bit integer (to avoid exposing this mess to the application, and + to simplify a good deal of internal arithmetic), so the only way to use them + successfully is if pcm_start is very large. + This means there isn't anything you can do with negative granule positions + that you couldn't have done with purely non-negative ones. + The main purpose of these routines is to allow us to think very explicitly + about the possible failure cases of all granule position manipulations.*/ + +/*Safely adds a small signed integer to a valid (not -1) granule position. + The result can use the full 64-bit range of values (both positive and + negative), but will fail on overflow (wrapping past -1; wrapping past + OP_INT64_MAX is explicitly okay). + [out] _dst_gp: The resulting granule position. + Only modified on success. + _src_gp: The granule position to add to. + This must not be -1. + _delta: The amount to add. + This is allowed to be up to 32 bits to support the maximum + duration of a single Ogg page (255 packets * 120 ms per + packet == 1,468,800 samples at 48 kHz). + Return: 0 on success, or OP_EINVAL if the result would wrap around past -1.*/ +static int op_granpos_add(ogg_int64_t *_dst_gp,ogg_int64_t _src_gp, + opus_int32 _delta){ + /*The code below handles this case correctly, but there's no reason we + should ever be called with these values, so make sure we aren't.*/ + OP_ASSERT(_src_gp!=-1); + if(_delta>0){ + /*Adding this amount to the granule position would overflow its 64-bit + range.*/ + if(OP_UNLIKELY(_src_gp<0)&&OP_UNLIKELY(_src_gp>=-1-_delta))return OP_EINVAL; + if(OP_UNLIKELY(_src_gp>OP_INT64_MAX-_delta)){ + /*Adding this amount to the granule position would overflow the positive + half of its 64-bit range. + Since signed overflow is undefined in C, do it in a way the compiler + isn't allowed to screw up.*/ + _delta-=(opus_int32)(OP_INT64_MAX-_src_gp)+1; + _src_gp=OP_INT64_MIN; + } + } + else if(_delta<0){ + /*Subtracting this amount from the granule position would underflow its + 64-bit range.*/ + if(_src_gp>=0&&OP_UNLIKELY(_src_gp<-_delta))return OP_EINVAL; + if(OP_UNLIKELY(_src_gp da < 0.*/ + da=(OP_INT64_MIN-_gp_a)-1; + /*_gp_b >= 0 => db >= 0.*/ + db=OP_INT64_MAX-_gp_b; + /*Step 2: Check for overflow.*/ + if(OP_UNLIKELY(OP_INT64_MAX+da= 0 => da <= 0*/ + da=_gp_a+OP_INT64_MIN; + /*_gp_b < 0 => db <= 0*/ + db=OP_INT64_MIN-_gp_b; + /*Step 2: Check for overflow.*/ + if(OP_UNLIKELY(da=0)return 1; + /*Else fall through.*/ + } + else if(OP_UNLIKELY(_gp_b<0))return -1; + /*No wrapping case.*/ + return (_gp_a>_gp_b)-(_gp_b>_gp_a); +} + +/*Returns the duration of the packet (in samples at 48 kHz), or a negative + value on error.*/ +static int op_get_packet_duration(const unsigned char *_data,int _len){ + int nframes; + int frame_size; + int nsamples; + nframes=opus_packet_get_nb_frames(_data,_len); + if(OP_UNLIKELY(nframes<0))return OP_EBADPACKET; + frame_size=opus_packet_get_samples_per_frame(_data,48000); + nsamples=nframes*frame_size; + if(OP_UNLIKELY(nsamples>120*48))return OP_EBADPACKET; + return nsamples; +} + +/*This function more properly belongs in info.c, but we define it here to allow + the static granule position manipulation functions to remain static.*/ +ogg_int64_t opus_granule_sample(const OpusHead *_head,ogg_int64_t _gp){ + opus_int32 pre_skip; + pre_skip=_head->pre_skip; + if(_gp!=-1&&op_granpos_add(&_gp,_gp,-pre_skip))_gp=-1; + return _gp; +} + +/*Grab all the packets currently in the stream state, and compute their + durations. + _of->op_count is set to the number of packets collected. + [out] _durations: Returns the durations of the individual packets. + Return: The total duration of all packets, or OP_HOLE if there was a hole.*/ +static opus_int32 op_collect_audio_packets(OggOpusFile *_of, + int _durations[255]){ + opus_int32 total_duration; + int op_count; + /*Count the durations of all packets in the page.*/ + op_count=0; + total_duration=0; + for(;;){ + int ret; + /*This takes advantage of undocumented libogg behavior that returned + ogg_packet buffers are valid at least until the next page is + submitted. + Relying on this is not too terrible, as _none_ of the Ogg memory + ownership/lifetime rules are well-documented. + But I can read its code and know this will work.*/ + ret=ogg_stream_packetout(&_of->os,_of->op+op_count); + if(!ret)break; + if(OP_UNLIKELY(ret<0)){ + /*We shouldn't get holes in the middle of pages.*/ + OP_ASSERT(op_count==0); + /*Set the return value and break out of the loop. + We want to make sure op_count gets set to 0, because we've ingested a + page, so any previously loaded packets are now invalid.*/ + total_duration=OP_HOLE; + break; + } + /*Unless libogg is broken, we can't get more than 255 packets from a + single page.*/ + OP_ASSERT(op_count<255); + _durations[op_count]=op_get_packet_duration(_of->op[op_count].packet, + _of->op[op_count].bytes); + if(OP_LIKELY(_durations[op_count]>0)){ + /*With at most 255 packets on a page, this can't overflow.*/ + total_duration+=_durations[op_count++]; + } + /*Ignore packets with an invalid TOC sequence.*/ + else if(op_count>0){ + /*But save the granule position, if there was one.*/ + _of->op[op_count-1].granulepos=_of->op[op_count].granulepos; + } + } + _of->op_pos=0; + _of->op_count=op_count; + return total_duration; +} + +/*Starting from current cursor position, get the initial PCM offset of the next + page. + This also validates the granule position on the first page with a completed + audio data packet, as required by the spec. + If this link is completely empty (no pages with completed packets), then this + function sets pcm_start=pcm_end=0 and returns the BOS page of the next link + (if any). + In the seekable case, we initialize pcm_end=-1 before calling this function, + so that later we can detect that the link was empty before calling + op_find_final_pcm_offset(). + [inout] _link: The link for which to find pcm_start. + [out] _og: Returns the BOS page of the next link if this link was empty. + In the unseekable case, we can then feed this to + op_fetch_headers() to start the next link. + The caller may pass NULL (e.g., for seekable streams), in + which case this page will be discarded. + Return: 0 on success, 1 if there is a buffered BOS page available, or a + negative value on unrecoverable error.*/ +static int op_find_initial_pcm_offset(OggOpusFile *_of, + OggOpusLink *_link,ogg_page *_og){ + ogg_page og; + ogg_int64_t pcm_start; + ogg_int64_t prev_packet_gp; + ogg_int64_t cur_page_gp; + ogg_uint32_t serialno; + opus_int32 total_duration; + int durations[255]; + int cur_page_eos; + int op_count; + int pi; + if(_og==NULL)_og=&og; + serialno=_of->os.serialno; + op_count=0; + /*We shouldn't have to initialize total_duration, but gcc is too dumb to + figure out that op_count>0 implies we've been through the whole loop at + least once.*/ + total_duration=0; + do{ + opus_int64 llret; + llret=op_get_next_page(_of,_og,_of->end); + /*We should get a page unless the file is truncated or mangled. + Otherwise there are no audio data packets in the whole logical stream.*/ + if(OP_UNLIKELY(llret<0)){ + /*Fail if there was a read error.*/ + if(llrethead.pre_skip>0)return OP_EBADTIMESTAMP; + /*Set pcm_end and end_offset so we can skip the call to + op_find_final_pcm_offset().*/ + _link->pcm_start=_link->pcm_end=0; + _link->end_offset=_link->data_offset; + return 0; + } + /*Similarly, if we hit the next link in the chain, we've gone too far.*/ + if(OP_UNLIKELY(ogg_page_bos(_og))){ + if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP; + /*Set pcm_end and end_offset so we can skip the call to + op_find_final_pcm_offset().*/ + _link->pcm_end=_link->pcm_start=0; + _link->end_offset=_link->data_offset; + /*Tell the caller we've got a buffered page for them.*/ + return 1; + } + /*Ignore pages from other streams (not strictly necessary, because of the + checks in ogg_stream_pagein(), but saves some work).*/ + if(serialno!=(ogg_uint32_t)ogg_page_serialno(_og))continue; + ogg_stream_pagein(&_of->os,_og); + /*Bitrate tracking: add the header's bytes here. + The body bytes are counted when we consume the packets.*/ + _of->bytes_tracked+=_og->header_len; + /*Count the durations of all packets in the page.*/ + do total_duration=op_collect_audio_packets(_of,durations); + /*Ignore holes.*/ + while(OP_UNLIKELY(total_duration<0)); + op_count=_of->op_count; + } + while(op_count<=0); + /*We found the first page with a completed audio data packet: actually look + at the granule position. + RFC 3533 says, "A special value of -1 (in two's complement) indicates that + no packets finish on this page," which does not say that a granule + position that is NOT -1 indicates that some packets DO finish on that page + (even though this was the intention, libogg itself violated this intention + for years before we fixed it). + The Ogg Opus specification only imposes its start-time requirements + on the granule position of the first page with completed packets, + so we ignore any set granule positions until then.*/ + cur_page_gp=_of->op[op_count-1].granulepos; + /*But getting a packet without a valid granule position on the page is not + okay.*/ + if(cur_page_gp==-1)return OP_EBADTIMESTAMP; + cur_page_eos=_of->op[op_count-1].e_o_s; + if(OP_LIKELY(!cur_page_eos)){ + /*The EOS flag wasn't set. + Work backwards from the provided granule position to get the starting PCM + offset.*/ + if(OP_UNLIKELY(op_granpos_add(&pcm_start,cur_page_gp,-total_duration)<0)){ + /*The starting granule position MUST not be smaller than the amount of + audio on the first page with completed packets.*/ + return OP_EBADTIMESTAMP; + } + } + else{ + /*The first page with completed packets was also the last.*/ + if(OP_LIKELY(op_granpos_add(&pcm_start,cur_page_gp,-total_duration)<0)){ + /*If there's less audio on the page than indicated by the granule + position, then we're doing end-trimming, and the starting PCM offset + is zero by spec mandate.*/ + pcm_start=0; + /*However, the end-trimming MUST not ask us to trim more samples than + exist after applying the pre-skip.*/ + if(OP_UNLIKELY(op_granpos_cmp(cur_page_gp,_link->head.pre_skip)<0)){ + return OP_EBADTIMESTAMP; + } + } + } + /*Timestamp the individual packets.*/ + prev_packet_gp=pcm_start; + for(pi=0;pi0){ + /*If we trimmed the entire packet, stop (the spec says encoders + shouldn't do this, but we support it anyway).*/ + if(OP_UNLIKELY(diff>durations[pi]))break; + _of->op[pi].granulepos=prev_packet_gp=cur_page_gp; + /*Move the EOS flag to this packet, if necessary, so we'll trim the + samples.*/ + _of->op[pi].e_o_s=1; + continue; + } + } + /*Update the granule position as normal.*/ + OP_ALWAYS_TRUE(!op_granpos_add(&_of->op[pi].granulepos, + prev_packet_gp,durations[pi])); + prev_packet_gp=_of->op[pi].granulepos; + } + /*Update the packet count after end-trimming.*/ + _of->op_count=pi; + _of->cur_discard_count=_link->head.pre_skip; + _of->prev_packet_gp=_link->pcm_start=pcm_start; + return 0; +} + +/*Starting from current cursor position, get the final PCM offset of the + previous page. + This also validates the duration of the link, which, while not strictly + required by the spec, we need to ensure duration calculations don't + overflow. + This is only done for seekable sources. + We must validate that op_find_initial_pcm_offset() succeeded for this link + before calling this function, otherwise it will scan the entire stream + backwards until it reaches the start, and then fail.*/ +static int op_find_final_pcm_offset(OggOpusFile *_of, + const ogg_uint32_t *_serialnos,int _nserialnos,OggOpusLink *_link, + opus_int64 _offset,ogg_uint32_t _end_serialno,ogg_int64_t _end_gp, + ogg_int64_t *_total_duration){ + ogg_int64_t total_duration; + ogg_int64_t duration; + ogg_uint32_t cur_serialno; + /*For the time being, fetch end PCM offset the simple way.*/ + cur_serialno=_link->serialno; + if(_end_serialno!=cur_serialno||_end_gp==-1){ + _offset=op_get_last_page(_of,&_end_gp,_offset, + cur_serialno,_serialnos,_nserialnos); + if(OP_UNLIKELY(_offset<0))return (int)_offset; + } + /*At worst we should have found the first page with completed packets.*/ + if(OP_UNLIKELY(_offset<_link->data_offset))return OP_EBADLINK; + /*This implementation requires that the difference between the first and last + granule positions in each link be representable in a signed, 64-bit + number, and that each link also have at least as many samples as the + pre-skip requires.*/ + if(OP_UNLIKELY(op_granpos_diff(&duration,_end_gp,_link->pcm_start)<0) + ||OP_UNLIKELY(duration<_link->head.pre_skip)){ + return OP_EBADTIMESTAMP; + } + /*We also require that the total duration be representable in a signed, + 64-bit number.*/ + duration-=_link->head.pre_skip; + total_duration=*_total_duration; + if(OP_UNLIKELY(OP_INT64_MAX-durationpcm_end=_end_gp; + _link->end_offset=_offset; + return 0; +} + +/*Rescale the number _x from the range [0,_from] to [0,_to]. + _from and _to must be positive.*/ +static opus_int64 op_rescale64(opus_int64 _x,opus_int64 _from,opus_int64 _to){ + opus_int64 frac; + opus_int64 ret; + int i; + if(_x>=_from)return _to; + if(_x<=0)return 0; + frac=0; + for(i=0;i<63;i++){ + frac<<=1; + OP_ASSERT(_x<=_from); + if(_x>=_from>>1){ + _x-=_from-_x; + frac|=1; + } + else _x<<=1; + } + ret=0; + for(i=0;i<63;i++){ + if(frac&1)ret=(ret&_to&1)+(ret>>1)+(_to>>1); + else ret>>=1; + frac>>=1; + } + return ret; +} + +/*The minimum granule position spacing allowed for making predictions. + This corresponds to about 1 second of audio at 48 kHz for both Opus and + Vorbis, or one keyframe interval in Theora with the default keyframe spacing + of 256.*/ +#define OP_GP_SPACING_MIN (48000) + +/*Try to estimate the location of the next link using the current seek + records, assuming the initial granule position of any streams we've found is + 0.*/ +static opus_int64 op_predict_link_start(const OpusSeekRecord *_sr,int _nsr, + opus_int64 _searched,opus_int64 _end_searched,opus_int32 _bias){ + opus_int64 bisect; + int sri; + int srj; + /*Require that we be at least OP_CHUNK_SIZE from the end. + We don't require that we be at least OP_CHUNK_SIZE from the beginning, + because if we are we'll just scan forward without seeking.*/ + _end_searched-=OP_CHUNK_SIZE; + if(_searched>=_end_searched)return -1; + bisect=_end_searched; + for(sri=0;sri<_nsr;sri++){ + ogg_int64_t gp1; + ogg_int64_t gp2_min; + ogg_uint32_t serialno1; + opus_int64 offset1; + /*If the granule position is negative, either it's invalid or we'd cause + overflow.*/ + gp1=_sr[sri].gp; + if(gp1<0)continue; + /*We require some minimum distance between granule positions to make an + estimate. + We don't actually know what granule position scheme is being used, + because we have no idea what kind of stream these came from. + Therefore we require a minimum spacing between them, with the + expectation that while bitrates and granule position increments might + vary locally in quite complex ways, they are globally smooth.*/ + if(OP_UNLIKELY(op_granpos_add(&gp2_min,gp1,OP_GP_SPACING_MIN)<0)){ + /*No granule position would satisfy us.*/ + continue; + } + offset1=_sr[sri].offset; + serialno1=_sr[sri].serialno; + for(srj=sri;srj-->0;){ + ogg_int64_t gp2; + opus_int64 offset2; + opus_int64 num; + ogg_int64_t den; + ogg_int64_t ipart; + gp2=_sr[srj].gp; + if(gp20); + if(ipart>0&&(offset2-_searched)/ipart=_end_searched?-1:bisect; +} + +/*Finds each bitstream link, one at a time, using a bisection search. + This has to begin by knowing the offset of the first link's initial page.*/ +static int op_bisect_forward_serialno(OggOpusFile *_of, + opus_int64 _searched,OpusSeekRecord *_sr,int _csr, + ogg_uint32_t **_serialnos,int *_nserialnos,int *_cserialnos){ + ogg_page og; + OggOpusLink *links; + int nlinks; + int clinks; + ogg_uint32_t *serialnos; + int nserialnos; + ogg_int64_t total_duration; + int nsr; + int ret; + links=_of->links; + nlinks=clinks=_of->nlinks; + total_duration=0; + /*We start with one seek record, for the last page in the file. + We build up a list of records for places we seek to during link + enumeration. + This list is kept sorted in reverse order. + We only care about seek locations that were _not_ in the current link, + therefore we can add them one at a time to the end of the list as we + improve the lower bound on the location where the next link starts.*/ + nsr=1; + for(;;){ + opus_int64 end_searched; + opus_int64 bisect; + opus_int64 next; + opus_int64 last; + ogg_int64_t end_offset; + ogg_int64_t end_gp; + int sri; + serialnos=*_serialnos; + nserialnos=*_nserialnos; + if(OP_UNLIKELY(nlinks>=clinks)){ + if(OP_UNLIKELY(clinks>INT_MAX-1>>1))return OP_EFAULT; + clinks=2*clinks+1; + OP_ASSERT(nlinkslinks=links; + } + /*Invariants: + We have the headers and serial numbers for the link beginning at 'begin'. + We have the offset and granule position of the last page in the file + (potentially not a page we care about).*/ + /*Scan the seek records we already have to save us some bisection.*/ + for(sri=0;sri1){ + opus_int64 last_offset; + opus_int64 avg_link_size; + opus_int64 upper_limit; + last_offset=links[nlinks-1].offset; + avg_link_size=last_offset/(nlinks-1); + upper_limit=end_searched-OP_CHUNK_SIZE-avg_link_size; + if(OP_LIKELY(last_offset>_searched-avg_link_size) + &&OP_LIKELY(last_offset>1); + /*If we're within OP_CHUNK_SIZE of the start, scan forward.*/ + if(bisect-_searchedoffset-last>=0); + OP_ASSERT(_of->offset-last<=OP_PAGE_SIZE_MAX); + _sr[nsr].size=(opus_int32)(_of->offset-last); + _sr[nsr].serialno=serialno; + _sr[nsr].gp=gp; + nsr++; + } + } + else{ + _searched=_of->offset; + next_bias=OP_CHUNK_SIZE; + if(serialno==links[nlinks-1].serialno){ + /*This page was from the stream we want, remember it. + If it's the last such page in the link, we won't have to go back + looking for it later.*/ + end_gp=gp; + end_offset=last; + } + } + } + bisect=op_predict_link_start(_sr,nsr,_searched,end_searched,next_bias); + } + /*Bisection point found. + Get the final granule position of the previous link, assuming + op_find_initial_pcm_offset() didn't already determine the link was + empty.*/ + if(OP_LIKELY(links[nlinks-1].pcm_end==-1)){ + if(end_gp==-1){ + /*If we don't know where the end page is, we'll have to seek back and + look for it, starting from the end of the link.*/ + end_offset=next; + /*Also forget the last page we read. + It won't be available after the seek.*/ + last=-1; + } + ret=op_find_final_pcm_offset(_of,serialnos,nserialnos, + links+nlinks-1,end_offset,links[nlinks-1].serialno,end_gp, + &total_duration); + if(OP_UNLIKELY(ret<0))return ret; + } + if(last!=next){ + /*The last page we read was not the first page the next link. + Move the cursor position to the offset of that first page. + This only performs an actual seek if the first page of the next link + does not start at the end of the last page from the current Opus + stream with a valid granule position.*/ + ret=op_seek_helper(_of,next); + if(OP_UNLIKELY(ret<0))return ret; + } + ret=op_fetch_headers(_of,&links[nlinks].head,&links[nlinks].tags, + _serialnos,_nserialnos,_cserialnos,last!=next?NULL:&og); + if(OP_UNLIKELY(ret<0))return ret; + links[nlinks].offset=next; + links[nlinks].data_offset=_of->offset; + links[nlinks].serialno=_of->os.serialno; + links[nlinks].pcm_end=-1; + /*This might consume a page from the next link, however the next bisection + always starts with a seek.*/ + ret=op_find_initial_pcm_offset(_of,links+nlinks,NULL); + if(OP_UNLIKELY(ret<0))return ret; + _searched=_of->offset; + /*Mark the current link count so it can be cleaned up on error.*/ + _of->nlinks=++nlinks; + } + /*Last page is in the starting serialno list, so we've reached the last link. + Now find the last granule position for it (if we didn't the first time we + looked at the end of the stream, and if op_find_initial_pcm_offset() + didn't already determine the link was empty).*/ + if(OP_LIKELY(links[nlinks-1].pcm_end==-1)){ + ret=op_find_final_pcm_offset(_of,serialnos,nserialnos, + links+nlinks-1,_sr[0].offset,_sr[0].serialno,_sr[0].gp,&total_duration); + if(OP_UNLIKELY(ret<0))return ret; + } + /*Trim back the links array if necessary.*/ + links=(OggOpusLink *)_ogg_realloc(links,sizeof(*links)*nlinks); + if(OP_LIKELY(links!=NULL))_of->links=links; + /*We also don't need these anymore.*/ + _ogg_free(*_serialnos); + *_serialnos=NULL; + *_cserialnos=*_nserialnos=0; + return 0; +} + +static void op_update_gain(OggOpusFile *_of){ + OpusHead *head; + opus_int32 gain_q8; + int li; + /*If decode isn't ready, then we'll apply the gain when we initialize the + decoder.*/ + if(_of->ready_stategain_offset_q8; + li=_of->seekable?_of->cur_link:0; + head=&_of->links[li].head; + /*We don't have to worry about overflow here because the header gain and + track gain must lie in the range [-32768,32767], and the user-supplied + offset has been pre-clamped to [-98302,98303].*/ + switch(_of->gain_type){ + case OP_TRACK_GAIN:{ + int track_gain_q8; + track_gain_q8=0; + opus_tags_get_track_gain(&_of->links[li].tags,&track_gain_q8); + gain_q8+=track_gain_q8; + } + /*Fall through.*/ + case OP_HEADER_GAIN:gain_q8+=head->output_gain;break; + case OP_ABSOLUTE_GAIN:break; + default:OP_ASSERT(0); + } + gain_q8=OP_CLAMP(-32768,gain_q8,32767); + OP_ASSERT(_of->od!=NULL); +#if defined(OPUS_SET_GAIN) + opus_multistream_decoder_ctl(_of->od,OPUS_SET_GAIN(gain_q8)); +#else +/*A fallback that works with both float and fixed-point is a bunch of work, + so just force people to use a sufficiently new version. + This is deployed well enough at this point that this shouldn't be a burden.*/ +# error "libopus 1.0.1 or later required" +#endif +} + +static int op_make_decode_ready(OggOpusFile *_of){ + const OpusHead *head; + int li; + int stream_count; + int coupled_count; + int channel_count; + if(_of->ready_state>OP_STREAMSET)return 0; + if(OP_UNLIKELY(_of->ready_stateseekable?_of->cur_link:0; + head=&_of->links[li].head; + stream_count=head->stream_count; + coupled_count=head->coupled_count; + channel_count=head->channel_count; + /*Check to see if the current decoder is compatible with the current link.*/ + if(_of->od!=NULL&&_of->od_stream_count==stream_count + &&_of->od_coupled_count==coupled_count&&_of->od_channel_count==channel_count + &&memcmp(_of->od_mapping,head->mapping, + sizeof(*head->mapping)*channel_count)==0){ + opus_multistream_decoder_ctl(_of->od,OPUS_RESET_STATE); + } + else{ + int err; + opus_multistream_decoder_destroy(_of->od); + _of->od=opus_multistream_decoder_create(48000,channel_count, + stream_count,coupled_count,head->mapping,&err); + if(_of->od==NULL)return OP_EFAULT; + _of->od_stream_count=stream_count; + _of->od_coupled_count=coupled_count; + _of->od_channel_count=channel_count; + memcpy(_of->od_mapping,head->mapping,sizeof(*head->mapping)*channel_count); + } + _of->ready_state=OP_INITSET; + _of->bytes_tracked=0; + _of->samples_tracked=0; +#if !defined(OP_FIXED_POINT) + _of->state_channel_count=0; + /*Use the serial number for the PRNG seed to get repeatable output for + straight play-throughs.*/ + _of->dither_seed=_of->links[li].serialno; +#endif + op_update_gain(_of); + return 0; +} + +static int op_open_seekable2_impl(OggOpusFile *_of){ + /*64 seek records should be enough for anybody. + Actually, with a bisection search in a 63-bit range down to OP_CHUNK_SIZE + granularity, much more than enough.*/ + OpusSeekRecord sr[64]; + opus_int64 data_offset; + int ret; + /*We can seek, so set out learning all about this file.*/ + (*_of->callbacks.seek)(_of->source,0,SEEK_END); + _of->offset=_of->end=(*_of->callbacks.tell)(_of->source); + if(OP_UNLIKELY(_of->end<0))return OP_EREAD; + data_offset=_of->links[0].data_offset; + if(OP_UNLIKELY(_of->endend, + _of->links[0].serialno,_of->serialnos,_of->nserialnos); + if(OP_UNLIKELY(ret<0))return ret; + /*If there's any trailing junk, forget about it.*/ + _of->end=sr[0].offset+sr[0].size; + if(OP_UNLIKELY(_of->endserialnos,&_of->nserialnos,&_of->cserialnos); +} + +static int op_open_seekable2(OggOpusFile *_of){ + ogg_sync_state oy_start; + ogg_stream_state os_start; + ogg_packet *op_start; + opus_int64 start_offset; + int start_op_count; + int ret; + /*We're partially open and have a first link header state in storage in _of. + Save off that stream state so we can come back to it. + It would be simpler to just dump all this state and seek back to + links[0].data_offset when we're done. + But we do the extra work to allow us to seek back to _exactly_ the same + stream position we're at now. + This allows, e.g., the HTTP backend to continue reading from the original + connection (if it's still available), instead of opening a new one. + This means we can open and start playing a normal Opus file with a single + link and reasonable packet sizes using only two HTTP requests.*/ + start_op_count=_of->op_count; + /*This is a bit too large to put on the stack unconditionally.*/ + op_start=(ogg_packet *)_ogg_malloc(sizeof(*op_start)*start_op_count); + if(op_start==NULL)return OP_EFAULT; + *&oy_start=_of->oy; + *&os_start=_of->os; + start_offset=_of->offset; + memcpy(op_start,_of->op,sizeof(*op_start)*start_op_count); + OP_ASSERT((*_of->callbacks.tell)(_of->source)==op_position(_of)); + ogg_sync_init(&_of->oy); + ogg_stream_init(&_of->os,-1); + ret=op_open_seekable2_impl(_of); + /*Restore the old stream state.*/ + ogg_stream_clear(&_of->os); + ogg_sync_clear(&_of->oy); + *&_of->oy=*&oy_start; + *&_of->os=*&os_start; + _of->offset=start_offset; + _of->op_count=start_op_count; + memcpy(_of->op,op_start,sizeof(*_of->op)*start_op_count); + _ogg_free(op_start); + _of->prev_packet_gp=_of->links[0].pcm_start; + _of->cur_discard_count=_of->links[0].head.pre_skip; + if(OP_UNLIKELY(ret<0))return ret; + /*And restore the position indicator.*/ + ret=(*_of->callbacks.seek)(_of->source,op_position(_of),SEEK_SET); + return OP_UNLIKELY(ret<0)?OP_EREAD:0; +} + +/*Clear out the current logical bitstream decoder.*/ +static void op_decode_clear(OggOpusFile *_of){ + /*We don't actually free the decoder. + We might be able to re-use it for the next link.*/ + _of->op_count=0; + _of->od_buffer_size=0; + _of->prev_packet_gp=-1; + if(!_of->seekable){ + OP_ASSERT(_of->ready_state>=OP_INITSET); + opus_tags_clear(&_of->links[0].tags); + } + _of->ready_state=OP_OPENED; +} + +static void op_clear(OggOpusFile *_of){ + OggOpusLink *links; + _ogg_free(_of->od_buffer); + if(_of->od!=NULL)opus_multistream_decoder_destroy(_of->od); + links=_of->links; + if(!_of->seekable){ + if(_of->ready_state>OP_OPENED||_of->ready_state==OP_PARTOPEN){ + opus_tags_clear(&links[0].tags); + } + } + else if(OP_LIKELY(links!=NULL)){ + int nlinks; + int link; + nlinks=_of->nlinks; + for(link=0;linkserialnos); + ogg_stream_clear(&_of->os); + ogg_sync_clear(&_of->oy); + if(_of->callbacks.close!=NULL)(*_of->callbacks.close)(_of->source); +} + +static int op_open1(OggOpusFile *_of, + void *_source,const OpusFileCallbacks *_cb, + const unsigned char *_initial_data,size_t _initial_bytes){ + ogg_page og; + ogg_page *pog; + int seekable; + int ret; + memset(_of,0,sizeof(*_of)); + _of->end=-1; + _of->source=_source; + *&_of->callbacks=*_cb; + /*At a minimum, we need to be able to read data.*/ + if(OP_UNLIKELY(_of->callbacks.read==NULL))return OP_EREAD; + /*Initialize the framing state.*/ + ogg_sync_init(&_of->oy); + /*Perhaps some data was previously read into a buffer for testing against + other stream types. + Allow initialization from this previously read data (especially as we may + be reading from a non-seekable stream). + This requires copying it into a buffer allocated by ogg_sync_buffer() and + doesn't support seeking, so this is not a good mechanism to use for + decoding entire files from RAM.*/ + if(_initial_bytes>0){ + char *buffer; + buffer=ogg_sync_buffer(&_of->oy,_initial_bytes); + memcpy(buffer,_initial_data,_initial_bytes*sizeof(*buffer)); + ogg_sync_wrote(&_of->oy,_initial_bytes); + } + /*Can we seek? + Stevens suggests the seek test is portable.*/ + seekable=_cb->seek!=NULL&&(*_cb->seek)(_source,0,SEEK_CUR)!=-1; + /*If seek is implemented, tell must also be implemented.*/ + if(seekable){ + opus_int64 pos; + if(OP_UNLIKELY(_of->callbacks.tell==NULL))return OP_EINVAL; + pos=(*_of->callbacks.tell)(_of->source); + /*If the current position is not equal to the initial bytes consumed, + absolute seeking will not work.*/ + if(OP_UNLIKELY(pos!=(opus_int64)_initial_bytes))return OP_EINVAL; + } + _of->seekable=seekable; + /*Don't seek yet. + Set up a 'single' (current) logical bitstream entry for partial open.*/ + _of->links=(OggOpusLink *)_ogg_malloc(sizeof(*_of->links)); + /*The serialno gets filled in later by op_fetch_headers().*/ + ogg_stream_init(&_of->os,-1); + pog=NULL; + for(;;){ + /*Fetch all BOS pages, store the Opus header and all seen serial numbers, + and load subsequent Opus setup headers.*/ + ret=op_fetch_headers(_of,&_of->links[0].head,&_of->links[0].tags, + &_of->serialnos,&_of->nserialnos,&_of->cserialnos,pog); + if(OP_UNLIKELY(ret<0))break; + _of->nlinks=1; + _of->links[0].offset=0; + _of->links[0].data_offset=_of->offset; + _of->links[0].pcm_end=-1; + _of->links[0].serialno=_of->os.serialno; + /*Fetch the initial PCM offset.*/ + ret=op_find_initial_pcm_offset(_of,_of->links,&og); + if(seekable||OP_LIKELY(ret<=0))break; + /*This link was empty, but we already have the BOS page for the next one in + og. + We can't seek, so start processing the next link right now.*/ + opus_tags_clear(&_of->links[0].tags); + _of->nlinks=0; + if(!seekable)_of->cur_link++; + pog=&og; + } + if(OP_LIKELY(ret>=0))_of->ready_state=OP_PARTOPEN; + return ret; +} + +static int op_open2(OggOpusFile *_of){ + int ret; + OP_ASSERT(_of->ready_state==OP_PARTOPEN); + if(_of->seekable){ + _of->ready_state=OP_OPENED; + ret=op_open_seekable2(_of); + } + else ret=0; + if(OP_LIKELY(ret>=0)){ + /*We have buffered packets from op_find_initial_pcm_offset(). + Move to OP_INITSET so we can use them.*/ + _of->ready_state=OP_STREAMSET; + ret=op_make_decode_ready(_of); + if(OP_LIKELY(ret>=0))return 0; + } + /*Don't auto-close the stream on failure.*/ + _of->callbacks.close=NULL; + op_clear(_of); + return ret; +} + +OggOpusFile *op_test_callbacks(void *_source,const OpusFileCallbacks *_cb, + const unsigned char *_initial_data,size_t _initial_bytes,int *_error){ + OggOpusFile *of; + int ret; + of=(OggOpusFile *)_ogg_malloc(sizeof(*of)); + ret=OP_EFAULT; + if(OP_LIKELY(of!=NULL)){ + ret=op_open1(of,_source,_cb,_initial_data,_initial_bytes); + if(OP_LIKELY(ret>=0)){ + if(_error!=NULL)*_error=0; + return of; + } + /*Don't auto-close the stream on failure.*/ + of->callbacks.close=NULL; + op_clear(of); + _ogg_free(of); + } + if(_error!=NULL)*_error=ret; + return NULL; +} + +OggOpusFile *op_open_callbacks(void *_source,const OpusFileCallbacks *_cb, + const unsigned char *_initial_data,size_t _initial_bytes,int *_error){ + OggOpusFile *of; + of=op_test_callbacks(_source,_cb,_initial_data,_initial_bytes,_error); + if(OP_LIKELY(of!=NULL)){ + int ret; + ret=op_open2(of); + if(OP_LIKELY(ret>=0))return of; + if(_error!=NULL)*_error=ret; + _ogg_free(of); + } + return NULL; +} + +/*Convenience routine to clean up from failure for the open functions that + create their own streams.*/ +static OggOpusFile *op_open_close_on_failure(void *_source, + const OpusFileCallbacks *_cb,int *_error){ + OggOpusFile *of; + if(OP_UNLIKELY(_source==NULL)){ + if(_error!=NULL)*_error=OP_EFAULT; + return NULL; + } + of=op_open_callbacks(_source,_cb,NULL,0,_error); + if(OP_UNLIKELY(of==NULL))(*_cb->close)(_source); + return of; +} + +OggOpusFile *op_open_file(const char *_path,int *_error){ + OpusFileCallbacks cb; + return op_open_close_on_failure(op_fopen(&cb,_path,"rb"),&cb,_error); +} + +OggOpusFile *op_open_memory(const unsigned char *_data,size_t _size, + int *_error){ + OpusFileCallbacks cb; + return op_open_close_on_failure(op_mem_stream_create(&cb,_data,_size),&cb, + _error); +} + +/*Convenience routine to clean up from failure for the open functions that + create their own streams.*/ +static OggOpusFile *op_test_close_on_failure(void *_source, + const OpusFileCallbacks *_cb,int *_error){ + OggOpusFile *of; + if(OP_UNLIKELY(_source==NULL)){ + if(_error!=NULL)*_error=OP_EFAULT; + return NULL; + } + of=op_test_callbacks(_source,_cb,NULL,0,_error); + if(OP_UNLIKELY(of==NULL))(*_cb->close)(_source); + return of; +} + +OggOpusFile *op_test_file(const char *_path,int *_error){ + OpusFileCallbacks cb; + return op_test_close_on_failure(op_fopen(&cb,_path,"rb"),&cb,_error); +} + +OggOpusFile *op_test_memory(const unsigned char *_data,size_t _size, + int *_error){ + OpusFileCallbacks cb; + return op_test_close_on_failure(op_mem_stream_create(&cb,_data,_size),&cb, + _error); +} + +int op_test_open(OggOpusFile *_of){ + int ret; + if(OP_UNLIKELY(_of->ready_state!=OP_PARTOPEN))return OP_EINVAL; + ret=op_open2(_of); + /*op_open2() will clear this structure on failure. + Reset its contents to prevent double-frees in op_free().*/ + if(OP_UNLIKELY(ret<0))memset(_of,0,sizeof(*_of)); + return ret; +} + +void op_free(OggOpusFile *_of){ + if(OP_LIKELY(_of!=NULL)){ + op_clear(_of); + _ogg_free(_of); + } +} + +int op_seekable(const OggOpusFile *_of){ + return _of->seekable; +} + +int op_link_count(const OggOpusFile *_of){ + return _of->nlinks; +} + +ogg_uint32_t op_serialno(const OggOpusFile *_of,int _li){ + if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1; + if(!_of->seekable)_li=0; + return _of->links[_li<0?_of->cur_link:_li].serialno; +} + +int op_channel_count(const OggOpusFile *_of,int _li){ + return op_head(_of,_li)->channel_count; +} + +opus_int64 op_raw_total(const OggOpusFile *_of,int _li){ + if(OP_UNLIKELY(_of->ready_stateseekable) + ||OP_UNLIKELY(_li>=_of->nlinks)){ + return OP_EINVAL; + } + if(_li<0)return _of->end-_of->links[0].offset; + return (_li+1>=_of->nlinks?_of->end:_of->links[_li+1].offset) + -_of->links[_li].offset; +} + +ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li){ + OggOpusLink *links; + ogg_int64_t diff; + int nlinks; + nlinks=_of->nlinks; + if(OP_UNLIKELY(_of->ready_stateseekable) + ||OP_UNLIKELY(_li>=nlinks)){ + return OP_EINVAL; + } + links=_of->links; + /*We verify that the granule position differences are larger than the + pre-skip and that the total duration does not overflow during link + enumeration, so we don't have to check here.*/ + if(_li<0){ + ogg_int64_t pcm_total; + int li; + pcm_total=0; + for(li=0;li=_of->nlinks))_li=_of->nlinks-1; + if(!_of->seekable)_li=0; + return &_of->links[_li<0?_of->cur_link:_li].head; +} + +const OpusTags *op_tags(const OggOpusFile *_of,int _li){ + if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1; + if(!_of->seekable){ + if(_of->ready_stateready_state!=OP_PARTOPEN){ + return NULL; + } + _li=0; + } + else if(_li<0)_li=_of->ready_state>=OP_STREAMSET?_of->cur_link:0; + return &_of->links[_li].tags; +} + +int op_current_link(const OggOpusFile *_of){ + if(OP_UNLIKELY(_of->ready_statecur_link; +} + +/*Compute an average bitrate given a byte and sample count. + Return: The bitrate in bits per second.*/ +static opus_int32 op_calc_bitrate(opus_int64 _bytes,ogg_int64_t _samples){ + /*These rates are absurd, but let's handle them anyway.*/ + if(OP_UNLIKELY(_bytes>(OP_INT64_MAX-(_samples>>1))/(48000*8))){ + ogg_int64_t den; + if(OP_UNLIKELY(_bytes/(OP_INT32_MAX/(48000*8))>=_samples)){ + return OP_INT32_MAX; + } + den=_samples/(48000*8); + return (opus_int32)((_bytes+(den>>1))/den); + } + if(OP_UNLIKELY(_samples<=0))return OP_INT32_MAX; + /*This can't actually overflow in normal operation: even with a pre-skip of + 545 2.5 ms frames with 8 streams running at 1282*8+1 bytes per packet + (1275 byte frames + Opus framing overhead + Ogg lacing values), that all + produce a single sample of decoded output, we still don't top 45 Mbps. + The only way to get bitrates larger than that is with excessive Opus + padding, more encoded streams than output channels, or lots and lots of + Ogg pages with no packets on them.*/ + return (opus_int32)OP_MIN((_bytes*48000*8+(_samples>>1))/_samples, + OP_INT32_MAX); +} + +opus_int32 op_bitrate(const OggOpusFile *_of,int _li){ + if(OP_UNLIKELY(_of->ready_stateseekable) + ||OP_UNLIKELY(_li>=_of->nlinks)){ + return OP_EINVAL; + } + return op_calc_bitrate(op_raw_total(_of,_li),op_pcm_total(_of,_li)); +} + +opus_int32 op_bitrate_instant(OggOpusFile *_of){ + ogg_int64_t samples_tracked; + opus_int32 ret; + if(OP_UNLIKELY(_of->ready_statesamples_tracked; + if(OP_UNLIKELY(samples_tracked==0))return OP_FALSE; + ret=op_calc_bitrate(_of->bytes_tracked,samples_tracked); + _of->bytes_tracked=0; + _of->samples_tracked=0; + return ret; +} + +/*Fetch and process a page. + This handles the case where we're at a bitstream boundary and dumps the + decoding machine. + If the decoding machine is unloaded, it loads it. + It also keeps prev_packet_gp up to date (seek and read both use this; seek + uses a special hack with _readp). + Return: <0) Error, OP_HOLE (lost packet), or OP_EOF. + 0) Need more data (only if _readp==0). + 1) Got at least one audio data packet.*/ +static int op_fetch_and_process_page(OggOpusFile *_of, + ogg_page *_og,opus_int64 _page_pos,int _readp,int _spanp,int _ignore_holes){ + OggOpusLink *links; + ogg_uint32_t cur_serialno; + int seekable; + int cur_link; + int ret; + /*We shouldn't get here if we have unprocessed packets.*/ + OP_ASSERT(_of->ready_stateop_pos>=_of->op_count); + if(!_readp)return 0; + seekable=_of->seekable; + links=_of->links; + cur_link=seekable?_of->cur_link:0; + cur_serialno=links[cur_link].serialno; + /*Handle one page.*/ + for(;;){ + ogg_page og; + OP_ASSERT(_of->ready_state>=OP_OPENED); + /*This loop is not strictly necessary, but there's no sense in doing the + extra checks of the larger loop for the common case in a multiplexed + bistream where the page is simply part of a different logical + bitstream.*/ + do{ + /*If we were given a page to use, use it.*/ + if(_og!=NULL){ + *&og=*_og; + _og=NULL; + } + /*Keep reading until we get a page with the correct serialno.*/ + else _page_pos=op_get_next_page(_of,&og,_of->end); + /*EOF: Leave uninitialized.*/ + if(_page_pos<0)return _page_posready_state>=OP_STREAMSET)){ + if(cur_serialno!=(ogg_uint32_t)ogg_page_serialno(&og)){ + /*Two possibilities: + 1) Another stream is multiplexed into this logical section, or*/ + if(OP_LIKELY(!ogg_page_bos(&og)))continue; + /* 2) Our decoding just traversed a bitstream boundary.*/ + if(!_spanp)return OP_EOF; + if(OP_LIKELY(_of->ready_state>=OP_INITSET))op_decode_clear(_of); + break; + } + } + /*Bitrate tracking: add the header's bytes here. + The body bytes are counted when we consume the packets.*/ + _of->bytes_tracked+=og.header_len; + } + while(0); + /*Do we need to load a new machine before submitting the page? + This is different in the seekable and non-seekable cases. + In the seekable case, we already have all the header information loaded + and cached. + We just initialize the machine with it and continue on our merry way. + In the non-seekable (streaming) case, we'll only be at a boundary if we + just left the previous logical bitstream, and we're now nominally at the + header of the next bitstream.*/ + if(OP_UNLIKELY(_of->ready_statenlinks; + for(li=0;li=nlinks)continue; + cur_serialno=serialno; + _of->cur_link=cur_link=li; + ogg_stream_reset_serialno(&_of->os,serialno); + _of->ready_state=OP_STREAMSET; + /*If we're at the start of this link, initialize the granule position + and pre-skip tracking.*/ + if(_page_pos<=links[cur_link].data_offset){ + _of->prev_packet_gp=links[cur_link].pcm_start; + _of->cur_discard_count=links[cur_link].head.pre_skip; + /*Ignore a hole at the start of a new link (this is common for + streams joined in the middle) or after seeking.*/ + _ignore_holes=1; + } + } + else{ + do{ + /*We're streaming. + Fetch the two header packets, build the info struct.*/ + ret=op_fetch_headers(_of,&links[0].head,&links[0].tags, + NULL,NULL,NULL,&og); + if(OP_UNLIKELY(ret<0))return ret; + /*op_find_initial_pcm_offset() will suppress any initial hole for us, + so no need to set _ignore_holes.*/ + ret=op_find_initial_pcm_offset(_of,links,&og); + if(OP_UNLIKELY(ret<0))return ret; + _of->links[0].serialno=cur_serialno=_of->os.serialno; + _of->cur_link++; + } + /*If the link was empty, keep going, because we already have the + BOS page of the next one in og.*/ + while(OP_UNLIKELY(ret>0)); + /*If we didn't get any packets out of op_find_initial_pcm_offset(), + keep going (this is possible if end-trimming trimmed them all).*/ + if(_of->op_count<=0)continue; + /*Otherwise, we're done.*/ + ret=op_make_decode_ready(_of); + if(OP_UNLIKELY(ret<0))return ret; + return 1; + } + } + /*The buffered page is the data we want, and we're ready for it. + Add it to the stream state.*/ + if(OP_UNLIKELY(_of->ready_state==OP_STREAMSET)){ + ret=op_make_decode_ready(_of); + if(OP_UNLIKELY(ret<0))return ret; + } + /*Extract all the packets from the current page.*/ + ogg_stream_pagein(&_of->os,&og); + if(OP_LIKELY(_of->ready_state>=OP_INITSET)){ + opus_int32 total_duration; + int durations[255]; + int op_count; + total_duration=op_collect_audio_packets(_of,durations); + if(OP_UNLIKELY(total_duration<0)){ + /*Drain the packets from the page anyway.*/ + total_duration=op_collect_audio_packets(_of,durations); + OP_ASSERT(total_duration>=0); + /*Report holes to the caller.*/ + if(!_ignore_holes)return OP_HOLE; + } + op_count=_of->op_count; + /*If we found at least one audio data packet, compute per-packet granule + positions for them.*/ + if(op_count>0){ + ogg_int64_t diff; + ogg_int64_t prev_packet_gp; + ogg_int64_t cur_packet_gp; + ogg_int64_t cur_page_gp; + int cur_page_eos; + int pi; + cur_page_gp=_of->op[op_count-1].granulepos; + cur_page_eos=_of->op[op_count-1].e_o_s; + prev_packet_gp=_of->prev_packet_gp; + if(OP_UNLIKELY(prev_packet_gp==-1)){ + opus_int32 cur_discard_count; + /*This is the first call after a raw seek. + Try to reconstruct prev_packet_gp from scratch.*/ + OP_ASSERT(seekable); + if(OP_UNLIKELY(cur_page_eos)){ + /*If the first page we hit after our seek was the EOS page, and + we didn't start from data_offset or before, we don't have + enough information to do end-trimming. + Proceed to the next link, rather than risk playing back some + samples that shouldn't have been played.*/ + _of->op_count=0; + continue; + } + /*By default discard 80 ms of data after a seek, unless we seek + into the pre-skip region.*/ + cur_discard_count=80*48; + cur_page_gp=_of->op[op_count-1].granulepos; + /*Try to initialize prev_packet_gp. + If the current page had packets but didn't have a granule + position, or the granule position it had was too small (both + illegal), just use the starting granule position for the link.*/ + prev_packet_gp=links[cur_link].pcm_start; + if(OP_LIKELY(cur_page_gp!=-1)){ + op_granpos_add(&prev_packet_gp,cur_page_gp,-total_duration); + } + if(OP_LIKELY(!op_granpos_diff(&diff, + prev_packet_gp,links[cur_link].pcm_start))){ + opus_int32 pre_skip; + /*If we start at the beginning of the pre-skip region, or we're + at least 80 ms from the end of the pre-skip region, we discard + to the end of the pre-skip region. + Otherwise, we still use the 80 ms default, which will discard + past the end of the pre-skip region.*/ + pre_skip=links[cur_link].head.pre_skip; + if(diff>=0&&diff<=OP_MAX(0,pre_skip-80*48)){ + cur_discard_count=pre_skip-(int)diff; + } + } + _of->cur_discard_count=cur_discard_count; + } + if(OP_UNLIKELY(cur_page_gp==-1)){ + /*This page had completed packets but didn't have a valid granule + position. + This is illegal, but we'll try to handle it by continuing to count + forwards from the previous page.*/ + if(op_granpos_add(&cur_page_gp,prev_packet_gp,total_duration)<0){ + /*The timestamp for this page overflowed.*/ + cur_page_gp=links[cur_link].pcm_end; + } + } + /*If we hit the last page, handle end-trimming.*/ + if(OP_UNLIKELY(cur_page_eos) + &&OP_LIKELY(!op_granpos_diff(&diff,cur_page_gp,prev_packet_gp)) + &&OP_LIKELY(diff0){ + /*If we trimmed the entire packet, stop (the spec says encoders + shouldn't do this, but we support it anyway).*/ + if(OP_UNLIKELY(diff>durations[pi]))break; + cur_packet_gp=cur_page_gp; + /*Move the EOS flag to this packet, if necessary, so we'll trim + the samples during decode.*/ + _of->op[pi].e_o_s=1; + } + else{ + /*Update the granule position as normal.*/ + OP_ALWAYS_TRUE(!op_granpos_add(&cur_packet_gp, + cur_packet_gp,durations[pi])); + } + _of->op[pi].granulepos=cur_packet_gp; + OP_ALWAYS_TRUE(!op_granpos_diff(&diff,cur_page_gp,cur_packet_gp)); + } + } + else{ + /*Propagate timestamps to earlier packets. + op_granpos_add(&prev_packet_gp,prev_packet_gp,total_duration) + should succeed and give prev_packet_gp==cur_page_gp. + But we don't bother to check that, as there isn't much we can do + if it's not true. + The only thing we guarantee is that the start and end granule + positions of the packets are valid, and that they are monotonic + within a page. + They might be completely out of range for this link (we'll check + that elsewhere), or non-monotonic between pages.*/ + if(OP_UNLIKELY(op_granpos_add(&prev_packet_gp, + cur_page_gp,-total_duration)<0)){ + /*The starting timestamp for the first packet on this page + underflowed. + This is illegal, but we ignore it.*/ + prev_packet_gp=0; + } + for(pi=0;pi=0); + OP_ALWAYS_TRUE(!op_granpos_add(&cur_packet_gp, + cur_packet_gp,durations[pi])); + _of->op[pi].granulepos=cur_packet_gp; + } + OP_ASSERT(total_duration==0); + } + _of->prev_packet_gp=prev_packet_gp; + _of->op_count=pi; + /*If end-trimming didn't trim all the packets, we're done.*/ + if(OP_LIKELY(pi>0))return 1; + } + } + } +} + +int op_raw_seek(OggOpusFile *_of,opus_int64 _pos){ + int ret; + if(OP_UNLIKELY(_of->ready_stateseekable))return OP_ENOSEEK; + if(OP_UNLIKELY(_pos<0)||OP_UNLIKELY(_pos>_of->end))return OP_EINVAL; + /*Clear out any buffered, decoded data.*/ + op_decode_clear(_of); + _of->bytes_tracked=0; + _of->samples_tracked=0; + ret=op_seek_helper(_of,_pos); + if(OP_UNLIKELY(ret<0))return OP_EREAD; + ret=op_fetch_and_process_page(_of,NULL,-1,1,1,1); + /*If we hit EOF, op_fetch_and_process_page() leaves us uninitialized. + Instead, jump to the end.*/ + if(ret==OP_EOF){ + int cur_link; + op_decode_clear(_of); + cur_link=_of->nlinks-1; + _of->cur_link=cur_link; + _of->prev_packet_gp=_of->links[cur_link].pcm_end; + _of->cur_discard_count=0; + ret=0; + } + else if(ret>0)ret=0; + return ret; +} + +/*Convert a PCM offset relative to the start of the whole stream to a granule + position in an individual link.*/ +static ogg_int64_t op_get_granulepos(const OggOpusFile *_of, + ogg_int64_t _pcm_offset,int *_li){ + const OggOpusLink *links; + ogg_int64_t duration; + int nlinks; + int li; + OP_ASSERT(_pcm_offset>=0); + nlinks=_of->nlinks; + links=_of->links; + for(li=0;OP_LIKELY(liOP_INT64_MAX-_pcm_offset)){ + /*Adding this amount to the granule position would overflow the positive + half of its 64-bit range. + Since signed overflow is undefined in C, do it in a way the compiler + isn't allowed to screw up.*/ + _pcm_offset-=OP_INT64_MAX-pcm_start+1; + pcm_start=OP_INT64_MIN; + } + pcm_start+=_pcm_offset; + *_li=li; + return pcm_start; + } + _pcm_offset-=duration; + } + return -1; +} + +/*This controls how close the target has to be to use the current stream + position to subdivide the initial range. + Two minutes seems to be a good default.*/ +#define OP_CUR_TIME_THRESH (120*48*(opus_int32)1000) + +/*Note: The OP_SMALL_FOOTPRINT #define doesn't (currently) save much code size, + but it's meant to serve as documentation for portions of the seeking + algorithm that are purely optional, to aid others learning from/porting this + code to other contexts.*/ +/*#define OP_SMALL_FOOTPRINT (1)*/ + +/*Search within link _li for the page with the highest granule position + preceding (or equal to) _target_gp. + There is a danger here: missing pages or incorrect frame number information + in the bitstream could make our task impossible. + Account for that (and report it as an error condition).*/ +static int op_pcm_seek_page(OggOpusFile *_of, + ogg_int64_t _target_gp,int _li){ + const OggOpusLink *link; + ogg_page og; + ogg_int64_t pcm_pre_skip; + ogg_int64_t pcm_start; + ogg_int64_t pcm_end; + ogg_int64_t best_gp; + ogg_int64_t diff; + ogg_uint32_t serialno; + opus_int32 pre_skip; + opus_int64 begin; + opus_int64 end; + opus_int64 boundary; + opus_int64 best; + opus_int64 page_offset; + opus_int64 d0; + opus_int64 d1; + opus_int64 d2; + int force_bisect; + int ret; + _of->bytes_tracked=0; + _of->samples_tracked=0; + link=_of->links+_li; + best_gp=pcm_start=link->pcm_start; + pcm_end=link->pcm_end; + serialno=link->serialno; + best=begin=link->data_offset; + page_offset=-1; + /*We discard the first 80 ms of data after a seek, so seek back that much + farther. + If we can't, simply seek to the beginning of the link.*/ + if(OP_UNLIKELY(op_granpos_add(&_target_gp,_target_gp,-80*48)<0) + ||OP_UNLIKELY(op_granpos_cmp(_target_gp,pcm_start)<0)){ + _target_gp=pcm_start; + } + /*Special case seeking to the start of the link.*/ + pre_skip=link->head.pre_skip; + OP_ALWAYS_TRUE(!op_granpos_add(&pcm_pre_skip,pcm_start,pre_skip)); + if(op_granpos_cmp(_target_gp,pcm_pre_skip)<0)end=boundary=begin; + else{ + end=boundary=link->end_offset; +#if !defined(OP_SMALL_FOOTPRINT) + /*If we were decoding from this link, we can narrow the range a bit.*/ + if(_li==_of->cur_link&&_of->ready_state>=OP_INITSET){ + opus_int64 offset; + int op_count; + op_count=_of->op_count; + /*The only way the offset can be invalid _and_ we can fail the granule + position checks below is if someone changed the contents of the last + page since we read it. + We'd be within our rights to just return OP_EBADLINK in that case, but + we'll simply ignore the current position instead.*/ + offset=_of->offset; + if(op_count>0&&OP_LIKELY(offset<=end)){ + ogg_int64_t gp; + /*Make sure the timestamp is valid. + The granule position might be -1 if we collected the packets from a + page without a granule position after reporting a hole.*/ + gp=_of->op[op_count-1].granulepos; + if(OP_LIKELY(gp!=-1)&&OP_LIKELY(op_granpos_cmp(pcm_start,gp)<0) + &&OP_LIKELY(op_granpos_cmp(pcm_end,gp)>0)){ + OP_ALWAYS_TRUE(!op_granpos_diff(&diff,gp,_target_gp)); + /*We only actually use the current time if either + a) We can cut off at least half the range, or + b) We're seeking sufficiently close to the current position that + it's likely to be informative. + Otherwise it appears using the whole link range to estimate the + first seek location gives better results, on average.*/ + if(diff<0){ + OP_ASSERT(offset>=begin); + if(offset-begin>=end-begin>>1||diff>-OP_CUR_TIME_THRESH){ + best=begin=offset; + best_gp=pcm_start=gp; + } + } + else{ + ogg_int64_t prev_page_gp; + /*We might get lucky and already have the packet with the target + buffered. + Worth checking. + For very small files (with all of the data in a single page, + generally 1 second or less), we can loop them continuously + without seeking at all.*/ + OP_ALWAYS_TRUE(!op_granpos_add(&prev_page_gp,_of->op[0].granulepos, + op_get_packet_duration(_of->op[0].packet,_of->op[0].bytes))); + if(op_granpos_cmp(prev_page_gp,_target_gp)<=0){ + /*Don't call op_decode_clear(), because it will dump our + packets.*/ + _of->op_pos=0; + _of->od_buffer_size=0; + _of->prev_packet_gp=prev_page_gp; + _of->ready_state=OP_STREAMSET; + return op_make_decode_ready(_of); + } + /*No such luck. + Check if we can cut off at least half the range, though.*/ + if(offset-begin<=end-begin>>1||diff>1; + d1=d2>>1; + d2=end-begin>>1; + if(force_bisect)bisect=begin+(end-begin>>1); + else{ + ogg_int64_t diff2; + OP_ALWAYS_TRUE(!op_granpos_diff(&diff,_target_gp,pcm_start)); + OP_ALWAYS_TRUE(!op_granpos_diff(&diff2,pcm_end,pcm_start)); + /*Take a (pretty decent) guess.*/ + bisect=begin+op_rescale64(diff,diff2,end-begin)-OP_CHUNK_SIZE; + } + if(bisect-OP_CHUNK_SIZEoffset){ + page_offset=-1; + ret=op_seek_helper(_of,bisect); + if(OP_UNLIKELY(ret<0))return ret; + } + chunk_size=OP_CHUNK_SIZE; + next_boundary=boundary; + while(beginoffset; + if(OP_UNLIKELY(op_granpos_cmp(pcm_start,gp)>0) + ||OP_UNLIKELY(op_granpos_cmp(pcm_end,gp)<0)){ + /*Don't let pcm_start get out of range! + That could happen with an invalid timestamp.*/ + break; + } + /*Save the byte offset of the end of the page with this granule + position.*/ + best=begin; + best_gp=pcm_start=gp; + OP_ALWAYS_TRUE(!op_granpos_diff(&diff,_target_gp,pcm_start)); + /*If we're more than a second away from our target, break out and + do another bisection.*/ + if(diff>48000)break; + /*Otherwise, keep scanning forward (do NOT use begin+1).*/ + bisect=begin; + } + else{ + /*We found a page that ends after our target.*/ + /*If we scanned the whole interval before we found it, we're done.*/ + if(bisect<=begin+1)end=begin; + else{ + end=bisect; + /*In later iterations, don't read past the first page we found.*/ + boundary=next_boundary; + /*If we're not making much progress shrinking the interval size, + start forcing straight bisection to limit the worst case.*/ + force_bisect=end-begin>d0*2; + /*Don't let pcm_end get out of range! + That could happen with an invalid timestamp.*/ + if(OP_LIKELY(op_granpos_cmp(pcm_end,gp)>0) + &&OP_LIKELY(op_granpos_cmp(pcm_start,gp)<=0)){ + pcm_end=gp; + } + break; + } + } + } + } + } + /*Found our page. + Seek to the end of it and update prev_packet_gp. + Our caller will set cur_discard_count. + This is an easier case than op_raw_seek(), as we don't need to keep any + packets from the page we found.*/ + /*Seek, if necessary.*/ + if(best!=page_offset){ + page_offset=-1; + ret=op_seek_helper(_of,best); + if(OP_UNLIKELY(ret<0))return ret; + } + OP_ASSERT(op_granpos_cmp(best_gp,pcm_start)>=0); + _of->cur_link=_li; + _of->ready_state=OP_STREAMSET; + _of->prev_packet_gp=best_gp; + ogg_stream_reset_serialno(&_of->os,serialno); + ret=op_fetch_and_process_page(_of,page_offset<0?NULL:&og,page_offset,1,0,1); + if(OP_UNLIKELY(ret<=0))return OP_EBADLINK; + /*Verify result.*/ + if(OP_UNLIKELY(op_granpos_cmp(_of->prev_packet_gp,_target_gp)>0)){ + return OP_EBADLINK; + } + return 0; +} + +int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset){ + const OggOpusLink *link; + ogg_int64_t pcm_start; + ogg_int64_t target_gp; + ogg_int64_t prev_packet_gp; + ogg_int64_t skip; + ogg_int64_t diff; + int op_count; + int op_pos; + int ret; + int li; + if(OP_UNLIKELY(_of->ready_stateseekable))return OP_ENOSEEK; + if(OP_UNLIKELY(_pcm_offset<0))return OP_EINVAL; + target_gp=op_get_granulepos(_of,_pcm_offset,&li); + if(OP_UNLIKELY(target_gp==-1))return OP_EINVAL; + link=_of->links+li; + pcm_start=link->pcm_start; + OP_ALWAYS_TRUE(!op_granpos_diff(&_pcm_offset,target_gp,pcm_start)); +#if !defined(OP_SMALL_FOOTPRINT) + /*For small (90 ms or less) forward seeks within the same link, just decode + forward. + This also optimizes the case of seeking to the current position.*/ + if(li==_of->cur_link&&_of->ready_state>=OP_INITSET){ + ogg_int64_t gp; + gp=_of->prev_packet_gp; + if(OP_LIKELY(gp!=-1)){ + int nbuffered; + nbuffered=OP_MAX(_of->od_buffer_size-_of->od_buffer_pos,0); + OP_ALWAYS_TRUE(!op_granpos_add(&gp,gp,-nbuffered)); + /*We do _not_ add cur_discard_count to gp. + Otherwise the total amount to discard could grow without bound, and it + would be better just to do a full seek.*/ + if(OP_LIKELY(!op_granpos_diff(&diff,gp,pcm_start))){ + ogg_int64_t discard_count; + discard_count=_pcm_offset-diff; + /*We use a threshold of 90 ms instead of 80, since 80 ms is the + _minimum_ we would have discarded after a full seek. + Assuming 20 ms frames (the default), we'd discard 90 ms on average.*/ + if(discard_count>=0&&OP_UNLIKELY(discard_count<90*48)){ + _of->cur_discard_count=(opus_int32)discard_count; + return 0; + } + } + } + } +#endif + ret=op_pcm_seek_page(_of,target_gp,li); + if(OP_UNLIKELY(ret<0))return ret; + /*Now skip samples until we actually get to our target.*/ + /*Figure out where we should skip to.*/ + if(_pcm_offset<=link->head.pre_skip)skip=0; + else skip=OP_MAX(_pcm_offset-80*48,0); + OP_ASSERT(_pcm_offset-skip>=0); + OP_ASSERT(_pcm_offset-skipop_count; + prev_packet_gp=_of->prev_packet_gp; + for(op_pos=_of->op_pos;op_posop[op_pos].granulepos; + if(OP_LIKELY(!op_granpos_diff(&diff,cur_packet_gp,pcm_start)) + &&diff>skip){ + break; + } + prev_packet_gp=cur_packet_gp; + } + _of->prev_packet_gp=prev_packet_gp; + _of->op_pos=op_pos; + if(op_posskip)return OP_EBADLINK; + OP_ASSERT(_pcm_offset-diffcur_discard_count=(opus_int32)(_pcm_offset-diff); + return 0; +} + +opus_int64 op_raw_tell(const OggOpusFile *_of){ + if(OP_UNLIKELY(_of->ready_stateoffset; +} + +/*Convert a granule position from a given link to a PCM offset relative to the + start of the whole stream. + For unseekable sources, this gets reset to 0 at the beginning of each link.*/ +static ogg_int64_t op_get_pcm_offset(const OggOpusFile *_of, + ogg_int64_t _gp,int _li){ + const OggOpusLink *links; + ogg_int64_t pcm_offset; + ogg_int64_t delta; + int li; + links=_of->links; + pcm_offset=0; + OP_ASSERT(_li<_of->nlinks); + for(li=0;li<_li;li++){ + OP_ALWAYS_TRUE(!op_granpos_diff(&delta, + links[li].pcm_end,links[li].pcm_start)); + delta-=links[li].head.pre_skip; + pcm_offset+=delta; + } + OP_ASSERT(_li>=0); + if(_of->seekable&&OP_UNLIKELY(op_granpos_cmp(_gp,links[_li].pcm_end)>0)){ + _gp=links[_li].pcm_end; + } + if(OP_LIKELY(op_granpos_cmp(_gp,links[_li].pcm_start)>0)){ + if(OP_UNLIKELY(op_granpos_diff(&delta,_gp,links[_li].pcm_start)<0)){ + /*This means an unseekable stream claimed to have a page from more than + 2 billion days after we joined.*/ + OP_ASSERT(!_of->seekable); + return OP_INT64_MAX; + } + if(deltaready_stateprev_packet_gp; + if(gp==-1)return 0; + nbuffered=OP_MAX(_of->od_buffer_size-_of->od_buffer_pos,0); + OP_ALWAYS_TRUE(!op_granpos_add(&gp,gp,-nbuffered)); + li=_of->seekable?_of->cur_link:0; + if(op_granpos_add(&gp,gp,_of->cur_discard_count)<0){ + gp=_of->links[li].pcm_end; + } + return op_get_pcm_offset(_of,gp,li); +} + +void op_set_decode_callback(OggOpusFile *_of, + op_decode_cb_func _decode_cb,void *_ctx){ + _of->decode_cb=_decode_cb; + _of->decode_cb_ctx=_ctx; +} + +int op_set_gain_offset(OggOpusFile *_of, + int _gain_type,opus_int32 _gain_offset_q8){ + if(_gain_type!=OP_HEADER_GAIN&&_gain_type!=OP_TRACK_GAIN + &&_gain_type!=OP_ABSOLUTE_GAIN){ + return OP_EINVAL; + } + _of->gain_type=_gain_type; + /*The sum of header gain and track gain lies in the range [-65536,65534]. + These bounds allow the offset to set the final value to anywhere in the + range [-32768,32767], which is what we'll clamp it to before applying.*/ + _of->gain_offset_q8=OP_CLAMP(-98302,_gain_offset_q8,98303); + op_update_gain(_of); + return 0; +} + +void op_set_dither_enabled(OggOpusFile *_of,int _enabled){ +#if !defined(OP_FIXED_POINT) + _of->dither_disabled=!_enabled; + if(!_enabled)_of->dither_mute=65; +#endif +} + +/*Allocate the decoder scratch buffer. + This is done lazily, since if the user provides large enough buffers, we'll + never need it.*/ +static int op_init_buffer(OggOpusFile *_of){ + int nchannels_max; + if(_of->seekable){ + const OggOpusLink *links; + int nlinks; + int li; + links=_of->links; + nlinks=_of->nlinks; + nchannels_max=1; + for(li=0;liod_buffer=(op_sample *)_ogg_malloc( + sizeof(*_of->od_buffer)*nchannels_max*120*48); + if(_of->od_buffer==NULL)return OP_EFAULT; + return 0; +} + +/*Decode a single packet into the target buffer.*/ +static int op_decode(OggOpusFile *_of,op_sample *_pcm, + const ogg_packet *_op,int _nsamples,int _nchannels){ + int ret; + /*First we try using the application-provided decode callback.*/ + if(_of->decode_cb!=NULL){ +#if defined(OP_FIXED_POINT) + ret=(*_of->decode_cb)(_of->decode_cb_ctx,_of->od,_pcm,_op, + _nsamples,_nchannels,OP_DEC_FORMAT_SHORT,_of->cur_link); +#else + ret=(*_of->decode_cb)(_of->decode_cb_ctx,_of->od,_pcm,_op, + _nsamples,_nchannels,OP_DEC_FORMAT_FLOAT,_of->cur_link); +#endif + } + else ret=OP_DEC_USE_DEFAULT; + /*If the application didn't want to handle decoding, do it ourselves.*/ + if(ret==OP_DEC_USE_DEFAULT){ +#if defined(OP_FIXED_POINT) + ret=opus_multistream_decode(_of->od, + _op->packet,_op->bytes,_pcm,_nsamples,0); +#else + ret=opus_multistream_decode_float(_of->od, + _op->packet,_op->bytes,_pcm,_nsamples,0); +#endif + OP_ASSERT(ret<0||ret==_nsamples); + } + /*If the application returned a positive value other than 0 or + OP_DEC_USE_DEFAULT, fail.*/ + else if(OP_UNLIKELY(ret>0))return OP_EBADPACKET; + if(OP_UNLIKELY(ret<0))return OP_EBADPACKET; + return ret; +} + +/*Read more samples from the stream, using the same API as op_read() or + op_read_float().*/ +static int op_read_native(OggOpusFile *_of, + op_sample *_pcm,int _buf_size,int *_li){ + if(OP_UNLIKELY(_of->ready_stateready_state>=OP_INITSET)){ + int nchannels; + int od_buffer_pos; + int nsamples; + int op_pos; + nchannels=_of->links[_of->seekable?_of->cur_link:0].head.channel_count; + od_buffer_pos=_of->od_buffer_pos; + nsamples=_of->od_buffer_size-od_buffer_pos; + /*If we have buffered samples, return them.*/ + if(nsamples>0){ + if(nsamples*nchannels>_buf_size)nsamples=_buf_size/nchannels; + memcpy(_pcm,_of->od_buffer+nchannels*od_buffer_pos, + sizeof(*_pcm)*nchannels*nsamples); + od_buffer_pos+=nsamples; + _of->od_buffer_pos=od_buffer_pos; + if(_li!=NULL)*_li=_of->cur_link; + return nsamples; + } + /*If we have buffered packets, decode one.*/ + op_pos=_of->op_pos; + if(OP_LIKELY(op_pos<_of->op_count)){ + const ogg_packet *pop; + ogg_int64_t diff; + opus_int32 cur_discard_count; + int duration; + int trimmed_duration; + pop=_of->op+op_pos++; + _of->op_pos=op_pos; + cur_discard_count=_of->cur_discard_count; + duration=op_get_packet_duration(pop->packet,pop->bytes); + /*We don't buffer packets with an invalid TOC sequence.*/ + OP_ASSERT(duration>0); + trimmed_duration=duration; + /*Perform end-trimming.*/ + if(OP_UNLIKELY(pop->e_o_s)){ + if(OP_UNLIKELY(op_granpos_cmp(pop->granulepos, + _of->prev_packet_gp)<=0)){ + trimmed_duration=0; + } + else if(OP_LIKELY(!op_granpos_diff(&diff, + pop->granulepos,_of->prev_packet_gp))){ + trimmed_duration=(int)OP_MIN(diff,trimmed_duration); + } + } + _of->prev_packet_gp=pop->granulepos; + if(OP_UNLIKELY(duration*nchannels>_buf_size)){ + op_sample *buf; + /*If the user's buffer is too small, decode into a scratch buffer.*/ + buf=_of->od_buffer; + if(OP_UNLIKELY(buf==NULL)){ + ret=op_init_buffer(_of); + if(OP_UNLIKELY(ret<0))return ret; + buf=_of->od_buffer; + } + ret=op_decode(_of,buf,pop,duration,nchannels); + if(OP_UNLIKELY(ret<0))return ret; + /*Perform pre-skip/pre-roll.*/ + od_buffer_pos=(int)OP_MIN(trimmed_duration,cur_discard_count); + cur_discard_count-=od_buffer_pos; + _of->cur_discard_count=cur_discard_count; + _of->od_buffer_pos=od_buffer_pos; + _of->od_buffer_size=trimmed_duration; + /*Update bitrate tracking based on the actual samples we used from + what was decoded.*/ + _of->bytes_tracked+=pop->bytes; + _of->samples_tracked+=trimmed_duration-od_buffer_pos; + } + else{ + /*Otherwise decode directly into the user's buffer.*/ + ret=op_decode(_of,_pcm,pop,duration,nchannels); + if(OP_UNLIKELY(ret<0))return ret; + if(OP_LIKELY(trimmed_duration>0)){ + /*Perform pre-skip/pre-roll.*/ + od_buffer_pos=(int)OP_MIN(trimmed_duration,cur_discard_count); + cur_discard_count-=od_buffer_pos; + _of->cur_discard_count=cur_discard_count; + trimmed_duration-=od_buffer_pos; + if(OP_LIKELY(trimmed_duration>0) + &&OP_UNLIKELY(od_buffer_pos>0)){ + memmove(_pcm,_pcm+od_buffer_pos*nchannels, + sizeof(*_pcm)*trimmed_duration*nchannels); + } + /*Update bitrate tracking based on the actual samples we used from + what was decoded.*/ + _of->bytes_tracked+=pop->bytes; + _of->samples_tracked+=trimmed_duration; + if(OP_LIKELY(trimmed_duration>0)){ + if(_li!=NULL)*_li=_of->cur_link; + return trimmed_duration; + } + } + } + /*Don't grab another page yet. + This one might have more packets, or might have buffered data now.*/ + continue; + } + } + /*Suck in another page.*/ + ret=op_fetch_and_process_page(_of,NULL,-1,1,1,0); + if(OP_UNLIKELY(ret==OP_EOF)){ + if(_li!=NULL)*_li=_of->cur_link; + return 0; + } + if(OP_UNLIKELY(ret<0))return ret; + } +} + +/*A generic filter to apply to the decoded audio data. + _src is non-const because we will destructively modify the contents of the + source buffer that we consume in some cases.*/ +typedef int (*op_read_filter_func)(OggOpusFile *_of,void *_dst,int _dst_sz, + op_sample *_src,int _nsamples,int _nchannels); + +/*Decode some samples and then apply a custom filter to them. + This is used to convert to different output formats.*/ +static int op_filter_read_native(OggOpusFile *_of,void *_dst,int _dst_sz, + op_read_filter_func _filter,int *_li){ + int ret; + /*Ensure we have some decoded samples in our buffer.*/ + ret=op_read_native(_of,NULL,0,_li); + /*Now apply the filter to them.*/ + if(OP_LIKELY(ret>=0)&&OP_LIKELY(_of->ready_state>=OP_INITSET)){ + int od_buffer_pos; + od_buffer_pos=_of->od_buffer_pos; + ret=_of->od_buffer_size-od_buffer_pos; + if(OP_LIKELY(ret>0)){ + int nchannels; + nchannels=_of->links[_of->seekable?_of->cur_link:0].head.channel_count; + ret=(*_filter)(_of,_dst,_dst_sz, + _of->od_buffer+nchannels*od_buffer_pos,ret,nchannels); + OP_ASSERT(ret>=0); + OP_ASSERT(ret<=_of->od_buffer_size-od_buffer_pos); + od_buffer_pos+=ret; + _of->od_buffer_pos=od_buffer_pos; + } + } + return ret; +} + +#if !defined(OP_FIXED_POINT)||!defined(OP_DISABLE_FLOAT_API) + +/*Matrices for downmixing from the supported channel counts to stereo. + The matrices with 5 or more channels are normalized to a total volume of 2.0, + since most mixes sound too quiet if normalized to 1.0 (as there is generally + little volume in the side/rear channels).*/ +static const float OP_STEREO_DOWNMIX[OP_NCHANNELS_MAX-2][OP_NCHANNELS_MAX][2]={ + /*3.0*/ + { + {0.5858F,0.0F},{0.4142F,0.4142F},{0.0F,0.5858F} + }, + /*quadrophonic*/ + { + {0.4226F,0.0F},{0.0F,0.4226F},{0.366F,0.2114F},{0.2114F,0.336F} + }, + /*5.0*/ + { + {0.651F,0.0F},{0.46F,0.46F},{0.0F,0.651F},{0.5636F,0.3254F}, + {0.3254F,0.5636F} + }, + /*5.1*/ + { + {0.529F,0.0F},{0.3741F,0.3741F},{0.0F,0.529F},{0.4582F,0.2645F}, + {0.2645F,0.4582F},{0.3741F,0.3741F} + }, + /*6.1*/ + { + {0.4553F,0.0F},{0.322F,0.322F},{0.0F,0.4553F},{0.3943F,0.2277F}, + {0.2277F,0.3943F},{0.2788F,0.2788F},{0.322F,0.322F} + }, + /*7.1*/ + { + {0.3886F,0.0F},{0.2748F,0.2748F},{0.0F,0.3886F},{0.3366F,0.1943F}, + {0.1943F,0.3366F},{0.3366F,0.1943F},{0.1943F,0.3366F},{0.2748F,0.2748F} + } +}; + +#endif + +#if defined(OP_FIXED_POINT) + +/*Matrices for downmixing from the supported channel counts to stereo. + The matrices with 5 or more channels are normalized to a total volume of 2.0, + since most mixes sound too quiet if normalized to 1.0 (as there is generally + little volume in the side/rear channels). + Hence we keep the coefficients in Q14, so the downmix values won't overflow a + 32-bit number.*/ +static const opus_int16 OP_STEREO_DOWNMIX_Q14 + [OP_NCHANNELS_MAX-2][OP_NCHANNELS_MAX][2]={ + /*3.0*/ + { + {9598,0},{6786,6786},{0,9598} + }, + /*quadrophonic*/ + { + {6924,0},{0,6924},{5996,3464},{3464,5996} + }, + /*5.0*/ + { + {10666,0},{7537,7537},{0,10666},{9234,5331},{5331,9234} + }, + /*5.1*/ + { + {8668,0},{6129,6129},{0,8668},{7507,4335},{4335,7507},{6129,6129} + }, + /*6.1*/ + { + {7459,0},{5275,5275},{0,7459},{6460,3731},{3731,6460},{4568,4568}, + {5275,5275} + }, + /*7.1*/ + { + {6368,0},{4502,4502},{0,6368},{5515,3183},{3183,5515},{5515,3183}, + {3183,5515},{4502,4502} + } +}; + +int op_read(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size,int *_li){ + return op_read_native(_of,_pcm,_buf_size,_li); +} + +static int op_stereo_filter(OggOpusFile *_of,void *_dst,int _dst_sz, + op_sample *_src,int _nsamples,int _nchannels){ + (void)_of; + _nsamples=OP_MIN(_nsamples,_dst_sz>>1); + if(_nchannels==2)memcpy(_dst,_src,_nsamples*2*sizeof(*_src)); + else{ + opus_int16 *dst; + int i; + dst=(opus_int16 *)_dst; + if(_nchannels==1){ + for(i=0;i<_nsamples;i++)dst[2*i+0]=dst[2*i+1]=_src[i]; + } + else{ + for(i=0;i<_nsamples;i++){ + opus_int32 l; + opus_int32 r; + int ci; + l=r=0; + for(ci=0;ci<_nchannels;ci++){ + opus_int32 s; + s=_src[_nchannels*i+ci]; + l+=OP_STEREO_DOWNMIX_Q14[_nchannels-3][ci][0]*s; + r+=OP_STEREO_DOWNMIX_Q14[_nchannels-3][ci][1]*s; + } + /*TODO: For 5 or more channels, we should do soft clipping here.*/ + dst[2*i+0]=(opus_int16)OP_CLAMP(-32768,l+8192>>14,32767); + dst[2*i+1]=(opus_int16)OP_CLAMP(-32768,r+8192>>14,32767); + } + } + } + return _nsamples; +} + +int op_read_stereo(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size){ + return op_filter_read_native(_of,_pcm,_buf_size,op_stereo_filter,NULL); +} + +# if !defined(OP_DISABLE_FLOAT_API) + +static int op_short2float_filter(OggOpusFile *_of,void *_dst,int _dst_sz, + op_sample *_src,int _nsamples,int _nchannels){ + float *dst; + int i; + (void)_of; + dst=(float *)_dst; + if(OP_UNLIKELY(_nsamples*_nchannels>_dst_sz))_nsamples=_dst_sz/_nchannels; + _dst_sz=_nsamples*_nchannels; + for(i=0;i<_dst_sz;i++)dst[i]=(1.0F/32768)*_src[i]; + return _nsamples; +} + +int op_read_float(OggOpusFile *_of,float *_pcm,int _buf_size,int *_li){ + return op_filter_read_native(_of,_pcm,_buf_size,op_short2float_filter,_li); +} + +static int op_short2float_stereo_filter(OggOpusFile *_of, + void *_dst,int _dst_sz,op_sample *_src,int _nsamples,int _nchannels){ + float *dst; + int i; + dst=(float *)_dst; + _nsamples=OP_MIN(_nsamples,_dst_sz>>1); + if(_nchannels==1){ + _nsamples=op_short2float_filter(_of,dst,_nsamples,_src,_nsamples,1); + for(i=_nsamples;i-->0;)dst[2*i+0]=dst[2*i+1]=dst[i]; + } + else if(_nchannels<5){ + /*For 3 or 4 channels, we can downmix in fixed point without risk of + clipping.*/ + if(_nchannels>2){ + _nsamples=op_stereo_filter(_of,_src,_nsamples*2, + _src,_nsamples,_nchannels); + } + return op_short2float_filter(_of,dst,_dst_sz,_src,_nsamples,2); + } + else{ + /*For 5 or more channels, we convert to floats and then downmix (so that we + don't risk clipping).*/ + for(i=0;i<_nsamples;i++){ + float l; + float r; + int ci; + l=r=0; + for(ci=0;ci<_nchannels;ci++){ + float s; + s=(1.0F/32768)*_src[_nchannels*i+ci]; + l+=OP_STEREO_DOWNMIX[_nchannels-3][ci][0]*s; + r+=OP_STEREO_DOWNMIX[_nchannels-3][ci][1]*s; + } + dst[2*i+0]=l; + dst[2*i+1]=r; + } + } + return _nsamples; +} + +int op_read_float_stereo(OggOpusFile *_of,float *_pcm,int _buf_size){ + return op_filter_read_native(_of,_pcm,_buf_size, + op_short2float_stereo_filter,NULL); +} + +# endif + +#else + +# if defined(OP_HAVE_LRINTF) +# include +# define op_float2int(_x) (lrintf(_x)) +# else +# define op_float2int(_x) ((int)((_x)+((_x)<0?-0.5F:0.5F))) +# endif + +/*The dithering code here is adapted from opusdec, part of opus-tools. + It was originally written by Greg Maxwell.*/ + +static opus_uint32 op_rand(opus_uint32 _seed){ + return _seed*96314165+907633515&0xFFFFFFFFU; +} + +/*This implements 16-bit quantization with full triangular dither and IIR noise + shaping. + The noise shaping filters were designed by Sebastian Gesemann, and are based + on the LAME ATH curves with flattening to limit their peak gain to 20 dB. + Everyone else's noise shaping filters are mildly crazy. + The 48 kHz version of this filter is just a warped version of the 44.1 kHz + filter and probably could be improved by shifting the HF shelf up in + frequency a little bit, since 48 kHz has a bit more room and being more + conservative against bat-ears is probably more important than more noise + suppression. + This process can increase the peak level of the signal (in theory by the peak + error of 1.5 +20 dB, though that is unobservably rare). + To avoid clipping, the signal is attenuated by a couple thousandths of a dB. + Initially, the approach taken here was to only attenuate by the 99.9th + percentile, making clipping rare but not impossible (like SoX), but the + limited gain of the filter means that the worst case was only two + thousandths of a dB more, so this just uses the worst case. + The attenuation is probably also helpful to prevent clipping in the DAC + reconstruction filters or downstream resampling, in any case.*/ + +# define OP_GAIN (32753.0F) + +# define OP_PRNG_GAIN (1.0F/0xFFFFFFFF) + +/*48 kHz noise shaping filter, sd=2.34.*/ + +static const float OP_FCOEF_B[4]={ + 2.2374F,-0.7339F,-0.1251F,-0.6033F +}; + +static const float OP_FCOEF_A[4]={ + 0.9030F,0.0116F,-0.5853F,-0.2571F +}; + +static int op_float2short_filter(OggOpusFile *_of,void *_dst,int _dst_sz, + float *_src,int _nsamples,int _nchannels){ + opus_int16 *dst; + int ci; + int i; + dst=(opus_int16 *)_dst; + if(OP_UNLIKELY(_nsamples*_nchannels>_dst_sz))_nsamples=_dst_sz/_nchannels; +# if defined(OP_SOFT_CLIP) + if(_of->state_channel_count!=_nchannels){ + for(ci=0;ci<_nchannels;ci++)_of->clip_state[ci]=0; + } + opus_pcm_soft_clip(_src,_nsamples,_nchannels,_of->clip_state); +# endif + if(_of->dither_disabled){ + for(i=0;i<_nchannels*_nsamples;i++){ + dst[i]=op_float2int(OP_CLAMP(-32768,32768.0F*_src[i],32767)); + } + } + else{ + opus_uint32 seed; + int mute; + seed=_of->dither_seed; + mute=_of->dither_mute; + if(_of->state_channel_count!=_nchannels)mute=65; + /*In order to avoid replacing digital silence with quiet dither noise, we + mute if the output has been silent for a while.*/ + if(mute>64)memset(_of->dither_a,0,sizeof(*_of->dither_a)*4*_nchannels); + for(i=0;i<_nsamples;i++){ + int silent; + silent=1; + for(ci=0;ci<_nchannels;ci++){ + float r; + float s; + float err; + int si; + int j; + s=_src[_nchannels*i+ci]; + silent&=s==0; + s*=OP_GAIN; + err=0; + for(j=0;j<4;j++){ + err+=OP_FCOEF_B[j]*_of->dither_b[ci*4+j] + -OP_FCOEF_A[j]*_of->dither_a[ci*4+j]; + } + for(j=3;j-->0;)_of->dither_a[ci*4+j+1]=_of->dither_a[ci*4+j]; + for(j=3;j-->0;)_of->dither_b[ci*4+j+1]=_of->dither_b[ci*4+j]; + _of->dither_a[ci*4]=err; + s-=err; + if(mute>16)r=0; + else{ + seed=op_rand(seed); + r=seed*OP_PRNG_GAIN; + seed=op_rand(seed); + r-=seed*OP_PRNG_GAIN; + } + /*Clamp in float out of paranoia that the input will be > 96 dBFS and + wrap if the integer is clamped.*/ + si=op_float2int(OP_CLAMP(-32768,s+r,32767)); + dst[_nchannels*i+ci]=(opus_int16)si; + /*Including clipping in the noise shaping is generally disastrous: the + futile effort to restore the clipped energy results in more clipping. + However, small amounts---at the level which could normally be created + by dither and rounding---are harmless and can even reduce clipping + somewhat due to the clipping sometimes reducing the dither + rounding + error.*/ + _of->dither_b[ci*4]=mute>16?0:OP_CLAMP(-1.5F,si-s,1.5F); + } + mute++; + if(!silent)mute=0; + } + _of->dither_mute=OP_MIN(mute,65); + _of->dither_seed=seed; + } + _of->state_channel_count=_nchannels; + return _nsamples; +} + +int op_read(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size,int *_li){ + return op_filter_read_native(_of,_pcm,_buf_size,op_float2short_filter,_li); +} + +int op_read_float(OggOpusFile *_of,float *_pcm,int _buf_size,int *_li){ + _of->state_channel_count=0; + return op_read_native(_of,_pcm,_buf_size,_li); +} + +static int op_stereo_filter(OggOpusFile *_of,void *_dst,int _dst_sz, + op_sample *_src,int _nsamples,int _nchannels){ + (void)_of; + _nsamples=OP_MIN(_nsamples,_dst_sz>>1); + if(_nchannels==2)memcpy(_dst,_src,_nsamples*2*sizeof(*_src)); + else{ + float *dst; + int i; + dst=(float *)_dst; + if(_nchannels==1){ + for(i=0;i<_nsamples;i++)dst[2*i+0]=dst[2*i+1]=_src[i]; + } + else{ + for(i=0;i<_nsamples;i++){ + float l; + float r; + int ci; + l=r=0; + for(ci=0;ci<_nchannels;ci++){ + l+=OP_STEREO_DOWNMIX[_nchannels-3][ci][0]*_src[_nchannels*i+ci]; + r+=OP_STEREO_DOWNMIX[_nchannels-3][ci][1]*_src[_nchannels*i+ci]; + } + dst[2*i+0]=l; + dst[2*i+1]=r; + } + } + } + return _nsamples; +} + +static int op_float2short_stereo_filter(OggOpusFile *_of, + void *_dst,int _dst_sz,op_sample *_src,int _nsamples,int _nchannels){ + opus_int16 *dst; + dst=(opus_int16 *)_dst; + if(_nchannels==1){ + int i; + _nsamples=op_float2short_filter(_of,dst,_dst_sz>>1,_src,_nsamples,1); + for(i=_nsamples;i-->0;)dst[2*i+0]=dst[2*i+1]=dst[i]; + } + else{ + if(_nchannels>2){ + _nsamples=OP_MIN(_nsamples,_dst_sz>>1); + _nsamples=op_stereo_filter(_of,_src,_nsamples*2, + _src,_nsamples,_nchannels); + } + _nsamples=op_float2short_filter(_of,dst,_dst_sz,_src,_nsamples,2); + } + return _nsamples; +} + +int op_read_stereo(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size){ + return op_filter_read_native(_of,_pcm,_buf_size, + op_float2short_stereo_filter,NULL); +} + +int op_read_float_stereo(OggOpusFile *_of,float *_pcm,int _buf_size){ + _of->state_channel_count=0; + return op_filter_read_native(_of,_pcm,_buf_size,op_stereo_filter,NULL); +} + +#endif diff --git a/TelegramClient.Opus/opus/opusfile/opusfile.h b/TelegramClient.Opus/opus/opusfile/opusfile.h new file mode 100755 index 0000000..ae58da9 --- /dev/null +++ b/TelegramClient.Opus/opus/opusfile/opusfile.h @@ -0,0 +1,2089 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: stdio-based convenience library for opening/seeking/decoding + last mod: $Id: vorbisfile.h 17182 2010-04-29 03:48:32Z xiphmont $ + + ********************************************************************/ +#if !defined(_opusfile_h) +# define _opusfile_h (1) + +/**\mainpage + \section Introduction + + This is the documentation for the libopusfile C API. + + The libopusfile package provides a convenient high-level API for + decoding and basic manipulation of all Ogg Opus audio streams. + libopusfile is implemented as a layer on top of Xiph.Org's + reference + libogg + and + libopus + libraries. + + libopusfile provides several sets of built-in routines for + file/stream access, and may also use custom stream I/O routines provided by + the embedded environment. + There are built-in I/O routines provided for ANSI-compliant + stdio (FILE *), memory buffers, and URLs + (including URLs, plus optionally and URLs). + + \section Organization + + The main API is divided into several sections: + - \ref stream_open_close + - \ref stream_info + - \ref stream_decoding + - \ref stream_seeking + + Several additional sections are not tied to the main API. + - \ref stream_callbacks + - \ref header_info + - \ref error_codes + + \section Overview + + The libopusfile API always decodes files to 48 kHz. + The original sample rate is not preserved by the lossy compression, though + it is stored in the header to allow you to resample to it after decoding + (the libopusfile API does not currently provide a resampler, + but the + the + Speex resampler is a good choice if you need one). + In general, if you are playing back the audio, you should leave it at + 48 kHz, provided your audio hardware supports it. + When decoding to a file, it may be worth resampling back to the original + sample rate, so as not to surprise users who might not expect the sample + rate to change after encoding to Opus and decoding. + + Opus files can contain anywhere from 1 to 255 channels of audio. + The channel mappings for up to 8 channels are the same as the + Vorbis + mappings. + A special stereo API can convert everything to 2 channels, making it simple + to support multichannel files in an application which only has stereo + output. + Although the libopusfile ABI provides support for the theoretical + maximum number of channels, the current implementation does not support + files with more than 8 channels, as they do not have well-defined channel + mappings. + + Like all Ogg files, Opus files may be "chained". + That is, multiple Opus files may be combined into a single, longer file just + by concatenating the original files. + This is commonly done in internet radio streaming, as it allows the title + and artist to be updated each time the song changes, since each link in the + chain includes its own set of metadata. + + libopusfile fully supports chained files. + It will decode the first Opus stream found in each link of a chained file + (ignoring any other streams that might be concurrently multiplexed with it, + such as a video stream). + + The channel count can also change between links. + If your application is not prepared to deal with this, it can use the stereo + API to ensure the audio from all links will always get decoded into a + common format. + Since libopusfile always decodes to 48 kHz, you do not have to + worry about the sample rate changing between links (as was possible with + Vorbis). + This makes application support for chained files with libopusfile + very easy.*/ + +# if defined(__cplusplus) +extern "C" { +# endif + +# include +# include +# include +# include "opus_multistream.h" + +/**@cond PRIVATE*/ + +/*Enable special features for gcc and gcc-compatible compilers.*/ +# if !defined(OP_GNUC_PREREQ) +# if defined(__GNUC__)&&defined(__GNUC_MINOR__) +# define OP_GNUC_PREREQ(_maj,_min) \ + ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) +# else +# define OP_GNUC_PREREQ(_maj,_min) 0 +# endif +# endif + +# if OP_GNUC_PREREQ(4,0) +# pragma GCC visibility push(default) +# endif + +typedef struct OpusHead OpusHead; +typedef struct OpusTags OpusTags; +typedef struct OpusPictureTag OpusPictureTag; +typedef struct OpusServerInfo OpusServerInfo; +typedef struct OpusFileCallbacks OpusFileCallbacks; +typedef struct OggOpusFile OggOpusFile; + +/*Warning attributes for libopusfile functions.*/ +# if OP_GNUC_PREREQ(3,4) +# define OP_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +# else +# define OP_WARN_UNUSED_RESULT +# endif +# if OP_GNUC_PREREQ(3,4) +# define OP_ARG_NONNULL(_x) __attribute__((__nonnull__(_x))) +# else +# define OP_ARG_NONNULL(_x) +# endif + +/**@endcond*/ + +/**\defgroup error_codes Error Codes*/ +/*@{*/ +/**\name List of possible error codes + Many of the functions in this library return a negative error code when a + function fails. + This list provides a brief explanation of the common errors. + See each individual function for more details on what a specific error code + means in that context.*/ +/*@{*/ + +/**A request did not succeed.*/ +#define OP_FALSE (-1) +/*Currently not used externally.*/ +#define OP_EOF (-2) +/**There was a hole in the page sequence numbers (e.g., a page was corrupt or + missing).*/ +#define OP_HOLE (-3) +/**An underlying read, seek, or tell operation failed when it should have + succeeded.*/ +#define OP_EREAD (-128) +/**A NULL pointer was passed where one was unexpected, or an + internal memory allocation failed, or an internal library error was + encountered.*/ +#define OP_EFAULT (-129) +/**The stream used a feature that is not implemented, such as an unsupported + channel family.*/ +#define OP_EIMPL (-130) +/**One or more parameters to a function were invalid.*/ +#define OP_EINVAL (-131) +/**A purported Ogg Opus stream did not begin with an Ogg page, a purported + header packet did not start with one of the required strings, "OpusHead" or + "OpusTags", or a link in a chained file was encountered that did not + contain any logical Opus streams.*/ +#define OP_ENOTFORMAT (-132) +/**A required header packet was not properly formatted, contained illegal + values, or was missing altogether.*/ +#define OP_EBADHEADER (-133) +/**The ID header contained an unrecognized version number.*/ +#define OP_EVERSION (-134) +/*Currently not used at all.*/ +#define OP_ENOTAUDIO (-135) +/**An audio packet failed to decode properly. + This is usually caused by a multistream Ogg packet where the durations of + the individual Opus packets contained in it are not all the same.*/ +#define OP_EBADPACKET (-136) +/**We failed to find data we had seen before, or the bitstream structure was + sufficiently malformed that seeking to the target destination was + impossible.*/ +#define OP_EBADLINK (-137) +/**An operation that requires seeking was requested on an unseekable stream.*/ +#define OP_ENOSEEK (-138) +/**The first or last granule position of a link failed basic validity checks.*/ +#define OP_EBADTIMESTAMP (-139) + +/*@}*/ +/*@}*/ + +/**\defgroup header_info Header Information*/ +/*@{*/ + +/**The maximum number of channels in an Ogg Opus stream.*/ +#define OPUS_CHANNEL_COUNT_MAX (255) + +/**Ogg Opus bitstream information. + This contains the basic playback parameters for a stream, and corresponds to + the initial ID header packet of an Ogg Opus stream.*/ +struct OpusHead{ + /**The Ogg Opus format version, in the range 0...255. + The top 4 bits represent a "major" version, and the bottom four bits + represent backwards-compatible "minor" revisions. + The current specification describes version 1. + This library will recognize versions up through 15 as backwards compatible + with the current specification. + An earlier draft of the specification described a version 0, but the only + difference between version 1 and version 0 is that version 0 did + not specify the semantics for handling the version field.*/ + int version; + /**The number of channels, in the range 1...255.*/ + int channel_count; + /**The number of samples that should be discarded from the beginning of the + stream.*/ + unsigned pre_skip; + /**The sampling rate of the original input. + All Opus audio is coded at 48 kHz, and should also be decoded at 48 kHz + for playback (unless the target hardware does not support this sampling + rate). + However, this field may be used to resample the audio back to the original + sampling rate, for example, when saving the output to a file.*/ + opus_uint32 input_sample_rate; + /**The gain to apply to the decoded output, in dB, as a Q8 value in the range + -32768...32767. + The libopusfile API will automatically apply this gain to the + decoded output before returning it, scaling it by + pow(10,output_gain/(20.0*256)).*/ + int output_gain; + /**The channel mapping family, in the range 0...255. + Channel mapping family 0 covers mono or stereo in a single stream. + Channel mapping family 1 covers 1 to 8 channels in one or more streams, + using the Vorbis speaker assignments. + Channel mapping family 255 covers 1 to 255 channels in one or more + streams, but without any defined speaker assignment.*/ + int mapping_family; + /**The number of Opus streams in each Ogg packet, in the range 1...255.*/ + int stream_count; + /**The number of coupled Opus streams in each Ogg packet, in the range + 0...127. + This must satisfy 0 <= coupled_count <= stream_count and + coupled_count + stream_count <= 255. + The coupled streams appear first, before all uncoupled streams, in an Ogg + Opus packet.*/ + int coupled_count; + /**The mapping from coded stream channels to output channels. + Let index=mapping[k] be the value for channel k. + If index<2*coupled_count, then it refers to the left channel + from stream (index/2) if even, and the right channel from + stream (index/2) if odd. + Otherwise, it refers to the output of the uncoupled stream + (index-coupled_count).*/ + unsigned char mapping[OPUS_CHANNEL_COUNT_MAX]; +}; + +/**The metadata from an Ogg Opus stream. + + This structure holds the in-stream metadata corresponding to the 'comment' + header packet of an Ogg Opus stream. + The comment header is meant to be used much like someone jotting a quick + note on the label of a CD. + It should be a short, to the point text note that can be more than a couple + words, but not more than a short paragraph. + + The metadata is stored as a series of (tag, value) pairs, in length-encoded + string vectors, using the same format as Vorbis (without the final "framing + bit"), Theora, and Speex, except for the packet header. + The first occurrence of the '=' character delimits the tag and value. + A particular tag may occur more than once, and order is significant. + The character set encoding for the strings is always UTF-8, but the tag + names are limited to ASCII, and treated as case-insensitive. + See the Vorbis + comment header specification for details. + + In filling in this structure, libopusfile will null-terminate the + #user_comments strings for safety. + However, the bitstream format itself treats them as 8-bit clean vectors, + possibly containing NUL characters, so the #comment_lengths array should be + treated as their authoritative length. + + This structure is binary and source-compatible with a + vorbis_comment, and pointers to it may be freely cast to + vorbis_comment pointers, and vice versa. + It is provided as a separate type to avoid introducing a compile-time + dependency on the libvorbis headers.*/ +struct OpusTags{ + /**The array of comment string vectors.*/ + char **user_comments; + /**An array of the corresponding length of each vector, in bytes.*/ + int *comment_lengths; + /**The total number of comment streams.*/ + int comments; + /**The null-terminated vendor string. + This identifies the software used to encode the stream.*/ + char *vendor; +}; + +/**\name Picture tag image formats*/ +/*@{*/ + +/**The MIME type was not recognized, or the image data did not match the + declared MIME type.*/ +#define OP_PIC_FORMAT_UNKNOWN (-1) +/**The MIME type indicates the image data is really a URL.*/ +#define OP_PIC_FORMAT_URL (0) +/**The image is a JPEG.*/ +#define OP_PIC_FORMAT_JPEG (1) +/**The image is a PNG.*/ +#define OP_PIC_FORMAT_PNG (2) +/**The image is a GIF.*/ +#define OP_PIC_FORMAT_GIF (3) + +/*@}*/ + +/**The contents of a METADATA_BLOCK_PICTURE tag.*/ +struct OpusPictureTag{ + /**The picture type according to the ID3v2 APIC frame: +
      +
    1. Other
    2. +
    3. 32x32 pixels 'file icon' (PNG only)
    4. +
    5. Other file icon
    6. +
    7. Cover (front)
    8. +
    9. Cover (back)
    10. +
    11. Leaflet page
    12. +
    13. Media (e.g. label side of CD)
    14. +
    15. Lead artist/lead performer/soloist
    16. +
    17. Artist/performer
    18. +
    19. Conductor
    20. +
    21. Band/Orchestra
    22. +
    23. Composer
    24. +
    25. Lyricist/text writer
    26. +
    27. Recording Location
    28. +
    29. During recording
    30. +
    31. During performance
    32. +
    33. Movie/video screen capture
    34. +
    35. A bright colored fish
    36. +
    37. Illustration
    38. +
    39. Band/artist logotype
    40. +
    41. Publisher/Studio logotype
    42. +
    + Others are reserved and should not be used. + There may only be one each of picture type 1 and 2 in a file.*/ + opus_int32 type; + /**The MIME type of the picture, in printable ASCII characters 0x20-0x7E. + The MIME type may also be "-->" to signify that the data part + is a URL pointing to the picture instead of the picture data itself. + In this case, a terminating NUL is appended to the URL string in #data, + but #data_length is set to the length of the string excluding that + terminating NUL.*/ + char *mime_type; + /**The description of the picture, in UTF-8.*/ + char *description; + /**The width of the picture in pixels.*/ + opus_uint32 width; + /**The height of the picture in pixels.*/ + opus_uint32 height; + /**The color depth of the picture in bits-per-pixel (not + bits-per-channel).*/ + opus_uint32 depth; + /**For indexed-color pictures (e.g., GIF), the number of colors used, or 0 + for non-indexed pictures.*/ + opus_uint32 colors; + /**The length of the picture data in bytes.*/ + opus_uint32 data_length; + /**The binary picture data.*/ + unsigned char *data; + /**The format of the picture data, if known. + One of +
      +
    • #OP_PIC_FORMAT_UNKNOWN,
    • +
    • #OP_PIC_FORMAT_URL,
    • +
    • #OP_PIC_FORMAT_JPEG,
    • +
    • #OP_PIC_FORMAT_PNG, or
    • +
    • #OP_PIC_FORMAT_GIF.
    • +
    */ + int format; +}; + +/**\name Functions for manipulating header data + + These functions manipulate the #OpusHead and #OpusTags structures, + which describe the audio parameters and tag-value metadata, respectively. + These can be used to query the headers returned by libopusfile, or + to parse Opus headers from sources other than an Ogg Opus stream, provided + they use the same format.*/ +/*@{*/ + +/**Parses the contents of the ID header packet of an Ogg Opus stream. + \param[out] _head Returns the contents of the parsed packet. + The contents of this structure are untouched on error. + This may be NULL to merely test the header + for validity. + \param[in] _data The contents of the ID header packet. + \param _len The number of bytes of data in the ID header packet. + \return 0 on success or a negative value on error. + \retval #OP_ENOTFORMAT If the data does not start with the "OpusHead" + string. + \retval #OP_EVERSION If the version field signaled a version this library + does not know how to parse. + \retval #OP_EIMPL If the channel mapping family was 255, which general + purpose players should not attempt to play. + \retval #OP_EBADHEADER If the contents of the packet otherwise violate the + Ogg Opus specification: +
      +
    • Insufficient data,
    • +
    • Too much data for the known minor versions,
    • +
    • An unrecognized channel mapping family,
    • +
    • Zero channels or too many channels,
    • +
    • Zero coded streams,
    • +
    • Too many coupled streams, or
    • +
    • An invalid channel mapping index.
    • +
    */ +OP_WARN_UNUSED_RESULT int opus_head_parse(OpusHead *_head, + const unsigned char *_data,size_t _len) OP_ARG_NONNULL(2); + +/**Converts a granule position to a sample offset for a given Ogg Opus stream. + The sample offset is simply _gp-_head->pre_skip. + Granule position values smaller than OpusHead#pre_skip correspond to audio + that should never be played, and thus have no associated sample offset. + This function returns -1 for such values. + This function also correctly handles extremely large granule positions, + which may have wrapped around to a negative number when stored in a signed + ogg_int64_t value. + \param _head The #OpusHead information from the ID header of the stream. + \param _gp The granule position to convert. + \return The sample offset associated with the given granule position + (counting at a 48 kHz sampling rate), or the special value -1 on + error (i.e., the granule position was smaller than the pre-skip + amount).*/ +ogg_int64_t opus_granule_sample(const OpusHead *_head,ogg_int64_t _gp) + OP_ARG_NONNULL(1); + +/**Parses the contents of the 'comment' header packet of an Ogg Opus stream. + \param[out] _tags An uninitialized #OpusTags structure. + This returns the contents of the parsed packet. + The contents of this structure are untouched on error. + This may be NULL to merely test the header + for validity. + \param[in] _data The contents of the 'comment' header packet. + \param _len The number of bytes of data in the 'info' header packet. + \retval 0 Success. + \retval #OP_ENOTFORMAT If the data does not start with the "OpusTags" + string. + \retval #OP_EBADHEADER If the contents of the packet otherwise violate the + Ogg Opus specification. + \retval #OP_EFAULT If there wasn't enough memory to store the tags.*/ +OP_WARN_UNUSED_RESULT int opus_tags_parse(OpusTags *_tags, + const unsigned char *_data,size_t _len) OP_ARG_NONNULL(2); + +/**Performs a deep copy of an #OpusTags structure. + \param _dst The #OpusTags structure to copy into. + If this function fails, the contents of this structure remain + untouched. + \param _src The #OpusTags structure to copy from. + \retval 0 Success. + \retval #OP_EFAULT If there wasn't enough memory to copy the tags.*/ +int opus_tags_copy(OpusTags *_dst,const OpusTags *_src) OP_ARG_NONNULL(1); + +/**Initializes an #OpusTags structure. + This should be called on a freshly allocated #OpusTags structure before + attempting to use it. + \param _tags The #OpusTags structure to initialize.*/ +void opus_tags_init(OpusTags *_tags) OP_ARG_NONNULL(1); + +/**Add a (tag, value) pair to an initialized #OpusTags structure. + \note Neither opus_tags_add() nor opus_tags_add_comment() support values + containing embedded NULs, although the bitstream format does support them. + To add such tags, you will need to manipulate the #OpusTags structure + directly. + \param _tags The #OpusTags structure to add the (tag, value) pair to. + \param _tag A NUL-terminated, case-insensitive, ASCII string containing + the tag to add (without an '=' character). + \param _value A NUL-terminated UTF-8 containing the corresponding value. + \return 0 on success, or a negative value on failure. + \retval #OP_EFAULT An internal memory allocation failed.*/ +int opus_tags_add(OpusTags *_tags,const char *_tag,const char *_value) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2) OP_ARG_NONNULL(3); + +/**Add a comment to an initialized #OpusTags structure. + \note Neither opus_tags_add_comment() nor opus_tags_add() support comments + containing embedded NULs, although the bitstream format does support them. + To add such tags, you will need to manipulate the #OpusTags structure + directly. + \param _tags The #OpusTags structure to add the comment to. + \param _comment A NUL-terminated UTF-8 string containing the comment in + "TAG=value" form. + \return 0 on success, or a negative value on failure. + \retval #OP_EFAULT An internal memory allocation failed.*/ +int opus_tags_add_comment(OpusTags *_tags,const char *_comment) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Look up a comment value by its tag. + \param _tags An initialized #OpusTags structure. + \param _tag The tag to look up. + \param _count The instance of the tag. + The same tag can appear multiple times, each with a distinct + value, so an index is required to retrieve them all. + The order in which these values appear is significant and + should be preserved. + Use opus_tags_query_count() to get the legal range for the + \a _count parameter. + \return A pointer to the queried tag's value. + This points directly to data in the #OpusTags structure. + It should not be modified or freed by the application, and + modifications to the structure may invalidate the pointer. + \retval NULL If no matching tag is found.*/ +const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Look up the number of instances of a tag. + Call this first when querying for a specific tag and then iterate over the + number of instances with separate calls to opus_tags_query() to retrieve + all the values for that tag in order. + \param _tags An initialized #OpusTags structure. + \param _tag The tag to look up. + \return The number of instances of this particular tag.*/ +int opus_tags_query_count(const OpusTags *_tags,const char *_tag) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Get the track gain from an R128_TRACK_GAIN tag, if one was specified. + This searches for the first R128_TRACK_GAIN tag with a valid signed, + 16-bit decimal integer value and returns the value. + This routine is exposed merely for convenience for applications which wish + to do something special with the track gain (i.e., display it). + If you simply wish to apply the track gain instead of the header gain, you + can use op_set_gain_offset() with an #OP_TRACK_GAIN type and no offset. + \param _tags An initialized #OpusTags structure. + \param[out] _gain_q8 The track gain, in 1/256ths of a dB. + This will lie in the range [-32768,32767], and should + be applied in addition to the header gain. + On error, no value is returned, and the previous + contents remain unchanged. + \return 0 on success, or a negative value on error. + \retval #OP_FALSE There was no track gain available in the given tags.*/ +int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8) + OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Clears the #OpusTags structure. + This should be called on an #OpusTags structure after it is no longer + needed. + It will free all memory used by the structure members. + \param _tags The #OpusTags structure to clear.*/ +void opus_tags_clear(OpusTags *_tags) OP_ARG_NONNULL(1); + +/**Check if \a _comment is an instance of a \a _tag_name tag. + \see opus_tagncompare + \param _tag_name A NUL-terminated, case-insensitive, ASCII string containing + the name of the tag to check for (without the terminating + '=' character). + \param _comment The comment string to check. + \return An integer less than, equal to, or greater than zero if \a _comment + is found respectively, to be less than, to match, or be greater + than a "tag=value" string whose tag matches \a _tag_name.*/ +int opus_tagcompare(const char *_tag_name,const char *_comment); + +/**Check if \a _comment is an instance of a \a _tag_name tag. + This version is slightly more efficient than opus_tagcompare() if the length + of the tag name is already known (e.g., because it is a constant). + \see opus_tagcompare + \param _tag_name A case-insensitive ASCII string containing the name of the + tag to check for (without the terminating '=' character). + \param _tag_len The number of characters in the tag name. + This must be non-negative. + \param _comment The comment string to check. + \return An integer less than, equal to, or greater than zero if \a _comment + is found respectively, to be less than, to match, or be greater + than a "tag=value" string whose tag matches the first \a _tag_len + characters of \a _tag_name.*/ +int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment); + +/**Parse a single METADATA_BLOCK_PICTURE tag. + This decodes the BASE64-encoded content of the tag and returns a structure + with the MIME type, description, image parameters (if known), and the + compressed image data. + If the MIME type indicates the presence of an image format we recognize + (JPEG, PNG, or GIF) and the actual image data contains the magic signature + associated with that format, then the OpusPictureTag::format field will be + set to the corresponding format. + This is provided as a convenience to avoid requiring applications to parse + the MIME type and/or do their own format detection for the commonly used + formats. + In this case, we also attempt to extract the image parameters directly from + the image data (overriding any that were present in the tag, which the + specification says applications are not meant to rely on). + The application must still provide its own support for actually decoding the + image data and, if applicable, retrieving that data from URLs. + \param[out] _pic Returns the parsed picture data. + No sanitation is done on the type, MIME type, or + description fields, so these might return invalid values. + The contents of this structure are left unmodified on + failure. + \param _tag The METADATA_BLOCK_PICTURE tag contents. + The leading "METADATA_BLOCK_PICTURE=" portion is optional, + to allow the function to be used on either directly on the + values in OpusTags::user_comments or on the return value + of opus_tags_query(). + \return 0 on success or a negative value on error. + \retval #OP_ENOTFORMAT The METADATA_BLOCK_PICTURE contents were not valid. + \retval #OP_EFAULT There was not enough memory to store the picture tag + contents.*/ +OP_WARN_UNUSED_RESULT int opus_picture_tag_parse(OpusPictureTag *_pic, + const char *_tag) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Initializes an #OpusPictureTag structure. + This should be called on a freshly allocated #OpusPictureTag structure + before attempting to use it. + \param _pic The #OpusPictureTag structure to initialize.*/ +void opus_picture_tag_init(OpusPictureTag *_pic) OP_ARG_NONNULL(1); + +/**Clears the #OpusPictureTag structure. + This should be called on an #OpusPictureTag structure after it is no longer + needed. + It will free all memory used by the structure members. + \param _pic The #OpusPictureTag structure to clear.*/ +void opus_picture_tag_clear(OpusPictureTag *_pic) OP_ARG_NONNULL(1); + +/*@}*/ + +/*@}*/ + +/**\defgroup url_options URL Reading Options*/ +/*@{*/ +/**\name URL reading options + Options for op_url_stream_create() and associated functions. + These allow you to provide proxy configuration parameters, skip SSL + certificate checks, etc. + Options are processed in order, and if the same option is passed multiple + times, only the value specified by the last occurrence has an effect + (unless otherwise specified). + They may be expanded in the future.*/ +/*@{*/ + +/**@cond PRIVATE*/ + +/*These are the raw numbers used to define the request codes. + They should not be used directly.*/ +#define OP_SSL_SKIP_CERTIFICATE_CHECK_REQUEST (6464) +#define OP_HTTP_PROXY_HOST_REQUEST (6528) +#define OP_HTTP_PROXY_PORT_REQUEST (6592) +#define OP_HTTP_PROXY_USER_REQUEST (6656) +#define OP_HTTP_PROXY_PASS_REQUEST (6720) +#define OP_GET_SERVER_INFO_REQUEST (6784) + +#define OP_URL_OPT(_request) ((_request)+(char *)0) + +/*These macros trigger compilation errors or warnings if the wrong types are + provided to one of the URL options.*/ +#define OP_CHECK_INT(_x) ((void)((_x)==(opus_int32)0),(opus_int32)(_x)) +#define OP_CHECK_CONST_CHAR_PTR(_x) ((_x)+((_x)-(const char *)(_x))) +#define OP_CHECK_SERVER_INFO_PTR(_x) ((_x)+((_x)-(OpusServerInfo *)(_x))) + +/**@endcond*/ + +/**HTTP/Shoutcast/Icecast server information associated with a URL.*/ +struct OpusServerInfo{ + /**The name of the server (icy-name/ice-name). + This is NULL if there was no icy-name or + ice-name header.*/ + char *name; + /**A short description of the server (icy-description/ice-description). + This is NULL if there was no icy-description or + ice-description header.*/ + char *description; + /**The genre the server falls under (icy-genre/ice-genre). + This is NULL if there was no icy-genre or + ice-genre header.*/ + char *genre; + /**The homepage for the server (icy-url/ice-url). + This is NULL if there was no icy-url or + ice-url header.*/ + char *url; + /**The software used by the origin server (Server). + This is NULL if there was no Server header.*/ + char *server; + /**The media type of the entity sent to the recepient (Content-Type). + This is NULL if there was no Content-Type + header.*/ + char *content_type; + /**The nominal stream bitrate in kbps (icy-br/ice-bitrate). + This is -1 if there was no icy-br or + ice-bitrate header.*/ + opus_int32 bitrate_kbps; + /**Flag indicating whether the server is public (1) or not + (0) (icy-pub/ice-public). + This is -1 if there was no icy-pub or + ice-public header.*/ + int is_public; + /**Flag indicating whether the server is using HTTPS instead of HTTP. + This is 0 unless HTTPS is being used. + This may not match the protocol used in the original URL if there were + redirections.*/ + int is_ssl; +}; + +/**Initializes an #OpusServerInfo structure. + All fields are set as if the corresponding header was not available. + \param _info The #OpusServerInfo structure to initialize. + \note If you use this function, you must link against libopusurl.*/ +void opus_server_info_init(OpusServerInfo *_info) OP_ARG_NONNULL(1); + +/**Clears the #OpusServerInfo structure. + This should be called on an #OpusServerInfo structure after it is no longer + needed. + It will free all memory used by the structure members. + \param _info The #OpusServerInfo structure to clear. + \note If you use this function, you must link against libopusurl.*/ +void opus_server_info_clear(OpusServerInfo *_info) OP_ARG_NONNULL(1); + +/**Skip the certificate check when connecting via TLS/SSL (https). + \param _b opus_int32: Whether or not to skip the certificate + check. + The check will be skipped if \a _b is non-zero, and will not be + skipped if \a _b is zero. + \hideinitializer*/ +#define OP_SSL_SKIP_CERTIFICATE_CHECK(_b) \ + OP_URL_OPT(OP_SSL_SKIP_CERTIFICATE_CHECK_REQUEST),OP_CHECK_INT(_b) + +/**Proxy connections through the given host. + If no port is specified via #OP_HTTP_PROXY_PORT, the port number defaults + to 8080 (http-alt). + All proxy parameters are ignored for non-http and non-https URLs. + \param _host const char *: The proxy server hostname. + This may be NULL to disable the use of a proxy + server. + \hideinitializer*/ +#define OP_HTTP_PROXY_HOST(_host) \ + OP_URL_OPT(OP_HTTP_PROXY_HOST_REQUEST),OP_CHECK_CONST_CHAR_PTR(_host) + +/**Use the given port when proxying connections. + This option only has an effect if #OP_HTTP_PROXY_HOST is specified with a + non-NULL \a _host. + If this option is not provided, the proxy port number defaults to 8080 + (http-alt). + All proxy parameters are ignored for non-http and non-https URLs. + \param _port opus_int32: The proxy server port. + This must be in the range 0...65535 (inclusive), or the + URL function this is passed to will fail. + \hideinitializer*/ +#define OP_HTTP_PROXY_PORT(_port) \ + OP_URL_OPT(OP_HTTP_PROXY_PORT_REQUEST),OP_CHECK_INT(_port) + +/**Use the given user name for authentication when proxying connections. + All proxy parameters are ignored for non-http and non-https URLs. + \param _user const char *: The proxy server user name. + This may be NULL to disable proxy + authentication. + A non-NULL value only has an effect + if #OP_HTTP_PROXY_HOST and #OP_HTTP_PROXY_PASS + are also specified with non-NULL + arguments. + \hideinitializer*/ +#define OP_HTTP_PROXY_USER(_user) \ + OP_URL_OPT(OP_HTTP_PROXY_USER_REQUEST),OP_CHECK_CONST_CHAR_PTR(_user) + +/**Use the given password for authentication when proxying connections. + All proxy parameters are ignored for non-http and non-https URLs. + \param _pass const char *: The proxy server password. + This may be NULL to disable proxy + authentication. + A non-NULL value only has an effect + if #OP_HTTP_PROXY_HOST and #OP_HTTP_PROXY_USER + are also specified with non-NULL + arguments. + \hideinitializer*/ +#define OP_HTTP_PROXY_PASS(_pass) \ + OP_URL_OPT(OP_HTTP_PROXY_PASS_REQUEST),OP_CHECK_CONST_CHAR_PTR(_pass) + +/**Parse information about the streaming server (if any) and return it. + Very little validation is done. + In particular, OpusServerInfo::url may not be a valid URL, + OpusServerInfo::bitrate_kbps may not really be in kbps, and + OpusServerInfo::content_type may not be a valid MIME type. + The character set of the string fields is not specified anywhere, and should + not be assumed to be valid UTF-8. + \param _info OpusServerInfo *: Returns information about the server. + If there is any error opening the stream, the + contents of this structure remain + unmodified. + On success, fills in the structure with the + server information that was available, if + any. + After a successful return, the contents of + this structure should be freed by calling + opus_server_info_clear(). + \hideinitializer*/ +#define OP_GET_SERVER_INFO(_info) \ + OP_URL_OPT(OP_GET_SERVER_INFO_REQUEST),OP_CHECK_SERVER_INFO_PTR(_info) + +/*@}*/ +/*@}*/ + +/**\defgroup stream_callbacks Abstract Stream Reading Interface*/ +/*@{*/ +/**\name Functions for reading from streams + These functions define the interface used to read from and seek in a stream + of data. + A stream does not need to implement seeking, but the decoder will not be + able to seek if it does not do so. + These functions also include some convenience routines for working with + standard FILE pointers, complete streams stored in a single + block of memory, or URLs.*/ +/*@{*/ + +/**Reads up to \a _nbytes bytes of data from \a _stream. + \param _stream The stream to read from. + \param[out] _ptr The buffer to store the data in. + \param _nbytes The maximum number of bytes to read. + This function may return fewer, though it will not + return zero unless it reaches end-of-file. + \return The number of bytes successfully read, or a negative value on + error.*/ +typedef int (*op_read_func)(void *_stream,unsigned char *_ptr,int _nbytes); + +/**Sets the position indicator for \a _stream. + The new position, measured in bytes, is obtained by adding \a _offset + bytes to the position specified by \a _whence. + If \a _whence is set to SEEK_SET, SEEK_CUR, or + SEEK_END, the offset is relative to the start of the stream, + the current position indicator, or end-of-file, respectively. + \retval 0 Success. + \retval -1 Seeking is not supported or an error occurred. + errno need not be set.*/ +typedef int (*op_seek_func)(void *_stream,opus_int64 _offset,int _whence); + +/**Obtains the current value of the position indicator for \a _stream. + \return The current position indicator.*/ +typedef opus_int64 (*op_tell_func)(void *_stream); + +/**Closes the underlying stream. + \retval 0 Success. + \retval EOF An error occurred. + errno need not be set.*/ +typedef int (*op_close_func)(void *_stream); + +/**The callbacks used to access non-FILE stream resources. + The function prototypes are basically the same as for the stdio functions + fread(), fseek(), ftell(), and + fclose(). + The differences are that the FILE * arguments have been + replaced with a void *, which is to be used as a pointer to + whatever internal data these functions might need, that #seek and #tell + take and return 64-bit offsets, and that #seek must return -1 if + the stream is unseekable.*/ +struct OpusFileCallbacks{ + /**Used to read data from the stream. + This must not be NULL.*/ + op_read_func read; + /**Used to seek in the stream. + This may be NULL if seeking is not implemented.*/ + op_seek_func seek; + /**Used to return the current read position in the stream. + This may be NULL if seeking is not implemented.*/ + op_tell_func tell; + /**Used to close the stream when the decoder is freed. + This may be NULL to leave the stream open.*/ + op_close_func close; +}; + +/**Opens a stream with fopen() and fills in a set of callbacks + that can be used to access it. + This is useful to avoid writing your own portable 64-bit seeking wrappers, + and also avoids cross-module linking issues on Windows, where a + FILE * must be accessed by routines defined in the same module + that opened it. + \param[out] _cb The callbacks to use for this file. + If there is an error opening the file, nothing will be + filled in here. + \param _path The path to the file to open. + On Windows, this string must be UTF-8 (to allow access to + files whose names cannot be represented in the current + MBCS code page). + All other systems use the native character encoding. + \param _mode The mode to open the file in. + \return A stream handle to use with the callbacks, or NULL on + error.*/ +OP_WARN_UNUSED_RESULT void *op_fopen(OpusFileCallbacks *_cb, + const char *_path,const char *_mode) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2) + OP_ARG_NONNULL(3); + +/**Opens a stream with fdopen() and fills in a set of callbacks + that can be used to access it. + This is useful to avoid writing your own portable 64-bit seeking wrappers, + and also avoids cross-module linking issues on Windows, where a + FILE * must be accessed by routines defined in the same module + that opened it. + \param[out] _cb The callbacks to use for this file. + If there is an error opening the file, nothing will be + filled in here. + \param _fd The file descriptor to open. + \param _mode The mode to open the file in. + \return A stream handle to use with the callbacks, or NULL on + error.*/ +OP_WARN_UNUSED_RESULT void *op_fdopen(OpusFileCallbacks *_cb, + int _fd,const char *_mode) OP_ARG_NONNULL(1) OP_ARG_NONNULL(3); + +/**Opens a stream with freopen() and fills in a set of callbacks + that can be used to access it. + This is useful to avoid writing your own portable 64-bit seeking wrappers, + and also avoids cross-module linking issues on Windows, where a + FILE * must be accessed by routines defined in the same module + that opened it. + \param[out] _cb The callbacks to use for this file. + If there is an error opening the file, nothing will be + filled in here. + \param _path The path to the file to open. + On Windows, this string must be UTF-8 (to allow access + to files whose names cannot be represented in the + current MBCS code page). + All other systems use the native character encoding. + \param _mode The mode to open the file in. + \param _stream A stream previously returned by op_fopen(), op_fdopen(), + or op_freopen(). + \return A stream handle to use with the callbacks, or NULL on + error.*/ +OP_WARN_UNUSED_RESULT void *op_freopen(OpusFileCallbacks *_cb, + const char *_path,const char *_mode,void *_stream) OP_ARG_NONNULL(1) + OP_ARG_NONNULL(2) OP_ARG_NONNULL(3) OP_ARG_NONNULL(4); + +/**Creates a stream that reads from the given block of memory. + This block of memory must contain the complete stream to decode. + This is useful for caching small streams (e.g., sound effects) in RAM. + \param[out] _cb The callbacks to use for this stream. + If there is an error creating the stream, nothing will be + filled in here. + \param _data The block of memory to read from. + \param _size The size of the block of memory. + \return A stream handle to use with the callbacks, or NULL on + error.*/ +OP_WARN_UNUSED_RESULT void *op_mem_stream_create(OpusFileCallbacks *_cb, + const unsigned char *_data,size_t _size) OP_ARG_NONNULL(1); + +/**Creates a stream that reads from the given URL. + This function behaves identically to op_url_stream_create(), except that it + takes a va_list instead of a variable number of arguments. + It does not call the va_end macro, and because it invokes the + va_arg macro, the value of \a _ap is undefined after the call. + \note If you use this function, you must link against libopusurl. + \param[out] _cb The callbacks to use for this stream. + If there is an error creating the stream, nothing will + be filled in here. + \param _url The URL to read from. + Currently only the , , and + schemes are supported. + Both and may be disabled at compile + time, in which case opening such URLs will always fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, with + internationalized domain names encoded in punycode, + before passing them to this function. + \param[in,out] _ap A list of the \ref url_options "optional flags" to use. + This is a variable-length list of options terminated + with NULL. + \return A stream handle to use with the callbacks, or NULL on + error.*/ +OP_WARN_UNUSED_RESULT void *op_url_stream_vcreate(OpusFileCallbacks *_cb, + const char *_url,va_list _ap) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/**Creates a stream that reads from the given URL. + \note If you use this function, you must link against libopusurl. + \param[out] _cb The callbacks to use for this stream. + If there is an error creating the stream, nothing will be + filled in here. + \param _url The URL to read from. + Currently only the , , and schemes + are supported. + Both and may be disabled at compile time, + in which case opening such URLs will always fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, with + internationalized domain names encoded in punycode, before + passing them to this function. + \param ... The \ref url_options "optional flags" to use. + This is a variable-length list of options terminated with + NULL. + \return A stream handle to use with the callbacks, or NULL on + error.*/ +OP_WARN_UNUSED_RESULT void *op_url_stream_create(OpusFileCallbacks *_cb, + const char *_url,...) OP_ARG_NONNULL(1) OP_ARG_NONNULL(2); + +/*@}*/ +/*@}*/ + +/**\defgroup stream_open_close Opening and Closing*/ +/*@{*/ +/**\name Functions for opening and closing streams + + These functions allow you to test a stream to see if it is Opus, open it, + and close it. + Several flavors are provided for each of the built-in stream types, plus a + more general version which takes a set of application-provided callbacks.*/ +/*@{*/ + +/**Test to see if this is an Opus stream. + For good results, you will need at least 57 bytes (for a pure Opus-only + stream). + Something like 512 bytes will give more reliable results for multiplexed + streams. + This function is meant to be a quick-rejection filter. + Its purpose is not to guarantee that a stream is a valid Opus stream, but to + ensure that it looks enough like Opus that it isn't going to be recognized + as some other format (except possibly an Opus stream that is also + multiplexed with other codecs, such as video). + \param[out] _head The parsed ID header contents. + You may pass NULL if you do not need + this information. + If the function fails, the contents of this structure + remain untouched. + \param _initial_data An initial buffer of data from the start of the + stream. + \param _initial_bytes The number of bytes in \a _initial_data. + \return 0 if the data appears to be Opus, or a negative value on error. + \retval #OP_FALSE There was not enough data to tell if this was an Opus + stream or not. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL The stream used a feature that is not implemented, + such as an unsupported channel family. + \retval #OP_ENOTFORMAT If the data did not contain a recognizable ID + header for an Opus stream. + \retval #OP_EVERSION If the version field signaled a version this library + does not know how to parse. + \retval #OP_EBADHEADER The ID header was not properly formatted or contained + illegal values.*/ +int op_test(OpusHead *_head, + const unsigned char *_initial_data,size_t _initial_bytes); + +/**Open a stream from the given file path. + \param _path The path to the file to open. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want the + failure code. + The failure code will be #OP_EFAULT if the file could not + be opened, or one of the other failure codes from + op_open_callbacks() otherwise. + \return A freshly opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_open_file(const char *_path,int *_error) + OP_ARG_NONNULL(1); + +/**Open a stream from a memory buffer. + \param _data The memory buffer to open. + \param _size The number of bytes in the buffer. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want the + failure code. + See op_open_callbacks() for a full list of failure codes. + \return A freshly opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_open_memory(const unsigned char *_data, + size_t _size,int *_error); + +/**Open a stream from a URL. + This function behaves identically to op_open_url(), except that it + takes a va_list instead of a variable number of arguments. + It does not call the va_end macro, and because it invokes the + va_arg macro, the value of \a _ap is undefined after the call. + \note If you use this function, you must link against libopusurl. + \param _url The URL to open. + Currently only the , , and + schemes are supported. + Both and may be disabled at compile + time, in which case opening such URLs will always + fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, + with internationalized domain names encoded in + punycode, before passing them to this function. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want + the failure code. + See op_open_callbacks() for a full list of failure + codes. + \param[in,out] _ap A list of the \ref url_options "optional flags" to + use. + This is a variable-length list of options terminated + with NULL. + \return A freshly opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_vopen_url(const char *_url, + int *_error,va_list _ap) OP_ARG_NONNULL(1); + +/**Open a stream from a URL. + \note If you use this function, you must link against libopusurl. + \param _url The URL to open. + Currently only the , , and schemes + are supported. + Both and may be disabled at compile + time, in which case opening such URLs will always fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, with + internationalized domain names encoded in punycode, + before passing them to this function. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want the + failure code. + See op_open_callbacks() for a full list of failure codes. + \param ... The \ref url_options "optional flags" to use. + This is a variable-length list of options terminated with + NULL. + \return A freshly opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url, + int *_error,...) OP_ARG_NONNULL(1); + +/**Open a stream using the given set of callbacks to access it. + \param _source The stream to read from (e.g., a FILE *). + \param _cb The callbacks with which to access the stream. + read() must + be implemented. + seek() and + tell() may + be NULL, or may always return -1 to + indicate a source is unseekable, but if + seek() is + implemented and succeeds on a particular source, then + tell() must + also. + close() may + be NULL, but if it is not, it will be + called when the \c OggOpusFile is destroyed by + op_free(). + It will not be called if op_open_callbacks() fails + with an error. + \param _initial_data An initial buffer of data from the start of the + stream. + Applications can read some number of bytes from the + start of the stream to help identify this as an Opus + stream, and then provide them here to allow the + stream to be opened, even if it is unseekable. + \param _initial_bytes The number of bytes in \a _initial_data. + If the stream is seekable, its current position (as + reported by + tell() + at the start of this function) must be equal to + \a _initial_bytes. + Otherwise, seeking to absolute positions will + generate inconsistent results. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want + the failure code. + The failure code will be one of +
    +
    #OP_EREAD
    +
    An underlying read, seek, or tell operation + failed when it should have succeeded, or we failed + to find data in the stream we had seen before.
    +
    #OP_EFAULT
    +
    There was a memory allocation failure, or an + internal library error.
    +
    #OP_EIMPL
    +
    The stream used a feature that is not + implemented, such as an unsupported channel + family.
    +
    #OP_EINVAL
    +
    seek() + was implemented and succeeded on this source, but + tell() + did not, or the starting position indicator was + not equal to \a _initial_bytes.
    +
    #OP_ENOTFORMAT
    +
    The stream contained a link that did not have + any logical Opus streams in it.
    +
    #OP_EBADHEADER
    +
    A required header packet was not properly + formatted, contained illegal values, or was missing + altogether.
    +
    #OP_EVERSION
    +
    An ID header contained an unrecognized version + number.
    +
    #OP_EBADLINK
    +
    We failed to find data we had seen before after + seeking.
    +
    #OP_EBADTIMESTAMP
    +
    The first or last timestamp in a link failed + basic validity checks.
    +
    + \return A freshly opened \c OggOpusFile, or NULL on error. + libopusfile does not take ownership of the source + if the call fails. + The calling application is responsible for closing the source if + this call returns an error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_open_callbacks(void *_source, + const OpusFileCallbacks *_cb,const unsigned char *_initial_data, + size_t _initial_bytes,int *_error) OP_ARG_NONNULL(2); + +/**Partially open a stream from the given file path. + \see op_test_callbacks + \param _path The path to the file to open. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want the + failure code. + The failure code will be #OP_EFAULT if the file could not + be opened, or one of the other failure codes from + op_open_callbacks() otherwise. + \return A partially opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_test_file(const char *_path,int *_error) + OP_ARG_NONNULL(1); + +/**Partially open a stream from a memory buffer. + \see op_test_callbacks + \param _data The memory buffer to open. + \param _size The number of bytes in the buffer. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want the + failure code. + See op_open_callbacks() for a full list of failure codes. + \return A partially opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_test_memory(const unsigned char *_data, + size_t _size,int *_error); + +/**Partially open a stream from a URL. + This function behaves identically to op_test_url(), except that it + takes a va_list instead of a variable number of arguments. + It does not call the va_end macro, and because it invokes the + va_arg macro, the value of \a _ap is undefined after the call. + \note If you use this function, you must link against libopusurl. + \see op_test_url + \see op_test_callbacks + \param _url The URL to open. + Currently only the , , and + schemes are supported. + Both and may be disabled at compile + time, in which case opening such URLs will always + fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, + with internationalized domain names encoded in + punycode, before passing them to this function. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want + the failure code. + See op_open_callbacks() for a full list of failure + codes. + \param[in,out] _ap A list of the \ref url_options "optional flags" to + use. + This is a variable-length list of options terminated + with NULL. + \return A partially opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_vtest_url(const char *_url, + int *_error,va_list _ap) OP_ARG_NONNULL(1); + +/**Partially open a stream from a URL. + \note If you use this function, you must link against libopusurl. + \see op_test_callbacks + \param _url The URL to open. + Currently only the , , and + schemes are supported. + Both and may be disabled at compile + time, in which case opening such URLs will always fail. + Currently this only supports URIs. + IRIs should be converted to UTF-8 and URL-escaped, with + internationalized domain names encoded in punycode, + before passing them to this function. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want the + failure code. + See op_open_callbacks() for a full list of failure + codes. + \param ... The \ref url_options "optional flags" to use. + This is a variable-length list of options terminated + with NULL. + \return A partially opened \c OggOpusFile, or NULL on error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_test_url(const char *_url, + int *_error,...) OP_ARG_NONNULL(1); + +/**Partially open a stream using the given set of callbacks to access it. + This tests for Opusness and loads the headers for the first link. + It does not seek (although it tests for seekability). + You can query a partially open stream for the few pieces of basic + information returned by op_serialno(), op_channel_count(), op_head(), and + op_tags() (but only for the first link). + You may also determine if it is seekable via a call to op_seekable(). + You cannot read audio from the stream, seek, get the size or duration, + get information from links other than the first one, or even get the total + number of links until you finish opening the stream with op_test_open(). + If you do not need to do any of these things, you can dispose of it with + op_free() instead. + + This function is provided mostly to simplify porting existing code that used + libvorbisfile. + For new code, you are likely better off using op_test() instead, which + is less resource-intensive, requires less data to succeed, and imposes a + hard limit on the amount of data it examines (important for unseekable + sources, where all such data must be buffered until you are sure of the + stream type). + \param _source The stream to read from (e.g., a FILE *). + \param _cb The callbacks with which to access the stream. + read() must + be implemented. + seek() and + tell() may + be NULL, or may always return -1 to + indicate a source is unseekable, but if + seek() is + implemented and succeeds on a particular source, then + tell() must + also. + close() may + be NULL, but if it is not, it will be + called when the \c OggOpusFile is destroyed by + op_free(). + It will not be called if op_open_callbacks() fails + with an error. + \param _initial_data An initial buffer of data from the start of the + stream. + Applications can read some number of bytes from the + start of the stream to help identify this as an Opus + stream, and then provide them here to allow the + stream to be tested more thoroughly, even if it is + unseekable. + \param _initial_bytes The number of bytes in \a _initial_data. + If the stream is seekable, its current position (as + reported by + tell() + at the start of this function) must be equal to + \a _initial_bytes. + Otherwise, seeking to absolute positions will + generate inconsistent results. + \param[out] _error Returns 0 on success, or a failure code on error. + You may pass in NULL if you don't want + the failure code. + See op_open_callbacks() for a full list of failure + codes. + \return A partially opened \c OggOpusFile, or NULL on error. + libopusfile does not take ownership of the source + if the call fails. + The calling application is responsible for closing the source if + this call returns an error.*/ +OP_WARN_UNUSED_RESULT OggOpusFile *op_test_callbacks(void *_source, + const OpusFileCallbacks *_cb,const unsigned char *_initial_data, + size_t _initial_bytes,int *_error) OP_ARG_NONNULL(2); + +/**Finish opening a stream partially opened with op_test_callbacks() or one of + the associated convenience functions. + If this function fails, you are still responsible for freeing the + \c OggOpusFile with op_free(). + \param _of The \c OggOpusFile to finish opening. + \return 0 on success, or a negative value on error. + \retval #OP_EREAD An underlying read, seek, or tell operation failed + when it should have succeeded. + \retval #OP_EFAULT There was a memory allocation failure, or an + internal library error. + \retval #OP_EIMPL The stream used a feature that is not implemented, + such as an unsupported channel family. + \retval #OP_EINVAL The stream was not partially opened with + op_test_callbacks() or one of the associated + convenience functions. + \retval #OP_ENOTFORMAT The stream contained a link that did not have any + logical Opus streams in it. + \retval #OP_EBADHEADER A required header packet was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An ID header contained an unrecognized version + number. + \retval #OP_EBADLINK We failed to find data we had seen before after + seeking. + \retval #OP_EBADTIMESTAMP The first or last timestamp in a link failed basic + validity checks.*/ +int op_test_open(OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Release all memory used by an \c OggOpusFile. + \param _of The \c OggOpusFile to free.*/ +void op_free(OggOpusFile *_of); + +/*@}*/ +/*@}*/ + +/**\defgroup stream_info Stream Information*/ +/*@{*/ +/**\name Functions for obtaining information about streams + + These functions allow you to get basic information about a stream, including + seekability, the number of links (for chained streams), plus the size, + duration, bitrate, header parameters, and meta information for each link + (or, where available, the stream as a whole). + Some of these (size, duration) are only available for seekable streams. + You can also query the current stream position, link, and playback time, + and instantaneous bitrate during playback. + + Some of these functions may be used successfully on the partially open + streams returned by op_test_callbacks() or one of the associated + convenience functions. + Their documention will indicate so explicitly.*/ +/*@{*/ + +/**Returns whether or not the data source being read is seekable. + This is true if +
      +
    1. The seek() and + tell() callbacks are both + non-NULL,
    2. +
    3. The seek() callback was + successfully executed at least once, and
    4. +
    5. The tell() callback was + successfully able to report the position indicator afterwards.
    6. +
    + This function may be called on partially-opened streams. + \param _of The \c OggOpusFile whose seekable status is to be returned. + \return A non-zero value if seekable, and 0 if unseekable.*/ +int op_seekable(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Returns the number of links in this chained stream. + This function may be called on partially-opened streams, but it will always + return 1. + The actual number of links is not known until the stream is fully opened. + \param _of The \c OggOpusFile from which to retrieve the link count. + \return For fully-open seekable sources, this returns the total number of + links in the whole stream, which will be at least 1. + For partially-open or unseekable sources, this always returns 1.*/ +int op_link_count(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Get the serial number of the given link in a (possibly-chained) Ogg Opus + stream. + This function may be called on partially-opened streams, but it will always + return the serial number of the Opus stream in the first link. + \param _of The \c OggOpusFile from which to retrieve the serial number. + \param _li The index of the link whose serial number should be retrieved. + Use a negative number to get the serial number of the current + link. + \return The serial number of the given link. + If \a _li is greater than the total number of links, this returns + the serial number of the last link. + If the source is not seekable, this always returns the serial number + of the current link.*/ +opus_uint32 op_serialno(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the channel count of the given link in a (possibly-chained) Ogg Opus + stream. + This is equivalent to op_head(_of,_li)->channel_count, but + is provided for convenience. + This function may be called on partially-opened streams, but it will always + return the channel count of the Opus stream in the first link. + \param _of The \c OggOpusFile from which to retrieve the channel count. + \param _li The index of the link whose channel count should be retrieved. + Use a negative number to get the channel count of the current + link. + \return The channel count of the given link. + If \a _li is greater than the total number of links, this returns + the channel count of the last link. + If the source is not seekable, this always returns the channel count + of the current link.*/ +int op_channel_count(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the total (compressed) size of the stream, or of an individual link in + a (possibly-chained) Ogg Opus stream, including all headers and Ogg muxing + overhead. + \param _of The \c OggOpusFile from which to retrieve the compressed size. + \param _li The index of the link whose compressed size should be computed. + Use a negative number to get the compressed size of the entire + stream. + \return The compressed size of the entire stream if \a _li is negative, the + compressed size of link \a _li if it is non-negative, or a negative + value on error. + The compressed size of the entire stream may be smaller than that + of the underlying source if trailing garbage was detected in the + file. + \retval #OP_EINVAL The source is not seekable (so we can't know the length), + \a _li wasn't less than the total number of links in + the stream, or the stream was only partially open.*/ +opus_int64 op_raw_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the total PCM length (number of samples at 48 kHz) of the stream, or of + an individual link in a (possibly-chained) Ogg Opus stream. + Users looking for op_time_total() should use op_pcm_total() + instead. + Because timestamps in Opus are fixed at 48 kHz, there is no need for a + separate function to convert this to seconds (and leaving it out avoids + introducing floating point to the API, for those that wish to avoid it). + \param _of The \c OggOpusFile from which to retrieve the PCM offset. + \param _li The index of the link whose PCM length should be computed. + Use a negative number to get the PCM length of the entire stream. + \return The PCM length of the entire stream if \a _li is negative, the PCM + length of link \a _li if it is non-negative, or a negative value on + error. + \retval #OP_EINVAL The source is not seekable (so we can't know the length), + \a _li wasn't less than the total number of links in + the stream, or the stream was only partially open.*/ +ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the ID header information for the given link in a (possibly chained) Ogg + Opus stream. + This function may be called on partially-opened streams, but it will always + return the ID header information of the Opus stream in the first link. + \param _of The \c OggOpusFile from which to retrieve the ID header + information. + \param _li The index of the link whose ID header information should be + retrieved. + Use a negative number to get the ID header information of the + current link. + For an unseekable stream, \a _li is ignored, and the ID header + information for the current link is always returned, if + available. + \return The contents of the ID header for the given link.*/ +const OpusHead *op_head(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Get the comment header information for the given link in a (possibly + chained) Ogg Opus stream. + This function may be called on partially-opened streams, but it will always + return the tags from the Opus stream in the first link. + \param _of The \c OggOpusFile from which to retrieve the comment header + information. + \param _li The index of the link whose comment header information should be + retrieved. + Use a negative number to get the comment header information of + the current link. + For an unseekable stream, \a _li is ignored, and the comment + header information for the current link is always returned, if + available. + \return The contents of the comment header for the given link, or + NULL if this is an unseekable stream that encountered + an invalid link.*/ +const OpusTags *op_tags(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Retrieve the index of the current link. + This is the link that produced the data most recently read by + op_read_float() or its associated functions, or, after a seek, the link + that the seek target landed in. + Reading more data may advance the link index (even on the first read after a + seek). + \param _of The \c OggOpusFile from which to retrieve the current link index. + \return The index of the current link on success, or a negative value on + failure. + For seekable streams, this is a number between 0 and the value + returned by op_link_count(). + For unseekable streams, this value starts at 0 and increments by one + each time a new link is encountered (even though op_link_count() + always returns 1). + \retval #OP_EINVAL The stream was only partially open.*/ +int op_current_link(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Computes the bitrate for a given link in a (possibly chained) Ogg Opus + stream. + The stream must be seekable to compute the bitrate. + For unseekable streams, use op_bitrate_instant() to get periodic estimates. + \param _of The \c OggOpusFile from which to retrieve the bitrate. + \param _li The index of the link whose bitrate should be computed. + USe a negative number to get the bitrate of the whole stream. + \return The bitrate on success, or a negative value on error. + \retval #OP_EINVAL The stream was only partially open, the stream was not + seekable, or \a _li was larger than the number of + links.*/ +opus_int32 op_bitrate(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1); + +/**Compute the instantaneous bitrate, measured as the ratio of bits to playable + samples decoded since a) the last call to op_bitrate_instant(), b) the last + seek, or c) the start of playback, whichever was most recent. + This will spike somewhat after a seek or at the start/end of a chain + boundary, as pre-skip, pre-roll, and end-trimming causes samples to be + decoded but not played. + \param _of The \c OggOpusFile from which to retrieve the bitrate. + \return The bitrate, in bits per second, or a negative value on error. + \retval #OP_FALSE No data has been decoded since any of the events + described above. + \retval #OP_EINVAL The stream was only partially open.*/ +opus_int32 op_bitrate_instant(OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Obtain the current value of the position indicator for \a _of. + \param _of The \c OggOpusFile from which to retrieve the position indicator. + \return The byte position that is currently being read from. + \retval #OP_EINVAL The stream was only partially open.*/ +opus_int64 op_raw_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/**Obtain the PCM offset of the next sample to be read. + If the stream is not properly timestamped, this might not increment by the + proper amount between reads, or even return monotonically increasing + values. + \param _of The \c OggOpusFile from which to retrieve the PCM offset. + \return The PCM offset of the next sample to be read. + \retval #OP_EINVAL The stream was only partially open.*/ +ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1); + +/*@}*/ +/*@}*/ + +/**\defgroup stream_seeking Seeking*/ +/*@{*/ +/**\name Functions for seeking in Opus streams + + These functions let you seek in Opus streams, if the underlying source + support it. + Seeking is implemented for all built-in stream I/O routines, though some + individual sources may not be seekable (pipes, live HTTP streams, or HTTP + streams from a server that does not support Range requests). + + op_raw_seek() is the fastest: it is guaranteed to perform at most one + physical seek, but, since the target is a byte position, makes no guarantee + how close to a given time it will come. + op_pcm_seek() provides sample-accurate seeking. + The number of physical seeks it requires is still quite small (often 1 or + 2, even in highly variable bitrate streams). + + Seeking in Opus requires decoding some pre-roll amount before playback to + allow the internal state to converge (as if recovering from packet loss). + This is handled internally by libopusfile, but means there is + little extra overhead for decoding up to the exact position requested + (since it must decode some amount of audio anyway). + It also means that decoding after seeking may not return exactly the same + values as would be obtained by decoding the stream straight through. + However, such differences are expected to be smaller than the loss + introduced by Opus's lossy compression.*/ +/*@{*/ + +/**Seek to a byte offset relative to the compressed data. + This also scans packets to update the PCM cursor. + It will cross a logical bitstream boundary, but only if it can't get any + packets out of the tail of the link to which it seeks. + \param _of The \c OggOpusFile in which to seek. + \param _byte_offset The byte position to seek to. + \return 0 on success, or a negative error code on failure. + \retval #OP_EREAD The underlying seek operation failed. + \retval #OP_EINVAL The stream was only partially open, or the target was + outside the valid range for the stream. + \retval #OP_ENOSEEK This stream is not seekable. + \retval #OP_EBADLINK Failed to initialize a decoder for a stream for an + unknown reason.*/ +int op_raw_seek(OggOpusFile *_of,opus_int64 _byte_offset) OP_ARG_NONNULL(1); + +/**Seek to the specified PCM offset, such that decoding will begin at exactly + the requested position. + \param _of The \c OggOpusFile in which to seek. + \param _pcm_offset The PCM offset to seek to. + This is in samples at 48 kHz relative to the start of the + stream. + \return 0 on success, or a negative value on error. + \retval #OP_EREAD An underlying read or seek operation failed. + \retval #OP_EINVAL The stream was only partially open, or the target was + outside the valid range for the stream. + \retval #OP_ENOSEEK This stream is not seekable. + \retval #OP_EBADLINK We failed to find data we had seen before, or the + bitstream structure was sufficiently malformed that + seeking to the target destination was impossible.*/ +int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset) OP_ARG_NONNULL(1); + +/*@}*/ +/*@}*/ + +/**\defgroup stream_decoding Decoding*/ +/*@{*/ +/**\name Functions for decoding audio data + + These functions retrieve actual decoded audio data from the stream. + The general functions, op_read() and op_read_float() return 16-bit or + floating-point output, both using native endian ordering. + The number of channels returned can change from link to link in a chained + stream. + There are special functions, op_read_stereo() and op_read_float_stereo(), + which always output two channels, to simplify applications which do not + wish to handle multichannel audio. + These downmix multichannel files to two channels, so they can always return + samples in the same format for every link in a chained file. + + If the rest of your audio processing chain can handle floating point, those + routines should be preferred, as floating point output avoids introducing + clipping and other issues which might be avoided entirely if, e.g., you + scale down the volume at some other stage. + However, if you intend to direct consume 16-bit samples, the conversion in + libopusfile provides noise-shaping dithering and, if compiled + against libopus 1.1 or later, soft-clipping prevention. + + libopusfile can also be configured at compile time to use the + fixed-point libopus API. + If so, libopusfile's floating-point API may also be disabled. + In that configuration, nothing in libopusfile will use any + floating-point operations, to simplify support on devices without an + adequate FPU. + + \warning HTTPS streams may be be vulnerable to truncation attacks if you do + not check the error return code from op_read_float() or its associated + functions. + If the remote peer does not close the connection gracefully (with a TLS + "close notify" message), these functions will return #OP_EREAD instead of 0 + when they reach the end of the file. + If you are reading from an URL (particularly if seeking is not + supported), you should make sure to check for this error and warn the user + appropriately.*/ +/*@{*/ + +/**Indicates that the decoding callback should produce signed 16-bit + native-endian output samples.*/ +#define OP_DEC_FORMAT_SHORT (7008) +/**Indicates that the decoding callback should produce 32-bit native-endian + float samples.*/ +#define OP_DEC_FORMAT_FLOAT (7040) + +/**Indicates that the decoding callback did not decode anything, and that + libopusfile should decode normally instead.*/ +#define OP_DEC_USE_DEFAULT (6720) + +/**Called to decode an Opus packet. + This should invoke the functional equivalent of opus_multistream_decode() or + opus_multistream_decode_float(), except that it returns 0 on success + instead of the number of decoded samples (which is known a priori). + \param _ctx The application-provided callback context. + \param _decoder The decoder to use to decode the packet. + \param[out] _pcm The buffer to decode into. + This will always have enough room for \a _nchannels of + \a _nsamples samples, which should be placed into this + buffer interleaved. + \param _op The packet to decode. + This will always have its granule position set to a valid + value. + \param _nsamples The number of samples expected from the packet. + \param _nchannels The number of channels expected from the packet. + \param _format The desired sample output format. + This is either #OP_DEC_FORMAT_SHORT or + #OP_DEC_FORMAT_FLOAT. + \param _li The index of the link from which this packet was decoded. + \return A non-negative value on success, or a negative value on error. + The error codes should be the same as those returned by + opus_multistream_decode() or opus_multistream_decode_float(). + \retval 0 Decoding was successful. + The application has filled the buffer with + exactly \a _nsamples*\a + _nchannels samples in the requested + format. + \retval #OP_DEC_USE_DEFAULT No decoding was done. + libopusfile should decode normally + instead.*/ +typedef int (*op_decode_cb_func)(void *_ctx,OpusMSDecoder *_decoder,void *_pcm, + const ogg_packet *_op,int _nsamples,int _nchannels,int _format,int _li); + +/**Sets the packet decode callback function. + This is called once for each packet that needs to be decoded. + A call to this function is no guarantee that the audio will eventually be + delivered to the application. + Some or all of the data from the packet may be discarded (i.e., at the + beginning or end of a link, or after a seek), however the callback is + required to provide all of it. + \param _of The \c OggOpusFile on which to set the decode callback. + \param _decode_cb The callback function to call. + This may be NULL to disable calling the + callback. + \param _ctx The application-provided context pointer to pass to the + callback on each call.*/ +void op_set_decode_callback(OggOpusFile *_of, + op_decode_cb_func _decode_cb,void *_ctx) OP_ARG_NONNULL(1); + +/**Gain offset type that indicates that the provided offset is relative to the + header gain. + This is the default.*/ +#define OP_HEADER_GAIN (0) + +/**Gain offset type that indicates that the provided offset is relative to the + R128_TRACK_GAIN value (if any), in addition to the header gain.*/ +#define OP_TRACK_GAIN (3008) + +/**Gain offset type that indicates that the provided offset should be used as + the gain directly, without applying any the header or track gains.*/ +#define OP_ABSOLUTE_GAIN (3009) + +/**Sets the gain to be used for decoded output. + By default, the gain in the header is applied with no additional offset. + The total gain (including header gain and/or track gain, if applicable, and + this offset), will be clamped to [-32768,32767]/256 dB. + This is more than enough to saturate or underflow 16-bit PCM. + \note The new gain will not be applied to any already buffered, decoded + output. + This means you cannot change it sample-by-sample, as at best it will be + updated packet-by-packet. + It is meant for setting a target volume level, rather than applying smooth + fades, etc. + \param _of The \c OggOpusFile on which to set the gain offset. + \param _gain_type One of #OP_HEADER_GAIN, #OP_TRACK_GAIN, or + #OP_ABSOLUTE_GAIN. + \param _gain_offset_q8 The gain offset to apply, in 1/256ths of a dB. + \return 0 on success or a negative value on error. + \retval #OP_EINVAL The \a _gain_type was unrecognized.*/ +int op_set_gain_offset(OggOpusFile *_of, + int _gain_type,opus_int32 _gain_offset_q8) OP_ARG_NONNULL(1); + +/**Sets whether or not dithering is enabled for 16-bit decoding. + By default, when libopusfile is compiled to use floating-point + internally, calling op_read() or op_read_stereo() will first decode to + float, and then convert to fixed-point using noise-shaping dithering. + This flag can be used to disable that dithering. + When the application uses op_read_float() or op_read_float_stereo(), or when + the library has been compiled to decode directly to fixed point, this flag + has no effect. + \param _of The \c OggOpusFile on which to enable or disable dithering. + \param _enabled A non-zero value to enable dithering, or 0 to disable it.*/ +void op_set_dither_enabled(OggOpusFile *_of,int _enabled) OP_ARG_NONNULL(1); + +/**Reads more samples from the stream. + \note Although \a _buf_size must indicate the total number of values that + can be stored in \a _pcm, the return value is the number of samples + per channel. + This is done because +
      +
    1. The channel count cannot be known a priori (reading more samples might + advance us into the next link, with a different channel count), so + \a _buf_size cannot also be in units of samples per channel,
    2. +
    3. Returning the samples per channel matches the libopus API + as closely as we're able,
    4. +
    5. Returning the total number of values instead of samples per channel + would mean the caller would need a division to compute the samples per + channel, and might worry about the possibility of getting back samples + for some channels and not others, and
    6. +
    7. This approach is relatively fool-proof: if an application passes too + small a value to \a _buf_size, they will simply get fewer samples back, + and if they assume the return value is the total number of values, then + they will simply read too few (rather than reading too many and going + off the end of the buffer).
    8. +
    + \param _of The \c OggOpusFile from which to read. + \param[out] _pcm A buffer in which to store the output PCM samples, as + signed native-endian 16-bit values at 48 kHz + with a nominal range of [-32768,32767). + Multiple channels are interleaved using the + Vorbis + channel ordering. + This must have room for at least \a _buf_size values. + \param _buf_size The number of values that can be stored in \a _pcm. + It is recommended that this be large enough for at + least 120 ms of data at 48 kHz per channel (5760 + values per channel). + Smaller buffers will simply return less data, possibly + consuming more memory to buffer the data internally. + libopusfile may return less data than + requested. + If so, there is no guarantee that the remaining data + in \a _pcm will be unmodified. + \param[out] _li The index of the link this data was decoded from. + You may pass NULL if you do not need this + information. + If this function fails (returning a negative value), + this parameter is left unset. + \return The number of samples read per channel on success, or a negative + value on failure. + The channel count can be retrieved on success by calling + op_head(_of,*_li). + The number of samples returned may be 0 if the buffer was too small + to store even a single sample for all channels, or if end-of-file + was reached. + The list of possible failure codes follows. + Most of them can only be returned by unseekable, chained streams + that encounter a new link. + \retval #OP_HOLE There was a hole in the data, and some samples + may have been skipped. + Call this function again to continue decoding + past the hole. + \retval #OP_EREAD An underlying read operation failed. + This may signal a truncation attack from an + source. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL An unseekable stream encountered a new link that + used a feature that is not implemented, such as + an unsupported channel family. + \retval #OP_EINVAL The stream was only partially open. + \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that + did not have any logical Opus streams in it. + \retval #OP_EBADHEADER An unseekable stream encountered a new link with a + required header packet that was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An unseekable stream encountered a new link with + an ID header that contained an unrecognized + version number. + \retval #OP_EBADPACKET Failed to properly decode the next packet. + \retval #OP_EBADLINK We failed to find data we had seen before. + \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with + a starting timestamp that failed basic validity + checks.*/ +OP_WARN_UNUSED_RESULT int op_read(OggOpusFile *_of, + opus_int16 *_pcm,int _buf_size,int *_li) OP_ARG_NONNULL(1); + +/**Reads more samples from the stream. + \note Although \a _buf_size must indicate the total number of values that + can be stored in \a _pcm, the return value is the number of samples + per channel. +
      +
    1. The channel count cannot be known a priori (reading more samples might + advance us into the next link, with a different channel count), so + \a _buf_size cannot also be in units of samples per channel,
    2. +
    3. Returning the samples per channel matches the libopus API + as closely as we're able,
    4. +
    5. Returning the total number of values instead of samples per channel + would mean the caller would need a division to compute the samples per + channel, and might worry about the possibility of getting back samples + for some channels and not others, and
    6. +
    7. This approach is relatively fool-proof: if an application passes too + small a value to \a _buf_size, they will simply get fewer samples back, + and if they assume the return value is the total number of values, then + they will simply read too few (rather than reading too many and going + off the end of the buffer).
    8. +
    + \param _of The \c OggOpusFile from which to read. + \param[out] _pcm A buffer in which to store the output PCM samples as + signed floats at 48 kHz with a nominal range of + [-1.0,1.0]. + Multiple channels are interleaved using the + Vorbis + channel ordering. + This must have room for at least \a _buf_size floats. + \param _buf_size The number of floats that can be stored in \a _pcm. + It is recommended that this be large enough for at + least 120 ms of data at 48 kHz per channel (5760 + samples per channel). + Smaller buffers will simply return less data, possibly + consuming more memory to buffer the data internally. + If less than \a _buf_size values are returned, + libopusfile makes no guarantee that the + remaining data in \a _pcm will be unmodified. + \param[out] _li The index of the link this data was decoded from. + You may pass NULL if you do not need this + information. + If this function fails (returning a negative value), + this parameter is left unset. + \return The number of samples read per channel on success, or a negative + value on failure. + The channel count can be retrieved on success by calling + op_head(_of,*_li). + The number of samples returned may be 0 if the buffer was too small + to store even a single sample for all channels, or if end-of-file + was reached. + The list of possible failure codes follows. + Most of them can only be returned by unseekable, chained streams + that encounter a new link. + \retval #OP_HOLE There was a hole in the data, and some samples + may have been skipped. + Call this function again to continue decoding + past the hole. + \retval #OP_EREAD An underlying read operation failed. + This may signal a truncation attack from an + source. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL An unseekable stream encountered a new link that + used a feature that is not implemented, such as + an unsupported channel family. + \retval #OP_EINVAL The stream was only partially open. + \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that + did not have any logical Opus streams in it. + \retval #OP_EBADHEADER An unseekable stream encountered a new link with a + required header packet that was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An unseekable stream encountered a new link with + an ID header that contained an unrecognized + version number. + \retval #OP_EBADPACKET Failed to properly decode the next packet. + \retval #OP_EBADLINK We failed to find data we had seen before. + \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with + a starting timestamp that failed basic validity + checks.*/ +OP_WARN_UNUSED_RESULT int op_read_float(OggOpusFile *_of, + float *_pcm,int _buf_size,int *_li) OP_ARG_NONNULL(1); + +/**Reads more samples from the stream and downmixes to stereo, if necessary. + This function is intended for simple players that want a uniform output + format, even if the channel count changes between links in a chained + stream. + \note \a _buf_size indicates the total number of values that can be stored + in \a _pcm, while the return value is the number of samples per + channel, even though the channel count is known, for consistency with + op_read(). + \param _of The \c OggOpusFile from which to read. + \param[out] _pcm A buffer in which to store the output PCM samples, as + signed native-endian 16-bit values at 48 kHz + with a nominal range of [-32768,32767). + The left and right channels are interleaved in the + buffer. + This must have room for at least \a _buf_size values. + \param _buf_size The number of values that can be stored in \a _pcm. + It is recommended that this be large enough for at + least 120 ms of data at 48 kHz per channel (11520 + values total). + Smaller buffers will simply return less data, possibly + consuming more memory to buffer the data internally. + If less than \a _buf_size values are returned, + libopusfile makes no guarantee that the + remaining data in \a _pcm will be unmodified. + \return The number of samples read per channel on success, or a negative + value on failure. + The number of samples returned may be 0 if the buffer was too small + to store even a single sample for both channels, or if end-of-file + was reached. + The list of possible failure codes follows. + Most of them can only be returned by unseekable, chained streams + that encounter a new link. + \retval #OP_HOLE There was a hole in the data, and some samples + may have been skipped. + Call this function again to continue decoding + past the hole. + \retval #OP_EREAD An underlying read operation failed. + This may signal a truncation attack from an + source. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL An unseekable stream encountered a new link that + used a feature that is not implemented, such as + an unsupported channel family. + \retval #OP_EINVAL The stream was only partially open. + \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that + did not have any logical Opus streams in it. + \retval #OP_EBADHEADER An unseekable stream encountered a new link with a + required header packet that was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An unseekable stream encountered a new link with + an ID header that contained an unrecognized + version number. + \retval #OP_EBADPACKET Failed to properly decode the next packet. + \retval #OP_EBADLINK We failed to find data we had seen before. + \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with + a starting timestamp that failed basic validity + checks.*/ +OP_WARN_UNUSED_RESULT int op_read_stereo(OggOpusFile *_of, + opus_int16 *_pcm,int _buf_size) OP_ARG_NONNULL(1); + +/**Reads more samples from the stream and downmixes to stereo, if necessary. + This function is intended for simple players that want a uniform output + format, even if the channel count changes between links in a chained + stream. + \note \a _buf_size indicates the total number of values that can be stored + in \a _pcm, while the return value is the number of samples per + channel, even though the channel count is known, for consistency with + op_read_float(). + \param _of The \c OggOpusFile from which to read. + \param[out] _pcm A buffer in which to store the output PCM samples, as + signed floats at 48 kHz with a nominal range of + [-1.0,1.0]. + The left and right channels are interleaved in the + buffer. + This must have room for at least \a _buf_size values. + \param _buf_size The number of values that can be stored in \a _pcm. + It is recommended that this be large enough for at + least 120 ms of data at 48 kHz per channel (11520 + values total). + Smaller buffers will simply return less data, possibly + consuming more memory to buffer the data internally. + If less than \a _buf_size values are returned, + libopusfile makes no guarantee that the + remaining data in \a _pcm will be unmodified. + \return The number of samples read per channel on success, or a negative + value on failure. + The number of samples returned may be 0 if the buffer was too small + to store even a single sample for both channels, or if end-of-file + was reached. + The list of possible failure codes follows. + Most of them can only be returned by unseekable, chained streams + that encounter a new link. + \retval #OP_HOLE There was a hole in the data, and some samples + may have been skipped. + Call this function again to continue decoding + past the hole. + \retval #OP_EREAD An underlying read operation failed. + This may signal a truncation attack from an + source. + \retval #OP_EFAULT An internal memory allocation failed. + \retval #OP_EIMPL An unseekable stream encountered a new link that + used a feature that is not implemented, such as + an unsupported channel family. + \retval #OP_EINVAL The stream was only partially open. + \retval #OP_ENOTFORMAT An unseekable stream encountered a new link that + that did not have any logical Opus streams in it. + \retval #OP_EBADHEADER An unseekable stream encountered a new link with a + required header packet that was not properly + formatted, contained illegal values, or was + missing altogether. + \retval #OP_EVERSION An unseekable stream encountered a new link with + an ID header that contained an unrecognized + version number. + \retval #OP_EBADPACKET Failed to properly decode the next packet. + \retval #OP_EBADLINK We failed to find data we had seen before. + \retval #OP_EBADTIMESTAMP An unseekable stream encountered a new link with + a starting timestamp that failed basic validity + checks.*/ +OP_WARN_UNUSED_RESULT int op_read_float_stereo(OggOpusFile *_of, + float *_pcm,int _buf_size) OP_ARG_NONNULL(1); + +/*@}*/ +/*@}*/ + +# if OP_GNUC_PREREQ(4,0) +# pragma GCC visibility pop +# endif + +# if defined(__cplusplus) +} +# endif + +#endif diff --git a/TelegramClient.Opus/opus/opusfile/stream.c b/TelegramClient.Opus/opus/opusfile/stream.c new file mode 100755 index 0000000..0238a6b --- /dev/null +++ b/TelegramClient.Opus/opus/opusfile/stream.c @@ -0,0 +1,366 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 * + * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * + * * + ******************************************************************** + + function: stdio-based convenience library for opening/seeking/decoding + last mod: $Id: vorbisfile.c 17573 2010-10-27 14:53:59Z xiphmont $ + + ********************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "internal.h" +#include +#include +#include +#include +#include +#if defined(_WIN32) +# include +#endif + +typedef struct OpusMemStream OpusMemStream; + +#define OP_MEM_SIZE_MAX (~(size_t)0>>1) +#define OP_MEM_DIFF_MAX ((ptrdiff_t)OP_MEM_SIZE_MAX) + +/*The context information needed to read from a block of memory as if it were a + file.*/ +struct OpusMemStream{ + /*The block of memory to read from.*/ + const unsigned char *data; + /*The total size of the block. + This must be at most OP_MEM_SIZE_MAX to prevent signed overflow while + seeking.*/ + ptrdiff_t size; + /*The current file position. + This is allowed to be set arbitrarily greater than size (i.e., past the end + of the block, though we will not read data past the end of the block), but + is not allowed to be negative (i.e., before the beginning of the block).*/ + ptrdiff_t pos; +}; + +static int op_fread(void *_stream,unsigned char *_ptr,int _buf_size){ + FILE *stream; + size_t ret; + /*Check for empty read.*/ + if(_buf_size<=0)return 0; + stream=(FILE *)_stream; + ret=fread(_ptr,1,_buf_size,stream); + OP_ASSERT(ret<=(size_t)_buf_size); + /*If ret==0 and !feof(stream), there was a read error.*/ + return ret>0||feof(stream)?(int)ret:OP_EREAD; +} + +static int op_fseek(void *_stream,opus_int64 _offset,int _whence){ +#if defined(_WIN32) + /*_fseeki64() is not exposed until MSCVCRT80. + This is the default starting with MSVC 2005 (_MSC_VER>=1400), but we want + to allow linking against older MSVCRT versions for compatibility back to + XP without installing extra runtime libraries. + i686-pc-mingw32 does not have fseeko() and requires + __MSVCRT_VERSION__>=0x800 for _fseeki64(), which screws up linking with + other libraries (that don't use MSVCRT80 from MSVC 2005 by default). + i686-w64-mingw32 does have fseeko() and respects _FILE_OFFSET_BITS, but I + don't know how to detect that at compile time. + We could just use fseeko64() (which is available in both), but its + implemented using fgetpos()/fsetpos() just like this code, except without + the overflow checking, so we prefer our version.*/ + opus_int64 pos; + /*We don't use fpos_t directly because it might be a struct if __STDC__ is + non-zero or _INTEGRAL_MAX_BITS < 64. + I'm not certain when the latter is true, but someone could in theory set + the former. + Either way, it should be binary compatible with a normal 64-bit int (this + assumption is not portable, but I believe it is true for MSVCRT).*/ + OP_ASSERT(sizeof(pos)==sizeof(fpos_t)); + /*Translate the seek to an absolute one.*/ + if(_whence==SEEK_CUR){ + int ret; + ret=fgetpos((FILE *)_stream,(fpos_t *)&pos); + if(ret)return ret; + } + else if(_whence==SEEK_END)pos=_filelengthi64(_fileno((FILE *)_stream)); + else if(_whence==SEEK_SET)pos=0; + else return -1; + /*Check for errors or overflow.*/ + if(pos<0||_offset<-pos||_offset>OP_INT64_MAX-pos)return -1; + pos+=_offset; + return fsetpos((FILE *)_stream,(fpos_t *)&pos); +#else + /*This function actually conforms to the SUSv2 and POSIX.1-2001, so we prefer + it except on Windows.*/ + return fseeko((FILE *)_stream,(off_t)_offset,_whence); +#endif +} + +static opus_int64 op_ftell(void *_stream){ +#if defined(_WIN32) + /*_ftelli64() is not exposed until MSCVCRT80, and ftello()/ftello64() have + the same problems as fseeko()/fseeko64() in MingW. + See above for a more detailed explanation.*/ + opus_int64 pos; + OP_ASSERT(sizeof(pos)==sizeof(fpos_t)); + return fgetpos((FILE *)_stream,(fpos_t *)&pos)?-1:pos; +#else + /*This function actually conforms to the SUSv2 and POSIX.1-2001, so we prefer + it except on Windows.*/ + return ftello((FILE *)_stream); +#endif +} + +static const OpusFileCallbacks OP_FILE_CALLBACKS={ + op_fread, + op_fseek, + op_ftell, + (op_close_func)fclose +}; + +#if defined(_WIN32) +# include +# include + +/*Windows doesn't accept UTF-8 by default, and we don't have a wchar_t API, + so if we just pass the path to fopen(), then there'd be no way for a user + of our API to open a Unicode filename. + Instead, we translate from UTF-8 to UTF-16 and use Windows' wchar_t API. + This makes this API more consistent with platforms where the character set + used by fopen is the same as used on disk, which is generally UTF-8, and + with our metadata API, which always uses UTF-8.*/ +static wchar_t *op_utf8_to_utf16(const char *_src){ + wchar_t *dst; + size_t len; + len=strlen(_src); + /*Worst-case output is 1 wide character per 1 input character.*/ + dst=(wchar_t *)_ogg_malloc(sizeof(*dst)*(len+1)); + if(dst!=NULL){ + size_t si; + size_t di; + for(di=si=0;si=0x80U){ + /*This is a 2-byte sequence that is not overlong.*/ + dst[di++]=w; + si++; + continue; + } + } + else{ + int c2; + /*This is safe, because c1 was not 0 and _src is NUL-terminated.*/ + c2=(unsigned char)_src[si+2]; + if((c2&0xC0)==0x80){ + /*Found at least two continuation bytes.*/ + if((c0&0xF0)==0xE0){ + wchar_t w; + /*Start byte says this is a 3-byte sequence.*/ + w=(c0&0xF)<<12|(c1&0x3F)<<6|c2&0x3F; + if(w>=0x800U&&(w<0xD800||w>=0xE000)&&w<0xFFFE){ + /*This is a 3-byte sequence that is not overlong, not a + UTF-16 surrogate pair value, and not a 'not a character' + value.*/ + dst[di++]=w; + si+=2; + continue; + } + } + else{ + int c3; + /*This is safe, because c2 was not 0 and _src is + NUL-terminated.*/ + c3=(unsigned char)_src[si+3]; + if((c3&0xC0)==0x80){ + /*Found at least three continuation bytes.*/ + if((c0&0xF8)==0xF0){ + opus_uint32 w; + /*Start byte says this is a 4-byte sequence.*/ + w=(c0&7)<<18|(c1&0x3F)<<12|(c2&0x3F)<<6&(c3&0x3F); + if(w>=0x10000U&&w<0x110000U){ + /*This is a 4-byte sequence that is not overlong and not + greater than the largest valid Unicode code point. + Convert it to a surrogate pair.*/ + w-=0x10000; + dst[di++]=(wchar_t)(0xD800+(w>>10)); + dst[di++]=(wchar_t)(0xDC00+(w&0x3FF)); + si+=3; + continue; + } + } + } + } + } + } + } + } + /*If we got here, we encountered an illegal UTF-8 sequence.*/ + _ogg_free(dst); + return NULL; + } + OP_ASSERT(di<=len); + dst[di]='\0'; + } + return dst; +} + +#endif + +void *op_fopen(OpusFileCallbacks *_cb,const char *_path,const char *_mode){ + FILE *fp; +#if !defined(_WIN32) + fp=fopen(_path,_mode); +#else + fp=NULL; + if(_path==NULL||_mode==NULL)errno=EINVAL; + else{ + wchar_t *wpath; + wchar_t *wmode; + wpath=op_utf8_to_utf16(_path); + wmode=op_utf8_to_utf16(_mode); + if(wmode==NULL)errno=EINVAL; + else if(wpath==NULL)errno=ENOENT; + else fp=_wfopen(wpath,wmode); + _ogg_free(wmode); + _ogg_free(wpath); + } +#endif + if(fp!=NULL)*_cb=*&OP_FILE_CALLBACKS; + return fp; +} + +void *op_fdopen(OpusFileCallbacks *_cb,int _fd,const char *_mode){ + FILE *fp; + fp=fdopen(_fd,_mode); + if(fp!=NULL)*_cb=*&OP_FILE_CALLBACKS; + return fp; +} + +void *op_freopen(OpusFileCallbacks *_cb,const char *_path,const char *_mode, + void *_stream){ + FILE *fp; +#if !defined(_WIN32) + fp=freopen(_path,_mode,(FILE *)_stream); +#else + fp=NULL; + if(_path==NULL||_mode==NULL)errno=EINVAL; + else{ + wchar_t *wpath; + wchar_t *wmode; + wpath=op_utf8_to_utf16(_path); + wmode=op_utf8_to_utf16(_mode); + if(wmode==NULL)errno=EINVAL; + else if(wpath==NULL)errno=ENOENT; + else fp=_wfreopen(wpath,wmode,(FILE *)_stream); + _ogg_free(wmode); + _ogg_free(wpath); + } +#endif + if(fp!=NULL)*_cb=*&OP_FILE_CALLBACKS; + return fp; +} + +static int op_mem_read(void *_stream,unsigned char *_ptr,int _buf_size){ + OpusMemStream *stream; + ptrdiff_t size; + ptrdiff_t pos; + stream=(OpusMemStream *)_stream; + /*Check for empty read.*/ + if(_buf_size<=0)return 0; + size=stream->size; + pos=stream->pos; + /*Check for EOF.*/ + if(pos>=size)return 0; + /*Check for a short read.*/ + _buf_size=(int)OP_MIN(size-pos,_buf_size); + memcpy(_ptr,stream->data+pos,_buf_size); + pos+=_buf_size; + stream->pos=pos; + return _buf_size; +} + +static int op_mem_seek(void *_stream,opus_int64 _offset,int _whence){ + OpusMemStream *stream; + ptrdiff_t pos; + stream=(OpusMemStream *)_stream; + pos=stream->pos; + OP_ASSERT(pos>=0); + switch(_whence){ + case SEEK_SET:{ + /*Check for overflow:*/ + if(_offset<0||_offset>OP_MEM_DIFF_MAX)return -1; + pos=(ptrdiff_t)_offset; + }break; + case SEEK_CUR:{ + /*Check for overflow:*/ + if(_offset<-pos||_offset>OP_MEM_DIFF_MAX-pos)return -1; + pos=(ptrdiff_t)(pos+_offset); + }break; + case SEEK_END:{ + ptrdiff_t size; + size=stream->size; + OP_ASSERT(size>=0); + /*Check for overflow:*/ + if(_offset>size||_offsetpos=pos; + return 0; +} + +static opus_int64 op_mem_tell(void *_stream){ + OpusMemStream *stream; + stream=(OpusMemStream *)_stream; + return (ogg_int64_t)stream->pos; +} + +static int op_mem_close(void *_stream){ + _ogg_free(_stream); + return 0; +} + +static const OpusFileCallbacks OP_MEM_CALLBACKS={ + op_mem_read, + op_mem_seek, + op_mem_tell, + op_mem_close +}; + +void *op_mem_stream_create(OpusFileCallbacks *_cb, + const unsigned char *_data,size_t _size){ + OpusMemStream *stream; + if(_size>OP_MEM_SIZE_MAX)return NULL; + stream=(OpusMemStream *)_ogg_malloc(sizeof(*stream)); + if(stream!=NULL){ + *_cb=*&OP_MEM_CALLBACKS; + stream->data=_data; + stream->size=_size; + stream->pos=0; + } + return stream; +} diff --git a/TelegramClient.Opus/opus/silk/A2NLSF.c b/TelegramClient.Opus/opus/silk/A2NLSF.c new file mode 100755 index 0000000..74b1b95 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/A2NLSF.c @@ -0,0 +1,252 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +/* Conversion between prediction filter coefficients and NLSFs */ +/* Requires the order to be an even number */ +/* A piecewise linear approximation maps LSF <-> cos(LSF) */ +/* Therefore the result is not accurate NLSFs, but the two */ +/* functions are accurate inverses of each other */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" +#include "tables.h" + +/* Number of binary divisions, when not in low complexity mode */ +#define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */ +#define MAX_ITERATIONS_A2NLSF_FIX 30 + +/* Helper function for A2NLSF(..) */ +/* Transforms polynomials from cos(n*f) to cos(f)^n */ +static OPUS_INLINE void silk_A2NLSF_trans_poly( + opus_int32 *p, /* I/O Polynomial */ + const opus_int dd /* I Polynomial order (= filter order / 2 ) */ +) +{ + opus_int k, n; + + for( k = 2; k <= dd; k++ ) { + for( n = dd; n > k; n-- ) { + p[ n - 2 ] -= p[ n ]; + } + p[ k - 2 ] -= silk_LSHIFT( p[ k ], 1 ); + } +} +/* Helper function for A2NLSF(..) */ +/* Polynomial evaluation */ +static OPUS_INLINE opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in Q16 */ + opus_int32 *p, /* I Polynomial, Q16 */ + const opus_int32 x, /* I Evaluation point, Q12 */ + const opus_int dd /* I Order */ +) +{ + opus_int n; + opus_int32 x_Q16, y32; + + y32 = p[ dd ]; /* Q16 */ + x_Q16 = silk_LSHIFT( x, 4 ); + for( n = dd - 1; n >= 0; n-- ) { + y32 = silk_SMLAWW( p[ n ], y32, x_Q16 ); /* Q16 */ + } + return y32; +} + +static OPUS_INLINE void silk_A2NLSF_init( + const opus_int32 *a_Q16, + opus_int32 *P, + opus_int32 *Q, + const opus_int dd +) +{ + opus_int k; + + /* Convert filter coefs to even and odd polynomials */ + P[dd] = silk_LSHIFT( 1, 16 ); + Q[dd] = silk_LSHIFT( 1, 16 ); + for( k = 0; k < dd; k++ ) { + P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; /* Q16 */ + Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; /* Q16 */ + } + + /* Divide out zeros as we have that for even filter orders, */ + /* z = 1 is always a root in Q, and */ + /* z = -1 is always a root in P */ + for( k = dd; k > 0; k-- ) { + P[ k - 1 ] -= P[ k ]; + Q[ k - 1 ] += Q[ k ]; + } + + /* Transform polynomials from cos(n*f) to cos(f)^n */ + silk_A2NLSF_trans_poly( P, dd ); + silk_A2NLSF_trans_poly( Q, dd ); +} + +/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */ +/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */ +void silk_A2NLSF( + opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */ + opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */ + const opus_int d /* I Filter order (must be even) */ +) +{ + opus_int i, k, m, dd, root_ix, ffrac; + opus_int32 xlo, xhi, xmid; + opus_int32 ylo, yhi, ymid, thr; + opus_int32 nom, den; + opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ]; + opus_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ]; + opus_int32 *PQ[ 2 ]; + opus_int32 *p; + + /* Store pointers to array */ + PQ[ 0 ] = P; + PQ[ 1 ] = Q; + + dd = silk_RSHIFT( d, 1 ); + + silk_A2NLSF_init( a_Q16, P, Q, dd ); + + /* Find roots, alternating between P and Q */ + p = P; /* Pointer to polynomial */ + + xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/ + ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); + + if( ylo < 0 ) { + /* Set the first NLSF to zero and move on to the next */ + NLSF[ 0 ] = 0; + p = Q; /* Pointer to polynomial */ + ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); + root_ix = 1; /* Index of current root */ + } else { + root_ix = 0; /* Index of current root */ + } + k = 1; /* Loop counter */ + i = 0; /* Counter for bandwidth expansions applied */ + thr = 0; + while( 1 ) { + /* Evaluate polynomial */ + xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */ + yhi = silk_A2NLSF_eval_poly( p, xhi, dd ); + + /* Detect zero crossing */ + if( ( ylo <= 0 && yhi >= thr ) || ( ylo >= 0 && yhi <= -thr ) ) { + if( yhi == 0 ) { + /* If the root lies exactly at the end of the current */ + /* interval, look for the next root in the next interval */ + thr = 1; + } else { + thr = 0; + } + /* Binary division */ + ffrac = -256; + for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) { + /* Evaluate polynomial */ + xmid = silk_RSHIFT_ROUND( xlo + xhi, 1 ); + ymid = silk_A2NLSF_eval_poly( p, xmid, dd ); + + /* Detect zero crossing */ + if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) { + /* Reduce frequency */ + xhi = xmid; + yhi = ymid; + } else { + /* Increase frequency */ + xlo = xmid; + ylo = ymid; + ffrac = silk_ADD_RSHIFT( ffrac, 128, m ); + } + } + + /* Interpolate */ + if( silk_abs( ylo ) < 65536 ) { + /* Avoid dividing by zero */ + den = ylo - yhi; + nom = silk_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + silk_RSHIFT( den, 1 ); + if( den != 0 ) { + ffrac += silk_DIV32( nom, den ); + } + } else { + /* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */ + ffrac += silk_DIV32( ylo, silk_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) ); + } + NLSF[ root_ix ] = (opus_int16)silk_min_32( silk_LSHIFT( (opus_int32)k, 8 ) + ffrac, silk_int16_MAX ); + + silk_assert( NLSF[ root_ix ] >= 0 ); + + root_ix++; /* Next root */ + if( root_ix >= d ) { + /* Found all roots */ + break; + } + /* Alternate pointer to polynomial */ + p = PQ[ root_ix & 1 ]; + + /* Evaluate polynomial */ + xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; /* Q12*/ + ylo = silk_LSHIFT( 1 - ( root_ix & 2 ), 12 ); + } else { + /* Increment loop counter */ + k++; + xlo = xhi; + ylo = yhi; + thr = 0; + + if( k > LSF_COS_TAB_SZ_FIX ) { + i++; + if( i > MAX_ITERATIONS_A2NLSF_FIX ) { + /* Set NLSFs to white spectrum and exit */ + NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 ); + for( k = 1; k < d; k++ ) { + NLSF[ k ] = (opus_int16)silk_SMULBB( k + 1, NLSF[ 0 ] ); + } + return; + } + + /* Error: Apply progressively more bandwidth expansion and run again */ + silk_bwexpander_32( a_Q16, d, 65536 - silk_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015*/ + + silk_A2NLSF_init( a_Q16, P, Q, dd ); + p = P; /* Pointer to polynomial */ + xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/ + ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); + if( ylo < 0 ) { + /* Set the first NLSF to zero and move on to the next */ + NLSF[ 0 ] = 0; + p = Q; /* Pointer to polynomial */ + ylo = silk_A2NLSF_eval_poly( p, xlo, dd ); + root_ix = 1; /* Index of current root */ + } else { + root_ix = 0; /* Index of current root */ + } + k = 1; /* Reset loop counter */ + } + } + } +} diff --git a/TelegramClient.Opus/opus/silk/API.h b/TelegramClient.Opus/opus/silk/API.h new file mode 100755 index 0000000..f0601bc --- /dev/null +++ b/TelegramClient.Opus/opus/silk/API.h @@ -0,0 +1,133 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_API_H +#define SILK_API_H + +#include "control.h" +#include "typedef.h" +#include "errors.h" +#include "entenc.h" +#include "entdec.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define SILK_MAX_FRAMES_PER_PACKET 3 + +/* Struct for TOC (Table of Contents) */ +typedef struct { + opus_int VADFlag; /* Voice activity for packet */ + opus_int VADFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* Voice activity for each frame in packet */ + opus_int inbandFECFlag; /* Flag indicating if packet contains in-band FEC */ +} silk_TOC_struct; + +/****************************************/ +/* Encoder functions */ +/****************************************/ + +/***********************************************/ +/* Get size in bytes of the Silk encoder state */ +/***********************************************/ +opus_int silk_Get_Encoder_Size( /* O Returns error code */ + opus_int *encSizeBytes /* O Number of bytes in SILK encoder state */ +); + +/*************************/ +/* Init or reset encoder */ +/*************************/ +opus_int silk_InitEncoder( /* O Returns error code */ + void *encState, /* I/O State */ + int arch, /* I Run-time architecture */ + silk_EncControlStruct *encStatus /* O Encoder Status */ +); + +/**************************/ +/* Encode frame with Silk */ +/**************************/ +/* Note: if prefillFlag is set, the input must contain 10 ms of audio, irrespective of what */ +/* encControl->payloadSize_ms is set to */ +opus_int silk_Encode( /* O Returns error code */ + void *encState, /* I/O State */ + silk_EncControlStruct *encControl, /* I Control status */ + const opus_int16 *samplesIn, /* I Speech sample input vector */ + opus_int nSamplesIn, /* I Number of samples in input vector */ + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */ + const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */ +); + +/****************************************/ +/* Decoder functions */ +/****************************************/ + +/***********************************************/ +/* Get size in bytes of the Silk decoder state */ +/***********************************************/ +opus_int silk_Get_Decoder_Size( /* O Returns error code */ + opus_int *decSizeBytes /* O Number of bytes in SILK decoder state */ +); + +/*************************/ +/* Init or Reset decoder */ +/*************************/ +opus_int silk_InitDecoder( /* O Returns error code */ + void *decState /* I/O State */ +); + +/******************/ +/* Decode a frame */ +/******************/ +opus_int silk_Decode( /* O Returns error code */ + void* decState, /* I/O State */ + silk_DecControlStruct* decControl, /* I/O Control Structure */ + opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */ + opus_int newPacketFlag, /* I Indicates first decoder call for this packet */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int16 *samplesOut, /* O Decoded output speech vector */ + opus_int32 *nSamplesOut /* O Number of samples decoded */ +); + +#if 0 +/**************************************/ +/* Get table of contents for a packet */ +/**************************************/ +opus_int silk_get_TOC( + const opus_uint8 *payload, /* I Payload data */ + const opus_int nBytesIn, /* I Number of input bytes */ + const opus_int nFramesPerPayload, /* I Number of SILK frames per payload */ + silk_TOC_struct *Silk_TOC /* O Type of content */ +); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/TelegramClient.Opus/opus/silk/CNG.c b/TelegramClient.Opus/opus/silk/CNG.c new file mode 100755 index 0000000..8481d95 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/CNG.c @@ -0,0 +1,172 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "stack_alloc.h" + +/* Generates excitation for CNG LPC synthesis */ +static OPUS_INLINE void silk_CNG_exc( + opus_int32 residual_Q10[], /* O CNG residual signal Q10 */ + opus_int32 exc_buf_Q14[], /* I Random samples buffer Q10 */ + opus_int32 Gain_Q16, /* I Gain to apply */ + opus_int length, /* I Length */ + opus_int32 *rand_seed /* I/O Seed to random index generator */ +) +{ + opus_int32 seed; + opus_int i, idx, exc_mask; + + exc_mask = CNG_BUF_MASK_MAX; + while( exc_mask > length ) { + exc_mask = silk_RSHIFT( exc_mask, 1 ); + } + + seed = *rand_seed; + for( i = 0; i < length; i++ ) { + seed = silk_RAND( seed ); + idx = (opus_int)( silk_RSHIFT( seed, 24 ) & exc_mask ); + silk_assert( idx >= 0 ); + silk_assert( idx <= CNG_BUF_MASK_MAX ); + residual_Q10[ i ] = (opus_int16)silk_SAT16( silk_SMULWW( exc_buf_Q14[ idx ], Gain_Q16 >> 4 ) ); + } + *rand_seed = seed; +} + +void silk_CNG_Reset( + silk_decoder_state *psDec /* I/O Decoder state */ +) +{ + opus_int i, NLSF_step_Q15, NLSF_acc_Q15; + + NLSF_step_Q15 = silk_DIV32_16( silk_int16_MAX, psDec->LPC_order + 1 ); + NLSF_acc_Q15 = 0; + for( i = 0; i < psDec->LPC_order; i++ ) { + NLSF_acc_Q15 += NLSF_step_Q15; + psDec->sCNG.CNG_smth_NLSF_Q15[ i ] = NLSF_acc_Q15; + } + psDec->sCNG.CNG_smth_Gain_Q16 = 0; + psDec->sCNG.rand_seed = 3176576; +} + +/* Updates CNG estimate, and applies the CNG when packet was lost */ +void silk_CNG( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 frame[], /* I/O Signal */ + opus_int length /* I Length of residual */ +) +{ + opus_int i, subfr; + opus_int32 sum_Q6, max_Gain_Q16; + opus_int16 A_Q12[ MAX_LPC_ORDER ]; + silk_CNG_struct *psCNG = &psDec->sCNG; + SAVE_STACK; + + if( psDec->fs_kHz != psCNG->fs_kHz ) { + /* Reset state */ + silk_CNG_Reset( psDec ); + + psCNG->fs_kHz = psDec->fs_kHz; + } + if( psDec->lossCnt == 0 && psDec->prevSignalType == TYPE_NO_VOICE_ACTIVITY ) { + /* Update CNG parameters */ + + /* Smoothing of LSF's */ + for( i = 0; i < psDec->LPC_order; i++ ) { + psCNG->CNG_smth_NLSF_Q15[ i ] += silk_SMULWB( (opus_int32)psDec->prevNLSF_Q15[ i ] - (opus_int32)psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 ); + } + /* Find the subframe with the highest gain */ + max_Gain_Q16 = 0; + subfr = 0; + for( i = 0; i < psDec->nb_subfr; i++ ) { + if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) { + max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ]; + subfr = i; + } + } + /* Update CNG excitation buffer with excitation from this subframe */ + silk_memmove( &psCNG->CNG_exc_buf_Q14[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q14, ( psDec->nb_subfr - 1 ) * psDec->subfr_length * sizeof( opus_int32 ) ); + silk_memcpy( psCNG->CNG_exc_buf_Q14, &psDec->exc_Q14[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( opus_int32 ) ); + + /* Smooth gains */ + for( i = 0; i < psDec->nb_subfr; i++ ) { + psCNG->CNG_smth_Gain_Q16 += silk_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 ); + } + } + + /* Add CNG when packet is lost or during DTX */ + if( psDec->lossCnt ) { + VARDECL( opus_int32, CNG_sig_Q10 ); + + ALLOC( CNG_sig_Q10, length + MAX_LPC_ORDER, opus_int32 ); + + /* Generate CNG excitation */ + silk_CNG_exc( CNG_sig_Q10 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, psCNG->CNG_smth_Gain_Q16, length, &psCNG->rand_seed ); + + /* Convert CNG NLSF to filter representation */ + silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order ); + + /* Generate CNG signal, by synthesis filtering */ + silk_memcpy( CNG_sig_Q10, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) ); + for( i = 0; i < length; i++ ) { + silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 ); + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + sum_Q6 = silk_RSHIFT( psDec->LPC_order, 1 ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); + if( psDec->LPC_order == 16 ) { + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] ); + sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] ); + } + + /* Update states */ + CNG_sig_Q10[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q10[ MAX_LPC_ORDER + i ], sum_Q6, 4 ); + + frame[ i ] = silk_ADD_SAT16( frame[ i ], silk_RSHIFT_ROUND( sum_Q6, 6 ) ); + } + silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q10[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); + } else { + silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( opus_int32 ) ); + } + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/HP_variable_cutoff.c b/TelegramClient.Opus/opus/silk/HP_variable_cutoff.c new file mode 100755 index 0000000..bbe10f0 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/HP_variable_cutoff.c @@ -0,0 +1,77 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef FIXED_POINT +#include "main_FIX.h" +#else +#include "main_FLP.h" +#endif +#include "tuning_parameters.h" + +/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ +void silk_HP_variable_cutoff( + silk_encoder_state_Fxx state_Fxx[] /* I/O Encoder states */ +) +{ + opus_int quality_Q15; + opus_int32 pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7; + silk_encoder_state *psEncC1 = &state_Fxx[ 0 ].sCmn; + + /* Adaptive cutoff frequency: estimate low end of pitch frequency range */ + if( psEncC1->prevSignalType == TYPE_VOICED ) { + /* difference, in log domain */ + pitch_freq_Hz_Q16 = silk_DIV32_16( silk_LSHIFT( silk_MUL( psEncC1->fs_kHz, 1000 ), 16 ), psEncC1->prevLag ); + pitch_freq_log_Q7 = silk_lin2log( pitch_freq_Hz_Q16 ) - ( 16 << 7 ); + + /* adjustment based on quality */ + quality_Q15 = psEncC1->input_quality_bands_Q15[ 0 ]; + pitch_freq_log_Q7 = silk_SMLAWB( pitch_freq_log_Q7, silk_SMULWB( silk_LSHIFT( -quality_Q15, 2 ), quality_Q15 ), + pitch_freq_log_Q7 - ( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ) ) ); + + /* delta_freq = pitch_freq_log - psEnc->variable_HP_smth1; */ + delta_freq_Q7 = pitch_freq_log_Q7 - silk_RSHIFT( psEncC1->variable_HP_smth1_Q15, 8 ); + if( delta_freq_Q7 < 0 ) { + /* less smoothing for decreasing pitch frequency, to track something close to the minimum */ + delta_freq_Q7 = silk_MUL( delta_freq_Q7, 3 ); + } + + /* limit delta, to reduce impact of outliers in pitch estimation */ + delta_freq_Q7 = silk_LIMIT_32( delta_freq_Q7, -SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ), SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ) ); + + /* update smoother */ + psEncC1->variable_HP_smth1_Q15 = silk_SMLAWB( psEncC1->variable_HP_smth1_Q15, + silk_SMULBB( psEncC1->speech_activity_Q8, delta_freq_Q7 ), SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF1, 16 ) ); + + /* limit frequency range */ + psEncC1->variable_HP_smth1_Q15 = silk_LIMIT_32( psEncC1->variable_HP_smth1_Q15, + silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ), + silk_LSHIFT( silk_lin2log( VARIABLE_HP_MAX_CUTOFF_HZ ), 8 ) ); + } +} diff --git a/TelegramClient.Opus/opus/silk/Inlines.h b/TelegramClient.Opus/opus/silk/Inlines.h new file mode 100755 index 0000000..ec986cd --- /dev/null +++ b/TelegramClient.Opus/opus/silk/Inlines.h @@ -0,0 +1,188 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +/*! \file silk_Inlines.h + * \brief silk_Inlines.h defines OPUS_INLINE signal processing functions. + */ + +#ifndef SILK_FIX_INLINES_H +#define SILK_FIX_INLINES_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* count leading zeros of opus_int64 */ +static OPUS_INLINE opus_int32 silk_CLZ64( opus_int64 in ) +{ + opus_int32 in_upper; + + in_upper = (opus_int32)silk_RSHIFT64(in, 32); + if (in_upper == 0) { + /* Search in the lower 32 bits */ + return 32 + silk_CLZ32( (opus_int32) in ); + } else { + /* Search in the upper 32 bits */ + return silk_CLZ32( in_upper ); + } +} + +/* get number of leading zeros and fractional part (the bits right after the leading one */ +static OPUS_INLINE void silk_CLZ_FRAC( + opus_int32 in, /* I input */ + opus_int32 *lz, /* O number of leading zeros */ + opus_int32 *frac_Q7 /* O the 7 bits right after the leading one */ +) +{ + opus_int32 lzeros = silk_CLZ32(in); + + * lz = lzeros; + * frac_Q7 = silk_ROR32(in, 24 - lzeros) & 0x7f; +} + +/* Approximation of square root */ +/* Accuracy: < +/- 10% for output values > 15 */ +/* < +/- 2.5% for output values > 120 */ +static OPUS_INLINE opus_int32 silk_SQRT_APPROX( opus_int32 x ) +{ + opus_int32 y, lz, frac_Q7; + + if( x <= 0 ) { + return 0; + } + + silk_CLZ_FRAC(x, &lz, &frac_Q7); + + if( lz & 1 ) { + y = 32768; + } else { + y = 46214; /* 46214 = sqrt(2) * 32768 */ + } + + /* get scaling right */ + y >>= silk_RSHIFT(lz, 1); + + /* increment using fractional part of input */ + y = silk_SMLAWB(y, y, silk_SMULBB(213, frac_Q7)); + + return y; +} + +/* Divide two int32 values and return result as int32 in a given Q-domain */ +static OPUS_INLINE opus_int32 silk_DIV32_varQ( /* O returns a good approximation of "(a32 << Qres) / b32" */ + const opus_int32 a32, /* I numerator (Q0) */ + const opus_int32 b32, /* I denominator (Q0) */ + const opus_int Qres /* I Q-domain of result (>= 0) */ +) +{ + opus_int a_headrm, b_headrm, lshift; + opus_int32 b32_inv, a32_nrm, b32_nrm, result; + + silk_assert( b32 != 0 ); + silk_assert( Qres >= 0 ); + + /* Compute number of bits head room and normalize inputs */ + a_headrm = silk_CLZ32( silk_abs(a32) ) - 1; + a32_nrm = silk_LSHIFT(a32, a_headrm); /* Q: a_headrm */ + b_headrm = silk_CLZ32( silk_abs(b32) ) - 1; + b32_nrm = silk_LSHIFT(b32, b_headrm); /* Q: b_headrm */ + + /* Inverse of b32, with 14 bits of precision */ + b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */ + + /* First approximation */ + result = silk_SMULWB(a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */ + + /* Compute residual by subtracting product of denominator and first approximation */ + /* It's OK to overflow because the final value of a32_nrm should always be small */ + a32_nrm = silk_SUB32_ovflw(a32_nrm, silk_LSHIFT_ovflw( silk_SMMUL(b32_nrm, result), 3 )); /* Q: a_headrm */ + + /* Refinement */ + result = silk_SMLAWB(result, a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */ + + /* Convert to Qres domain */ + lshift = 29 + a_headrm - b_headrm - Qres; + if( lshift < 0 ) { + return silk_LSHIFT_SAT32(result, -lshift); + } else { + if( lshift < 32){ + return silk_RSHIFT(result, lshift); + } else { + /* Avoid undefined result */ + return 0; + } + } +} + +/* Invert int32 value and return result as int32 in a given Q-domain */ +static OPUS_INLINE opus_int32 silk_INVERSE32_varQ( /* O returns a good approximation of "(1 << Qres) / b32" */ + const opus_int32 b32, /* I denominator (Q0) */ + const opus_int Qres /* I Q-domain of result (> 0) */ +) +{ + opus_int b_headrm, lshift; + opus_int32 b32_inv, b32_nrm, err_Q32, result; + + silk_assert( b32 != 0 ); + silk_assert( Qres > 0 ); + + /* Compute number of bits head room and normalize input */ + b_headrm = silk_CLZ32( silk_abs(b32) ) - 1; + b32_nrm = silk_LSHIFT(b32, b_headrm); /* Q: b_headrm */ + + /* Inverse of b32, with 14 bits of precision */ + b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */ + + /* First approximation */ + result = silk_LSHIFT(b32_inv, 16); /* Q: 61 - b_headrm */ + + /* Compute residual by subtracting product of denominator and first approximation from one */ + err_Q32 = silk_LSHIFT( ((opus_int32)1<<29) - silk_SMULWB(b32_nrm, b32_inv), 3 ); /* Q32 */ + + /* Refinement */ + result = silk_SMLAWW(result, err_Q32, b32_inv); /* Q: 61 - b_headrm */ + + /* Convert to Qres domain */ + lshift = 61 - b_headrm - Qres; + if( lshift <= 0 ) { + return silk_LSHIFT_SAT32(result, -lshift); + } else { + if( lshift < 32){ + return silk_RSHIFT(result, lshift); + }else{ + /* Avoid undefined result */ + return 0; + } + } +} + +#ifdef __cplusplus +} +#endif + +#endif /* SILK_FIX_INLINES_H */ diff --git a/TelegramClient.Opus/opus/silk/LPC_analysis_filter.c b/TelegramClient.Opus/opus/silk/LPC_analysis_filter.c new file mode 100755 index 0000000..9d1f16c --- /dev/null +++ b/TelegramClient.Opus/opus/silk/LPC_analysis_filter.c @@ -0,0 +1,106 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" +#include "celt_lpc.h" + +/*******************************************/ +/* LPC analysis filter */ +/* NB! State is kept internally and the */ +/* filter always starts with zero state */ +/* first d output samples are set to zero */ +/*******************************************/ + +void silk_LPC_analysis_filter( + opus_int16 *out, /* O Output signal */ + const opus_int16 *in, /* I Input signal */ + const opus_int16 *B, /* I MA prediction coefficients, Q12 [order] */ + const opus_int32 len, /* I Signal length */ + const opus_int32 d /* I Filter order */ +) +{ + opus_int j; +#ifdef FIXED_POINT + opus_int16 mem[SILK_MAX_ORDER_LPC]; + opus_int16 num[SILK_MAX_ORDER_LPC]; +#else + int ix; + opus_int32 out32_Q12, out32; + const opus_int16 *in_ptr; +#endif + + silk_assert( d >= 6 ); + silk_assert( (d & 1) == 0 ); + silk_assert( d <= len ); + +#ifdef FIXED_POINT + silk_assert( d <= SILK_MAX_ORDER_LPC ); + for ( j = 0; j < d; j++ ) { + num[ j ] = -B[ j ]; + } + for (j=0;j 0; k-- ) { + /* Check for stability */ + if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) { + return 0; + } + + /* Set RC equal to negated AR coef */ + rc_Q31 = -silk_LSHIFT( Anew_QA[ k ], 31 - QA ); + + /* rc_mult1_Q30 range: [ 1 : 2^30 ] */ + rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); + silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */ + silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) ); + + /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */ + mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) ); + rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 ); + + /* Update inverse gain */ + /* invGain_Q30 range: [ 0 : 2^30 ] */ + invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 ); + silk_assert( invGain_Q30 >= 0 ); + silk_assert( invGain_Q30 <= ( 1 << 30 ) ); + + /* Swap pointers */ + Aold_QA = Anew_QA; + Anew_QA = A_QA[ k & 1 ]; + + /* Update AR coefficient */ + for( n = 0; n < k; n++ ) { + tmp_QA = Aold_QA[ n ] - MUL32_FRAC_Q( Aold_QA[ k - n - 1 ], rc_Q31, 31 ); + Anew_QA[ n ] = MUL32_FRAC_Q( tmp_QA, rc_mult2 , mult2Q ); + } + } + + /* Check for stability */ + if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) { + return 0; + } + + /* Set RC equal to negated AR coef */ + rc_Q31 = -silk_LSHIFT( Anew_QA[ 0 ], 31 - QA ); + + /* Range: [ 1 : 2^30 ] */ + rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); + + /* Update inverse gain */ + /* Range: [ 0 : 2^30 ] */ + invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 ); + silk_assert( invGain_Q30 >= 0 ); + silk_assert( invGain_Q30 <= 1<<30 ); + + return invGain_Q30; +} + +/* For input in Q12 domain */ +opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */ + const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */ + const opus_int order /* I Prediction order */ +) +{ + opus_int k; + opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; + opus_int32 *Anew_QA; + opus_int32 DC_resp = 0; + + Anew_QA = Atmp_QA[ order & 1 ]; + + /* Increase Q domain of the AR coefficients */ + for( k = 0; k < order; k++ ) { + DC_resp += (opus_int32)A_Q12[ k ]; + Anew_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 ); + } + /* If the DC is unstable, we don't even need to do the full calculations */ + if( DC_resp >= 4096 ) { + return 0; + } + return LPC_inverse_pred_gain_QA( Atmp_QA, order ); +} + +#ifdef FIXED_POINT + +/* For input in Q24 domain */ +opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */ + const opus_int32 *A_Q24, /* I Prediction coefficients [order] */ + const opus_int order /* I Prediction order */ +) +{ + opus_int k; + opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ]; + opus_int32 *Anew_QA; + + Anew_QA = Atmp_QA[ order & 1 ]; + + /* Increase Q domain of the AR coefficients */ + for( k = 0; k < order; k++ ) { + Anew_QA[ k ] = silk_RSHIFT32( A_Q24[ k ], 24 - QA ); + } + + return LPC_inverse_pred_gain_QA( Atmp_QA, order ); +} +#endif diff --git a/TelegramClient.Opus/opus/silk/LP_variable_cutoff.c b/TelegramClient.Opus/opus/silk/LP_variable_cutoff.c new file mode 100755 index 0000000..f639e1f --- /dev/null +++ b/TelegramClient.Opus/opus/silk/LP_variable_cutoff.c @@ -0,0 +1,135 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + Elliptic/Cauer filters designed with 0.1 dB passband ripple, + 80 dB minimum stopband attenuation, and + [0.95 : 0.15 : 0.35] normalized cut off frequencies. +*/ + +#include "main.h" + +/* Helper function, interpolates the filter taps */ +static OPUS_INLINE void silk_LP_interpolate_filter_taps( + opus_int32 B_Q28[ TRANSITION_NB ], + opus_int32 A_Q28[ TRANSITION_NA ], + const opus_int ind, + const opus_int32 fac_Q16 +) +{ + opus_int nb, na; + + if( ind < TRANSITION_INT_NUM - 1 ) { + if( fac_Q16 > 0 ) { + if( fac_Q16 < 32768 ) { /* fac_Q16 is in range of a 16-bit int */ + /* Piece-wise linear interpolation of B and A */ + for( nb = 0; nb < TRANSITION_NB; nb++ ) { + B_Q28[ nb ] = silk_SMLAWB( + silk_Transition_LP_B_Q28[ ind ][ nb ], + silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] - + silk_Transition_LP_B_Q28[ ind ][ nb ], + fac_Q16 ); + } + for( na = 0; na < TRANSITION_NA; na++ ) { + A_Q28[ na ] = silk_SMLAWB( + silk_Transition_LP_A_Q28[ ind ][ na ], + silk_Transition_LP_A_Q28[ ind + 1 ][ na ] - + silk_Transition_LP_A_Q28[ ind ][ na ], + fac_Q16 ); + } + } else { /* ( fac_Q16 - ( 1 << 16 ) ) is in range of a 16-bit int */ + silk_assert( fac_Q16 - ( 1 << 16 ) == silk_SAT16( fac_Q16 - ( 1 << 16 ) ) ); + /* Piece-wise linear interpolation of B and A */ + for( nb = 0; nb < TRANSITION_NB; nb++ ) { + B_Q28[ nb ] = silk_SMLAWB( + silk_Transition_LP_B_Q28[ ind + 1 ][ nb ], + silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] - + silk_Transition_LP_B_Q28[ ind ][ nb ], + fac_Q16 - ( (opus_int32)1 << 16 ) ); + } + for( na = 0; na < TRANSITION_NA; na++ ) { + A_Q28[ na ] = silk_SMLAWB( + silk_Transition_LP_A_Q28[ ind + 1 ][ na ], + silk_Transition_LP_A_Q28[ ind + 1 ][ na ] - + silk_Transition_LP_A_Q28[ ind ][ na ], + fac_Q16 - ( (opus_int32)1 << 16 ) ); + } + } + } else { + silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( opus_int32 ) ); + silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( opus_int32 ) ); + } + } else { + silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( opus_int32 ) ); + silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( opus_int32 ) ); + } +} + +/* Low-pass filter with variable cutoff frequency based on */ +/* piece-wise linear interpolation between elliptic filters */ +/* Start by setting psEncC->mode <> 0; */ +/* Deactivate by setting psEncC->mode = 0; */ +void silk_LP_variable_cutoff( + silk_LP_state *psLP, /* I/O LP filter state */ + opus_int16 *frame, /* I/O Low-pass filtered output signal */ + const opus_int frame_length /* I Frame length */ +) +{ + opus_int32 B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0; + opus_int ind = 0; + + silk_assert( psLP->transition_frame_no >= 0 && psLP->transition_frame_no <= TRANSITION_FRAMES ); + + /* Run filter if needed */ + if( psLP->mode != 0 ) { + /* Calculate index and interpolation factor for interpolation */ +#if( TRANSITION_INT_STEPS == 64 ) + fac_Q16 = silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 - 6 ); +#else + fac_Q16 = silk_DIV32_16( silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 ), TRANSITION_FRAMES ); +#endif + ind = silk_RSHIFT( fac_Q16, 16 ); + fac_Q16 -= silk_LSHIFT( ind, 16 ); + + silk_assert( ind >= 0 ); + silk_assert( ind < TRANSITION_INT_NUM ); + + /* Interpolate filter coefficients */ + silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 ); + + /* Update transition frame number for next frame */ + psLP->transition_frame_no = silk_LIMIT( psLP->transition_frame_no + psLP->mode, 0, TRANSITION_FRAMES ); + + /* ARMA low-pass filtering */ + silk_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 ); + silk_biquad_alt( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length, 1); + } +} diff --git a/TelegramClient.Opus/opus/silk/MacroCount.h b/TelegramClient.Opus/opus/silk/MacroCount.h new file mode 100755 index 0000000..834817d --- /dev/null +++ b/TelegramClient.Opus/opus/silk/MacroCount.h @@ -0,0 +1,718 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SIGPROCFIX_API_MACROCOUNT_H +#define SIGPROCFIX_API_MACROCOUNT_H +#include + +#ifdef silk_MACRO_COUNT +#define varDefine opus_int64 ops_count = 0; + +extern opus_int64 ops_count; + +static OPUS_INLINE opus_int64 silk_SaveCount(){ + return(ops_count); +} + +static OPUS_INLINE opus_int64 silk_SaveResetCount(){ + opus_int64 ret; + + ret = ops_count; + ops_count = 0; + return(ret); +} + +static OPUS_INLINE silk_PrintCount(){ + printf("ops_count = %d \n ", (opus_int32)ops_count); +} + +#undef silk_MUL +static OPUS_INLINE opus_int32 silk_MUL(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + ops_count += 4; + ret = a32 * b32; + return ret; +} + +#undef silk_MUL_uint +static OPUS_INLINE opus_uint32 silk_MUL_uint(opus_uint32 a32, opus_uint32 b32){ + opus_uint32 ret; + ops_count += 4; + ret = a32 * b32; + return ret; +} +#undef silk_MLA +static OPUS_INLINE opus_int32 silk_MLA(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ops_count += 4; + ret = a32 + b32 * c32; + return ret; +} + +#undef silk_MLA_uint +static OPUS_INLINE opus_int32 silk_MLA_uint(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32){ + opus_uint32 ret; + ops_count += 4; + ret = a32 + b32 * c32; + return ret; +} + +#undef silk_SMULWB +static OPUS_INLINE opus_int32 silk_SMULWB(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + ops_count += 5; + ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16); + return ret; +} +#undef silk_SMLAWB +static OPUS_INLINE opus_int32 silk_SMLAWB(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ops_count += 5; + ret = ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16))); + return ret; +} + +#undef silk_SMULWT +static OPUS_INLINE opus_int32 silk_SMULWT(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + ops_count += 4; + ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16); + return ret; +} +#undef silk_SMLAWT +static OPUS_INLINE opus_int32 silk_SMLAWT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ops_count += 4; + ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16)); + return ret; +} + +#undef silk_SMULBB +static OPUS_INLINE opus_int32 silk_SMULBB(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + ops_count += 1; + ret = (opus_int32)((opus_int16)a32) * (opus_int32)((opus_int16)b32); + return ret; +} +#undef silk_SMLABB +static OPUS_INLINE opus_int32 silk_SMLABB(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ops_count += 1; + ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32); + return ret; +} + +#undef silk_SMULBT +static OPUS_INLINE opus_int32 silk_SMULBT(opus_int32 a32, opus_int32 b32 ){ + opus_int32 ret; + ops_count += 4; + ret = ((opus_int32)((opus_int16)a32)) * (b32 >> 16); + return ret; +} + +#undef silk_SMLABT +static OPUS_INLINE opus_int32 silk_SMLABT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ops_count += 1; + ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16); + return ret; +} + +#undef silk_SMULTT +static OPUS_INLINE opus_int32 silk_SMULTT(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + ops_count += 1; + ret = (a32 >> 16) * (b32 >> 16); + return ret; +} + +#undef silk_SMLATT +static OPUS_INLINE opus_int32 silk_SMLATT(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + ops_count += 1; + ret = a32 + (b32 >> 16) * (c32 >> 16); + return ret; +} + + +/* multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode)*/ +#undef silk_MLA_ovflw +#define silk_MLA_ovflw silk_MLA + +#undef silk_SMLABB_ovflw +#define silk_SMLABB_ovflw silk_SMLABB + +#undef silk_SMLABT_ovflw +#define silk_SMLABT_ovflw silk_SMLABT + +#undef silk_SMLATT_ovflw +#define silk_SMLATT_ovflw silk_SMLATT + +#undef silk_SMLAWB_ovflw +#define silk_SMLAWB_ovflw silk_SMLAWB + +#undef silk_SMLAWT_ovflw +#define silk_SMLAWT_ovflw silk_SMLAWT + +#undef silk_SMULL +static OPUS_INLINE opus_int64 silk_SMULL(opus_int32 a32, opus_int32 b32){ + opus_int64 ret; + ops_count += 8; + ret = ((opus_int64)(a32) * /*(opus_int64)*/(b32)); + return ret; +} + +#undef silk_SMLAL +static OPUS_INLINE opus_int64 silk_SMLAL(opus_int64 a64, opus_int32 b32, opus_int32 c32){ + opus_int64 ret; + ops_count += 8; + ret = a64 + ((opus_int64)(b32) * /*(opus_int64)*/(c32)); + return ret; +} +#undef silk_SMLALBB +static OPUS_INLINE opus_int64 silk_SMLALBB(opus_int64 a64, opus_int16 b16, opus_int16 c16){ + opus_int64 ret; + ops_count += 4; + ret = a64 + ((opus_int64)(b16) * /*(opus_int64)*/(c16)); + return ret; +} + +#undef SigProcFIX_CLZ16 +static OPUS_INLINE opus_int32 SigProcFIX_CLZ16(opus_int16 in16) +{ + opus_int32 out32 = 0; + ops_count += 10; + if( in16 == 0 ) { + return 16; + } + /* test nibbles */ + if( in16 & 0xFF00 ) { + if( in16 & 0xF000 ) { + in16 >>= 12; + } else { + out32 += 4; + in16 >>= 8; + } + } else { + if( in16 & 0xFFF0 ) { + out32 += 8; + in16 >>= 4; + } else { + out32 += 12; + } + } + /* test bits and return */ + if( in16 & 0xC ) { + if( in16 & 0x8 ) + return out32 + 0; + else + return out32 + 1; + } else { + if( in16 & 0xE ) + return out32 + 2; + else + return out32 + 3; + } +} + +#undef SigProcFIX_CLZ32 +static OPUS_INLINE opus_int32 SigProcFIX_CLZ32(opus_int32 in32) +{ + /* test highest 16 bits and convert to opus_int16 */ + ops_count += 2; + if( in32 & 0xFFFF0000 ) { + return SigProcFIX_CLZ16((opus_int16)(in32 >> 16)); + } else { + return SigProcFIX_CLZ16((opus_int16)in32) + 16; + } +} + +#undef silk_DIV32 +static OPUS_INLINE opus_int32 silk_DIV32(opus_int32 a32, opus_int32 b32){ + ops_count += 64; + return a32 / b32; +} + +#undef silk_DIV32_16 +static OPUS_INLINE opus_int32 silk_DIV32_16(opus_int32 a32, opus_int32 b32){ + ops_count += 32; + return a32 / b32; +} + +#undef silk_SAT8 +static OPUS_INLINE opus_int8 silk_SAT8(opus_int64 a){ + opus_int8 tmp; + ops_count += 1; + tmp = (opus_int8)((a) > silk_int8_MAX ? silk_int8_MAX : \ + ((a) < silk_int8_MIN ? silk_int8_MIN : (a))); + return(tmp); +} + +#undef silk_SAT16 +static OPUS_INLINE opus_int16 silk_SAT16(opus_int64 a){ + opus_int16 tmp; + ops_count += 1; + tmp = (opus_int16)((a) > silk_int16_MAX ? silk_int16_MAX : \ + ((a) < silk_int16_MIN ? silk_int16_MIN : (a))); + return(tmp); +} +#undef silk_SAT32 +static OPUS_INLINE opus_int32 silk_SAT32(opus_int64 a){ + opus_int32 tmp; + ops_count += 1; + tmp = (opus_int32)((a) > silk_int32_MAX ? silk_int32_MAX : \ + ((a) < silk_int32_MIN ? silk_int32_MIN : (a))); + return(tmp); +} +#undef silk_POS_SAT32 +static OPUS_INLINE opus_int32 silk_POS_SAT32(opus_int64 a){ + opus_int32 tmp; + ops_count += 1; + tmp = (opus_int32)((a) > silk_int32_MAX ? silk_int32_MAX : (a)); + return(tmp); +} + +#undef silk_ADD_POS_SAT8 +static OPUS_INLINE opus_int8 silk_ADD_POS_SAT8(opus_int64 a, opus_int64 b){ + opus_int8 tmp; + ops_count += 1; + tmp = (opus_int8)((((a)+(b)) & 0x80) ? silk_int8_MAX : ((a)+(b))); + return(tmp); +} +#undef silk_ADD_POS_SAT16 +static OPUS_INLINE opus_int16 silk_ADD_POS_SAT16(opus_int64 a, opus_int64 b){ + opus_int16 tmp; + ops_count += 1; + tmp = (opus_int16)((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b))); + return(tmp); +} + +#undef silk_ADD_POS_SAT32 +static OPUS_INLINE opus_int32 silk_ADD_POS_SAT32(opus_int64 a, opus_int64 b){ + opus_int32 tmp; + ops_count += 1; + tmp = (opus_int32)((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b))); + return(tmp); +} + +#undef silk_ADD_POS_SAT64 +static OPUS_INLINE opus_int64 silk_ADD_POS_SAT64(opus_int64 a, opus_int64 b){ + opus_int64 tmp; + ops_count += 1; + tmp = ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b))); + return(tmp); +} + +#undef silk_LSHIFT8 +static OPUS_INLINE opus_int8 silk_LSHIFT8(opus_int8 a, opus_int32 shift){ + opus_int8 ret; + ops_count += 1; + ret = a << shift; + return ret; +} +#undef silk_LSHIFT16 +static OPUS_INLINE opus_int16 silk_LSHIFT16(opus_int16 a, opus_int32 shift){ + opus_int16 ret; + ops_count += 1; + ret = a << shift; + return ret; +} +#undef silk_LSHIFT32 +static OPUS_INLINE opus_int32 silk_LSHIFT32(opus_int32 a, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a << shift; + return ret; +} +#undef silk_LSHIFT64 +static OPUS_INLINE opus_int64 silk_LSHIFT64(opus_int64 a, opus_int shift){ + ops_count += 1; + return a << shift; +} + +#undef silk_LSHIFT_ovflw +static OPUS_INLINE opus_int32 silk_LSHIFT_ovflw(opus_int32 a, opus_int32 shift){ + ops_count += 1; + return a << shift; +} + +#undef silk_LSHIFT_uint +static OPUS_INLINE opus_uint32 silk_LSHIFT_uint(opus_uint32 a, opus_int32 shift){ + opus_uint32 ret; + ops_count += 1; + ret = a << shift; + return ret; +} + +#undef silk_RSHIFT8 +static OPUS_INLINE opus_int8 silk_RSHIFT8(opus_int8 a, opus_int32 shift){ + ops_count += 1; + return a >> shift; +} +#undef silk_RSHIFT16 +static OPUS_INLINE opus_int16 silk_RSHIFT16(opus_int16 a, opus_int32 shift){ + ops_count += 1; + return a >> shift; +} +#undef silk_RSHIFT32 +static OPUS_INLINE opus_int32 silk_RSHIFT32(opus_int32 a, opus_int32 shift){ + ops_count += 1; + return a >> shift; +} +#undef silk_RSHIFT64 +static OPUS_INLINE opus_int64 silk_RSHIFT64(opus_int64 a, opus_int64 shift){ + ops_count += 1; + return a >> shift; +} + +#undef silk_RSHIFT_uint +static OPUS_INLINE opus_uint32 silk_RSHIFT_uint(opus_uint32 a, opus_int32 shift){ + ops_count += 1; + return a >> shift; +} + +#undef silk_ADD_LSHIFT +static OPUS_INLINE opus_int32 silk_ADD_LSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a + (b << shift); + return ret; /* shift >= 0*/ +} +#undef silk_ADD_LSHIFT32 +static OPUS_INLINE opus_int32 silk_ADD_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a + (b << shift); + return ret; /* shift >= 0*/ +} +#undef silk_ADD_LSHIFT_uint +static OPUS_INLINE opus_uint32 silk_ADD_LSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){ + opus_uint32 ret; + ops_count += 1; + ret = a + (b << shift); + return ret; /* shift >= 0*/ +} +#undef silk_ADD_RSHIFT +static OPUS_INLINE opus_int32 silk_ADD_RSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a + (b >> shift); + return ret; /* shift > 0*/ +} +#undef silk_ADD_RSHIFT32 +static OPUS_INLINE opus_int32 silk_ADD_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a + (b >> shift); + return ret; /* shift > 0*/ +} +#undef silk_ADD_RSHIFT_uint +static OPUS_INLINE opus_uint32 silk_ADD_RSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){ + opus_uint32 ret; + ops_count += 1; + ret = a + (b >> shift); + return ret; /* shift > 0*/ +} +#undef silk_SUB_LSHIFT32 +static OPUS_INLINE opus_int32 silk_SUB_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a - (b << shift); + return ret; /* shift >= 0*/ +} +#undef silk_SUB_RSHIFT32 +static OPUS_INLINE opus_int32 silk_SUB_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){ + opus_int32 ret; + ops_count += 1; + ret = a - (b >> shift); + return ret; /* shift > 0*/ +} + +#undef silk_RSHIFT_ROUND +static OPUS_INLINE opus_int32 silk_RSHIFT_ROUND(opus_int32 a, opus_int32 shift){ + opus_int32 ret; + ops_count += 3; + ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1; + return ret; +} + +#undef silk_RSHIFT_ROUND64 +static OPUS_INLINE opus_int64 silk_RSHIFT_ROUND64(opus_int64 a, opus_int32 shift){ + opus_int64 ret; + ops_count += 6; + ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1; + return ret; +} + +#undef silk_abs_int64 +static OPUS_INLINE opus_int64 silk_abs_int64(opus_int64 a){ + ops_count += 1; + return (((a) > 0) ? (a) : -(a)); /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN*/ +} + +#undef silk_abs_int32 +static OPUS_INLINE opus_int32 silk_abs_int32(opus_int32 a){ + ops_count += 1; + return silk_abs(a); +} + + +#undef silk_min +static silk_min(a, b){ + ops_count += 1; + return (((a) < (b)) ? (a) : (b)); +} +#undef silk_max +static silk_max(a, b){ + ops_count += 1; + return (((a) > (b)) ? (a) : (b)); +} +#undef silk_sign +static silk_sign(a){ + ops_count += 1; + return ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 )); +} + +#undef silk_ADD16 +static OPUS_INLINE opus_int16 silk_ADD16(opus_int16 a, opus_int16 b){ + opus_int16 ret; + ops_count += 1; + ret = a + b; + return ret; +} + +#undef silk_ADD32 +static OPUS_INLINE opus_int32 silk_ADD32(opus_int32 a, opus_int32 b){ + opus_int32 ret; + ops_count += 1; + ret = a + b; + return ret; +} + +#undef silk_ADD64 +static OPUS_INLINE opus_int64 silk_ADD64(opus_int64 a, opus_int64 b){ + opus_int64 ret; + ops_count += 2; + ret = a + b; + return ret; +} + +#undef silk_SUB16 +static OPUS_INLINE opus_int16 silk_SUB16(opus_int16 a, opus_int16 b){ + opus_int16 ret; + ops_count += 1; + ret = a - b; + return ret; +} + +#undef silk_SUB32 +static OPUS_INLINE opus_int32 silk_SUB32(opus_int32 a, opus_int32 b){ + opus_int32 ret; + ops_count += 1; + ret = a - b; + return ret; +} + +#undef silk_SUB64 +static OPUS_INLINE opus_int64 silk_SUB64(opus_int64 a, opus_int64 b){ + opus_int64 ret; + ops_count += 2; + ret = a - b; + return ret; +} + +#undef silk_ADD_SAT16 +static OPUS_INLINE opus_int16 silk_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) { + opus_int16 res; + /* Nb will be counted in AKP_add32 and silk_SAT16*/ + res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) ); + return res; +} + +#undef silk_ADD_SAT32 +static OPUS_INLINE opus_int32 silk_ADD_SAT32(opus_int32 a32, opus_int32 b32){ + opus_int32 res; + ops_count += 1; + res = ((((a32) + (b32)) & 0x80000000) == 0 ? \ + ((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) : \ + ((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) ); + return res; +} + +#undef silk_ADD_SAT64 +static OPUS_INLINE opus_int64 silk_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) { + opus_int64 res; + ops_count += 1; + res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \ + ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) : \ + ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) ); + return res; +} + +#undef silk_SUB_SAT16 +static OPUS_INLINE opus_int16 silk_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) { + opus_int16 res; + silk_assert(0); + /* Nb will be counted in sub-macros*/ + res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) ); + return res; +} + +#undef silk_SUB_SAT32 +static OPUS_INLINE opus_int32 silk_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) { + opus_int32 res; + ops_count += 1; + res = ((((a32)-(b32)) & 0x80000000) == 0 ? \ + (( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \ + ((((a32)^0x80000000) & (b32) & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) ); + return res; +} + +#undef silk_SUB_SAT64 +static OPUS_INLINE opus_int64 silk_SUB_SAT64( opus_int64 a64, opus_int64 b64 ) { + opus_int64 res; + ops_count += 1; + res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \ + (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) : \ + ((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) ); + + return res; +} + +#undef silk_SMULWW +static OPUS_INLINE opus_int32 silk_SMULWW(opus_int32 a32, opus_int32 b32){ + opus_int32 ret; + /* Nb will be counted in sub-macros*/ + ret = silk_MLA(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16)); + return ret; +} + +#undef silk_SMLAWW +static OPUS_INLINE opus_int32 silk_SMLAWW(opus_int32 a32, opus_int32 b32, opus_int32 c32){ + opus_int32 ret; + /* Nb will be counted in sub-macros*/ + ret = silk_MLA(silk_SMLAWB((a32), (b32), (c32)), (b32), silk_RSHIFT_ROUND((c32), 16)); + return ret; +} + +#undef silk_min_int +static OPUS_INLINE opus_int silk_min_int(opus_int a, opus_int b) +{ + ops_count += 1; + return (((a) < (b)) ? (a) : (b)); +} + +#undef silk_min_16 +static OPUS_INLINE opus_int16 silk_min_16(opus_int16 a, opus_int16 b) +{ + ops_count += 1; + return (((a) < (b)) ? (a) : (b)); +} +#undef silk_min_32 +static OPUS_INLINE opus_int32 silk_min_32(opus_int32 a, opus_int32 b) +{ + ops_count += 1; + return (((a) < (b)) ? (a) : (b)); +} +#undef silk_min_64 +static OPUS_INLINE opus_int64 silk_min_64(opus_int64 a, opus_int64 b) +{ + ops_count += 1; + return (((a) < (b)) ? (a) : (b)); +} + +/* silk_min() versions with typecast in the function call */ +#undef silk_max_int +static OPUS_INLINE opus_int silk_max_int(opus_int a, opus_int b) +{ + ops_count += 1; + return (((a) > (b)) ? (a) : (b)); +} +#undef silk_max_16 +static OPUS_INLINE opus_int16 silk_max_16(opus_int16 a, opus_int16 b) +{ + ops_count += 1; + return (((a) > (b)) ? (a) : (b)); +} +#undef silk_max_32 +static OPUS_INLINE opus_int32 silk_max_32(opus_int32 a, opus_int32 b) +{ + ops_count += 1; + return (((a) > (b)) ? (a) : (b)); +} + +#undef silk_max_64 +static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b) +{ + ops_count += 1; + return (((a) > (b)) ? (a) : (b)); +} + + +#undef silk_LIMIT_int +static OPUS_INLINE opus_int silk_LIMIT_int(opus_int a, opus_int limit1, opus_int limit2) +{ + opus_int ret; + ops_count += 6; + + ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ + : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))); + + return(ret); +} + +#undef silk_LIMIT_16 +static OPUS_INLINE opus_int16 silk_LIMIT_16(opus_int16 a, opus_int16 limit1, opus_int16 limit2) +{ + opus_int16 ret; + ops_count += 6; + + ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ + : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))); + +return(ret); +} + + +#undef silk_LIMIT_32 +static OPUS_INLINE opus_int silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2) +{ + opus_int32 ret; + ops_count += 6; + + ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ + : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))); + return(ret); +} + +#else +#define varDefine +#define silk_SaveCount() + +#endif +#endif + diff --git a/TelegramClient.Opus/opus/silk/MacroDebug.h b/TelegramClient.Opus/opus/silk/MacroDebug.h new file mode 100755 index 0000000..35aedc5 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/MacroDebug.h @@ -0,0 +1,952 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Copyright (C) 2012 Xiph.Org Foundation +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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef MACRO_DEBUG_H +#define MACRO_DEBUG_H + +/* Redefine macro functions with extensive assertion in DEBUG mode. + As functions can't be undefined, this file can't work with SigProcFIX_MacroCount.h */ + +#if ( defined (FIXED_DEBUG) || ( 0 && defined (_DEBUG) ) ) && !defined (silk_MACRO_COUNT) + +#undef silk_ADD16 +#define silk_ADD16(a,b) silk_ADD16_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int16 silk_ADD16_(opus_int16 a, opus_int16 b, char *file, int line){ + opus_int16 ret; + + ret = a + b; + if ( ret != silk_ADD_SAT16( a, b ) ) + { + fprintf (stderr, "silk_ADD16(%d, %d) in %s: line %d\n", a, b, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_ADD32 +#define silk_ADD32(a,b) silk_ADD32_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_ADD32_(opus_int32 a, opus_int32 b, char *file, int line){ + opus_int32 ret; + + ret = a + b; + if ( ret != silk_ADD_SAT32( a, b ) ) + { + fprintf (stderr, "silk_ADD32(%d, %d) in %s: line %d\n", a, b, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_ADD64 +#define silk_ADD64(a,b) silk_ADD64_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int64 silk_ADD64_(opus_int64 a, opus_int64 b, char *file, int line){ + opus_int64 ret; + + ret = a + b; + if ( ret != silk_ADD_SAT64( a, b ) ) + { + fprintf (stderr, "silk_ADD64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)b, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_SUB16 +#define silk_SUB16(a,b) silk_SUB16_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int16 silk_SUB16_(opus_int16 a, opus_int16 b, char *file, int line){ + opus_int16 ret; + + ret = a - b; + if ( ret != silk_SUB_SAT16( a, b ) ) + { + fprintf (stderr, "silk_SUB16(%d, %d) in %s: line %d\n", a, b, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_SUB32 +#define silk_SUB32(a,b) silk_SUB32_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SUB32_(opus_int32 a, opus_int32 b, char *file, int line){ + opus_int32 ret; + + ret = a - b; + if ( ret != silk_SUB_SAT32( a, b ) ) + { + fprintf (stderr, "silk_SUB32(%d, %d) in %s: line %d\n", a, b, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_SUB64 +#define silk_SUB64(a,b) silk_SUB64_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int64 silk_SUB64_(opus_int64 a, opus_int64 b, char *file, int line){ + opus_int64 ret; + + ret = a - b; + if ( ret != silk_SUB_SAT64( a, b ) ) + { + fprintf (stderr, "silk_SUB64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)b, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_ADD_SAT16 +#define silk_ADD_SAT16(a,b) silk_ADD_SAT16_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int16 silk_ADD_SAT16_( opus_int16 a16, opus_int16 b16, char *file, int line) { + opus_int16 res; + res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) ); + if ( res != silk_SAT16( (opus_int32)a16 + (opus_int32)b16 ) ) + { + fprintf (stderr, "silk_ADD_SAT16(%d, %d) in %s: line %d\n", a16, b16, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return res; +} + +#undef silk_ADD_SAT32 +#define silk_ADD_SAT32(a,b) silk_ADD_SAT32_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_ADD_SAT32_(opus_int32 a32, opus_int32 b32, char *file, int line){ + opus_int32 res; + res = ((((opus_uint32)(a32) + (opus_uint32)(b32)) & 0x80000000) == 0 ? \ + ((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) : \ + ((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) ); + if ( res != silk_SAT32( (opus_int64)a32 + (opus_int64)b32 ) ) + { + fprintf (stderr, "silk_ADD_SAT32(%d, %d) in %s: line %d\n", a32, b32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return res; +} + +#undef silk_ADD_SAT64 +#define silk_ADD_SAT64(a,b) silk_ADD_SAT64_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int64 silk_ADD_SAT64_( opus_int64 a64, opus_int64 b64, char *file, int line) { + opus_int64 res; + int fail = 0; + res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \ + ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) : \ + ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) ); + if( res != a64 + b64 ) { + /* Check that we saturated to the correct extreme value */ + if ( !(( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) || + ( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) ) ) + { + fail = 1; + } + } else { + /* Saturation not necessary */ + fail = res != a64 + b64; + } + if ( fail ) + { + fprintf (stderr, "silk_ADD_SAT64(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return res; +} + +#undef silk_SUB_SAT16 +#define silk_SUB_SAT16(a,b) silk_SUB_SAT16_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int16 silk_SUB_SAT16_( opus_int16 a16, opus_int16 b16, char *file, int line ) { + opus_int16 res; + res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) ); + if ( res != silk_SAT16( (opus_int32)a16 - (opus_int32)b16 ) ) + { + fprintf (stderr, "silk_SUB_SAT16(%d, %d) in %s: line %d\n", a16, b16, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return res; +} + +#undef silk_SUB_SAT32 +#define silk_SUB_SAT32(a,b) silk_SUB_SAT32_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SUB_SAT32_( opus_int32 a32, opus_int32 b32, char *file, int line ) { + opus_int32 res; + res = ((((opus_uint32)(a32)-(opus_uint32)(b32)) & 0x80000000) == 0 ? \ + (( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \ + ((((a32)^0x80000000) & (b32) & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) ); + if ( res != silk_SAT32( (opus_int64)a32 - (opus_int64)b32 ) ) + { + fprintf (stderr, "silk_SUB_SAT32(%d, %d) in %s: line %d\n", a32, b32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return res; +} + +#undef silk_SUB_SAT64 +#define silk_SUB_SAT64(a,b) silk_SUB_SAT64_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int64 silk_SUB_SAT64_( opus_int64 a64, opus_int64 b64, char *file, int line ) { + opus_int64 res; + int fail = 0; + res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \ + (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) : \ + ((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) ); + if( res != a64 - b64 ) { + /* Check that we saturated to the correct extreme value */ + if( !(( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) || + ( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) )) + { + fail = 1; + } + } else { + /* Saturation not necessary */ + fail = res != a64 - b64; + } + if ( fail ) + { + fprintf (stderr, "silk_SUB_SAT64(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return res; +} + +#undef silk_MUL +#define silk_MUL(a,b) silk_MUL_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_MUL_(opus_int32 a32, opus_int32 b32, char *file, int line){ + opus_int32 ret; + opus_int64 ret64; + ret = a32 * b32; + ret64 = (opus_int64)a32 * (opus_int64)b32; + if ( (opus_int64)ret != ret64 ) + { + fprintf (stderr, "silk_MUL(%d, %d) in %s: line %d\n", a32, b32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_MUL_uint +#define silk_MUL_uint(a,b) silk_MUL_uint_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_uint32 silk_MUL_uint_(opus_uint32 a32, opus_uint32 b32, char *file, int line){ + opus_uint32 ret; + ret = a32 * b32; + if ( (opus_uint64)ret != (opus_uint64)a32 * (opus_uint64)b32 ) + { + fprintf (stderr, "silk_MUL_uint(%u, %u) in %s: line %d\n", a32, b32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_MLA +#define silk_MLA(a,b,c) silk_MLA_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_MLA_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){ + opus_int32 ret; + ret = a32 + b32 * c32; + if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32 ) + { + fprintf (stderr, "silk_MLA(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_MLA_uint +#define silk_MLA_uint(a,b,c) silk_MLA_uint_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_MLA_uint_(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32, char *file, int line){ + opus_uint32 ret; + ret = a32 + b32 * c32; + if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32 ) + { + fprintf (stderr, "silk_MLA_uint(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_SMULWB +#define silk_SMULWB(a,b) silk_SMULWB_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SMULWB_(opus_int32 a32, opus_int32 b32, char *file, int line){ + opus_int32 ret; + ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16); + if ( (opus_int64)ret != ((opus_int64)a32 * (opus_int16)b32) >> 16 ) + { + fprintf (stderr, "silk_SMULWB(%d, %d) in %s: line %d\n", a32, b32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_SMLAWB +#define silk_SMLAWB(a,b,c) silk_SMLAWB_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SMLAWB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){ + opus_int32 ret; + ret = silk_ADD32( a32, silk_SMULWB( b32, c32 ) ); + if ( silk_ADD32( a32, silk_SMULWB( b32, c32 ) ) != silk_ADD_SAT32( a32, silk_SMULWB( b32, c32 ) ) ) + { + fprintf (stderr, "silk_SMLAWB(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_SMULWT +#define silk_SMULWT(a,b) silk_SMULWT_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SMULWT_(opus_int32 a32, opus_int32 b32, char *file, int line){ + opus_int32 ret; + ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16); + if ( (opus_int64)ret != ((opus_int64)a32 * (b32 >> 16)) >> 16 ) + { + fprintf (stderr, "silk_SMULWT(%d, %d) in %s: line %d\n", a32, b32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_SMLAWT +#define silk_SMLAWT(a,b,c) silk_SMLAWT_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SMLAWT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){ + opus_int32 ret; + ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16)); + if ( (opus_int64)ret != (opus_int64)a32 + (((opus_int64)b32 * (c32 >> 16)) >> 16) ) + { + fprintf (stderr, "silk_SMLAWT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_SMULL +#define silk_SMULL(a,b) silk_SMULL_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int64 silk_SMULL_(opus_int64 a64, opus_int64 b64, char *file, int line){ + opus_int64 ret64; + int fail = 0; + ret64 = a64 * b64; + if( b64 != 0 ) { + fail = a64 != (ret64 / b64); + } else if( a64 != 0 ) { + fail = b64 != (ret64 / a64); + } + if ( fail ) + { + fprintf (stderr, "silk_SMULL(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret64; +} + +/* no checking needed for silk_SMULBB */ +#undef silk_SMLABB +#define silk_SMLABB(a,b,c) silk_SMLABB_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SMLABB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){ + opus_int32 ret; + ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32); + if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int16)c32 ) + { + fprintf (stderr, "silk_SMLABB(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +/* no checking needed for silk_SMULBT */ +#undef silk_SMLABT +#define silk_SMLABT(a,b,c) silk_SMLABT_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SMLABT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){ + opus_int32 ret; + ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16); + if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (c32 >> 16) ) + { + fprintf (stderr, "silk_SMLABT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +/* no checking needed for silk_SMULTT */ +#undef silk_SMLATT +#define silk_SMLATT(a,b,c) silk_SMLATT_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SMLATT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){ + opus_int32 ret; + ret = a32 + (b32 >> 16) * (c32 >> 16); + if ( (opus_int64)ret != (opus_int64)a32 + (b32 >> 16) * (c32 >> 16) ) + { + fprintf (stderr, "silk_SMLATT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_SMULWW +#define silk_SMULWW(a,b) silk_SMULWW_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SMULWW_(opus_int32 a32, opus_int32 b32, char *file, int line){ + opus_int32 ret, tmp1, tmp2; + opus_int64 ret64; + int fail = 0; + + ret = silk_SMULWB( a32, b32 ); + tmp1 = silk_RSHIFT_ROUND( b32, 16 ); + tmp2 = silk_MUL( a32, tmp1 ); + + fail |= (opus_int64)tmp2 != (opus_int64) a32 * (opus_int64) tmp1; + + tmp1 = ret; + ret = silk_ADD32( tmp1, tmp2 ); + fail |= silk_ADD32( tmp1, tmp2 ) != silk_ADD_SAT32( tmp1, tmp2 ); + + ret64 = silk_RSHIFT64( silk_SMULL( a32, b32 ), 16 ); + fail |= (opus_int64)ret != ret64; + + if ( fail ) + { + fprintf (stderr, "silk_SMULWT(%d, %d) in %s: line %d\n", a32, b32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + + return ret; +} + +#undef silk_SMLAWW +#define silk_SMLAWW(a,b,c) silk_SMLAWW_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SMLAWW_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){ + opus_int32 ret, tmp; + + tmp = silk_SMULWW( b32, c32 ); + ret = silk_ADD32( a32, tmp ); + if ( ret != silk_ADD_SAT32( a32, tmp ) ) + { + fprintf (stderr, "silk_SMLAWW(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +/* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) */ +#undef silk_MLA_ovflw +#define silk_MLA_ovflw(a32, b32, c32) ((a32) + ((b32) * (c32))) +#undef silk_SMLABB_ovflw +#define silk_SMLABB_ovflw(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32))) + +/* no checking needed for silk_SMULL + no checking needed for silk_SMLAL + no checking needed for silk_SMLALBB + no checking needed for SigProcFIX_CLZ16 + no checking needed for SigProcFIX_CLZ32*/ + +#undef silk_DIV32 +#define silk_DIV32(a,b) silk_DIV32_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_DIV32_(opus_int32 a32, opus_int32 b32, char *file, int line){ + if ( b32 == 0 ) + { + fprintf (stderr, "silk_DIV32(%d, %d) in %s: line %d\n", a32, b32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return a32 / b32; +} + +#undef silk_DIV32_16 +#define silk_DIV32_16(a,b) silk_DIV32_16_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_DIV32_16_(opus_int32 a32, opus_int32 b32, char *file, int line){ + int fail = 0; + fail |= b32 == 0; + fail |= b32 > silk_int16_MAX; + fail |= b32 < silk_int16_MIN; + if ( fail ) + { + fprintf (stderr, "silk_DIV32_16(%d, %d) in %s: line %d\n", a32, b32, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return a32 / b32; +} + +/* no checking needed for silk_SAT8 + no checking needed for silk_SAT16 + no checking needed for silk_SAT32 + no checking needed for silk_POS_SAT32 + no checking needed for silk_ADD_POS_SAT8 + no checking needed for silk_ADD_POS_SAT16 + no checking needed for silk_ADD_POS_SAT32 + no checking needed for silk_ADD_POS_SAT64 */ + +#undef silk_LSHIFT8 +#define silk_LSHIFT8(a,b) silk_LSHIFT8_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int8 silk_LSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){ + opus_int8 ret; + int fail = 0; + ret = a << shift; + fail |= shift < 0; + fail |= shift >= 8; + fail |= (opus_int64)ret != ((opus_int64)a) << shift; + if ( fail ) + { + fprintf (stderr, "silk_LSHIFT8(%d, %d) in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_LSHIFT16 +#define silk_LSHIFT16(a,b) silk_LSHIFT16_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int16 silk_LSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){ + opus_int16 ret; + int fail = 0; + ret = a << shift; + fail |= shift < 0; + fail |= shift >= 16; + fail |= (opus_int64)ret != ((opus_int64)a) << shift; + if ( fail ) + { + fprintf (stderr, "silk_LSHIFT16(%d, %d) in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_LSHIFT32 +#define silk_LSHIFT32(a,b) silk_LSHIFT32_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_LSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){ + opus_int32 ret; + int fail = 0; + ret = a << shift; + fail |= shift < 0; + fail |= shift >= 32; + fail |= (opus_int64)ret != ((opus_int64)a) << shift; + if ( fail ) + { + fprintf (stderr, "silk_LSHIFT32(%d, %d) in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_LSHIFT64 +#define silk_LSHIFT64(a,b) silk_LSHIFT64_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int64 silk_LSHIFT64_(opus_int64 a, opus_int shift, char *file, int line){ + opus_int64 ret; + int fail = 0; + ret = a << shift; + fail |= shift < 0; + fail |= shift >= 64; + fail |= (ret>>shift) != ((opus_int64)a); + if ( fail ) + { + fprintf (stderr, "silk_LSHIFT64(%lld, %d) in %s: line %d\n", (long long)a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_LSHIFT_ovflw +#define silk_LSHIFT_ovflw(a,b) silk_LSHIFT_ovflw_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_LSHIFT_ovflw_(opus_int32 a, opus_int32 shift, char *file, int line){ + if ( (shift < 0) || (shift >= 32) ) /* no check for overflow */ + { + fprintf (stderr, "silk_LSHIFT_ovflw(%d, %d) in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return a << shift; +} + +#undef silk_LSHIFT_uint +#define silk_LSHIFT_uint(a,b) silk_LSHIFT_uint_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_uint32 silk_LSHIFT_uint_(opus_uint32 a, opus_int32 shift, char *file, int line){ + opus_uint32 ret; + ret = a << shift; + if ( (shift < 0) || ((opus_int64)ret != ((opus_int64)a) << shift)) + { + fprintf (stderr, "silk_LSHIFT_uint(%u, %d) in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_RSHIFT8 +#define silk_RSHITF8(a,b) silk_RSHIFT8_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int8 silk_RSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){ + if ( (shift < 0) || (shift>=8) ) + { + fprintf (stderr, "silk_RSHITF8(%d, %d) in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return a >> shift; +} + +#undef silk_RSHIFT16 +#define silk_RSHITF16(a,b) silk_RSHIFT16_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int16 silk_RSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){ + if ( (shift < 0) || (shift>=16) ) + { + fprintf (stderr, "silk_RSHITF16(%d, %d) in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return a >> shift; +} + +#undef silk_RSHIFT32 +#define silk_RSHIFT32(a,b) silk_RSHIFT32_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_RSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){ + if ( (shift < 0) || (shift>=32) ) + { + fprintf (stderr, "silk_RSHITF32(%d, %d) in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return a >> shift; +} + +#undef silk_RSHIFT64 +#define silk_RSHIFT64(a,b) silk_RSHIFT64_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int64 silk_RSHIFT64_(opus_int64 a, opus_int64 shift, char *file, int line){ + if ( (shift < 0) || (shift>=64) ) + { + fprintf (stderr, "silk_RSHITF64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return a >> shift; +} + +#undef silk_RSHIFT_uint +#define silk_RSHIFT_uint(a,b) silk_RSHIFT_uint_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_uint32 silk_RSHIFT_uint_(opus_uint32 a, opus_int32 shift, char *file, int line){ + if ( (shift < 0) || (shift>32) ) + { + fprintf (stderr, "silk_RSHIFT_uint(%u, %d) in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return a >> shift; +} + +#undef silk_ADD_LSHIFT +#define silk_ADD_LSHIFT(a,b,c) silk_ADD_LSHIFT_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE int silk_ADD_LSHIFT_(int a, int b, int shift, char *file, int line){ + opus_int16 ret; + ret = a + (b << shift); + if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) ) + { + fprintf (stderr, "silk_ADD_LSHIFT(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; /* shift >= 0 */ +} + +#undef silk_ADD_LSHIFT32 +#define silk_ADD_LSHIFT32(a,b,c) silk_ADD_LSHIFT32_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_ADD_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){ + opus_int32 ret; + ret = a + (b << shift); + if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) ) + { + fprintf (stderr, "silk_ADD_LSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; /* shift >= 0 */ +} + +#undef silk_ADD_LSHIFT_uint +#define silk_ADD_LSHIFT_uint(a,b,c) silk_ADD_LSHIFT_uint_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_uint32 silk_ADD_LSHIFT_uint_(opus_uint32 a, opus_uint32 b, opus_int32 shift, char *file, int line){ + opus_uint32 ret; + ret = a + (b << shift); + if ( (shift < 0) || (shift>32) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) ) + { + fprintf (stderr, "silk_ADD_LSHIFT_uint(%u, %u, %d) in %s: line %d\n", a, b, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; /* shift >= 0 */ +} + +#undef silk_ADD_RSHIFT +#define silk_ADD_RSHIFT(a,b,c) silk_ADD_RSHIFT_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE int silk_ADD_RSHIFT_(int a, int b, int shift, char *file, int line){ + opus_int16 ret; + ret = a + (b >> shift); + if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) ) + { + fprintf (stderr, "silk_ADD_RSHIFT(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; /* shift > 0 */ +} + +#undef silk_ADD_RSHIFT32 +#define silk_ADD_RSHIFT32(a,b,c) silk_ADD_RSHIFT32_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_ADD_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){ + opus_int32 ret; + ret = a + (b >> shift); + if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) ) + { + fprintf (stderr, "silk_ADD_RSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; /* shift > 0 */ +} + +#undef silk_ADD_RSHIFT_uint +#define silk_ADD_RSHIFT_uint(a,b,c) silk_ADD_RSHIFT_uint_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_uint32 silk_ADD_RSHIFT_uint_(opus_uint32 a, opus_uint32 b, opus_int32 shift, char *file, int line){ + opus_uint32 ret; + ret = a + (b >> shift); + if ( (shift < 0) || (shift>32) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) ) + { + fprintf (stderr, "silk_ADD_RSHIFT_uint(%u, %u, %d) in %s: line %d\n", a, b, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; /* shift > 0 */ +} + +#undef silk_SUB_LSHIFT32 +#define silk_SUB_LSHIFT32(a,b,c) silk_SUB_LSHIFT32_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SUB_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){ + opus_int32 ret; + ret = a - (b << shift); + if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (((opus_int64)b) << shift)) ) + { + fprintf (stderr, "silk_SUB_LSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; /* shift >= 0 */ +} + +#undef silk_SUB_RSHIFT32 +#define silk_SUB_RSHIFT32(a,b,c) silk_SUB_RSHIFT32_((a), (b), (c), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_SUB_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){ + opus_int32 ret; + ret = a - (b >> shift); + if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (((opus_int64)b) >> shift)) ) + { + fprintf (stderr, "silk_SUB_RSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; /* shift > 0 */ +} + +#undef silk_RSHIFT_ROUND +#define silk_RSHIFT_ROUND(a,b) silk_RSHIFT_ROUND_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_RSHIFT_ROUND_(opus_int32 a, opus_int32 shift, char *file, int line){ + opus_int32 ret; + ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1; + /* the marco definition can't handle a shift of zero */ + if ( (shift <= 0) || (shift>31) || ((opus_int64)ret != ((opus_int64)a + ((opus_int64)1 << (shift - 1))) >> shift) ) + { + fprintf (stderr, "silk_RSHIFT_ROUND(%d, %d) in %s: line %d\n", a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return ret; +} + +#undef silk_RSHIFT_ROUND64 +#define silk_RSHIFT_ROUND64(a,b) silk_RSHIFT_ROUND64_((a), (b), __FILE__, __LINE__) +static OPUS_INLINE opus_int64 silk_RSHIFT_ROUND64_(opus_int64 a, opus_int32 shift, char *file, int line){ + opus_int64 ret; + /* the marco definition can't handle a shift of zero */ + if ( (shift <= 0) || (shift>=64) ) + { + fprintf (stderr, "silk_RSHIFT_ROUND64(%lld, %d) in %s: line %d\n", (long long)a, shift, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1; + return ret; +} + +/* silk_abs is used on floats also, so doesn't work... */ +/*#undef silk_abs +static OPUS_INLINE opus_int32 silk_abs(opus_int32 a){ + silk_assert(a != 0x80000000); + return (((a) > 0) ? (a) : -(a)); // Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN +}*/ + +#undef silk_abs_int64 +#define silk_abs_int64(a) silk_abs_int64_((a), __FILE__, __LINE__) +static OPUS_INLINE opus_int64 silk_abs_int64_(opus_int64 a, char *file, int line){ + if ( a == silk_int64_MIN ) + { + fprintf (stderr, "silk_abs_int64(%lld) in %s: line %d\n", (long long)a, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return (((a) > 0) ? (a) : -(a)); /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */ +} + +#undef silk_abs_int32 +#define silk_abs_int32(a) silk_abs_int32_((a), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_abs_int32_(opus_int32 a, char *file, int line){ + if ( a == silk_int32_MIN ) + { + fprintf (stderr, "silk_abs_int32(%d) in %s: line %d\n", a, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return silk_abs(a); +} + +#undef silk_CHECK_FIT8 +#define silk_CHECK_FIT8(a) silk_CHECK_FIT8_((a), __FILE__, __LINE__) +static OPUS_INLINE opus_int8 silk_CHECK_FIT8_( opus_int64 a, char *file, int line ){ + opus_int8 ret; + ret = (opus_int8)a; + if ( (opus_int64)ret != a ) + { + fprintf (stderr, "silk_CHECK_FIT8(%lld) in %s: line %d\n", (long long)a, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return( ret ); +} + +#undef silk_CHECK_FIT16 +#define silk_CHECK_FIT16(a) silk_CHECK_FIT16_((a), __FILE__, __LINE__) +static OPUS_INLINE opus_int16 silk_CHECK_FIT16_( opus_int64 a, char *file, int line ){ + opus_int16 ret; + ret = (opus_int16)a; + if ( (opus_int64)ret != a ) + { + fprintf (stderr, "silk_CHECK_FIT16(%lld) in %s: line %d\n", (long long)a, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return( ret ); +} + +#undef silk_CHECK_FIT32 +#define silk_CHECK_FIT32(a) silk_CHECK_FIT32_((a), __FILE__, __LINE__) +static OPUS_INLINE opus_int32 silk_CHECK_FIT32_( opus_int64 a, char *file, int line ){ + opus_int32 ret; + ret = (opus_int32)a; + if ( (opus_int64)ret != a ) + { + fprintf (stderr, "silk_CHECK_FIT32(%lld) in %s: line %d\n", (long long)a, file, line); +#ifdef FIXED_DEBUG_ASSERT + silk_assert( 0 ); +#endif + } + return( ret ); +} + +/* no checking for silk_NSHIFT_MUL_32_32 + no checking for silk_NSHIFT_MUL_16_16 + no checking needed for silk_min + no checking needed for silk_max + no checking needed for silk_sign +*/ + +#endif +#endif /* MACRO_DEBUG_H */ diff --git a/TelegramClient.Opus/opus/silk/NLSF2A.c b/TelegramClient.Opus/opus/silk/NLSF2A.c new file mode 100755 index 0000000..b1c559e --- /dev/null +++ b/TelegramClient.Opus/opus/silk/NLSF2A.c @@ -0,0 +1,178 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* conversion between prediction filter coefficients and LSFs */ +/* order should be even */ +/* a piecewise linear approximation maps LSF <-> cos(LSF) */ +/* therefore the result is not accurate LSFs, but the two */ +/* functions are accurate inverses of each other */ + +#include "SigProc_FIX.h" +#include "tables.h" + +#define QA 16 + +/* helper function for NLSF2A(..) */ +static OPUS_INLINE void silk_NLSF2A_find_poly( + opus_int32 *out, /* O intermediate polynomial, QA [dd+1] */ + const opus_int32 *cLSF, /* I vector of interleaved 2*cos(LSFs), QA [d] */ + opus_int dd /* I polynomial order (= 1/2 * filter order) */ +) +{ + opus_int k, n; + opus_int32 ftmp; + + out[0] = silk_LSHIFT( 1, QA ); + out[1] = -cLSF[0]; + for( k = 1; k < dd; k++ ) { + ftmp = cLSF[2*k]; /* QA*/ + out[k+1] = silk_LSHIFT( out[k-1], 1 ) - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[k] ), QA ); + for( n = k; n > 1; n-- ) { + out[n] += out[n-2] - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[n-1] ), QA ); + } + out[1] -= ftmp; + } +} + +/* compute whitening filter coefficients from normalized line spectral frequencies */ +void silk_NLSF2A( + opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */ + const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */ + const opus_int d /* I filter order (should be even) */ +) +{ + /* This ordering was found to maximize quality. It improves numerical accuracy of + silk_NLSF2A_find_poly() compared to "standard" ordering. */ + static const unsigned char ordering16[16] = { + 0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1 + }; + static const unsigned char ordering10[10] = { + 0, 9, 6, 3, 4, 5, 8, 1, 2, 7 + }; + const unsigned char *ordering; + opus_int k, i, dd; + opus_int32 cos_LSF_QA[ SILK_MAX_ORDER_LPC ]; + opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ]; + opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta; + opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ]; + opus_int32 maxabs, absval, idx=0, sc_Q16; + + silk_assert( LSF_COS_TAB_SZ_FIX == 128 ); + silk_assert( d==10||d==16 ); + + /* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */ + ordering = d == 16 ? ordering16 : ordering10; + for( k = 0; k < d; k++ ) { + silk_assert(NLSF[k] >= 0 ); + + /* f_int on a scale 0-127 (rounded down) */ + f_int = silk_RSHIFT( NLSF[k], 15 - 7 ); + + /* f_frac, range: 0..255 */ + f_frac = NLSF[k] - silk_LSHIFT( f_int, 15 - 7 ); + + silk_assert(f_int >= 0); + silk_assert(f_int < LSF_COS_TAB_SZ_FIX ); + + /* Read start and end value from table */ + cos_val = silk_LSFCosTab_FIX_Q12[ f_int ]; /* Q12 */ + delta = silk_LSFCosTab_FIX_Q12[ f_int + 1 ] - cos_val; /* Q12, with a range of 0..200 */ + + /* Linear interpolation */ + cos_LSF_QA[ordering[k]] = silk_RSHIFT_ROUND( silk_LSHIFT( cos_val, 8 ) + silk_MUL( delta, f_frac ), 20 - QA ); /* QA */ + } + + dd = silk_RSHIFT( d, 1 ); + + /* generate even and odd polynomials using convolution */ + silk_NLSF2A_find_poly( P, &cos_LSF_QA[ 0 ], dd ); + silk_NLSF2A_find_poly( Q, &cos_LSF_QA[ 1 ], dd ); + + /* convert even and odd polynomials to opus_int32 Q12 filter coefs */ + for( k = 0; k < dd; k++ ) { + Ptmp = P[ k+1 ] + P[ k ]; + Qtmp = Q[ k+1 ] - Q[ k ]; + + /* the Ptmp and Qtmp values at this stage need to fit in int32 */ + a32_QA1[ k ] = -Qtmp - Ptmp; /* QA+1 */ + a32_QA1[ d-k-1 ] = Qtmp - Ptmp; /* QA+1 */ + } + + /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */ + for( i = 0; i < 10; i++ ) { + /* Find maximum absolute value and its index */ + maxabs = 0; + for( k = 0; k < d; k++ ) { + absval = silk_abs( a32_QA1[k] ); + if( absval > maxabs ) { + maxabs = absval; + idx = k; + } + } + maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 ); /* QA+1 -> Q12 */ + + if( maxabs > silk_int16_MAX ) { + /* Reduce magnitude of prediction coefficients */ + maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */ + sc_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ), + silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) ); + silk_bwexpander_32( a32_QA1, d, sc_Q16 ); + } else { + break; + } + } + + if( i == 10 ) { + /* Reached the last iteration, clip the coefficients */ + for( k = 0; k < d; k++ ) { + a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */ + a32_QA1[ k ] = silk_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 ); + } + } else { + for( k = 0; k < d; k++ ) { + a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */ + } + } + + for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) { + if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) { + /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */ + /* on the unscaled coefficients, convert to Q12 and measure again */ + silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) ); + for( k = 0; k < d; k++ ) { + a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */ + } + } else { + break; + } + } +} + diff --git a/TelegramClient.Opus/opus/silk/NLSF_VQ.c b/TelegramClient.Opus/opus/silk/NLSF_VQ.c new file mode 100755 index 0000000..69b6e22 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/NLSF_VQ.c @@ -0,0 +1,68 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */ +void silk_NLSF_VQ( + opus_int32 err_Q26[], /* O Quantization errors [K] */ + const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */ + const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */ + const opus_int K, /* I Number of codebook vectors */ + const opus_int LPC_order /* I Number of LPCs */ +) +{ + opus_int i, m; + opus_int32 diff_Q15, sum_error_Q30, sum_error_Q26; + + silk_assert( LPC_order <= 16 ); + silk_assert( ( LPC_order & 1 ) == 0 ); + + /* Loop over codebook */ + for( i = 0; i < K; i++ ) { + sum_error_Q26 = 0; + for( m = 0; m < LPC_order; m += 2 ) { + /* Compute weighted squared quantization error for index m */ + diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/ + sum_error_Q30 = silk_SMULBB( diff_Q15, diff_Q15 ); + + /* Compute weighted squared quantization error for index m + 1 */ + diff_Q15 = silk_SUB_LSHIFT32( in_Q15[m + 1], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/ + sum_error_Q30 = silk_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 ); + + sum_error_Q26 = silk_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 ); + + silk_assert( sum_error_Q26 >= 0 ); + silk_assert( sum_error_Q30 >= 0 ); + } + err_Q26[ i ] = sum_error_Q26; + } +} diff --git a/TelegramClient.Opus/opus/silk/NLSF_VQ_weights_laroia.c b/TelegramClient.Opus/opus/silk/NLSF_VQ_weights_laroia.c new file mode 100755 index 0000000..04894c5 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/NLSF_VQ_weights_laroia.c @@ -0,0 +1,80 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "define.h" +#include "SigProc_FIX.h" + +/* +R. Laroia, N. Phamdo and N. Farvardin, "Robust and Efficient Quantization of Speech LSP +Parameters Using Structured Vector Quantization", Proc. IEEE Int. Conf. Acoust., Speech, +Signal Processing, pp. 641-644, 1991. +*/ + +/* Laroia low complexity NLSF weights */ +void silk_NLSF_VQ_weights_laroia( + opus_int16 *pNLSFW_Q_OUT, /* O Pointer to input vector weights [D] */ + const opus_int16 *pNLSF_Q15, /* I Pointer to input vector [D] */ + const opus_int D /* I Input vector dimension (even) */ +) +{ + opus_int k; + opus_int32 tmp1_int, tmp2_int; + + silk_assert( D > 0 ); + silk_assert( ( D & 1 ) == 0 ); + + /* First value */ + tmp1_int = silk_max_int( pNLSF_Q15[ 0 ], 1 ); + tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int ); + tmp2_int = silk_max_int( pNLSF_Q15[ 1 ] - pNLSF_Q15[ 0 ], 1 ); + tmp2_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp2_int ); + pNLSFW_Q_OUT[ 0 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX ); + silk_assert( pNLSFW_Q_OUT[ 0 ] > 0 ); + + /* Main loop */ + for( k = 1; k < D - 1; k += 2 ) { + tmp1_int = silk_max_int( pNLSF_Q15[ k + 1 ] - pNLSF_Q15[ k ], 1 ); + tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int ); + pNLSFW_Q_OUT[ k ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX ); + silk_assert( pNLSFW_Q_OUT[ k ] > 0 ); + + tmp2_int = silk_max_int( pNLSF_Q15[ k + 2 ] - pNLSF_Q15[ k + 1 ], 1 ); + tmp2_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp2_int ); + pNLSFW_Q_OUT[ k + 1 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX ); + silk_assert( pNLSFW_Q_OUT[ k + 1 ] > 0 ); + } + + /* Last value */ + tmp1_int = silk_max_int( ( 1 << 15 ) - pNLSF_Q15[ D - 1 ], 1 ); + tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int ); + pNLSFW_Q_OUT[ D - 1 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX ); + silk_assert( pNLSFW_Q_OUT[ D - 1 ] > 0 ); +} diff --git a/TelegramClient.Opus/opus/silk/NLSF_decode.c b/TelegramClient.Opus/opus/silk/NLSF_decode.c new file mode 100755 index 0000000..9f71506 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/NLSF_decode.c @@ -0,0 +1,101 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Predictive dequantizer for NLSF residuals */ +static OPUS_INLINE void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */ + opus_int16 x_Q10[], /* O Output [ order ] */ + const opus_int8 indices[], /* I Quantization indices [ order ] */ + const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */ + const opus_int quant_step_size_Q16, /* I Quantization step size */ + const opus_int16 order /* I Number of input values */ +) +{ + opus_int i, out_Q10, pred_Q10; + + out_Q10 = 0; + for( i = order-1; i >= 0; i-- ) { + pred_Q10 = silk_RSHIFT( silk_SMULBB( out_Q10, (opus_int16)pred_coef_Q8[ i ] ), 8 ); + out_Q10 = silk_LSHIFT( indices[ i ], 10 ); + if( out_Q10 > 0 ) { + out_Q10 = silk_SUB16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } else if( out_Q10 < 0 ) { + out_Q10 = silk_ADD16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } + out_Q10 = silk_SMLAWB( pred_Q10, (opus_int32)out_Q10, quant_step_size_Q16 ); + x_Q10[ i ] = out_Q10; + } +} + + +/***********************/ +/* NLSF vector decoder */ +/***********************/ +void silk_NLSF_decode( + opus_int16 *pNLSF_Q15, /* O Quantized NLSF vector [ LPC_ORDER ] */ + opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */ + const silk_NLSF_CB_struct *psNLSF_CB /* I Codebook object */ +) +{ + opus_int i; + opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; + opus_int16 ec_ix[ MAX_LPC_ORDER ]; + opus_int16 res_Q10[ MAX_LPC_ORDER ]; + opus_int16 W_tmp_QW[ MAX_LPC_ORDER ]; + opus_int32 W_tmp_Q9, NLSF_Q15_tmp; + const opus_uint8 *pCB_element; + + /* Decode first stage */ + pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ]; + for( i = 0; i < psNLSF_CB->order; i++ ) { + pNLSF_Q15[ i ] = silk_LSHIFT( (opus_int16)pCB_element[ i ], 7 ); + } + + /* Unpack entropy table indices and predictor for current CB1 index */ + silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] ); + + /* Predictive residual dequantizer */ + silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order ); + + /* Weights from codebook vector */ + silk_NLSF_VQ_weights_laroia( W_tmp_QW, pNLSF_Q15, psNLSF_CB->order ); + + /* Apply inverse square-rooted weights and add to output */ + for( i = 0; i < psNLSF_CB->order; i++ ) { + W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); + NLSF_Q15_tmp = silk_ADD32( pNLSF_Q15[ i ], silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), W_tmp_Q9 ) ); + pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 ); + } + + /* NLSF stabilization */ + silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order ); +} diff --git a/TelegramClient.Opus/opus/silk/NLSF_del_dec_quant.c b/TelegramClient.Opus/opus/silk/NLSF_del_dec_quant.c new file mode 100755 index 0000000..504dbbd --- /dev/null +++ b/TelegramClient.Opus/opus/silk/NLSF_del_dec_quant.c @@ -0,0 +1,207 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Delayed-decision quantizer for NLSF residuals */ +opus_int32 silk_NLSF_del_dec_quant( /* O Returns RD value in Q25 */ + opus_int8 indices[], /* O Quantization indices [ order ] */ + const opus_int16 x_Q10[], /* I Input [ order ] */ + const opus_int16 w_Q5[], /* I Weights [ order ] */ + const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */ + const opus_int16 ec_ix[], /* I Indices to entropy coding tables [ order ] */ + const opus_uint8 ec_rates_Q5[], /* I Rates [] */ + const opus_int quant_step_size_Q16, /* I Quantization step size */ + const opus_int16 inv_quant_step_size_Q6, /* I Inverse quantization step size */ + const opus_int32 mu_Q20, /* I R/D tradeoff */ + const opus_int16 order /* I Number of input values */ +) +{ + opus_int i, j, nStates, ind_tmp, ind_min_max, ind_max_min, in_Q10, res_Q10; + opus_int pred_Q10, diff_Q10, out0_Q10, out1_Q10, rate0_Q5, rate1_Q5; + opus_int32 RD_tmp_Q25, min_Q25, min_max_Q25, max_min_Q25, pred_coef_Q16; + opus_int ind_sort[ NLSF_QUANT_DEL_DEC_STATES ]; + opus_int8 ind[ NLSF_QUANT_DEL_DEC_STATES ][ MAX_LPC_ORDER ]; + opus_int16 prev_out_Q10[ 2 * NLSF_QUANT_DEL_DEC_STATES ]; + opus_int32 RD_Q25[ 2 * NLSF_QUANT_DEL_DEC_STATES ]; + opus_int32 RD_min_Q25[ NLSF_QUANT_DEL_DEC_STATES ]; + opus_int32 RD_max_Q25[ NLSF_QUANT_DEL_DEC_STATES ]; + const opus_uint8 *rates_Q5; + + silk_assert( (NLSF_QUANT_DEL_DEC_STATES & (NLSF_QUANT_DEL_DEC_STATES-1)) == 0 ); /* must be power of two */ + + nStates = 1; + RD_Q25[ 0 ] = 0; + prev_out_Q10[ 0 ] = 0; + for( i = order - 1; ; i-- ) { + rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ]; + pred_coef_Q16 = silk_LSHIFT( (opus_int32)pred_coef_Q8[ i ], 8 ); + in_Q10 = x_Q10[ i ]; + for( j = 0; j < nStates; j++ ) { + pred_Q10 = silk_SMULWB( pred_coef_Q16, prev_out_Q10[ j ] ); + res_Q10 = silk_SUB16( in_Q10, pred_Q10 ); + ind_tmp = silk_SMULWB( (opus_int32)inv_quant_step_size_Q6, res_Q10 ); + ind_tmp = silk_LIMIT( ind_tmp, -NLSF_QUANT_MAX_AMPLITUDE_EXT, NLSF_QUANT_MAX_AMPLITUDE_EXT-1 ); + ind[ j ][ i ] = (opus_int8)ind_tmp; + + /* compute outputs for ind_tmp and ind_tmp + 1 */ + out0_Q10 = silk_LSHIFT( ind_tmp, 10 ); + out1_Q10 = silk_ADD16( out0_Q10, 1024 ); + if( ind_tmp > 0 ) { + out0_Q10 = silk_SUB16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } else if( ind_tmp == 0 ) { + out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } else if( ind_tmp == -1 ) { + out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } else { + out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + out1_Q10 = silk_ADD16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); + } + out0_Q10 = silk_SMULWB( (opus_int32)out0_Q10, quant_step_size_Q16 ); + out1_Q10 = silk_SMULWB( (opus_int32)out1_Q10, quant_step_size_Q16 ); + out0_Q10 = silk_ADD16( out0_Q10, pred_Q10 ); + out1_Q10 = silk_ADD16( out1_Q10, pred_Q10 ); + prev_out_Q10[ j ] = out0_Q10; + prev_out_Q10[ j + nStates ] = out1_Q10; + + /* compute RD for ind_tmp and ind_tmp + 1 */ + if( ind_tmp + 1 >= NLSF_QUANT_MAX_AMPLITUDE ) { + if( ind_tmp + 1 == NLSF_QUANT_MAX_AMPLITUDE ) { + rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ]; + rate1_Q5 = 280; + } else { + rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, 43, ind_tmp ); + rate1_Q5 = silk_ADD16( rate0_Q5, 43 ); + } + } else if( ind_tmp <= -NLSF_QUANT_MAX_AMPLITUDE ) { + if( ind_tmp == -NLSF_QUANT_MAX_AMPLITUDE ) { + rate0_Q5 = 280; + rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ]; + } else { + rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, -43, ind_tmp ); + rate1_Q5 = silk_SUB16( rate0_Q5, 43 ); + } + } else { + rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ]; + rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ]; + } + RD_tmp_Q25 = RD_Q25[ j ]; + diff_Q10 = silk_SUB16( in_Q10, out0_Q10 ); + RD_Q25[ j ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate0_Q5 ); + diff_Q10 = silk_SUB16( in_Q10, out1_Q10 ); + RD_Q25[ j + nStates ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate1_Q5 ); + } + + if( nStates <= ( NLSF_QUANT_DEL_DEC_STATES >> 1 ) ) { + /* double number of states and copy */ + for( j = 0; j < nStates; j++ ) { + ind[ j + nStates ][ i ] = ind[ j ][ i ] + 1; + } + nStates = silk_LSHIFT( nStates, 1 ); + for( j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { + ind[ j ][ i ] = ind[ j - nStates ][ i ]; + } + } else if( i > 0 ) { + /* sort lower and upper half of RD_Q25, pairwise */ + for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { + if( RD_Q25[ j ] > RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] ) { + RD_max_Q25[ j ] = RD_Q25[ j ]; + RD_min_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ]; + RD_Q25[ j ] = RD_min_Q25[ j ]; + RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] = RD_max_Q25[ j ]; + /* swap prev_out values */ + out0_Q10 = prev_out_Q10[ j ]; + prev_out_Q10[ j ] = prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ]; + prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ] = out0_Q10; + ind_sort[ j ] = j + NLSF_QUANT_DEL_DEC_STATES; + } else { + RD_min_Q25[ j ] = RD_Q25[ j ]; + RD_max_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ]; + ind_sort[ j ] = j; + } + } + /* compare the highest RD values of the winning half with the lowest one in the losing half, and copy if necessary */ + /* afterwards ind_sort[] will contain the indices of the NLSF_QUANT_DEL_DEC_STATES winning RD values */ + while( 1 ) { + min_max_Q25 = silk_int32_MAX; + max_min_Q25 = 0; + ind_min_max = 0; + ind_max_min = 0; + for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { + if( min_max_Q25 > RD_max_Q25[ j ] ) { + min_max_Q25 = RD_max_Q25[ j ]; + ind_min_max = j; + } + if( max_min_Q25 < RD_min_Q25[ j ] ) { + max_min_Q25 = RD_min_Q25[ j ]; + ind_max_min = j; + } + } + if( min_max_Q25 >= max_min_Q25 ) { + break; + } + /* copy ind_min_max to ind_max_min */ + ind_sort[ ind_max_min ] = ind_sort[ ind_min_max ] ^ NLSF_QUANT_DEL_DEC_STATES; + RD_Q25[ ind_max_min ] = RD_Q25[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ]; + prev_out_Q10[ ind_max_min ] = prev_out_Q10[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ]; + RD_min_Q25[ ind_max_min ] = 0; + RD_max_Q25[ ind_min_max ] = silk_int32_MAX; + silk_memcpy( ind[ ind_max_min ], ind[ ind_min_max ], MAX_LPC_ORDER * sizeof( opus_int8 ) ); + } + /* increment index if it comes from the upper half */ + for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) { + ind[ j ][ i ] += silk_RSHIFT( ind_sort[ j ], NLSF_QUANT_DEL_DEC_STATES_LOG2 ); + } + } else { /* i == 0 */ + break; + } + } + + /* last sample: find winner, copy indices and return RD value */ + ind_tmp = 0; + min_Q25 = silk_int32_MAX; + for( j = 0; j < 2 * NLSF_QUANT_DEL_DEC_STATES; j++ ) { + if( min_Q25 > RD_Q25[ j ] ) { + min_Q25 = RD_Q25[ j ]; + ind_tmp = j; + } + } + for( j = 0; j < order; j++ ) { + indices[ j ] = ind[ ind_tmp & ( NLSF_QUANT_DEL_DEC_STATES - 1 ) ][ j ]; + silk_assert( indices[ j ] >= -NLSF_QUANT_MAX_AMPLITUDE_EXT ); + silk_assert( indices[ j ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); + } + indices[ 0 ] += silk_RSHIFT( ind_tmp, NLSF_QUANT_DEL_DEC_STATES_LOG2 ); + silk_assert( indices[ 0 ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT ); + silk_assert( min_Q25 >= 0 ); + return min_Q25; +} diff --git a/TelegramClient.Opus/opus/silk/NLSF_encode.c b/TelegramClient.Opus/opus/silk/NLSF_encode.c new file mode 100755 index 0000000..03a036f --- /dev/null +++ b/TelegramClient.Opus/opus/silk/NLSF_encode.c @@ -0,0 +1,136 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "stack_alloc.h" + +/***********************/ +/* NLSF vector encoder */ +/***********************/ +opus_int32 silk_NLSF_encode( /* O Returns RD value in Q25 */ + opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */ + opus_int16 *pNLSF_Q15, /* I/O Quantized NLSF vector [ LPC_ORDER ] */ + const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */ + const opus_int16 *pW_QW, /* I NLSF weight vector [ LPC_ORDER ] */ + const opus_int NLSF_mu_Q20, /* I Rate weight for the RD optimization */ + const opus_int nSurvivors, /* I Max survivors after first stage */ + const opus_int signalType /* I Signal type: 0/1/2 */ +) +{ + opus_int i, s, ind1, bestIndex, prob_Q8, bits_q7; + opus_int32 W_tmp_Q9; + VARDECL( opus_int32, err_Q26 ); + VARDECL( opus_int32, RD_Q25 ); + VARDECL( opus_int, tempIndices1 ); + VARDECL( opus_int8, tempIndices2 ); + opus_int16 res_Q15[ MAX_LPC_ORDER ]; + opus_int16 res_Q10[ MAX_LPC_ORDER ]; + opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ]; + opus_int16 W_tmp_QW[ MAX_LPC_ORDER ]; + opus_int16 W_adj_Q5[ MAX_LPC_ORDER ]; + opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; + opus_int16 ec_ix[ MAX_LPC_ORDER ]; + const opus_uint8 *pCB_element, *iCDF_ptr; + SAVE_STACK; + + silk_assert( nSurvivors <= NLSF_VQ_MAX_SURVIVORS ); + silk_assert( signalType >= 0 && signalType <= 2 ); + silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 ); + + /* NLSF stabilization */ + silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order ); + + /* First stage: VQ */ + ALLOC( err_Q26, psNLSF_CB->nVectors, opus_int32 ); + silk_NLSF_VQ( err_Q26, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->nVectors, psNLSF_CB->order ); + + /* Sort the quantization errors */ + ALLOC( tempIndices1, nSurvivors, opus_int ); + silk_insertion_sort_increasing( err_Q26, tempIndices1, psNLSF_CB->nVectors, nSurvivors ); + + ALLOC( RD_Q25, nSurvivors, opus_int32 ); + ALLOC( tempIndices2, nSurvivors * MAX_LPC_ORDER, opus_int8 ); + + /* Loop over survivors */ + for( s = 0; s < nSurvivors; s++ ) { + ind1 = tempIndices1[ s ]; + + /* Residual after first stage */ + pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ]; + for( i = 0; i < psNLSF_CB->order; i++ ) { + NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 ); + res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ]; + } + + /* Weights from codebook vector */ + silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order ); + + /* Apply square-rooted weights */ + for( i = 0; i < psNLSF_CB->order; i++ ) { + W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) ); + res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 ); + } + + /* Modify input weights accordingly */ + for( i = 0; i < psNLSF_CB->order; i++ ) { + W_adj_Q5[ i ] = silk_DIV32_16( silk_LSHIFT( (opus_int32)pW_QW[ i ], 5 ), W_tmp_QW[ i ] ); + } + + /* Unpack entropy table indices and predictor for current CB1 index */ + silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, ind1 ); + + /* Trellis quantizer */ + RD_Q25[ s ] = silk_NLSF_del_dec_quant( &tempIndices2[ s * MAX_LPC_ORDER ], res_Q10, W_adj_Q5, pred_Q8, ec_ix, + psNLSF_CB->ec_Rates_Q5, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->invQuantStepSize_Q6, NLSF_mu_Q20, psNLSF_CB->order ); + + /* Add rate for first stage */ + iCDF_ptr = &psNLSF_CB->CB1_iCDF[ ( signalType >> 1 ) * psNLSF_CB->nVectors ]; + if( ind1 == 0 ) { + prob_Q8 = 256 - iCDF_ptr[ ind1 ]; + } else { + prob_Q8 = iCDF_ptr[ ind1 - 1 ] - iCDF_ptr[ ind1 ]; + } + bits_q7 = ( 8 << 7 ) - silk_lin2log( prob_Q8 ); + RD_Q25[ s ] = silk_SMLABB( RD_Q25[ s ], bits_q7, silk_RSHIFT( NLSF_mu_Q20, 2 ) ); + } + + /* Find the lowest rate-distortion error */ + silk_insertion_sort_increasing( RD_Q25, &bestIndex, nSurvivors, 1 ); + + NLSFIndices[ 0 ] = (opus_int8)tempIndices1[ bestIndex ]; + silk_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) ); + + /* Decode */ + silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB ); + + RESTORE_STACK; + return RD_Q25[ 0 ]; +} diff --git a/TelegramClient.Opus/opus/silk/NLSF_stabilize.c b/TelegramClient.Opus/opus/silk/NLSF_stabilize.c new file mode 100755 index 0000000..1fa1ea3 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/NLSF_stabilize.c @@ -0,0 +1,142 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* NLSF stabilizer: */ +/* */ +/* - Moves NLSFs further apart if they are too close */ +/* - Moves NLSFs away from borders if they are too close */ +/* - High effort to achieve a modification with minimum */ +/* Euclidean distance to input vector */ +/* - Output are sorted NLSF coefficients */ +/* */ + +#include "SigProc_FIX.h" + +/* Constant Definitions */ +#define MAX_LOOPS 20 + +/* NLSF stabilizer, for a single input data vector */ +void silk_NLSF_stabilize( + opus_int16 *NLSF_Q15, /* I/O Unstable/stabilized normalized LSF vector in Q15 [L] */ + const opus_int16 *NDeltaMin_Q15, /* I Min distance vector, NDeltaMin_Q15[L] must be >= 1 [L+1] */ + const opus_int L /* I Number of NLSF parameters in the input vector */ +) +{ + opus_int i, I=0, k, loops; + opus_int16 center_freq_Q15; + opus_int32 diff_Q15, min_diff_Q15, min_center_Q15, max_center_Q15; + + /* This is necessary to ensure an output within range of a opus_int16 */ + silk_assert( NDeltaMin_Q15[L] >= 1 ); + + for( loops = 0; loops < MAX_LOOPS; loops++ ) { + /**************************/ + /* Find smallest distance */ + /**************************/ + /* First element */ + min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0]; + I = 0; + /* Middle elements */ + for( i = 1; i <= L-1; i++ ) { + diff_Q15 = NLSF_Q15[i] - ( NLSF_Q15[i-1] + NDeltaMin_Q15[i] ); + if( diff_Q15 < min_diff_Q15 ) { + min_diff_Q15 = diff_Q15; + I = i; + } + } + /* Last element */ + diff_Q15 = ( 1 << 15 ) - ( NLSF_Q15[L-1] + NDeltaMin_Q15[L] ); + if( diff_Q15 < min_diff_Q15 ) { + min_diff_Q15 = diff_Q15; + I = L; + } + + /***************************************************/ + /* Now check if the smallest distance non-negative */ + /***************************************************/ + if( min_diff_Q15 >= 0 ) { + return; + } + + if( I == 0 ) { + /* Move away from lower limit */ + NLSF_Q15[0] = NDeltaMin_Q15[0]; + + } else if( I == L) { + /* Move away from higher limit */ + NLSF_Q15[L-1] = ( 1 << 15 ) - NDeltaMin_Q15[L]; + + } else { + /* Find the lower extreme for the location of the current center frequency */ + min_center_Q15 = 0; + for( k = 0; k < I; k++ ) { + min_center_Q15 += NDeltaMin_Q15[k]; + } + min_center_Q15 += silk_RSHIFT( NDeltaMin_Q15[I], 1 ); + + /* Find the upper extreme for the location of the current center frequency */ + max_center_Q15 = 1 << 15; + for( k = L; k > I; k-- ) { + max_center_Q15 -= NDeltaMin_Q15[k]; + } + max_center_Q15 -= silk_RSHIFT( NDeltaMin_Q15[I], 1 ); + + /* Move apart, sorted by value, keeping the same center frequency */ + center_freq_Q15 = (opus_int16)silk_LIMIT_32( silk_RSHIFT_ROUND( (opus_int32)NLSF_Q15[I-1] + (opus_int32)NLSF_Q15[I], 1 ), + min_center_Q15, max_center_Q15 ); + NLSF_Q15[I-1] = center_freq_Q15 - silk_RSHIFT( NDeltaMin_Q15[I], 1 ); + NLSF_Q15[I] = NLSF_Q15[I-1] + NDeltaMin_Q15[I]; + } + } + + /* Safe and simple fall back method, which is less ideal than the above */ + if( loops == MAX_LOOPS ) + { + /* Insertion sort (fast for already almost sorted arrays): */ + /* Best case: O(n) for an already sorted array */ + /* Worst case: O(n^2) for an inversely sorted array */ + silk_insertion_sort_increasing_all_values_int16( &NLSF_Q15[0], L ); + + /* First NLSF should be no less than NDeltaMin[0] */ + NLSF_Q15[0] = silk_max_int( NLSF_Q15[0], NDeltaMin_Q15[0] ); + + /* Keep delta_min distance between the NLSFs */ + for( i = 1; i < L; i++ ) + NLSF_Q15[i] = silk_max_int( NLSF_Q15[i], NLSF_Q15[i-1] + NDeltaMin_Q15[i] ); + + /* Last NLSF should be no higher than 1 - NDeltaMin[L] */ + NLSF_Q15[L-1] = silk_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] ); + + /* Keep NDeltaMin distance between the NLSFs */ + for( i = L-2; i >= 0; i-- ) + NLSF_Q15[i] = silk_min_int( NLSF_Q15[i], NLSF_Q15[i+1] - NDeltaMin_Q15[i+1] ); + } +} diff --git a/TelegramClient.Opus/opus/silk/NLSF_unpack.c b/TelegramClient.Opus/opus/silk/NLSF_unpack.c new file mode 100755 index 0000000..17bd23f --- /dev/null +++ b/TelegramClient.Opus/opus/silk/NLSF_unpack.c @@ -0,0 +1,55 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Unpack predictor values and indices for entropy coding tables */ +void silk_NLSF_unpack( + opus_int16 ec_ix[], /* O Indices to entropy tables [ LPC_ORDER ] */ + opus_uint8 pred_Q8[], /* O LSF predictor [ LPC_ORDER ] */ + const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */ + const opus_int CB1_index /* I Index of vector in first LSF codebook */ +) +{ + opus_int i; + opus_uint8 entry; + const opus_uint8 *ec_sel_ptr; + + ec_sel_ptr = &psNLSF_CB->ec_sel[ CB1_index * psNLSF_CB->order / 2 ]; + for( i = 0; i < psNLSF_CB->order; i += 2 ) { + entry = *ec_sel_ptr++; + ec_ix [ i ] = silk_SMULBB( silk_RSHIFT( entry, 1 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 ); + pred_Q8[ i ] = psNLSF_CB->pred_Q8[ i + ( entry & 1 ) * ( psNLSF_CB->order - 1 ) ]; + ec_ix [ i + 1 ] = silk_SMULBB( silk_RSHIFT( entry, 5 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 ); + pred_Q8[ i + 1 ] = psNLSF_CB->pred_Q8[ i + ( silk_RSHIFT( entry, 4 ) & 1 ) * ( psNLSF_CB->order - 1 ) + 1 ]; + } +} + diff --git a/TelegramClient.Opus/opus/silk/NSQ.c b/TelegramClient.Opus/opus/silk/NSQ.c new file mode 100755 index 0000000..cf5b3fd --- /dev/null +++ b/TelegramClient.Opus/opus/silk/NSQ.c @@ -0,0 +1,446 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "stack_alloc.h" + +static OPUS_INLINE void silk_nsq_scale_states( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + const opus_int32 x_Q3[], /* I input in Q3 */ + opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */ + const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ + opus_int subfr, /* I subframe number */ + const opus_int LTP_scale_Q14, /* I */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ + const opus_int signal_type /* I Signal type */ +); + +static OPUS_INLINE void silk_noise_shape_quantizer( + silk_nsq_state *NSQ, /* I/O NSQ state */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_sc_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q15[], /* I/O LTP state */ + const opus_int16 a_Q12[], /* I Short term prediction coefs */ + const opus_int16 b_Q14[], /* I Long term prediction coefs */ + const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */ + opus_int lag, /* I Pitch lag */ + opus_int32 HarmShapeFIRPacked_Q14, /* I */ + opus_int Tilt_Q14, /* I Spectral tilt */ + opus_int32 LF_shp_Q14, /* I */ + opus_int32 Gain_Q16, /* I */ + opus_int Lambda_Q10, /* I */ + opus_int offset_Q10, /* I */ + opus_int length, /* I Input length */ + opus_int shapingLPCOrder, /* I Noise shaping AR filter order */ + opus_int predictLPCOrder /* I Prediction filter order */ +); + +void silk_NSQ( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */ + const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */ + const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ + const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */ + const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */ + const opus_int LTP_scale_Q14 /* I LTP state scaling */ +) +{ + opus_int k, lag, start_idx, LSF_interpolation_flag; + const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; + opus_int16 *pxq; + VARDECL( opus_int32, sLTP_Q15 ); + VARDECL( opus_int16, sLTP ); + opus_int32 HarmShapeFIRPacked_Q14; + opus_int offset_Q10; + VARDECL( opus_int32, x_sc_Q10 ); + SAVE_STACK; + + NSQ->rand_seed = psIndices->Seed; + + /* Set unvoiced lag to the previous one, overwrite later for voiced */ + lag = NSQ->lagPrev; + + silk_assert( NSQ->prev_gain_Q16 != 0 ); + + offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; + + if( psIndices->NLSFInterpCoef_Q2 == 4 ) { + LSF_interpolation_flag = 0; + } else { + LSF_interpolation_flag = 1; + } + + ALLOC( sLTP_Q15, + psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); + ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); + ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); + /* Set up pointers to start of sub frame */ + NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; + for( k = 0; k < psEncC->nb_subfr; k++ ) { + A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ]; + B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; + AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Noise shape parameters */ + silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); + HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); + HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); + + NSQ->rewhite_flag = 0; + if( psIndices->signalType == TYPE_VOICED ) { + /* Voiced */ + lag = pitchL[ k ]; + + /* Re-whitening */ + if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { + /* Rewhiten with new A coefs */ + start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; + silk_assert( start_idx > 0 ); + + silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], + A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder ); + + NSQ->rewhite_flag = 1; + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + } + } + + silk_nsq_scale_states( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType ); + + silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14, + AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10, + offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder ); + + x_Q3 += psEncC->subfr_length; + pulses += psEncC->subfr_length; + pxq += psEncC->subfr_length; + } + + /* Update lagPrev for next frame */ + NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; + + /* Save quantized speech and noise shaping signals */ + /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */ + silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); + silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); + RESTORE_STACK; +} + +/***********************************/ +/* silk_noise_shape_quantizer */ +/***********************************/ +static OPUS_INLINE void silk_noise_shape_quantizer( + silk_nsq_state *NSQ, /* I/O NSQ state */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_sc_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q15[], /* I/O LTP state */ + const opus_int16 a_Q12[], /* I Short term prediction coefs */ + const opus_int16 b_Q14[], /* I Long term prediction coefs */ + const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */ + opus_int lag, /* I Pitch lag */ + opus_int32 HarmShapeFIRPacked_Q14, /* I */ + opus_int Tilt_Q14, /* I Spectral tilt */ + opus_int32 LF_shp_Q14, /* I */ + opus_int32 Gain_Q16, /* I */ + opus_int Lambda_Q10, /* I */ + opus_int offset_Q10, /* I */ + opus_int length, /* I Input length */ + opus_int shapingLPCOrder, /* I Noise shaping AR filter order */ + opus_int predictLPCOrder /* I Prediction filter order */ +) +{ + opus_int i, j; + opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q12, n_LTP_Q13; + opus_int32 n_LF_Q12, r_Q10, rr_Q10, q1_Q0, q1_Q10, q2_Q10, rd1_Q20, rd2_Q20; + opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; + opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; + opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr; + + shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; + pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); + + /* Set up short term AR state */ + psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ]; + + for( i = 0; i < length; i++ ) { + /* Generate dither */ + NSQ->rand_seed = silk_RAND( NSQ->rand_seed ); + + /* Short-term prediction */ + silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 ); + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LPC_pred_Q10 = silk_RSHIFT( predictLPCOrder, 1 ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ 0 ], a_Q12[ 0 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); + if( predictLPCOrder == 16 ) { + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -10 ], a_Q12[ 10 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -11 ], a_Q12[ 11 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -12 ], a_Q12[ 12 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -13 ], a_Q12[ 13 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -14 ], a_Q12[ 14 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -15 ], a_Q12[ 15 ] ); + } + + /* Long-term prediction */ + if( signalType == TYPE_VOICED ) { + /* Unrolled loop */ + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LTP_pred_Q13 = 2; + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], b_Q14[ 1 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); + pred_lag_ptr++; + } else { + LTP_pred_Q13 = 0; + } + + /* Noise shape feedback */ + silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ + tmp2 = psLPC_Q14[ 0 ]; + tmp1 = NSQ->sAR2_Q14[ 0 ]; + NSQ->sAR2_Q14[ 0 ] = tmp2; + n_AR_Q12 = silk_RSHIFT( shapingLPCOrder, 1 ); + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp2, AR_shp_Q13[ 0 ] ); + for( j = 2; j < shapingLPCOrder; j += 2 ) { + tmp2 = NSQ->sAR2_Q14[ j - 1 ]; + NSQ->sAR2_Q14[ j - 1 ] = tmp1; + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp1, AR_shp_Q13[ j - 1 ] ); + tmp1 = NSQ->sAR2_Q14[ j + 0 ]; + NSQ->sAR2_Q14[ j + 0 ] = tmp2; + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp2, AR_shp_Q13[ j ] ); + } + NSQ->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); + + n_AR_Q12 = silk_LSHIFT32( n_AR_Q12, 1 ); /* Q11 -> Q12 */ + n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 ); + + n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 ); + n_LF_Q12 = silk_SMLAWT( n_LF_Q12, NSQ->sLF_AR_shp_Q14, LF_shp_Q14 ); + + silk_assert( lag > 0 || signalType != TYPE_VOICED ); + + /* Combine prediction and noise shaping signals */ + tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */ + tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */ + if( lag > 0 ) { + /* Symmetric, packed FIR coefficients */ + n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); + n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); + n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 ); + shp_lag_ptr++; + + tmp2 = silk_SUB32( LTP_pred_Q13, n_LTP_Q13 ); /* Q13 */ + tmp1 = silk_ADD_LSHIFT32( tmp2, tmp1, 1 ); /* Q13 */ + tmp1 = silk_RSHIFT_ROUND( tmp1, 3 ); /* Q10 */ + } else { + tmp1 = silk_RSHIFT_ROUND( tmp1, 2 ); /* Q10 */ + } + + r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */ + + /* Flip sign depending on dither */ + if ( NSQ->rand_seed < 0 ) { + r_Q10 = -r_Q10; + } + r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); + + /* Find two quantization level candidates and measure their rate-distortion */ + q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); + q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); + if( q1_Q0 > 0 ) { + q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = silk_ADD32( q1_Q10, 1024 ); + rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q0 == 0 ) { + q1_Q10 = offset_Q10; + q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q0 == -1 ) { + q2_Q10 = offset_Q10; + q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else { /* Q1_Q0 < -1 */ + q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = silk_ADD32( q1_Q10, 1024 ); + rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q20 = silk_SMULBB( -q2_Q10, Lambda_Q10 ); + } + rr_Q10 = silk_SUB32( r_Q10, q1_Q10 ); + rd1_Q20 = silk_SMLABB( rd1_Q20, rr_Q10, rr_Q10 ); + rr_Q10 = silk_SUB32( r_Q10, q2_Q10 ); + rd2_Q20 = silk_SMLABB( rd2_Q20, rr_Q10, rr_Q10 ); + + if( rd2_Q20 < rd1_Q20 ) { + q1_Q10 = q2_Q10; + } + + pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 ); + + /* Excitation */ + exc_Q14 = silk_LSHIFT( q1_Q10, 4 ); + if ( NSQ->rand_seed < 0 ) { + exc_Q14 = -exc_Q14; + } + + /* Add predictions */ + LPC_exc_Q14 = silk_ADD_LSHIFT32( exc_Q14, LTP_pred_Q13, 1 ); + xq_Q14 = silk_ADD_LSHIFT32( LPC_exc_Q14, LPC_pred_Q10, 4 ); + + /* Scale XQ back to normal level before saving */ + xq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( xq_Q14, Gain_Q10 ), 8 ) ); + + /* Update states */ + psLPC_Q14++; + *psLPC_Q14 = xq_Q14; + sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 ); + NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14; + + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 ); + sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q14, 1 ); + NSQ->sLTP_shp_buf_idx++; + NSQ->sLTP_buf_idx++; + + /* Make dither dependent on quantized signal */ + NSQ->rand_seed = silk_ADD32_ovflw( NSQ->rand_seed, pulses[ i ] ); + } + + /* Update LPC synth buffer */ + silk_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); +} + +static OPUS_INLINE void silk_nsq_scale_states( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + const opus_int32 x_Q3[], /* I input in Q3 */ + opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */ + const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ + opus_int subfr, /* I subframe number */ + const opus_int LTP_scale_Q14, /* I */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ + const opus_int signal_type /* I Signal type */ +) +{ + opus_int i, lag; + opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23; + + lag = pitchL[ subfr ]; + inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 ); + silk_assert( inv_gain_Q31 != 0 ); + + /* Calculate gain adjustment factor */ + if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { + gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 ); + } else { + gain_adj_Q16 = (opus_int32)1 << 16; + } + + /* Scale input */ + inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 ); + for( i = 0; i < psEncC->subfr_length; i++ ) { + x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 ); + } + + /* Save inverse gain */ + NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; + + /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ + if( NSQ->rewhite_flag ) { + if( subfr == 0 ) { + /* Do LTP downscaling */ + inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); + } + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + silk_assert( i < MAX_FRAME_LENGTH ); + sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); + } + } + + /* Adjust for changing gain */ + if( gain_adj_Q16 != (opus_int32)1 << 16 ) { + /* Scale long-term shaping state */ + for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) { + NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] ); + } + + /* Scale long-term prediction state */ + if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); + } + } + + NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 ); + + /* Scale short-term prediction and shaping states */ + for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { + NSQ->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] ); + } + for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { + NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] ); + } + } +} diff --git a/TelegramClient.Opus/opus/silk/NSQ_del_dec.c b/TelegramClient.Opus/opus/silk/NSQ_del_dec.c new file mode 100755 index 0000000..522be40 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/NSQ_del_dec.c @@ -0,0 +1,719 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "stack_alloc.h" + +typedef struct { + opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ]; + opus_int32 RandState[ DECISION_DELAY ]; + opus_int32 Q_Q10[ DECISION_DELAY ]; + opus_int32 Xq_Q14[ DECISION_DELAY ]; + opus_int32 Pred_Q15[ DECISION_DELAY ]; + opus_int32 Shape_Q14[ DECISION_DELAY ]; + opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ]; + opus_int32 LF_AR_Q14; + opus_int32 Seed; + opus_int32 SeedInit; + opus_int32 RD_Q10; +} NSQ_del_dec_struct; + +typedef struct { + opus_int32 Q_Q10; + opus_int32 RD_Q10; + opus_int32 xq_Q14; + opus_int32 LF_AR_Q14; + opus_int32 sLTP_shp_Q14; + opus_int32 LPC_exc_Q14; +} NSQ_sample_struct; + +typedef NSQ_sample_struct NSQ_sample_pair[ 2 ]; + +static OPUS_INLINE void silk_nsq_del_dec_scale_states( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + const opus_int32 x_Q3[], /* I Input in Q3 */ + opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ + const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ + opus_int subfr, /* I Subframe number */ + opus_int nStatesDelayedDecision, /* I Number of del dec states */ + const opus_int LTP_scale_Q14, /* I LTP state scaling */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ + const opus_int signal_type, /* I Signal type */ + const opus_int decisionDelay /* I Decision delay */ +); + +/******************************************/ +/* Noise shape quantizer for one subframe */ +/******************************************/ +static OPUS_INLINE void silk_noise_shape_quantizer_del_dec( + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q15[], /* I/O LTP filter state */ + opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */ + const opus_int16 a_Q12[], /* I Short term prediction coefs */ + const opus_int16 b_Q14[], /* I Long term prediction coefs */ + const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */ + opus_int lag, /* I Pitch lag */ + opus_int32 HarmShapeFIRPacked_Q14, /* I */ + opus_int Tilt_Q14, /* I Spectral tilt */ + opus_int32 LF_shp_Q14, /* I */ + opus_int32 Gain_Q16, /* I */ + opus_int Lambda_Q10, /* I */ + opus_int offset_Q10, /* I */ + opus_int length, /* I Input length */ + opus_int subfr, /* I Subframe number */ + opus_int shapingLPCOrder, /* I Shaping LPC filter order */ + opus_int predictLPCOrder, /* I Prediction filter order */ + opus_int warping_Q16, /* I */ + opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ + opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ + opus_int decisionDelay /* I */ +); + +void silk_NSQ_del_dec( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */ + const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */ + const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ + const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */ + const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */ + const opus_int LTP_scale_Q14 /* I LTP state scaling */ +) +{ + opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr; + opus_int last_smple_idx, smpl_buf_idx, decisionDelay; + const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13; + opus_int16 *pxq; + VARDECL( opus_int32, sLTP_Q15 ); + VARDECL( opus_int16, sLTP ); + opus_int32 HarmShapeFIRPacked_Q14; + opus_int offset_Q10; + opus_int32 RDmin_Q10, Gain_Q10; + VARDECL( opus_int32, x_sc_Q10 ); + VARDECL( opus_int32, delayedGain_Q10 ); + VARDECL( NSQ_del_dec_struct, psDelDec ); + NSQ_del_dec_struct *psDD; + SAVE_STACK; + + /* Set unvoiced lag to the previous one, overwrite later for voiced */ + lag = NSQ->lagPrev; + + silk_assert( NSQ->prev_gain_Q16 != 0 ); + + /* Initialize delayed decision states */ + ALLOC( psDelDec, psEncC->nStatesDelayedDecision, NSQ_del_dec_struct ); + silk_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) ); + for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + psDD->Seed = ( k + psIndices->Seed ) & 3; + psDD->SeedInit = psDD->Seed; + psDD->RD_Q10 = 0; + psDD->LF_AR_Q14 = NSQ->sLF_AR_shp_Q14; + psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ]; + silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) ); + } + + offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ]; + smpl_buf_idx = 0; /* index of oldest samples */ + + decisionDelay = silk_min_int( DECISION_DELAY, psEncC->subfr_length ); + + /* For voiced frames limit the decision delay to lower than the pitch lag */ + if( psIndices->signalType == TYPE_VOICED ) { + for( k = 0; k < psEncC->nb_subfr; k++ ) { + decisionDelay = silk_min_int( decisionDelay, pitchL[ k ] - LTP_ORDER / 2 - 1 ); + } + } else { + if( lag > 0 ) { + decisionDelay = silk_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 ); + } + } + + if( psIndices->NLSFInterpCoef_Q2 == 4 ) { + LSF_interpolation_flag = 0; + } else { + LSF_interpolation_flag = 1; + } + + ALLOC( sLTP_Q15, + psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); + ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); + ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); + ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 ); + /* Set up pointers to start of sub frame */ + pxq = &NSQ->xq[ psEncC->ltp_mem_length ]; + NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length; + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + subfr = 0; + for( k = 0; k < psEncC->nb_subfr; k++ ) { + A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ]; + B_Q14 = <PCoef_Q14[ k * LTP_ORDER ]; + AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Noise shape parameters */ + silk_assert( HarmShapeGain_Q14[ k ] >= 0 ); + HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 ); + HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 ); + + NSQ->rewhite_flag = 0; + if( psIndices->signalType == TYPE_VOICED ) { + /* Voiced */ + lag = pitchL[ k ]; + + /* Re-whitening */ + if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) { + if( k == 2 ) { + /* RESET DELAYED DECISIONS */ + /* Find winner */ + RDmin_Q10 = psDelDec[ 0 ].RD_Q10; + Winner_ind = 0; + for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) { + if( psDelDec[ i ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psDelDec[ i ].RD_Q10; + Winner_ind = i; + } + } + for( i = 0; i < psEncC->nStatesDelayedDecision; i++ ) { + if( i != Winner_ind ) { + psDelDec[ i ].RD_Q10 += ( silk_int32_MAX >> 4 ); + silk_assert( psDelDec[ i ].RD_Q10 >= 0 ); + } + } + + /* Copy final part of signals from winner state to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + last_smple_idx = smpl_buf_idx + decisionDelay; + for( i = 0; i < decisionDelay; i++ ) { + last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; + pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( + silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) ); + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ]; + } + + subfr = 0; + } + + /* Rewhiten with new A coefs */ + start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2; + silk_assert( start_idx > 0 ); + + silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ], + A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder ); + + NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; + NSQ->rewhite_flag = 1; + } + } + + silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, + psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay ); + + silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, + delayedGain_Q10, A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], + Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder, + psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay ); + + x_Q3 += psEncC->subfr_length; + pulses += psEncC->subfr_length; + pxq += psEncC->subfr_length; + } + + /* Find winner */ + RDmin_Q10 = psDelDec[ 0 ].RD_Q10; + Winner_ind = 0; + for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) { + if( psDelDec[ k ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psDelDec[ k ].RD_Q10; + Winner_ind = k; + } + } + + /* Copy final part of signals from winner state to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + psIndices->Seed = psDD->SeedInit; + last_smple_idx = smpl_buf_idx + decisionDelay; + Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 ); + for( i = 0; i < decisionDelay; i++ ) { + last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK; + pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( + silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) ); + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ]; + } + silk_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + silk_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) ); + + /* Update states */ + NSQ->sLF_AR_shp_Q14 = psDD->LF_AR_Q14; + NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; + + /* Save quantized speech signal */ + /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */ + silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) ); + silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) ); + RESTORE_STACK; +} + +/******************************************/ +/* Noise shape quantizer for one subframe */ +/******************************************/ +static OPUS_INLINE void silk_noise_shape_quantizer_del_dec( + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + opus_int signalType, /* I Signal type */ + const opus_int32 x_Q10[], /* I */ + opus_int8 pulses[], /* O */ + opus_int16 xq[], /* O */ + opus_int32 sLTP_Q15[], /* I/O LTP filter state */ + opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */ + const opus_int16 a_Q12[], /* I Short term prediction coefs */ + const opus_int16 b_Q14[], /* I Long term prediction coefs */ + const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */ + opus_int lag, /* I Pitch lag */ + opus_int32 HarmShapeFIRPacked_Q14, /* I */ + opus_int Tilt_Q14, /* I Spectral tilt */ + opus_int32 LF_shp_Q14, /* I */ + opus_int32 Gain_Q16, /* I */ + opus_int Lambda_Q10, /* I */ + opus_int offset_Q10, /* I */ + opus_int length, /* I Input length */ + opus_int subfr, /* I Subframe number */ + opus_int shapingLPCOrder, /* I Shaping LPC filter order */ + opus_int predictLPCOrder, /* I Prediction filter order */ + opus_int warping_Q16, /* I */ + opus_int nStatesDelayedDecision, /* I Number of states in decision tree */ + opus_int *smpl_buf_idx, /* I Index to newest samples in buffers */ + opus_int decisionDelay /* I */ +) +{ + opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx; + opus_int32 Winner_rand_state; + opus_int32 LTP_pred_Q14, LPC_pred_Q14, n_AR_Q14, n_LTP_Q14; + opus_int32 n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10; + opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10; + opus_int32 tmp1, tmp2, sLF_AR_shp_Q14; + opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14; + VARDECL( NSQ_sample_pair, psSampleState ); + NSQ_del_dec_struct *psDD; + NSQ_sample_struct *psSS; + SAVE_STACK; + + silk_assert( nStatesDelayedDecision > 0 ); + ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair ); + + shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ]; + pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 ); + + for( i = 0; i < length; i++ ) { + /* Perform common calculations used in all states */ + + /* Long-term prediction */ + if( signalType == TYPE_VOICED ) { + /* Unrolled loop */ + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LTP_pred_Q14 = 2; + LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ 0 ], b_Q14[ 0 ] ); + LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] ); + LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] ); + LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] ); + LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] ); + LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */ + pred_lag_ptr++; + } else { + LTP_pred_Q14 = 0; + } + + /* Long-term shaping */ + if( lag > 0 ) { + /* Symmetric, packed FIR coefficients */ + n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 ); + n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 ); + n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */ + shp_lag_ptr++; + } else { + n_LTP_Q14 = 0; + } + + for( k = 0; k < nStatesDelayedDecision; k++ ) { + /* Delayed decision state */ + psDD = &psDelDec[ k ]; + + /* Sample state */ + psSS = psSampleState[ k ]; + + /* Generate dither */ + psDD->Seed = silk_RAND( psDD->Seed ); + + /* Pointer used in short term prediction and shaping */ + psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ]; + /* Short-term prediction */ + silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 ); + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LPC_pred_Q14 = silk_RSHIFT( predictLPCOrder, 1 ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ 0 ], a_Q12[ 0 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -1 ], a_Q12[ 1 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -2 ], a_Q12[ 2 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -3 ], a_Q12[ 3 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -4 ], a_Q12[ 4 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -5 ], a_Q12[ 5 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -6 ], a_Q12[ 6 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -7 ], a_Q12[ 7 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -8 ], a_Q12[ 8 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -9 ], a_Q12[ 9 ] ); + if( predictLPCOrder == 16 ) { + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -10 ], a_Q12[ 10 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -11 ], a_Q12[ 11 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -12 ], a_Q12[ 12 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -13 ], a_Q12[ 13 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -14 ], a_Q12[ 14 ] ); + LPC_pred_Q14 = silk_SMLAWB( LPC_pred_Q14, psLPC_Q14[ -15 ], a_Q12[ 15 ] ); + } + LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */ + + /* Noise shape feedback */ + silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ + /* Output of lowpass section */ + tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 ); + psDD->sAR2_Q14[ 0 ] = tmp2; + n_AR_Q14 = silk_RSHIFT( shapingLPCOrder, 1 ); + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ 0 ] ); + /* Loop over allpass sections */ + for( j = 2; j < shapingLPCOrder; j += 2 ) { + /* Output of allpass section */ + tmp2 = silk_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 ); + psDD->sAR2_Q14[ j - 1 ] = tmp1; + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ j - 1 ] ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 ); + psDD->sAR2_Q14[ j + 0 ] = tmp2; + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ j ] ); + } + psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1; + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] ); + + n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 1 ); /* Q11 -> Q12 */ + n_AR_Q14 = silk_SMLAWB( n_AR_Q14, psDD->LF_AR_Q14, Tilt_Q14 ); /* Q12 */ + n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 2 ); /* Q12 -> Q14 */ + + n_LF_Q14 = silk_SMULWB( psDD->Shape_Q14[ *smpl_buf_idx ], LF_shp_Q14 ); /* Q12 */ + n_LF_Q14 = silk_SMLAWT( n_LF_Q14, psDD->LF_AR_Q14, LF_shp_Q14 ); /* Q12 */ + n_LF_Q14 = silk_LSHIFT( n_LF_Q14, 2 ); /* Q12 -> Q14 */ + + /* Input minus prediction plus noise feedback */ + /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */ + tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */ + tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */ + tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */ + tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */ + + r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */ + + /* Flip sign depending on dither */ + if ( psDD->Seed < 0 ) { + r_Q10 = -r_Q10; + } + r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 ); + + /* Find two quantization level candidates and measure their rate-distortion */ + q1_Q10 = silk_SUB32( r_Q10, offset_Q10 ); + q1_Q0 = silk_RSHIFT( q1_Q10, 10 ); + if( q1_Q0 > 0 ) { + q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = silk_ADD32( q1_Q10, 1024 ); + rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q0 == 0 ) { + q1_Q10 = offset_Q10; + q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else if( q1_Q0 == -1 ) { + q2_Q10 = offset_Q10; + q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 ); + rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 ); + } else { /* q1_Q0 < -1 */ + q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 ); + q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 ); + q2_Q10 = silk_ADD32( q1_Q10, 1024 ); + rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 ); + rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 ); + } + rr_Q10 = silk_SUB32( r_Q10, q1_Q10 ); + rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 ); + rr_Q10 = silk_SUB32( r_Q10, q2_Q10 ); + rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 ); + + if( rd1_Q10 < rd2_Q10 ) { + psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); + psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); + psSS[ 0 ].Q_Q10 = q1_Q10; + psSS[ 1 ].Q_Q10 = q2_Q10; + } else { + psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 ); + psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 ); + psSS[ 0 ].Q_Q10 = q2_Q10; + psSS[ 1 ].Q_Q10 = q1_Q10; + } + + /* Update states for best quantization */ + + /* Quantized excitation */ + exc_Q14 = silk_LSHIFT32( psSS[ 0 ].Q_Q10, 4 ); + if ( psDD->Seed < 0 ) { + exc_Q14 = -exc_Q14; + } + + /* Add predictions */ + LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); + xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); + + /* Update states */ + sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); + psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); + psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14; + psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14; + psSS[ 0 ].xq_Q14 = xq_Q14; + + /* Update states for second best quantization */ + + /* Quantized excitation */ + exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 ); + if ( psDD->Seed < 0 ) { + exc_Q14 = -exc_Q14; + } + + + /* Add predictions */ + LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 ); + xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 ); + + /* Update states */ + sLF_AR_shp_Q14 = silk_SUB32( xq_Q14, n_AR_Q14 ); + psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 ); + psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14; + psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14; + psSS[ 1 ].xq_Q14 = xq_Q14; + } + + *smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */ + last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */ + + /* Find winner */ + RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; + Winner_ind = 0; + for( k = 1; k < nStatesDelayedDecision; k++ ) { + if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10; + Winner_ind = k; + } + } + + /* Increase RD values of expired states */ + Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ]; + for( k = 0; k < nStatesDelayedDecision; k++ ) { + if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) { + psSampleState[ k ][ 0 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 0 ].RD_Q10, silk_int32_MAX >> 4 ); + psSampleState[ k ][ 1 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 1 ].RD_Q10, silk_int32_MAX >> 4 ); + silk_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 ); + } + } + + /* Find worst in first set and best in second set */ + RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10; + RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10; + RDmax_ind = 0; + RDmin_ind = 0; + for( k = 1; k < nStatesDelayedDecision; k++ ) { + /* find worst in first set */ + if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) { + RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10; + RDmax_ind = k; + } + /* find best in second set */ + if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) { + RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10; + RDmin_ind = k; + } + } + + /* Replace a state if best from second set outperforms worst in first set */ + if( RDmin_Q10 < RDmax_Q10 ) { + silk_memcpy( ( (opus_int32 *)&psDelDec[ RDmax_ind ] ) + i, + ( (opus_int32 *)&psDelDec[ RDmin_ind ] ) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) ); + silk_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) ); + } + + /* Write samples from winner to output and long-term filter states */ + psDD = &psDelDec[ Winner_ind ]; + if( subfr > 0 || i >= decisionDelay ) { + pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 ); + xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( + silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], delayedGain_Q10[ last_smple_idx ] ), 8 ) ); + NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q14[ last_smple_idx ]; + sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q15[ last_smple_idx ]; + } + NSQ->sLTP_shp_buf_idx++; + NSQ->sLTP_buf_idx++; + + /* Update states */ + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + psSS = &psSampleState[ k ][ 0 ]; + psDD->LF_AR_Q14 = psSS->LF_AR_Q14; + psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14; + psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14; + psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10; + psDD->Pred_Q15[ *smpl_buf_idx ] = silk_LSHIFT32( psSS->LPC_exc_Q14, 1 ); + psDD->Shape_Q14[ *smpl_buf_idx ] = psSS->sLTP_shp_Q14; + psDD->Seed = silk_ADD32_ovflw( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) ); + psDD->RandState[ *smpl_buf_idx ] = psDD->Seed; + psDD->RD_Q10 = psSS->RD_Q10; + } + delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10; + } + /* Update LPC states */ + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) ); + } + RESTORE_STACK; +} + +static OPUS_INLINE void silk_nsq_del_dec_scale_states( + const silk_encoder_state *psEncC, /* I Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */ + const opus_int32 x_Q3[], /* I Input in Q3 */ + opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */ + const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */ + opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */ + opus_int subfr, /* I Subframe number */ + opus_int nStatesDelayedDecision, /* I Number of del dec states */ + const opus_int LTP_scale_Q14, /* I LTP state scaling */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */ + const opus_int signal_type, /* I Signal type */ + const opus_int decisionDelay /* I Decision delay */ +) +{ + opus_int i, k, lag; + opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23; + NSQ_del_dec_struct *psDD; + + lag = pitchL[ subfr ]; + inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 ); + silk_assert( inv_gain_Q31 != 0 ); + + /* Calculate gain adjustment factor */ + if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { + gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 ); + } else { + gain_adj_Q16 = (opus_int32)1 << 16; + } + + /* Scale input */ + inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 ); + for( i = 0; i < psEncC->subfr_length; i++ ) { + x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 ); + } + + /* Save inverse gain */ + NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; + + /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */ + if( NSQ->rewhite_flag ) { + if( subfr == 0 ) { + /* Do LTP downscaling */ + inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 ); + } + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) { + silk_assert( i < MAX_FRAME_LENGTH ); + sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] ); + } + } + + /* Adjust for changing gain */ + if( gain_adj_Q16 != (opus_int32)1 << 16 ) { + /* Scale long-term shaping state */ + for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) { + NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] ); + } + + /* Scale long-term prediction state */ + if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) { + for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) { + sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] ); + } + } + + for( k = 0; k < nStatesDelayedDecision; k++ ) { + psDD = &psDelDec[ k ]; + + /* Scale scalar states */ + psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 ); + + /* Scale short-term prediction and shaping states */ + for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) { + psDD->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] ); + } + for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) { + psDD->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] ); + } + for( i = 0; i < DECISION_DELAY; i++ ) { + psDD->Pred_Q15[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Pred_Q15[ i ] ); + psDD->Shape_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q14[ i ] ); + } + } + } +} diff --git a/TelegramClient.Opus/opus/silk/PLC.c b/TelegramClient.Opus/opus/silk/PLC.c new file mode 100755 index 0000000..01f4001 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/PLC.c @@ -0,0 +1,423 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "stack_alloc.h" +#include "PLC.h" + +#define NB_ATT 2 +static const opus_int16 HARM_ATT_Q15[NB_ATT] = { 32440, 31130 }; /* 0.99, 0.95 */ +static const opus_int16 PLC_RAND_ATTENUATE_V_Q15[NB_ATT] = { 31130, 26214 }; /* 0.95, 0.8 */ +static const opus_int16 PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = { 32440, 29491 }; /* 0.99, 0.9 */ + +static OPUS_INLINE void silk_PLC_update( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl /* I/O Decoder control */ +); + +static OPUS_INLINE void silk_PLC_conceal( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 frame[] /* O LPC residual signal */ +); + + +void silk_PLC_Reset( + silk_decoder_state *psDec /* I/O Decoder state */ +) +{ + psDec->sPLC.pitchL_Q8 = silk_LSHIFT( psDec->frame_length, 8 - 1 ); + psDec->sPLC.prevGain_Q16[ 0 ] = SILK_FIX_CONST( 1, 16 ); + psDec->sPLC.prevGain_Q16[ 1 ] = SILK_FIX_CONST( 1, 16 ); + psDec->sPLC.subfr_length = 20; + psDec->sPLC.nb_subfr = 2; +} + +void silk_PLC( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 frame[], /* I/O signal */ + opus_int lost /* I Loss flag */ +) +{ + /* PLC control function */ + if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) { + silk_PLC_Reset( psDec ); + psDec->sPLC.fs_kHz = psDec->fs_kHz; + } + + if( lost ) { + /****************************/ + /* Generate Signal */ + /****************************/ + silk_PLC_conceal( psDec, psDecCtrl, frame ); + + psDec->lossCnt++; + } else { + /****************************/ + /* Update state */ + /****************************/ + silk_PLC_update( psDec, psDecCtrl ); + } +} + +/**************************************************/ +/* Update state of PLC */ +/**************************************************/ +static OPUS_INLINE void silk_PLC_update( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl /* I/O Decoder control */ +) +{ + opus_int32 LTP_Gain_Q14, temp_LTP_Gain_Q14; + opus_int i, j; + silk_PLC_struct *psPLC; + + psPLC = &psDec->sPLC; + + /* Update parameters used in case of packet loss */ + psDec->prevSignalType = psDec->indices.signalType; + LTP_Gain_Q14 = 0; + if( psDec->indices.signalType == TYPE_VOICED ) { + /* Find the parameters for the last subframe which contains a pitch pulse */ + for( j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; j++ ) { + if( j == psDec->nb_subfr ) { + break; + } + temp_LTP_Gain_Q14 = 0; + for( i = 0; i < LTP_ORDER; i++ ) { + temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[ ( psDec->nb_subfr - 1 - j ) * LTP_ORDER + i ]; + } + if( temp_LTP_Gain_Q14 > LTP_Gain_Q14 ) { + LTP_Gain_Q14 = temp_LTP_Gain_Q14; + silk_memcpy( psPLC->LTPCoef_Q14, + &psDecCtrl->LTPCoef_Q14[ silk_SMULBB( psDec->nb_subfr - 1 - j, LTP_ORDER ) ], + LTP_ORDER * sizeof( opus_int16 ) ); + + psPLC->pitchL_Q8 = silk_LSHIFT( psDecCtrl->pitchL[ psDec->nb_subfr - 1 - j ], 8 ); + } + } + + silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) ); + psPLC->LTPCoef_Q14[ LTP_ORDER / 2 ] = LTP_Gain_Q14; + + /* Limit LT coefs */ + if( LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14 ) { + opus_int scale_Q10; + opus_int32 tmp; + + tmp = silk_LSHIFT( V_PITCH_GAIN_START_MIN_Q14, 10 ); + scale_Q10 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) ); + for( i = 0; i < LTP_ORDER; i++ ) { + psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q10 ), 10 ); + } + } else if( LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14 ) { + opus_int scale_Q14; + opus_int32 tmp; + + tmp = silk_LSHIFT( V_PITCH_GAIN_START_MAX_Q14, 14 ); + scale_Q14 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) ); + for( i = 0; i < LTP_ORDER; i++ ) { + psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q14 ), 14 ); + } + } + } else { + psPLC->pitchL_Q8 = silk_LSHIFT( silk_SMULBB( psDec->fs_kHz, 18 ), 8 ); + silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 )); + } + + /* Save LPC coeficients */ + silk_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) ); + psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14; + + /* Save last two gains */ + silk_memcpy( psPLC->prevGain_Q16, &psDecCtrl->Gains_Q16[ psDec->nb_subfr - 2 ], 2 * sizeof( opus_int32 ) ); + + psPLC->subfr_length = psDec->subfr_length; + psPLC->nb_subfr = psDec->nb_subfr; +} + +static OPUS_INLINE void silk_PLC_conceal( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 frame[] /* O LPC residual signal */ +) +{ + opus_int i, j, k; + opus_int lag, idx, sLTP_buf_idx, shift1, shift2; + opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q30; + opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr; + opus_int32 LPC_pred_Q10, LTP_pred_Q12; + opus_int16 rand_scale_Q14; + opus_int16 *B_Q14, *exc_buf_ptr; + opus_int32 *sLPC_Q14_ptr; + VARDECL( opus_int16, exc_buf ); + opus_int16 A_Q12[ MAX_LPC_ORDER ]; + VARDECL( opus_int16, sLTP ); + VARDECL( opus_int32, sLTP_Q14 ); + silk_PLC_struct *psPLC = &psDec->sPLC; + opus_int32 prevGain_Q10[2]; + SAVE_STACK; + + ALLOC( exc_buf, 2*psPLC->subfr_length, opus_int16 ); + ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 ); + ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 ); + + prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6); + prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6); + + if( psDec->first_frame_after_reset ) { + silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) ); + } + + /* Find random noise component */ + /* Scale previous excitation signal */ + exc_buf_ptr = exc_buf; + for( k = 0; k < 2; k++ ) { + for( i = 0; i < psPLC->subfr_length; i++ ) { + exc_buf_ptr[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT( + silk_SMULWW( psDec->exc_Q14[ i + ( k + psPLC->nb_subfr - 2 ) * psPLC->subfr_length ], prevGain_Q10[ k ] ), 8 ) ); + } + exc_buf_ptr += psPLC->subfr_length; + } + /* Find the subframe with lowest energy of the last two and use that as random noise generator */ + silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psPLC->subfr_length ); + silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psPLC->subfr_length ], psPLC->subfr_length ); + + if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) { + /* First sub-frame has lowest energy */ + rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ]; + } else { + /* Second sub-frame has lowest energy */ + rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ]; + } + + /* Set up Gain to random noise component */ + B_Q14 = psPLC->LTPCoef_Q14; + rand_scale_Q14 = psPLC->randScale_Q14; + + /* Set up attenuation gains */ + harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; + if( psDec->prevSignalType == TYPE_VOICED ) { + rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; + } else { + rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ]; + } + + /* LPC concealment. Apply BWE to previous LPC */ + silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) ); + + /* Preload LPC coeficients to array on stack. Gives small performance gain */ + silk_memcpy( A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) ); + + /* First Lost frame */ + if( psDec->lossCnt == 0 ) { + rand_scale_Q14 = 1 << 14; + + /* Reduce random noise Gain for voiced frames */ + if( psDec->prevSignalType == TYPE_VOICED ) { + for( i = 0; i < LTP_ORDER; i++ ) { + rand_scale_Q14 -= B_Q14[ i ]; + } + rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */ + rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 ); + } else { + /* Reduce random noise for unvoiced frames with high LPC gain */ + opus_int32 invGain_Q30, down_scale_Q30; + + invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order ); + + down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 ); + down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 ); + down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES ); + + rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 ); + } + } + + rand_seed = psPLC->rand_seed; + lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); + sLTP_buf_idx = psDec->ltp_mem_length; + + /* Rewhiten LTP state */ + idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2; + silk_assert( idx > 0 ); + silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order ); + /* Scale LTP state */ + inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 ); + inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 ); + for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) { + sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] ); + } + + /***************************/ + /* LTP synthesis filtering */ + /***************************/ + for( k = 0; k < psDec->nb_subfr; k++ ) { + /* Set up pointer */ + pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + for( i = 0; i < psDec->subfr_length; i++ ) { + /* Unrolled loop */ + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LTP_pred_Q12 = 2; + LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); + LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); + LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); + LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); + LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); + pred_lag_ptr++; + + /* Generate LPC excitation */ + rand_seed = silk_RAND( rand_seed ); + idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK; + sLTP_Q14[ sLTP_buf_idx ] = silk_LSHIFT32( silk_SMLAWB( LTP_pred_Q12, rand_ptr[ idx ], rand_scale_Q14 ), 2 ); + sLTP_buf_idx++; + } + + /* Gradually reduce LTP gain */ + for( j = 0; j < LTP_ORDER; j++ ) { + B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 ); + } + /* Gradually reduce excitation gain */ + rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 ); + + /* Slowly increase pitch lag */ + psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 ); + psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) ); + lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 ); + } + + /***************************/ + /* LPC synthesis filtering */ + /***************************/ + sLPC_Q14_ptr = &sLTP_Q14[ psDec->ltp_mem_length - MAX_LPC_ORDER ]; + + /* Copy LPC state */ + silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) ); + + silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */ + for( i = 0; i < psDec->frame_length; i++ ) { + /* partly unrolled */ + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); + for( j = 10; j < psDec->LPC_order; j++ ) { + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] ); + } + + /* Add prediction to LPC excitation */ + sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 ); + + /* Scale with Gain */ + frame[ i ] = (opus_int16)silk_SAT16( silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], prevGain_Q10[ 1 ] ), 8 ) ) ); + } + + /* Save LPC state */ + silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); + + /**************************************/ + /* Update states */ + /**************************************/ + psPLC->rand_seed = rand_seed; + psPLC->randScale_Q14 = rand_scale_Q14; + for( i = 0; i < MAX_NB_SUBFR; i++ ) { + psDecCtrl->pitchL[ i ] = lag; + } + RESTORE_STACK; +} + +/* Glues concealed frames with new good received frames */ +void silk_PLC_glue_frames( + silk_decoder_state *psDec, /* I/O decoder state */ + opus_int16 frame[], /* I/O signal */ + opus_int length /* I length of signal */ +) +{ + opus_int i, energy_shift; + opus_int32 energy; + silk_PLC_struct *psPLC; + psPLC = &psDec->sPLC; + + if( psDec->lossCnt ) { + /* Calculate energy in concealed residual */ + silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, frame, length ); + + psPLC->last_frame_lost = 1; + } else { + if( psDec->sPLC.last_frame_lost ) { + /* Calculate residual in decoded signal if last frame was lost */ + silk_sum_sqr_shift( &energy, &energy_shift, frame, length ); + + /* Normalize energies */ + if( energy_shift > psPLC->conc_energy_shift ) { + psPLC->conc_energy = silk_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift ); + } else if( energy_shift < psPLC->conc_energy_shift ) { + energy = silk_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift ); + } + + /* Fade in the energy difference */ + if( energy > psPLC->conc_energy ) { + opus_int32 frac_Q24, LZ; + opus_int32 gain_Q16, slope_Q16; + + LZ = silk_CLZ32( psPLC->conc_energy ); + LZ = LZ - 1; + psPLC->conc_energy = silk_LSHIFT( psPLC->conc_energy, LZ ); + energy = silk_RSHIFT( energy, silk_max_32( 24 - LZ, 0 ) ); + + frac_Q24 = silk_DIV32( psPLC->conc_energy, silk_max( energy, 1 ) ); + + gain_Q16 = silk_LSHIFT( silk_SQRT_APPROX( frac_Q24 ), 4 ); + slope_Q16 = silk_DIV32_16( ( (opus_int32)1 << 16 ) - gain_Q16, length ); + /* Make slope 4x steeper to avoid missing onsets after DTX */ + slope_Q16 = silk_LSHIFT( slope_Q16, 2 ); + + for( i = 0; i < length; i++ ) { + frame[ i ] = silk_SMULWB( gain_Q16, frame[ i ] ); + gain_Q16 += slope_Q16; + if( gain_Q16 > (opus_int32)1 << 16 ) { + break; + } + } + } + } + psPLC->last_frame_lost = 0; + } +} diff --git a/TelegramClient.Opus/opus/silk/PLC.h b/TelegramClient.Opus/opus/silk/PLC.h new file mode 100755 index 0000000..f1e2ecc --- /dev/null +++ b/TelegramClient.Opus/opus/silk/PLC.h @@ -0,0 +1,61 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_PLC_H +#define SILK_PLC_H + +#include "main.h" + +#define BWE_COEF 0.99 +#define V_PITCH_GAIN_START_MIN_Q14 11469 /* 0.7 in Q14 */ +#define V_PITCH_GAIN_START_MAX_Q14 15565 /* 0.95 in Q14 */ +#define MAX_PITCH_LAG_MS 18 +#define RAND_BUF_SIZE 128 +#define RAND_BUF_MASK ( RAND_BUF_SIZE - 1 ) +#define LOG2_INV_LPC_GAIN_HIGH_THRES 3 /* 2^3 = 8 dB LPC gain */ +#define LOG2_INV_LPC_GAIN_LOW_THRES 8 /* 2^8 = 24 dB LPC gain */ +#define PITCH_DRIFT_FAC_Q16 655 /* 0.01 in Q16 */ + +void silk_PLC_Reset( + silk_decoder_state *psDec /* I/O Decoder state */ +); + +void silk_PLC( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 frame[], /* I/O signal */ + opus_int lost /* I Loss flag */ +); + +void silk_PLC_glue_frames( + silk_decoder_state *psDec, /* I/O decoder state */ + opus_int16 frame[], /* I/O signal */ + opus_int length /* I length of signal */ +); + +#endif + diff --git a/TelegramClient.Opus/opus/silk/SigProc_FIX.h b/TelegramClient.Opus/opus/silk/SigProc_FIX.h new file mode 100755 index 0000000..1b58057 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/SigProc_FIX.h @@ -0,0 +1,594 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_SIGPROC_FIX_H +#define SILK_SIGPROC_FIX_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*#define silk_MACRO_COUNT */ /* Used to enable WMOPS counting */ + +#define SILK_MAX_ORDER_LPC 16 /* max order of the LPC analysis in schur() and k2a() */ + +#include /* for memset(), memcpy(), memmove() */ +#include "typedef.h" +#include "resampler_structs.h" +#include "macros.h" + + +/********************************************************************/ +/* SIGNAL PROCESSING FUNCTIONS */ +/********************************************************************/ + +/*! + * Initialize/reset the resampler state for a given pair of input/output sampling rates +*/ +opus_int silk_resampler_init( + silk_resampler_state_struct *S, /* I/O Resampler state */ + opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */ + opus_int32 Fs_Hz_out, /* I Output sampling rate (Hz) */ + opus_int forEnc /* I If 1: encoder; if 0: decoder */ +); + +/*! + * Resampler: convert from one sampling rate to another + */ +opus_int silk_resampler( + silk_resampler_state_struct *S, /* I/O Resampler state */ + opus_int16 out[], /* O Output signal */ + const opus_int16 in[], /* I Input signal */ + opus_int32 inLen /* I Number of input samples */ +); + +/*! +* Downsample 2x, mediocre quality +*/ +void silk_resampler_down2( + opus_int32 *S, /* I/O State vector [ 2 ] */ + opus_int16 *out, /* O Output signal [ len ] */ + const opus_int16 *in, /* I Input signal [ floor(len/2) ] */ + opus_int32 inLen /* I Number of input samples */ +); + +/*! + * Downsample by a factor 2/3, low quality +*/ +void silk_resampler_down2_3( + opus_int32 *S, /* I/O State vector [ 6 ] */ + opus_int16 *out, /* O Output signal [ floor(2*inLen/3) ] */ + const opus_int16 *in, /* I Input signal [ inLen ] */ + opus_int32 inLen /* I Number of input samples */ +); + +/*! + * second order ARMA filter; + * slower than biquad() but uses more precise coefficients + * can handle (slowly) varying coefficients + */ +void silk_biquad_alt( + const opus_int16 *in, /* I input signal */ + const opus_int32 *B_Q28, /* I MA coefficients [3] */ + const opus_int32 *A_Q28, /* I AR coefficients [2] */ + opus_int32 *S, /* I/O State vector [2] */ + opus_int16 *out, /* O output signal */ + const opus_int32 len, /* I signal length (must be even) */ + opus_int stride /* I Operate on interleaved signal if > 1 */ +); + +/* Variable order MA prediction error filter. */ +void silk_LPC_analysis_filter( + opus_int16 *out, /* O Output signal */ + const opus_int16 *in, /* I Input signal */ + const opus_int16 *B, /* I MA prediction coefficients, Q12 [order] */ + const opus_int32 len, /* I Signal length */ + const opus_int32 d /* I Filter order */ +); + +/* Chirp (bandwidth expand) LP AR filter */ +void silk_bwexpander( + opus_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */ + const opus_int d, /* I Length of ar */ + opus_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */ +); + +/* Chirp (bandwidth expand) LP AR filter */ +void silk_bwexpander_32( + opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */ + const opus_int d, /* I Length of ar */ + opus_int32 chirp_Q16 /* I Chirp factor in Q16 */ +); + +/* Compute inverse of LPC prediction gain, and */ +/* test if LPC coefficients are stable (all poles within unit circle) */ +opus_int32 silk_LPC_inverse_pred_gain( /* O Returns inverse prediction gain in energy domain, Q30 */ + const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */ + const opus_int order /* I Prediction order */ +); + +/* For input in Q24 domain */ +opus_int32 silk_LPC_inverse_pred_gain_Q24( /* O Returns inverse prediction gain in energy domain, Q30 */ + const opus_int32 *A_Q24, /* I Prediction coefficients [order] */ + const opus_int order /* I Prediction order */ +); + +/* Split signal in two decimated bands using first-order allpass filters */ +void silk_ana_filt_bank_1( + const opus_int16 *in, /* I Input signal [N] */ + opus_int32 *S, /* I/O State vector [2] */ + opus_int16 *outL, /* O Low band [N/2] */ + opus_int16 *outH, /* O High band [N/2] */ + const opus_int32 N /* I Number of input samples */ +); + +/********************************************************************/ +/* SCALAR FUNCTIONS */ +/********************************************************************/ + +/* Approximation of 128 * log2() (exact inverse of approx 2^() below) */ +/* Convert input to a log scale */ +opus_int32 silk_lin2log( + const opus_int32 inLin /* I input in linear scale */ +); + +/* Approximation of a sigmoid function */ +opus_int silk_sigm_Q15( + opus_int in_Q5 /* I */ +); + +/* Approximation of 2^() (exact inverse of approx log2() above) */ +/* Convert input to a linear scale */ +opus_int32 silk_log2lin( + const opus_int32 inLog_Q7 /* I input on log scale */ +); + +/* Compute number of bits to right shift the sum of squares of a vector */ +/* of int16s to make it fit in an int32 */ +void silk_sum_sqr_shift( + opus_int32 *energy, /* O Energy of x, after shifting to the right */ + opus_int *shift, /* O Number of bits right shift applied to energy */ + const opus_int16 *x, /* I Input vector */ + opus_int len /* I Length of input vector */ +); + +/* Calculates the reflection coefficients from the correlation sequence */ +/* Faster than schur64(), but much less accurate. */ +/* uses SMLAWB(), requiring armv5E and higher. */ +opus_int32 silk_schur( /* O Returns residual energy */ + opus_int16 *rc_Q15, /* O reflection coefficients [order] Q15 */ + const opus_int32 *c, /* I correlations [order+1] */ + const opus_int32 order /* I prediction order */ +); + +/* Calculates the reflection coefficients from the correlation sequence */ +/* Slower than schur(), but more accurate. */ +/* Uses SMULL(), available on armv4 */ +opus_int32 silk_schur64( /* O returns residual energy */ + opus_int32 rc_Q16[], /* O Reflection coefficients [order] Q16 */ + const opus_int32 c[], /* I Correlations [order+1] */ + opus_int32 order /* I Prediction order */ +); + +/* Step up function, converts reflection coefficients to prediction coefficients */ +void silk_k2a( + opus_int32 *A_Q24, /* O Prediction coefficients [order] Q24 */ + const opus_int16 *rc_Q15, /* I Reflection coefficients [order] Q15 */ + const opus_int32 order /* I Prediction order */ +); + +/* Step up function, converts reflection coefficients to prediction coefficients */ +void silk_k2a_Q16( + opus_int32 *A_Q24, /* O Prediction coefficients [order] Q24 */ + const opus_int32 *rc_Q16, /* I Reflection coefficients [order] Q16 */ + const opus_int32 order /* I Prediction order */ +); + +/* Apply sine window to signal vector. */ +/* Window types: */ +/* 1 -> sine window from 0 to pi/2 */ +/* 2 -> sine window from pi/2 to pi */ +/* every other sample of window is linearly interpolated, for speed */ +void silk_apply_sine_window( + opus_int16 px_win[], /* O Pointer to windowed signal */ + const opus_int16 px[], /* I Pointer to input signal */ + const opus_int win_type, /* I Selects a window type */ + const opus_int length /* I Window length, multiple of 4 */ +); + +/* Compute autocorrelation */ +void silk_autocorr( + opus_int32 *results, /* O Result (length correlationCount) */ + opus_int *scale, /* O Scaling of the correlation vector */ + const opus_int16 *inputData, /* I Input data to correlate */ + const opus_int inputDataSize, /* I Length of input */ + const opus_int correlationCount, /* I Number of correlation taps to compute */ + int arch /* I Run-time architecture */ +); + +void silk_decode_pitch( + opus_int16 lagIndex, /* I */ + opus_int8 contourIndex, /* O */ + opus_int pitch_lags[], /* O 4 pitch values */ + const opus_int Fs_kHz, /* I sampling frequency (kHz) */ + const opus_int nb_subfr /* I number of sub frames */ +); + +opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */ + const opus_int16 *frame, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */ + opus_int *pitch_out, /* O 4 pitch lag values */ + opus_int16 *lagIndex, /* O Lag Index */ + opus_int8 *contourIndex, /* O Pitch contour Index */ + opus_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */ + opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */ + const opus_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */ + const opus_int search_thres2_Q13, /* I Final threshold for lag candidates 0 - 1 */ + const opus_int Fs_kHz, /* I Sample frequency (kHz) */ + const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */ + const opus_int nb_subfr, /* I number of 5 ms subframes */ + int arch /* I Run-time architecture */ +); + +/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */ +/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */ +void silk_A2NLSF( + opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */ + opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */ + const opus_int d /* I Filter order (must be even) */ +); + +/* compute whitening filter coefficients from normalized line spectral frequencies */ +void silk_NLSF2A( + opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */ + const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */ + const opus_int d /* I filter order (should be even) */ +); + +void silk_insertion_sort_increasing( + opus_int32 *a, /* I/O Unsorted / Sorted vector */ + opus_int *idx, /* O Index vector for the sorted elements */ + const opus_int L, /* I Vector length */ + const opus_int K /* I Number of correctly sorted positions */ +); + +void silk_insertion_sort_decreasing_int16( + opus_int16 *a, /* I/O Unsorted / Sorted vector */ + opus_int *idx, /* O Index vector for the sorted elements */ + const opus_int L, /* I Vector length */ + const opus_int K /* I Number of correctly sorted positions */ +); + +void silk_insertion_sort_increasing_all_values_int16( + opus_int16 *a, /* I/O Unsorted / Sorted vector */ + const opus_int L /* I Vector length */ +); + +/* NLSF stabilizer, for a single input data vector */ +void silk_NLSF_stabilize( + opus_int16 *NLSF_Q15, /* I/O Unstable/stabilized normalized LSF vector in Q15 [L] */ + const opus_int16 *NDeltaMin_Q15, /* I Min distance vector, NDeltaMin_Q15[L] must be >= 1 [L+1] */ + const opus_int L /* I Number of NLSF parameters in the input vector */ +); + +/* Laroia low complexity NLSF weights */ +void silk_NLSF_VQ_weights_laroia( + opus_int16 *pNLSFW_Q_OUT, /* O Pointer to input vector weights [D] */ + const opus_int16 *pNLSF_Q15, /* I Pointer to input vector [D] */ + const opus_int D /* I Input vector dimension (even) */ +); + +/* Compute reflection coefficients from input signal */ +void silk_burg_modified( + opus_int32 *res_nrg, /* O Residual energy */ + opus_int *res_nrg_Q, /* O Residual energy Q value */ + opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ + const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */ + const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */ + const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */ + const opus_int nb_subfr, /* I Number of subframes stacked in x */ + const opus_int D, /* I Order */ + int arch /* I Run-time architecture */ +); + +/* Copy and multiply a vector by a constant */ +void silk_scale_copy_vector16( + opus_int16 *data_out, + const opus_int16 *data_in, + opus_int32 gain_Q16, /* I Gain in Q16 */ + const opus_int dataSize /* I Length */ +); + +/* Some for the LTP related function requires Q26 to work.*/ +void silk_scale_vector32_Q26_lshift_18( + opus_int32 *data1, /* I/O Q0/Q18 */ + opus_int32 gain_Q26, /* I Q26 */ + opus_int dataSize /* I length */ +); + +/********************************************************************/ +/* INLINE ARM MATH */ +/********************************************************************/ + +/* return sum( inVec1[i] * inVec2[i] ) */ +opus_int32 silk_inner_prod_aligned( + const opus_int16 *const inVec1, /* I input vector 1 */ + const opus_int16 *const inVec2, /* I input vector 2 */ + const opus_int len /* I vector lengths */ +); + +opus_int32 silk_inner_prod_aligned_scale( + const opus_int16 *const inVec1, /* I input vector 1 */ + const opus_int16 *const inVec2, /* I input vector 2 */ + const opus_int scale, /* I number of bits to shift */ + const opus_int len /* I vector lengths */ +); + +opus_int64 silk_inner_prod16_aligned_64( + const opus_int16 *inVec1, /* I input vector 1 */ + const opus_int16 *inVec2, /* I input vector 2 */ + const opus_int len /* I vector lengths */ +); + +/********************************************************************/ +/* MACROS */ +/********************************************************************/ + +/* Rotate a32 right by 'rot' bits. Negative rot values result in rotating + left. Output is 32bit int. + Note: contemporary compilers recognize the C expression below and + compile it into a 'ror' instruction if available. No need for OPUS_INLINE ASM! */ +static OPUS_INLINE opus_int32 silk_ROR32( opus_int32 a32, opus_int rot ) +{ + opus_uint32 x = (opus_uint32) a32; + opus_uint32 r = (opus_uint32) rot; + opus_uint32 m = (opus_uint32) -rot; + if( rot == 0 ) { + return a32; + } else if( rot < 0 ) { + return (opus_int32) ((x << m) | (x >> (32 - m))); + } else { + return (opus_int32) ((x << (32 - r)) | (x >> r)); + } +} + +/* Allocate opus_int16 aligned to 4-byte memory address */ +#if EMBEDDED_ARM +#define silk_DWORD_ALIGN __attribute__((aligned(4))) +#else +#define silk_DWORD_ALIGN +#endif + +/* Useful Macros that can be adjusted to other platforms */ +#define silk_memcpy(dest, src, size) memcpy((dest), (src), (size)) +#define silk_memset(dest, src, size) memset((dest), (src), (size)) +#define silk_memmove(dest, src, size) memmove((dest), (src), (size)) + +/* Fixed point macros */ + +/* (a32 * b32) output have to be 32bit int */ +#define silk_MUL(a32, b32) ((a32) * (b32)) + +/* (a32 * b32) output have to be 32bit uint */ +#define silk_MUL_uint(a32, b32) silk_MUL(a32, b32) + +/* a32 + (b32 * c32) output have to be 32bit int */ +#define silk_MLA(a32, b32, c32) silk_ADD32((a32),((b32) * (c32))) + +/* a32 + (b32 * c32) output have to be 32bit uint */ +#define silk_MLA_uint(a32, b32, c32) silk_MLA(a32, b32, c32) + +/* ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int */ +#define silk_SMULTT(a32, b32) (((a32) >> 16) * ((b32) >> 16)) + +/* a32 + ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int */ +#define silk_SMLATT(a32, b32, c32) silk_ADD32((a32),((b32) >> 16) * ((c32) >> 16)) + +#define silk_SMLALBB(a64, b16, c16) silk_ADD64((a64),(opus_int64)((opus_int32)(b16) * (opus_int32)(c16))) + +/* (a32 * b32) */ +#define silk_SMULL(a32, b32) ((opus_int64)(a32) * /*(opus_int64)*/(b32)) + +/* Adds two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour + (just standard two's complement implementation-specific behaviour) */ +#define silk_ADD32_ovflw(a, b) ((opus_int32)((opus_uint32)(a) + (opus_uint32)(b))) +/* Subtractss two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour + (just standard two's complement implementation-specific behaviour) */ +#define silk_SUB32_ovflw(a, b) ((opus_int32)((opus_uint32)(a) - (opus_uint32)(b))) + +/* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) */ +#define silk_MLA_ovflw(a32, b32, c32) silk_ADD32_ovflw((a32), (opus_uint32)(b32) * (opus_uint32)(c32)) +#define silk_SMLABB_ovflw(a32, b32, c32) (silk_ADD32_ovflw((a32) , ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32)))) + +#define silk_DIV32_16(a32, b16) ((opus_int32)((a32) / (b16))) +#define silk_DIV32(a32, b32) ((opus_int32)((a32) / (b32))) + +/* These macros enables checking for overflow in silk_API_Debug.h*/ +#define silk_ADD16(a, b) ((a) + (b)) +#define silk_ADD32(a, b) ((a) + (b)) +#define silk_ADD64(a, b) ((a) + (b)) + +#define silk_SUB16(a, b) ((a) - (b)) +#define silk_SUB32(a, b) ((a) - (b)) +#define silk_SUB64(a, b) ((a) - (b)) + +#define silk_SAT8(a) ((a) > silk_int8_MAX ? silk_int8_MAX : \ + ((a) < silk_int8_MIN ? silk_int8_MIN : (a))) +#define silk_SAT16(a) ((a) > silk_int16_MAX ? silk_int16_MAX : \ + ((a) < silk_int16_MIN ? silk_int16_MIN : (a))) +#define silk_SAT32(a) ((a) > silk_int32_MAX ? silk_int32_MAX : \ + ((a) < silk_int32_MIN ? silk_int32_MIN : (a))) + +#define silk_CHECK_FIT8(a) (a) +#define silk_CHECK_FIT16(a) (a) +#define silk_CHECK_FIT32(a) (a) + +#define silk_ADD_SAT16(a, b) (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a), (b) ) ) +#define silk_ADD_SAT64(a, b) ((((a) + (b)) & 0x8000000000000000LL) == 0 ? \ + ((((a) & (b)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a)+(b)) : \ + ((((a) | (b)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a)+(b)) ) + +#define silk_SUB_SAT16(a, b) (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a), (b) ) ) +#define silk_SUB_SAT64(a, b) ((((a)-(b)) & 0x8000000000000000LL) == 0 ? \ + (( (a) & ((b)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a)-(b)) : \ + ((((a)^0x8000000000000000LL) & (b) & 0x8000000000000000LL) ? silk_int64_MAX : (a)-(b)) ) + +/* Saturation for positive input values */ +#define silk_POS_SAT32(a) ((a) > silk_int32_MAX ? silk_int32_MAX : (a)) + +/* Add with saturation for positive input values */ +#define silk_ADD_POS_SAT8(a, b) ((((a)+(b)) & 0x80) ? silk_int8_MAX : ((a)+(b))) +#define silk_ADD_POS_SAT16(a, b) ((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b))) +#define silk_ADD_POS_SAT32(a, b) ((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b))) +#define silk_ADD_POS_SAT64(a, b) ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b))) + +#define silk_LSHIFT8(a, shift) ((opus_int8)((opus_uint8)(a)<<(shift))) /* shift >= 0, shift < 8 */ +#define silk_LSHIFT16(a, shift) ((opus_int16)((opus_uint16)(a)<<(shift))) /* shift >= 0, shift < 16 */ +#define silk_LSHIFT32(a, shift) ((opus_int32)((opus_uint32)(a)<<(shift))) /* shift >= 0, shift < 32 */ +#define silk_LSHIFT64(a, shift) ((opus_int64)((opus_uint64)(a)<<(shift))) /* shift >= 0, shift < 64 */ +#define silk_LSHIFT(a, shift) silk_LSHIFT32(a, shift) /* shift >= 0, shift < 32 */ + +#define silk_RSHIFT8(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 8 */ +#define silk_RSHIFT16(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 16 */ +#define silk_RSHIFT32(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 32 */ +#define silk_RSHIFT64(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 64 */ +#define silk_RSHIFT(a, shift) silk_RSHIFT32(a, shift) /* shift >= 0, shift < 32 */ + +/* saturates before shifting */ +#define silk_LSHIFT_SAT32(a, shift) (silk_LSHIFT32( silk_LIMIT( (a), silk_RSHIFT32( silk_int32_MIN, (shift) ), \ + silk_RSHIFT32( silk_int32_MAX, (shift) ) ), (shift) )) + +#define silk_LSHIFT_ovflw(a, shift) ((opus_int32)((opus_uint32)(a) << (shift))) /* shift >= 0, allowed to overflow */ +#define silk_LSHIFT_uint(a, shift) ((a) << (shift)) /* shift >= 0 */ +#define silk_RSHIFT_uint(a, shift) ((a) >> (shift)) /* shift >= 0 */ + +#define silk_ADD_LSHIFT(a, b, shift) ((a) + silk_LSHIFT((b), (shift))) /* shift >= 0 */ +#define silk_ADD_LSHIFT32(a, b, shift) silk_ADD32((a), silk_LSHIFT32((b), (shift))) /* shift >= 0 */ +#define silk_ADD_LSHIFT_uint(a, b, shift) ((a) + silk_LSHIFT_uint((b), (shift))) /* shift >= 0 */ +#define silk_ADD_RSHIFT(a, b, shift) ((a) + silk_RSHIFT((b), (shift))) /* shift >= 0 */ +#define silk_ADD_RSHIFT32(a, b, shift) silk_ADD32((a), silk_RSHIFT32((b), (shift))) /* shift >= 0 */ +#define silk_ADD_RSHIFT_uint(a, b, shift) ((a) + silk_RSHIFT_uint((b), (shift))) /* shift >= 0 */ +#define silk_SUB_LSHIFT32(a, b, shift) silk_SUB32((a), silk_LSHIFT32((b), (shift))) /* shift >= 0 */ +#define silk_SUB_RSHIFT32(a, b, shift) silk_SUB32((a), silk_RSHIFT32((b), (shift))) /* shift >= 0 */ + +/* Requires that shift > 0 */ +#define silk_RSHIFT_ROUND(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1) +#define silk_RSHIFT_ROUND64(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1) + +/* Number of rightshift required to fit the multiplication */ +#define silk_NSHIFT_MUL_32_32(a, b) ( -(31- (32-silk_CLZ32(silk_abs(a)) + (32-silk_CLZ32(silk_abs(b))))) ) +#define silk_NSHIFT_MUL_16_16(a, b) ( -(15- (16-silk_CLZ16(silk_abs(a)) + (16-silk_CLZ16(silk_abs(b))))) ) + + +#define silk_min(a, b) (((a) < (b)) ? (a) : (b)) +#define silk_max(a, b) (((a) > (b)) ? (a) : (b)) + +/* Macro to convert floating-point constants to fixed-point */ +#define SILK_FIX_CONST( C, Q ) ((opus_int32)((C) * ((opus_int64)1 << (Q)) + 0.5)) + +/* silk_min() versions with typecast in the function call */ +static OPUS_INLINE opus_int silk_min_int(opus_int a, opus_int b) +{ + return (((a) < (b)) ? (a) : (b)); +} +static OPUS_INLINE opus_int16 silk_min_16(opus_int16 a, opus_int16 b) +{ + return (((a) < (b)) ? (a) : (b)); +} +static OPUS_INLINE opus_int32 silk_min_32(opus_int32 a, opus_int32 b) +{ + return (((a) < (b)) ? (a) : (b)); +} +static OPUS_INLINE opus_int64 silk_min_64(opus_int64 a, opus_int64 b) +{ + return (((a) < (b)) ? (a) : (b)); +} + +/* silk_min() versions with typecast in the function call */ +static OPUS_INLINE opus_int silk_max_int(opus_int a, opus_int b) +{ + return (((a) > (b)) ? (a) : (b)); +} +static OPUS_INLINE opus_int16 silk_max_16(opus_int16 a, opus_int16 b) +{ + return (((a) > (b)) ? (a) : (b)); +} +static OPUS_INLINE opus_int32 silk_max_32(opus_int32 a, opus_int32 b) +{ + return (((a) > (b)) ? (a) : (b)); +} +static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b) +{ + return (((a) > (b)) ? (a) : (b)); +} + +#define silk_LIMIT( a, limit1, limit2) ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \ + : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a)))) + +#define silk_LIMIT_int silk_LIMIT +#define silk_LIMIT_16 silk_LIMIT +#define silk_LIMIT_32 silk_LIMIT + +#define silk_abs(a) (((a) > 0) ? (a) : -(a)) /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */ +#define silk_abs_int(a) (((a) ^ ((a) >> (8 * sizeof(a) - 1))) - ((a) >> (8 * sizeof(a) - 1))) +#define silk_abs_int32(a) (((a) ^ ((a) >> 31)) - ((a) >> 31)) +#define silk_abs_int64(a) (((a) > 0) ? (a) : -(a)) + +#define silk_sign(a) ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 )) + +/* PSEUDO-RANDOM GENERATOR */ +/* Make sure to store the result as the seed for the next call (also in between */ +/* frames), otherwise result won't be random at all. When only using some of the */ +/* bits, take the most significant bits by right-shifting. */ +#define silk_RAND(seed) (silk_MLA_ovflw(907633515, (seed), 196314165)) + +/* Add some multiplication functions that can be easily mapped to ARM. */ + +/* silk_SMMUL: Signed top word multiply. + ARMv6 2 instruction cycles. + ARMv3M+ 3 instruction cycles. use SMULL and ignore LSB registers.(except xM)*/ +/*#define silk_SMMUL(a32, b32) (opus_int32)silk_RSHIFT(silk_SMLAL(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16)), 16)*/ +/* the following seems faster on x86 */ +#define silk_SMMUL(a32, b32) (opus_int32)silk_RSHIFT64(silk_SMULL((a32), (b32)), 32) + +#include "Inlines.h" +#include "MacroCount.h" +#include "MacroDebug.h" + +#ifdef OPUS_ARM_INLINE_ASM +#include "arm/SigProc_FIX_armv4.h" +#endif + +#ifdef OPUS_ARM_INLINE_EDSP +#include "arm/SigProc_FIX_armv5e.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SILK_SIGPROC_FIX_H */ diff --git a/TelegramClient.Opus/opus/silk/VAD.c b/TelegramClient.Opus/opus/silk/VAD.c new file mode 100755 index 0000000..a809098 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/VAD.c @@ -0,0 +1,357 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "stack_alloc.h" + +/* Silk VAD noise level estimation */ +static OPUS_INLINE void silk_VAD_GetNoiseLevels( + const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */ + silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ +); + +/**********************************/ +/* Initialization of the Silk VAD */ +/**********************************/ +opus_int silk_VAD_Init( /* O Return value, 0 if success */ + silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ +) +{ + opus_int b, ret = 0; + + /* reset state memory */ + silk_memset( psSilk_VAD, 0, sizeof( silk_VAD_state ) ); + + /* init noise levels */ + /* Initialize array with approx pink noise levels (psd proportional to inverse of frequency) */ + for( b = 0; b < VAD_N_BANDS; b++ ) { + psSilk_VAD->NoiseLevelBias[ b ] = silk_max_32( silk_DIV32_16( VAD_NOISE_LEVELS_BIAS, b + 1 ), 1 ); + } + + /* Initialize state */ + for( b = 0; b < VAD_N_BANDS; b++ ) { + psSilk_VAD->NL[ b ] = silk_MUL( 100, psSilk_VAD->NoiseLevelBias[ b ] ); + psSilk_VAD->inv_NL[ b ] = silk_DIV32( silk_int32_MAX, psSilk_VAD->NL[ b ] ); + } + psSilk_VAD->counter = 15; + + /* init smoothed energy-to-noise ratio*/ + for( b = 0; b < VAD_N_BANDS; b++ ) { + psSilk_VAD->NrgRatioSmth_Q8[ b ] = 100 * 256; /* 100 * 256 --> 20 dB SNR */ + } + + return( ret ); +} + +/* Weighting factors for tilt measure */ +static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 }; + +/***************************************/ +/* Get the speech activity level in Q8 */ +/***************************************/ +opus_int silk_VAD_GetSA_Q8( /* O Return value, 0 if success */ + silk_encoder_state *psEncC, /* I/O Encoder state */ + const opus_int16 pIn[] /* I PCM input */ +) +{ + opus_int SA_Q15, pSNR_dB_Q7, input_tilt; + opus_int decimated_framelength1, decimated_framelength2; + opus_int decimated_framelength; + opus_int dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s; + opus_int32 sumSquared, smooth_coef_Q16; + opus_int16 HPstateTmp; + VARDECL( opus_int16, X ); + opus_int32 Xnrg[ VAD_N_BANDS ]; + opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ]; + opus_int32 speech_nrg, x_tmp; + opus_int X_offset[ VAD_N_BANDS ]; + opus_int ret = 0; + silk_VAD_state *psSilk_VAD = &psEncC->sVAD; + SAVE_STACK; + + /* Safety checks */ + silk_assert( VAD_N_BANDS == 4 ); + silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length ); + silk_assert( psEncC->frame_length <= 512 ); + silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) ); + + /***********************/ + /* Filter and Decimate */ + /***********************/ + decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 ); + decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 ); + decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 ); + /* Decimate into 4 bands: + 0 L 3L L 3L 5L + - -- - -- -- + 8 8 2 4 4 + + [0-1 kHz| temp. |1-2 kHz| 2-4 kHz | 4-8 kHz | + + They're arranged to allow the minimal ( frame_length / 4 ) extra + scratch space during the downsampling process */ + X_offset[ 0 ] = 0; + X_offset[ 1 ] = decimated_framelength + decimated_framelength2; + X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength; + X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2; + ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 ); + + /* 0-8 kHz to 0-4 kHz and 4-8 kHz */ + silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], + X, &X[ X_offset[ 3 ] ], psEncC->frame_length ); + + /* 0-4 kHz to 0-2 kHz and 2-4 kHz */ + silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ], + X, &X[ X_offset[ 2 ] ], decimated_framelength1 ); + + /* 0-2 kHz to 0-1 kHz and 1-2 kHz */ + silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ], + X, &X[ X_offset[ 1 ] ], decimated_framelength2 ); + + /*********************************************/ + /* HP filter on lowest band (differentiator) */ + /*********************************************/ + X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 ); + HPstateTmp = X[ decimated_framelength - 1 ]; + for( i = decimated_framelength - 1; i > 0; i-- ) { + X[ i - 1 ] = silk_RSHIFT( X[ i - 1 ], 1 ); + X[ i ] -= X[ i - 1 ]; + } + X[ 0 ] -= psSilk_VAD->HPstate; + psSilk_VAD->HPstate = HPstateTmp; + + /*************************************/ + /* Calculate the energy in each band */ + /*************************************/ + for( b = 0; b < VAD_N_BANDS; b++ ) { + /* Find the decimated framelength in the non-uniformly divided bands */ + decimated_framelength = silk_RSHIFT( psEncC->frame_length, silk_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) ); + + /* Split length into subframe lengths */ + dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 ); + dec_subframe_offset = 0; + + /* Compute energy per sub-frame */ + /* initialize with summed energy of last subframe */ + Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ]; + for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) { + sumSquared = 0; + for( i = 0; i < dec_subframe_length; i++ ) { + /* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2. */ + /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */ + x_tmp = silk_RSHIFT( + X[ X_offset[ b ] + i + dec_subframe_offset ], 3 ); + sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp ); + + /* Safety check */ + silk_assert( sumSquared >= 0 ); + } + + /* Add/saturate summed energy of current subframe */ + if( s < VAD_INTERNAL_SUBFRAMES - 1 ) { + Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared ); + } else { + /* Look-ahead subframe */ + Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) ); + } + + dec_subframe_offset += dec_subframe_length; + } + psSilk_VAD->XnrgSubfr[ b ] = sumSquared; + } + + /********************/ + /* Noise estimation */ + /********************/ + silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD ); + + /***********************************************/ + /* Signal-plus-noise to noise ratio estimation */ + /***********************************************/ + sumSquared = 0; + input_tilt = 0; + for( b = 0; b < VAD_N_BANDS; b++ ) { + speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ]; + if( speech_nrg > 0 ) { + /* Divide, with sufficient resolution */ + if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) { + NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 ); + } else { + NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 ); + } + + /* Convert to log domain */ + SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128; + + /* Sum-of-squares */ + sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */ + + /* Tilt measure */ + if( speech_nrg < ( (opus_int32)1 << 20 ) ) { + /* Scale down SNR value for small subband speech energies */ + SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 ); + } + input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 ); + } else { + NrgToNoiseRatio_Q8[ b ] = 256; + } + } + + /* Mean-of-squares */ + sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */ + + /* Root-mean-square approximation, scale to dBs, and write to output pointer */ + pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */ + + /*********************************/ + /* Speech Probability Estimation */ + /*********************************/ + SA_Q15 = silk_sigm_Q15( silk_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 ); + + /**************************/ + /* Frequency Tilt Measure */ + /**************************/ + psEncC->input_tilt_Q15 = silk_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 ); + + /**************************************************/ + /* Scale the sigmoid output based on power levels */ + /**************************************************/ + speech_nrg = 0; + for( b = 0; b < VAD_N_BANDS; b++ ) { + /* Accumulate signal-without-noise energies, higher frequency bands have more weight */ + speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 ); + } + + /* Power scaling */ + if( speech_nrg <= 0 ) { + SA_Q15 = silk_RSHIFT( SA_Q15, 1 ); + } else if( speech_nrg < 32768 ) { + if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { + speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 ); + } else { + speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 ); + } + + /* square-root */ + speech_nrg = silk_SQRT_APPROX( speech_nrg ); + SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 ); + } + + /* Copy the resulting speech activity in Q8 */ + psEncC->speech_activity_Q8 = silk_min_int( silk_RSHIFT( SA_Q15, 7 ), silk_uint8_MAX ); + + /***********************************/ + /* Energy Level and SNR estimation */ + /***********************************/ + /* Smoothing coefficient */ + smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( (opus_int32)SA_Q15, SA_Q15 ) ); + + if( psEncC->frame_length == 10 * psEncC->fs_kHz ) { + smooth_coef_Q16 >>= 1; + } + + for( b = 0; b < VAD_N_BANDS; b++ ) { + /* compute smoothed energy-to-noise ratio per band */ + psSilk_VAD->NrgRatioSmth_Q8[ b ] = silk_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ], + NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 ); + + /* signal to noise ratio in dB per band */ + SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 ); + /* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */ + psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) ); + } + + RESTORE_STACK; + return( ret ); +} + +/**************************/ +/* Noise level estimation */ +/**************************/ +static OPUS_INLINE void silk_VAD_GetNoiseLevels( + const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */ + silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ +) +{ + opus_int k; + opus_int32 nl, nrg, inv_nrg; + opus_int coef, min_coef; + + /* Initially faster smoothing */ + if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */ + min_coef = silk_DIV32_16( silk_int16_MAX, silk_RSHIFT( psSilk_VAD->counter, 4 ) + 1 ); + } else { + min_coef = 0; + } + + for( k = 0; k < VAD_N_BANDS; k++ ) { + /* Get old noise level estimate for current band */ + nl = psSilk_VAD->NL[ k ]; + silk_assert( nl >= 0 ); + + /* Add bias */ + nrg = silk_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] ); + silk_assert( nrg > 0 ); + + /* Invert energies */ + inv_nrg = silk_DIV32( silk_int32_MAX, nrg ); + silk_assert( inv_nrg >= 0 ); + + /* Less update when subband energy is high */ + if( nrg > silk_LSHIFT( nl, 3 ) ) { + coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3; + } else if( nrg < nl ) { + coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16; + } else { + coef = silk_SMULWB( silk_SMULWW( inv_nrg, nl ), VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 << 1 ); + } + + /* Initially faster smoothing */ + coef = silk_max_int( coef, min_coef ); + + /* Smooth inverse energies */ + psSilk_VAD->inv_NL[ k ] = silk_SMLAWB( psSilk_VAD->inv_NL[ k ], inv_nrg - psSilk_VAD->inv_NL[ k ], coef ); + silk_assert( psSilk_VAD->inv_NL[ k ] >= 0 ); + + /* Compute noise level by inverting again */ + nl = silk_DIV32( silk_int32_MAX, psSilk_VAD->inv_NL[ k ] ); + silk_assert( nl >= 0 ); + + /* Limit noise levels (guarantee 7 bits of head room) */ + nl = silk_min( nl, 0x00FFFFFF ); + + /* Store as part of state */ + psSilk_VAD->NL[ k ] = nl; + } + + /* Increment frame counter */ + psSilk_VAD->counter++; +} diff --git a/TelegramClient.Opus/opus/silk/VQ_WMat_EC.c b/TelegramClient.Opus/opus/silk/VQ_WMat_EC.c new file mode 100755 index 0000000..13d5d34 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/VQ_WMat_EC.c @@ -0,0 +1,120 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */ +void silk_VQ_WMat_EC( + opus_int8 *ind, /* O index of best codebook vector */ + opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ + opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ + const opus_int16 *in_Q14, /* I input vector to be quantized */ + const opus_int32 *W_Q18, /* I weighting matrix */ + const opus_int8 *cb_Q7, /* I codebook */ + const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */ + const opus_uint8 *cl_Q5, /* I code length for each codebook vector */ + const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */ + const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ + opus_int L /* I number of vectors in codebook */ +) +{ + opus_int k, gain_tmp_Q7; + const opus_int8 *cb_row_Q7; + opus_int16 diff_Q14[ 5 ]; + opus_int32 sum1_Q14, sum2_Q16; + + /* Loop over codebook */ + *rate_dist_Q14 = silk_int32_MAX; + cb_row_Q7 = cb_Q7; + for( k = 0; k < L; k++ ) { + gain_tmp_Q7 = cb_gain_Q7[k]; + + diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 ); + diff_Q14[ 1 ] = in_Q14[ 1 ] - silk_LSHIFT( cb_row_Q7[ 1 ], 7 ); + diff_Q14[ 2 ] = in_Q14[ 2 ] - silk_LSHIFT( cb_row_Q7[ 2 ], 7 ); + diff_Q14[ 3 ] = in_Q14[ 3 ] - silk_LSHIFT( cb_row_Q7[ 3 ], 7 ); + diff_Q14[ 4 ] = in_Q14[ 4 ] - silk_LSHIFT( cb_row_Q7[ 4 ], 7 ); + + /* Weighted rate */ + sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] ); + + /* Penalty for too large gain */ + sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 ); + + silk_assert( sum1_Q14 >= 0 ); + + /* first row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 1 ], diff_Q14[ 1 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14[ 2 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 3 ], diff_Q14[ 3 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14[ 4 ] ); + sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] ); + + /* second row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] ); + sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] ); + + /* third row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] ); + sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] ); + + /* fourth row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] ); + sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 ); + sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] ); + + /* last row of W_Q18 */ + sum2_Q16 = silk_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] ); + sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] ); + + silk_assert( sum1_Q14 >= 0 ); + + /* find best */ + if( sum1_Q14 < *rate_dist_Q14 ) { + *rate_dist_Q14 = sum1_Q14; + *ind = (opus_int8)k; + *gain_Q7 = gain_tmp_Q7; + } + + /* Go to next cbk vector */ + cb_row_Q7 += LTP_ORDER; + } +} diff --git a/TelegramClient.Opus/opus/silk/ana_filt_bank_1.c b/TelegramClient.Opus/opus/silk/ana_filt_bank_1.c new file mode 100755 index 0000000..24cfb03 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/ana_filt_bank_1.c @@ -0,0 +1,74 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* Coefficients for 2-band filter bank based on first-order allpass filters */ +static opus_int16 A_fb1_20 = 5394 << 1; +static opus_int16 A_fb1_21 = -24290; /* (opus_int16)(20623 << 1) */ + +/* Split signal into two decimated bands using first-order allpass filters */ +void silk_ana_filt_bank_1( + const opus_int16 *in, /* I Input signal [N] */ + opus_int32 *S, /* I/O State vector [2] */ + opus_int16 *outL, /* O Low band [N/2] */ + opus_int16 *outH, /* O High band [N/2] */ + const opus_int32 N /* I Number of input samples */ +) +{ + opus_int k, N2 = silk_RSHIFT( N, 1 ); + opus_int32 in32, X, Y, out_1, out_2; + + /* Internal variables and state are in Q10 format */ + for( k = 0; k < N2; k++ ) { + /* Convert to Q10 */ + in32 = silk_LSHIFT( (opus_int32)in[ 2 * k ], 10 ); + + /* All-pass section for even input sample */ + Y = silk_SUB32( in32, S[ 0 ] ); + X = silk_SMLAWB( Y, Y, A_fb1_21 ); + out_1 = silk_ADD32( S[ 0 ], X ); + S[ 0 ] = silk_ADD32( in32, X ); + + /* Convert to Q10 */ + in32 = silk_LSHIFT( (opus_int32)in[ 2 * k + 1 ], 10 ); + + /* All-pass section for odd input sample, and add to output of previous section */ + Y = silk_SUB32( in32, S[ 1 ] ); + X = silk_SMULWB( Y, A_fb1_20 ); + out_2 = silk_ADD32( S[ 1 ], X ); + S[ 1 ] = silk_ADD32( in32, X ); + + /* Add/subtract, convert back to int16 and store to output */ + outL[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_ADD32( out_2, out_1 ), 11 ) ); + outH[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SUB32( out_2, out_1 ), 11 ) ); + } +} diff --git a/TelegramClient.Opus/opus/silk/arm/SigProc_FIX_armv4.h b/TelegramClient.Opus/opus/silk/arm/SigProc_FIX_armv4.h new file mode 100755 index 0000000..ff62b1e --- /dev/null +++ b/TelegramClient.Opus/opus/silk/arm/SigProc_FIX_armv4.h @@ -0,0 +1,47 @@ +/*********************************************************************** +Copyright (C) 2013 Xiph.Org Foundation and contributors +Copyright (c) 2013 Parrot +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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_SIGPROC_FIX_ARMv4_H +#define SILK_SIGPROC_FIX_ARMv4_H + +#undef silk_MLA +static OPUS_INLINE opus_int32 silk_MLA_armv4(opus_int32 a, opus_int32 b, + opus_int32 c) +{ + opus_int32 res; + __asm__( + "#silk_MLA\n\t" + "mla %0, %1, %2, %3\n\t" + : "=&r"(res) + : "r"(b), "r"(c), "r"(a) + ); + return res; +} +#define silk_MLA(a, b, c) (silk_MLA_armv4(a, b, c)) + +#endif diff --git a/TelegramClient.Opus/opus/silk/arm/SigProc_FIX_armv5e.h b/TelegramClient.Opus/opus/silk/arm/SigProc_FIX_armv5e.h new file mode 100755 index 0000000..617a09c --- /dev/null +++ b/TelegramClient.Opus/opus/silk/arm/SigProc_FIX_armv5e.h @@ -0,0 +1,61 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Copyright (c) 2013 Parrot +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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_SIGPROC_FIX_ARMv5E_H +#define SILK_SIGPROC_FIX_ARMv5E_H + +#undef silk_SMULTT +static OPUS_INLINE opus_int32 silk_SMULTT_armv5e(opus_int32 a, opus_int32 b) +{ + opus_int32 res; + __asm__( + "#silk_SMULTT\n\t" + "smultt %0, %1, %2\n\t" + : "=r"(res) + : "%r"(a), "r"(b) + ); + return res; +} +#define silk_SMULTT(a, b) (silk_SMULTT_armv5e(a, b)) + +#undef silk_SMLATT +static OPUS_INLINE opus_int32 silk_SMLATT_armv5e(opus_int32 a, opus_int32 b, + opus_int32 c) +{ + opus_int32 res; + __asm__( + "#silk_SMLATT\n\t" + "smlatt %0, %1, %2, %3\n\t" + : "=r"(res) + : "%r"(b), "r"(c), "r"(a) + ); + return res; +} +#define silk_SMLATT(a, b, c) (silk_SMLATT_armv5e(a, b, c)) + +#endif diff --git a/TelegramClient.Opus/opus/silk/arm/macros_armv4.h b/TelegramClient.Opus/opus/silk/arm/macros_armv4.h new file mode 100755 index 0000000..3f30e97 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/arm/macros_armv4.h @@ -0,0 +1,103 @@ +/*********************************************************************** +Copyright (C) 2013 Xiph.Org Foundation and contributors. +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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_MACROS_ARMv4_H +#define SILK_MACROS_ARMv4_H + +/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */ +#undef silk_SMULWB +static OPUS_INLINE opus_int32 silk_SMULWB_armv4(opus_int32 a, opus_int16 b) +{ + unsigned rd_lo; + int rd_hi; + __asm__( + "#silk_SMULWB\n\t" + "smull %0, %1, %2, %3\n\t" + : "=&r"(rd_lo), "=&r"(rd_hi) + : "%r"(a), "r"(b<<16) + ); + return rd_hi; +} +#define silk_SMULWB(a, b) (silk_SMULWB_armv4(a, b)) + +/* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */ +#undef silk_SMLAWB +#define silk_SMLAWB(a, b, c) ((a) + silk_SMULWB(b, c)) + +/* (a32 * (b32 >> 16)) >> 16 */ +#undef silk_SMULWT +static OPUS_INLINE opus_int32 silk_SMULWT_armv4(opus_int32 a, opus_int32 b) +{ + unsigned rd_lo; + int rd_hi; + __asm__( + "#silk_SMULWT\n\t" + "smull %0, %1, %2, %3\n\t" + : "=&r"(rd_lo), "=&r"(rd_hi) + : "%r"(a), "r"(b&~0xFFFF) + ); + return rd_hi; +} +#define silk_SMULWT(a, b) (silk_SMULWT_armv4(a, b)) + +/* a32 + (b32 * (c32 >> 16)) >> 16 */ +#undef silk_SMLAWT +#define silk_SMLAWT(a, b, c) ((a) + silk_SMULWT(b, c)) + +/* (a32 * b32) >> 16 */ +#undef silk_SMULWW +static OPUS_INLINE opus_int32 silk_SMULWW_armv4(opus_int32 a, opus_int32 b) +{ + unsigned rd_lo; + int rd_hi; + __asm__( + "#silk_SMULWW\n\t" + "smull %0, %1, %2, %3\n\t" + : "=&r"(rd_lo), "=&r"(rd_hi) + : "%r"(a), "r"(b) + ); + return (rd_hi<<16)+(rd_lo>>16); +} +#define silk_SMULWW(a, b) (silk_SMULWW_armv4(a, b)) + +#undef silk_SMLAWW +static OPUS_INLINE opus_int32 silk_SMLAWW_armv4(opus_int32 a, opus_int32 b, + opus_int32 c) +{ + unsigned rd_lo; + int rd_hi; + __asm__( + "#silk_SMLAWW\n\t" + "smull %0, %1, %2, %3\n\t" + : "=&r"(rd_lo), "=&r"(rd_hi) + : "%r"(b), "r"(c) + ); + return a+(rd_hi<<16)+(rd_lo>>16); +} +#define silk_SMLAWW(a, b, c) (silk_SMLAWW_armv4(a, b, c)) + +#endif /* SILK_MACROS_ARMv4_H */ diff --git a/TelegramClient.Opus/opus/silk/arm/macros_armv5e.h b/TelegramClient.Opus/opus/silk/arm/macros_armv5e.h new file mode 100755 index 0000000..aad4117 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/arm/macros_armv5e.h @@ -0,0 +1,213 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. All rights reserved. +Copyright (c) 2013 Parrot +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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_MACROS_ARMv5E_H +#define SILK_MACROS_ARMv5E_H + +/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */ +#undef silk_SMULWB +static OPUS_INLINE opus_int32 silk_SMULWB_armv5e(opus_int32 a, opus_int16 b) +{ + int res; + __asm__( + "#silk_SMULWB\n\t" + "smulwb %0, %1, %2\n\t" + : "=r"(res) + : "r"(a), "r"(b) + ); + return res; +} +#define silk_SMULWB(a, b) (silk_SMULWB_armv5e(a, b)) + +/* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */ +#undef silk_SMLAWB +static OPUS_INLINE opus_int32 silk_SMLAWB_armv5e(opus_int32 a, opus_int32 b, + opus_int16 c) +{ + int res; + __asm__( + "#silk_SMLAWB\n\t" + "smlawb %0, %1, %2, %3\n\t" + : "=r"(res) + : "r"(b), "r"(c), "r"(a) + ); + return res; +} +#define silk_SMLAWB(a, b, c) (silk_SMLAWB_armv5e(a, b, c)) + +/* (a32 * (b32 >> 16)) >> 16 */ +#undef silk_SMULWT +static OPUS_INLINE opus_int32 silk_SMULWT_armv5e(opus_int32 a, opus_int32 b) +{ + int res; + __asm__( + "#silk_SMULWT\n\t" + "smulwt %0, %1, %2\n\t" + : "=r"(res) + : "r"(a), "r"(b) + ); + return res; +} +#define silk_SMULWT(a, b) (silk_SMULWT_armv5e(a, b)) + +/* a32 + (b32 * (c32 >> 16)) >> 16 */ +#undef silk_SMLAWT +static OPUS_INLINE opus_int32 silk_SMLAWT_armv5e(opus_int32 a, opus_int32 b, + opus_int32 c) +{ + int res; + __asm__( + "#silk_SMLAWT\n\t" + "smlawt %0, %1, %2, %3\n\t" + : "=r"(res) + : "r"(b), "r"(c), "r"(a) + ); + return res; +} +#define silk_SMLAWT(a, b, c) (silk_SMLAWT_armv5e(a, b, c)) + +/* (opus_int32)((opus_int16)(a3))) * (opus_int32)((opus_int16)(b32)) output have to be 32bit int */ +#undef silk_SMULBB +static OPUS_INLINE opus_int32 silk_SMULBB_armv5e(opus_int32 a, opus_int32 b) +{ + int res; + __asm__( + "#silk_SMULBB\n\t" + "smulbb %0, %1, %2\n\t" + : "=r"(res) + : "%r"(a), "r"(b) + ); + return res; +} +#define silk_SMULBB(a, b) (silk_SMULBB_armv5e(a, b)) + +/* a32 + (opus_int32)((opus_int16)(b32)) * (opus_int32)((opus_int16)(c32)) output have to be 32bit int */ +#undef silk_SMLABB +static OPUS_INLINE opus_int32 silk_SMLABB_armv5e(opus_int32 a, opus_int32 b, + opus_int32 c) +{ + int res; + __asm__( + "#silk_SMLABB\n\t" + "smlabb %0, %1, %2, %3\n\t" + : "=r"(res) + : "%r"(b), "r"(c), "r"(a) + ); + return res; +} +#define silk_SMLABB(a, b, c) (silk_SMLABB_armv5e(a, b, c)) + +/* (opus_int32)((opus_int16)(a32)) * (b32 >> 16) */ +#undef silk_SMULBT +static OPUS_INLINE opus_int32 silk_SMULBT_armv5e(opus_int32 a, opus_int32 b) +{ + int res; + __asm__( + "#silk_SMULBT\n\t" + "smulbt %0, %1, %2\n\t" + : "=r"(res) + : "r"(a), "r"(b) + ); + return res; +} +#define silk_SMULBT(a, b) (silk_SMULBT_armv5e(a, b)) + +/* a32 + (opus_int32)((opus_int16)(b32)) * (c32 >> 16) */ +#undef silk_SMLABT +static OPUS_INLINE opus_int32 silk_SMLABT_armv5e(opus_int32 a, opus_int32 b, + opus_int32 c) +{ + int res; + __asm__( + "#silk_SMLABT\n\t" + "smlabt %0, %1, %2, %3\n\t" + : "=r"(res) + : "r"(b), "r"(c), "r"(a) + ); + return res; +} +#define silk_SMLABT(a, b, c) (silk_SMLABT_armv5e(a, b, c)) + +/* add/subtract with output saturated */ +#undef silk_ADD_SAT32 +static OPUS_INLINE opus_int32 silk_ADD_SAT32_armv5e(opus_int32 a, opus_int32 b) +{ + int res; + __asm__( + "#silk_ADD_SAT32\n\t" + "qadd %0, %1, %2\n\t" + : "=r"(res) + : "%r"(a), "r"(b) + ); + return res; +} +#define silk_ADD_SAT32(a, b) (silk_ADD_SAT32_armv5e(a, b)) + +#undef silk_SUB_SAT32 +static OPUS_INLINE opus_int32 silk_SUB_SAT32_armv5e(opus_int32 a, opus_int32 b) +{ + int res; + __asm__( + "#silk_SUB_SAT32\n\t" + "qsub %0, %1, %2\n\t" + : "=r"(res) + : "r"(a), "r"(b) + ); + return res; +} +#define silk_SUB_SAT32(a, b) (silk_SUB_SAT32_armv5e(a, b)) + +#undef silk_CLZ16 +static OPUS_INLINE opus_int32 silk_CLZ16_armv5(opus_int16 in16) +{ + int res; + __asm__( + "#silk_CLZ16\n\t" + "clz %0, %1;\n" + : "=r"(res) + : "r"(in16<<16|0x8000) + ); + return res; +} +#define silk_CLZ16(in16) (silk_CLZ16_armv5(in16)) + +#undef silk_CLZ32 +static OPUS_INLINE opus_int32 silk_CLZ32_armv5(opus_int32 in32) +{ + int res; + __asm__( + "#silk_CLZ32\n\t" + "clz %0, %1\n\t" + : "=r"(res) + : "r"(in32) + ); + return res; +} +#define silk_CLZ32(in32) (silk_CLZ32_armv5(in32)) + +#endif /* SILK_MACROS_ARMv5E_H */ diff --git a/TelegramClient.Opus/opus/silk/biquad_alt.c b/TelegramClient.Opus/opus/silk/biquad_alt.c new file mode 100755 index 0000000..d55f5ee --- /dev/null +++ b/TelegramClient.Opus/opus/silk/biquad_alt.c @@ -0,0 +1,78 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +/* * + * silk_biquad_alt.c * + * * + * Second order ARMA filter * + * Can handle slowly varying filter coefficients * + * */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* Second order ARMA filter, alternative implementation */ +void silk_biquad_alt( + const opus_int16 *in, /* I input signal */ + const opus_int32 *B_Q28, /* I MA coefficients [3] */ + const opus_int32 *A_Q28, /* I AR coefficients [2] */ + opus_int32 *S, /* I/O State vector [2] */ + opus_int16 *out, /* O output signal */ + const opus_int32 len, /* I signal length (must be even) */ + opus_int stride /* I Operate on interleaved signal if > 1 */ +) +{ + /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */ + opus_int k; + opus_int32 inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14; + + /* Negate A_Q28 values and split in two parts */ + A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */ + A0_U_Q28 = silk_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */ + A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */ + A1_U_Q28 = silk_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */ + + for( k = 0; k < len; k++ ) { + /* S[ 0 ], S[ 1 ]: Q12 */ + inval = in[ k * stride ]; + out32_Q14 = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 ); + + S[ 0 ] = S[1] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A0_L_Q28 ), 14 ); + S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14, A0_U_Q28 ); + S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], inval); + + S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A1_L_Q28 ), 14 ); + S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14, A1_U_Q28 ); + S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval ); + + /* Scale back to Q0 and saturate */ + out[ k * stride ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) ); + } +} diff --git a/TelegramClient.Opus/opus/silk/bwexpander.c b/TelegramClient.Opus/opus/silk/bwexpander.c new file mode 100755 index 0000000..2eb4456 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/bwexpander.c @@ -0,0 +1,51 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* Chirp (bandwidth expand) LP AR filter */ +void silk_bwexpander( + opus_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */ + const opus_int d, /* I Length of ar */ + opus_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */ +) +{ + opus_int i; + opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536; + + /* NB: Dont use silk_SMULWB, instead of silk_RSHIFT_ROUND( silk_MUL(), 16 ), below. */ + /* Bias in silk_SMULWB can lead to unstable filters */ + for( i = 0; i < d - 1; i++ ) { + ar[ i ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ i ] ), 16 ); + chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 ); + } + ar[ d - 1 ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ d - 1 ] ), 16 ); +} diff --git a/TelegramClient.Opus/opus/silk/bwexpander_32.c b/TelegramClient.Opus/opus/silk/bwexpander_32.c new file mode 100755 index 0000000..d0010f7 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/bwexpander_32.c @@ -0,0 +1,50 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* Chirp (bandwidth expand) LP AR filter */ +void silk_bwexpander_32( + opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */ + const opus_int d, /* I Length of ar */ + opus_int32 chirp_Q16 /* I Chirp factor in Q16 */ +) +{ + opus_int i; + opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536; + + for( i = 0; i < d - 1; i++ ) { + ar[ i ] = silk_SMULWW( chirp_Q16, ar[ i ] ); + chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 ); + } + ar[ d - 1 ] = silk_SMULWW( chirp_Q16, ar[ d - 1 ] ); +} + diff --git a/TelegramClient.Opus/opus/silk/check_control_input.c b/TelegramClient.Opus/opus/silk/check_control_input.c new file mode 100755 index 0000000..b5de9ce --- /dev/null +++ b/TelegramClient.Opus/opus/silk/check_control_input.c @@ -0,0 +1,106 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "control.h" +#include "errors.h" + +/* Check encoder control struct */ +opus_int check_control_input( + silk_EncControlStruct *encControl /* I Control structure */ +) +{ + silk_assert( encControl != NULL ); + + if( ( ( encControl->API_sampleRate != 8000 ) && + ( encControl->API_sampleRate != 12000 ) && + ( encControl->API_sampleRate != 16000 ) && + ( encControl->API_sampleRate != 24000 ) && + ( encControl->API_sampleRate != 32000 ) && + ( encControl->API_sampleRate != 44100 ) && + ( encControl->API_sampleRate != 48000 ) ) || + ( ( encControl->desiredInternalSampleRate != 8000 ) && + ( encControl->desiredInternalSampleRate != 12000 ) && + ( encControl->desiredInternalSampleRate != 16000 ) ) || + ( ( encControl->maxInternalSampleRate != 8000 ) && + ( encControl->maxInternalSampleRate != 12000 ) && + ( encControl->maxInternalSampleRate != 16000 ) ) || + ( ( encControl->minInternalSampleRate != 8000 ) && + ( encControl->minInternalSampleRate != 12000 ) && + ( encControl->minInternalSampleRate != 16000 ) ) || + ( encControl->minInternalSampleRate > encControl->desiredInternalSampleRate ) || + ( encControl->maxInternalSampleRate < encControl->desiredInternalSampleRate ) || + ( encControl->minInternalSampleRate > encControl->maxInternalSampleRate ) ) { + silk_assert( 0 ); + return SILK_ENC_FS_NOT_SUPPORTED; + } + if( encControl->payloadSize_ms != 10 && + encControl->payloadSize_ms != 20 && + encControl->payloadSize_ms != 40 && + encControl->payloadSize_ms != 60 ) { + silk_assert( 0 ); + return SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; + } + if( encControl->packetLossPercentage < 0 || encControl->packetLossPercentage > 100 ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_LOSS_RATE; + } + if( encControl->useDTX < 0 || encControl->useDTX > 1 ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_DTX_SETTING; + } + if( encControl->useCBR < 0 || encControl->useCBR > 1 ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_CBR_SETTING; + } + if( encControl->useInBandFEC < 0 || encControl->useInBandFEC > 1 ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_INBAND_FEC_SETTING; + } + if( encControl->nChannelsAPI < 1 || encControl->nChannelsAPI > ENCODER_NUM_CHANNELS ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; + } + if( encControl->nChannelsInternal < 1 || encControl->nChannelsInternal > ENCODER_NUM_CHANNELS ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; + } + if( encControl->nChannelsInternal > encControl->nChannelsAPI ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR; + } + if( encControl->complexity < 0 || encControl->complexity > 10 ) { + silk_assert( 0 ); + return SILK_ENC_INVALID_COMPLEXITY_SETTING; + } + + return SILK_NO_ERROR; +} diff --git a/TelegramClient.Opus/opus/silk/code_signs.c b/TelegramClient.Opus/opus/silk/code_signs.c new file mode 100755 index 0000000..0419ea2 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/code_signs.c @@ -0,0 +1,115 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/*#define silk_enc_map(a) ((a) > 0 ? 1 : 0)*/ +/*#define silk_dec_map(a) ((a) > 0 ? 1 : -1)*/ +/* shifting avoids if-statement */ +#define silk_enc_map(a) ( silk_RSHIFT( (a), 15 ) + 1 ) +#define silk_dec_map(a) ( silk_LSHIFT( (a), 1 ) - 1 ) + +/* Encodes signs of excitation */ +void silk_encode_signs( + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + const opus_int8 pulses[], /* I pulse signal */ + opus_int length, /* I length of input */ + const opus_int signalType, /* I Signal type */ + const opus_int quantOffsetType, /* I Quantization offset type */ + const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */ +) +{ + opus_int i, j, p; + opus_uint8 icdf[ 2 ]; + const opus_int8 *q_ptr; + const opus_uint8 *icdf_ptr; + + icdf[ 1 ] = 0; + q_ptr = pulses; + i = silk_SMULBB( 7, silk_ADD_LSHIFT( quantOffsetType, signalType, 1 ) ); + icdf_ptr = &silk_sign_iCDF[ i ]; + length = silk_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH ); + for( i = 0; i < length; i++ ) { + p = sum_pulses[ i ]; + if( p > 0 ) { + icdf[ 0 ] = icdf_ptr[ silk_min( p & 0x1F, 6 ) ]; + for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) { + if( q_ptr[ j ] != 0 ) { + ec_enc_icdf( psRangeEnc, silk_enc_map( q_ptr[ j ]), icdf, 8 ); + } + } + } + q_ptr += SHELL_CODEC_FRAME_LENGTH; + } +} + +/* Decodes signs of excitation */ +void silk_decode_signs( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int pulses[], /* I/O pulse signal */ + opus_int length, /* I length of input */ + const opus_int signalType, /* I Signal type */ + const opus_int quantOffsetType, /* I Quantization offset type */ + const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */ +) +{ + opus_int i, j, p; + opus_uint8 icdf[ 2 ]; + opus_int *q_ptr; + const opus_uint8 *icdf_ptr; + + icdf[ 1 ] = 0; + q_ptr = pulses; + i = silk_SMULBB( 7, silk_ADD_LSHIFT( quantOffsetType, signalType, 1 ) ); + icdf_ptr = &silk_sign_iCDF[ i ]; + length = silk_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH ); + for( i = 0; i < length; i++ ) { + p = sum_pulses[ i ]; + if( p > 0 ) { + icdf[ 0 ] = icdf_ptr[ silk_min( p & 0x1F, 6 ) ]; + for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) { + if( q_ptr[ j ] > 0 ) { + /* attach sign */ +#if 0 + /* conditional implementation */ + if( ec_dec_icdf( psRangeDec, icdf, 8 ) == 0 ) { + q_ptr[ j ] = -q_ptr[ j ]; + } +#else + /* implementation with shift, subtraction, multiplication */ + q_ptr[ j ] *= silk_dec_map( ec_dec_icdf( psRangeDec, icdf, 8 ) ); +#endif + } + } + } + q_ptr += SHELL_CODEC_FRAME_LENGTH; + } +} diff --git a/TelegramClient.Opus/opus/silk/control.h b/TelegramClient.Opus/opus/silk/control.h new file mode 100755 index 0000000..747e542 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/control.h @@ -0,0 +1,142 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_CONTROL_H +#define SILK_CONTROL_H + +#include "typedef.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Decoder API flags */ +#define FLAG_DECODE_NORMAL 0 +#define FLAG_PACKET_LOST 1 +#define FLAG_DECODE_LBRR 2 + +/***********************************************/ +/* Structure for controlling encoder operation */ +/***********************************************/ +typedef struct { + /* I: Number of channels; 1/2 */ + opus_int32 nChannelsAPI; + + /* I: Number of channels; 1/2 */ + opus_int32 nChannelsInternal; + + /* I: Input signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000 */ + opus_int32 API_sampleRate; + + /* I: Maximum internal sampling rate in Hertz; 8000/12000/16000 */ + opus_int32 maxInternalSampleRate; + + /* I: Minimum internal sampling rate in Hertz; 8000/12000/16000 */ + opus_int32 minInternalSampleRate; + + /* I: Soft request for internal sampling rate in Hertz; 8000/12000/16000 */ + opus_int32 desiredInternalSampleRate; + + /* I: Number of samples per packet in milliseconds; 10/20/40/60 */ + opus_int payloadSize_ms; + + /* I: Bitrate during active speech in bits/second; internally limited */ + opus_int32 bitRate; + + /* I: Uplink packet loss in percent (0-100) */ + opus_int packetLossPercentage; + + /* I: Complexity mode; 0 is lowest, 10 is highest complexity */ + opus_int complexity; + + /* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */ + opus_int useInBandFEC; + + /* I: Flag to enable discontinuous transmission (DTX); 0/1 */ + opus_int useDTX; + + /* I: Flag to use constant bitrate */ + opus_int useCBR; + + /* I: Maximum number of bits allowed for the frame */ + opus_int maxBits; + + /* I: Causes a smooth downmix to mono */ + opus_int toMono; + + /* I: Opus encoder is allowing us to switch bandwidth */ + opus_int opusCanSwitch; + + /* I: Make frames as independent as possible (but still use LPC) */ + opus_int reducedDependency; + + /* O: Internal sampling rate used, in Hertz; 8000/12000/16000 */ + opus_int32 internalSampleRate; + + /* O: Flag that bandwidth switching is allowed (because low voice activity) */ + opus_int allowBandwidthSwitch; + + /* O: Flag that SILK runs in WB mode without variable LP filter (use for switching between WB/SWB/FB) */ + opus_int inWBmodeWithoutVariableLP; + + /* O: Stereo width */ + opus_int stereoWidth_Q14; + + /* O: Tells the Opus encoder we're ready to switch */ + opus_int switchReady; + +} silk_EncControlStruct; + +/**************************************************************************/ +/* Structure for controlling decoder operation and reading decoder status */ +/**************************************************************************/ +typedef struct { + /* I: Number of channels; 1/2 */ + opus_int32 nChannelsAPI; + + /* I: Number of channels; 1/2 */ + opus_int32 nChannelsInternal; + + /* I: Output signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000 */ + opus_int32 API_sampleRate; + + /* I: Internal sampling rate used, in Hertz; 8000/12000/16000 */ + opus_int32 internalSampleRate; + + /* I: Number of samples per packet in milliseconds; 10/20/40/60 */ + opus_int payloadSize_ms; + + /* O: Pitch lag of previous frame (0 if unvoiced), measured in samples at 48 kHz */ + opus_int prevPitchLag; +} silk_DecControlStruct; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/TelegramClient.Opus/opus/silk/control_SNR.c b/TelegramClient.Opus/opus/silk/control_SNR.c new file mode 100755 index 0000000..f04e69f --- /dev/null +++ b/TelegramClient.Opus/opus/silk/control_SNR.c @@ -0,0 +1,81 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "tuning_parameters.h" + +/* Control SNR of redidual quantizer */ +opus_int silk_control_SNR( + silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */ + opus_int32 TargetRate_bps /* I Target max bitrate (bps) */ +) +{ + opus_int k, ret = SILK_NO_ERROR; + opus_int32 frac_Q6; + const opus_int32 *rateTable; + + /* Set bitrate/coding quality */ + TargetRate_bps = silk_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS ); + if( TargetRate_bps != psEncC->TargetRate_bps ) { + psEncC->TargetRate_bps = TargetRate_bps; + + /* If new TargetRate_bps, translate to SNR_dB value */ + if( psEncC->fs_kHz == 8 ) { + rateTable = silk_TargetRate_table_NB; + } else if( psEncC->fs_kHz == 12 ) { + rateTable = silk_TargetRate_table_MB; + } else { + rateTable = silk_TargetRate_table_WB; + } + + /* Reduce bitrate for 10 ms modes in these calculations */ + if( psEncC->nb_subfr == 2 ) { + TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS; + } + + /* Find bitrate interval in table and interpolate */ + for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) { + if( TargetRate_bps <= rateTable[ k ] ) { + frac_Q6 = silk_DIV32( silk_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ), + rateTable[ k ] - rateTable[ k - 1 ] ); + psEncC->SNR_dB_Q7 = silk_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + silk_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] ); + break; + } + } + + /* Reduce coding quality whenever LBRR is enabled, to free up some bits */ + if( psEncC->LBRR_enabled ) { + psEncC->SNR_dB_Q7 = silk_SMLABB( psEncC->SNR_dB_Q7, 12 - psEncC->LBRR_GainIncreases, SILK_FIX_CONST( -0.25, 7 ) ); + } + } + + return ret; +} diff --git a/TelegramClient.Opus/opus/silk/control_audio_bandwidth.c b/TelegramClient.Opus/opus/silk/control_audio_bandwidth.c new file mode 100755 index 0000000..4f9bc5c --- /dev/null +++ b/TelegramClient.Opus/opus/silk/control_audio_bandwidth.c @@ -0,0 +1,126 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "tuning_parameters.h" + +/* Control internal sampling rate */ +opus_int silk_control_audio_bandwidth( + silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */ + silk_EncControlStruct *encControl /* I Control structure */ +) +{ + opus_int fs_kHz; + opus_int32 fs_Hz; + + fs_kHz = psEncC->fs_kHz; + fs_Hz = silk_SMULBB( fs_kHz, 1000 ); + if( fs_Hz == 0 ) { + /* Encoder has just been initialized */ + fs_Hz = silk_min( psEncC->desiredInternal_fs_Hz, psEncC->API_fs_Hz ); + fs_kHz = silk_DIV32_16( fs_Hz, 1000 ); + } else if( fs_Hz > psEncC->API_fs_Hz || fs_Hz > psEncC->maxInternal_fs_Hz || fs_Hz < psEncC->minInternal_fs_Hz ) { + /* Make sure internal rate is not higher than external rate or maximum allowed, or lower than minimum allowed */ + fs_Hz = psEncC->API_fs_Hz; + fs_Hz = silk_min( fs_Hz, psEncC->maxInternal_fs_Hz ); + fs_Hz = silk_max( fs_Hz, psEncC->minInternal_fs_Hz ); + fs_kHz = silk_DIV32_16( fs_Hz, 1000 ); + } else { + /* State machine for the internal sampling rate switching */ + if( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES ) { + /* Stop transition phase */ + psEncC->sLP.mode = 0; + } + if( psEncC->allow_bandwidth_switch || encControl->opusCanSwitch ) { + /* Check if we should switch down */ + if( silk_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz ) + { + /* Switch down */ + if( psEncC->sLP.mode == 0 ) { + /* New transition */ + psEncC->sLP.transition_frame_no = TRANSITION_FRAMES; + + /* Reset transition filter state */ + silk_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) ); + } + if( encControl->opusCanSwitch ) { + /* Stop transition phase */ + psEncC->sLP.mode = 0; + + /* Switch to a lower sample frequency */ + fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8; + } else { + if( psEncC->sLP.transition_frame_no <= 0 ) { + encControl->switchReady = 1; + /* Make room for redundancy */ + encControl->maxBits -= encControl->maxBits * 5 / ( encControl->payloadSize_ms + 5 ); + } else { + /* Direction: down (at double speed) */ + psEncC->sLP.mode = -2; + } + } + } + else + /* Check if we should switch up */ + if( silk_SMULBB( psEncC->fs_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz ) + { + /* Switch up */ + if( encControl->opusCanSwitch ) { + /* Switch to a higher sample frequency */ + fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16; + + /* New transition */ + psEncC->sLP.transition_frame_no = 0; + + /* Reset transition filter state */ + silk_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) ); + + /* Direction: up */ + psEncC->sLP.mode = 1; + } else { + if( psEncC->sLP.mode == 0 ) { + encControl->switchReady = 1; + /* Make room for redundancy */ + encControl->maxBits -= encControl->maxBits * 5 / ( encControl->payloadSize_ms + 5 ); + } else { + /* Direction: up */ + psEncC->sLP.mode = 1; + } + } + } else { + if (psEncC->sLP.mode<0) + psEncC->sLP.mode = 1; + } + } + } + + return fs_kHz; +} diff --git a/TelegramClient.Opus/opus/silk/control_codec.c b/TelegramClient.Opus/opus/silk/control_codec.c new file mode 100755 index 0000000..1f674bd --- /dev/null +++ b/TelegramClient.Opus/opus/silk/control_codec.c @@ -0,0 +1,422 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef FIXED_POINT +#include "main_FIX.h" +#define silk_encoder_state_Fxx silk_encoder_state_FIX +#else +#include "main_FLP.h" +#define silk_encoder_state_Fxx silk_encoder_state_FLP +#endif +#include "stack_alloc.h" +#include "tuning_parameters.h" +#include "pitch_est_defines.h" + +static opus_int silk_setup_resamplers( + silk_encoder_state_Fxx *psEnc, /* I/O */ + opus_int fs_kHz /* I */ +); + +static opus_int silk_setup_fs( + silk_encoder_state_Fxx *psEnc, /* I/O */ + opus_int fs_kHz, /* I */ + opus_int PacketSize_ms /* I */ +); + +static opus_int silk_setup_complexity( + silk_encoder_state *psEncC, /* I/O */ + opus_int Complexity /* I */ +); + +static OPUS_INLINE opus_int silk_setup_LBRR( + silk_encoder_state *psEncC, /* I/O */ + const opus_int32 TargetRate_bps /* I */ +); + + +/* Control encoder */ +opus_int silk_control_encoder( + silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */ + silk_EncControlStruct *encControl, /* I Control structure */ + const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */ + const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */ + const opus_int channelNb, /* I Channel number */ + const opus_int force_fs_kHz +) +{ + opus_int fs_kHz, ret = 0; + + psEnc->sCmn.useDTX = encControl->useDTX; + psEnc->sCmn.useCBR = encControl->useCBR; + psEnc->sCmn.API_fs_Hz = encControl->API_sampleRate; + psEnc->sCmn.maxInternal_fs_Hz = encControl->maxInternalSampleRate; + psEnc->sCmn.minInternal_fs_Hz = encControl->minInternalSampleRate; + psEnc->sCmn.desiredInternal_fs_Hz = encControl->desiredInternalSampleRate; + psEnc->sCmn.useInBandFEC = encControl->useInBandFEC; + psEnc->sCmn.nChannelsAPI = encControl->nChannelsAPI; + psEnc->sCmn.nChannelsInternal = encControl->nChannelsInternal; + psEnc->sCmn.allow_bandwidth_switch = allow_bw_switch; + psEnc->sCmn.channelNb = channelNb; + + if( psEnc->sCmn.controlled_since_last_payload != 0 && psEnc->sCmn.prefillFlag == 0 ) { + if( psEnc->sCmn.API_fs_Hz != psEnc->sCmn.prev_API_fs_Hz && psEnc->sCmn.fs_kHz > 0 ) { + /* Change in API sampling rate in the middle of encoding a packet */ + ret += silk_setup_resamplers( psEnc, psEnc->sCmn.fs_kHz ); + } + return ret; + } + + /* Beyond this point we know that there are no previously coded frames in the payload buffer */ + + /********************************************/ + /* Determine internal sampling rate */ + /********************************************/ + fs_kHz = silk_control_audio_bandwidth( &psEnc->sCmn, encControl ); + if( force_fs_kHz ) { + fs_kHz = force_fs_kHz; + } + /********************************************/ + /* Prepare resampler and buffered data */ + /********************************************/ + ret += silk_setup_resamplers( psEnc, fs_kHz ); + + /********************************************/ + /* Set internal sampling frequency */ + /********************************************/ + ret += silk_setup_fs( psEnc, fs_kHz, encControl->payloadSize_ms ); + + /********************************************/ + /* Set encoding complexity */ + /********************************************/ + ret += silk_setup_complexity( &psEnc->sCmn, encControl->complexity ); + + /********************************************/ + /* Set packet loss rate measured by farend */ + /********************************************/ + psEnc->sCmn.PacketLoss_perc = encControl->packetLossPercentage; + + /********************************************/ + /* Set LBRR usage */ + /********************************************/ + ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps ); + + psEnc->sCmn.controlled_since_last_payload = 1; + + return ret; +} + +static opus_int silk_setup_resamplers( + silk_encoder_state_Fxx *psEnc, /* I/O */ + opus_int fs_kHz /* I */ +) +{ + opus_int ret = SILK_NO_ERROR; + SAVE_STACK; + + if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz ) + { + if( psEnc->sCmn.fs_kHz == 0 ) { + /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ + ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000, 1 ); + } else { + VARDECL( opus_int16, x_buf_API_fs_Hz ); + VARDECL( silk_resampler_state_struct, temp_resampler_state ); +#ifdef FIXED_POINT + opus_int16 *x_bufFIX = psEnc->x_buf; +#else + VARDECL( opus_int16, x_bufFIX ); + opus_int32 new_buf_samples; +#endif + opus_int32 api_buf_samples; + opus_int32 old_buf_samples; + opus_int32 buf_length_ms; + + buf_length_ms = silk_LSHIFT( psEnc->sCmn.nb_subfr * 5, 1 ) + LA_SHAPE_MS; + old_buf_samples = buf_length_ms * psEnc->sCmn.fs_kHz; + +#ifndef FIXED_POINT + new_buf_samples = buf_length_ms * fs_kHz; + ALLOC( x_bufFIX, silk_max( old_buf_samples, new_buf_samples ), + opus_int16 ); + silk_float2short_array( x_bufFIX, psEnc->x_buf, old_buf_samples ); +#endif + + /* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */ + ALLOC( temp_resampler_state, 1, silk_resampler_state_struct ); + ret += silk_resampler_init( temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz, 0 ); + + /* Calculate number of samples to temporarily upsample */ + api_buf_samples = buf_length_ms * silk_DIV32_16( psEnc->sCmn.API_fs_Hz, 1000 ); + + /* Temporary resampling of x_buf data to API_fs_Hz */ + ALLOC( x_buf_API_fs_Hz, api_buf_samples, opus_int16 ); + ret += silk_resampler( temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, old_buf_samples ); + + /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */ + ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, silk_SMULBB( fs_kHz, 1000 ), 1 ); + + /* Correct resampler state by resampling buffered data from API_fs_Hz to fs_kHz */ + ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, api_buf_samples ); + +#ifndef FIXED_POINT + silk_short2float_array( psEnc->x_buf, x_bufFIX, new_buf_samples); +#endif + } + } + + psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz; + + RESTORE_STACK; + return ret; +} + +static opus_int silk_setup_fs( + silk_encoder_state_Fxx *psEnc, /* I/O */ + opus_int fs_kHz, /* I */ + opus_int PacketSize_ms /* I */ +) +{ + opus_int ret = SILK_NO_ERROR; + + /* Set packet size */ + if( PacketSize_ms != psEnc->sCmn.PacketSize_ms ) { + if( ( PacketSize_ms != 10 ) && + ( PacketSize_ms != 20 ) && + ( PacketSize_ms != 40 ) && + ( PacketSize_ms != 60 ) ) { + ret = SILK_ENC_PACKET_SIZE_NOT_SUPPORTED; + } + if( PacketSize_ms <= 10 ) { + psEnc->sCmn.nFramesPerPacket = 1; + psEnc->sCmn.nb_subfr = PacketSize_ms == 10 ? 2 : 1; + psEnc->sCmn.frame_length = silk_SMULBB( PacketSize_ms, fs_kHz ); + psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz ); + if( psEnc->sCmn.fs_kHz == 8 ) { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; + } else { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; + } + } else { + psEnc->sCmn.nFramesPerPacket = silk_DIV32_16( PacketSize_ms, MAX_FRAME_LENGTH_MS ); + psEnc->sCmn.nb_subfr = MAX_NB_SUBFR; + psEnc->sCmn.frame_length = silk_SMULBB( 20, fs_kHz ); + psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz ); + if( psEnc->sCmn.fs_kHz == 8 ) { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; + } else { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF; + } + } + psEnc->sCmn.PacketSize_ms = PacketSize_ms; + psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ + } + + /* Set internal sampling frequency */ + silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); + silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 ); + if( psEnc->sCmn.fs_kHz != fs_kHz ) { + /* reset part of the state */ + silk_memset( &psEnc->sShape, 0, sizeof( psEnc->sShape ) ); + silk_memset( &psEnc->sPrefilt, 0, sizeof( psEnc->sPrefilt ) ); + silk_memset( &psEnc->sCmn.sNSQ, 0, sizeof( psEnc->sCmn.sNSQ ) ); + silk_memset( psEnc->sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); + silk_memset( &psEnc->sCmn.sLP.In_LP_State, 0, sizeof( psEnc->sCmn.sLP.In_LP_State ) ); + psEnc->sCmn.inputBufIx = 0; + psEnc->sCmn.nFramesEncoded = 0; + psEnc->sCmn.TargetRate_bps = 0; /* trigger new SNR computation */ + + /* Initialize non-zero parameters */ + psEnc->sCmn.prevLag = 100; + psEnc->sCmn.first_frame_after_reset = 1; + psEnc->sPrefilt.lagPrev = 100; + psEnc->sShape.LastGainIndex = 10; + psEnc->sCmn.sNSQ.lagPrev = 100; + psEnc->sCmn.sNSQ.prev_gain_Q16 = 65536; + psEnc->sCmn.prevSignalType = TYPE_NO_VOICE_ACTIVITY; + + psEnc->sCmn.fs_kHz = fs_kHz; + if( psEnc->sCmn.fs_kHz == 8 ) { + if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; + } else { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; + } + } else { + if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF; + } else { + psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; + } + } + if( psEnc->sCmn.fs_kHz == 8 || psEnc->sCmn.fs_kHz == 12 ) { + psEnc->sCmn.predictLPCOrder = MIN_LPC_ORDER; + psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_NB_MB; + } else { + psEnc->sCmn.predictLPCOrder = MAX_LPC_ORDER; + psEnc->sCmn.psNLSF_CB = &silk_NLSF_CB_WB; + } + psEnc->sCmn.subfr_length = SUB_FRAME_LENGTH_MS * fs_kHz; + psEnc->sCmn.frame_length = silk_SMULBB( psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr ); + psEnc->sCmn.ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz ); + psEnc->sCmn.la_pitch = silk_SMULBB( LA_PITCH_MS, fs_kHz ); + psEnc->sCmn.max_pitch_lag = silk_SMULBB( 18, fs_kHz ); + if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) { + psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz ); + } else { + psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz ); + } + if( psEnc->sCmn.fs_kHz == 16 ) { + psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_WB, 9 ); + psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform8_iCDF; + } else if( psEnc->sCmn.fs_kHz == 12 ) { + psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_MB, 9 ); + psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform6_iCDF; + } else { + psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_NB, 9 ); + psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform4_iCDF; + } + } + + /* Check that settings are valid */ + silk_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length ); + + return ret; +} + +static opus_int silk_setup_complexity( + silk_encoder_state *psEncC, /* I/O */ + opus_int Complexity /* I */ +) +{ + opus_int ret = 0; + + /* Set encoding complexity */ + silk_assert( Complexity >= 0 && Complexity <= 10 ); + if( Complexity < 2 ) { + psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 ); + psEncC->pitchEstimationLPCOrder = 6; + psEncC->shapingLPCOrder = 8; + psEncC->la_shape = 3 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = 1; + psEncC->useInterpolatedNLSFs = 0; + psEncC->LTPQuantLowComplexity = 1; + psEncC->NLSF_MSVQ_Survivors = 2; + psEncC->warping_Q16 = 0; + } else if( Complexity < 4 ) { + psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.76, 16 ); + psEncC->pitchEstimationLPCOrder = 8; + psEncC->shapingLPCOrder = 10; + psEncC->la_shape = 5 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = 1; + psEncC->useInterpolatedNLSFs = 0; + psEncC->LTPQuantLowComplexity = 0; + psEncC->NLSF_MSVQ_Survivors = 4; + psEncC->warping_Q16 = 0; + } else if( Complexity < 6 ) { + psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.74, 16 ); + psEncC->pitchEstimationLPCOrder = 10; + psEncC->shapingLPCOrder = 12; + psEncC->la_shape = 5 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = 2; + psEncC->useInterpolatedNLSFs = 1; + psEncC->LTPQuantLowComplexity = 0; + psEncC->NLSF_MSVQ_Survivors = 8; + psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); + } else if( Complexity < 8 ) { + psEncC->pitchEstimationComplexity = SILK_PE_MID_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.72, 16 ); + psEncC->pitchEstimationLPCOrder = 12; + psEncC->shapingLPCOrder = 14; + psEncC->la_shape = 5 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = 3; + psEncC->useInterpolatedNLSFs = 1; + psEncC->LTPQuantLowComplexity = 0; + psEncC->NLSF_MSVQ_Survivors = 16; + psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); + } else { + psEncC->pitchEstimationComplexity = SILK_PE_MAX_COMPLEX; + psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.7, 16 ); + psEncC->pitchEstimationLPCOrder = 16; + psEncC->shapingLPCOrder = 16; + psEncC->la_shape = 5 * psEncC->fs_kHz; + psEncC->nStatesDelayedDecision = MAX_DEL_DEC_STATES; + psEncC->useInterpolatedNLSFs = 1; + psEncC->LTPQuantLowComplexity = 0; + psEncC->NLSF_MSVQ_Survivors = 32; + psEncC->warping_Q16 = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 ); + } + + /* Do not allow higher pitch estimation LPC order than predict LPC order */ + psEncC->pitchEstimationLPCOrder = silk_min_int( psEncC->pitchEstimationLPCOrder, psEncC->predictLPCOrder ); + psEncC->shapeWinLength = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape; + psEncC->Complexity = Complexity; + + silk_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER ); + silk_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER ); + silk_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES ); + silk_assert( psEncC->warping_Q16 <= 32767 ); + silk_assert( psEncC->la_shape <= LA_SHAPE_MAX ); + silk_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX ); + silk_assert( psEncC->NLSF_MSVQ_Survivors <= NLSF_VQ_MAX_SURVIVORS ); + + return ret; +} + +static OPUS_INLINE opus_int silk_setup_LBRR( + silk_encoder_state *psEncC, /* I/O */ + const opus_int32 TargetRate_bps /* I */ +) +{ + opus_int ret = SILK_NO_ERROR; + opus_int32 LBRR_rate_thres_bps; + + psEncC->LBRR_enabled = 0; + if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) { + if( psEncC->fs_kHz == 8 ) { + LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS; + } else if( psEncC->fs_kHz == 12 ) { + LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS; + } else { + LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS; + } + LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) ); + + if( TargetRate_bps > LBRR_rate_thres_bps ) { + /* Set gain increase for coding LBRR excitation */ + psEncC->LBRR_enabled = 1; + psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 ); + } + } + + return ret; +} diff --git a/TelegramClient.Opus/opus/silk/debug.c b/TelegramClient.Opus/opus/silk/debug.c new file mode 100755 index 0000000..9253faf --- /dev/null +++ b/TelegramClient.Opus/opus/silk/debug.c @@ -0,0 +1,170 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "debug.h" +#include "SigProc_FIX.h" + +#if SILK_TIC_TOC + +#ifdef _WIN32 + +#if (defined(_WIN32) || defined(_WINCE)) +#include /* timer */ +#else /* Linux or Mac*/ +#include +#endif + +unsigned long silk_GetHighResolutionTime(void) /* O time in usec*/ +{ + /* Returns a time counter in microsec */ + /* the resolution is platform dependent */ + /* but is typically 1.62 us resolution */ + LARGE_INTEGER lpPerformanceCount; + LARGE_INTEGER lpFrequency; + QueryPerformanceCounter(&lpPerformanceCount); + QueryPerformanceFrequency(&lpFrequency); + return (unsigned long)((1000000*(lpPerformanceCount.QuadPart)) / lpFrequency.QuadPart); +} +#else /* Linux or Mac*/ +unsigned long GetHighResolutionTime(void) /* O time in usec*/ +{ + struct timeval tv; + gettimeofday(&tv, 0); + return((tv.tv_sec*1000000)+(tv.tv_usec)); +} +#endif + +int silk_Timer_nTimers = 0; +int silk_Timer_depth_ctr = 0; +char silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN]; +#ifdef WIN32 +LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX]; +#else +unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX]; +#endif +unsigned int silk_Timer_cnt[silk_NUM_TIMERS_MAX]; +opus_int64 silk_Timer_min[silk_NUM_TIMERS_MAX]; +opus_int64 silk_Timer_sum[silk_NUM_TIMERS_MAX]; +opus_int64 silk_Timer_max[silk_NUM_TIMERS_MAX]; +opus_int64 silk_Timer_depth[silk_NUM_TIMERS_MAX]; + +#ifdef WIN32 +void silk_TimerSave(char *file_name) +{ + if( silk_Timer_nTimers > 0 ) + { + int k; + FILE *fp; + LARGE_INTEGER lpFrequency; + LARGE_INTEGER lpPerformanceCount1, lpPerformanceCount2; + int del = 0x7FFFFFFF; + double avg, sum_avg; + /* estimate overhead of calling performance counters */ + for( k = 0; k < 1000; k++ ) { + QueryPerformanceCounter(&lpPerformanceCount1); + QueryPerformanceCounter(&lpPerformanceCount2); + lpPerformanceCount2.QuadPart -= lpPerformanceCount1.QuadPart; + if( (int)lpPerformanceCount2.LowPart < del ) + del = lpPerformanceCount2.LowPart; + } + QueryPerformanceFrequency(&lpFrequency); + /* print results to file */ + sum_avg = 0.0f; + for( k = 0; k < silk_Timer_nTimers; k++ ) { + if (silk_Timer_depth[k] == 0) { + sum_avg += (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart * silk_Timer_cnt[k]; + } + } + fp = fopen(file_name, "w"); + fprintf(fp, " min avg %% max count\n"); + for( k = 0; k < silk_Timer_nTimers; k++ ) { + if (silk_Timer_depth[k] == 0) { + fprintf(fp, "%-28s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 1) { + fprintf(fp, " %-27s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 2) { + fprintf(fp, " %-26s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 3) { + fprintf(fp, " %-25s", silk_Timer_tags[k]); + } else { + fprintf(fp, " %-24s", silk_Timer_tags[k]); + } + avg = (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart; + fprintf(fp, "%8.2f", (1e6 * (silk_max_64(silk_Timer_min[k] - del, 0))) / lpFrequency.QuadPart); + fprintf(fp, "%12.2f %6.2f", avg, 100.0 * avg / sum_avg * silk_Timer_cnt[k]); + fprintf(fp, "%12.2f", (1e6 * (silk_max_64(silk_Timer_max[k] - del, 0))) / lpFrequency.QuadPart); + fprintf(fp, "%10d\n", silk_Timer_cnt[k]); + } + fprintf(fp, " microseconds\n"); + fclose(fp); + } +} +#else +void silk_TimerSave(char *file_name) +{ + if( silk_Timer_nTimers > 0 ) + { + int k; + FILE *fp; + /* print results to file */ + fp = fopen(file_name, "w"); + fprintf(fp, " min avg max count\n"); + for( k = 0; k < silk_Timer_nTimers; k++ ) + { + if (silk_Timer_depth[k] == 0) { + fprintf(fp, "%-28s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 1) { + fprintf(fp, " %-27s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 2) { + fprintf(fp, " %-26s", silk_Timer_tags[k]); + } else if (silk_Timer_depth[k] == 3) { + fprintf(fp, " %-25s", silk_Timer_tags[k]); + } else { + fprintf(fp, " %-24s", silk_Timer_tags[k]); + } + fprintf(fp, "%d ", silk_Timer_min[k]); + fprintf(fp, "%f ", (double)silk_Timer_sum[k] / (double)silk_Timer_cnt[k]); + fprintf(fp, "%d ", silk_Timer_max[k]); + fprintf(fp, "%10d\n", silk_Timer_cnt[k]); + } + fprintf(fp, " microseconds\n"); + fclose(fp); + } +} +#endif + +#endif /* SILK_TIC_TOC */ + +#if SILK_DEBUG +FILE *silk_debug_store_fp[ silk_NUM_STORES_MAX ]; +int silk_debug_store_count = 0; +#endif /* SILK_DEBUG */ + diff --git a/TelegramClient.Opus/opus/silk/debug.h b/TelegramClient.Opus/opus/silk/debug.h new file mode 100755 index 0000000..efb6d3e --- /dev/null +++ b/TelegramClient.Opus/opus/silk/debug.h @@ -0,0 +1,279 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_DEBUG_H +#define SILK_DEBUG_H + +#include "typedef.h" +#include /* file writing */ +#include /* strcpy, strcmp */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +unsigned long GetHighResolutionTime(void); /* O time in usec*/ + +/* make SILK_DEBUG dependent on compiler's _DEBUG */ +#if defined _WIN32 + #ifdef _DEBUG + #define SILK_DEBUG 1 + #else + #define SILK_DEBUG 0 + #endif + + /* overrule the above */ + #if 0 + /* #define NO_ASSERTS*/ + #undef SILK_DEBUG + #define SILK_DEBUG 1 + #endif +#else + #define SILK_DEBUG 0 +#endif + +/* Flag for using timers */ +#define SILK_TIC_TOC 0 + + +#if SILK_TIC_TOC + +#if (defined(_WIN32) || defined(_WINCE)) +#include /* timer */ +#else /* Linux or Mac*/ +#include +#endif + +/*********************************/ +/* timer functions for profiling */ +/*********************************/ +/* example: */ +/* */ +/* TIC(LPC) */ +/* do_LPC(in_vec, order, acoef); // do LPC analysis */ +/* TOC(LPC) */ +/* */ +/* and call the following just before exiting (from main) */ +/* */ +/* silk_TimerSave("silk_TimingData.txt"); */ +/* */ +/* results are now in silk_TimingData.txt */ + +void silk_TimerSave(char *file_name); + +/* max number of timers (in different locations) */ +#define silk_NUM_TIMERS_MAX 50 +/* max length of name tags in TIC(..), TOC(..) */ +#define silk_NUM_TIMERS_MAX_TAG_LEN 30 + +extern int silk_Timer_nTimers; +extern int silk_Timer_depth_ctr; +extern char silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN]; +#ifdef _WIN32 +extern LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX]; +#else +extern unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX]; +#endif +extern unsigned int silk_Timer_cnt[silk_NUM_TIMERS_MAX]; +extern opus_int64 silk_Timer_sum[silk_NUM_TIMERS_MAX]; +extern opus_int64 silk_Timer_max[silk_NUM_TIMERS_MAX]; +extern opus_int64 silk_Timer_min[silk_NUM_TIMERS_MAX]; +extern opus_int64 silk_Timer_depth[silk_NUM_TIMERS_MAX]; + +/* WARNING: TIC()/TOC can measure only up to 0.1 seconds at a time */ +#ifdef _WIN32 +#define TIC(TAG_NAME) { \ + static int init = 0; \ + static int ID = -1; \ + if( init == 0 ) \ + { \ + int k; \ + init = 1; \ + for( k = 0; k < silk_Timer_nTimers; k++ ) { \ + if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ + ID = k; \ + break; \ + } \ + } \ + if (ID == -1) { \ + ID = silk_Timer_nTimers; \ + silk_Timer_nTimers++; \ + silk_Timer_depth[ID] = silk_Timer_depth_ctr; \ + strcpy(silk_Timer_tags[ID], #TAG_NAME); \ + silk_Timer_cnt[ID] = 0; \ + silk_Timer_sum[ID] = 0; \ + silk_Timer_min[ID] = 0xFFFFFFFF; \ + silk_Timer_max[ID] = 0; \ + } \ + } \ + silk_Timer_depth_ctr++; \ + QueryPerformanceCounter(&silk_Timer_start[ID]); \ +} +#else +#define TIC(TAG_NAME) { \ + static int init = 0; \ + static int ID = -1; \ + if( init == 0 ) \ + { \ + int k; \ + init = 1; \ + for( k = 0; k < silk_Timer_nTimers; k++ ) { \ + if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ + ID = k; \ + break; \ + } \ + } \ + if (ID == -1) { \ + ID = silk_Timer_nTimers; \ + silk_Timer_nTimers++; \ + silk_Timer_depth[ID] = silk_Timer_depth_ctr; \ + strcpy(silk_Timer_tags[ID], #TAG_NAME); \ + silk_Timer_cnt[ID] = 0; \ + silk_Timer_sum[ID] = 0; \ + silk_Timer_min[ID] = 0xFFFFFFFF; \ + silk_Timer_max[ID] = 0; \ + } \ + } \ + silk_Timer_depth_ctr++; \ + silk_Timer_start[ID] = GetHighResolutionTime(); \ +} +#endif + +#ifdef _WIN32 +#define TOC(TAG_NAME) { \ + LARGE_INTEGER lpPerformanceCount; \ + static int init = 0; \ + static int ID = 0; \ + if( init == 0 ) \ + { \ + int k; \ + init = 1; \ + for( k = 0; k < silk_Timer_nTimers; k++ ) { \ + if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ + ID = k; \ + break; \ + } \ + } \ + } \ + QueryPerformanceCounter(&lpPerformanceCount); \ + lpPerformanceCount.QuadPart -= silk_Timer_start[ID].QuadPart; \ + if((lpPerformanceCount.QuadPart < 100000000) && \ + (lpPerformanceCount.QuadPart >= 0)) { \ + silk_Timer_cnt[ID]++; \ + silk_Timer_sum[ID] += lpPerformanceCount.QuadPart; \ + if( lpPerformanceCount.QuadPart > silk_Timer_max[ID] ) \ + silk_Timer_max[ID] = lpPerformanceCount.QuadPart; \ + if( lpPerformanceCount.QuadPart < silk_Timer_min[ID] ) \ + silk_Timer_min[ID] = lpPerformanceCount.QuadPart; \ + } \ + silk_Timer_depth_ctr--; \ +} +#else +#define TOC(TAG_NAME) { \ + unsigned long endTime; \ + static int init = 0; \ + static int ID = 0; \ + if( init == 0 ) \ + { \ + int k; \ + init = 1; \ + for( k = 0; k < silk_Timer_nTimers; k++ ) { \ + if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) { \ + ID = k; \ + break; \ + } \ + } \ + } \ + endTime = GetHighResolutionTime(); \ + endTime -= silk_Timer_start[ID]; \ + if((endTime < 100000000) && \ + (endTime >= 0)) { \ + silk_Timer_cnt[ID]++; \ + silk_Timer_sum[ID] += endTime; \ + if( endTime > silk_Timer_max[ID] ) \ + silk_Timer_max[ID] = endTime; \ + if( endTime < silk_Timer_min[ID] ) \ + silk_Timer_min[ID] = endTime; \ + } \ + silk_Timer_depth_ctr--; \ +} +#endif + +#else /* SILK_TIC_TOC */ + +/* define macros as empty strings */ +#define TIC(TAG_NAME) +#define TOC(TAG_NAME) +#define silk_TimerSave(FILE_NAME) + +#endif /* SILK_TIC_TOC */ + + +#if SILK_DEBUG +/************************************/ +/* write data to file for debugging */ +/************************************/ +/* Example: DEBUG_STORE_DATA(testfile.pcm, &RIN[0], 160*sizeof(opus_int16)); */ + +#define silk_NUM_STORES_MAX 100 +extern FILE *silk_debug_store_fp[ silk_NUM_STORES_MAX ]; +extern int silk_debug_store_count; + +/* Faster way of storing the data */ +#define DEBUG_STORE_DATA( FILE_NAME, DATA_PTR, N_BYTES ) { \ + static opus_int init = 0, cnt = 0; \ + static FILE **fp; \ + if (init == 0) { \ + init = 1; \ + cnt = silk_debug_store_count++; \ + silk_debug_store_fp[ cnt ] = fopen(#FILE_NAME, "wb"); \ + } \ + fwrite((DATA_PTR), (N_BYTES), 1, silk_debug_store_fp[ cnt ]); \ +} + +/* Call this at the end of main() */ +#define SILK_DEBUG_STORE_CLOSE_FILES { \ + opus_int i; \ + for( i = 0; i < silk_debug_store_count; i++ ) { \ + fclose( silk_debug_store_fp[ i ] ); \ + } \ +} + +#else /* SILK_DEBUG */ + +/* define macros as empty strings */ +#define DEBUG_STORE_DATA(FILE_NAME, DATA_PTR, N_BYTES) +#define SILK_DEBUG_STORE_CLOSE_FILES + +#endif /* SILK_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* SILK_DEBUG_H */ diff --git a/TelegramClient.Opus/opus/silk/dec_API.c b/TelegramClient.Opus/opus/silk/dec_API.c new file mode 100755 index 0000000..4cbcf71 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/dec_API.c @@ -0,0 +1,397 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "API.h" +#include "main.h" +#include "stack_alloc.h" + +/************************/ +/* Decoder Super Struct */ +/************************/ +typedef struct { + silk_decoder_state channel_state[ DECODER_NUM_CHANNELS ]; + stereo_dec_state sStereo; + opus_int nChannelsAPI; + opus_int nChannelsInternal; + opus_int prev_decode_only_middle; +} silk_decoder; + +/*********************/ +/* Decoder functions */ +/*********************/ + +opus_int silk_Get_Decoder_Size( /* O Returns error code */ + opus_int *decSizeBytes /* O Number of bytes in SILK decoder state */ +) +{ + opus_int ret = SILK_NO_ERROR; + + *decSizeBytes = sizeof( silk_decoder ); + + return ret; +} + +/* Reset decoder state */ +opus_int silk_InitDecoder( /* O Returns error code */ + void *decState /* I/O State */ +) +{ + opus_int n, ret = SILK_NO_ERROR; + silk_decoder_state *channel_state = ((silk_decoder *)decState)->channel_state; + + for( n = 0; n < DECODER_NUM_CHANNELS; n++ ) { + ret = silk_init_decoder( &channel_state[ n ] ); + } + silk_memset(&((silk_decoder *)decState)->sStereo, 0, sizeof(((silk_decoder *)decState)->sStereo)); + /* Not strictly needed, but it's cleaner that way */ + ((silk_decoder *)decState)->prev_decode_only_middle = 0; + + return ret; +} + +/* Decode a frame */ +opus_int silk_Decode( /* O Returns error code */ + void* decState, /* I/O State */ + silk_DecControlStruct* decControl, /* I/O Control Structure */ + opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */ + opus_int newPacketFlag, /* I Indicates first decoder call for this packet */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int16 *samplesOut, /* O Decoded output speech vector */ + opus_int32 *nSamplesOut /* O Number of samples decoded */ +) +{ + opus_int i, n, decode_only_middle = 0, ret = SILK_NO_ERROR; + opus_int32 nSamplesOutDec, LBRR_symbol; + opus_int16 *samplesOut1_tmp[ 2 ]; + VARDECL( opus_int16, samplesOut1_tmp_storage ); + VARDECL( opus_int16, samplesOut2_tmp ); + opus_int32 MS_pred_Q13[ 2 ] = { 0 }; + opus_int16 *resample_out_ptr; + silk_decoder *psDec = ( silk_decoder * )decState; + silk_decoder_state *channel_state = psDec->channel_state; + opus_int has_side; + opus_int stereo_to_mono; + SAVE_STACK; + + silk_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 ); + + /**********************************/ + /* Test if first frame in payload */ + /**********************************/ + if( newPacketFlag ) { + for( n = 0; n < decControl->nChannelsInternal; n++ ) { + channel_state[ n ].nFramesDecoded = 0; /* Used to count frames in packet */ + } + } + + /* If Mono -> Stereo transition in bitstream: init state of second channel */ + if( decControl->nChannelsInternal > psDec->nChannelsInternal ) { + ret += silk_init_decoder( &channel_state[ 1 ] ); + } + + stereo_to_mono = decControl->nChannelsInternal == 1 && psDec->nChannelsInternal == 2 && + ( decControl->internalSampleRate == 1000*channel_state[ 0 ].fs_kHz ); + + if( channel_state[ 0 ].nFramesDecoded == 0 ) { + for( n = 0; n < decControl->nChannelsInternal; n++ ) { + opus_int fs_kHz_dec; + if( decControl->payloadSize_ms == 0 ) { + /* Assuming packet loss, use 10 ms */ + channel_state[ n ].nFramesPerPacket = 1; + channel_state[ n ].nb_subfr = 2; + } else if( decControl->payloadSize_ms == 10 ) { + channel_state[ n ].nFramesPerPacket = 1; + channel_state[ n ].nb_subfr = 2; + } else if( decControl->payloadSize_ms == 20 ) { + channel_state[ n ].nFramesPerPacket = 1; + channel_state[ n ].nb_subfr = 4; + } else if( decControl->payloadSize_ms == 40 ) { + channel_state[ n ].nFramesPerPacket = 2; + channel_state[ n ].nb_subfr = 4; + } else if( decControl->payloadSize_ms == 60 ) { + channel_state[ n ].nFramesPerPacket = 3; + channel_state[ n ].nb_subfr = 4; + } else { + silk_assert( 0 ); + RESTORE_STACK; + return SILK_DEC_INVALID_FRAME_SIZE; + } + fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1; + if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) { + silk_assert( 0 ); + RESTORE_STACK; + return SILK_DEC_INVALID_SAMPLING_FREQUENCY; + } + ret += silk_decoder_set_fs( &channel_state[ n ], fs_kHz_dec, decControl->API_sampleRate ); + } + } + + if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 && ( psDec->nChannelsAPI == 1 || psDec->nChannelsInternal == 1 ) ) { + silk_memset( psDec->sStereo.pred_prev_Q13, 0, sizeof( psDec->sStereo.pred_prev_Q13 ) ); + silk_memset( psDec->sStereo.sSide, 0, sizeof( psDec->sStereo.sSide ) ); + silk_memcpy( &channel_state[ 1 ].resampler_state, &channel_state[ 0 ].resampler_state, sizeof( silk_resampler_state_struct ) ); + } + psDec->nChannelsAPI = decControl->nChannelsAPI; + psDec->nChannelsInternal = decControl->nChannelsInternal; + + if( decControl->API_sampleRate > (opus_int32)MAX_API_FS_KHZ * 1000 || decControl->API_sampleRate < 8000 ) { + ret = SILK_DEC_INVALID_SAMPLING_FREQUENCY; + RESTORE_STACK; + return( ret ); + } + + if( lostFlag != FLAG_PACKET_LOST && channel_state[ 0 ].nFramesDecoded == 0 ) { + /* First decoder call for this payload */ + /* Decode VAD flags and LBRR flag */ + for( n = 0; n < decControl->nChannelsInternal; n++ ) { + for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) { + channel_state[ n ].VAD_flags[ i ] = ec_dec_bit_logp(psRangeDec, 1); + } + channel_state[ n ].LBRR_flag = ec_dec_bit_logp(psRangeDec, 1); + } + /* Decode LBRR flags */ + for( n = 0; n < decControl->nChannelsInternal; n++ ) { + silk_memset( channel_state[ n ].LBRR_flags, 0, sizeof( channel_state[ n ].LBRR_flags ) ); + if( channel_state[ n ].LBRR_flag ) { + if( channel_state[ n ].nFramesPerPacket == 1 ) { + channel_state[ n ].LBRR_flags[ 0 ] = 1; + } else { + LBRR_symbol = ec_dec_icdf( psRangeDec, silk_LBRR_flags_iCDF_ptr[ channel_state[ n ].nFramesPerPacket - 2 ], 8 ) + 1; + for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) { + channel_state[ n ].LBRR_flags[ i ] = silk_RSHIFT( LBRR_symbol, i ) & 1; + } + } + } + } + + if( lostFlag == FLAG_DECODE_NORMAL ) { + /* Regular decoding: skip all LBRR data */ + for( i = 0; i < channel_state[ 0 ].nFramesPerPacket; i++ ) { + for( n = 0; n < decControl->nChannelsInternal; n++ ) { + if( channel_state[ n ].LBRR_flags[ i ] ) { + opus_int pulses[ MAX_FRAME_LENGTH ]; + opus_int condCoding; + + if( decControl->nChannelsInternal == 2 && n == 0 ) { + silk_stereo_decode_pred( psRangeDec, MS_pred_Q13 ); + if( channel_state[ 1 ].LBRR_flags[ i ] == 0 ) { + silk_stereo_decode_mid_only( psRangeDec, &decode_only_middle ); + } + } + /* Use conditional coding if previous frame available */ + if( i > 0 && channel_state[ n ].LBRR_flags[ i - 1 ] ) { + condCoding = CODE_CONDITIONALLY; + } else { + condCoding = CODE_INDEPENDENTLY; + } + silk_decode_indices( &channel_state[ n ], psRangeDec, i, 1, condCoding ); + silk_decode_pulses( psRangeDec, pulses, channel_state[ n ].indices.signalType, + channel_state[ n ].indices.quantOffsetType, channel_state[ n ].frame_length ); + } + } + } + } + } + + /* Get MS predictor index */ + if( decControl->nChannelsInternal == 2 ) { + if( lostFlag == FLAG_DECODE_NORMAL || + ( lostFlag == FLAG_DECODE_LBRR && channel_state[ 0 ].LBRR_flags[ channel_state[ 0 ].nFramesDecoded ] == 1 ) ) + { + silk_stereo_decode_pred( psRangeDec, MS_pred_Q13 ); + /* For LBRR data, decode mid-only flag only if side-channel's LBRR flag is false */ + if( ( lostFlag == FLAG_DECODE_NORMAL && channel_state[ 1 ].VAD_flags[ channel_state[ 0 ].nFramesDecoded ] == 0 ) || + ( lostFlag == FLAG_DECODE_LBRR && channel_state[ 1 ].LBRR_flags[ channel_state[ 0 ].nFramesDecoded ] == 0 ) ) + { + silk_stereo_decode_mid_only( psRangeDec, &decode_only_middle ); + } else { + decode_only_middle = 0; + } + } else { + for( n = 0; n < 2; n++ ) { + MS_pred_Q13[ n ] = psDec->sStereo.pred_prev_Q13[ n ]; + } + } + } + + /* Reset side channel decoder prediction memory for first frame with side coding */ + if( decControl->nChannelsInternal == 2 && decode_only_middle == 0 && psDec->prev_decode_only_middle == 1 ) { + silk_memset( psDec->channel_state[ 1 ].outBuf, 0, sizeof(psDec->channel_state[ 1 ].outBuf) ); + silk_memset( psDec->channel_state[ 1 ].sLPC_Q14_buf, 0, sizeof(psDec->channel_state[ 1 ].sLPC_Q14_buf) ); + psDec->channel_state[ 1 ].lagPrev = 100; + psDec->channel_state[ 1 ].LastGainIndex = 10; + psDec->channel_state[ 1 ].prevSignalType = TYPE_NO_VOICE_ACTIVITY; + psDec->channel_state[ 1 ].first_frame_after_reset = 1; + } + + ALLOC( samplesOut1_tmp_storage, + decControl->nChannelsInternal*( + channel_state[ 0 ].frame_length + 2 ), + opus_int16 ); + samplesOut1_tmp[ 0 ] = samplesOut1_tmp_storage; + samplesOut1_tmp[ 1 ] = samplesOut1_tmp_storage + + channel_state[ 0 ].frame_length + 2; + + if( lostFlag == FLAG_DECODE_NORMAL ) { + has_side = !decode_only_middle; + } else { + has_side = !psDec->prev_decode_only_middle + || (decControl->nChannelsInternal == 2 && lostFlag == FLAG_DECODE_LBRR && channel_state[1].LBRR_flags[ channel_state[1].nFramesDecoded ] == 1 ); + } + /* Call decoder for one frame */ + for( n = 0; n < decControl->nChannelsInternal; n++ ) { + if( n == 0 || has_side ) { + opus_int FrameIndex; + opus_int condCoding; + + FrameIndex = channel_state[ 0 ].nFramesDecoded - n; + /* Use independent coding if no previous frame available */ + if( FrameIndex <= 0 ) { + condCoding = CODE_INDEPENDENTLY; + } else if( lostFlag == FLAG_DECODE_LBRR ) { + condCoding = channel_state[ n ].LBRR_flags[ FrameIndex - 1 ] ? CODE_CONDITIONALLY : CODE_INDEPENDENTLY; + } else if( n > 0 && psDec->prev_decode_only_middle ) { + /* If we skipped a side frame in this packet, we don't + need LTP scaling; the LTP state is well-defined. */ + condCoding = CODE_INDEPENDENTLY_NO_LTP_SCALING; + } else { + condCoding = CODE_CONDITIONALLY; + } + ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag, condCoding); + } else { + silk_memset( &samplesOut1_tmp[ n ][ 2 ], 0, nSamplesOutDec * sizeof( opus_int16 ) ); + } + channel_state[ n ].nFramesDecoded++; + } + + if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) { + /* Convert Mid/Side to Left/Right */ + silk_stereo_MS_to_LR( &psDec->sStereo, samplesOut1_tmp[ 0 ], samplesOut1_tmp[ 1 ], MS_pred_Q13, channel_state[ 0 ].fs_kHz, nSamplesOutDec ); + } else { + /* Buffering */ + silk_memcpy( samplesOut1_tmp[ 0 ], psDec->sStereo.sMid, 2 * sizeof( opus_int16 ) ); + silk_memcpy( psDec->sStereo.sMid, &samplesOut1_tmp[ 0 ][ nSamplesOutDec ], 2 * sizeof( opus_int16 ) ); + } + + /* Number of output samples */ + *nSamplesOut = silk_DIV32( nSamplesOutDec * decControl->API_sampleRate, silk_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ) ); + + /* Set up pointers to temp buffers */ + ALLOC( samplesOut2_tmp, + decControl->nChannelsAPI == 2 ? *nSamplesOut : ALLOC_NONE, opus_int16 ); + if( decControl->nChannelsAPI == 2 ) { + resample_out_ptr = samplesOut2_tmp; + } else { + resample_out_ptr = samplesOut; + } + + for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) { + + /* Resample decoded signal to API_sampleRate */ + ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec ); + + /* Interleave if stereo output and stereo stream */ + if( decControl->nChannelsAPI == 2 ) { + for( i = 0; i < *nSamplesOut; i++ ) { + samplesOut[ n + 2 * i ] = resample_out_ptr[ i ]; + } + } + } + + /* Create two channel output from mono stream */ + if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 1 ) { + if ( stereo_to_mono ){ + /* Resample right channel for newly collapsed stereo just in case + we weren't doing collapsing when switching to mono */ + ret += silk_resampler( &channel_state[ 1 ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ 0 ][ 1 ], nSamplesOutDec ); + + for( i = 0; i < *nSamplesOut; i++ ) { + samplesOut[ 1 + 2 * i ] = resample_out_ptr[ i ]; + } + } else { + for( i = 0; i < *nSamplesOut; i++ ) { + samplesOut[ 1 + 2 * i ] = samplesOut[ 0 + 2 * i ]; + } + } + } + + /* Export pitch lag, measured at 48 kHz sampling rate */ + if( channel_state[ 0 ].prevSignalType == TYPE_VOICED ) { + int mult_tab[ 3 ] = { 6, 4, 3 }; + decControl->prevPitchLag = channel_state[ 0 ].lagPrev * mult_tab[ ( channel_state[ 0 ].fs_kHz - 8 ) >> 2 ]; + } else { + decControl->prevPitchLag = 0; + } + + if( lostFlag == FLAG_PACKET_LOST ) { + /* On packet loss, remove the gain clamping to prevent having the energy "bounce back" + if we lose packets when the energy is going down */ + for ( i = 0; i < psDec->nChannelsInternal; i++ ) + psDec->channel_state[ i ].LastGainIndex = 10; + } else { + psDec->prev_decode_only_middle = decode_only_middle; + } + RESTORE_STACK; + return ret; +} + +#if 0 +/* Getting table of contents for a packet */ +opus_int silk_get_TOC( + const opus_uint8 *payload, /* I Payload data */ + const opus_int nBytesIn, /* I Number of input bytes */ + const opus_int nFramesPerPayload, /* I Number of SILK frames per payload */ + silk_TOC_struct *Silk_TOC /* O Type of content */ +) +{ + opus_int i, flags, ret = SILK_NO_ERROR; + + if( nBytesIn < 1 ) { + return -1; + } + if( nFramesPerPayload < 0 || nFramesPerPayload > 3 ) { + return -1; + } + + silk_memset( Silk_TOC, 0, sizeof( *Silk_TOC ) ); + + /* For stereo, extract the flags for the mid channel */ + flags = silk_RSHIFT( payload[ 0 ], 7 - nFramesPerPayload ) & ( silk_LSHIFT( 1, nFramesPerPayload + 1 ) - 1 ); + + Silk_TOC->inbandFECFlag = flags & 1; + for( i = nFramesPerPayload - 1; i >= 0 ; i-- ) { + flags = silk_RSHIFT( flags, 1 ); + Silk_TOC->VADFlags[ i ] = flags & 1; + Silk_TOC->VADFlag |= flags & 1; + } + + return ret; +} +#endif diff --git a/TelegramClient.Opus/opus/silk/decode_core.c b/TelegramClient.Opus/opus/silk/decode_core.c new file mode 100755 index 0000000..a820bf1 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/decode_core.c @@ -0,0 +1,238 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "stack_alloc.h" + +/**********************************************************/ +/* Core decoder. Performs inverse NSQ operation LTP + LPC */ +/**********************************************************/ +void silk_decode_core( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I Decoder control */ + opus_int16 xq[], /* O Decoded speech */ + const opus_int pulses[ MAX_FRAME_LENGTH ] /* I Pulse signal */ +) +{ + opus_int i, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType; + opus_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ]; + VARDECL( opus_int16, sLTP ); + VARDECL( opus_int32, sLTP_Q15 ); + opus_int32 LTP_pred_Q13, LPC_pred_Q10, Gain_Q10, inv_gain_Q31, gain_adj_Q16, rand_seed, offset_Q10; + opus_int32 *pred_lag_ptr, *pexc_Q14, *pres_Q14; + VARDECL( opus_int32, res_Q14 ); + VARDECL( opus_int32, sLPC_Q14 ); + SAVE_STACK; + + silk_assert( psDec->prev_gain_Q16 != 0 ); + + ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 ); + ALLOC( sLTP_Q15, psDec->ltp_mem_length + psDec->frame_length, opus_int32 ); + ALLOC( res_Q14, psDec->subfr_length, opus_int32 ); + ALLOC( sLPC_Q14, psDec->subfr_length + MAX_LPC_ORDER, opus_int32 ); + + offset_Q10 = silk_Quantization_Offsets_Q10[ psDec->indices.signalType >> 1 ][ psDec->indices.quantOffsetType ]; + + if( psDec->indices.NLSFInterpCoef_Q2 < 1 << 2 ) { + NLSF_interpolation_flag = 1; + } else { + NLSF_interpolation_flag = 0; + } + + /* Decode excitation */ + rand_seed = psDec->indices.Seed; + for( i = 0; i < psDec->frame_length; i++ ) { + rand_seed = silk_RAND( rand_seed ); + psDec->exc_Q14[ i ] = silk_LSHIFT( (opus_int32)pulses[ i ], 14 ); + if( psDec->exc_Q14[ i ] > 0 ) { + psDec->exc_Q14[ i ] -= QUANT_LEVEL_ADJUST_Q10 << 4; + } else + if( psDec->exc_Q14[ i ] < 0 ) { + psDec->exc_Q14[ i ] += QUANT_LEVEL_ADJUST_Q10 << 4; + } + psDec->exc_Q14[ i ] += offset_Q10 << 4; + if( rand_seed < 0 ) { + psDec->exc_Q14[ i ] = -psDec->exc_Q14[ i ]; + } + + rand_seed = silk_ADD32_ovflw( rand_seed, pulses[ i ] ); + } + + /* Copy LPC state */ + silk_memcpy( sLPC_Q14, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) ); + + pexc_Q14 = psDec->exc_Q14; + pxq = xq; + sLTP_buf_idx = psDec->ltp_mem_length; + /* Loop over subframes */ + for( k = 0; k < psDec->nb_subfr; k++ ) { + pres_Q14 = res_Q14; + A_Q12 = psDecCtrl->PredCoef_Q12[ k >> 1 ]; + + /* Preload LPC coeficients to array on stack. Gives small performance gain */ + silk_memcpy( A_Q12_tmp, A_Q12, psDec->LPC_order * sizeof( opus_int16 ) ); + B_Q14 = &psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER ]; + signalType = psDec->indices.signalType; + + Gain_Q10 = silk_RSHIFT( psDecCtrl->Gains_Q16[ k ], 6 ); + inv_gain_Q31 = silk_INVERSE32_varQ( psDecCtrl->Gains_Q16[ k ], 47 ); + + /* Calculate gain adjustment factor */ + if( psDecCtrl->Gains_Q16[ k ] != psDec->prev_gain_Q16 ) { + gain_adj_Q16 = silk_DIV32_varQ( psDec->prev_gain_Q16, psDecCtrl->Gains_Q16[ k ], 16 ); + + /* Scale short term state */ + for( i = 0; i < MAX_LPC_ORDER; i++ ) { + sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, sLPC_Q14[ i ] ); + } + } else { + gain_adj_Q16 = (opus_int32)1 << 16; + } + + /* Save inv_gain */ + silk_assert( inv_gain_Q31 != 0 ); + psDec->prev_gain_Q16 = psDecCtrl->Gains_Q16[ k ]; + + /* Avoid abrupt transition from voiced PLC to unvoiced normal decoding */ + if( psDec->lossCnt && psDec->prevSignalType == TYPE_VOICED && + psDec->indices.signalType != TYPE_VOICED && k < MAX_NB_SUBFR/2 ) { + + silk_memset( B_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) ); + B_Q14[ LTP_ORDER/2 ] = SILK_FIX_CONST( 0.25, 14 ); + + signalType = TYPE_VOICED; + psDecCtrl->pitchL[ k ] = psDec->lagPrev; + } + + if( signalType == TYPE_VOICED ) { + /* Voiced */ + lag = psDecCtrl->pitchL[ k ]; + + /* Re-whitening */ + if( k == 0 || ( k == 2 && NLSF_interpolation_flag ) ) { + /* Rewhiten with new A coefs */ + start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2; + silk_assert( start_idx > 0 ); + + if( k == 2 ) { + silk_memcpy( &psDec->outBuf[ psDec->ltp_mem_length ], xq, 2 * psDec->subfr_length * sizeof( opus_int16 ) ); + } + + silk_LPC_analysis_filter( &sLTP[ start_idx ], &psDec->outBuf[ start_idx + k * psDec->subfr_length ], + A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order ); + + /* After rewhitening the LTP state is unscaled */ + if( k == 0 ) { + /* Do LTP downscaling to reduce inter-packet dependency */ + inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, psDecCtrl->LTP_scale_Q14 ), 2 ); + } + for( i = 0; i < lag + LTP_ORDER/2; i++ ) { + sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWB( inv_gain_Q31, sLTP[ psDec->ltp_mem_length - i - 1 ] ); + } + } else { + /* Update LTP state when Gain changes */ + if( gain_adj_Q16 != (opus_int32)1 << 16 ) { + for( i = 0; i < lag + LTP_ORDER/2; i++ ) { + sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ sLTP_buf_idx - i - 1 ] ); + } + } + } + } + + /* Long-term prediction */ + if( signalType == TYPE_VOICED ) { + /* Set up pointer */ + pred_lag_ptr = &sLTP_Q15[ sLTP_buf_idx - lag + LTP_ORDER / 2 ]; + for( i = 0; i < psDec->subfr_length; i++ ) { + /* Unrolled loop */ + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LTP_pred_Q13 = 2; + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ 0 ], B_Q14[ 0 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], B_Q14[ 1 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], B_Q14[ 2 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], B_Q14[ 3 ] ); + LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], B_Q14[ 4 ] ); + pred_lag_ptr++; + + /* Generate LPC excitation */ + pres_Q14[ i ] = silk_ADD_LSHIFT32( pexc_Q14[ i ], LTP_pred_Q13, 1 ); + + /* Update states */ + sLTP_Q15[ sLTP_buf_idx ] = silk_LSHIFT( pres_Q14[ i ], 1 ); + sLTP_buf_idx++; + } + } else { + pres_Q14 = pexc_Q14; + } + + for( i = 0; i < psDec->subfr_length; i++ ) { + /* Short-term prediction */ + silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 ); + /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ + LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12_tmp[ 1 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp[ 2 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12_tmp[ 3 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12_tmp[ 4 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12_tmp[ 5 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12_tmp[ 6 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp[ 7 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12_tmp[ 8 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] ); + if( psDec->LPC_order == 16 ) { + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12_tmp[ 10 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12_tmp[ 11 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12_tmp[ 12 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12_tmp[ 13 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12_tmp[ 14 ] ); + LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12_tmp[ 15 ] ); + } + + /* Add prediction to LPC excitation */ + sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( pres_Q14[ i ], LPC_pred_Q10, 4 ); + + /* Scale with gain */ + pxq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) ); + } + + /* DEBUG_STORE_DATA( dec.pcm, pxq, psDec->subfr_length * sizeof( opus_int16 ) ) */ + + /* Update LPC filter state */ + silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); + pexc_Q14 += psDec->subfr_length; + pxq += psDec->subfr_length; + } + + /* Save LPC state */ + silk_memcpy( psDec->sLPC_Q14_buf, sLPC_Q14, MAX_LPC_ORDER * sizeof( opus_int32 ) ); + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/decode_frame.c b/TelegramClient.Opus/opus/silk/decode_frame.c new file mode 100755 index 0000000..abc00a3 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/decode_frame.c @@ -0,0 +1,128 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "stack_alloc.h" +#include "PLC.h" + +/****************/ +/* Decode frame */ +/****************/ +opus_int silk_decode_frame( + silk_decoder_state *psDec, /* I/O Pointer to Silk decoder state */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int16 pOut[], /* O Pointer to output speech frame */ + opus_int32 *pN, /* O Pointer to size of output frame */ + opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */ + opus_int condCoding /* I The type of conditional coding to use */ +) +{ + VARDECL( silk_decoder_control, psDecCtrl ); + opus_int L, mv_len, ret = 0; + VARDECL( opus_int, pulses ); + SAVE_STACK; + + L = psDec->frame_length; + ALLOC( psDecCtrl, 1, silk_decoder_control ); + ALLOC( pulses, (L + SHELL_CODEC_FRAME_LENGTH - 1) & + ~(SHELL_CODEC_FRAME_LENGTH - 1), opus_int ); + psDecCtrl->LTP_scale_Q14 = 0; + + /* Safety checks */ + silk_assert( L > 0 && L <= MAX_FRAME_LENGTH ); + + if( lostFlag == FLAG_DECODE_NORMAL || + ( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) ) + { + /*********************************************/ + /* Decode quantization indices of side info */ + /*********************************************/ + silk_decode_indices( psDec, psRangeDec, psDec->nFramesDecoded, lostFlag, condCoding ); + + /*********************************************/ + /* Decode quantization indices of excitation */ + /*********************************************/ + silk_decode_pulses( psRangeDec, pulses, psDec->indices.signalType, + psDec->indices.quantOffsetType, psDec->frame_length ); + + /********************************************/ + /* Decode parameters and pulse signal */ + /********************************************/ + silk_decode_parameters( psDec, psDecCtrl, condCoding ); + + /********************************************************/ + /* Run inverse NSQ */ + /********************************************************/ + silk_decode_core( psDec, psDecCtrl, pOut, pulses ); + + /********************************************************/ + /* Update PLC state */ + /********************************************************/ + silk_PLC( psDec, psDecCtrl, pOut, 0 ); + + psDec->lossCnt = 0; + psDec->prevSignalType = psDec->indices.signalType; + silk_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 ); + + /* A frame has been decoded without errors */ + psDec->first_frame_after_reset = 0; + } else { + /* Handle packet loss by extrapolation */ + silk_PLC( psDec, psDecCtrl, pOut, 1 ); + } + + /*************************/ + /* Update output buffer. */ + /*************************/ + silk_assert( psDec->ltp_mem_length >= psDec->frame_length ); + mv_len = psDec->ltp_mem_length - psDec->frame_length; + silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) ); + silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) ); + + /****************************************************************/ + /* Ensure smooth connection of extrapolated and good frames */ + /****************************************************************/ + silk_PLC_glue_frames( psDec, pOut, L ); + + /************************************************/ + /* Comfort noise generation / estimation */ + /************************************************/ + silk_CNG( psDec, psDecCtrl, pOut, L ); + + /* Update some decoder state variables */ + psDec->lagPrev = psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; + + /* Set output frame length */ + *pN = L; + + RESTORE_STACK; + return ret; +} diff --git a/TelegramClient.Opus/opus/silk/decode_indices.c b/TelegramClient.Opus/opus/silk/decode_indices.c new file mode 100755 index 0000000..7afe5c2 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/decode_indices.c @@ -0,0 +1,151 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Decode side-information parameters from payload */ +void silk_decode_indices( + silk_decoder_state *psDec, /* I/O State */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int FrameIndex, /* I Frame number */ + opus_int decode_LBRR, /* I Flag indicating LBRR data is being decoded */ + opus_int condCoding /* I The type of conditional coding to use */ +) +{ + opus_int i, k, Ix; + opus_int decode_absolute_lagIndex, delta_lagIndex; + opus_int16 ec_ix[ MAX_LPC_ORDER ]; + opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; + + /*******************************************/ + /* Decode signal type and quantizer offset */ + /*******************************************/ + if( decode_LBRR || psDec->VAD_flags[ FrameIndex ] ) { + Ix = ec_dec_icdf( psRangeDec, silk_type_offset_VAD_iCDF, 8 ) + 2; + } else { + Ix = ec_dec_icdf( psRangeDec, silk_type_offset_no_VAD_iCDF, 8 ); + } + psDec->indices.signalType = (opus_int8)silk_RSHIFT( Ix, 1 ); + psDec->indices.quantOffsetType = (opus_int8)( Ix & 1 ); + + /****************/ + /* Decode gains */ + /****************/ + /* First subframe */ + if( condCoding == CODE_CONDITIONALLY ) { + /* Conditional coding */ + psDec->indices.GainsIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 ); + } else { + /* Independent coding, in two stages: MSB bits followed by 3 LSBs */ + psDec->indices.GainsIndices[ 0 ] = (opus_int8)silk_LSHIFT( ec_dec_icdf( psRangeDec, silk_gain_iCDF[ psDec->indices.signalType ], 8 ), 3 ); + psDec->indices.GainsIndices[ 0 ] += (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform8_iCDF, 8 ); + } + + /* Remaining subframes */ + for( i = 1; i < psDec->nb_subfr; i++ ) { + psDec->indices.GainsIndices[ i ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 ); + } + + /**********************/ + /* Decode LSF Indices */ + /**********************/ + psDec->indices.NLSFIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 ); + silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] ); + silk_assert( psDec->psNLSF_CB->order == psDec->LPC_order ); + for( i = 0; i < psDec->psNLSF_CB->order; i++ ) { + Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); + if( Ix == 0 ) { + Ix -= ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 ); + } else if( Ix == 2 * NLSF_QUANT_MAX_AMPLITUDE ) { + Ix += ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 ); + } + psDec->indices.NLSFIndices[ i+1 ] = (opus_int8)( Ix - NLSF_QUANT_MAX_AMPLITUDE ); + } + + /* Decode LSF interpolation factor */ + if( psDec->nb_subfr == MAX_NB_SUBFR ) { + psDec->indices.NLSFInterpCoef_Q2 = (opus_int8)ec_dec_icdf( psRangeDec, silk_NLSF_interpolation_factor_iCDF, 8 ); + } else { + psDec->indices.NLSFInterpCoef_Q2 = 4; + } + + if( psDec->indices.signalType == TYPE_VOICED ) + { + /*********************/ + /* Decode pitch lags */ + /*********************/ + /* Get lag index */ + decode_absolute_lagIndex = 1; + if( condCoding == CODE_CONDITIONALLY && psDec->ec_prevSignalType == TYPE_VOICED ) { + /* Decode Delta index */ + delta_lagIndex = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_delta_iCDF, 8 ); + if( delta_lagIndex > 0 ) { + delta_lagIndex = delta_lagIndex - 9; + psDec->indices.lagIndex = (opus_int16)( psDec->ec_prevLagIndex + delta_lagIndex ); + decode_absolute_lagIndex = 0; + } + } + if( decode_absolute_lagIndex ) { + /* Absolute decoding */ + psDec->indices.lagIndex = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_lag_iCDF, 8 ) * silk_RSHIFT( psDec->fs_kHz, 1 ); + psDec->indices.lagIndex += (opus_int16)ec_dec_icdf( psRangeDec, psDec->pitch_lag_low_bits_iCDF, 8 ); + } + psDec->ec_prevLagIndex = psDec->indices.lagIndex; + + /* Get countour index */ + psDec->indices.contourIndex = (opus_int8)ec_dec_icdf( psRangeDec, psDec->pitch_contour_iCDF, 8 ); + + /********************/ + /* Decode LTP gains */ + /********************/ + /* Decode PERIndex value */ + psDec->indices.PERIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_per_index_iCDF, 8 ); + + for( k = 0; k < psDec->nb_subfr; k++ ) { + psDec->indices.LTPIndex[ k ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_gain_iCDF_ptrs[ psDec->indices.PERIndex ], 8 ); + } + + /**********************/ + /* Decode LTP scaling */ + /**********************/ + if( condCoding == CODE_INDEPENDENTLY ) { + psDec->indices.LTP_scaleIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTPscale_iCDF, 8 ); + } else { + psDec->indices.LTP_scaleIndex = 0; + } + } + psDec->ec_prevSignalType = psDec->indices.signalType; + + /***************/ + /* Decode seed */ + /***************/ + psDec->indices.Seed = (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform4_iCDF, 8 ); +} diff --git a/TelegramClient.Opus/opus/silk/decode_parameters.c b/TelegramClient.Opus/opus/silk/decode_parameters.c new file mode 100755 index 0000000..e345b1d --- /dev/null +++ b/TelegramClient.Opus/opus/silk/decode_parameters.c @@ -0,0 +1,115 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Decode parameters from payload */ +void silk_decode_parameters( + silk_decoder_state *psDec, /* I/O State */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int condCoding /* I The type of conditional coding to use */ +) +{ + opus_int i, k, Ix; + opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], pNLSF0_Q15[ MAX_LPC_ORDER ]; + const opus_int8 *cbk_ptr_Q7; + + /* Dequant Gains */ + silk_gains_dequant( psDecCtrl->Gains_Q16, psDec->indices.GainsIndices, + &psDec->LastGainIndex, condCoding == CODE_CONDITIONALLY, psDec->nb_subfr ); + + /****************/ + /* Decode NLSFs */ + /****************/ + silk_NLSF_decode( pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB ); + + /* Convert NLSF parameters to AR prediction filter coefficients */ + silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order ); + + /* If just reset, e.g., because internal Fs changed, do not allow interpolation */ + /* improves the case of packet loss in the first frame after a switch */ + if( psDec->first_frame_after_reset == 1 ) { + psDec->indices.NLSFInterpCoef_Q2 = 4; + } + + if( psDec->indices.NLSFInterpCoef_Q2 < 4 ) { + /* Calculation of the interpolated NLSF0 vector from the interpolation factor, */ + /* the previous NLSF1, and the current NLSF1 */ + for( i = 0; i < psDec->LPC_order; i++ ) { + pNLSF0_Q15[ i ] = psDec->prevNLSF_Q15[ i ] + silk_RSHIFT( silk_MUL( psDec->indices.NLSFInterpCoef_Q2, + pNLSF_Q15[ i ] - psDec->prevNLSF_Q15[ i ] ), 2 ); + } + + /* Convert NLSF parameters to AR prediction filter coefficients */ + silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order ); + } else { + /* Copy LPC coefficients for first half from second half */ + silk_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) ); + } + + silk_memcpy( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( opus_int16 ) ); + + /* After a packet loss do BWE of LPC coefs */ + if( psDec->lossCnt ) { + silk_bwexpander( psDecCtrl->PredCoef_Q12[ 0 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 ); + silk_bwexpander( psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 ); + } + + if( psDec->indices.signalType == TYPE_VOICED ) { + /*********************/ + /* Decode pitch lags */ + /*********************/ + + /* Decode pitch values */ + silk_decode_pitch( psDec->indices.lagIndex, psDec->indices.contourIndex, psDecCtrl->pitchL, psDec->fs_kHz, psDec->nb_subfr ); + + /* Decode Codebook Index */ + cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ psDec->indices.PERIndex ]; /* set pointer to start of codebook */ + + for( k = 0; k < psDec->nb_subfr; k++ ) { + Ix = psDec->indices.LTPIndex[ k ]; + for( i = 0; i < LTP_ORDER; i++ ) { + psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER + i ] = silk_LSHIFT( cbk_ptr_Q7[ Ix * LTP_ORDER + i ], 7 ); + } + } + + /**********************/ + /* Decode LTP scaling */ + /**********************/ + Ix = psDec->indices.LTP_scaleIndex; + psDecCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ Ix ]; + } else { + silk_memset( psDecCtrl->pitchL, 0, psDec->nb_subfr * sizeof( opus_int ) ); + silk_memset( psDecCtrl->LTPCoef_Q14, 0, LTP_ORDER * psDec->nb_subfr * sizeof( opus_int16 ) ); + psDec->indices.PERIndex = 0; + psDecCtrl->LTP_scale_Q14 = 0; + } +} diff --git a/TelegramClient.Opus/opus/silk/decode_pitch.c b/TelegramClient.Opus/opus/silk/decode_pitch.c new file mode 100755 index 0000000..fedbc6a --- /dev/null +++ b/TelegramClient.Opus/opus/silk/decode_pitch.c @@ -0,0 +1,77 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/*********************************************************** +* Pitch analyser function +********************************************************** */ +#include "SigProc_FIX.h" +#include "pitch_est_defines.h" + +void silk_decode_pitch( + opus_int16 lagIndex, /* I */ + opus_int8 contourIndex, /* O */ + opus_int pitch_lags[], /* O 4 pitch values */ + const opus_int Fs_kHz, /* I sampling frequency (kHz) */ + const opus_int nb_subfr /* I number of sub frames */ +) +{ + opus_int lag, k, min_lag, max_lag, cbk_size; + const opus_int8 *Lag_CB_ptr; + + if( Fs_kHz == 8 ) { + if( nb_subfr == PE_MAX_NB_SUBFR ) { + Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ]; + cbk_size = PE_NB_CBKS_STAGE2_EXT; + } else { + silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 ); + Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ]; + cbk_size = PE_NB_CBKS_STAGE2_10MS; + } + } else { + if( nb_subfr == PE_MAX_NB_SUBFR ) { + Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; + cbk_size = PE_NB_CBKS_STAGE3_MAX; + } else { + silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 ); + Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; + cbk_size = PE_NB_CBKS_STAGE3_10MS; + } + } + + min_lag = silk_SMULBB( PE_MIN_LAG_MS, Fs_kHz ); + max_lag = silk_SMULBB( PE_MAX_LAG_MS, Fs_kHz ); + lag = min_lag + lagIndex; + + for( k = 0; k < nb_subfr; k++ ) { + pitch_lags[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, contourIndex, cbk_size ); + pitch_lags[ k ] = silk_LIMIT( pitch_lags[ k ], min_lag, max_lag ); + } +} diff --git a/TelegramClient.Opus/opus/silk/decode_pulses.c b/TelegramClient.Opus/opus/silk/decode_pulses.c new file mode 100755 index 0000000..e8a87c2 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/decode_pulses.c @@ -0,0 +1,115 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/*********************************************/ +/* Decode quantization indices of excitation */ +/*********************************************/ +void silk_decode_pulses( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int pulses[], /* O Excitation signal */ + const opus_int signalType, /* I Sigtype */ + const opus_int quantOffsetType, /* I quantOffsetType */ + const opus_int frame_length /* I Frame length */ +) +{ + opus_int i, j, k, iter, abs_q, nLS, RateLevelIndex; + opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ], nLshifts[ MAX_NB_SHELL_BLOCKS ]; + opus_int *pulses_ptr; + const opus_uint8 *cdf_ptr; + + /*********************/ + /* Decode rate level */ + /*********************/ + RateLevelIndex = ec_dec_icdf( psRangeDec, silk_rate_levels_iCDF[ signalType >> 1 ], 8 ); + + /* Calculate number of shell blocks */ + silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH ); + iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH ); + if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) { + silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */ + iter++; + } + + /***************************************************/ + /* Sum-Weighted-Pulses Decoding */ + /***************************************************/ + cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ]; + for( i = 0; i < iter; i++ ) { + nLshifts[ i ] = 0; + sum_pulses[ i ] = ec_dec_icdf( psRangeDec, cdf_ptr, 8 ); + + /* LSB indication */ + while( sum_pulses[ i ] == MAX_PULSES + 1 ) { + nLshifts[ i ]++; + /* When we've already got 10 LSBs, we shift the table to not allow (MAX_PULSES + 1) */ + sum_pulses[ i ] = ec_dec_icdf( psRangeDec, + silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1] + ( nLshifts[ i ] == 10 ), 8 ); + } + } + + /***************************************************/ + /* Shell decoding */ + /***************************************************/ + for( i = 0; i < iter; i++ ) { + if( sum_pulses[ i ] > 0 ) { + silk_shell_decoder( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], psRangeDec, sum_pulses[ i ] ); + } else { + silk_memset( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof( opus_int ) ); + } + } + + /***************************************************/ + /* LSB Decoding */ + /***************************************************/ + for( i = 0; i < iter; i++ ) { + if( nLshifts[ i ] > 0 ) { + nLS = nLshifts[ i ]; + pulses_ptr = &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ]; + for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { + abs_q = pulses_ptr[ k ]; + for( j = 0; j < nLS; j++ ) { + abs_q = silk_LSHIFT( abs_q, 1 ); + abs_q += ec_dec_icdf( psRangeDec, silk_lsb_iCDF, 8 ); + } + pulses_ptr[ k ] = abs_q; + } + /* Mark the number of pulses non-zero for sign decoding. */ + sum_pulses[ i ] |= nLS << 5; + } + } + + /****************************************/ + /* Decode and add signs to pulse signal */ + /****************************************/ + silk_decode_signs( psRangeDec, pulses, frame_length, signalType, quantOffsetType, sum_pulses ); +} diff --git a/TelegramClient.Opus/opus/silk/decoder_set_fs.c b/TelegramClient.Opus/opus/silk/decoder_set_fs.c new file mode 100755 index 0000000..eef0fd2 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/decoder_set_fs.c @@ -0,0 +1,108 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Set decoder sampling rate */ +opus_int silk_decoder_set_fs( + silk_decoder_state *psDec, /* I/O Decoder state pointer */ + opus_int fs_kHz, /* I Sampling frequency (kHz) */ + opus_int32 fs_API_Hz /* I API Sampling frequency (Hz) */ +) +{ + opus_int frame_length, ret = 0; + + silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 ); + silk_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 ); + + /* New (sub)frame length */ + psDec->subfr_length = silk_SMULBB( SUB_FRAME_LENGTH_MS, fs_kHz ); + frame_length = silk_SMULBB( psDec->nb_subfr, psDec->subfr_length ); + + /* Initialize resampler when switching internal or external sampling frequency */ + if( psDec->fs_kHz != fs_kHz || psDec->fs_API_hz != fs_API_Hz ) { + /* Initialize the resampler for dec_API.c preparing resampling from fs_kHz to API_fs_Hz */ + ret += silk_resampler_init( &psDec->resampler_state, silk_SMULBB( fs_kHz, 1000 ), fs_API_Hz, 0 ); + + psDec->fs_API_hz = fs_API_Hz; + } + + if( psDec->fs_kHz != fs_kHz || frame_length != psDec->frame_length ) { + if( fs_kHz == 8 ) { + if( psDec->nb_subfr == MAX_NB_SUBFR ) { + psDec->pitch_contour_iCDF = silk_pitch_contour_NB_iCDF; + } else { + psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF; + } + } else { + if( psDec->nb_subfr == MAX_NB_SUBFR ) { + psDec->pitch_contour_iCDF = silk_pitch_contour_iCDF; + } else { + psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF; + } + } + if( psDec->fs_kHz != fs_kHz ) { + psDec->ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz ); + if( fs_kHz == 8 || fs_kHz == 12 ) { + psDec->LPC_order = MIN_LPC_ORDER; + psDec->psNLSF_CB = &silk_NLSF_CB_NB_MB; + } else { + psDec->LPC_order = MAX_LPC_ORDER; + psDec->psNLSF_CB = &silk_NLSF_CB_WB; + } + if( fs_kHz == 16 ) { + psDec->pitch_lag_low_bits_iCDF = silk_uniform8_iCDF; + } else if( fs_kHz == 12 ) { + psDec->pitch_lag_low_bits_iCDF = silk_uniform6_iCDF; + } else if( fs_kHz == 8 ) { + psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF; + } else { + /* unsupported sampling rate */ + silk_assert( 0 ); + } + psDec->first_frame_after_reset = 1; + psDec->lagPrev = 100; + psDec->LastGainIndex = 10; + psDec->prevSignalType = TYPE_NO_VOICE_ACTIVITY; + silk_memset( psDec->outBuf, 0, sizeof(psDec->outBuf)); + silk_memset( psDec->sLPC_Q14_buf, 0, sizeof(psDec->sLPC_Q14_buf) ); + } + + psDec->fs_kHz = fs_kHz; + psDec->frame_length = frame_length; + } + + /* Check that settings are valid */ + silk_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH ); + + return ret; +} + diff --git a/TelegramClient.Opus/opus/silk/define.h b/TelegramClient.Opus/opus/silk/define.h new file mode 100755 index 0000000..c47aca9 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/define.h @@ -0,0 +1,235 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_DEFINE_H +#define SILK_DEFINE_H + +#include "errors.h" +#include "typedef.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Max number of encoder channels (1/2) */ +#define ENCODER_NUM_CHANNELS 2 +/* Number of decoder channels (1/2) */ +#define DECODER_NUM_CHANNELS 2 + +#define MAX_FRAMES_PER_PACKET 3 + +/* Limits on bitrate */ +#define MIN_TARGET_RATE_BPS 5000 +#define MAX_TARGET_RATE_BPS 80000 +#define TARGET_RATE_TAB_SZ 8 + +/* LBRR thresholds */ +#define LBRR_NB_MIN_RATE_BPS 12000 +#define LBRR_MB_MIN_RATE_BPS 14000 +#define LBRR_WB_MIN_RATE_BPS 16000 + +/* DTX settings */ +#define NB_SPEECH_FRAMES_BEFORE_DTX 10 /* eq 200 ms */ +#define MAX_CONSECUTIVE_DTX 20 /* eq 400 ms */ + +/* Maximum sampling frequency */ +#define MAX_FS_KHZ 16 +#define MAX_API_FS_KHZ 48 + +/* Signal types */ +#define TYPE_NO_VOICE_ACTIVITY 0 +#define TYPE_UNVOICED 1 +#define TYPE_VOICED 2 + +/* Conditional coding types */ +#define CODE_INDEPENDENTLY 0 +#define CODE_INDEPENDENTLY_NO_LTP_SCALING 1 +#define CODE_CONDITIONALLY 2 + +/* Settings for stereo processing */ +#define STEREO_QUANT_TAB_SIZE 16 +#define STEREO_QUANT_SUB_STEPS 5 +#define STEREO_INTERP_LEN_MS 8 /* must be even */ +#define STEREO_RATIO_SMOOTH_COEF 0.01 /* smoothing coef for signal norms and stereo width */ + +/* Range of pitch lag estimates */ +#define PITCH_EST_MIN_LAG_MS 2 /* 2 ms -> 500 Hz */ +#define PITCH_EST_MAX_LAG_MS 18 /* 18 ms -> 56 Hz */ + +/* Maximum number of subframes */ +#define MAX_NB_SUBFR 4 + +/* Number of samples per frame */ +#define LTP_MEM_LENGTH_MS 20 +#define SUB_FRAME_LENGTH_MS 5 +#define MAX_SUB_FRAME_LENGTH ( SUB_FRAME_LENGTH_MS * MAX_FS_KHZ ) +#define MAX_FRAME_LENGTH_MS ( SUB_FRAME_LENGTH_MS * MAX_NB_SUBFR ) +#define MAX_FRAME_LENGTH ( MAX_FRAME_LENGTH_MS * MAX_FS_KHZ ) + +/* Milliseconds of lookahead for pitch analysis */ +#define LA_PITCH_MS 2 +#define LA_PITCH_MAX ( LA_PITCH_MS * MAX_FS_KHZ ) + +/* Order of LPC used in find pitch */ +#define MAX_FIND_PITCH_LPC_ORDER 16 + +/* Length of LPC window used in find pitch */ +#define FIND_PITCH_LPC_WIN_MS ( 20 + (LA_PITCH_MS << 1) ) +#define FIND_PITCH_LPC_WIN_MS_2_SF ( 10 + (LA_PITCH_MS << 1) ) +#define FIND_PITCH_LPC_WIN_MAX ( FIND_PITCH_LPC_WIN_MS * MAX_FS_KHZ ) + +/* Milliseconds of lookahead for noise shape analysis */ +#define LA_SHAPE_MS 5 +#define LA_SHAPE_MAX ( LA_SHAPE_MS * MAX_FS_KHZ ) + +/* Maximum length of LPC window used in noise shape analysis */ +#define SHAPE_LPC_WIN_MAX ( 15 * MAX_FS_KHZ ) + +/* dB level of lowest gain quantization level */ +#define MIN_QGAIN_DB 2 +/* dB level of highest gain quantization level */ +#define MAX_QGAIN_DB 88 +/* Number of gain quantization levels */ +#define N_LEVELS_QGAIN 64 +/* Max increase in gain quantization index */ +#define MAX_DELTA_GAIN_QUANT 36 +/* Max decrease in gain quantization index */ +#define MIN_DELTA_GAIN_QUANT -4 + +/* Quantization offsets (multiples of 4) */ +#define OFFSET_VL_Q10 32 +#define OFFSET_VH_Q10 100 +#define OFFSET_UVL_Q10 100 +#define OFFSET_UVH_Q10 240 + +#define QUANT_LEVEL_ADJUST_Q10 80 + +/* Maximum numbers of iterations used to stabilize an LPC vector */ +#define MAX_LPC_STABILIZE_ITERATIONS 16 +#define MAX_PREDICTION_POWER_GAIN 1e4f +#define MAX_PREDICTION_POWER_GAIN_AFTER_RESET 1e2f + +#define MAX_LPC_ORDER 16 +#define MIN_LPC_ORDER 10 + +/* Find Pred Coef defines */ +#define LTP_ORDER 5 + +/* LTP quantization settings */ +#define NB_LTP_CBKS 3 + +/* Flag to use harmonic noise shaping */ +#define USE_HARM_SHAPING 1 + +/* Max LPC order of noise shaping filters */ +#define MAX_SHAPE_LPC_ORDER 16 + +#define HARM_SHAPE_FIR_TAPS 3 + +/* Maximum number of delayed decision states */ +#define MAX_DEL_DEC_STATES 4 + +#define LTP_BUF_LENGTH 512 +#define LTP_MASK ( LTP_BUF_LENGTH - 1 ) + +#define DECISION_DELAY 32 +#define DECISION_DELAY_MASK ( DECISION_DELAY - 1 ) + +/* Number of subframes for excitation entropy coding */ +#define SHELL_CODEC_FRAME_LENGTH 16 +#define LOG2_SHELL_CODEC_FRAME_LENGTH 4 +#define MAX_NB_SHELL_BLOCKS ( MAX_FRAME_LENGTH / SHELL_CODEC_FRAME_LENGTH ) + +/* Number of rate levels, for entropy coding of excitation */ +#define N_RATE_LEVELS 10 + +/* Maximum sum of pulses per shell coding frame */ +#define MAX_PULSES 16 + +#define MAX_MATRIX_SIZE MAX_LPC_ORDER /* Max of LPC Order and LTP order */ + +#if( MAX_LPC_ORDER > DECISION_DELAY ) +# define NSQ_LPC_BUF_LENGTH MAX_LPC_ORDER +#else +# define NSQ_LPC_BUF_LENGTH DECISION_DELAY +#endif + +/***************************/ +/* Voice activity detector */ +/***************************/ +#define VAD_N_BANDS 4 + +#define VAD_INTERNAL_SUBFRAMES_LOG2 2 +#define VAD_INTERNAL_SUBFRAMES ( 1 << VAD_INTERNAL_SUBFRAMES_LOG2 ) + +#define VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 1024 /* Must be < 4096 */ +#define VAD_NOISE_LEVELS_BIAS 50 + +/* Sigmoid settings */ +#define VAD_NEGATIVE_OFFSET_Q5 128 /* sigmoid is 0 at -128 */ +#define VAD_SNR_FACTOR_Q16 45000 + +/* smoothing for SNR measurement */ +#define VAD_SNR_SMOOTH_COEF_Q18 4096 + +/* Size of the piecewise linear cosine approximation table for the LSFs */ +#define LSF_COS_TAB_SZ_FIX 128 + +/******************/ +/* NLSF quantizer */ +/******************/ +#define NLSF_W_Q 2 +#define NLSF_VQ_MAX_VECTORS 32 +#define NLSF_VQ_MAX_SURVIVORS 32 +#define NLSF_QUANT_MAX_AMPLITUDE 4 +#define NLSF_QUANT_MAX_AMPLITUDE_EXT 10 +#define NLSF_QUANT_LEVEL_ADJ 0.1 +#define NLSF_QUANT_DEL_DEC_STATES_LOG2 2 +#define NLSF_QUANT_DEL_DEC_STATES ( 1 << NLSF_QUANT_DEL_DEC_STATES_LOG2 ) + +/* Transition filtering for mode switching */ +#define TRANSITION_TIME_MS 5120 /* 5120 = 64 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 64*(20*4)*/ +#define TRANSITION_NB 3 /* Hardcoded in tables */ +#define TRANSITION_NA 2 /* Hardcoded in tables */ +#define TRANSITION_INT_NUM 5 /* Hardcoded in tables */ +#define TRANSITION_FRAMES ( TRANSITION_TIME_MS / MAX_FRAME_LENGTH_MS ) +#define TRANSITION_INT_STEPS ( TRANSITION_FRAMES / ( TRANSITION_INT_NUM - 1 ) ) + +/* BWE factors to apply after packet loss */ +#define BWE_AFTER_LOSS_Q16 63570 + +/* Defines for CN generation */ +#define CNG_BUF_MASK_MAX 255 /* 2^floor(log2(MAX_FRAME_LENGTH))-1 */ +#define CNG_GAIN_SMTH_Q16 4634 /* 0.25^(1/4) */ +#define CNG_NLSF_SMTH_Q16 16348 /* 0.25 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/TelegramClient.Opus/opus/silk/enc_API.c b/TelegramClient.Opus/opus/silk/enc_API.c new file mode 100755 index 0000000..43739ef --- /dev/null +++ b/TelegramClient.Opus/opus/silk/enc_API.c @@ -0,0 +1,556 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "define.h" +#include "API.h" +#include "control.h" +#include "typedef.h" +#include "stack_alloc.h" +#include "structs.h" +#include "tuning_parameters.h" +#ifdef FIXED_POINT +#include "main_FIX.h" +#else +#include "main_FLP.h" +#endif + +/***************************************/ +/* Read control structure from encoder */ +/***************************************/ +static opus_int silk_QueryEncoder( /* O Returns error code */ + const void *encState, /* I State */ + silk_EncControlStruct *encStatus /* O Encoder Status */ +); + +/****************************************/ +/* Encoder functions */ +/****************************************/ + +opus_int silk_Get_Encoder_Size( /* O Returns error code */ + opus_int *encSizeBytes /* O Number of bytes in SILK encoder state */ +) +{ + opus_int ret = SILK_NO_ERROR; + + *encSizeBytes = sizeof( silk_encoder ); + + return ret; +} + +/*************************/ +/* Init or Reset encoder */ +/*************************/ +opus_int silk_InitEncoder( /* O Returns error code */ + void *encState, /* I/O State */ + int arch, /* I Run-time architecture */ + silk_EncControlStruct *encStatus /* O Encoder Status */ +) +{ + silk_encoder *psEnc; + opus_int n, ret = SILK_NO_ERROR; + + psEnc = (silk_encoder *)encState; + + /* Reset encoder */ + silk_memset( psEnc, 0, sizeof( silk_encoder ) ); + for( n = 0; n < ENCODER_NUM_CHANNELS; n++ ) { + if( ret += silk_init_encoder( &psEnc->state_Fxx[ n ], arch ) ) { + silk_assert( 0 ); + } + } + + psEnc->nChannelsAPI = 1; + psEnc->nChannelsInternal = 1; + + /* Read control structure */ + if( ret += silk_QueryEncoder( encState, encStatus ) ) { + silk_assert( 0 ); + } + + return ret; +} + +/***************************************/ +/* Read control structure from encoder */ +/***************************************/ +static opus_int silk_QueryEncoder( /* O Returns error code */ + const void *encState, /* I State */ + silk_EncControlStruct *encStatus /* O Encoder Status */ +) +{ + opus_int ret = SILK_NO_ERROR; + silk_encoder_state_Fxx *state_Fxx; + silk_encoder *psEnc = (silk_encoder *)encState; + + state_Fxx = psEnc->state_Fxx; + + encStatus->nChannelsAPI = psEnc->nChannelsAPI; + encStatus->nChannelsInternal = psEnc->nChannelsInternal; + encStatus->API_sampleRate = state_Fxx[ 0 ].sCmn.API_fs_Hz; + encStatus->maxInternalSampleRate = state_Fxx[ 0 ].sCmn.maxInternal_fs_Hz; + encStatus->minInternalSampleRate = state_Fxx[ 0 ].sCmn.minInternal_fs_Hz; + encStatus->desiredInternalSampleRate = state_Fxx[ 0 ].sCmn.desiredInternal_fs_Hz; + encStatus->payloadSize_ms = state_Fxx[ 0 ].sCmn.PacketSize_ms; + encStatus->bitRate = state_Fxx[ 0 ].sCmn.TargetRate_bps; + encStatus->packetLossPercentage = state_Fxx[ 0 ].sCmn.PacketLoss_perc; + encStatus->complexity = state_Fxx[ 0 ].sCmn.Complexity; + encStatus->useInBandFEC = state_Fxx[ 0 ].sCmn.useInBandFEC; + encStatus->useDTX = state_Fxx[ 0 ].sCmn.useDTX; + encStatus->useCBR = state_Fxx[ 0 ].sCmn.useCBR; + encStatus->internalSampleRate = silk_SMULBB( state_Fxx[ 0 ].sCmn.fs_kHz, 1000 ); + encStatus->allowBandwidthSwitch = state_Fxx[ 0 ].sCmn.allow_bandwidth_switch; + encStatus->inWBmodeWithoutVariableLP = state_Fxx[ 0 ].sCmn.fs_kHz == 16 && state_Fxx[ 0 ].sCmn.sLP.mode == 0; + + return ret; +} + + +/**************************/ +/* Encode frame with Silk */ +/**************************/ +/* Note: if prefillFlag is set, the input must contain 10 ms of audio, irrespective of what */ +/* encControl->payloadSize_ms is set to */ +opus_int silk_Encode( /* O Returns error code */ + void *encState, /* I/O State */ + silk_EncControlStruct *encControl, /* I Control status */ + const opus_int16 *samplesIn, /* I Speech sample input vector */ + opus_int nSamplesIn, /* I Number of samples in input vector */ + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */ + const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */ +) +{ + opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0; + opus_int nSamplesToBuffer, nSamplesToBufferMax, nBlocksOf10ms; + opus_int nSamplesFromInput = 0, nSamplesFromInputMax; + opus_int speech_act_thr_for_switch_Q8; + opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol, sum; + silk_encoder *psEnc = ( silk_encoder * )encState; + VARDECL( opus_int16, buf ); + opus_int transition, curr_block, tot_blocks; + SAVE_STACK; + + if (encControl->reducedDependency) + { + psEnc->state_Fxx[0].sCmn.first_frame_after_reset = 1; + psEnc->state_Fxx[1].sCmn.first_frame_after_reset = 1; + } + psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0; + + /* Check values in encoder control structure */ + if( ( ret = check_control_input( encControl ) != 0 ) ) { + silk_assert( 0 ); + RESTORE_STACK; + return ret; + } + + encControl->switchReady = 0; + + if( encControl->nChannelsInternal > psEnc->nChannelsInternal ) { + /* Mono -> Stereo transition: init state of second channel and stereo state */ + ret += silk_init_encoder( &psEnc->state_Fxx[ 1 ], psEnc->state_Fxx[ 0 ].sCmn.arch ); + silk_memset( psEnc->sStereo.pred_prev_Q13, 0, sizeof( psEnc->sStereo.pred_prev_Q13 ) ); + silk_memset( psEnc->sStereo.sSide, 0, sizeof( psEnc->sStereo.sSide ) ); + psEnc->sStereo.mid_side_amp_Q0[ 0 ] = 0; + psEnc->sStereo.mid_side_amp_Q0[ 1 ] = 1; + psEnc->sStereo.mid_side_amp_Q0[ 2 ] = 0; + psEnc->sStereo.mid_side_amp_Q0[ 3 ] = 1; + psEnc->sStereo.width_prev_Q14 = 0; + psEnc->sStereo.smth_width_Q14 = SILK_FIX_CONST( 1, 14 ); + if( psEnc->nChannelsAPI == 2 ) { + silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof( silk_resampler_state_struct ) ); + silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.In_HP_State, &psEnc->state_Fxx[ 0 ].sCmn.In_HP_State, sizeof( psEnc->state_Fxx[ 1 ].sCmn.In_HP_State ) ); + } + } + + transition = (encControl->payloadSize_ms != psEnc->state_Fxx[ 0 ].sCmn.PacketSize_ms) || (psEnc->nChannelsInternal != encControl->nChannelsInternal); + + psEnc->nChannelsAPI = encControl->nChannelsAPI; + psEnc->nChannelsInternal = encControl->nChannelsInternal; + + nBlocksOf10ms = silk_DIV32( 100 * nSamplesIn, encControl->API_sampleRate ); + tot_blocks = ( nBlocksOf10ms > 1 ) ? nBlocksOf10ms >> 1 : 1; + curr_block = 0; + if( prefillFlag ) { + /* Only accept input length of 10 ms */ + if( nBlocksOf10ms != 1 ) { + silk_assert( 0 ); + RESTORE_STACK; + return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; + } + /* Reset Encoder */ + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + ret = silk_init_encoder( &psEnc->state_Fxx[ n ], psEnc->state_Fxx[ n ].sCmn.arch ); + silk_assert( !ret ); + } + tmp_payloadSize_ms = encControl->payloadSize_ms; + encControl->payloadSize_ms = 10; + tmp_complexity = encControl->complexity; + encControl->complexity = 0; + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; + psEnc->state_Fxx[ n ].sCmn.prefillFlag = 1; + } + } else { + /* Only accept input lengths that are a multiple of 10 ms */ + if( nBlocksOf10ms * encControl->API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0 ) { + silk_assert( 0 ); + RESTORE_STACK; + return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; + } + /* Make sure no more than one packet can be produced */ + if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) { + silk_assert( 0 ); + RESTORE_STACK; + return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES; + } + } + + TargetRate_bps = silk_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 ); + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + /* Force the side channel to the same rate as the mid */ + opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0; + if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) { + silk_assert( 0 ); + RESTORE_STACK; + return ret; + } + if( psEnc->state_Fxx[n].sCmn.first_frame_after_reset || transition ) { + for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) { + psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] = 0; + } + } + psEnc->state_Fxx[ n ].sCmn.inDTX = psEnc->state_Fxx[ n ].sCmn.useDTX; + } + silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); + + /* Input buffering/resampling and encoding */ + nSamplesToBufferMax = + 10 * nBlocksOf10ms * psEnc->state_Fxx[ 0 ].sCmn.fs_kHz; + nSamplesFromInputMax = + silk_DIV32_16( nSamplesToBufferMax * + psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, + psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 ); + ALLOC( buf, nSamplesFromInputMax, opus_int16 ); + while( 1 ) { + nSamplesToBuffer = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx; + nSamplesToBuffer = silk_min( nSamplesToBuffer, nSamplesToBufferMax ); + nSamplesFromInput = silk_DIV32_16( nSamplesToBuffer * psEnc->state_Fxx[ 0 ].sCmn.API_fs_Hz, psEnc->state_Fxx[ 0 ].sCmn.fs_kHz * 1000 ); + /* Resample and write to buffer */ + if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) { + opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded; + for( n = 0; n < nSamplesFromInput; n++ ) { + buf[ n ] = samplesIn[ 2 * n ]; + } + /* Making sure to start both resamplers from the same state when switching from mono to stereo */ + if( psEnc->nPrevChannelsInternal == 1 && id==0 ) { + silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof(psEnc->state_Fxx[ 1 ].sCmn.resampler_state)); + } + + ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; + + nSamplesToBuffer = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx; + nSamplesToBuffer = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz ); + for( n = 0; n < nSamplesFromInput; n++ ) { + buf[ n ] = samplesIn[ 2 * n + 1 ]; + } + ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + + psEnc->state_Fxx[ 1 ].sCmn.inputBufIx += nSamplesToBuffer; + } else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) { + /* Combine left and right channels before resampling */ + for( n = 0; n < nSamplesFromInput; n++ ) { + sum = samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ]; + buf[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 ); + } + ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + /* On the first mono frame, average the results for the two resampler states */ + if( psEnc->nPrevChannelsInternal == 2 && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 ) { + ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + for( n = 0; n < psEnc->state_Fxx[ 0 ].sCmn.frame_length; n++ ) { + psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx+n+2 ] = + silk_RSHIFT(psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx+n+2 ] + + psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx+n+2 ], 1); + } + } + psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; + } else { + silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 ); + silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16)); + ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, + &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput ); + psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer; + } + + samplesIn += nSamplesFromInput * encControl->nChannelsAPI; + nSamplesIn -= nSamplesFromInput; + + /* Default */ + psEnc->allowBandwidthSwitch = 0; + + /* Silk encoder */ + if( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx >= psEnc->state_Fxx[ 0 ].sCmn.frame_length ) { + /* Enough data in input buffer, so encode */ + silk_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length ); + silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length ); + + /* Deal with LBRR data */ + if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 && !prefillFlag ) { + /* Create space at start of payload for VAD and FEC flags */ + opus_uint8 iCDF[ 2 ] = { 0, 0 }; + iCDF[ 0 ] = 256 - silk_RSHIFT( 256, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal ); + ec_enc_icdf( psRangeEnc, 0, iCDF, 8 ); + + /* Encode any LBRR data from previous packet */ + /* Encode LBRR flags */ + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + LBRR_symbol = 0; + for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) { + LBRR_symbol |= silk_LSHIFT( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ], i ); + } + psEnc->state_Fxx[ n ].sCmn.LBRR_flag = LBRR_symbol > 0 ? 1 : 0; + if( LBRR_symbol && psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket > 1 ) { + ec_enc_icdf( psRangeEnc, LBRR_symbol - 1, silk_LBRR_flags_iCDF_ptr[ psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket - 2 ], 8 ); + } + } + + /* Code LBRR indices and excitation signals */ + for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) { + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + if( psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] ) { + opus_int condCoding; + + if( encControl->nChannelsInternal == 2 && n == 0 ) { + silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.predIx[ i ] ); + /* For LBRR data there's no need to code the mid-only flag if the side-channel LBRR flag is set */ + if( psEnc->state_Fxx[ 1 ].sCmn.LBRR_flags[ i ] == 0 ) { + silk_stereo_encode_mid_only( psRangeEnc, psEnc->sStereo.mid_only_flags[ i ] ); + } + } + /* Use conditional coding if previous frame available */ + if( i > 0 && psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i - 1 ] ) { + condCoding = CODE_CONDITIONALLY; + } else { + condCoding = CODE_INDEPENDENTLY; + } + silk_encode_indices( &psEnc->state_Fxx[ n ].sCmn, psRangeEnc, i, 1, condCoding ); + silk_encode_pulses( psRangeEnc, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].signalType, psEnc->state_Fxx[ n ].sCmn.indices_LBRR[i].quantOffsetType, + psEnc->state_Fxx[ n ].sCmn.pulses_LBRR[ i ], psEnc->state_Fxx[ n ].sCmn.frame_length ); + } + } + } + + /* Reset LBRR flags */ + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + silk_memset( psEnc->state_Fxx[ n ].sCmn.LBRR_flags, 0, sizeof( psEnc->state_Fxx[ n ].sCmn.LBRR_flags ) ); + } + } + + silk_HP_variable_cutoff( psEnc->state_Fxx ); + + /* Total target bits for packet */ + nBits = silk_DIV32_16( silk_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 ); + /* Subtract half of the bits already used */ + if( !prefillFlag ) { + nBits -= ec_tell( psRangeEnc ) >> 1; + } + /* Divide by number of uncoded frames left in packet */ + nBits = silk_DIV32_16( nBits, psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket - psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ); + /* Convert to bits/second */ + if( encControl->payloadSize_ms == 10 ) { + TargetRate_bps = silk_SMULBB( nBits, 100 ); + } else { + TargetRate_bps = silk_SMULBB( nBits, 50 ); + } + /* Subtract fraction of bits in excess of target in previous packets */ + TargetRate_bps -= silk_DIV32_16( silk_MUL( psEnc->nBitsExceeded, 1000 ), BITRESERVOIR_DECAY_TIME_MS ); + /* Never exceed input bitrate */ + TargetRate_bps = silk_LIMIT( TargetRate_bps, encControl->bitRate, 5000 ); + + /* Convert Left/Right to Mid/Side */ + if( encControl->nChannelsInternal == 2 ) { + silk_stereo_LR_to_MS( &psEnc->sStereo, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ 2 ], &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ 2 ], + psEnc->sStereo.predIx[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ], &psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ], + MStargetRates_bps, TargetRate_bps, psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8, encControl->toMono, + psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, psEnc->state_Fxx[ 0 ].sCmn.frame_length ); + if( psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] == 0 ) { + /* Reset side channel encoder memory for first frame with side coding */ + if( psEnc->prev_decode_only_middle == 1 ) { + silk_memset( &psEnc->state_Fxx[ 1 ].sShape, 0, sizeof( psEnc->state_Fxx[ 1 ].sShape ) ); + silk_memset( &psEnc->state_Fxx[ 1 ].sPrefilt, 0, sizeof( psEnc->state_Fxx[ 1 ].sPrefilt ) ); + silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sNSQ, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sNSQ ) ); + silk_memset( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15 ) ); + silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State ) ); + psEnc->state_Fxx[ 1 ].sCmn.prevLag = 100; + psEnc->state_Fxx[ 1 ].sCmn.sNSQ.lagPrev = 100; + psEnc->state_Fxx[ 1 ].sShape.LastGainIndex = 10; + psEnc->state_Fxx[ 1 ].sCmn.prevSignalType = TYPE_NO_VOICE_ACTIVITY; + psEnc->state_Fxx[ 1 ].sCmn.sNSQ.prev_gain_Q16 = 65536; + psEnc->state_Fxx[ 1 ].sCmn.first_frame_after_reset = 1; + } + silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ] ); + } else { + psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] = 0; + } + if( !prefillFlag ) { + silk_stereo_encode_pred( psRangeEnc, psEnc->sStereo.predIx[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] ); + if( psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] == 0 ) { + silk_stereo_encode_mid_only( psRangeEnc, psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] ); + } + } + } else { + /* Buffering */ + silk_memcpy( psEnc->state_Fxx[ 0 ].sCmn.inputBuf, psEnc->sStereo.sMid, 2 * sizeof( opus_int16 ) ); + silk_memcpy( psEnc->sStereo.sMid, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.frame_length ], 2 * sizeof( opus_int16 ) ); + } + silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ] ); + + /* Encode */ + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + opus_int maxBits, useCBR; + + /* Handling rate constraints */ + maxBits = encControl->maxBits; + if( tot_blocks == 2 && curr_block == 0 ) { + maxBits = maxBits * 3 / 5; + } else if( tot_blocks == 3 ) { + if( curr_block == 0 ) { + maxBits = maxBits * 2 / 5; + } else if( curr_block == 1 ) { + maxBits = maxBits * 3 / 4; + } + } + useCBR = encControl->useCBR && curr_block == tot_blocks - 1; + + if( encControl->nChannelsInternal == 1 ) { + channelRate_bps = TargetRate_bps; + } else { + channelRate_bps = MStargetRates_bps[ n ]; + if( n == 0 && MStargetRates_bps[ 1 ] > 0 ) { + useCBR = 0; + /* Give mid up to 1/2 of the max bits for that frame */ + maxBits -= encControl->maxBits / ( tot_blocks * 2 ); + } + } + + if( channelRate_bps > 0 ) { + opus_int condCoding; + + silk_control_SNR( &psEnc->state_Fxx[ n ].sCmn, channelRate_bps ); + + /* Use independent coding if no previous frame available */ + if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded - n <= 0 ) { + condCoding = CODE_INDEPENDENTLY; + } else if( n > 0 && psEnc->prev_decode_only_middle ) { + /* If we skipped a side frame in this packet, we don't + need LTP scaling; the LTP state is well-defined. */ + condCoding = CODE_INDEPENDENTLY_NO_LTP_SCALING; + } else { + condCoding = CODE_CONDITIONALLY; + } + if( ( ret = silk_encode_frame_Fxx( &psEnc->state_Fxx[ n ], nBytesOut, psRangeEnc, condCoding, maxBits, useCBR ) ) != 0 ) { + silk_assert( 0 ); + } + } + psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; + psEnc->state_Fxx[ n ].sCmn.inputBufIx = 0; + psEnc->state_Fxx[ n ].sCmn.nFramesEncoded++; + } + psEnc->prev_decode_only_middle = psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded - 1 ]; + + /* Insert VAD and FEC flags at beginning of bitstream */ + if( *nBytesOut > 0 && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket) { + flags = 0; + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + for( i = 0; i < psEnc->state_Fxx[ n ].sCmn.nFramesPerPacket; i++ ) { + flags = silk_LSHIFT( flags, 1 ); + flags |= psEnc->state_Fxx[ n ].sCmn.VAD_flags[ i ]; + } + flags = silk_LSHIFT( flags, 1 ); + flags |= psEnc->state_Fxx[ n ].sCmn.LBRR_flag; + } + if( !prefillFlag ) { + ec_enc_patch_initial_bits( psRangeEnc, flags, ( psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket + 1 ) * encControl->nChannelsInternal ); + } + + /* Return zero bytes if all channels DTXed */ + if( psEnc->state_Fxx[ 0 ].sCmn.inDTX && ( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inDTX ) ) { + *nBytesOut = 0; + } + + psEnc->nBitsExceeded += *nBytesOut * 8; + psEnc->nBitsExceeded -= silk_DIV32_16( silk_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 ); + psEnc->nBitsExceeded = silk_LIMIT( psEnc->nBitsExceeded, 0, 10000 ); + + /* Update flag indicating if bandwidth switching is allowed */ + speech_act_thr_for_switch_Q8 = silk_SMLAWB( SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ), + SILK_FIX_CONST( ( 1 - SPEECH_ACTIVITY_DTX_THRES ) / MAX_BANDWIDTH_SWITCH_DELAY_MS, 16 + 8 ), psEnc->timeSinceSwitchAllowed_ms ); + if( psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8 < speech_act_thr_for_switch_Q8 ) { + psEnc->allowBandwidthSwitch = 1; + psEnc->timeSinceSwitchAllowed_ms = 0; + } else { + psEnc->allowBandwidthSwitch = 0; + psEnc->timeSinceSwitchAllowed_ms += encControl->payloadSize_ms; + } + } + + if( nSamplesIn == 0 ) { + break; + } + } else { + break; + } + curr_block++; + } + + psEnc->nPrevChannelsInternal = encControl->nChannelsInternal; + + encControl->allowBandwidthSwitch = psEnc->allowBandwidthSwitch; + encControl->inWBmodeWithoutVariableLP = psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == 16 && psEnc->state_Fxx[ 0 ].sCmn.sLP.mode == 0; + encControl->internalSampleRate = silk_SMULBB( psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, 1000 ); + encControl->stereoWidth_Q14 = encControl->toMono ? 0 : psEnc->sStereo.smth_width_Q14; + if( prefillFlag ) { + encControl->payloadSize_ms = tmp_payloadSize_ms; + encControl->complexity = tmp_complexity; + for( n = 0; n < encControl->nChannelsInternal; n++ ) { + psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0; + psEnc->state_Fxx[ n ].sCmn.prefillFlag = 0; + } + } + + RESTORE_STACK; + return ret; +} + diff --git a/TelegramClient.Opus/opus/silk/encode_indices.c b/TelegramClient.Opus/opus/silk/encode_indices.c new file mode 100755 index 0000000..666c8c0 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/encode_indices.c @@ -0,0 +1,181 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Encode side-information parameters to payload */ +void silk_encode_indices( + silk_encoder_state *psEncC, /* I/O Encoder state */ + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int FrameIndex, /* I Frame number */ + opus_int encode_LBRR, /* I Flag indicating LBRR data is being encoded */ + opus_int condCoding /* I The type of conditional coding to use */ +) +{ + opus_int i, k, typeOffset; + opus_int encode_absolute_lagIndex, delta_lagIndex; + opus_int16 ec_ix[ MAX_LPC_ORDER ]; + opus_uint8 pred_Q8[ MAX_LPC_ORDER ]; + const SideInfoIndices *psIndices; + + if( encode_LBRR ) { + psIndices = &psEncC->indices_LBRR[ FrameIndex ]; + } else { + psIndices = &psEncC->indices; + } + + /*******************************************/ + /* Encode signal type and quantizer offset */ + /*******************************************/ + typeOffset = 2 * psIndices->signalType + psIndices->quantOffsetType; + silk_assert( typeOffset >= 0 && typeOffset < 6 ); + silk_assert( encode_LBRR == 0 || typeOffset >= 2 ); + if( encode_LBRR || typeOffset >= 2 ) { + ec_enc_icdf( psRangeEnc, typeOffset - 2, silk_type_offset_VAD_iCDF, 8 ); + } else { + ec_enc_icdf( psRangeEnc, typeOffset, silk_type_offset_no_VAD_iCDF, 8 ); + } + + /****************/ + /* Encode gains */ + /****************/ + /* first subframe */ + if( condCoding == CODE_CONDITIONALLY ) { + /* conditional coding */ + silk_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ); + ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ], silk_delta_gain_iCDF, 8 ); + } else { + /* independent coding, in two stages: MSB bits followed by 3 LSBs */ + silk_assert( psIndices->GainsIndices[ 0 ] >= 0 && psIndices->GainsIndices[ 0 ] < N_LEVELS_QGAIN ); + ec_enc_icdf( psRangeEnc, silk_RSHIFT( psIndices->GainsIndices[ 0 ], 3 ), silk_gain_iCDF[ psIndices->signalType ], 8 ); + ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ 0 ] & 7, silk_uniform8_iCDF, 8 ); + } + + /* remaining subframes */ + for( i = 1; i < psEncC->nb_subfr; i++ ) { + silk_assert( psIndices->GainsIndices[ i ] >= 0 && psIndices->GainsIndices[ i ] < MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ); + ec_enc_icdf( psRangeEnc, psIndices->GainsIndices[ i ], silk_delta_gain_iCDF, 8 ); + } + + /****************/ + /* Encode NLSFs */ + /****************/ + ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ 0 ], &psEncC->psNLSF_CB->CB1_iCDF[ ( psIndices->signalType >> 1 ) * psEncC->psNLSF_CB->nVectors ], 8 ); + silk_NLSF_unpack( ec_ix, pred_Q8, psEncC->psNLSF_CB, psIndices->NLSFIndices[ 0 ] ); + silk_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder ); + for( i = 0; i < psEncC->psNLSF_CB->order; i++ ) { + if( psIndices->NLSFIndices[ i+1 ] >= NLSF_QUANT_MAX_AMPLITUDE ) { + ec_enc_icdf( psRangeEnc, 2 * NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); + ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 ); + } else if( psIndices->NLSFIndices[ i+1 ] <= -NLSF_QUANT_MAX_AMPLITUDE ) { + ec_enc_icdf( psRangeEnc, 0, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); + ec_enc_icdf( psRangeEnc, -psIndices->NLSFIndices[ i+1 ] - NLSF_QUANT_MAX_AMPLITUDE, silk_NLSF_EXT_iCDF, 8 ); + } else { + ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ i+1 ] + NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 ); + } + } + + /* Encode NLSF interpolation factor */ + if( psEncC->nb_subfr == MAX_NB_SUBFR ) { + silk_assert( psIndices->NLSFInterpCoef_Q2 >= 0 && psIndices->NLSFInterpCoef_Q2 < 5 ); + ec_enc_icdf( psRangeEnc, psIndices->NLSFInterpCoef_Q2, silk_NLSF_interpolation_factor_iCDF, 8 ); + } + + if( psIndices->signalType == TYPE_VOICED ) + { + /*********************/ + /* Encode pitch lags */ + /*********************/ + /* lag index */ + encode_absolute_lagIndex = 1; + if( condCoding == CODE_CONDITIONALLY && psEncC->ec_prevSignalType == TYPE_VOICED ) { + /* Delta Encoding */ + delta_lagIndex = psIndices->lagIndex - psEncC->ec_prevLagIndex; + if( delta_lagIndex < -8 || delta_lagIndex > 11 ) { + delta_lagIndex = 0; + } else { + delta_lagIndex = delta_lagIndex + 9; + encode_absolute_lagIndex = 0; /* Only use delta */ + } + silk_assert( delta_lagIndex >= 0 && delta_lagIndex < 21 ); + ec_enc_icdf( psRangeEnc, delta_lagIndex, silk_pitch_delta_iCDF, 8 ); + } + if( encode_absolute_lagIndex ) { + /* Absolute encoding */ + opus_int32 pitch_high_bits, pitch_low_bits; + pitch_high_bits = silk_DIV32_16( psIndices->lagIndex, silk_RSHIFT( psEncC->fs_kHz, 1 ) ); + pitch_low_bits = psIndices->lagIndex - silk_SMULBB( pitch_high_bits, silk_RSHIFT( psEncC->fs_kHz, 1 ) ); + silk_assert( pitch_low_bits < psEncC->fs_kHz / 2 ); + silk_assert( pitch_high_bits < 32 ); + ec_enc_icdf( psRangeEnc, pitch_high_bits, silk_pitch_lag_iCDF, 8 ); + ec_enc_icdf( psRangeEnc, pitch_low_bits, psEncC->pitch_lag_low_bits_iCDF, 8 ); + } + psEncC->ec_prevLagIndex = psIndices->lagIndex; + + /* Countour index */ + silk_assert( psIndices->contourIndex >= 0 ); + silk_assert( ( psIndices->contourIndex < 34 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 4 ) || + ( psIndices->contourIndex < 11 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 4 ) || + ( psIndices->contourIndex < 12 && psEncC->fs_kHz > 8 && psEncC->nb_subfr == 2 ) || + ( psIndices->contourIndex < 3 && psEncC->fs_kHz == 8 && psEncC->nb_subfr == 2 ) ); + ec_enc_icdf( psRangeEnc, psIndices->contourIndex, psEncC->pitch_contour_iCDF, 8 ); + + /********************/ + /* Encode LTP gains */ + /********************/ + /* PERIndex value */ + silk_assert( psIndices->PERIndex >= 0 && psIndices->PERIndex < 3 ); + ec_enc_icdf( psRangeEnc, psIndices->PERIndex, silk_LTP_per_index_iCDF, 8 ); + + /* Codebook Indices */ + for( k = 0; k < psEncC->nb_subfr; k++ ) { + silk_assert( psIndices->LTPIndex[ k ] >= 0 && psIndices->LTPIndex[ k ] < ( 8 << psIndices->PERIndex ) ); + ec_enc_icdf( psRangeEnc, psIndices->LTPIndex[ k ], silk_LTP_gain_iCDF_ptrs[ psIndices->PERIndex ], 8 ); + } + + /**********************/ + /* Encode LTP scaling */ + /**********************/ + if( condCoding == CODE_INDEPENDENTLY ) { + silk_assert( psIndices->LTP_scaleIndex >= 0 && psIndices->LTP_scaleIndex < 3 ); + ec_enc_icdf( psRangeEnc, psIndices->LTP_scaleIndex, silk_LTPscale_iCDF, 8 ); + } + silk_assert( !condCoding || psIndices->LTP_scaleIndex == 0 ); + } + + psEncC->ec_prevSignalType = psIndices->signalType; + + /***************/ + /* Encode seed */ + /***************/ + silk_assert( psIndices->Seed >= 0 && psIndices->Seed < 4 ); + ec_enc_icdf( psRangeEnc, psIndices->Seed, silk_uniform4_iCDF, 8 ); +} diff --git a/TelegramClient.Opus/opus/silk/encode_pulses.c b/TelegramClient.Opus/opus/silk/encode_pulses.c new file mode 100755 index 0000000..a450143 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/encode_pulses.c @@ -0,0 +1,206 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "stack_alloc.h" + +/*********************************************/ +/* Encode quantization indices of excitation */ +/*********************************************/ + +static OPUS_INLINE opus_int combine_and_check( /* return ok */ + opus_int *pulses_comb, /* O */ + const opus_int *pulses_in, /* I */ + opus_int max_pulses, /* I max value for sum of pulses */ + opus_int len /* I number of output values */ +) +{ + opus_int k, sum; + + for( k = 0; k < len; k++ ) { + sum = pulses_in[ 2 * k ] + pulses_in[ 2 * k + 1 ]; + if( sum > max_pulses ) { + return 1; + } + pulses_comb[ k ] = sum; + } + + return 0; +} + +/* Encode quantization indices of excitation */ +void silk_encode_pulses( + ec_enc *psRangeEnc, /* I/O compressor data structure */ + const opus_int signalType, /* I Signal type */ + const opus_int quantOffsetType, /* I quantOffsetType */ + opus_int8 pulses[], /* I quantization indices */ + const opus_int frame_length /* I Frame length */ +) +{ + opus_int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0; + opus_int32 abs_q, minSumBits_Q5, sumBits_Q5; + VARDECL( opus_int, abs_pulses ); + VARDECL( opus_int, sum_pulses ); + VARDECL( opus_int, nRshifts ); + opus_int pulses_comb[ 8 ]; + opus_int *abs_pulses_ptr; + const opus_int8 *pulses_ptr; + const opus_uint8 *cdf_ptr; + const opus_uint8 *nBits_ptr; + SAVE_STACK; + + silk_memset( pulses_comb, 0, 8 * sizeof( opus_int ) ); /* Fixing Valgrind reported problem*/ + + /****************************/ + /* Prepare for shell coding */ + /****************************/ + /* Calculate number of shell blocks */ + silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH ); + iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH ); + if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) { + silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */ + iter++; + silk_memset( &pulses[ frame_length ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(opus_int8)); + } + + /* Take the absolute value of the pulses */ + ALLOC( abs_pulses, iter * SHELL_CODEC_FRAME_LENGTH, opus_int ); + silk_assert( !( SHELL_CODEC_FRAME_LENGTH & 3 ) ); + for( i = 0; i < iter * SHELL_CODEC_FRAME_LENGTH; i+=4 ) { + abs_pulses[i+0] = ( opus_int )silk_abs( pulses[ i + 0 ] ); + abs_pulses[i+1] = ( opus_int )silk_abs( pulses[ i + 1 ] ); + abs_pulses[i+2] = ( opus_int )silk_abs( pulses[ i + 2 ] ); + abs_pulses[i+3] = ( opus_int )silk_abs( pulses[ i + 3 ] ); + } + + /* Calc sum pulses per shell code frame */ + ALLOC( sum_pulses, iter, opus_int ); + ALLOC( nRshifts, iter, opus_int ); + abs_pulses_ptr = abs_pulses; + for( i = 0; i < iter; i++ ) { + nRshifts[ i ] = 0; + + while( 1 ) { + /* 1+1 -> 2 */ + scale_down = combine_and_check( pulses_comb, abs_pulses_ptr, silk_max_pulses_table[ 0 ], 8 ); + /* 2+2 -> 4 */ + scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 1 ], 4 ); + /* 4+4 -> 8 */ + scale_down += combine_and_check( pulses_comb, pulses_comb, silk_max_pulses_table[ 2 ], 2 ); + /* 8+8 -> 16 */ + scale_down += combine_and_check( &sum_pulses[ i ], pulses_comb, silk_max_pulses_table[ 3 ], 1 ); + + if( scale_down ) { + /* We need to downscale the quantization signal */ + nRshifts[ i ]++; + for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { + abs_pulses_ptr[ k ] = silk_RSHIFT( abs_pulses_ptr[ k ], 1 ); + } + } else { + /* Jump out of while(1) loop and go to next shell coding frame */ + break; + } + } + abs_pulses_ptr += SHELL_CODEC_FRAME_LENGTH; + } + + /**************/ + /* Rate level */ + /**************/ + /* find rate level that leads to fewest bits for coding of pulses per block info */ + minSumBits_Q5 = silk_int32_MAX; + for( k = 0; k < N_RATE_LEVELS - 1; k++ ) { + nBits_ptr = silk_pulses_per_block_BITS_Q5[ k ]; + sumBits_Q5 = silk_rate_levels_BITS_Q5[ signalType >> 1 ][ k ]; + for( i = 0; i < iter; i++ ) { + if( nRshifts[ i ] > 0 ) { + sumBits_Q5 += nBits_ptr[ MAX_PULSES + 1 ]; + } else { + sumBits_Q5 += nBits_ptr[ sum_pulses[ i ] ]; + } + } + if( sumBits_Q5 < minSumBits_Q5 ) { + minSumBits_Q5 = sumBits_Q5; + RateLevelIndex = k; + } + } + ec_enc_icdf( psRangeEnc, RateLevelIndex, silk_rate_levels_iCDF[ signalType >> 1 ], 8 ); + + /***************************************************/ + /* Sum-Weighted-Pulses Encoding */ + /***************************************************/ + cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ]; + for( i = 0; i < iter; i++ ) { + if( nRshifts[ i ] == 0 ) { + ec_enc_icdf( psRangeEnc, sum_pulses[ i ], cdf_ptr, 8 ); + } else { + ec_enc_icdf( psRangeEnc, MAX_PULSES + 1, cdf_ptr, 8 ); + for( k = 0; k < nRshifts[ i ] - 1; k++ ) { + ec_enc_icdf( psRangeEnc, MAX_PULSES + 1, silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); + } + ec_enc_icdf( psRangeEnc, sum_pulses[ i ], silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1 ], 8 ); + } + } + + /******************/ + /* Shell Encoding */ + /******************/ + for( i = 0; i < iter; i++ ) { + if( sum_pulses[ i ] > 0 ) { + silk_shell_encoder( psRangeEnc, &abs_pulses[ i * SHELL_CODEC_FRAME_LENGTH ] ); + } + } + + /****************/ + /* LSB Encoding */ + /****************/ + for( i = 0; i < iter; i++ ) { + if( nRshifts[ i ] > 0 ) { + pulses_ptr = &pulses[ i * SHELL_CODEC_FRAME_LENGTH ]; + nLS = nRshifts[ i ] - 1; + for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) { + abs_q = (opus_int8)silk_abs( pulses_ptr[ k ] ); + for( j = nLS; j > 0; j-- ) { + bit = silk_RSHIFT( abs_q, j ) & 1; + ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 ); + } + bit = abs_q & 1; + ec_enc_icdf( psRangeEnc, bit, silk_lsb_iCDF, 8 ); + } + } + } + + /****************/ + /* Encode signs */ + /****************/ + silk_encode_signs( psRangeEnc, pulses, frame_length, signalType, quantOffsetType, sum_pulses ); + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/errors.h b/TelegramClient.Opus/opus/silk/errors.h new file mode 100755 index 0000000..4507080 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/errors.h @@ -0,0 +1,98 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_ERRORS_H +#define SILK_ERRORS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/******************/ +/* Error messages */ +/******************/ +#define SILK_NO_ERROR 0 + +/**************************/ +/* Encoder error messages */ +/**************************/ + +/* Input length is not a multiple of 10 ms, or length is longer than the packet length */ +#define SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES -101 + +/* Sampling frequency not 8000, 12000 or 16000 Hertz */ +#define SILK_ENC_FS_NOT_SUPPORTED -102 + +/* Packet size not 10, 20, 40, or 60 ms */ +#define SILK_ENC_PACKET_SIZE_NOT_SUPPORTED -103 + +/* Allocated payload buffer too short */ +#define SILK_ENC_PAYLOAD_BUF_TOO_SHORT -104 + +/* Loss rate not between 0 and 100 percent */ +#define SILK_ENC_INVALID_LOSS_RATE -105 + +/* Complexity setting not valid, use 0...10 */ +#define SILK_ENC_INVALID_COMPLEXITY_SETTING -106 + +/* Inband FEC setting not valid, use 0 or 1 */ +#define SILK_ENC_INVALID_INBAND_FEC_SETTING -107 + +/* DTX setting not valid, use 0 or 1 */ +#define SILK_ENC_INVALID_DTX_SETTING -108 + +/* CBR setting not valid, use 0 or 1 */ +#define SILK_ENC_INVALID_CBR_SETTING -109 + +/* Internal encoder error */ +#define SILK_ENC_INTERNAL_ERROR -110 + +/* Internal encoder error */ +#define SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR -111 + +/**************************/ +/* Decoder error messages */ +/**************************/ + +/* Output sampling frequency lower than internal decoded sampling frequency */ +#define SILK_DEC_INVALID_SAMPLING_FREQUENCY -200 + +/* Payload size exceeded the maximum allowed 1024 bytes */ +#define SILK_DEC_PAYLOAD_TOO_LARGE -201 + +/* Payload has bit errors */ +#define SILK_DEC_PAYLOAD_ERROR -202 + +/* Payload has bit errors */ +#define SILK_DEC_INVALID_FRAME_SIZE -203 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/TelegramClient.Opus/opus/silk/fixed/LTP_analysis_filter_FIX.c b/TelegramClient.Opus/opus/silk/fixed/LTP_analysis_filter_FIX.c new file mode 100755 index 0000000..a941908 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/LTP_analysis_filter_FIX.c @@ -0,0 +1,85 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" + +void silk_LTP_analysis_filter_FIX( + opus_int16 *LTP_res, /* O LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length ) */ + const opus_int16 *x, /* I Pointer to input signal with at least max( pitchL ) preceding samples */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag, one for each subframe */ + const opus_int32 invGains_Q16[ MAX_NB_SUBFR ], /* I Inverse quantization gains, one for each subframe */ + const opus_int subfr_length, /* I Length of each subframe */ + const opus_int nb_subfr, /* I Number of subframes */ + const opus_int pre_length /* I Length of the preceding samples starting at &x[0] for each subframe */ +) +{ + const opus_int16 *x_ptr, *x_lag_ptr; + opus_int16 Btmp_Q14[ LTP_ORDER ]; + opus_int16 *LTP_res_ptr; + opus_int k, i, j; + opus_int32 LTP_est; + + x_ptr = x; + LTP_res_ptr = LTP_res; + for( k = 0; k < nb_subfr; k++ ) { + + x_lag_ptr = x_ptr - pitchL[ k ]; + for( i = 0; i < LTP_ORDER; i++ ) { + Btmp_Q14[ i ] = LTPCoef_Q14[ k * LTP_ORDER + i ]; + } + + /* LTP analysis FIR filter */ + for( i = 0; i < subfr_length + pre_length; i++ ) { + LTP_res_ptr[ i ] = x_ptr[ i ]; + + /* Long-term prediction */ + LTP_est = silk_SMULBB( x_lag_ptr[ LTP_ORDER / 2 ], Btmp_Q14[ 0 ] ); + for( j = 1; j < LTP_ORDER; j++ ) { + LTP_est = silk_SMLABB_ovflw( LTP_est, x_lag_ptr[ LTP_ORDER / 2 - j ], Btmp_Q14[ j ] ); + } + LTP_est = silk_RSHIFT_ROUND( LTP_est, 14 ); /* round and -> Q0*/ + + /* Subtract long-term prediction */ + LTP_res_ptr[ i ] = (opus_int16)silk_SAT16( (opus_int32)x_ptr[ i ] - LTP_est ); + + /* Scale residual */ + LTP_res_ptr[ i ] = silk_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] ); + + x_lag_ptr++; + } + + /* Update pointers */ + LTP_res_ptr += subfr_length + pre_length; + x_ptr += subfr_length; + } +} + diff --git a/TelegramClient.Opus/opus/silk/fixed/LTP_scale_ctrl_FIX.c b/TelegramClient.Opus/opus/silk/fixed/LTP_scale_ctrl_FIX.c new file mode 100755 index 0000000..3dcedef --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/LTP_scale_ctrl_FIX.c @@ -0,0 +1,53 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" + +/* Calculation of LTP state scaling */ +void silk_LTP_scale_ctrl_FIX( + silk_encoder_state_FIX *psEnc, /* I/O encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ + opus_int condCoding /* I The type of conditional coding to use */ +) +{ + opus_int round_loss; + + if( condCoding == CODE_INDEPENDENTLY ) { + /* Only scale if first frame in packet */ + round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket; + psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( + silk_SMULWB( silk_SMULBB( round_loss, psEncCtrl->LTPredCodGain_Q7 ), SILK_FIX_CONST( 0.1, 9 ) ), 0, 2 ); + } else { + /* Default is minimum scaling */ + psEnc->sCmn.indices.LTP_scaleIndex = 0; + } + psEncCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ]; +} diff --git a/TelegramClient.Opus/opus/silk/fixed/apply_sine_window_FIX.c b/TelegramClient.Opus/opus/silk/fixed/apply_sine_window_FIX.c new file mode 100755 index 0000000..4502b71 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/apply_sine_window_FIX.c @@ -0,0 +1,101 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* Apply sine window to signal vector. */ +/* Window types: */ +/* 1 -> sine window from 0 to pi/2 */ +/* 2 -> sine window from pi/2 to pi */ +/* Every other sample is linearly interpolated, for speed. */ +/* Window length must be between 16 and 120 (incl) and a multiple of 4. */ + +/* Matlab code for table: + for k=16:9*4:16+2*9*4, fprintf(' %7.d,', -round(65536*pi ./ (k:4:k+8*4))); fprintf('\n'); end +*/ +static const opus_int16 freq_table_Q16[ 27 ] = { + 12111, 9804, 8235, 7100, 6239, 5565, 5022, 4575, 4202, + 3885, 3612, 3375, 3167, 2984, 2820, 2674, 2542, 2422, + 2313, 2214, 2123, 2038, 1961, 1889, 1822, 1760, 1702, +}; + +void silk_apply_sine_window( + opus_int16 px_win[], /* O Pointer to windowed signal */ + const opus_int16 px[], /* I Pointer to input signal */ + const opus_int win_type, /* I Selects a window type */ + const opus_int length /* I Window length, multiple of 4 */ +) +{ + opus_int k, f_Q16, c_Q16; + opus_int32 S0_Q16, S1_Q16; + + silk_assert( win_type == 1 || win_type == 2 ); + + /* Length must be in a range from 16 to 120 and a multiple of 4 */ + silk_assert( length >= 16 && length <= 120 ); + silk_assert( ( length & 3 ) == 0 ); + + /* Frequency */ + k = ( length >> 2 ) - 4; + silk_assert( k >= 0 && k <= 26 ); + f_Q16 = (opus_int)freq_table_Q16[ k ]; + + /* Factor used for cosine approximation */ + c_Q16 = silk_SMULWB( (opus_int32)f_Q16, -f_Q16 ); + silk_assert( c_Q16 >= -32768 ); + + /* initialize state */ + if( win_type == 1 ) { + /* start from 0 */ + S0_Q16 = 0; + /* approximation of sin(f) */ + S1_Q16 = f_Q16 + silk_RSHIFT( length, 3 ); + } else { + /* start from 1 */ + S0_Q16 = ( (opus_int32)1 << 16 ); + /* approximation of cos(f) */ + S1_Q16 = ( (opus_int32)1 << 16 ) + silk_RSHIFT( c_Q16, 1 ) + silk_RSHIFT( length, 4 ); + } + + /* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */ + /* 4 samples at a time */ + for( k = 0; k < length; k += 4 ) { + px_win[ k ] = (opus_int16)silk_SMULWB( silk_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k ] ); + px_win[ k + 1 ] = (opus_int16)silk_SMULWB( S1_Q16, px[ k + 1] ); + S0_Q16 = silk_SMULWB( S1_Q16, c_Q16 ) + silk_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1; + S0_Q16 = silk_min( S0_Q16, ( (opus_int32)1 << 16 ) ); + + px_win[ k + 2 ] = (opus_int16)silk_SMULWB( silk_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k + 2] ); + px_win[ k + 3 ] = (opus_int16)silk_SMULWB( S0_Q16, px[ k + 3 ] ); + S1_Q16 = silk_SMULWB( S0_Q16, c_Q16 ) + silk_LSHIFT( S0_Q16, 1 ) - S1_Q16; + S1_Q16 = silk_min( S1_Q16, ( (opus_int32)1 << 16 ) ); + } +} diff --git a/TelegramClient.Opus/opus/silk/fixed/autocorr_FIX.c b/TelegramClient.Opus/opus/silk/fixed/autocorr_FIX.c new file mode 100755 index 0000000..de95c98 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/autocorr_FIX.c @@ -0,0 +1,48 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" +#include "celt_lpc.h" + +/* Compute autocorrelation */ +void silk_autocorr( + opus_int32 *results, /* O Result (length correlationCount) */ + opus_int *scale, /* O Scaling of the correlation vector */ + const opus_int16 *inputData, /* I Input data to correlate */ + const opus_int inputDataSize, /* I Length of input */ + const opus_int correlationCount, /* I Number of correlation taps to compute */ + int arch /* I Run-time architecture */ +) +{ + opus_int corrCount; + corrCount = silk_min_int( inputDataSize, correlationCount ); + *scale = _celt_autocorr(inputData, results, NULL, 0, corrCount-1, inputDataSize, arch); +} diff --git a/TelegramClient.Opus/opus/silk/fixed/burg_modified_FIX.c b/TelegramClient.Opus/opus/silk/fixed/burg_modified_FIX.c new file mode 100755 index 0000000..db34829 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/burg_modified_FIX.c @@ -0,0 +1,279 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" +#include "define.h" +#include "tuning_parameters.h" +#include "pitch.h" + +#define MAX_FRAME_SIZE 384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */ + +#define QA 25 +#define N_BITS_HEAD_ROOM 2 +#define MIN_RSHIFTS -16 +#define MAX_RSHIFTS (32 - QA) + +/* Compute reflection coefficients from input signal */ +void silk_burg_modified( + opus_int32 *res_nrg, /* O Residual energy */ + opus_int *res_nrg_Q, /* O Residual energy Q value */ + opus_int32 A_Q16[], /* O Prediction coefficients (length order) */ + const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */ + const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */ + const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */ + const opus_int nb_subfr, /* I Number of subframes stacked in x */ + const opus_int D, /* I Order */ + int arch /* I Run-time architecture */ +) +{ + opus_int k, n, s, lz, rshifts, rshifts_extra, reached_max_gain; + opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2; + const opus_int16 *x_ptr; + opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ]; + opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ]; + opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ]; + opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ]; + opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ]; + opus_int32 xcorr[ SILK_MAX_ORDER_LPC ]; + + silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE ); + + /* Compute autocorrelations, added over subframes */ + silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length ); + if( rshifts > MAX_RSHIFTS ) { + C0 = silk_LSHIFT32( C0, rshifts - MAX_RSHIFTS ); + silk_assert( C0 > 0 ); + rshifts = MAX_RSHIFTS; + } else { + lz = silk_CLZ32( C0 ) - 1; + rshifts_extra = N_BITS_HEAD_ROOM - lz; + if( rshifts_extra > 0 ) { + rshifts_extra = silk_min( rshifts_extra, MAX_RSHIFTS - rshifts ); + C0 = silk_RSHIFT32( C0, rshifts_extra ); + } else { + rshifts_extra = silk_max( rshifts_extra, MIN_RSHIFTS - rshifts ); + C0 = silk_LSHIFT32( C0, -rshifts_extra ); + } + rshifts += rshifts_extra; + } + CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ + silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); + if( rshifts > 0 ) { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + for( n = 1; n < D + 1; n++ ) { + C_first_row[ n - 1 ] += (opus_int32)silk_RSHIFT64( + silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n ), rshifts ); + } + } + } else { + for( s = 0; s < nb_subfr; s++ ) { + int i; + opus_int32 d; + x_ptr = x + s * subfr_length; + celt_pitch_xcorr(x_ptr, x_ptr + 1, xcorr, subfr_length - D, D, arch ); + for( n = 1; n < D + 1; n++ ) { + for ( i = n + subfr_length - D, d = 0; i < subfr_length; i++ ) + d = MAC16_16( d, x_ptr[ i ], x_ptr[ i - n ] ); + xcorr[ n - 1 ] += d; + } + for( n = 1; n < D + 1; n++ ) { + C_first_row[ n - 1 ] += silk_LSHIFT32( xcorr[ n - 1 ], -rshifts ); + } + } + } + silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) ); + + /* Initialize */ + CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1; /* Q(-rshifts) */ + + invGain_Q30 = (opus_int32)1 << 30; + reached_max_gain = 0; + for( n = 0; n < D; n++ ) { + /* Update first row of correlation matrix (without first element) */ + /* Update last row of correlation matrix (without last element, stored in reversed order) */ + /* Update C * Af */ + /* Update C * flipud(Af) (stored in reversed order) */ + if( rshifts > -2 ) { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], 16 - rshifts ); /* Q(16-rshifts) */ + x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); /* Q(16-rshifts) */ + tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], QA - 16 ); /* Q(QA-16) */ + tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); /* Q(QA-16) */ + for( k = 0; k < n; k++ ) { + C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ + C_last_row[ k ] = silk_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ + Atmp_QA = Af_QA[ k ]; + tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); /* Q(QA-16) */ + tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); /* Q(QA-16) */ + } + tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts ); /* Q(16-rshifts) */ + tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts ); /* Q(16-rshifts) */ + for( k = 0; k <= n; k++ ) { + CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); /* Q( -rshift ) */ + CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); /* Q( -rshift ) */ + } + } + } else { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + x1 = -silk_LSHIFT32( (opus_int32)x_ptr[ n ], -rshifts ); /* Q( -rshifts ) */ + x2 = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); /* Q( -rshifts ) */ + tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ], 17 ); /* Q17 */ + tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 ); /* Q17 */ + for( k = 0; k < n; k++ ) { + C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); /* Q( -rshifts ) */ + C_last_row[ k ] = silk_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */ + Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); /* Q17 */ + tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); /* Q17 */ + tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); /* Q17 */ + } + tmp1 = -tmp1; /* Q17 */ + tmp2 = -tmp2; /* Q17 */ + for( k = 0; k <= n; k++ ) { + CAf[ k ] = silk_SMLAWW( CAf[ k ], tmp1, + silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) ); /* Q( -rshift ) */ + CAb[ k ] = silk_SMLAWW( CAb[ k ], tmp2, + silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift ) */ + } + } + } + + /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */ + tmp1 = C_first_row[ n ]; /* Q( -rshifts ) */ + tmp2 = C_last_row[ n ]; /* Q( -rshifts ) */ + num = 0; /* Q( -rshifts ) */ + nrg = silk_ADD32( CAb[ 0 ], CAf[ 0 ] ); /* Q( 1-rshifts ) */ + for( k = 0; k < n; k++ ) { + Atmp_QA = Af_QA[ k ]; + lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1; + lz = silk_min( 32 - QA, lz ); + Atmp1 = silk_LSHIFT32( Atmp_QA, lz ); /* Q( QA + lz ) */ + + tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ + tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ + num = silk_ADD_LSHIFT32( num, silk_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); /* Q( -rshifts ) */ + nrg = silk_ADD_LSHIFT32( nrg, silk_SMMUL( silk_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ), + Atmp1 ), 32 - QA - lz ); /* Q( 1-rshifts ) */ + } + CAf[ n + 1 ] = tmp1; /* Q( -rshifts ) */ + CAb[ n + 1 ] = tmp2; /* Q( -rshifts ) */ + num = silk_ADD32( num, tmp2 ); /* Q( -rshifts ) */ + num = silk_LSHIFT32( -num, 1 ); /* Q( 1-rshifts ) */ + + /* Calculate the next order reflection (parcor) coefficient */ + if( silk_abs( num ) < nrg ) { + rc_Q31 = silk_DIV32_varQ( num, nrg, 31 ); + } else { + rc_Q31 = ( num > 0 ) ? silk_int32_MAX : silk_int32_MIN; + } + + /* Update inverse prediction gain */ + tmp1 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 ); + tmp1 = silk_LSHIFT( silk_SMMUL( invGain_Q30, tmp1 ), 2 ); + if( tmp1 <= minInvGain_Q30 ) { + /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */ + tmp2 = ( (opus_int32)1 << 30 ) - silk_DIV32_varQ( minInvGain_Q30, invGain_Q30, 30 ); /* Q30 */ + rc_Q31 = silk_SQRT_APPROX( tmp2 ); /* Q15 */ + /* Newton-Raphson iteration */ + rc_Q31 = silk_RSHIFT32( rc_Q31 + silk_DIV32( tmp2, rc_Q31 ), 1 ); /* Q15 */ + rc_Q31 = silk_LSHIFT32( rc_Q31, 16 ); /* Q31 */ + if( num < 0 ) { + /* Ensure adjusted reflection coefficients has the original sign */ + rc_Q31 = -rc_Q31; + } + invGain_Q30 = minInvGain_Q30; + reached_max_gain = 1; + } else { + invGain_Q30 = tmp1; + } + + /* Update the AR coefficients */ + for( k = 0; k < (n + 1) >> 1; k++ ) { + tmp1 = Af_QA[ k ]; /* QA */ + tmp2 = Af_QA[ n - k - 1 ]; /* QA */ + Af_QA[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* QA */ + Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* QA */ + } + Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA ); /* QA */ + + if( reached_max_gain ) { + /* Reached max prediction gain; set remaining coefficients to zero and exit loop */ + for( k = n + 1; k < D; k++ ) { + Af_QA[ k ] = 0; + } + break; + } + + /* Update C * Af and C * Ab */ + for( k = 0; k <= n + 1; k++ ) { + tmp1 = CAf[ k ]; /* Q( -rshifts ) */ + tmp2 = CAb[ n - k + 1 ]; /* Q( -rshifts ) */ + CAf[ k ] = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 ); /* Q( -rshifts ) */ + CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 ); /* Q( -rshifts ) */ + } + } + + if( reached_max_gain ) { + for( k = 0; k < D; k++ ) { + /* Scale coefficients */ + A_Q16[ k ] = -silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); + } + /* Subtract energy of preceding samples from C0 */ + if( rshifts > 0 ) { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D ), rshifts ); + } + } else { + for( s = 0; s < nb_subfr; s++ ) { + x_ptr = x + s * subfr_length; + C0 -= silk_LSHIFT32( silk_inner_prod_aligned( x_ptr, x_ptr, D ), -rshifts ); + } + } + /* Approximate residual energy */ + *res_nrg = silk_LSHIFT( silk_SMMUL( invGain_Q30, C0 ), 2 ); + *res_nrg_Q = -rshifts; + } else { + /* Return residual energy */ + nrg = CAf[ 0 ]; /* Q( -rshifts ) */ + tmp1 = (opus_int32)1 << 16; /* Q16 */ + for( k = 0; k < D; k++ ) { + Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); /* Q16 */ + nrg = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); /* Q( -rshifts ) */ + tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 ); /* Q16 */ + A_Q16[ k ] = -Atmp1; + } + *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ), -tmp1 );/* Q( -rshifts ) */ + *res_nrg_Q = -rshifts; + } +} diff --git a/TelegramClient.Opus/opus/silk/fixed/corrMatrix_FIX.c b/TelegramClient.Opus/opus/silk/fixed/corrMatrix_FIX.c new file mode 100755 index 0000000..c617270 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/corrMatrix_FIX.c @@ -0,0 +1,156 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/********************************************************************** + * Correlation Matrix Computations for LS estimate. + **********************************************************************/ + +#include "main_FIX.h" + +/* Calculates correlation vector X'*t */ +void silk_corrVector_FIX( + const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ + const opus_int16 *t, /* I Target vector [L] */ + const opus_int L, /* I Length of vectors */ + const opus_int order, /* I Max lag for correlation */ + opus_int32 *Xt, /* O Pointer to X'*t correlation vector [order] */ + const opus_int rshifts /* I Right shifts of correlations */ +) +{ + opus_int lag, i; + const opus_int16 *ptr1, *ptr2; + opus_int32 inner_prod; + + ptr1 = &x[ order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */ + ptr2 = t; + /* Calculate X'*t */ + if( rshifts > 0 ) { + /* Right shifting used */ + for( lag = 0; lag < order; lag++ ) { + inner_prod = 0; + for( i = 0; i < L; i++ ) { + inner_prod += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts ); + } + Xt[ lag ] = inner_prod; /* X[:,lag]'*t */ + ptr1--; /* Go to next column of X */ + } + } else { + silk_assert( rshifts == 0 ); + for( lag = 0; lag < order; lag++ ) { + Xt[ lag ] = silk_inner_prod_aligned( ptr1, ptr2, L ); /* X[:,lag]'*t */ + ptr1--; /* Go to next column of X */ + } + } +} + +/* Calculates correlation matrix X'*X */ +void silk_corrMatrix_FIX( + const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ + const opus_int L, /* I Length of vectors */ + const opus_int order, /* I Max lag for correlation */ + const opus_int head_room, /* I Desired headroom */ + opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */ + opus_int *rshifts /* I/O Right shifts of correlations */ +) +{ + opus_int i, j, lag, rshifts_local, head_room_rshifts; + opus_int32 energy; + const opus_int16 *ptr1, *ptr2; + + /* Calculate energy to find shift used to fit in 32 bits */ + silk_sum_sqr_shift( &energy, &rshifts_local, x, L + order - 1 ); + /* Add shifts to get the desired head room */ + head_room_rshifts = silk_max( head_room - silk_CLZ32( energy ), 0 ); + + energy = silk_RSHIFT32( energy, head_room_rshifts ); + rshifts_local += head_room_rshifts; + + /* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */ + /* Remove contribution of first order - 1 samples */ + for( i = 0; i < order - 1; i++ ) { + energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), rshifts_local ); + } + if( rshifts_local < *rshifts ) { + /* Adjust energy */ + energy = silk_RSHIFT32( energy, *rshifts - rshifts_local ); + rshifts_local = *rshifts; + } + + /* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */ + /* Fill out the diagonal of the correlation matrix */ + matrix_ptr( XX, 0, 0, order ) = energy; + ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */ + for( j = 1; j < order; j++ ) { + energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), rshifts_local ) ); + energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), rshifts_local ) ); + matrix_ptr( XX, j, j, order ) = energy; + } + + ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */ + /* Calculate the remaining elements of the correlation matrix */ + if( rshifts_local > 0 ) { + /* Right shifting used */ + for( lag = 1; lag < order; lag++ ) { + /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ + energy = 0; + for( i = 0; i < L; i++ ) { + energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts_local ); + } + /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ + matrix_ptr( XX, lag, 0, order ) = energy; + matrix_ptr( XX, 0, lag, order ) = energy; + for( j = 1; j < ( order - lag ); j++ ) { + energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), rshifts_local ) ); + energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), rshifts_local ) ); + matrix_ptr( XX, lag + j, j, order ) = energy; + matrix_ptr( XX, j, lag + j, order ) = energy; + } + ptr2--; /* Update pointer to first sample of next column (lag) in X */ + } + } else { + for( lag = 1; lag < order; lag++ ) { + /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */ + energy = silk_inner_prod_aligned( ptr1, ptr2, L ); + matrix_ptr( XX, lag, 0, order ) = energy; + matrix_ptr( XX, 0, lag, order ) = energy; + /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */ + for( j = 1; j < ( order - lag ); j++ ) { + energy = silk_SUB32( energy, silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ) ); + energy = silk_SMLABB( energy, ptr1[ -j ], ptr2[ -j ] ); + matrix_ptr( XX, lag + j, j, order ) = energy; + matrix_ptr( XX, j, lag + j, order ) = energy; + } + ptr2--;/* Update pointer to first sample of next column (lag) in X */ + } + } + *rshifts = rshifts_local; +} + diff --git a/TelegramClient.Opus/opus/silk/fixed/encode_frame_FIX.c b/TelegramClient.Opus/opus/silk/fixed/encode_frame_FIX.c new file mode 100755 index 0000000..b490986 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/encode_frame_FIX.c @@ -0,0 +1,385 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" +#include "stack_alloc.h" +#include "tuning_parameters.h" + +/* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */ +static OPUS_INLINE void silk_LBRR_encode_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ + const opus_int32 xfw_Q3[], /* I Input signal */ + opus_int condCoding /* I The type of conditional coding used so far for this frame */ +); + +void silk_encode_do_VAD_FIX( + silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */ +) +{ + /****************************/ + /* Voice Activity Detection */ + /****************************/ + silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1 ); + + /**************************************************/ + /* Convert speech activity into VAD and DTX flags */ + /**************************************************/ + if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) { + psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY; + psEnc->sCmn.noSpeechCounter++; + if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) { + psEnc->sCmn.inDTX = 0; + } else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) { + psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX; + psEnc->sCmn.inDTX = 0; + } + psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 0; + } else { + psEnc->sCmn.noSpeechCounter = 0; + psEnc->sCmn.inDTX = 0; + psEnc->sCmn.indices.signalType = TYPE_UNVOICED; + psEnc->sCmn.VAD_flags[ psEnc->sCmn.nFramesEncoded ] = 1; + } +} + +/****************/ +/* Encode frame */ +/****************/ +opus_int silk_encode_frame_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ + opus_int32 *pnBytesOut, /* O Pointer to number of payload bytes; */ + ec_enc *psRangeEnc, /* I/O compressor data structure */ + opus_int condCoding, /* I The type of conditional coding to use */ + opus_int maxBits, /* I If > 0: maximum number of output bits */ + opus_int useCBR /* I Flag to force constant-bitrate operation */ +) +{ + silk_encoder_control_FIX sEncCtrl; + opus_int i, iter, maxIter, found_upper, found_lower, ret = 0; + opus_int16 *x_frame; + ec_enc sRangeEnc_copy, sRangeEnc_copy2; + silk_nsq_state sNSQ_copy, sNSQ_copy2; + opus_int32 seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper; + opus_int32 gainsID, gainsID_lower, gainsID_upper; + opus_int16 gainMult_Q8; + opus_int16 ec_prevLagIndex_copy; + opus_int ec_prevSignalType_copy; + opus_int8 LastGainIndex_copy2; + SAVE_STACK; + + /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */ + LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0; + + psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3; + + /**************************************************************/ + /* Set up Input Pointers, and insert frame in input buffer */ + /*************************************************************/ + /* start of frame to encode */ + x_frame = psEnc->x_buf + psEnc->sCmn.ltp_mem_length; + + /***************************************/ + /* Ensure smooth bandwidth transitions */ + /***************************************/ + silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length ); + + /*******************************************/ + /* Copy new frame to front of input buffer */ + /*******************************************/ + silk_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) ); + + if( !psEnc->sCmn.prefillFlag ) { + VARDECL( opus_int32, xfw_Q3 ); + VARDECL( opus_int16, res_pitch ); + VARDECL( opus_uint8, ec_buf_copy ); + opus_int16 *res_pitch_frame; + + ALLOC( res_pitch, + psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + + psEnc->sCmn.ltp_mem_length, opus_int16 ); + /* start of pitch LPC residual frame */ + res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length; + + /*****************************************/ + /* Find pitch lags, initial LPC analysis */ + /*****************************************/ + silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, psEnc->sCmn.arch ); + + /************************/ + /* Noise shape analysis */ + /************************/ + silk_noise_shape_analysis_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, psEnc->sCmn.arch ); + + /***************************************************/ + /* Find linear prediction coefficients (LPC + LTP) */ + /***************************************************/ + silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding ); + + /****************************************/ + /* Process gains */ + /****************************************/ + silk_process_gains_FIX( psEnc, &sEncCtrl, condCoding ); + + /*****************************************/ + /* Prefiltering for noise shaper */ + /*****************************************/ + ALLOC( xfw_Q3, psEnc->sCmn.frame_length, opus_int32 ); + silk_prefilter_FIX( psEnc, &sEncCtrl, xfw_Q3, x_frame ); + + /****************************************/ + /* Low Bitrate Redundant Encoding */ + /****************************************/ + silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw_Q3, condCoding ); + + /* Loop over quantizer and entropy coding to control bitrate */ + maxIter = 6; + gainMult_Q8 = SILK_FIX_CONST( 1, 8 ); + found_lower = 0; + found_upper = 0; + gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr ); + gainsID_lower = -1; + gainsID_upper = -1; + /* Copy part of the input state */ + silk_memcpy( &sRangeEnc_copy, psRangeEnc, sizeof( ec_enc ) ); + silk_memcpy( &sNSQ_copy, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); + seed_copy = psEnc->sCmn.indices.Seed; + ec_prevLagIndex_copy = psEnc->sCmn.ec_prevLagIndex; + ec_prevSignalType_copy = psEnc->sCmn.ec_prevSignalType; + ALLOC( ec_buf_copy, 1275, opus_uint8 ); + for( iter = 0; ; iter++ ) { + if( gainsID == gainsID_lower ) { + nBits = nBits_lower; + } else if( gainsID == gainsID_upper ) { + nBits = nBits_upper; + } else { + /* Restore part of the input state */ + if( iter > 0 ) { + silk_memcpy( psRangeEnc, &sRangeEnc_copy, sizeof( ec_enc ) ); + silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy, sizeof( silk_nsq_state ) ); + psEnc->sCmn.indices.Seed = seed_copy; + psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy; + psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy; + } + + /*****************************************/ + /* Noise shaping quantization */ + /*****************************************/ + if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { + silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses, + sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, + sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 ); + } else { + silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses, + sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14, + sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 ); + } + + /****************************************/ + /* Encode Parameters */ + /****************************************/ + silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding ); + + /****************************************/ + /* Encode Excitation Signal */ + /****************************************/ + silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType, + psEnc->sCmn.pulses, psEnc->sCmn.frame_length ); + + nBits = ec_tell( psRangeEnc ); + + if( useCBR == 0 && iter == 0 && nBits <= maxBits ) { + break; + } + } + + if( iter == maxIter ) { + if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) { + /* Restore output state from earlier iteration that did meet the bitrate budget */ + silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) ); + silk_assert( sRangeEnc_copy2.offs <= 1275 ); + silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs ); + silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) ); + psEnc->sShape.LastGainIndex = LastGainIndex_copy2; + } + break; + } + + if( nBits > maxBits ) { + if( found_lower == 0 && iter >= 2 ) { + /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */ + sEncCtrl.Lambda_Q10 = silk_ADD_RSHIFT32( sEncCtrl.Lambda_Q10, sEncCtrl.Lambda_Q10, 1 ); + found_upper = 0; + gainsID_upper = -1; + } else { + found_upper = 1; + nBits_upper = nBits; + gainMult_upper = gainMult_Q8; + gainsID_upper = gainsID; + } + } else if( nBits < maxBits - 5 ) { + found_lower = 1; + nBits_lower = nBits; + gainMult_lower = gainMult_Q8; + if( gainsID != gainsID_lower ) { + gainsID_lower = gainsID; + /* Copy part of the output state */ + silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) ); + silk_assert( psRangeEnc->offs <= 1275 ); + silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs ); + silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); + LastGainIndex_copy2 = psEnc->sShape.LastGainIndex; + } + } else { + /* Within 5 bits of budget: close enough */ + break; + } + + if( ( found_lower & found_upper ) == 0 ) { + /* Adjust gain according to high-rate rate/distortion curve */ + opus_int32 gain_factor_Q16; + gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) ); + gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) ); + if( nBits > maxBits ) { + gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) ); + } + gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 ); + } else { + /* Adjust gain by interpolating */ + gainMult_Q8 = gainMult_lower + silk_DIV32_16( silk_MUL( gainMult_upper - gainMult_lower, maxBits - nBits_lower ), nBits_upper - nBits_lower ); + /* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */ + if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) { + gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ); + } else + if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) { + gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ); + } + } + + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 ); + } + + /* Quantize gains */ + psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev; + silk_gains_quant( psEnc->sCmn.indices.GainsIndices, sEncCtrl.Gains_Q16, + &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); + + /* Unique identifier of gains vector */ + gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr ); + } + } + + /* Update input buffer */ + silk_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ], + ( psEnc->sCmn.ltp_mem_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( opus_int16 ) ); + + /* Exit without entropy coding */ + if( psEnc->sCmn.prefillFlag ) { + /* No payload */ + *pnBytesOut = 0; + RESTORE_STACK; + return ret; + } + + /* Parameters needed for next frame */ + psEnc->sCmn.prevLag = sEncCtrl.pitchL[ psEnc->sCmn.nb_subfr - 1 ]; + psEnc->sCmn.prevSignalType = psEnc->sCmn.indices.signalType; + + /****************************************/ + /* Finalize payload */ + /****************************************/ + psEnc->sCmn.first_frame_after_reset = 0; + /* Payload size */ + *pnBytesOut = silk_RSHIFT( ec_tell( psRangeEnc ) + 7, 3 ); + + RESTORE_STACK; + return ret; +} + +/* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate */ +static OPUS_INLINE void silk_LBRR_encode_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk FIX encoder control struct */ + const opus_int32 xfw_Q3[], /* I Input signal */ + opus_int condCoding /* I The type of conditional coding used so far for this frame */ +) +{ + opus_int32 TempGains_Q16[ MAX_NB_SUBFR ]; + SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ]; + silk_nsq_state sNSQ_LBRR; + + /*******************************************/ + /* Control use of inband LBRR */ + /*******************************************/ + if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.speech_activity_Q8 > SILK_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) ) { + psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded ] = 1; + + /* Copy noise shaping quantizer state and quantization indices from regular encoding */ + silk_memcpy( &sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) ); + silk_memcpy( psIndices_LBRR, &psEnc->sCmn.indices, sizeof( SideInfoIndices ) ); + + /* Save original gains */ + silk_memcpy( TempGains_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); + + if( psEnc->sCmn.nFramesEncoded == 0 || psEnc->sCmn.LBRR_flags[ psEnc->sCmn.nFramesEncoded - 1 ] == 0 ) { + /* First frame in packet or previous frame not LBRR coded */ + psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex; + + /* Increase Gains to get target LBRR rate */ + psIndices_LBRR->GainsIndices[ 0 ] = psIndices_LBRR->GainsIndices[ 0 ] + psEnc->sCmn.LBRR_GainIncreases; + psIndices_LBRR->GainsIndices[ 0 ] = silk_min_int( psIndices_LBRR->GainsIndices[ 0 ], N_LEVELS_QGAIN - 1 ); + } + + /* Decode to get gains in sync with decoder */ + /* Overwrite unquantized gains with quantized gains */ + silk_gains_dequant( psEncCtrl->Gains_Q16, psIndices_LBRR->GainsIndices, + &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); + + /*****************************************/ + /* Noise shaping quantization */ + /*****************************************/ + if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) { + silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3, + psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, + psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, + psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 ); + } else { + silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3, + psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14, + psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14, + psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 ); + } + + /* Restore original gains */ + silk_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); + } +} diff --git a/TelegramClient.Opus/opus/silk/fixed/find_LPC_FIX.c b/TelegramClient.Opus/opus/silk/fixed/find_LPC_FIX.c new file mode 100755 index 0000000..783d32e --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/find_LPC_FIX.c @@ -0,0 +1,151 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" +#include "stack_alloc.h" +#include "tuning_parameters.h" + +/* Finds LPC vector from correlations, and converts to NLSF */ +void silk_find_LPC_FIX( + silk_encoder_state *psEncC, /* I/O Encoder state */ + opus_int16 NLSF_Q15[], /* O NLSFs */ + const opus_int16 x[], /* I Input signal */ + const opus_int32 minInvGain_Q30 /* I Inverse of max prediction gain */ +) +{ + opus_int k, subfr_length; + opus_int32 a_Q16[ MAX_LPC_ORDER ]; + opus_int isInterpLower, shift; + opus_int32 res_nrg0, res_nrg1; + opus_int rshift0, rshift1; + + /* Used only for LSF interpolation */ + opus_int32 a_tmp_Q16[ MAX_LPC_ORDER ], res_nrg_interp, res_nrg, res_tmp_nrg; + opus_int res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q; + opus_int16 a_tmp_Q12[ MAX_LPC_ORDER ]; + opus_int16 NLSF0_Q15[ MAX_LPC_ORDER ]; + SAVE_STACK; + + subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder; + + /* Default: no interpolation */ + psEncC->indices.NLSFInterpCoef_Q2 = 4; + + /* Burg AR analysis for the full frame */ + silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, minInvGain_Q30, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder, psEncC->arch ); + + if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) { + VARDECL( opus_int16, LPC_res ); + + /* Optimal solution for last 10 ms */ + silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + 2 * subfr_length, minInvGain_Q30, subfr_length, 2, psEncC->predictLPCOrder, psEncC->arch ); + + /* subtract residual energy here, as that's easier than adding it to the */ + /* residual energy of the first 10 ms in each iteration of the search below */ + shift = res_tmp_nrg_Q - res_nrg_Q; + if( shift >= 0 ) { + if( shift < 32 ) { + res_nrg = res_nrg - silk_RSHIFT( res_tmp_nrg, shift ); + } + } else { + silk_assert( shift > -32 ); + res_nrg = silk_RSHIFT( res_nrg, -shift ) - res_tmp_nrg; + res_nrg_Q = res_tmp_nrg_Q; + } + + /* Convert to NLSFs */ + silk_A2NLSF( NLSF_Q15, a_tmp_Q16, psEncC->predictLPCOrder ); + + ALLOC( LPC_res, 2 * subfr_length, opus_int16 ); + + /* Search over interpolation indices to find the one with lowest residual energy */ + for( k = 3; k >= 0; k-- ) { + /* Interpolate NLSFs for first half */ + silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder ); + + /* Convert to LPC for residual energy evaluation */ + silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder ); + + /* Calculate residual energy with NLSF interpolation */ + silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, psEncC->predictLPCOrder ); + + silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + psEncC->predictLPCOrder, subfr_length - psEncC->predictLPCOrder ); + silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder ); + + /* Add subframe energies from first half frame */ + shift = rshift0 - rshift1; + if( shift >= 0 ) { + res_nrg1 = silk_RSHIFT( res_nrg1, shift ); + res_nrg_interp_Q = -rshift0; + } else { + res_nrg0 = silk_RSHIFT( res_nrg0, -shift ); + res_nrg_interp_Q = -rshift1; + } + res_nrg_interp = silk_ADD32( res_nrg0, res_nrg1 ); + + /* Compare with first half energy without NLSF interpolation, or best interpolated value so far */ + shift = res_nrg_interp_Q - res_nrg_Q; + if( shift >= 0 ) { + if( silk_RSHIFT( res_nrg_interp, shift ) < res_nrg ) { + isInterpLower = silk_TRUE; + } else { + isInterpLower = silk_FALSE; + } + } else { + if( -shift < 32 ) { + if( res_nrg_interp < silk_RSHIFT( res_nrg, -shift ) ) { + isInterpLower = silk_TRUE; + } else { + isInterpLower = silk_FALSE; + } + } else { + isInterpLower = silk_FALSE; + } + } + + /* Determine whether current interpolated NLSFs are best so far */ + if( isInterpLower == silk_TRUE ) { + /* Interpolation has lower residual energy */ + res_nrg = res_nrg_interp; + res_nrg_Q = res_nrg_interp_Q; + psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k; + } + } + } + + if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) { + /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */ + silk_A2NLSF( NLSF_Q15, a_Q16, psEncC->predictLPCOrder ); + } + + silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) ); + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/fixed/find_LTP_FIX.c b/TelegramClient.Opus/opus/silk/fixed/find_LTP_FIX.c new file mode 100755 index 0000000..8c4d703 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/find_LTP_FIX.c @@ -0,0 +1,244 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" +#include "tuning_parameters.h" + +/* Head room for correlations */ +#define LTP_CORRS_HEAD_ROOM 2 + +void silk_fit_LTP( + opus_int32 LTP_coefs_Q16[ LTP_ORDER ], + opus_int16 LTP_coefs_Q14[ LTP_ORDER ] +); + +void silk_find_LTP_FIX( + opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ + opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ + opus_int *LTPredCodGain_Q7, /* O LTP coding gain */ + const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */ + const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ + const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */ + const opus_int subfr_length, /* I subframe length */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int mem_offset, /* I number of samples in LTP memory */ + opus_int corr_rshifts[ MAX_NB_SUBFR ] /* O right shifts applied to correlations */ +) +{ + opus_int i, k, lshift; + const opus_int16 *r_ptr, *lag_ptr; + opus_int16 *b_Q14_ptr; + + opus_int32 regu; + opus_int32 *WLTP_ptr; + opus_int32 b_Q16[ LTP_ORDER ], delta_b_Q14[ LTP_ORDER ], d_Q14[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], g_Q26; + opus_int32 w[ MAX_NB_SUBFR ], WLTP_max, max_abs_d_Q14, max_w_bits; + + opus_int32 temp32, denom32; + opus_int extra_shifts; + opus_int rr_shifts, maxRshifts, maxRshifts_wxtra, LZs; + opus_int32 LPC_res_nrg, LPC_LTP_res_nrg, div_Q16; + opus_int32 Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ]; + opus_int32 wd, m_Q12; + + b_Q14_ptr = b_Q14; + WLTP_ptr = WLTP; + r_ptr = &r_lpc[ mem_offset ]; + for( k = 0; k < nb_subfr; k++ ) { + lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 ); + + silk_sum_sqr_shift( &rr[ k ], &rr_shifts, r_ptr, subfr_length ); /* rr[ k ] in Q( -rr_shifts ) */ + + /* Assure headroom */ + LZs = silk_CLZ32( rr[k] ); + if( LZs < LTP_CORRS_HEAD_ROOM ) { + rr[ k ] = silk_RSHIFT_ROUND( rr[ k ], LTP_CORRS_HEAD_ROOM - LZs ); + rr_shifts += ( LTP_CORRS_HEAD_ROOM - LZs ); + } + corr_rshifts[ k ] = rr_shifts; + silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, LTP_CORRS_HEAD_ROOM, WLTP_ptr, &corr_rshifts[ k ] ); /* WLTP_fix_ptr in Q( -corr_rshifts[ k ] ) */ + + /* The correlation vector always has lower max abs value than rr and/or RR so head room is assured */ + silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr, corr_rshifts[ k ] ); /* Rr_fix_ptr in Q( -corr_rshifts[ k ] ) */ + if( corr_rshifts[ k ] > rr_shifts ) { + rr[ k ] = silk_RSHIFT( rr[ k ], corr_rshifts[ k ] - rr_shifts ); /* rr[ k ] in Q( -corr_rshifts[ k ] ) */ + } + silk_assert( rr[ k ] >= 0 ); + + regu = 1; + regu = silk_SMLAWB( regu, rr[ k ], SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); + regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); + regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) ); + silk_regularize_correlations_FIX( WLTP_ptr, &rr[k], regu, LTP_ORDER ); + + silk_solve_LDL_FIX( WLTP_ptr, LTP_ORDER, Rr, b_Q16 ); /* WLTP_fix_ptr and Rr_fix_ptr both in Q(-corr_rshifts[k]) */ + + /* Limit and store in Q14 */ + silk_fit_LTP( b_Q16, b_Q14_ptr ); + + /* Calculate residual energy */ + nrg[ k ] = silk_residual_energy16_covar_FIX( b_Q14_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER, 14 ); /* nrg_fix in Q( -corr_rshifts[ k ] ) */ + + /* temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); */ + extra_shifts = silk_min_int( corr_rshifts[ k ], LTP_CORRS_HEAD_ROOM ); + denom32 = silk_LSHIFT_SAT32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 + extra_shifts ) + /* Q( -corr_rshifts[ k ] + extra_shifts ) */ + silk_RSHIFT( silk_SMULWB( (opus_int32)subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */ + denom32 = silk_max( denom32, 1 ); + silk_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < silk_int32_MAX ); /* Wght always < 0.5 in Q0 */ + temp32 = silk_DIV32( silk_LSHIFT( (opus_int32)Wght_Q15[ k ], 16 ), denom32 ); /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */ + temp32 = silk_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 ); /* Q26 */ + + /* Limit temp such that the below scaling never wraps around */ + WLTP_max = 0; + for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) { + WLTP_max = silk_max( WLTP_ptr[ i ], WLTP_max ); + } + lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */ + silk_assert( 26 - 18 + lshift >= 0 ); + if( 26 - 18 + lshift < 31 ) { + temp32 = silk_min_32( temp32, silk_LSHIFT( (opus_int32)1, 26 - 18 + lshift ) ); + } + + silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */ + + w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER/2, LTP_ORDER/2, LTP_ORDER ); /* w in Q( 18 - corr_rshifts[ k ] ) */ + silk_assert( w[k] >= 0 ); + + r_ptr += subfr_length; + b_Q14_ptr += LTP_ORDER; + WLTP_ptr += LTP_ORDER * LTP_ORDER; + } + + maxRshifts = 0; + for( k = 0; k < nb_subfr; k++ ) { + maxRshifts = silk_max_int( corr_rshifts[ k ], maxRshifts ); + } + + /* Compute LTP coding gain */ + if( LTPredCodGain_Q7 != NULL ) { + LPC_LTP_res_nrg = 0; + LPC_res_nrg = 0; + silk_assert( LTP_CORRS_HEAD_ROOM >= 2 ); /* Check that no overflow will happen when adding */ + for( k = 0; k < nb_subfr; k++ ) { + LPC_res_nrg = silk_ADD32( LPC_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( rr[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ + LPC_LTP_res_nrg = silk_ADD32( LPC_LTP_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */ + } + LPC_LTP_res_nrg = silk_max( LPC_LTP_res_nrg, 1 ); /* avoid division by zero */ + + div_Q16 = silk_DIV32_varQ( LPC_res_nrg, LPC_LTP_res_nrg, 16 ); + *LTPredCodGain_Q7 = ( opus_int )silk_SMULBB( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ); + + silk_assert( *LTPredCodGain_Q7 == ( opus_int )silk_SAT16( silk_MUL( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ) ) ); + } + + /* smoothing */ + /* d = sum( B, 1 ); */ + b_Q14_ptr = b_Q14; + for( k = 0; k < nb_subfr; k++ ) { + d_Q14[ k ] = 0; + for( i = 0; i < LTP_ORDER; i++ ) { + d_Q14[ k ] += b_Q14_ptr[ i ]; + } + b_Q14_ptr += LTP_ORDER; + } + + /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */ + + /* Find maximum absolute value of d_Q14 and the bits used by w in Q0 */ + max_abs_d_Q14 = 0; + max_w_bits = 0; + for( k = 0; k < nb_subfr; k++ ) { + max_abs_d_Q14 = silk_max_32( max_abs_d_Q14, silk_abs( d_Q14[ k ] ) ); + /* w[ k ] is in Q( 18 - corr_rshifts[ k ] ) */ + /* Find bits needed in Q( 18 - maxRshifts ) */ + max_w_bits = silk_max_32( max_w_bits, 32 - silk_CLZ32( w[ k ] ) + corr_rshifts[ k ] - maxRshifts ); + } + + /* max_abs_d_Q14 = (5 << 15); worst case, i.e. LTP_ORDER * -silk_int16_MIN */ + silk_assert( max_abs_d_Q14 <= ( 5 << 15 ) ); + + /* How many bits is needed for w*d' in Q( 18 - maxRshifts ) in the worst case, of all d_Q14's being equal to max_abs_d_Q14 */ + extra_shifts = max_w_bits + 32 - silk_CLZ32( max_abs_d_Q14 ) - 14; + + /* Subtract what we got available; bits in output var plus maxRshifts */ + extra_shifts -= ( 32 - 1 - 2 + maxRshifts ); /* Keep sign bit free as well as 2 bits for accumulation */ + extra_shifts = silk_max_int( extra_shifts, 0 ); + + maxRshifts_wxtra = maxRshifts + extra_shifts; + + temp32 = silk_RSHIFT( 262, maxRshifts + extra_shifts ) + 1; /* 1e-3f in Q( 18 - (maxRshifts + extra_shifts) ) */ + wd = 0; + for( k = 0; k < nb_subfr; k++ ) { + /* w has at least 2 bits of headroom so no overflow should happen */ + temp32 = silk_ADD32( temp32, silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ) ); /* Q( 18 - maxRshifts_wxtra ) */ + wd = silk_ADD32( wd, silk_LSHIFT( silk_SMULWW( silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ), d_Q14[ k ] ), 2 ) ); /* Q( 18 - maxRshifts_wxtra ) */ + } + m_Q12 = silk_DIV32_varQ( wd, temp32, 12 ); + + b_Q14_ptr = b_Q14; + for( k = 0; k < nb_subfr; k++ ) { + /* w_fix[ k ] from Q( 18 - corr_rshifts[ k ] ) to Q( 16 ) */ + if( 2 - corr_rshifts[k] > 0 ) { + temp32 = silk_RSHIFT( w[ k ], 2 - corr_rshifts[ k ] ); + } else { + temp32 = silk_LSHIFT_SAT32( w[ k ], corr_rshifts[ k ] - 2 ); + } + + g_Q26 = silk_MUL( + silk_DIV32( + SILK_FIX_CONST( LTP_SMOOTHING, 26 ), + silk_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ), /* Q10 */ + silk_LSHIFT_SAT32( silk_SUB_SAT32( (opus_int32)m_Q12, silk_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) ); /* Q16 */ + + temp32 = 0; + for( i = 0; i < LTP_ORDER; i++ ) { + delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */ + temp32 += delta_b_Q14[ i ]; /* Q14 */ + } + temp32 = silk_DIV32( g_Q26, temp32 ); /* Q14 -> Q12 */ + for( i = 0; i < LTP_ORDER; i++ ) { + b_Q14_ptr[ i ] = silk_LIMIT_32( (opus_int32)b_Q14_ptr[ i ] + silk_SMULWB( silk_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 ); + } + b_Q14_ptr += LTP_ORDER; + } +} + +void silk_fit_LTP( + opus_int32 LTP_coefs_Q16[ LTP_ORDER ], + opus_int16 LTP_coefs_Q14[ LTP_ORDER ] +) +{ + opus_int i; + + for( i = 0; i < LTP_ORDER; i++ ) { + LTP_coefs_Q14[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) ); + } +} diff --git a/TelegramClient.Opus/opus/silk/fixed/find_pitch_lags_FIX.c b/TelegramClient.Opus/opus/silk/fixed/find_pitch_lags_FIX.c new file mode 100755 index 0000000..620f8dc --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/find_pitch_lags_FIX.c @@ -0,0 +1,145 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" +#include "stack_alloc.h" +#include "tuning_parameters.h" + +/* Find pitch lags */ +void silk_find_pitch_lags_FIX( + silk_encoder_state_FIX *psEnc, /* I/O encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ + opus_int16 res[], /* O residual */ + const opus_int16 x[], /* I Speech signal */ + int arch /* I Run-time architecture */ +) +{ + opus_int buf_len, i, scale; + opus_int32 thrhld_Q13, res_nrg; + const opus_int16 *x_buf, *x_buf_ptr; + VARDECL( opus_int16, Wsig ); + opus_int16 *Wsig_ptr; + opus_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ]; + opus_int16 rc_Q15[ MAX_FIND_PITCH_LPC_ORDER ]; + opus_int32 A_Q24[ MAX_FIND_PITCH_LPC_ORDER ]; + opus_int16 A_Q12[ MAX_FIND_PITCH_LPC_ORDER ]; + SAVE_STACK; + + /******************************************/ + /* Set up buffer lengths etc based on Fs */ + /******************************************/ + buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length; + + /* Safety check */ + silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length ); + + x_buf = x - psEnc->sCmn.ltp_mem_length; + + /*************************************/ + /* Estimate LPC AR coefficients */ + /*************************************/ + + /* Calculate windowed signal */ + + ALLOC( Wsig, psEnc->sCmn.pitch_LPC_win_length, opus_int16 ); + + /* First LA_LTP samples */ + x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length; + Wsig_ptr = Wsig; + silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch ); + + /* Middle un - windowed samples */ + Wsig_ptr += psEnc->sCmn.la_pitch; + x_buf_ptr += psEnc->sCmn.la_pitch; + silk_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) ); + + /* Last LA_LTP samples */ + Wsig_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ); + x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ); + silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch ); + + /* Calculate autocorrelation sequence */ + silk_autocorr( auto_corr, &scale, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1, arch ); + + /* Add white noise, as fraction of energy */ + auto_corr[ 0 ] = silk_SMLAWB( auto_corr[ 0 ], auto_corr[ 0 ], SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ) + 1; + + /* Calculate the reflection coefficients using schur */ + res_nrg = silk_schur( rc_Q15, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder ); + + /* Prediction gain */ + psEncCtrl->predGain_Q16 = silk_DIV32_varQ( auto_corr[ 0 ], silk_max_int( res_nrg, 1 ), 16 ); + + /* Convert reflection coefficients to prediction coefficients */ + silk_k2a( A_Q24, rc_Q15, psEnc->sCmn.pitchEstimationLPCOrder ); + + /* Convert From 32 bit Q24 to 16 bit Q12 coefs */ + for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) { + A_Q12[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT( A_Q24[ i ], 12 ) ); + } + + /* Do BWE */ + silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SILK_FIX_CONST( FIND_PITCH_BANDWIDTH_EXPANSION, 16 ) ); + + /*****************************************/ + /* LPC analysis filtering */ + /*****************************************/ + silk_LPC_analysis_filter( res, x_buf, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder ); + + if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) { + /* Threshold for pitch estimator */ + thrhld_Q13 = SILK_FIX_CONST( 0.6, 13 ); + thrhld_Q13 = silk_SMLABB( thrhld_Q13, SILK_FIX_CONST( -0.004, 13 ), psEnc->sCmn.pitchEstimationLPCOrder ); + thrhld_Q13 = silk_SMLAWB( thrhld_Q13, SILK_FIX_CONST( -0.1, 21 ), psEnc->sCmn.speech_activity_Q8 ); + thrhld_Q13 = silk_SMLABB( thrhld_Q13, SILK_FIX_CONST( -0.15, 13 ), silk_RSHIFT( psEnc->sCmn.prevSignalType, 1 ) ); + thrhld_Q13 = silk_SMLAWB( thrhld_Q13, SILK_FIX_CONST( -0.1, 14 ), psEnc->sCmn.input_tilt_Q15 ); + thrhld_Q13 = silk_SAT16( thrhld_Q13 ); + + /*****************************************/ + /* Call pitch estimator */ + /*****************************************/ + if( silk_pitch_analysis_core( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, &psEnc->sCmn.indices.contourIndex, + &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16, + (opus_int)thrhld_Q13, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr, + psEnc->sCmn.arch) == 0 ) + { + psEnc->sCmn.indices.signalType = TYPE_VOICED; + } else { + psEnc->sCmn.indices.signalType = TYPE_UNVOICED; + } + } else { + silk_memset( psEncCtrl->pitchL, 0, sizeof( psEncCtrl->pitchL ) ); + psEnc->sCmn.indices.lagIndex = 0; + psEnc->sCmn.indices.contourIndex = 0; + psEnc->LTPCorr_Q15 = 0; + } + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/fixed/find_pred_coefs_FIX.c b/TelegramClient.Opus/opus/silk/fixed/find_pred_coefs_FIX.c new file mode 100755 index 0000000..5c22f82 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/find_pred_coefs_FIX.c @@ -0,0 +1,147 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" +#include "stack_alloc.h" + +void silk_find_pred_coefs_FIX( + silk_encoder_state_FIX *psEnc, /* I/O encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ + const opus_int16 res_pitch[], /* I Residual from pitch analysis */ + const opus_int16 x[], /* I Speech signal */ + opus_int condCoding /* I The type of conditional coding to use */ +) +{ + opus_int i; + opus_int32 invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ], Wght_Q15[ MAX_NB_SUBFR ]; + opus_int16 NLSF_Q15[ MAX_LPC_ORDER ]; + const opus_int16 *x_ptr; + opus_int16 *x_pre_ptr; + VARDECL( opus_int16, LPC_in_pre ); + opus_int32 tmp, min_gain_Q16, minInvGain_Q30; + opus_int LTP_corrs_rshift[ MAX_NB_SUBFR ]; + SAVE_STACK; + + /* weighting for weighted least squares */ + min_gain_Q16 = silk_int32_MAX >> 6; + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + min_gain_Q16 = silk_min( min_gain_Q16, psEncCtrl->Gains_Q16[ i ] ); + } + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + /* Divide to Q16 */ + silk_assert( psEncCtrl->Gains_Q16[ i ] > 0 ); + /* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */ + invGains_Q16[ i ] = silk_DIV32_varQ( min_gain_Q16, psEncCtrl->Gains_Q16[ i ], 16 - 2 ); + + /* Ensure Wght_Q15 a minimum value 1 */ + invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 363 ); + + /* Square the inverted gains */ + silk_assert( invGains_Q16[ i ] == silk_SAT16( invGains_Q16[ i ] ) ); + tmp = silk_SMULWB( invGains_Q16[ i ], invGains_Q16[ i ] ); + Wght_Q15[ i ] = silk_RSHIFT( tmp, 1 ); + + /* Invert the inverted and normalized gains */ + local_gains[ i ] = silk_DIV32( ( (opus_int32)1 << 16 ), invGains_Q16[ i ] ); + } + + ALLOC( LPC_in_pre, + psEnc->sCmn.nb_subfr * psEnc->sCmn.predictLPCOrder + + psEnc->sCmn.frame_length, opus_int16 ); + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + VARDECL( opus_int32, WLTP ); + + /**********/ + /* VOICED */ + /**********/ + silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 ); + + ALLOC( WLTP, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 ); + + /* LTP analysis */ + silk_find_LTP_FIX( psEncCtrl->LTPCoef_Q14, WLTP, &psEncCtrl->LTPredCodGain_Q7, + res_pitch, psEncCtrl->pitchL, Wght_Q15, psEnc->sCmn.subfr_length, + psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length, LTP_corrs_rshift ); + + /* Quantize LTP gain parameters */ + silk_quant_LTP_gains( psEncCtrl->LTPCoef_Q14, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex, + &psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr); + + /* Control LTP scaling */ + silk_LTP_scale_ctrl_FIX( psEnc, psEncCtrl, condCoding ); + + /* Create LTP residual */ + silk_LTP_analysis_filter_FIX( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef_Q14, + psEncCtrl->pitchL, invGains_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); + + } else { + /************/ + /* UNVOICED */ + /************/ + /* Create signal with prepended subframes, scaled by inverse gains */ + x_ptr = x - psEnc->sCmn.predictLPCOrder; + x_pre_ptr = LPC_in_pre; + for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) { + silk_scale_copy_vector16( x_pre_ptr, x_ptr, invGains_Q16[ i ], + psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder ); + x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder; + x_ptr += psEnc->sCmn.subfr_length; + } + + silk_memset( psEncCtrl->LTPCoef_Q14, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( opus_int16 ) ); + psEncCtrl->LTPredCodGain_Q7 = 0; + psEnc->sCmn.sum_log_gain_Q7 = 0; + } + + /* Limit on total predictive coding gain */ + if( psEnc->sCmn.first_frame_after_reset ) { + minInvGain_Q30 = SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET, 30 ); + } else { + minInvGain_Q30 = silk_log2lin( silk_SMLAWB( 16 << 7, (opus_int32)psEncCtrl->LTPredCodGain_Q7, SILK_FIX_CONST( 1.0 / 3, 16 ) ) ); /* Q16 */ + minInvGain_Q30 = silk_DIV32_varQ( minInvGain_Q30, + silk_SMULWW( SILK_FIX_CONST( MAX_PREDICTION_POWER_GAIN, 0 ), + silk_SMLAWB( SILK_FIX_CONST( 0.25, 18 ), SILK_FIX_CONST( 0.75, 18 ), psEncCtrl->coding_quality_Q14 ) ), 14 ); + } + + /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */ + silk_find_LPC_FIX( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain_Q30 ); + + /* Quantize LSFs */ + silk_process_NLSFs( &psEnc->sCmn, psEncCtrl->PredCoef_Q12, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 ); + + /* Calculate residual energy using quantized LPC coefficients */ + silk_residual_energy_FIX( psEncCtrl->ResNrg, psEncCtrl->ResNrgQ, LPC_in_pre, psEncCtrl->PredCoef_Q12, local_gains, + psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder ); + + /* Copy to prediction struct for use in next frame for interpolation */ + silk_memcpy( psEnc->sCmn.prev_NLSFq_Q15, NLSF_Q15, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) ); + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/fixed/k2a_FIX.c b/TelegramClient.Opus/opus/silk/fixed/k2a_FIX.c new file mode 100755 index 0000000..5fee599 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/k2a_FIX.c @@ -0,0 +1,53 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* Step up function, converts reflection coefficients to prediction coefficients */ +void silk_k2a( + opus_int32 *A_Q24, /* O Prediction coefficients [order] Q24 */ + const opus_int16 *rc_Q15, /* I Reflection coefficients [order] Q15 */ + const opus_int32 order /* I Prediction order */ +) +{ + opus_int k, n; + opus_int32 Atmp[ SILK_MAX_ORDER_LPC ]; + + for( k = 0; k < order; k++ ) { + for( n = 0; n < k; n++ ) { + Atmp[ n ] = A_Q24[ n ]; + } + for( n = 0; n < k; n++ ) { + A_Q24[ n ] = silk_SMLAWB( A_Q24[ n ], silk_LSHIFT( Atmp[ k - n - 1 ], 1 ), rc_Q15[ k ] ); + } + A_Q24[ k ] = -silk_LSHIFT( (opus_int32)rc_Q15[ k ], 9 ); + } +} diff --git a/TelegramClient.Opus/opus/silk/fixed/k2a_Q16_FIX.c b/TelegramClient.Opus/opus/silk/fixed/k2a_Q16_FIX.c new file mode 100755 index 0000000..3b03987 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/k2a_Q16_FIX.c @@ -0,0 +1,53 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* Step up function, converts reflection coefficients to prediction coefficients */ +void silk_k2a_Q16( + opus_int32 *A_Q24, /* O Prediction coefficients [order] Q24 */ + const opus_int32 *rc_Q16, /* I Reflection coefficients [order] Q16 */ + const opus_int32 order /* I Prediction order */ +) +{ + opus_int k, n; + opus_int32 Atmp[ SILK_MAX_ORDER_LPC ]; + + for( k = 0; k < order; k++ ) { + for( n = 0; n < k; n++ ) { + Atmp[ n ] = A_Q24[ n ]; + } + for( n = 0; n < k; n++ ) { + A_Q24[ n ] = silk_SMLAWW( A_Q24[ n ], Atmp[ k - n - 1 ], rc_Q16[ k ] ); + } + A_Q24[ k ] = -silk_LSHIFT( rc_Q16[ k ], 8 ); + } +} diff --git a/TelegramClient.Opus/opus/silk/fixed/main_FIX.h b/TelegramClient.Opus/opus/silk/fixed/main_FIX.h new file mode 100755 index 0000000..a56ca07 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/main_FIX.h @@ -0,0 +1,257 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_MAIN_FIX_H +#define SILK_MAIN_FIX_H + +#include "SigProc_FIX.h" +#include "structs_FIX.h" +#include "control.h" +#include "main.h" +#include "PLC.h" +#include "debug.h" +#include "entenc.h" + +#ifndef FORCE_CPP_BUILD +#ifdef __cplusplus +extern "C" +{ +#endif +#endif + +#define silk_encoder_state_Fxx silk_encoder_state_FIX +#define silk_encode_do_VAD_Fxx silk_encode_do_VAD_FIX +#define silk_encode_frame_Fxx silk_encode_frame_FIX + +/*********************/ +/* Encoder Functions */ +/*********************/ + +/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */ +void silk_HP_variable_cutoff( + silk_encoder_state_Fxx state_Fxx[] /* I/O Encoder states */ +); + +/* Encoder main function */ +void silk_encode_do_VAD_FIX( + silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */ +); + +/* Encoder main function */ +opus_int silk_encode_frame_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */ + opus_int32 *pnBytesOut, /* O Pointer to number of payload bytes; */ + ec_enc *psRangeEnc, /* I/O compressor data structure */ + opus_int condCoding, /* I The type of conditional coding to use */ + opus_int maxBits, /* I If > 0: maximum number of output bits */ + opus_int useCBR /* I Flag to force constant-bitrate operation */ +); + +/* Initializes the Silk encoder state */ +opus_int silk_init_encoder( + silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk FIX encoder state */ + int arch /* I Run-time architecture */ +); + +/* Control the Silk encoder */ +opus_int silk_control_encoder( + silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */ + silk_EncControlStruct *encControl, /* I Control structure */ + const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */ + const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */ + const opus_int channelNb, /* I Channel number */ + const opus_int force_fs_kHz +); + +/****************/ +/* Prefiltering */ +/****************/ +void silk_prefilter_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ + const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ + opus_int32 xw_Q10[], /* O Weighted signal */ + const opus_int16 x[] /* I Speech signal */ +); + +/**************************/ +/* Noise shaping analysis */ +/**************************/ +/* Compute noise shaping coefficients and initial gain values */ +void silk_noise_shape_analysis_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ + silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ + const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */ + const opus_int16 *x, /* I Input signal [ frame_length + la_shape ] */ + int arch /* I Run-time architecture */ +); + +/* Autocorrelations for a warped frequency axis */ +void silk_warped_autocorrelation_FIX( + opus_int32 *corr, /* O Result [order + 1] */ + opus_int *scale, /* O Scaling of the correlation vector */ + const opus_int16 *input, /* I Input data to correlate */ + const opus_int warping_Q16, /* I Warping coefficient */ + const opus_int length, /* I Length of input */ + const opus_int order /* I Correlation order (even) */ +); + +/* Calculation of LTP state scaling */ +void silk_LTP_scale_ctrl_FIX( + silk_encoder_state_FIX *psEnc, /* I/O encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ + opus_int condCoding /* I The type of conditional coding to use */ +); + +/**********************************************/ +/* Prediction Analysis */ +/**********************************************/ +/* Find pitch lags */ +void silk_find_pitch_lags_FIX( + silk_encoder_state_FIX *psEnc, /* I/O encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ + opus_int16 res[], /* O residual */ + const opus_int16 x[], /* I Speech signal */ + int arch /* I Run-time architecture */ +); + +/* Find LPC and LTP coefficients */ +void silk_find_pred_coefs_FIX( + silk_encoder_state_FIX *psEnc, /* I/O encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */ + const opus_int16 res_pitch[], /* I Residual from pitch analysis */ + const opus_int16 x[], /* I Speech signal */ + opus_int condCoding /* I The type of conditional coding to use */ +); + +/* LPC analysis */ +void silk_find_LPC_FIX( + silk_encoder_state *psEncC, /* I/O Encoder state */ + opus_int16 NLSF_Q15[], /* O NLSFs */ + const opus_int16 x[], /* I Input signal */ + const opus_int32 minInvGain_Q30 /* I Inverse of max prediction gain */ +); + +/* LTP analysis */ +void silk_find_LTP_FIX( + opus_int16 b_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* O LTP coefs */ + opus_int32 WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */ + opus_int *LTPredCodGain_Q7, /* O LTP coding gain */ + const opus_int16 r_lpc[], /* I residual signal after LPC signal + state for first 10 ms */ + const opus_int lag[ MAX_NB_SUBFR ], /* I LTP lags */ + const opus_int32 Wght_Q15[ MAX_NB_SUBFR ], /* I weights */ + const opus_int subfr_length, /* I subframe length */ + const opus_int nb_subfr, /* I number of subframes */ + const opus_int mem_offset, /* I number of samples in LTP memory */ + opus_int corr_rshifts[ MAX_NB_SUBFR ] /* O right shifts applied to correlations */ +); + +void silk_LTP_analysis_filter_FIX( + opus_int16 *LTP_res, /* O LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length ) */ + const opus_int16 *x, /* I Pointer to input signal with at least max( pitchL ) preceding samples */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag, one for each subframe */ + const opus_int32 invGains_Q16[ MAX_NB_SUBFR ], /* I Inverse quantization gains, one for each subframe */ + const opus_int subfr_length, /* I Length of each subframe */ + const opus_int nb_subfr, /* I Number of subframes */ + const opus_int pre_length /* I Length of the preceding samples starting at &x[0] for each subframe */ +); + +/* Calculates residual energies of input subframes where all subframes have LPC_order */ +/* of preceding samples */ +void silk_residual_energy_FIX( + opus_int32 nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ + opus_int nrgsQ[ MAX_NB_SUBFR ], /* O Q value per subframe */ + const opus_int16 x[], /* I Input signal */ + opus_int16 a_Q12[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */ + const opus_int32 gains[ MAX_NB_SUBFR ], /* I Quantization gains */ + const opus_int subfr_length, /* I Subframe length */ + const opus_int nb_subfr, /* I Number of subframes */ + const opus_int LPC_order /* I LPC order */ +); + +/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ +opus_int32 silk_residual_energy16_covar_FIX( + const opus_int16 *c, /* I Prediction vector */ + const opus_int32 *wXX, /* I Correlation matrix */ + const opus_int32 *wXx, /* I Correlation vector */ + opus_int32 wxx, /* I Signal energy */ + opus_int D, /* I Dimension */ + opus_int cQ /* I Q value for c vector 0 - 15 */ +); + +/* Processing of gains */ +void silk_process_gains_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control */ + opus_int condCoding /* I The type of conditional coding to use */ +); + +/******************/ +/* Linear Algebra */ +/******************/ +/* Calculates correlation matrix X'*X */ +void silk_corrMatrix_FIX( + const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ + const opus_int L, /* I Length of vectors */ + const opus_int order, /* I Max lag for correlation */ + const opus_int head_room, /* I Desired headroom */ + opus_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ] */ + opus_int *rshifts /* I/O Right shifts of correlations */ +); + +/* Calculates correlation vector X'*t */ +void silk_corrVector_FIX( + const opus_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */ + const opus_int16 *t, /* I Target vector [L] */ + const opus_int L, /* I Length of vectors */ + const opus_int order, /* I Max lag for correlation */ + opus_int32 *Xt, /* O Pointer to X'*t correlation vector [order] */ + const opus_int rshifts /* I Right shifts of correlations */ +); + +/* Add noise to matrix diagonal */ +void silk_regularize_correlations_FIX( + opus_int32 *XX, /* I/O Correlation matrices */ + opus_int32 *xx, /* I/O Correlation values */ + opus_int32 noise, /* I Noise to add */ + opus_int D /* I Dimension of XX */ +); + +/* Solves Ax = b, assuming A is symmetric */ +void silk_solve_LDL_FIX( + opus_int32 *A, /* I Pointer to symetric square matrix A */ + opus_int M, /* I Size of matrix */ + const opus_int32 *b, /* I Pointer to b vector */ + opus_int32 *x_Q16 /* O Pointer to x solution vector */ +); + +#ifndef FORCE_CPP_BUILD +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* FORCE_CPP_BUILD */ +#endif /* SILK_MAIN_FIX_H */ diff --git a/TelegramClient.Opus/opus/silk/fixed/noise_shape_analysis_FIX.c b/TelegramClient.Opus/opus/silk/fixed/noise_shape_analysis_FIX.c new file mode 100755 index 0000000..e24d2e9 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/noise_shape_analysis_FIX.c @@ -0,0 +1,445 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" +#include "stack_alloc.h" +#include "tuning_parameters.h" + +/* Compute gain to make warped filter coefficients have a zero mean log frequency response on a */ +/* non-warped frequency scale. (So that it can be implemented with a minimum-phase monic filter.) */ +/* Note: A monic filter is one with the first coefficient equal to 1.0. In Silk we omit the first */ +/* coefficient in an array of coefficients, for monic filters. */ +static OPUS_INLINE opus_int32 warped_gain( /* gain in Q16*/ + const opus_int32 *coefs_Q24, + opus_int lambda_Q16, + opus_int order +) { + opus_int i; + opus_int32 gain_Q24; + + lambda_Q16 = -lambda_Q16; + gain_Q24 = coefs_Q24[ order - 1 ]; + for( i = order - 2; i >= 0; i-- ) { + gain_Q24 = silk_SMLAWB( coefs_Q24[ i ], gain_Q24, lambda_Q16 ); + } + gain_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), gain_Q24, -lambda_Q16 ); + return silk_INVERSE32_varQ( gain_Q24, 40 ); +} + +/* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum */ +/* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */ +static OPUS_INLINE void limit_warped_coefs( + opus_int32 *coefs_syn_Q24, + opus_int32 *coefs_ana_Q24, + opus_int lambda_Q16, + opus_int32 limit_Q24, + opus_int order +) { + opus_int i, iter, ind = 0; + opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16; + opus_int32 nom_Q16, den_Q24; + + /* Convert to monic coefficients */ + lambda_Q16 = -lambda_Q16; + for( i = order - 1; i > 0; i-- ) { + coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); + coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); + } + lambda_Q16 = -lambda_Q16; + nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 ); + den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); + gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); + den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); + gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); + for( i = 0; i < order; i++ ) { + coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); + coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); + } + + for( iter = 0; iter < 10; iter++ ) { + /* Find maximum absolute value */ + maxabs_Q24 = -1; + for( i = 0; i < order; i++ ) { + tmp = silk_max( silk_abs_int32( coefs_syn_Q24[ i ] ), silk_abs_int32( coefs_ana_Q24[ i ] ) ); + if( tmp > maxabs_Q24 ) { + maxabs_Q24 = tmp; + ind = i; + } + } + if( maxabs_Q24 <= limit_Q24 ) { + /* Coefficients are within range - done */ + return; + } + + /* Convert back to true warped coefficients */ + for( i = 1; i < order; i++ ) { + coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); + coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); + } + gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 ); + gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 ); + for( i = 0; i < order; i++ ) { + coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); + coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); + } + + /* Apply bandwidth expansion */ + chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ( + silk_SMULWB( maxabs_Q24 - limit_Q24, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ), + silk_MUL( maxabs_Q24, ind + 1 ), 22 ); + silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 ); + silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 ); + + /* Convert to monic warped coefficients */ + lambda_Q16 = -lambda_Q16; + for( i = order - 1; i > 0; i-- ) { + coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 ); + coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 ); + } + lambda_Q16 = -lambda_Q16; + nom_Q16 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 ); + den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 ); + gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); + den_Q24 = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 ); + gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 ); + for( i = 0; i < order; i++ ) { + coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] ); + coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] ); + } + } + silk_assert( 0 ); +} + +/**************************************************************/ +/* Compute noise shaping coefficients and initial gain values */ +/**************************************************************/ +void silk_noise_shape_analysis_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */ + silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */ + const opus_int16 *pitch_res, /* I LPC residual from pitch analysis */ + const opus_int16 *x, /* I Input signal [ frame_length + la_shape ] */ + int arch /* I Run-time architecture */ +) +{ + silk_shape_state_FIX *psShapeSt = &psEnc->sShape; + opus_int k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0; + opus_int32 SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32; + opus_int32 nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7; + opus_int32 delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8; + opus_int32 auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ]; + opus_int32 refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ]; + opus_int32 AR1_Q24[ MAX_SHAPE_LPC_ORDER ]; + opus_int32 AR2_Q24[ MAX_SHAPE_LPC_ORDER ]; + VARDECL( opus_int16, x_windowed ); + const opus_int16 *x_ptr, *pitch_res_ptr; + SAVE_STACK; + + /* Point to start of first LPC analysis block */ + x_ptr = x - psEnc->sCmn.la_shape; + + /****************/ + /* GAIN CONTROL */ + /****************/ + SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7; + + /* Input quality is the average of the quality in the lowest two VAD bands */ + psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ] + + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 ); + + /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */ + psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 - + SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 ); + + /* Reduce coding SNR during low speech activity */ + if( psEnc->sCmn.useCBR == 0 ) { + b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8; + b_Q8 = silk_SMULWB( silk_LSHIFT( b_Q8, 8 ), b_Q8 ); + SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, + silk_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ), /* Q11*/ + silk_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) ); /* Q12*/ + } + + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* Reduce gains for periodic signals */ + SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( HARM_SNR_INCR_dB, 8 ), psEnc->LTPCorr_Q15 ); + } else { + /* For unvoiced signals and low-quality input, adjust the quality slower than SNR_dB setting */ + SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, + silk_SMLAWB( SILK_FIX_CONST( 6.0, 9 ), -SILK_FIX_CONST( 0.4, 18 ), psEnc->sCmn.SNR_dB_Q7 ), + SILK_FIX_CONST( 1.0, 14 ) - psEncCtrl->input_quality_Q14 ); + } + + /*************************/ + /* SPARSENESS PROCESSING */ + /*************************/ + /* Set quantizer offset */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* Initially set to 0; may be overruled in process_gains(..) */ + psEnc->sCmn.indices.quantOffsetType = 0; + psEncCtrl->sparseness_Q8 = 0; + } else { + /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */ + nSamples = silk_LSHIFT( psEnc->sCmn.fs_kHz, 1 ); + energy_variation_Q7 = 0; + log_energy_prev_Q7 = 0; + pitch_res_ptr = pitch_res; + for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) { + silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples ); + nrg += silk_RSHIFT( nSamples, scale ); /* Q(-scale)*/ + + log_energy_Q7 = silk_lin2log( nrg ); + if( k > 0 ) { + energy_variation_Q7 += silk_abs( log_energy_Q7 - log_energy_prev_Q7 ); + } + log_energy_prev_Q7 = log_energy_Q7; + pitch_res_ptr += nSamples; + } + + psEncCtrl->sparseness_Q8 = silk_RSHIFT( silk_sigm_Q15( silk_SMULWB( energy_variation_Q7 - + SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 ); + + /* Set quantization offset depending on sparseness measure */ + if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) { + psEnc->sCmn.indices.quantOffsetType = 0; + } else { + psEnc->sCmn.indices.quantOffsetType = 1; + } + + /* Increase coding SNR for sparse signals */ + SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SILK_FIX_CONST( 0.5, 8 ) ); + } + + /*******************************/ + /* Control bandwidth expansion */ + /*******************************/ + /* More BWE for signals with high prediction gain */ + strength_Q16 = silk_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ); + BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ), + silk_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 ); + delta_Q16 = silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - silk_SMULBB( 3, psEncCtrl->coding_quality_Q14 ), + SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) ); + BWExp1_Q16 = silk_SUB32( BWExp1_Q16, delta_Q16 ); + BWExp2_Q16 = silk_ADD32( BWExp2_Q16, delta_Q16 ); + /* BWExp1 will be applied after BWExp2, so make it relative */ + BWExp1_Q16 = silk_DIV32_16( silk_LSHIFT( BWExp1_Q16, 14 ), silk_RSHIFT( BWExp2_Q16, 2 ) ); + + if( psEnc->sCmn.warping_Q16 > 0 ) { + /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */ + warping_Q16 = silk_SMLAWB( psEnc->sCmn.warping_Q16, (opus_int32)psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( 0.01, 18 ) ); + } else { + warping_Q16 = 0; + } + + /********************************************/ + /* Compute noise shaping AR coefs and gains */ + /********************************************/ + ALLOC( x_windowed, psEnc->sCmn.shapeWinLength, opus_int16 ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + /* Apply window: sine slope followed by flat part followed by cosine slope */ + opus_int shift, slope_part, flat_part; + flat_part = psEnc->sCmn.fs_kHz * 3; + slope_part = silk_RSHIFT( psEnc->sCmn.shapeWinLength - flat_part, 1 ); + + silk_apply_sine_window( x_windowed, x_ptr, 1, slope_part ); + shift = slope_part; + silk_memcpy( x_windowed + shift, x_ptr + shift, flat_part * sizeof(opus_int16) ); + shift += flat_part; + silk_apply_sine_window( x_windowed + shift, x_ptr + shift, 2, slope_part ); + + /* Update pointer: next LPC analysis block */ + x_ptr += psEnc->sCmn.subfr_length; + + if( psEnc->sCmn.warping_Q16 > 0 ) { + /* Calculate warped auto correlation */ + silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder ); + } else { + /* Calculate regular auto correlation */ + silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch ); + } + + /* Add white noise, as a fraction of energy */ + auto_corr[0] = silk_ADD32( auto_corr[0], silk_max_32( silk_SMULWB( silk_RSHIFT( auto_corr[ 0 ], 4 ), + SILK_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) ); + + /* Calculate the reflection coefficients using schur */ + nrg = silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder ); + silk_assert( nrg >= 0 ); + + /* Convert reflection coefficients to prediction coefficients */ + silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder ); + + Qnrg = -scale; /* range: -12...30*/ + silk_assert( Qnrg >= -12 ); + silk_assert( Qnrg <= 30 ); + + /* Make sure that Qnrg is an even number */ + if( Qnrg & 1 ) { + Qnrg -= 1; + nrg >>= 1; + } + + tmp32 = silk_SQRT_APPROX( nrg ); + Qnrg >>= 1; /* range: -6...15*/ + + psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( tmp32, 16 - Qnrg ); + + if( psEnc->sCmn.warping_Q16 > 0 ) { + /* Adjust gain for warping */ + gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder ); + silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); + if ( silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 ) >= ( silk_int32_MAX >> 1 ) ) { + psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX; + } else { + psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); + } + } + + /* Bandwidth expansion for synthesis filter shaping */ + silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 ); + + /* Compute noise shaping filter coefficients */ + silk_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) ); + + /* Bandwidth expansion for analysis filter shaping */ + silk_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) ); + silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 ); + + /* Ratio of prediction gains, in energy domain */ + pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder ); + nrg = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder ); + + /*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/ + pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 ); + psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 ); + + /* Convert to monic warped prediction coefficients and limit absolute values */ + limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder ); + + /* Convert from Q24 to Q13 and store in int16 */ + for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) { + psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) ); + psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) ); + } + } + + /*****************/ + /* Gain tweaking */ + /*****************/ + /* Increase gains during low speech activity and put lower limit on gains */ + gain_mult_Q16 = silk_log2lin( -silk_SMLAWB( -SILK_FIX_CONST( 16.0, 7 ), SNR_adj_dB_Q7, SILK_FIX_CONST( 0.16, 16 ) ) ); + gain_add_Q16 = silk_log2lin( silk_SMLAWB( SILK_FIX_CONST( 16.0, 7 ), SILK_FIX_CONST( MIN_QGAIN_DB, 7 ), SILK_FIX_CONST( 0.16, 16 ) ) ); + silk_assert( gain_mult_Q16 > 0 ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 ); + silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 ); + psEncCtrl->Gains_Q16[ k ] = silk_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 ); + } + + gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + silk_RSHIFT_ROUND( silk_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ), + psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->GainsPre_Q14[ k ] = silk_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] ); + } + + /************************************************/ + /* Control low-frequency shaping and noise tilt */ + /************************************************/ + /* Less low frequency shaping for noisy inputs */ + strength_Q16 = silk_MUL( SILK_FIX_CONST( LOW_FREQ_SHAPING, 4 ), silk_SMLAWB( SILK_FIX_CONST( 1.0, 12 ), + SILK_FIX_CONST( LOW_QUALITY_LOW_FREQ_SHAPING_DECR, 13 ), psEnc->sCmn.input_quality_bands_Q15[ 0 ] - SILK_FIX_CONST( 1.0, 15 ) ) ); + strength_Q16 = silk_RSHIFT( silk_MUL( strength_Q16, psEnc->sCmn.speech_activity_Q8 ), 8 ); + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */ + /*f = 400; freqz([1, -0.98 + 2e-4 * f], [1, -0.97 + 7e-4 * f], 2^12, Fs); axis([0, 1000, -10, 1])*/ + opus_int fs_kHz_inv = silk_DIV32_16( SILK_FIX_CONST( 0.2, 14 ), psEnc->sCmn.fs_kHz ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + b_Q14 = fs_kHz_inv + silk_DIV32_16( SILK_FIX_CONST( 3.0, 14 ), psEncCtrl->pitchL[ k ] ); + /* Pack two coefficients in one int32 */ + psEncCtrl->LF_shp_Q14[ k ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - silk_SMULWB( strength_Q16, b_Q14 ), 16 ); + psEncCtrl->LF_shp_Q14[ k ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); + } + silk_assert( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ) < SILK_FIX_CONST( 0.5, 24 ) ); /* Guarantees that second argument to SMULWB() is within range of an opus_int16*/ + Tilt_Q16 = - SILK_FIX_CONST( HP_NOISE_COEF, 16 ) - + silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - SILK_FIX_CONST( HP_NOISE_COEF, 16 ), + silk_SMULWB( SILK_FIX_CONST( HARM_HP_NOISE_COEF, 24 ), psEnc->sCmn.speech_activity_Q8 ) ); + } else { + b_Q14 = silk_DIV32_16( 21299, psEnc->sCmn.fs_kHz ); /* 1.3_Q0 = 21299_Q14*/ + /* Pack two coefficients in one int32 */ + psEncCtrl->LF_shp_Q14[ 0 ] = silk_LSHIFT( SILK_FIX_CONST( 1.0, 14 ) - b_Q14 - + silk_SMULWB( strength_Q16, silk_SMULWB( SILK_FIX_CONST( 0.6, 16 ), b_Q14 ) ), 16 ); + psEncCtrl->LF_shp_Q14[ 0 ] |= (opus_uint16)( b_Q14 - SILK_FIX_CONST( 1.0, 14 ) ); + for( k = 1; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->LF_shp_Q14[ k ] = psEncCtrl->LF_shp_Q14[ 0 ]; + } + Tilt_Q16 = -SILK_FIX_CONST( HP_NOISE_COEF, 16 ); + } + + /****************************/ + /* HARMONIC SHAPING CONTROL */ + /****************************/ + /* Control boosting of harmonic frequencies */ + HarmBoost_Q16 = silk_SMULWB( silk_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ), + psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) ); + + /* More harmonic boost for noisy input signals */ + HarmBoost_Q16 = silk_SMLAWB( HarmBoost_Q16, + SILK_FIX_CONST( 1.0, 16 ) - silk_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) ); + + if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /* More harmonic noise shaping for high bitrates or noisy input */ + HarmShapeGain_Q16 = silk_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ), + SILK_FIX_CONST( 1.0, 16 ) - silk_SMULWB( SILK_FIX_CONST( 1.0, 18 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 4 ), + psEncCtrl->input_quality_Q14 ), SILK_FIX_CONST( HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING, 16 ) ); + + /* Less harmonic noise shaping for less periodic signals */ + HarmShapeGain_Q16 = silk_SMULWB( silk_LSHIFT( HarmShapeGain_Q16, 1 ), + silk_SQRT_APPROX( silk_LSHIFT( psEnc->LTPCorr_Q15, 15 ) ) ); + } else { + HarmShapeGain_Q16 = 0; + } + + /*************************/ + /* Smooth over subframes */ + /*************************/ + for( k = 0; k < MAX_NB_SUBFR; k++ ) { + psShapeSt->HarmBoost_smth_Q16 = + silk_SMLAWB( psShapeSt->HarmBoost_smth_Q16, HarmBoost_Q16 - psShapeSt->HarmBoost_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); + psShapeSt->HarmShapeGain_smth_Q16 = + silk_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); + psShapeSt->Tilt_smth_Q16 = + silk_SMLAWB( psShapeSt->Tilt_smth_Q16, Tilt_Q16 - psShapeSt->Tilt_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) ); + + psEncCtrl->HarmBoost_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16, 2 ); + psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 ); + psEncCtrl->Tilt_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16, 2 ); + } + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/fixed/pitch_analysis_core_FIX.c b/TelegramClient.Opus/opus/silk/fixed/pitch_analysis_core_FIX.c new file mode 100755 index 0000000..1641a0f --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/pitch_analysis_core_FIX.c @@ -0,0 +1,744 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/*********************************************************** +* Pitch analyser function +********************************************************** */ +#include "SigProc_FIX.h" +#include "pitch_est_defines.h" +#include "stack_alloc.h" +#include "debug.h" +#include "pitch.h" + +#define SCRATCH_SIZE 22 +#define SF_LENGTH_4KHZ ( PE_SUBFR_LENGTH_MS * 4 ) +#define SF_LENGTH_8KHZ ( PE_SUBFR_LENGTH_MS * 8 ) +#define MIN_LAG_4KHZ ( PE_MIN_LAG_MS * 4 ) +#define MIN_LAG_8KHZ ( PE_MIN_LAG_MS * 8 ) +#define MAX_LAG_4KHZ ( PE_MAX_LAG_MS * 4 ) +#define MAX_LAG_8KHZ ( PE_MAX_LAG_MS * 8 - 1 ) +#define CSTRIDE_4KHZ ( MAX_LAG_4KHZ + 1 - MIN_LAG_4KHZ ) +#define CSTRIDE_8KHZ ( MAX_LAG_8KHZ + 3 - ( MIN_LAG_8KHZ - 2 ) ) +#define D_COMP_MIN ( MIN_LAG_8KHZ - 3 ) +#define D_COMP_MAX ( MAX_LAG_8KHZ + 4 ) +#define D_COMP_STRIDE ( D_COMP_MAX - D_COMP_MIN ) + +typedef opus_int32 silk_pe_stage3_vals[ PE_NB_STAGE3_LAGS ]; + +/************************************************************/ +/* Internally used functions */ +/************************************************************/ +static void silk_P_Ana_calc_corr_st3( + silk_pe_stage3_vals cross_corr_st3[], /* O 3 DIM correlation array */ + const opus_int16 frame[], /* I vector to correlate */ + opus_int start_lag, /* I lag offset to search around */ + opus_int sf_length, /* I length of a 5 ms subframe */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity, /* I Complexity setting */ + int arch /* I Run-time architecture */ +); + +static void silk_P_Ana_calc_energy_st3( + silk_pe_stage3_vals energies_st3[], /* O 3 DIM energy array */ + const opus_int16 frame[], /* I vector to calc energy in */ + opus_int start_lag, /* I lag offset to search around */ + opus_int sf_length, /* I length of one 5 ms subframe */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity /* I Complexity setting */ +); + +/*************************************************************/ +/* FIXED POINT CORE PITCH ANALYSIS FUNCTION */ +/*************************************************************/ +opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */ + const opus_int16 *frame, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */ + opus_int *pitch_out, /* O 4 pitch lag values */ + opus_int16 *lagIndex, /* O Lag Index */ + opus_int8 *contourIndex, /* O Pitch contour Index */ + opus_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */ + opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */ + const opus_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */ + const opus_int search_thres2_Q13, /* I Final threshold for lag candidates 0 - 1 */ + const opus_int Fs_kHz, /* I Sample frequency (kHz) */ + const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */ + const opus_int nb_subfr, /* I number of 5 ms subframes */ + int arch /* I Run-time architecture */ +) +{ + VARDECL( opus_int16, frame_8kHz ); + VARDECL( opus_int16, frame_4kHz ); + opus_int32 filt_state[ 6 ]; + const opus_int16 *input_frame_ptr; + opus_int i, k, d, j; + VARDECL( opus_int16, C ); + VARDECL( opus_int32, xcorr32 ); + const opus_int16 *target_ptr, *basis_ptr; + opus_int32 cross_corr, normalizer, energy, shift, energy_basis, energy_target; + opus_int d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp; + VARDECL( opus_int16, d_comp ); + opus_int32 sum, threshold, lag_counter; + opus_int CBimax, CBimax_new, CBimax_old, lag, start_lag, end_lag, lag_new; + opus_int32 CC[ PE_NB_CBKS_STAGE2_EXT ], CCmax, CCmax_b, CCmax_new_b, CCmax_new; + VARDECL( silk_pe_stage3_vals, energies_st3 ); + VARDECL( silk_pe_stage3_vals, cross_corr_st3 ); + opus_int frame_length, frame_length_8kHz, frame_length_4kHz; + opus_int sf_length; + opus_int min_lag; + opus_int max_lag; + opus_int32 contour_bias_Q15, diff; + opus_int nb_cbk_search, cbk_size; + opus_int32 delta_lag_log2_sqr_Q7, lag_log2_Q7, prevLag_log2_Q7, prev_lag_bias_Q13; + const opus_int8 *Lag_CB_ptr; + SAVE_STACK; + /* Check for valid sampling frequency */ + silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 ); + + /* Check for valid complexity setting */ + silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); + silk_assert( complexity <= SILK_PE_MAX_COMPLEX ); + + silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) ); + silk_assert( search_thres2_Q13 >= 0 && search_thres2_Q13 <= (1<<13) ); + + /* Set up frame lengths max / min lag for the sampling frequency */ + frame_length = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * Fs_kHz; + frame_length_4kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 4; + frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8; + sf_length = PE_SUBFR_LENGTH_MS * Fs_kHz; + min_lag = PE_MIN_LAG_MS * Fs_kHz; + max_lag = PE_MAX_LAG_MS * Fs_kHz - 1; + + /* Resample from input sampled at Fs_kHz to 8 kHz */ + ALLOC( frame_8kHz, frame_length_8kHz, opus_int16 ); + if( Fs_kHz == 16 ) { + silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) ); + silk_resampler_down2( filt_state, frame_8kHz, frame, frame_length ); + } else if( Fs_kHz == 12 ) { + silk_memset( filt_state, 0, 6 * sizeof( opus_int32 ) ); + silk_resampler_down2_3( filt_state, frame_8kHz, frame, frame_length ); + } else { + silk_assert( Fs_kHz == 8 ); + silk_memcpy( frame_8kHz, frame, frame_length_8kHz * sizeof(opus_int16) ); + } + + /* Decimate again to 4 kHz */ + silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );/* Set state to zero */ + ALLOC( frame_4kHz, frame_length_4kHz, opus_int16 ); + silk_resampler_down2( filt_state, frame_4kHz, frame_8kHz, frame_length_8kHz ); + + /* Low-pass filter */ + for( i = frame_length_4kHz - 1; i > 0; i-- ) { + frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] ); + } + + /******************************************************************************* + ** Scale 4 kHz signal down to prevent correlations measures from overflowing + ** find scaling as max scaling for each 8kHz(?) subframe + *******************************************************************************/ + + /* Inner product is calculated with different lengths, so scale for the worst case */ + silk_sum_sqr_shift( &energy, &shift, frame_4kHz, frame_length_4kHz ); + if( shift > 0 ) { + shift = silk_RSHIFT( shift, 1 ); + for( i = 0; i < frame_length_4kHz; i++ ) { + frame_4kHz[ i ] = silk_RSHIFT( frame_4kHz[ i ], shift ); + } + } + + /****************************************************************************** + * FIRST STAGE, operating in 4 khz + ******************************************************************************/ + ALLOC( C, nb_subfr * CSTRIDE_8KHZ, opus_int16 ); + ALLOC( xcorr32, MAX_LAG_4KHZ-MIN_LAG_4KHZ+1, opus_int32 ); + silk_memset( C, 0, (nb_subfr >> 1) * CSTRIDE_4KHZ * sizeof( opus_int16 ) ); + target_ptr = &frame_4kHz[ silk_LSHIFT( SF_LENGTH_4KHZ, 2 ) ]; + for( k = 0; k < nb_subfr >> 1; k++ ) { + /* Check that we are within range of the array */ + silk_assert( target_ptr >= frame_4kHz ); + silk_assert( target_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz ); + + basis_ptr = target_ptr - MIN_LAG_4KHZ; + + /* Check that we are within range of the array */ + silk_assert( basis_ptr >= frame_4kHz ); + silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz ); + + celt_pitch_xcorr( target_ptr, target_ptr - MAX_LAG_4KHZ, xcorr32, SF_LENGTH_8KHZ, MAX_LAG_4KHZ - MIN_LAG_4KHZ + 1, arch ); + + /* Calculate first vector products before loop */ + cross_corr = xcorr32[ MAX_LAG_4KHZ - MIN_LAG_4KHZ ]; + normalizer = silk_inner_prod_aligned( target_ptr, target_ptr, SF_LENGTH_8KHZ ); + normalizer = silk_ADD32( normalizer, silk_inner_prod_aligned( basis_ptr, basis_ptr, SF_LENGTH_8KHZ ) ); + normalizer = silk_ADD32( normalizer, silk_SMULBB( SF_LENGTH_8KHZ, 4000 ) ); + + matrix_ptr( C, k, 0, CSTRIDE_4KHZ ) = + (opus_int16)silk_DIV32_varQ( cross_corr, normalizer, 13 + 1 ); /* Q13 */ + + /* From now on normalizer is computed recursively */ + for( d = MIN_LAG_4KHZ + 1; d <= MAX_LAG_4KHZ; d++ ) { + basis_ptr--; + + /* Check that we are within range of the array */ + silk_assert( basis_ptr >= frame_4kHz ); + silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz ); + + cross_corr = xcorr32[ MAX_LAG_4KHZ - d ]; + + /* Add contribution of new sample and remove contribution from oldest sample */ + normalizer = silk_ADD32( normalizer, + silk_SMULBB( basis_ptr[ 0 ], basis_ptr[ 0 ] ) - + silk_SMULBB( basis_ptr[ SF_LENGTH_8KHZ ], basis_ptr[ SF_LENGTH_8KHZ ] ) ); + + matrix_ptr( C, k, d - MIN_LAG_4KHZ, CSTRIDE_4KHZ) = + (opus_int16)silk_DIV32_varQ( cross_corr, normalizer, 13 + 1 ); /* Q13 */ + } + /* Update target pointer */ + target_ptr += SF_LENGTH_8KHZ; + } + + /* Combine two subframes into single correlation measure and apply short-lag bias */ + if( nb_subfr == PE_MAX_NB_SUBFR ) { + for( i = MAX_LAG_4KHZ; i >= MIN_LAG_4KHZ; i-- ) { + sum = (opus_int32)matrix_ptr( C, 0, i - MIN_LAG_4KHZ, CSTRIDE_4KHZ ) + + (opus_int32)matrix_ptr( C, 1, i - MIN_LAG_4KHZ, CSTRIDE_4KHZ ); /* Q14 */ + sum = silk_SMLAWB( sum, sum, silk_LSHIFT( -i, 4 ) ); /* Q14 */ + C[ i - MIN_LAG_4KHZ ] = (opus_int16)sum; /* Q14 */ + } + } else { + /* Only short-lag bias */ + for( i = MAX_LAG_4KHZ; i >= MIN_LAG_4KHZ; i-- ) { + sum = silk_LSHIFT( (opus_int32)C[ i - MIN_LAG_4KHZ ], 1 ); /* Q14 */ + sum = silk_SMLAWB( sum, sum, silk_LSHIFT( -i, 4 ) ); /* Q14 */ + C[ i - MIN_LAG_4KHZ ] = (opus_int16)sum; /* Q14 */ + } + } + + /* Sort */ + length_d_srch = silk_ADD_LSHIFT32( 4, complexity, 1 ); + silk_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH ); + silk_insertion_sort_decreasing_int16( C, d_srch, CSTRIDE_4KHZ, + length_d_srch ); + + /* Escape if correlation is very low already here */ + Cmax = (opus_int)C[ 0 ]; /* Q14 */ + if( Cmax < SILK_FIX_CONST( 0.2, 14 ) ) { + silk_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) ); + *LTPCorr_Q15 = 0; + *lagIndex = 0; + *contourIndex = 0; + RESTORE_STACK; + return 1; + } + + threshold = silk_SMULWB( search_thres1_Q16, Cmax ); + for( i = 0; i < length_d_srch; i++ ) { + /* Convert to 8 kHz indices for the sorted correlation that exceeds the threshold */ + if( C[ i ] > threshold ) { + d_srch[ i ] = silk_LSHIFT( d_srch[ i ] + MIN_LAG_4KHZ, 1 ); + } else { + length_d_srch = i; + break; + } + } + silk_assert( length_d_srch > 0 ); + + ALLOC( d_comp, D_COMP_STRIDE, opus_int16 ); + for( i = D_COMP_MIN; i < D_COMP_MAX; i++ ) { + d_comp[ i - D_COMP_MIN ] = 0; + } + for( i = 0; i < length_d_srch; i++ ) { + d_comp[ d_srch[ i ] - D_COMP_MIN ] = 1; + } + + /* Convolution */ + for( i = D_COMP_MAX - 1; i >= MIN_LAG_8KHZ; i-- ) { + d_comp[ i - D_COMP_MIN ] += + d_comp[ i - 1 - D_COMP_MIN ] + d_comp[ i - 2 - D_COMP_MIN ]; + } + + length_d_srch = 0; + for( i = MIN_LAG_8KHZ; i < MAX_LAG_8KHZ + 1; i++ ) { + if( d_comp[ i + 1 - D_COMP_MIN ] > 0 ) { + d_srch[ length_d_srch ] = i; + length_d_srch++; + } + } + + /* Convolution */ + for( i = D_COMP_MAX - 1; i >= MIN_LAG_8KHZ; i-- ) { + d_comp[ i - D_COMP_MIN ] += d_comp[ i - 1 - D_COMP_MIN ] + + d_comp[ i - 2 - D_COMP_MIN ] + d_comp[ i - 3 - D_COMP_MIN ]; + } + + length_d_comp = 0; + for( i = MIN_LAG_8KHZ; i < D_COMP_MAX; i++ ) { + if( d_comp[ i - D_COMP_MIN ] > 0 ) { + d_comp[ length_d_comp ] = i - 2; + length_d_comp++; + } + } + + /********************************************************************************** + ** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation + *************************************************************************************/ + + /****************************************************************************** + ** Scale signal down to avoid correlations measures from overflowing + *******************************************************************************/ + /* find scaling as max scaling for each subframe */ + silk_sum_sqr_shift( &energy, &shift, frame_8kHz, frame_length_8kHz ); + if( shift > 0 ) { + shift = silk_RSHIFT( shift, 1 ); + for( i = 0; i < frame_length_8kHz; i++ ) { + frame_8kHz[ i ] = silk_RSHIFT( frame_8kHz[ i ], shift ); + } + } + + /********************************************************************************* + * Find energy of each subframe projected onto its history, for a range of delays + *********************************************************************************/ + silk_memset( C, 0, nb_subfr * CSTRIDE_8KHZ * sizeof( opus_int16 ) ); + + target_ptr = &frame_8kHz[ PE_LTP_MEM_LENGTH_MS * 8 ]; + for( k = 0; k < nb_subfr; k++ ) { + + /* Check that we are within range of the array */ + silk_assert( target_ptr >= frame_8kHz ); + silk_assert( target_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz ); + + energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, SF_LENGTH_8KHZ ), 1 ); + for( j = 0; j < length_d_comp; j++ ) { + d = d_comp[ j ]; + basis_ptr = target_ptr - d; + + /* Check that we are within range of the array */ + silk_assert( basis_ptr >= frame_8kHz ); + silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz ); + + cross_corr = silk_inner_prod_aligned( target_ptr, basis_ptr, SF_LENGTH_8KHZ ); + if( cross_corr > 0 ) { + energy_basis = silk_inner_prod_aligned( basis_ptr, basis_ptr, SF_LENGTH_8KHZ ); + matrix_ptr( C, k, d - ( MIN_LAG_8KHZ - 2 ), CSTRIDE_8KHZ ) = + (opus_int16)silk_DIV32_varQ( cross_corr, + silk_ADD32( energy_target, + energy_basis ), + 13 + 1 ); /* Q13 */ + } else { + matrix_ptr( C, k, d - ( MIN_LAG_8KHZ - 2 ), CSTRIDE_8KHZ ) = 0; + } + } + target_ptr += SF_LENGTH_8KHZ; + } + + /* search over lag range and lags codebook */ + /* scale factor for lag codebook, as a function of center lag */ + + CCmax = silk_int32_MIN; + CCmax_b = silk_int32_MIN; + + CBimax = 0; /* To avoid returning undefined lag values */ + lag = -1; /* To check if lag with strong enough correlation has been found */ + + if( prevLag > 0 ) { + if( Fs_kHz == 12 ) { + prevLag = silk_DIV32_16( silk_LSHIFT( prevLag, 1 ), 3 ); + } else if( Fs_kHz == 16 ) { + prevLag = silk_RSHIFT( prevLag, 1 ); + } + prevLag_log2_Q7 = silk_lin2log( (opus_int32)prevLag ); + } else { + prevLag_log2_Q7 = 0; + } + silk_assert( search_thres2_Q13 == silk_SAT16( search_thres2_Q13 ) ); + /* Set up stage 2 codebook based on number of subframes */ + if( nb_subfr == PE_MAX_NB_SUBFR ) { + cbk_size = PE_NB_CBKS_STAGE2_EXT; + Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ]; + if( Fs_kHz == 8 && complexity > SILK_PE_MIN_COMPLEX ) { + /* If input is 8 khz use a larger codebook here because it is last stage */ + nb_cbk_search = PE_NB_CBKS_STAGE2_EXT; + } else { + nb_cbk_search = PE_NB_CBKS_STAGE2; + } + } else { + cbk_size = PE_NB_CBKS_STAGE2_10MS; + Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ]; + nb_cbk_search = PE_NB_CBKS_STAGE2_10MS; + } + + for( k = 0; k < length_d_srch; k++ ) { + d = d_srch[ k ]; + for( j = 0; j < nb_cbk_search; j++ ) { + CC[ j ] = 0; + for( i = 0; i < nb_subfr; i++ ) { + opus_int d_subfr; + /* Try all codebooks */ + d_subfr = d + matrix_ptr( Lag_CB_ptr, i, j, cbk_size ); + CC[ j ] = CC[ j ] + + (opus_int32)matrix_ptr( C, i, + d_subfr - ( MIN_LAG_8KHZ - 2 ), + CSTRIDE_8KHZ ); + } + } + /* Find best codebook */ + CCmax_new = silk_int32_MIN; + CBimax_new = 0; + for( i = 0; i < nb_cbk_search; i++ ) { + if( CC[ i ] > CCmax_new ) { + CCmax_new = CC[ i ]; + CBimax_new = i; + } + } + + /* Bias towards shorter lags */ + lag_log2_Q7 = silk_lin2log( d ); /* Q7 */ + silk_assert( lag_log2_Q7 == silk_SAT16( lag_log2_Q7 ) ); + silk_assert( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 13 ) == silk_SAT16( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 13 ) ) ); + CCmax_new_b = CCmax_new - silk_RSHIFT( silk_SMULBB( nb_subfr * SILK_FIX_CONST( PE_SHORTLAG_BIAS, 13 ), lag_log2_Q7 ), 7 ); /* Q13 */ + + /* Bias towards previous lag */ + silk_assert( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 13 ) == silk_SAT16( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 13 ) ) ); + if( prevLag > 0 ) { + delta_lag_log2_sqr_Q7 = lag_log2_Q7 - prevLag_log2_Q7; + silk_assert( delta_lag_log2_sqr_Q7 == silk_SAT16( delta_lag_log2_sqr_Q7 ) ); + delta_lag_log2_sqr_Q7 = silk_RSHIFT( silk_SMULBB( delta_lag_log2_sqr_Q7, delta_lag_log2_sqr_Q7 ), 7 ); + prev_lag_bias_Q13 = silk_RSHIFT( silk_SMULBB( nb_subfr * SILK_FIX_CONST( PE_PREVLAG_BIAS, 13 ), *LTPCorr_Q15 ), 15 ); /* Q13 */ + prev_lag_bias_Q13 = silk_DIV32( silk_MUL( prev_lag_bias_Q13, delta_lag_log2_sqr_Q7 ), delta_lag_log2_sqr_Q7 + SILK_FIX_CONST( 0.5, 7 ) ); + CCmax_new_b -= prev_lag_bias_Q13; /* Q13 */ + } + + if( CCmax_new_b > CCmax_b && /* Find maximum biased correlation */ + CCmax_new > silk_SMULBB( nb_subfr, search_thres2_Q13 ) && /* Correlation needs to be high enough to be voiced */ + silk_CB_lags_stage2[ 0 ][ CBimax_new ] <= MIN_LAG_8KHZ /* Lag must be in range */ + ) { + CCmax_b = CCmax_new_b; + CCmax = CCmax_new; + lag = d; + CBimax = CBimax_new; + } + } + + if( lag == -1 ) { + /* No suitable candidate found */ + silk_memset( pitch_out, 0, nb_subfr * sizeof( opus_int ) ); + *LTPCorr_Q15 = 0; + *lagIndex = 0; + *contourIndex = 0; + RESTORE_STACK; + return 1; + } + + /* Output normalized correlation */ + *LTPCorr_Q15 = (opus_int)silk_LSHIFT( silk_DIV32_16( CCmax, nb_subfr ), 2 ); + silk_assert( *LTPCorr_Q15 >= 0 ); + + if( Fs_kHz > 8 ) { + VARDECL( opus_int16, scratch_mem ); + /***************************************************************************/ + /* Scale input signal down to avoid correlations measures from overflowing */ + /***************************************************************************/ + /* find scaling as max scaling for each subframe */ + silk_sum_sqr_shift( &energy, &shift, frame, frame_length ); + ALLOC( scratch_mem, shift > 0 ? frame_length : ALLOC_NONE, opus_int16 ); + if( shift > 0 ) { + /* Move signal to scratch mem because the input signal should be unchanged */ + shift = silk_RSHIFT( shift, 1 ); + for( i = 0; i < frame_length; i++ ) { + scratch_mem[ i ] = silk_RSHIFT( frame[ i ], shift ); + } + input_frame_ptr = scratch_mem; + } else { + input_frame_ptr = frame; + } + + /* Search in original signal */ + + CBimax_old = CBimax; + /* Compensate for decimation */ + silk_assert( lag == silk_SAT16( lag ) ); + if( Fs_kHz == 12 ) { + lag = silk_RSHIFT( silk_SMULBB( lag, 3 ), 1 ); + } else if( Fs_kHz == 16 ) { + lag = silk_LSHIFT( lag, 1 ); + } else { + lag = silk_SMULBB( lag, 3 ); + } + + lag = silk_LIMIT_int( lag, min_lag, max_lag ); + start_lag = silk_max_int( lag - 2, min_lag ); + end_lag = silk_min_int( lag + 2, max_lag ); + lag_new = lag; /* to avoid undefined lag */ + CBimax = 0; /* to avoid undefined lag */ + + CCmax = silk_int32_MIN; + /* pitch lags according to second stage */ + for( k = 0; k < nb_subfr; k++ ) { + pitch_out[ k ] = lag + 2 * silk_CB_lags_stage2[ k ][ CBimax_old ]; + } + + /* Set up codebook parameters according to complexity setting and frame length */ + if( nb_subfr == PE_MAX_NB_SUBFR ) { + nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ]; + cbk_size = PE_NB_CBKS_STAGE3_MAX; + Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; + } else { + nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; + cbk_size = PE_NB_CBKS_STAGE3_10MS; + Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; + } + + /* Calculate the correlations and energies needed in stage 3 */ + ALLOC( energies_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals ); + ALLOC( cross_corr_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals ); + silk_P_Ana_calc_corr_st3( cross_corr_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch ); + silk_P_Ana_calc_energy_st3( energies_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity ); + + lag_counter = 0; + silk_assert( lag == silk_SAT16( lag ) ); + contour_bias_Q15 = silk_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 15 ), lag ); + + target_ptr = &input_frame_ptr[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ]; + energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, nb_subfr * sf_length ), 1 ); + for( d = start_lag; d <= end_lag; d++ ) { + for( j = 0; j < nb_cbk_search; j++ ) { + cross_corr = 0; + energy = energy_target; + for( k = 0; k < nb_subfr; k++ ) { + cross_corr = silk_ADD32( cross_corr, + matrix_ptr( cross_corr_st3, k, j, + nb_cbk_search )[ lag_counter ] ); + energy = silk_ADD32( energy, + matrix_ptr( energies_st3, k, j, + nb_cbk_search )[ lag_counter ] ); + silk_assert( energy >= 0 ); + } + if( cross_corr > 0 ) { + CCmax_new = silk_DIV32_varQ( cross_corr, energy, 13 + 1 ); /* Q13 */ + /* Reduce depending on flatness of contour */ + diff = silk_int16_MAX - silk_MUL( contour_bias_Q15, j ); /* Q15 */ + silk_assert( diff == silk_SAT16( diff ) ); + CCmax_new = silk_SMULWB( CCmax_new, diff ); /* Q14 */ + } else { + CCmax_new = 0; + } + + if( CCmax_new > CCmax && ( d + silk_CB_lags_stage3[ 0 ][ j ] ) <= max_lag ) { + CCmax = CCmax_new; + lag_new = d; + CBimax = j; + } + } + lag_counter++; + } + + for( k = 0; k < nb_subfr; k++ ) { + pitch_out[ k ] = lag_new + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size ); + pitch_out[ k ] = silk_LIMIT( pitch_out[ k ], min_lag, PE_MAX_LAG_MS * Fs_kHz ); + } + *lagIndex = (opus_int16)( lag_new - min_lag); + *contourIndex = (opus_int8)CBimax; + } else { /* Fs_kHz == 8 */ + /* Save Lags */ + for( k = 0; k < nb_subfr; k++ ) { + pitch_out[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, CBimax, cbk_size ); + pitch_out[ k ] = silk_LIMIT( pitch_out[ k ], MIN_LAG_8KHZ, PE_MAX_LAG_MS * 8 ); + } + *lagIndex = (opus_int16)( lag - MIN_LAG_8KHZ ); + *contourIndex = (opus_int8)CBimax; + } + silk_assert( *lagIndex >= 0 ); + /* return as voiced */ + RESTORE_STACK; + return 0; +} + +/*********************************************************************** + * Calculates the correlations used in stage 3 search. In order to cover + * the whole lag codebook for all the searched offset lags (lag +- 2), + * the following correlations are needed in each sub frame: + * + * sf1: lag range [-8,...,7] total 16 correlations + * sf2: lag range [-4,...,4] total 9 correlations + * sf3: lag range [-3,....4] total 8 correltions + * sf4: lag range [-6,....8] total 15 correlations + * + * In total 48 correlations. The direct implementation computed in worst + * case 4*12*5 = 240 correlations, but more likely around 120. + ***********************************************************************/ +static void silk_P_Ana_calc_corr_st3( + silk_pe_stage3_vals cross_corr_st3[], /* O 3 DIM correlation array */ + const opus_int16 frame[], /* I vector to correlate */ + opus_int start_lag, /* I lag offset to search around */ + opus_int sf_length, /* I length of a 5 ms subframe */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity, /* I Complexity setting */ + int arch /* I Run-time architecture */ +) +{ + const opus_int16 *target_ptr; + opus_int i, j, k, lag_counter, lag_low, lag_high; + opus_int nb_cbk_search, delta, idx, cbk_size; + VARDECL( opus_int32, scratch_mem ); + VARDECL( opus_int32, xcorr32 ); + const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; + SAVE_STACK; + + silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); + silk_assert( complexity <= SILK_PE_MAX_COMPLEX ); + + if( nb_subfr == PE_MAX_NB_SUBFR ) { + Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ]; + Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; + nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ]; + cbk_size = PE_NB_CBKS_STAGE3_MAX; + } else { + silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1); + Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ]; + Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; + nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; + cbk_size = PE_NB_CBKS_STAGE3_10MS; + } + ALLOC( scratch_mem, SCRATCH_SIZE, opus_int32 ); + ALLOC( xcorr32, SCRATCH_SIZE, opus_int32 ); + + target_ptr = &frame[ silk_LSHIFT( sf_length, 2 ) ]; /* Pointer to middle of frame */ + for( k = 0; k < nb_subfr; k++ ) { + lag_counter = 0; + + /* Calculate the correlations for each subframe */ + lag_low = matrix_ptr( Lag_range_ptr, k, 0, 2 ); + lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 ); + silk_assert(lag_high-lag_low+1 <= SCRATCH_SIZE); + celt_pitch_xcorr( target_ptr, target_ptr - start_lag - lag_high, xcorr32, sf_length, lag_high - lag_low + 1, arch ); + for( j = lag_low; j <= lag_high; j++ ) { + silk_assert( lag_counter < SCRATCH_SIZE ); + scratch_mem[ lag_counter ] = xcorr32[ lag_high - j ]; + lag_counter++; + } + + delta = matrix_ptr( Lag_range_ptr, k, 0, 2 ); + for( i = 0; i < nb_cbk_search; i++ ) { + /* Fill out the 3 dim array that stores the correlations for */ + /* each code_book vector for each start lag */ + idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta; + for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) { + silk_assert( idx + j < SCRATCH_SIZE ); + silk_assert( idx + j < lag_counter ); + matrix_ptr( cross_corr_st3, k, i, nb_cbk_search )[ j ] = + scratch_mem[ idx + j ]; + } + } + target_ptr += sf_length; + } + RESTORE_STACK; +} + +/********************************************************************/ +/* Calculate the energies for first two subframes. The energies are */ +/* calculated recursively. */ +/********************************************************************/ +static void silk_P_Ana_calc_energy_st3( + silk_pe_stage3_vals energies_st3[], /* O 3 DIM energy array */ + const opus_int16 frame[], /* I vector to calc energy in */ + opus_int start_lag, /* I lag offset to search around */ + opus_int sf_length, /* I length of one 5 ms subframe */ + opus_int nb_subfr, /* I number of subframes */ + opus_int complexity /* I Complexity setting */ +) +{ + const opus_int16 *target_ptr, *basis_ptr; + opus_int32 energy; + opus_int k, i, j, lag_counter; + opus_int nb_cbk_search, delta, idx, cbk_size, lag_diff; + VARDECL( opus_int32, scratch_mem ); + const opus_int8 *Lag_range_ptr, *Lag_CB_ptr; + SAVE_STACK; + + silk_assert( complexity >= SILK_PE_MIN_COMPLEX ); + silk_assert( complexity <= SILK_PE_MAX_COMPLEX ); + + if( nb_subfr == PE_MAX_NB_SUBFR ) { + Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ]; + Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ]; + nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ]; + cbk_size = PE_NB_CBKS_STAGE3_MAX; + } else { + silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1); + Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ]; + Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ]; + nb_cbk_search = PE_NB_CBKS_STAGE3_10MS; + cbk_size = PE_NB_CBKS_STAGE3_10MS; + } + ALLOC( scratch_mem, SCRATCH_SIZE, opus_int32 ); + + target_ptr = &frame[ silk_LSHIFT( sf_length, 2 ) ]; + for( k = 0; k < nb_subfr; k++ ) { + lag_counter = 0; + + /* Calculate the energy for first lag */ + basis_ptr = target_ptr - ( start_lag + matrix_ptr( Lag_range_ptr, k, 0, 2 ) ); + energy = silk_inner_prod_aligned( basis_ptr, basis_ptr, sf_length ); + silk_assert( energy >= 0 ); + scratch_mem[ lag_counter ] = energy; + lag_counter++; + + lag_diff = ( matrix_ptr( Lag_range_ptr, k, 1, 2 ) - matrix_ptr( Lag_range_ptr, k, 0, 2 ) + 1 ); + for( i = 1; i < lag_diff; i++ ) { + /* remove part outside new window */ + energy -= silk_SMULBB( basis_ptr[ sf_length - i ], basis_ptr[ sf_length - i ] ); + silk_assert( energy >= 0 ); + + /* add part that comes into window */ + energy = silk_ADD_SAT32( energy, silk_SMULBB( basis_ptr[ -i ], basis_ptr[ -i ] ) ); + silk_assert( energy >= 0 ); + silk_assert( lag_counter < SCRATCH_SIZE ); + scratch_mem[ lag_counter ] = energy; + lag_counter++; + } + + delta = matrix_ptr( Lag_range_ptr, k, 0, 2 ); + for( i = 0; i < nb_cbk_search; i++ ) { + /* Fill out the 3 dim array that stores the correlations for */ + /* each code_book vector for each start lag */ + idx = matrix_ptr( Lag_CB_ptr, k, i, cbk_size ) - delta; + for( j = 0; j < PE_NB_STAGE3_LAGS; j++ ) { + silk_assert( idx + j < SCRATCH_SIZE ); + silk_assert( idx + j < lag_counter ); + matrix_ptr( energies_st3, k, i, nb_cbk_search )[ j ] = + scratch_mem[ idx + j ]; + silk_assert( + matrix_ptr( energies_st3, k, i, nb_cbk_search )[ j ] >= 0 ); + } + } + target_ptr += sf_length; + } + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/fixed/prefilter_FIX.c b/TelegramClient.Opus/opus/silk/fixed/prefilter_FIX.c new file mode 100755 index 0000000..d381730 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/prefilter_FIX.c @@ -0,0 +1,209 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" +#include "stack_alloc.h" +#include "tuning_parameters.h" + +/* Prefilter for finding Quantizer input signal */ +static OPUS_INLINE void silk_prefilt_FIX( + silk_prefilter_state_FIX *P, /* I/O state */ + opus_int32 st_res_Q12[], /* I short term residual signal */ + opus_int32 xw_Q3[], /* O prefiltered signal */ + opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ + opus_int Tilt_Q14, /* I Tilt shaping coeficient */ + opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */ + opus_int lag, /* I Lag for harmonic shaping */ + opus_int length /* I Length of signals */ +); + +void silk_warped_LPC_analysis_filter_FIX( + opus_int32 state[], /* I/O State [order + 1] */ + opus_int32 res_Q2[], /* O Residual signal [length] */ + const opus_int16 coef_Q13[], /* I Coefficients [order] */ + const opus_int16 input[], /* I Input signal [length] */ + const opus_int16 lambda_Q16, /* I Warping factor */ + const opus_int length, /* I Length of input signal */ + const opus_int order /* I Filter order (even) */ +) +{ + opus_int n, i; + opus_int32 acc_Q11, tmp1, tmp2; + + /* Order must be even */ + silk_assert( ( order & 1 ) == 0 ); + + for( n = 0; n < length; n++ ) { + /* Output of lowpass section */ + tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 ); + state[ 0 ] = silk_LSHIFT( input[ n ], 14 ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 ); + state[ 1 ] = tmp2; + acc_Q11 = silk_RSHIFT( order, 1 ); + acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] ); + /* Loop over allpass sections */ + for( i = 2; i < order; i += 2 ) { + /* Output of allpass section */ + tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 ); + state[ i ] = tmp1; + acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] ); + /* Output of allpass section */ + tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 ); + state[ i + 1 ] = tmp2; + acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] ); + } + state[ order ] = tmp1; + acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] ); + res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 ); + } +} + +void silk_prefilter_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ + const silk_encoder_control_FIX *psEncCtrl, /* I Encoder control */ + opus_int32 xw_Q3[], /* O Weighted signal */ + const opus_int16 x[] /* I Speech signal */ +) +{ + silk_prefilter_state_FIX *P = &psEnc->sPrefilt; + opus_int j, k, lag; + opus_int32 tmp_32; + const opus_int16 *AR1_shp_Q13; + const opus_int16 *px; + opus_int32 *pxw_Q3; + opus_int HarmShapeGain_Q12, Tilt_Q14; + opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14; + VARDECL( opus_int32, x_filt_Q12 ); + VARDECL( opus_int32, st_res_Q2 ); + opus_int16 B_Q10[ 2 ]; + SAVE_STACK; + + /* Set up pointers */ + px = x; + pxw_Q3 = xw_Q3; + lag = P->lagPrev; + ALLOC( x_filt_Q12, psEnc->sCmn.subfr_length, opus_int32 ); + ALLOC( st_res_Q2, psEnc->sCmn.subfr_length, opus_int32 ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + /* Update Variables that change per sub frame */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + lag = psEncCtrl->pitchL[ k ]; + } + + /* Noise shape parameters */ + HarmShapeGain_Q12 = silk_SMULWB( (opus_int32)psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] ); + silk_assert( HarmShapeGain_Q12 >= 0 ); + HarmShapeFIRPacked_Q12 = silk_RSHIFT( HarmShapeGain_Q12, 2 ); + HarmShapeFIRPacked_Q12 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 ); + Tilt_Q14 = psEncCtrl->Tilt_Q14[ k ]; + LF_shp_Q14 = psEncCtrl->LF_shp_Q14[ k ]; + AR1_shp_Q13 = &psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER ]; + + /* Short term FIR filtering*/ + silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res_Q2, AR1_shp_Q13, px, + psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder ); + + /* Reduce (mainly) low frequencies during harmonic emphasis */ + B_Q10[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 4 ); + tmp_32 = silk_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 ); /* Q26 */ + tmp_32 = silk_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ); /* Q26 */ + tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] ); /* Q24 */ + tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 ); /* Q10 */ + B_Q10[ 1 ]= silk_SAT16( tmp_32 ); + x_filt_Q12[ 0 ] = silk_MLA( silk_MUL( st_res_Q2[ 0 ], B_Q10[ 0 ] ), P->sHarmHP_Q2, B_Q10[ 1 ] ); + for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) { + x_filt_Q12[ j ] = silk_MLA( silk_MUL( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] ); + } + P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ]; + + silk_prefilt_FIX( P, x_filt_Q12, pxw_Q3, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length ); + + px += psEnc->sCmn.subfr_length; + pxw_Q3 += psEnc->sCmn.subfr_length; + } + + P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ]; + RESTORE_STACK; +} + +/* Prefilter for finding Quantizer input signal */ +static OPUS_INLINE void silk_prefilt_FIX( + silk_prefilter_state_FIX *P, /* I/O state */ + opus_int32 st_res_Q12[], /* I short term residual signal */ + opus_int32 xw_Q3[], /* O prefiltered signal */ + opus_int32 HarmShapeFIRPacked_Q12, /* I Harmonic shaping coeficients */ + opus_int Tilt_Q14, /* I Tilt shaping coeficient */ + opus_int32 LF_shp_Q14, /* I Low-frequancy shaping coeficients */ + opus_int lag, /* I Lag for harmonic shaping */ + opus_int length /* I Length of signals */ +) +{ + opus_int i, idx, LTP_shp_buf_idx; + opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10; + opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12; + opus_int16 *LTP_shp_buf; + + /* To speed up use temp variables instead of using the struct */ + LTP_shp_buf = P->sLTP_shp; + LTP_shp_buf_idx = P->sLTP_shp_buf_idx; + sLF_AR_shp_Q12 = P->sLF_AR_shp_Q12; + sLF_MA_shp_Q12 = P->sLF_MA_shp_Q12; + + for( i = 0; i < length; i++ ) { + if( lag > 0 ) { + /* unrolled loop */ + silk_assert( HARM_SHAPE_FIR_TAPS == 3 ); + idx = lag + LTP_shp_buf_idx; + n_LTP_Q12 = silk_SMULBB( LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); + n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 ) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); + n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 ); + } else { + n_LTP_Q12 = 0; + } + + n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 ); + n_LF_Q10 = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 ); + + sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) ); + sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12, silk_LSHIFT( n_LF_Q10, 2 ) ); + + LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK; + LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) ); + + xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 ); + } + + /* Copy temp variable back to state */ + P->sLF_AR_shp_Q12 = sLF_AR_shp_Q12; + P->sLF_MA_shp_Q12 = sLF_MA_shp_Q12; + P->sLTP_shp_buf_idx = LTP_shp_buf_idx; +} diff --git a/TelegramClient.Opus/opus/silk/fixed/process_gains_FIX.c b/TelegramClient.Opus/opus/silk/fixed/process_gains_FIX.c new file mode 100755 index 0000000..05aba31 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/process_gains_FIX.c @@ -0,0 +1,117 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" +#include "tuning_parameters.h" + +/* Processing of gains */ +void silk_process_gains_FIX( + silk_encoder_state_FIX *psEnc, /* I/O Encoder state */ + silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control */ + opus_int condCoding /* I The type of conditional coding to use */ +) +{ + silk_shape_state_FIX *psShapeSt = &psEnc->sShape; + opus_int k; + opus_int32 s_Q16, InvMaxSqrVal_Q16, gain, gain_squared, ResNrg, ResNrgPart, quant_offset_Q10; + + /* Gain reduction when LTP coding gain is high */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + /*s = -0.5f * silk_sigmoid( 0.25f * ( psEncCtrl->LTPredCodGain - 12.0f ) ); */ + s_Q16 = -silk_sigm_Q15( silk_RSHIFT_ROUND( psEncCtrl->LTPredCodGain_Q7 - SILK_FIX_CONST( 12.0, 7 ), 4 ) ); + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + psEncCtrl->Gains_Q16[ k ] = silk_SMLAWB( psEncCtrl->Gains_Q16[ k ], psEncCtrl->Gains_Q16[ k ], s_Q16 ); + } + } + + /* Limit the quantized signal */ + /* InvMaxSqrVal = pow( 2.0f, 0.33f * ( 21.0f - SNR_dB ) ) / subfr_length; */ + InvMaxSqrVal_Q16 = silk_DIV32_16( silk_log2lin( + silk_SMULWB( SILK_FIX_CONST( 21 + 16 / 0.33, 7 ) - psEnc->sCmn.SNR_dB_Q7, SILK_FIX_CONST( 0.33, 16 ) ) ), psEnc->sCmn.subfr_length ); + + for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) { + /* Soft limit on ratio residual energy and squared gains */ + ResNrg = psEncCtrl->ResNrg[ k ]; + ResNrgPart = silk_SMULWW( ResNrg, InvMaxSqrVal_Q16 ); + if( psEncCtrl->ResNrgQ[ k ] > 0 ) { + ResNrgPart = silk_RSHIFT_ROUND( ResNrgPart, psEncCtrl->ResNrgQ[ k ] ); + } else { + if( ResNrgPart >= silk_RSHIFT( silk_int32_MAX, -psEncCtrl->ResNrgQ[ k ] ) ) { + ResNrgPart = silk_int32_MAX; + } else { + ResNrgPart = silk_LSHIFT( ResNrgPart, -psEncCtrl->ResNrgQ[ k ] ); + } + } + gain = psEncCtrl->Gains_Q16[ k ]; + gain_squared = silk_ADD_SAT32( ResNrgPart, silk_SMMUL( gain, gain ) ); + if( gain_squared < silk_int16_MAX ) { + /* recalculate with higher precision */ + gain_squared = silk_SMLAWW( silk_LSHIFT( ResNrgPart, 16 ), gain, gain ); + silk_assert( gain_squared > 0 ); + gain = silk_SQRT_APPROX( gain_squared ); /* Q8 */ + gain = silk_min( gain, silk_int32_MAX >> 8 ); + psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( gain, 8 ); /* Q16 */ + } else { + gain = silk_SQRT_APPROX( gain_squared ); /* Q0 */ + gain = silk_min( gain, silk_int32_MAX >> 16 ); + psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( gain, 16 ); /* Q16 */ + } + } + + /* Save unquantized gains and gain Index */ + silk_memcpy( psEncCtrl->GainsUnq_Q16, psEncCtrl->Gains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) ); + psEncCtrl->lastGainIndexPrev = psShapeSt->LastGainIndex; + + /* Quantize gains */ + silk_gains_quant( psEnc->sCmn.indices.GainsIndices, psEncCtrl->Gains_Q16, + &psShapeSt->LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr ); + + /* Set quantizer offset for voiced signals. Larger offset when LTP coding gain is low or tilt is high (ie low-pass) */ + if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) { + if( psEncCtrl->LTPredCodGain_Q7 + silk_RSHIFT( psEnc->sCmn.input_tilt_Q15, 8 ) > SILK_FIX_CONST( 1.0, 7 ) ) { + psEnc->sCmn.indices.quantOffsetType = 0; + } else { + psEnc->sCmn.indices.quantOffsetType = 1; + } + } + + /* Quantizer boundary adjustment */ + quant_offset_Q10 = silk_Quantization_Offsets_Q10[ psEnc->sCmn.indices.signalType >> 1 ][ psEnc->sCmn.indices.quantOffsetType ]; + psEncCtrl->Lambda_Q10 = SILK_FIX_CONST( LAMBDA_OFFSET, 10 ) + + silk_SMULBB( SILK_FIX_CONST( LAMBDA_DELAYED_DECISIONS, 10 ), psEnc->sCmn.nStatesDelayedDecision ) + + silk_SMULWB( SILK_FIX_CONST( LAMBDA_SPEECH_ACT, 18 ), psEnc->sCmn.speech_activity_Q8 ) + + silk_SMULWB( SILK_FIX_CONST( LAMBDA_INPUT_QUALITY, 12 ), psEncCtrl->input_quality_Q14 ) + + silk_SMULWB( SILK_FIX_CONST( LAMBDA_CODING_QUALITY, 12 ), psEncCtrl->coding_quality_Q14 ) + + silk_SMULWB( SILK_FIX_CONST( LAMBDA_QUANT_OFFSET, 16 ), quant_offset_Q10 ); + + silk_assert( psEncCtrl->Lambda_Q10 > 0 ); + silk_assert( psEncCtrl->Lambda_Q10 < SILK_FIX_CONST( 2, 10 ) ); +} diff --git a/TelegramClient.Opus/opus/silk/fixed/regularize_correlations_FIX.c b/TelegramClient.Opus/opus/silk/fixed/regularize_correlations_FIX.c new file mode 100755 index 0000000..a2836b0 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/regularize_correlations_FIX.c @@ -0,0 +1,47 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" + +/* Add noise to matrix diagonal */ +void silk_regularize_correlations_FIX( + opus_int32 *XX, /* I/O Correlation matrices */ + opus_int32 *xx, /* I/O Correlation values */ + opus_int32 noise, /* I Noise to add */ + opus_int D /* I Dimension of XX */ +) +{ + opus_int i; + for( i = 0; i < D; i++ ) { + matrix_ptr( &XX[ 0 ], i, i, D ) = silk_ADD32( matrix_ptr( &XX[ 0 ], i, i, D ), noise ); + } + xx[ 0 ] += noise; +} diff --git a/TelegramClient.Opus/opus/silk/fixed/residual_energy16_FIX.c b/TelegramClient.Opus/opus/silk/fixed/residual_energy16_FIX.c new file mode 100755 index 0000000..ebffb2a --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/residual_energy16_FIX.c @@ -0,0 +1,103 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" + +/* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */ +opus_int32 silk_residual_energy16_covar_FIX( + const opus_int16 *c, /* I Prediction vector */ + const opus_int32 *wXX, /* I Correlation matrix */ + const opus_int32 *wXx, /* I Correlation vector */ + opus_int32 wxx, /* I Signal energy */ + opus_int D, /* I Dimension */ + opus_int cQ /* I Q value for c vector 0 - 15 */ +) +{ + opus_int i, j, lshifts, Qxtra; + opus_int32 c_max, w_max, tmp, tmp2, nrg; + opus_int cn[ MAX_MATRIX_SIZE ]; + const opus_int32 *pRow; + + /* Safety checks */ + silk_assert( D >= 0 ); + silk_assert( D <= 16 ); + silk_assert( cQ > 0 ); + silk_assert( cQ < 16 ); + + lshifts = 16 - cQ; + Qxtra = lshifts; + + c_max = 0; + for( i = 0; i < D; i++ ) { + c_max = silk_max_32( c_max, silk_abs( (opus_int32)c[ i ] ) ); + } + Qxtra = silk_min_int( Qxtra, silk_CLZ32( c_max ) - 17 ); + + w_max = silk_max_32( wXX[ 0 ], wXX[ D * D - 1 ] ); + Qxtra = silk_min_int( Qxtra, silk_CLZ32( silk_MUL( D, silk_RSHIFT( silk_SMULWB( w_max, c_max ), 4 ) ) ) - 5 ); + Qxtra = silk_max_int( Qxtra, 0 ); + for( i = 0; i < D; i++ ) { + cn[ i ] = silk_LSHIFT( ( opus_int )c[ i ], Qxtra ); + silk_assert( silk_abs(cn[i]) <= ( silk_int16_MAX + 1 ) ); /* Check that silk_SMLAWB can be used */ + } + lshifts -= Qxtra; + + /* Compute wxx - 2 * wXx * c */ + tmp = 0; + for( i = 0; i < D; i++ ) { + tmp = silk_SMLAWB( tmp, wXx[ i ], cn[ i ] ); + } + nrg = silk_RSHIFT( wxx, 1 + lshifts ) - tmp; /* Q: -lshifts - 1 */ + + /* Add c' * wXX * c, assuming wXX is symmetric */ + tmp2 = 0; + for( i = 0; i < D; i++ ) { + tmp = 0; + pRow = &wXX[ i * D ]; + for( j = i + 1; j < D; j++ ) { + tmp = silk_SMLAWB( tmp, pRow[ j ], cn[ j ] ); + } + tmp = silk_SMLAWB( tmp, silk_RSHIFT( pRow[ i ], 1 ), cn[ i ] ); + tmp2 = silk_SMLAWB( tmp2, tmp, cn[ i ] ); + } + nrg = silk_ADD_LSHIFT32( nrg, tmp2, lshifts ); /* Q: -lshifts - 1 */ + + /* Keep one bit free always, because we add them for LSF interpolation */ + if( nrg < 1 ) { + nrg = 1; + } else if( nrg > silk_RSHIFT( silk_int32_MAX, lshifts + 2 ) ) { + nrg = silk_int32_MAX >> 1; + } else { + nrg = silk_LSHIFT( nrg, lshifts + 1 ); /* Q0 */ + } + return nrg; + +} diff --git a/TelegramClient.Opus/opus/silk/fixed/residual_energy_FIX.c b/TelegramClient.Opus/opus/silk/fixed/residual_energy_FIX.c new file mode 100755 index 0000000..105ae31 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/residual_energy_FIX.c @@ -0,0 +1,97 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" +#include "stack_alloc.h" + +/* Calculates residual energies of input subframes where all subframes have LPC_order */ +/* of preceding samples */ +void silk_residual_energy_FIX( + opus_int32 nrgs[ MAX_NB_SUBFR ], /* O Residual energy per subframe */ + opus_int nrgsQ[ MAX_NB_SUBFR ], /* O Q value per subframe */ + const opus_int16 x[], /* I Input signal */ + opus_int16 a_Q12[ 2 ][ MAX_LPC_ORDER ], /* I AR coefs for each frame half */ + const opus_int32 gains[ MAX_NB_SUBFR ], /* I Quantization gains */ + const opus_int subfr_length, /* I Subframe length */ + const opus_int nb_subfr, /* I Number of subframes */ + const opus_int LPC_order /* I LPC order */ +) +{ + opus_int offset, i, j, rshift, lz1, lz2; + opus_int16 *LPC_res_ptr; + VARDECL( opus_int16, LPC_res ); + const opus_int16 *x_ptr; + opus_int32 tmp32; + SAVE_STACK; + + x_ptr = x; + offset = LPC_order + subfr_length; + + /* Filter input to create the LPC residual for each frame half, and measure subframe energies */ + ALLOC( LPC_res, ( MAX_NB_SUBFR >> 1 ) * offset, opus_int16 ); + silk_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr ); + for( i = 0; i < nb_subfr >> 1; i++ ) { + /* Calculate half frame LPC residual signal including preceding samples */ + silk_LPC_analysis_filter( LPC_res, x_ptr, a_Q12[ i ], ( MAX_NB_SUBFR >> 1 ) * offset, LPC_order ); + + /* Point to first subframe of the just calculated LPC residual signal */ + LPC_res_ptr = LPC_res + LPC_order; + for( j = 0; j < ( MAX_NB_SUBFR >> 1 ); j++ ) { + /* Measure subframe energy */ + silk_sum_sqr_shift( &nrgs[ i * ( MAX_NB_SUBFR >> 1 ) + j ], &rshift, LPC_res_ptr, subfr_length ); + + /* Set Q values for the measured energy */ + nrgsQ[ i * ( MAX_NB_SUBFR >> 1 ) + j ] = -rshift; + + /* Move to next subframe */ + LPC_res_ptr += offset; + } + /* Move to next frame half */ + x_ptr += ( MAX_NB_SUBFR >> 1 ) * offset; + } + + /* Apply the squared subframe gains */ + for( i = 0; i < nb_subfr; i++ ) { + /* Fully upscale gains and energies */ + lz1 = silk_CLZ32( nrgs[ i ] ) - 1; + lz2 = silk_CLZ32( gains[ i ] ) - 1; + + tmp32 = silk_LSHIFT32( gains[ i ], lz2 ); + + /* Find squared gains */ + tmp32 = silk_SMMUL( tmp32, tmp32 ); /* Q( 2 * lz2 - 32 )*/ + + /* Scale energies */ + nrgs[ i ] = silk_SMMUL( tmp32, silk_LSHIFT32( nrgs[ i ], lz1 ) ); /* Q( nrgsQ[ i ] + lz1 + 2 * lz2 - 32 - 32 )*/ + nrgsQ[ i ] += lz1 + 2 * lz2 - 32 - 32; + } + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/fixed/schur64_FIX.c b/TelegramClient.Opus/opus/silk/fixed/schur64_FIX.c new file mode 100755 index 0000000..764a10e --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/schur64_FIX.c @@ -0,0 +1,92 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* Slower than schur(), but more accurate. */ +/* Uses SMULL(), available on armv4 */ +opus_int32 silk_schur64( /* O returns residual energy */ + opus_int32 rc_Q16[], /* O Reflection coefficients [order] Q16 */ + const opus_int32 c[], /* I Correlations [order+1] */ + opus_int32 order /* I Prediction order */ +) +{ + opus_int k, n; + opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; + opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31; + + silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 ); + + /* Check for invalid input */ + if( c[ 0 ] <= 0 ) { + silk_memset( rc_Q16, 0, order * sizeof( opus_int32 ) ); + return 0; + } + + for( k = 0; k < order + 1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; + } + + for( k = 0; k < order; k++ ) { + /* Check that we won't be getting an unstable rc, otherwise stop here. */ + if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) { + if ( C[ k + 1 ][ 0 ] > 0 ) { + rc_Q16[ k ] = -SILK_FIX_CONST( .99f, 16 ); + } else { + rc_Q16[ k ] = SILK_FIX_CONST( .99f, 16 ); + } + k++; + break; + } + + /* Get reflection coefficient: divide two Q30 values and get result in Q31 */ + rc_tmp_Q31 = silk_DIV32_varQ( -C[ k + 1 ][ 0 ], C[ 0 ][ 1 ], 31 ); + + /* Save the output */ + rc_Q16[ k ] = silk_RSHIFT_ROUND( rc_tmp_Q31, 15 ); + + /* Update correlations */ + for( n = 0; n < order - k; n++ ) { + Ctmp1_Q30 = C[ n + k + 1 ][ 0 ]; + Ctmp2_Q30 = C[ n ][ 1 ]; + + /* Multiply and add the highest int32 */ + C[ n + k + 1 ][ 0 ] = Ctmp1_Q30 + silk_SMMUL( silk_LSHIFT( Ctmp2_Q30, 1 ), rc_tmp_Q31 ); + C[ n ][ 1 ] = Ctmp2_Q30 + silk_SMMUL( silk_LSHIFT( Ctmp1_Q30, 1 ), rc_tmp_Q31 ); + } + } + + for(; k < order; k++ ) { + rc_Q16[ k ] = 0; + } + + return silk_max_32( 1, C[ 0 ][ 1 ] ); +} diff --git a/TelegramClient.Opus/opus/silk/fixed/schur_FIX.c b/TelegramClient.Opus/opus/silk/fixed/schur_FIX.c new file mode 100755 index 0000000..c4c0ef2 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/schur_FIX.c @@ -0,0 +1,106 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* Faster than schur64(), but much less accurate. */ +/* uses SMLAWB(), requiring armv5E and higher. */ +opus_int32 silk_schur( /* O Returns residual energy */ + opus_int16 *rc_Q15, /* O reflection coefficients [order] Q15 */ + const opus_int32 *c, /* I correlations [order+1] */ + const opus_int32 order /* I prediction order */ +) +{ + opus_int k, n, lz; + opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ]; + opus_int32 Ctmp1, Ctmp2, rc_tmp_Q15; + + silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 ); + + /* Get number of leading zeros */ + lz = silk_CLZ32( c[ 0 ] ); + + /* Copy correlations and adjust level to Q30 */ + if( lz < 2 ) { + /* lz must be 1, so shift one to the right */ + for( k = 0; k < order + 1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = silk_RSHIFT( c[ k ], 1 ); + } + } else if( lz > 2 ) { + /* Shift to the left */ + lz -= 2; + for( k = 0; k < order + 1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = silk_LSHIFT( c[ k ], lz ); + } + } else { + /* No need to shift */ + for( k = 0; k < order + 1; k++ ) { + C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ]; + } + } + + for( k = 0; k < order; k++ ) { + /* Check that we won't be getting an unstable rc, otherwise stop here. */ + if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) { + if ( C[ k + 1 ][ 0 ] > 0 ) { + rc_Q15[ k ] = -SILK_FIX_CONST( .99f, 15 ); + } else { + rc_Q15[ k ] = SILK_FIX_CONST( .99f, 15 ); + } + k++; + break; + } + + /* Get reflection coefficient */ + rc_tmp_Q15 = -silk_DIV32_16( C[ k + 1 ][ 0 ], silk_max_32( silk_RSHIFT( C[ 0 ][ 1 ], 15 ), 1 ) ); + + /* Clip (shouldn't happen for properly conditioned inputs) */ + rc_tmp_Q15 = silk_SAT16( rc_tmp_Q15 ); + + /* Store */ + rc_Q15[ k ] = (opus_int16)rc_tmp_Q15; + + /* Update correlations */ + for( n = 0; n < order - k; n++ ) { + Ctmp1 = C[ n + k + 1 ][ 0 ]; + Ctmp2 = C[ n ][ 1 ]; + C[ n + k + 1 ][ 0 ] = silk_SMLAWB( Ctmp1, silk_LSHIFT( Ctmp2, 1 ), rc_tmp_Q15 ); + C[ n ][ 1 ] = silk_SMLAWB( Ctmp2, silk_LSHIFT( Ctmp1, 1 ), rc_tmp_Q15 ); + } + } + + for(; k < order; k++ ) { + rc_Q15[ k ] = 0; + } + + /* return residual energy */ + return silk_max_32( 1, C[ 0 ][ 1 ] ); +} diff --git a/TelegramClient.Opus/opus/silk/fixed/solve_LS_FIX.c b/TelegramClient.Opus/opus/silk/fixed/solve_LS_FIX.c new file mode 100755 index 0000000..51d7d49 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/solve_LS_FIX.c @@ -0,0 +1,249 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" +#include "stack_alloc.h" +#include "tuning_parameters.h" + +/*****************************/ +/* Internal function headers */ +/*****************************/ + +typedef struct { + opus_int32 Q36_part; + opus_int32 Q48_part; +} inv_D_t; + +/* Factorize square matrix A into LDL form */ +static OPUS_INLINE void silk_LDL_factorize_FIX( + opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */ + opus_int M, /* I Size of Matrix */ + opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ + inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ +); + +/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */ +static OPUS_INLINE void silk_LS_SolveFirst_FIX( + const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ + opus_int M, /* I Dim of Matrix equation */ + const opus_int32 *b, /* I b Vector */ + opus_int32 *x_Q16 /* O x Vector */ +); + +/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */ +static OPUS_INLINE void silk_LS_SolveLast_FIX( + const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ + const opus_int M, /* I Dim of Matrix equation */ + const opus_int32 *b, /* I b Vector */ + opus_int32 *x_Q16 /* O x Vector */ +); + +static OPUS_INLINE void silk_LS_divide_Q16_FIX( + opus_int32 T[], /* I/O Numenator vector */ + inv_D_t *inv_D, /* I 1 / D vector */ + opus_int M /* I dimension */ +); + +/* Solves Ax = b, assuming A is symmetric */ +void silk_solve_LDL_FIX( + opus_int32 *A, /* I Pointer to symetric square matrix A */ + opus_int M, /* I Size of matrix */ + const opus_int32 *b, /* I Pointer to b vector */ + opus_int32 *x_Q16 /* O Pointer to x solution vector */ +) +{ + VARDECL( opus_int32, L_Q16 ); + opus_int32 Y[ MAX_MATRIX_SIZE ]; + inv_D_t inv_D[ MAX_MATRIX_SIZE ]; + SAVE_STACK; + + silk_assert( M <= MAX_MATRIX_SIZE ); + ALLOC( L_Q16, M * M, opus_int32 ); + + /*************************************************** + Factorize A by LDL such that A = L*D*L', + where L is lower triangular with ones on diagonal + ****************************************************/ + silk_LDL_factorize_FIX( A, M, L_Q16, inv_D ); + + /**************************************************** + * substitute D*L'*x = Y. ie: + L*D*L'*x = b => L*Y = b <=> Y = inv(L)*b + ******************************************************/ + silk_LS_SolveFirst_FIX( L_Q16, M, b, Y ); + + /**************************************************** + D*L'*x = Y <=> L'*x = inv(D)*Y, because D is + diagonal just multiply with 1/d_i + ****************************************************/ + silk_LS_divide_Q16_FIX( Y, inv_D, M ); + + /**************************************************** + x = inv(L') * inv(D) * Y + *****************************************************/ + silk_LS_SolveLast_FIX( L_Q16, M, Y, x_Q16 ); + RESTORE_STACK; +} + +static OPUS_INLINE void silk_LDL_factorize_FIX( + opus_int32 *A, /* I/O Pointer to Symetric Square Matrix */ + opus_int M, /* I Size of Matrix */ + opus_int32 *L_Q16, /* I/O Pointer to Square Upper triangular Matrix */ + inv_D_t *inv_D /* I/O Pointer to vector holding inverted diagonal elements of D */ +) +{ + opus_int i, j, k, status, loop_count; + const opus_int32 *ptr1, *ptr2; + opus_int32 diag_min_value, tmp_32, err; + opus_int32 v_Q0[ MAX_MATRIX_SIZE ], D_Q0[ MAX_MATRIX_SIZE ]; + opus_int32 one_div_diag_Q36, one_div_diag_Q40, one_div_diag_Q48; + + silk_assert( M <= MAX_MATRIX_SIZE ); + + status = 1; + diag_min_value = silk_max_32( silk_SMMUL( silk_ADD_SAT32( A[ 0 ], A[ silk_SMULBB( M, M ) - 1 ] ), SILK_FIX_CONST( FIND_LTP_COND_FAC, 31 ) ), 1 << 9 ); + for( loop_count = 0; loop_count < M && status == 1; loop_count++ ) { + status = 0; + for( j = 0; j < M; j++ ) { + ptr1 = matrix_adr( L_Q16, j, 0, M ); + tmp_32 = 0; + for( i = 0; i < j; i++ ) { + v_Q0[ i ] = silk_SMULWW( D_Q0[ i ], ptr1[ i ] ); /* Q0 */ + tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ i ], ptr1[ i ] ); /* Q0 */ + } + tmp_32 = silk_SUB32( matrix_ptr( A, j, j, M ), tmp_32 ); + + if( tmp_32 < diag_min_value ) { + tmp_32 = silk_SUB32( silk_SMULBB( loop_count + 1, diag_min_value ), tmp_32 ); + /* Matrix not positive semi-definite, or ill conditioned */ + for( i = 0; i < M; i++ ) { + matrix_ptr( A, i, i, M ) = silk_ADD32( matrix_ptr( A, i, i, M ), tmp_32 ); + } + status = 1; + break; + } + D_Q0[ j ] = tmp_32; /* always < max(Correlation) */ + + /* two-step division */ + one_div_diag_Q36 = silk_INVERSE32_varQ( tmp_32, 36 ); /* Q36 */ + one_div_diag_Q40 = silk_LSHIFT( one_div_diag_Q36, 4 ); /* Q40 */ + err = silk_SUB32( (opus_int32)1 << 24, silk_SMULWW( tmp_32, one_div_diag_Q40 ) ); /* Q24 */ + one_div_diag_Q48 = silk_SMULWW( err, one_div_diag_Q40 ); /* Q48 */ + + /* Save 1/Ds */ + inv_D[ j ].Q36_part = one_div_diag_Q36; + inv_D[ j ].Q48_part = one_div_diag_Q48; + + matrix_ptr( L_Q16, j, j, M ) = 65536; /* 1.0 in Q16 */ + ptr1 = matrix_adr( A, j, 0, M ); + ptr2 = matrix_adr( L_Q16, j + 1, 0, M ); + for( i = j + 1; i < M; i++ ) { + tmp_32 = 0; + for( k = 0; k < j; k++ ) { + tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ k ], ptr2[ k ] ); /* Q0 */ + } + tmp_32 = silk_SUB32( ptr1[ i ], tmp_32 ); /* always < max(Correlation) */ + + /* tmp_32 / D_Q0[j] : Divide to Q16 */ + matrix_ptr( L_Q16, i, j, M ) = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), + silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); + + /* go to next column */ + ptr2 += M; + } + } + } + + silk_assert( status == 0 ); +} + +static OPUS_INLINE void silk_LS_divide_Q16_FIX( + opus_int32 T[], /* I/O Numenator vector */ + inv_D_t *inv_D, /* I 1 / D vector */ + opus_int M /* I dimension */ +) +{ + opus_int i; + opus_int32 tmp_32; + opus_int32 one_div_diag_Q36, one_div_diag_Q48; + + for( i = 0; i < M; i++ ) { + one_div_diag_Q36 = inv_D[ i ].Q36_part; + one_div_diag_Q48 = inv_D[ i ].Q48_part; + + tmp_32 = T[ i ]; + T[ i ] = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) ); + } +} + +/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */ +static OPUS_INLINE void silk_LS_SolveFirst_FIX( + const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ + opus_int M, /* I Dim of Matrix equation */ + const opus_int32 *b, /* I b Vector */ + opus_int32 *x_Q16 /* O x Vector */ +) +{ + opus_int i, j; + const opus_int32 *ptr32; + opus_int32 tmp_32; + + for( i = 0; i < M; i++ ) { + ptr32 = matrix_adr( L_Q16, i, 0, M ); + tmp_32 = 0; + for( j = 0; j < i; j++ ) { + tmp_32 = silk_SMLAWW( tmp_32, ptr32[ j ], x_Q16[ j ] ); + } + x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 ); + } +} + +/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */ +static OPUS_INLINE void silk_LS_SolveLast_FIX( + const opus_int32 *L_Q16, /* I Pointer to Lower Triangular Matrix */ + const opus_int M, /* I Dim of Matrix equation */ + const opus_int32 *b, /* I b Vector */ + opus_int32 *x_Q16 /* O x Vector */ +) +{ + opus_int i, j; + const opus_int32 *ptr32; + opus_int32 tmp_32; + + for( i = M - 1; i >= 0; i-- ) { + ptr32 = matrix_adr( L_Q16, 0, i, M ); + tmp_32 = 0; + for( j = M - 1; j > i; j-- ) { + tmp_32 = silk_SMLAWW( tmp_32, ptr32[ silk_SMULBB( j, M ) ], x_Q16[ j ] ); + } + x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 ); + } +} diff --git a/TelegramClient.Opus/opus/silk/fixed/structs_FIX.h b/TelegramClient.Opus/opus/silk/fixed/structs_FIX.h new file mode 100755 index 0000000..244b479 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/structs_FIX.h @@ -0,0 +1,133 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_STRUCTS_FIX_H +#define SILK_STRUCTS_FIX_H + +#include "typedef.h" +#include "main.h" +#include "structs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/********************************/ +/* Noise shaping analysis state */ +/********************************/ +typedef struct { + opus_int8 LastGainIndex; + opus_int32 HarmBoost_smth_Q16; + opus_int32 HarmShapeGain_smth_Q16; + opus_int32 Tilt_smth_Q16; +} silk_shape_state_FIX; + +/********************************/ +/* Prefilter state */ +/********************************/ +typedef struct { + opus_int16 sLTP_shp[ LTP_BUF_LENGTH ]; + opus_int32 sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ]; + opus_int sLTP_shp_buf_idx; + opus_int32 sLF_AR_shp_Q12; + opus_int32 sLF_MA_shp_Q12; + opus_int32 sHarmHP_Q2; + opus_int32 rand_seed; + opus_int lagPrev; +} silk_prefilter_state_FIX; + +/********************************/ +/* Encoder state FIX */ +/********************************/ +typedef struct { + silk_encoder_state sCmn; /* Common struct, shared with floating-point code */ + silk_shape_state_FIX sShape; /* Shape state */ + silk_prefilter_state_FIX sPrefilt; /* Prefilter State */ + + /* Buffer for find pitch and noise shape analysis */ + silk_DWORD_ALIGN opus_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */ + opus_int LTPCorr_Q15; /* Normalized correlation from pitch lag estimator */ +} silk_encoder_state_FIX; + +/************************/ +/* Encoder control FIX */ +/************************/ +typedef struct { + /* Prediction and coding parameters */ + opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; + silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; + opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ]; + opus_int LTP_scale_Q14; + opus_int pitchL[ MAX_NB_SUBFR ]; + + /* Noise shaping parameters */ + /* Testing */ + silk_DWORD_ALIGN opus_int16 AR1_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; + silk_DWORD_ALIGN opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ]; + opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ]; /* Packs two int16 coefficients per int32 value */ + opus_int GainsPre_Q14[ MAX_NB_SUBFR ]; + opus_int HarmBoost_Q14[ MAX_NB_SUBFR ]; + opus_int Tilt_Q14[ MAX_NB_SUBFR ]; + opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ]; + opus_int Lambda_Q10; + opus_int input_quality_Q14; + opus_int coding_quality_Q14; + + /* measures */ + opus_int sparseness_Q8; + opus_int32 predGain_Q16; + opus_int LTPredCodGain_Q7; + opus_int32 ResNrg[ MAX_NB_SUBFR ]; /* Residual energy per subframe */ + opus_int ResNrgQ[ MAX_NB_SUBFR ]; /* Q domain for the residual energy > 0 */ + + /* Parameters for CBR mode */ + opus_int32 GainsUnq_Q16[ MAX_NB_SUBFR ]; + opus_int8 lastGainIndexPrev; +} silk_encoder_control_FIX; + +/************************/ +/* Encoder Super Struct */ +/************************/ +typedef struct { + silk_encoder_state_FIX state_Fxx[ ENCODER_NUM_CHANNELS ]; + stereo_enc_state sStereo; + opus_int32 nBitsExceeded; + opus_int nChannelsAPI; + opus_int nChannelsInternal; + opus_int nPrevChannelsInternal; + opus_int timeSinceSwitchAllowed_ms; + opus_int allowBandwidthSwitch; + opus_int prev_decode_only_middle; +} silk_encoder; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/TelegramClient.Opus/opus/silk/fixed/vector_ops_FIX.c b/TelegramClient.Opus/opus/silk/fixed/vector_ops_FIX.c new file mode 100755 index 0000000..509c8b3 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/vector_ops_FIX.c @@ -0,0 +1,96 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* Copy and multiply a vector by a constant */ +void silk_scale_copy_vector16( + opus_int16 *data_out, + const opus_int16 *data_in, + opus_int32 gain_Q16, /* I Gain in Q16 */ + const opus_int dataSize /* I Length */ +) +{ + opus_int i; + opus_int32 tmp32; + + for( i = 0; i < dataSize; i++ ) { + tmp32 = silk_SMULWB( gain_Q16, data_in[ i ] ); + data_out[ i ] = (opus_int16)silk_CHECK_FIT16( tmp32 ); + } +} + +/* Multiply a vector by a constant */ +void silk_scale_vector32_Q26_lshift_18( + opus_int32 *data1, /* I/O Q0/Q18 */ + opus_int32 gain_Q26, /* I Q26 */ + opus_int dataSize /* I length */ +) +{ + opus_int i; + + for( i = 0; i < dataSize; i++ ) { + data1[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( silk_SMULL( data1[ i ], gain_Q26 ), 8 ) ); /* OUTPUT: Q18 */ + } +} + +/* sum = for(i=0;i6, memory access can be reduced by half. */ +opus_int32 silk_inner_prod_aligned( + const opus_int16 *const inVec1, /* I input vector 1 */ + const opus_int16 *const inVec2, /* I input vector 2 */ + const opus_int len /* I vector lengths */ +) +{ + opus_int i; + opus_int32 sum = 0; + for( i = 0; i < len; i++ ) { + sum = silk_SMLABB( sum, inVec1[ i ], inVec2[ i ] ); + } + return sum; +} + +opus_int64 silk_inner_prod16_aligned_64( + const opus_int16 *inVec1, /* I input vector 1 */ + const opus_int16 *inVec2, /* I input vector 2 */ + const opus_int len /* I vector lengths */ +) +{ + opus_int i; + opus_int64 sum = 0; + for( i = 0; i < len; i++ ) { + sum = silk_SMLALBB( sum, inVec1[ i ], inVec2[ i ] ); + } + return sum; +} diff --git a/TelegramClient.Opus/opus/silk/fixed/warped_autocorrelation_FIX.c b/TelegramClient.Opus/opus/silk/fixed/warped_autocorrelation_FIX.c new file mode 100755 index 0000000..a4a579b --- /dev/null +++ b/TelegramClient.Opus/opus/silk/fixed/warped_autocorrelation_FIX.c @@ -0,0 +1,88 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main_FIX.h" + +#define QC 10 +#define QS 14 + +/* Autocorrelations for a warped frequency axis */ +void silk_warped_autocorrelation_FIX( + opus_int32 *corr, /* O Result [order + 1] */ + opus_int *scale, /* O Scaling of the correlation vector */ + const opus_int16 *input, /* I Input data to correlate */ + const opus_int warping_Q16, /* I Warping coefficient */ + const opus_int length, /* I Length of input */ + const opus_int order /* I Correlation order (even) */ +) +{ + opus_int n, i, lsh; + opus_int32 tmp1_QS, tmp2_QS; + opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; + opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; + + /* Order must be even */ + silk_assert( ( order & 1 ) == 0 ); + silk_assert( 2 * QS - QC >= 0 ); + + /* Loop over samples */ + for( n = 0; n < length; n++ ) { + tmp1_QS = silk_LSHIFT32( (opus_int32)input[ n ], QS ); + /* Loop over allpass sections */ + for( i = 0; i < order; i += 2 ) { + /* Output of allpass section */ + tmp2_QS = silk_SMLAWB( state_QS[ i ], state_QS[ i + 1 ] - tmp1_QS, warping_Q16 ); + state_QS[ i ] = tmp1_QS; + corr_QC[ i ] += silk_RSHIFT64( silk_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); + /* Output of allpass section */ + tmp1_QS = silk_SMLAWB( state_QS[ i + 1 ], state_QS[ i + 2 ] - tmp2_QS, warping_Q16 ); + state_QS[ i + 1 ] = tmp2_QS; + corr_QC[ i + 1 ] += silk_RSHIFT64( silk_SMULL( tmp2_QS, state_QS[ 0 ] ), 2 * QS - QC ); + } + state_QS[ order ] = tmp1_QS; + corr_QC[ order ] += silk_RSHIFT64( silk_SMULL( tmp1_QS, state_QS[ 0 ] ), 2 * QS - QC ); + } + + lsh = silk_CLZ64( corr_QC[ 0 ] ) - 35; + lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC ); + *scale = -( QC + lsh ); + silk_assert( *scale >= -30 && *scale <= 12 ); + if( lsh >= 0 ) { + for( i = 0; i < order + 1; i++ ) { + corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QC[ i ], lsh ) ); + } + } else { + for( i = 0; i < order + 1; i++ ) { + corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QC[ i ], -lsh ) ); + } + } + silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/ +} diff --git a/TelegramClient.Opus/opus/silk/gain_quant.c b/TelegramClient.Opus/opus/silk/gain_quant.c new file mode 100755 index 0000000..64ccd06 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/gain_quant.c @@ -0,0 +1,141 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +#define OFFSET ( ( MIN_QGAIN_DB * 128 ) / 6 + 16 * 128 ) +#define SCALE_Q16 ( ( 65536 * ( N_LEVELS_QGAIN - 1 ) ) / ( ( ( MAX_QGAIN_DB - MIN_QGAIN_DB ) * 128 ) / 6 ) ) +#define INV_SCALE_Q16 ( ( 65536 * ( ( ( MAX_QGAIN_DB - MIN_QGAIN_DB ) * 128 ) / 6 ) ) / ( N_LEVELS_QGAIN - 1 ) ) + +/* Gain scalar quantization with hysteresis, uniform on log scale */ +void silk_gains_quant( + opus_int8 ind[ MAX_NB_SUBFR ], /* O gain indices */ + opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* I/O gains (quantized out) */ + opus_int8 *prev_ind, /* I/O last index in previous frame */ + const opus_int conditional, /* I first gain is delta coded if 1 */ + const opus_int nb_subfr /* I number of subframes */ +) +{ + opus_int k, double_step_size_threshold; + + for( k = 0; k < nb_subfr; k++ ) { + /* Convert to log scale, scale, floor() */ + ind[ k ] = silk_SMULWB( SCALE_Q16, silk_lin2log( gain_Q16[ k ] ) - OFFSET ); + + /* Round towards previous quantized gain (hysteresis) */ + if( ind[ k ] < *prev_ind ) { + ind[ k ]++; + } + ind[ k ] = silk_LIMIT_int( ind[ k ], 0, N_LEVELS_QGAIN - 1 ); + + /* Compute delta indices and limit */ + if( k == 0 && conditional == 0 ) { + /* Full index */ + ind[ k ] = silk_LIMIT_int( ind[ k ], *prev_ind + MIN_DELTA_GAIN_QUANT, N_LEVELS_QGAIN - 1 ); + *prev_ind = ind[ k ]; + } else { + /* Delta index */ + ind[ k ] = ind[ k ] - *prev_ind; + + /* Double the quantization step size for large gain increases, so that the max gain level can be reached */ + double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind; + if( ind[ k ] > double_step_size_threshold ) { + ind[ k ] = double_step_size_threshold + silk_RSHIFT( ind[ k ] - double_step_size_threshold + 1, 1 ); + } + + ind[ k ] = silk_LIMIT_int( ind[ k ], MIN_DELTA_GAIN_QUANT, MAX_DELTA_GAIN_QUANT ); + + /* Accumulate deltas */ + if( ind[ k ] > double_step_size_threshold ) { + *prev_ind += silk_LSHIFT( ind[ k ], 1 ) - double_step_size_threshold; + } else { + *prev_ind += ind[ k ]; + } + + /* Shift to make non-negative */ + ind[ k ] -= MIN_DELTA_GAIN_QUANT; + } + + /* Scale and convert to linear scale */ + gain_Q16[ k ] = silk_log2lin( silk_min_32( silk_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */ + } +} + +/* Gains scalar dequantization, uniform on log scale */ +void silk_gains_dequant( + opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* O quantized gains */ + const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */ + opus_int8 *prev_ind, /* I/O last index in previous frame */ + const opus_int conditional, /* I first gain is delta coded if 1 */ + const opus_int nb_subfr /* I number of subframes */ +) +{ + opus_int k, ind_tmp, double_step_size_threshold; + + for( k = 0; k < nb_subfr; k++ ) { + if( k == 0 && conditional == 0 ) { + /* Gain index is not allowed to go down more than 16 steps (~21.8 dB) */ + *prev_ind = silk_max_int( ind[ k ], *prev_ind - 16 ); + } else { + /* Delta index */ + ind_tmp = ind[ k ] + MIN_DELTA_GAIN_QUANT; + + /* Accumulate deltas */ + double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind; + if( ind_tmp > double_step_size_threshold ) { + *prev_ind += silk_LSHIFT( ind_tmp, 1 ) - double_step_size_threshold; + } else { + *prev_ind += ind_tmp; + } + } + *prev_ind = silk_LIMIT_int( *prev_ind, 0, N_LEVELS_QGAIN - 1 ); + + /* Scale and convert to linear scale */ + gain_Q16[ k ] = silk_log2lin( silk_min_32( silk_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) ); /* 3967 = 31 in Q7 */ + } +} + +/* Compute unique identifier of gain indices vector */ +opus_int32 silk_gains_ID( /* O returns unique identifier of gains */ + const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */ + const opus_int nb_subfr /* I number of subframes */ +) +{ + opus_int k; + opus_int32 gainsID; + + gainsID = 0; + for( k = 0; k < nb_subfr; k++ ) { + gainsID = silk_ADD_LSHIFT32( ind[ k ], gainsID, 8 ); + } + + return gainsID; +} diff --git a/TelegramClient.Opus/opus/silk/init_decoder.c b/TelegramClient.Opus/opus/silk/init_decoder.c new file mode 100755 index 0000000..f887c67 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/init_decoder.c @@ -0,0 +1,56 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/************************/ +/* Init Decoder State */ +/************************/ +opus_int silk_init_decoder( + silk_decoder_state *psDec /* I/O Decoder state pointer */ +) +{ + /* Clear the entire encoder state, except anything copied */ + silk_memset( psDec, 0, sizeof( silk_decoder_state ) ); + + /* Used to deactivate LSF interpolation */ + psDec->first_frame_after_reset = 1; + psDec->prev_gain_Q16 = 65536; + + /* Reset CNG state */ + silk_CNG_Reset( psDec ); + + /* Reset PLC state */ + silk_PLC_Reset( psDec ); + + return(0); +} + diff --git a/TelegramClient.Opus/opus/silk/init_encoder.c b/TelegramClient.Opus/opus/silk/init_encoder.c new file mode 100755 index 0000000..65995c3 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/init_encoder.c @@ -0,0 +1,64 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef FIXED_POINT +#include "main_FIX.h" +#else +#include "main_FLP.h" +#endif +#include "tuning_parameters.h" +#include "cpu_support.h" + +/*********************************/ +/* Initialize Silk Encoder state */ +/*********************************/ +opus_int silk_init_encoder( + silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk FIX encoder state */ + int arch /* I Run-time architecture */ +) +{ + opus_int ret = 0; + + /* Clear the entire encoder state */ + silk_memset( psEnc, 0, sizeof( silk_encoder_state_Fxx ) ); + + psEnc->sCmn.arch = arch; + + psEnc->sCmn.variable_HP_smth1_Q15 = silk_LSHIFT( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ), 8 ); + psEnc->sCmn.variable_HP_smth2_Q15 = psEnc->sCmn.variable_HP_smth1_Q15; + + /* Used to deactivate LSF interpolation, pitch prediction */ + psEnc->sCmn.first_frame_after_reset = 1; + + /* Initialize Silk VAD */ + ret += silk_VAD_Init( &psEnc->sCmn.sVAD ); + + return ret; +} diff --git a/TelegramClient.Opus/opus/silk/inner_prod_aligned.c b/TelegramClient.Opus/opus/silk/inner_prod_aligned.c new file mode 100755 index 0000000..257ae9e --- /dev/null +++ b/TelegramClient.Opus/opus/silk/inner_prod_aligned.c @@ -0,0 +1,47 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +opus_int32 silk_inner_prod_aligned_scale( + const opus_int16 *const inVec1, /* I input vector 1 */ + const opus_int16 *const inVec2, /* I input vector 2 */ + const opus_int scale, /* I number of bits to shift */ + const opus_int len /* I vector lengths */ +) +{ + opus_int i; + opus_int32 sum = 0; + for( i = 0; i < len; i++ ) { + sum = silk_ADD_RSHIFT32( sum, silk_SMULBB( inVec1[ i ], inVec2[ i ] ), scale ); + } + return sum; +} diff --git a/TelegramClient.Opus/opus/silk/interpolate.c b/TelegramClient.Opus/opus/silk/interpolate.c new file mode 100755 index 0000000..1bd8ca4 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/interpolate.c @@ -0,0 +1,51 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Interpolate two vectors */ +void silk_interpolate( + opus_int16 xi[ MAX_LPC_ORDER ], /* O interpolated vector */ + const opus_int16 x0[ MAX_LPC_ORDER ], /* I first vector */ + const opus_int16 x1[ MAX_LPC_ORDER ], /* I second vector */ + const opus_int ifact_Q2, /* I interp. factor, weight on 2nd vector */ + const opus_int d /* I number of parameters */ +) +{ + opus_int i; + + silk_assert( ifact_Q2 >= 0 ); + silk_assert( ifact_Q2 <= 4 ); + + for( i = 0; i < d; i++ ) { + xi[ i ] = (opus_int16)silk_ADD_RSHIFT( x0[ i ], silk_SMULBB( x1[ i ] - x0[ i ], ifact_Q2 ), 2 ); + } +} diff --git a/TelegramClient.Opus/opus/silk/lin2log.c b/TelegramClient.Opus/opus/silk/lin2log.c new file mode 100755 index 0000000..d4fe515 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/lin2log.c @@ -0,0 +1,46 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" +/* Approximation of 128 * log2() (very close inverse of silk_log2lin()) */ +/* Convert input to a log scale */ +opus_int32 silk_lin2log( + const opus_int32 inLin /* I input in linear scale */ +) +{ + opus_int32 lz, frac_Q7; + + silk_CLZ_FRAC( inLin, &lz, &frac_Q7 ); + + /* Piece-wise parabolic approximation */ + return silk_LSHIFT( 31 - lz, 7 ) + silk_SMLAWB( frac_Q7, silk_MUL( frac_Q7, 128 - frac_Q7 ), 179 ); +} + diff --git a/TelegramClient.Opus/opus/silk/log2lin.c b/TelegramClient.Opus/opus/silk/log2lin.c new file mode 100755 index 0000000..a692e00 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/log2lin.c @@ -0,0 +1,58 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* Approximation of 2^() (very close inverse of silk_lin2log()) */ +/* Convert input to a linear scale */ +opus_int32 silk_log2lin( + const opus_int32 inLog_Q7 /* I input on log scale */ +) +{ + opus_int32 out, frac_Q7; + + if( inLog_Q7 < 0 ) { + return 0; + } else if ( inLog_Q7 >= 3967 ) { + return silk_int32_MAX; + } + + out = silk_LSHIFT( 1, silk_RSHIFT( inLog_Q7, 7 ) ); + frac_Q7 = inLog_Q7 & 0x7F; + if( inLog_Q7 < 2048 ) { + /* Piece-wise parabolic approximation */ + out = silk_ADD_RSHIFT32( out, silk_MUL( out, silk_SMLAWB( frac_Q7, silk_SMULBB( frac_Q7, 128 - frac_Q7 ), -174 ) ), 7 ); + } else { + /* Piece-wise parabolic approximation */ + out = silk_MLA( out, silk_RSHIFT( out, 7 ), silk_SMLAWB( frac_Q7, silk_SMULBB( frac_Q7, 128 - frac_Q7 ), -174 ) ); + } + return out; +} diff --git a/TelegramClient.Opus/opus/silk/macros.h b/TelegramClient.Opus/opus/silk/macros.h new file mode 100755 index 0000000..a84e5a5 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/macros.h @@ -0,0 +1,115 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_MACROS_H +#define SILK_MACROS_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "opus_types.h" +#include "opus_defines.h" + +/* This is an OPUS_INLINE header file for general platform. */ + +/* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */ +#define silk_SMULWB(a32, b32) ((((a32) >> 16) * (opus_int32)((opus_int16)(b32))) + ((((a32) & 0x0000FFFF) * (opus_int32)((opus_int16)(b32))) >> 16)) + +/* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */ +#define silk_SMLAWB(a32, b32, c32) ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16))) + +/* (a32 * (b32 >> 16)) >> 16 */ +#define silk_SMULWT(a32, b32) (((a32) >> 16) * ((b32) >> 16) + ((((a32) & 0x0000FFFF) * ((b32) >> 16)) >> 16)) + +/* a32 + (b32 * (c32 >> 16)) >> 16 */ +#define silk_SMLAWT(a32, b32, c32) ((a32) + (((b32) >> 16) * ((c32) >> 16)) + ((((b32) & 0x0000FFFF) * ((c32) >> 16)) >> 16)) + +/* (opus_int32)((opus_int16)(a3))) * (opus_int32)((opus_int16)(b32)) output have to be 32bit int */ +#define silk_SMULBB(a32, b32) ((opus_int32)((opus_int16)(a32)) * (opus_int32)((opus_int16)(b32))) + +/* a32 + (opus_int32)((opus_int16)(b32)) * (opus_int32)((opus_int16)(c32)) output have to be 32bit int */ +#define silk_SMLABB(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32))) + +/* (opus_int32)((opus_int16)(a32)) * (b32 >> 16) */ +#define silk_SMULBT(a32, b32) ((opus_int32)((opus_int16)(a32)) * ((b32) >> 16)) + +/* a32 + (opus_int32)((opus_int16)(b32)) * (c32 >> 16) */ +#define silk_SMLABT(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * ((c32) >> 16)) + +/* a64 + (b32 * c32) */ +#define silk_SMLAL(a64, b32, c32) (silk_ADD64((a64), ((opus_int64)(b32) * (opus_int64)(c32)))) + +/* (a32 * b32) >> 16 */ +#define silk_SMULWW(a32, b32) silk_MLA(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16)) + +/* a32 + ((b32 * c32) >> 16) */ +#define silk_SMLAWW(a32, b32, c32) silk_MLA(silk_SMLAWB((a32), (b32), (c32)), (b32), silk_RSHIFT_ROUND((c32), 16)) + +/* add/subtract with output saturated */ +#define silk_ADD_SAT32(a, b) ((((opus_uint32)(a) + (opus_uint32)(b)) & 0x80000000) == 0 ? \ + ((((a) & (b)) & 0x80000000) != 0 ? silk_int32_MIN : (a)+(b)) : \ + ((((a) | (b)) & 0x80000000) == 0 ? silk_int32_MAX : (a)+(b)) ) + +#define silk_SUB_SAT32(a, b) ((((opus_uint32)(a)-(opus_uint32)(b)) & 0x80000000) == 0 ? \ + (( (a) & ((b)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a)-(b)) : \ + ((((a)^0x80000000) & (b) & 0x80000000) ? silk_int32_MAX : (a)-(b)) ) + +#include "ecintrin.h" + +static OPUS_INLINE opus_int32 silk_CLZ16(opus_int16 in16) +{ + return 32 - EC_ILOG(in16<<16|0x8000); +} + +static OPUS_INLINE opus_int32 silk_CLZ32(opus_int32 in32) +{ + return in32 ? 32 - EC_ILOG(in32) : 32; +} + +/* Row based */ +#define matrix_ptr(Matrix_base_adr, row, column, N) \ + (*((Matrix_base_adr) + ((row)*(N)+(column)))) +#define matrix_adr(Matrix_base_adr, row, column, N) \ + ((Matrix_base_adr) + ((row)*(N)+(column))) + +/* Column based */ +#ifndef matrix_c_ptr +# define matrix_c_ptr(Matrix_base_adr, row, column, M) \ + (*((Matrix_base_adr) + ((row)+(M)*(column)))) +#endif + +#ifdef OPUS_ARM_INLINE_ASM +#include "arm/macros_armv4.h" +#endif + +#ifdef OPUS_ARM_INLINE_EDSP +#include "arm/macros_armv5e.h" +#endif + +#endif /* SILK_MACROS_H */ + diff --git a/TelegramClient.Opus/opus/silk/main.h b/TelegramClient.Opus/opus/silk/main.h new file mode 100755 index 0000000..2bdf897 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/main.h @@ -0,0 +1,438 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_MAIN_H +#define SILK_MAIN_H + +#include "SigProc_FIX.h" +#include "define.h" +#include "structs.h" +#include "tables.h" +#include "PLC.h" +#include "control.h" +#include "debug.h" +#include "entenc.h" +#include "entdec.h" + +/* Convert Left/Right stereo signal to adaptive Mid/Side representation */ +void silk_stereo_LR_to_MS( + stereo_enc_state *state, /* I/O State */ + opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ + opus_int16 x2[], /* I/O Right input signal, becomes side signal */ + opus_int8 ix[ 2 ][ 3 ], /* O Quantization indices */ + opus_int8 *mid_only_flag, /* O Flag: only mid signal coded */ + opus_int32 mid_side_rates_bps[], /* O Bitrates for mid and side signals */ + opus_int32 total_rate_bps, /* I Total bitrate */ + opus_int prev_speech_act_Q8, /* I Speech activity level in previous frame */ + opus_int toMono, /* I Last frame before a stereo->mono transition */ + opus_int fs_kHz, /* I Sample rate (kHz) */ + opus_int frame_length /* I Number of samples */ +); + +/* Convert adaptive Mid/Side representation to Left/Right stereo signal */ +void silk_stereo_MS_to_LR( + stereo_dec_state *state, /* I/O State */ + opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ + opus_int16 x2[], /* I/O Right input signal, becomes side signal */ + const opus_int32 pred_Q13[], /* I Predictors */ + opus_int fs_kHz, /* I Samples rate (kHz) */ + opus_int frame_length /* I Number of samples */ +); + +/* Find least-squares prediction gain for one signal based on another and quantize it */ +opus_int32 silk_stereo_find_predictor( /* O Returns predictor in Q13 */ + opus_int32 *ratio_Q14, /* O Ratio of residual and mid energies */ + const opus_int16 x[], /* I Basis signal */ + const opus_int16 y[], /* I Target signal */ + opus_int32 mid_res_amp_Q0[], /* I/O Smoothed mid, residual norms */ + opus_int length, /* I Number of samples */ + opus_int smooth_coef_Q16 /* I Smoothing coefficient */ +); + +/* Quantize mid/side predictors */ +void silk_stereo_quant_pred( + opus_int32 pred_Q13[], /* I/O Predictors (out: quantized) */ + opus_int8 ix[ 2 ][ 3 ] /* O Quantization indices */ +); + +/* Entropy code the mid/side quantization indices */ +void silk_stereo_encode_pred( + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int8 ix[ 2 ][ 3 ] /* I Quantization indices */ +); + +/* Entropy code the mid-only flag */ +void silk_stereo_encode_mid_only( + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int8 mid_only_flag +); + +/* Decode mid/side predictors */ +void silk_stereo_decode_pred( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int32 pred_Q13[] /* O Predictors */ +); + +/* Decode mid-only flag */ +void silk_stereo_decode_mid_only( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int *decode_only_mid /* O Flag that only mid channel has been coded */ +); + +/* Encodes signs of excitation */ +void silk_encode_signs( + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + const opus_int8 pulses[], /* I pulse signal */ + opus_int length, /* I length of input */ + const opus_int signalType, /* I Signal type */ + const opus_int quantOffsetType, /* I Quantization offset type */ + const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */ +); + +/* Decodes signs of excitation */ +void silk_decode_signs( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int pulses[], /* I/O pulse signal */ + opus_int length, /* I length of input */ + const opus_int signalType, /* I Signal type */ + const opus_int quantOffsetType, /* I Quantization offset type */ + const opus_int sum_pulses[ MAX_NB_SHELL_BLOCKS ] /* I Sum of absolute pulses per block */ +); + +/* Check encoder control struct */ +opus_int check_control_input( + silk_EncControlStruct *encControl /* I Control structure */ +); + +/* Control internal sampling rate */ +opus_int silk_control_audio_bandwidth( + silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */ + silk_EncControlStruct *encControl /* I Control structure */ +); + +/* Control SNR of redidual quantizer */ +opus_int silk_control_SNR( + silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */ + opus_int32 TargetRate_bps /* I Target max bitrate (bps) */ +); + +/***************/ +/* Shell coder */ +/***************/ + +/* Encode quantization indices of excitation */ +void silk_encode_pulses( + ec_enc *psRangeEnc, /* I/O compressor data structure */ + const opus_int signalType, /* I Signal type */ + const opus_int quantOffsetType, /* I quantOffsetType */ + opus_int8 pulses[], /* I quantization indices */ + const opus_int frame_length /* I Frame length */ +); + +/* Shell encoder, operates on one shell code frame of 16 pulses */ +void silk_shell_encoder( + ec_enc *psRangeEnc, /* I/O compressor data structure */ + const opus_int *pulses0 /* I data: nonnegative pulse amplitudes */ +); + +/* Shell decoder, operates on one shell code frame of 16 pulses */ +void silk_shell_decoder( + opus_int *pulses0, /* O data: nonnegative pulse amplitudes */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + const opus_int pulses4 /* I number of pulses per pulse-subframe */ +); + +/* Gain scalar quantization with hysteresis, uniform on log scale */ +void silk_gains_quant( + opus_int8 ind[ MAX_NB_SUBFR ], /* O gain indices */ + opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* I/O gains (quantized out) */ + opus_int8 *prev_ind, /* I/O last index in previous frame */ + const opus_int conditional, /* I first gain is delta coded if 1 */ + const opus_int nb_subfr /* I number of subframes */ +); + +/* Gains scalar dequantization, uniform on log scale */ +void silk_gains_dequant( + opus_int32 gain_Q16[ MAX_NB_SUBFR ], /* O quantized gains */ + const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */ + opus_int8 *prev_ind, /* I/O last index in previous frame */ + const opus_int conditional, /* I first gain is delta coded if 1 */ + const opus_int nb_subfr /* I number of subframes */ +); + +/* Compute unique identifier of gain indices vector */ +opus_int32 silk_gains_ID( /* O returns unique identifier of gains */ + const opus_int8 ind[ MAX_NB_SUBFR ], /* I gain indices */ + const opus_int nb_subfr /* I number of subframes */ +); + +/* Interpolate two vectors */ +void silk_interpolate( + opus_int16 xi[ MAX_LPC_ORDER ], /* O interpolated vector */ + const opus_int16 x0[ MAX_LPC_ORDER ], /* I first vector */ + const opus_int16 x1[ MAX_LPC_ORDER ], /* I second vector */ + const opus_int ifact_Q2, /* I interp. factor, weight on 2nd vector */ + const opus_int d /* I number of parameters */ +); + +/* LTP tap quantizer */ +void silk_quant_LTP_gains( + opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)quantized LTP gains */ + opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */ + opus_int8 *periodicity_index, /* O Periodicity Index */ + opus_int32 *sum_gain_dB_Q7, /* I/O Cumulative max prediction gain */ + const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */ + opus_int mu_Q9, /* I Mu value (R/D tradeoff) */ + opus_int lowComplexity, /* I Flag for low complexity */ + const opus_int nb_subfr /* I number of subframes */ +); + +/* Entropy constrained matrix-weighted VQ, for a single input data vector */ +void silk_VQ_WMat_EC( + opus_int8 *ind, /* O index of best codebook vector */ + opus_int32 *rate_dist_Q14, /* O best weighted quant error + mu * rate */ + opus_int *gain_Q7, /* O sum of absolute LTP coefficients */ + const opus_int16 *in_Q14, /* I input vector to be quantized */ + const opus_int32 *W_Q18, /* I weighting matrix */ + const opus_int8 *cb_Q7, /* I codebook */ + const opus_uint8 *cb_gain_Q7, /* I codebook effective gain */ + const opus_uint8 *cl_Q5, /* I code length for each codebook vector */ + const opus_int mu_Q9, /* I tradeoff betw. weighted error and rate */ + const opus_int32 max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ + opus_int L /* I number of vectors in codebook */ +); + +/************************************/ +/* Noise shaping quantization (NSQ) */ +/************************************/ +void silk_NSQ( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */ + const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */ + const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ + const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */ + const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */ + const opus_int LTP_scale_Q14 /* I LTP state scaling */ +); + +/* Noise shaping using delayed decision */ +void silk_NSQ_del_dec( + const silk_encoder_state *psEncC, /* I/O Encoder State */ + silk_nsq_state *NSQ, /* I/O NSQ state */ + SideInfoIndices *psIndices, /* I/O Quantization Indices */ + const opus_int32 x_Q3[], /* I Prefiltered input signal */ + opus_int8 pulses[], /* O Quantized pulse signal */ + const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */ + const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ + const opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */ + const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */ + const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */ + const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */ + const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */ + const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */ + const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */ + const opus_int LTP_scale_Q14 /* I LTP state scaling */ +); + +/************/ +/* Silk VAD */ +/************/ +/* Initialize the Silk VAD */ +opus_int silk_VAD_Init( /* O Return value, 0 if success */ + silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */ +); + +/* Get speech activity level in Q8 */ +opus_int silk_VAD_GetSA_Q8( /* O Return value, 0 if success */ + silk_encoder_state *psEncC, /* I/O Encoder state */ + const opus_int16 pIn[] /* I PCM input */ +); + +/* Low-pass filter with variable cutoff frequency based on */ +/* piece-wise linear interpolation between elliptic filters */ +/* Start by setting transition_frame_no = 1; */ +void silk_LP_variable_cutoff( + silk_LP_state *psLP, /* I/O LP filter state */ + opus_int16 *frame, /* I/O Low-pass filtered output signal */ + const opus_int frame_length /* I Frame length */ +); + +/******************/ +/* NLSF Quantizer */ +/******************/ +/* Limit, stabilize, convert and quantize NLSFs */ +void silk_process_NLSFs( + silk_encoder_state *psEncC, /* I/O Encoder state */ + opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */ + opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ + const opus_int16 prev_NLSFq_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */ +); + +opus_int32 silk_NLSF_encode( /* O Returns RD value in Q25 */ + opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */ + opus_int16 *pNLSF_Q15, /* I/O Quantized NLSF vector [ LPC_ORDER ] */ + const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */ + const opus_int16 *pW_QW, /* I NLSF weight vector [ LPC_ORDER ] */ + const opus_int NLSF_mu_Q20, /* I Rate weight for the RD optimization */ + const opus_int nSurvivors, /* I Max survivors after first stage */ + const opus_int signalType /* I Signal type: 0/1/2 */ +); + +/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */ +void silk_NLSF_VQ( + opus_int32 err_Q26[], /* O Quantization errors [K] */ + const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */ + const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */ + const opus_int K, /* I Number of codebook vectors */ + const opus_int LPC_order /* I Number of LPCs */ +); + +/* Delayed-decision quantizer for NLSF residuals */ +opus_int32 silk_NLSF_del_dec_quant( /* O Returns RD value in Q25 */ + opus_int8 indices[], /* O Quantization indices [ order ] */ + const opus_int16 x_Q10[], /* I Input [ order ] */ + const opus_int16 w_Q5[], /* I Weights [ order ] */ + const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */ + const opus_int16 ec_ix[], /* I Indices to entropy coding tables [ order ] */ + const opus_uint8 ec_rates_Q5[], /* I Rates [] */ + const opus_int quant_step_size_Q16, /* I Quantization step size */ + const opus_int16 inv_quant_step_size_Q6, /* I Inverse quantization step size */ + const opus_int32 mu_Q20, /* I R/D tradeoff */ + const opus_int16 order /* I Number of input values */ +); + +/* Unpack predictor values and indices for entropy coding tables */ +void silk_NLSF_unpack( + opus_int16 ec_ix[], /* O Indices to entropy tables [ LPC_ORDER ] */ + opus_uint8 pred_Q8[], /* O LSF predictor [ LPC_ORDER ] */ + const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */ + const opus_int CB1_index /* I Index of vector in first LSF codebook */ +); + +/***********************/ +/* NLSF vector decoder */ +/***********************/ +void silk_NLSF_decode( + opus_int16 *pNLSF_Q15, /* O Quantized NLSF vector [ LPC_ORDER ] */ + opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */ + const silk_NLSF_CB_struct *psNLSF_CB /* I Codebook object */ +); + +/****************************************************/ +/* Decoder Functions */ +/****************************************************/ +opus_int silk_init_decoder( + silk_decoder_state *psDec /* I/O Decoder state pointer */ +); + +/* Set decoder sampling rate */ +opus_int silk_decoder_set_fs( + silk_decoder_state *psDec, /* I/O Decoder state pointer */ + opus_int fs_kHz, /* I Sampling frequency (kHz) */ + opus_int32 fs_API_Hz /* I API Sampling frequency (Hz) */ +); + +/****************/ +/* Decode frame */ +/****************/ +opus_int silk_decode_frame( + silk_decoder_state *psDec, /* I/O Pointer to Silk decoder state */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int16 pOut[], /* O Pointer to output speech frame */ + opus_int32 *pN, /* O Pointer to size of output frame */ + opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */ + opus_int condCoding /* I The type of conditional coding to use */ +); + +/* Decode indices from bitstream */ +void silk_decode_indices( + silk_decoder_state *psDec, /* I/O State */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int FrameIndex, /* I Frame number */ + opus_int decode_LBRR, /* I Flag indicating LBRR data is being decoded */ + opus_int condCoding /* I The type of conditional coding to use */ +); + +/* Decode parameters from payload */ +void silk_decode_parameters( + silk_decoder_state *psDec, /* I/O State */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int condCoding /* I The type of conditional coding to use */ +); + +/* Core decoder. Performs inverse NSQ operation LTP + LPC */ +void silk_decode_core( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I Decoder control */ + opus_int16 xq[], /* O Decoded speech */ + const opus_int pulses[ MAX_FRAME_LENGTH ] /* I Pulse signal */ +); + +/* Decode quantization indices of excitation (Shell coding) */ +void silk_decode_pulses( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int pulses[], /* O Excitation signal */ + const opus_int signalType, /* I Sigtype */ + const opus_int quantOffsetType, /* I quantOffsetType */ + const opus_int frame_length /* I Frame length */ +); + +/******************/ +/* CNG */ +/******************/ + +/* Reset CNG */ +void silk_CNG_Reset( + silk_decoder_state *psDec /* I/O Decoder state */ +); + +/* Updates CNG estimate, and applies the CNG when packet was lost */ +void silk_CNG( + silk_decoder_state *psDec, /* I/O Decoder state */ + silk_decoder_control *psDecCtrl, /* I/O Decoder control */ + opus_int16 frame[], /* I/O Signal */ + opus_int length /* I Length of residual */ +); + +/* Encoding of various parameters */ +void silk_encode_indices( + silk_encoder_state *psEncC, /* I/O Encoder state */ + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int FrameIndex, /* I Frame number */ + opus_int encode_LBRR, /* I Flag indicating LBRR data is being encoded */ + opus_int condCoding /* I The type of conditional coding to use */ +); + +#endif diff --git a/TelegramClient.Opus/opus/silk/pitch_est_defines.h b/TelegramClient.Opus/opus/silk/pitch_est_defines.h new file mode 100755 index 0000000..e1e4b5d --- /dev/null +++ b/TelegramClient.Opus/opus/silk/pitch_est_defines.h @@ -0,0 +1,88 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_PE_DEFINES_H +#define SILK_PE_DEFINES_H + +#include "SigProc_FIX.h" + +/********************************************************/ +/* Definitions for pitch estimator */ +/********************************************************/ + +#define PE_MAX_FS_KHZ 16 /* Maximum sampling frequency used */ + +#define PE_MAX_NB_SUBFR 4 +#define PE_SUBFR_LENGTH_MS 5 /* 5 ms */ + +#define PE_LTP_MEM_LENGTH_MS ( 4 * PE_SUBFR_LENGTH_MS ) + +#define PE_MAX_FRAME_LENGTH_MS ( PE_LTP_MEM_LENGTH_MS + PE_MAX_NB_SUBFR * PE_SUBFR_LENGTH_MS ) +#define PE_MAX_FRAME_LENGTH ( PE_MAX_FRAME_LENGTH_MS * PE_MAX_FS_KHZ ) +#define PE_MAX_FRAME_LENGTH_ST_1 ( PE_MAX_FRAME_LENGTH >> 2 ) +#define PE_MAX_FRAME_LENGTH_ST_2 ( PE_MAX_FRAME_LENGTH >> 1 ) + +#define PE_MAX_LAG_MS 18 /* 18 ms -> 56 Hz */ +#define PE_MIN_LAG_MS 2 /* 2 ms -> 500 Hz */ +#define PE_MAX_LAG ( PE_MAX_LAG_MS * PE_MAX_FS_KHZ ) +#define PE_MIN_LAG ( PE_MIN_LAG_MS * PE_MAX_FS_KHZ ) + +#define PE_D_SRCH_LENGTH 24 + +#define PE_NB_STAGE3_LAGS 5 + +#define PE_NB_CBKS_STAGE2 3 +#define PE_NB_CBKS_STAGE2_EXT 11 + +#define PE_NB_CBKS_STAGE3_MAX 34 +#define PE_NB_CBKS_STAGE3_MID 24 +#define PE_NB_CBKS_STAGE3_MIN 16 + +#define PE_NB_CBKS_STAGE3_10MS 12 +#define PE_NB_CBKS_STAGE2_10MS 3 + +#define PE_SHORTLAG_BIAS 0.2f /* for logarithmic weighting */ +#define PE_PREVLAG_BIAS 0.2f /* for logarithmic weighting */ +#define PE_FLATCONTOUR_BIAS 0.05f + +#define SILK_PE_MIN_COMPLEX 0 +#define SILK_PE_MID_COMPLEX 1 +#define SILK_PE_MAX_COMPLEX 2 + +/* Tables for 20 ms frames */ +extern const opus_int8 silk_CB_lags_stage2[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE2_EXT ]; +extern const opus_int8 silk_CB_lags_stage3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ]; +extern const opus_int8 silk_Lag_range_stage3[ SILK_PE_MAX_COMPLEX + 1 ] [ PE_MAX_NB_SUBFR ][ 2 ]; +extern const opus_int8 silk_nb_cbk_searchs_stage3[ SILK_PE_MAX_COMPLEX + 1 ]; + +/* Tables for 10 ms frames */ +extern const opus_int8 silk_CB_lags_stage2_10_ms[ PE_MAX_NB_SUBFR >> 1][ 3 ]; +extern const opus_int8 silk_CB_lags_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 12 ]; +extern const opus_int8 silk_Lag_range_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 2 ]; + +#endif + diff --git a/TelegramClient.Opus/opus/silk/pitch_est_tables.c b/TelegramClient.Opus/opus/silk/pitch_est_tables.c new file mode 100755 index 0000000..81a8bac --- /dev/null +++ b/TelegramClient.Opus/opus/silk/pitch_est_tables.c @@ -0,0 +1,99 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "typedef.h" +#include "pitch_est_defines.h" + +const opus_int8 silk_CB_lags_stage2_10_ms[ PE_MAX_NB_SUBFR >> 1][ PE_NB_CBKS_STAGE2_10MS ] = +{ + {0, 1, 0}, + {0, 0, 1} +}; + +const opus_int8 silk_CB_lags_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ PE_NB_CBKS_STAGE3_10MS ] = +{ + { 0, 0, 1,-1, 1,-1, 2,-2, 2,-2, 3,-3}, + { 0, 1, 0, 1,-1, 2,-1, 2,-2, 3,-2, 3} +}; + +const opus_int8 silk_Lag_range_stage3_10_ms[ PE_MAX_NB_SUBFR >> 1 ][ 2 ] = +{ + {-3, 7}, + {-2, 7} +}; + +const opus_int8 silk_CB_lags_stage2[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE2_EXT ] = +{ + {0, 2,-1,-1,-1, 0, 0, 1, 1, 0, 1}, + {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0}, + {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0}, + {0,-1, 2, 1, 0, 1, 1, 0, 0,-1,-1} +}; + +const opus_int8 silk_CB_lags_stage3[ PE_MAX_NB_SUBFR ][ PE_NB_CBKS_STAGE3_MAX ] = +{ + {0, 0, 1,-1, 0, 1,-1, 0,-1, 1,-2, 2,-2,-2, 2,-3, 2, 3,-3,-4, 3,-4, 4, 4,-5, 5,-6,-5, 6,-7, 6, 5, 8,-9}, + {0, 0, 1, 0, 0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 1,-1, 0, 1,-1,-1, 1,-1, 2, 1,-1, 2,-2,-2, 2,-2, 2, 2, 3,-3}, + {0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1,-1, 1, 0, 0, 2, 1,-1, 2,-1,-1, 2,-1, 2, 2,-1, 3,-2,-2,-2, 3}, + {0, 1, 0, 0, 1, 0, 1,-1, 2,-1, 2,-1, 2, 3,-2, 3,-2,-2, 4, 4,-3, 5,-3,-4, 6,-4, 6, 5,-5, 8,-6,-5,-7, 9} +}; + +const opus_int8 silk_Lag_range_stage3[ SILK_PE_MAX_COMPLEX + 1 ] [ PE_MAX_NB_SUBFR ][ 2 ] = +{ + /* Lags to search for low number of stage3 cbks */ + { + {-5,8}, + {-1,6}, + {-1,6}, + {-4,10} + }, + /* Lags to search for middle number of stage3 cbks */ + { + {-6,10}, + {-2,6}, + {-1,6}, + {-5,10} + }, + /* Lags to search for max number of stage3 cbks */ + { + {-9,12}, + {-3,7}, + {-2,7}, + {-7,13} + } +}; + +const opus_int8 silk_nb_cbk_searchs_stage3[ SILK_PE_MAX_COMPLEX + 1 ] = +{ + PE_NB_CBKS_STAGE3_MIN, + PE_NB_CBKS_STAGE3_MID, + PE_NB_CBKS_STAGE3_MAX +}; diff --git a/TelegramClient.Opus/opus/silk/process_NLSFs.c b/TelegramClient.Opus/opus/silk/process_NLSFs.c new file mode 100755 index 0000000..c27cf03 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/process_NLSFs.c @@ -0,0 +1,105 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Limit, stabilize, convert and quantize NLSFs */ +void silk_process_NLSFs( + silk_encoder_state *psEncC, /* I/O Encoder state */ + opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ], /* O Prediction coefficients */ + opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], /* I/O Normalized LSFs (quant out) (0 - (2^15-1)) */ + const opus_int16 prev_NLSFq_Q15[ MAX_LPC_ORDER ] /* I Previous Normalized LSFs (0 - (2^15-1)) */ +) +{ + opus_int i, doInterpolate; + opus_int NLSF_mu_Q20; + opus_int32 i_sqr_Q15; + opus_int16 pNLSF0_temp_Q15[ MAX_LPC_ORDER ]; + opus_int16 pNLSFW_QW[ MAX_LPC_ORDER ]; + opus_int16 pNLSFW0_temp_QW[ MAX_LPC_ORDER ]; + + silk_assert( psEncC->speech_activity_Q8 >= 0 ); + silk_assert( psEncC->speech_activity_Q8 <= SILK_FIX_CONST( 1.0, 8 ) ); + silk_assert( psEncC->useInterpolatedNLSFs == 1 || psEncC->indices.NLSFInterpCoef_Q2 == ( 1 << 2 ) ); + + /***********************/ + /* Calculate mu values */ + /***********************/ + /* NLSF_mu = 0.003 - 0.0015 * psEnc->speech_activity; */ + NLSF_mu_Q20 = silk_SMLAWB( SILK_FIX_CONST( 0.003, 20 ), SILK_FIX_CONST( -0.001, 28 ), psEncC->speech_activity_Q8 ); + if( psEncC->nb_subfr == 2 ) { + /* Multiply by 1.5 for 10 ms packets */ + NLSF_mu_Q20 = silk_ADD_RSHIFT( NLSF_mu_Q20, NLSF_mu_Q20, 1 ); + } + + silk_assert( NLSF_mu_Q20 > 0 ); + silk_assert( NLSF_mu_Q20 <= SILK_FIX_CONST( 0.005, 20 ) ); + + /* Calculate NLSF weights */ + silk_NLSF_VQ_weights_laroia( pNLSFW_QW, pNLSF_Q15, psEncC->predictLPCOrder ); + + /* Update NLSF weights for interpolated NLSFs */ + doInterpolate = ( psEncC->useInterpolatedNLSFs == 1 ) && ( psEncC->indices.NLSFInterpCoef_Q2 < 4 ); + if( doInterpolate ) { + /* Calculate the interpolated NLSF vector for the first half */ + silk_interpolate( pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, + psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder ); + + /* Calculate first half NLSF weights for the interpolated NLSFs */ + silk_NLSF_VQ_weights_laroia( pNLSFW0_temp_QW, pNLSF0_temp_Q15, psEncC->predictLPCOrder ); + + /* Update NLSF weights with contribution from first half */ + i_sqr_Q15 = silk_LSHIFT( silk_SMULBB( psEncC->indices.NLSFInterpCoef_Q2, psEncC->indices.NLSFInterpCoef_Q2 ), 11 ); + for( i = 0; i < psEncC->predictLPCOrder; i++ ) { + pNLSFW_QW[ i ] = silk_SMLAWB( silk_RSHIFT( pNLSFW_QW[ i ], 1 ), (opus_int32)pNLSFW0_temp_QW[ i ], i_sqr_Q15 ); + silk_assert( pNLSFW_QW[ i ] >= 1 ); + } + } + + silk_NLSF_encode( psEncC->indices.NLSFIndices, pNLSF_Q15, psEncC->psNLSF_CB, pNLSFW_QW, + NLSF_mu_Q20, psEncC->NLSF_MSVQ_Survivors, psEncC->indices.signalType ); + + /* Convert quantized NLSFs back to LPC coefficients */ + silk_NLSF2A( PredCoef_Q12[ 1 ], pNLSF_Q15, psEncC->predictLPCOrder ); + + if( doInterpolate ) { + /* Calculate the interpolated, quantized LSF vector for the first half */ + silk_interpolate( pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15, + psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder ); + + /* Convert back to LPC coefficients */ + silk_NLSF2A( PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEncC->predictLPCOrder ); + + } else { + /* Copy LPC coefficients for first half from second half */ + silk_memcpy( PredCoef_Q12[ 0 ], PredCoef_Q12[ 1 ], psEncC->predictLPCOrder * sizeof( opus_int16 ) ); + } +} diff --git a/TelegramClient.Opus/opus/silk/quant_LTP_gains.c b/TelegramClient.Opus/opus/silk/quant_LTP_gains.c new file mode 100755 index 0000000..fd0870d --- /dev/null +++ b/TelegramClient.Opus/opus/silk/quant_LTP_gains.c @@ -0,0 +1,128 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "tuning_parameters.h" + +void silk_quant_LTP_gains( + opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ], /* I/O (un)quantized LTP gains */ + opus_int8 cbk_index[ MAX_NB_SUBFR ], /* O Codebook Index */ + opus_int8 *periodicity_index, /* O Periodicity Index */ + opus_int32 *sum_log_gain_Q7, /* I/O Cumulative max prediction gain */ + const opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I Error Weights in Q18 */ + opus_int mu_Q9, /* I Mu value (R/D tradeoff) */ + opus_int lowComplexity, /* I Flag for low complexity */ + const opus_int nb_subfr /* I number of subframes */ +) +{ + opus_int j, k, cbk_size; + opus_int8 temp_idx[ MAX_NB_SUBFR ]; + const opus_uint8 *cl_ptr_Q5; + const opus_int8 *cbk_ptr_Q7; + const opus_uint8 *cbk_gain_ptr_Q7; + const opus_int16 *b_Q14_ptr; + const opus_int32 *W_Q18_ptr; + opus_int32 rate_dist_Q14_subfr, rate_dist_Q14, min_rate_dist_Q14; + opus_int32 sum_log_gain_tmp_Q7, best_sum_log_gain_Q7, max_gain_Q7, gain_Q7; + + /***************************************************/ + /* iterate over different codebooks with different */ + /* rates/distortions, and choose best */ + /***************************************************/ + min_rate_dist_Q14 = silk_int32_MAX; + best_sum_log_gain_Q7 = 0; + for( k = 0; k < 3; k++ ) { + /* Safety margin for pitch gain control, to take into account factors + such as state rescaling/rewhitening. */ + opus_int32 gain_safety = SILK_FIX_CONST( 0.4, 7 ); + + cl_ptr_Q5 = silk_LTP_gain_BITS_Q5_ptrs[ k ]; + cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ k ]; + cbk_gain_ptr_Q7 = silk_LTP_vq_gain_ptrs_Q7[ k ]; + cbk_size = silk_LTP_vq_sizes[ k ]; + + /* Set up pointer to first subframe */ + W_Q18_ptr = W_Q18; + b_Q14_ptr = B_Q14; + + rate_dist_Q14 = 0; + sum_log_gain_tmp_Q7 = *sum_log_gain_Q7; + for( j = 0; j < nb_subfr; j++ ) { + max_gain_Q7 = silk_log2lin( ( SILK_FIX_CONST( MAX_SUM_LOG_GAIN_DB / 6.0, 7 ) - sum_log_gain_tmp_Q7 ) + + SILK_FIX_CONST( 7, 7 ) ) - gain_safety; + + silk_VQ_WMat_EC( + &temp_idx[ j ], /* O index of best codebook vector */ + &rate_dist_Q14_subfr, /* O best weighted quantization error + mu * rate */ + &gain_Q7, /* O sum of absolute LTP coefficients */ + b_Q14_ptr, /* I input vector to be quantized */ + W_Q18_ptr, /* I weighting matrix */ + cbk_ptr_Q7, /* I codebook */ + cbk_gain_ptr_Q7, /* I codebook effective gains */ + cl_ptr_Q5, /* I code length for each codebook vector */ + mu_Q9, /* I tradeoff between weighted error and rate */ + max_gain_Q7, /* I maximum sum of absolute LTP coefficients */ + cbk_size /* I number of vectors in codebook */ + ); + + rate_dist_Q14 = silk_ADD_POS_SAT32( rate_dist_Q14, rate_dist_Q14_subfr ); + sum_log_gain_tmp_Q7 = silk_max(0, sum_log_gain_tmp_Q7 + + silk_lin2log( gain_safety + gain_Q7 ) - SILK_FIX_CONST( 7, 7 )); + + b_Q14_ptr += LTP_ORDER; + W_Q18_ptr += LTP_ORDER * LTP_ORDER; + } + + /* Avoid never finding a codebook */ + rate_dist_Q14 = silk_min( silk_int32_MAX - 1, rate_dist_Q14 ); + + if( rate_dist_Q14 < min_rate_dist_Q14 ) { + min_rate_dist_Q14 = rate_dist_Q14; + *periodicity_index = (opus_int8)k; + silk_memcpy( cbk_index, temp_idx, nb_subfr * sizeof( opus_int8 ) ); + best_sum_log_gain_Q7 = sum_log_gain_tmp_Q7; + } + + /* Break early in low-complexity mode if rate distortion is below threshold */ + if( lowComplexity && ( rate_dist_Q14 < silk_LTP_gain_middle_avg_RD_Q14 ) ) { + break; + } + } + + cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ *periodicity_index ]; + for( j = 0; j < nb_subfr; j++ ) { + for( k = 0; k < LTP_ORDER; k++ ) { + B_Q14[ j * LTP_ORDER + k ] = silk_LSHIFT( cbk_ptr_Q7[ cbk_index[ j ] * LTP_ORDER + k ], 7 ); + } + } + *sum_log_gain_Q7 = best_sum_log_gain_Q7; +} + diff --git a/TelegramClient.Opus/opus/silk/resampler.c b/TelegramClient.Opus/opus/silk/resampler.c new file mode 100755 index 0000000..374fbb3 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/resampler.c @@ -0,0 +1,215 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Matrix of resampling methods used: + * Fs_out (kHz) + * 8 12 16 24 48 + * + * 8 C UF U UF UF + * 12 AF C UF U UF + * Fs_in (kHz) 16 D AF C UF UF + * 24 AF D AF C U + * 48 AF AF AF D C + * + * C -> Copy (no resampling) + * D -> Allpass-based 2x downsampling + * U -> Allpass-based 2x upsampling + * UF -> Allpass-based 2x upsampling followed by FIR interpolation + * AF -> AR2 filter followed by FIR interpolation + */ + +#include "resampler_private.h" + +/* Tables with delay compensation values to equalize total delay for different modes */ +static const opus_int8 delay_matrix_enc[ 5 ][ 3 ] = { +/* in \ out 8 12 16 */ +/* 8 */ { 6, 0, 3 }, +/* 12 */ { 0, 7, 3 }, +/* 16 */ { 0, 1, 10 }, +/* 24 */ { 0, 2, 6 }, +/* 48 */ { 18, 10, 12 } +}; + +static const opus_int8 delay_matrix_dec[ 3 ][ 5 ] = { +/* in \ out 8 12 16 24 48 */ +/* 8 */ { 4, 0, 2, 0, 0 }, +/* 12 */ { 0, 9, 4, 7, 4 }, +/* 16 */ { 0, 3, 12, 7, 7 } +}; + +/* Simple way to make [8000, 12000, 16000, 24000, 48000] to [0, 1, 2, 3, 4] */ +#define rateID(R) ( ( ( ((R)>>12) - ((R)>16000) ) >> ((R)>24000) ) - 1 ) + +#define USE_silk_resampler_copy (0) +#define USE_silk_resampler_private_up2_HQ_wrapper (1) +#define USE_silk_resampler_private_IIR_FIR (2) +#define USE_silk_resampler_private_down_FIR (3) + +/* Initialize/reset the resampler state for a given pair of input/output sampling rates */ +opus_int silk_resampler_init( + silk_resampler_state_struct *S, /* I/O Resampler state */ + opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */ + opus_int32 Fs_Hz_out, /* I Output sampling rate (Hz) */ + opus_int forEnc /* I If 1: encoder; if 0: decoder */ +) +{ + opus_int up2x; + + /* Clear state */ + silk_memset( S, 0, sizeof( silk_resampler_state_struct ) ); + + /* Input checking */ + if( forEnc ) { + if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 && Fs_Hz_in != 24000 && Fs_Hz_in != 48000 ) || + ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 ) ) { + silk_assert( 0 ); + return -1; + } + S->inputDelay = delay_matrix_enc[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ]; + } else { + if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 ) || + ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000 ) ) { + silk_assert( 0 ); + return -1; + } + S->inputDelay = delay_matrix_dec[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ]; + } + + S->Fs_in_kHz = silk_DIV32_16( Fs_Hz_in, 1000 ); + S->Fs_out_kHz = silk_DIV32_16( Fs_Hz_out, 1000 ); + + /* Number of samples processed per batch */ + S->batchSize = S->Fs_in_kHz * RESAMPLER_MAX_BATCH_SIZE_MS; + + /* Find resampler with the right sampling ratio */ + up2x = 0; + if( Fs_Hz_out > Fs_Hz_in ) { + /* Upsample */ + if( Fs_Hz_out == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 1 */ + /* Special case: directly use 2x upsampler */ + S->resampler_function = USE_silk_resampler_private_up2_HQ_wrapper; + } else { + /* Default resampler */ + S->resampler_function = USE_silk_resampler_private_IIR_FIR; + up2x = 1; + } + } else if ( Fs_Hz_out < Fs_Hz_in ) { + /* Downsample */ + S->resampler_function = USE_silk_resampler_private_down_FIR; + if( silk_MUL( Fs_Hz_out, 4 ) == silk_MUL( Fs_Hz_in, 3 ) ) { /* Fs_out : Fs_in = 3 : 4 */ + S->FIR_Fracs = 3; + S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0; + S->Coefs = silk_Resampler_3_4_COEFS; + } else if( silk_MUL( Fs_Hz_out, 3 ) == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 3 */ + S->FIR_Fracs = 2; + S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0; + S->Coefs = silk_Resampler_2_3_COEFS; + } else if( silk_MUL( Fs_Hz_out, 2 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 2 */ + S->FIR_Fracs = 1; + S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR1; + S->Coefs = silk_Resampler_1_2_COEFS; + } else if( silk_MUL( Fs_Hz_out, 3 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 3 */ + S->FIR_Fracs = 1; + S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2; + S->Coefs = silk_Resampler_1_3_COEFS; + } else if( silk_MUL( Fs_Hz_out, 4 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 4 */ + S->FIR_Fracs = 1; + S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2; + S->Coefs = silk_Resampler_1_4_COEFS; + } else if( silk_MUL( Fs_Hz_out, 6 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 6 */ + S->FIR_Fracs = 1; + S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2; + S->Coefs = silk_Resampler_1_6_COEFS; + } else { + /* None available */ + silk_assert( 0 ); + return -1; + } + } else { + /* Input and output sampling rates are equal: copy */ + S->resampler_function = USE_silk_resampler_copy; + } + + /* Ratio of input/output samples */ + S->invRatio_Q16 = silk_LSHIFT32( silk_DIV32( silk_LSHIFT32( Fs_Hz_in, 14 + up2x ), Fs_Hz_out ), 2 ); + /* Make sure the ratio is rounded up */ + while( silk_SMULWW( S->invRatio_Q16, Fs_Hz_out ) < silk_LSHIFT32( Fs_Hz_in, up2x ) ) { + S->invRatio_Q16++; + } + + return 0; +} + +/* Resampler: convert from one sampling rate to another */ +/* Input and output sampling rate are at most 48000 Hz */ +opus_int silk_resampler( + silk_resampler_state_struct *S, /* I/O Resampler state */ + opus_int16 out[], /* O Output signal */ + const opus_int16 in[], /* I Input signal */ + opus_int32 inLen /* I Number of input samples */ +) +{ + opus_int nSamples; + + /* Need at least 1 ms of input data */ + silk_assert( inLen >= S->Fs_in_kHz ); + /* Delay can't exceed the 1 ms of buffering */ + silk_assert( S->inputDelay <= S->Fs_in_kHz ); + + nSamples = S->Fs_in_kHz - S->inputDelay; + + /* Copy to delay buffer */ + silk_memcpy( &S->delayBuf[ S->inputDelay ], in, nSamples * sizeof( opus_int16 ) ); + + switch( S->resampler_function ) { + case USE_silk_resampler_private_up2_HQ_wrapper: + silk_resampler_private_up2_HQ_wrapper( S, out, S->delayBuf, S->Fs_in_kHz ); + silk_resampler_private_up2_HQ_wrapper( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz ); + break; + case USE_silk_resampler_private_IIR_FIR: + silk_resampler_private_IIR_FIR( S, out, S->delayBuf, S->Fs_in_kHz ); + silk_resampler_private_IIR_FIR( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz ); + break; + case USE_silk_resampler_private_down_FIR: + silk_resampler_private_down_FIR( S, out, S->delayBuf, S->Fs_in_kHz ); + silk_resampler_private_down_FIR( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz ); + break; + default: + silk_memcpy( out, S->delayBuf, S->Fs_in_kHz * sizeof( opus_int16 ) ); + silk_memcpy( &out[ S->Fs_out_kHz ], &in[ nSamples ], ( inLen - S->Fs_in_kHz ) * sizeof( opus_int16 ) ); + } + + /* Copy to delay buffer */ + silk_memcpy( S->delayBuf, &in[ inLen - S->inputDelay ], S->inputDelay * sizeof( opus_int16 ) ); + + return 0; +} diff --git a/TelegramClient.Opus/opus/silk/resampler_down2.c b/TelegramClient.Opus/opus/silk/resampler_down2.c new file mode 100755 index 0000000..cec3634 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/resampler_down2.c @@ -0,0 +1,74 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" +#include "resampler_rom.h" + +/* Downsample by a factor 2 */ +void silk_resampler_down2( + opus_int32 *S, /* I/O State vector [ 2 ] */ + opus_int16 *out, /* O Output signal [ floor(len/2) ] */ + const opus_int16 *in, /* I Input signal [ len ] */ + opus_int32 inLen /* I Number of input samples */ +) +{ + opus_int32 k, len2 = silk_RSHIFT32( inLen, 1 ); + opus_int32 in32, out32, Y, X; + + silk_assert( silk_resampler_down2_0 > 0 ); + silk_assert( silk_resampler_down2_1 < 0 ); + + /* Internal variables and state are in Q10 format */ + for( k = 0; k < len2; k++ ) { + /* Convert to Q10 */ + in32 = silk_LSHIFT( (opus_int32)in[ 2 * k ], 10 ); + + /* All-pass section for even input sample */ + Y = silk_SUB32( in32, S[ 0 ] ); + X = silk_SMLAWB( Y, Y, silk_resampler_down2_1 ); + out32 = silk_ADD32( S[ 0 ], X ); + S[ 0 ] = silk_ADD32( in32, X ); + + /* Convert to Q10 */ + in32 = silk_LSHIFT( (opus_int32)in[ 2 * k + 1 ], 10 ); + + /* All-pass section for odd input sample, and add to output of previous section */ + Y = silk_SUB32( in32, S[ 1 ] ); + X = silk_SMULWB( Y, silk_resampler_down2_0 ); + out32 = silk_ADD32( out32, S[ 1 ] ); + out32 = silk_ADD32( out32, X ); + S[ 1 ] = silk_ADD32( in32, X ); + + /* Add, convert back to int16 and store to output */ + out[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32, 11 ) ); + } +} + diff --git a/TelegramClient.Opus/opus/silk/resampler_down2_3.c b/TelegramClient.Opus/opus/silk/resampler_down2_3.c new file mode 100755 index 0000000..4342614 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/resampler_down2_3.c @@ -0,0 +1,103 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" +#include "resampler_private.h" +#include "stack_alloc.h" + +#define ORDER_FIR 4 + +/* Downsample by a factor 2/3, low quality */ +void silk_resampler_down2_3( + opus_int32 *S, /* I/O State vector [ 6 ] */ + opus_int16 *out, /* O Output signal [ floor(2*inLen/3) ] */ + const opus_int16 *in, /* I Input signal [ inLen ] */ + opus_int32 inLen /* I Number of input samples */ +) +{ + opus_int32 nSamplesIn, counter, res_Q6; + VARDECL( opus_int32, buf ); + opus_int32 *buf_ptr; + SAVE_STACK; + + ALLOC( buf, RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR, opus_int32 ); + + /* Copy buffered samples to start of buffer */ + silk_memcpy( buf, S, ORDER_FIR * sizeof( opus_int32 ) ); + + /* Iterate over blocks of frameSizeIn input samples */ + while( 1 ) { + nSamplesIn = silk_min( inLen, RESAMPLER_MAX_BATCH_SIZE_IN ); + + /* Second-order AR filter (output in Q8) */ + silk_resampler_private_AR2( &S[ ORDER_FIR ], &buf[ ORDER_FIR ], in, + silk_Resampler_2_3_COEFS_LQ, nSamplesIn ); + + /* Interpolate filtered signal */ + buf_ptr = buf; + counter = nSamplesIn; + while( counter > 2 ) { + /* Inner product */ + res_Q6 = silk_SMULWB( buf_ptr[ 0 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); + + res_Q6 = silk_SMULWB( buf_ptr[ 1 ], silk_Resampler_2_3_COEFS_LQ[ 4 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], silk_Resampler_2_3_COEFS_LQ[ 5 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], silk_Resampler_2_3_COEFS_LQ[ 3 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], silk_Resampler_2_3_COEFS_LQ[ 2 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); + + buf_ptr += 3; + counter -= 3; + } + + in += nSamplesIn; + inLen -= nSamplesIn; + + if( inLen > 0 ) { + /* More iterations to do; copy last part of filtered signal to beginning of buffer */ + silk_memcpy( buf, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) ); + } else { + break; + } + } + + /* Copy last part of filtered signal to the state for the next call */ + silk_memcpy( S, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) ); + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/resampler_private.h b/TelegramClient.Opus/opus/silk/resampler_private.h new file mode 100755 index 0000000..422a7d9 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/resampler_private.h @@ -0,0 +1,88 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_RESAMPLER_PRIVATE_H +#define SILK_RESAMPLER_PRIVATE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "SigProc_FIX.h" +#include "resampler_structs.h" +#include "resampler_rom.h" + +/* Number of input samples to process in the inner loop */ +#define RESAMPLER_MAX_BATCH_SIZE_MS 10 +#define RESAMPLER_MAX_FS_KHZ 48 +#define RESAMPLER_MAX_BATCH_SIZE_IN ( RESAMPLER_MAX_BATCH_SIZE_MS * RESAMPLER_MAX_FS_KHZ ) + +/* Description: Hybrid IIR/FIR polyphase implementation of resampling */ +void silk_resampler_private_IIR_FIR( + void *SS, /* I/O Resampler state */ + opus_int16 out[], /* O Output signal */ + const opus_int16 in[], /* I Input signal */ + opus_int32 inLen /* I Number of input samples */ +); + +/* Description: Hybrid IIR/FIR polyphase implementation of resampling */ +void silk_resampler_private_down_FIR( + void *SS, /* I/O Resampler state */ + opus_int16 out[], /* O Output signal */ + const opus_int16 in[], /* I Input signal */ + opus_int32 inLen /* I Number of input samples */ +); + +/* Upsample by a factor 2, high quality */ +void silk_resampler_private_up2_HQ_wrapper( + void *SS, /* I/O Resampler state (unused) */ + opus_int16 *out, /* O Output signal [ 2 * len ] */ + const opus_int16 *in, /* I Input signal [ len ] */ + opus_int32 len /* I Number of input samples */ +); + +/* Upsample by a factor 2, high quality */ +void silk_resampler_private_up2_HQ( + opus_int32 *S, /* I/O Resampler state [ 6 ] */ + opus_int16 *out, /* O Output signal [ 2 * len ] */ + const opus_int16 *in, /* I Input signal [ len ] */ + opus_int32 len /* I Number of input samples */ +); + +/* Second order AR filter */ +void silk_resampler_private_AR2( + opus_int32 S[], /* I/O State vector [ 2 ] */ + opus_int32 out_Q8[], /* O Output signal */ + const opus_int16 in[], /* I Input signal */ + const opus_int16 A_Q14[], /* I AR coefficients, Q14 */ + opus_int32 len /* I Signal length */ +); + +#ifdef __cplusplus +} +#endif +#endif /* SILK_RESAMPLER_PRIVATE_H */ diff --git a/TelegramClient.Opus/opus/silk/resampler_private_AR2.c b/TelegramClient.Opus/opus/silk/resampler_private_AR2.c new file mode 100755 index 0000000..5fff237 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/resampler_private_AR2.c @@ -0,0 +1,55 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" +#include "resampler_private.h" + +/* Second order AR filter with single delay elements */ +void silk_resampler_private_AR2( + opus_int32 S[], /* I/O State vector [ 2 ] */ + opus_int32 out_Q8[], /* O Output signal */ + const opus_int16 in[], /* I Input signal */ + const opus_int16 A_Q14[], /* I AR coefficients, Q14 */ + opus_int32 len /* I Signal length */ +) +{ + opus_int32 k; + opus_int32 out32; + + for( k = 0; k < len; k++ ) { + out32 = silk_ADD_LSHIFT32( S[ 0 ], (opus_int32)in[ k ], 8 ); + out_Q8[ k ] = out32; + out32 = silk_LSHIFT( out32, 2 ); + S[ 0 ] = silk_SMLAWB( S[ 1 ], out32, A_Q14[ 0 ] ); + S[ 1 ] = silk_SMULWB( out32, A_Q14[ 1 ] ); + } +} + diff --git a/TelegramClient.Opus/opus/silk/resampler_private_IIR_FIR.c b/TelegramClient.Opus/opus/silk/resampler_private_IIR_FIR.c new file mode 100755 index 0000000..6b2b3a2 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/resampler_private_IIR_FIR.c @@ -0,0 +1,107 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" +#include "resampler_private.h" +#include "stack_alloc.h" + +static OPUS_INLINE opus_int16 *silk_resampler_private_IIR_FIR_INTERPOL( + opus_int16 *out, + opus_int16 *buf, + opus_int32 max_index_Q16, + opus_int32 index_increment_Q16 +) +{ + opus_int32 index_Q16, res_Q15; + opus_int16 *buf_ptr; + opus_int32 table_index; + + /* Interpolate upsampled signal and store in output array */ + for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { + table_index = silk_SMULWB( index_Q16 & 0xFFFF, 12 ); + buf_ptr = &buf[ index_Q16 >> 16 ]; + + res_Q15 = silk_SMULBB( buf_ptr[ 0 ], silk_resampler_frac_FIR_12[ table_index ][ 0 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 1 ], silk_resampler_frac_FIR_12[ table_index ][ 1 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 2 ], silk_resampler_frac_FIR_12[ table_index ][ 2 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 3 ], silk_resampler_frac_FIR_12[ table_index ][ 3 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 4 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 3 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 5 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 2 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 6 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 1 ] ); + res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 7 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 0 ] ); + *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q15, 15 ) ); + } + return out; +} +/* Upsample using a combination of allpass-based 2x upsampling and FIR interpolation */ +void silk_resampler_private_IIR_FIR( + void *SS, /* I/O Resampler state */ + opus_int16 out[], /* O Output signal */ + const opus_int16 in[], /* I Input signal */ + opus_int32 inLen /* I Number of input samples */ +) +{ + silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; + opus_int32 nSamplesIn; + opus_int32 max_index_Q16, index_increment_Q16; + VARDECL( opus_int16, buf ); + SAVE_STACK; + + ALLOC( buf, 2 * S->batchSize + RESAMPLER_ORDER_FIR_12, opus_int16 ); + + /* Copy buffered samples to start of buffer */ + silk_memcpy( buf, S->sFIR.i16, RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) ); + + /* Iterate over blocks of frameSizeIn input samples */ + index_increment_Q16 = S->invRatio_Q16; + while( 1 ) { + nSamplesIn = silk_min( inLen, S->batchSize ); + + /* Upsample 2x */ + silk_resampler_private_up2_HQ( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_12 ], in, nSamplesIn ); + + max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 + 1 ); /* + 1 because 2x upsampling */ + out = silk_resampler_private_IIR_FIR_INTERPOL( out, buf, max_index_Q16, index_increment_Q16 ); + in += nSamplesIn; + inLen -= nSamplesIn; + + if( inLen > 0 ) { + /* More iterations to do; copy last part of filtered signal to beginning of buffer */ + silk_memcpy( buf, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) ); + } else { + break; + } + } + + /* Copy last part of filtered signal to the state for the next call */ + silk_memcpy( S->sFIR.i16, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) ); + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/resampler_private_down_FIR.c b/TelegramClient.Opus/opus/silk/resampler_private_down_FIR.c new file mode 100755 index 0000000..783e42b --- /dev/null +++ b/TelegramClient.Opus/opus/silk/resampler_private_down_FIR.c @@ -0,0 +1,194 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" +#include "resampler_private.h" +#include "stack_alloc.h" + +static OPUS_INLINE opus_int16 *silk_resampler_private_down_FIR_INTERPOL( + opus_int16 *out, + opus_int32 *buf, + const opus_int16 *FIR_Coefs, + opus_int FIR_Order, + opus_int FIR_Fracs, + opus_int32 max_index_Q16, + opus_int32 index_increment_Q16 +) +{ + opus_int32 index_Q16, res_Q6; + opus_int32 *buf_ptr; + opus_int32 interpol_ind; + const opus_int16 *interpol_ptr; + + switch( FIR_Order ) { + case RESAMPLER_DOWN_ORDER_FIR0: + for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { + /* Integer part gives pointer to buffered input */ + buf_ptr = buf + silk_RSHIFT( index_Q16, 16 ); + + /* Fractional part gives interpolation coefficients */ + interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs ); + + /* Inner product */ + interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * interpol_ind ]; + res_Q6 = silk_SMULWB( buf_ptr[ 0 ], interpol_ptr[ 0 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 6 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 8 ] ); + interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * ( FIR_Fracs - 1 - interpol_ind ) ]; + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 17 ], interpol_ptr[ 0 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 16 ], interpol_ptr[ 1 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 2 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 3 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 4 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 5 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 6 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 7 ] ); + res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 9 ], interpol_ptr[ 8 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); + } + break; + case RESAMPLER_DOWN_ORDER_FIR1: + for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { + /* Integer part gives pointer to buffered input */ + buf_ptr = buf + silk_RSHIFT( index_Q16, 16 ); + + /* Inner product */ + res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 23 ] ), FIR_Coefs[ 0 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 22 ] ), FIR_Coefs[ 1 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 21 ] ), FIR_Coefs[ 2 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 20 ] ), FIR_Coefs[ 3 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 19 ] ), FIR_Coefs[ 4 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 18 ] ), FIR_Coefs[ 5 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 17 ] ), FIR_Coefs[ 6 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 16 ] ), FIR_Coefs[ 7 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 8 ], buf_ptr[ 15 ] ), FIR_Coefs[ 8 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 9 ], buf_ptr[ 14 ] ), FIR_Coefs[ 9 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 13 ] ), FIR_Coefs[ 10 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 12 ] ), FIR_Coefs[ 11 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); + } + break; + case RESAMPLER_DOWN_ORDER_FIR2: + for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { + /* Integer part gives pointer to buffered input */ + buf_ptr = buf + silk_RSHIFT( index_Q16, 16 ); + + /* Inner product */ + res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 35 ] ), FIR_Coefs[ 0 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 34 ] ), FIR_Coefs[ 1 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 33 ] ), FIR_Coefs[ 2 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 32 ] ), FIR_Coefs[ 3 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 31 ] ), FIR_Coefs[ 4 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 30 ] ), FIR_Coefs[ 5 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 29 ] ), FIR_Coefs[ 6 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 28 ] ), FIR_Coefs[ 7 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 8 ], buf_ptr[ 27 ] ), FIR_Coefs[ 8 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 9 ], buf_ptr[ 26 ] ), FIR_Coefs[ 9 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 25 ] ), FIR_Coefs[ 10 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 24 ] ), FIR_Coefs[ 11 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 12 ], buf_ptr[ 23 ] ), FIR_Coefs[ 12 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 13 ], buf_ptr[ 22 ] ), FIR_Coefs[ 13 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 14 ], buf_ptr[ 21 ] ), FIR_Coefs[ 14 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 15 ], buf_ptr[ 20 ] ), FIR_Coefs[ 15 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 16 ], buf_ptr[ 19 ] ), FIR_Coefs[ 16 ] ); + res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 17 ], buf_ptr[ 18 ] ), FIR_Coefs[ 17 ] ); + + /* Scale down, saturate and store in output array */ + *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) ); + } + break; + default: + silk_assert( 0 ); + } + return out; +} + +/* Resample with a 2nd order AR filter followed by FIR interpolation */ +void silk_resampler_private_down_FIR( + void *SS, /* I/O Resampler state */ + opus_int16 out[], /* O Output signal */ + const opus_int16 in[], /* I Input signal */ + opus_int32 inLen /* I Number of input samples */ +) +{ + silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; + opus_int32 nSamplesIn; + opus_int32 max_index_Q16, index_increment_Q16; + VARDECL( opus_int32, buf ); + const opus_int16 *FIR_Coefs; + SAVE_STACK; + + ALLOC( buf, S->batchSize + S->FIR_Order, opus_int32 ); + + /* Copy buffered samples to start of buffer */ + silk_memcpy( buf, S->sFIR.i32, S->FIR_Order * sizeof( opus_int32 ) ); + + FIR_Coefs = &S->Coefs[ 2 ]; + + /* Iterate over blocks of frameSizeIn input samples */ + index_increment_Q16 = S->invRatio_Q16; + while( 1 ) { + nSamplesIn = silk_min( inLen, S->batchSize ); + + /* Second-order AR filter (output in Q8) */ + silk_resampler_private_AR2( S->sIIR, &buf[ S->FIR_Order ], in, S->Coefs, nSamplesIn ); + + max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 ); + + /* Interpolate filtered signal */ + out = silk_resampler_private_down_FIR_INTERPOL( out, buf, FIR_Coefs, S->FIR_Order, + S->FIR_Fracs, max_index_Q16, index_increment_Q16 ); + + in += nSamplesIn; + inLen -= nSamplesIn; + + if( inLen > 1 ) { + /* More iterations to do; copy last part of filtered signal to beginning of buffer */ + silk_memcpy( buf, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) ); + } else { + break; + } + } + + /* Copy last part of filtered signal to the state for the next call */ + silk_memcpy( S->sFIR.i32, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) ); + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/resampler_private_up2_HQ.c b/TelegramClient.Opus/opus/silk/resampler_private_up2_HQ.c new file mode 100755 index 0000000..c7ec8de --- /dev/null +++ b/TelegramClient.Opus/opus/silk/resampler_private_up2_HQ.c @@ -0,0 +1,113 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" +#include "resampler_private.h" + +/* Upsample by a factor 2, high quality */ +/* Uses 2nd order allpass filters for the 2x upsampling, followed by a */ +/* notch filter just above Nyquist. */ +void silk_resampler_private_up2_HQ( + opus_int32 *S, /* I/O Resampler state [ 6 ] */ + opus_int16 *out, /* O Output signal [ 2 * len ] */ + const opus_int16 *in, /* I Input signal [ len ] */ + opus_int32 len /* I Number of input samples */ +) +{ + opus_int32 k; + opus_int32 in32, out32_1, out32_2, Y, X; + + silk_assert( silk_resampler_up2_hq_0[ 0 ] > 0 ); + silk_assert( silk_resampler_up2_hq_0[ 1 ] > 0 ); + silk_assert( silk_resampler_up2_hq_0[ 2 ] < 0 ); + silk_assert( silk_resampler_up2_hq_1[ 0 ] > 0 ); + silk_assert( silk_resampler_up2_hq_1[ 1 ] > 0 ); + silk_assert( silk_resampler_up2_hq_1[ 2 ] < 0 ); + + /* Internal variables and state are in Q10 format */ + for( k = 0; k < len; k++ ) { + /* Convert to Q10 */ + in32 = silk_LSHIFT( (opus_int32)in[ k ], 10 ); + + /* First all-pass section for even output sample */ + Y = silk_SUB32( in32, S[ 0 ] ); + X = silk_SMULWB( Y, silk_resampler_up2_hq_0[ 0 ] ); + out32_1 = silk_ADD32( S[ 0 ], X ); + S[ 0 ] = silk_ADD32( in32, X ); + + /* Second all-pass section for even output sample */ + Y = silk_SUB32( out32_1, S[ 1 ] ); + X = silk_SMULWB( Y, silk_resampler_up2_hq_0[ 1 ] ); + out32_2 = silk_ADD32( S[ 1 ], X ); + S[ 1 ] = silk_ADD32( out32_1, X ); + + /* Third all-pass section for even output sample */ + Y = silk_SUB32( out32_2, S[ 2 ] ); + X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_0[ 2 ] ); + out32_1 = silk_ADD32( S[ 2 ], X ); + S[ 2 ] = silk_ADD32( out32_2, X ); + + /* Apply gain in Q15, convert back to int16 and store to output */ + out[ 2 * k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) ); + + /* First all-pass section for odd output sample */ + Y = silk_SUB32( in32, S[ 3 ] ); + X = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 0 ] ); + out32_1 = silk_ADD32( S[ 3 ], X ); + S[ 3 ] = silk_ADD32( in32, X ); + + /* Second all-pass section for odd output sample */ + Y = silk_SUB32( out32_1, S[ 4 ] ); + X = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 1 ] ); + out32_2 = silk_ADD32( S[ 4 ], X ); + S[ 4 ] = silk_ADD32( out32_1, X ); + + /* Third all-pass section for odd output sample */ + Y = silk_SUB32( out32_2, S[ 5 ] ); + X = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_1[ 2 ] ); + out32_1 = silk_ADD32( S[ 5 ], X ); + S[ 5 ] = silk_ADD32( out32_2, X ); + + /* Apply gain in Q15, convert back to int16 and store to output */ + out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) ); + } +} + +void silk_resampler_private_up2_HQ_wrapper( + void *SS, /* I/O Resampler state (unused) */ + opus_int16 *out, /* O Output signal [ 2 * len ] */ + const opus_int16 *in, /* I Input signal [ len ] */ + opus_int32 len /* I Number of input samples */ +) +{ + silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; + silk_resampler_private_up2_HQ( S->sIIR, out, in, len ); +} diff --git a/TelegramClient.Opus/opus/silk/resampler_rom.c b/TelegramClient.Opus/opus/silk/resampler_rom.c new file mode 100755 index 0000000..2d50270 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/resampler_rom.c @@ -0,0 +1,96 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Filter coefficients for IIR/FIR polyphase resampling * + * Total size: 179 Words (358 Bytes) */ + +#include "resampler_private.h" + +/* Matlab code for the notch filter coefficients: */ +/* B = [1, 0.147, 1]; A = [1, 0.107, 0.89]; G = 0.93; freqz(G * B, A, 2^14, 16e3); axis([0, 8000, -10, 1]) */ +/* fprintf('\t%6d, %6d, %6d, %6d\n', round(B(2)*2^16), round(-A(2)*2^16), round((1-A(3))*2^16), round(G*2^15)) */ +/* const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 9634, -7012, 7209, 30474 }; */ + +/* Tables with IIR and FIR coefficients for fractional downsamplers (123 Words) */ +silk_DWORD_ALIGN const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = { + -20694, -13867, + -49, 64, 17, -157, 353, -496, 163, 11047, 22205, + -39, 6, 91, -170, 186, 23, -896, 6336, 19928, + -19, -36, 102, -89, -24, 328, -951, 2568, 15909, +}; + +silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = { + -14457, -14019, + 64, 128, -122, 36, 310, -768, 584, 9267, 17733, + 12, 128, 18, -142, 288, -117, -865, 4123, 14459, +}; + +silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR1 / 2 ] = { + 616, -14323, + -10, 39, 58, -46, -84, 120, 184, -315, -541, 1284, 5380, 9024, +}; + +silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = { + 16102, -15162, + -13, 0, 20, 26, 5, -31, -43, -4, 65, 90, 7, -157, -248, -44, 593, 1583, 2612, 3271, +}; + +silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_4_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = { + 22500, -15099, + 3, -14, -20, -15, 2, 25, 37, 25, -16, -71, -107, -79, 50, 292, 623, 982, 1288, 1464, +}; + +silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_6_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = { + 27540, -15257, + 17, 12, 8, 1, -10, -22, -30, -32, -22, 3, 44, 100, 168, 243, 317, 381, 429, 455, +}; + +silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = { + -2797, -6507, + 4697, 10739, + 1567, 8276, +}; + +/* Table with interplation fractions of 1/24, 3/24, 5/24, ... , 23/24 : 23/24 (46 Words) */ +silk_DWORD_ALIGN const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ] = { + { 189, -600, 617, 30567 }, + { 117, -159, -1070, 29704 }, + { 52, 221, -2392, 28276 }, + { -4, 529, -3350, 26341 }, + { -48, 758, -3956, 23973 }, + { -80, 905, -4235, 21254 }, + { -99, 972, -4222, 18278 }, + { -107, 967, -3957, 15143 }, + { -103, 896, -3487, 11950 }, + { -91, 773, -2865, 8798 }, + { -71, 611, -2143, 5784 }, + { -46, 425, -1375, 2996 }, +}; diff --git a/TelegramClient.Opus/opus/silk/resampler_rom.h b/TelegramClient.Opus/opus/silk/resampler_rom.h new file mode 100755 index 0000000..490b338 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/resampler_rom.h @@ -0,0 +1,68 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_FIX_RESAMPLER_ROM_H +#define SILK_FIX_RESAMPLER_ROM_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "typedef.h" +#include "resampler_structs.h" + +#define RESAMPLER_DOWN_ORDER_FIR0 18 +#define RESAMPLER_DOWN_ORDER_FIR1 24 +#define RESAMPLER_DOWN_ORDER_FIR2 36 +#define RESAMPLER_ORDER_FIR_12 8 + +/* Tables for 2x downsampler */ +static const opus_int16 silk_resampler_down2_0 = 9872; +static const opus_int16 silk_resampler_down2_1 = 39809 - 65536; + +/* Tables for 2x upsampler, high quality */ +static const opus_int16 silk_resampler_up2_hq_0[ 3 ] = { 1746, 14986, 39083 - 65536 }; +static const opus_int16 silk_resampler_up2_hq_1[ 3 ] = { 6854, 25769, 55542 - 65536 }; + +/* Tables with IIR and FIR coefficients for fractional downsamplers */ +extern const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ]; +extern const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ]; +extern const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR1 / 2 ]; +extern const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ]; +extern const opus_int16 silk_Resampler_1_4_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ]; +extern const opus_int16 silk_Resampler_1_6_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ]; +extern const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ]; + +/* Table with interplation fractions of 1/24, 3/24, ..., 23/24 */ +extern const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ]; + +#ifdef __cplusplus +} +#endif + +#endif /* SILK_FIX_RESAMPLER_ROM_H */ diff --git a/TelegramClient.Opus/opus/silk/resampler_structs.h b/TelegramClient.Opus/opus/silk/resampler_structs.h new file mode 100755 index 0000000..9e9457d --- /dev/null +++ b/TelegramClient.Opus/opus/silk/resampler_structs.h @@ -0,0 +1,60 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_RESAMPLER_STRUCTS_H +#define SILK_RESAMPLER_STRUCTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define SILK_RESAMPLER_MAX_FIR_ORDER 36 +#define SILK_RESAMPLER_MAX_IIR_ORDER 6 + +typedef struct _silk_resampler_state_struct{ + opus_int32 sIIR[ SILK_RESAMPLER_MAX_IIR_ORDER ]; /* this must be the first element of this struct */ + union{ + opus_int32 i32[ SILK_RESAMPLER_MAX_FIR_ORDER ]; + opus_int16 i16[ SILK_RESAMPLER_MAX_FIR_ORDER ]; + } sFIR; + opus_int16 delayBuf[ 48 ]; + opus_int resampler_function; + opus_int batchSize; + opus_int32 invRatio_Q16; + opus_int FIR_Order; + opus_int FIR_Fracs; + opus_int Fs_in_kHz; + opus_int Fs_out_kHz; + opus_int inputDelay; + const opus_int16 *Coefs; +} silk_resampler_state_struct; + +#ifdef __cplusplus +} +#endif +#endif /* SILK_RESAMPLER_STRUCTS_H */ + diff --git a/TelegramClient.Opus/opus/silk/shell_coder.c b/TelegramClient.Opus/opus/silk/shell_coder.c new file mode 100755 index 0000000..796f57d --- /dev/null +++ b/TelegramClient.Opus/opus/silk/shell_coder.c @@ -0,0 +1,151 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* shell coder; pulse-subframe length is hardcoded */ + +static OPUS_INLINE void combine_pulses( + opus_int *out, /* O combined pulses vector [len] */ + const opus_int *in, /* I input vector [2 * len] */ + const opus_int len /* I number of OUTPUT samples */ +) +{ + opus_int k; + for( k = 0; k < len; k++ ) { + out[ k ] = in[ 2 * k ] + in[ 2 * k + 1 ]; + } +} + +static OPUS_INLINE void encode_split( + ec_enc *psRangeEnc, /* I/O compressor data structure */ + const opus_int p_child1, /* I pulse amplitude of first child subframe */ + const opus_int p, /* I pulse amplitude of current subframe */ + const opus_uint8 *shell_table /* I table of shell cdfs */ +) +{ + if( p > 0 ) { + ec_enc_icdf( psRangeEnc, p_child1, &shell_table[ silk_shell_code_table_offsets[ p ] ], 8 ); + } +} + +static OPUS_INLINE void decode_split( + opus_int *p_child1, /* O pulse amplitude of first child subframe */ + opus_int *p_child2, /* O pulse amplitude of second child subframe */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + const opus_int p, /* I pulse amplitude of current subframe */ + const opus_uint8 *shell_table /* I table of shell cdfs */ +) +{ + if( p > 0 ) { + p_child1[ 0 ] = ec_dec_icdf( psRangeDec, &shell_table[ silk_shell_code_table_offsets[ p ] ], 8 ); + p_child2[ 0 ] = p - p_child1[ 0 ]; + } else { + p_child1[ 0 ] = 0; + p_child2[ 0 ] = 0; + } +} + +/* Shell encoder, operates on one shell code frame of 16 pulses */ +void silk_shell_encoder( + ec_enc *psRangeEnc, /* I/O compressor data structure */ + const opus_int *pulses0 /* I data: nonnegative pulse amplitudes */ +) +{ + opus_int pulses1[ 8 ], pulses2[ 4 ], pulses3[ 2 ], pulses4[ 1 ]; + + /* this function operates on one shell code frame of 16 pulses */ + silk_assert( SHELL_CODEC_FRAME_LENGTH == 16 ); + + /* tree representation per pulse-subframe */ + combine_pulses( pulses1, pulses0, 8 ); + combine_pulses( pulses2, pulses1, 4 ); + combine_pulses( pulses3, pulses2, 2 ); + combine_pulses( pulses4, pulses3, 1 ); + + encode_split( psRangeEnc, pulses3[ 0 ], pulses4[ 0 ], silk_shell_code_table3 ); + + encode_split( psRangeEnc, pulses2[ 0 ], pulses3[ 0 ], silk_shell_code_table2 ); + + encode_split( psRangeEnc, pulses1[ 0 ], pulses2[ 0 ], silk_shell_code_table1 ); + encode_split( psRangeEnc, pulses0[ 0 ], pulses1[ 0 ], silk_shell_code_table0 ); + encode_split( psRangeEnc, pulses0[ 2 ], pulses1[ 1 ], silk_shell_code_table0 ); + + encode_split( psRangeEnc, pulses1[ 2 ], pulses2[ 1 ], silk_shell_code_table1 ); + encode_split( psRangeEnc, pulses0[ 4 ], pulses1[ 2 ], silk_shell_code_table0 ); + encode_split( psRangeEnc, pulses0[ 6 ], pulses1[ 3 ], silk_shell_code_table0 ); + + encode_split( psRangeEnc, pulses2[ 2 ], pulses3[ 1 ], silk_shell_code_table2 ); + + encode_split( psRangeEnc, pulses1[ 4 ], pulses2[ 2 ], silk_shell_code_table1 ); + encode_split( psRangeEnc, pulses0[ 8 ], pulses1[ 4 ], silk_shell_code_table0 ); + encode_split( psRangeEnc, pulses0[ 10 ], pulses1[ 5 ], silk_shell_code_table0 ); + + encode_split( psRangeEnc, pulses1[ 6 ], pulses2[ 3 ], silk_shell_code_table1 ); + encode_split( psRangeEnc, pulses0[ 12 ], pulses1[ 6 ], silk_shell_code_table0 ); + encode_split( psRangeEnc, pulses0[ 14 ], pulses1[ 7 ], silk_shell_code_table0 ); +} + + +/* Shell decoder, operates on one shell code frame of 16 pulses */ +void silk_shell_decoder( + opus_int *pulses0, /* O data: nonnegative pulse amplitudes */ + ec_dec *psRangeDec, /* I/O Compressor data structure */ + const opus_int pulses4 /* I number of pulses per pulse-subframe */ +) +{ + opus_int pulses3[ 2 ], pulses2[ 4 ], pulses1[ 8 ]; + + /* this function operates on one shell code frame of 16 pulses */ + silk_assert( SHELL_CODEC_FRAME_LENGTH == 16 ); + + decode_split( &pulses3[ 0 ], &pulses3[ 1 ], psRangeDec, pulses4, silk_shell_code_table3 ); + + decode_split( &pulses2[ 0 ], &pulses2[ 1 ], psRangeDec, pulses3[ 0 ], silk_shell_code_table2 ); + + decode_split( &pulses1[ 0 ], &pulses1[ 1 ], psRangeDec, pulses2[ 0 ], silk_shell_code_table1 ); + decode_split( &pulses0[ 0 ], &pulses0[ 1 ], psRangeDec, pulses1[ 0 ], silk_shell_code_table0 ); + decode_split( &pulses0[ 2 ], &pulses0[ 3 ], psRangeDec, pulses1[ 1 ], silk_shell_code_table0 ); + + decode_split( &pulses1[ 2 ], &pulses1[ 3 ], psRangeDec, pulses2[ 1 ], silk_shell_code_table1 ); + decode_split( &pulses0[ 4 ], &pulses0[ 5 ], psRangeDec, pulses1[ 2 ], silk_shell_code_table0 ); + decode_split( &pulses0[ 6 ], &pulses0[ 7 ], psRangeDec, pulses1[ 3 ], silk_shell_code_table0 ); + + decode_split( &pulses2[ 2 ], &pulses2[ 3 ], psRangeDec, pulses3[ 1 ], silk_shell_code_table2 ); + + decode_split( &pulses1[ 4 ], &pulses1[ 5 ], psRangeDec, pulses2[ 2 ], silk_shell_code_table1 ); + decode_split( &pulses0[ 8 ], &pulses0[ 9 ], psRangeDec, pulses1[ 4 ], silk_shell_code_table0 ); + decode_split( &pulses0[ 10 ], &pulses0[ 11 ], psRangeDec, pulses1[ 5 ], silk_shell_code_table0 ); + + decode_split( &pulses1[ 6 ], &pulses1[ 7 ], psRangeDec, pulses2[ 3 ], silk_shell_code_table1 ); + decode_split( &pulses0[ 12 ], &pulses0[ 13 ], psRangeDec, pulses1[ 6 ], silk_shell_code_table0 ); + decode_split( &pulses0[ 14 ], &pulses0[ 15 ], psRangeDec, pulses1[ 7 ], silk_shell_code_table0 ); +} diff --git a/TelegramClient.Opus/opus/silk/sigm_Q15.c b/TelegramClient.Opus/opus/silk/sigm_Q15.c new file mode 100755 index 0000000..3c507d2 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/sigm_Q15.c @@ -0,0 +1,76 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Approximate sigmoid function */ + +#include "SigProc_FIX.h" + +/* fprintf(1, '%d, ', round(1024 * ([1 ./ (1 + exp(-(1:5))), 1] - 1 ./ (1 + exp(-(0:5)))))); */ +static const opus_int32 sigm_LUT_slope_Q10[ 6 ] = { + 237, 153, 73, 30, 12, 7 +}; +/* fprintf(1, '%d, ', round(32767 * 1 ./ (1 + exp(-(0:5))))); */ +static const opus_int32 sigm_LUT_pos_Q15[ 6 ] = { + 16384, 23955, 28861, 31213, 32178, 32548 +}; +/* fprintf(1, '%d, ', round(32767 * 1 ./ (1 + exp((0:5))))); */ +static const opus_int32 sigm_LUT_neg_Q15[ 6 ] = { + 16384, 8812, 3906, 1554, 589, 219 +}; + +opus_int silk_sigm_Q15( + opus_int in_Q5 /* I */ +) +{ + opus_int ind; + + if( in_Q5 < 0 ) { + /* Negative input */ + in_Q5 = -in_Q5; + if( in_Q5 >= 6 * 32 ) { + return 0; /* Clip */ + } else { + /* Linear interpolation of look up table */ + ind = silk_RSHIFT( in_Q5, 5 ); + return( sigm_LUT_neg_Q15[ ind ] - silk_SMULBB( sigm_LUT_slope_Q10[ ind ], in_Q5 & 0x1F ) ); + } + } else { + /* Positive input */ + if( in_Q5 >= 6 * 32 ) { + return 32767; /* clip */ + } else { + /* Linear interpolation of look up table */ + ind = silk_RSHIFT( in_Q5, 5 ); + return( sigm_LUT_pos_Q15[ ind ] + silk_SMULBB( sigm_LUT_slope_Q10[ ind ], in_Q5 & 0x1F ) ); + } + } +} + diff --git a/TelegramClient.Opus/opus/silk/sort.c b/TelegramClient.Opus/opus/silk/sort.c new file mode 100755 index 0000000..8670dbd --- /dev/null +++ b/TelegramClient.Opus/opus/silk/sort.c @@ -0,0 +1,154 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Insertion sort (fast for already almost sorted arrays): */ +/* Best case: O(n) for an already sorted array */ +/* Worst case: O(n^2) for an inversely sorted array */ +/* */ +/* Shell short: http://en.wikipedia.org/wiki/Shell_sort */ + +#include "SigProc_FIX.h" + +void silk_insertion_sort_increasing( + opus_int32 *a, /* I/O Unsorted / Sorted vector */ + opus_int *idx, /* O Index vector for the sorted elements */ + const opus_int L, /* I Vector length */ + const opus_int K /* I Number of correctly sorted positions */ +) +{ + opus_int32 value; + opus_int i, j; + + /* Safety checks */ + silk_assert( K > 0 ); + silk_assert( L > 0 ); + silk_assert( L >= K ); + + /* Write start indices in index vector */ + for( i = 0; i < K; i++ ) { + idx[ i ] = i; + } + + /* Sort vector elements by value, increasing order */ + for( i = 1; i < K; i++ ) { + value = a[ i ]; + for( j = i - 1; ( j >= 0 ) && ( value < a[ j ] ); j-- ) { + a[ j + 1 ] = a[ j ]; /* Shift value */ + idx[ j + 1 ] = idx[ j ]; /* Shift index */ + } + a[ j + 1 ] = value; /* Write value */ + idx[ j + 1 ] = i; /* Write index */ + } + + /* If less than L values are asked for, check the remaining values, */ + /* but only spend CPU to ensure that the K first values are correct */ + for( i = K; i < L; i++ ) { + value = a[ i ]; + if( value < a[ K - 1 ] ) { + for( j = K - 2; ( j >= 0 ) && ( value < a[ j ] ); j-- ) { + a[ j + 1 ] = a[ j ]; /* Shift value */ + idx[ j + 1 ] = idx[ j ]; /* Shift index */ + } + a[ j + 1 ] = value; /* Write value */ + idx[ j + 1 ] = i; /* Write index */ + } + } +} + +#ifdef FIXED_POINT +/* This function is only used by the fixed-point build */ +void silk_insertion_sort_decreasing_int16( + opus_int16 *a, /* I/O Unsorted / Sorted vector */ + opus_int *idx, /* O Index vector for the sorted elements */ + const opus_int L, /* I Vector length */ + const opus_int K /* I Number of correctly sorted positions */ +) +{ + opus_int i, j; + opus_int value; + + /* Safety checks */ + silk_assert( K > 0 ); + silk_assert( L > 0 ); + silk_assert( L >= K ); + + /* Write start indices in index vector */ + for( i = 0; i < K; i++ ) { + idx[ i ] = i; + } + + /* Sort vector elements by value, decreasing order */ + for( i = 1; i < K; i++ ) { + value = a[ i ]; + for( j = i - 1; ( j >= 0 ) && ( value > a[ j ] ); j-- ) { + a[ j + 1 ] = a[ j ]; /* Shift value */ + idx[ j + 1 ] = idx[ j ]; /* Shift index */ + } + a[ j + 1 ] = value; /* Write value */ + idx[ j + 1 ] = i; /* Write index */ + } + + /* If less than L values are asked for, check the remaining values, */ + /* but only spend CPU to ensure that the K first values are correct */ + for( i = K; i < L; i++ ) { + value = a[ i ]; + if( value > a[ K - 1 ] ) { + for( j = K - 2; ( j >= 0 ) && ( value > a[ j ] ); j-- ) { + a[ j + 1 ] = a[ j ]; /* Shift value */ + idx[ j + 1 ] = idx[ j ]; /* Shift index */ + } + a[ j + 1 ] = value; /* Write value */ + idx[ j + 1 ] = i; /* Write index */ + } + } +} +#endif + +void silk_insertion_sort_increasing_all_values_int16( + opus_int16 *a, /* I/O Unsorted / Sorted vector */ + const opus_int L /* I Vector length */ +) +{ + opus_int value; + opus_int i, j; + + /* Safety checks */ + silk_assert( L > 0 ); + + /* Sort vector elements by value, increasing order */ + for( i = 1; i < L; i++ ) { + value = a[ i ]; + for( j = i - 1; ( j >= 0 ) && ( value < a[ j ] ); j-- ) { + a[ j + 1 ] = a[ j ]; /* Shift value */ + } + a[ j + 1 ] = value; /* Write value */ + } +} diff --git a/TelegramClient.Opus/opus/silk/stereo_LR_to_MS.c b/TelegramClient.Opus/opus/silk/stereo_LR_to_MS.c new file mode 100755 index 0000000..42906e6 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/stereo_LR_to_MS.c @@ -0,0 +1,229 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" +#include "stack_alloc.h" + +/* Convert Left/Right stereo signal to adaptive Mid/Side representation */ +void silk_stereo_LR_to_MS( + stereo_enc_state *state, /* I/O State */ + opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ + opus_int16 x2[], /* I/O Right input signal, becomes side signal */ + opus_int8 ix[ 2 ][ 3 ], /* O Quantization indices */ + opus_int8 *mid_only_flag, /* O Flag: only mid signal coded */ + opus_int32 mid_side_rates_bps[], /* O Bitrates for mid and side signals */ + opus_int32 total_rate_bps, /* I Total bitrate */ + opus_int prev_speech_act_Q8, /* I Speech activity level in previous frame */ + opus_int toMono, /* I Last frame before a stereo->mono transition */ + opus_int fs_kHz, /* I Sample rate (kHz) */ + opus_int frame_length /* I Number of samples */ +) +{ + opus_int n, is10msFrame, denom_Q16, delta0_Q13, delta1_Q13; + opus_int32 sum, diff, smooth_coef_Q16, pred_Q13[ 2 ], pred0_Q13, pred1_Q13; + opus_int32 LP_ratio_Q14, HP_ratio_Q14, frac_Q16, frac_3_Q16, min_mid_rate_bps, width_Q14, w_Q24, deltaw_Q24; + VARDECL( opus_int16, side ); + VARDECL( opus_int16, LP_mid ); + VARDECL( opus_int16, HP_mid ); + VARDECL( opus_int16, LP_side ); + VARDECL( opus_int16, HP_side ); + opus_int16 *mid = &x1[ -2 ]; + SAVE_STACK; + + ALLOC( side, frame_length + 2, opus_int16 ); + /* Convert to basic mid/side signals */ + for( n = 0; n < frame_length + 2; n++ ) { + sum = x1[ n - 2 ] + (opus_int32)x2[ n - 2 ]; + diff = x1[ n - 2 ] - (opus_int32)x2[ n - 2 ]; + mid[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum, 1 ); + side[ n ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( diff, 1 ) ); + } + + /* Buffering */ + silk_memcpy( mid, state->sMid, 2 * sizeof( opus_int16 ) ); + silk_memcpy( side, state->sSide, 2 * sizeof( opus_int16 ) ); + silk_memcpy( state->sMid, &mid[ frame_length ], 2 * sizeof( opus_int16 ) ); + silk_memcpy( state->sSide, &side[ frame_length ], 2 * sizeof( opus_int16 ) ); + + /* LP and HP filter mid signal */ + ALLOC( LP_mid, frame_length, opus_int16 ); + ALLOC( HP_mid, frame_length, opus_int16 ); + for( n = 0; n < frame_length; n++ ) { + sum = silk_RSHIFT_ROUND( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 2 ); + LP_mid[ n ] = sum; + HP_mid[ n ] = mid[ n + 1 ] - sum; + } + + /* LP and HP filter side signal */ + ALLOC( LP_side, frame_length, opus_int16 ); + ALLOC( HP_side, frame_length, opus_int16 ); + for( n = 0; n < frame_length; n++ ) { + sum = silk_RSHIFT_ROUND( silk_ADD_LSHIFT( side[ n ] + side[ n + 2 ], side[ n + 1 ], 1 ), 2 ); + LP_side[ n ] = sum; + HP_side[ n ] = side[ n + 1 ] - sum; + } + + /* Find energies and predictors */ + is10msFrame = frame_length == 10 * fs_kHz; + smooth_coef_Q16 = is10msFrame ? + SILK_FIX_CONST( STEREO_RATIO_SMOOTH_COEF / 2, 16 ) : + SILK_FIX_CONST( STEREO_RATIO_SMOOTH_COEF, 16 ); + smooth_coef_Q16 = silk_SMULWB( silk_SMULBB( prev_speech_act_Q8, prev_speech_act_Q8 ), smooth_coef_Q16 ); + + pred_Q13[ 0 ] = silk_stereo_find_predictor( &LP_ratio_Q14, LP_mid, LP_side, &state->mid_side_amp_Q0[ 0 ], frame_length, smooth_coef_Q16 ); + pred_Q13[ 1 ] = silk_stereo_find_predictor( &HP_ratio_Q14, HP_mid, HP_side, &state->mid_side_amp_Q0[ 2 ], frame_length, smooth_coef_Q16 ); + /* Ratio of the norms of residual and mid signals */ + frac_Q16 = silk_SMLABB( HP_ratio_Q14, LP_ratio_Q14, 3 ); + frac_Q16 = silk_min( frac_Q16, SILK_FIX_CONST( 1, 16 ) ); + + /* Determine bitrate distribution between mid and side, and possibly reduce stereo width */ + total_rate_bps -= is10msFrame ? 1200 : 600; /* Subtract approximate bitrate for coding stereo parameters */ + if( total_rate_bps < 1 ) { + total_rate_bps = 1; + } + min_mid_rate_bps = silk_SMLABB( 2000, fs_kHz, 900 ); + silk_assert( min_mid_rate_bps < 32767 ); + /* Default bitrate distribution: 8 parts for Mid and (5+3*frac) parts for Side. so: mid_rate = ( 8 / ( 13 + 3 * frac ) ) * total_ rate */ + frac_3_Q16 = silk_MUL( 3, frac_Q16 ); + mid_side_rates_bps[ 0 ] = silk_DIV32_varQ( total_rate_bps, SILK_FIX_CONST( 8 + 5, 16 ) + frac_3_Q16, 16+3 ); + /* If Mid bitrate below minimum, reduce stereo width */ + if( mid_side_rates_bps[ 0 ] < min_mid_rate_bps ) { + mid_side_rates_bps[ 0 ] = min_mid_rate_bps; + mid_side_rates_bps[ 1 ] = total_rate_bps - mid_side_rates_bps[ 0 ]; + /* width = 4 * ( 2 * side_rate - min_rate ) / ( ( 1 + 3 * frac ) * min_rate ) */ + width_Q14 = silk_DIV32_varQ( silk_LSHIFT( mid_side_rates_bps[ 1 ], 1 ) - min_mid_rate_bps, + silk_SMULWB( SILK_FIX_CONST( 1, 16 ) + frac_3_Q16, min_mid_rate_bps ), 14+2 ); + width_Q14 = silk_LIMIT( width_Q14, 0, SILK_FIX_CONST( 1, 14 ) ); + } else { + mid_side_rates_bps[ 1 ] = total_rate_bps - mid_side_rates_bps[ 0 ]; + width_Q14 = SILK_FIX_CONST( 1, 14 ); + } + + /* Smoother */ + state->smth_width_Q14 = (opus_int16)silk_SMLAWB( state->smth_width_Q14, width_Q14 - state->smth_width_Q14, smooth_coef_Q16 ); + + /* At very low bitrates or for inputs that are nearly amplitude panned, switch to panned-mono coding */ + *mid_only_flag = 0; + if( toMono ) { + /* Last frame before stereo->mono transition; collapse stereo width */ + width_Q14 = 0; + pred_Q13[ 0 ] = 0; + pred_Q13[ 1 ] = 0; + silk_stereo_quant_pred( pred_Q13, ix ); + } else if( state->width_prev_Q14 == 0 && + ( 8 * total_rate_bps < 13 * min_mid_rate_bps || silk_SMULWB( frac_Q16, state->smth_width_Q14 ) < SILK_FIX_CONST( 0.05, 14 ) ) ) + { + /* Code as panned-mono; previous frame already had zero width */ + /* Scale down and quantize predictors */ + pred_Q13[ 0 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); + pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); + silk_stereo_quant_pred( pred_Q13, ix ); + /* Collapse stereo width */ + width_Q14 = 0; + pred_Q13[ 0 ] = 0; + pred_Q13[ 1 ] = 0; + mid_side_rates_bps[ 0 ] = total_rate_bps; + mid_side_rates_bps[ 1 ] = 0; + *mid_only_flag = 1; + } else if( state->width_prev_Q14 != 0 && + ( 8 * total_rate_bps < 11 * min_mid_rate_bps || silk_SMULWB( frac_Q16, state->smth_width_Q14 ) < SILK_FIX_CONST( 0.02, 14 ) ) ) + { + /* Transition to zero-width stereo */ + /* Scale down and quantize predictors */ + pred_Q13[ 0 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); + pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); + silk_stereo_quant_pred( pred_Q13, ix ); + /* Collapse stereo width */ + width_Q14 = 0; + pred_Q13[ 0 ] = 0; + pred_Q13[ 1 ] = 0; + } else if( state->smth_width_Q14 > SILK_FIX_CONST( 0.95, 14 ) ) { + /* Full-width stereo coding */ + silk_stereo_quant_pred( pred_Q13, ix ); + width_Q14 = SILK_FIX_CONST( 1, 14 ); + } else { + /* Reduced-width stereo coding; scale down and quantize predictors */ + pred_Q13[ 0 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 0 ] ), 14 ); + pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); + silk_stereo_quant_pred( pred_Q13, ix ); + width_Q14 = state->smth_width_Q14; + } + + /* Make sure to keep on encoding until the tapered output has been transmitted */ + if( *mid_only_flag == 1 ) { + state->silent_side_len += frame_length - STEREO_INTERP_LEN_MS * fs_kHz; + if( state->silent_side_len < LA_SHAPE_MS * fs_kHz ) { + *mid_only_flag = 0; + } else { + /* Limit to avoid wrapping around */ + state->silent_side_len = 10000; + } + } else { + state->silent_side_len = 0; + } + + if( *mid_only_flag == 0 && mid_side_rates_bps[ 1 ] < 1 ) { + mid_side_rates_bps[ 1 ] = 1; + mid_side_rates_bps[ 0 ] = silk_max_int( 1, total_rate_bps - mid_side_rates_bps[ 1 ]); + } + + /* Interpolate predictors and subtract prediction from side channel */ + pred0_Q13 = -state->pred_prev_Q13[ 0 ]; + pred1_Q13 = -state->pred_prev_Q13[ 1 ]; + w_Q24 = silk_LSHIFT( state->width_prev_Q14, 10 ); + denom_Q16 = silk_DIV32_16( (opus_int32)1 << 16, STEREO_INTERP_LEN_MS * fs_kHz ); + delta0_Q13 = -silk_RSHIFT_ROUND( silk_SMULBB( pred_Q13[ 0 ] - state->pred_prev_Q13[ 0 ], denom_Q16 ), 16 ); + delta1_Q13 = -silk_RSHIFT_ROUND( silk_SMULBB( pred_Q13[ 1 ] - state->pred_prev_Q13[ 1 ], denom_Q16 ), 16 ); + deltaw_Q24 = silk_LSHIFT( silk_SMULWB( width_Q14 - state->width_prev_Q14, denom_Q16 ), 10 ); + for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) { + pred0_Q13 += delta0_Q13; + pred1_Q13 += delta1_Q13; + w_Q24 += deltaw_Q24; + sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ + sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + x2[ n - 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); + } + + pred0_Q13 = -pred_Q13[ 0 ]; + pred1_Q13 = -pred_Q13[ 1 ]; + w_Q24 = silk_LSHIFT( width_Q14, 10 ); + for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { + sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 ); /* Q8 */ + sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)mid[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + x2[ n - 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); + } + state->pred_prev_Q13[ 0 ] = (opus_int16)pred_Q13[ 0 ]; + state->pred_prev_Q13[ 1 ] = (opus_int16)pred_Q13[ 1 ]; + state->width_prev_Q14 = (opus_int16)width_Q14; + RESTORE_STACK; +} diff --git a/TelegramClient.Opus/opus/silk/stereo_MS_to_LR.c b/TelegramClient.Opus/opus/silk/stereo_MS_to_LR.c new file mode 100755 index 0000000..62521a4 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/stereo_MS_to_LR.c @@ -0,0 +1,85 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Convert adaptive Mid/Side representation to Left/Right stereo signal */ +void silk_stereo_MS_to_LR( + stereo_dec_state *state, /* I/O State */ + opus_int16 x1[], /* I/O Left input signal, becomes mid signal */ + opus_int16 x2[], /* I/O Right input signal, becomes side signal */ + const opus_int32 pred_Q13[], /* I Predictors */ + opus_int fs_kHz, /* I Samples rate (kHz) */ + opus_int frame_length /* I Number of samples */ +) +{ + opus_int n, denom_Q16, delta0_Q13, delta1_Q13; + opus_int32 sum, diff, pred0_Q13, pred1_Q13; + + /* Buffering */ + silk_memcpy( x1, state->sMid, 2 * sizeof( opus_int16 ) ); + silk_memcpy( x2, state->sSide, 2 * sizeof( opus_int16 ) ); + silk_memcpy( state->sMid, &x1[ frame_length ], 2 * sizeof( opus_int16 ) ); + silk_memcpy( state->sSide, &x2[ frame_length ], 2 * sizeof( opus_int16 ) ); + + /* Interpolate predictors and add prediction to side channel */ + pred0_Q13 = state->pred_prev_Q13[ 0 ]; + pred1_Q13 = state->pred_prev_Q13[ 1 ]; + denom_Q16 = silk_DIV32_16( (opus_int32)1 << 16, STEREO_INTERP_LEN_MS * fs_kHz ); + delta0_Q13 = silk_RSHIFT_ROUND( silk_SMULBB( pred_Q13[ 0 ] - state->pred_prev_Q13[ 0 ], denom_Q16 ), 16 ); + delta1_Q13 = silk_RSHIFT_ROUND( silk_SMULBB( pred_Q13[ 1 ] - state->pred_prev_Q13[ 1 ], denom_Q16 ), 16 ); + for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) { + pred0_Q13 += delta0_Q13; + pred1_Q13 += delta1_Q13; + sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ + sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); + } + pred0_Q13 = pred_Q13[ 0 ]; + pred1_Q13 = pred_Q13[ 1 ]; + for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) { + sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 ); /* Q11 */ + sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 ); /* Q8 */ + sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 ); /* Q8 */ + x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) ); + } + state->pred_prev_Q13[ 0 ] = pred_Q13[ 0 ]; + state->pred_prev_Q13[ 1 ] = pred_Q13[ 1 ]; + + /* Convert to left/right signals */ + for( n = 0; n < frame_length; n++ ) { + sum = x1[ n + 1 ] + (opus_int32)x2[ n + 1 ]; + diff = x1[ n + 1 ] - (opus_int32)x2[ n + 1 ]; + x1[ n + 1 ] = (opus_int16)silk_SAT16( sum ); + x2[ n + 1 ] = (opus_int16)silk_SAT16( diff ); + } +} diff --git a/TelegramClient.Opus/opus/silk/stereo_decode_pred.c b/TelegramClient.Opus/opus/silk/stereo_decode_pred.c new file mode 100755 index 0000000..56ba392 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/stereo_decode_pred.c @@ -0,0 +1,73 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Decode mid/side predictors */ +void silk_stereo_decode_pred( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int32 pred_Q13[] /* O Predictors */ +) +{ + opus_int n, ix[ 2 ][ 3 ]; + opus_int32 low_Q13, step_Q13; + + /* Entropy decoding */ + n = ec_dec_icdf( psRangeDec, silk_stereo_pred_joint_iCDF, 8 ); + ix[ 0 ][ 2 ] = silk_DIV32_16( n, 5 ); + ix[ 1 ][ 2 ] = n - 5 * ix[ 0 ][ 2 ]; + for( n = 0; n < 2; n++ ) { + ix[ n ][ 0 ] = ec_dec_icdf( psRangeDec, silk_uniform3_iCDF, 8 ); + ix[ n ][ 1 ] = ec_dec_icdf( psRangeDec, silk_uniform5_iCDF, 8 ); + } + + /* Dequantize */ + for( n = 0; n < 2; n++ ) { + ix[ n ][ 0 ] += 3 * ix[ n ][ 2 ]; + low_Q13 = silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] ]; + step_Q13 = silk_SMULWB( silk_stereo_pred_quant_Q13[ ix[ n ][ 0 ] + 1 ] - low_Q13, + SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) ); + pred_Q13[ n ] = silk_SMLABB( low_Q13, step_Q13, 2 * ix[ n ][ 1 ] + 1 ); + } + + /* Subtract second from first predictor (helps when actually applying these) */ + pred_Q13[ 0 ] -= pred_Q13[ 1 ]; +} + +/* Decode mid-only flag */ +void silk_stereo_decode_mid_only( + ec_dec *psRangeDec, /* I/O Compressor data structure */ + opus_int *decode_only_mid /* O Flag that only mid channel has been coded */ +) +{ + /* Decode flag that only mid channel is coded */ + *decode_only_mid = ec_dec_icdf( psRangeDec, silk_stereo_only_code_mid_iCDF, 8 ); +} diff --git a/TelegramClient.Opus/opus/silk/stereo_encode_pred.c b/TelegramClient.Opus/opus/silk/stereo_encode_pred.c new file mode 100755 index 0000000..e6dd195 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/stereo_encode_pred.c @@ -0,0 +1,62 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Entropy code the mid/side quantization indices */ +void silk_stereo_encode_pred( + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int8 ix[ 2 ][ 3 ] /* I Quantization indices */ +) +{ + opus_int n; + + /* Entropy coding */ + n = 5 * ix[ 0 ][ 2 ] + ix[ 1 ][ 2 ]; + silk_assert( n < 25 ); + ec_enc_icdf( psRangeEnc, n, silk_stereo_pred_joint_iCDF, 8 ); + for( n = 0; n < 2; n++ ) { + silk_assert( ix[ n ][ 0 ] < 3 ); + silk_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS ); + ec_enc_icdf( psRangeEnc, ix[ n ][ 0 ], silk_uniform3_iCDF, 8 ); + ec_enc_icdf( psRangeEnc, ix[ n ][ 1 ], silk_uniform5_iCDF, 8 ); + } +} + +/* Entropy code the mid-only flag */ +void silk_stereo_encode_mid_only( + ec_enc *psRangeEnc, /* I/O Compressor data structure */ + opus_int8 mid_only_flag +) +{ + /* Encode flag that only mid channel is coded */ + ec_enc_icdf( psRangeEnc, mid_only_flag, silk_stereo_only_code_mid_iCDF, 8 ); +} diff --git a/TelegramClient.Opus/opus/silk/stereo_find_predictor.c b/TelegramClient.Opus/opus/silk/stereo_find_predictor.c new file mode 100755 index 0000000..e30e90b --- /dev/null +++ b/TelegramClient.Opus/opus/silk/stereo_find_predictor.c @@ -0,0 +1,79 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Find least-squares prediction gain for one signal based on another and quantize it */ +opus_int32 silk_stereo_find_predictor( /* O Returns predictor in Q13 */ + opus_int32 *ratio_Q14, /* O Ratio of residual and mid energies */ + const opus_int16 x[], /* I Basis signal */ + const opus_int16 y[], /* I Target signal */ + opus_int32 mid_res_amp_Q0[], /* I/O Smoothed mid, residual norms */ + opus_int length, /* I Number of samples */ + opus_int smooth_coef_Q16 /* I Smoothing coefficient */ +) +{ + opus_int scale, scale1, scale2; + opus_int32 nrgx, nrgy, corr, pred_Q13, pred2_Q10; + + /* Find predictor */ + silk_sum_sqr_shift( &nrgx, &scale1, x, length ); + silk_sum_sqr_shift( &nrgy, &scale2, y, length ); + scale = silk_max_int( scale1, scale2 ); + scale = scale + ( scale & 1 ); /* make even */ + nrgy = silk_RSHIFT32( nrgy, scale - scale2 ); + nrgx = silk_RSHIFT32( nrgx, scale - scale1 ); + nrgx = silk_max_int( nrgx, 1 ); + corr = silk_inner_prod_aligned_scale( x, y, scale, length ); + pred_Q13 = silk_DIV32_varQ( corr, nrgx, 13 ); + pred_Q13 = silk_LIMIT( pred_Q13, -(1 << 14), 1 << 14 ); + pred2_Q10 = silk_SMULWB( pred_Q13, pred_Q13 ); + + /* Faster update for signals with large prediction parameters */ + smooth_coef_Q16 = (opus_int)silk_max_int( smooth_coef_Q16, silk_abs( pred2_Q10 ) ); + + /* Smoothed mid and residual norms */ + silk_assert( smooth_coef_Q16 < 32768 ); + scale = silk_RSHIFT( scale, 1 ); + mid_res_amp_Q0[ 0 ] = silk_SMLAWB( mid_res_amp_Q0[ 0 ], silk_LSHIFT( silk_SQRT_APPROX( nrgx ), scale ) - mid_res_amp_Q0[ 0 ], + smooth_coef_Q16 ); + /* Residual energy = nrgy - 2 * pred * corr + pred^2 * nrgx */ + nrgy = silk_SUB_LSHIFT32( nrgy, silk_SMULWB( corr, pred_Q13 ), 3 + 1 ); + nrgy = silk_ADD_LSHIFT32( nrgy, silk_SMULWB( nrgx, pred2_Q10 ), 6 ); + mid_res_amp_Q0[ 1 ] = silk_SMLAWB( mid_res_amp_Q0[ 1 ], silk_LSHIFT( silk_SQRT_APPROX( nrgy ), scale ) - mid_res_amp_Q0[ 1 ], + smooth_coef_Q16 ); + + /* Ratio of smoothed residual and mid norms */ + *ratio_Q14 = silk_DIV32_varQ( mid_res_amp_Q0[ 1 ], silk_max( mid_res_amp_Q0[ 0 ], 1 ), 14 ); + *ratio_Q14 = silk_LIMIT( *ratio_Q14, 0, 32767 ); + + return pred_Q13; +} diff --git a/TelegramClient.Opus/opus/silk/stereo_quant_pred.c b/TelegramClient.Opus/opus/silk/stereo_quant_pred.c new file mode 100755 index 0000000..d4ced6c --- /dev/null +++ b/TelegramClient.Opus/opus/silk/stereo_quant_pred.c @@ -0,0 +1,73 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "main.h" + +/* Quantize mid/side predictors */ +void silk_stereo_quant_pred( + opus_int32 pred_Q13[], /* I/O Predictors (out: quantized) */ + opus_int8 ix[ 2 ][ 3 ] /* O Quantization indices */ +) +{ + opus_int i, j, n; + opus_int32 low_Q13, step_Q13, lvl_Q13, err_min_Q13, err_Q13, quant_pred_Q13 = 0; + + /* Quantize */ + for( n = 0; n < 2; n++ ) { + /* Brute-force search over quantization levels */ + err_min_Q13 = silk_int32_MAX; + for( i = 0; i < STEREO_QUANT_TAB_SIZE - 1; i++ ) { + low_Q13 = silk_stereo_pred_quant_Q13[ i ]; + step_Q13 = silk_SMULWB( silk_stereo_pred_quant_Q13[ i + 1 ] - low_Q13, + SILK_FIX_CONST( 0.5 / STEREO_QUANT_SUB_STEPS, 16 ) ); + for( j = 0; j < STEREO_QUANT_SUB_STEPS; j++ ) { + lvl_Q13 = silk_SMLABB( low_Q13, step_Q13, 2 * j + 1 ); + err_Q13 = silk_abs( pred_Q13[ n ] - lvl_Q13 ); + if( err_Q13 < err_min_Q13 ) { + err_min_Q13 = err_Q13; + quant_pred_Q13 = lvl_Q13; + ix[ n ][ 0 ] = i; + ix[ n ][ 1 ] = j; + } else { + /* Error increasing, so we're past the optimum */ + goto done; + } + } + } + done: + ix[ n ][ 2 ] = silk_DIV32_16( ix[ n ][ 0 ], 3 ); + ix[ n ][ 0 ] -= ix[ n ][ 2 ] * 3; + pred_Q13[ n ] = quant_pred_Q13; + } + + /* Subtract second from first predictor (helps when actually applying these) */ + pred_Q13[ 0 ] -= pred_Q13[ 1 ]; +} diff --git a/TelegramClient.Opus/opus/silk/structs.h b/TelegramClient.Opus/opus/silk/structs.h new file mode 100755 index 0000000..1826b36 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/structs.h @@ -0,0 +1,327 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_STRUCTS_H +#define SILK_STRUCTS_H + +#include "typedef.h" +#include "SigProc_FIX.h" +#include "define.h" +#include "entenc.h" +#include "entdec.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************************/ +/* Noise shaping quantization state */ +/************************************/ +typedef struct { + opus_int16 xq[ 2 * MAX_FRAME_LENGTH ]; /* Buffer for quantized output signal */ + opus_int32 sLTP_shp_Q14[ 2 * MAX_FRAME_LENGTH ]; + opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ]; + opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ]; + opus_int32 sLF_AR_shp_Q14; + opus_int lagPrev; + opus_int sLTP_buf_idx; + opus_int sLTP_shp_buf_idx; + opus_int32 rand_seed; + opus_int32 prev_gain_Q16; + opus_int rewhite_flag; +} silk_nsq_state; + +/********************************/ +/* VAD state */ +/********************************/ +typedef struct { + opus_int32 AnaState[ 2 ]; /* Analysis filterbank state: 0-8 kHz */ + opus_int32 AnaState1[ 2 ]; /* Analysis filterbank state: 0-4 kHz */ + opus_int32 AnaState2[ 2 ]; /* Analysis filterbank state: 0-2 kHz */ + opus_int32 XnrgSubfr[ VAD_N_BANDS ]; /* Subframe energies */ + opus_int32 NrgRatioSmth_Q8[ VAD_N_BANDS ]; /* Smoothed energy level in each band */ + opus_int16 HPstate; /* State of differentiator in the lowest band */ + opus_int32 NL[ VAD_N_BANDS ]; /* Noise energy level in each band */ + opus_int32 inv_NL[ VAD_N_BANDS ]; /* Inverse noise energy level in each band */ + opus_int32 NoiseLevelBias[ VAD_N_BANDS ]; /* Noise level estimator bias/offset */ + opus_int32 counter; /* Frame counter used in the initial phase */ +} silk_VAD_state; + +/* Variable cut-off low-pass filter state */ +typedef struct { + opus_int32 In_LP_State[ 2 ]; /* Low pass filter state */ + opus_int32 transition_frame_no; /* Counter which is mapped to a cut-off frequency */ + opus_int mode; /* Operating mode, <0: switch down, >0: switch up; 0: do nothing */ +} silk_LP_state; + +/* Structure containing NLSF codebook */ +typedef struct { + const opus_int16 nVectors; + const opus_int16 order; + const opus_int16 quantStepSize_Q16; + const opus_int16 invQuantStepSize_Q6; + const opus_uint8 *CB1_NLSF_Q8; + const opus_uint8 *CB1_iCDF; + const opus_uint8 *pred_Q8; + const opus_uint8 *ec_sel; + const opus_uint8 *ec_iCDF; + const opus_uint8 *ec_Rates_Q5; + const opus_int16 *deltaMin_Q15; +} silk_NLSF_CB_struct; + +typedef struct { + opus_int16 pred_prev_Q13[ 2 ]; + opus_int16 sMid[ 2 ]; + opus_int16 sSide[ 2 ]; + opus_int32 mid_side_amp_Q0[ 4 ]; + opus_int16 smth_width_Q14; + opus_int16 width_prev_Q14; + opus_int16 silent_side_len; + opus_int8 predIx[ MAX_FRAMES_PER_PACKET ][ 2 ][ 3 ]; + opus_int8 mid_only_flags[ MAX_FRAMES_PER_PACKET ]; +} stereo_enc_state; + +typedef struct { + opus_int16 pred_prev_Q13[ 2 ]; + opus_int16 sMid[ 2 ]; + opus_int16 sSide[ 2 ]; +} stereo_dec_state; + +typedef struct { + opus_int8 GainsIndices[ MAX_NB_SUBFR ]; + opus_int8 LTPIndex[ MAX_NB_SUBFR ]; + opus_int8 NLSFIndices[ MAX_LPC_ORDER + 1 ]; + opus_int16 lagIndex; + opus_int8 contourIndex; + opus_int8 signalType; + opus_int8 quantOffsetType; + opus_int8 NLSFInterpCoef_Q2; + opus_int8 PERIndex; + opus_int8 LTP_scaleIndex; + opus_int8 Seed; +} SideInfoIndices; + +/********************************/ +/* Encoder state */ +/********************************/ +typedef struct { + opus_int32 In_HP_State[ 2 ]; /* High pass filter state */ + opus_int32 variable_HP_smth1_Q15; /* State of first smoother */ + opus_int32 variable_HP_smth2_Q15; /* State of second smoother */ + silk_LP_state sLP; /* Low pass filter state */ + silk_VAD_state sVAD; /* Voice activity detector state */ + silk_nsq_state sNSQ; /* Noise Shape Quantizer State */ + opus_int16 prev_NLSFq_Q15[ MAX_LPC_ORDER ]; /* Previously quantized NLSF vector */ + opus_int speech_activity_Q8; /* Speech activity */ + opus_int allow_bandwidth_switch; /* Flag indicating that switching of internal bandwidth is allowed */ + opus_int8 LBRRprevLastGainIndex; + opus_int8 prevSignalType; + opus_int prevLag; + opus_int pitch_LPC_win_length; + opus_int max_pitch_lag; /* Highest possible pitch lag (samples) */ + opus_int32 API_fs_Hz; /* API sampling frequency (Hz) */ + opus_int32 prev_API_fs_Hz; /* Previous API sampling frequency (Hz) */ + opus_int maxInternal_fs_Hz; /* Maximum internal sampling frequency (Hz) */ + opus_int minInternal_fs_Hz; /* Minimum internal sampling frequency (Hz) */ + opus_int desiredInternal_fs_Hz; /* Soft request for internal sampling frequency (Hz) */ + opus_int fs_kHz; /* Internal sampling frequency (kHz) */ + opus_int nb_subfr; /* Number of 5 ms subframes in a frame */ + opus_int frame_length; /* Frame length (samples) */ + opus_int subfr_length; /* Subframe length (samples) */ + opus_int ltp_mem_length; /* Length of LTP memory */ + opus_int la_pitch; /* Look-ahead for pitch analysis (samples) */ + opus_int la_shape; /* Look-ahead for noise shape analysis (samples) */ + opus_int shapeWinLength; /* Window length for noise shape analysis (samples) */ + opus_int32 TargetRate_bps; /* Target bitrate (bps) */ + opus_int PacketSize_ms; /* Number of milliseconds to put in each packet */ + opus_int PacketLoss_perc; /* Packet loss rate measured by farend */ + opus_int32 frameCounter; + opus_int Complexity; /* Complexity setting */ + opus_int nStatesDelayedDecision; /* Number of states in delayed decision quantization */ + opus_int useInterpolatedNLSFs; /* Flag for using NLSF interpolation */ + opus_int shapingLPCOrder; /* Filter order for noise shaping filters */ + opus_int predictLPCOrder; /* Filter order for prediction filters */ + opus_int pitchEstimationComplexity; /* Complexity level for pitch estimator */ + opus_int pitchEstimationLPCOrder; /* Whitening filter order for pitch estimator */ + opus_int32 pitchEstimationThreshold_Q16; /* Threshold for pitch estimator */ + opus_int LTPQuantLowComplexity; /* Flag for low complexity LTP quantization */ + opus_int mu_LTP_Q9; /* Rate-distortion tradeoff in LTP quantization */ + opus_int32 sum_log_gain_Q7; /* Cumulative max prediction gain */ + opus_int NLSF_MSVQ_Survivors; /* Number of survivors in NLSF MSVQ */ + opus_int first_frame_after_reset; /* Flag for deactivating NLSF interpolation, pitch prediction */ + opus_int controlled_since_last_payload; /* Flag for ensuring codec_control only runs once per packet */ + opus_int warping_Q16; /* Warping parameter for warped noise shaping */ + opus_int useCBR; /* Flag to enable constant bitrate */ + opus_int prefillFlag; /* Flag to indicate that only buffers are prefilled, no coding */ + const opus_uint8 *pitch_lag_low_bits_iCDF; /* Pointer to iCDF table for low bits of pitch lag index */ + const opus_uint8 *pitch_contour_iCDF; /* Pointer to iCDF table for pitch contour index */ + const silk_NLSF_CB_struct *psNLSF_CB; /* Pointer to NLSF codebook */ + opus_int input_quality_bands_Q15[ VAD_N_BANDS ]; + opus_int input_tilt_Q15; + opus_int SNR_dB_Q7; /* Quality setting */ + + opus_int8 VAD_flags[ MAX_FRAMES_PER_PACKET ]; + opus_int8 LBRR_flag; + opus_int LBRR_flags[ MAX_FRAMES_PER_PACKET ]; + + SideInfoIndices indices; + opus_int8 pulses[ MAX_FRAME_LENGTH ]; + + int arch; + + /* Input/output buffering */ + opus_int16 inputBuf[ MAX_FRAME_LENGTH + 2 ]; /* Buffer containing input signal */ + opus_int inputBufIx; + opus_int nFramesPerPacket; + opus_int nFramesEncoded; /* Number of frames analyzed in current packet */ + + opus_int nChannelsAPI; + opus_int nChannelsInternal; + opus_int channelNb; + + /* Parameters For LTP scaling Control */ + opus_int frames_since_onset; + + /* Specifically for entropy coding */ + opus_int ec_prevSignalType; + opus_int16 ec_prevLagIndex; + + silk_resampler_state_struct resampler_state; + + /* DTX */ + opus_int useDTX; /* Flag to enable DTX */ + opus_int inDTX; /* Flag to signal DTX period */ + opus_int noSpeechCounter; /* Counts concecutive nonactive frames, used by DTX */ + + /* Inband Low Bitrate Redundancy (LBRR) data */ + opus_int useInBandFEC; /* Saves the API setting for query */ + opus_int LBRR_enabled; /* Depends on useInBandFRC, bitrate and packet loss rate */ + opus_int LBRR_GainIncreases; /* Gains increment for coding LBRR frames */ + SideInfoIndices indices_LBRR[ MAX_FRAMES_PER_PACKET ]; + opus_int8 pulses_LBRR[ MAX_FRAMES_PER_PACKET ][ MAX_FRAME_LENGTH ]; +} silk_encoder_state; + + +/* Struct for Packet Loss Concealment */ +typedef struct { + opus_int32 pitchL_Q8; /* Pitch lag to use for voiced concealment */ + opus_int16 LTPCoef_Q14[ LTP_ORDER ]; /* LTP coeficients to use for voiced concealment */ + opus_int16 prevLPC_Q12[ MAX_LPC_ORDER ]; + opus_int last_frame_lost; /* Was previous frame lost */ + opus_int32 rand_seed; /* Seed for unvoiced signal generation */ + opus_int16 randScale_Q14; /* Scaling of unvoiced random signal */ + opus_int32 conc_energy; + opus_int conc_energy_shift; + opus_int16 prevLTP_scale_Q14; + opus_int32 prevGain_Q16[ 2 ]; + opus_int fs_kHz; + opus_int nb_subfr; + opus_int subfr_length; +} silk_PLC_struct; + +/* Struct for CNG */ +typedef struct { + opus_int32 CNG_exc_buf_Q14[ MAX_FRAME_LENGTH ]; + opus_int16 CNG_smth_NLSF_Q15[ MAX_LPC_ORDER ]; + opus_int32 CNG_synth_state[ MAX_LPC_ORDER ]; + opus_int32 CNG_smth_Gain_Q16; + opus_int32 rand_seed; + opus_int fs_kHz; +} silk_CNG_struct; + +/********************************/ +/* Decoder state */ +/********************************/ +typedef struct { + opus_int32 prev_gain_Q16; + opus_int32 exc_Q14[ MAX_FRAME_LENGTH ]; + opus_int32 sLPC_Q14_buf[ MAX_LPC_ORDER ]; + opus_int16 outBuf[ MAX_FRAME_LENGTH + 2 * MAX_SUB_FRAME_LENGTH ]; /* Buffer for output signal */ + opus_int lagPrev; /* Previous Lag */ + opus_int8 LastGainIndex; /* Previous gain index */ + opus_int fs_kHz; /* Sampling frequency in kHz */ + opus_int32 fs_API_hz; /* API sample frequency (Hz) */ + opus_int nb_subfr; /* Number of 5 ms subframes in a frame */ + opus_int frame_length; /* Frame length (samples) */ + opus_int subfr_length; /* Subframe length (samples) */ + opus_int ltp_mem_length; /* Length of LTP memory */ + opus_int LPC_order; /* LPC order */ + opus_int16 prevNLSF_Q15[ MAX_LPC_ORDER ]; /* Used to interpolate LSFs */ + opus_int first_frame_after_reset; /* Flag for deactivating NLSF interpolation */ + const opus_uint8 *pitch_lag_low_bits_iCDF; /* Pointer to iCDF table for low bits of pitch lag index */ + const opus_uint8 *pitch_contour_iCDF; /* Pointer to iCDF table for pitch contour index */ + + /* For buffering payload in case of more frames per packet */ + opus_int nFramesDecoded; + opus_int nFramesPerPacket; + + /* Specifically for entropy coding */ + opus_int ec_prevSignalType; + opus_int16 ec_prevLagIndex; + + opus_int VAD_flags[ MAX_FRAMES_PER_PACKET ]; + opus_int LBRR_flag; + opus_int LBRR_flags[ MAX_FRAMES_PER_PACKET ]; + + silk_resampler_state_struct resampler_state; + + const silk_NLSF_CB_struct *psNLSF_CB; /* Pointer to NLSF codebook */ + + /* Quantization indices */ + SideInfoIndices indices; + + /* CNG state */ + silk_CNG_struct sCNG; + + /* Stuff used for PLC */ + opus_int lossCnt; + opus_int prevSignalType; + + silk_PLC_struct sPLC; + +} silk_decoder_state; + +/************************/ +/* Decoder control */ +/************************/ +typedef struct { + /* Prediction and coding parameters */ + opus_int pitchL[ MAX_NB_SUBFR ]; + opus_int32 Gains_Q16[ MAX_NB_SUBFR ]; + /* Holds interpolated and final coefficients, 4-byte aligned */ + silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ]; + opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ]; + opus_int LTP_scale_Q14; +} silk_decoder_control; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/TelegramClient.Opus/opus/silk/sum_sqr_shift.c b/TelegramClient.Opus/opus/silk/sum_sqr_shift.c new file mode 100755 index 0000000..12514c9 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/sum_sqr_shift.c @@ -0,0 +1,85 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "SigProc_FIX.h" + +/* Compute number of bits to right shift the sum of squares of a vector */ +/* of int16s to make it fit in an int32 */ +void silk_sum_sqr_shift( + opus_int32 *energy, /* O Energy of x, after shifting to the right */ + opus_int *shift, /* O Number of bits right shift applied to energy */ + const opus_int16 *x, /* I Input vector */ + opus_int len /* I Length of input vector */ +) +{ + opus_int i, shft; + opus_int32 nrg_tmp, nrg; + + nrg = 0; + shft = 0; + len--; + for( i = 0; i < len; i += 2 ) { + nrg = silk_SMLABB_ovflw( nrg, x[ i ], x[ i ] ); + nrg = silk_SMLABB_ovflw( nrg, x[ i + 1 ], x[ i + 1 ] ); + if( nrg < 0 ) { + /* Scale down */ + nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 ); + shft = 2; + break; + } + } + for( ; i < len; i += 2 ) { + nrg_tmp = silk_SMULBB( x[ i ], x[ i ] ); + nrg_tmp = silk_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] ); + nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, (opus_uint32)nrg_tmp, shft ); + if( nrg < 0 ) { + /* Scale down */ + nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 ); + shft += 2; + } + } + if( i == len ) { + /* One sample left to process */ + nrg_tmp = silk_SMULBB( x[ i ], x[ i ] ); + nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft ); + } + + /* Make sure to have at least one extra leading zero (two leading zeros in total) */ + if( nrg & 0xC0000000 ) { + nrg = silk_RSHIFT_uint( (opus_uint32)nrg, 2 ); + shft += 2; + } + + /* Output arguments */ + *shift = shft; + *energy = nrg; +} + diff --git a/TelegramClient.Opus/opus/silk/table_LSF_cos.c b/TelegramClient.Opus/opus/silk/table_LSF_cos.c new file mode 100755 index 0000000..ec9dc63 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/table_LSF_cos.c @@ -0,0 +1,70 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tables.h" + +/* Cosine approximation table for LSF conversion */ +/* Q12 values (even) */ +const opus_int16 silk_LSFCosTab_FIX_Q12[ LSF_COS_TAB_SZ_FIX + 1 ] = { + 8192, 8190, 8182, 8170, + 8152, 8130, 8104, 8072, + 8034, 7994, 7946, 7896, + 7840, 7778, 7714, 7644, + 7568, 7490, 7406, 7318, + 7226, 7128, 7026, 6922, + 6812, 6698, 6580, 6458, + 6332, 6204, 6070, 5934, + 5792, 5648, 5502, 5352, + 5198, 5040, 4880, 4718, + 4552, 4382, 4212, 4038, + 3862, 3684, 3502, 3320, + 3136, 2948, 2760, 2570, + 2378, 2186, 1990, 1794, + 1598, 1400, 1202, 1002, + 802, 602, 402, 202, + 0, -202, -402, -602, + -802, -1002, -1202, -1400, + -1598, -1794, -1990, -2186, + -2378, -2570, -2760, -2948, + -3136, -3320, -3502, -3684, + -3862, -4038, -4212, -4382, + -4552, -4718, -4880, -5040, + -5198, -5352, -5502, -5648, + -5792, -5934, -6070, -6204, + -6332, -6458, -6580, -6698, + -6812, -6922, -7026, -7128, + -7226, -7318, -7406, -7490, + -7568, -7644, -7714, -7778, + -7840, -7896, -7946, -7994, + -8034, -8072, -8104, -8130, + -8152, -8170, -8182, -8190, + -8192 +}; diff --git a/TelegramClient.Opus/opus/silk/tables.h b/TelegramClient.Opus/opus/silk/tables.h new file mode 100755 index 0000000..a91431e --- /dev/null +++ b/TelegramClient.Opus/opus/silk/tables.h @@ -0,0 +1,122 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_TABLES_H +#define SILK_TABLES_H + +#include "define.h" +#include "structs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Entropy coding tables (with size in bytes indicated) */ +extern const opus_uint8 silk_gain_iCDF[ 3 ][ N_LEVELS_QGAIN / 8 ]; /* 24 */ +extern const opus_uint8 silk_delta_gain_iCDF[ MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ]; /* 41 */ + +extern const opus_uint8 silk_pitch_lag_iCDF[ 2 * ( PITCH_EST_MAX_LAG_MS - PITCH_EST_MIN_LAG_MS ) ];/* 32 */ +extern const opus_uint8 silk_pitch_delta_iCDF[ 21 ]; /* 21 */ +extern const opus_uint8 silk_pitch_contour_iCDF[ 34 ]; /* 34 */ +extern const opus_uint8 silk_pitch_contour_NB_iCDF[ 11 ]; /* 11 */ +extern const opus_uint8 silk_pitch_contour_10_ms_iCDF[ 12 ]; /* 12 */ +extern const opus_uint8 silk_pitch_contour_10_ms_NB_iCDF[ 3 ]; /* 3 */ + +extern const opus_uint8 silk_pulses_per_block_iCDF[ N_RATE_LEVELS ][ MAX_PULSES + 2 ]; /* 180 */ +extern const opus_uint8 silk_pulses_per_block_BITS_Q5[ N_RATE_LEVELS - 1 ][ MAX_PULSES + 2 ]; /* 162 */ + +extern const opus_uint8 silk_rate_levels_iCDF[ 2 ][ N_RATE_LEVELS - 1 ]; /* 18 */ +extern const opus_uint8 silk_rate_levels_BITS_Q5[ 2 ][ N_RATE_LEVELS - 1 ]; /* 18 */ + +extern const opus_uint8 silk_max_pulses_table[ 4 ]; /* 4 */ + +extern const opus_uint8 silk_shell_code_table0[ 152 ]; /* 152 */ +extern const opus_uint8 silk_shell_code_table1[ 152 ]; /* 152 */ +extern const opus_uint8 silk_shell_code_table2[ 152 ]; /* 152 */ +extern const opus_uint8 silk_shell_code_table3[ 152 ]; /* 152 */ +extern const opus_uint8 silk_shell_code_table_offsets[ MAX_PULSES + 1 ]; /* 17 */ + +extern const opus_uint8 silk_lsb_iCDF[ 2 ]; /* 2 */ + +extern const opus_uint8 silk_sign_iCDF[ 42 ]; /* 42 */ + +extern const opus_uint8 silk_uniform3_iCDF[ 3 ]; /* 3 */ +extern const opus_uint8 silk_uniform4_iCDF[ 4 ]; /* 4 */ +extern const opus_uint8 silk_uniform5_iCDF[ 5 ]; /* 5 */ +extern const opus_uint8 silk_uniform6_iCDF[ 6 ]; /* 6 */ +extern const opus_uint8 silk_uniform8_iCDF[ 8 ]; /* 8 */ + +extern const opus_uint8 silk_NLSF_EXT_iCDF[ 7 ]; /* 7 */ + +extern const opus_uint8 silk_LTP_per_index_iCDF[ 3 ]; /* 3 */ +extern const opus_uint8 * const silk_LTP_gain_iCDF_ptrs[ NB_LTP_CBKS ]; /* 3 */ +extern const opus_uint8 * const silk_LTP_gain_BITS_Q5_ptrs[ NB_LTP_CBKS ]; /* 3 */ +extern const opus_int16 silk_LTP_gain_middle_avg_RD_Q14; +extern const opus_int8 * const silk_LTP_vq_ptrs_Q7[ NB_LTP_CBKS ]; /* 168 */ +extern const opus_uint8 * const silk_LTP_vq_gain_ptrs_Q7[NB_LTP_CBKS]; + +extern const opus_int8 silk_LTP_vq_sizes[ NB_LTP_CBKS ]; /* 3 */ + +extern const opus_uint8 silk_LTPscale_iCDF[ 3 ]; /* 4 */ +extern const opus_int16 silk_LTPScales_table_Q14[ 3 ]; /* 6 */ + +extern const opus_uint8 silk_type_offset_VAD_iCDF[ 4 ]; /* 4 */ +extern const opus_uint8 silk_type_offset_no_VAD_iCDF[ 2 ]; /* 2 */ + +extern const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ]; /* 32 */ +extern const opus_uint8 silk_stereo_pred_joint_iCDF[ 25 ]; /* 25 */ +extern const opus_uint8 silk_stereo_only_code_mid_iCDF[ 2 ]; /* 2 */ + +extern const opus_uint8 * const silk_LBRR_flags_iCDF_ptr[ 2 ]; /* 10 */ + +extern const opus_uint8 silk_NLSF_interpolation_factor_iCDF[ 5 ]; /* 5 */ + +extern const silk_NLSF_CB_struct silk_NLSF_CB_WB; /* 1040 */ +extern const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB; /* 728 */ + +/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */ +extern const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ]; /* 32 */ +extern const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ]; /* 32 */ +extern const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ]; /* 32 */ +extern const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ]; /* 32 */ + +/* Quantization offsets */ +extern const opus_int16 silk_Quantization_Offsets_Q10[ 2 ][ 2 ]; /* 8 */ + +/* Interpolation points for filter coefficients used in the bandwidth transition smoother */ +extern const opus_int32 silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NB ]; /* 60 */ +extern const opus_int32 silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NA ]; /* 60 */ + +/* Rom table with cosine values */ +extern const opus_int16 silk_LSFCosTab_FIX_Q12[ LSF_COS_TAB_SZ_FIX + 1 ]; /* 258 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/TelegramClient.Opus/opus/silk/tables_LTP.c b/TelegramClient.Opus/opus/silk/tables_LTP.c new file mode 100755 index 0000000..0e6a025 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/tables_LTP.c @@ -0,0 +1,296 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tables.h" + +const opus_uint8 silk_LTP_per_index_iCDF[3] = { + 179, 99, 0 +}; + +static const opus_uint8 silk_LTP_gain_iCDF_0[8] = { + 71, 56, 43, 30, 21, 12, 6, 0 +}; + +static const opus_uint8 silk_LTP_gain_iCDF_1[16] = { + 199, 165, 144, 124, 109, 96, 84, 71, + 61, 51, 42, 32, 23, 15, 8, 0 +}; + +static const opus_uint8 silk_LTP_gain_iCDF_2[32] = { + 241, 225, 211, 199, 187, 175, 164, 153, + 142, 132, 123, 114, 105, 96, 88, 80, + 72, 64, 57, 50, 44, 38, 33, 29, + 24, 20, 16, 12, 9, 5, 2, 0 +}; + +const opus_int16 silk_LTP_gain_middle_avg_RD_Q14 = 12304; + +static const opus_uint8 silk_LTP_gain_BITS_Q5_0[8] = { + 15, 131, 138, 138, 155, 155, 173, 173 +}; + +static const opus_uint8 silk_LTP_gain_BITS_Q5_1[16] = { + 69, 93, 115, 118, 131, 138, 141, 138, + 150, 150, 155, 150, 155, 160, 166, 160 +}; + +static const opus_uint8 silk_LTP_gain_BITS_Q5_2[32] = { + 131, 128, 134, 141, 141, 141, 145, 145, + 145, 150, 155, 155, 155, 155, 160, 160, + 160, 160, 166, 166, 173, 173, 182, 192, + 182, 192, 192, 192, 205, 192, 205, 224 +}; + +const opus_uint8 * const silk_LTP_gain_iCDF_ptrs[NB_LTP_CBKS] = { + silk_LTP_gain_iCDF_0, + silk_LTP_gain_iCDF_1, + silk_LTP_gain_iCDF_2 +}; + +const opus_uint8 * const silk_LTP_gain_BITS_Q5_ptrs[NB_LTP_CBKS] = { + silk_LTP_gain_BITS_Q5_0, + silk_LTP_gain_BITS_Q5_1, + silk_LTP_gain_BITS_Q5_2 +}; + +static const opus_int8 silk_LTP_gain_vq_0[8][5] = +{ +{ + 4, 6, 24, 7, 5 +}, +{ + 0, 0, 2, 0, 0 +}, +{ + 12, 28, 41, 13, -4 +}, +{ + -9, 15, 42, 25, 14 +}, +{ + 1, -2, 62, 41, -9 +}, +{ + -10, 37, 65, -4, 3 +}, +{ + -6, 4, 66, 7, -8 +}, +{ + 16, 14, 38, -3, 33 +} +}; + +static const opus_int8 silk_LTP_gain_vq_1[16][5] = +{ +{ + 13, 22, 39, 23, 12 +}, +{ + -1, 36, 64, 27, -6 +}, +{ + -7, 10, 55, 43, 17 +}, +{ + 1, 1, 8, 1, 1 +}, +{ + 6, -11, 74, 53, -9 +}, +{ + -12, 55, 76, -12, 8 +}, +{ + -3, 3, 93, 27, -4 +}, +{ + 26, 39, 59, 3, -8 +}, +{ + 2, 0, 77, 11, 9 +}, +{ + -8, 22, 44, -6, 7 +}, +{ + 40, 9, 26, 3, 9 +}, +{ + -7, 20, 101, -7, 4 +}, +{ + 3, -8, 42, 26, 0 +}, +{ + -15, 33, 68, 2, 23 +}, +{ + -2, 55, 46, -2, 15 +}, +{ + 3, -1, 21, 16, 41 +} +}; + +static const opus_int8 silk_LTP_gain_vq_2[32][5] = +{ +{ + -6, 27, 61, 39, 5 +}, +{ + -11, 42, 88, 4, 1 +}, +{ + -2, 60, 65, 6, -4 +}, +{ + -1, -5, 73, 56, 1 +}, +{ + -9, 19, 94, 29, -9 +}, +{ + 0, 12, 99, 6, 4 +}, +{ + 8, -19, 102, 46, -13 +}, +{ + 3, 2, 13, 3, 2 +}, +{ + 9, -21, 84, 72, -18 +}, +{ + -11, 46, 104, -22, 8 +}, +{ + 18, 38, 48, 23, 0 +}, +{ + -16, 70, 83, -21, 11 +}, +{ + 5, -11, 117, 22, -8 +}, +{ + -6, 23, 117, -12, 3 +}, +{ + 3, -8, 95, 28, 4 +}, +{ + -10, 15, 77, 60, -15 +}, +{ + -1, 4, 124, 2, -4 +}, +{ + 3, 38, 84, 24, -25 +}, +{ + 2, 13, 42, 13, 31 +}, +{ + 21, -4, 56, 46, -1 +}, +{ + -1, 35, 79, -13, 19 +}, +{ + -7, 65, 88, -9, -14 +}, +{ + 20, 4, 81, 49, -29 +}, +{ + 20, 0, 75, 3, -17 +}, +{ + 5, -9, 44, 92, -8 +}, +{ + 1, -3, 22, 69, 31 +}, +{ + -6, 95, 41, -12, 5 +}, +{ + 39, 67, 16, -4, 1 +}, +{ + 0, -6, 120, 55, -36 +}, +{ + -13, 44, 122, 4, -24 +}, +{ + 81, 5, 11, 3, 7 +}, +{ + 2, 0, 9, 10, 88 +} +}; + +const opus_int8 * const silk_LTP_vq_ptrs_Q7[NB_LTP_CBKS] = { + (opus_int8 *)&silk_LTP_gain_vq_0[0][0], + (opus_int8 *)&silk_LTP_gain_vq_1[0][0], + (opus_int8 *)&silk_LTP_gain_vq_2[0][0] +}; + +/* Maximum frequency-dependent response of the pitch taps above, + computed as max(abs(freqz(taps))) */ +static const opus_uint8 silk_LTP_gain_vq_0_gain[8] = { + 46, 2, 90, 87, 93, 91, 82, 98 +}; + +static const opus_uint8 silk_LTP_gain_vq_1_gain[16] = { + 109, 120, 118, 12, 113, 115, 117, 119, + 99, 59, 87, 111, 63, 111, 112, 80 +}; + +static const opus_uint8 silk_LTP_gain_vq_2_gain[32] = { + 126, 124, 125, 124, 129, 121, 126, 23, + 132, 127, 127, 127, 126, 127, 122, 133, + 130, 134, 101, 118, 119, 145, 126, 86, + 124, 120, 123, 119, 170, 173, 107, 109 +}; + +const opus_uint8 * const silk_LTP_vq_gain_ptrs_Q7[NB_LTP_CBKS] = { + &silk_LTP_gain_vq_0_gain[0], + &silk_LTP_gain_vq_1_gain[0], + &silk_LTP_gain_vq_2_gain[0] +}; + +const opus_int8 silk_LTP_vq_sizes[NB_LTP_CBKS] = { + 8, 16, 32 +}; diff --git a/TelegramClient.Opus/opus/silk/tables_NLSF_CB_NB_MB.c b/TelegramClient.Opus/opus/silk/tables_NLSF_CB_NB_MB.c new file mode 100755 index 0000000..8c59d20 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/tables_NLSF_CB_NB_MB.c @@ -0,0 +1,159 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tables.h" + +static const opus_uint8 silk_NLSF_CB1_NB_MB_Q8[ 320 ] = { + 12, 35, 60, 83, 108, 132, 157, 180, + 206, 228, 15, 32, 55, 77, 101, 125, + 151, 175, 201, 225, 19, 42, 66, 89, + 114, 137, 162, 184, 209, 230, 12, 25, + 50, 72, 97, 120, 147, 172, 200, 223, + 26, 44, 69, 90, 114, 135, 159, 180, + 205, 225, 13, 22, 53, 80, 106, 130, + 156, 180, 205, 228, 15, 25, 44, 64, + 90, 115, 142, 168, 196, 222, 19, 24, + 62, 82, 100, 120, 145, 168, 190, 214, + 22, 31, 50, 79, 103, 120, 151, 170, + 203, 227, 21, 29, 45, 65, 106, 124, + 150, 171, 196, 224, 30, 49, 75, 97, + 121, 142, 165, 186, 209, 229, 19, 25, + 52, 70, 93, 116, 143, 166, 192, 219, + 26, 34, 62, 75, 97, 118, 145, 167, + 194, 217, 25, 33, 56, 70, 91, 113, + 143, 165, 196, 223, 21, 34, 51, 72, + 97, 117, 145, 171, 196, 222, 20, 29, + 50, 67, 90, 117, 144, 168, 197, 221, + 22, 31, 48, 66, 95, 117, 146, 168, + 196, 222, 24, 33, 51, 77, 116, 134, + 158, 180, 200, 224, 21, 28, 70, 87, + 106, 124, 149, 170, 194, 217, 26, 33, + 53, 64, 83, 117, 152, 173, 204, 225, + 27, 34, 65, 95, 108, 129, 155, 174, + 210, 225, 20, 26, 72, 99, 113, 131, + 154, 176, 200, 219, 34, 43, 61, 78, + 93, 114, 155, 177, 205, 229, 23, 29, + 54, 97, 124, 138, 163, 179, 209, 229, + 30, 38, 56, 89, 118, 129, 158, 178, + 200, 231, 21, 29, 49, 63, 85, 111, + 142, 163, 193, 222, 27, 48, 77, 103, + 133, 158, 179, 196, 215, 232, 29, 47, + 74, 99, 124, 151, 176, 198, 220, 237, + 33, 42, 61, 76, 93, 121, 155, 174, + 207, 225, 29, 53, 87, 112, 136, 154, + 170, 188, 208, 227, 24, 30, 52, 84, + 131, 150, 166, 186, 203, 229, 37, 48, + 64, 84, 104, 118, 156, 177, 201, 230 +}; + +static const opus_uint8 silk_NLSF_CB1_iCDF_NB_MB[ 64 ] = { + 212, 178, 148, 129, 108, 96, 85, 82, + 79, 77, 61, 59, 57, 56, 51, 49, + 48, 45, 42, 41, 40, 38, 36, 34, + 31, 30, 21, 12, 10, 3, 1, 0, + 255, 245, 244, 236, 233, 225, 217, 203, + 190, 176, 175, 161, 149, 136, 125, 114, + 102, 91, 81, 71, 60, 52, 43, 35, + 28, 20, 19, 18, 12, 11, 5, 0 +}; + +static const opus_uint8 silk_NLSF_CB2_SELECT_NB_MB[ 160 ] = { + 16, 0, 0, 0, 0, 99, 66, 36, + 36, 34, 36, 34, 34, 34, 34, 83, + 69, 36, 52, 34, 116, 102, 70, 68, + 68, 176, 102, 68, 68, 34, 65, 85, + 68, 84, 36, 116, 141, 152, 139, 170, + 132, 187, 184, 216, 137, 132, 249, 168, + 185, 139, 104, 102, 100, 68, 68, 178, + 218, 185, 185, 170, 244, 216, 187, 187, + 170, 244, 187, 187, 219, 138, 103, 155, + 184, 185, 137, 116, 183, 155, 152, 136, + 132, 217, 184, 184, 170, 164, 217, 171, + 155, 139, 244, 169, 184, 185, 170, 164, + 216, 223, 218, 138, 214, 143, 188, 218, + 168, 244, 141, 136, 155, 170, 168, 138, + 220, 219, 139, 164, 219, 202, 216, 137, + 168, 186, 246, 185, 139, 116, 185, 219, + 185, 138, 100, 100, 134, 100, 102, 34, + 68, 68, 100, 68, 168, 203, 221, 218, + 168, 167, 154, 136, 104, 70, 164, 246, + 171, 137, 139, 137, 155, 218, 219, 139 +}; + +static const opus_uint8 silk_NLSF_CB2_iCDF_NB_MB[ 72 ] = { + 255, 254, 253, 238, 14, 3, 2, 1, + 0, 255, 254, 252, 218, 35, 3, 2, + 1, 0, 255, 254, 250, 208, 59, 4, + 2, 1, 0, 255, 254, 246, 194, 71, + 10, 2, 1, 0, 255, 252, 236, 183, + 82, 8, 2, 1, 0, 255, 252, 235, + 180, 90, 17, 2, 1, 0, 255, 248, + 224, 171, 97, 30, 4, 1, 0, 255, + 254, 236, 173, 95, 37, 7, 1, 0 +}; + +static const opus_uint8 silk_NLSF_CB2_BITS_NB_MB_Q5[ 72 ] = { + 255, 255, 255, 131, 6, 145, 255, 255, + 255, 255, 255, 236, 93, 15, 96, 255, + 255, 255, 255, 255, 194, 83, 25, 71, + 221, 255, 255, 255, 255, 162, 73, 34, + 66, 162, 255, 255, 255, 210, 126, 73, + 43, 57, 173, 255, 255, 255, 201, 125, + 71, 48, 58, 130, 255, 255, 255, 166, + 110, 73, 57, 62, 104, 210, 255, 255, + 251, 123, 65, 55, 68, 100, 171, 255 +}; + +static const opus_uint8 silk_NLSF_PRED_NB_MB_Q8[ 18 ] = { + 179, 138, 140, 148, 151, 149, 153, 151, + 163, 116, 67, 82, 59, 92, 72, 100, + 89, 92 +}; + +static const opus_int16 silk_NLSF_DELTA_MIN_NB_MB_Q15[ 11 ] = { + 250, 3, 6, 3, 3, 3, 4, 3, + 3, 3, 461 +}; + +const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB = +{ + 32, + 10, + SILK_FIX_CONST( 0.18, 16 ), + SILK_FIX_CONST( 1.0 / 0.18, 6 ), + silk_NLSF_CB1_NB_MB_Q8, + silk_NLSF_CB1_iCDF_NB_MB, + silk_NLSF_PRED_NB_MB_Q8, + silk_NLSF_CB2_SELECT_NB_MB, + silk_NLSF_CB2_iCDF_NB_MB, + silk_NLSF_CB2_BITS_NB_MB_Q5, + silk_NLSF_DELTA_MIN_NB_MB_Q15, +}; diff --git a/TelegramClient.Opus/opus/silk/tables_NLSF_CB_WB.c b/TelegramClient.Opus/opus/silk/tables_NLSF_CB_WB.c new file mode 100755 index 0000000..50af87e --- /dev/null +++ b/TelegramClient.Opus/opus/silk/tables_NLSF_CB_WB.c @@ -0,0 +1,198 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tables.h" + +static const opus_uint8 silk_NLSF_CB1_WB_Q8[ 512 ] = { + 7, 23, 38, 54, 69, 85, 100, 116, + 131, 147, 162, 178, 193, 208, 223, 239, + 13, 25, 41, 55, 69, 83, 98, 112, + 127, 142, 157, 171, 187, 203, 220, 236, + 15, 21, 34, 51, 61, 78, 92, 106, + 126, 136, 152, 167, 185, 205, 225, 240, + 10, 21, 36, 50, 63, 79, 95, 110, + 126, 141, 157, 173, 189, 205, 221, 237, + 17, 20, 37, 51, 59, 78, 89, 107, + 123, 134, 150, 164, 184, 205, 224, 240, + 10, 15, 32, 51, 67, 81, 96, 112, + 129, 142, 158, 173, 189, 204, 220, 236, + 8, 21, 37, 51, 65, 79, 98, 113, + 126, 138, 155, 168, 179, 192, 209, 218, + 12, 15, 34, 55, 63, 78, 87, 108, + 118, 131, 148, 167, 185, 203, 219, 236, + 16, 19, 32, 36, 56, 79, 91, 108, + 118, 136, 154, 171, 186, 204, 220, 237, + 11, 28, 43, 58, 74, 89, 105, 120, + 135, 150, 165, 180, 196, 211, 226, 241, + 6, 16, 33, 46, 60, 75, 92, 107, + 123, 137, 156, 169, 185, 199, 214, 225, + 11, 19, 30, 44, 57, 74, 89, 105, + 121, 135, 152, 169, 186, 202, 218, 234, + 12, 19, 29, 46, 57, 71, 88, 100, + 120, 132, 148, 165, 182, 199, 216, 233, + 17, 23, 35, 46, 56, 77, 92, 106, + 123, 134, 152, 167, 185, 204, 222, 237, + 14, 17, 45, 53, 63, 75, 89, 107, + 115, 132, 151, 171, 188, 206, 221, 240, + 9, 16, 29, 40, 56, 71, 88, 103, + 119, 137, 154, 171, 189, 205, 222, 237, + 16, 19, 36, 48, 57, 76, 87, 105, + 118, 132, 150, 167, 185, 202, 218, 236, + 12, 17, 29, 54, 71, 81, 94, 104, + 126, 136, 149, 164, 182, 201, 221, 237, + 15, 28, 47, 62, 79, 97, 115, 129, + 142, 155, 168, 180, 194, 208, 223, 238, + 8, 14, 30, 45, 62, 78, 94, 111, + 127, 143, 159, 175, 192, 207, 223, 239, + 17, 30, 49, 62, 79, 92, 107, 119, + 132, 145, 160, 174, 190, 204, 220, 235, + 14, 19, 36, 45, 61, 76, 91, 108, + 121, 138, 154, 172, 189, 205, 222, 238, + 12, 18, 31, 45, 60, 76, 91, 107, + 123, 138, 154, 171, 187, 204, 221, 236, + 13, 17, 31, 43, 53, 70, 83, 103, + 114, 131, 149, 167, 185, 203, 220, 237, + 17, 22, 35, 42, 58, 78, 93, 110, + 125, 139, 155, 170, 188, 206, 224, 240, + 8, 15, 34, 50, 67, 83, 99, 115, + 131, 146, 162, 178, 193, 209, 224, 239, + 13, 16, 41, 66, 73, 86, 95, 111, + 128, 137, 150, 163, 183, 206, 225, 241, + 17, 25, 37, 52, 63, 75, 92, 102, + 119, 132, 144, 160, 175, 191, 212, 231, + 19, 31, 49, 65, 83, 100, 117, 133, + 147, 161, 174, 187, 200, 213, 227, 242, + 18, 31, 52, 68, 88, 103, 117, 126, + 138, 149, 163, 177, 192, 207, 223, 239, + 16, 29, 47, 61, 76, 90, 106, 119, + 133, 147, 161, 176, 193, 209, 224, 240, + 15, 21, 35, 50, 61, 73, 86, 97, + 110, 119, 129, 141, 175, 198, 218, 237 +}; + +static const opus_uint8 silk_NLSF_CB1_iCDF_WB[ 64 ] = { + 225, 204, 201, 184, 183, 175, 158, 154, + 153, 135, 119, 115, 113, 110, 109, 99, + 98, 95, 79, 68, 52, 50, 48, 45, + 43, 32, 31, 27, 18, 10, 3, 0, + 255, 251, 235, 230, 212, 201, 196, 182, + 167, 166, 163, 151, 138, 124, 110, 104, + 90, 78, 76, 70, 69, 57, 45, 34, + 24, 21, 11, 6, 5, 4, 3, 0 +}; + +static const opus_uint8 silk_NLSF_CB2_SELECT_WB[ 256 ] = { + 0, 0, 0, 0, 0, 0, 0, 1, + 100, 102, 102, 68, 68, 36, 34, 96, + 164, 107, 158, 185, 180, 185, 139, 102, + 64, 66, 36, 34, 34, 0, 1, 32, + 208, 139, 141, 191, 152, 185, 155, 104, + 96, 171, 104, 166, 102, 102, 102, 132, + 1, 0, 0, 0, 0, 16, 16, 0, + 80, 109, 78, 107, 185, 139, 103, 101, + 208, 212, 141, 139, 173, 153, 123, 103, + 36, 0, 0, 0, 0, 0, 0, 1, + 48, 0, 0, 0, 0, 0, 0, 32, + 68, 135, 123, 119, 119, 103, 69, 98, + 68, 103, 120, 118, 118, 102, 71, 98, + 134, 136, 157, 184, 182, 153, 139, 134, + 208, 168, 248, 75, 189, 143, 121, 107, + 32, 49, 34, 34, 34, 0, 17, 2, + 210, 235, 139, 123, 185, 137, 105, 134, + 98, 135, 104, 182, 100, 183, 171, 134, + 100, 70, 68, 70, 66, 66, 34, 131, + 64, 166, 102, 68, 36, 2, 1, 0, + 134, 166, 102, 68, 34, 34, 66, 132, + 212, 246, 158, 139, 107, 107, 87, 102, + 100, 219, 125, 122, 137, 118, 103, 132, + 114, 135, 137, 105, 171, 106, 50, 34, + 164, 214, 141, 143, 185, 151, 121, 103, + 192, 34, 0, 0, 0, 0, 0, 1, + 208, 109, 74, 187, 134, 249, 159, 137, + 102, 110, 154, 118, 87, 101, 119, 101, + 0, 2, 0, 36, 36, 66, 68, 35, + 96, 164, 102, 100, 36, 0, 2, 33, + 167, 138, 174, 102, 100, 84, 2, 2, + 100, 107, 120, 119, 36, 197, 24, 0 +}; + +static const opus_uint8 silk_NLSF_CB2_iCDF_WB[ 72 ] = { + 255, 254, 253, 244, 12, 3, 2, 1, + 0, 255, 254, 252, 224, 38, 3, 2, + 1, 0, 255, 254, 251, 209, 57, 4, + 2, 1, 0, 255, 254, 244, 195, 69, + 4, 2, 1, 0, 255, 251, 232, 184, + 84, 7, 2, 1, 0, 255, 254, 240, + 186, 86, 14, 2, 1, 0, 255, 254, + 239, 178, 91, 30, 5, 1, 0, 255, + 248, 227, 177, 100, 19, 2, 1, 0 +}; + +static const opus_uint8 silk_NLSF_CB2_BITS_WB_Q5[ 72 ] = { + 255, 255, 255, 156, 4, 154, 255, 255, + 255, 255, 255, 227, 102, 15, 92, 255, + 255, 255, 255, 255, 213, 83, 24, 72, + 236, 255, 255, 255, 255, 150, 76, 33, + 63, 214, 255, 255, 255, 190, 121, 77, + 43, 55, 185, 255, 255, 255, 245, 137, + 71, 43, 59, 139, 255, 255, 255, 255, + 131, 66, 50, 66, 107, 194, 255, 255, + 166, 116, 76, 55, 53, 125, 255, 255 +}; + +static const opus_uint8 silk_NLSF_PRED_WB_Q8[ 30 ] = { + 175, 148, 160, 176, 178, 173, 174, 164, + 177, 174, 196, 182, 198, 192, 182, 68, + 62, 66, 60, 72, 117, 85, 90, 118, + 136, 151, 142, 160, 142, 155 +}; + +static const opus_int16 silk_NLSF_DELTA_MIN_WB_Q15[ 17 ] = { + 100, 3, 40, 3, 3, 3, 5, 14, + 14, 10, 11, 3, 8, 9, 7, 3, + 347 +}; + +const silk_NLSF_CB_struct silk_NLSF_CB_WB = +{ + 32, + 16, + SILK_FIX_CONST( 0.15, 16 ), + SILK_FIX_CONST( 1.0 / 0.15, 6 ), + silk_NLSF_CB1_WB_Q8, + silk_NLSF_CB1_iCDF_WB, + silk_NLSF_PRED_WB_Q8, + silk_NLSF_CB2_SELECT_WB, + silk_NLSF_CB2_iCDF_WB, + silk_NLSF_CB2_BITS_WB_Q5, + silk_NLSF_DELTA_MIN_WB_Q15, +}; + diff --git a/TelegramClient.Opus/opus/silk/tables_gain.c b/TelegramClient.Opus/opus/silk/tables_gain.c new file mode 100755 index 0000000..37e41d8 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/tables_gain.c @@ -0,0 +1,63 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tables.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +const opus_uint8 silk_gain_iCDF[ 3 ][ N_LEVELS_QGAIN / 8 ] = +{ +{ + 224, 112, 44, 15, 3, 2, 1, 0 +}, +{ + 254, 237, 192, 132, 70, 23, 4, 0 +}, +{ + 255, 252, 226, 155, 61, 11, 2, 0 +} +}; + +const opus_uint8 silk_delta_gain_iCDF[ MAX_DELTA_GAIN_QUANT - MIN_DELTA_GAIN_QUANT + 1 ] = { + 250, 245, 234, 203, 71, 50, 42, 38, + 35, 33, 31, 29, 28, 27, 26, 25, + 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, + 8, 7, 6, 5, 4, 3, 2, 1, + 0 +}; + +#ifdef __cplusplus +} +#endif diff --git a/TelegramClient.Opus/opus/silk/tables_other.c b/TelegramClient.Opus/opus/silk/tables_other.c new file mode 100755 index 0000000..398686b --- /dev/null +++ b/TelegramClient.Opus/opus/silk/tables_other.c @@ -0,0 +1,138 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "structs.h" +#include "define.h" +#include "tables.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */ +const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ] = { + 0, 8000, 9400, 11500, 13500, 17500, 25000, MAX_TARGET_RATE_BPS +}; +const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ] = { + 0, 9000, 12000, 14500, 18500, 24500, 35500, MAX_TARGET_RATE_BPS +}; +const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ] = { + 0, 10500, 14000, 17000, 21500, 28500, 42000, MAX_TARGET_RATE_BPS +}; +const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ] = { + 18, 29, 38, 40, 46, 52, 62, 84 +}; + +/* Tables for stereo predictor coding */ +const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ] = { + -13732, -10050, -8266, -7526, -6500, -5000, -2950, -820, + 820, 2950, 5000, 6500, 7526, 8266, 10050, 13732 +}; +const opus_uint8 silk_stereo_pred_joint_iCDF[ 25 ] = { + 249, 247, 246, 245, 244, + 234, 210, 202, 201, 200, + 197, 174, 82, 59, 56, + 55, 54, 46, 22, 12, + 11, 10, 9, 7, 0 +}; +const opus_uint8 silk_stereo_only_code_mid_iCDF[ 2 ] = { 64, 0 }; + +/* Tables for LBRR flags */ +static const opus_uint8 silk_LBRR_flags_2_iCDF[ 3 ] = { 203, 150, 0 }; +static const opus_uint8 silk_LBRR_flags_3_iCDF[ 7 ] = { 215, 195, 166, 125, 110, 82, 0 }; +const opus_uint8 * const silk_LBRR_flags_iCDF_ptr[ 2 ] = { + silk_LBRR_flags_2_iCDF, + silk_LBRR_flags_3_iCDF +}; + +/* Table for LSB coding */ +const opus_uint8 silk_lsb_iCDF[ 2 ] = { 120, 0 }; + +/* Tables for LTPScale */ +const opus_uint8 silk_LTPscale_iCDF[ 3 ] = { 128, 64, 0 }; + +/* Tables for signal type and offset coding */ +const opus_uint8 silk_type_offset_VAD_iCDF[ 4 ] = { + 232, 158, 10, 0 +}; +const opus_uint8 silk_type_offset_no_VAD_iCDF[ 2 ] = { + 230, 0 +}; + +/* Tables for NLSF interpolation factor */ +const opus_uint8 silk_NLSF_interpolation_factor_iCDF[ 5 ] = { 243, 221, 192, 181, 0 }; + +/* Quantization offsets */ +const opus_int16 silk_Quantization_Offsets_Q10[ 2 ][ 2 ] = { + { OFFSET_UVL_Q10, OFFSET_UVH_Q10 }, { OFFSET_VL_Q10, OFFSET_VH_Q10 } +}; + +/* Table for LTPScale */ +const opus_int16 silk_LTPScales_table_Q14[ 3 ] = { 15565, 12288, 8192 }; + +/* Uniform entropy tables */ +const opus_uint8 silk_uniform3_iCDF[ 3 ] = { 171, 85, 0 }; +const opus_uint8 silk_uniform4_iCDF[ 4 ] = { 192, 128, 64, 0 }; +const opus_uint8 silk_uniform5_iCDF[ 5 ] = { 205, 154, 102, 51, 0 }; +const opus_uint8 silk_uniform6_iCDF[ 6 ] = { 213, 171, 128, 85, 43, 0 }; +const opus_uint8 silk_uniform8_iCDF[ 8 ] = { 224, 192, 160, 128, 96, 64, 32, 0 }; + +const opus_uint8 silk_NLSF_EXT_iCDF[ 7 ] = { 100, 40, 16, 7, 3, 1, 0 }; + +/* Elliptic/Cauer filters designed with 0.1 dB passband ripple, + 80 dB minimum stopband attenuation, and + [0.95 : 0.15 : 0.35] normalized cut off frequencies. */ + +/* Interpolation points for filter coefficients used in the bandwidth transition smoother */ +const opus_int32 silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NB ] = +{ +{ 250767114, 501534038, 250767114 }, +{ 209867381, 419732057, 209867381 }, +{ 170987846, 341967853, 170987846 }, +{ 131531482, 263046905, 131531482 }, +{ 89306658, 178584282, 89306658 } +}; + +/* Interpolation points for filter coefficients used in the bandwidth transition smoother */ +const opus_int32 silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM ][ TRANSITION_NA ] = +{ +{ 506393414, 239854379 }, +{ 411067935, 169683996 }, +{ 306733530, 116694253 }, +{ 185807084, 77959395 }, +{ 35497197, 57401098 } +}; + +#ifdef __cplusplus +} +#endif + diff --git a/TelegramClient.Opus/opus/silk/tables_pitch_lag.c b/TelegramClient.Opus/opus/silk/tables_pitch_lag.c new file mode 100755 index 0000000..e80cc59 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/tables_pitch_lag.c @@ -0,0 +1,69 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tables.h" + +const opus_uint8 silk_pitch_lag_iCDF[ 2 * ( PITCH_EST_MAX_LAG_MS - PITCH_EST_MIN_LAG_MS ) ] = { + 253, 250, 244, 233, 212, 182, 150, 131, + 120, 110, 98, 85, 72, 60, 49, 40, + 32, 25, 19, 15, 13, 11, 9, 8, + 7, 6, 5, 4, 3, 2, 1, 0 +}; + +const opus_uint8 silk_pitch_delta_iCDF[21] = { + 210, 208, 206, 203, 199, 193, 183, 168, + 142, 104, 74, 52, 37, 27, 20, 14, + 10, 6, 4, 2, 0 +}; + +const opus_uint8 silk_pitch_contour_iCDF[34] = { + 223, 201, 183, 167, 152, 138, 124, 111, + 98, 88, 79, 70, 62, 56, 50, 44, + 39, 35, 31, 27, 24, 21, 18, 16, + 14, 12, 10, 8, 6, 4, 3, 2, + 1, 0 +}; + +const opus_uint8 silk_pitch_contour_NB_iCDF[11] = { + 188, 176, 155, 138, 119, 97, 67, 43, + 26, 10, 0 +}; + +const opus_uint8 silk_pitch_contour_10_ms_iCDF[12] = { + 165, 119, 80, 61, 47, 35, 27, 20, + 14, 9, 4, 0 +}; + +const opus_uint8 silk_pitch_contour_10_ms_NB_iCDF[3] = { + 113, 63, 0 +}; + + diff --git a/TelegramClient.Opus/opus/silk/tables_pulses_per_block.c b/TelegramClient.Opus/opus/silk/tables_pulses_per_block.c new file mode 100755 index 0000000..c7c01c8 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/tables_pulses_per_block.c @@ -0,0 +1,264 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tables.h" + +const opus_uint8 silk_max_pulses_table[ 4 ] = { + 8, 10, 12, 16 +}; + +const opus_uint8 silk_pulses_per_block_iCDF[ 10 ][ 18 ] = { +{ + 125, 51, 26, 18, 15, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, + 1, 0 +}, +{ + 198, 105, 45, 22, 15, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, + 1, 0 +}, +{ + 213, 162, 116, 83, 59, 43, 32, 24, + 18, 15, 12, 9, 7, 6, 5, 3, + 2, 0 +}, +{ + 239, 187, 116, 59, 28, 16, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, + 1, 0 +}, +{ + 250, 229, 188, 135, 86, 51, 30, 19, + 13, 10, 8, 6, 5, 4, 3, 2, + 1, 0 +}, +{ + 249, 235, 213, 185, 156, 128, 103, 83, + 66, 53, 42, 33, 26, 21, 17, 13, + 10, 0 +}, +{ + 254, 249, 235, 206, 164, 118, 77, 46, + 27, 16, 10, 7, 5, 4, 3, 2, + 1, 0 +}, +{ + 255, 253, 249, 239, 220, 191, 156, 119, + 85, 57, 37, 23, 15, 10, 6, 4, + 2, 0 +}, +{ + 255, 253, 251, 246, 237, 223, 203, 179, + 152, 124, 98, 75, 55, 40, 29, 21, + 15, 0 +}, +{ + 255, 254, 253, 247, 220, 162, 106, 67, + 42, 28, 18, 12, 9, 6, 4, 3, + 2, 0 +} +}; + +const opus_uint8 silk_pulses_per_block_BITS_Q5[ 9 ][ 18 ] = { +{ + 31, 57, 107, 160, 205, 205, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255 +}, +{ + 69, 47, 67, 111, 166, 205, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255 +}, +{ + 82, 74, 79, 95, 109, 128, 145, 160, + 173, 205, 205, 205, 224, 255, 255, 224, + 255, 224 +}, +{ + 125, 74, 59, 69, 97, 141, 182, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255 +}, +{ + 173, 115, 85, 73, 76, 92, 115, 145, + 173, 205, 224, 224, 255, 255, 255, 255, + 255, 255 +}, +{ + 166, 134, 113, 102, 101, 102, 107, 118, + 125, 138, 145, 155, 166, 182, 192, 192, + 205, 150 +}, +{ + 224, 182, 134, 101, 83, 79, 85, 97, + 120, 145, 173, 205, 224, 255, 255, 255, + 255, 255 +}, +{ + 255, 224, 192, 150, 120, 101, 92, 89, + 93, 102, 118, 134, 160, 182, 192, 224, + 224, 224 +}, +{ + 255, 224, 224, 182, 155, 134, 118, 109, + 104, 102, 106, 111, 118, 131, 145, 160, + 173, 131 +} +}; + +const opus_uint8 silk_rate_levels_iCDF[ 2 ][ 9 ] = +{ +{ + 241, 190, 178, 132, 87, 74, 41, 14, + 0 +}, +{ + 223, 193, 157, 140, 106, 57, 39, 18, + 0 +} +}; + +const opus_uint8 silk_rate_levels_BITS_Q5[ 2 ][ 9 ] = +{ +{ + 131, 74, 141, 79, 80, 138, 95, 104, + 134 +}, +{ + 95, 99, 91, 125, 93, 76, 123, 115, + 123 +} +}; + +const opus_uint8 silk_shell_code_table0[ 152 ] = { + 128, 0, 214, 42, 0, 235, 128, 21, + 0, 244, 184, 72, 11, 0, 248, 214, + 128, 42, 7, 0, 248, 225, 170, 80, + 25, 5, 0, 251, 236, 198, 126, 54, + 18, 3, 0, 250, 238, 211, 159, 82, + 35, 15, 5, 0, 250, 231, 203, 168, + 128, 88, 53, 25, 6, 0, 252, 238, + 216, 185, 148, 108, 71, 40, 18, 4, + 0, 253, 243, 225, 199, 166, 128, 90, + 57, 31, 13, 3, 0, 254, 246, 233, + 212, 183, 147, 109, 73, 44, 23, 10, + 2, 0, 255, 250, 240, 223, 198, 166, + 128, 90, 58, 33, 16, 6, 1, 0, + 255, 251, 244, 231, 210, 181, 146, 110, + 75, 46, 25, 12, 5, 1, 0, 255, + 253, 248, 238, 221, 196, 164, 128, 92, + 60, 35, 18, 8, 3, 1, 0, 255, + 253, 249, 242, 229, 208, 180, 146, 110, + 76, 48, 27, 14, 7, 3, 1, 0 +}; + +const opus_uint8 silk_shell_code_table1[ 152 ] = { + 129, 0, 207, 50, 0, 236, 129, 20, + 0, 245, 185, 72, 10, 0, 249, 213, + 129, 42, 6, 0, 250, 226, 169, 87, + 27, 4, 0, 251, 233, 194, 130, 62, + 20, 4, 0, 250, 236, 207, 160, 99, + 47, 17, 3, 0, 255, 240, 217, 182, + 131, 81, 41, 11, 1, 0, 255, 254, + 233, 201, 159, 107, 61, 20, 2, 1, + 0, 255, 249, 233, 206, 170, 128, 86, + 50, 23, 7, 1, 0, 255, 250, 238, + 217, 186, 148, 108, 70, 39, 18, 6, + 1, 0, 255, 252, 243, 226, 200, 166, + 128, 90, 56, 30, 13, 4, 1, 0, + 255, 252, 245, 231, 209, 180, 146, 110, + 76, 47, 25, 11, 4, 1, 0, 255, + 253, 248, 237, 219, 194, 163, 128, 93, + 62, 37, 19, 8, 3, 1, 0, 255, + 254, 250, 241, 226, 205, 177, 145, 111, + 79, 51, 30, 15, 6, 2, 1, 0 +}; + +const opus_uint8 silk_shell_code_table2[ 152 ] = { + 129, 0, 203, 54, 0, 234, 129, 23, + 0, 245, 184, 73, 10, 0, 250, 215, + 129, 41, 5, 0, 252, 232, 173, 86, + 24, 3, 0, 253, 240, 200, 129, 56, + 15, 2, 0, 253, 244, 217, 164, 94, + 38, 10, 1, 0, 253, 245, 226, 189, + 132, 71, 27, 7, 1, 0, 253, 246, + 231, 203, 159, 105, 56, 23, 6, 1, + 0, 255, 248, 235, 213, 179, 133, 85, + 47, 19, 5, 1, 0, 255, 254, 243, + 221, 194, 159, 117, 70, 37, 12, 2, + 1, 0, 255, 254, 248, 234, 208, 171, + 128, 85, 48, 22, 8, 2, 1, 0, + 255, 254, 250, 240, 220, 189, 149, 107, + 67, 36, 16, 6, 2, 1, 0, 255, + 254, 251, 243, 227, 201, 166, 128, 90, + 55, 29, 13, 5, 2, 1, 0, 255, + 254, 252, 246, 234, 213, 183, 147, 109, + 73, 43, 22, 10, 4, 2, 1, 0 +}; + +const opus_uint8 silk_shell_code_table3[ 152 ] = { + 130, 0, 200, 58, 0, 231, 130, 26, + 0, 244, 184, 76, 12, 0, 249, 214, + 130, 43, 6, 0, 252, 232, 173, 87, + 24, 3, 0, 253, 241, 203, 131, 56, + 14, 2, 0, 254, 246, 221, 167, 94, + 35, 8, 1, 0, 254, 249, 232, 193, + 130, 65, 23, 5, 1, 0, 255, 251, + 239, 211, 162, 99, 45, 15, 4, 1, + 0, 255, 251, 243, 223, 186, 131, 74, + 33, 11, 3, 1, 0, 255, 252, 245, + 230, 202, 158, 105, 57, 24, 8, 2, + 1, 0, 255, 253, 247, 235, 214, 179, + 132, 84, 44, 19, 7, 2, 1, 0, + 255, 254, 250, 240, 223, 196, 159, 112, + 69, 36, 15, 6, 2, 1, 0, 255, + 254, 253, 245, 231, 209, 176, 136, 93, + 55, 27, 11, 3, 2, 1, 0, 255, + 254, 253, 252, 239, 221, 194, 158, 117, + 76, 42, 18, 4, 3, 2, 1, 0 +}; + +const opus_uint8 silk_shell_code_table_offsets[ 17 ] = { + 0, 0, 2, 5, 9, 14, 20, 27, + 35, 44, 54, 65, 77, 90, 104, 119, + 135 +}; + +const opus_uint8 silk_sign_iCDF[ 42 ] = { + 254, 49, 67, 77, 82, 93, 99, + 198, 11, 18, 24, 31, 36, 45, + 255, 46, 66, 78, 87, 94, 104, + 208, 14, 21, 32, 42, 51, 66, + 255, 94, 104, 109, 112, 115, 118, + 248, 53, 69, 80, 88, 95, 102 +}; diff --git a/TelegramClient.Opus/opus/silk/tuning_parameters.h b/TelegramClient.Opus/opus/silk/tuning_parameters.h new file mode 100755 index 0000000..e1057bb --- /dev/null +++ b/TelegramClient.Opus/opus/silk/tuning_parameters.h @@ -0,0 +1,171 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_TUNING_PARAMETERS_H +#define SILK_TUNING_PARAMETERS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Decay time for bitreservoir */ +#define BITRESERVOIR_DECAY_TIME_MS 500 + +/*******************/ +/* Pitch estimator */ +/*******************/ + +/* Level of noise floor for whitening filter LPC analysis in pitch analysis */ +#define FIND_PITCH_WHITE_NOISE_FRACTION 1e-3f + +/* Bandwidth expansion for whitening filter in pitch analysis */ +#define FIND_PITCH_BANDWIDTH_EXPANSION 0.99f + +/*********************/ +/* Linear prediction */ +/*********************/ + +/* LPC analysis regularization */ +#define FIND_LPC_COND_FAC 1e-5f + +/* LTP analysis defines */ +#define FIND_LTP_COND_FAC 1e-5f +#define LTP_DAMPING 0.05f +#define LTP_SMOOTHING 0.1f + +/* LTP quantization settings */ +#define MU_LTP_QUANT_NB 0.03f +#define MU_LTP_QUANT_MB 0.025f +#define MU_LTP_QUANT_WB 0.02f + +/* Max cumulative LTP gain */ +#define MAX_SUM_LOG_GAIN_DB 250.0f + +/***********************/ +/* High pass filtering */ +/***********************/ + +/* Smoothing parameters for low end of pitch frequency range estimation */ +#define VARIABLE_HP_SMTH_COEF1 0.1f +#define VARIABLE_HP_SMTH_COEF2 0.015f +#define VARIABLE_HP_MAX_DELTA_FREQ 0.4f + +/* Min and max cut-off frequency values (-3 dB points) */ +#define VARIABLE_HP_MIN_CUTOFF_HZ 60 +#define VARIABLE_HP_MAX_CUTOFF_HZ 100 + +/***********/ +/* Various */ +/***********/ + +/* VAD threshold */ +#define SPEECH_ACTIVITY_DTX_THRES 0.05f + +/* Speech Activity LBRR enable threshold */ +#define LBRR_SPEECH_ACTIVITY_THRES 0.3f + +/*************************/ +/* Perceptual parameters */ +/*************************/ + +/* reduction in coding SNR during low speech activity */ +#define BG_SNR_DECR_dB 2.0f + +/* factor for reducing quantization noise during voiced speech */ +#define HARM_SNR_INCR_dB 2.0f + +/* factor for reducing quantization noise for unvoiced sparse signals */ +#define SPARSE_SNR_INCR_dB 2.0f + +/* threshold for sparseness measure above which to use lower quantization offset during unvoiced */ +#define SPARSENESS_THRESHOLD_QNT_OFFSET 0.75f + +/* warping control */ +#define WARPING_MULTIPLIER 0.015f + +/* fraction added to first autocorrelation value */ +#define SHAPE_WHITE_NOISE_FRACTION 5e-5f + +/* noise shaping filter chirp factor */ +#define BANDWIDTH_EXPANSION 0.95f + +/* difference between chirp factors for analysis and synthesis noise shaping filters at low bitrates */ +#define LOW_RATE_BANDWIDTH_EXPANSION_DELTA 0.01f + +/* extra harmonic boosting (signal shaping) at low bitrates */ +#define LOW_RATE_HARMONIC_BOOST 0.1f + +/* extra harmonic boosting (signal shaping) for noisy input signals */ +#define LOW_INPUT_QUALITY_HARMONIC_BOOST 0.1f + +/* harmonic noise shaping */ +#define HARMONIC_SHAPING 0.3f + +/* extra harmonic noise shaping for high bitrates or noisy input */ +#define HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING 0.2f + +/* parameter for shaping noise towards higher frequencies */ +#define HP_NOISE_COEF 0.25f + +/* parameter for shaping noise even more towards higher frequencies during voiced speech */ +#define HARM_HP_NOISE_COEF 0.35f + +/* parameter for applying a high-pass tilt to the input signal */ +#define INPUT_TILT 0.05f + +/* parameter for extra high-pass tilt to the input signal at high rates */ +#define HIGH_RATE_INPUT_TILT 0.1f + +/* parameter for reducing noise at the very low frequencies */ +#define LOW_FREQ_SHAPING 4.0f + +/* less reduction of noise at the very low frequencies for signals with low SNR at low frequencies */ +#define LOW_QUALITY_LOW_FREQ_SHAPING_DECR 0.5f + +/* subframe smoothing coefficient for HarmBoost, HarmShapeGain, Tilt (lower -> more smoothing) */ +#define SUBFR_SMTH_COEF 0.4f + +/* parameters defining the R/D tradeoff in the residual quantizer */ +#define LAMBDA_OFFSET 1.2f +#define LAMBDA_SPEECH_ACT -0.2f +#define LAMBDA_DELAYED_DECISIONS -0.05f +#define LAMBDA_INPUT_QUALITY -0.1f +#define LAMBDA_CODING_QUALITY -0.2f +#define LAMBDA_QUANT_OFFSET 0.8f + +/* Compensation in bitrate calculations for 10 ms modes */ +#define REDUCE_BITRATE_10_MS_BPS 2200 + +/* Maximum time before allowing a bandwidth transition */ +#define MAX_BANDWIDTH_SWITCH_DELAY_MS 5000 + +#ifdef __cplusplus +} +#endif + +#endif /* SILK_TUNING_PARAMETERS_H */ diff --git a/TelegramClient.Opus/opus/silk/typedef.h b/TelegramClient.Opus/opus/silk/typedef.h new file mode 100755 index 0000000..97b7e70 --- /dev/null +++ b/TelegramClient.Opus/opus/silk/typedef.h @@ -0,0 +1,78 @@ +/*********************************************************************** +Copyright (c) 2006-2011, Skype Limited. 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. +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific 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. +***********************************************************************/ + +#ifndef SILK_TYPEDEF_H +#define SILK_TYPEDEF_H + +#include "opus_types.h" +#include "opus_defines.h" + +#ifndef FIXED_POINT +# include +# define silk_float float +# define silk_float_MAX FLT_MAX +#endif + +#define silk_int64_MAX ((opus_int64)0x7FFFFFFFFFFFFFFFLL) /* 2^63 - 1 */ +#define silk_int64_MIN ((opus_int64)0x8000000000000000LL) /* -2^63 */ +#define silk_int32_MAX 0x7FFFFFFF /* 2^31 - 1 = 2147483647 */ +#define silk_int32_MIN ((opus_int32)0x80000000) /* -2^31 = -2147483648 */ +#define silk_int16_MAX 0x7FFF /* 2^15 - 1 = 32767 */ +#define silk_int16_MIN ((opus_int16)0x8000) /* -2^15 = -32768 */ +#define silk_int8_MAX 0x7F /* 2^7 - 1 = 127 */ +#define silk_int8_MIN ((opus_int8)0x80) /* -2^7 = -128 */ +#define silk_uint8_MAX 0xFF /* 2^8 - 1 = 255 */ + +#define silk_TRUE 1 +#define silk_FALSE 0 + +/* assertions */ +#if (defined _WIN32 && !defined _WINCE && !defined(__GNUC__) && !defined(NO_ASSERTS)) +# ifndef silk_assert +# include /* ASSERTE() */ +# define silk_assert(COND) _ASSERTE(COND) +# endif +#else +# ifdef ENABLE_ASSERTIONS +# include +# include +#define silk_fatal(str) _silk_fatal(str, __FILE__, __LINE__); +#ifdef __GNUC__ +__attribute__((noreturn)) +#endif +static OPUS_INLINE void _silk_fatal(const char *str, const char *file, int line) +{ + fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str); + abort(); +} +# define silk_assert(COND) {if (!(COND)) {silk_fatal("assertion failed: " #COND);}} +# else +# define silk_assert(COND) +# endif +#endif + +#endif /* SILK_TYPEDEF_H */ diff --git a/TelegramClient.Opus/opus/src/analysis.c b/TelegramClient.Opus/opus/src/analysis.c new file mode 100755 index 0000000..778a62a --- /dev/null +++ b/TelegramClient.Opus/opus/src/analysis.c @@ -0,0 +1,645 @@ +/* Copyright (c) 2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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 FOUNDATION 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "kiss_fft.h" +#include "celt.h" +#include "modes.h" +#include "arch.h" +#include "quant_bands.h" +#include +#include "analysis.h" +#include "mlp.h" +#include "stack_alloc.h" + +extern const MLP net; + +#ifndef M_PI +#define M_PI 3.141592653 +#endif + +static const float dct_table[128] = { + 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, + 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, + 0.351851f, 0.338330f, 0.311806f, 0.273300f, 0.224292f, 0.166664f, 0.102631f, 0.034654f, + -0.034654f,-0.102631f,-0.166664f,-0.224292f,-0.273300f,-0.311806f,-0.338330f,-0.351851f, + 0.346760f, 0.293969f, 0.196424f, 0.068975f,-0.068975f,-0.196424f,-0.293969f,-0.346760f, + -0.346760f,-0.293969f,-0.196424f,-0.068975f, 0.068975f, 0.196424f, 0.293969f, 0.346760f, + 0.338330f, 0.224292f, 0.034654f,-0.166664f,-0.311806f,-0.351851f,-0.273300f,-0.102631f, + 0.102631f, 0.273300f, 0.351851f, 0.311806f, 0.166664f,-0.034654f,-0.224292f,-0.338330f, + 0.326641f, 0.135299f,-0.135299f,-0.326641f,-0.326641f,-0.135299f, 0.135299f, 0.326641f, + 0.326641f, 0.135299f,-0.135299f,-0.326641f,-0.326641f,-0.135299f, 0.135299f, 0.326641f, + 0.311806f, 0.034654f,-0.273300f,-0.338330f,-0.102631f, 0.224292f, 0.351851f, 0.166664f, + -0.166664f,-0.351851f,-0.224292f, 0.102631f, 0.338330f, 0.273300f,-0.034654f,-0.311806f, + 0.293969f,-0.068975f,-0.346760f,-0.196424f, 0.196424f, 0.346760f, 0.068975f,-0.293969f, + -0.293969f, 0.068975f, 0.346760f, 0.196424f,-0.196424f,-0.346760f,-0.068975f, 0.293969f, + 0.273300f,-0.166664f,-0.338330f, 0.034654f, 0.351851f, 0.102631f,-0.311806f,-0.224292f, + 0.224292f, 0.311806f,-0.102631f,-0.351851f,-0.034654f, 0.338330f, 0.166664f,-0.273300f, +}; + +static const float analysis_window[240] = { + 0.000043f, 0.000171f, 0.000385f, 0.000685f, 0.001071f, 0.001541f, 0.002098f, 0.002739f, + 0.003466f, 0.004278f, 0.005174f, 0.006156f, 0.007222f, 0.008373f, 0.009607f, 0.010926f, + 0.012329f, 0.013815f, 0.015385f, 0.017037f, 0.018772f, 0.020590f, 0.022490f, 0.024472f, + 0.026535f, 0.028679f, 0.030904f, 0.033210f, 0.035595f, 0.038060f, 0.040604f, 0.043227f, + 0.045928f, 0.048707f, 0.051564f, 0.054497f, 0.057506f, 0.060591f, 0.063752f, 0.066987f, + 0.070297f, 0.073680f, 0.077136f, 0.080665f, 0.084265f, 0.087937f, 0.091679f, 0.095492f, + 0.099373f, 0.103323f, 0.107342f, 0.111427f, 0.115579f, 0.119797f, 0.124080f, 0.128428f, + 0.132839f, 0.137313f, 0.141849f, 0.146447f, 0.151105f, 0.155823f, 0.160600f, 0.165435f, + 0.170327f, 0.175276f, 0.180280f, 0.185340f, 0.190453f, 0.195619f, 0.200838f, 0.206107f, + 0.211427f, 0.216797f, 0.222215f, 0.227680f, 0.233193f, 0.238751f, 0.244353f, 0.250000f, + 0.255689f, 0.261421f, 0.267193f, 0.273005f, 0.278856f, 0.284744f, 0.290670f, 0.296632f, + 0.302628f, 0.308658f, 0.314721f, 0.320816f, 0.326941f, 0.333097f, 0.339280f, 0.345492f, + 0.351729f, 0.357992f, 0.364280f, 0.370590f, 0.376923f, 0.383277f, 0.389651f, 0.396044f, + 0.402455f, 0.408882f, 0.415325f, 0.421783f, 0.428254f, 0.434737f, 0.441231f, 0.447736f, + 0.454249f, 0.460770f, 0.467298f, 0.473832f, 0.480370f, 0.486912f, 0.493455f, 0.500000f, + 0.506545f, 0.513088f, 0.519630f, 0.526168f, 0.532702f, 0.539230f, 0.545751f, 0.552264f, + 0.558769f, 0.565263f, 0.571746f, 0.578217f, 0.584675f, 0.591118f, 0.597545f, 0.603956f, + 0.610349f, 0.616723f, 0.623077f, 0.629410f, 0.635720f, 0.642008f, 0.648271f, 0.654508f, + 0.660720f, 0.666903f, 0.673059f, 0.679184f, 0.685279f, 0.691342f, 0.697372f, 0.703368f, + 0.709330f, 0.715256f, 0.721144f, 0.726995f, 0.732807f, 0.738579f, 0.744311f, 0.750000f, + 0.755647f, 0.761249f, 0.766807f, 0.772320f, 0.777785f, 0.783203f, 0.788573f, 0.793893f, + 0.799162f, 0.804381f, 0.809547f, 0.814660f, 0.819720f, 0.824724f, 0.829673f, 0.834565f, + 0.839400f, 0.844177f, 0.848895f, 0.853553f, 0.858151f, 0.862687f, 0.867161f, 0.871572f, + 0.875920f, 0.880203f, 0.884421f, 0.888573f, 0.892658f, 0.896677f, 0.900627f, 0.904508f, + 0.908321f, 0.912063f, 0.915735f, 0.919335f, 0.922864f, 0.926320f, 0.929703f, 0.933013f, + 0.936248f, 0.939409f, 0.942494f, 0.945503f, 0.948436f, 0.951293f, 0.954072f, 0.956773f, + 0.959396f, 0.961940f, 0.964405f, 0.966790f, 0.969096f, 0.971321f, 0.973465f, 0.975528f, + 0.977510f, 0.979410f, 0.981228f, 0.982963f, 0.984615f, 0.986185f, 0.987671f, 0.989074f, + 0.990393f, 0.991627f, 0.992778f, 0.993844f, 0.994826f, 0.995722f, 0.996534f, 0.997261f, + 0.997902f, 0.998459f, 0.998929f, 0.999315f, 0.999615f, 0.999829f, 0.999957f, 1.000000f, +}; + +static const int tbands[NB_TBANDS+1] = { + 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120 +}; + +static const int extra_bands[NB_TOT_BANDS+1] = { + 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120, 160, 200 +}; + +/*static const float tweight[NB_TBANDS+1] = { + .3, .4, .5, .6, .7, .8, .9, 1., 1., 1., 1., 1., 1., 1., .8, .7, .6, .5 +};*/ + +#define NB_TONAL_SKIP_BANDS 9 + +#define cA 0.43157974f +#define cB 0.67848403f +#define cC 0.08595542f +#define cE ((float)M_PI/2) +static OPUS_INLINE float fast_atan2f(float y, float x) { + float x2, y2; + /* Should avoid underflow on the values we'll get */ + if (ABS16(x)+ABS16(y)<1e-9f) + { + x*=1e12f; + y*=1e12f; + } + x2 = x*x; + y2 = y*y; + if(x2read_pos; + curr_lookahead = tonal->write_pos-tonal->read_pos; + if (curr_lookahead<0) + curr_lookahead += DETECT_SIZE; + + if (len > 480 && pos != tonal->write_pos) + { + pos++; + if (pos==DETECT_SIZE) + pos=0; + } + if (pos == tonal->write_pos) + pos--; + if (pos<0) + pos = DETECT_SIZE-1; + OPUS_COPY(info_out, &tonal->info[pos], 1); + tonal->read_subframe += len/120; + while (tonal->read_subframe>=4) + { + tonal->read_subframe -= 4; + tonal->read_pos++; + } + if (tonal->read_pos>=DETECT_SIZE) + tonal->read_pos-=DETECT_SIZE; + + /* Compensate for the delay in the features themselves. + FIXME: Need a better estimate the 10 I just made up */ + curr_lookahead = IMAX(curr_lookahead-10, 0); + + psum=0; + /* Summing the probability of transition patterns that involve music at + time (DETECT_SIZE-curr_lookahead-1) */ + for (i=0;ipmusic[i]; + for (;ipspeech[i]; + psum = psum*tonal->music_confidence + (1-psum)*tonal->speech_confidence; + /*printf("%f %f %f\n", psum, info_out->music_prob, info_out->tonality);*/ + + info_out->music_prob = psum; +} + +void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info_out, const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix) +{ + int i, b; + const kiss_fft_state *kfft; + VARDECL(kiss_fft_cpx, in); + VARDECL(kiss_fft_cpx, out); + int N = 480, N2=240; + float * OPUS_RESTRICT A = tonal->angle; + float * OPUS_RESTRICT dA = tonal->d_angle; + float * OPUS_RESTRICT d2A = tonal->d2_angle; + VARDECL(float, tonality); + VARDECL(float, noisiness); + float band_tonality[NB_TBANDS]; + float logE[NB_TBANDS]; + float BFCC[8]; + float features[25]; + float frame_tonality; + float max_frame_tonality; + /*float tw_sum=0;*/ + float frame_noisiness; + const float pi4 = (float)(M_PI*M_PI*M_PI*M_PI); + float slope=0; + float frame_stationarity; + float relativeE; + float frame_probs[2]; + float alpha, alphaE, alphaE2; + float frame_loudness; + float bandwidth_mask; + int bandwidth=0; + float maxE = 0; + float noise_floor; + int remaining; + AnalysisInfo *info; + SAVE_STACK; + + tonal->last_transition++; + alpha = 1.f/IMIN(20, 1+tonal->count); + alphaE = 1.f/IMIN(50, 1+tonal->count); + alphaE2 = 1.f/IMIN(1000, 1+tonal->count); + + if (tonal->count<4) + tonal->music_prob = .5; + kfft = celt_mode->mdct.kfft[0]; + if (tonal->count==0) + tonal->mem_fill = 240; + downmix(x, &tonal->inmem[tonal->mem_fill], IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C); + if (tonal->mem_fill+len < ANALYSIS_BUF_SIZE) + { + tonal->mem_fill += len; + /* Don't have enough to update the analysis */ + RESTORE_STACK; + return; + } + info = &tonal->info[tonal->write_pos++]; + if (tonal->write_pos>=DETECT_SIZE) + tonal->write_pos-=DETECT_SIZE; + + ALLOC(in, 480, kiss_fft_cpx); + ALLOC(out, 480, kiss_fft_cpx); + ALLOC(tonality, 240, float); + ALLOC(noisiness, 240, float); + for (i=0;iinmem[i]); + in[i].i = (kiss_fft_scalar)(w*tonal->inmem[N2+i]); + in[N-i-1].r = (kiss_fft_scalar)(w*tonal->inmem[N-i-1]); + in[N-i-1].i = (kiss_fft_scalar)(w*tonal->inmem[N+N2-i-1]); + } + OPUS_MOVE(tonal->inmem, tonal->inmem+ANALYSIS_BUF_SIZE-240, 240); + remaining = len - (ANALYSIS_BUF_SIZE-tonal->mem_fill); + downmix(x, &tonal->inmem[240], remaining, offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C); + tonal->mem_fill = 240 + remaining; + opus_fft(kfft, in, out); + + for (i=1;iactivity = 0; + frame_noisiness = 0; + frame_stationarity = 0; + if (!tonal->count) + { + for (b=0;blowE[b] = 1e10; + tonal->highE[b] = -1e10; + } + } + relativeE = 0; + frame_loudness = 0; + for (b=0;bE[tonal->E_count][b] = E; + frame_noisiness += nE/(1e-15f+E); + + frame_loudness += (float)sqrt(E+1e-10f); + logE[b] = (float)log(E+1e-10f); + tonal->lowE[b] = MIN32(logE[b], tonal->lowE[b]+.01f); + tonal->highE[b] = MAX32(logE[b], tonal->highE[b]-.1f); + if (tonal->highE[b] < tonal->lowE[b]+1.f) + { + tonal->highE[b]+=.5f; + tonal->lowE[b]-=.5f; + } + relativeE += (logE[b]-tonal->lowE[b])/(1e-15f+tonal->highE[b]-tonal->lowE[b]); + + L1=L2=0; + for (i=0;iE[i][b]); + L2 += tonal->E[i][b]; + } + + stationarity = MIN16(0.99f,L1/(float)sqrt(1e-15+NB_FRAMES*L2)); + stationarity *= stationarity; + stationarity *= stationarity; + frame_stationarity += stationarity; + /*band_tonality[b] = tE/(1e-15+E)*/; + band_tonality[b] = MAX16(tE/(1e-15f+E), stationarity*tonal->prev_band_tonality[b]); +#if 0 + if (b>=NB_TONAL_SKIP_BANDS) + { + frame_tonality += tweight[b]*band_tonality[b]; + tw_sum += tweight[b]; + } +#else + frame_tonality += band_tonality[b]; + if (b>=NB_TBANDS-NB_TONAL_SKIP_BANDS) + frame_tonality -= band_tonality[b-NB_TBANDS+NB_TONAL_SKIP_BANDS]; +#endif + max_frame_tonality = MAX16(max_frame_tonality, (1.f+.03f*(b-NB_TBANDS))*frame_tonality); + slope += band_tonality[b]*(b-8); + /*printf("%f %f ", band_tonality[b], stationarity);*/ + tonal->prev_band_tonality[b] = band_tonality[b]; + } + + bandwidth_mask = 0; + bandwidth = 0; + maxE = 0; + noise_floor = 5.7e-4f/(1<<(IMAX(0,lsb_depth-8))); +#ifdef FIXED_POINT + noise_floor *= 1<<(15+SIG_SHIFT); +#endif + noise_floor *= noise_floor; + for (b=0;bmeanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E); + E = MAX32(E, tonal->meanE[b]); + /* Use a simple follower with 13 dB/Bark slope for spreading function */ + bandwidth_mask = MAX32(.05f*bandwidth_mask, E); + /* Consider the band "active" only if all these conditions are met: + 1) less than 10 dB below the simple follower + 2) less than 90 dB below the peak band (maximal masking possible considering + both the ATH and the loudness-dependent slope of the spreading function) + 3) above the PCM quantization noise floor + */ + if (E>.1*bandwidth_mask && E*1e9f > maxE && E > noise_floor*(band_end-band_start)) + bandwidth = b; + } + if (tonal->count<=2) + bandwidth = 20; + frame_loudness = 20*(float)log10(frame_loudness); + tonal->Etracker = MAX32(tonal->Etracker-.03f, frame_loudness); + tonal->lowECount *= (1-alphaE); + if (frame_loudness < tonal->Etracker-30) + tonal->lowECount += alphaE; + + for (i=0;i<8;i++) + { + float sum=0; + for (b=0;b<16;b++) + sum += dct_table[i*16+b]*logE[b]; + BFCC[i] = sum; + } + + frame_stationarity /= NB_TBANDS; + relativeE /= NB_TBANDS; + if (tonal->count<10) + relativeE = .5; + frame_noisiness /= NB_TBANDS; +#if 1 + info->activity = frame_noisiness + (1-frame_noisiness)*relativeE; +#else + info->activity = .5*(1+frame_noisiness-frame_stationarity); +#endif + frame_tonality = (max_frame_tonality/(NB_TBANDS-NB_TONAL_SKIP_BANDS)); + frame_tonality = MAX16(frame_tonality, tonal->prev_tonality*.8f); + tonal->prev_tonality = frame_tonality; + + slope /= 8*8; + info->tonality_slope = slope; + + tonal->E_count = (tonal->E_count+1)%NB_FRAMES; + tonal->count++; + info->tonality = frame_tonality; + + for (i=0;i<4;i++) + features[i] = -0.12299f*(BFCC[i]+tonal->mem[i+24]) + 0.49195f*(tonal->mem[i]+tonal->mem[i+16]) + 0.69693f*tonal->mem[i+8] - 1.4349f*tonal->cmean[i]; + + for (i=0;i<4;i++) + tonal->cmean[i] = (1-alpha)*tonal->cmean[i] + alpha*BFCC[i]; + + for (i=0;i<4;i++) + features[4+i] = 0.63246f*(BFCC[i]-tonal->mem[i+24]) + 0.31623f*(tonal->mem[i]-tonal->mem[i+16]); + for (i=0;i<3;i++) + features[8+i] = 0.53452f*(BFCC[i]+tonal->mem[i+24]) - 0.26726f*(tonal->mem[i]+tonal->mem[i+16]) -0.53452f*tonal->mem[i+8]; + + if (tonal->count > 5) + { + for (i=0;i<9;i++) + tonal->std[i] = (1-alpha)*tonal->std[i] + alpha*features[i]*features[i]; + } + + for (i=0;i<8;i++) + { + tonal->mem[i+24] = tonal->mem[i+16]; + tonal->mem[i+16] = tonal->mem[i+8]; + tonal->mem[i+8] = tonal->mem[i]; + tonal->mem[i] = BFCC[i]; + } + for (i=0;i<9;i++) + features[11+i] = (float)sqrt(tonal->std[i]); + features[20] = info->tonality; + features[21] = info->activity; + features[22] = frame_stationarity; + features[23] = info->tonality_slope; + features[24] = tonal->lowECount; + +#ifndef DISABLE_FLOAT_API + mlp_process(&net, features, frame_probs); + frame_probs[0] = .5f*(frame_probs[0]+1); + /* Curve fitting between the MLP probability and the actual probability */ + frame_probs[0] = .01f + 1.21f*frame_probs[0]*frame_probs[0] - .23f*(float)pow(frame_probs[0], 10); + /* Probability of active audio (as opposed to silence) */ + frame_probs[1] = .5f*frame_probs[1]+.5f; + /* Consider that silence has a 50-50 probability. */ + frame_probs[0] = frame_probs[1]*frame_probs[0] + (1-frame_probs[1])*.5f; + + /*printf("%f %f ", frame_probs[0], frame_probs[1]);*/ + { + /* Probability of state transition */ + float tau; + /* Represents independence of the MLP probabilities, where + beta=1 means fully independent. */ + float beta; + /* Denormalized probability of speech (p0) and music (p1) after update */ + float p0, p1; + /* Probabilities for "all speech" and "all music" */ + float s0, m0; + /* Probability sum for renormalisation */ + float psum; + /* Instantaneous probability of speech and music, with beta pre-applied. */ + float speech0; + float music0; + + /* One transition every 3 minutes of active audio */ + tau = .00005f*frame_probs[1]; + beta = .05f; + if (1) { + /* Adapt beta based on how "unexpected" the new prob is */ + float p, q; + p = MAX16(.05f,MIN16(.95f,frame_probs[0])); + q = MAX16(.05f,MIN16(.95f,tonal->music_prob)); + beta = .01f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p)); + } + /* p0 and p1 are the probabilities of speech and music at this frame + using only information from previous frame and applying the + state transition model */ + p0 = (1-tonal->music_prob)*(1-tau) + tonal->music_prob *tau; + p1 = tonal->music_prob *(1-tau) + (1-tonal->music_prob)*tau; + /* We apply the current probability with exponent beta to work around + the fact that the probability estimates aren't independent. */ + p0 *= (float)pow(1-frame_probs[0], beta); + p1 *= (float)pow(frame_probs[0], beta); + /* Normalise the probabilities to get the Marokv probability of music. */ + tonal->music_prob = p1/(p0+p1); + info->music_prob = tonal->music_prob; + + /* This chunk of code deals with delayed decision. */ + psum=1e-20f; + /* Instantaneous probability of speech and music, with beta pre-applied. */ + speech0 = (float)pow(1-frame_probs[0], beta); + music0 = (float)pow(frame_probs[0], beta); + if (tonal->count==1) + { + tonal->pspeech[0]=.5; + tonal->pmusic [0]=.5; + } + /* Updated probability of having only speech (s0) or only music (m0), + before considering the new observation. */ + s0 = tonal->pspeech[0] + tonal->pspeech[1]; + m0 = tonal->pmusic [0] + tonal->pmusic [1]; + /* Updates s0 and m0 with instantaneous probability. */ + tonal->pspeech[0] = s0*(1-tau)*speech0; + tonal->pmusic [0] = m0*(1-tau)*music0; + /* Propagate the transition probabilities */ + for (i=1;ipspeech[i] = tonal->pspeech[i+1]*speech0; + tonal->pmusic [i] = tonal->pmusic [i+1]*music0; + } + /* Probability that the latest frame is speech, when all the previous ones were music. */ + tonal->pspeech[DETECT_SIZE-1] = m0*tau*speech0; + /* Probability that the latest frame is music, when all the previous ones were speech. */ + tonal->pmusic [DETECT_SIZE-1] = s0*tau*music0; + + /* Renormalise probabilities to 1 */ + for (i=0;ipspeech[i] + tonal->pmusic[i]; + psum = 1.f/psum; + for (i=0;ipspeech[i] *= psum; + tonal->pmusic [i] *= psum; + } + psum = tonal->pmusic[0]; + for (i=1;ipspeech[i]; + + /* Estimate our confidence in the speech/music decisions */ + if (frame_probs[1]>.75) + { + if (tonal->music_prob>.9) + { + float adapt; + adapt = 1.f/(++tonal->music_confidence_count); + tonal->music_confidence_count = IMIN(tonal->music_confidence_count, 500); + tonal->music_confidence += adapt*MAX16(-.2f,frame_probs[0]-tonal->music_confidence); + } + if (tonal->music_prob<.1) + { + float adapt; + adapt = 1.f/(++tonal->speech_confidence_count); + tonal->speech_confidence_count = IMIN(tonal->speech_confidence_count, 500); + tonal->speech_confidence += adapt*MIN16(.2f,frame_probs[0]-tonal->speech_confidence); + } + } else { + if (tonal->music_confidence_count==0) + tonal->music_confidence = .9f; + if (tonal->speech_confidence_count==0) + tonal->speech_confidence = .1f; + } + } + if (tonal->last_music != (tonal->music_prob>.5f)) + tonal->last_transition=0; + tonal->last_music = tonal->music_prob>.5f; +#else + info->music_prob = 0; +#endif + /*for (i=0;i<25;i++) + printf("%f ", features[i]); + printf("\n");*/ + + info->bandwidth = bandwidth; + /*printf("%d %d\n", info->bandwidth, info->opus_bandwidth);*/ + info->noisiness = frame_noisiness; + info->valid = 1; + if (info_out!=NULL) + OPUS_COPY(info_out, info, 1); + RESTORE_STACK; +} + +void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm, + int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs, + int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info) +{ + int offset; + int pcm_len; + + if (analysis_pcm != NULL) + { + /* Avoid overflow/wrap-around of the analysis buffer */ + analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/100, analysis_frame_size); + + pcm_len = analysis_frame_size - analysis->analysis_offset; + offset = analysis->analysis_offset; + do { + tonality_analysis(analysis, NULL, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, c1, c2, C, lsb_depth, downmix); + offset += 480; + pcm_len -= 480; + } while (pcm_len>0); + analysis->analysis_offset = analysis_frame_size; + + analysis->analysis_offset -= frame_size; + } + + analysis_info->valid = 0; + tonality_get_info(analysis, analysis_info, frame_size); +} diff --git a/TelegramClient.Opus/opus/src/analysis.h b/TelegramClient.Opus/opus/src/analysis.h new file mode 100755 index 0000000..be0388f --- /dev/null +++ b/TelegramClient.Opus/opus/src/analysis.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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 FOUNDATION 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. +*/ + +#ifndef ANALYSIS_H +#define ANALYSIS_H + +#include "celt.h" +#include "opus_private.h" + +#define NB_FRAMES 8 +#define NB_TBANDS 18 +#define NB_TOT_BANDS 21 +#define ANALYSIS_BUF_SIZE 720 /* 15 ms at 48 kHz */ + +#define DETECT_SIZE 200 + +typedef struct { + float angle[240]; + float d_angle[240]; + float d2_angle[240]; + opus_val32 inmem[ANALYSIS_BUF_SIZE]; + int mem_fill; /* number of usable samples in the buffer */ + float prev_band_tonality[NB_TBANDS]; + float prev_tonality; + float E[NB_FRAMES][NB_TBANDS]; + float lowE[NB_TBANDS]; + float highE[NB_TBANDS]; + float meanE[NB_TOT_BANDS]; + float mem[32]; + float cmean[8]; + float std[9]; + float music_prob; + float Etracker; + float lowECount; + int E_count; + int last_music; + int last_transition; + int count; + float subframe_mem[3]; + int analysis_offset; + /** Probability of having speech for time i to DETECT_SIZE-1 (and music before). + pspeech[0] is the probability that all frames in the window are speech. */ + float pspeech[DETECT_SIZE]; + /** Probability of having music for time i to DETECT_SIZE-1 (and speech before). + pmusic[0] is the probability that all frames in the window are music. */ + float pmusic[DETECT_SIZE]; + float speech_confidence; + float music_confidence; + int speech_confidence_count; + int music_confidence_count; + int write_pos; + int read_pos; + int read_subframe; + AnalysisInfo info[DETECT_SIZE]; +} TonalityAnalysisState; + +void tonality_analysis(TonalityAnalysisState *tonal, AnalysisInfo *info, + const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix); + +void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len); + +void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm, + int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs, + int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info); + +#endif diff --git a/TelegramClient.Opus/opus/src/mlp.c b/TelegramClient.Opus/opus/src/mlp.c new file mode 100755 index 0000000..4638602 --- /dev/null +++ b/TelegramClient.Opus/opus/src/mlp.c @@ -0,0 +1,140 @@ +/* Copyright (c) 2008-2011 Octasic Inc. + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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 FOUNDATION 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "opus_types.h" +#include "opus_defines.h" + +#include +#include "mlp.h" +#include "arch.h" +#include "tansig_table.h" +#define MAX_NEURONS 100 + +#if 0 +static OPUS_INLINE opus_val16 tansig_approx(opus_val32 _x) /* Q19 */ +{ + int i; + opus_val16 xx; /* Q11 */ + /*double x, y;*/ + opus_val16 dy, yy; /* Q14 */ + /*x = 1.9073e-06*_x;*/ + if (_x>=QCONST32(8,19)) + return QCONST32(1.,14); + if (_x<=-QCONST32(8,19)) + return -QCONST32(1.,14); + xx = EXTRACT16(SHR32(_x, 8)); + /*i = lrint(25*x);*/ + i = SHR32(ADD32(1024,MULT16_16(25, xx)),11); + /*x -= .04*i;*/ + xx -= EXTRACT16(SHR32(MULT16_16(20972,i),8)); + /*x = xx*(1./2048);*/ + /*y = tansig_table[250+i];*/ + yy = tansig_table[250+i]; + /*y = yy*(1./16384);*/ + dy = 16384-MULT16_16_Q14(yy,yy); + yy = yy + MULT16_16_Q14(MULT16_16_Q11(xx,dy),(16384 - MULT16_16_Q11(yy,xx))); + return yy; +} +#else +/*extern const float tansig_table[501];*/ +static OPUS_INLINE float tansig_approx(float x) +{ + int i; + float y, dy; + float sign=1; + /* Tests are reversed to catch NaNs */ + if (!(x<8)) + return 1; + if (!(x>-8)) + return -1; + if (x<0) + { + x=-x; + sign=-1; + } + i = (int)floor(.5f+25*x); + x -= .04f*i; + y = tansig_table[i]; + dy = 1-y*y; + y = y + x*dy*(1 - y*x); + return sign*y; +} +#endif + +#if 0 +void mlp_process(const MLP *m, const opus_val16 *in, opus_val16 *out) +{ + int j; + opus_val16 hidden[MAX_NEURONS]; + const opus_val16 *W = m->weights; + /* Copy to tmp_in */ + for (j=0;jtopo[1];j++) + { + int k; + opus_val32 sum = SHL32(EXTEND32(*W++),8); + for (k=0;ktopo[0];k++) + sum = MAC16_16(sum, in[k],*W++); + hidden[j] = tansig_approx(sum); + } + for (j=0;jtopo[2];j++) + { + int k; + opus_val32 sum = SHL32(EXTEND32(*W++),14); + for (k=0;ktopo[1];k++) + sum = MAC16_16(sum, hidden[k], *W++); + out[j] = tansig_approx(EXTRACT16(PSHR32(sum,17))); + } +} +#else +void mlp_process(const MLP *m, const float *in, float *out) +{ + int j; + float hidden[MAX_NEURONS]; + const float *W = m->weights; + /* Copy to tmp_in */ + for (j=0;jtopo[1];j++) + { + int k; + float sum = *W++; + for (k=0;ktopo[0];k++) + sum = sum + in[k]**W++; + hidden[j] = tansig_approx(sum); + } + for (j=0;jtopo[2];j++) + { + int k; + float sum = *W++; + for (k=0;ktopo[1];k++) + sum = sum + hidden[k]**W++; + out[j] = tansig_approx(sum); + } +} +#endif diff --git a/TelegramClient.Opus/opus/src/mlp.h b/TelegramClient.Opus/opus/src/mlp.h new file mode 100755 index 0000000..86c8e06 --- /dev/null +++ b/TelegramClient.Opus/opus/src/mlp.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2008-2011 Octasic Inc. + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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 FOUNDATION 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. +*/ + +#ifndef _MLP_H_ +#define _MLP_H_ + +#include "arch.h" + +typedef struct { + int layers; + const int *topo; + const float *weights; +} MLP; + +void mlp_process(const MLP *m, const float *in, float *out); + +#endif /* _MLP_H_ */ diff --git a/TelegramClient.Opus/opus/src/mlp_data.c b/TelegramClient.Opus/opus/src/mlp_data.c new file mode 100755 index 0000000..401c4c0 --- /dev/null +++ b/TelegramClient.Opus/opus/src/mlp_data.c @@ -0,0 +1,105 @@ +/* The contents of this file was automatically generated by mlp_train.c + It contains multi-layer perceptron (MLP) weights. */ + +#include "mlp.h" + +/* RMS error was 0.138320, seed was 1361535663 */ + +static const float weights[422] = { + +/* hidden layer */ +-0.0941125f, -0.302976f, -0.603555f, -0.19393f, -0.185983f, +-0.601617f, -0.0465317f, -0.114563f, -0.103599f, -0.618938f, +-0.317859f, -0.169949f, -0.0702885f, 0.148065f, 0.409524f, +0.548432f, 0.367649f, -0.494393f, 0.764306f, -1.83957f, +0.170849f, 12.786f, -1.08848f, -1.27284f, -16.2606f, +24.1773f, -5.57454f, -0.17276f, -0.163388f, -0.224421f, +-0.0948944f, -0.0728695f, -0.26557f, -0.100283f, -0.0515459f, +-0.146142f, -0.120674f, -0.180655f, 0.12857f, 0.442138f, +-0.493735f, 0.167767f, 0.206699f, -0.197567f, 0.417999f, +1.50364f, -0.773341f, -10.0401f, 0.401872f, 2.97966f, +15.2165f, -1.88905f, -1.19254f, 0.0285397f, -0.00405139f, +0.0707565f, 0.00825699f, -0.0927269f, -0.010393f, -0.00428882f, +-0.00489743f, -0.0709731f, -0.00255992f, 0.0395619f, 0.226424f, +0.0325231f, 0.162175f, -0.100118f, 0.485789f, 0.12697f, +0.285937f, 0.0155637f, 0.10546f, 3.05558f, 1.15059f, +-1.00904f, -1.83088f, 3.31766f, -3.42516f, -0.119135f, +-0.0405654f, 0.00690068f, 0.0179877f, -0.0382487f, 0.00597941f, +-0.0183611f, 0.00190395f, -0.144322f, -0.0435671f, 0.000990594f, +0.221087f, 0.142405f, 0.484066f, 0.404395f, 0.511955f, +-0.237255f, 0.241742f, 0.35045f, -0.699428f, 10.3993f, +2.6507f, -2.43459f, -4.18838f, 1.05928f, 1.71067f, +0.00667811f, -0.0721335f, -0.0397346f, 0.0362704f, -0.11496f, +-0.0235776f, 0.0082161f, -0.0141741f, -0.0329699f, -0.0354253f, +0.00277404f, -0.290654f, -1.14767f, -0.319157f, -0.686544f, +0.36897f, 0.478899f, 0.182579f, -0.411069f, 0.881104f, +-4.60683f, 1.4697f, 0.335845f, -1.81905f, -30.1699f, +5.55225f, 0.0019508f, -0.123576f, -0.0727332f, -0.0641597f, +-0.0534458f, -0.108166f, -0.0937368f, -0.0697883f, -0.0275475f, +-0.192309f, -0.110074f, 0.285375f, -0.405597f, 0.0926724f, +-0.287881f, -0.851193f, -0.099493f, -0.233764f, -1.2852f, +1.13611f, 3.12168f, -0.0699f, -1.86216f, 2.65292f, +-7.31036f, 2.44776f, -0.00111802f, -0.0632786f, -0.0376296f, +-0.149851f, 0.142963f, 0.184368f, 0.123433f, 0.0756158f, +0.117312f, 0.0933395f, 0.0692163f, 0.0842592f, 0.0704683f, +0.0589963f, 0.0942205f, -0.448862f, 0.0262677f, 0.270352f, +-0.262317f, 0.172586f, 2.00227f, -0.159216f, 0.038422f, +10.2073f, 4.15536f, -2.3407f, -0.0550265f, 0.00964792f, +-0.141336f, 0.0274501f, 0.0343921f, -0.0487428f, 0.0950172f, +-0.00775017f, -0.0372492f, -0.00548121f, -0.0663695f, 0.0960506f, +-0.200008f, -0.0412827f, 0.58728f, 0.0515787f, 0.337254f, +0.855024f, 0.668371f, -0.114904f, -3.62962f, -0.467477f, +-0.215472f, 2.61537f, 0.406117f, -1.36373f, 0.0425394f, +0.12208f, 0.0934502f, 0.123055f, 0.0340935f, -0.142466f, +0.035037f, -0.0490666f, 0.0733208f, 0.0576672f, 0.123984f, +-0.0517194f, -0.253018f, 0.590565f, 0.145849f, 0.315185f, +0.221534f, -0.149081f, 0.216161f, -0.349575f, 24.5664f, +-0.994196f, 0.614289f, -18.7905f, -2.83277f, -0.716801f, +-0.347201f, 0.479515f, -0.246027f, 0.0758683f, 0.137293f, +-0.17781f, 0.118751f, -0.00108329f, -0.237334f, 0.355732f, +-0.12991f, -0.0547627f, -0.318576f, -0.325524f, 0.180494f, +-0.0625604f, 0.141219f, 0.344064f, 0.37658f, -0.591772f, +5.8427f, -0.38075f, 0.221894f, -1.41934f, -1.87943e+06f, +1.34114f, 0.0283355f, -0.0447856f, -0.0211466f, -0.0256927f, +0.0139618f, 0.0207934f, -0.0107666f, 0.0110969f, 0.0586069f, +-0.0253545f, -0.0328433f, 0.11872f, -0.216943f, 0.145748f, +0.119808f, -0.0915211f, -0.120647f, -0.0787719f, -0.143644f, +-0.595116f, -1.152f, -1.25335f, -1.17092f, 4.34023f, +-975268.f, -1.37033f, -0.0401123f, 0.210602f, -0.136656f, +0.135962f, -0.0523293f, 0.0444604f, 0.0143928f, 0.00412666f, +-0.0193003f, 0.218452f, -0.110204f, -2.02563f, 0.918238f, +-2.45362f, 1.19542f, -0.061362f, -1.92243f, 0.308111f, +0.49764f, 0.912356f, 0.209272f, -2.34525f, 2.19326f, +-6.47121f, 1.69771f, -0.725123f, 0.0118929f, 0.0377944f, +0.0554003f, 0.0226452f, -0.0704421f, -0.0300309f, 0.0122978f, +-0.0041782f, -0.0686612f, 0.0313115f, 0.039111f, 0.364111f, +-0.0945548f, 0.0229876f, -0.17414f, 0.329795f, 0.114714f, +0.30022f, 0.106997f, 0.132355f, 5.79932f, 0.908058f, +-0.905324f, -3.3561f, 0.190647f, 0.184211f, -0.673648f, +0.231807f, -0.0586222f, 0.230752f, -0.438277f, 0.245857f, +-0.17215f, 0.0876383f, -0.720512f, 0.162515f, 0.0170571f, +0.101781f, 0.388477f, 1.32931f, 1.08548f, -0.936301f, +-2.36958f, -6.71988f, -3.44376f, 2.13818f, 14.2318f, +4.91459f, -3.09052f, -9.69191f, -0.768234f, 1.79604f, +0.0549653f, 0.163399f, 0.0797025f, 0.0343933f, -0.0555876f, +-0.00505673f, 0.0187258f, 0.0326628f, 0.0231486f, 0.15573f, +0.0476223f, -0.254824f, 1.60155f, -0.801221f, 2.55496f, +0.737629f, -1.36249f, -0.695463f, -2.44301f, -1.73188f, +3.95279f, 1.89068f, 0.486087f, -11.3343f, 3.9416e+06f, + +/* output layer */ +-0.381439f, 0.12115f, -0.906927f, 2.93878f, 1.6388f, +0.882811f, 0.874344f, 1.21726f, -0.874545f, 0.321706f, +0.785055f, 0.946558f, -0.575066f, -3.46553f, 0.884905f, +0.0924047f, -9.90712f, 0.391338f, 0.160103f, -2.04954f, +4.1455f, 0.0684029f, -0.144761f, -0.285282f, 0.379244f, +-1.1584f, -0.0277241f, -9.85f, -4.82386f, 3.71333f, +3.87308f, 3.52558f}; + +static const int topo[3] = {25, 15, 2}; + +const MLP net = { + 3, + topo, + weights +}; diff --git a/TelegramClient.Opus/opus/src/opus.c b/TelegramClient.Opus/opus/src/opus.c new file mode 100755 index 0000000..30890b9 --- /dev/null +++ b/TelegramClient.Opus/opus/src/opus.c @@ -0,0 +1,329 @@ +/* Copyright (c) 2011 Xiph.Org Foundation, Skype Limited + Written by Jean-Marc Valin and Koen Vos */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "opus.h" +#include "opus_private.h" + +#ifndef DISABLE_FLOAT_API +OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem) +{ + int c; + int i; + float *x; + + if (C<1 || N<1 || !_x || !declip_mem) return; + + /* First thing: saturate everything to +/- 2 which is the highest level our + non-linearity can handle. At the point where the signal reaches +/-2, + the derivative will be zero anyway, so this doesn't introduce any + discontinuity in the derivative. */ + for (i=0;i=0) + break; + x[i*C] = x[i*C]+a*x[i*C]*x[i*C]; + } + + curr=0; + x0 = x[0]; + while(1) + { + int start, end; + float maxval; + int special=0; + int peak_pos; + for (i=curr;i1 || x[i*C]<-1) + break; + } + if (i==N) + { + a=0; + break; + } + peak_pos = i; + start=end=i; + maxval=ABS16(x[i*C]); + /* Look for first zero crossing before clipping */ + while (start>0 && x[i*C]*x[(start-1)*C]>=0) + start--; + /* Look for first zero crossing after clipping */ + while (end=0) + { + /* Look for other peaks until the next zero-crossing. */ + if (ABS16(x[end*C])>maxval) + { + maxval = ABS16(x[end*C]); + peak_pos = end; + } + end++; + } + /* Detect the special case where we clip before the first zero crossing */ + special = (start==0 && x[i*C]*x[0]>=0); + + /* Compute a such that maxval + a*maxval^2 = 1 */ + a=(maxval-1)/(maxval*maxval); + if (x[i*C]>0) + a = -a; + /* Apply soft clipping */ + for (i=start;i=2) + { + /* Add a linear ramp from the first sample to the signal peak. + This avoids a discontinuity at the beginning of the frame. */ + float delta; + float offset = x0-x[0]; + delta = offset / peak_pos; + for (i=curr;i>2; + return 2; + } +} + +static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size) +{ + if (len<1) + { + *size = -1; + return -1; + } else if (data[0]<252) + { + *size = data[0]; + return 1; + } else if (len<2) + { + *size = -1; + return -1; + } else { + *size = 4*data[1] + data[0]; + return 2; + } +} + +int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, + int self_delimited, unsigned char *out_toc, + const unsigned char *frames[48], opus_int16 size[48], + int *payload_offset, opus_int32 *packet_offset) +{ + int i, bytes; + int count; + int cbr; + unsigned char ch, toc; + int framesize; + opus_int32 last_size; + opus_int32 pad = 0; + const unsigned char *data0 = data; + + if (size==NULL) + return OPUS_BAD_ARG; + + framesize = opus_packet_get_samples_per_frame(data, 48000); + + cbr = 0; + toc = *data++; + len--; + last_size = len; + switch (toc&0x3) + { + /* One frame */ + case 0: + count=1; + break; + /* Two CBR frames */ + case 1: + count=2; + cbr = 1; + if (!self_delimited) + { + if (len&0x1) + return OPUS_INVALID_PACKET; + last_size = len/2; + /* If last_size doesn't fit in size[0], we'll catch it later */ + size[0] = (opus_int16)last_size; + } + break; + /* Two VBR frames */ + case 2: + count = 2; + bytes = parse_size(data, len, size); + len -= bytes; + if (size[0]<0 || size[0] > len) + return OPUS_INVALID_PACKET; + data += bytes; + last_size = len-size[0]; + break; + /* Multiple CBR/VBR frames (from 0 to 120 ms) */ + default: /*case 3:*/ + if (len<1) + return OPUS_INVALID_PACKET; + /* Number of frames encoded in bits 0 to 5 */ + ch = *data++; + count = ch&0x3F; + if (count <= 0 || framesize*count > 5760) + return OPUS_INVALID_PACKET; + len--; + /* Padding flag is bit 6 */ + if (ch&0x40) + { + int p; + do { + int tmp; + if (len<=0) + return OPUS_INVALID_PACKET; + p = *data++; + len--; + tmp = p==255 ? 254: p; + len -= tmp; + pad += tmp; + } while (p==255); + } + if (len<0) + return OPUS_INVALID_PACKET; + /* VBR flag is bit 7 */ + cbr = !(ch&0x80); + if (!cbr) + { + /* VBR case */ + last_size = len; + for (i=0;i len) + return OPUS_INVALID_PACKET; + data += bytes; + last_size -= bytes+size[i]; + } + if (last_size<0) + return OPUS_INVALID_PACKET; + } else if (!self_delimited) + { + /* CBR case */ + last_size = len/count; + if (last_size*count!=len) + return OPUS_INVALID_PACKET; + for (i=0;i len) + return OPUS_INVALID_PACKET; + data += bytes; + /* For CBR packets, apply the size to all the frames. */ + if (cbr) + { + if (size[count-1]*count > len) + return OPUS_INVALID_PACKET; + for (i=0;i last_size) + return OPUS_INVALID_PACKET; + } else + { + /* Because it's not encoded explicitly, it's possible the size of the + last packet (or all the packets, for the CBR case) is larger than + 1275. Reject them here.*/ + if (last_size > 1275) + return OPUS_INVALID_PACKET; + size[count-1] = (opus_int16)last_size; + } + + if (payload_offset) + *payload_offset = (int)(data-data0); + + for (i=0;i= 2) && !defined(__OPTIMIZE__) +# pragma message "You appear to be compiling without optimization, if so opus will be very slow." +#endif + +#include +#include "celt.h" +#include "opus.h" +#include "entdec.h" +#include "modes.h" +#include "API.h" +#include "stack_alloc.h" +#include "float_cast.h" +#include "opus_private.h" +#include "os_support.h" +#include "structs.h" +#include "define.h" +#include "mathops.h" +#include "cpu_support.h" + +struct OpusDecoder { + int celt_dec_offset; + int silk_dec_offset; + int channels; + opus_int32 Fs; /** Sampling rate (at the API level) */ + silk_DecControlStruct DecControl; + int decode_gain; + + /* Everything beyond this point gets cleared on a reset */ +#define OPUS_DECODER_RESET_START stream_channels + int stream_channels; + + int bandwidth; + int mode; + int prev_mode; + int frame_size; + int prev_redundancy; + int last_packet_duration; +#ifndef FIXED_POINT + opus_val16 softclip_mem[2]; +#endif + + opus_uint32 rangeFinal; +}; + +#ifdef FIXED_POINT +static OPUS_INLINE opus_int16 SAT16(opus_int32 x) { + return x > 32767 ? 32767 : x < -32768 ? -32768 : (opus_int16)x; +} +#endif + + +int opus_decoder_get_size(int channels) +{ + int silkDecSizeBytes, celtDecSizeBytes; + int ret; + if (channels<1 || channels > 2) + return 0; + ret = silk_Get_Decoder_Size( &silkDecSizeBytes ); + if(ret) + return 0; + silkDecSizeBytes = align(silkDecSizeBytes); + celtDecSizeBytes = celt_decoder_get_size(channels); + return align(sizeof(OpusDecoder))+silkDecSizeBytes+celtDecSizeBytes; +} + +int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels) +{ + void *silk_dec; + CELTDecoder *celt_dec; + int ret, silkDecSizeBytes; + + if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000) + || (channels!=1&&channels!=2)) + return OPUS_BAD_ARG; + + OPUS_CLEAR((char*)st, opus_decoder_get_size(channels)); + /* Initialize SILK encoder */ + ret = silk_Get_Decoder_Size(&silkDecSizeBytes); + if (ret) + return OPUS_INTERNAL_ERROR; + + silkDecSizeBytes = align(silkDecSizeBytes); + st->silk_dec_offset = align(sizeof(OpusDecoder)); + st->celt_dec_offset = st->silk_dec_offset+silkDecSizeBytes; + silk_dec = (char*)st+st->silk_dec_offset; + celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset); + st->stream_channels = st->channels = channels; + + st->Fs = Fs; + st->DecControl.API_sampleRate = st->Fs; + st->DecControl.nChannelsAPI = st->channels; + + /* Reset decoder */ + ret = silk_InitDecoder( silk_dec ); + if(ret)return OPUS_INTERNAL_ERROR; + + /* Initialize CELT decoder */ + ret = celt_decoder_init(celt_dec, Fs, channels); + if(ret!=OPUS_OK)return OPUS_INTERNAL_ERROR; + + celt_decoder_ctl(celt_dec, CELT_SET_SIGNALLING(0)); + + st->prev_mode = 0; + st->frame_size = Fs/400; + return OPUS_OK; +} + +OpusDecoder *opus_decoder_create(opus_int32 Fs, int channels, int *error) +{ + int ret; + OpusDecoder *st; + if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000) + || (channels!=1&&channels!=2)) + { + if (error) + *error = OPUS_BAD_ARG; + return NULL; + } + st = (OpusDecoder *)opus_alloc(opus_decoder_get_size(channels)); + if (st == NULL) + { + if (error) + *error = OPUS_ALLOC_FAIL; + return NULL; + } + ret = opus_decoder_init(st, Fs, channels); + if (error) + *error = ret; + if (ret != OPUS_OK) + { + opus_free(st); + st = NULL; + } + return st; +} + +static void smooth_fade(const opus_val16 *in1, const opus_val16 *in2, + opus_val16 *out, int overlap, int channels, + const opus_val16 *window, opus_int32 Fs) +{ + int i, c; + int inc = 48000/Fs; + for (c=0;csilk_dec_offset; + celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset); + F20 = st->Fs/50; + F10 = F20>>1; + F5 = F10>>1; + F2_5 = F5>>1; + if (frame_size < F2_5) + { + RESTORE_STACK; + return OPUS_BUFFER_TOO_SMALL; + } + /* Limit frame_size to avoid excessive stack allocations. */ + frame_size = IMIN(frame_size, st->Fs/25*3); + /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */ + if (len<=1) + { + data = NULL; + /* In that case, don't conceal more than what the ToC says */ + frame_size = IMIN(frame_size, st->frame_size); + } + if (data != NULL) + { + audiosize = st->frame_size; + mode = st->mode; + ec_dec_init(&dec,(unsigned char*)data,len); + } else { + audiosize = frame_size; + mode = st->prev_mode; + + if (mode == 0) + { + /* If we haven't got any packet yet, all we can do is return zeros */ + for (i=0;ichannels;i++) + pcm[i] = 0; + RESTORE_STACK; + return audiosize; + } + + /* Avoids trying to run the PLC on sizes other than 2.5 (CELT), 5 (CELT), + 10, or 20 (e.g. 12.5 or 30 ms). */ + if (audiosize > F20) + { + do { + int ret = opus_decode_frame(st, NULL, 0, pcm, IMIN(audiosize, F20), 0); + if (ret<0) + { + RESTORE_STACK; + return ret; + } + pcm += ret*st->channels; + audiosize -= ret; + } while (audiosize > 0); + RESTORE_STACK; + return frame_size; + } else if (audiosize < F20) + { + if (audiosize > F10) + audiosize = F10; + else if (mode != MODE_SILK_ONLY && audiosize > F5 && audiosize < F10) + audiosize = F5; + } + } + + pcm_transition_silk_size = ALLOC_NONE; + pcm_transition_celt_size = ALLOC_NONE; + if (data!=NULL && st->prev_mode > 0 && ( + (mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy) + || (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) ) + ) + { + transition = 1; + /* Decide where to allocate the stack memory for pcm_transition */ + if (mode == MODE_CELT_ONLY) + pcm_transition_celt_size = F5*st->channels; + else + pcm_transition_silk_size = F5*st->channels; + } + ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_val16); + if (transition && mode == MODE_CELT_ONLY) + { + pcm_transition = pcm_transition_celt; + opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); + } + if (audiosize > frame_size) + { + /*fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);*/ + RESTORE_STACK; + return OPUS_BAD_ARG; + } else { + frame_size = audiosize; + } + + /* Don't allocate any memory when in CELT-only mode */ + pcm_silk_size = (mode != MODE_CELT_ONLY) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE; + ALLOC(pcm_silk, pcm_silk_size, opus_int16); + + /* SILK processing */ + if (mode != MODE_CELT_ONLY) + { + int lost_flag, decoded_samples; + opus_int16 *pcm_ptr = pcm_silk; + + if (st->prev_mode==MODE_CELT_ONLY) + silk_InitDecoder( silk_dec ); + + /* The SILK PLC cannot produce frames of less than 10 ms */ + st->DecControl.payloadSize_ms = IMAX(10, 1000 * audiosize / st->Fs); + + if (data != NULL) + { + st->DecControl.nChannelsInternal = st->stream_channels; + if( mode == MODE_SILK_ONLY ) { + if( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) { + st->DecControl.internalSampleRate = 8000; + } else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) { + st->DecControl.internalSampleRate = 12000; + } else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) { + st->DecControl.internalSampleRate = 16000; + } else { + st->DecControl.internalSampleRate = 16000; + silk_assert( 0 ); + } + } else { + /* Hybrid mode */ + st->DecControl.internalSampleRate = 16000; + } + } + + lost_flag = data == NULL ? 1 : 2 * decode_fec; + decoded_samples = 0; + do { + /* Call SILK decoder */ + int first_frame = decoded_samples == 0; + silk_ret = silk_Decode( silk_dec, &st->DecControl, + lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size ); + if( silk_ret ) { + if (lost_flag) { + /* PLC failure should not be fatal */ + silk_frame_size = frame_size; + for (i=0;ichannels;i++) + pcm_ptr[i] = 0; + } else { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + } + pcm_ptr += silk_frame_size * st->channels; + decoded_samples += silk_frame_size; + } while( decoded_samples < frame_size ); + } + + start_band = 0; + if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL + && ec_tell(&dec)+17+20*(st->mode == MODE_HYBRID) <= 8*len) + { + /* Check if we have a redundant 0-8 kHz band */ + if (mode == MODE_HYBRID) + redundancy = ec_dec_bit_logp(&dec, 12); + else + redundancy = 1; + if (redundancy) + { + celt_to_silk = ec_dec_bit_logp(&dec, 1); + /* redundancy_bytes will be at least two, in the non-hybrid + case due to the ec_tell() check above */ + redundancy_bytes = mode==MODE_HYBRID ? + (opus_int32)ec_dec_uint(&dec, 256)+2 : + len-((ec_tell(&dec)+7)>>3); + len -= redundancy_bytes; + /* This is a sanity check. It should never happen for a valid + packet, so the exact behaviour is not normative. */ + if (len*8 < ec_tell(&dec)) + { + len = 0; + redundancy_bytes = 0; + redundancy = 0; + } + /* Shrink decoder because of raw bits */ + dec.storage -= redundancy_bytes; + } + } + if (mode != MODE_CELT_ONLY) + start_band = 17; + + { + int endband=21; + + switch(st->bandwidth) + { + case OPUS_BANDWIDTH_NARROWBAND: + endband = 13; + break; + case OPUS_BANDWIDTH_MEDIUMBAND: + case OPUS_BANDWIDTH_WIDEBAND: + endband = 17; + break; + case OPUS_BANDWIDTH_SUPERWIDEBAND: + endband = 19; + break; + case OPUS_BANDWIDTH_FULLBAND: + endband = 21; + break; + } + celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband)); + celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels)); + } + + if (redundancy) + { + transition = 0; + pcm_transition_silk_size=ALLOC_NONE; + } + + ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16); + + if (transition && mode != MODE_CELT_ONLY) + { + pcm_transition = pcm_transition_silk; + opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); + } + + /* Only allocation memory for redundancy if/when needed */ + redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE; + ALLOC(redundant_audio, redundant_audio_size, opus_val16); + + /* 5 ms redundant frame for CELT->SILK*/ + if (redundancy && celt_to_silk) + { + celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); + celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, + redundant_audio, F5, NULL); + celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)); + } + + /* MUST be after PLC */ + celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band)); + + if (mode != MODE_SILK_ONLY) + { + int celt_frame_size = IMIN(F20, frame_size); + /* Make sure to discard any previous CELT state */ + if (mode != st->prev_mode && st->prev_mode > 0 && !st->prev_redundancy) + celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); + /* Decode CELT */ + celt_ret = celt_decode_with_ec(celt_dec, decode_fec ? NULL : data, + len, pcm, celt_frame_size, &dec); + } else { + unsigned char silence[2] = {0xFF, 0xFF}; + for (i=0;ichannels;i++) + pcm[i] = 0; + /* For hybrid -> SILK transitions, we let the CELT MDCT + do a fade-out by decoding a silence frame */ + if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) ) + { + celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); + celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL); + } + } + + if (mode != MODE_CELT_ONLY) + { +#ifdef FIXED_POINT + for (i=0;ichannels;i++) + pcm[i] = SAT16(pcm[i] + pcm_silk[i]); +#else + for (i=0;ichannels;i++) + pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]); +#endif + } + + { + const CELTMode *celt_mode; + celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode)); + window = celt_mode->window; + } + + /* 5 ms redundant frame for SILK->CELT */ + if (redundancy && !celt_to_silk) + { + celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); + celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); + + celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL); + celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)); + smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5, + pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs); + } + if (redundancy && celt_to_silk) + { + for (c=0;cchannels;c++) + { + for (i=0;ichannels*i+c] = redundant_audio[st->channels*i+c]; + } + smooth_fade(redundant_audio+st->channels*F2_5, pcm+st->channels*F2_5, + pcm+st->channels*F2_5, F2_5, st->channels, window, st->Fs); + } + if (transition) + { + if (audiosize >= F5) + { + for (i=0;ichannels*F2_5;i++) + pcm[i] = pcm_transition[i]; + smooth_fade(pcm_transition+st->channels*F2_5, pcm+st->channels*F2_5, + pcm+st->channels*F2_5, F2_5, + st->channels, window, st->Fs); + } else { + /* Not enough time to do a clean transition, but we do it anyway + This will not preserve amplitude perfectly and may introduce + a bit of temporal aliasing, but it shouldn't be too bad and + that's pretty much the best we can do. In any case, generating this + transition it pretty silly in the first place */ + smooth_fade(pcm_transition, pcm, + pcm, F2_5, + st->channels, window, st->Fs); + } + } + + if(st->decode_gain) + { + opus_val32 gain; + gain = celt_exp2(MULT16_16_P15(QCONST16(6.48814081e-4f, 25), st->decode_gain)); + for (i=0;ichannels;i++) + { + opus_val32 x; + x = MULT16_32_P16(pcm[i],gain); + pcm[i] = SATURATE(x, 32767); + } + } + + if (len <= 1) + st->rangeFinal = 0; + else + st->rangeFinal = dec.rng ^ redundant_rng; + + st->prev_mode = mode; + st->prev_redundancy = redundancy && !celt_to_silk; + + if (celt_ret>=0) + { + if (OPUS_CHECK_ARRAY(pcm, audiosize*st->channels)) + OPUS_PRINT_INT(audiosize); + } + + RESTORE_STACK; + return celt_ret < 0 ? celt_ret : audiosize; + +} + +int opus_decode_native(OpusDecoder *st, const unsigned char *data, + opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec, + int self_delimited, opus_int32 *packet_offset, int soft_clip) +{ + int i, nb_samples; + int count, offset; + unsigned char toc; + int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels; + /* 48 x 2.5 ms = 120 ms */ + opus_int16 size[48]; + if (decode_fec<0 || decode_fec>1) + return OPUS_BAD_ARG; + /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */ + if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0) + return OPUS_BAD_ARG; + if (len==0 || data==NULL) + { + int pcm_count=0; + do { + int ret; + ret = opus_decode_frame(st, NULL, 0, pcm+pcm_count*st->channels, frame_size-pcm_count, 0); + if (ret<0) + return ret; + pcm_count += ret; + } while (pcm_count < frame_size); + celt_assert(pcm_count == frame_size); + if (OPUS_CHECK_ARRAY(pcm, pcm_count*st->channels)) + OPUS_PRINT_INT(pcm_count); + st->last_packet_duration = pcm_count; + return pcm_count; + } else if (len<0) + return OPUS_BAD_ARG; + + packet_mode = opus_packet_get_mode(data); + packet_bandwidth = opus_packet_get_bandwidth(data); + packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs); + packet_stream_channels = opus_packet_get_nb_channels(data); + + count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, + size, &offset, packet_offset); + if (count<0) + return count; + + data += offset; + + if (decode_fec) + { + int duration_copy; + int ret; + /* If no FEC can be present, run the PLC (recursive call) */ + if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY) + return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, soft_clip); + /* Otherwise, run the PLC on everything except the size for which we might have FEC */ + duration_copy = st->last_packet_duration; + if (frame_size-packet_frame_size!=0) + { + ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL, soft_clip); + if (ret<0) + { + st->last_packet_duration = duration_copy; + return ret; + } + celt_assert(ret==frame_size-packet_frame_size); + } + /* Complete with FEC */ + st->mode = packet_mode; + st->bandwidth = packet_bandwidth; + st->frame_size = packet_frame_size; + st->stream_channels = packet_stream_channels; + ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size), + packet_frame_size, 1); + if (ret<0) + return ret; + else { + if (OPUS_CHECK_ARRAY(pcm, frame_size*st->channels)) + OPUS_PRINT_INT(frame_size); + st->last_packet_duration = frame_size; + return frame_size; + } + } + + if (count*packet_frame_size > frame_size) + return OPUS_BUFFER_TOO_SMALL; + + /* Update the state as the last step to avoid updating it on an invalid packet */ + st->mode = packet_mode; + st->bandwidth = packet_bandwidth; + st->frame_size = packet_frame_size; + st->stream_channels = packet_stream_channels; + + nb_samples=0; + for (i=0;ichannels, frame_size-nb_samples, 0); + if (ret<0) + return ret; + celt_assert(ret==packet_frame_size); + data += size[i]; + nb_samples += ret; + } + st->last_packet_duration = nb_samples; + if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels)) + OPUS_PRINT_INT(nb_samples); +#ifndef FIXED_POINT + if (soft_clip) + opus_pcm_soft_clip(pcm, nb_samples, st->channels, st->softclip_mem); + else + st->softclip_mem[0]=st->softclip_mem[1]=0; +#endif + return nb_samples; +} + +#ifdef FIXED_POINT + +int opus_decode(OpusDecoder *st, const unsigned char *data, + opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) +{ + if(frame_size<=0) + return OPUS_BAD_ARG; + return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0); +} + +#ifndef DISABLE_FLOAT_API +int opus_decode_float(OpusDecoder *st, const unsigned char *data, + opus_int32 len, float *pcm, int frame_size, int decode_fec) +{ + VARDECL(opus_int16, out); + int ret, i; + ALLOC_STACK; + + if(frame_size<=0) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + ALLOC(out, frame_size*st->channels, opus_int16); + + ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0); + if (ret > 0) + { + for (i=0;ichannels;i++) + pcm[i] = (1.f/32768.f)*(out[i]); + } + RESTORE_STACK; + return ret; +} +#endif + + +#else +int opus_decode(OpusDecoder *st, const unsigned char *data, + opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec) +{ + VARDECL(float, out); + int ret, i; + ALLOC_STACK; + + if(frame_size<=0) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + + ALLOC(out, frame_size*st->channels, float); + + ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1); + if (ret > 0) + { + for (i=0;ichannels;i++) + pcm[i] = FLOAT2INT16(out[i]); + } + RESTORE_STACK; + return ret; +} + +int opus_decode_float(OpusDecoder *st, const unsigned char *data, + opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) +{ + if(frame_size<=0) + return OPUS_BAD_ARG; + return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0); +} + +#endif + +int opus_decoder_ctl(OpusDecoder *st, int request, ...) +{ + int ret = OPUS_OK; + va_list ap; + void *silk_dec; + CELTDecoder *celt_dec; + + silk_dec = (char*)st+st->silk_dec_offset; + celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset); + + + va_start(ap, request); + + switch (request) + { + case OPUS_GET_BANDWIDTH_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->bandwidth; + } + break; + case OPUS_GET_FINAL_RANGE_REQUEST: + { + opus_uint32 *value = va_arg(ap, opus_uint32*); + if (!value) + { + goto bad_arg; + } + *value = st->rangeFinal; + } + break; + case OPUS_RESET_STATE: + { + OPUS_CLEAR((char*)&st->OPUS_DECODER_RESET_START, + sizeof(OpusDecoder)- + ((char*)&st->OPUS_DECODER_RESET_START - (char*)st)); + + celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); + silk_InitDecoder( silk_dec ); + st->stream_channels = st->channels; + st->frame_size = st->Fs/400; + } + break; + case OPUS_GET_SAMPLE_RATE_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->Fs; + } + break; + case OPUS_GET_PITCH_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + if (st->prev_mode == MODE_CELT_ONLY) + celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value)); + else + *value = st->DecControl.prevPitchLag; + } + break; + case OPUS_GET_GAIN_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->decode_gain; + } + break; + case OPUS_SET_GAIN_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<-32768 || value>32767) + { + goto bad_arg; + } + st->decode_gain = value; + } + break; + case OPUS_GET_LAST_PACKET_DURATION_REQUEST: + { + opus_uint32 *value = va_arg(ap, opus_uint32*); + if (!value) + { + goto bad_arg; + } + *value = st->last_packet_duration; + } + break; + default: + /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/ + ret = OPUS_UNIMPLEMENTED; + break; + } + + va_end(ap); + return ret; +bad_arg: + va_end(ap); + return OPUS_BAD_ARG; +} + +void opus_decoder_destroy(OpusDecoder *st) +{ + opus_free(st); +} + + +int opus_packet_get_bandwidth(const unsigned char *data) +{ + int bandwidth; + if (data[0]&0x80) + { + bandwidth = OPUS_BANDWIDTH_MEDIUMBAND + ((data[0]>>5)&0x3); + if (bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) + bandwidth = OPUS_BANDWIDTH_NARROWBAND; + } else if ((data[0]&0x60) == 0x60) + { + bandwidth = (data[0]&0x10) ? OPUS_BANDWIDTH_FULLBAND : + OPUS_BANDWIDTH_SUPERWIDEBAND; + } else { + bandwidth = OPUS_BANDWIDTH_NARROWBAND + ((data[0]>>5)&0x3); + } + return bandwidth; +} + +int opus_packet_get_samples_per_frame(const unsigned char *data, + opus_int32 Fs) +{ + int audiosize; + if (data[0]&0x80) + { + audiosize = ((data[0]>>3)&0x3); + audiosize = (Fs<>3)&0x3); + if (audiosize == 3) + audiosize = Fs*60/1000; + else + audiosize = (Fs< Fs*3) + return OPUS_INVALID_PACKET; + else + return samples; +} + +int opus_decoder_get_nb_samples(const OpusDecoder *dec, + const unsigned char packet[], opus_int32 len) +{ + return opus_packet_get_nb_samples(packet, len, dec->Fs); +} diff --git a/TelegramClient.Opus/opus/src/opus_encoder.c b/TelegramClient.Opus/opus/src/opus_encoder.c new file mode 100755 index 0000000..fbd3de6 --- /dev/null +++ b/TelegramClient.Opus/opus/src/opus_encoder.c @@ -0,0 +1,2488 @@ +/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited + Written by Jean-Marc Valin and Koen Vos */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "celt.h" +#include "entenc.h" +#include "modes.h" +#include "API.h" +#include "stack_alloc.h" +#include "float_cast.h" +#include "opus.h" +#include "arch.h" +#include "opus_private.h" +#include "os_support.h" +#include "cpu_support.h" +#include "analysis.h" +#include "mathops.h" +#include "tuning_parameters.h" +#ifdef FIXED_POINT +#include "fixed/structs_FIX.h" +#else +#include "float/structs_FLP.h" +#endif + +#define MAX_ENCODER_BUFFER 480 + +typedef struct { + opus_val32 XX, XY, YY; + opus_val16 smoothed_width; + opus_val16 max_follower; +} StereoWidthState; + +struct OpusEncoder { + int celt_enc_offset; + int silk_enc_offset; + silk_EncControlStruct silk_mode; + int application; + int channels; + int delay_compensation; + int force_channels; + int signal_type; + int user_bandwidth; + int max_bandwidth; + int user_forced_mode; + int voice_ratio; + opus_int32 Fs; + int use_vbr; + int vbr_constraint; + int variable_duration; + opus_int32 bitrate_bps; + opus_int32 user_bitrate_bps; + int lsb_depth; + int encoder_buffer; + int lfe; + +#define OPUS_ENCODER_RESET_START stream_channels + int stream_channels; + opus_int16 hybrid_stereo_width_Q14; + opus_int32 variable_HP_smth2_Q15; + opus_val16 prev_HB_gain; + opus_val32 hp_mem[4]; + int mode; + int prev_mode; + int prev_channels; + int prev_framesize; + int bandwidth; + int silk_bw_switch; + /* Sampling rate (at the API level) */ + int first; + opus_val16 * energy_masking; + StereoWidthState width_mem; + opus_val16 delay_buffer[MAX_ENCODER_BUFFER*2]; +#ifndef DISABLE_FLOAT_API + TonalityAnalysisState analysis; + int detected_bandwidth; + int analysis_offset; +#endif + opus_uint32 rangeFinal; + int arch; +}; + +/* Transition tables for the voice and music. First column is the + middle (memoriless) threshold. The second column is the hysteresis + (difference with the middle) */ +static const opus_int32 mono_voice_bandwidth_thresholds[8] = { + 11000, 1000, /* NB<->MB */ + 14000, 1000, /* MB<->WB */ + 17000, 1000, /* WB<->SWB */ + 21000, 2000, /* SWB<->FB */ +}; +static const opus_int32 mono_music_bandwidth_thresholds[8] = { + 12000, 1000, /* NB<->MB */ + 15000, 1000, /* MB<->WB */ + 18000, 2000, /* WB<->SWB */ + 22000, 2000, /* SWB<->FB */ +}; +static const opus_int32 stereo_voice_bandwidth_thresholds[8] = { + 11000, 1000, /* NB<->MB */ + 14000, 1000, /* MB<->WB */ + 21000, 2000, /* WB<->SWB */ + 28000, 2000, /* SWB<->FB */ +}; +static const opus_int32 stereo_music_bandwidth_thresholds[8] = { + 12000, 1000, /* NB<->MB */ + 18000, 2000, /* MB<->WB */ + 21000, 2000, /* WB<->SWB */ + 30000, 2000, /* SWB<->FB */ +}; +/* Threshold bit-rates for switching between mono and stereo */ +static const opus_int32 stereo_voice_threshold = 30000; +static const opus_int32 stereo_music_threshold = 30000; + +/* Threshold bit-rate for switching between SILK/hybrid and CELT-only */ +static const opus_int32 mode_thresholds[2][2] = { + /* voice */ /* music */ + { 64000, 16000}, /* mono */ + { 36000, 16000}, /* stereo */ +}; + +int opus_encoder_get_size(int channels) +{ + int silkEncSizeBytes, celtEncSizeBytes; + int ret; + if (channels<1 || channels > 2) + return 0; + ret = silk_Get_Encoder_Size( &silkEncSizeBytes ); + if (ret) + return 0; + silkEncSizeBytes = align(silkEncSizeBytes); + celtEncSizeBytes = celt_encoder_get_size(channels); + return align(sizeof(OpusEncoder))+silkEncSizeBytes+celtEncSizeBytes; +} + +int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int application) +{ + void *silk_enc; + CELTEncoder *celt_enc; + int err; + int ret, silkEncSizeBytes; + + if((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)||(channels!=1&&channels!=2)|| + (application != OPUS_APPLICATION_VOIP && application != OPUS_APPLICATION_AUDIO + && application != OPUS_APPLICATION_RESTRICTED_LOWDELAY)) + return OPUS_BAD_ARG; + + OPUS_CLEAR((char*)st, opus_encoder_get_size(channels)); + /* Create SILK encoder */ + ret = silk_Get_Encoder_Size( &silkEncSizeBytes ); + if (ret) + return OPUS_BAD_ARG; + silkEncSizeBytes = align(silkEncSizeBytes); + st->silk_enc_offset = align(sizeof(OpusEncoder)); + st->celt_enc_offset = st->silk_enc_offset+silkEncSizeBytes; + silk_enc = (char*)st+st->silk_enc_offset; + celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset); + + st->stream_channels = st->channels = channels; + + st->Fs = Fs; + + st->arch = opus_select_arch(); + + ret = silk_InitEncoder( silk_enc, st->arch, &st->silk_mode ); + if(ret)return OPUS_INTERNAL_ERROR; + + /* default SILK parameters */ + st->silk_mode.nChannelsAPI = channels; + st->silk_mode.nChannelsInternal = channels; + st->silk_mode.API_sampleRate = st->Fs; + st->silk_mode.maxInternalSampleRate = 16000; + st->silk_mode.minInternalSampleRate = 8000; + st->silk_mode.desiredInternalSampleRate = 16000; + st->silk_mode.payloadSize_ms = 20; + st->silk_mode.bitRate = 25000; + st->silk_mode.packetLossPercentage = 0; + st->silk_mode.complexity = 9; + st->silk_mode.useInBandFEC = 0; + st->silk_mode.useDTX = 0; + st->silk_mode.useCBR = 0; + st->silk_mode.reducedDependency = 0; + + /* Create CELT encoder */ + /* Initialize CELT encoder */ + err = celt_encoder_init(celt_enc, Fs, channels, st->arch); + if(err!=OPUS_OK)return OPUS_INTERNAL_ERROR; + + celt_encoder_ctl(celt_enc, CELT_SET_SIGNALLING(0)); + celt_encoder_ctl(celt_enc, OPUS_SET_COMPLEXITY(st->silk_mode.complexity)); + + st->use_vbr = 1; + /* Makes constrained VBR the default (safer for real-time use) */ + st->vbr_constraint = 1; + st->user_bitrate_bps = OPUS_AUTO; + st->bitrate_bps = 3000+Fs*channels; + st->application = application; + st->signal_type = OPUS_AUTO; + st->user_bandwidth = OPUS_AUTO; + st->max_bandwidth = OPUS_BANDWIDTH_FULLBAND; + st->force_channels = OPUS_AUTO; + st->user_forced_mode = OPUS_AUTO; + st->voice_ratio = -1; + st->encoder_buffer = st->Fs/100; + st->lsb_depth = 24; + st->variable_duration = OPUS_FRAMESIZE_ARG; + + /* Delay compensation of 4 ms (2.5 ms for SILK's extra look-ahead + + 1.5 ms for SILK resamplers and stereo prediction) */ + st->delay_compensation = st->Fs/250; + + st->hybrid_stereo_width_Q14 = 1 << 14; + st->prev_HB_gain = Q15ONE; + st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ); + st->first = 1; + st->mode = MODE_HYBRID; + st->bandwidth = OPUS_BANDWIDTH_FULLBAND; + + return OPUS_OK; +} + +static unsigned char gen_toc(int mode, int framerate, int bandwidth, int channels) +{ + int period; + unsigned char toc; + period = 0; + while (framerate < 400) + { + framerate <<= 1; + period++; + } + if (mode == MODE_SILK_ONLY) + { + toc = (bandwidth-OPUS_BANDWIDTH_NARROWBAND)<<5; + toc |= (period-2)<<3; + } else if (mode == MODE_CELT_ONLY) + { + int tmp = bandwidth-OPUS_BANDWIDTH_MEDIUMBAND; + if (tmp < 0) + tmp = 0; + toc = 0x80; + toc |= tmp << 5; + toc |= period<<3; + } else /* Hybrid */ + { + toc = 0x60; + toc |= (bandwidth-OPUS_BANDWIDTH_SUPERWIDEBAND)<<4; + toc |= (period-2)<<3; + } + toc |= (channels==2)<<2; + return toc; +} + +#ifndef FIXED_POINT +static void silk_biquad_float( + const opus_val16 *in, /* I: Input signal */ + const opus_int32 *B_Q28, /* I: MA coefficients [3] */ + const opus_int32 *A_Q28, /* I: AR coefficients [2] */ + opus_val32 *S, /* I/O: State vector [2] */ + opus_val16 *out, /* O: Output signal */ + const opus_int32 len, /* I: Signal length (must be even) */ + int stride +) +{ + /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */ + opus_int k; + opus_val32 vout; + opus_val32 inval; + opus_val32 A[2], B[3]; + + A[0] = (opus_val32)(A_Q28[0] * (1.f/((opus_int32)1<<28))); + A[1] = (opus_val32)(A_Q28[1] * (1.f/((opus_int32)1<<28))); + B[0] = (opus_val32)(B_Q28[0] * (1.f/((opus_int32)1<<28))); + B[1] = (opus_val32)(B_Q28[1] * (1.f/((opus_int32)1<<28))); + B[2] = (opus_val32)(B_Q28[2] * (1.f/((opus_int32)1<<28))); + + /* Negate A_Q28 values and split in two parts */ + + for( k = 0; k < len; k++ ) { + /* S[ 0 ], S[ 1 ]: Q12 */ + inval = in[ k*stride ]; + vout = S[ 0 ] + B[0]*inval; + + S[ 0 ] = S[1] - vout*A[0] + B[1]*inval; + + S[ 1 ] = - vout*A[1] + B[2]*inval + VERY_SMALL; + + /* Scale back to Q0 and saturate */ + out[ k*stride ] = vout; + } +} +#endif + +static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs) +{ + opus_int32 B_Q28[ 3 ], A_Q28[ 2 ]; + opus_int32 Fc_Q19, r_Q28, r_Q22; + + silk_assert( cutoff_Hz <= silk_int32_MAX / SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ) ); + Fc_Q19 = silk_DIV32_16( silk_SMULBB( SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ), cutoff_Hz ), Fs/1000 ); + silk_assert( Fc_Q19 > 0 && Fc_Q19 < 32768 ); + + r_Q28 = SILK_FIX_CONST( 1.0, 28 ) - silk_MUL( SILK_FIX_CONST( 0.92, 9 ), Fc_Q19 ); + + /* b = r * [ 1; -2; 1 ]; */ + /* a = [ 1; -2 * r * ( 1 - 0.5 * Fc^2 ); r^2 ]; */ + B_Q28[ 0 ] = r_Q28; + B_Q28[ 1 ] = silk_LSHIFT( -r_Q28, 1 ); + B_Q28[ 2 ] = r_Q28; + + /* -r * ( 2 - Fc * Fc ); */ + r_Q22 = silk_RSHIFT( r_Q28, 6 ); + A_Q28[ 0 ] = silk_SMULWW( r_Q22, silk_SMULWW( Fc_Q19, Fc_Q19 ) - SILK_FIX_CONST( 2.0, 22 ) ); + A_Q28[ 1 ] = silk_SMULWW( r_Q22, r_Q22 ); + +#ifdef FIXED_POINT + silk_biquad_alt( in, B_Q28, A_Q28, hp_mem, out, len, channels ); + if( channels == 2 ) { + silk_biquad_alt( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels ); + } +#else + silk_biquad_float( in, B_Q28, A_Q28, hp_mem, out, len, channels ); + if( channels == 2 ) { + silk_biquad_float( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels ); + } +#endif +} + +#ifdef FIXED_POINT +static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs) +{ + int c, i; + int shift; + + /* Approximates -round(log2(4.*cutoff_Hz/Fs)) */ + shift=celt_ilog2(Fs/(cutoff_Hz*3)); + for (c=0;cFs/400; + if (st->user_bitrate_bps==OPUS_AUTO) + return 60*st->Fs/frame_size + st->Fs*st->channels; + else if (st->user_bitrate_bps==OPUS_BITRATE_MAX) + return max_data_bytes*8*st->Fs/frame_size; + else + return st->user_bitrate_bps; +} + +#ifndef DISABLE_FLOAT_API +/* Don't use more than 60 ms for the frame size analysis */ +#define MAX_DYNAMIC_FRAMESIZE 24 +/* Estimates how much the bitrate will be boosted based on the sub-frame energy */ +static float transient_boost(const float *E, const float *E_1, int LM, int maxM) +{ + int i; + int M; + float sumE=0, sumE_1=0; + float metric; + + M = IMIN(maxM, (1<10 ? 1 : 0;*/ + /*return MAX16(0,1-exp(-.25*(metric-2.)));*/ + return MIN16(1,(float)sqrt(MAX16(0,.05f*(metric-2)))); +} + +/* Viterbi decoding trying to find the best frame size combination using look-ahead + + State numbering: + 0: unused + 1: 2.5 ms + 2: 5 ms (#1) + 3: 5 ms (#2) + 4: 10 ms (#1) + 5: 10 ms (#2) + 6: 10 ms (#3) + 7: 10 ms (#4) + 8: 20 ms (#1) + 9: 20 ms (#2) + 10: 20 ms (#3) + 11: 20 ms (#4) + 12: 20 ms (#5) + 13: 20 ms (#6) + 14: 20 ms (#7) + 15: 20 ms (#8) +*/ +static int transient_viterbi(const float *E, const float *E_1, int N, int frame_cost, int rate) +{ + int i; + float cost[MAX_DYNAMIC_FRAMESIZE][16]; + int states[MAX_DYNAMIC_FRAMESIZE][16]; + float best_cost; + int best_state; + float factor; + /* Take into account that we damp VBR in the 32 kb/s to 64 kb/s range. */ + if (rate<80) + factor=0; + else if (rate>160) + factor=1; + else + factor = (rate-80.f)/80.f; + /* Makes variable framesize less aggressive at lower bitrates, but I can't + find any valid theoretical justification for this (other than it seems + to help) */ + for (i=0;i<16;i++) + { + /* Impossible state */ + states[0][i] = -1; + cost[0][i] = 1e10; + } + for (i=0;i<4;i++) + { + cost[0][1<=0;i--) + { + /*printf("%d ", best_state);*/ + best_state = states[i][best_state]; + } + /*printf("%d\n", best_state);*/ + return best_state; +} + +int optimize_framesize(const opus_val16 *x, int len, int C, opus_int32 Fs, + int bitrate, opus_val16 tonality, float *mem, int buffering, + downmix_func downmix) +{ + int N; + int i; + float e[MAX_DYNAMIC_FRAMESIZE+4]; + float e_1[MAX_DYNAMIC_FRAMESIZE+3]; + opus_val32 memx; + int bestLM=0; + int subframe; + int pos; + VARDECL(opus_val32, sub); + + subframe = Fs/400; + ALLOC(sub, subframe, opus_val32); + e[0]=mem[0]; + e_1[0]=1.f/(EPSILON+mem[0]); + if (buffering) + { + /* Consider the CELT delay when not in restricted-lowdelay */ + /* We assume the buffering is between 2.5 and 5 ms */ + int offset = 2*subframe - buffering; + celt_assert(offset>=0 && offset <= subframe); + x += C*offset; + len -= offset; + e[1]=mem[1]; + e_1[1]=1.f/(EPSILON+mem[1]); + e[2]=mem[2]; + e_1[2]=1.f/(EPSILON+mem[2]); + pos = 3; + } else { + pos=1; + } + N=IMIN(len/subframe, MAX_DYNAMIC_FRAMESIZE); + /* Just silencing a warning, it's really initialized later */ + memx = 0; + for (i=0;i-1) + { + for (j=0;j-1) + { + for (j=0;j= OPUS_FRAMESIZE_2_5_MS && variable_duration <= OPUS_FRAMESIZE_60_MS) + new_size = IMIN(3*Fs/50, (Fs/400)<<(variable_duration-OPUS_FRAMESIZE_2_5_MS)); + else + return -1; + if (new_size>frame_size) + return -1; + if (400*new_size!=Fs && 200*new_size!=Fs && 100*new_size!=Fs && + 50*new_size!=Fs && 25*new_size!=Fs && 50*new_size!=3*Fs) + return -1; + return new_size; +} + +opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size, + int variable_duration, int C, opus_int32 Fs, int bitrate_bps, + int delay_compensation, downmix_func downmix +#ifndef DISABLE_FLOAT_API + , float *subframe_mem +#endif + ) +{ +#ifndef DISABLE_FLOAT_API + if (variable_duration == OPUS_FRAMESIZE_VARIABLE && frame_size >= Fs/200) + { + int LM = 3; + LM = optimize_framesize(analysis_pcm, frame_size, C, Fs, bitrate_bps, + 0, subframe_mem, delay_compensation, downmix); + while ((Fs/400<frame_size) + LM--; + frame_size = (Fs/400<XX += MULT16_32_Q15(short_alpha, xx-mem->XX); + mem->XY += MULT16_32_Q15(short_alpha, xy-mem->XY); + mem->YY += MULT16_32_Q15(short_alpha, yy-mem->YY); + mem->XX = MAX32(0, mem->XX); + mem->XY = MAX32(0, mem->XY); + mem->YY = MAX32(0, mem->YY); + if (MAX32(mem->XX, mem->YY)>QCONST16(8e-4f, 18)) + { + sqrt_xx = celt_sqrt(mem->XX); + sqrt_yy = celt_sqrt(mem->YY); + qrrt_xx = celt_sqrt(sqrt_xx); + qrrt_yy = celt_sqrt(sqrt_yy); + /* Inter-channel correlation */ + mem->XY = MIN32(mem->XY, sqrt_xx*sqrt_yy); + corr = SHR32(frac_div32(mem->XY,EPSILON+MULT16_16(sqrt_xx,sqrt_yy)),16); + /* Approximate loudness difference */ + ldiff = Q15ONE*ABS16(qrrt_xx-qrrt_yy)/(EPSILON+qrrt_xx+qrrt_yy); + width = MULT16_16_Q15(celt_sqrt(QCONST32(1.f,30)-MULT16_16(corr,corr)), ldiff); + /* Smoothing over one second */ + mem->smoothed_width += (width-mem->smoothed_width)/frame_rate; + /* Peak follower */ + mem->max_follower = MAX16(mem->max_follower-QCONST16(.02f,15)/frame_rate, mem->smoothed_width); + } else { + width = 0; + corr=Q15ONE; + ldiff=0; + } + /*printf("%f %f %f %f %f ", corr/(float)Q15ONE, ldiff/(float)Q15ONE, width/(float)Q15ONE, mem->smoothed_width/(float)Q15ONE, mem->max_follower/(float)Q15ONE);*/ + return EXTRACT16(MIN32(Q15ONE,20*mem->max_follower)); +} + +opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size, + unsigned char *data, opus_int32 out_data_bytes, int lsb_depth, + const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2, int analysis_channels, downmix_func downmix) +{ + void *silk_enc; + CELTEncoder *celt_enc; + int i; + int ret=0; + opus_int32 nBytes; + ec_enc enc; + int bytes_target; + int prefill=0; + int start_band = 0; + int redundancy = 0; + int redundancy_bytes = 0; /* Number of bytes to use for redundancy frame */ + int celt_to_silk = 0; + VARDECL(opus_val16, pcm_buf); + int nb_compr_bytes; + int to_celt = 0; + opus_uint32 redundant_rng = 0; + int cutoff_Hz, hp_freq_smth1; + int voice_est; /* Probability of voice in Q7 */ + opus_int32 equiv_rate; + int delay_compensation; + int frame_rate; + opus_int32 max_rate; /* Max bitrate we're allowed to use */ + int curr_bandwidth; + opus_val16 HB_gain; + opus_int32 max_data_bytes; /* Max number of bytes we're allowed to use */ + int total_buffer; + opus_val16 stereo_width; + const CELTMode *celt_mode; + AnalysisInfo analysis_info; + int analysis_read_pos_bak=-1; + int analysis_read_subframe_bak=-1; + VARDECL(opus_val16, tmp_prefill); + + ALLOC_STACK; + + max_data_bytes = IMIN(1276, out_data_bytes); + + st->rangeFinal = 0; + if ((!st->variable_duration && 400*frame_size != st->Fs && 200*frame_size != st->Fs && 100*frame_size != st->Fs && + 50*frame_size != st->Fs && 25*frame_size != st->Fs && 50*frame_size != 3*st->Fs) + || (400*frame_size < st->Fs) + || max_data_bytes<=0 + ) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + silk_enc = (char*)st+st->silk_enc_offset; + celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset); + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + + lsb_depth = IMIN(lsb_depth, st->lsb_depth); + + analysis_info.valid = 0; + celt_encoder_ctl(celt_enc, CELT_GET_MODE(&celt_mode)); +#ifndef DISABLE_FLOAT_API +#ifdef FIXED_POINT + if (st->silk_mode.complexity >= 10 && st->Fs==48000) +#else + if (st->silk_mode.complexity >= 7 && st->Fs==48000) +#endif + { + analysis_read_pos_bak = st->analysis.read_pos; + analysis_read_subframe_bak = st->analysis.read_subframe; + run_analysis(&st->analysis, celt_mode, analysis_pcm, analysis_size, frame_size, + c1, c2, analysis_channels, st->Fs, + lsb_depth, downmix, &analysis_info); + } +#endif + + st->voice_ratio = -1; + +#ifndef DISABLE_FLOAT_API + st->detected_bandwidth = 0; + if (analysis_info.valid) + { + int analysis_bandwidth; + if (st->signal_type == OPUS_AUTO) + st->voice_ratio = (int)floor(.5+100*(1-analysis_info.music_prob)); + + analysis_bandwidth = analysis_info.bandwidth; + if (analysis_bandwidth<=12) + st->detected_bandwidth = OPUS_BANDWIDTH_NARROWBAND; + else if (analysis_bandwidth<=14) + st->detected_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; + else if (analysis_bandwidth<=16) + st->detected_bandwidth = OPUS_BANDWIDTH_WIDEBAND; + else if (analysis_bandwidth<=18) + st->detected_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; + else + st->detected_bandwidth = OPUS_BANDWIDTH_FULLBAND; + } +#endif + + if (st->channels==2 && st->force_channels!=1) + stereo_width = compute_stereo_width(pcm, frame_size, st->Fs, &st->width_mem); + else + stereo_width = 0; + total_buffer = delay_compensation; + st->bitrate_bps = user_bitrate_to_bitrate(st, frame_size, max_data_bytes); + + frame_rate = st->Fs/frame_size; + if (max_data_bytes<3 || st->bitrate_bps < 3*frame_rate*8 + || (frame_rate<50 && (max_data_bytes*frame_rate<300 || st->bitrate_bps < 2400))) + { + /*If the space is too low to do something useful, emit 'PLC' frames.*/ + int tocmode = st->mode; + int bw = st->bandwidth == 0 ? OPUS_BANDWIDTH_NARROWBAND : st->bandwidth; + if (tocmode==0) + tocmode = MODE_SILK_ONLY; + if (frame_rate>100) + tocmode = MODE_CELT_ONLY; + if (frame_rate < 50) + tocmode = MODE_SILK_ONLY; + if(tocmode==MODE_SILK_ONLY&&bw>OPUS_BANDWIDTH_WIDEBAND) + bw=OPUS_BANDWIDTH_WIDEBAND; + else if (tocmode==MODE_CELT_ONLY&&bw==OPUS_BANDWIDTH_MEDIUMBAND) + bw=OPUS_BANDWIDTH_NARROWBAND; + else if (bw<=OPUS_BANDWIDTH_SUPERWIDEBAND) + bw=OPUS_BANDWIDTH_SUPERWIDEBAND; + data[0] = gen_toc(tocmode, frame_rate, bw, st->stream_channels); + RESTORE_STACK; + return 1; + } + if (!st->use_vbr) + { + int cbrBytes; + cbrBytes = IMIN( (st->bitrate_bps + 4*frame_rate)/(8*frame_rate) , max_data_bytes); + st->bitrate_bps = cbrBytes * (8*frame_rate); + max_data_bytes = cbrBytes; + } + max_rate = frame_rate*max_data_bytes*8; + + /* Equivalent 20-ms rate for mode/channel/bandwidth decisions */ + equiv_rate = st->bitrate_bps - (40*st->channels+20)*(st->Fs/frame_size - 50); + + if (st->signal_type == OPUS_SIGNAL_VOICE) + voice_est = 127; + else if (st->signal_type == OPUS_SIGNAL_MUSIC) + voice_est = 0; + else if (st->voice_ratio >= 0) + { + voice_est = st->voice_ratio*327>>8; + /* For AUDIO, never be more than 90% confident of having speech */ + if (st->application == OPUS_APPLICATION_AUDIO) + voice_est = IMIN(voice_est, 115); + } else if (st->application == OPUS_APPLICATION_VOIP) + voice_est = 115; + else + voice_est = 48; + + if (st->force_channels!=OPUS_AUTO && st->channels == 2) + { + st->stream_channels = st->force_channels; + } else { +#ifdef FUZZING + /* Random mono/stereo decision */ + if (st->channels == 2 && (rand()&0x1F)==0) + st->stream_channels = 3-st->stream_channels; +#else + /* Rate-dependent mono-stereo decision */ + if (st->channels == 2) + { + opus_int32 stereo_threshold; + stereo_threshold = stereo_music_threshold + ((voice_est*voice_est*(stereo_voice_threshold-stereo_music_threshold))>>14); + if (st->stream_channels == 2) + stereo_threshold -= 1000; + else + stereo_threshold += 1000; + st->stream_channels = (equiv_rate > stereo_threshold) ? 2 : 1; + } else { + st->stream_channels = st->channels; + } +#endif + } + equiv_rate = st->bitrate_bps - (40*st->stream_channels+20)*(st->Fs/frame_size - 50); + + /* Mode selection depending on application and signal type */ + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + { + st->mode = MODE_CELT_ONLY; + } else if (st->user_forced_mode == OPUS_AUTO) + { +#ifdef FUZZING + /* Random mode switching */ + if ((rand()&0xF)==0) + { + if ((rand()&0x1)==0) + st->mode = MODE_CELT_ONLY; + else + st->mode = MODE_SILK_ONLY; + } else { + if (st->prev_mode==MODE_CELT_ONLY) + st->mode = MODE_CELT_ONLY; + else + st->mode = MODE_SILK_ONLY; + } +#else + opus_int32 mode_voice, mode_music; + opus_int32 threshold; + + /* Interpolate based on stereo width */ + mode_voice = (opus_int32)(MULT16_32_Q15(Q15ONE-stereo_width,mode_thresholds[0][0]) + + MULT16_32_Q15(stereo_width,mode_thresholds[1][0])); + mode_music = (opus_int32)(MULT16_32_Q15(Q15ONE-stereo_width,mode_thresholds[1][1]) + + MULT16_32_Q15(stereo_width,mode_thresholds[1][1])); + /* Interpolate based on speech/music probability */ + threshold = mode_music + ((voice_est*voice_est*(mode_voice-mode_music))>>14); + /* Bias towards SILK for VoIP because of some useful features */ + if (st->application == OPUS_APPLICATION_VOIP) + threshold += 8000; + + /*printf("%f %d\n", stereo_width/(float)Q15ONE, threshold);*/ + /* Hysteresis */ + if (st->prev_mode == MODE_CELT_ONLY) + threshold -= 4000; + else if (st->prev_mode>0) + threshold += 4000; + + st->mode = (equiv_rate >= threshold) ? MODE_CELT_ONLY: MODE_SILK_ONLY; + + /* When FEC is enabled and there's enough packet loss, use SILK */ + if (st->silk_mode.useInBandFEC && st->silk_mode.packetLossPercentage > (128-voice_est)>>4) + st->mode = MODE_SILK_ONLY; + /* When encoding voice and DTX is enabled, set the encoder to SILK mode (at least for now) */ + if (st->silk_mode.useDTX && voice_est > 100) + st->mode = MODE_SILK_ONLY; +#endif + } else { + st->mode = st->user_forced_mode; + } + + /* Override the chosen mode to make sure we meet the requested frame size */ + if (st->mode != MODE_CELT_ONLY && frame_size < st->Fs/100) + st->mode = MODE_CELT_ONLY; + if (st->lfe) + st->mode = MODE_CELT_ONLY; + /* If max_data_bytes represents less than 8 kb/s, switch to CELT-only mode */ + if (max_data_bytes < (frame_rate > 50 ? 12000 : 8000)*frame_size / (st->Fs * 8)) + st->mode = MODE_CELT_ONLY; + + if (st->stream_channels == 1 && st->prev_channels ==2 && st->silk_mode.toMono==0 + && st->mode != MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY) + { + /* Delay stereo->mono transition by two frames so that SILK can do a smooth downmix */ + st->silk_mode.toMono = 1; + st->stream_channels = 2; + } else { + st->silk_mode.toMono = 0; + } + + if (st->prev_mode > 0 && + ((st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) || + (st->mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY))) + { + redundancy = 1; + celt_to_silk = (st->mode != MODE_CELT_ONLY); + if (!celt_to_silk) + { + /* Switch to SILK/hybrid if frame size is 10 ms or more*/ + if (frame_size >= st->Fs/100) + { + st->mode = st->prev_mode; + to_celt = 1; + } else { + redundancy=0; + } + } + } + /* For the first frame at a new SILK bandwidth */ + if (st->silk_bw_switch) + { + redundancy = 1; + celt_to_silk = 1; + st->silk_bw_switch = 0; + prefill=1; + } + + if (redundancy) + { + /* Fair share of the max size allowed */ + redundancy_bytes = IMIN(257, max_data_bytes*(opus_int32)(st->Fs/200)/(frame_size+st->Fs/200)); + /* For VBR, target the actual bitrate (subject to the limit above) */ + if (st->use_vbr) + redundancy_bytes = IMIN(redundancy_bytes, st->bitrate_bps/1600); + } + + if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) + { + silk_EncControlStruct dummy; + silk_InitEncoder( silk_enc, st->arch, &dummy); + prefill=1; + } + + /* Automatic (rate-dependent) bandwidth selection */ + if (st->mode == MODE_CELT_ONLY || st->first || st->silk_mode.allowBandwidthSwitch) + { + const opus_int32 *voice_bandwidth_thresholds, *music_bandwidth_thresholds; + opus_int32 bandwidth_thresholds[8]; + int bandwidth = OPUS_BANDWIDTH_FULLBAND; + opus_int32 equiv_rate2; + + equiv_rate2 = equiv_rate; + if (st->mode != MODE_CELT_ONLY) + { + /* Adjust the threshold +/- 10% depending on complexity */ + equiv_rate2 = equiv_rate2 * (45+st->silk_mode.complexity)/50; + /* CBR is less efficient by ~1 kb/s */ + if (!st->use_vbr) + equiv_rate2 -= 1000; + } + if (st->channels==2 && st->force_channels!=1) + { + voice_bandwidth_thresholds = stereo_voice_bandwidth_thresholds; + music_bandwidth_thresholds = stereo_music_bandwidth_thresholds; + } else { + voice_bandwidth_thresholds = mono_voice_bandwidth_thresholds; + music_bandwidth_thresholds = mono_music_bandwidth_thresholds; + } + /* Interpolate bandwidth thresholds depending on voice estimation */ + for (i=0;i<8;i++) + { + bandwidth_thresholds[i] = music_bandwidth_thresholds[i] + + ((voice_est*voice_est*(voice_bandwidth_thresholds[i]-music_bandwidth_thresholds[i]))>>14); + } + do { + int threshold, hysteresis; + threshold = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)]; + hysteresis = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)+1]; + if (!st->first) + { + if (st->bandwidth >= bandwidth) + threshold -= hysteresis; + else + threshold += hysteresis; + } + if (equiv_rate2 >= threshold) + break; + } while (--bandwidth>OPUS_BANDWIDTH_NARROWBAND); + st->bandwidth = bandwidth; + /* Prevents any transition to SWB/FB until the SILK layer has fully + switched to WB mode and turned the variable LP filter off */ + if (!st->first && st->mode != MODE_CELT_ONLY && !st->silk_mode.inWBmodeWithoutVariableLP && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND) + st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; + } + + if (st->bandwidth>st->max_bandwidth) + st->bandwidth = st->max_bandwidth; + + if (st->user_bandwidth != OPUS_AUTO) + st->bandwidth = st->user_bandwidth; + + /* This prevents us from using hybrid at unsafe CBR/max rates */ + if (st->mode != MODE_CELT_ONLY && max_rate < 15000) + { + st->bandwidth = IMIN(st->bandwidth, OPUS_BANDWIDTH_WIDEBAND); + } + + /* Prevents Opus from wasting bits on frequencies that are above + the Nyquist rate of the input signal */ + if (st->Fs <= 24000 && st->bandwidth > OPUS_BANDWIDTH_SUPERWIDEBAND) + st->bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; + if (st->Fs <= 16000 && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND) + st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; + if (st->Fs <= 12000 && st->bandwidth > OPUS_BANDWIDTH_MEDIUMBAND) + st->bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; + if (st->Fs <= 8000 && st->bandwidth > OPUS_BANDWIDTH_NARROWBAND) + st->bandwidth = OPUS_BANDWIDTH_NARROWBAND; +#ifndef DISABLE_FLOAT_API + /* Use detected bandwidth to reduce the encoded bandwidth. */ + if (st->detected_bandwidth && st->user_bandwidth == OPUS_AUTO) + { + int min_detected_bandwidth; + /* Makes bandwidth detection more conservative just in case the detector + gets it wrong when we could have coded a high bandwidth transparently. + When operating in SILK/hybrid mode, we don't go below wideband to avoid + more complicated switches that require redundancy. */ + if (equiv_rate <= 18000*st->stream_channels && st->mode == MODE_CELT_ONLY) + min_detected_bandwidth = OPUS_BANDWIDTH_NARROWBAND; + else if (equiv_rate <= 24000*st->stream_channels && st->mode == MODE_CELT_ONLY) + min_detected_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; + else if (equiv_rate <= 30000*st->stream_channels) + min_detected_bandwidth = OPUS_BANDWIDTH_WIDEBAND; + else if (equiv_rate <= 44000*st->stream_channels) + min_detected_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; + else + min_detected_bandwidth = OPUS_BANDWIDTH_FULLBAND; + + st->detected_bandwidth = IMAX(st->detected_bandwidth, min_detected_bandwidth); + st->bandwidth = IMIN(st->bandwidth, st->detected_bandwidth); + } +#endif + celt_encoder_ctl(celt_enc, OPUS_SET_LSB_DEPTH(lsb_depth)); + + /* CELT mode doesn't support mediumband, use wideband instead */ + if (st->mode == MODE_CELT_ONLY && st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) + st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; + if (st->lfe) + st->bandwidth = OPUS_BANDWIDTH_NARROWBAND; + + /* Can't support higher than wideband for >20 ms frames */ + if (frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY || st->bandwidth > OPUS_BANDWIDTH_WIDEBAND)) + { + VARDECL(unsigned char, tmp_data); + int nb_frames; + int bak_mode, bak_bandwidth, bak_channels, bak_to_mono; + VARDECL(OpusRepacketizer, rp); + opus_int32 bytes_per_frame; + opus_int32 repacketize_len; + +#ifndef DISABLE_FLOAT_API + if (analysis_read_pos_bak!= -1) + { + st->analysis.read_pos = analysis_read_pos_bak; + st->analysis.read_subframe = analysis_read_subframe_bak; + } +#endif + + nb_frames = frame_size > st->Fs/25 ? 3 : 2; + bytes_per_frame = IMIN(1276,(out_data_bytes-3)/nb_frames); + + ALLOC(tmp_data, nb_frames*bytes_per_frame, unsigned char); + + ALLOC(rp, 1, OpusRepacketizer); + opus_repacketizer_init(rp); + + bak_mode = st->user_forced_mode; + bak_bandwidth = st->user_bandwidth; + bak_channels = st->force_channels; + + st->user_forced_mode = st->mode; + st->user_bandwidth = st->bandwidth; + st->force_channels = st->stream_channels; + bak_to_mono = st->silk_mode.toMono; + + if (bak_to_mono) + st->force_channels = 1; + else + st->prev_channels = st->stream_channels; + for (i=0;isilk_mode.toMono = 0; + /* When switching from SILK/Hybrid to CELT, only ask for a switch at the last frame */ + if (to_celt && i==nb_frames-1) + st->user_forced_mode = MODE_CELT_ONLY; + tmp_len = opus_encode_native(st, pcm+i*(st->channels*st->Fs/50), st->Fs/50, + tmp_data+i*bytes_per_frame, bytes_per_frame, lsb_depth, + NULL, 0, c1, c2, analysis_channels, downmix); + if (tmp_len<0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + ret = opus_repacketizer_cat(rp, tmp_data+i*bytes_per_frame, tmp_len); + if (ret<0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + } + if (st->use_vbr) + repacketize_len = out_data_bytes; + else + repacketize_len = IMIN(3*st->bitrate_bps/(3*8*50/nb_frames), out_data_bytes); + ret = opus_repacketizer_out_range_impl(rp, 0, nb_frames, data, repacketize_len, 0, !st->use_vbr); + if (ret<0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + st->user_forced_mode = bak_mode; + st->user_bandwidth = bak_bandwidth; + st->force_channels = bak_channels; + st->silk_mode.toMono = bak_to_mono; + RESTORE_STACK; + return ret; + } + curr_bandwidth = st->bandwidth; + + /* Chooses the appropriate mode for speech + *NEVER* switch to/from CELT-only mode here as this will invalidate some assumptions */ + if (st->mode == MODE_SILK_ONLY && curr_bandwidth > OPUS_BANDWIDTH_WIDEBAND) + st->mode = MODE_HYBRID; + if (st->mode == MODE_HYBRID && curr_bandwidth <= OPUS_BANDWIDTH_WIDEBAND) + st->mode = MODE_SILK_ONLY; + + /* printf("%d %d %d %d\n", st->bitrate_bps, st->stream_channels, st->mode, curr_bandwidth); */ + bytes_target = IMIN(max_data_bytes-redundancy_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1; + + data += 1; + + ec_enc_init(&enc, data, max_data_bytes-1); + + ALLOC(pcm_buf, (total_buffer+frame_size)*st->channels, opus_val16); + for (i=0;ichannels;i++) + pcm_buf[i] = st->delay_buffer[(st->encoder_buffer-total_buffer)*st->channels+i]; + + if (st->mode == MODE_CELT_ONLY) + hp_freq_smth1 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ); + else + hp_freq_smth1 = ((silk_encoder*)silk_enc)->state_Fxx[0].sCmn.variable_HP_smth1_Q15; + + st->variable_HP_smth2_Q15 = silk_SMLAWB( st->variable_HP_smth2_Q15, + hp_freq_smth1 - st->variable_HP_smth2_Q15, SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF2, 16 ) ); + + /* convert from log scale to Hertz */ + cutoff_Hz = silk_log2lin( silk_RSHIFT( st->variable_HP_smth2_Q15, 8 ) ); + + if (st->application == OPUS_APPLICATION_VOIP) + { + hp_cutoff(pcm, cutoff_Hz, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs); + } else { + dc_reject(pcm, 3, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs); + } + + + + /* SILK processing */ + HB_gain = Q15ONE; + if (st->mode != MODE_CELT_ONLY) + { + opus_int32 total_bitRate, celt_rate; +#ifdef FIXED_POINT + const opus_int16 *pcm_silk; +#else + VARDECL(opus_int16, pcm_silk); + ALLOC(pcm_silk, st->channels*frame_size, opus_int16); +#endif + + /* Distribute bits between SILK and CELT */ + total_bitRate = 8 * bytes_target * frame_rate; + if( st->mode == MODE_HYBRID ) { + int HB_gain_ref; + /* Base rate for SILK */ + st->silk_mode.bitRate = st->stream_channels * ( 5000 + 1000 * ( st->Fs == 100 * frame_size ) ); + if( curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND ) { + /* SILK gets 2/3 of the remaining bits */ + st->silk_mode.bitRate += ( total_bitRate - st->silk_mode.bitRate ) * 2 / 3; + } else { /* FULLBAND */ + /* SILK gets 3/5 of the remaining bits */ + st->silk_mode.bitRate += ( total_bitRate - st->silk_mode.bitRate ) * 3 / 5; + } + /* Don't let SILK use more than 80% */ + if( st->silk_mode.bitRate > total_bitRate * 4/5 ) { + st->silk_mode.bitRate = total_bitRate * 4/5; + } + if (!st->energy_masking) + { + /* Increasingly attenuate high band when it gets allocated fewer bits */ + celt_rate = total_bitRate - st->silk_mode.bitRate; + HB_gain_ref = (curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND) ? 3000 : 3600; + HB_gain = SHL32((opus_val32)celt_rate, 9) / SHR32((opus_val32)celt_rate + st->stream_channels * HB_gain_ref, 6); + HB_gain = HB_gain < Q15ONE*6/7 ? HB_gain + Q15ONE/7 : Q15ONE; + } + } else { + /* SILK gets all bits */ + st->silk_mode.bitRate = total_bitRate; + } + + /* Surround masking for SILK */ + if (st->energy_masking && st->use_vbr && !st->lfe) + { + opus_val32 mask_sum=0; + opus_val16 masking_depth; + opus_int32 rate_offset; + int c; + int end = 17; + opus_int16 srate = 16000; + if (st->bandwidth == OPUS_BANDWIDTH_NARROWBAND) + { + end = 13; + srate = 8000; + } else if (st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) + { + end = 15; + srate = 12000; + } + for (c=0;cchannels;c++) + { + for(i=0;ienergy_masking[21*c+i], + QCONST16(.5f, DB_SHIFT)), -QCONST16(2.0f, DB_SHIFT)); + if (mask > 0) + mask = HALF16(mask); + mask_sum += mask; + } + } + /* Conservative rate reduction, we cut the masking in half */ + masking_depth = mask_sum / end*st->channels; + masking_depth += QCONST16(.2f, DB_SHIFT); + rate_offset = (opus_int32)PSHR32(MULT16_16(srate, masking_depth), DB_SHIFT); + rate_offset = MAX32(rate_offset, -2*st->silk_mode.bitRate/3); + /* Split the rate change between the SILK and CELT part for hybrid. */ + if (st->bandwidth==OPUS_BANDWIDTH_SUPERWIDEBAND || st->bandwidth==OPUS_BANDWIDTH_FULLBAND) + st->silk_mode.bitRate += 3*rate_offset/5; + else + st->silk_mode.bitRate += rate_offset; + bytes_target += rate_offset * frame_size / (8 * st->Fs); + } + + st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs; + st->silk_mode.nChannelsAPI = st->channels; + st->silk_mode.nChannelsInternal = st->stream_channels; + if (curr_bandwidth == OPUS_BANDWIDTH_NARROWBAND) { + st->silk_mode.desiredInternalSampleRate = 8000; + } else if (curr_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) { + st->silk_mode.desiredInternalSampleRate = 12000; + } else { + silk_assert( st->mode == MODE_HYBRID || curr_bandwidth == OPUS_BANDWIDTH_WIDEBAND ); + st->silk_mode.desiredInternalSampleRate = 16000; + } + if( st->mode == MODE_HYBRID ) { + /* Don't allow bandwidth reduction at lowest bitrates in hybrid mode */ + st->silk_mode.minInternalSampleRate = 16000; + } else { + st->silk_mode.minInternalSampleRate = 8000; + } + + if (st->mode == MODE_SILK_ONLY) + { + opus_int32 effective_max_rate = max_rate; + st->silk_mode.maxInternalSampleRate = 16000; + if (frame_rate > 50) + effective_max_rate = effective_max_rate*2/3; + if (effective_max_rate < 13000) + { + st->silk_mode.maxInternalSampleRate = 12000; + st->silk_mode.desiredInternalSampleRate = IMIN(12000, st->silk_mode.desiredInternalSampleRate); + } + if (effective_max_rate < 9600) + { + st->silk_mode.maxInternalSampleRate = 8000; + st->silk_mode.desiredInternalSampleRate = IMIN(8000, st->silk_mode.desiredInternalSampleRate); + } + } else { + st->silk_mode.maxInternalSampleRate = 16000; + } + + st->silk_mode.useCBR = !st->use_vbr; + + /* Call SILK encoder for the low band */ + nBytes = IMIN(1275, max_data_bytes-1-redundancy_bytes); + + st->silk_mode.maxBits = nBytes*8; + /* Only allow up to 90% of the bits for hybrid mode*/ + if (st->mode == MODE_HYBRID) + st->silk_mode.maxBits = (opus_int32)st->silk_mode.maxBits*9/10; + if (st->silk_mode.useCBR) + { + st->silk_mode.maxBits = (st->silk_mode.bitRate * frame_size / (st->Fs * 8))*8; + /* Reduce the initial target to make it easier to reach the CBR rate */ + st->silk_mode.bitRate = IMAX(1, st->silk_mode.bitRate-2000); + } + + if (prefill) + { + opus_int32 zero=0; + int prefill_offset; + /* Use a smooth onset for the SILK prefill to avoid the encoder trying to encode + a discontinuity. The exact location is what we need to avoid leaving any "gap" + in the audio when mixing with the redundant CELT frame. Here we can afford to + overwrite st->delay_buffer because the only thing that uses it before it gets + rewritten is tmp_prefill[] and even then only the part after the ramp really + gets used (rather than sent to the encoder and discarded) */ + prefill_offset = st->channels*(st->encoder_buffer-st->delay_compensation-st->Fs/400); + gain_fade(st->delay_buffer+prefill_offset, st->delay_buffer+prefill_offset, + 0, Q15ONE, celt_mode->overlap, st->Fs/400, st->channels, celt_mode->window, st->Fs); + for(i=0;idelay_buffer[i]=0; +#ifdef FIXED_POINT + pcm_silk = st->delay_buffer; +#else + for (i=0;iencoder_buffer*st->channels;i++) + pcm_silk[i] = FLOAT2INT16(st->delay_buffer[i]); +#endif + silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, 1 ); + } + +#ifdef FIXED_POINT + pcm_silk = pcm_buf+total_buffer*st->channels; +#else + for (i=0;ichannels;i++) + pcm_silk[i] = FLOAT2INT16(pcm_buf[total_buffer*st->channels + i]); +#endif + ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0 ); + if( ret ) { + /*fprintf (stderr, "SILK encode error: %d\n", ret);*/ + /* Handle error */ + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + if (nBytes==0) + { + st->rangeFinal = 0; + data[-1] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels); + RESTORE_STACK; + return 1; + } + /* Extract SILK internal bandwidth for signaling in first byte */ + if( st->mode == MODE_SILK_ONLY ) { + if( st->silk_mode.internalSampleRate == 8000 ) { + curr_bandwidth = OPUS_BANDWIDTH_NARROWBAND; + } else if( st->silk_mode.internalSampleRate == 12000 ) { + curr_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; + } else if( st->silk_mode.internalSampleRate == 16000 ) { + curr_bandwidth = OPUS_BANDWIDTH_WIDEBAND; + } + } else { + silk_assert( st->silk_mode.internalSampleRate == 16000 ); + } + + st->silk_mode.opusCanSwitch = st->silk_mode.switchReady; + /* FIXME: How do we allocate the redundancy for CBR? */ + if (st->silk_mode.opusCanSwitch) + { + redundancy = 1; + celt_to_silk = 0; + st->silk_bw_switch = 1; + } + } + + /* CELT processing */ + { + int endband=21; + + switch(curr_bandwidth) + { + case OPUS_BANDWIDTH_NARROWBAND: + endband = 13; + break; + case OPUS_BANDWIDTH_MEDIUMBAND: + case OPUS_BANDWIDTH_WIDEBAND: + endband = 17; + break; + case OPUS_BANDWIDTH_SUPERWIDEBAND: + endband = 19; + break; + case OPUS_BANDWIDTH_FULLBAND: + endband = 21; + break; + } + celt_encoder_ctl(celt_enc, CELT_SET_END_BAND(endband)); + celt_encoder_ctl(celt_enc, CELT_SET_CHANNELS(st->stream_channels)); + } + celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(OPUS_BITRATE_MAX)); + if (st->mode != MODE_SILK_ONLY) + { + opus_val32 celt_pred=2; + celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0)); + /* We may still decide to disable prediction later */ + if (st->silk_mode.reducedDependency) + celt_pred = 0; + celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(celt_pred)); + + if (st->mode == MODE_HYBRID) + { + int len; + + len = (ec_tell(&enc)+7)>>3; + if (redundancy) + len += st->mode == MODE_HYBRID ? 3 : 1; + if( st->use_vbr ) { + nb_compr_bytes = len + bytes_target - (st->silk_mode.bitRate * frame_size) / (8 * st->Fs); + } else { + /* check if SILK used up too much */ + nb_compr_bytes = len > bytes_target ? len : bytes_target; + } + } else { + if (st->use_vbr) + { + opus_int32 bonus=0; +#ifndef DISABLE_FLOAT_API + if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != st->Fs/50) + { + bonus = (60*st->stream_channels+40)*(st->Fs/frame_size-50); + if (analysis_info.valid) + bonus = (opus_int32)(bonus*(1.f+.5f*analysis_info.tonality)); + } +#endif + celt_encoder_ctl(celt_enc, OPUS_SET_VBR(1)); + celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(st->vbr_constraint)); + celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps+bonus)); + nb_compr_bytes = max_data_bytes-1-redundancy_bytes; + } else { + nb_compr_bytes = bytes_target; + } + } + + } else { + nb_compr_bytes = 0; + } + + ALLOC(tmp_prefill, st->channels*st->Fs/400, opus_val16); + if (st->mode != MODE_SILK_ONLY && st->mode != st->prev_mode && st->prev_mode > 0) + { + for (i=0;ichannels*st->Fs/400;i++) + tmp_prefill[i] = st->delay_buffer[(st->encoder_buffer-total_buffer-st->Fs/400)*st->channels + i]; + } + + for (i=0;ichannels*(st->encoder_buffer-(frame_size+total_buffer));i++) + st->delay_buffer[i] = st->delay_buffer[i+st->channels*frame_size]; + for (;iencoder_buffer*st->channels;i++) + st->delay_buffer[i] = pcm_buf[(frame_size+total_buffer-st->encoder_buffer)*st->channels+i]; + + /* gain_fade() and stereo_fade() need to be after the buffer copying + because we don't want any of this to affect the SILK part */ + if( st->prev_HB_gain < Q15ONE || HB_gain < Q15ONE ) { + gain_fade(pcm_buf, pcm_buf, + st->prev_HB_gain, HB_gain, celt_mode->overlap, frame_size, st->channels, celt_mode->window, st->Fs); + } + st->prev_HB_gain = HB_gain; + if (st->mode != MODE_HYBRID || st->stream_channels==1) + st->silk_mode.stereoWidth_Q14 = IMIN((1<<14),2*IMAX(0,equiv_rate-30000)); + if( !st->energy_masking && st->channels == 2 ) { + /* Apply stereo width reduction (at low bitrates) */ + if( st->hybrid_stereo_width_Q14 < (1 << 14) || st->silk_mode.stereoWidth_Q14 < (1 << 14) ) { + opus_val16 g1, g2; + g1 = st->hybrid_stereo_width_Q14; + g2 = (opus_val16)(st->silk_mode.stereoWidth_Q14); +#ifdef FIXED_POINT + g1 = g1==16384 ? Q15ONE : SHL16(g1,1); + g2 = g2==16384 ? Q15ONE : SHL16(g2,1); +#else + g1 *= (1.f/16384); + g2 *= (1.f/16384); +#endif + stereo_fade(pcm_buf, pcm_buf, g1, g2, celt_mode->overlap, + frame_size, st->channels, celt_mode->window, st->Fs); + st->hybrid_stereo_width_Q14 = st->silk_mode.stereoWidth_Q14; + } + } + + if ( st->mode != MODE_CELT_ONLY && ec_tell(&enc)+17+20*(st->mode == MODE_HYBRID) <= 8*(max_data_bytes-1)) + { + /* For SILK mode, the redundancy is inferred from the length */ + if (st->mode == MODE_HYBRID && (redundancy || ec_tell(&enc)+37 <= 8*nb_compr_bytes)) + ec_enc_bit_logp(&enc, redundancy, 12); + if (redundancy) + { + int max_redundancy; + ec_enc_bit_logp(&enc, celt_to_silk, 1); + if (st->mode == MODE_HYBRID) + max_redundancy = (max_data_bytes-1)-nb_compr_bytes; + else + max_redundancy = (max_data_bytes-1)-((ec_tell(&enc)+7)>>3); + /* Target the same bit-rate for redundancy as for the rest, + up to a max of 257 bytes */ + redundancy_bytes = IMIN(max_redundancy, st->bitrate_bps/1600); + redundancy_bytes = IMIN(257, IMAX(2, redundancy_bytes)); + if (st->mode == MODE_HYBRID) + ec_enc_uint(&enc, redundancy_bytes-2, 256); + } + } else { + redundancy = 0; + } + + if (!redundancy) + { + st->silk_bw_switch = 0; + redundancy_bytes = 0; + } + if (st->mode != MODE_CELT_ONLY)start_band=17; + + if (st->mode == MODE_SILK_ONLY) + { + ret = (ec_tell(&enc)+7)>>3; + ec_enc_done(&enc); + nb_compr_bytes = ret; + } else { + nb_compr_bytes = IMIN((max_data_bytes-1)-redundancy_bytes, nb_compr_bytes); + ec_enc_shrink(&enc, nb_compr_bytes); + } + +#ifndef DISABLE_FLOAT_API + if (redundancy || st->mode != MODE_SILK_ONLY) + celt_encoder_ctl(celt_enc, CELT_SET_ANALYSIS(&analysis_info)); +#endif + + /* 5 ms redundant frame for CELT->SILK */ + if (redundancy && celt_to_silk) + { + int err; + celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0)); + celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0)); + err = celt_encode_with_ec(celt_enc, pcm_buf, st->Fs/200, data+nb_compr_bytes, redundancy_bytes, NULL); + if (err < 0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + celt_encoder_ctl(celt_enc, OPUS_GET_FINAL_RANGE(&redundant_rng)); + celt_encoder_ctl(celt_enc, OPUS_RESET_STATE); + } + + celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(start_band)); + + if (st->mode != MODE_SILK_ONLY) + { + if (st->mode != st->prev_mode && st->prev_mode > 0) + { + unsigned char dummy[2]; + celt_encoder_ctl(celt_enc, OPUS_RESET_STATE); + + /* Prefilling */ + celt_encode_with_ec(celt_enc, tmp_prefill, st->Fs/400, dummy, 2, NULL); + celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0)); + } + /* If false, we already busted the budget and we'll end up with a "PLC packet" */ + if (ec_tell(&enc) <= 8*nb_compr_bytes) + { + ret = celt_encode_with_ec(celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc); + if (ret < 0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + } + } + + /* 5 ms redundant frame for SILK->CELT */ + if (redundancy && !celt_to_silk) + { + int err; + unsigned char dummy[2]; + int N2, N4; + N2 = st->Fs/200; + N4 = st->Fs/400; + + celt_encoder_ctl(celt_enc, OPUS_RESET_STATE); + celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0)); + celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0)); + + /* NOTE: We could speed this up slightly (at the expense of code size) by just adding a function that prefills the buffer */ + celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2-N4), N4, dummy, 2, NULL); + + err = celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2), N2, data+nb_compr_bytes, redundancy_bytes, NULL); + if (err < 0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + celt_encoder_ctl(celt_enc, OPUS_GET_FINAL_RANGE(&redundant_rng)); + } + + + + /* Signalling the mode in the first byte */ + data--; + data[0] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels); + + st->rangeFinal = enc.rng ^ redundant_rng; + + if (to_celt) + st->prev_mode = MODE_CELT_ONLY; + else + st->prev_mode = st->mode; + st->prev_channels = st->stream_channels; + st->prev_framesize = frame_size; + + st->first = 0; + + /* In the unlikely case that the SILK encoder busted its target, tell + the decoder to call the PLC */ + if (ec_tell(&enc) > (max_data_bytes-1)*8) + { + if (max_data_bytes < 2) + { + RESTORE_STACK; + return OPUS_BUFFER_TOO_SMALL; + } + data[1] = 0; + ret = 1; + st->rangeFinal = 0; + } else if (st->mode==MODE_SILK_ONLY&&!redundancy) + { + /*When in LPC only mode it's perfectly + reasonable to strip off trailing zero bytes as + the required range decoder behavior is to + fill these in. This can't be done when the MDCT + modes are used because the decoder needs to know + the actual length for allocation purposes.*/ + while(ret>2&&data[ret]==0)ret--; + } + /* Count ToC and redundancy */ + ret += 1+redundancy_bytes; + if (!st->use_vbr) + { + if (opus_packet_pad(data, ret, max_data_bytes) != OPUS_OK) + + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + ret = max_data_bytes; + } + RESTORE_STACK; + return ret; +} + +#ifdef FIXED_POINT + +#ifndef DISABLE_FLOAT_API +opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size, + unsigned char *data, opus_int32 max_data_bytes) +{ + int i, ret; + int frame_size; + int delay_compensation; + VARDECL(opus_int16, in); + ALLOC_STACK; + + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, st->channels, st->Fs, st->bitrate_bps, + delay_compensation, downmix_float, st->analysis.subframe_mem); + + ALLOC(in, frame_size*st->channels, opus_int16); + + for (i=0;ichannels;i++) + in[i] = FLOAT2INT16(pcm[i]); + ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, pcm, analysis_frame_size, 0, -2, st->channels, downmix_float); + RESTORE_STACK; + return ret; +} +#endif + +opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size, + unsigned char *data, opus_int32 out_data_bytes) +{ + int frame_size; + int delay_compensation; + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, st->channels, st->Fs, st->bitrate_bps, + delay_compensation, downmix_int +#ifndef DISABLE_FLOAT_API + , st->analysis.subframe_mem +#endif + ); + return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16, pcm, analysis_frame_size, 0, -2, st->channels, downmix_int); +} + +#else +opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size, + unsigned char *data, opus_int32 max_data_bytes) +{ + int i, ret; + int frame_size; + int delay_compensation; + VARDECL(float, in); + ALLOC_STACK; + + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, st->channels, st->Fs, st->bitrate_bps, + delay_compensation, downmix_int, st->analysis.subframe_mem); + + ALLOC(in, frame_size*st->channels, float); + + for (i=0;ichannels;i++) + in[i] = (1.0f/32768)*pcm[i]; + ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, pcm, analysis_frame_size, 0, -2, st->channels, downmix_int); + RESTORE_STACK; + return ret; +} +opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size, + unsigned char *data, opus_int32 out_data_bytes) +{ + int frame_size; + int delay_compensation; + if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY) + delay_compensation = 0; + else + delay_compensation = st->delay_compensation; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, st->channels, st->Fs, st->bitrate_bps, + delay_compensation, downmix_float, st->analysis.subframe_mem); + return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24, + pcm, analysis_frame_size, 0, -2, st->channels, downmix_float); +} +#endif + + +int opus_encoder_ctl(OpusEncoder *st, int request, ...) +{ + int ret; + CELTEncoder *celt_enc; + va_list ap; + + ret = OPUS_OK; + va_start(ap, request); + + celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset); + + switch (request) + { + case OPUS_SET_APPLICATION_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if ( (value != OPUS_APPLICATION_VOIP && value != OPUS_APPLICATION_AUDIO + && value != OPUS_APPLICATION_RESTRICTED_LOWDELAY) + || (!st->first && st->application != value)) + { + ret = OPUS_BAD_ARG; + break; + } + st->application = value; + } + break; + case OPUS_GET_APPLICATION_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->application; + } + break; + case OPUS_SET_BITRATE_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX) + { + if (value <= 0) + goto bad_arg; + else if (value <= 500) + value = 500; + else if (value > (opus_int32)300000*st->channels) + value = (opus_int32)300000*st->channels; + } + st->user_bitrate_bps = value; + } + break; + case OPUS_GET_BITRATE_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = user_bitrate_to_bitrate(st, st->prev_framesize, 1276); + } + break; + case OPUS_SET_FORCE_CHANNELS_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if((value<1 || value>st->channels) && value != OPUS_AUTO) + { + goto bad_arg; + } + st->force_channels = value; + } + break; + case OPUS_GET_FORCE_CHANNELS_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->force_channels; + } + break; + case OPUS_SET_MAX_BANDWIDTH_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) + { + goto bad_arg; + } + st->max_bandwidth = value; + if (st->max_bandwidth == OPUS_BANDWIDTH_NARROWBAND) { + st->silk_mode.maxInternalSampleRate = 8000; + } else if (st->max_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) { + st->silk_mode.maxInternalSampleRate = 12000; + } else { + st->silk_mode.maxInternalSampleRate = 16000; + } + } + break; + case OPUS_GET_MAX_BANDWIDTH_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->max_bandwidth; + } + break; + case OPUS_SET_BANDWIDTH_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if ((value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) && value != OPUS_AUTO) + { + goto bad_arg; + } + st->user_bandwidth = value; + if (st->user_bandwidth == OPUS_BANDWIDTH_NARROWBAND) { + st->silk_mode.maxInternalSampleRate = 8000; + } else if (st->user_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) { + st->silk_mode.maxInternalSampleRate = 12000; + } else { + st->silk_mode.maxInternalSampleRate = 16000; + } + } + break; + case OPUS_GET_BANDWIDTH_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->bandwidth; + } + break; + case OPUS_SET_DTX_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if(value<0 || value>1) + { + goto bad_arg; + } + st->silk_mode.useDTX = value; + } + break; + case OPUS_GET_DTX_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->silk_mode.useDTX; + } + break; + case OPUS_SET_COMPLEXITY_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if(value<0 || value>10) + { + goto bad_arg; + } + st->silk_mode.complexity = value; + celt_encoder_ctl(celt_enc, OPUS_SET_COMPLEXITY(value)); + } + break; + case OPUS_GET_COMPLEXITY_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->silk_mode.complexity; + } + break; + case OPUS_SET_INBAND_FEC_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if(value<0 || value>1) + { + goto bad_arg; + } + st->silk_mode.useInBandFEC = value; + } + break; + case OPUS_GET_INBAND_FEC_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->silk_mode.useInBandFEC; + } + break; + case OPUS_SET_PACKET_LOSS_PERC_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value < 0 || value > 100) + { + goto bad_arg; + } + st->silk_mode.packetLossPercentage = value; + celt_encoder_ctl(celt_enc, OPUS_SET_PACKET_LOSS_PERC(value)); + } + break; + case OPUS_GET_PACKET_LOSS_PERC_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->silk_mode.packetLossPercentage; + } + break; + case OPUS_SET_VBR_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if(value<0 || value>1) + { + goto bad_arg; + } + st->use_vbr = value; + st->silk_mode.useCBR = 1-value; + } + break; + case OPUS_GET_VBR_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->use_vbr; + } + break; + case OPUS_SET_VOICE_RATIO_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<-1 || value>100) + { + goto bad_arg; + } + st->voice_ratio = value; + } + break; + case OPUS_GET_VOICE_RATIO_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->voice_ratio; + } + break; + case OPUS_SET_VBR_CONSTRAINT_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if(value<0 || value>1) + { + goto bad_arg; + } + st->vbr_constraint = value; + } + break; + case OPUS_GET_VBR_CONSTRAINT_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->vbr_constraint; + } + break; + case OPUS_SET_SIGNAL_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if(value!=OPUS_AUTO && value!=OPUS_SIGNAL_VOICE && value!=OPUS_SIGNAL_MUSIC) + { + goto bad_arg; + } + st->signal_type = value; + } + break; + case OPUS_GET_SIGNAL_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->signal_type; + } + break; + case OPUS_GET_LOOKAHEAD_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->Fs/400; + if (st->application != OPUS_APPLICATION_RESTRICTED_LOWDELAY) + *value += st->delay_compensation; + } + break; + case OPUS_GET_SAMPLE_RATE_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->Fs; + } + break; + case OPUS_GET_FINAL_RANGE_REQUEST: + { + opus_uint32 *value = va_arg(ap, opus_uint32*); + if (!value) + { + goto bad_arg; + } + *value = st->rangeFinal; + } + break; + case OPUS_SET_LSB_DEPTH_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value<8 || value>24) + { + goto bad_arg; + } + st->lsb_depth=value; + } + break; + case OPUS_GET_LSB_DEPTH_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->lsb_depth; + } + break; + case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value != OPUS_FRAMESIZE_ARG && value != OPUS_FRAMESIZE_2_5_MS && + value != OPUS_FRAMESIZE_5_MS && value != OPUS_FRAMESIZE_10_MS && + value != OPUS_FRAMESIZE_20_MS && value != OPUS_FRAMESIZE_40_MS && + value != OPUS_FRAMESIZE_60_MS && value != OPUS_FRAMESIZE_VARIABLE) + { + goto bad_arg; + } + st->variable_duration = value; + celt_encoder_ctl(celt_enc, OPUS_SET_EXPERT_FRAME_DURATION(value)); + } + break; + case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->variable_duration; + } + break; + case OPUS_SET_PREDICTION_DISABLED_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if (value > 1 || value < 0) + goto bad_arg; + st->silk_mode.reducedDependency = value; + } + break; + case OPUS_GET_PREDICTION_DISABLED_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + goto bad_arg; + *value = st->silk_mode.reducedDependency; + } + break; + case OPUS_RESET_STATE: + { + void *silk_enc; + silk_EncControlStruct dummy; + silk_enc = (char*)st+st->silk_enc_offset; + + OPUS_CLEAR((char*)&st->OPUS_ENCODER_RESET_START, + sizeof(OpusEncoder)- + ((char*)&st->OPUS_ENCODER_RESET_START - (char*)st)); + + celt_encoder_ctl(celt_enc, OPUS_RESET_STATE); + silk_InitEncoder( silk_enc, st->arch, &dummy ); + st->stream_channels = st->channels; + st->hybrid_stereo_width_Q14 = 1 << 14; + st->prev_HB_gain = Q15ONE; + st->first = 1; + st->mode = MODE_HYBRID; + st->bandwidth = OPUS_BANDWIDTH_FULLBAND; + st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ); + } + break; + case OPUS_SET_FORCE_MODE_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + if ((value < MODE_SILK_ONLY || value > MODE_CELT_ONLY) && value != OPUS_AUTO) + { + goto bad_arg; + } + st->user_forced_mode = value; + } + break; + case OPUS_SET_LFE_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->lfe = value; + ret = celt_encoder_ctl(celt_enc, OPUS_SET_LFE(value)); + } + break; + case OPUS_SET_ENERGY_MASK_REQUEST: + { + opus_val16 *value = va_arg(ap, opus_val16*); + st->energy_masking = value; + ret = celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_MASK(value)); + } + break; + + case CELT_GET_MODE_REQUEST: + { + const CELTMode ** value = va_arg(ap, const CELTMode**); + if (!value) + { + goto bad_arg; + } + ret = celt_encoder_ctl(celt_enc, CELT_GET_MODE(value)); + } + break; + default: + /* fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);*/ + ret = OPUS_UNIMPLEMENTED; + break; + } + va_end(ap); + return ret; +bad_arg: + va_end(ap); + return OPUS_BAD_ARG; +} + +void opus_encoder_destroy(OpusEncoder *st) +{ + opus_free(st); +} diff --git a/TelegramClient.Opus/opus/src/opus_multistream.c b/TelegramClient.Opus/opus/src/opus_multistream.c new file mode 100755 index 0000000..09c3639 --- /dev/null +++ b/TelegramClient.Opus/opus/src/opus_multistream.c @@ -0,0 +1,92 @@ +/* Copyright (c) 2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "opus_multistream.h" +#include "opus.h" +#include "opus_private.h" +#include "stack_alloc.h" +#include +#include "float_cast.h" +#include "os_support.h" + + +int validate_layout(const ChannelLayout *layout) +{ + int i, max_channel; + + max_channel = layout->nb_streams+layout->nb_coupled_streams; + if (max_channel>255) + return 0; + for (i=0;inb_channels;i++) + { + if (layout->mapping[i] >= max_channel && layout->mapping[i] != 255) + return 0; + } + return 1; +} + + +int get_left_channel(const ChannelLayout *layout, int stream_id, int prev) +{ + int i; + i = (prev<0) ? 0 : prev+1; + for (;inb_channels;i++) + { + if (layout->mapping[i]==stream_id*2) + return i; + } + return -1; +} + +int get_right_channel(const ChannelLayout *layout, int stream_id, int prev) +{ + int i; + i = (prev<0) ? 0 : prev+1; + for (;inb_channels;i++) + { + if (layout->mapping[i]==stream_id*2+1) + return i; + } + return -1; +} + +int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev) +{ + int i; + i = (prev<0) ? 0 : prev+1; + for (;inb_channels;i++) + { + if (layout->mapping[i]==stream_id+layout->nb_coupled_streams) + return i; + } + return -1; +} + diff --git a/TelegramClient.Opus/opus/src/opus_multistream_decoder.c b/TelegramClient.Opus/opus/src/opus_multistream_decoder.c new file mode 100755 index 0000000..a05fa1e --- /dev/null +++ b/TelegramClient.Opus/opus/src/opus_multistream_decoder.c @@ -0,0 +1,537 @@ +/* Copyright (c) 2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "opus_multistream.h" +#include "opus.h" +#include "opus_private.h" +#include "stack_alloc.h" +#include +#include "float_cast.h" +#include "os_support.h" + +struct OpusMSDecoder { + ChannelLayout layout; + /* Decoder states go here */ +}; + + + + +/* DECODER */ + +opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams) +{ + int coupled_size; + int mono_size; + + if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0; + coupled_size = opus_decoder_get_size(2); + mono_size = opus_decoder_get_size(1); + return align(sizeof(OpusMSDecoder)) + + nb_coupled_streams * align(coupled_size) + + (nb_streams-nb_coupled_streams) * align(mono_size); +} + +int opus_multistream_decoder_init( + OpusMSDecoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping +) +{ + int coupled_size; + int mono_size; + int i, ret; + char *ptr; + + if ((channels>255) || (channels<1) || (coupled_streams>streams) || + (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0)) + return OPUS_BAD_ARG; + + st->layout.nb_channels = channels; + st->layout.nb_streams = streams; + st->layout.nb_coupled_streams = coupled_streams; + + for (i=0;ilayout.nb_channels;i++) + st->layout.mapping[i] = mapping[i]; + if (!validate_layout(&st->layout)) + return OPUS_BAD_ARG; + + ptr = (char*)st + align(sizeof(OpusMSDecoder)); + coupled_size = opus_decoder_get_size(2); + mono_size = opus_decoder_get_size(1); + + for (i=0;ilayout.nb_coupled_streams;i++) + { + ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2); + if(ret!=OPUS_OK)return ret; + ptr += align(coupled_size); + } + for (;ilayout.nb_streams;i++) + { + ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1); + if(ret!=OPUS_OK)return ret; + ptr += align(mono_size); + } + return OPUS_OK; +} + + +OpusMSDecoder *opus_multistream_decoder_create( + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int *error +) +{ + int ret; + OpusMSDecoder *st; + if ((channels>255) || (channels<1) || (coupled_streams>streams) || + (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0)) + { + if (error) + *error = OPUS_BAD_ARG; + return NULL; + } + st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams)); + if (st==NULL) + { + if (error) + *error = OPUS_ALLOC_FAIL; + return NULL; + } + ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping); + if (error) + *error = ret; + if (ret != OPUS_OK) + { + opus_free(st); + st = NULL; + } + return st; +} + +typedef void (*opus_copy_channel_out_func)( + void *dst, + int dst_stride, + int dst_channel, + const opus_val16 *src, + int src_stride, + int frame_size +); + +static int opus_multistream_packet_validate(const unsigned char *data, + opus_int32 len, int nb_streams, opus_int32 Fs) +{ + int s; + int count; + unsigned char toc; + opus_int16 size[48]; + int samples=0; + opus_int32 packet_offset; + + for (s=0;slayout.nb_streams-1) + { + RESTORE_STACK; + return OPUS_INVALID_PACKET; + } + if (!do_plc) + { + int ret = opus_multistream_packet_validate(data, len, st->layout.nb_streams, Fs); + if (ret < 0) + { + RESTORE_STACK; + return ret; + } else if (ret > frame_size) + { + RESTORE_STACK; + return OPUS_BUFFER_TOO_SMALL; + } + } + for (s=0;slayout.nb_streams;s++) + { + OpusDecoder *dec; + int packet_offset, ret; + + dec = (OpusDecoder*)ptr; + ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size); + + if (!do_plc && len<=0) + { + RESTORE_STACK; + return OPUS_INTERNAL_ERROR; + } + packet_offset = 0; + ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip); + data += packet_offset; + len -= packet_offset; + if (ret <= 0) + { + RESTORE_STACK; + return ret; + } + frame_size = ret; + if (s < st->layout.nb_coupled_streams) + { + int chan, prev; + prev = -1; + /* Copy "left" audio to the channel(s) where it belongs */ + while ( (chan = get_left_channel(&st->layout, s, prev)) != -1) + { + (*copy_channel_out)(pcm, st->layout.nb_channels, chan, + buf, 2, frame_size); + prev = chan; + } + prev = -1; + /* Copy "right" audio to the channel(s) where it belongs */ + while ( (chan = get_right_channel(&st->layout, s, prev)) != -1) + { + (*copy_channel_out)(pcm, st->layout.nb_channels, chan, + buf+1, 2, frame_size); + prev = chan; + } + } else { + int chan, prev; + prev = -1; + /* Copy audio to the channel(s) where it belongs */ + while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1) + { + (*copy_channel_out)(pcm, st->layout.nb_channels, chan, + buf, 1, frame_size); + prev = chan; + } + } + } + /* Handle muted channels */ + for (c=0;clayout.nb_channels;c++) + { + if (st->layout.mapping[c] == 255) + { + (*copy_channel_out)(pcm, st->layout.nb_channels, c, + NULL, 0, frame_size); + } + } + RESTORE_STACK; + return frame_size; +} + +#if !defined(DISABLE_FLOAT_API) +static void opus_copy_channel_out_float( + void *dst, + int dst_stride, + int dst_channel, + const opus_val16 *src, + int src_stride, + int frame_size +) +{ + float *float_dst; + opus_int32 i; + float_dst = (float*)dst; + if (src != NULL) + { + for (i=0;ilayout.nb_streams;s++) + { + OpusDecoder *dec; + dec = (OpusDecoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + ret = opus_decoder_ctl(dec, request, &tmp); + if (ret != OPUS_OK) break; + *value ^= tmp; + } + } + break; + case OPUS_RESET_STATE: + { + int s; + for (s=0;slayout.nb_streams;s++) + { + OpusDecoder *dec; + + dec = (OpusDecoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + ret = opus_decoder_ctl(dec, OPUS_RESET_STATE); + if (ret != OPUS_OK) + break; + } + } + break; + case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST: + { + int s; + opus_int32 stream_id; + OpusDecoder **value; + stream_id = va_arg(ap, opus_int32); + if (stream_id<0 || stream_id >= st->layout.nb_streams) + ret = OPUS_BAD_ARG; + value = va_arg(ap, OpusDecoder**); + if (!value) + { + goto bad_arg; + } + for (s=0;slayout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + } + *value = (OpusDecoder*)ptr; + } + break; + case OPUS_SET_GAIN_REQUEST: + { + int s; + /* This works for int32 params */ + opus_int32 value = va_arg(ap, opus_int32); + for (s=0;slayout.nb_streams;s++) + { + OpusDecoder *dec; + + dec = (OpusDecoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + ret = opus_decoder_ctl(dec, request, value); + if (ret != OPUS_OK) + break; + } + } + break; + default: + ret = OPUS_UNIMPLEMENTED; + break; + } + + va_end(ap); + return ret; +bad_arg: + va_end(ap); + return OPUS_BAD_ARG; +} + + +void opus_multistream_decoder_destroy(OpusMSDecoder *st) +{ + opus_free(st); +} diff --git a/TelegramClient.Opus/opus/src/opus_multistream_encoder.c b/TelegramClient.Opus/opus/src/opus_multistream_encoder.c new file mode 100755 index 0000000..49e2791 --- /dev/null +++ b/TelegramClient.Opus/opus/src/opus_multistream_encoder.c @@ -0,0 +1,1174 @@ +/* Copyright (c) 2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "opus_multistream.h" +#include "opus.h" +#include "opus_private.h" +#include "stack_alloc.h" +#include +#include "float_cast.h" +#include "os_support.h" +#include "mathops.h" +#include "mdct.h" +#include "modes.h" +#include "bands.h" +#include "quant_bands.h" + +typedef struct { + int nb_streams; + int nb_coupled_streams; + unsigned char mapping[8]; +} VorbisLayout; + +/* Index is nb_channel-1*/ +static const VorbisLayout vorbis_mappings[8] = { + {1, 0, {0}}, /* 1: mono */ + {1, 1, {0, 1}}, /* 2: stereo */ + {2, 1, {0, 2, 1}}, /* 3: 1-d surround */ + {2, 2, {0, 1, 2, 3}}, /* 4: quadraphonic surround */ + {3, 2, {0, 4, 1, 2, 3}}, /* 5: 5-channel surround */ + {4, 2, {0, 4, 1, 2, 3, 5}}, /* 6: 5.1 surround */ + {4, 3, {0, 4, 1, 2, 3, 5, 6}}, /* 7: 6.1 surround */ + {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */ +}; + +typedef void (*opus_copy_channel_in_func)( + opus_val16 *dst, + int dst_stride, + const void *src, + int src_stride, + int src_channel, + int frame_size +); + +struct OpusMSEncoder { + ChannelLayout layout; + int lfe_stream; + int application; + int variable_duration; + int surround; + opus_int32 bitrate_bps; + float subframe_mem[3]; + /* Encoder states go here */ + /* then opus_val32 window_mem[channels*120]; */ + /* then opus_val32 preemph_mem[channels]; */ +}; + +static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st) +{ + int s; + char *ptr; + int coupled_size, mono_size; + + coupled_size = opus_encoder_get_size(2); + mono_size = opus_encoder_get_size(1); + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + for (s=0;slayout.nb_streams;s++) + { + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + } + return (opus_val32*)(ptr+st->layout.nb_channels*120*sizeof(opus_val32)); +} + +static opus_val32 *ms_get_window_mem(OpusMSEncoder *st) +{ + int s; + char *ptr; + int coupled_size, mono_size; + + coupled_size = opus_encoder_get_size(2); + mono_size = opus_encoder_get_size(1); + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + for (s=0;slayout.nb_streams;s++) + { + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + } + return (opus_val32*)ptr; +} + +static int validate_encoder_layout(const ChannelLayout *layout) +{ + int s; + for (s=0;snb_streams;s++) + { + if (s < layout->nb_coupled_streams) + { + if (get_left_channel(layout, s, -1)==-1) + return 0; + if (get_right_channel(layout, s, -1)==-1) + return 0; + } else { + if (get_mono_channel(layout, s, -1)==-1) + return 0; + } + } + return 1; +} + +static void channel_pos(int channels, int pos[8]) +{ + /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */ + if (channels==4) + { + pos[0]=1; + pos[1]=3; + pos[2]=1; + pos[3]=3; + } else if (channels==3||channels==5||channels==6) + { + pos[0]=1; + pos[1]=2; + pos[2]=3; + pos[3]=1; + pos[4]=3; + pos[5]=0; + } else if (channels==7) + { + pos[0]=1; + pos[1]=2; + pos[2]=3; + pos[3]=1; + pos[4]=3; + pos[5]=2; + pos[6]=0; + } else if (channels==8) + { + pos[0]=1; + pos[1]=2; + pos[2]=3; + pos[3]=1; + pos[4]=3; + pos[5]=1; + pos[6]=3; + pos[7]=0; + } +} + +#if 1 +/* Computes a rough approximation of log2(2^a + 2^b) */ +static opus_val16 logSum(opus_val16 a, opus_val16 b) +{ + opus_val16 max; + opus_val32 diff; + opus_val16 frac; + static const opus_val16 diff_table[17] = { + QCONST16(0.5000000f, DB_SHIFT), QCONST16(0.2924813f, DB_SHIFT), QCONST16(0.1609640f, DB_SHIFT), QCONST16(0.0849625f, DB_SHIFT), + QCONST16(0.0437314f, DB_SHIFT), QCONST16(0.0221971f, DB_SHIFT), QCONST16(0.0111839f, DB_SHIFT), QCONST16(0.0056136f, DB_SHIFT), + QCONST16(0.0028123f, DB_SHIFT) + }; + int low; + if (a>b) + { + max = a; + diff = SUB32(EXTEND32(a),EXTEND32(b)); + } else { + max = b; + diff = SUB32(EXTEND32(b),EXTEND32(a)); + } + if (diff >= QCONST16(8.f, DB_SHIFT)) + return max; +#ifdef FIXED_POINT + low = SHR32(diff, DB_SHIFT-1); + frac = SHL16(diff - SHL16(low, DB_SHIFT-1), 16-DB_SHIFT); +#else + low = (int)floor(2*diff); + frac = 2*diff - low; +#endif + return max + diff_table[low] + MULT16_16_Q15(frac, SUB16(diff_table[low+1], diff_table[low])); +} +#else +opus_val16 logSum(opus_val16 a, opus_val16 b) +{ + return log2(pow(4, a)+ pow(4, b))/2; +} +#endif + +void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *bandLogE, opus_val32 *mem, opus_val32 *preemph_mem, + int len, int overlap, int channels, int rate, opus_copy_channel_in_func copy_channel_in +) +{ + int c; + int i; + int LM; + int pos[8] = {0}; + int upsample; + int frame_size; + opus_val16 channel_offset; + opus_val32 bandE[21]; + opus_val16 maskLogE[3][21]; + VARDECL(opus_val32, in); + VARDECL(opus_val16, x); + VARDECL(opus_val32, freq); + SAVE_STACK; + + upsample = resampling_factor(rate); + frame_size = len*upsample; + + for (LM=0;LMmaxLM;LM++) + if (celt_mode->shortMdctSize<preemph, preemph_mem+c, 0); + clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window, overlap, celt_mode->maxLM-LM, 1); + if (upsample != 1) + { + int bound = len; + for (i=0;i=0;i--) + bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT)); + if (pos[c]==1) + { + for (i=0;i<21;i++) + maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]); + } else if (pos[c]==3) + { + for (i=0;i<21;i++) + maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]); + } else if (pos[c]==2) + { + for (i=0;i<21;i++) + { + maskLogE[0][i] = logSum(maskLogE[0][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT)); + maskLogE[2][i] = logSum(maskLogE[2][i], bandLogE[21*c+i]-QCONST16(.5f, DB_SHIFT)); + } + } +#if 0 + for (i=0;i<21;i++) + printf("%f ", bandLogE[21*c+i]); + float sum=0; + for (i=0;i<21;i++) + sum += bandLogE[21*c+i]; + printf("%f ", sum/21); +#endif + OPUS_COPY(mem+c*overlap, in+frame_size, overlap); + } + for (i=0;i<21;i++) + maskLogE[1][i] = MIN32(maskLogE[0][i],maskLogE[2][i]); + channel_offset = HALF16(celt_log2(QCONST32(2.f,14)/(channels-1))); + for (c=0;c<3;c++) + for (i=0;i<21;i++) + maskLogE[c][i] += channel_offset; +#if 0 + for (c=0;c<3;c++) + { + for (i=0;i<21;i++) + printf("%f ", maskLogE[c][i]); + } +#endif + for (c=0;cnb_streams||nb_coupled_streams<0)return 0; + coupled_size = opus_encoder_get_size(2); + mono_size = opus_encoder_get_size(1); + return align(sizeof(OpusMSEncoder)) + + nb_coupled_streams * align(coupled_size) + + (nb_streams-nb_coupled_streams) * align(mono_size); +} + +opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family) +{ + int nb_streams; + int nb_coupled_streams; + opus_int32 size; + + if (mapping_family==0) + { + if (channels==1) + { + nb_streams=1; + nb_coupled_streams=0; + } else if (channels==2) + { + nb_streams=1; + nb_coupled_streams=1; + } else + return 0; + } else if (mapping_family==1 && channels<=8 && channels>=1) + { + nb_streams=vorbis_mappings[channels-1].nb_streams; + nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams; + } else if (mapping_family==255) + { + nb_streams=channels; + nb_coupled_streams=0; + } else + return 0; + size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams); + if (channels>2) + { + size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32)); + } + return size; +} + + +static int opus_multistream_encoder_init_impl( + OpusMSEncoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application, + int surround +) +{ + int coupled_size; + int mono_size; + int i, ret; + char *ptr; + + if ((channels>255) || (channels<1) || (coupled_streams>streams) || + (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0)) + return OPUS_BAD_ARG; + + st->layout.nb_channels = channels; + st->layout.nb_streams = streams; + st->layout.nb_coupled_streams = coupled_streams; + st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0; + if (!surround) + st->lfe_stream = -1; + st->bitrate_bps = OPUS_AUTO; + st->application = application; + st->variable_duration = OPUS_FRAMESIZE_ARG; + for (i=0;ilayout.nb_channels;i++) + st->layout.mapping[i] = mapping[i]; + if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout)) + return OPUS_BAD_ARG; + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + coupled_size = opus_encoder_get_size(2); + mono_size = opus_encoder_get_size(1); + + for (i=0;ilayout.nb_coupled_streams;i++) + { + ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application); + if(ret!=OPUS_OK)return ret; + if (i==st->lfe_stream) + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1)); + ptr += align(coupled_size); + } + for (;ilayout.nb_streams;i++) + { + ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application); + if (i==st->lfe_stream) + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1)); + if(ret!=OPUS_OK)return ret; + ptr += align(mono_size); + } + if (surround) + { + OPUS_CLEAR(ms_get_preemph_mem(st), channels); + OPUS_CLEAR(ms_get_window_mem(st), channels*120); + } + st->surround = surround; + return OPUS_OK; +} + +int opus_multistream_encoder_init( + OpusMSEncoder *st, + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application +) +{ + return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0); +} + +int opus_multistream_surround_encoder_init( + OpusMSEncoder *st, + opus_int32 Fs, + int channels, + int mapping_family, + int *streams, + int *coupled_streams, + unsigned char *mapping, + int application +) +{ + if ((channels>255) || (channels<1)) + return OPUS_BAD_ARG; + st->lfe_stream = -1; + if (mapping_family==0) + { + if (channels==1) + { + *streams=1; + *coupled_streams=0; + mapping[0]=0; + } else if (channels==2) + { + *streams=1; + *coupled_streams=1; + mapping[0]=0; + mapping[1]=1; + } else + return OPUS_UNIMPLEMENTED; + } else if (mapping_family==1 && channels<=8 && channels>=1) + { + int i; + *streams=vorbis_mappings[channels-1].nb_streams; + *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams; + for (i=0;i=6) + st->lfe_stream = *streams-1; + } else if (mapping_family==255) + { + int i; + *streams=channels; + *coupled_streams=0; + for(i=0;i2&&mapping_family==1); +} + +OpusMSEncoder *opus_multistream_encoder_create( + opus_int32 Fs, + int channels, + int streams, + int coupled_streams, + const unsigned char *mapping, + int application, + int *error +) +{ + int ret; + OpusMSEncoder *st; + if ((channels>255) || (channels<1) || (coupled_streams>streams) || + (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0)) + { + if (error) + *error = OPUS_BAD_ARG; + return NULL; + } + st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams)); + if (st==NULL) + { + if (error) + *error = OPUS_ALLOC_FAIL; + return NULL; + } + ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application); + if (ret != OPUS_OK) + { + opus_free(st); + st = NULL; + } + if (error) + *error = ret; + return st; +} + +OpusMSEncoder *opus_multistream_surround_encoder_create( + opus_int32 Fs, + int channels, + int mapping_family, + int *streams, + int *coupled_streams, + unsigned char *mapping, + int application, + int *error +) +{ + int ret; + OpusMSEncoder *st; + if ((channels>255) || (channels<1)) + { + if (error) + *error = OPUS_BAD_ARG; + return NULL; + } + st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family)); + if (st==NULL) + { + if (error) + *error = OPUS_ALLOC_FAIL; + return NULL; + } + ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application); + if (ret != OPUS_OK) + { + opus_free(st); + st = NULL; + } + if (error) + *error = ret; + return st; +} + +static void surround_rate_allocation( + OpusMSEncoder *st, + opus_int32 *rate, + int frame_size + ) +{ + int i; + opus_int32 channel_rate; + opus_int32 Fs; + char *ptr; + int stream_offset; + int lfe_offset; + int coupled_ratio; /* Q8 */ + int lfe_ratio; /* Q8 */ + + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs)); + + if (st->bitrate_bps > st->layout.nb_channels*40000) + stream_offset = 20000; + else + stream_offset = st->bitrate_bps/st->layout.nb_channels/2; + stream_offset += 60*(Fs/frame_size-50); + /* We start by giving each stream (coupled or uncoupled) the same bitrate. + This models the main saving of coupled channels over uncoupled. */ + /* The LFE stream is an exception to the above and gets fewer bits. */ + lfe_offset = 3500 + 60*(Fs/frame_size-50); + /* Coupled streams get twice the mono rate after the first 20 kb/s. */ + coupled_ratio = 512; + /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */ + lfe_ratio = 32; + + /* Compute bitrate allocation between streams */ + if (st->bitrate_bps==OPUS_AUTO) + { + channel_rate = Fs+60*Fs/frame_size; + } else if (st->bitrate_bps==OPUS_BITRATE_MAX) + { + channel_rate = 300000; + } else { + int nb_lfe; + int nb_uncoupled; + int nb_coupled; + int total; + nb_lfe = (st->lfe_stream!=-1); + nb_coupled = st->layout.nb_coupled_streams; + nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe; + total = (nb_uncoupled<<8) /* mono */ + + coupled_ratio*nb_coupled /* stereo */ + + nb_lfe*lfe_ratio; + channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total; + } +#ifndef FIXED_POINT + if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50) + { + opus_int32 bonus; + bonus = 60*(Fs/frame_size-50); + channel_rate += bonus; + } +#endif + + for (i=0;ilayout.nb_streams;i++) + { + if (ilayout.nb_coupled_streams) + rate[i] = stream_offset+(channel_rate*coupled_ratio>>8); + else if (i!=st->lfe_stream) + rate[i] = stream_offset+channel_rate; + else + rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8); + } +} + +/* Max size in case the encoder decides to return three frames */ +#define MS_FRAME_TMP (3*1275+7) +static int opus_multistream_encode_native +( + OpusMSEncoder *st, + opus_copy_channel_in_func copy_channel_in, + const void *pcm, + int analysis_frame_size, + unsigned char *data, + opus_int32 max_data_bytes, + int lsb_depth, + downmix_func downmix +) +{ + opus_int32 Fs; + int coupled_size; + int mono_size; + int s; + char *ptr; + int tot_size; + VARDECL(opus_val16, buf); + VARDECL(opus_val16, bandSMR); + unsigned char tmp_data[MS_FRAME_TMP]; + OpusRepacketizer rp; + opus_int32 vbr; + const CELTMode *celt_mode; + opus_int32 bitrates[256]; + opus_val16 bandLogE[42]; + opus_val32 *mem = NULL; + opus_val32 *preemph_mem=NULL; + int frame_size; + ALLOC_STACK; + + if (st->surround) + { + preemph_mem = ms_get_preemph_mem(st); + mem = ms_get_window_mem(st); + } + + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs)); + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr)); + opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode)); + + { + opus_int32 delay_compensation; + int channels; + + channels = st->layout.nb_streams + st->layout.nb_coupled_streams; + opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation)); + delay_compensation -= Fs/400; + frame_size = compute_frame_size(pcm, analysis_frame_size, + st->variable_duration, channels, Fs, st->bitrate_bps, + delay_compensation, downmix +#ifndef DISABLE_FLOAT_API + , st->subframe_mem +#endif + ); + } + + if (400*frame_size < Fs) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + /* Validate frame_size before using it to allocate stack space. + This mirrors the checks in opus_encode[_float](). */ + if (400*frame_size != Fs && 200*frame_size != Fs && + 100*frame_size != Fs && 50*frame_size != Fs && + 25*frame_size != Fs && 50*frame_size != 3*Fs) + { + RESTORE_STACK; + return OPUS_BAD_ARG; + } + ALLOC(buf, 2*frame_size, opus_val16); + coupled_size = opus_encoder_get_size(2); + mono_size = opus_encoder_get_size(1); + + ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16); + if (st->surround) + { + surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in); + } + + if (max_data_bytes < 4*st->layout.nb_streams-1) + { + RESTORE_STACK; + return OPUS_BUFFER_TOO_SMALL; + } + + /* Compute bitrate allocation between streams (this could be a lot better) */ + surround_rate_allocation(st, bitrates, frame_size); + + if (!vbr) + max_data_bytes = IMIN(max_data_bytes, 3*st->bitrate_bps/(3*8*Fs/frame_size)); + + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + for (s=0;slayout.nb_streams;s++) + { + OpusEncoder *enc; + enc = (OpusEncoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s])); + if (st->surround) + { + opus_int32 equiv_rate; + equiv_rate = st->bitrate_bps; + if (frame_size*50 < Fs) + equiv_rate -= 60*(Fs/frame_size - 50)*st->layout.nb_channels; + if (equiv_rate > 10000*st->layout.nb_channels) + opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND)); + else if (equiv_rate > 7000*st->layout.nb_channels) + opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND)); + else if (equiv_rate > 5000*st->layout.nb_channels) + opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND)); + else + opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND)); + if (s < st->layout.nb_coupled_streams) + { + /* To preserve the spatial image, force stereo CELT on coupled streams */ + opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY)); + opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2)); + } + } + } + + ptr = (char*)st + align(sizeof(OpusMSEncoder)); + /* Counting ToC */ + tot_size = 0; + for (s=0;slayout.nb_streams;s++) + { + OpusEncoder *enc; + int len; + int curr_max; + int c1, c2; + + opus_repacketizer_init(&rp); + enc = (OpusEncoder*)ptr; + if (s < st->layout.nb_coupled_streams) + { + int i; + int left, right; + left = get_left_channel(&st->layout, s, -1); + right = get_right_channel(&st->layout, s, -1); + (*copy_channel_in)(buf, 2, + pcm, st->layout.nb_channels, left, frame_size); + (*copy_channel_in)(buf+1, 2, + pcm, st->layout.nb_channels, right, frame_size); + ptr += align(coupled_size); + if (st->surround) + { + for (i=0;i<21;i++) + { + bandLogE[i] = bandSMR[21*left+i]; + bandLogE[21+i] = bandSMR[21*right+i]; + } + } + c1 = left; + c2 = right; + } else { + int i; + int chan = get_mono_channel(&st->layout, s, -1); + (*copy_channel_in)(buf, 1, + pcm, st->layout.nb_channels, chan, frame_size); + ptr += align(mono_size); + if (st->surround) + { + for (i=0;i<21;i++) + bandLogE[i] = bandSMR[21*chan+i]; + } + c1 = chan; + c2 = -1; + } + if (st->surround) + opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE)); + /* number of bytes left (+Toc) */ + curr_max = max_data_bytes - tot_size; + /* Reserve three bytes for the last stream and four for the others */ + curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1); + curr_max = IMIN(curr_max,MS_FRAME_TMP); + if (!vbr && s == st->layout.nb_streams-1) + opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size))); + len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth, + pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix); + if (len<0) + { + RESTORE_STACK; + return len; + } + /* We need to use the repacketizer to add the self-delimiting lengths + while taking into account the fact that the encoder can now return + more than one frame at a time (e.g. 60 ms CELT-only) */ + opus_repacketizer_cat(&rp, tmp_data, len); + len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp), + data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1); + data += len; + tot_size += len; + } + /*printf("\n");*/ + RESTORE_STACK; + return tot_size; +} + +#if !defined(DISABLE_FLOAT_API) +static void opus_copy_channel_in_float( + opus_val16 *dst, + int dst_stride, + const void *src, + int src_stride, + int src_channel, + int frame_size +) +{ + const float *float_src; + opus_int32 i; + float_src = (const float *)src; + for (i=0;ibitrate_bps = value; + } + break; + case OPUS_GET_BITRATE_REQUEST: + { + int s; + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = 0; + for (s=0;slayout.nb_streams;s++) + { + opus_int32 rate; + OpusEncoder *enc; + enc = (OpusEncoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + opus_encoder_ctl(enc, request, &rate); + *value += rate; + } + } + break; + case OPUS_GET_LSB_DEPTH_REQUEST: + case OPUS_GET_VBR_REQUEST: + case OPUS_GET_APPLICATION_REQUEST: + case OPUS_GET_BANDWIDTH_REQUEST: + case OPUS_GET_COMPLEXITY_REQUEST: + case OPUS_GET_PACKET_LOSS_PERC_REQUEST: + case OPUS_GET_DTX_REQUEST: + case OPUS_GET_VOICE_RATIO_REQUEST: + case OPUS_GET_VBR_CONSTRAINT_REQUEST: + case OPUS_GET_SIGNAL_REQUEST: + case OPUS_GET_LOOKAHEAD_REQUEST: + case OPUS_GET_SAMPLE_RATE_REQUEST: + case OPUS_GET_INBAND_FEC_REQUEST: + case OPUS_GET_FORCE_CHANNELS_REQUEST: + case OPUS_GET_PREDICTION_DISABLED_REQUEST: + { + OpusEncoder *enc; + /* For int32* GET params, just query the first stream */ + opus_int32 *value = va_arg(ap, opus_int32*); + enc = (OpusEncoder*)ptr; + ret = opus_encoder_ctl(enc, request, value); + } + break; + case OPUS_GET_FINAL_RANGE_REQUEST: + { + int s; + opus_uint32 *value = va_arg(ap, opus_uint32*); + opus_uint32 tmp; + if (!value) + { + goto bad_arg; + } + *value=0; + for (s=0;slayout.nb_streams;s++) + { + OpusEncoder *enc; + enc = (OpusEncoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + ret = opus_encoder_ctl(enc, request, &tmp); + if (ret != OPUS_OK) break; + *value ^= tmp; + } + } + break; + case OPUS_SET_LSB_DEPTH_REQUEST: + case OPUS_SET_COMPLEXITY_REQUEST: + case OPUS_SET_VBR_REQUEST: + case OPUS_SET_VBR_CONSTRAINT_REQUEST: + case OPUS_SET_MAX_BANDWIDTH_REQUEST: + case OPUS_SET_BANDWIDTH_REQUEST: + case OPUS_SET_SIGNAL_REQUEST: + case OPUS_SET_APPLICATION_REQUEST: + case OPUS_SET_INBAND_FEC_REQUEST: + case OPUS_SET_PACKET_LOSS_PERC_REQUEST: + case OPUS_SET_DTX_REQUEST: + case OPUS_SET_FORCE_MODE_REQUEST: + case OPUS_SET_FORCE_CHANNELS_REQUEST: + case OPUS_SET_PREDICTION_DISABLED_REQUEST: + { + int s; + /* This works for int32 params */ + opus_int32 value = va_arg(ap, opus_int32); + for (s=0;slayout.nb_streams;s++) + { + OpusEncoder *enc; + + enc = (OpusEncoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + ret = opus_encoder_ctl(enc, request, value); + if (ret != OPUS_OK) + break; + } + } + break; + case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST: + { + int s; + opus_int32 stream_id; + OpusEncoder **value; + stream_id = va_arg(ap, opus_int32); + if (stream_id<0 || stream_id >= st->layout.nb_streams) + ret = OPUS_BAD_ARG; + value = va_arg(ap, OpusEncoder**); + if (!value) + { + goto bad_arg; + } + for (s=0;slayout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + } + *value = (OpusEncoder*)ptr; + } + break; + case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST: + { + opus_int32 value = va_arg(ap, opus_int32); + st->variable_duration = value; + } + break; + case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST: + { + opus_int32 *value = va_arg(ap, opus_int32*); + if (!value) + { + goto bad_arg; + } + *value = st->variable_duration; + } + break; + case OPUS_RESET_STATE: + { + int s; + st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0; + if (st->surround) + { + OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels); + OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120); + } + for (s=0;slayout.nb_streams;s++) + { + OpusEncoder *enc; + enc = (OpusEncoder*)ptr; + if (s < st->layout.nb_coupled_streams) + ptr += align(coupled_size); + else + ptr += align(mono_size); + ret = opus_encoder_ctl(enc, OPUS_RESET_STATE); + if (ret != OPUS_OK) + break; + } + } + break; + default: + ret = OPUS_UNIMPLEMENTED; + break; + } + + va_end(ap); + return ret; +bad_arg: + va_end(ap); + return OPUS_BAD_ARG; +} + +void opus_multistream_encoder_destroy(OpusMSEncoder *st) +{ + opus_free(st); +} diff --git a/TelegramClient.Opus/opus/src/opus_private.h b/TelegramClient.Opus/opus/src/opus_private.h new file mode 100755 index 0000000..83225f2 --- /dev/null +++ b/TelegramClient.Opus/opus/src/opus_private.h @@ -0,0 +1,129 @@ +/* Copyright (c) 2012 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + + +#ifndef OPUS_PRIVATE_H +#define OPUS_PRIVATE_H + +#include "arch.h" +#include "opus.h" +#include "celt.h" + +struct OpusRepacketizer { + unsigned char toc; + int nb_frames; + const unsigned char *frames[48]; + opus_int16 len[48]; + int framesize; +}; + +typedef struct ChannelLayout { + int nb_channels; + int nb_streams; + int nb_coupled_streams; + unsigned char mapping[256]; +} ChannelLayout; + +int validate_layout(const ChannelLayout *layout); +int get_left_channel(const ChannelLayout *layout, int stream_id, int prev); +int get_right_channel(const ChannelLayout *layout, int stream_id, int prev); +int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev); + + + +#define MODE_SILK_ONLY 1000 +#define MODE_HYBRID 1001 +#define MODE_CELT_ONLY 1002 + +#define OPUS_SET_VOICE_RATIO_REQUEST 11018 +#define OPUS_GET_VOICE_RATIO_REQUEST 11019 + +/** Configures the encoder's expected percentage of voice + * opposed to music or other signals. + * + * @note This interface is currently more aspiration than actuality. It's + * ultimately expected to bias an automatic signal classifier, but it currently + * just shifts the static bitrate to mode mapping around a little bit. + * + * @param[in] x int: Voice percentage in the range 0-100, inclusive. + * @hideinitializer */ +#define OPUS_SET_VOICE_RATIO(x) OPUS_SET_VOICE_RATIO_REQUEST, __opus_check_int(x) +/** Gets the encoder's configured voice ratio value, @see OPUS_SET_VOICE_RATIO + * + * @param[out] x int*: Voice percentage in the range 0-100, inclusive. + * @hideinitializer */ +#define OPUS_GET_VOICE_RATIO(x) OPUS_GET_VOICE_RATIO_REQUEST, __opus_check_int_ptr(x) + + +#define OPUS_SET_FORCE_MODE_REQUEST 11002 +#define OPUS_SET_FORCE_MODE(x) OPUS_SET_FORCE_MODE_REQUEST, __opus_check_int(x) + +typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int); +void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C); +void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C); + +int optimize_framesize(const opus_val16 *x, int len, int C, opus_int32 Fs, + int bitrate, opus_val16 tonality, float *mem, int buffering, + downmix_func downmix); + +int encode_size(int size, unsigned char *data); + +opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs); + +opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size, + int variable_duration, int C, opus_int32 Fs, int bitrate_bps, + int delay_compensation, downmix_func downmix +#ifndef DISABLE_FLOAT_API + , float *subframe_mem +#endif + ); + +opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size, + unsigned char *data, opus_int32 out_data_bytes, int lsb_depth, + const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2, int analysis_channels, downmix_func downmix); + +int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len, + opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited, + opus_int32 *packet_offset, int soft_clip); + +/* Make sure everything's aligned to sizeof(void *) bytes */ +static OPUS_INLINE int align(int i) +{ + return (i+(int)sizeof(void *)-1)&-(int)sizeof(void *); +} + +int opus_packet_parse_impl(const unsigned char *data, opus_int32 len, + int self_delimited, unsigned char *out_toc, + const unsigned char *frames[48], opus_int16 size[48], + int *payload_offset, opus_int32 *packet_offset); + +opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, + unsigned char *data, opus_int32 maxlen, int self_delimited, int pad); + +int pad_frame(unsigned char *data, opus_int32 len, opus_int32 new_len); + +#endif /* OPUS_PRIVATE_H */ diff --git a/TelegramClient.Opus/opus/src/repacketizer.c b/TelegramClient.Opus/opus/src/repacketizer.c new file mode 100755 index 0000000..a62675c --- /dev/null +++ b/TelegramClient.Opus/opus/src/repacketizer.c @@ -0,0 +1,345 @@ +/* Copyright (c) 2011 Xiph.Org Foundation + Written by Jean-Marc Valin */ +/* + 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. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "opus.h" +#include "opus_private.h" +#include "os_support.h" + + +int opus_repacketizer_get_size(void) +{ + return sizeof(OpusRepacketizer); +} + +OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) +{ + rp->nb_frames = 0; + return rp; +} + +OpusRepacketizer *opus_repacketizer_create(void) +{ + OpusRepacketizer *rp; + rp=(OpusRepacketizer *)opus_alloc(opus_repacketizer_get_size()); + if(rp==NULL)return NULL; + return opus_repacketizer_init(rp); +} + +void opus_repacketizer_destroy(OpusRepacketizer *rp) +{ + opus_free(rp); +} + +static int opus_repacketizer_cat_impl(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len, int self_delimited) +{ + unsigned char tmp_toc; + int curr_nb_frames,ret; + /* Set of check ToC */ + if (len<1) return OPUS_INVALID_PACKET; + if (rp->nb_frames == 0) + { + rp->toc = data[0]; + rp->framesize = opus_packet_get_samples_per_frame(data, 8000); + } else if ((rp->toc&0xFC) != (data[0]&0xFC)) + { + /*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp->toc, data[0]);*/ + return OPUS_INVALID_PACKET; + } + curr_nb_frames = opus_packet_get_nb_frames(data, len); + if(curr_nb_frames<1) return OPUS_INVALID_PACKET; + + /* Check the 120 ms maximum packet size */ + if ((curr_nb_frames+rp->nb_frames)*rp->framesize > 960) + { + return OPUS_INVALID_PACKET; + } + + ret=opus_packet_parse_impl(data, len, self_delimited, &tmp_toc, &rp->frames[rp->nb_frames], &rp->len[rp->nb_frames], NULL, NULL); + if(ret<1)return ret; + + rp->nb_frames += curr_nb_frames; + return OPUS_OK; +} + +int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) +{ + return opus_repacketizer_cat_impl(rp, data, len, 0); +} + +int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) +{ + return rp->nb_frames; +} + +opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end, + unsigned char *data, opus_int32 maxlen, int self_delimited, int pad) +{ + int i, count; + opus_int32 tot_size; + opus_int16 *len; + const unsigned char **frames; + unsigned char * ptr; + + if (begin<0 || begin>=end || end>rp->nb_frames) + { + /*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/ + return OPUS_BAD_ARG; + } + count = end-begin; + + len = rp->len+begin; + frames = rp->frames+begin; + if (self_delimited) + tot_size = 1 + (len[count-1]>=252); + else + tot_size = 0; + + ptr = data; + if (count==1) + { + /* Code 0 */ + tot_size += len[0]+1; + if (tot_size > maxlen) + return OPUS_BUFFER_TOO_SMALL; + *ptr++ = rp->toc&0xFC; + } else if (count==2) + { + if (len[1] == len[0]) + { + /* Code 1 */ + tot_size += 2*len[0]+1; + if (tot_size > maxlen) + return OPUS_BUFFER_TOO_SMALL; + *ptr++ = (rp->toc&0xFC) | 0x1; + } else { + /* Code 2 */ + tot_size += len[0]+len[1]+2+(len[0]>=252); + if (tot_size > maxlen) + return OPUS_BUFFER_TOO_SMALL; + *ptr++ = (rp->toc&0xFC) | 0x2; + ptr += encode_size(len[0], ptr); + } + } + if (count > 2 || (pad && tot_size < maxlen)) + { + /* Code 3 */ + int vbr; + int pad_amount=0; + + /* Restart the process for the padding case */ + ptr = data; + if (self_delimited) + tot_size = 1 + (len[count-1]>=252); + else + tot_size = 0; + vbr = 0; + for (i=1;i=252) + len[i]; + tot_size += len[count-1]; + + if (tot_size > maxlen) + return OPUS_BUFFER_TOO_SMALL; + *ptr++ = (rp->toc&0xFC) | 0x3; + *ptr++ = count | 0x80; + } else { + tot_size += count*len[0]+2; + if (tot_size > maxlen) + return OPUS_BUFFER_TOO_SMALL; + *ptr++ = (rp->toc&0xFC) | 0x3; + *ptr++ = count; + } + pad_amount = pad ? (maxlen-tot_size) : 0; + if (pad_amount != 0) + { + int nb_255s; + data[1] |= 0x40; + nb_255s = (pad_amount-1)/255; + for (i=0;inb_frames, data, maxlen, 0, 0); +} + +int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len) +{ + OpusRepacketizer rp; + opus_int32 ret; + if (len < 1) + return OPUS_BAD_ARG; + if (len==new_len) + return OPUS_OK; + else if (len > new_len) + return OPUS_BAD_ARG; + opus_repacketizer_init(&rp); + /* Moving payload to the end of the packet so we can do in-place padding */ + OPUS_MOVE(data+new_len-len, data, len); + opus_repacketizer_cat(&rp, data+new_len-len, len); + ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, 1); + if (ret > 0) + return OPUS_OK; + else + return ret; +} + +opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len) +{ + OpusRepacketizer rp; + opus_int32 ret; + if (len < 1) + return OPUS_BAD_ARG; + opus_repacketizer_init(&rp); + ret = opus_repacketizer_cat(&rp, data, len); + if (ret < 0) + return ret; + ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 0); + celt_assert(ret > 0 && ret <= len); + return ret; +} + +int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams) +{ + int s; + int count; + unsigned char toc; + opus_int16 size[48]; + opus_int32 packet_offset; + opus_int32 amount; + + if (len < 1) + return OPUS_BAD_ARG; + if (len==new_len) + return OPUS_OK; + else if (len > new_len) + return OPUS_BAD_ARG; + amount = new_len - len; + /* Seek to last stream */ + for (s=0;s +#include +#include + +#define MAX_PACKETOUT 32000 + +void usage(char *argv0) +{ + fprintf(stderr, "usage: %s [options] input_file output_file\n", argv0); +} + +static void int_to_char(opus_uint32 i, unsigned char ch[4]) +{ + ch[0] = i>>24; + ch[1] = (i>>16)&0xFF; + ch[2] = (i>>8)&0xFF; + ch[3] = i&0xFF; +} + +static opus_uint32 char_to_int(unsigned char ch[4]) +{ + return ((opus_uint32)ch[0]<<24) | ((opus_uint32)ch[1]<<16) + | ((opus_uint32)ch[2]<< 8) | (opus_uint32)ch[3]; +} + +int main(int argc, char *argv[]) +{ + int i, eof=0; + FILE *fin, *fout; + unsigned char packets[48][1500]; + int len[48]; + int rng[48]; + OpusRepacketizer *rp; + unsigned char output_packet[MAX_PACKETOUT]; + int merge = 1, split=0; + + if (argc < 3) + { + usage(argv[0]); + return EXIT_FAILURE; + } + for (i=1;i48) + { + fprintf(stderr, "-merge parameter must be less than 48.\n"); + return EXIT_FAILURE; + } + i++; + } else if (strcmp(argv[i], "-split")==0) + split = 1; + else + { + fprintf(stderr, "Unknown option: %s\n", argv[i]); + usage(argv[0]); + return EXIT_FAILURE; + } + } + fin = fopen(argv[argc-2], "r"); + if(fin==NULL) + { + fprintf(stderr, "Error opening input file: %s\n", argv[argc-2]); + return EXIT_FAILURE; + } + fout = fopen(argv[argc-1], "w"); + if(fout==NULL) + { + fprintf(stderr, "Error opening output file: %s\n", argv[argc-1]); + fclose(fin); + return EXIT_FAILURE; + } + + rp = opus_repacketizer_create(); + while (!eof) + { + int err; + int nb_packets=merge; + opus_repacketizer_init(rp); + for (i=0;i1500 || len[i]<0) + { + if (feof(fin)) + { + eof = 1; + } else { + fprintf(stderr, "Invalid payload length\n"); + fclose(fin); + fclose(fout); + return EXIT_FAILURE; + } + break; + } + err = fread(ch, 1, 4, fin); + rng[i] = char_to_int(ch); + err = fread(packets[i], 1, len[i], fin); + if (feof(fin)) + { + eof = 1; + break; + } + err = opus_repacketizer_cat(rp, packets[i], len[i]); + if (err!=OPUS_OK) + { + fprintf(stderr, "opus_repacketizer_cat() failed: %s\n", opus_strerror(err)); + break; + } + } + nb_packets = i; + + if (eof) + break; + + if (!split) + { + err = opus_repacketizer_out(rp, output_packet, MAX_PACKETOUT); + if (err>0) { + unsigned char int_field[4]; + int_to_char(err, int_field); + if(fwrite(int_field, 1, 4, fout)!=4){ + fprintf(stderr, "Error writing.\n"); + return EXIT_FAILURE; + } + int_to_char(rng[nb_packets-1], int_field); + if (fwrite(int_field, 1, 4, fout)!=4) { + fprintf(stderr, "Error writing.\n"); + return EXIT_FAILURE; + } + if (fwrite(output_packet, 1, err, fout)!=(unsigned)err) { + fprintf(stderr, "Error writing.\n"); + return EXIT_FAILURE; + } + /*fprintf(stderr, "out len = %d\n", err);*/ + } else { + fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err)); + } + } else { + int nb_frames = opus_repacketizer_get_nb_frames(rp); + for (i=0;i0) { + unsigned char int_field[4]; + int_to_char(err, int_field); + if (fwrite(int_field, 1, 4, fout)!=4) { + fprintf(stderr, "Error writing.\n"); + return EXIT_FAILURE; + } + if (i==nb_frames-1) + int_to_char(rng[nb_packets-1], int_field); + else + int_to_char(0, int_field); + if (fwrite(int_field, 1, 4, fout)!=4) { + fprintf(stderr, "Error writing.\n"); + return EXIT_FAILURE; + } + if (fwrite(output_packet, 1, err, fout)!=(unsigned)err) { + fprintf(stderr, "Error writing.\n"); + return EXIT_FAILURE; + } + /*fprintf(stderr, "out len = %d\n", err);*/ + } else { + fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err)); + } + + } + } + } + + fclose(fin); + fclose(fout); + return EXIT_SUCCESS; +} diff --git a/TelegramClient.Opus/opus/src/tansig_table.h b/TelegramClient.Opus/opus/src/tansig_table.h new file mode 100755 index 0000000..c76f844 --- /dev/null +++ b/TelegramClient.Opus/opus/src/tansig_table.h @@ -0,0 +1,45 @@ +/* This file is auto-generated by gen_tables */ + +static const float tansig_table[201] = { +0.000000f, 0.039979f, 0.079830f, 0.119427f, 0.158649f, +0.197375f, 0.235496f, 0.272905f, 0.309507f, 0.345214f, +0.379949f, 0.413644f, 0.446244f, 0.477700f, 0.507977f, +0.537050f, 0.564900f, 0.591519f, 0.616909f, 0.641077f, +0.664037f, 0.685809f, 0.706419f, 0.725897f, 0.744277f, +0.761594f, 0.777888f, 0.793199f, 0.807569f, 0.821040f, +0.833655f, 0.845456f, 0.856485f, 0.866784f, 0.876393f, +0.885352f, 0.893698f, 0.901468f, 0.908698f, 0.915420f, +0.921669f, 0.927473f, 0.932862f, 0.937863f, 0.942503f, +0.946806f, 0.950795f, 0.954492f, 0.957917f, 0.961090f, +0.964028f, 0.966747f, 0.969265f, 0.971594f, 0.973749f, +0.975743f, 0.977587f, 0.979293f, 0.980869f, 0.982327f, +0.983675f, 0.984921f, 0.986072f, 0.987136f, 0.988119f, +0.989027f, 0.989867f, 0.990642f, 0.991359f, 0.992020f, +0.992631f, 0.993196f, 0.993718f, 0.994199f, 0.994644f, +0.995055f, 0.995434f, 0.995784f, 0.996108f, 0.996407f, +0.996682f, 0.996937f, 0.997172f, 0.997389f, 0.997590f, +0.997775f, 0.997946f, 0.998104f, 0.998249f, 0.998384f, +0.998508f, 0.998623f, 0.998728f, 0.998826f, 0.998916f, +0.999000f, 0.999076f, 0.999147f, 0.999213f, 0.999273f, +0.999329f, 0.999381f, 0.999428f, 0.999472f, 0.999513f, +0.999550f, 0.999585f, 0.999617f, 0.999646f, 0.999673f, +0.999699f, 0.999722f, 0.999743f, 0.999763f, 0.999781f, +0.999798f, 0.999813f, 0.999828f, 0.999841f, 0.999853f, +0.999865f, 0.999875f, 0.999885f, 0.999893f, 0.999902f, +0.999909f, 0.999916f, 0.999923f, 0.999929f, 0.999934f, +0.999939f, 0.999944f, 0.999948f, 0.999952f, 0.999956f, +0.999959f, 0.999962f, 0.999965f, 0.999968f, 0.999970f, +0.999973f, 0.999975f, 0.999977f, 0.999978f, 0.999980f, +0.999982f, 0.999983f, 0.999984f, 0.999986f, 0.999987f, +0.999988f, 0.999989f, 0.999990f, 0.999990f, 0.999991f, +0.999992f, 0.999992f, 0.999993f, 0.999994f, 0.999994f, +0.999994f, 0.999995f, 0.999995f, 0.999996f, 0.999996f, +0.999996f, 0.999997f, 0.999997f, 0.999997f, 0.999997f, +0.999997f, 0.999998f, 0.999998f, 0.999998f, 0.999998f, +0.999998f, 0.999998f, 0.999999f, 0.999999f, 0.999999f, +0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, +0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, +1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, +1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, +1.000000f, +}; diff --git a/TelegramClient.Opus/pch.cpp b/TelegramClient.Opus/pch.cpp new file mode 100755 index 0000000..f3963b9 --- /dev/null +++ b/TelegramClient.Opus/pch.cpp @@ -0,0 +1,6 @@ +// +// pch.cpp +// Include the standard header and generate the precompiled header. +// + +#include "pch.h" diff --git a/TelegramClient.Opus/pch.h b/TelegramClient.Opus/pch.h new file mode 100755 index 0000000..ae20898 --- /dev/null +++ b/TelegramClient.Opus/pch.h @@ -0,0 +1,6 @@ +// +// pch.h +// Header for standard system include files. +// + +#pragma once diff --git a/TelegramClient.Player.WP8/Properties/AssemblyInfo.cs b/TelegramClient.Player.WP8/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..45db9cd --- /dev/null +++ b/TelegramClient.Player.WP8/Properties/AssemblyInfo.cs @@ -0,0 +1,44 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("TelegramClient.Player.WP8")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TelegramClient.Player.WP8")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[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("62c14349-ed3b-4ff0-8635-f970aa1a8e32")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/TelegramClient.Player.WP8/TelegramClient.Player.WP8.csproj b/TelegramClient.Player.WP8/TelegramClient.Player.WP8.csproj new file mode 100755 index 0000000..4ae0aa7 --- /dev/null +++ b/TelegramClient.Player.WP8/TelegramClient.Player.WP8.csproj @@ -0,0 +1,102 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TelegramClient.Player + TelegramClient.Player + WindowsPhone + v8.0 + $(TargetFrameworkVersion) + false + true + true + 11.0 + AgentLibrary + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\x86\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\x86\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\ARM\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\ARM\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + AudioPlayer.cs + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.Player/AudioPlayer.cs b/TelegramClient.Player/AudioPlayer.cs new file mode 100755 index 0000000..4c43647 --- /dev/null +++ b/TelegramClient.Player/AudioPlayer.cs @@ -0,0 +1,233 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using Microsoft.Phone.BackgroundAudio; +using System.Collections.Generic; + +namespace TelegramClient.Player +{ + public class AudioPlayer : AudioPlayerAgent + { + private static volatile bool _classInitialized; + + // What's the current track? + static int currentTrackNumber = 0; + + // A playlist made up of AudioTrack items. + private static List _playList = new List + { + + // A remote URI + new AudioTrack(new Uri("http://traffic.libsyn.com/wpradio/WPRadio_29.mp3", UriKind.Absolute), + "Episode 29", + "Windows Phone Radio", + "Windows Phone Radio Podcast", + new Uri("shared/media/Episode29.jpg", UriKind.Relative)) + }; + + + /// + /// AudioPlayer instances can share the same process. + /// Static fields can be used to share state between AudioPlayer instances + /// or to communicate with the Audio Streaming agent. + /// + public AudioPlayer() + { + if (!_classInitialized) + { + _classInitialized = true; + // Subscribe to the managed exception handler + Deployment.Current.Dispatcher.BeginInvoke(delegate + { + Application.Current.UnhandledException += AudioPlayer_UnhandledException; + }); + } + } + + /// Code to execute on Unhandled Exceptions + private void AudioPlayer_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) + { + if (System.Diagnostics.Debugger.IsAttached) + { + // An unhandled exception has occurred; break into the debugger + System.Diagnostics.Debugger.Break(); + } + } + + + /// + /// Increments the currentTrackNumber and plays the correpsonding track. + /// + /// The BackgroundAudioPlayer + private void PlayNextTrack(BackgroundAudioPlayer player) + { + if (++currentTrackNumber >= _playList.Count) + { + currentTrackNumber = 0; + } + + PlayTrack(player); + } + + + /// + /// Decrements the currentTrackNumber and plays the correpsonding track. + /// + /// The BackgroundAudioPlayer + private void PlayPreviousTrack(BackgroundAudioPlayer player) + { + if (--currentTrackNumber < 0) + { + currentTrackNumber = _playList.Count - 1; + } + + PlayTrack(player); + } + + + /// + /// Plays the track in our playlist at the currentTrackNumber position. + /// + /// The BackgroundAudioPlayer + private void PlayTrack(BackgroundAudioPlayer player) + { + if (PlayState.Paused == player.PlayerState) + { + // If we're paused, we already have + // the track set, so just resume playing. + player.Play(); + } + else + { + // Set which track to play. When the TrackReady state is received + // in the OnPlayStateChanged handler, call player.Play(). + //player.Track = _playList[currentTrackNumber]; + + if (player.Track != null) player.Play(); + } + + } + + + /// + /// Called when the playstate changes, except for the Error state (see OnError) + /// + /// The BackgroundAudioPlayer + /// The track playing at the time the playstate changed + /// The new playstate of the player + /// + /// Play State changes cannot be cancelled. They are raised even if the application + /// caused the state change itself, assuming the application has opted-in to the callback. + /// + /// Notable playstate events: + /// (a) TrackEnded: invoked when the player has no current track. The agent can set the next track. + /// (b) TrackReady: an audio track has been set and it is now ready for playack. + /// + /// Call NotifyComplete() only once, after the agent request has been completed, including async callbacks. + /// + protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState) + { + switch (playState) + { + case PlayState.TrackEnded: + //PlayNextTrack(player); + player.Stop(); + break; + + case PlayState.TrackReady: + // The track to play is set in the PlayTrack method. + player.Play(); + break; + } + + NotifyComplete(); + } + + + /// + /// Called when the user requests an action using application/system provided UI + /// + /// The BackgroundAudioPlayer + /// The track playing at the time of the user action + /// The action the user has requested + /// The data associated with the requested action. + /// In the current version this parameter is only for use with the Seek action, + /// to indicate the requested position of an audio track + /// + /// User actions do not automatically make any changes in system state; the agent is responsible + /// for carrying out the user actions if they are supported. + /// + /// Call NotifyComplete() only once, after the agent request has been completed, including async callbacks. + /// + protected override void OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param) + { + switch (action) + { + case UserAction.Play: + PlayTrack(player); + break; + + case UserAction.Pause: + player.Pause(); + break; + + case UserAction.SkipPrevious: + PlayPreviousTrack(player); + break; + + case UserAction.SkipNext: + PlayNextTrack(player); + break; + case UserAction.Seek: + player.Position = (TimeSpan)param; + break; + } + + NotifyComplete(); + } + + + /// + /// Called whenever there is an error with playback, such as an AudioTrack not downloading correctly + /// + /// The BackgroundAudioPlayer + /// The track that had the error + /// The error that occured + /// If true, playback cannot continue and playback of the track will stop + /// + /// This method is not guaranteed to be called in all cases. For example, if the background agent + /// itself has an unhandled exception, it won't get called back to handle its own errors. + /// + protected override void OnError(BackgroundAudioPlayer player, AudioTrack track, Exception error, bool isFatal) + { + if (isFatal) + { + Abort(); + } + else + { + NotifyComplete(); + } + + } + + /// + /// Called when the agent request is getting cancelled + /// + /// + /// Once the request is Cancelled, the agent gets 5 seconds to finish its work, + /// by calling NotifyComplete()/Abort(). + /// + protected override void OnCancel() + { + base.OnCancel(); + NotifyComplete(); + } + } +} diff --git a/TelegramClient.Player/Properties/AssemblyInfo.cs b/TelegramClient.Player/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..1ca5bcc --- /dev/null +++ b/TelegramClient.Player/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("TelegramClient.Player")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TelegramClient.Player")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[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("c5f29433-1957-4c9e-a7d6-56e52a89afa4")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/TelegramClient.Player/TelegramClient.Player.csproj b/TelegramClient.Player/TelegramClient.Player.csproj new file mode 100755 index 0000000..c0e0230 --- /dev/null +++ b/TelegramClient.Player/TelegramClient.Player.csproj @@ -0,0 +1,67 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {C5F29433-1957-4C9E-A7D6-56E52A89AFA4} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TelegramClient.Player + TelegramClient.Player + v4.0 + $(TargetFrameworkVersion) + WindowsPhone71 + Silverlight + false + true + true + AudioPlayerAgent + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.ScheduledTaskAgent.WP8/Properties/AssemblyInfo.cs b/TelegramClient.ScheduledTaskAgent.WP8/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..9bc496b --- /dev/null +++ b/TelegramClient.ScheduledTaskAgent.WP8/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("TelegramClient.ScheduledTaskAgent.WP8")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TelegramClient.ScheduledTaskAgent.WP8")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[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("30ada306-4873-4af3-99d3-be57e723013c")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/TelegramClient.ScheduledTaskAgent.WP8/TelegramClient.ScheduledTaskAgent.WP8.csproj b/TelegramClient.ScheduledTaskAgent.WP8/TelegramClient.ScheduledTaskAgent.WP8.csproj new file mode 100755 index 0000000..47c17ee --- /dev/null +++ b/TelegramClient.ScheduledTaskAgent.WP8/TelegramClient.ScheduledTaskAgent.WP8.csproj @@ -0,0 +1,108 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {30ADA306-4873-4AF3-99D3-BE57E723013C} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TelegramClient.ScheduledTaskAgent + TelegramClient.ScheduledTaskAgent + WindowsPhone + v8.0 + $(TargetFrameworkVersion) + false + true + true + 11.0 + AgentLibrary + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\x86\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\x86\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + true + full + false + Bin\ARM\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8 + true + true + prompt + 4 + + + pdbonly + true + Bin\ARM\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + ScheduledAgent.cs + + + + + + {e79d5093-8038-4a5f-8a98-ca38c0d0886f} + Telegram.Api.WP8 + + + + + + + \ No newline at end of file diff --git a/TelegramClient.ScheduledTaskAgent/Properties/AssemblyInfo.cs b/TelegramClient.ScheduledTaskAgent/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..0505e6a --- /dev/null +++ b/TelegramClient.ScheduledTaskAgent/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("TelegramClient.ScheduledTaskAgent")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TelegramClient.ScheduledTaskAgent")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[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("218abb75-04fb-4e0e-bbb5-69dd36b204b5")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/TelegramClient.ScheduledTaskAgent/ScheduledAgent.cs b/TelegramClient.ScheduledTaskAgent/ScheduledAgent.cs new file mode 100755 index 0000000..ebaff30 --- /dev/null +++ b/TelegramClient.ScheduledTaskAgent/ScheduledAgent.cs @@ -0,0 +1,113 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Windows; +using Microsoft.Phone.Scheduler; +using Microsoft.Phone.Shell; + +namespace TelegramClient.ScheduledTaskAgent +{ + public class ScheduledAgent : Microsoft.Phone.Scheduler.ScheduledTaskAgent + { + private static volatile bool _classInitialized; + + /// + /// ScheduledAgent constructor, initializes the UnhandledException handler + /// + public ScheduledAgent() + { + if (!_classInitialized) + { + _classInitialized = true; + // Subscribe to the managed exception handler + Deployment.Current.Dispatcher.BeginInvoke(delegate + { + Application.Current.UnhandledException += ScheduledAgent_UnhandledException; + }); + } + } + + /// Code to execute on Unhandled Exceptions + private void ScheduledAgent_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) + { + if (System.Diagnostics.Debugger.IsAttached) + { + // An unhandled exception has occurred; break into the debugger + System.Diagnostics.Debugger.Break(); + } + } + + /// + /// Agent that runs a scheduled task + /// + /// + /// The invoked task + /// + /// + /// This method is called when a periodic or resource intensive task is invoked + /// + protected override void OnInvoke(ScheduledTask task) + { +// var manualResetEvent = new ManualResetEvent(false); +// var eventAggregator = new EventAggregator(); +// var cacheService = new InMemoryCacheService(eventAggregator); +// var updatesService = new UpdatesService(cacheService, eventAggregator); +// //TODO: Add code to perform your task in background +// if (ShellTile.ActiveTiles.FirstOrDefault() == null) return; + +// ShellTileData tileData; +//#if WP8 +// tileData = new StandardTileData { Count = 99 }; +// //tileDate = new IconicTileData { Count = 99, WideContent1 = "", WideContent2 = "", WideContent3 = "" }; +//#else +// tileData = new StandardTileData { BackTitle = DateTime.Now.ToString("dd-MMM HH:mm") }; +//#endif +// try +// { +// var tile = ShellTile.ActiveTiles.FirstOrDefault(); +// if (tile != null) +// { +// tile.Update(tileData); +// } +// } +// catch (Exception e) +// { + +// } + + + +// try +// { +// //var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); +// //if (!isAuthorized) return; + +// var mtProtoService = new MTProtoService(updatesService, cacheService, new TransportService()); +// //var stateService = IoC.Get(); + +// //TLUtils.WritePerformance(">>OnActivate GetDifferenceAsync"); +// updatesService.GetCurrentUserId = () => mtProtoService.CurrentUserId; +// updatesService.GetStateAsync = mtProtoService.GetStateAsync; +// updatesService.GetDHConfigAsync = mtProtoService.GetDHConfigAsync; +// updatesService.GetDifferenceAsync = mtProtoService.GetDifferenceAsync; +// updatesService.AcceptEncryptionAsync = mtProtoService.AcceptEncryptionAsync; +// //stateService.SuppressNotifications = true; + +// var timer = Stopwatch.StartNew(); +// updatesService.LoadStateAndUpdate(false, () => +// { +// //TLUtils.WritePerformance("::GetDifference time: " + timer.Elapsed); +// //stateService.SuppressNotifications = false; +// }); +// } +// catch (Exception e) +// { +// //TLUtils.WriteException(e); +// } + +// manualResetEvent.WaitOne(20000); + NotifyComplete(); + } + } +} \ No newline at end of file diff --git a/TelegramClient.ScheduledTaskAgent/TelegramClient.ScheduledTaskAgent.csproj b/TelegramClient.ScheduledTaskAgent/TelegramClient.ScheduledTaskAgent.csproj new file mode 100755 index 0000000..9bfd53b --- /dev/null +++ b/TelegramClient.ScheduledTaskAgent/TelegramClient.ScheduledTaskAgent.csproj @@ -0,0 +1,73 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {218ABB75-04FB-4E0E-BBB5-69DD36B204B5} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TelegramClient.ScheduledTaskAgent + TelegramClient.ScheduledTaskAgent + v4.0 + $(TargetFrameworkVersion) + WindowsPhone71 + Silverlight + false + true + true + ScheduledTaskAgent + ..\ + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + ..\packages\Caliburn.Micro.1.5.2\lib\wp71\Caliburn.Micro.dll + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.Tasks/BackgroundDifferenceLoader.cs b/TelegramClient.Tasks/BackgroundDifferenceLoader.cs new file mode 100755 index 0000000..6c3920a --- /dev/null +++ b/TelegramClient.Tasks/BackgroundDifferenceLoader.cs @@ -0,0 +1,278 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using Windows.ApplicationModel.Background; +using Telegram.Api; +using Telegram.Api.Aggregator; +using Telegram.Api.Helpers; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.Connection; +using Telegram.Api.Services.DeviceInfo; +using Telegram.Api.Services.Updates; +using Telegram.Api.TL; +using Telegram.Api.Transport; + +namespace TelegramClient.Tasks +{ + public sealed class BackgroundDifferenceLoader : IBackgroundTask + { + private readonly Mutex _appOpenMutex = new Mutex(false, Constants.TelegramMessengerMutexName); + + private static bool _logEnabled = true; + + private static void Log(string message, Action callback = null) + { + if (!_logEnabled) return; + + Telegram.Logs.Log.Write(string.Format("::BackgroundDifferenceLoader {0} {1}", _id, message), callback.SafeInvoke); +#if DEBUG + //PushUtils.AddToast("difference", string.Format("{0} {1}", _id, message), string.Empty, string.Empty, null, null); +#endif + } + + private static readonly int _id = new Random().Next(999); + + private TLInitConnection GetInitConnection() + { + return TLUtils.OpenObjectFromMTProtoFile(_initConnectionSyncRoot, Constants.InitConnectionFileName) ?? + new TLInitConnection + { + DeviceModel = new TLString("unknown"), + AppVersion = new TLString("background task"), + SystemVersion = new TLString("8.10.0.0") + }; + } + + public void Run(IBackgroundTaskInstance taskInstance) + { + Telegram.Logs.Log.WriteSync = true; + + var stopwatch = Stopwatch.StartNew(); + + if (!_appOpenMutex.WaitOne(0)) + { + Log("cancel"); + + return; + } + _appOpenMutex.ReleaseMutex(); + + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (!isAuthorized) + { + Log("cancel isAuthorized=false"); + } + + var deferral = taskInstance.GetDeferral(); + RunAsync(() => + { + Log(string.Format("stop elapsed={0}", stopwatch.Elapsed)); + deferral.Complete(); + }); + } + + private readonly object _stateRoot = new object(); + + private readonly object _initConnectionSyncRoot = new object(); + + private void RunAsync(Action callback) + { + var deviceInfoService = new DeviceInfoService(GetInitConnection(), true, "BackgroundDifferenceLoader", _id); + var eventAggregator = new TelegramEventAggregator(); + var cacheService = new InMemoryCacheService(eventAggregator); + var updatesService = new UpdatesService(cacheService, eventAggregator); + var transportService = new TransportService(); + var connectionService = new ConnectionService(deviceInfoService); + var publicConfigService = new MockupPublicConfigService(); + + var manualResetEvent = new ManualResetEvent(false); + var mtProtoService = new MTProtoService(deviceInfoService, updatesService, cacheService, transportService, connectionService, publicConfigService); + mtProtoService.Initialized += (o, e) => + { + var lastTime = TLUtils.OpenObjectFromMTProtoFile(_differenceTimeSyncRoot, Constants.DifferenceTimeFileName); + if (lastTime != null) + { + var now = TLUtils.DateToUniversalTimeTLInt(mtProtoService.ClientTicksDelta, DateTime.Now); + + if (lastTime.Value + Constants.DifferenceMinInterval > now.Value) + { + manualResetEvent.Set(); + return; + } + } + + var clientState = TLUtils.OpenObjectFromMTProtoFile(_stateRoot, Constants.StateFileName); + _results = TLUtils.OpenObjectFromMTProtoFile>(_differenceFileSyncRoot, Constants.DifferenceFileName) ?? new TLVector(); + var state = GetState(clientState, _results); + + if (state != null) + { + GetDifferenceAsync(mtProtoService, state, () => manualResetEvent.Set()); + } + else + { + manualResetEvent.Set(); + } + }; + mtProtoService.InitializationFailed += (o, e) => + { + manualResetEvent.Set(); + }; + mtProtoService.Initialize(); + +#if DEBUG + manualResetEvent.WaitOne(15000); +#else + manualResetEvent.WaitOne(15000); +#endif + + callback.SafeInvoke(); + } + + private static TLState GetState(TLState clientState, TLVector results) + { + var state = clientState; + for (var i = 0; i < results.Count; i++) + { + var difference = results[i]; + if (difference != null) + { + if (difference.State.Pts.Value < clientState.Pts.Value) + { + results.RemoveAt(i--); + continue; + } + + if (difference.State.Pts.Value > state.Pts.Value) + { + state = difference.State; + } + } + } + + return state; + } + + private void GetDifferenceAsync(IMTProtoService mtProtoService, TLState state, Action callback) + { + Log(string.Format("get_diff [{0}]", state)); + mtProtoService.GetDifferenceWithoutUpdatesAsync(state.Pts, state.Date, state.Qts, + result => + { + var now = TLUtils.DateToUniversalTimeTLInt(mtProtoService.ClientTicksDelta, DateTime.Now); + TLUtils.SaveObjectToMTProtoFile(_differenceTimeSyncRoot, Constants.DifferenceTimeFileName, now); + + var differenceEmpty = result as TLDifferenceEmpty; + if (differenceEmpty != null) + { + Log(string.Format("diff_empty date={0} seq={1}", differenceEmpty.Date, differenceEmpty.Seq)); + + //DeleteFile(); + + callback.SafeInvoke(); + } + + var difference = result as TLDifference; + if (difference != null) + { + SaveToFile(difference); + + var differenceSlice = result as TLDifferenceSlice; + if (differenceSlice != null) + { + Log(string.Format("diff_slice [{0}]", differenceSlice.State)); + + GetDifferenceAsync(mtProtoService, differenceSlice.State, callback); + } + else + { + Log(string.Format("diff [{0}]", difference.State)); + + callback.SafeInvoke(); + } + } + }, + error => + { + Log(string.Format("diff_error={0}\n{1}", error, error.Exception)); + + callback.SafeInvoke(); + }); + } + + private readonly object _differenceFileSyncRoot = new object(); + + private readonly object _differenceTimeSyncRoot = new object(); + + private TLVector _results; + + private void SaveToFile(TLDifference result) + { + if (result == null) return; + + AddResult(_results, result); + + TLUtils.SaveObjectToMTProtoFile(_differenceFileSyncRoot, Constants.DifferenceFileName, _results); + } + + private void AddResult(TLVector results, TLDifference result) + { + if (results.Count > 0) + { + var firstResult = results.FirstOrDefault(); + var usersCache = new Dictionary(); + var chatsCache = new Dictionary(); + + foreach (var user in firstResult.Users) + { + usersCache[user.Index] = user; + } + + foreach (var chat in firstResult.Chats) + { + chatsCache[chat.Index] = chat; + } + + foreach (var user in result.Users) + { + usersCache[user.Index] = user; + } + + foreach (var chat in result.Chats) + { + chatsCache[chat.Index] = chat; + } + + result.Users = new TLVector(); + result.Chats = new TLVector(); + + var users = new TLVector(); + foreach (var user in usersCache.Values) + { + users.Add(user); + } + firstResult.Users = users; + + var chats = new TLVector(); + foreach (var chat in chatsCache.Values) + { + chats.Add(chat); + } + firstResult.Chats = chats; + } + + _results.Add(result); + } + } +} diff --git a/TelegramClient.Tasks/InteractiveNotificationsBackgroundTask.cs b/TelegramClient.Tasks/InteractiveNotificationsBackgroundTask.cs new file mode 100755 index 0000000..aef7bcf --- /dev/null +++ b/TelegramClient.Tasks/InteractiveNotificationsBackgroundTask.cs @@ -0,0 +1,434 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Windows.ApplicationModel.Background; +using Windows.Foundation.Collections; +using Telegram.Api; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.Connection; +using Telegram.Api.Services.DeviceInfo; +using Telegram.Api.Services.Updates; +using Telegram.Api.TL; +using Telegram.Api.TL.Functions.Channels; +using Telegram.Api.TL.Functions.Messages; +using Telegram.Api.Transport; +using Windows.Foundation.Metadata; + + +namespace TelegramClient.Tasks +{ + public sealed class InteractiveNotificationsBackgroundTask : IBackgroundTask + { + private readonly Mutex _appOpenMutex = new Mutex(false, Constants.TelegramMessengerMutexName); + + private bool _logEnabled = true; + + private void Log(string message, Action callback = null) + { + if (!_logEnabled) return; + + Telegram.Logs.Log.Write(string.Format("::InteractiveNotificationsBackgroundTask {0} {1}", _id, message), callback.SafeInvoke); +#if DEBUG + //PushUtils.AddToast("scheduler", message, string.Empty, string.Empty, null, null); +#endif + } + + private static readonly int _id = new Random().Next(999); + + private readonly object _initConnectionSyncRoot = new object(); + + private TLInitConnection GetInitConnection() + { + return TLUtils.OpenObjectFromMTProtoFile(_initConnectionSyncRoot, Constants.InitConnectionFileName) ?? + new TLInitConnection + { + DeviceModel = new TLString("unknown"), + AppVersion = new TLString("background task"), + SystemVersion = new TLString("10.0.0.0") + }; + } + + private readonly object _actionInfoSyncRoot = new object(); + + public void Run(IBackgroundTaskInstance taskInstance) + { + var details = taskInstance.TriggerDetails as IToastNotificationActionTriggerDetail; + if (details == null) return; + if (string.IsNullOrEmpty(details.Argument)) return; + object message; + if (!details.UserInput.TryGetValue("message", out message)) return; + + var inputPeer = GetInputPeer(details.Argument); + if (inputPeer == null) return; + + var msgId = GetMsgId(details.Argument); + + Telegram.Logs.Log.WriteSync = true; + + taskInstance.Canceled += OnTaskCanceled; + var deferral = taskInstance.GetDeferral(); + + var stopwatch = Stopwatch.StartNew(); + + var task = taskInstance.Task; + var name = task != null ? task.Name : null; + Log("start " + name); + if (!_appOpenMutex.WaitOne(0)) + { + Log("cancel", deferral.Complete); + + return; + } + _appOpenMutex.ReleaseMutex(); + Log("release mutex"); + + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (!isAuthorized) + { + Log("cancel isAuthorized=false", deferral.Complete); + + return; + } + Log("isAuthorized=true"); + + + if (details.Argument.StartsWith("action=reply")) + { + SendReply(inputPeer, new TLString(message.ToString()), new TLInt(int.MaxValue)); + } + else if (details.Argument.StartsWith("action=mute")) + { + UpdateNotifySettings(inputPeer, new TLInt(1 * 60 * 60)); + } + else if (details.Argument.StartsWith("action=disable")) + { + UpdateNotifySettings(inputPeer, new TLInt(int.MaxValue)); + } + + Log("stop " + stopwatch.Elapsed, deferral.Complete); + } + + private void UpdateNotifySettings(TLInputPeerBase inputPeer, TLInt muteUntil) + { + var deviceInfoService = new DeviceInfoService(GetInitConnection(), true, "InteractiveNotificationsBackgroundTask", _id); + var eventAggregator = new TelegramEventAggregator(); + var cacheService = new InMemoryCacheService(eventAggregator); + var updatesService = new UpdatesService(cacheService, eventAggregator); + var transportService = new TransportService(); + var connectionService = new ConnectionService(deviceInfoService); + var publicConfigService = new MockupPublicConfigService(); + + var manualResetEvent = new ManualResetEvent(false); + Log("before init"); + var mtProtoService = new MTProtoService(deviceInfoService, updatesService, cacheService, transportService, connectionService, publicConfigService); + mtProtoService.Initialized += (o, e) => + { + Log("init completed"); + + mtProtoService.GetNotifySettingsAsync(new TLInputNotifyPeer { Peer = inputPeer }, + result => + { + Log("getNotifySettings completed", () => + { + var peerNotifySettings = result as TLPeerNotifySettings; + if (peerNotifySettings != null) + { + if (muteUntil.Value < int.MaxValue) + { + muteUntil = TLUtils.DateToUniversalTimeTLInt(mtProtoService.ClientTicksDelta, DateTime.Now.AddSeconds(muteUntil.Value)); + } + + var inputPeerNotifySettings = new TLInputPeerNotifySettings78 + { + Flags = new TLInt(0), + MuteUntil = muteUntil, + Sound = peerNotifySettings.Sound, + }; + + mtProtoService.UpdateNotifySettingsAsync(new TLInputNotifyPeer { Peer = inputPeer }, + inputPeerNotifySettings, + result2 => + { + Log("setNotifySettings completed", () => + { + manualResetEvent.Set(); + }); + }, + error2 => + { + Log(string.Format("setNotifySettings error={0}\n{1}", error2, error2.Exception), + async () => + { + await Task.Delay(TimeSpan.FromSeconds(1.0)); + manualResetEvent.Set(); + }); + }); + } + else + { + manualResetEvent.Set(); + } + }); + }, + error => + { + Log(string.Format("getNotifySettings error={0}\n{1}", error, error.Exception), + async () => + { + await Task.Delay(TimeSpan.FromSeconds(1.0)); + manualResetEvent.Set(); + }); + }); + }; + mtProtoService.InitializationFailed += (o, e) => + { + Log("init failed"); + + manualResetEvent.Set(); + }; + mtProtoService.Initialize(); +#if DEBUG + manualResetEvent.WaitOne(); +#else + manualResetEvent.WaitOne(15000); +#endif + } + + private void SendReply(TLInputPeerBase inputPeer, TLString message, TLInt msgId) + { + if (msgId == null) return; + if (TLString.IsNullOrEmpty(message)) return; + + var actionInfo = TLUtils.OpenObjectFromMTProtoFile>(_actionInfoSyncRoot, Constants.ActionQueueFileName) ?? new TLVector(); + + var count = actionInfo.Count; + Log("send count=" + count); + + var peerChannel = inputPeer as TLInputPeerChannel; + var readHistory = peerChannel != null + ? (TLObject)new TLReadChannelHistory { Channel = new TLInputChannel { ChannelId = peerChannel.ChatId, AccessHash = peerChannel.AccessHash }, MaxId = msgId } + : new TLReadHistory { Peer = inputPeer, MaxId = msgId }; + + var readHistoryActionInfo = new TLActionInfo(); + readHistoryActionInfo.SendBefore = new TLInt(0); + readHistoryActionInfo.Action = readHistory; + + actionInfo.Add(readHistoryActionInfo); + + var sendMessage = new TLSendMessage(); + sendMessage.Flags = new TLInt(0); + sendMessage.Peer = inputPeer; + sendMessage.Message = message; + sendMessage.RandomId = TLLong.Random(); + + var sendMessageActionInfo = new TLActionInfo(); + sendMessageActionInfo.SendBefore = new TLInt(0); + sendMessageActionInfo.Action = sendMessage; + + actionInfo.Add(sendMessageActionInfo); + + TLUtils.SaveObjectToMTProtoFile(new object(), Constants.ActionQueueFileName, actionInfo); + + if (actionInfo.Count > 0) + { + var deviceInfoService = new DeviceInfoService(GetInitConnection(), true, "InteractiveNotificationsBackgroundTask", _id); + var eventAggregator = new TelegramEventAggregator(); + var cacheService = new InMemoryCacheService(eventAggregator); + var updatesService = new UpdatesService(cacheService, eventAggregator); + var transportService = new TransportService(); + var connectionService = new ConnectionService(deviceInfoService); + var publicConfigService = new MockupPublicConfigService(); + + var manualResetEvent = new ManualResetEvent(false); + Log("before init"); + var requestsToRemove = new List(); + var mtProtoService = new MTProtoService(deviceInfoService, updatesService, cacheService, transportService, connectionService, publicConfigService); + mtProtoService.Initialized += async (o, e) => + { + Log("init completed"); + + var actionsString = new StringBuilder(); + foreach (var info in actionInfo) + { + actionsString.AppendLine(info.ToString()); + } + Log(actionsString.ToString()); + + var sendMessageActions = new List(); + const int maxActionCount = 10; + var currentCount = 0; + foreach (var ai in actionInfo) + { + if (TLUtils.IsValidAction(ai.Action) && currentCount < maxActionCount) + { + currentCount++; + sendMessageActions.Add(ai.Action); + } + } + + if (sendMessageActions.Count > 0) + { + mtProtoService.SendActionsAsync(sendMessageActions, + (request, result) => // will be invoked for each sent action + { + requestsToRemove.Add(request); + var sendingMessages = mtProtoService.SendingMessages; + Log("send completed count=" + sendingMessages, () => + { + if (sendingMessages == 0) + { + _clearActionInfoFile = true; + + manualResetEvent.Set(); + } + }); + }, + error => + { + Log(string.Format("send error={0}\n{1}", error, error.Exception), + async () => + { + await Task.Delay(TimeSpan.FromSeconds(1.0)); + manualResetEvent.Set(); + }); + }); + } + else + { + manualResetEvent.Set(); + } + }; + mtProtoService.InitializationFailed += (o, e) => + { + Log("init failed"); + + manualResetEvent.Set(); + }; + mtProtoService.Initialize(); +#if DEBUG + manualResetEvent.WaitOne(); +#else + manualResetEvent.WaitOne(15000); +#endif + if (_clearActionInfoFile) + { + Log("clear"); + lock (_actionInfoSyncRoot) + { + var actions = actionInfo; + + foreach (var o in requestsToRemove) + { + MTProtoService.RemoveActionInfoCommon(actions, o); + } + + TLUtils.SaveObjectToMTProtoFile(_actionInfoSyncRoot, Constants.ActionQueueFileName, actions); + } + } + } + } + + private static TLInt GetMsgId(string argument) + { + var parameters = argument.Split(' '); + foreach (var parameter in parameters) + { + if (parameter.StartsWith("msg_id")) + { + int msgId; + var split = parameter.Split('='); + if (split.Length == 2 && Int32.TryParse(split[1], out msgId)) + { + return new TLInt(msgId); + } + } + } + + return null; + } + + private static TLInputPeerBase GetInputPeer(string argument) + { + var parameters = argument.Split(' '); + if (parameters.Length >= 2) + { + if (parameters[1].StartsWith("chat_id")) + { + int chatId; + var split1 = parameters[1].Split('='); + if (split1.Length == 2 && Int32.TryParse(split1[1], out chatId)) + { + return new TLInputPeerChat { ChatId = new TLInt(chatId) }; + } + } + else if (parameters[1].StartsWith("from_id")) + { + if (parameters.Length >= 3) + { + if (parameters[2].StartsWith("access_hash")) + { + int fromId; + long accessHash; + var split1 = parameters[1].Split('='); + var split2 = parameters[2].Split('='); + if (split1.Length == 2 && Int32.TryParse(split1[1], out fromId) + && split2.Length == 2 && Int64.TryParse(split2[1], out accessHash)) + { + return new TLInputPeerUser { UserId = new TLInt(fromId), AccessHash = new TLLong(accessHash) }; + } + } + } + } + else if (parameters[1].StartsWith("channel_id")) + { + if (parameters.Length >= 3) + { + if (parameters[2].StartsWith("access_hash")) + { + int chatId; + long accessHash; + var split1 = parameters[1].Split('='); + var split2 = parameters[2].Split('='); + if (split1.Length == 2 && Int32.TryParse(split1[1], out chatId) + && split2.Length == 2 && Int64.TryParse(split2[1], out accessHash)) + { + return new TLInputPeerChannel { ChatId = new TLInt(chatId), AccessHash = new TLLong(accessHash) }; + } + } + } + } + } + + return null; + } + + private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) + { + Log(string.Format("cancel reason={0}", reason)); + } + + private bool _clearActionInfoFile; + } + + [Guid(2487554906, 14579, 17142, 150, 170, 121, 85, 176, 240, 61, 162)] + public interface IToastNotificationActionTriggerDetail + { + string Argument { get; } + + ValueSet UserInput { get; } + } +} diff --git a/TelegramClient.Tasks/MessageSchedulerBackgroundTask.cs b/TelegramClient.Tasks/MessageSchedulerBackgroundTask.cs new file mode 100755 index 0000000..c434157 --- /dev/null +++ b/TelegramClient.Tasks/MessageSchedulerBackgroundTask.cs @@ -0,0 +1,214 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Windows.ApplicationModel.Background; +using Telegram.Api; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.Connection; +using Telegram.Api.Services.DeviceInfo; +using Telegram.Api.Services.Updates; +using Telegram.Api.TL; +using Telegram.Api.Transport; + +namespace TelegramClient.Tasks +{ + public sealed class MessageSchedulerBackgroundTask : IBackgroundTask + { + private readonly Mutex _appOpenMutex = new Mutex(false, Constants.TelegramMessengerMutexName); + + private bool _logEnabled = true; + + private void Log(string message, Action callback = null) + { + if (!_logEnabled) return; + + Telegram.Logs.Log.Write(string.Format("::MessageSchedulerBackgroundTask {0} {1}", _id, message), callback.SafeInvoke); +#if DEBUG + //PushUtils.AddToast("scheduler", message, string.Empty, string.Empty, null, null); +#endif + } + + private static readonly int _id = new Random().Next(999); + + private readonly object _initConnectionSyncRoot = new object(); + + private TLInitConnection GetInitConnection() + { + return TLUtils.OpenObjectFromMTProtoFile(_initConnectionSyncRoot, Constants.InitConnectionFileName) ?? + new TLInitConnection + { + DeviceModel = new TLString("unknown"), + AppVersion = new TLString("background task"), + SystemVersion = new TLString("8.10.0.0") + }; + } + + private readonly object _actionInfoSyncRoot = new object(); + + public async void Run(IBackgroundTaskInstance taskInstance) + { + try + { + + + Telegram.Logs.Log.WriteSync = true; + + taskInstance.Canceled += OnTaskCanceled; + var deferral = taskInstance.GetDeferral(); + + var stopwatch = Stopwatch.StartNew(); + var task = taskInstance.Task; + var name = task != null ? task.Name : null; + Log("start " + name); + if (!_appOpenMutex.WaitOne(0)) + { + Log("cancel", deferral.Complete); + + return; + } + _appOpenMutex.ReleaseMutex(); + Log("release mutex"); + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (!isAuthorized) + { + Log("cancel isAuthorized=false", deferral.Complete); + + return; + } + Log("isAuthorized=true"); + + var actionInfo = TLUtils.OpenObjectFromMTProtoFile>(_actionInfoSyncRoot, Constants.ActionQueueFileName) ?? new TLVector(); + var count = actionInfo.Count; + Log("send count=" + count); + + if (count > 0) + { + var deviceInfoService = new DeviceInfoService(GetInitConnection(), true, "MessageSchedulerBackgroundTask", _id); + + var publicConfigService = new MockupPublicConfigService(); + var eventAggregator = new TelegramEventAggregator(); + var cacheService = new InMemoryCacheService(eventAggregator); + var updatesService = new UpdatesService(cacheService, eventAggregator); + var transportService = new TransportService(); + var connectionService = new ConnectionService(deviceInfoService); + + var manualResetEvent = new ManualResetEvent(false); + Log("before init"); + var requestsToRemove = new List(); + var mtProtoService = new MTProtoService(deviceInfoService, updatesService, cacheService, transportService, connectionService, publicConfigService); + mtProtoService.Initialized += async (o, e) => + { + Log("init completed"); + + var actionsString = new StringBuilder(); + foreach (var info in actionInfo) + { + actionsString.AppendLine(info.ToString()); + } + Log(actionsString.ToString()); + + var sendMessageActions = new List(); + const int maxActionCount = 10; + var currentCount = 0; + foreach (var ai in actionInfo) + { + if (TLUtils.IsValidAction(ai.Action) && currentCount < maxActionCount) + { + currentCount++; + sendMessageActions.Add(ai.Action); + } + } + + if (sendMessageActions.Count > 0) + { + await Task.Delay(TimeSpan.FromSeconds(3.0)); + + mtProtoService.SendActionsAsync(sendMessageActions, + (request, result) => // will be invoked for each sent action + { + requestsToRemove.Add(request); + var sendingMessages = mtProtoService.SendingMessages; + Log("send completed count=" + sendingMessages, () => + { + if (sendingMessages == 0) + { + _clearActionInfoFile = true; + + manualResetEvent.Set(); + } + }); + }, + error => + { + Log(string.Format("send error={0}\n{1}", error, error.Exception), + async () => + { + await Task.Delay(TimeSpan.FromSeconds(1.0)); + manualResetEvent.Set(); + }); + }); + } + else + { + manualResetEvent.Set(); + } + }; + mtProtoService.InitializationFailed += (o, e) => + { + Log("init failed"); + + manualResetEvent.Set(); + }; + mtProtoService.Initialize(); +#if DEBUG + manualResetEvent.WaitOne(); +#else + manualResetEvent.WaitOne(15000); +#endif + if (_clearActionInfoFile) + { + Log("clear"); + lock (_actionInfoSyncRoot) + { + var actions = actionInfo; + + foreach (var o in requestsToRemove) + { + MTProtoService.RemoveActionInfoCommon(actions, o); + } + + TLUtils.SaveObjectToMTProtoFile(_actionInfoSyncRoot, Constants.ActionQueueFileName, actions); + } + } + } + + Log("stop " + stopwatch.Elapsed, deferral.Complete); + } + catch (Exception ex) + { + + } + } + + private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) + { + Log(string.Format("cancel reason={0}", reason)); + } + + private bool _clearActionInfoFile; + } +} diff --git a/TelegramClient.Tasks/Properties/AssemblyInfo.cs b/TelegramClient.Tasks/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..8e818f4 --- /dev/null +++ b/TelegramClient.Tasks/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("TelegramClient.Tasks")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TelegramClient.Tasks")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 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 Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: ComVisible(false)] +[assembly: NeutralResourcesLanguageAttribute("en")] diff --git a/TelegramClient.Tasks/PushNotificationsBackgroundTask.cs b/TelegramClient.Tasks/PushNotificationsBackgroundTask.cs new file mode 100755 index 0000000..f4adc7f --- /dev/null +++ b/TelegramClient.Tasks/PushNotificationsBackgroundTask.cs @@ -0,0 +1,111 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using Windows.ApplicationModel.Background; +using Windows.ApplicationModel.Resources; +#if WNS_PUSH_SERVICE +using Windows.Networking.PushNotifications; +#endif +using Windows.UI.Xaml; +using Telegram.Api; +using Telegram.Api.Helpers; +using Telegram.Api.Extensions; +using Telegram.Api.TL; + +namespace TelegramClient.Tasks +{ + public sealed class PushNotificationsBackgroundTask : IBackgroundTask + { + private readonly Mutex _appOpenMutex = new Mutex(false, Constants.TelegramMessengerMutexName); + + private static bool _logEnabled = true; + + private static readonly int _id = new Random().Next(999); + + private static void Log(string message, Action callback = null) + { + if (!_logEnabled) return; + + Telegram.Logs.Log.Write(string.Format("::PushNotificationsBackgroundTask {0} {1}", _id, message), callback.SafeInvoke); +#if DEBUG + //PushUtils.AddToast("push", message, string.Empty, string.Empty, null, null); +#endif + } + + public void Run(IBackgroundTaskInstance taskInstance) + { +#if WNS_PUSH_SERVICE + Telegram.Logs.Log.WriteSync = true; + + var stopwatch = Stopwatch.StartNew(); + + var rawNotification = taskInstance.TriggerDetails as RawNotification; + var payload = rawNotification != null ? rawNotification.Content : null; + var rootObject = payload != null ? PushUtils.GetRootObject(payload) : null; + var data = rootObject != null ? rootObject.data : null; + var locKey = data != null ? data.loc_key : null; + + Log(string.Format("start locKey={0}", locKey)); + if (!_appOpenMutex.WaitOne(0)) + { + Log("cancel"); + + return; + } + _appOpenMutex.ReleaseMutex(); + + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (!isAuthorized) + { + Log(string.Format("cancel isAuthorized=false\npayload={0}", payload)); + return; + } + + try + { + var initConnection = GetInitConnection(); + if (initConnection != null) + { + SystemVersion = initConnection.SystemVersion != null + ? initConnection.SystemVersion.ToString() + : string.Empty; + Log(string.Format(initConnection.ToString())); + } + else + { + Log(string.Format("empty init_connection")); + } + //string[] supportedLanguages = { "de", "en", "es", "it", "nl", "pt" }; + //var language = initConnection != null ? initConnection.LangCode.ToString() : "en"; + //language = supportedLanguages.Contains(language) ? language : "en"; + Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = ""; + + PushUtils.UpdateToastAndTiles(taskInstance.TriggerDetails as RawNotification); + } + catch (Exception ex) + { + Log(string.Format("ex={0}\npayload={1}", ex, payload)); + } + + Log(string.Format("stop elapsed={0}", stopwatch.Elapsed)); +#endif + } + + public static string SystemVersion { get; set; } + + private readonly object _initConnectionSyncRoot = new object(); + + private TLInitConnection GetInitConnection() + { + return TLUtils.OpenObjectFromMTProtoFile(_initConnectionSyncRoot, Constants.InitConnectionFileName); + } + } +} diff --git a/TelegramClient.Tasks/PushUtils.cs b/TelegramClient.Tasks/PushUtils.cs new file mode 100755 index 0000000..277aedd --- /dev/null +++ b/TelegramClient.Tasks/PushUtils.cs @@ -0,0 +1,764 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define INTERACTIVE_NOTIFICATIONS +//#endif + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Runtime.Serialization.Json; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Linq; +using Windows.ApplicationModel.Resources; +using Windows.ApplicationModel.Resources.Core; +using Windows.Data.Xml.Dom; +using Windows.Storage; +using Windows.Storage.Search; +#if WNS_PUSH_SERVICE +using Windows.Networking.PushNotifications; +using Windows.UI.Notifications; +#endif +using Telegram.Api.Helpers; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; + +namespace TelegramClient.Tasks +{ + public static class PushUtils + { +#if WNS_PUSH_SERVICE + public static void UpdateToastAndTiles(RawNotification rawNotification) + { + var payload = rawNotification != null ? rawNotification.Content : null; + if (payload == null) return; + + var rootObject = GetRootObject(payload); + if (rootObject == null) return; + if (rootObject.data == null) return; + + if (rootObject.data.loc_key == null) + { + var groupname = GetGroup(rootObject.data); + RemoveToastGroup(groupname); + return; + } + + var caption = GetCaption(rootObject.data); + var message = GetMessage(rootObject.data); + var sound = GetSound(rootObject.data); + var launch = GetLaunch(rootObject.data); + var tag = GetTag(rootObject.data); + var group = GetGroup(rootObject.data); + + if (!IsMuted(rootObject.data) && !Notifications.IsDisabled) + { + AddToast(rootObject, caption, message, sound, launch, tag, group); + } + if (!IsServiceNotification(rootObject.data)) + { + UpdateTile(caption, message); + } + UpdateBadge(rootObject.data.badge); + } +#endif + + private static bool IsMuted(Data data) + { + return data.mute == "1"; + } + + private static bool IsServiceNotification(Data data) + { + return data.loc_key == "DC_UPDATE"; + } + + public static RootObject GetRootObject(string payload) + { + var serializer = new DataContractJsonSerializer(typeof(RootObject)); + RootObject rootObject; + using (var stream = new MemoryStream(Encoding.Unicode.GetBytes(payload))) + { + rootObject = serializer.ReadObject(stream) as RootObject; + } + + return rootObject; + } + + private static string GetCaption(Data data) + { + var locKey = data.loc_key; + if (locKey == null) + { + return "locKey=null"; + } + + if (locKey.StartsWith("CHAT") || locKey.StartsWith("GEOCHAT")) + { + return data.loc_args[1]; + } + + if (locKey.StartsWith("MESSAGE")) + { + return data.loc_args[0]; + } + + if (locKey.StartsWith("CHANNEL")) + { + return data.loc_args[0]; + } + + if (locKey.StartsWith("PINNED")) + { + return data.loc_args[0]; + } + + if (locKey.StartsWith("AUTH") + || locKey.StartsWith("CONTACT") + || locKey.StartsWith("ENCRYPTED") + || locKey.StartsWith("ENCRYPTION") + || locKey.StartsWith("PHONE")) + { + return "Telegram"; + } + +#if DEBUG + return locKey; +#else + return "Telegram"; +#endif + } + + private static string GetSound(Data data) + { + return data.sound; + } + + private static string GetGroup(Data data) + { + return data.group; + } + + private static string GetTag(Data data) + { + return data.tag; + } + + private static string GetLaunch(Data data) + { + var locKey = data.loc_key; + if (locKey == null) return null; + + var path = "/Views/ShellView.xaml"; + if (locKey == "DC_UPDATE") + { + path = "/Views/Additional/SettingsView.xaml"; + } + + var customParams = new List {"Action=" + locKey}; + if (data.custom != null) + { + customParams.AddRange(data.custom.GetParams()); + } + + return string.Format("{0}?{1}", path, string.Join("&", customParams)); + } + + private static string GetMessage(Data data) + { + var locKey = data.loc_key; + if (locKey == null) + { + Telegram.Logs.Log.Write("::PushNotificationsBackgroundTask locKey=null text=" + data.text); + return string.Empty; + } + + string locValue; + var resourceLoader = ResourceLoader.GetForViewIndependentUse("TelegramClient.Tasks/Resources"); + + locValue = resourceLoader.GetString(locKey); + if (locValue != "") + { + return string.Format(locValue, data.loc_args).Replace("\r\n", "\n").Replace("\n", " "); + } + var builder = new StringBuilder(); + if (data.loc_args != null) + { + builder.AppendLine("loc_args"); + foreach (var locArg in data.loc_args) + { + builder.AppendLine(locArg); + } + } + Telegram.Logs.Log.Write(string.Format("::PushNotificationsBackgroundTask missing locKey={0} locArgs={1}", locKey, builder.ToString())); + + //if (locKey.StartsWith("CHAT") || locKey.StartsWith("GEOCHAT")) + //{ + // return data.text; + //} + + //if (locKey.StartsWith("MESSAGE")) + //{ + // if (locKey == "MESSAGE_TEXT") + // { + // return data.loc_args[1]; + // } + + // return data.text; //add localization string here + //} + +#if DEBUG + return data.text; +#else + return string.Empty; +#endif + } + + private static void UpdateBadge(int badgeNumber) + { +#if WNS_PUSH_SERVICE + var badgeUpdater = BadgeUpdateManager.CreateBadgeUpdaterForApplication(); + if (badgeNumber == 0) + { + badgeUpdater.Clear(); + return; + } + + var badgeXml = BadgeUpdateManager.GetTemplateContent(BadgeTemplateType.BadgeNumber); + + var badgeElement = (XmlElement)badgeXml.SelectSingleNode("/badge"); + badgeElement.SetAttribute("value", badgeNumber.ToString()); + + try + { + badgeUpdater.Update(new BadgeNotification(badgeXml)); + } + catch (Exception ex) + { + Telegram.Logs.Log.Write(ex.ToString()); + } +#endif + } + + private static async Task IsFileExists(string fileName) + { + bool fileExists = true; + Stream fileStream = null; + StorageFile file = null; + + try + { + file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName); + fileStream = await file.OpenStreamForReadAsync(); + fileStream.Dispose(); + } + catch (FileNotFoundException) + { + // If the file dosn't exits it throws an exception, make fileExists false in this case + fileExists = false; + } + finally + { + if (fileStream != null) + { + fileStream.Dispose(); + } + } + + return fileExists; + } + + public static void AddToast(RootObject rootObject, string caption, string message, string sound, string launch, string tag, string group) + { +#if WNS_PUSH_SERVICE +#if INTERACTIVE_NOTIFICATIONS + + var toastNotifier = ToastNotificationManager.CreateToastNotifier(); + Version version = null; + if (rootObject.data.system != null && rootObject.data.system != null) + { + Version.TryParse(rootObject.data.system, out version); + } + var toastXml = new XmlDocument(); + if (version != null && version.Major >= 10) + { + string arguments; + string imageSource; + GetArgumentsAndImageSource(rootObject, out arguments, out imageSource); + + var xml = + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + //"" + //+ "" + //+ "" + //+ "Text1" + //+ "Text2" + //+ "/Page1.xaml" + //+ "" + //+ ""; + + toastXml.LoadXml(xml); + SetToastImage(toastXml, imageSource, arguments != null && arguments.StartsWith("from_id")); + SetActions(toastXml, arguments); + } + else + { + toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); + } + + SetText(toastXml, caption, message); + SetLaunch(toastXml, launch); + + if (!string.IsNullOrEmpty(sound) + && !string.Equals(sound, "default", StringComparison.OrdinalIgnoreCase)) + { + SetSound(toastXml, sound); + } + + try + { + var toast = new ToastNotification(toastXml); + if (tag != null) toast.Tag = tag; + if (group != null) toast.Group = group; + //RemoveToastGroup(group); + toastNotifier.Show(toast); + } + catch (Exception ex) + { + Telegram.Logs.Log.Write(ex.ToString()); + } +#else + var toastNotifier = ToastNotificationManager.CreateToastNotifier(); + + var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02); + SetText(toastXml, caption, message); + SetLaunch(toastXml, launch); + + if (!string.IsNullOrEmpty(sound) + && !string.Equals(sound, "default", StringComparison.OrdinalIgnoreCase)) + { + SetSound(toastXml, sound); + } + + try + { + var toast = new ToastNotification(toastXml); + if (tag != null) toast.Tag = tag; + if (group != null) toast.Group = group; + //RemoveToastGroup(group); + toastNotifier.Show(toast); + } + catch (Exception ex) + { + Telegram.Logs.Log.Write(ex.ToString()); + } +#endif +#endif + } + + private static void GetArgumentsAndImageSource(RootObject rootObject, out string arguments, out string imageSource) + { + arguments = null; + imageSource = null; + + if (rootObject != null) + { + var data = rootObject.data; + if (data != null) + { + var custom = data.custom; + if (custom != null) + { + if (custom.from_id != null) + { + int fromId; + if (Int32.TryParse(custom.from_id, out fromId)) + { + arguments = GetArguments("from_id", custom.from_id, true, custom); + } + } + else if (custom.chat_id != null) + { + int chatId; + if (Int32.TryParse(custom.chat_id, out chatId)) + { + arguments = GetArguments("chat_id", custom.chat_id, false, custom); + } + } + else if (custom.channel_id != null) + { + int channelId; + if (Int32.TryParse(custom.channel_id, out channelId)) + { + if (data.loc_key != null + && data.loc_key.StartsWith("CHAT")) + { + arguments = GetArguments("channel_id", custom.channel_id, true, custom); + } + } + } + + imageSource = GetImageSource(custom); + } + } + } + } + + private static string GetImageSource(Custom custom) + { + string imageSource = null; + if (custom.mtpeer != null) + { + var location = custom.mtpeer.ph; + if (location != null) + { + var fileName = String.Format("{0}_{1}_{2}.jpg", + location.volume_id, + location.local_id, + location.secret); + + if (IsFileExists(fileName).Result) + { + imageSource = fileName; + } + } + } + + return imageSource; + } + + private static string GetArguments(string peer, string peerId, bool needAccessHash, Custom custom) + { + string arguments = null; + + if (custom.mtpeer != null && custom.mtpeer.ah != null || !needAccessHash) + { + arguments = string.Format("{0}={1}", peer, peerId); + + if (custom.mtpeer != null && custom.mtpeer.ah != null) + { + arguments += string.Format(" access_hash={0}", custom.mtpeer.ah); + } + + if (custom.msg_id != null) + { + arguments += string.Format(" msg_id={0}", custom.msg_id); + } + } + + return arguments; + } + + private static void RemoveToastGroup(string groupname) + { +#if WNS_PUSH_SERVICE + ToastNotificationManager.History.RemoveGroup(groupname); +#endif + } + + private static void UpdateTile(string caption, string message) + { +#if WNS_PUSH_SERVICE + var tileUpdater = TileUpdateManager.CreateTileUpdaterForApplication(); + //tileUpdater.EnableNotificationQueue(false); + tileUpdater.EnableNotificationQueue(true); + tileUpdater.EnableNotificationQueueForSquare150x150(false); + //tileUpdater.EnableNotificationQueueForWide310x150(true); + + var wideTileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150IconWithBadgeAndText); + SetImage(wideTileXml, "IconicSmall110.png"); + SetText(wideTileXml, caption, message); + + var squareTile150Xml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150IconWithBadge); + SetImage(squareTile150Xml, "IconicTileMedium202.png"); + AppendTile(wideTileXml, squareTile150Xml); + + var squareTile71Xml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare71x71IconWithBadge); + SetImage(squareTile71Xml, "IconicSmall110.png"); + AppendTile(wideTileXml, squareTile71Xml); + + try + { + tileUpdater.Update(new TileNotification(wideTileXml)); + } + catch (Exception ex) + { + Telegram.Logs.Log.Write(ex.ToString()); + } +#endif + } + + private static void AppendTile(XmlDocument toTile, XmlDocument fromTile) + { + var fromTileNode = toTile.ImportNode(fromTile.GetElementsByTagName("binding").Item(0), true); + toTile.GetElementsByTagName("visual")[0].AppendChild(fromTileNode); + } + + private static void SetText(XmlDocument document, string caption, string message) + { + var toastTextElements = document.GetElementsByTagName("text"); + toastTextElements[0].InnerText = caption ?? string.Empty; + toastTextElements[1].InnerText = message ?? string.Empty; + } + + private static void SetActions(XmlDocument document, string arguments) + { + if (arguments == null) return; + + var resourceLoader = ResourceLoader.GetForViewIndependentUse("TelegramClient.Tasks/Resources"); + + //"" + + //"" + + //"" + + //"" + + var toastNode = document.SelectSingleNode("/toast"); + var actionsElement = document.CreateElement("actions"); + + var inputElement = document.CreateElement("input"); + inputElement.SetAttribute("id", "message"); + inputElement.SetAttribute("type", "text"); + inputElement.SetAttribute("placeHolderContent", resourceLoader.GetString("TypeReply")); + actionsElement.AppendChild(inputElement); + + var replyAction = document.CreateElement("action"); + replyAction.SetAttribute("activationType", "background"); + replyAction.SetAttribute("content", resourceLoader.GetString("Reply")); + replyAction.SetAttribute("arguments", "action=reply " + arguments); + replyAction.SetAttribute("hint-inputId", "message"); + replyAction.SetAttribute("imageUri", "Images/W10M/ic_send_2x.png"); + actionsElement.AppendChild(replyAction); + + var muteAction = document.CreateElement("action"); + muteAction.SetAttribute("activationType", "background"); + muteAction.SetAttribute("content", resourceLoader.GetString("Mute1Hour")); + muteAction.SetAttribute("arguments", "action=mute " + arguments); + actionsElement.AppendChild(muteAction); + + var disableAction = document.CreateElement("action"); + disableAction.SetAttribute("activationType", "background"); + disableAction.SetAttribute("content", resourceLoader.GetString("Disable")); + disableAction.SetAttribute("arguments", "action=disable " + arguments); + actionsElement.AppendChild(disableAction); + + toastNode.AppendChild(actionsElement); + } + + private static void SetToastImage(XmlDocument document, string imageSource, bool isUserPlaceholder) + { + var imageElements = document.GetElementsByTagName("image"); + if (imageSource == null) + { + ((XmlElement)imageElements[0]).SetAttribute("src", isUserPlaceholder ? "ms-appx:///Images/W10M/user_placeholder.png" : "ms-appx:///Images/W10M/group_placeholder.png"); + } + else + { + ((XmlElement)imageElements[0]).SetAttribute("src", "ms-appdata:///local/" + imageSource); + } + } + + private static void SetImage(XmlDocument document, string imageSource) + { + var imageElements = document.GetElementsByTagName("image"); + ((XmlElement)imageElements[0]).SetAttribute("src", imageSource); + } + + private static void SetSound(XmlDocument document, string soundSource) + { + //return; + + if (!Regex.IsMatch(soundSource, @"^sound[1-6]$", RegexOptions.IgnoreCase)) + { + return; + } + + var toastNode = document.SelectSingleNode("/toast"); + ((XmlElement)toastNode).SetAttribute("duration", "long"); + var audioElement = document.CreateElement("audio"); + audioElement.SetAttribute("src", "ms-appx:///Sounds/" + soundSource + ".wav"); + audioElement.SetAttribute("loop", "false"); + + toastNode.AppendChild(audioElement); + } + + private static void SetLaunch(XmlDocument document, string launch) + { + if (string.IsNullOrEmpty(launch)) + { + return; + } + if (PushNotificationsBackgroundTask.SystemVersion != null + && PushNotificationsBackgroundTask.SystemVersion.StartsWith("10")) //10.0.10572.0 or less + { + try + { + var currentVersion = new Version(PushNotificationsBackgroundTask.SystemVersion); + var minVersion = new Version("10.0.10572.0"); + if (currentVersion < minVersion) + { + return; + } + } + catch (Exception ex) + { + Telegram.Logs.Log.Write(ex.ToString()); + } + } + //launch = "/Views/ShellView.xaml"; + var toastNode = document.SelectSingleNode("/toast"); + ((XmlElement)toastNode).SetAttribute("launch", launch); + } + + //private static readonly Dictionary _locKeys = new Dictionary + //{ + // {"MESSAGE_FWDS", "forwarded you {1} messages"}, + // {"MESSAGE_TEXT", "{1}"}, + // {"MESSAGE_NOTEXT", "sent you a message"}, + // {"MESSAGE_PHOTO", "sent you a photo"}, + // {"MESSAGE_VIDEO", "sent you a video"}, + // {"MESSAGE_DOC", "sent you a document"}, + // {"MESSAGE_GIF", "sent you a GIF"}, + // {"MESSAGE_AUDIO", "sent you a voice message"}, + // {"MESSAGE_CONTACT", "shared a contact with you"}, + // {"MESSAGE_GEO", "sent you a map"}, + // {"MESSAGE_STICKER", "sent you a sticker"}, + + // {"CHAT_MESSAGE_FWDS", "{0} forwarded {2} messages to the group"}, + // {"CHAT_MESSAGE_TEXT", "{0}: {2}"}, + // {"CHAT_MESSAGE_NOTEXT", "{0} sent a message to the group"}, + // {"CHAT_MESSAGE_PHOTO", "{0} sent a photo to the group"}, + // {"CHAT_MESSAGE_VIDEO", "{0} sent a video to the group"}, + // {"CHAT_MESSAGE_DOC", "{0} sent a document to the group"}, + // {"CHAT_MESSAGE_GIF", "{0} sent a GIF to the group"}, + // {"CHAT_MESSAGE_AUDIO", "{0} sent a voice message to the group"}, + // {"CHAT_MESSAGE_CONTACT", "{0} shared a contact in the group"}, + // {"CHAT_MESSAGE_GEO", "{0} sent a map to the group"}, + // {"CHAT_MESSAGE_STICKER", "{0} sent a sticker to the group"}, + + // {"CHANNEL_MESSAGE_FWDS", "posted {1} forwarded messages"}, + // {"CHANNEL_MESSAGE_TEXT", "{1}"}, + // {"CHANNEL_MESSAGE_NOTEXT", "posted a message"}, + // {"CHANNEL_MESSAGE_PHOTO", "posted a photo"}, + // {"CHANNEL_MESSAGE_VIDEO", "posted a video"}, + // {"CHANNEL_MESSAGE_DOC", "posted a document"}, + // {"CHANNEL_MESSAGE_GIF", "posted a GIF"}, + // {"CHANNEL_MESSAGE_AUDIO", "posted a voice message"}, + // {"CHANNEL_MESSAGE_CONTACT", "posted a contact"}, + // {"CHANNEL_MESSAGE_GEO", "posted a map"}, + // {"CHANNEL_MESSAGE_STICKER", "posted a sticker"}, + + // {"CHAT_CREATED", "{0} invited you to the group"}, + // {"CHAT_TITLE_EDITED", "{0} edited the group's name"}, + // {"CHAT_PHOTO_EDITED", "{0} edited the group's photo"}, + // {"CHAT_ADD_MEMBER", "{0} invited {2} to the group"}, + // {"CHAT_ADD_YOU", "{0} invited you to the group"}, + // {"CHAT_DELETE_MEMBER", "{0} kicked {2} from the group"}, + // {"CHAT_DELETE_YOU", "{0} kicked you from the group"}, + // {"CHAT_LEFT", "{0} has left the group"}, + // {"CHAT_RETURNED", "{0} has returned to the group"}, + // {"GEOCHAT_CHECKIN", "{0} has checked-in"}, + // {"CHAT_JOINED", "{0} has joined the group"}, + + // {"CONTACT_JOINED", "{0} joined the App!"}, + // {"AUTH_UNKNOWN", "New login from unrecognized device {0}"}, + // {"AUTH_REGION", "New login from unrecognized device {0}, location: {1}"}, + + // {"CONTACT_PHOTO", "updated profile photo"}, + + // {"ENCRYPTION_REQUEST", "You have a new message"}, + // {"ENCRYPTION_ACCEPT", "You have a new message"}, + // {"ENCRYPTED_MESSAGE", "You have a new message"}, + + // {"DC_UPDATE", "Open this notification to update app settings"}, + + // {"LOCKED_MESSAGE", "You have a new message"} + //}; + } + + + public sealed class Photo + { + public string volume_id { get; set; } + public string local_id { get; set; } + public string secret { get; set; } + public int dc_id { get; set; } + } + + public sealed class MTPeer + { + public string ah { get; set; } + public Photo ph { get; set; } + } + + public sealed class Custom + { + public string msg_id { get; set; } + public string from_id { get; set; } + public string chat_id { get; set; } + public string channel_id { get; set; } + public MTPeer mtpeer { get; set; } + public string call_id { get; set; } + public string call_ah { get; set; } + + public string group + { + get + { + if (chat_id != null) return "c" + chat_id; + if (channel_id != null) return "c" + chat_id; + if (from_id != null) return "u" + from_id; + return null; + } + } + + public string tag { get { return msg_id; } } + + public IEnumerable GetParams() + { + if (msg_id != null) yield return "msg_id=" + msg_id; + if (from_id != null) yield return "from_id=" + from_id; + if (chat_id != null) yield return "chat_id=" + chat_id; + if (channel_id != null) yield return "channel_id=" + channel_id; + } + } + + public sealed class Data + { + public Custom custom { get; set; } + public string sound { get; set; } + public string mute { get; set; } + public int badge { get; set; } + public string loc_key { get; set; } + public string[] loc_args { get; set; } + public int random_id { get; set; } + public int user_id { get; set; } + public string text { get; set; } + public string system { get; set; } + + public string group { get { return custom != null ? custom.group : null; } } + public string tag { get { return custom != null ? custom.tag : null; } } + } + + public sealed class RootObject + { + public int date { get; set; } + public Data data { get; set; } + } +} \ No newline at end of file diff --git a/TelegramClient.Tasks/Resources/de/Resources.resw b/TelegramClient.Tasks/Resources/de/Resources.resw new file mode 100755 index 0000000..cb5a750 --- /dev/null +++ b/TelegramClient.Tasks/Resources/de/Resources.resw @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Zugriff von unbekanntem Gerät {0}, Standort: {1} + + + Zugriff von unbekanntem Gerät {0} + + + hat eine Sprachnachricht gesendet + + + hat einen Kontakt gesendet + + + hat eine Datei gesendet + + + hat {1} Nachrichten weitergeleitet + + + hat dich eingeladen, {1} zu spielen + + + hat einen Standort gesendet + + + hat ein GIF gesendet + + + hat eine Nachricht gesendet + + + hat ein Bild gesendet + + + hat einen Sticker gesendet + + + {1} + + + hat ein Video gesendet + + + {0} hat {2} in die Gruppe eingeladen + + + {0} hat dich in die Gruppe eingeladen + + + {0} hat dich in die Gruppe eingeladen + + + {0} hat {2} aus der Gruppe entfernt + + + {0} hat dich aus der Gruppe entfernt + + + {0} ist der Gruppe beigetreten + + + {0} hat die Gruppe verlassen + + + {0} hat eine Sprachnachricht an die Gruppe gesendet + + + {0} hat einen Kontakt an die Gruppe gesendet + + + {0} hat ein Dokument an die Gruppe gesendet + + + {0} hat an die Gruppe {2} Nachrichten weitergeleitet + + + {0} hat die Gruppe eingeladen, {2} zu spielen + + + {0} hat einen Standort an die Gruppe gesendet + + + {0} hat ein GIF an die Gruppe gesendet + + + {0} hat eine Rechnung für {2} gesendet + + + {0} hat eine Nachricht an die Gruppe gesendet + + + {0} hat ein Bild an die Gruppe gesendet + + + {0} hat einen Sticker an die Gruppe gesendet + + + {0}: {2} + + + {0} hat ein Video an die Gruppe gesendet + + + {0} hat das Bild der Gruppe geändert + + + {0} ist in die Gruppe zurückgekehrt + + + {0} hat den Namen der Gruppe geändert + + + {0} benutzt jetzt Telegram! + + + hat das Profilbild geändert + + + Diese Mitteilung öffnen, um die App-Einstellungen zu aktualisieren + + + Deaktivieren + + + Du hast eine neue Nachricht + + + Du hast eine neue Nachricht + + + Du hast eine neue Nachricht + + + {0} hat eingecheckt + + + Du hast eine neue Nachricht + + + hat dir eine Sprachnachricht gesendet + + + hat dir einen Kontakt gesendet + + + hat dir ein Dokument gesendet + + + hat dir {1} Nachrichten weitergeleitet + + + hat dich eingeladen, {1} zu spielen + + + hat dir einen Standort gesendet + + + hat dir ein GIF gesendet + + + hat dir eine Rechnung für {1} gesendet + + + hat dir eine Nachricht gesendet + + + hat dir ein Bild gesendet + + + hat dir einen Sticker gesendet + + + {1} + + + hat dir ein Video gesendet + + + Stumm für 1 Stunde + + + Du hast einen Anruf von {0} verpasst + + + {0} ruft dich an! + + + hat eine Sprachnachricht angeheftet + + + hat einen Kontakt angeheftet + + + hat eine Datei angeheftet + + + hat ein Spiel angeheftet + + + hat einen Standort angeheftet + + + hat ein GIF angeheftet + + + hat eine Rechnung anheftet + + + hat eine Nachricht angeheftet + + + hat ein Bild angeheftet + + + hat einen Sticker angeheftet + + + hat "{1}" angeheftet + + + hat ein Video angeheftet + + + Antworten + + + Tippe deine Antwort + + diff --git a/TelegramClient.Tasks/Resources/en/Resources.resw b/TelegramClient.Tasks/Resources/en/Resources.resw new file mode 100755 index 0000000..1ec4361 --- /dev/null +++ b/TelegramClient.Tasks/Resources/en/Resources.resw @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New login from unrecognized device {0}, location: {1} + + + New login from unrecognized device {0} + + + posted a voice message + + + posted a contact + + + posted a document + + + posted {1} forwarded messages + + + invited you to play {1} + + + posted a map + + + posted a GIF + + + posted a message + + + posted a photo + + + posted a sticker + + + {1} + + + posted a video + + + {0} invited {2} to the group + + + {0} invited you to the group + + + {0} invited you to the group + + + {0} kicked {2} from the group + + + {0} kicked you from the group + + + {0} has joined the group + + + {0} has left the group + + + {0} sent a voice message to the group + + + {0} shared a contact in the group + + + {0} sent a document to the group + + + {0} forwarded {2} messages to the group + + + {0} invited the group to play {2} + + + {0} sent a map to the group + + + {0} sent a GIF to the group + + + {0} sent an invoice for {2} + + + {0} sent a message to the group + + + {0} sent a photo to the group + + + {0} sent a sticker to the group + + + {0}: {2} + + + {0} sent a video to the group + + + {0} edited the group's photo + + + {0} has returned to the group + + + {0} edited the group's name + + + {0} joined the App! + + + updated profile photo + + + Open this notification to update app settings + + + Disable + + + You have a new message + + + You have a new message + + + You have a new message + + + {0} has checked-in + + + You have a new message + + + sent you a voice message + + + shared a contact with you + + + sent you a document + + + forwarded you {1} messages + + + invited you to play {1} + + + sent you a map + + + sent you a GIF + + + sent you an invoice for {1} + + + sent you a message + + + sent you a photo + + + sent you a sticker + + + {1} + + + sent you a video + + + Mute for 1 hour + + + You missed a call from {0} + + + {0} is calling you! + + + pinned a voice message + + + pinned a contact + + + pinned a file + + + pinned a game + + + pinned a map + + + pinned a GIF + + + pinned an invoice + + + pinned a message + + + pinned a photo + + + pinned a sticker + + + pinned "{1}" + + + pinned a video + + + Reply + + + Type a reply + + \ No newline at end of file diff --git a/TelegramClient.Tasks/Resources/es/Resources.resw b/TelegramClient.Tasks/Resources/es/Resources.resw new file mode 100755 index 0000000..4b2afea --- /dev/null +++ b/TelegramClient.Tasks/Resources/es/Resources.resw @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Inicio de sesión en un dispositivo desconocido {0}, ubicación: {1} + + + Inicio de sesión en un dispositivo desconocido {0} + + + publicó un mensaje de voz + + + publicó un contacto + + + publicó un archivo + + + publicó {1} mensajes reenviados + + + te invitó a jugar {1} + + + publicó un mapa + + + publicó un GIF + + + publicó un mensaje + + + publicó una foto + + + publicó un sticker + + + {1} + + + publicó un vídeo + + + {0} invitó {2} al grupo + + + {0} te invitó al grupo + + + {0} te invitó al grupo + + + {0} expulsó a {2} del grupo + + + {0} te expulsó del grupo + + + {0} se unió al grupo + + + {0} dejó el grupo + + + {0} envío un mensaje de voz al grupo + + + {0} compartió un contacto en el grupo + + + {0} envió un archivo al grupo + + + {0} reenvió {2} mensajes al grupo + + + {0} invitó al grupo a jugar a {2} + + + {0} envió un mapa al grupo + + + {0} envió un GIF al grupo + + + {0} envió una factura por {2} + + + {0} envió un mensaje al grupo + + + {0} envió una foto al grupo + + + {0} envió un sticker al grupo + + + {0}: {2} + + + {0} envió un vídeo al grupo + + + {0} editó la foto del grupo + + + {0} volvió al grupo + + + {0} editó el nombre del grupo + + + ¡{0} se unió a Telegram! + + + actualizó la foto de perfil + + + Abre esta notificación para actualizar los ajustes de la aplicación + + + Desactivar + + + Tienes un nuevo mensaje + + + Tienes un nuevo mensaje + + + Tienes un nuevo mensaje + + + {0} hizo check-in + + + Tienes un mensaje nuevo + + + te envió un mensaje de voz + + + compartió un contacto contigo + + + te envió un archivo + + + te reenvió {1} mensajes + + + te invitó a jugar a {1} + + + te envió un mapa + + + te envió un GIF + + + te envió una factura por {1} + + + te envió un mensaje + + + te envió una foto + + + te envió un sticker + + + {1} + + + te envió un vídeo + + + Silenciar 1 hora + + + Perdiste una llamada de {0} + + + ¡{0} te está llamando! + + + ancló un mensaje de voz + + + ancló un contacto + + + ancló un archivo + + + ancló un juego + + + ancló un mapa + + + ancló un GIF + + + ancló una factura + + + ancló un mensaje + + + ancló una foto + + + ancló un sticker + + + ancló "{1}" + + + ancló un vídeo + + + Responder + + + Escribe una respuesta + + diff --git a/TelegramClient.Tasks/Resources/it/Resources.resw b/TelegramClient.Tasks/Resources/it/Resources.resw new file mode 100755 index 0000000..88b4f2d --- /dev/null +++ b/TelegramClient.Tasks/Resources/it/Resources.resw @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Accesso da un nuovo dispositivo {0}, posizione: {1} + + + Accesso da un nuovo dispositivo {0} + + + ha pubblicato un messaggio vocale + + + ha pubblicato un contatto + + + ha pubblicato un documento + + + ha pubblicato {1} messaggi inoltrati + + + ti ha invitato a giocare a {1} + + + ha pubblicato una posizione + + + ha pubblicato una GIF + + + ha pubblicato un messaggio + + + ha pubblicato una foto + + + ha pubblicato uno sticker + + + {1} + + + ha pubblicato un video + + + {0} ha aggiunto {2} al gruppo + + + {0} ti ha aggiunto al gruppo + + + {0} ti ha aggiunto al gruppo + + + {0} ha rimosso {2} dal gruppo + + + {0} ti ha rimosso dal gruppo + + + {0} si è unito al gruppo + + + {0} ha lasciato il gruppo + + + {0} ha inviato una nota vocale al gruppo + + + {0} ha condiviso un contatto con il gruppo + + + {0} ha inviato un file al gruppo + + + {0} ha inoltrato {2} messaggi al gruppo + + + {0} ha invitato il gruppo a giocare a {2} + + + {0} ha inviato una posizione al gruppo + + + {0} ha inviato una GIF al gruppo + + + {0} ha inviato una fattura per {2} + + + {0} ha inviato un messaggio al gruppo + + + {0} ha inviato una foto al gruppo + + + {0} ha inviato uno sticker al gruppo + + + {0}: {2} + + + {0} ha inviato un video al gruppo + + + {0} ha cambiato la foto del gruppo + + + {0} è tornato nel gruppo + + + {0} ha cambiato il nome del gruppo + + + {0} si è unito a Telegram + + + ha aggiornato la foto profilo + + + Apri questa notifica per aggiornare le impostazioni dell'applicazione + + + Disabilita + + + Hai un nuovo messaggio + + + Hai un nuovo messaggio + + + Hai un nuovo messaggio + + + {0} ha fatto il check-in + + + Hai un nuovo messaggio + + + ti ha inviato una nota vocale + + + ha condiviso un contatto con te + + + ti ha inviato un file + + + ti ha inoltrato {1} messaggi + + + ti ha invitato a giocare a {1} + + + ti ha inviato una posizione + + + ti ha inviato una GIF + + + ti ha inviato una fattura per {1} + + + ti ha inviato un messaggio + + + ti ha inviato una foto + + + ti ha inviato uno sticker + + + {1} + + + ti ha inviato un video + + + Silenzia per 1 ora + + + Hai perso una chiamata da {0} + + + {0} ti sta chiamando! + + + ha fissato un messaggio vocale + + + ha fissato un contatto + + + ha fissato un file + + + ha fissato un gioco + + + ha fissato una posizione + + + ha fissato una GIF + + + ha fissato una fattura + + + ha fissato un messaggio + + + ha fissato una foto + + + ha fissato uno sticker + + + ha fissato "{1}" + + + ha fissato un video + + + Rispondi + + + Scrivi una risposta + + diff --git a/TelegramClient.Tasks/Resources/nl/Resources.resw b/TelegramClient.Tasks/Resources/nl/Resources.resw new file mode 100755 index 0000000..805fecf --- /dev/null +++ b/TelegramClient.Tasks/Resources/nl/Resources.resw @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Ingelogd vanaf een nieuw apparaat: {0}, locatie: {1} + + + Ingelogd vanaf een nieuw apparaat: {0} + + + plaatste een spraakbericht + + + plaatste een contact + + + plaatste een bestand + + + plaatste {1} doorgestuurde berichten + + + wil {1} met je spelen + + + plaatste een kaart + + + plaatste een GIF + + + plaatste een bericht + + + plaatste een foto + + + plaatste een sticker + + + {1} + + + plaatste een video + + + {0} heeft {2} uitgenodigd voor de groep + + + {0} heeft je uitgenodigd voor de groep + + + {0} heeft je uitgenodigd voor de groep + + + {0} heeft {2} verwijderd uit de groep + + + {0} heeft je verwijderd uit de groep + + + {0} is nu lid van de groep + + + {0} heeft de groep verlaten + + + {0} heeft een spraakbericht gestuurd naar de groep + + + {0} heeft een contact gedeeld met de groep + + + {0} heeft een bestand gestuurd naar de groep + + + {0} heeft {2} berichten doorgestuurd naar de groep + + + {0} wil {2} met de groep spelen + + + {0} heeft een kaart gestuurd naar de groep + + + {0} heeft een GIF gestuurd naar de groep + + + {0} heeft je een factuur van {2} gestuurd + + + {0} heeft een bericht gestuurd naar de groep + + + {0} heeft een foto gestuurd naar de groep + + + {0} heeft een sticker gestuurd naar de groep + + + {0}: {2} + + + {0} heeft een video gestuurd naar de groep + + + {0} heeft de groepsafbeelding gewijzigd + + + {0} is teruggekeerd naar de groep + + + {0} heeft de groepsnaam gewijzigd + + + {0} heeft nu Telegram! + + + heeft zijn/haar profielfoto gewijzigd + + + Open deze melding om app-instellingen bij te werken + + + Uitschakelen + + + Je hebt een nieuw bericht + + + Je hebt een nieuw bericht + + + Je hebt een nieuw bericht + + + {0} is ingecheckt + + + Je hebt een nieuw bericht + + + heeft je een spraakbericht gestuurd + + + heeft een contact met je gedeeld + + + heeft je een bestand gestuurd + + + Stuurde {1} berichten door + + + wil {1} met je spelen + + + heeft je een kaart gestuurd + + + heeft je een GIF gestuurd + + + heeft je een factuur van {1} gestuurd + + + heeft je een bericht gestuurd + + + heeft je een foto gestuurd + + + heeft je een sticker gestuurd + + + {1} + + + heeft je een video gestuurd + + + 1 uur stil + + + Gemiste oproep van {0} + + + {0} belt je + + + heeft spraakbericht vastgezet + + + heeft contact vastgezet + + + heeft bestand vastgezet + + + heeft een spel vastgezet + + + heeft locatie vastgezet + + + heeft GIF vastgezet + + + factuur vastgezet + + + heeft bericht vastgezet + + + heeft foto vastgezet + + + heeft sticker vastgezet + + + vastgezet "{1}" + + + heeft video vastgezet + + + Antwoord + + + Tik je antwoord + + diff --git a/TelegramClient.Tasks/Resources/pt/Resources.resw b/TelegramClient.Tasks/Resources/pt/Resources.resw new file mode 100755 index 0000000..a717b92 --- /dev/null +++ b/TelegramClient.Tasks/Resources/pt/Resources.resw @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Novo login de um dispositivo desconhecido {0}, localização: {1} + + + Novo login de dispositivo desconhecido {0} + + + postou uma mensagem de voz + + + postou um contato + + + postou um documento + + + postou {1} mensagens encaminhadas + + + te convidou para jogar {1} + + + postou um mapa + + + postou um GIF + + + postou uma mensagem + + + postou uma foto + + + postou um sticker + + + {1} + + + postou um vídeo + + + {0} convidou {2} para o grupo + + + {0} convidou você para o grupo + + + {0} convidou você para o grupo + + + {0} removeu {2} do grupo + + + {0} removeu você do grupo + + + {0} entrou no grupo + + + {0} deixou o grupo + + + {0} enviou uma mensagem de voz para o grupo + + + {0} compartilhou um contato no grupo + + + {0} enviou um documento para o grupo + + + {0} encaminhou {2} mensagens para o grupo + + + {0} convidou o grupo para jogar {2} + + + {0} enviou um mapa para o grupo + + + {0} enviou um GIF para o grupo + + + {0} enviou uma fatura para {2} + + + {0} enviou uma mensagem para o grupo + + + {0} enviou uma foto para o grupo + + + {0} enviou um sticker para o grupo + + + {0}: {2} + + + {0} enviou um vídeo para o grupo + + + {0} alterou a foto do grupo + + + {0} retornou ao grupo + + + {0} editou o nome do grupo + + + {0} entrou para o Telegram! + + + atualizou a foto do perfil + + + Abra essa notificação para atualizar as configurações + + + Desativar + + + Você tem uma nova mensagem + + + Você tem uma nova mensagem + + + Você tem uma nova mensagem + + + {0} foi verificado + + + Você tem uma nova mensagem + + + te enviou uma mensagem de voz + + + compartilhou um contato com você + + + te enviou um documento + + + encaminhou para você {1} mensagens + + + te convidou para jogar {1} + + + te enviou um mapa + + + te enviou um GIF + + + enviou uma fatura para {1} + + + te enviou uma mensagem + + + te enviou uma foto + + + te enviou um sticker + + + {1} + + + te enviou um vídeo + + + Silenciar por 1 hora + + + Você perdeu uma chamada de {0} + + + {0} está te ligando! + + + fixou uma mensagem de voz + + + fixou um contato + + + fixou um arquivo + + + fixou um jogo + + + fixou um mapa + + + fixou um GIF + + + fixou uma fatura + + + fixou uma mensagem + + + fixou uma foto + + + fixou um sticker + + + fixou "{1}" + + + fixou um vídeo + + + Responder + + + Escrever uma resposta + + diff --git a/TelegramClient.Tasks/Resources/ru/Resources.resw b/TelegramClient.Tasks/Resources/ru/Resources.resw new file mode 100755 index 0000000..1ec4361 --- /dev/null +++ b/TelegramClient.Tasks/Resources/ru/Resources.resw @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + New login from unrecognized device {0}, location: {1} + + + New login from unrecognized device {0} + + + posted a voice message + + + posted a contact + + + posted a document + + + posted {1} forwarded messages + + + invited you to play {1} + + + posted a map + + + posted a GIF + + + posted a message + + + posted a photo + + + posted a sticker + + + {1} + + + posted a video + + + {0} invited {2} to the group + + + {0} invited you to the group + + + {0} invited you to the group + + + {0} kicked {2} from the group + + + {0} kicked you from the group + + + {0} has joined the group + + + {0} has left the group + + + {0} sent a voice message to the group + + + {0} shared a contact in the group + + + {0} sent a document to the group + + + {0} forwarded {2} messages to the group + + + {0} invited the group to play {2} + + + {0} sent a map to the group + + + {0} sent a GIF to the group + + + {0} sent an invoice for {2} + + + {0} sent a message to the group + + + {0} sent a photo to the group + + + {0} sent a sticker to the group + + + {0}: {2} + + + {0} sent a video to the group + + + {0} edited the group's photo + + + {0} has returned to the group + + + {0} edited the group's name + + + {0} joined the App! + + + updated profile photo + + + Open this notification to update app settings + + + Disable + + + You have a new message + + + You have a new message + + + You have a new message + + + {0} has checked-in + + + You have a new message + + + sent you a voice message + + + shared a contact with you + + + sent you a document + + + forwarded you {1} messages + + + invited you to play {1} + + + sent you a map + + + sent you a GIF + + + sent you an invoice for {1} + + + sent you a message + + + sent you a photo + + + sent you a sticker + + + {1} + + + sent you a video + + + Mute for 1 hour + + + You missed a call from {0} + + + {0} is calling you! + + + pinned a voice message + + + pinned a contact + + + pinned a file + + + pinned a game + + + pinned a map + + + pinned a GIF + + + pinned an invoice + + + pinned a message + + + pinned a photo + + + pinned a sticker + + + pinned "{1}" + + + pinned a video + + + Reply + + + Type a reply + + \ No newline at end of file diff --git a/TelegramClient.Tasks/TelegramClient.Tasks.csproj b/TelegramClient.Tasks/TelegramClient.Tasks.csproj new file mode 100755 index 0000000..23a9ea9 --- /dev/null +++ b/TelegramClient.Tasks/TelegramClient.Tasks.csproj @@ -0,0 +1,132 @@ + + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {997BD0C4-68E8-4495-904A-EB798B166832} + winmdobj + Properties + TelegramClient.Tasks + en + en;de;es;it;nl;pt; + TelegramClient.Tasks + 8.1 + 12 + 512 + {76F1466A-8B6D-4E39-A767-685A06062A39};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + true + full + false + bin\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE;NETFX_CORE;WINDOWS_PHONE_APP + prompt + 4 + + + true + bin\ARM\Debug\ + TRACE;DEBUG;NETFX_CORE;WINDOWS_PHONE_APP; + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_PHONE_APP; + true + ;2008 + pdbonly + ARM + false + prompt + true + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_PHONE_APP + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_PHONE_APP + true + ;2008 + pdbonly + x86 + false + prompt + true + + + + + {de897f51-af1f-48fe-9dbb-6b308f9740d1} + Telegram.Api.PCL + + + + + + + + + + + + + + Designer + + + Designer + + + Designer + + + Designer + + + Designer + + + + + + + 12.0 + + + WindowsPhoneApp + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/ARM/libwebp.dll b/TelegramClient.WP8/ARM/libwebp.dll new file mode 100755 index 0000000..453de9f Binary files /dev/null and b/TelegramClient.WP8/ARM/libwebp.dll differ diff --git a/TelegramClient.WP8/ApplicationIcon.png b/TelegramClient.WP8/ApplicationIcon.png new file mode 100755 index 0000000..0ad2da5 Binary files /dev/null and b/TelegramClient.WP8/ApplicationIcon.png differ diff --git a/TelegramClient.WP8/ApplicationIcon210.png b/TelegramClient.WP8/ApplicationIcon210.png new file mode 100755 index 0000000..038bb69 Binary files /dev/null and b/TelegramClient.WP8/ApplicationIcon210.png differ diff --git a/TelegramClient.WP8/ApplicationIcon99.png b/TelegramClient.WP8/ApplicationIcon99.png new file mode 100755 index 0000000..ee216d1 Binary files /dev/null and b/TelegramClient.WP8/ApplicationIcon99.png differ diff --git a/TelegramClient.WP8/Background.png b/TelegramClient.WP8/Background.png new file mode 100755 index 0000000..07c89f3 Binary files /dev/null and b/TelegramClient.WP8/Background.png differ diff --git a/TelegramClient.WP8/Behaviors/InfiniteScrollingBehavior.cs b/TelegramClient.WP8/Behaviors/InfiniteScrollingBehavior.cs new file mode 100755 index 0000000..b336748 --- /dev/null +++ b/TelegramClient.WP8/Behaviors/InfiniteScrollingBehavior.cs @@ -0,0 +1,57 @@ +using System.Windows.Interactivity; +using Microsoft.Phone.Controls; + +namespace TelegramClient.Behaviors +{ + public class IncrementalLoadingTrigger : TriggerBase + { + private int _knob = 1; + + public int Knob + { + get { return _knob; } + set { _knob = value; } + } + + protected override void OnAttached() + { + base.OnAttached(); + AssociatedObject.ItemRealized += OnItemRealized; + } + + private void OnItemRealized(object sender, ItemRealizationEventArgs e) + { + var longListSelector = sender as LongListSelector; + if (longListSelector == null) + { + return; + } + + var item = e.Container.Content; + var items = longListSelector.ItemsSource; + var index = items.IndexOf(item); + + //if (items.Count >= Knob + // && e.Container.Content.Equals(longListSelector.ItemsSource[longListSelector.ItemsSource.Count - Knob])) + //{ + // InvokeActions(null); + //} + + if (items.Count - index <= Knob) + { + InvokeActions(null); + } + } + + protected override void OnDetaching() + { + base.OnDetaching(); + AssociatedObject.ItemRealized -= OnItemRealized; + } + } + + public class InfiniteScrollingBehavior : Behavior + { + + } +} diff --git a/TelegramClient.WP8/Controls/StartView/DragEventArgs.cs b/TelegramClient.WP8/Controls/StartView/DragEventArgs.cs new file mode 100755 index 0000000..cdba7fc --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/DragEventArgs.cs @@ -0,0 +1,33 @@ +using System.Diagnostics.CodeAnalysis; +using System.Windows; + +namespace TelegramClient.Controls.StartView +{ + internal class DragEventArgs : GestureEventArgs + { + public DragEventArgs() + { + } + + public DragEventArgs(InputDeltaArgs args) + { + if (args != null) + { + CumulativeDistance = args.CumulativeTranslation; + DeltaDistance = args.DeltaTranslation; + } + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + public bool IsTouchComplete { get; private set; } + + public Point DeltaDistance { get; private set; } + + public Point CumulativeDistance { get; internal set; } + + public void MarkAsFinalTouchManipulation() + { + IsTouchComplete = true; + } + } +} diff --git a/TelegramClient.WP8/Controls/StartView/FlickEventArgs.cs b/TelegramClient.WP8/Controls/StartView/FlickEventArgs.cs new file mode 100755 index 0000000..cef3bf3 --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/FlickEventArgs.cs @@ -0,0 +1,7 @@ +namespace TelegramClient.Controls.StartView +{ + internal class FlickEventArgs : GestureEventArgs + { + public double Angle { get; internal set; } + } +} diff --git a/TelegramClient.WP8/Controls/StartView/GestureEventArgs.cs b/TelegramClient.WP8/Controls/StartView/GestureEventArgs.cs new file mode 100755 index 0000000..6f2e4e8 --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/GestureEventArgs.cs @@ -0,0 +1,6 @@ +namespace TelegramClient.Controls.StartView +{ + internal class GestureEventArgs : System.EventArgs + { + } +} diff --git a/TelegramClient.WP8/Controls/StartView/GestureHelper.cs b/TelegramClient.WP8/Controls/StartView/GestureHelper.cs new file mode 100755 index 0000000..1f02d1e --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/GestureHelper.cs @@ -0,0 +1,201 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Windows; +using System.Windows.Media; +using TelegramClient.Controls.StartView; +using DragEventArgs = TelegramClient.Controls.StartView.DragEventArgs; + +internal abstract class GestureHelper +{ + private readonly Size DeadZoneInPixels = new Size(12, 12); + + private DragLock _dragLock; + private bool _dragging; + private WeakReference _gestureSource; + private Point _gestureOrigin; + + protected GestureHelper(UIElement target, bool shouldHandleAllDrags) + { + Target = target; + ShouldHandleAllDrags = shouldHandleAllDrags; + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + protected bool ShouldHandleAllDrags { get; private set; } + + protected UIElement Target { get; private set; } + + public event EventHandler GestureStart; + + public event EventHandler Flick; + + public event EventHandler GestureEnd; + + public event EventHandler HorizontalDrag; + + public event EventHandler VerticalDrag; + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + public static GestureHelper Create(UIElement target) + { + return GestureHelper.Create(target, true); + } + + public static GestureHelper Create(UIElement target, bool shouldHandleAllDrags) + { + GestureHelper gestureHelper = new ManipulationGestureHelper(target, shouldHandleAllDrags); + gestureHelper.Start(); + return gestureHelper; + } + + protected abstract void HookEvents(); + + public void Start() + { + HookEvents(); + } + + protected void NotifyDown(InputBaseArgs args) + { + GestureEventArgs e = new GestureEventArgs(); + _gestureSource = new WeakReference(args.Source); + _gestureOrigin = args.Origin; + _dragLock = DragLock.Unset; + _dragging = false; + RaiseGestureStart(e); + } + + protected void NotifyMove(InputDeltaArgs args) + { + if (Math.Abs(args.CumulativeTranslation.X) > DeadZoneInPixels.Width || Math.Abs(args.CumulativeTranslation.Y) > DeadZoneInPixels.Height) + { + if (!_dragging) + { + ReleaseMouseCaptureAtGestureOrigin(); + } + + _dragging = true; + + if (_dragLock == DragLock.Unset) + { + double angle = GestureHelper.AngleFromVector(args.CumulativeTranslation.X, args.CumulativeTranslation.Y) % 180; + _dragLock = angle <= 45 || angle >= 135 ? DragLock.Horizontal : DragLock.Vertical; + } + } + + if (_dragging) + { + RaiseDragEvents(args); + } + } + + private void ReleaseMouseCaptureAtGestureOrigin() + { + if (_gestureSource != null) + { + FrameworkElement gestureSource = _gestureSource.Target as FrameworkElement; + if (gestureSource != null) + { + foreach (UIElement element in VisualTreeHelper.FindElementsInHostCoordinates( + gestureSource.TransformToVisual(null).Transform(_gestureOrigin), Application.Current.RootVisual)) + { + element.ReleaseMouseCapture(); + } + } + } + } + + protected void NotifyUp(InputCompletedArgs args) + { + EventArgs e = EventArgs.Empty; + _dragLock = DragLock.Unset; + _dragging = false; + + if (args.IsInertial) + { + double angle = GestureHelper.AngleFromVector(args.FinalLinearVelocity.X, args.FinalLinearVelocity.Y); + if (angle <= 45 || angle >= 315) + { + angle = 0; + } + else if (angle >= 135 && angle <= 225) + { + angle = 180; + } + + FlickEventArgs flickEventArgs = new FlickEventArgs + { + Angle = angle + }; + ReleaseMouseCaptureAtGestureOrigin(); + RaiseFlick(flickEventArgs); + } + else if (args.TotalTranslation.X != 0 || args.TotalTranslation.Y != 0) + { + DragEventArgs dragEventArgs = new DragEventArgs + { + CumulativeDistance = args.TotalTranslation + }; + dragEventArgs.MarkAsFinalTouchManipulation(); + e = dragEventArgs; + } + + RaiseGestureEnd(e); + } + + private void RaiseGestureStart(GestureEventArgs args) + { + SafeRaise.Raise(GestureStart, this, args); + } + + private void RaiseFlick(FlickEventArgs args) + { + SafeRaise.Raise(Flick, this, args); + } + + private void RaiseGestureEnd(EventArgs args) + { + SafeRaise.Raise(GestureEnd, this, args); + } + + private void RaiseDragEvents(InputDeltaArgs args) + { + DragEventArgs e = new DragEventArgs(args); + if (args.DeltaTranslation.X != 0 && _dragLock == DragLock.Horizontal) + { + RaiseHorizontalDrag(e); + } + else if (args.DeltaTranslation.Y != 0 && _dragLock == DragLock.Vertical) + { + RaiseVerticalDrag(e); + } + } + + private void RaiseHorizontalDrag(DragEventArgs args) + { + SafeRaise.Raise(HorizontalDrag, this, args); + } + + private void RaiseVerticalDrag(DragEventArgs args) + { + SafeRaise.Raise(VerticalDrag, this, args); + } + + private static double AngleFromVector(double x, double y) + { + double num = Math.Atan2(y, x); + if (num < 0) + { + num = 2 * Math.PI + num; + } + return num * 360 / (2 * Math.PI); + } + + private enum DragLock + { + Unset, + Free, + Vertical, + Horizontal, + } +} diff --git a/TelegramClient.WP8/Controls/StartView/InputBaseArgs.cs b/TelegramClient.WP8/Controls/StartView/InputBaseArgs.cs new file mode 100755 index 0000000..48c0cff --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/InputBaseArgs.cs @@ -0,0 +1,17 @@ +using System.Windows; + +namespace TelegramClient.Controls.StartView +{ + internal class InputBaseArgs + { + protected InputBaseArgs(UIElement source, Point origin) + { + Source = source; + Origin = origin; + } + + public UIElement Source { get; private set; } + + public Point Origin { get; private set; } + } +} diff --git a/TelegramClient.WP8/Controls/StartView/InputCompletedArgs.cs b/TelegramClient.WP8/Controls/StartView/InputCompletedArgs.cs new file mode 100755 index 0000000..8d8cd54 --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/InputCompletedArgs.cs @@ -0,0 +1,18 @@ +using System.Windows; + +namespace TelegramClient.Controls.StartView +{ + internal abstract class InputCompletedArgs : InputBaseArgs + { + protected InputCompletedArgs(UIElement source, Point origin) + : base(source, origin) + { + } + + public abstract Point TotalTranslation { get; } + + public abstract Point FinalLinearVelocity { get; } + + public abstract bool IsInertial { get; } + } +} diff --git a/TelegramClient.WP8/Controls/StartView/InputDeltaArgs.cs b/TelegramClient.WP8/Controls/StartView/InputDeltaArgs.cs new file mode 100755 index 0000000..798898e --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/InputDeltaArgs.cs @@ -0,0 +1,20 @@ +using System.Windows; + +namespace TelegramClient.Controls.StartView +{ + internal abstract class InputDeltaArgs : InputBaseArgs + { + protected InputDeltaArgs(UIElement source, Point origin) + : base(source, origin) + { + } + + public abstract Point DeltaTranslation { get; } + + public abstract Point CumulativeTranslation { get; } + + public abstract Point ExpansionVelocity { get; } + + public abstract Point LinearVelocity { get; } + } +} diff --git a/TelegramClient.WP8/Controls/StartView/ManipulationGestureHelper.cs b/TelegramClient.WP8/Controls/StartView/ManipulationGestureHelper.cs new file mode 100755 index 0000000..2aec859 --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/ManipulationGestureHelper.cs @@ -0,0 +1,125 @@ +using System.Windows; +using System.Windows.Input; + +namespace TelegramClient.Controls.StartView +{ + internal class ManipulationGestureHelper : GestureHelper + { + public ManipulationGestureHelper(UIElement target, bool shouldHandleAllDrags) + : base(target, shouldHandleAllDrags) + { + } + + protected override void HookEvents() + { + Target.ManipulationStarted += Target_ManipulationStarted; + Target.ManipulationDelta += Target_ManipulationDelta; + Target.ManipulationCompleted += Target_ManipulationCompleted; + } + + private void Target_ManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + NotifyDown(new ManipulationBaseArgs(e)); + } + + private void Target_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + NotifyMove(new ManipulationDeltaArgs(e)); + } + + private void Target_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + NotifyUp(new ManiulationCompletedArgs(e)); + } + + private class ManipulationBaseArgs : InputBaseArgs + { + public ManipulationBaseArgs(ManipulationStartedEventArgs args) + : base(args.ManipulationContainer, args.ManipulationOrigin) + { + } + } + + private class ManipulationDeltaArgs : InputDeltaArgs + { + private ManipulationDeltaEventArgs _args; + + public ManipulationDeltaArgs(ManipulationDeltaEventArgs args) + : base(args.ManipulationContainer, args.ManipulationOrigin) + { + _args = args; + } + + + public override Point DeltaTranslation + { + get + { + return _args.DeltaManipulation.Translation; + } + } + + public override Point CumulativeTranslation + { + get + { + return _args.CumulativeManipulation.Translation; + } + } + + public override Point ExpansionVelocity + { + get + { + return _args.Velocities.ExpansionVelocity; + } + } + + public override Point LinearVelocity + { + get + { + return _args.Velocities.LinearVelocity; + } + } + } + + private class ManiulationCompletedArgs : InputCompletedArgs + { + private ManipulationCompletedEventArgs _args; + + public ManiulationCompletedArgs(ManipulationCompletedEventArgs args) + : base(args.ManipulationContainer, args.ManipulationOrigin) + { + _args = args; + } + + public override Point TotalTranslation + { + get + { + return _args.TotalManipulation.Translation; + } + } + + public override Point FinalLinearVelocity + { + get + { + if (_args.FinalVelocities != null) + return _args.FinalVelocities.LinearVelocity; + else + return new Point(0, 0); + } + } + + public override bool IsInertial + { + get + { + return _args.IsInertial; + } + } + } + } +} diff --git a/TelegramClient.WP8/Controls/StartView/SafeRaise.cs b/TelegramClient.WP8/Controls/StartView/SafeRaise.cs new file mode 100755 index 0000000..2b03853 --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/SafeRaise.cs @@ -0,0 +1,93 @@ +// (c) Copyright Microsoft Corporation. +// This source is subject to the Microsoft Public License (Ms-PL). +// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. +// All other rights reserved. + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace TelegramClient.Controls.StartView +{ + /// + /// A helper class for raising events safely. + /// + internal static class SafeRaise + { + /// + /// Raises an event in a thread-safe manner, also does the null check. + /// + /// The event to raise. + /// The event sender. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")] + public static void Raise(EventHandler eventToRaise, object sender) + { + if (eventToRaise != null) + { + eventToRaise(sender, System.EventArgs.Empty); + } + } + + /// + /// Raises an event in a thread-safe manner, also does the null check. + /// + /// The event to raise. + /// The event sender. + public static void Raise(EventHandler eventToRaise, object sender) + { + Raise(eventToRaise, sender, System.EventArgs.Empty); + } + + /// + /// Raises an event in a thread-safe manner, also does the null check. + /// + /// The event args type. + /// The event to raise. + /// The event sender. + /// The event args. + public static void Raise(EventHandler eventToRaise, object sender, T args) where T : System.EventArgs + { + if (eventToRaise != null) + { + eventToRaise(sender, args); + } + } + + // Lazy event args creation example: + // + // public class MyEventArgs : EventArgs + // { + // public MyEventArgs(int x) { X = x; } + // public int X { get; set; } + // } + // + // event EventHandler Foo; + // + // public void Bar() + // { + // int y = 2; + // Raise(Foo, null, () => { return new MyEventArgs(y); }); + // } + + /// + /// This is a method that returns event args, used for lazy creation. + /// + /// The event type. + /// + public delegate T GetEventArgs() where T : System.EventArgs; + + /// + /// Raise an event in a thread-safe manner, with the required null check. Lazily creates event args. + /// + /// The event args type. + /// The event to raise. + /// The event sender. + /// The delegate to return the event args if needed. + public static void Raise(EventHandler eventToRaise, object sender, GetEventArgs getEventArgs) where T : System.EventArgs + { + if (eventToRaise != null) + { + eventToRaise(sender, getEventArgs()); + } + } + } +} diff --git a/TelegramClient.WP8/Controls/StartView/StartView.cs b/TelegramClient.WP8/Controls/StartView/StartView.cs new file mode 100755 index 0000000..629ea88 --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/StartView.cs @@ -0,0 +1,582 @@ +using System; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Animation; +using Microsoft.Phone.Controls.Primitives; + +namespace TelegramClient.Controls.StartView +{ + /// + /// Creates a panoramic view of items that can be panned side-to-side, similar to the Start screen. + /// + [TemplatePart(Name = PanningTransformName, Type = typeof(TranslateTransform))] + [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(StartViewItem))] + public class StartView : TemplatedItemsControl, ISupportInitialize + { + internal static readonly Duration Immediately = TimeSpan.Zero; + private static readonly Duration DefaultDuration = TimeSpan.FromMilliseconds(300); + private static readonly Duration FlickDuration = DefaultDuration; + private static readonly Duration SnapDuration = DefaultDuration; + private static readonly Duration PanDuration = TimeSpan.FromMilliseconds(300); + + private const string PanningTransformName = "PanningTransform"; + + private readonly IEasingFunction _easingFunction = new ExponentialEase { Exponent = 5 }; + + private int _cumulativeDragDelta; + private int _effectiveDragDelta; + private int _flickDirection; + private int _targetOffset; + private bool _dragged; + private bool _adjustSelectedRequested; + private bool _suppressSelectionChangedEvent; + private bool _loaded; + private TransformAnimator _animator; + private bool _suppressAnimation; + private bool _ignorePropertyChange; + private bool _isDesignTime; + private InitializingData _initializingData; + + /// + /// Initializes a new instance of the StartView class. + /// + public StartView() + { + DefaultStyleKey = typeof(StartView); + + GestureHelper gestureHelper = GestureHelper.Create(this, true); + gestureHelper.GestureStart += (sender, args) => GestureStart(); + gestureHelper.HorizontalDrag += (sender, args) => HorizontalDrag(args); + gestureHelper.Flick += (sender, args) => Flick(args); + gestureHelper.GestureEnd += (sender, args) => GestureEnd(); + + SizeChanged += OnSizeChanged; + + Loaded += OnLoaded; + Unloaded += OnUnloaded; + + _isDesignTime = DesignerProperties.IsInDesignTool; + } + + internal StartViewPanel Panel { get; set; } + + internal int ItemsWidth { get; set; } + + internal int ViewportWidth { get; private set; } + + internal int ViewportHeight { get; private set; } + + private TranslateTransform PanningTransform { get; set; } + + private int ActualOffset + { + get { return PanningTransform == null ? 0 : (int)PanningTransform.X; } + } + + private int SelectionOffset + { + get + { + StartViewItem container = GetContainer(SelectedItem); + if (container != null) + { + return -container.StartPosition; + } + return 0; + } + } + + private bool IsInit + { + get { return _initializingData != null; } + } + + /// + /// Identifies the SelectedItem dependency property. + /// + public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register( + "SelectedItem", + typeof(object), + typeof(StartView), + new PropertyMetadata(null, (d, e) => ((StartView)d).OnSelectedItemChanged(e))); + + /// + /// Gets the selected item. + /// + /// + /// + /// Returns . + /// + public object SelectedItem + { + get { return GetValue(SelectedItemProperty); } + set { SetValue(SelectedItemProperty, value); } + } + + /// + /// Identifies the SelectedIndex dependency property. + /// + public static readonly DependencyProperty SelectedIndexProperty = DependencyProperty.Register( + "SelectedIndex", + typeof(int), + typeof(StartView), + new PropertyMetadata(-1, (d, e) => ((StartView)d).OnSelectedIndexChanged(e))); + + /// + /// Gets the selected index. + /// + /// + /// + /// Returns . + /// + public int SelectedIndex + { + get { return (int)GetValue(SelectedIndexProperty); } + set { SetValue(SelectedIndexProperty, value); } + } + + /// + /// Event that is invoked when selection changes. + /// + public event EventHandler SelectionChanged; + + /// + /// Handles the application of a new Template. + /// + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + PanningTransform = GetTemplateChild(PanningTransformName) as TranslateTransform; + + _animator = PanningTransform != null ? new TransformAnimator(PanningTransform) : null; + } + + /// + /// Handles the measurement of the control. + /// + /// + /// + /// Desired size. + /// + /// Available size. + protected override Size MeasureOverride(Size availableSize) + { + if (Application.Current.Host.Content.ActualWidth > 0) + { + ViewportWidth = !double.IsInfinity(availableSize.Width) ? (int)availableSize.Width : (int)Application.Current.Host.Content.ActualWidth; + ViewportHeight = !double.IsInfinity(availableSize.Height) ? (int)availableSize.Height : (int)Application.Current.Host.Content.ActualHeight; + } + else + { + ViewportWidth = (int)Math.Min(availableSize.Width, 480); + ViewportHeight = (int)Math.Min(availableSize.Height, 800); + } + + base.MeasureOverride(new Size(double.PositiveInfinity, ViewportHeight)); + + if (double.IsInfinity(availableSize.Width)) + { + availableSize.Width = ViewportWidth; + } + + if (double.IsInfinity(availableSize.Height)) + { + availableSize.Height = ViewportHeight; + } + + return availableSize; + } + + /// + /// Handles the arrange pass for the control. + /// + /// + /// + /// Render size. + /// + /// Final size. + protected override Size ArrangeOverride(Size finalSize) + { + finalSize.Width = DesiredSize.Width; + base.ArrangeOverride(finalSize); + return finalSize; + } + + /// + /// When the items have changed, we need to adjust the selection. + /// + /// The changed item. + protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) + { + base.OnItemsChanged(e); + + if (!IsInit) + { + RequestAdjustSelection(); + } + } + + internal void RequestAdjustSelection() + { + if (_adjustSelectedRequested) + { + return; + } + + LayoutUpdated += LayoutUpdatedAdjustSelection; + _adjustSelectedRequested = true; + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + _loaded = true; + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + _loaded = false; + } + + private void LayoutUpdatedAdjustSelection(object sender, System.EventArgs e) + { + _adjustSelectedRequested = false; + LayoutUpdated -= LayoutUpdatedAdjustSelection; + AdjustSelection(); + } + + private void AdjustSelection() + { + if (_isDesignTime) + { + if (_loaded) + { + _targetOffset = 0; + GoTo(_targetOffset, Immediately); + } + } + else + { + object oldSelectedItem = SelectedItem; + object newSelectedItem = null; + + if (Panel != null && Panel.VisibleChildren.Count > 0) + { + if (oldSelectedItem == null) + { + newSelectedItem = GetItem(Panel.VisibleChildren[0]); + } + else + { + StartViewItem oldContainer = GetContainer(oldSelectedItem); + newSelectedItem = oldContainer == null || !Panel.VisibleChildren.Contains(oldContainer) ? GetItem(Panel.VisibleChildren[0]) : oldSelectedItem; + } + } + else + { + _targetOffset = 0; + GoTo(_targetOffset, Immediately); + } + + SetSelectionInternal(newSelectedItem); + + StartViewItem newContainer = GetContainer(newSelectedItem); + if (newContainer != null) + { + _targetOffset = -newContainer.StartPosition; + GoTo(_targetOffset, Immediately); + } + } + } + + private void GestureStart() + { + _targetOffset = ActualOffset; + _flickDirection = 0; + _cumulativeDragDelta = 0; + _effectiveDragDelta = 0; + _dragged = false; + } + + private void HorizontalDrag(DragEventArgs args) + { + if (_flickDirection == 0) + { + _cumulativeDragDelta = (int)args.CumulativeDistance.X; + _effectiveDragDelta += (int)args.DeltaDistance.X; + _targetOffset += (int)args.DeltaDistance.X; + if (Math.Abs(_cumulativeDragDelta) <= ViewportWidth) + { + if (_effectiveDragDelta > 0 && SelectedIndex == 0 || _effectiveDragDelta < 0 && SelectedIndex == Items.Count - 1) + { + _effectiveDragDelta = 0; + _targetOffset = ActualOffset; + return; + } + + _dragged = true; + GoTo(_targetOffset, PanDuration); + } + } + } + + private void Flick(FlickEventArgs e) + { + if (e.Angle == 180) + { + _flickDirection = -1; + } + else if (e.Angle == 0) + { + _flickDirection = 1; + } + } + + private void GestureEnd() + { + if (_flickDirection == 0) + { + if (_dragged) + { + int snapTo; + int newDirection; + StartViewItem newSelection; + + Panel.GetSnapOffset(_targetOffset, ViewportWidth, Math.Sign(_cumulativeDragDelta), out snapTo, out newDirection, out newSelection); + + object newSelectedItem = GetItem(newSelection); + if (newSelectedItem != null) + { + _suppressAnimation = true; + SelectedItem = newSelectedItem; + _suppressAnimation = false; + } + + GoTo(snapTo, SnapDuration); + } + } + else + { + ProcessFlick(); + } + } + + private void ProcessFlick() + { + if (_flickDirection != 0) + { + StartViewPanel.ItemStop previous; + StartViewPanel.ItemStop current; + StartViewPanel.ItemStop next; + + Panel.GetStops(SelectionOffset, ItemsWidth, out previous, out current, out next); + + if (previous == current && current == next && next == null) + { + return; + } + + if (_flickDirection < 0 && next == null || _flickDirection > 0 && previous == null) + { + if (current != null) + { + GoTo(-current.Position, Immediately); + } + + return; + } + + _targetOffset = _flickDirection < 0 ? -next.Position : -previous.Position; + + _suppressAnimation = true; + SelectedItem = GetItem(_flickDirection < 0 ? next.Item : previous.Item); + _suppressAnimation = false; + + GoTo(_targetOffset, FlickDuration); + } + } + + private void GoTo(int offset, Duration duration, Action completionAction) + { + if (_animator != null) + { + _animator.GoTo(offset, duration, _easingFunction, completionAction); + } + } + + private void GoTo(int offset) + { + GoTo(offset, null); + } + + private void GoTo(int offset, Action completionAction) + { + int delta = Math.Abs(ActualOffset - offset); + GoTo(offset, TimeSpan.FromMilliseconds(delta * 2), completionAction); + } + + private void GoTo(int offset, Duration duration) + { + GoTo(offset, duration, null); + } + + private void SetSelectionInternal(object selectedItem) + { + _suppressSelectionChangedEvent = true; + SelectedItem = selectedItem; + _suppressSelectionChangedEvent = false; + } + + private void OnSelectedItemChanged(DependencyPropertyChangedEventArgs args) + { + if (IsInit) + { + return; + } + + if (_ignorePropertyChange) + { + _ignorePropertyChange = false; + return; + } + + if (!_isDesignTime) + { + if (args.NewValue == null && Items.Count > 0) + { + _ignorePropertyChange = true; + SelectedItem = args.OldValue; + throw new ArgumentException("SelectedItem"); + } + else if (args.NewValue != null && !Items.Contains(args.NewValue)) + { + _ignorePropertyChange = true; + SelectedItem = args.OldValue; + return; + } + } + + SelectedIndex = Items.IndexOf(args.NewValue); + + if (_suppressSelectionChangedEvent) + { + return; + } + + SafeRaise.Raise(SelectionChanged, this, (() => + { + object[] unselected; + if (args.OldValue != null) + { + unselected = new object[1] { args.OldValue }; + } + else + { + unselected = new object[0]; + } + + object[] selected; + if (args.NewValue != null) + { + selected = new object[1] { args.NewValue }; + } + else + { + selected = new object[0]; + } + + return new SelectionChangedEventArgs(unselected, selected); + })); + + if (!_suppressAnimation) + { + GoTo(SelectionOffset, _loaded ? DefaultDuration : Immediately); + } + } + + [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] + private void OnSelectedIndexChanged(DependencyPropertyChangedEventArgs args) + { + if (IsInit) + { + return; + } + + if (_ignorePropertyChange) + { + _ignorePropertyChange = false; + return; + } + + int newSelectedIndex = (int)args.NewValue; + int itemsCount = Items.Count; + + if (newSelectedIndex >= 0 && newSelectedIndex < itemsCount) + { + SelectedItem = Items[newSelectedIndex]; + } + else if (newSelectedIndex == -1 && itemsCount == 0) + { + SelectedItem = null; + } + else if (!_isDesignTime) + { + _ignorePropertyChange = true; + SelectedIndex = (int)args.OldValue; + throw new ArgumentOutOfRangeException("SelectedIndex"); + } + } + + private void OnSizeChanged(object sender, SizeChangedEventArgs e) + { + ViewportWidth = (int)e.NewSize.Width; + ViewportHeight = (int)e.NewSize.Height; + ItemsWidth = (int)Panel.ActualWidth; + } + + void ISupportInitialize.BeginInit() + { + _initializingData = new InitializingData + { + InitialItem = SelectedItem, + InitialIndex = SelectedIndex + }; + } + + void ISupportInitialize.EndInit() + { + if (_initializingData == null) + { + throw new InvalidOperationException(); + } + + int selectedIndex = SelectedIndex; + object selectedItem = SelectedItem; + + if (_initializingData.InitialIndex != selectedIndex) + { + SelectedIndex = _initializingData.InitialIndex; + _initializingData = null; + SelectedIndex = selectedIndex; + } + else if (!ReferenceEquals(_initializingData.InitialItem, selectedItem)) + { + SelectedItem = _initializingData.InitialItem; + _initializingData = null; + SelectedItem = selectedItem; + } + + _initializingData = null; + } + + private class InitializingData + { + public int InitialIndex; + public object InitialItem; + } + } +} diff --git a/TelegramClient.WP8/Controls/StartView/StartViewItem.cs b/TelegramClient.WP8/Controls/StartView/StartViewItem.cs new file mode 100755 index 0000000..3e5a0ad --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/StartViewItem.cs @@ -0,0 +1,22 @@ +using System.Windows.Controls; + +namespace TelegramClient.Controls.StartView +{ + /// + /// Represents an item in a StartView control. + /// + public class StartViewItem : ContentControl + { + /// + /// Initializes a new instance of the StartViewItem class. + /// + public StartViewItem() + { + DefaultStyleKey = typeof(StartViewItem); + } + + internal int StartPosition { get; set; } + + internal int ItemWidth { get; set; } + } +} \ No newline at end of file diff --git a/TelegramClient.WP8/Controls/StartView/StartViewPanel.cs b/TelegramClient.WP8/Controls/StartView/StartViewPanel.cs new file mode 100755 index 0000000..2a5310d --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/StartViewPanel.cs @@ -0,0 +1,371 @@ +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +namespace TelegramClient.Controls.StartView +{ + /// + /// Implements a custom Panel for the StartView control. + /// + public class StartViewPanel : Panel + { + private const int SnapThresholdDivisor = 2; + + private readonly List _visibleChildren = new List(); + private readonly List _itemStops = new List(); + private StartView _owner; + private StartViewItem _selectedItem; + + internal IList VisibleChildren + { + get { return _visibleChildren; } + } + + private StartView Owner + { + get { return _owner; } + set + { + if (_owner != value) + { + if (_owner != null) + { + _owner.Panel = null; + } + + _owner = value; + + if (_owner != null) + { + _owner.Panel = this; + } + } + } + } + + /// + /// Initializes a new instance of the StartViewPanel class. + /// + public StartViewPanel() + { + SizeChanged += OnSizeChanged; + Unloaded += OnUnloaded; + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + _owner = null; + } + + private void OnSizeChanged(object sender, SizeChangedEventArgs e) + { + Owner.ItemsWidth = (int)e.NewSize.Width; + } + + /// + /// Handles the measure pass for the control. + /// + /// + /// + /// Desired size. + /// + /// Available size. + protected override Size MeasureOverride(Size availableSize) + { + if (_owner == null) + { + FindOwner(); + } + + Size desiredSize = new Size(0, availableSize.Height); + + int childWidth = Owner.ViewportWidth; + int childHeight = (int)Math.Min(availableSize.Height, Owner.ViewportHeight); + Size childSize = new Size(childWidth, childHeight); + + _visibleChildren.Clear(); + + foreach (StartViewItem child in Children) + { + if (child.Visibility == Visibility.Visible) + { + _visibleChildren.Add(child); + child.Measure(childSize); + desiredSize.Width += childWidth; + } + } + + return desiredSize; + } + + /// + /// Handles the arrange pass for the control. + /// + /// + /// + /// Render size. + /// + /// Final size. + protected override Size ArrangeOverride(Size finalSize) + { + _itemStops.Clear(); + double x = 0; + Rect finalRect = new Rect(0, 0, 0, finalSize.Height); + + for (int index = 0; index < _visibleChildren.Count; ++index) + { + StartViewItem child = _visibleChildren[index]; + finalRect.X = child.StartPosition = (int)x; + _itemStops.Add(new ItemStop(child, child.StartPosition)); + finalRect.Width = Owner.ViewportWidth; + child.ItemWidth = (int)finalRect.Width; + child.Arrange(finalRect); + x += finalRect.Width; + } + + Owner.RequestAdjustSelection(); + + return finalSize; + } + + private void GetItemsInView(int offset, int viewportWidth, out int leftIndex, out int leftInView, out int centerIndex, out int rightIndex, out int rightInView) + { + leftIndex = leftInView = centerIndex = rightIndex = rightInView = -1; + + int count = VisibleChildren.Count; + if (count == 0) + { + return; + } + + for (int index = 0; index < count; ++index) + { + StartViewItem child = _visibleChildren[index]; + + int leftOffset = child.StartPosition + offset; + int rightOffset = leftOffset + child.ItemWidth - 1; + + if (leftOffset <= 0 && rightOffset >= 0) + { + leftIndex = index; + leftInView = Math.Min(viewportWidth, child.ItemWidth + leftOffset); + } + + if (leftOffset < viewportWidth && rightOffset >= viewportWidth) + { + rightIndex = index; + rightInView = Math.Min(viewportWidth, viewportWidth - leftOffset); + } + + if (leftOffset > 0 && rightOffset < viewportWidth) + { + centerIndex = index; + } + + if (index == 0 && leftInView == -1) + { + leftInView = leftOffset; + } + + if (index == count - 1 && rightInView == -1) + { + rightInView = viewportWidth - rightOffset - 1; + } + } + } + + internal void GetStops(int offset, int totalWidth, out ItemStop previous, out ItemStop current, out ItemStop next) + { + next = current = previous = null; + + if (VisibleChildren.Count == 0) + { + return; + } + + int nextIndex = -1; + int currentIndex = -1; + int previousIndex = -1; + + int position = -offset % totalWidth; + int itemStopIndex = 0; + + foreach (ItemStop itemStop in _itemStops) + { + if (itemStop.Position < position) + { + previousIndex = itemStopIndex; + } + else if (itemStop.Position > position) + { + nextIndex = itemStopIndex; + break; + } + else if (itemStop.Position == position) + { + currentIndex = itemStopIndex; + } + + ++itemStopIndex; + } + + if (previousIndex != -1) + { + previous = _itemStops[previousIndex]; + } + + if (currentIndex != -1) + { + current = _itemStops[currentIndex]; + } + + if (nextIndex != -1) + { + next = _itemStops[nextIndex]; + } + } + + internal void GetSnapOffset(int offset, int viewportWidth, int direction, out int snapTo, out int newDirection, out StartViewItem newSelection) + { + int snapThreshold = viewportWidth / SnapThresholdDivisor; + + snapTo = offset; + newDirection = direction; + newSelection = _selectedItem; + + if (VisibleChildren.Count == 0) + { + return; + } + + foreach (ItemStop itemStop in _itemStops) + { + if (itemStop.Position == -offset) + { + newSelection = itemStop.Item; + return; + } + } + + int leftIndex; + int leftInView; + int centerIndex; + int rightIndex; + int rightInView; + + GetItemsInView(offset, viewportWidth, out leftIndex, out leftInView, out centerIndex, out rightIndex, out rightInView); + + if (leftIndex == rightIndex && leftIndex != -1) + { + newSelection = _selectedItem = _visibleChildren[leftIndex]; + } + else + { + if (leftIndex == -1) + { + leftIndex = _visibleChildren.Count - 1; + } + + if (rightIndex == -1) + { + rightIndex = 0; + } + + int index; + if (direction < 0) + { + if (rightInView > snapThreshold) + { + index = GetBestIndex(centerIndex, rightIndex, leftIndex); + newDirection = -1; + } + else + { + index = GetBestIndex(leftIndex, centerIndex, rightIndex); + newDirection = 1; + } + } + else if (direction > 0) + { + if (leftInView > snapThreshold) + { + index = StartViewPanel.GetBestIndex(leftIndex, centerIndex, rightIndex); + newDirection = 1; + } + else + { + index = StartViewPanel.GetBestIndex(centerIndex, rightIndex, leftIndex); + newDirection = -1; + } + } + else if (centerIndex != -1) + { + index = centerIndex; + newDirection = -1; + } + else if (leftInView > rightInView) + { + index = leftIndex; + newDirection = -1; + } + else + { + index = rightIndex; + newDirection = 1; + } + + _selectedItem = _visibleChildren[index]; + snapTo = -_selectedItem.StartPosition; + newSelection = _selectedItem; + } + } + + private static int GetBestIndex(int n0, int n1, int n2) + { + if (n0 >= 0) + { + return n0; + } + + if (n1 >= 0) + { + return n1; + } + + if (n2 >= 0) + { + return n2; + } + + throw new InvalidOperationException("No best index."); + } + + private void FindOwner() + { + FrameworkElement frameworkElement = this; + StartView owner; + do + { + frameworkElement = (FrameworkElement)VisualTreeHelper.GetParent(frameworkElement); + owner = frameworkElement as StartView; + } + while (frameworkElement != null && owner == null); + Owner = owner; + } + + internal class ItemStop + { + public ItemStop(StartViewItem item, int position) + { + Item = item; + Position = position; + } + + public int Position { get; private set; } + + public StartViewItem Item { get; private set; } + } + } +} diff --git a/TelegramClient.WP8/Controls/StartView/TransformAnimator.cs b/TelegramClient.WP8/Controls/StartView/TransformAnimator.cs new file mode 100755 index 0000000..8f2e3af --- /dev/null +++ b/TelegramClient.WP8/Controls/StartView/TransformAnimator.cs @@ -0,0 +1,219 @@ +// (c) Copyright Microsoft Corporation. +// This source is subject to the Microsoft Public License (Ms-PL). +// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. +// All other rights reserved. + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Windows; +using System.Windows.Media; +using System.Windows.Media.Animation; + +namespace TelegramClient.Controls.StartView +{ + /// + /// A utility for animating a horizontal translation value. + /// + internal sealed class TransformAnimator + { + /// + /// Single static instance of a PropertyPath with string path "X". + /// + private static readonly PropertyPath TranslateXPropertyPath = new PropertyPath("X"); + + /// + /// The Storyboard instance for the animation. + /// + private readonly Storyboard _sbRunning = new Storyboard(); + + /// + /// The DoubleAnimation instance for a running animation. + /// + private readonly DoubleAnimation _daRunning = new DoubleAnimation(); + + /// + /// The target translate transform instance. + /// + private TranslateTransform _transform; + + /// + /// A one-time action for the current GoTo statement only. Cleared if + /// GoTo is called before the action runs. + /// + private Action _oneTimeAction; + + /// + /// Initializes a new instance of the TransformAnimator class. + /// + /// TranslateTransform instance. + public TransformAnimator(TranslateTransform translateTransform) + { + Debug.Assert(translateTransform != null); + _transform = translateTransform; + + _sbRunning.Completed += OnCompleted; + _sbRunning.Children.Add(_daRunning); + Storyboard.SetTarget(_daRunning, _transform); + Storyboard.SetTargetProperty(_daRunning, TranslateXPropertyPath); + } + + /// + /// Gets the current offset value from the translate transform object. + /// + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public double CurrentOffset + { + get { return _transform.X; } + } + + /// + /// Targets a new horizontal offset over a specified duration. + /// + /// The target offset value. + /// The duration for the animation. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public void GoTo(double targetOffset, Duration duration) + { + GoTo(targetOffset, duration, null, null); + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public void GoTo(double targetOffset, Duration duration, Action completionAction) + { + GoTo(targetOffset, duration, null, completionAction); + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public void GoTo(double targetOffset, Duration duration, IEasingFunction easingFunction) + { + GoTo(targetOffset, duration, easingFunction, null); + } + + public void GoTo(double targetOffset, Duration duration, IEasingFunction easingFunction, Action completionAction) + { + _daRunning.To = targetOffset; + _daRunning.Duration = duration; + _daRunning.EasingFunction = easingFunction; + _sbRunning.Begin(); + _sbRunning.SeekAlignedToLastTick(TimeSpan.Zero); + _oneTimeAction = completionAction; + } + + /// + /// Updates the easing function of the double animation. + /// + /// The easing funciton, if any, to use. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")] + public void UpdateEasingFunction(IEasingFunction ease) + { + if (_daRunning != null && _daRunning.EasingFunction != ease) + { + _daRunning.EasingFunction = ease; + } + } + + /// + /// Immediately updates the duration of the running double animation. + /// + /// The new duration value to use. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public void UpdateDuration(Duration duration) + { + if (_daRunning != null) + { + _daRunning.Duration = duration; + } + } + + /// + /// Handles animation completed + /// + /// Event source. + /// Event arguments. + private void OnCompleted(object sender, System.EventArgs e) + { + // Make sure the action is called when the animation is Stopped + // The complete event is triggered when it changes to Filling + // This is also called before the state has been changed so the state + // is still Active when switching to Filling + Action action = _oneTimeAction; + if (action != null && _sbRunning.GetCurrentState() != ClockState.Active) + { + _oneTimeAction = null; + action(); + } + } + + /// + /// Ensures and creates if needed the animator for an element. Will also + /// verify that a translate transform is present. + /// + /// The target element. + /// The animator reference. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public static void EnsureAnimator(FrameworkElement targetElement, ref TransformAnimator animator) + { + if (animator == null) + { + TranslateTransform transform = TransformAnimator.GetTranslateTransform(targetElement); + if (transform != null) + { + animator = new TransformAnimator(transform); + } + } + if (animator == null) + { + throw new InvalidOperationException("The animation system could not be prepared for the target element."); + } + } + + /// + /// Find a translate transform for the container or create one. + /// + /// The container. + /// Returns the TranslateTransform reference. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public static TranslateTransform GetTranslateTransform(UIElement container) + { + if (container == null) + { + throw new ArgumentNullException("container"); + } + + TranslateTransform transform = container.RenderTransform as TranslateTransform; + if (transform == null) + { + if (container.RenderTransform == null) + { + transform = new TranslateTransform(); + container.RenderTransform = transform; + } + else if (container.RenderTransform is TransformGroup) + { + TransformGroup g = container.RenderTransform as TransformGroup; + transform = (from t in g.Children + where t is TranslateTransform + select (TranslateTransform)t).FirstOrDefault(); + if (transform == null) + { + transform = new TranslateTransform(); + g.Children.Add(transform); + } + } + else + { + TransformGroup tg = new TransformGroup(); + var existing = container.RenderTransform; + container.RenderTransform = null; + tg.Children.Add(existing); + transform = new TranslateTransform(); + tg.Children.Add(transform); + container.RenderTransform = tg; + } + } + return transform; + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP8/FlipCycleTileMedium336.png b/TelegramClient.WP8/FlipCycleTileMedium336.png new file mode 100755 index 0000000..334fed6 Binary files /dev/null and b/TelegramClient.WP8/FlipCycleTileMedium336.png differ diff --git a/TelegramClient.WP8/FlipCycleTileSmall159.png b/TelegramClient.WP8/FlipCycleTileSmall159.png new file mode 100755 index 0000000..23afb2a Binary files /dev/null and b/TelegramClient.WP8/FlipCycleTileSmall159.png differ diff --git a/TelegramClient.WP8/IconicSmall110.png b/TelegramClient.WP8/IconicSmall110.png new file mode 100755 index 0000000..4479e8c Binary files /dev/null and b/TelegramClient.WP8/IconicSmall110.png differ diff --git a/TelegramClient.WP8/IconicTileMedium159.png b/TelegramClient.WP8/IconicTileMedium159.png new file mode 100755 index 0000000..ab4c8c6 Binary files /dev/null and b/TelegramClient.WP8/IconicTileMedium159.png differ diff --git a/TelegramClient.WP8/IconicTileMedium202.png b/TelegramClient.WP8/IconicTileMedium202.png new file mode 100755 index 0000000..e88da7e Binary files /dev/null and b/TelegramClient.WP8/IconicTileMedium202.png differ diff --git a/TelegramClient.WP8/Images/Audio/microphone.dark.png b/TelegramClient.WP8/Images/Audio/microphone.dark.png new file mode 100755 index 0000000..de5605e Binary files /dev/null and b/TelegramClient.WP8/Images/Audio/microphone.dark.png differ diff --git a/TelegramClient.WP8/Images/Audio/microphone.light.png b/TelegramClient.WP8/Images/Audio/microphone.light.png new file mode 100755 index 0000000..1ecea23 Binary files /dev/null and b/TelegramClient.WP8/Images/Audio/microphone.light.png differ diff --git a/TelegramClient.WP8/LongListSelectorEx.cs b/TelegramClient.WP8/LongListSelectorEx.cs new file mode 100755 index 0000000..11c4c46 --- /dev/null +++ b/TelegramClient.WP8/LongListSelectorEx.cs @@ -0,0 +1,459 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Media; +using System.Windows.Media.Animation; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Telegram.Api.TL; +using Telegram.Controls.Extensions; + +namespace TelegramClient +{ + public class LongListSelectorEx : LongListSelector + { + public static readonly DependencyProperty IsSelectionEnabledProperty = DependencyProperty.Register( + "IsSelectionEnabled", typeof (bool), typeof (LongListSelectorEx), new PropertyMetadata(OnIsSelectionEnabledChanged)); + + private static void OnIsSelectionEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var lls = (LongListSelectorEx) d; + + var projection = lls.Projection as PlaneProjection; + var upDown = projection != null && projection.RotationZ == 180.0; + var x = upDown ? -48.0 : 48.0; + + var viewport = lls.Viewport; + if ((bool)e.NewValue) + { + var storyboard = new Storyboard(); + if (!(viewport.RenderTransform is CompositeTransform)) + { + viewport.RenderTransform = new CompositeTransform(); + } + + if (viewport.CacheMode == null) + { + viewport.CacheMode = new BitmapCache(); + } + + var translateXAnimation = new DoubleAnimationUsingKeyFrames(); + translateXAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 0.0 }); + translateXAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.55), Value = x, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 5.0 } }); + Storyboard.SetTarget(translateXAnimation, viewport); + Storyboard.SetTargetProperty(translateXAnimation, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateX)")); + storyboard.Children.Add(translateXAnimation); + + //storyboard.Begin(); + Deployment.Current.Dispatcher.BeginInvoke(storyboard.Begin); + } + else + { + var storyboard = new Storyboard(); + if (!(viewport.RenderTransform is CompositeTransform)) + { + viewport.RenderTransform = new CompositeTransform(); + } + + var translateXAnimation = new DoubleAnimationUsingKeyFrames(); + translateXAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = x }); + translateXAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.55), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 5.0 } }); + Storyboard.SetTarget(translateXAnimation, viewport); + Storyboard.SetTargetProperty(translateXAnimation, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateX)")); + storyboard.Children.Add(translateXAnimation); + + //storyboard.Begin(); + Deployment.Current.Dispatcher.BeginInvoke(() => storyboard.Begin()); + } + } + + public bool IsSelectionEnabled + { + get { return (bool) GetValue(IsSelectionEnabledProperty); } + set { SetValue(IsSelectionEnabledProperty, value); } + } + + public static readonly DependencyProperty IsFirstSliceLoadedProperty = DependencyProperty.Register( + "IsFirstSliceLoaded", typeof(bool), typeof(LongListSelectorEx), new PropertyMetadata(true)); + + public bool IsFirstSliceLoaded + { + get { return (bool)GetValue(IsFirstSliceLoadedProperty); } + set { SetValue(IsFirstSliceLoadedProperty, value); } + } + + public int MeasureOverrideCount { get; set; } + + protected override Size MeasureOverride(Size availableSize) + { + try + { + //System.Diagnostics.Debug.WriteLine("LLS MeasureOverride " + MeasureOverrideCount); + MeasureOverrideCount++; + return base.MeasureOverride(availableSize); + } + catch (Exception e) + { + //System.Diagnostics.Debug.WriteLine("LLS MeasureOverride catch " + MeasureOverrideCount); + +#if DEBUG + MessageBox.Show("LongListSelectorEx.MeasureOverride ex " + e); +#endif + + return base.MeasureOverride(availableSize); + } + } + + private int _knob = 1; + + public int Knob + { + get { return _knob; } + set { _knob = value; } + } + + public ScrollBar VerticalScrollBar { get; protected set; } + + public ViewportControl Viewport { get; protected set; } + + public LongListSelectorEx() + { + ItemRealized += OnItemRealized; + } + + public override void OnApplyTemplate() + { + Viewport = (ViewportControl)GetTemplateChild("ViewportControl"); + + + + Viewport.ViewportChanged += OnViewportChanged; + Viewport.ManipulationStateChanged += OnManipulationStateChanged; + + base.OnApplyTemplate(); + } + + public static T GetChildOfType(DependencyObject depObj) where T : DependencyObject + { + if (depObj == null) return null; + + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) + { + var child = VisualTreeHelper.GetChild(depObj, i); + + var result = (child as T) ?? GetChildOfType(child); + if (result != null) return result; + } + return null; + } + + public static IEnumerable GetChildrenOfType(DependencyObject depObj) where T : DependencyObject + { + if (depObj == null) yield break; + + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) + { + var child = VisualTreeHelper.GetChild(depObj, i) as T; + + if (child != null) yield return child; + } + } + + private void OnManipulationStateChanged(object sender, ManipulationStateChangedEventArgs e) + { + + } + + private double _fromBegin; + + private void OnViewportChanged(object sender, ViewportChangedEventArgs e) + { + if (Viewport.Bounds.Y - Viewport.Viewport.Y == 0.0) + { + RaiseBegin(); + } + + var fromBegin = Viewport.Viewport.Y - Viewport.Bounds.Y; + if (fromBegin >= 500.0 && _fromBegin < 500.0) + { + System.Diagnostics.Debug.WriteLine("RaiseShowScrollButton"); + RaiseShowScrollButton(); + } + _fromBegin = fromBegin; + + if ((Viewport.Bounds.Height + Viewport.Bounds.Y) >= ActualHeight + && (Viewport.Bounds.Height + Viewport.Bounds.Y) == (Viewport.Viewport.Height + Viewport.Viewport.Y)) + { + //Telegram.Api.Helpers.Execute.ShowDebugMessage("CloseToEnd ActualHeight=" + ActualHeight + " Height+Y=" + (Viewport.Bounds.Height + Viewport.Bounds.Y)); + RaiseCloseToEnd(); + } + + RaiseViewportChanged(e); + //System.Diagnostics.Debug.WriteLine("bounds={0} viewport={1}", Viewport.Bounds, Viewport.Viewport); + } + + public bool IsHoldingScrollingPosition + { + get { return ListHeader != null; } + } + + public void HoldScrollingPosition() + { + ListHeader = null; + } + + public void UnholdScrollingPosition() + { + ListHeader = new Border { Visibility = Visibility.Collapsed }; + } + + public void ScrollToItem(object item) + { + if (ItemsSource.Count > 0 && ItemsSource[0] == item) + { + if (ItemsSource[0] == item && Viewport.Bounds.Y == Viewport.Viewport.Y) + { + //MessageBox.Show("ScrollToBottom optimization"); + return; + } + } + + ScrollTo(item); + } + + public event EventHandler ViewportChanged; + + protected virtual void RaiseViewportChanged(ViewportChangedEventArgs e) + { + var handler = ViewportChanged; + if (handler != null) handler(this, e); + } + + public event EventHandler ShowScrollButton; + + protected virtual void RaiseShowScrollButton() + { + var handler = ShowScrollButton; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler CloseToEnd; + + protected virtual void RaiseCloseToEnd() + { + var handler = CloseToEnd; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler CloseToBegin; + + protected virtual void RaiseCloseToBegin() + { + var handler = CloseToBegin; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler Begin; + + protected virtual void RaiseBegin() + { + var handler = Begin; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + + public static readonly DependencyProperty DownButtonVisibilityProperty = DependencyProperty.Register( + "DownButtonVisibility", typeof(Visibility), typeof(LongListSelectorEx), new PropertyMetadata(Visibility.Collapsed)); + + public Visibility DownButtonVisibility + { + get { return (Visibility)GetValue(DownButtonVisibilityProperty); } + set { SetValue(DownButtonVisibilityProperty, value); } + } + + public static readonly DependencyProperty PrevIndexProperty = DependencyProperty.Register( + "PrevIndex", typeof(int), typeof(LongListSelectorEx), new PropertyMetadata(default(int))); + + public int PrevIndex + { + get { return (int)GetValue(PrevIndexProperty); } + set { SetValue(PrevIndexProperty, value); } + } + + public static readonly DependencyProperty IndexProperty = DependencyProperty.Register( + "Index", typeof(int), typeof(LongListSelectorEx), new PropertyMetadata(default(int))); + + private Canvas _canvas; + + public int Index + { + get { return (int)GetValue(IndexProperty); } + set { SetValue(IndexProperty, value); } + } + + private bool _check; + + private void OnItemRealized(object sender, ItemRealizationEventArgs e) + { + if (_check) + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("OnItemRealized " + InView(e.Container)); + } + //MessageBox.Show("ItemRealized"); + //OnViewportChanged(sender, new ViewportChangedEventArgs()); + + var longListSelector = this; + + var item = e.Container.Content; + + + var items = longListSelector.ItemsSource; + var index = items.IndexOf(item); + + //if (items.Count >= Knob + // && e.Container.Content.Equals(longListSelector.ItemsSource[longListSelector.ItemsSource.Count - Knob])) + //{ + // InvokeActions(null); + //} + if (index > 20 + && IsFirstSliceLoaded + && PrevIndex > index) + { + DownButtonVisibility = Visibility.Visible; + } + else + { + DownButtonVisibility = Visibility.Collapsed; + //_prevIndex = 0; + } + + PrevIndex = index; + + if (items.Count - index <= Knob) + { + if (ManipulationState != ManipulationState.Idle) + { + RaiseCloseToEnd(); + return; + } + } + + if (index <= Knob) + { + if (ManipulationState != ManipulationState.Idle) + { + RaiseCloseToBegin(); + return; + } + } + + if (LayoutMode == LongListSelectorLayoutMode.List) + { + var message = e.Container.Content as TLMessageBase; + if (message == null) return; + + if (!message._isAnimated) + { + e.Container.Opacity = 1.0; + return; + } + + message._isAnimated = false; + + if (Visibility == Visibility.Collapsed) return; + + e.Container.Opacity = 0.0; + + if (e.Container.Tag != null && (bool) e.Container.Tag) + { + StartLoadingAnimation(e.Container); + return; + } + e.Container.Loaded += OnContainerLoaded; + e.Container.Unloaded += OnContainerUnloaded; + } + } + + private void OnContainerUnloaded(object sender, RoutedEventArgs e) + { + var container = (ContentPresenter)sender; + container.Tag = false; + container.Unloaded -= OnContainerUnloaded; + } + + private void OnContainerLoaded(object sender, RoutedEventArgs e) + { + var container = (ContentPresenter)sender; + container.Tag = true; + container.Loaded -= OnContainerLoaded; + + StartLoadingAnimation(container); + } + + private void StartLoadingAnimation(ContentPresenter container) + { + var message = container.Content as TLMessageBase; + if (message!= null + && message.Index == 160952) + { + TLUtils.WriteLine("startAnimation", LogSeverity.Error); + } + + container.CacheMode = new BitmapCache(); + var storyboard = new Storyboard(); + var opacityAnimation = new DoubleAnimation { To = 1.0, Duration = TimeSpan.FromSeconds(1.0) }; + Storyboard.SetTarget(opacityAnimation, container); + Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(opacityAnimation); + + Deployment.Current.Dispatcher.BeginInvoke(storyboard.Begin); + } + + public IList GetItemsInView() + { + if (_canvas == null) + { + var contentPresenter = GetChildOfType(Viewport); + var canvas = GetChildOfType(contentPresenter); + _canvas = GetChildOfType(canvas); + } + + var items = new List(); + foreach (var item in GetChildrenOfType(_canvas)) + { + if (InView(item))items.Add(item); + //var itemViewModel = item.DataContext as ItemViewModel; + //if (itemViewModel != null) + //{ + // itemViewModel.IsSelected = isSelected; + //} + //Debug.WriteLine(Canvas.GetTop(item) + " " + item.ActualHeight + " " + item.DataContext); + } + + return items; + } + + private bool InView(ContentPresenter item) + { + var height = Viewport.Viewport.Height < ActualHeight ? ActualHeight : Viewport.Viewport.Height; + var top = Canvas.GetTop(item); + if (top >= (Viewport.Viewport.Y - item.ActualHeight / 3.0 * 2.0) && (top + item.ActualHeight <= Viewport.Viewport.Y + height + item.ActualHeight / 3.0 * 2.0)) + { + return true; + } + + return false; + } + } +} diff --git a/TelegramClient.WP8/Properties/AppManifest.xml b/TelegramClient.WP8/Properties/AppManifest.xml new file mode 100755 index 0000000..a955232 --- /dev/null +++ b/TelegramClient.WP8/Properties/AppManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/TelegramClient.WP8/Properties/AssemblyInfo.cs b/TelegramClient.WP8/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..89f4f48 --- /dev/null +++ b/TelegramClient.WP8/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("TelegramClient.WP8")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TelegramClient.WP8")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[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("71105f98-f9d4-469f-a185-640c6024c9a0")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en")] diff --git a/TelegramClient.WP8/Properties/WMAppManifest.Private.xml b/TelegramClient.WP8/Properties/WMAppManifest.Private.xml new file mode 100755 index 0000000..57edee3 --- /dev/null +++ b/TelegramClient.WP8/Properties/WMAppManifest.Private.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + ApplicationIcon210.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + IconicSmall110.png + 0 + IconicTileMedium202.png + Telegram + + + true + + + + Images\LockScreen\Lockscreen.png + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/Properties/WMAppManifest.Public.xml b/TelegramClient.WP8/Properties/WMAppManifest.Public.xml new file mode 100755 index 0000000..d9d8fac --- /dev/null +++ b/TelegramClient.WP8/Properties/WMAppManifest.Public.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + ApplicationIcon210.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + IconicSmall110.png + 0 + IconicTileMedium202.png + Telegram + + + true + + + + Images\LockScreen\Lockscreen.png + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/Properties/WMAppManifest.xml b/TelegramClient.WP8/Properties/WMAppManifest.xml new file mode 100755 index 0000000..d9d8fac --- /dev/null +++ b/TelegramClient.WP8/Properties/WMAppManifest.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + ApplicationIcon210.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + IconicSmall110.png + 0 + IconicTileMedium202.png + Telegram + + + true + + + + Images\LockScreen\Lockscreen.png + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/TelegramClient.WP8.csproj b/TelegramClient.WP8/TelegramClient.WP8.csproj new file mode 100755 index 0000000..8bd03e6 --- /dev/null +++ b/TelegramClient.WP8/TelegramClient.WP8.csproj @@ -0,0 +1,6739 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {DD748D4D-D311-4DD5-878E-AC3B400DCE2E} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TelegramClient + TelegramClient.WP8 + v8.0 + + + + + WindowsPhone + true + ru%3bde%3bes%3bpt%3bnl%3bit + true + true + Telegram_1.11.0.0_wp8.xap + Properties\AppManifest.xml + TelegramClient.App + true + true + ..\ + true + 11.0 + + + true + full + false + Bin\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8; + true + true + prompt + 4 + false + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8; + true + true + prompt + 4 + false + + + true + Bin\x86\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8;SECRET_CHAT_17 + true + full + + + prompt + MinimumRecommendedRules.ruleset + false + + + Bin\x86\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8;SECRET_CHAT_17 + true + true + pdbonly + + + prompt + MinimumRecommendedRules.ruleset + + + true + Bin\ARM\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8;LOG_REGISTRATION + true + full + + + prompt + MinimumRecommendedRules.ruleset + false + + + Bin\ARM\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8;LOG_REGISTRATION;LAYER_26 + true + true + pdbonly + + + prompt + MinimumRecommendedRules.ruleset + + + true + bin\Debug Private Beta\ + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8;PRIVATE_BETA; + true + full + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + true + bin\x86\Debug Private Beta\ + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8;PRIVATE_BETA; + true + full + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + true + bin\ARM\Debug Private Beta\ + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8;PRIVATE_BETA; + true + full + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + bin\Release Private Beta\ + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8;PRIVATE_BETA; + true + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release Private Beta\ + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8;PRIVATE_BETA; + true + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + bin\ARM\Release Private Beta\ + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8;PRIVATE_BETA;LOG_REGISTRATION; + true + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + ..\Libraries\BugSense.dll + + + ..\packages\Caliburn.Micro.1.5.2\lib\wp71\Caliburn.Micro.dll + + + ..\packages\Caliburn.Micro.1.5.2\lib\wp71\Caliburn.Micro.Extensions.dll + + + ..\packages\Coding4Fun.Toolkit.Controls.2.0.7\lib\wp71\Coding4Fun.Toolkit.Controls.dll + + + ..\Libraries\Google.WebAnalytics.dll + + + ..\packages\ImageTools.0.3.1\lib\sl3-wp\ICSharpCode.SharpZLib.Phone.dll + + + ..\packages\ID3.0.3.0\lib\sl4-wp71\Id3.dll + + + ..\packages\ImageTools.0.3.1\lib\sl3-wp\ImageTools.dll + + + ..\packages\ImageTools.0.3.1\lib\sl3-wp\ImageTools.Controls.dll + + + ..\packages\ImageTools.0.3.1\lib\sl3-wp\ImageTools.Filtering.dll + + + ..\packages\ImageTools.0.3.1\lib\sl3-wp\ImageTools.IO.Bmp.dll + + + ..\packages\ImageTools.0.3.1\lib\sl3-wp\ImageTools.IO.Gif.dll + + + ..\packages\ImageTools.0.3.1\lib\sl3-wp\ImageTools.IO.Png.dll + + + ..\packages\ImageTools.0.3.1\lib\sl3-wp\ImageTools.Utils.dll + + + False + ..\Libraries\LayoutTransformer.dll + + + ..\packages\libphonenumber-csharp-portable.1.0.0.2\lib\libphonenumber-csharp-portable.dll + + + + + + False + ..\packages\WPtoolkit.4.2013.08.16\lib\wp8\Microsoft.Phone.Controls.Toolkit.dll + + + ..\Libraries\Microsoft.SilverlightMediaFramework.Compatibility.Phone.dll + + + ..\Libraries\Microsoft.WebAnalytics.dll + + + ..\Libraries\Microsoft.WebAnalytics.Behaviors.dll + + + ..\packages\ImageTools.0.3.1\lib\sl3-wp\PhoneCodeContractsAssemblies.dll + + + ..\packages\Rx-Core.2.2.2\lib\windowsphone71\System.Reactive.Core.dll + + + ..\packages\Rx-Interfaces.2.2.2\lib\windowsphone71\System.Reactive.Interfaces.dll + + + ..\packages\Rx-Linq.2.2.2\lib\windowsphone71\System.Reactive.Linq.dll + + + ..\packages\Rx-PlatformServices.2.2.3\lib\windowsphone71\System.Reactive.PlatformServices.dll + + + ..\packages\Rx-XAML.2.2.2\lib\windowsphone71\System.Reactive.Windows.Threading.dll + + + ..\packages\Caliburn.Micro.1.5.2\lib\wp71\System.Windows.Interactivity.dll + + + + + Analytics\AnalyticsProperties.cs + + + Analytics\AnalyticsService.cs + + + Analytics\AnalyticsTracker.cs + + + Analytics\ReviewRequester.cs + + + Animation\LinqToVisualTree.cs + + + Animation\MetroInMotion.cs + + + Animation\Navigation\AnimatedBasePage.cs + + + Animation\Navigation\AnimatorHelperBase.cs + + + Animation\Navigation\ContinuumAnimator.cs + + + Animation\Navigation\SlideAnimator.cs + + + Animation\Navigation\Storyboards.cs + + + Animation\Navigation\SwivelAnimator.cs + + + Animation\Navigation\TurnstileAnimator.cs + + + Animation\Navigation\TurnstileFeatherAnimator.cs + + + App.xaml.cs + + + Behaviors\MarkTapAsHandledBehavior.cs + + + Behaviors\PanAndZoomBehavior.cs + + + Behaviors\ProgressBarSmoother.cs + + + Behaviors\SelectionBehavior.cs + + + Behaviors\ThemeToStateBehavior.cs + + + Behaviors\ToggleSwitchLocalizedContentBehavior.cs + + + Behaviors\UpdateTextBindingBehavior.cs + + + Bootstrapper.cs + + + CapabilityPlaceholder.cs + + + Commands.cs + + + Constants.cs + + + Controls\BrowserNavigationService.cs + + + Controls\TelegramNavigationInTransition.cs + + + Controls\TelegramNavigationOutTransition.cs + + + Controls\TelegramNavigationTransition.cs + + + Controls\TelegramRichTextBox.cs + + + Controls\TelegramTransitionFrame.cs + + + Controls\TelegramTransitionService.cs + + + Controls\TelegramTurnstileTransition.cs + + + Controls\TestScrollableTextBlock.cs + + + Controls\TransitionFrame.cs + + + Converters\BackgroundImageConverter.cs + + + Converters\BooleanToValueConverter.cs + + + Converters\BooleanToVisibilityConverter.cs + + + Converters\ChatForbiddenToVisibilityConverter.cs + + + Converters\ChatToMaxHeight.cs + + + Converters\ChatToVisibilityConverter.cs + + + Converters\CountToVisibilityConverter.cs + + + Converters\DebugVisibilityConverter.cs + + + Converters\DefaultPhotoConverter.cs + + + Converters\DialogCaptionConverter.cs + + + Converters\DialogDetailsBackgroundConverter.cs + + + Converters\DialogMessageFromConverter.cs + + + Converters\DistanceAwayConverter.cs + + + Converters\EmptyDialogMessageConverter.cs + + + Converters\EmptyPhotoToVisibilityConverter.cs + + + Converters\EmptyStringToVisibilityConverter.cs + + + Converters\ExistsToVisibilityConverter.cs + + + Converters\ExtendedImageConverter.cs + + + Converters\FileExtToColorConverter.cs + + + Converters\FileNameConverter.cs + + + Converters\FileSizeConverter.cs + + + Converters\ForwardedMessageConverter.cs + + + Converters\GeoLocationToVisibilityConverter.cs + + + Converters\GeoPointToStaticGoogleMapsConverter.cs + + + Converters\GroupToBackgroundBrushValueConverter.cs + + + Converters\GroupToForegroundBrushValueConverter.cs + + + Converters\IdToPlaceholderBackgroundConverter.cs + + + Converters\IntToVisibilityConverter.cs + + + Converters\InvertBooleanConverter.cs + + + Converters\IsSelectedToBackgroundConverter.cs + + + Converters\LowercaseConverter.cs + + + Converters\MaskConverter.cs + + + Converters\MediaContactToPhotoConverter.cs + + + Converters\MediaEmptyToVisibilityConverter.cs + + + Converters\MediaSizeConverter.cs + + + Converters\MergeBrushesConverter.cs + + + Converters\MessageStateToForegroundConverter.cs + + + Converters\MessageStatusConverter.cs + + + Converters\MessageToBriefInfoConverter.cs + + + Converters\MessageToFontFamilyConverter.cs + + + Converters\MuteUntilToStringConverter.cs + + + Converters\NotifySettingsToVisibilityConverter.cs + + + Converters\NotServiceMessageToVisibilityConverter.cs + + + Converters\OverlayAccentBrushConverter.cs + + + Converters\PhoneNumberConverter.cs + + + Converters\PhotoBytesToImageConverter.cs + + + Converters\PhotoToDimensionConverter.cs + + + Converters\PhotoToThumbConverter.cs + + + Converters\PlaceholderDefaultImageConverter.cs + + + Converters\PrivateBetaToVisibilityConverter.cs + + + Converters\ProgressToVisibilityConverter.cs + + + Converters\ReplyMarkupButtonVisibilityConverter.cs + + + Converters\SecretChatsAvailabilityConverter.cs + + + Converters\SecretChatsForegroundConverter.cs + + + Converters\ServiceMessageToTextConverter.cs + + + Converters\StatusToImageConverter.cs + + + Converters\StickerSetToCountStringConverter.cs + + + Converters\StringEqualsToVisibilityConverter.cs + + + Converters\StringFormatConverter.cs + + + Converters\TestBindingConverter.cs + + + Converters\TextMessageToVisibilityConverter.cs + + + Converters\TextSizeToVisibilityConverter.cs + + + Converters\TLIntToDateTimeConverter.cs + + + Converters\UnreadCountToVisibilityConverter.cs + + + Converters\UnreadMessageConverter.cs + + + Converters\UnregisteredUserIdToVisibilityConverter.cs + + + Converters\UppercaseConverter.cs + + + Converters\UserStatusToBrushConverter.cs + + + Converters\UserStatusToStringConverter.cs + + + Converters\UserStatusToVisibilityConverter.cs + + + Converters\UserToActionStringConverter.cs + + + Converters\WP8VisibilityConverter.cs + + + EmojiPanel\Controls\Emoji\EmojiControl.xaml.cs + + + EmojiPanel\Controls\Emoji\EmojiData.cs + + + EmojiPanel\Controls\Emoji\EmojiSpriteItem.cs + + + EmojiPanel\Controls\Emoji\StickerSpriteItem.cs + + + EmojiPanel\Controls\Utilities\DelayedExecutor.cs + + + EmojiPanel\Controls\Utilities\Helpers.cs + + + EmojiPanel\Controls\Utilities\MyListItemBase.cs + + + EmojiPanel\Controls\Utilities\MyVirtualizingPanel.cs + + + EmojiPanel\Controls\Utilities\VirtSegment.cs + + + EmojiPanel\Controls\Utilities\VListItemBase.cs + + + EventArgs\UpdateChatTitleEventArgs.cs + + + Extensions\ApplicationExtensions.cs + + + Extensions\CollectionExtensions.cs + + + Helpers\Clip.cs + + + Helpers\CollectionHelper.cs + + + Helpers\ImageUtils.cs + + + Helpers\ItemsControlHelper.cs + + + Helpers\Property.cs + + + Helpers\TemplateSelectors\DocumentTemplateSelector.cs + + + Helpers\TemplateSelectors\EmptyDialogToDescriptionConverter.cs + + + Helpers\TemplateSelectors\ItemsPanelTemplateSelector.cs + + + Helpers\TemplateSelectors\LocationTemplateSelector.cs + + + Helpers\TemplateSelectors\MediaTemplateSelector.cs + + + Helpers\TemplateSelectors\MessageTemplateSelector.cs + + + Helpers\TemplateSelectors\SearchContactsTemplateSelector.cs + + + ViewModels\Contacts\AlphaKeyGroup.cs + + + Models\ContactsByLastName.cs + + + Models\Country.cs + + + Models\InAppNotifications.cs + + + Models\Settings.cs + + + Models\UsersByFirstName.cs + + + Models\UsersByLastName.cs + + + Resources\AppResources.de.Designer.cs + + + Resources\AppResources.Designer.cs + + + Resources\AppResources.es.Designer.cs + + + Resources\AppResources.it.Designer.cs + + + Resources\AppResources.nl.Designer.cs + + + Resources\AppResources.pt.Designer.cs + + + Resources\LocalizationConverter.cs + + + Resources\LocalizedStrings.cs + + + Services\CommonErrorHandler.cs + + + Services\ICommonErrorHandler.cs + + + Services\IPushService.cs + + + Services\IStateService.cs + + + Services\PushService.cs + + + Services\PushServiceBase.cs + + + Services\StateService.cs + + + Utils\Color.cs + + + Utils\Language.cs + + + Utils\TelegramUriMapper.cs + + + ViewModels\Additional\AboutViewModel.cs + + + ViewModels\Additional\AccountSelfDestructsViewModel.cs + + + ViewModels\Additional\AddChatParticipantConfirmationViewModel.cs + + + ViewModels\Additional\AllowUsersViewModel.cs + + + ViewModels\Additional\AskQuestionConfirmationViewModel.cs + + + ViewModels\Additional\BlockedContactsViewModel.cs + + + ViewModels\Additional\CacheViewModel.cs + + + ViewModels\Additional\ChangePasscodeViewModel.cs + + + ViewModels\Additional\ChangePasswordEmailViewModel.cs + + + ViewModels\Additional\ChangePasswordHintViewModel.cs + + + ViewModels\Additional\ChangePasswordViewModel.cs + + + ViewModels\Additional\ChangePhoneNumberViewModel.cs + + + ViewModels\Additional\ChooseAttachmentViewModel.cs + + + ViewModels\Additional\ChooseBackgroundViewModel.cs + + + ViewModels\Additional\ChooseCountryViewModel.cs + + + ViewModels\Additional\ChooseNotificationSpanViewModel.cs + + + ViewModels\Additional\ChooseTTLViewModel.cs + + + ViewModels\Additional\EditCurrentUserViewModel.cs + + + ViewModels\Additional\EditPhoneNumberViewModel.cs + + + ViewModels\Additional\EditUsernameViewModel.cs + + + ViewModels\Additional\EncryptionKeyViewModel.cs + + + ViewModels\Additional\EnterPasscodeViewModel.cs + + + ViewModels\Additional\EnterPasswordViewModel.cs + + + ViewModels\Additional\LastSeenViewModel.cs + + + ViewModels\Additional\LockscreenViewModel.cs + + + ViewModels\Additional\NotificationsViewModel.cs + + + ViewModels\Additional\PasscodeViewModel.cs + + + ViewModels\Additional\PasswordRecoveryViewModel.cs + + + ViewModels\Additional\PasswordViewModel.cs + + + ViewModels\Additional\PrivacySecureViewModel.cs + + + ViewModels\Additional\PrivacyStatementViewModel.cs + + + ViewModels\Additional\SelectMultipleUsersViewModel.cs + + + ViewModels\Additional\SessionsViewModel.cs + + + ViewModels\Additional\SettingsViewModel.cs + + + ViewModels\Additional\ShareViewModel.cs + + + ViewModels\Additional\SnapshotsViewModel.cs + + + ViewModels\Additional\SpecialThanksViewModel.cs + + + ViewModels\Additional\StartupViewModel.cs + + + ViewModels\Additional\StickersViewModel.cs + + + ViewModels\Auth\ConfirmPasswordViewModel.cs + + + ViewModels\Auth\ConfirmViewModel.cs + + + ViewModels\Auth\SignInViewModel.cs + + + ViewModels\Auth\SignUpViewModel.cs + + + ViewModels\Chats\AddChannelManagerViewModel.cs + + + ViewModels\Chats\AddChatParticipantViewModel.cs + + + ViewModels\Chats\AddSecretChatParticipantViewModel.cs + + + ViewModels\Chats\Chat2ViewModel.cs + + + ViewModels\Chats\ChatDetailsViewModel.cs + + + ViewModels\Chats\ChatViewModel.cs + + + ViewModels\Chats\EditChatViewModel.cs + + + ViewModels\Chats\InviteLinkViewModel.cs + + + ViewModels\Contacts\ContactDetailsViewModel.cs + + + ViewModels\Contacts\ContactInfoViewModel.cs + + + ViewModels\Contacts\ContactsViewModel.cs + + + ViewModels\Contacts\ContactViewModel.cs + + + ViewModels\Contacts\EditContactViewModel.cs + + + ViewModels\Contacts\SecretContactDetailsViewModel.cs + + + ViewModels\Contacts\SecretContactViewModel.cs + + + ViewModels\Contacts\ShareContactViewModel.cs + + + ViewModels\Debug\DebugViewModel.cs + + + ViewModels\Debug\LogViewModel.cs + + + ViewModels\Debug\LongPollViewModel.cs + + + ViewModels\Debug\PerformanceViewModel.cs + + + ViewModels\Dialogs\ChooseDialogViewModel.cs + + + ViewModels\Dialogs\ChooseParticipantsViewModel.cs + + + ViewModels\Dialogs\CommandHintsViewModel.cs + + + ViewModels\Dialogs\CreateBroadcastViewModel.cs + + + ViewModels\Dialogs\CreateChannelViewModel.cs + + + ViewModels\Dialogs\CreateDialogViewModel.cs + + + ViewModels\Dialogs\DialogDetailsMode.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Actions.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Channel.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Contact.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Document.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.GeoPoint.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Handle.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Media.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Photo.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Reply.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Search.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Video.cs + + + ViewModels\Dialogs\DialogSearchMessagesViewModel.cs + + + ViewModels\Dialogs\DialogsViewModel.Common.cs + + + ViewModels\Dialogs\HashtagHintsViewModel.cs + + + ViewModels\Dialogs\MessageViewerViewModel.cs + + + ViewModels\Dialogs\SecretChatDebugViewModel.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Document.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.GeoPoint.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Handle.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Media.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Photo.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Text.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Video.cs + + + ViewModels\Dialogs\UserActionViewModel.cs + + + ViewModels\Dialogs\UsernameHintsViewModel.cs + + + ViewModels\ItemDetailsViewModelBase.cs + + + ViewModels\ItemsViewModelBase.cs + + + ViewModels\Media\AnimatedImageViewerViewModel.cs + + + ViewModels\Media\DecryptedImageViewerViewModel.cs + + + ViewModels\Media\FilesViewModel.cs + + + ViewModels\Media\FullMediaViewModel.cs + + + ViewModels\Media\ImageEditorViewModel.cs + + + ViewModels\Media\ImageViewerViewModel.cs + + + ViewModels\Media\LinksViewModel.cs + + + ViewModels\Media\MapViewModel.cs + + + ViewModels\Media\MediaViewModel.cs + + + ViewModels\Media\ProfilePhotoViewerViewModel.cs + + + ViewModels\Media\SecretMediaViewModel.cs + + + ViewModels\Media\VideoCaptureViewModel.cs + + + ViewModels\Media\VideoPlayerViewModel.cs + + + ViewModels\Search\ISearch.cs + + + ViewModels\Search\SearchContactsViewModel.cs + + + ViewModels\Search\SearchDialogsViewModel.cs + + + ViewModels\Search\SearchFilesViewModel.cs + + + ViewModels\Search\SearchItemsViewModelBase.cs + + + ViewModels\Search\SearchLinksViewModel.cs + + + ViewModels\Search\SearchMessagesViewModel.cs + + + ViewModels\Search\SearchShellViewModel.cs + + + ViewModels\Search\SearchVenuesViewModel.cs + + + ViewModels\ShellViewModel.cs + + + ViewModels\ViewModelBase.cs + + + Views\Additional\AboutView.xaml.cs + + + Views\Additional\AccountSelfDestructsView.xaml.cs + AccountSelfDestructsView.xaml + + + Views\Additional\AddChatParticipantConfirmationView.xaml.cs + AddChatParticipantConfirmationView.xaml + + + Views\Additional\AllowUsersView.xaml.cs + AllowUsersView.xaml + + + Views\Additional\AskQuestionConfirmationView.xaml.cs + AskQuestionConfirmationView.xaml + + + Views\Additional\BlockedContactsView.xaml.cs + + + Views\Additional\BubbleBackgroundControl.xaml.cs + BubbleBackgroundControl.xaml + + + Views\Additional\CacheView.xaml.cs + CacheView.xaml + + + Views\Additional\ChangePasscodeView.xaml.cs + ChangePasscodeView.xaml + + + Views\Additional\ChangePasswordEmailView.xaml.cs + ChangePasswordEmailView.xaml + + + Views\Additional\ChangePasswordHintView.xaml.cs + ChangePasswordHintView.xaml + + + Views\Additional\ChangePasswordView.xaml.cs + ChangePasswordView.xaml + + + Views\Additional\ChangePhoneNumberView.xaml.cs + ChangePhoneNumberView.xaml + + + Views\Additional\ChooseAttachmentView.xaml.cs + + + Views\Additional\ChooseBackgroundView.xaml.cs + + + Views\Additional\ChooseCountryView.xaml.cs + + + Views\Additional\ChooseNotificationSpanView.xaml.cs + ChooseNotificationSpanView.xaml + + + Views\Additional\ChooseTTLView.xaml.cs + ChooseTTLView.xaml + + + Views\Additional\EditCurrentUserView.xaml.cs + + + Views\Additional\EditPhoneNumberView.xaml.cs + EditPhoneNumberView.xaml + + + Views\Additional\EditUsernameView.xaml.cs + EditUsernameView.xaml + + + Views\Additional\EncryptionKeyView.xaml.cs + EncryptionKeyView.xaml + + + Views\Additional\EnterPasscodeView.xaml.cs + EnterPasscodeView.xaml + + + Views\Additional\EnterPasswordView.xaml.cs + EnterPasswordView.xaml + + + Views\Additional\FallingSnowControl.xaml.cs + FallingSnowControl.xaml + + + Views\Additional\LastSeenView.xaml.cs + LastSeenView.xaml + + + Views\Additional\LockscreenView.xaml.cs + LockscreenView.xaml + + + Views\Additional\NotificationsView.xaml.cs + + + Views\Additional\NumericKeyboard.xaml.cs + NumericKeyboard.xaml + + + Views\Additional\PasscodeView.xaml.cs + PasscodeView.xaml + + + Views\Additional\PasswordRecoveryView.xaml.cs + PasswordRecoveryView.xaml + + + Views\Additional\PasswordView.xaml.cs + PasswordView.xaml + + + Views\Additional\PrivacySecurityView.xaml.cs + PrivacySecurityView.xaml + + + Views\Additional\PrivacyStatementView.xaml.cs + + + Views\Additional\SelectMultipleUsersView.xaml.cs + SelectMultipleUsersView.xaml + + + Views\Additional\SessionsView.xaml.cs + SessionsView.xaml + + + Views\Additional\SettingsView.xaml.cs + + + Views\Additional\ShareView.xaml.cs + ShareView.xaml + + + Views\Additional\SnapshotsView.xaml.cs + SnapshotsView.xaml + + + Views\Additional\SpecialThanksView.xaml.cs + SpecialThanksView.xaml + + + Views\Additional\StickersView.xaml.cs + StickersView.xaml + + + Views\Additional\TelegramPasswordBox.xaml.cs + TelegramPasswordBox.xaml + + + Views\Auth\ConfirmPasswordView.xaml.cs + ConfirmPasswordView.xaml + + + Views\Auth\ConfirmView.xaml.cs + + + Views\Auth\SignInView.xaml.cs + + + Views\Auth\SignUpView.xaml.cs + + + Views\Chats\AddChannelManagerView.xaml.cs + AddChannelManagerView.xaml + + + Views\Chats\AddChatParticipantView.xaml.cs + + + Views\Chats\AddSecretChatParticipantView.xaml.cs + AddSecretChatParticipantView.xaml + + + Views\Chats\Chat2View.xaml.cs + Chat2View.xaml + + + Views\Chats\ChatDetailsView.xaml.cs + + + Views\Chats\ChatView.xaml.cs + + + Views\Chats\EditChatView.xaml.cs + + + Views\Chats\InviteLinkView.xaml.cs + InviteLinkView.xaml + + + Views\Contacts\ContactDetailsView.xaml.cs + + + Views\Contacts\ContactInfoView.xaml.cs + ContactInfoView.xaml + + + Views\Contacts\ContactView.xaml.cs + + + Views\Contacts\EditContactView.xaml.cs + + + Views\Contacts\SecretContactDetailsView.xaml.cs + SecretContactDetailsView.xaml + + + Views\Contacts\SecretContactView.xaml.cs + SecretContactView.xaml + + + Views\Contacts\ShareContactView.xaml.cs + + + Views\Controls\ConversationTileControl.xaml.cs + + + Views\Controls\MainTitleControl.xaml.cs + + + Views\Controls\MessagePlayerControl.xaml.cs + MessagePlayerControl.xaml + + + Views\Controls\MessageStatusControl.xaml.cs + + + Views\Controls\PieSlice.cs + + + Views\Controls\SecretPhotoPlaceholder.xaml.cs + SecretPhotoPlaceholder.xaml + + + Views\Debug\DebugView.xaml.cs + + + Views\Debug\LongPollView.xaml.cs + + + Views\Debug\PerformanceView.xaml.cs + + + Views\Dialogs\ChooseDialogView.xaml.cs + ChooseDialogView.xaml + + + Views\Dialogs\ChooseParticipantsView.xaml.cs + + + Views\Dialogs\CommandHintsView.xaml.cs + CommandHintsView.xaml + + + Views\Dialogs\CommandsControl.xaml.cs + CommandsControl.xaml + + + Views\Dialogs\CreateBroadcastView.xaml.cs + CreateBroadcastView.xaml + + + Views\Dialogs\CreateChannelView.xaml.cs + CreateChannelView.xaml + + + Views\Dialogs\CreateDialogView.xaml.cs + + + Views\Dialogs\DialogSearchMessagesView.xaml.cs + DialogSearchMessagesView.xaml + + + Views\Dialogs\EmojiKeyboardControl.xaml.cs + EmojiKeyboardControl.xaml + + + Views\Dialogs\HashtagHintsView.xaml.cs + HashtagHintsView.xaml + + + Views\Dialogs\MessageViewerView.xaml.cs + MessageViewerView.xaml + + + Views\Dialogs\SecretChatDebugView.xaml.cs + SecretChatDebugView.xaml + + + Views\Dialogs\UserActionView.xaml.cs + UserActionView.xaml + + + Views\Dialogs\UsernameHintsView.xaml.cs + UsernameHintsView.xaml + + + Views\Media\AnimatedImageViewerView.xaml.cs + AnimatedImageViewerView.xaml + + + Views\Media\DecryptedImageViewerView.xaml.cs + DecryptedImageViewerView.xaml + + + Views\Media\FullMediaView.xaml.cs + FullMediaView.xaml + + + Views\Media\ImageEditorView.xaml.cs + ImageEditorView.xaml + + + Views\Media\ImageViewerView.xaml.cs + + + Views\Media\MapTileSources\GoogleMapsTileSource.cs + + + Views\Media\MapTileSources\OpenAeralMapTileSource.cs + + + Views\Media\MapTileSources\OpenStreetMapTileSource.cs + + + Views\Media\MapView.xaml.cs + + + Views\Media\ProfilePhotoViewerView.xaml.cs + + + Views\Media\SecretMediaView.xaml.cs + SecretMediaView.xaml + + + Views\Media\VideoCaptureView.xaml.cs + + + Views\Media\VideoPlayerView.xaml.cs + + + Views\Search\SearchContactsView.xaml.cs + + + Views\Search\SearchDialogsView.xaml.cs + + + Views\Search\SearchFilesView.xaml.cs + SearchFilesView.xaml + + + Views\Search\SearchLinksView.xaml.cs + SearchLinksView.xaml + + + Views\Search\SearchMessagesView.xaml.cs + + + Views\Search\SearchShellView.xaml.cs + + + Views\Search\SearchVenuesView.xaml.cs + SearchVenuesView.xaml + + + Views\ShellView.xaml.cs + + + Views\TelegramViewBase.cs + + + + + + + + + + + + + + + + + + + + + + StartupView.xaml + + + ContactsView.xaml + + + AudioRecorderControl.xaml + + + DialogDetailsView.xaml + + + DialogsView.xaml + + + SecretDialogDetailsView.xaml + + + LinksView.xaml + + + FilesView.xaml + + + MediaView.xaml + + + + + + + + Designer + + + + + App.xaml + MSBuild:Compile + Designer + + + EmojiPanel\Controls\Emoji\EmojiControl.xaml + MSBuild:Compile + Designer + + + Themes\Default\Button.xaml + MSBuild:Compile + Designer + + + Themes\Default\CheckBox.xaml + MSBuild:Compile + Designer + + + Themes\Default\ListBox.xaml + MSBuild:Compile + Designer + + + Themes\Default\ScrollViewer.xaml + MSBuild:Compile + Designer + + + Themes\Default\Slider.xaml + MSBuild:Compile + Designer + + + Themes\Default\Templates\DataTemplates.xaml + MSBuild:Compile + Designer + + + Themes\Default\Templates\ItemsPanel.xaml + MSBuild:Compile + Designer + + + Themes\Default\Templates\Media.xaml + MSBuild:Compile + Designer + + + Themes\Default\TextBlock.xaml + MSBuild:Compile + Designer + + + Themes\Default\TextBox.xaml + MSBuild:Compile + Designer + + + Themes\Default\Theme.xaml + MSBuild:Compile + Designer + + + Themes\Default\ToggleButton.xaml + MSBuild:Compile + Designer + + + Themes\Default\Transitions.xaml + MSBuild:Compile + Designer + + + Views\Additional\AboutView.xaml + MSBuild:Compile + Designer + + + Views\Additional\AccountSelfDestructsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\AddChatParticipantConfirmationView.xaml + MSBuild:Compile + Designer + + + Views\Additional\AllowUsersView.xaml + MSBuild:Compile + Designer + + + Views\Additional\AskQuestionConfirmationView.xaml + MSBuild:Compile + Designer + + + Views\Additional\BlockedContactsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\BubbleBackgroundControl.xaml + MSBuild:Compile + Designer + + + Views\Additional\CacheView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChangePasscodeView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChangePasswordEmailView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChangePasswordHintView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChangePasswordView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChangePhoneNumberView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChooseAttachmentView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChooseBackgroundView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChooseCountryView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChooseNotificationSpanView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChooseTTLView.xaml + MSBuild:Compile + Designer + + + Views\Additional\EditCurrentUserView.xaml + MSBuild:Compile + Designer + + + Views\Additional\EditPhoneNumberView.xaml + MSBuild:Compile + Designer + + + Views\Additional\EditUsernameView.xaml + MSBuild:Compile + Designer + + + Views\Additional\EncryptionKeyView.xaml + MSBuild:Compile + Designer + + + Views\Additional\EnterPasscodeView.xaml + MSBuild:Compile + Designer + + + Views\Additional\EnterPasswordView.xaml + MSBuild:Compile + Designer + + + Views\Additional\FallingSnowControl.xaml + MSBuild:Compile + Designer + + + Views\Additional\LastSeenView.xaml + MSBuild:Compile + Designer + + + Views\Additional\LockscreenView.xaml + MSBuild:Compile + Designer + + + Views\Additional\NotificationsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\NumericKeyboard.xaml + MSBuild:Compile + Designer + + + Views\Additional\PasscodeView.xaml + MSBuild:Compile + Designer + + + Views\Additional\PasswordRecoveryView.xaml + MSBuild:Compile + Designer + + + Views\Additional\PasswordView.xaml + MSBuild:Compile + Designer + + + Views\Additional\PrivacySecurityView.xaml + MSBuild:Compile + Designer + + + Views\Additional\PrivacyStatementView.xaml + MSBuild:Compile + Designer + + + Views\Additional\SelectMultipleUsersView.xaml + MSBuild:Compile + Designer + + + Views\Additional\SessionsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\SettingsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ShareView.xaml + MSBuild:Compile + Designer + + + Views\Additional\SnapshotsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\SpecialThanksView.xaml + MSBuild:Compile + Designer + + + Views\Additional\StickersView.xaml + MSBuild:Compile + Designer + + + Views\Additional\TelegramPasswordBox.xaml + MSBuild:Compile + Designer + + + Views\Auth\ConfirmPasswordView.xaml + MSBuild:Compile + Designer + + + Views\Auth\ConfirmView.xaml + MSBuild:Compile + Designer + + + Views\Auth\SignInView.xaml + MSBuild:Compile + Designer + + + Views\Auth\SignUpView.xaml + MSBuild:Compile + Designer + + + Views\Chats\AddChannelManagerView.xaml + MSBuild:Compile + Designer + + + Views\Chats\AddChatParticipantView.xaml + MSBuild:Compile + Designer + + + Views\Chats\AddSecretChatParticipantView.xaml + MSBuild:Compile + Designer + + + Views\Chats\Chat2View.xaml + MSBuild:Compile + Designer + + + Views\Chats\ChatDetailsView.xaml + MSBuild:Compile + Designer + + + Views\Chats\ChatView.xaml + MSBuild:Compile + Designer + + + Views\Chats\EditChatView.xaml + MSBuild:Compile + Designer + + + Views\Chats\InviteLinkView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\ContactDetailsView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\ContactInfoView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\ContactView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\EditContactView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\SecretContactDetailsView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\SecretContactView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\ShareContactView.xaml + MSBuild:Compile + Designer + + + Views\Controls\ConversationTileControl.xaml + MSBuild:Compile + Designer + + + Views\Controls\MainTitleControl.xaml + MSBuild:Compile + Designer + + + Views\Controls\MessagePlayerControl.xaml + MSBuild:Compile + Designer + + + Views\Controls\MessageStatusControl.xaml + MSBuild:Compile + Designer + + + Views\Controls\SecretPhotoPlaceholder.xaml + MSBuild:Compile + Designer + + + Views\Debug\DebugView.xaml + MSBuild:Compile + Designer + + + Views\Debug\LongPollView.xaml + MSBuild:Compile + Designer + + + Views\Debug\PerformanceView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\ChooseDialogView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\ChooseParticipantsView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\CommandHintsView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\CommandsControl.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\CreateBroadcastView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\CreateChannelView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\CreateDialogView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\DialogSearchMessagesView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\EmojiKeyboardControl.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\HashtagHintsView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\MessageViewerView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\SecretChatDebugView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\UserActionView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\UsernameHintsView.xaml + MSBuild:Compile + Designer + + + Views\Media\AnimatedImageViewerView.xaml + MSBuild:Compile + Designer + + + Views\Media\DecryptedImageViewerView.xaml + MSBuild:Compile + Designer + + + Views\Media\FullMediaView.xaml + MSBuild:Compile + Designer + + + Views\Media\ImageEditorView.xaml + MSBuild:Compile + Designer + + + Views\Media\ImageViewerView.xaml + MSBuild:Compile + Designer + + + Views\Media\MapView.xaml + MSBuild:Compile + Designer + + + Views\Media\ProfilePhotoViewerView.xaml + MSBuild:Compile + Designer + + + Views\Media\SecretMediaView.xaml + MSBuild:Compile + Designer + + + Views\Media\VideoCaptureView.xaml + MSBuild:Compile + Designer + + + Views\Media\VideoPlayerView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchContactsView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchDialogsView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchFilesView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchLinksView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchMessagesView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchShellView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchVenuesView.xaml + MSBuild:Compile + Designer + + + Views\ShellView.xaml + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + + + Assets\emoji.abc-WXGA.png + + + Assets\emoji.backspace-WXGA.png + + + Assets\emoji.category.1-WXGA.png + + + Assets\emoji.category.2-WXGA.png + + + Assets\emoji.category.3-WXGA.png + + + Assets\emoji.category.4-WXGA.png + + + Assets\emoji.category.5-WXGA.png + + + Assets\emoji.recent-WXGA.png + + + Assets\emoji.sticker-WXGA.png + + + Assets\Emoji\Separated\002320E3.png + + + Assets\Emoji\Separated\003020E3.png + + + Assets\Emoji\Separated\003120E3.png + + + Assets\Emoji\Separated\003220E3.png + + + Assets\Emoji\Separated\003320E3.png + + + Assets\Emoji\Separated\003420E3.png + + + Assets\Emoji\Separated\003520E3.png + + + Assets\Emoji\Separated\003620E3.png + + + Assets\Emoji\Separated\003720E3.png + + + Assets\Emoji\Separated\003820E3.png + + + Assets\Emoji\Separated\003920E3.png + + + Assets\Emoji\Separated\00a9.png + + + Assets\Emoji\Separated\00ae.png + + + Assets\Emoji\Separated\203C.png + + + Assets\Emoji\Separated\2049.png + + + Assets\Emoji\Separated\2122.png + + + Assets\Emoji\Separated\2139.png + + + Assets\Emoji\Separated\2194.png + + + Assets\Emoji\Separated\2195.png + + + Assets\Emoji\Separated\2196.png + + + Assets\Emoji\Separated\2197.png + + + Assets\Emoji\Separated\2198.png + + + Assets\Emoji\Separated\2199.png + + + Assets\Emoji\Separated\21A9.png + + + Assets\Emoji\Separated\21AA.png + + + Assets\Emoji\Separated\231A.png + + + Assets\Emoji\Separated\231B.png + + + Assets\Emoji\Separated\23e9.png + + + Assets\Emoji\Separated\23ea.png + + + Assets\Emoji\Separated\23eb.png + + + Assets\Emoji\Separated\23ec.png + + + Assets\Emoji\Separated\23f0.png + + + Assets\Emoji\Separated\23f3.png + + + Assets\Emoji\Separated\24C2.png + + + Assets\Emoji\Separated\25AA.png + + + Assets\Emoji\Separated\25AB.png + + + Assets\Emoji\Separated\25B6.png + + + Assets\Emoji\Separated\25C0.png + + + Assets\Emoji\Separated\25FB.png + + + Assets\Emoji\Separated\25FC.png + + + Assets\Emoji\Separated\25FD.png + + + Assets\Emoji\Separated\25FE.png + + + Assets\Emoji\Separated\2600.png + + + Assets\Emoji\Separated\2601.png + + + Assets\Emoji\Separated\2602.png + + + Assets\Emoji\Separated\2603.png + + + Assets\Emoji\Separated\2604.png + + + Assets\Emoji\Separated\260E.png + + + Assets\Emoji\Separated\2611.png + + + Assets\Emoji\Separated\2614.png + + + Assets\Emoji\Separated\2615.png + + + Assets\Emoji\Separated\2618.png + + + Assets\Emoji\Separated\261D.png + + + Assets\Emoji\Separated\261DD83CDFFB.png + + + Assets\Emoji\Separated\261DD83CDFFC.png + + + Assets\Emoji\Separated\261DD83CDFFD.png + + + Assets\Emoji\Separated\261DD83CDFFE.png + + + Assets\Emoji\Separated\261DD83CDFFF.png + + + Assets\Emoji\Separated\2620.png + + + Assets\Emoji\Separated\263A.png + + + Assets\Emoji\Separated\2648.png + + + Assets\Emoji\Separated\2649.png + + + Assets\Emoji\Separated\264A.png + + + Assets\Emoji\Separated\264B.png + + + Assets\Emoji\Separated\264C.png + + + Assets\Emoji\Separated\264D.png + + + Assets\Emoji\Separated\264E.png + + + Assets\Emoji\Separated\264F.png + + + Assets\Emoji\Separated\2650.png + + + Assets\Emoji\Separated\2651.png + + + Assets\Emoji\Separated\2652.png + + + Assets\Emoji\Separated\2653.png + + + Assets\Emoji\Separated\2660.png + + + Assets\Emoji\Separated\2663.png + + + Assets\Emoji\Separated\2665.png + + + Assets\Emoji\Separated\2666.png + + + Assets\Emoji\Separated\2668.png + + + Assets\Emoji\Separated\267B.png + + + Assets\Emoji\Separated\267F.png + + + Assets\Emoji\Separated\2692.png + + + Assets\Emoji\Separated\2693.png + + + Assets\Emoji\Separated\2694.png + + + Assets\Emoji\Separated\2696.png + + + Assets\Emoji\Separated\2697.png + + + Assets\Emoji\Separated\2699.png + + + Assets\Emoji\Separated\26A0.png + + + Assets\Emoji\Separated\26A1.png + + + Assets\Emoji\Separated\26AA.png + + + Assets\Emoji\Separated\26AB.png + + + Assets\Emoji\Separated\26B0.png + + + Assets\Emoji\Separated\26B1.png + + + Assets\Emoji\Separated\26BD.png + + + Assets\Emoji\Separated\26BE.png + + + Assets\Emoji\Separated\26C4.png + + + Assets\Emoji\Separated\26C5.png + + + Assets\Emoji\Separated\26C8.png + + + Assets\Emoji\Separated\26ce.png + + + Assets\Emoji\Separated\26CF.png + + + Assets\Emoji\Separated\26D1.png + + + Assets\Emoji\Separated\26D3.png + + + Assets\Emoji\Separated\26D4.png + + + Assets\Emoji\Separated\26E9.png + + + Assets\Emoji\Separated\26EA.png + + + Assets\Emoji\Separated\26F0.png + + + Assets\Emoji\Separated\26F1.png + + + Assets\Emoji\Separated\26F2.png + + + Assets\Emoji\Separated\26F3.png + + + Assets\Emoji\Separated\26F4.png + + + Assets\Emoji\Separated\26F5.png + + + Assets\Emoji\Separated\26F7.png + + + Assets\Emoji\Separated\26F8.png + + + Assets\Emoji\Separated\26F9.png + + + Assets\Emoji\Separated\26F9D83CDFFB.png + + + Assets\Emoji\Separated\26F9D83CDFFC.png + + + Assets\Emoji\Separated\26F9D83CDFFD.png + + + Assets\Emoji\Separated\26F9D83CDFFE.png + + + Assets\Emoji\Separated\26F9D83CDFFF.png + + + Assets\Emoji\Separated\26FA.png + + + Assets\Emoji\Separated\26FD.png + + + Assets\Emoji\Separated\2702.png + + + Assets\Emoji\Separated\2705.png + + + Assets\Emoji\Separated\2708.png + + + Assets\Emoji\Separated\2709.png + + + Assets\Emoji\Separated\270a.png + + + Assets\Emoji\Separated\270AD83CDFFB.png + + + Assets\Emoji\Separated\270AD83CDFFC.png + + + Assets\Emoji\Separated\270AD83CDFFD.png + + + Assets\Emoji\Separated\270AD83CDFFE.png + + + Assets\Emoji\Separated\270AD83CDFFF.png + + + Assets\Emoji\Separated\270b.png + + + Assets\Emoji\Separated\270BD83CDFFB.png + + + Assets\Emoji\Separated\270BD83CDFFC.png + + + Assets\Emoji\Separated\270BD83CDFFD.png + + + Assets\Emoji\Separated\270BD83CDFFE.png + + + Assets\Emoji\Separated\270BD83CDFFF.png + + + Assets\Emoji\Separated\270C.png + + + Assets\Emoji\Separated\270CD83CDFFB.png + + + Assets\Emoji\Separated\270CD83CDFFC.png + + + Assets\Emoji\Separated\270CD83CDFFD.png + + + Assets\Emoji\Separated\270CD83CDFFE.png + + + Assets\Emoji\Separated\270CD83CDFFF.png + + + Assets\Emoji\Separated\270D.png + + + Assets\Emoji\Separated\270DD83CDFFB.png + + + Assets\Emoji\Separated\270DD83CDFFC.png + + + Assets\Emoji\Separated\270DD83CDFFD.png + + + Assets\Emoji\Separated\270DD83CDFFE.png + + + Assets\Emoji\Separated\270DD83CDFFF.png + + + Assets\Emoji\Separated\270F.png + + + Assets\Emoji\Separated\2712.png + + + Assets\Emoji\Separated\2714.png + + + Assets\Emoji\Separated\2716.png + + + Assets\Emoji\Separated\2728.png + + + Assets\Emoji\Separated\2733.png + + + Assets\Emoji\Separated\2734.png + + + Assets\Emoji\Separated\2744.png + + + Assets\Emoji\Separated\2747.png + + + Assets\Emoji\Separated\274c.png + + + Assets\Emoji\Separated\274e.png + + + Assets\Emoji\Separated\2753.png + + + Assets\Emoji\Separated\2754.png + + + Assets\Emoji\Separated\2755.png + + + Assets\Emoji\Separated\2757.png + + + Assets\Emoji\Separated\2764.png + + + Assets\Emoji\Separated\2795.png + + + Assets\Emoji\Separated\2796.png + + + Assets\Emoji\Separated\2797.png + + + Assets\Emoji\Separated\27A1.png + + + Assets\Emoji\Separated\27b0.png + + + Assets\Emoji\Separated\27bf.png + + + Assets\Emoji\Separated\2934.png + + + Assets\Emoji\Separated\2935.png + + + Assets\Emoji\Separated\2B05.png + + + Assets\Emoji\Separated\2B06.png + + + Assets\Emoji\Separated\2B07.png + + + Assets\Emoji\Separated\2B1B.png + + + Assets\Emoji\Separated\2B1C.png + + + Assets\Emoji\Separated\2B50.png + + + Assets\Emoji\Separated\2B55.png + + + Assets\Emoji\Separated\3030.png + + + Assets\Emoji\Separated\303D.png + + + Assets\Emoji\Separated\3297.png + + + Assets\Emoji\Separated\3299.png + + + Assets\Emoji\Separated\D83CDC04.png + + + Assets\Emoji\Separated\D83CDCCF.png + + + Assets\Emoji\Separated\D83CDD70.png + + + Assets\Emoji\Separated\D83CDD71.png + + + Assets\Emoji\Separated\D83CDD7E.png + + + Assets\Emoji\Separated\D83CDD7F.png + + + Assets\Emoji\Separated\D83CDD8E.png + + + Assets\Emoji\Separated\D83CDD91.png + + + Assets\Emoji\Separated\D83CDD92.png + + + Assets\Emoji\Separated\D83CDD93.png + + + Assets\Emoji\Separated\D83CDD94.png + + + Assets\Emoji\Separated\D83CDD95.png + + + Assets\Emoji\Separated\D83CDD96.png + + + Assets\Emoji\Separated\D83CDD97.png + + + Assets\Emoji\Separated\D83CDD98.png + + + Assets\Emoji\Separated\D83CDD99.png + + + Assets\Emoji\Separated\D83CDD9A.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDF3.png + + + Assets\Emoji\Separated\D83CDDE9D83CDDEA.png + + + Assets\Emoji\Separated\D83CDDEAD83CDDF8.png + + + Assets\Emoji\Separated\D83CDDEBD83CDDF7.png + + + Assets\Emoji\Separated\D83CDDECD83CDDE7.png + + + Assets\Emoji\Separated\D83CDDEED83CDDF9.png + + + Assets\Emoji\Separated\D83CDDEFD83CDDF5.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDF7.png + + + Assets\Emoji\Separated\D83CDDF7D83CDDFA.png + + + Assets\Emoji\Separated\D83CDDFAD83CDDF8.png + + + Assets\Emoji\Separated\D83CDE01.png + + + Assets\Emoji\Separated\D83CDE02.png + + + Assets\Emoji\Separated\D83CDE1A.png + + + Assets\Emoji\Separated\D83CDE2F.png + + + Assets\Emoji\Separated\D83CDE32.png + + + Assets\Emoji\Separated\D83CDE33.png + + + Assets\Emoji\Separated\D83CDE34.png + + + Assets\Emoji\Separated\D83CDE35.png + + + Assets\Emoji\Separated\D83CDE36.png + + + Assets\Emoji\Separated\D83CDE37.png + + + Assets\Emoji\Separated\D83CDE38.png + + + Assets\Emoji\Separated\D83CDE39.png + + + Assets\Emoji\Separated\D83CDE3A.png + + + Assets\Emoji\Separated\D83CDE50.png + + + Assets\Emoji\Separated\D83CDE51.png + + + Assets\Emoji\Separated\D83CDF00.png + + + Assets\Emoji\Separated\D83CDF01.png + + + Assets\Emoji\Separated\D83CDF02.png + + + Assets\Emoji\Separated\D83CDF03.png + + + Assets\Emoji\Separated\D83CDF04.png + + + Assets\Emoji\Separated\D83CDF05.png + + + Assets\Emoji\Separated\D83CDF06.png + + + Assets\Emoji\Separated\D83CDF07.png + + + Assets\Emoji\Separated\D83CDF08.png + + + Assets\Emoji\Separated\D83CDF09.png + + + Assets\Emoji\Separated\D83CDF0A.png + + + Assets\Emoji\Separated\D83CDF0B.png + + + Assets\Emoji\Separated\D83CDF0C.png + + + Assets\Emoji\Separated\D83CDF0D.png + + + Assets\Emoji\Separated\D83CDF0E.png + + + Assets\Emoji\Separated\D83CDF0F.png + + + Assets\Emoji\Separated\D83CDF10.png + + + Assets\Emoji\Separated\D83CDF11.png + + + Assets\Emoji\Separated\D83CDF12.png + + + Assets\Emoji\Separated\D83CDF13.png + + + Assets\Emoji\Separated\D83CDF14.png + + + Assets\Emoji\Separated\D83CDF15.png + + + Assets\Emoji\Separated\D83CDF16.png + + + Assets\Emoji\Separated\D83CDF17.png + + + Assets\Emoji\Separated\D83CDF18.png + + + Assets\Emoji\Separated\D83CDF19.png + + + Assets\Emoji\Separated\D83CDF1A.png + + + Assets\Emoji\Separated\D83CDF1B.png + + + Assets\Emoji\Separated\D83CDF1C.png + + + Assets\Emoji\Separated\D83CDF1D.png + + + Assets\Emoji\Separated\D83CDF1E.png + + + Assets\Emoji\Separated\D83CDF1F.png + + + Assets\Emoji\Separated\D83CDF20.png + + + Assets\Emoji\Separated\D83CDF21.png + + + Assets\Emoji\Separated\D83CDF24.png + + + Assets\Emoji\Separated\D83CDF25.png + + + Assets\Emoji\Separated\D83CDF26.png + + + Assets\Emoji\Separated\D83CDF27.png + + + Assets\Emoji\Separated\D83CDF28.png + + + Assets\Emoji\Separated\D83CDF29.png + + + Assets\Emoji\Separated\D83CDF2A.png + + + Assets\Emoji\Separated\D83CDF2B.png + + + Assets\Emoji\Separated\D83CDF2C.png + + + Assets\Emoji\Separated\D83CDF2D.png + + + Assets\Emoji\Separated\D83CDF2E.png + + + Assets\Emoji\Separated\D83CDF2F.png + + + Assets\Emoji\Separated\D83CDF30.png + + + Assets\Emoji\Separated\D83CDF31.png + + + Assets\Emoji\Separated\D83CDF32.png + + + Assets\Emoji\Separated\D83CDF33.png + + + Assets\Emoji\Separated\D83CDF34.png + + + Assets\Emoji\Separated\D83CDF35.png + + + Assets\Emoji\Separated\D83CDF36.png + + + Assets\Emoji\Separated\D83CDF37.png + + + Assets\Emoji\Separated\D83CDF38.png + + + Assets\Emoji\Separated\D83CDF39.png + + + Assets\Emoji\Separated\D83CDF3A.png + + + Assets\Emoji\Separated\D83CDF3B.png + + + Assets\Emoji\Separated\D83CDF3C.png + + + Assets\Emoji\Separated\D83CDF3D.png + + + Assets\Emoji\Separated\D83CDF3E.png + + + Assets\Emoji\Separated\D83CDF3F.png + + + Assets\Emoji\Separated\D83CDF40.png + + + Assets\Emoji\Separated\D83CDF41.png + + + Assets\Emoji\Separated\D83CDF42.png + + + Assets\Emoji\Separated\D83CDF43.png + + + Assets\Emoji\Separated\D83CDF44.png + + + Assets\Emoji\Separated\D83CDF45.png + + + Assets\Emoji\Separated\D83CDF46.png + + + Assets\Emoji\Separated\D83CDF47.png + + + Assets\Emoji\Separated\D83CDF48.png + + + Assets\Emoji\Separated\D83CDF49.png + + + Assets\Emoji\Separated\D83CDF4A.png + + + Assets\Emoji\Separated\D83CDF4B.png + + + Assets\Emoji\Separated\D83CDF4C.png + + + Assets\Emoji\Separated\D83CDF4D.png + + + Assets\Emoji\Separated\D83CDF4E.png + + + Assets\Emoji\Separated\D83CDF4F.png + + + Assets\Emoji\Separated\D83CDF50.png + + + Assets\Emoji\Separated\D83CDF51.png + + + Assets\Emoji\Separated\D83CDF52.png + + + Assets\Emoji\Separated\D83CDF53.png + + + Assets\Emoji\Separated\D83CDF54.png + + + Assets\Emoji\Separated\D83CDF55.png + + + Assets\Emoji\Separated\D83CDF56.png + + + Assets\Emoji\Separated\D83CDF57.png + + + Assets\Emoji\Separated\D83CDF58.png + + + Assets\Emoji\Separated\D83CDF59.png + + + Assets\Emoji\Separated\D83CDF5A.png + + + Assets\Emoji\Separated\D83CDF5B.png + + + Assets\Emoji\Separated\D83CDF5C.png + + + Assets\Emoji\Separated\D83CDF5D.png + + + Assets\Emoji\Separated\D83CDF5E.png + + + Assets\Emoji\Separated\D83CDF5F.png + + + Assets\Emoji\Separated\D83CDF60.png + + + Assets\Emoji\Separated\D83CDF61.png + + + Assets\Emoji\Separated\D83CDF62.png + + + Assets\Emoji\Separated\D83CDF63.png + + + Assets\Emoji\Separated\D83CDF64.png + + + Assets\Emoji\Separated\D83CDF65.png + + + Assets\Emoji\Separated\D83CDF66.png + + + Assets\Emoji\Separated\D83CDF67.png + + + Assets\Emoji\Separated\D83CDF68.png + + + Assets\Emoji\Separated\D83CDF69.png + + + Assets\Emoji\Separated\D83CDF6A.png + + + Assets\Emoji\Separated\D83CDF6B.png + + + Assets\Emoji\Separated\D83CDF6C.png + + + Assets\Emoji\Separated\D83CDF6D.png + + + Assets\Emoji\Separated\D83CDF6E.png + + + Assets\Emoji\Separated\D83CDF6F.png + + + Assets\Emoji\Separated\D83CDF70.png + + + Assets\Emoji\Separated\D83CDF71.png + + + Assets\Emoji\Separated\D83CDF72.png + + + Assets\Emoji\Separated\D83CDF73.png + + + Assets\Emoji\Separated\D83CDF74.png + + + Assets\Emoji\Separated\D83CDF75.png + + + Assets\Emoji\Separated\D83CDF76.png + + + Assets\Emoji\Separated\D83CDF77.png + + + Assets\Emoji\Separated\D83CDF78.png + + + Assets\Emoji\Separated\D83CDF79.png + + + Assets\Emoji\Separated\D83CDF7A.png + + + Assets\Emoji\Separated\D83CDF7B.png + + + Assets\Emoji\Separated\D83CDF7C.png + + + Assets\Emoji\Separated\D83CDF7D.png + + + Assets\Emoji\Separated\D83CDF7E.png + + + Assets\Emoji\Separated\D83CDF7F.png + + + Assets\Emoji\Separated\D83CDF80.png + + + Assets\Emoji\Separated\D83CDF81.png + + + Assets\Emoji\Separated\D83CDF82.png + + + Assets\Emoji\Separated\D83CDF83.png + + + Assets\Emoji\Separated\D83CDF84.png + + + Assets\Emoji\Separated\D83CDF85.png + + + Assets\Emoji\Separated\D83CDF85D83CDFFB.png + + + Assets\Emoji\Separated\D83CDF85D83CDFFC.png + + + Assets\Emoji\Separated\D83CDF85D83CDFFD.png + + + Assets\Emoji\Separated\D83CDF85D83CDFFE.png + + + Assets\Emoji\Separated\D83CDF85D83CDFFF.png + + + Assets\Emoji\Separated\D83CDF86.png + + + Assets\Emoji\Separated\D83CDF87.png + + + Assets\Emoji\Separated\D83CDF88.png + + + Assets\Emoji\Separated\D83CDF89.png + + + Assets\Emoji\Separated\D83CDF8A.png + + + Assets\Emoji\Separated\D83CDF8B.png + + + Assets\Emoji\Separated\D83CDF8C.png + + + Assets\Emoji\Separated\D83CDF8D.png + + + Assets\Emoji\Separated\D83CDF8E.png + + + Assets\Emoji\Separated\D83CDF8F.png + + + Assets\Emoji\Separated\D83CDF90.png + + + Assets\Emoji\Separated\D83CDF91.png + + + Assets\Emoji\Separated\D83CDF92.png + + + Assets\Emoji\Separated\D83CDF93.png + + + Assets\Emoji\Separated\D83CDF96.png + + + Assets\Emoji\Separated\D83CDF97.png + + + Assets\Emoji\Separated\D83CDF9F.png + + + Assets\Emoji\Separated\D83CDFA0.png + + + Assets\Emoji\Separated\D83CDFA1.png + + + Assets\Emoji\Separated\D83CDFA2.png + + + Assets\Emoji\Separated\D83CDFA3.png + + + Assets\Emoji\Separated\D83CDFA4.png + + + Assets\Emoji\Separated\D83CDFA5.png + + + Assets\Emoji\Separated\D83CDFA6.png + + + Assets\Emoji\Separated\D83CDFA7.png + + + Assets\Emoji\Separated\D83CDFA8.png + + + Assets\Emoji\Separated\D83CDFA9.png + + + Assets\Emoji\Separated\D83CDFAA.png + + + Assets\Emoji\Separated\D83CDFAB.png + + + Assets\Emoji\Separated\D83CDFAC.png + + + Assets\Emoji\Separated\D83CDFAD.png + + + Assets\Emoji\Separated\D83CDFAE.png + + + Assets\Emoji\Separated\D83CDFAF.png + + + Assets\Emoji\Separated\D83CDFB0.png + + + Assets\Emoji\Separated\D83CDFB1.png + + + Assets\Emoji\Separated\D83CDFB2.png + + + Assets\Emoji\Separated\D83CDFB3.png + + + Assets\Emoji\Separated\D83CDFB4.png + + + Assets\Emoji\Separated\D83CDFB5.png + + + Assets\Emoji\Separated\D83CDFB6.png + + + Assets\Emoji\Separated\D83CDFB7.png + + + Assets\Emoji\Separated\D83CDFB8.png + + + Assets\Emoji\Separated\D83CDFB9.png + + + Assets\Emoji\Separated\D83CDFBA.png + + + Assets\Emoji\Separated\D83CDFBB.png + + + Assets\Emoji\Separated\D83CDFBC.png + + + Assets\Emoji\Separated\D83CDFBD.png + + + Assets\Emoji\Separated\D83CDFBE.png + + + Assets\Emoji\Separated\D83CDFBF.png + + + Assets\Emoji\Separated\D83CDFC0.png + + + Assets\Emoji\Separated\D83CDFC1.png + + + Assets\Emoji\Separated\D83CDFC2.png + + + Assets\Emoji\Separated\D83CDFC3.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFB.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFC.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFD.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFE.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFF.png + + + Assets\Emoji\Separated\D83CDFC4.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFB.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFC.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFD.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFE.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFF.png + + + Assets\Emoji\Separated\D83CDFC5.png + + + Assets\Emoji\Separated\D83CDFC6.png + + + Assets\Emoji\Separated\D83CDFC7.png + + + Assets\Emoji\Separated\D83CDFC7D83CDFFB.png + + + Assets\Emoji\Separated\D83CDFC7D83CDFFC.png + + + Assets\Emoji\Separated\D83CDFC7D83CDFFD.png + + + Assets\Emoji\Separated\D83CDFC7D83CDFFE.png + + + Assets\Emoji\Separated\D83CDFC7D83CDFFF.png + + + Assets\Emoji\Separated\D83CDFC8.png + + + Assets\Emoji\Separated\D83CDFC9.png + + + Assets\Emoji\Separated\D83CDFCA.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFB.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFC.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFD.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFE.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFF.png + + + Assets\Emoji\Separated\D83CDFCB.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFB.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFC.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFD.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFE.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFF.png + + + Assets\Emoji\Separated\D83CDFCC.png + + + Assets\Emoji\Separated\D83CDFCD.png + + + Assets\Emoji\Separated\D83CDFCE.png + + + Assets\Emoji\Separated\D83CDFCF.png + + + Assets\Emoji\Separated\D83CDFD0.png + + + Assets\Emoji\Separated\D83CDFD1.png + + + Assets\Emoji\Separated\D83CDFD2.png + + + Assets\Emoji\Separated\D83CDFD3.png + + + Assets\Emoji\Separated\D83CDFD4.png + + + Assets\Emoji\Separated\D83CDFD5.png + + + Assets\Emoji\Separated\D83CDFD6.png + + + Assets\Emoji\Separated\D83CDFD7.png + + + Assets\Emoji\Separated\D83CDFD8.png + + + Assets\Emoji\Separated\D83CDFD9.png + + + Assets\Emoji\Separated\D83CDFDA.png + + + Assets\Emoji\Separated\D83CDFDB.png + + + Assets\Emoji\Separated\D83CDFDC.png + + + Assets\Emoji\Separated\D83CDFDD.png + + + Assets\Emoji\Separated\D83CDFDE.png + + + Assets\Emoji\Separated\D83CDFDF.png + + + Assets\Emoji\Separated\D83CDFE0.png + + + Assets\Emoji\Separated\D83CDFE1.png + + + Assets\Emoji\Separated\D83CDFE2.png + + + Assets\Emoji\Separated\D83CDFE3.png + + + Assets\Emoji\Separated\D83CDFE4.png + + + Assets\Emoji\Separated\D83CDFE5.png + + + Assets\Emoji\Separated\D83CDFE6.png + + + Assets\Emoji\Separated\D83CDFE7.png + + + Assets\Emoji\Separated\D83CDFE8.png + + + Assets\Emoji\Separated\D83CDFE9.png + + + Assets\Emoji\Separated\D83CDFEA.png + + + Assets\Emoji\Separated\D83CDFEB.png + + + Assets\Emoji\Separated\D83CDFEC.png + + + Assets\Emoji\Separated\D83CDFED.png + + + Assets\Emoji\Separated\D83CDFEE.png + + + Assets\Emoji\Separated\D83CDFEF.png + + + Assets\Emoji\Separated\D83CDFF0.png + + + Assets\Emoji\Separated\D83CDFF3.png + + + Assets\Emoji\Separated\D83CDFF4.png + + + Assets\Emoji\Separated\D83CDFF5.png + + + Assets\Emoji\Separated\D83CDFF7.png + + + Assets\Emoji\Separated\D83CDFF8.png + + + Assets\Emoji\Separated\D83CDFF9.png + + + Assets\Emoji\Separated\D83CDFFA.png + + + Assets\Emoji\Separated\D83DDC00.png + + + Assets\Emoji\Separated\D83DDC01.png + + + Assets\Emoji\Separated\D83DDC02.png + + + Assets\Emoji\Separated\D83DDC03.png + + + Assets\Emoji\Separated\D83DDC04.png + + + Assets\Emoji\Separated\D83DDC05.png + + + Assets\Emoji\Separated\D83DDC06.png + + + Assets\Emoji\Separated\D83DDC07.png + + + Assets\Emoji\Separated\D83DDC08.png + + + Assets\Emoji\Separated\D83DDC09.png + + + Assets\Emoji\Separated\D83DDC0A.png + + + Assets\Emoji\Separated\D83DDC0B.png + + + Assets\Emoji\Separated\D83DDC0C.png + + + Assets\Emoji\Separated\D83DDC0D.png + + + Assets\Emoji\Separated\D83DDC0E.png + + + Assets\Emoji\Separated\D83DDC0F.png + + + Assets\Emoji\Separated\D83DDC10.png + + + Assets\Emoji\Separated\D83DDC11.png + + + Assets\Emoji\Separated\D83DDC12.png + + + Assets\Emoji\Separated\D83DDC13.png + + + Assets\Emoji\Separated\D83DDC14.png + + + Assets\Emoji\Separated\D83DDC15.png + + + Assets\Emoji\Separated\D83DDC16.png + + + Assets\Emoji\Separated\D83DDC17.png + + + Assets\Emoji\Separated\D83DDC18.png + + + Assets\Emoji\Separated\D83DDC19.png + + + Assets\Emoji\Separated\D83DDC1A.png + + + Assets\Emoji\Separated\D83DDC1B.png + + + Assets\Emoji\Separated\D83DDC1C.png + + + Assets\Emoji\Separated\D83DDC1D.png + + + Assets\Emoji\Separated\D83DDC1E.png + + + Assets\Emoji\Separated\D83DDC1F.png + + + Assets\Emoji\Separated\D83DDC20.png + + + Assets\Emoji\Separated\D83DDC21.png + + + Assets\Emoji\Separated\D83DDC22.png + + + Assets\Emoji\Separated\D83DDC23.png + + + Assets\Emoji\Separated\D83DDC24.png + + + Assets\Emoji\Separated\D83DDC25.png + + + Assets\Emoji\Separated\D83DDC26.png + + + Assets\Emoji\Separated\D83DDC27.png + + + Assets\Emoji\Separated\D83DDC28.png + + + Assets\Emoji\Separated\D83DDC29.png + + + Assets\Emoji\Separated\D83DDC2A.png + + + Assets\Emoji\Separated\D83DDC2B.png + + + Assets\Emoji\Separated\D83DDC2C.png + + + Assets\Emoji\Separated\D83DDC2D.png + + + Assets\Emoji\Separated\D83DDC2E.png + + + Assets\Emoji\Separated\D83DDC2F.png + + + Assets\Emoji\Separated\D83DDC30.png + + + Assets\Emoji\Separated\D83DDC31.png + + + Assets\Emoji\Separated\D83DDC32.png + + + Assets\Emoji\Separated\D83DDC33.png + + + Assets\Emoji\Separated\D83DDC34.png + + + Assets\Emoji\Separated\D83DDC35.png + + + Assets\Emoji\Separated\D83DDC36.png + + + Assets\Emoji\Separated\D83DDC37.png + + + Assets\Emoji\Separated\D83DDC38.png + + + Assets\Emoji\Separated\D83DDC39.png + + + Assets\Emoji\Separated\D83DDC3A.png + + + Assets\Emoji\Separated\D83DDC3B.png + + + Assets\Emoji\Separated\D83DDC3C.png + + + Assets\Emoji\Separated\D83DDC3D.png + + + Assets\Emoji\Separated\D83DDC3E.png + + + Assets\Emoji\Separated\D83DDC3F.png + + + Assets\Emoji\Separated\D83DDC40.png + + + Assets\Emoji\Separated\D83DDC41.png + + + Assets\Emoji\Separated\D83DDC42.png + + + Assets\Emoji\Separated\D83DDC42D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC42D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC42D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC42D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC42D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC43.png + + + Assets\Emoji\Separated\D83DDC43D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC43D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC43D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC43D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC43D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC44.png + + + Assets\Emoji\Separated\D83DDC45.png + + + Assets\Emoji\Separated\D83DDC46.png + + + Assets\Emoji\Separated\D83DDC46D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC46D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC46D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC46D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC46D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC47.png + + + Assets\Emoji\Separated\D83DDC47D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC47D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC47D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC47D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC47D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC48.png + + + Assets\Emoji\Separated\D83DDC48D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC48D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC48D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC48D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC48D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC49.png + + + Assets\Emoji\Separated\D83DDC49D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC49D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC49D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC49D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC49D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC4A.png + + + Assets\Emoji\Separated\D83DDC4AD83CDFFB.png + + + Assets\Emoji\Separated\D83DDC4AD83CDFFC.png + + + Assets\Emoji\Separated\D83DDC4AD83CDFFD.png + + + Assets\Emoji\Separated\D83DDC4AD83CDFFE.png + + + Assets\Emoji\Separated\D83DDC4AD83CDFFF.png + + + Assets\Emoji\Separated\D83DDC4B.png + + + Assets\Emoji\Separated\D83DDC4BD83CDFFB.png + + + Assets\Emoji\Separated\D83DDC4BD83CDFFC.png + + + Assets\Emoji\Separated\D83DDC4BD83CDFFD.png + + + Assets\Emoji\Separated\D83DDC4BD83CDFFE.png + + + Assets\Emoji\Separated\D83DDC4BD83CDFFF.png + + + Assets\Emoji\Separated\D83DDC4C.png + + + Assets\Emoji\Separated\D83DDC4CD83CDFFB.png + + + Assets\Emoji\Separated\D83DDC4CD83CDFFC.png + + + Assets\Emoji\Separated\D83DDC4CD83CDFFD.png + + + Assets\Emoji\Separated\D83DDC4CD83CDFFE.png + + + Assets\Emoji\Separated\D83DDC4CD83CDFFF.png + + + Assets\Emoji\Separated\D83DDC4D.png + + + Assets\Emoji\Separated\D83DDC4DD83CDFFB.png + + + Assets\Emoji\Separated\D83DDC4DD83CDFFC.png + + + Assets\Emoji\Separated\D83DDC4DD83CDFFD.png + + + Assets\Emoji\Separated\D83DDC4DD83CDFFE.png + + + Assets\Emoji\Separated\D83DDC4DD83CDFFF.png + + + Assets\Emoji\Separated\D83DDC4E.png + + + Assets\Emoji\Separated\D83DDC4ED83CDFFB.png + + + Assets\Emoji\Separated\D83DDC4ED83CDFFC.png + + + Assets\Emoji\Separated\D83DDC4ED83CDFFD.png + + + Assets\Emoji\Separated\D83DDC4ED83CDFFE.png + + + Assets\Emoji\Separated\D83DDC4ED83CDFFF.png + + + Assets\Emoji\Separated\D83DDC4F.png + + + Assets\Emoji\Separated\D83DDC4FD83CDFFB.png + + + Assets\Emoji\Separated\D83DDC4FD83CDFFC.png + + + Assets\Emoji\Separated\D83DDC4FD83CDFFD.png + + + Assets\Emoji\Separated\D83DDC4FD83CDFFE.png + + + Assets\Emoji\Separated\D83DDC4FD83CDFFF.png + + + Assets\Emoji\Separated\D83DDC50.png + + + Assets\Emoji\Separated\D83DDC50D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC50D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC50D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC50D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC50D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC51.png + + + Assets\Emoji\Separated\D83DDC52.png + + + Assets\Emoji\Separated\D83DDC53.png + + + Assets\Emoji\Separated\D83DDC54.png + + + Assets\Emoji\Separated\D83DDC55.png + + + Assets\Emoji\Separated\D83DDC56.png + + + Assets\Emoji\Separated\D83DDC57.png + + + Assets\Emoji\Separated\D83DDC58.png + + + Assets\Emoji\Separated\D83DDC59.png + + + Assets\Emoji\Separated\D83DDC5A.png + + + Assets\Emoji\Separated\D83DDC5B.png + + + Assets\Emoji\Separated\D83DDC5C.png + + + Assets\Emoji\Separated\D83DDC5D.png + + + Assets\Emoji\Separated\D83DDC5E.png + + + Assets\Emoji\Separated\D83DDC5F.png + + + Assets\Emoji\Separated\D83DDC60.png + + + Assets\Emoji\Separated\D83DDC61.png + + + Assets\Emoji\Separated\D83DDC62.png + + + Assets\Emoji\Separated\D83DDC63.png + + + Assets\Emoji\Separated\D83DDC64.png + + + Assets\Emoji\Separated\D83DDC65.png + + + Assets\Emoji\Separated\D83DDC66.png + + + Assets\Emoji\Separated\D83DDC66D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC66D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC66D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC66D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC66D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC67.png + + + Assets\Emoji\Separated\D83DDC67D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC67D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC67D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC67D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC67D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC68.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC69.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC6A.png + + + Assets\Emoji\Separated\D83DDC6B.png + + + Assets\Emoji\Separated\D83DDC6C.png + + + Assets\Emoji\Separated\D83DDC6D.png + + + Assets\Emoji\Separated\D83DDC6E.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFB.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFC.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFD.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFE.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFF.png + + + Assets\Emoji\Separated\D83DDC6F.png + + + Assets\Emoji\Separated\D83DDC70.png + + + Assets\Emoji\Separated\D83DDC70D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC70D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC70D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC70D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC70D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC71.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC72.png + + + Assets\Emoji\Separated\D83DDC72D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC72D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC72D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC72D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC72D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC73.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC74.png + + + Assets\Emoji\Separated\D83DDC74D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC74D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC74D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC74D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC74D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC75.png + + + Assets\Emoji\Separated\D83DDC75D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC75D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC75D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC75D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC75D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC76.png + + + Assets\Emoji\Separated\D83DDC76D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC76D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC76D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC76D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC76D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC77.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC78.png + + + Assets\Emoji\Separated\D83DDC78D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC78D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC78D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC78D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC78D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC79.png + + + Assets\Emoji\Separated\D83DDC7A.png + + + Assets\Emoji\Separated\D83DDC7B.png + + + Assets\Emoji\Separated\D83DDC7C.png + + + Assets\Emoji\Separated\D83DDC7CD83CDFFB.png + + + Assets\Emoji\Separated\D83DDC7CD83CDFFC.png + + + Assets\Emoji\Separated\D83DDC7CD83CDFFD.png + + + Assets\Emoji\Separated\D83DDC7CD83CDFFE.png + + + Assets\Emoji\Separated\D83DDC7CD83CDFFF.png + + + Assets\Emoji\Separated\D83DDC7D.png + + + Assets\Emoji\Separated\D83DDC7E.png + + + Assets\Emoji\Separated\D83DDC7F.png + + + Assets\Emoji\Separated\D83DDC80.png + + + Assets\Emoji\Separated\D83DDC81.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC82.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC83.png + + + Assets\Emoji\Separated\D83DDC83D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC83D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC83D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC83D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC83D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC84.png + + + Assets\Emoji\Separated\D83DDC85.png + + + Assets\Emoji\Separated\D83DDC85D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC85D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC85D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC85D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC85D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC86.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC87.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC88.png + + + Assets\Emoji\Separated\D83DDC89.png + + + Assets\Emoji\Separated\D83DDC8A.png + + + Assets\Emoji\Separated\D83DDC8B.png + + + Assets\Emoji\Separated\D83DDC8C.png + + + Assets\Emoji\Separated\D83DDC8D.png + + + Assets\Emoji\Separated\D83DDC8E.png + + + Assets\Emoji\Separated\D83DDC8F.png + + + Assets\Emoji\Separated\D83DDC90.png + + + Assets\Emoji\Separated\D83DDC91.png + + + Assets\Emoji\Separated\D83DDC92.png + + + Assets\Emoji\Separated\D83DDC93.png + + + Assets\Emoji\Separated\D83DDC94.png + + + Assets\Emoji\Separated\D83DDC95.png + + + Assets\Emoji\Separated\D83DDC96.png + + + Assets\Emoji\Separated\D83DDC97.png + + + Assets\Emoji\Separated\D83DDC98.png + + + Assets\Emoji\Separated\D83DDC99.png + + + Assets\Emoji\Separated\D83DDC9A.png + + + Assets\Emoji\Separated\D83DDC9B.png + + + Assets\Emoji\Separated\D83DDC9C.png + + + Assets\Emoji\Separated\D83DDC9D.png + + + Assets\Emoji\Separated\D83DDC9E.png + + + Assets\Emoji\Separated\D83DDC9F.png + + + Assets\Emoji\Separated\D83DDCA0.png + + + Assets\Emoji\Separated\D83DDCA1.png + + + Assets\Emoji\Separated\D83DDCA2.png + + + Assets\Emoji\Separated\D83DDCA3.png + + + Assets\Emoji\Separated\D83DDCA4.png + + + Assets\Emoji\Separated\D83DDCA5.png + + + Assets\Emoji\Separated\D83DDCA6.png + + + Assets\Emoji\Separated\D83DDCA7.png + + + Assets\Emoji\Separated\D83DDCA8.png + + + Assets\Emoji\Separated\D83DDCA9.png + + + Assets\Emoji\Separated\D83DDCAA.png + + + Assets\Emoji\Separated\D83DDCAAD83CDFFB.png + + + Assets\Emoji\Separated\D83DDCAAD83CDFFC.png + + + Assets\Emoji\Separated\D83DDCAAD83CDFFD.png + + + Assets\Emoji\Separated\D83DDCAAD83CDFFE.png + + + Assets\Emoji\Separated\D83DDCAAD83CDFFF.png + + + Assets\Emoji\Separated\D83DDCAB.png + + + Assets\Emoji\Separated\D83DDCAC.png + + + Assets\Emoji\Separated\D83DDCAD.png + + + Assets\Emoji\Separated\D83DDCAE.png + + + Assets\Emoji\Separated\D83DDCAF.png + + + Assets\Emoji\Separated\D83DDCB0.png + + + Assets\Emoji\Separated\D83DDCB1.png + + + Assets\Emoji\Separated\D83DDCB2.png + + + Assets\Emoji\Separated\D83DDCB3.png + + + Assets\Emoji\Separated\D83DDCB4.png + + + Assets\Emoji\Separated\D83DDCB5.png + + + Assets\Emoji\Separated\D83DDCB6.png + + + Assets\Emoji\Separated\D83DDCB7.png + + + Assets\Emoji\Separated\D83DDCB8.png + + + Assets\Emoji\Separated\D83DDCB9.png + + + Assets\Emoji\Separated\D83DDCBA.png + + + Assets\Emoji\Separated\D83DDCBB.png + + + Assets\Emoji\Separated\D83DDCBC.png + + + Assets\Emoji\Separated\D83DDCBD.png + + + Assets\Emoji\Separated\D83DDCBE.png + + + Assets\Emoji\Separated\D83DDCBF.png + + + Assets\Emoji\Separated\D83DDCC0.png + + + Assets\Emoji\Separated\D83DDCC1.png + + + Assets\Emoji\Separated\D83DDCC2.png + + + Assets\Emoji\Separated\D83DDCC3.png + + + Assets\Emoji\Separated\D83DDCC4.png + + + Assets\Emoji\Separated\D83DDCC5.png + + + Assets\Emoji\Separated\D83DDCC6.png + + + Assets\Emoji\Separated\D83DDCC7.png + + + Assets\Emoji\Separated\D83DDCC70.png + + + Assets\Emoji\Separated\D83DDCC70D83CDFFB.png + + + Assets\Emoji\Separated\D83DDCC70D83CDFFC.png + + + Assets\Emoji\Separated\D83DDCC70D83CDFFD.png + + + Assets\Emoji\Separated\D83DDCC70D83CDFFE.png + + + Assets\Emoji\Separated\D83DDCC70D83CDFFF.png + + + Assets\Emoji\Separated\D83DDCC77.png + + + Assets\Emoji\Separated\D83DDCC77D83CDFFB.png + + + Assets\Emoji\Separated\D83DDCC77D83CDFFC.png + + + Assets\Emoji\Separated\D83DDCC77D83CDFFD.png + + + Assets\Emoji\Separated\D83DDCC77D83CDFFE.png + + + Assets\Emoji\Separated\D83DDCC77D83CDFFF.png + + + Assets\Emoji\Separated\D83DDCC78.png + + + Assets\Emoji\Separated\D83DDCC78D83CDFFB.png + + + Assets\Emoji\Separated\D83DDCC78D83CDFFC.png + + + Assets\Emoji\Separated\D83DDCC78D83CDFFD.png + + + Assets\Emoji\Separated\D83DDCC78D83CDFFE.png + + + Assets\Emoji\Separated\D83DDCC78D83CDFFF.png + + + Assets\Emoji\Separated\D83DDCC7C.png + + + Assets\Emoji\Separated\D83DDCC7CD83CDFFB.png + + + Assets\Emoji\Separated\D83DDCC7CD83CDFFC.png + + + Assets\Emoji\Separated\D83DDCC7CD83CDFFD.png + + + Assets\Emoji\Separated\D83DDCC7CD83CDFFE.png + + + Assets\Emoji\Separated\D83DDCC7CD83CDFFF.png + + + Assets\Emoji\Separated\D83DDCC8.png + + + Assets\Emoji\Separated\D83DDCC81.png + + + Assets\Emoji\Separated\D83DDCC81D83CDFFB.png + + + Assets\Emoji\Separated\D83DDCC81D83CDFFC.png + + + Assets\Emoji\Separated\D83DDCC81D83CDFFD.png + + + Assets\Emoji\Separated\D83DDCC81D83CDFFE.png + + + Assets\Emoji\Separated\D83DDCC81D83CDFFF.png + + + Assets\Emoji\Separated\D83DDCC82.png + + + Assets\Emoji\Separated\D83DDCC82D83CDFFB.png + + + Assets\Emoji\Separated\D83DDCC82D83CDFFC.png + + + Assets\Emoji\Separated\D83DDCC82D83CDFFD.png + + + Assets\Emoji\Separated\D83DDCC82D83CDFFE.png + + + Assets\Emoji\Separated\D83DDCC82D83CDFFF.png + + + Assets\Emoji\Separated\D83DDCC83.png + + + Assets\Emoji\Separated\D83DDCC83D83CDFFB.png + + + Assets\Emoji\Separated\D83DDCC83D83CDFFC.png + + + Assets\Emoji\Separated\D83DDCC83D83CDFFD.png + + + Assets\Emoji\Separated\D83DDCC83D83CDFFE.png + + + Assets\Emoji\Separated\D83DDCC83D83CDFFF.png + + + Assets\Emoji\Separated\D83DDCC9.png + + + Assets\Emoji\Separated\D83DDCCA.png + + + Assets\Emoji\Separated\D83DDCCB.png + + + Assets\Emoji\Separated\D83DDCCC.png + + + Assets\Emoji\Separated\D83DDCCD.png + + + Assets\Emoji\Separated\D83DDCCE.png + + + Assets\Emoji\Separated\D83DDCCF.png + + + Assets\Emoji\Separated\D83DDCD0.png + + + Assets\Emoji\Separated\D83DDCD1.png + + + Assets\Emoji\Separated\D83DDCD2.png + + + Assets\Emoji\Separated\D83DDCD3.png + + + Assets\Emoji\Separated\D83DDCD4.png + + + Assets\Emoji\Separated\D83DDCD5.png + + + Assets\Emoji\Separated\D83DDCD6.png + + + Assets\Emoji\Separated\D83DDCD7.png + + + Assets\Emoji\Separated\D83DDCD8.png + + + Assets\Emoji\Separated\D83DDCD9.png + + + Assets\Emoji\Separated\D83DDCDA.png + + + Assets\Emoji\Separated\D83DDCDB.png + + + Assets\Emoji\Separated\D83DDCDC.png + + + Assets\Emoji\Separated\D83DDCDD.png + + + Assets\Emoji\Separated\D83DDCDE.png + + + Assets\Emoji\Separated\D83DDCDF.png + + + Assets\Emoji\Separated\D83DDCE0.png + + + Assets\Emoji\Separated\D83DDCE1.png + + + Assets\Emoji\Separated\D83DDCE2.png + + + Assets\Emoji\Separated\D83DDCE3.png + + + Assets\Emoji\Separated\D83DDCE4.png + + + Assets\Emoji\Separated\D83DDCE45.png + + + Assets\Emoji\Separated\D83DDCE45D83CDFFB.png + + + Assets\Emoji\Separated\D83DDCE45D83CDFFC.png + + + Assets\Emoji\Separated\D83DDCE45D83CDFFD.png + + + Assets\Emoji\Separated\D83DDCE45D83CDFFE.png + + + Assets\Emoji\Separated\D83DDCE45D83CDFFF.png + + + Assets\Emoji\Separated\D83DDCE46.png + + + Assets\Emoji\Separated\D83DDCE46D83CDFFB.png + + + Assets\Emoji\Separated\D83DDCE46D83CDFFC.png + + + Assets\Emoji\Separated\D83DDCE46D83CDFFD.png + + + Assets\Emoji\Separated\D83DDCE46D83CDFFE.png + + + Assets\Emoji\Separated\D83DDCE46D83CDFFF.png + + + Assets\Emoji\Separated\D83DDCE47.png + + + Assets\Emoji\Separated\D83DDCE47D83CDFFB.png + + + Assets\Emoji\Separated\D83DDCE47D83CDFFC.png + + + Assets\Emoji\Separated\D83DDCE47D83CDFFD.png + + + Assets\Emoji\Separated\D83DDCE47D83CDFFE.png + + + Assets\Emoji\Separated\D83DDCE47D83CDFFF.png + + + Assets\Emoji\Separated\D83DDCE5.png + + + Assets\Emoji\Separated\D83DDCE6.png + + + Assets\Emoji\Separated\D83DDCE7.png + + + Assets\Emoji\Separated\D83DDCE8.png + + + Assets\Emoji\Separated\D83DDCE9.png + + + Assets\Emoji\Separated\D83DDCEA.png + + + Assets\Emoji\Separated\D83DDCEB.png + + + Assets\Emoji\Separated\D83DDCEC.png + + + Assets\Emoji\Separated\D83DDCED.png + + + Assets\Emoji\Separated\D83DDCEE.png + + + Assets\Emoji\Separated\D83DDCEF.png + + + Assets\Emoji\Separated\D83DDCF0.png + + + Assets\Emoji\Separated\D83DDCF1.png + + + Assets\Emoji\Separated\D83DDCF2.png + + + Assets\Emoji\Separated\D83DDCF3.png + + + Assets\Emoji\Separated\D83DDCF4.png + + + Assets\Emoji\Separated\D83DDCF5.png + + + Assets\Emoji\Separated\D83DDCF6.png + + + Assets\Emoji\Separated\D83DDCF7.png + + + Assets\Emoji\Separated\D83DDCF9.png + + + Assets\Emoji\Separated\D83DDCFA.png + + + Assets\Emoji\Separated\D83DDCFB.png + + + Assets\Emoji\Separated\D83DDCFC.png + + + Assets\Emoji\Separated\D83DDCFF.png + + + Assets\Emoji\Separated\D83DDD00.png + + + Assets\Emoji\Separated\D83DDD01.png + + + Assets\Emoji\Separated\D83DDD02.png + + + Assets\Emoji\Separated\D83DDD03.png + + + Assets\Emoji\Separated\D83DDD04.png + + + Assets\Emoji\Separated\D83DDD05.png + + + Assets\Emoji\Separated\D83DDD06.png + + + Assets\Emoji\Separated\D83DDD07.png + + + Assets\Emoji\Separated\D83DDD08.png + + + Assets\Emoji\Separated\D83DDD09.png + + + Assets\Emoji\Separated\D83DDD0A.png + + + Assets\Emoji\Separated\D83DDD0B.png + + + Assets\Emoji\Separated\D83DDD0C.png + + + Assets\Emoji\Separated\D83DDD0D.png + + + Assets\Emoji\Separated\D83DDD0E.png + + + Assets\Emoji\Separated\D83DDD0F.png + + + Assets\Emoji\Separated\D83DDD10.png + + + Assets\Emoji\Separated\D83DDD11.png + + + Assets\Emoji\Separated\D83DDD12.png + + + Assets\Emoji\Separated\D83DDD13.png + + + Assets\Emoji\Separated\D83DDD14.png + + + Assets\Emoji\Separated\D83DDD15.png + + + Assets\Emoji\Separated\D83DDD16.png + + + Assets\Emoji\Separated\D83DDD17.png + + + Assets\Emoji\Separated\D83DDD18.png + + + Assets\Emoji\Separated\D83DDD19.png + + + Assets\Emoji\Separated\D83DDD1A.png + + + Assets\Emoji\Separated\D83DDD1B.png + + + Assets\Emoji\Separated\D83DDD1C.png + + + Assets\Emoji\Separated\D83DDD1D.png + + + Assets\Emoji\Separated\D83DDD1E.png + + + Assets\Emoji\Separated\D83DDD1F.png + + + Assets\Emoji\Separated\D83DDD20.png + + + Assets\Emoji\Separated\D83DDD21.png + + + Assets\Emoji\Separated\D83DDD22.png + + + Assets\Emoji\Separated\D83DDD23.png + + + Assets\Emoji\Separated\D83DDD24.png + + + Assets\Emoji\Separated\D83DDD25.png + + + Assets\Emoji\Separated\D83DDD26.png + + + Assets\Emoji\Separated\D83DDD27.png + + + Assets\Emoji\Separated\D83DDD28.png + + + Assets\Emoji\Separated\D83DDD29.png + + + Assets\Emoji\Separated\D83DDD2A.png + + + Assets\Emoji\Separated\D83DDD2B.png + + + Assets\Emoji\Separated\D83DDD2C.png + + + Assets\Emoji\Separated\D83DDD2D.png + + + Assets\Emoji\Separated\D83DDD2E.png + + + Assets\Emoji\Separated\D83DDD2F.png + + + Assets\Emoji\Separated\D83DDD30.png + + + Assets\Emoji\Separated\D83DDD31.png + + + Assets\Emoji\Separated\D83DDD32.png + + + Assets\Emoji\Separated\D83DDD33.png + + + Assets\Emoji\Separated\D83DDD34.png + + + Assets\Emoji\Separated\D83DDD35.png + + + Assets\Emoji\Separated\D83DDD36.png + + + Assets\Emoji\Separated\D83DDD37.png + + + Assets\Emoji\Separated\D83DDD38.png + + + Assets\Emoji\Separated\D83DDD39.png + + + Assets\Emoji\Separated\D83DDD3A.png + + + Assets\Emoji\Separated\D83DDD3B.png + + + Assets\Emoji\Separated\D83DDD3C.png + + + Assets\Emoji\Separated\D83DDD3D.png + + + Assets\Emoji\Separated\D83DDD4A.png + + + Assets\Emoji\Separated\D83DDD4B.png + + + Assets\Emoji\Separated\D83DDD4C.png + + + Assets\Emoji\Separated\D83DDD4D.png + + + Assets\Emoji\Separated\D83DDD50.png + + + Assets\Emoji\Separated\D83DDD51.png + + + Assets\Emoji\Separated\D83DDD52.png + + + Assets\Emoji\Separated\D83DDD53.png + + + Assets\Emoji\Separated\D83DDD54.png + + + Assets\Emoji\Separated\D83DDD55.png + + + Assets\Emoji\Separated\D83DDD56.png + + + Assets\Emoji\Separated\D83DDD57.png + + + Assets\Emoji\Separated\D83DDD58.png + + + Assets\Emoji\Separated\D83DDD59.png + + + Assets\Emoji\Separated\D83DDD5A.png + + + Assets\Emoji\Separated\D83DDD5B.png + + + Assets\Emoji\Separated\D83DDD5C.png + + + Assets\Emoji\Separated\D83DDD5D.png + + + Assets\Emoji\Separated\D83DDD5E.png + + + Assets\Emoji\Separated\D83DDD5F.png + + + Assets\Emoji\Separated\D83DDD60.png + + + Assets\Emoji\Separated\D83DDD61.png + + + Assets\Emoji\Separated\D83DDD62.png + + + Assets\Emoji\Separated\D83DDD63.png + + + Assets\Emoji\Separated\D83DDD64.png + + + Assets\Emoji\Separated\D83DDD65.png + + + Assets\Emoji\Separated\D83DDD66.png + + + Assets\Emoji\Separated\D83DDD67.png + + + Assets\Emoji\Separated\D83DDD6F.png + + + Assets\Emoji\Separated\D83DDD73.png + + + Assets\Emoji\Separated\D83DDD74.png + + + Assets\Emoji\Separated\D83DDD75.png + + + Assets\Emoji\Separated\D83DDD76.png + + + Assets\Emoji\Separated\D83DDD77.png + + + Assets\Emoji\Separated\D83DDD78.png + + + Assets\Emoji\Separated\D83DDD87.png + + + Assets\Emoji\Separated\D83DDD8A.png + + + Assets\Emoji\Separated\D83DDD8B.png + + + Assets\Emoji\Separated\D83DDD8C.png + + + Assets\Emoji\Separated\D83DDD8D.png + + + Assets\Emoji\Separated\D83DDD90.png + + + Assets\Emoji\Separated\D83DDD90D83CDFFB.png + + + Assets\Emoji\Separated\D83DDD90D83CDFFC.png + + + Assets\Emoji\Separated\D83DDD90D83CDFFD.png + + + Assets\Emoji\Separated\D83DDD90D83CDFFE.png + + + Assets\Emoji\Separated\D83DDD90D83CDFFF.png + + + Assets\Emoji\Separated\D83DDD95.png + + + Assets\Emoji\Separated\D83DDD95D83CDFFB.png + + + Assets\Emoji\Separated\D83DDD95D83CDFFC.png + + + Assets\Emoji\Separated\D83DDD95D83CDFFD.png + + + Assets\Emoji\Separated\D83DDD95D83CDFFE.png + + + Assets\Emoji\Separated\D83DDD95D83CDFFF.png + + + Assets\Emoji\Separated\D83DDD96.png + + + Assets\Emoji\Separated\D83DDD96D83CDFFB.png + + + Assets\Emoji\Separated\D83DDD96D83CDFFC.png + + + Assets\Emoji\Separated\D83DDD96D83CDFFD.png + + + Assets\Emoji\Separated\D83DDD96D83CDFFE.png + + + Assets\Emoji\Separated\D83DDD96D83CDFFF.png + + + Assets\Emoji\Separated\D83DDDBC.png + + + Assets\Emoji\Separated\D83DDDC2.png + + + Assets\Emoji\Separated\D83DDDC3.png + + + Assets\Emoji\Separated\D83DDDC4.png + + + Assets\Emoji\Separated\D83DDDD1.png + + + Assets\Emoji\Separated\D83DDDD2.png + + + Assets\Emoji\Separated\D83DDDD3.png + + + Assets\Emoji\Separated\D83DDDDD.png + + + Assets\Emoji\Separated\D83DDDDE.png + + + Assets\Emoji\Separated\D83DDDE1.png + + + Assets\Emoji\Separated\D83DDDE3.png + + + Assets\Emoji\Separated\D83DDDF3.png + + + Assets\Emoji\Separated\D83DDDFA.png + + + Assets\Emoji\Separated\D83DDDFB.png + + + Assets\Emoji\Separated\D83DDDFC.png + + + Assets\Emoji\Separated\D83DDDFD.png + + + Assets\Emoji\Separated\D83DDDFE.png + + + Assets\Emoji\Separated\D83DDDFF.png + + + Assets\Emoji\Separated\D83DDE00.png + + + Assets\Emoji\Separated\D83DDE01.png + + + Assets\Emoji\Separated\D83DDE02.png + + + Assets\Emoji\Separated\D83DDE03.png + + + Assets\Emoji\Separated\D83DDE04.png + + + Assets\Emoji\Separated\D83DDE05.png + + + Assets\Emoji\Separated\D83DDE06.png + + + Assets\Emoji\Separated\D83DDE07.png + + + Assets\Emoji\Separated\D83DDE08.png + + + Assets\Emoji\Separated\D83DDE09.png + + + Assets\Emoji\Separated\D83DDE0A.png + + + Assets\Emoji\Separated\D83DDE0B.png + + + Assets\Emoji\Separated\D83DDE0C.png + + + Assets\Emoji\Separated\D83DDE0D.png + + + Assets\Emoji\Separated\D83DDE0E.png + + + Assets\Emoji\Separated\D83DDE0F.png + + + Assets\Emoji\Separated\D83DDE10.png + + + Assets\Emoji\Separated\D83DDE11.png + + + Assets\Emoji\Separated\D83DDE12.png + + + Assets\Emoji\Separated\D83DDE13.png + + + Assets\Emoji\Separated\D83DDE14.png + + + Assets\Emoji\Separated\D83DDE15.png + + + Assets\Emoji\Separated\D83DDE16.png + + + Assets\Emoji\Separated\D83DDE17.png + + + Assets\Emoji\Separated\D83DDE18.png + + + Assets\Emoji\Separated\D83DDE19.png + + + Assets\Emoji\Separated\D83DDE1A.png + + + Assets\Emoji\Separated\D83DDE1B.png + + + Assets\Emoji\Separated\D83DDE1C.png + + + Assets\Emoji\Separated\D83DDE1D.png + + + Assets\Emoji\Separated\D83DDE1E.png + + + Assets\Emoji\Separated\D83DDE1F.png + + + Assets\Emoji\Separated\D83DDE20.png + + + Assets\Emoji\Separated\D83DDE21.png + + + Assets\Emoji\Separated\D83DDE22.png + + + Assets\Emoji\Separated\D83DDE23.png + + + Assets\Emoji\Separated\D83DDE24.png + + + Assets\Emoji\Separated\D83DDE25.png + + + Assets\Emoji\Separated\D83DDE26.png + + + Assets\Emoji\Separated\D83DDE27.png + + + Assets\Emoji\Separated\D83DDE28.png + + + Assets\Emoji\Separated\D83DDE29.png + + + Assets\Emoji\Separated\D83DDE2A.png + + + Assets\Emoji\Separated\D83DDE2B.png + + + Assets\Emoji\Separated\D83DDE2C.png + + + Assets\Emoji\Separated\D83DDE2D.png + + + Assets\Emoji\Separated\D83DDE2E.png + + + Assets\Emoji\Separated\D83DDE2F.png + + + Assets\Emoji\Separated\D83DDE30.png + + + Assets\Emoji\Separated\D83DDE31.png + + + Assets\Emoji\Separated\D83DDE32.png + + + Assets\Emoji\Separated\D83DDE33.png + + + Assets\Emoji\Separated\D83DDE34.png + + + Assets\Emoji\Separated\D83DDE35.png + + + Assets\Emoji\Separated\D83DDE36.png + + + Assets\Emoji\Separated\D83DDE37.png + + + Assets\Emoji\Separated\D83DDE38.png + + + Assets\Emoji\Separated\D83DDE39.png + + + Assets\Emoji\Separated\D83DDE3A.png + + + Assets\Emoji\Separated\D83DDE3B.png + + + Assets\Emoji\Separated\D83DDE3C.png + + + Assets\Emoji\Separated\D83DDE3D.png + + + Assets\Emoji\Separated\D83DDE3E.png + + + Assets\Emoji\Separated\D83DDE3F.png + + + Assets\Emoji\Separated\D83DDE40.png + + + Assets\Emoji\Separated\D83DDE45.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFB.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFC.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFD.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFE.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFF.png + + + Assets\Emoji\Separated\D83DDE46.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFB.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFC.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFD.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFE.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFF.png + + + Assets\Emoji\Separated\D83DDE47.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFB.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFC.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFD.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFE.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFF.png + + + Assets\Emoji\Separated\D83DDE48.png + + + Assets\Emoji\Separated\D83DDE49.png + + + Assets\Emoji\Separated\D83DDE4A.png + + + Assets\Emoji\Separated\D83DDE4B.png + + + Assets\Emoji\Separated\D83DDE4C.png + + + Assets\Emoji\Separated\D83DDE4CD83CDFFB.png + + + Assets\Emoji\Separated\D83DDE4CD83CDFFC.png + + + Assets\Emoji\Separated\D83DDE4CD83CDFFD.png + + + Assets\Emoji\Separated\D83DDE4CD83CDFFE.png + + + Assets\Emoji\Separated\D83DDE4CD83CDFFF.png + + + Assets\Emoji\Separated\D83DDE4D.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFB.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFC.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFD.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFE.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFF.png + + + Assets\Emoji\Separated\D83DDE4E.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFB.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFC.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFD.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFE.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFF.png + + + Assets\Emoji\Separated\D83DDE4F.png + + + Assets\Emoji\Separated\D83DDE4FD83CDFFB.png + + + Assets\Emoji\Separated\D83DDE4FD83CDFFC.png + + + Assets\Emoji\Separated\D83DDE4FD83CDFFD.png + + + Assets\Emoji\Separated\D83DDE4FD83CDFFE.png + + + Assets\Emoji\Separated\D83DDE4FD83CDFFF.png + + + Assets\Emoji\Separated\D83DDE80.png + + + Assets\Emoji\Separated\D83DDE81.png + + + Assets\Emoji\Separated\D83DDE82.png + + + Assets\Emoji\Separated\D83DDE83.png + + + Assets\Emoji\Separated\D83DDE84.png + + + Assets\Emoji\Separated\D83DDE85.png + + + Assets\Emoji\Separated\D83DDE86.png + + + Assets\Emoji\Separated\D83DDE87.png + + + Assets\Emoji\Separated\D83DDE88.png + + + Assets\Emoji\Separated\D83DDE89.png + + + Assets\Emoji\Separated\D83DDE8A.png + + + Assets\Emoji\Separated\D83DDE8B.png + + + Assets\Emoji\Separated\D83DDE8C.png + + + Assets\Emoji\Separated\D83DDE8D.png + + + Assets\Emoji\Separated\D83DDE8E.png + + + Assets\Emoji\Separated\D83DDE8F.png + + + Assets\Emoji\Separated\D83DDE90.png + + + Assets\Emoji\Separated\D83DDE91.png + + + Assets\Emoji\Separated\D83DDE92.png + + + Assets\Emoji\Separated\D83DDE93.png + + + Assets\Emoji\Separated\D83DDE94.png + + + Assets\Emoji\Separated\D83DDE95.png + + + Assets\Emoji\Separated\D83DDE96.png + + + Assets\Emoji\Separated\D83DDE97.png + + + Assets\Emoji\Separated\D83DDE98.png + + + Assets\Emoji\Separated\D83DDE99.png + + + Assets\Emoji\Separated\D83DDE9A.png + + + Assets\Emoji\Separated\D83DDE9B.png + + + Assets\Emoji\Separated\D83DDE9C.png + + + Assets\Emoji\Separated\D83DDE9D.png + + + Assets\Emoji\Separated\D83DDE9E.png + + + Assets\Emoji\Separated\D83DDE9F.png + + + Assets\Emoji\Separated\D83DDEA0.png + + + Assets\Emoji\Separated\D83DDEA1.png + + + Assets\Emoji\Separated\D83DDEA2.png + + + Assets\Emoji\Separated\D83DDEA3.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFB.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFC.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFD.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFE.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFF.png + + + Assets\Emoji\Separated\D83DDEA4.png + + + Assets\Emoji\Separated\D83DDEA5.png + + + Assets\Emoji\Separated\D83DDEA6.png + + + Assets\Emoji\Separated\D83DDEA7.png + + + Assets\Emoji\Separated\D83DDEA8.png + + + Assets\Emoji\Separated\D83DDEA9.png + + + Assets\Emoji\Separated\D83DDEAA.png + + + Assets\Emoji\Separated\D83DDEAB.png + + + Assets\Emoji\Separated\D83DDEAC.png + + + Assets\Emoji\Separated\D83DDEAD.png + + + Assets\Emoji\Separated\D83DDEAE.png + + + Assets\Emoji\Separated\D83DDEAF.png + + + Assets\Emoji\Separated\D83DDEB0.png + + + Assets\Emoji\Separated\D83DDEB1.png + + + Assets\Emoji\Separated\D83DDEB2.png + + + Assets\Emoji\Separated\D83DDEB3.png + + + Assets\Emoji\Separated\D83DDEB4.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFB.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFC.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFD.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFE.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFF.png + + + Assets\Emoji\Separated\D83DDEB5.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFB.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFC.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFD.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFE.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFF.png + + + Assets\Emoji\Separated\D83DDEB6.png + + + Assets\Emoji\Separated\D83DDEB7.png + + + Assets\Emoji\Separated\D83DDEB8.png + + + Assets\Emoji\Separated\D83DDEB9.png + + + Assets\Emoji\Separated\D83DDEBA.png + + + Assets\Emoji\Separated\D83DDEBB.png + + + Assets\Emoji\Separated\D83DDEBC.png + + + Assets\Emoji\Separated\D83DDEBD.png + + + Assets\Emoji\Separated\D83DDEBE.png + + + Assets\Emoji\Separated\D83DDEBF.png + + + Assets\Emoji\Separated\D83DDEC0.png + + + Assets\Emoji\Separated\D83DDEC0D83CDFFB.png + + + Assets\Emoji\Separated\D83DDEC0D83CDFFC.png + + + Assets\Emoji\Separated\D83DDEC0D83CDFFD.png + + + Assets\Emoji\Separated\D83DDEC0D83CDFFE.png + + + Assets\Emoji\Separated\D83DDEC0D83CDFFF.png + + + Assets\Emoji\Separated\D83DDEC1.png + + + Assets\Emoji\Separated\D83DDEC2.png + + + Assets\Emoji\Separated\D83DDEC3.png + + + Assets\Emoji\Separated\D83DDEC4.png + + + Assets\Emoji\Separated\D83DDEC5.png + + + Assets\Emoji\Separated\D83DDECB.png + + + Assets\Emoji\Separated\D83DDECC.png + + + Assets\Emoji\Separated\D83DDECD.png + + + Assets\Emoji\Separated\D83DDECE.png + + + Assets\Emoji\Separated\D83DDECF.png + + + Assets\Emoji\Separated\D83DDEE0.png + + + Assets\Emoji\Separated\D83DDEE1.png + + + Assets\Emoji\Separated\D83DDEE2.png + + + Assets\Emoji\Separated\D83DDEE3.png + + + Assets\Emoji\Separated\D83DDEE4.png + + + Assets\Emoji\Separated\D83DDEE5.png + + + Assets\Emoji\Separated\D83DDEE9.png + + + Assets\Emoji\Separated\D83DDEEB.png + + + Assets\Emoji\Separated\D83DDEEC.png + + + Assets\Emoji\Separated\D83DDEF0.png + + + Assets\Emoji\Separated\D83DDEF3.png + + + Assets\Emoji\Separated\D83EDD18D83CDFFB.png + + + Assets\Emoji\Separated\D83EDD18D83CDFFC.png + + + Assets\Emoji\Separated\D83EDD18D83CDFFD.png + + + Assets\Emoji\Separated\D83EDD18D83CDFFE.png + + + Assets\Emoji\Separated\D83EDD18D83CDFFF.png + + + Assets\Emoji\Separated\D83EDD80.png + + + Assets\Emoji\Separated\D83EDD81.png + + + Assets\Emoji\Separated\D83EDD82.png + + + Assets\Emoji\Separated\D83EDD83.png + + + Assets\Emoji\Separated\D83EDD84.png + + + Assets\Emoji\Separated\D83EDDC0.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat0_part0.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat0_part1.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat0_part2.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat0_part3.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat1_part0.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat1_part1.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat1_part2.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat2_part0.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat2_part1.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat2_part2.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat2_part3.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat2_part4.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat3_part0.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat3_part1.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat3_part2.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat4_part0.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat4_part1.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat4_part2.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat4_part3.png + + + Assets\Emoji\SpacedSpritesLandscape\sprite64_landscape_cat4_part4.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part3.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part4.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part5.png + + + Assets\Emoji\SpacedSprites\sprite64_cat1_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat1_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat1_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat1_part3.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part3.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part4.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part5.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part6.png + + + Assets\Emoji\SpacedSprites\sprite64_cat3_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat3_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat3_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part3.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part4.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part5.png + + + Assets\light.emoji.abc-WXGA.png + + + Assets\light.emoji.backspace-WXGA.png + + + Assets\light.emoji.category.1-WXGA.png + + + Assets\light.emoji.category.2-WXGA.png + + + Assets\light.emoji.category.3-WXGA.png + + + Assets\light.emoji.category.4-WXGA.png + + + Assets\light.emoji.category.5-WXGA.png + + + Assets\light.emoji.recent-WXGA.png + + + Assets\light.emoji.sticker-WXGA.png + + + Images\ApplicationBar\appbar.add.rest.png + + + Images\ApplicationBar\appbar.attach.png + + + Images\ApplicationBar\appbar.basecircle.png + + + Images\ApplicationBar\appbar.cancel.rest.png + + + Images\ApplicationBar\appbar.check.png + + + Images\ApplicationBar\appbar.delete.png + + + Images\ApplicationBar\appbar.edit.png + + + Images\ApplicationBar\appbar.feature.search.rest.png + + + Images\ApplicationBar\appbar.feature.video.rest.png + + + Images\ApplicationBar\appbar.forwardmessage.png + + + Images\ApplicationBar\appbar.manage.rest.png + + + Images\ApplicationBar\appbar.map.centerme.png + + + Images\ApplicationBar\appbar.map.checkin.png + + + Images\ApplicationBar\appbar.map.direction.png + + + Images\ApplicationBar\appbar.next.light.png + + + Images\ApplicationBar\appbar.next.png + + + Images\ApplicationBar\appbar.refresh.rest.png + + + Images\ApplicationBar\appbar.save.png + + + Images\ApplicationBar\appbar.send.text.rest.png + + + Images\ApplicationBar\appbar.share.png + + + Images\ApplicationBar\appbar.smile.png + + + Images\ApplicationBar\appbar.stop.rest.png + + + Images\ApplicationBar\appbar.transport.play.png + + + Images\Audio\appbar.basecircle.rest.png + + + Images\Audio\appbar.download.rest.png + + + Images\Audio\appbar.transport.pause.rest.png + + + Images\Audio\appbar.transport.play.rest.png + + + Images\Backgrounds\gallery_WXGA.png + + + Images\Backgrounds\wallpapercheck_WXGA.png + + + Images\Dialogs\broadcast-WXGA.png + + + Images\Dialogs\chat.check-WXGA.png + + + Images\Dialogs\chat.commands-WXGA.png + + + Images\Dialogs\chat.customkeyboard-WXGA.png + + + Images\Dialogs\chat.gas-WXGA.png + + + Images\Dialogs\chat.keyboard-WXGA.png + + + Images\Dialogs\chat.mute-WXGA.png + + + Images\Dialogs\chat.state.read-black-WXGA.png + + + Images\Dialogs\chat.state.sent-black-WXGA.png + + + Images\Dialogs\group-WXGA.png + + + Images\Dialogs\passcode.close-WXGA.png + + + Images\Dialogs\passcode.open-WXGA.png + + + Images\Dialogs\secretchat-black-WXGA.png + + + Images\Dialogs\secretchat-white-WXGA.png + + + Images\Dialogs\secretchat-WXGA.png + + + Images\LockScreen\lockscreen.logo.png + + + Images\LockScreen\lockscreen.logo.white.png + + + Images\LockScreen\lockscreen.png + + + Images\Maps\4SQ.png + + + Images\Maps\attach-location-black.png + + + Images\Maps\Map_Pin.png + + + Images\Messages\channel.broadcast-WXGA.png + + + Images\Messages\chat.nomessages-white-WXGA.png + + + Images\Messages\chat.nomessages-WXGA.png + + + Images\Messages\chat_doc-WXGA.png + + + Images\Messages\file.black-WXGA.png + + + Images\Messages\file.white-WXGA.png + + + Images\Messages\link.png + + + Images\Messages\media.black-WXGA.png + + + Images\Messages\media.download-WXGA.png + + + Images\Messages\media.white-WXGA.png + + + Images\Messages\message.deletereply.png + + + Images\Messages\message.state.broadcast.png + + + Images\Messages\message.state.read-WXGA.png + + + Images\Messages\message.state.sending-WXGA.png + + + Images\Messages\message.state.sent-WXGA.png + + + Images\Messages\message.state.views-WXGA.png + + + Images\Messages\unreadmessages.png + + + Images\NumericKeyboard\back.png + + + Images\NumericKeyboard\back.white.png + + + Images\PhoneNumber\changenumber_2x.png + + + Images\Placeholder\placeholder.broadcast.png + + + Images\Placeholder\placeholder.group.transparent-WXGA.png + + + Images\Placeholder\placeholder.user.transparent-WXGA.png + + + Images\Startup\intro.1-720p.png + + + Images\Startup\intro.2-WXGA.png + + + Images\Startup\intro.3-WXGA.png + + + Images\Startup\intro.4-WXGA.png + + + Images\Startup\intro.5-WXGA.png + + + Images\Startup\intro.6-WXGA.png + + + Sounds\Default.wav + + + Sounds\Sound1.wav + + + Sounds\Sound2.wav + + + Sounds\Sound3.wav + + + Sounds\Sound4.wav + + + Sounds\Sound5.wav + + + Sounds\Sound6.wav + + + ToastPromptIcon.png + + + + PreserveNewest + + + + + + Designer + + + Designer + + + + + + + {1E7F202B-8830-42F6-BCDA-2A6C590A7E10} + ExifLib + + + {E79D5093-8038-4A5F-8A98-CA38C0D0886F} + Telegram.Api.WP8 + + + {C1E19589-BD32-4DCF-AF58-393AD4D40B4E} + Telegram.Controls + + + {5E327850-E16E-4642-957A-FD52BF8D3D02} + TelegramClient.Opus + + + {C5F29433-1957-4C9E-A7D6-56E52A89AFA4} + TelegramClient.Player + + + {30ADA306-4873-4AF3-99D3-BE57E723013C} + TelegramClient.ScheduledTaskAgent.WP8 + + + {FAE12FD9-EDCA-433E-AD11-F1663A998F35} + TelegramClient.WebP + + + + + Resources\AppResources.de.resx + + + Resources\AppResources.es.resx + Designer + + + Resources\AppResources.it.resx + Designer + + + Resources\AppResources.nl.resx + Designer + + + Resources\AppResources.pt.resx + + + Resources\AppResources.resx + Designer + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/Themes/Default/LongListSelector.xaml b/TelegramClient.WP8/Themes/Default/LongListSelector.xaml new file mode 100755 index 0000000..0c1c7c0 --- /dev/null +++ b/TelegramClient.WP8/Themes/Default/LongListSelector.xaml @@ -0,0 +1,82 @@ + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/Themes/Default/ToggleSwitch.xaml b/TelegramClient.WP8/Themes/Default/ToggleSwitch.xaml new file mode 100755 index 0000000..19f5b36 --- /dev/null +++ b/TelegramClient.WP8/Themes/Default/ToggleSwitch.xaml @@ -0,0 +1,50 @@ + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/Themes/Generic.xaml b/TelegramClient.WP8/Themes/Generic.xaml new file mode 100755 index 0000000..41c3e84 --- /dev/null +++ b/TelegramClient.WP8/Themes/Generic.xaml @@ -0,0 +1,71 @@ + + + + + + + + + diff --git a/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Add.png b/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Add.png new file mode 100755 index 0000000..4b524d6 Binary files /dev/null and b/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Add.png differ diff --git a/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Cancel.png b/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Cancel.png new file mode 100755 index 0000000..4dd724f Binary files /dev/null and b/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Cancel.png differ diff --git a/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Check.png b/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Check.png new file mode 100755 index 0000000..7a07466 Binary files /dev/null and b/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Check.png differ diff --git a/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Delete.png b/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Delete.png new file mode 100755 index 0000000..95bb16d Binary files /dev/null and b/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Delete.png differ diff --git a/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Select.png b/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Select.png new file mode 100755 index 0000000..995deaa Binary files /dev/null and b/TelegramClient.WP8/Toolkit.Content/ApplicationBar.Select.png differ diff --git a/TelegramClient.WP8/ViewModels/Contacts/ContactsViewModel.cs b/TelegramClient.WP8/ViewModels/Contacts/ContactsViewModel.cs new file mode 100755 index 0000000..9dc149c --- /dev/null +++ b/TelegramClient.WP8/ViewModels/Contacts/ContactsViewModel.cs @@ -0,0 +1,592 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Threading; +using System.Windows; +using Caliburn.Micro; +using Microsoft.Phone.Globalization; +using Microsoft.Phone.Tasks; +using Microsoft.Phone.UserData; +using Telegram.Api.Helpers; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Converters; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.ViewModels.Search; + +namespace TelegramClient.ViewModels.Contacts +{ + public class ContactsViewModel : ItemsViewModelBase, + IHandle, + IHandle, + IHandle> + { + private ObservableCollection> _contacts; + + public ObservableCollection> Contacts + { + get { return _contacts; } + set { SetField(ref _contacts, value, () => Contacts); } + } + + private volatile bool _isGettingContacts; + + public bool FirstRun { get; set; } + + public ContactsViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, IEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + Items = new AlphaKeyGroup("@"); + + _contacts = new ObservableCollection>(); + _contacts.Add((AlphaKeyGroup)Items); + + DisplayName = LowercaseConverter.Convert(AppResources.Contacts); + Status = AppResources.Loading; + + EventAggregator.Subscribe(this); + } + + private void UpdateItemsAsync() + { + _isGettingContacts = true; + //IsWorking = true; + var contactIds = string.Join(",", Items.Select(x => x.Index).OrderBy(x => x)); + var hash = MD5Core.GetHash(contactIds); + var hashString = BitConverter.ToString(hash).Replace("-", string.Empty).ToLower(); + MTProtoService.GetContactsAsync(new TLString(hashString), + result => + { + _isGettingContacts = false; + + //IsWorking = false; + if (result is TLContactsNotModified) + { + return; + } + + InsertContacts(((TLContacts)result).Users, false); + }, + error => + { + _isGettingContacts = false; + //IsWorking = false; + }); + } + + private bool _runOnce = true; + + protected override void OnActivate() + { + base.OnActivate(); + + //if (FirstRun) + //{ + // SignInImport(); + //} + //else + { + if (!_runOnce) + { + BeginOnThreadPool(() => + { + Thread.Sleep(300); + try + { + foreach (var item in Items) + { + item.NotifyOfPropertyChange("Status"); + } + + } + catch (Exception e) + { + TLUtils.WriteLine(e.ToString(), LogSeverity.Error); + } + }); + + return; + } + _runOnce = false; + //BeginOnThreadPool(() => + { +#if WP7 + Thread.Sleep(400); +#endif + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (isAuthorized) + { + Status = Items.Count == 0 && LazyItems.Count == 0 ? AppResources.Loading : string.Empty; + var contacts = CacheService.GetContacts(); + Status = string.Empty; + var orderedContacts = contacts.OrderBy(x => x.FullName).ToList(); + var count = 0; + + Items.Clear(); + for (var i = 0; count < 10 && i < orderedContacts.Count; i++) + { + if (!(orderedContacts[i] is TLUserEmpty) + && orderedContacts[i].Index != StateService.CurrentUserId) + { + Items.Add(orderedContacts[i]); + } + count++; + } + + LazyItems.Clear(); + for (var i = count; i < orderedContacts.Count; i++) + { + if (!(orderedContacts[i] is TLUserEmpty) && orderedContacts[i].Index != StateService.CurrentUserId) + { + LazyItems.Add(orderedContacts[i]); + } + } + + + Status = Items.Count == 0 && LazyItems.Count == 0 ? AppResources.Loading : string.Empty; + if (LazyItems.Count > 0) + { + PopulateItems(() => + { + ImportContactsAsync(); + UpdateItemsAsync(); + }); + } + else + { + ImportContactsAsync(); + UpdateItemsAsync(); + } + } + }//); + } + } + + #region Commands + + public void AddContact() + { + EventAggregator.RequestTask(); + } + + public void DeleteContact(TLUserBase user) + { + if (user == null) return; + + MTProtoService.DeleteContactAsync( + user.ToInputUser(), + link => Items.Remove(user), + error => + { + + }); + } + + public void UserAction(TLUserBase user) + { + OpenContactDetails(user); + } + + public FrameworkElement OpenContactElement; + + public void SetOpenContactElement(object element) + { + OpenContactElement = element as FrameworkElement; + } + + public void OpenContactDetails(TLUserBase user) + { + if (user == null || user is TLUserEmpty) return; + + if (user is TLUserNotRegistered) + { + //return; + + EventAggregator.RequestTask(t => + { + t.Body = AppResources.InviteFriendMessage; + t.To = user.Phone.ToString(); + }); + return; + } + + StateService.DialogMessages = CacheService.GetHistory(user.Index); + StateService.With = user; + NavigationService.UriFor().Navigate(); + } + + private Stopwatch _stopwatch; + + private void ImportContactsAsync(bool fullReplace = false) + { + var contacts = new Microsoft.Phone.UserData.Contacts(); + contacts.SearchCompleted += (e, args) => OnSearchCompleted(e, args, fullReplace); + _stopwatch = Stopwatch.StartNew(); + contacts.SearchAsync(string.Empty, FilterKind.None, null); + } + + private char _prevKey = '#'; + + private void OnSearchCompleted(object sender, ContactsSearchEventArgs args, bool fullReplace) + { + + TLUtils.WritePerformance("::Search contacts time: " + _stopwatch.Elapsed); + _stopwatch = Stopwatch.StartNew(); + var contacts = args.Results; + + //var usersCache = Items.ToDictionary(x => x.Index); + + var contactsCache = new Dictionary(); + var notRegisteredContacts = new List(); + foreach (var contact in contacts) + { + foreach (var phoneNumber in contact.PhoneNumbers) + { + if (!contactsCache.ContainsKey(phoneNumber.PhoneNumber)) + { + contactsCache.Add(phoneNumber.PhoneNumber, contact); + } + } + var completeName = contact.CompleteName; + var firstName = completeName != null ? completeName.FirstName ?? "" : ""; + var lastName = completeName != null ? completeName.LastName ?? "" : ""; + + + if (string.IsNullOrEmpty(firstName) + && string.IsNullOrEmpty(lastName)) + { + if (!string.IsNullOrEmpty(contact.DisplayName)) + { + firstName = contact.DisplayName; + } + else + { + continue; + } + } + + var clientId = contact.GetHashCode(); + var phone = contact.PhoneNumbers.FirstOrDefault(); + if (phone != null) + //&& !usersCache.ContainsKey(clientId)) + { + var notRegisteredUser = new TLUserNotRegistered + { + Id = new TLInt(-1), + Phone = new TLString(phone.PhoneNumber), + _firstName = new TLString(firstName), + _lastName = new TLString(lastName), + ClientId = new TLLong(clientId), + _photo = new TLPhotoEmpty(), + PhoneNumbers = contact.PhoneNumbers + }; + + if (lastName.Length > 0) + { + notRegisteredContacts.Add(notRegisteredUser); + } + } + } + + + TLUtils.WritePerformance("::Get not registered phones time: " + _stopwatch.Elapsed); + + _stopwatch = Stopwatch.StartNew(); + + var groups = AlphaKeyGroup.CreateGroups( + notRegisteredContacts, + Thread.CurrentThread.CurrentUICulture, + x => x.FullName, + false); + + + TLUtils.WritePerformance("::Get groups time: " + _stopwatch.Elapsed); + + foreach (var @group in groups) + { + var gr = new AlphaKeyGroup(@group.Key); + foreach (var u in @group.OrderBy(x => x.FullName)) + { + gr.Add(u); + } + + BeginOnUIThread(() => + { + Contacts.Add(gr); + }); + } + + var phones = contactsCache.Keys.Take(Constants.MaxImportingContactsCount).ToList(); + var importingContacts = new TLVector(); + foreach (var phone in phones) + { + var completeName = contactsCache[phone].CompleteName; + + var firstName = completeName != null ? completeName.FirstName ?? "" : ""; + var lastName = completeName != null ? completeName.LastName ?? "" : ""; + + if (string.IsNullOrEmpty(firstName) + && string.IsNullOrEmpty(lastName)) + { + if (!string.IsNullOrEmpty(contactsCache[phone].DisplayName)) + { + firstName = contactsCache[phone].DisplayName; + } + else + { + continue; + } + } + + if (firstName == "" && lastName == "") continue; + + + var contact = new TLInputContact + { + Phone = new TLString(phone), + FirstName = new TLString(firstName), + LastName = new TLString(lastName), + ClientId = new TLLong(contactsCache[phone].GetHashCode()) + }; + + importingContacts.Add(contact); + } + + _isLoading = true; + var getResponse = false; + BeginOnThreadPool(() => + { + Thread.Sleep(1500); + if (!getResponse) + { + IsWorking = true; + } + }); + //IsWorking = true; + MTProtoService.ImportContactsAsync(importingContacts, new TLBool(false), + importedContacts => + { + getResponse = true; + _isLoading = true; + IsWorking = false; + Status = Items.Count == 0 && LazyItems.Count == 0 && importedContacts.Users.Count == 0 + ? string.Format("{0}", AppResources.NoContactsHere) + : string.Empty; + InsertContacts(importedContacts.Users, fullReplace); + }, + error => + { + getResponse = true; + _isLoading = true; + Status = string.Empty; + IsWorking = false; + }); + } + + private bool _isLoading; + + public override void RefreshItems() + { + ImportContactsAsync(true); + } + + public void InviteFriends() + { + EventAggregator.RequestTask(t => t.Body = AppResources.InviteFriendMessage); + } + + private void InsertContacts(IEnumerable newUsers, bool fullReplace) + { + var itemsCache = Items.OfType().ToDictionary(x => x.Index); + + + + var users = newUsers.OrderByDescending(x => x.FullName); + var addingUsers = new List(); + + //if (fullReplace) + //{ + // Items.Clear(); + // addingUsers.AddRange(users); + //} + //else + { + foreach (var user in users) + { + if (!itemsCache.ContainsKey(user.Index) && !(user is TLUserEmpty) && user.Index != StateService.CurrentUserId) + { + addingUsers.Add(user); + } + } + } + + Status = addingUsers.Count != 0 || Items.Count != 0 || LazyItems.Count != 0 ? string.Empty : Status; + foreach (var addingUser in addingUsers) + { + InsertContact(addingUser); + } + } + + private void InsertContact(TLUserBase user) + { + var comparer = Comparer.Default; + var position = 0; + for (var i = 0; i < Items.Count; i++) + { + if (comparer.Compare(Items[i].FullName, user.FullName) == 0) + { + position = -1; + break; + } + if (comparer.Compare(Items[i].FullName, user.FullName) > 0) + { + position = i; + break; + } + } + + if (position != -1) + { + BeginOnUIThread(() => Items.Insert(position, user)); + //Thread.Sleep(20); + } + } + + #endregion + + public void Handle(string command) + { + if (string.Equals(command, Commands.LogOutCommand)) + { + _runOnce = true; + LazyItems.Clear(); + Items.Clear(); + Status = string.Empty; + IsWorking = false; + } + } + + public void Handle(TaskCompleted taskCompleted) + { + if (taskCompleted.Result.TaskResult == TaskResult.OK) + { + ImportContactsAsync(); + } + } + + public void Search() + { + NavigationService.UriFor().Navigate(); + } + + public void Handle(TLUserBase user) + { + BeginOnUIThread(() => + { + var item = Items.FirstOrDefault(x => x.Index == user.Index); + if (item != null) + { + if (!(user is TLUserContact)) + { + Items.Remove(item); + } + } + else if (user is TLUserContact) + { + InsertContact(user); + } + }); + } + } + + public class AlphaKeyGroup : ObservableCollection + { + /// + /// The delegate that is used to get the key information. + /// + /// An object of type T + /// The key value to use for this object + public delegate string GetKeyDelegate(T item); + + /// + /// The Key of this group. + /// + public string Key { get; private set; } + + /// + /// Public constructor. + /// + /// The key for this group. + public AlphaKeyGroup(string key) + { + Key = key; + } + + /// + /// Create a list of AlphaGroup with keys set by a SortedLocaleGrouping. + /// + /// The + /// Theitems source for a LongListSelector + private static List> CreateGroups(SortedLocaleGrouping slg) + { + List> list = new List>(); + + foreach (string key in slg.GroupDisplayNames) + { + list.Add(new AlphaKeyGroup(key)); + } + + return list; + } + + /// + /// Create a list of AlphaGroup with keys set by a SortedLocaleGrouping. + /// + /// The items to place in the groups. + /// The CultureInfo to group and sort by. + /// A delegate to get the key from an item. + /// Will sort the data if true. + /// An items source for a LongListSelector + public static List> CreateGroups(IEnumerable items, CultureInfo ci, GetKeyDelegate getKey, bool sort) + { + SortedLocaleGrouping slg = new SortedLocaleGrouping(ci); + List> list = CreateGroups(slg); + + foreach (T item in items) + { + int index = 0; + if (slg.SupportsPhonetics) + { + //check if your database has yomi string for item + //if it does not, then do you want to generate Yomi or ask the user for this item. + //index = slg.GetGroupIndex(getKey(Yomiof(item))); + } + else + { + index = slg.GetGroupIndex(getKey(item)); + } + if (index >= 0 && index < list.Count) + { + list[index].Add(item); + } + } + + //if (sort) + //{ + // foreach (AlphaKeyGroup group in list) + // { + // group.Sort((c0, c1) => { return ci.CompareInfo.Compare(getKey(c0), getKey(c1)); }); + // } + //} + + return list; + } + + } +} diff --git a/TelegramClient.WP8/ViewModels/Dialogs/DialogDetailsViewModel.Audio.cs b/TelegramClient.WP8/ViewModels/Dialogs/DialogDetailsViewModel.Audio.cs new file mode 100755 index 0000000..a42a8d8 --- /dev/null +++ b/TelegramClient.WP8/ViewModels/Dialogs/DialogDetailsViewModel.Audio.cs @@ -0,0 +1,212 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections; +using System.IO; +using System.IO.IsolatedStorage; +using System.Text; +using Windows.Storage; +using Telegram.Api.TL; +using TelegramClient.Views.Controls; + +namespace TelegramClient.ViewModels.Dialogs +{ + public partial class DialogDetailsViewModel + { + public void SendAudio(AudioEventArgs args) + { + Telegram.Logs.Log.Write("DialogDetailsViewModel.SendAudio file_name=" + args.OggFileName); + + if (string.IsNullOrEmpty(args.OggFileName)) return; + + Telegram.Logs.Log.Write("DialogDetailsViewModel.SendAudio check_disable_feature file_name=" + args.OggFileName); + + var id = TLLong.Random(); + var accessHash = TLLong.Random(); + + var oggFileName = string.Format("audio{0}_{1}.mp3", id, accessHash); + var wavFileName = Path.GetFileNameWithoutExtension(oggFileName) + ".wav"; + + long size = 0; + using (var storage = IsolatedStorageFile.GetUserStoreForApplication()) + { + storage.MoveFile(args.OggFileName, oggFileName); + using (var file = storage.OpenFile(oggFileName, FileMode.Open, FileAccess.Read)) + { + size = file.Length; + } + + var wavStream = args.PcmStream.GetWavAsMemoryStream(16000, 1, 16); + using (var file = new IsolatedStorageFileStream(wavFileName, FileMode.OpenOrCreate, storage)) + { + wavStream.Seek(0, SeekOrigin.Begin); + wavStream.CopyTo(file); + file.Flush(); + } + } + + var opus = new TelegramClient_Opus.WindowsPhoneRuntimeComponent(); + var bytes = opus.GetWaveform(ApplicationData.Current.LocalFolder.Path + "\\" + oggFileName); + var resultSamples = bytes.Length; + var bites2 = new BitArray(5 * bytes.Length); + var count = 0; + for (var i = 0; i < bytes.Length; i++) + { + var result = bytes[i]; + var bit1 = result >> 0 & 0x1; + var bit2 = result >> 1 & 0x1; + var bit3 = result >> 2 & 0x1; + var bit4 = result >> 3 & 0x1; + var bit5 = result >> 4 & 0x1; + bites2[count] = Convert.ToBoolean(bit1); + bites2[count + 1] = Convert.ToBoolean(bit2); + bites2[count + 2] = Convert.ToBoolean(bit3); + bites2[count + 3] = Convert.ToBoolean(bit4); + bites2[count + 4] = Convert.ToBoolean(bit5); + count = count + 5; + } + + var bytesCount = (resultSamples * 5) / 8 + (((resultSamples * 5) % 8) == 0 ? 0 : 1); + var waveformBytes = new byte[bytesCount]; + bites2.CopyTo(waveformBytes, 0); + var waveform = waveformBytes != null ? TLString.FromBigEndianData(waveformBytes) : TLString.Empty; + + var audioAttribute = new TLDocumentAttributeAudio46 + { + Flags = new TLInt((int)DocumentAttributeAudioFlags.Voice), + Duration = new TLInt((int)args.Duration) + }; + + if (waveformBytes != null) + { + audioAttribute.Waveform = waveform; + } + + var attributes = new TLVector + { + audioAttribute + }; + + var document = new TLDocument54 + { + Id = id, + AccessHash = accessHash, + Date = TLUtils.DateToUniversalTimeTLInt(MTProtoService.ClientTicksDelta, DateTime.Now), + //Duration = new TLInt((int)args.Duration), + MimeType = new TLString("audio/ogg"), + Size = new TLInt((int)size), + Thumb = new TLPhotoSizeEmpty { Type = TLString.Empty }, + DCId = new TLInt(0), + Version = new TLInt(0), + Attributes = attributes + }; + + var channel = With as TLChannel; + var isChannel = channel != null && !channel.IsMegaGroup; + + var media = new TLMessageMediaDocument75 { Flags = new TLInt(0), Document = document, Caption = TLString.Empty, IsoFileName = oggFileName, NotListened = !isChannel }; + + var message = GetMessage(TLString.Empty, media); + + message.NotListened = !isChannel; + + Telegram.Logs.Log.Write(string.Format("DialogDetailsViewModel.SendAudio start sending file_name={0} rnd_id={1}", args.OggFileName, message.RandomId)); + BeginOnUIThread(() => + { + var previousMessage = InsertSendingMessage(message); + message.NotifyOfPropertyChange(() => message.Media); + IsEmptyDialog = Items.Count == 0 && (_messages == null || _messages.Count == 0) && LazyItems.Count == 0; + + BeginOnThreadPool(() => + CacheService.SyncSendingMessage( + message, previousMessage, + m => SendAudioInternal(message, args))); + }); + } + + private void SendAudioInternal(TLMessage message, AudioEventArgs args = null) + { + Telegram.Logs.Log.Write("DialogDetailsViewModel.SendAudioInternal rnd_id=" + message.RandomId); + + var documentMedia = message.Media as TLMessageMediaDocument; + if (documentMedia != null) + { + var fileName = documentMedia.IsoFileName; + if (string.IsNullOrEmpty(fileName)) + { + return; + } + + var document = documentMedia.Document as TLDocument; + if (document == null) + { + return; + } + + if (args != null) + { + var stringBuilder = new StringBuilder(); + stringBuilder.AppendLine("parts"); + foreach (var part in args.Parts) + { + stringBuilder.AppendLine(string.Format("file_part={0} position={1} count={2} status={3}", part.FilePart, part.Position, part.Count, part.Status)); + } + + Telegram.Logs.Log.Write("DialogDetailsViewModel.SendAudioInternal uploading rnd_id=" + message.RandomId + Environment.NewLine + stringBuilder); + + var fileId = args.FileId ?? TLLong.Random(); + message.Media.FileId = fileId; + message.Media.UploadingProgress = 0.001; + UploadAudioFileManager.UploadFile(fileId, message, fileName, args.Parts); + } + else + { + var fileId = TLLong.Random(); + message.Media.FileId = fileId; + message.Media.UploadingProgress = 0.001; + UploadAudioFileManager.UploadFile(fileId, message, fileName); + } + + return; + } + + var audioMedia = message.Media as TLMessageMediaAudio; + if (audioMedia != null) + { + var fileName = audioMedia.IsoFileName; + if (string.IsNullOrEmpty(fileName)) + { + return; + } + + var audio = audioMedia.Audio as TLAudio; + if (audio == null) + { + return; + } + + if (args != null) + { + var fileId = args.FileId ?? TLLong.Random(); + message.Media.FileId = fileId; + message.Media.UploadingProgress = 0.001; + UploadAudioFileManager.UploadFile(fileId, message, fileName, args.Parts); + } + else + { + var fileId = TLLong.Random(); + message.Media.FileId = fileId; + message.Media.UploadingProgress = 0.001; + UploadAudioFileManager.UploadFile(fileId, message, fileName); + } + + return; + } + } + } +} diff --git a/TelegramClient.WP8/ViewModels/Dialogs/DialogsViewModel.cs b/TelegramClient.WP8/ViewModels/Dialogs/DialogsViewModel.cs new file mode 100755 index 0000000..963682b --- /dev/null +++ b/TelegramClient.WP8/ViewModels/Dialogs/DialogsViewModel.cs @@ -0,0 +1,1641 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Data; +using System.Windows.Media; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.Cache.EventArgs; +using Telegram.Api.Services.FileManager; +using Telegram.Api.Services.Updates; +using Telegram.Api.TL; +using TelegramClient.Controls; +using TelegramClient.Converters; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.Utils; +using TelegramClient.ViewModels.Additional; +using TelegramClient.ViewModels.Contacts; +using TelegramClient.Views; +using Execute = Telegram.Api.Helpers.Execute; +using TypingTuple = Telegram.Api.WindowsPhone.Tuple; +using TypingUser = Telegram.Api.WindowsPhone.Tuple; + +namespace TelegramClient.ViewModels.Dialogs +{ + public partial class DialogsViewModel : ItemsViewModelBase, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle + { + #region Workaround + public Visibility EncryptedChatVisibility { get { return Visibility.Collapsed; } } + + public TLObject With { get { return null; } } + + public Visibility VerifiedVisibility { get { return Visibility.Collapsed; } } + + public TLDialogBase Self { get { return null; } } + + public TLMessageBase TopMessage { get { return null; } } + + public Brush MuteIconBackground { get { return new SolidColorBrush(Colors.White); } } + + public TLPeerNotifySettings NotifySettings { get { return null; } } + + public TLInt UnreadCount { get { return new TLInt(0); } } + #endregion + + public bool FirstRun { get; set; } + + public ICollectionView FilteredItems { get; set; } + + public bool TestMode { get; set; } + + public DialogsViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + App.Log("start DialogsViewModel.ctor"); + + //Items = new ObservableCollection(); + FilteredItems = new CollectionViewSource { Source = Items }.View; + FilteredItems.Filter += item => + { + var dialog = item as TLDialog; + if (dialog != null) + { + var chat = dialog.With as TLChat41; + if (chat != null) + { + return !chat.IsMigrated; + } + } + + return true; + }; + +#if DEBUG + Items.CollectionChanged += (sender, args) => + { + TLDialog71 promoDialog = null; + TLDialogBase firstDialog = Items.FirstOrDefault(); + if (args.NewItems != null) + { + for (int i = 0; i < args.NewItems.Count; i++) + { + var newItem = args.NewItems[i] as TLDialog71; + if (newItem != null && newItem.IsPromo) + { + promoDialog = newItem; + break; + } + } + } + + if (promoDialog != null) + { + var stackTrace = string.Format("Promo action={0} dialog={1} first_dialog={2}\n{3}", args.Action, promoDialog.Index, firstDialog != null ? firstDialog.Index.ToString() : null, TLObjectGenerator.GetStackTrace()); + Execute.BeginOnUIThread(TimeSpan.FromSeconds(20.0), () => + { + TLUtils.WriteException(":::Promo:::", new Exception(stackTrace)); + }); + } + }; +#endif + + EventAggregator.Subscribe(this); + DisplayName = LowercaseConverter.Convert(AppResources.Dialogs); + Status = Items.Count == 0 && LazyItems.Count == 0 ? AppResources.Loading : string.Empty; + + BeginOnThreadPool(() => + { + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (isAuthorized) + { + var dialogs = CacheService.GetDialogs(); + + var dialogsCache = new Dictionary(); + var clearedDialogs = new List(); + foreach (var dialog in dialogs) + { + if (!dialogsCache.ContainsKey(dialog.Index)) + { + clearedDialogs.Add(dialog); + dialogsCache[dialog.Index] = dialog; + } + else + { + var cachedDialog = dialogsCache[dialog.Index]; + if (cachedDialog.Peer is TLPeerUser && dialog.Peer is TLPeerUser) + { + CacheService.DeleteDialog(dialog); + continue; + } + if (cachedDialog.Peer is TLPeerChat && dialog.Peer is TLPeerChat) + { + CacheService.DeleteDialog(dialog); + continue; + } + if (cachedDialog.Peer is TLPeerChannel && dialog.Peer is TLPeerChannel) + { + CacheService.DeleteDialog(dialog); + continue; + } + } + } + + ReorderDrafts(clearedDialogs); + + // load cache + BeginOnUIThread(() => + { + Status = dialogs.Count == 0 ? AppResources.Loading : string.Empty; + Items.Clear(); + + const int maxDialogSlice = 8; + var importantCount = 0; + var count = 0; + for (var i = 0; i < clearedDialogs.Count && importantCount < maxDialogSlice; i++, count++) + { + Items.Add(clearedDialogs[i]); + var chat41 = clearedDialogs[i].With as TLChat41; + if (chat41 == null || !chat41.IsMigrated) + { + importantCount++; + } + } + + + if (count < clearedDialogs.Count) + { + BeginOnUIThread(() => + { + for (var i = count; i < clearedDialogs.Count; i++) + { + Items.Add(clearedDialogs[i]); + } + + CheckPromoChannel(); + + var importantDialogsCount = Math.Max(Telegram.Api.Constants.CachedDialogsCount, Items.OfType().Count()); + UpdateItemsAsync(importantDialogsCount); + }); + } + else + { + var importantDialogsCount = Math.Max(Telegram.Api.Constants.CachedDialogsCount, Items.OfType().Count()); + UpdateItemsAsync(importantDialogsCount); + } + }); + } + }); + + App.Log("stop DialogsViewModel.ctor"); + } + + public void CheckPromoChannel(bool force = false) + { + Execute.BeginOnThreadPool(() => + { + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (!isAuthorized) + { + return; + } + + var updateProxyData = false; + var proxyDataBase = CacheService.GetProxyData(); + var proxyDataPromo = proxyDataBase as TLProxyDataPromo; + if (proxyDataBase == null) + { + //Execute.ShowDebugMessage("GetPromoDialog"); + + MTProtoService.GetProxyDataAsync( + result => + { + proxyDataPromo = result as TLProxyDataPromo; + if (proxyDataPromo != null) + { + MTProtoService.GetPromoDialogAsync(MTProtoService.PeerToInputPeer(proxyDataPromo.Peer), + result2 => + { + + }); + } + }); + + return; + } + + if (proxyDataPromo != null) + { + var now = TLUtils.DateToUniversalTimeTLInt(MTProtoService.ClientTicksDelta, DateTime.Now); + var promoChannel = CacheService.GetChat(proxyDataPromo.Peer.Id) as TLChannel; + var promoDialog = CacheService.GetDialogs().OfType().FirstOrDefault(x => x.IsPromo && x.Peer.Id.Value == proxyDataPromo.Peer.Id.Value); + if (promoDialog == null && (promoChannel == null || promoChannel.Left.Value)) + { + //Execute.ShowDebugMessage("GetPromoDialog"); + + MTProtoService.GetPromoDialogAsync(MTProtoService.PeerToInputPeer(proxyDataPromo.Peer), + result => + { + + }); + } + else +//#if !DEBUG + if (proxyDataPromo.Expires.Value <= now.Value || force) +//#endif + { + //Execute.ShowDebugMessage("GetPromoDialog"); + + MTProtoService.GetProxyDataAsync( + result => + { + proxyDataPromo = result as TLProxyDataPromo; + if (proxyDataPromo != null) + { + MTProtoService.GetPromoDialogAsync(MTProtoService.PeerToInputPeer(proxyDataPromo.Peer), + result2 => + { + + }); + } + }); + + return; + } + } + }); + } + + private static void ReorderDrafts(IList dialogs) + { + for (var i = 0; i < dialogs.Count; i++) + { + var dialog53 = dialogs[i] as TLDialog53; + if (dialog53 != null) + { + var draft = dialog53.Draft as TLDraftMessage; + if (draft != null && dialog53.GetDateIndexWithDraft() > dialog53.GetDateIndex()) + { + var dateWithDraft = dialog53.GetDateIndexWithDraft(); + for (var j = 0; j < i; j++) + { + if (dateWithDraft >= dialogs[j].GetDateIndexWithDraft()) + { + dialogs.RemoveAt(i); + dialogs.Insert(j, dialog53); + break; + } + } + } + } + } + } + + private volatile bool _isUpdated; + + private void UpdateItemsAsync(int limit) + { + IsWorking = true; + + var stopwatch = Stopwatch.StartNew(); + //TLObject.LogNotify = true; + //TelegramEventAggregator.LogPublish = true; + MTProtoService.GetDialogsAsync(stopwatch, + new TLInt(0), + new TLInt(0), + new TLInputPeerEmpty(), + new TLInt(limit), + new TLInt(0), + result => + { + //System.Diagnostics.Debug.WriteLine("messages.getDialogs elapsed=" + stopwatch.Elapsed); + + // сортируем, т.к. при синхронизации, если есть отправляющиеся сообщений, то TopMessage будет замещен на них + // и начальная сортировка сломается + var orderedDialogs = new TLVector(result.Dialogs.Count); + foreach (var orderedDialog in result.Dialogs.OrderByDescending(x => x.GetDateIndexWithDraft())) + { + orderedDialogs.Add(orderedDialog); + } + result.Dialogs = orderedDialogs; + + //System.Diagnostics.Debug.WriteLine("messages.getDialogs ordering elapsed=" + stopwatch.Elapsed); + + BeginOnUIThread(() => + { + //System.Diagnostics.Debug.WriteLine("messages.getDialogs ui elapsed=" + stopwatch.Elapsed); + //TelegramEventAggregator.LogPublish = false; + //TLObject.LogNotify = false; + IsWorking = false; + IsLastSliceLoaded = result.Dialogs.Count < limit; + + _offset = limit; + + var needUpdate = Items.Count == 0; + var itemsCount = Items.Count; + int i = 0, j = 0; + var contactRegisteredDialogs = new List(); + var promoDialogs = new List(); + for (; i < result.Dialogs.Count && j < Items.Count; i++, j++) + { + if (itemsCount - 1 < i || result.Dialogs[i] != Items[j]) + { + // skip "User joined Telegram!" message + var dialog = Items[j] as TLDialog; + if (dialog != null) + { + var messageService = dialog.TopMessage as TLMessageService; + if (messageService != null && messageService.Action is TLMessageActionContactRegistered) + { + i--; + contactRegisteredDialogs.Add(dialog); + continue; + } + } + + var dialog71 = Items[j] as TLDialog71; + if (dialog71 != null && dialog71.IsPromo) + { + i--; + promoDialogs.Add(dialog); + continue; + } + + var encryptedDialog = Items[j] as TLEncryptedDialog; + if (encryptedDialog != null) + { + i--; + continue; + } + + + needUpdate = true; + break; + } + } + + if (i < j) + { + for (var k = i; k < j; k++) + { + if (k < result.Dialogs.Count) + { + Items.Add(result.Dialogs[k]); + } + } + } + + // load updated cache + Status = Items.Count == 0 && LazyItems.Count == 0 && result.Dialogs.Count == 0 ? AppResources.NoDialogsHere : string.Empty; + + if (needUpdate) + { + var startIndex = 0; + foreach (var dialog in contactRegisteredDialogs) + { + for (var k = startIndex; k < result.Dialogs.Count; k++) + { + if (dialog.GetDateIndexWithDraft() > result.Dialogs[k].GetDateIndexWithDraft()) + { + result.Dialogs.Insert(k, dialog); + startIndex = k; + break; + } + } + } + + startIndex = 0; + foreach (var dialog in promoDialogs) + { + for (var k = startIndex; k < result.Dialogs.Count; k++) + { + if (dialog.GetDateIndexWithDraft() > result.Dialogs[k].GetDateIndexWithDraft()) + { + result.Dialogs.Insert(k, dialog); + startIndex = k; + break; + } + } + } + + var encryptedDialogs = Items.OfType(); + startIndex = 0; + foreach (var encryptedDialog in encryptedDialogs) + { + for (var k = startIndex; k < result.Dialogs.Count; k++) + { + if (encryptedDialog.GetDateIndexWithDraft() > result.Dialogs[k].GetDateIndexWithDraft()) + { + result.Dialogs.Insert(k, encryptedDialog); + startIndex = k; + break; + } + } + } + + var broadcasts = Items.OfType(); + startIndex = 0; + foreach (var broadcast in broadcasts) + { + for (var k = startIndex; k < result.Dialogs.Count; k++) + { + if (broadcast.GetDateIndexWithDraft() > result.Dialogs[k].GetDateIndexWithDraft()) + { + result.Dialogs.Insert(k, broadcast); + startIndex = k; + break; + } + } + } + + Items.Clear(); + foreach (var dialog in result.Dialogs) + { + Items.Add(dialog); + } + + IsLastSliceLoaded = false; + _isUpdated = true; + } + else + { + _isUpdated = true; + } + //System.Diagnostics.Debug.WriteLine("messages.getDialogs end ui elapsed=" + stopwatch.Elapsed); + }); + }, + error => BeginOnUIThread(() => + { + _isUpdated = true; + Status = string.Empty; + IsWorking = false; + })); + } + + private bool _checkPromoChannel; + + protected override void OnActivate() + { + base.OnActivate(); + + if (FirstRun) + { + OnInitialize(); + } + + if (_checkPromoChannel) + { + CheckPromoChannel(); + } + else + { + _checkPromoChannel = true; + } + } + + protected override void OnInitialize() + { + BeginOnThreadPool(() => + { + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (!FirstRun) + { + return; + } + if (!isAuthorized) + { + return; + } + + FirstRun = false; + + Status = Items.Count == 0 && LazyItems.Count == 0 ? AppResources.Loading : string.Empty; + var limit = Constants.DialogsSlice; + MTProtoService.GetDialogsAsync(Stopwatch.StartNew(), + new TLInt(0), + new TLInt(0), + new TLInputPeerEmpty(), + new TLInt(limit), + new TLInt(0), + dialogs => Execute.BeginOnUIThread(() => + { + IsLastSliceLoaded = dialogs.Dialogs.Count < limit; + _offset = Constants.DialogsSlice; + + _isUpdated = true; + + const int maxDialogSlice = 8; + var importantCount = 0; + Items.Clear(); + for (var i = 0; i < dialogs.Dialogs.Count; i++) + { + if (importantCount < maxDialogSlice) + { + Items.Add(dialogs.Dialogs[i]); + } + else + { + LazyItems.Add(dialogs.Dialogs[i]); + } + + var chat41 = dialogs.Dialogs[i].With as TLChat41; + if (chat41 == null || !chat41.IsMigrated) + { + importantCount++; + } + } + + Status = Items.Count == 0 && LazyItems.Count == 0 ? AppResources.NoDialogsHere : string.Empty; + + if (LazyItems.Count > 0) + { + BeginOnUIThread(() => + { + for (var i = 0; i < LazyItems.Count; i++) + { + Items.Add(LazyItems[i]); + } + LazyItems.Clear(); + + InvokeImportContacts(); + }); + } + else + { + InvokeImportContacts(); + } + }), + error => BeginOnUIThread(() => + { + InvokeImportContacts(); + + Execute.ShowDebugMessage("messages.getDialogs error " + error); + _isUpdated = true; + Status = string.Empty; + })); + }); + + base.OnInitialize(); + } + + private void InvokeImportContacts() + { + var contacts = IoC.Get(); + contacts.Handle(new InvokeImportContacts()); + } + + #region Actions + + + + public FrameworkElement OpenDialogElement; + + public void SetOpenDialogElement(object element) + { + OpenDialogElement = element as FrameworkElement; + } + + + + public override void RefreshItems() + { + UpdateItemsAsync(Constants.DialogsSlice); + } + + #endregion + + public void Handle(TopMessageUpdatedEventArgs eventArgs) + { + eventArgs.Dialog.NotifyOfPropertyChange(() => eventArgs.Dialog.With); + OnTopMessageUpdated(this, eventArgs); + } + + public void Handle(TLUpdatePinnedDialogs update) + { + Handle(new UpdateCompletedEventArgs()); + } + + public void Handle(TLUpdateDialogPinned76 update) + { + var dialogPeer = update.Peer as TLDialogPeer; + if (dialogPeer != null) + { + OnTopMessageUpdated(this, new TopMessageUpdatedEventArgs(dialogPeer.Peer) { NotifyPinned = true }); + } + + return; + } + + public void Handle(TLUpdateDraftMessage update) + { + OnTopMessageUpdated(this, new TopMessageUpdatedEventArgs(update.Peer)); + return; + + Execute.BeginOnUIThread(() => + { + TLDialog53 dialog53 = null; + for (var i = 0; i < Items.Count; i++) + { + if (Items[i].Index == update.Peer.Id.Value) + { + dialog53 = Items[i] as TLDialog53; + if (dialog53 != null) + { + dialog53.Draft = update.Draft; + + dialog53.NotifyOfPropertyChange(() => dialog53.Self); + } + Items.RemoveAt(i); + break; + } + } + + if (dialog53 != null) + { + for (var i = 0; i < Items.Count; i++) + { + if (Items[i].GetDateIndexWithDraft() <= dialog53.GetDateIndexWithDraft()) + { + Items.Insert(i, dialog53); + break; + } + } + } + }); + } + + public void Handle(ChannelUpdateCompletedEventArgs args) + { + var dialog = CacheService.GetDialog(new TLPeerChannel { Id = args.ChannelId }); + if (dialog != null) + { + var topMessage = dialog.Messages.FirstOrDefault(); + if (topMessage != null) + { + Handle(new TopMessageUpdatedEventArgs(dialog, topMessage)); + } + } + } + + public void Handle(DialogAddedEventArgs eventArgs) + { + OnDialogAdded(this, eventArgs); + } + + private void OnTopMessageUpdatedInternal(object sender, TopMessageUpdatedEventArgs e) + { + if (e.Dialog == null) + { + if (e.Peer != null) + { + for (var i = 0; i < Items.Count; i++) + { + if (Items[i].Peer.GetType() == e.Peer.GetType() + && Items[i].Index == e.Peer.Id.Value) + { + e = new TopMessageUpdatedEventArgs(Items[i], (TLMessageBase)null); + break; + } + } + } + + if (e.Dialog == null) return; + } + + if (e.NotifyPinned) e.Dialog.NotifyOfPropertyChange(() => e.Dialog.IsPinned); + + int currentPosition; + int newPosition; + try + { + var chat = e.Dialog.With as TLChat; + if (chat != null) + { + var dialog = e.Dialog as TLDialog; + if (dialog != null) + { + var topMessage = dialog.TopMessage as TLMessageService; + if (topMessage != null) + { + var actionChatMigratedTo = topMessage.Action as TLMessageActionChatMigrateTo; + if (actionChatMigratedTo != null) + { + Items.Remove(e.Dialog); + return; + } + + var actionChatDeleteUser = topMessage.Action as TLMessageActionChatDeleteUser; + if (actionChatDeleteUser != null) + { + if (actionChatDeleteUser.UserId.Value == StateService.CurrentUserId) + { + Items.Remove(e.Dialog); + return; + } + } + } + } + } + + var channel = e.Dialog.With as TLChannel; + if (channel != null) + { + var dialog = e.Dialog as TLDialog; + if (dialog != null) + { + var topMessage = dialog.TopMessage as TLMessageService; + if (topMessage != null) + { + var actionChatDeleteUser = topMessage.Action as TLMessageActionChatDeleteUser; + if (actionChatDeleteUser != null) + { + if (actionChatDeleteUser.UserId.Value == StateService.CurrentUserId) + { + Items.Remove(e.Dialog); + return; + } + } + } + } + } + + e.Dialog.Typing = null; + + currentPosition = Items.IndexOf(e.Dialog); + + newPosition = currentPosition; + for (var i = 0; i < Items.Count; i++) + { + if (// мигает диалог, если просто обновляется последнее сообщение, то номер становится на 1 больше + // и сначала удаляем, а потом вставляем на туже позицию + i != currentPosition + && Items[i].GetDateIndexWithDraft() <= e.Dialog.GetDateIndexWithDraft()) + { + newPosition = i; + break; + } + } + + if (currentPosition == -1 + && currentPosition == newPosition) + { + Execute.ShowDebugMessage("TLDialog with=" + e.Dialog.With + " curPos=newPos=-1 isLastSliceLoaded=" + IsLastSliceLoaded); + + // channels not from current slice + if (IsLastSliceLoaded) + { + Items.Add(e.Dialog); + Status = Items.Count > 0 || LazyItems.Count > 0 ? string.Empty : Status; + + return; + } + else + { + return; + } + } + + if (currentPosition != newPosition) + { + if (currentPosition >= 0 + && currentPosition < newPosition) + { + // т.к. будем сначала удалять диалог а потом вставлять, то + // curPos + 1 = newPos - это вставка на тоже место и не имеет смысла + // Update: имеет, т.к. обновляется инфа о последнем сообщении + if (currentPosition + 1 == newPosition) + { + Items[currentPosition].NotifyOfPropertyChange(() => Items[currentPosition].Self); + Items[currentPosition].NotifyOfPropertyChange(() => Items[currentPosition].UnreadCount); + var dialog71 = Items[currentPosition] as TLDialog71; + if (dialog71 != null) + { + dialog71.NotifyOfPropertyChange(() => dialog71.UnreadMentionsCount); + } + + return; + } + Items.Remove(e.Dialog); + Items.Insert(newPosition - 1, e.Dialog); + } + else + { + Items.Remove(e.Dialog); + Items.Insert(newPosition, e.Dialog); + } + } + else + { + // удалили сообщение и диалог должен переместиться ниже загруженной части списка + if (!IsLastSliceLoaded + && Items.Count > 0 + && Items[Items.Count - 1].GetDateIndexWithDraft() > e.Dialog.GetDateIndexWithDraft()) + { + Items.Remove(e.Dialog); + } + + Items[currentPosition].NotifyOfPropertyChange(() => Items[currentPosition].Self); + Items[currentPosition].NotifyOfPropertyChange(() => Items[currentPosition].UnreadCount); + var dialog71 = Items[currentPosition] as TLDialog71; + if (dialog71 != null) + { + dialog71.NotifyOfPropertyChange(() => dialog71.UnreadMentionsCount); + } + } + } + catch (Exception ex) + { + Telegram.Logs.Log.Write(string.Format("DialogsViewModel.Handle OnTopMessageUpdatedEventArgs ex " + ex)); + throw ex; + } + } + + private void OnTopMessageUpdated(object sender, TopMessageUpdatedEventArgs e) + { + BeginOnUIThread(() => + { + OnTopMessageUpdatedInternal(sender, e); + }); + } + + private void OnDialogAdded(object sender, DialogAddedEventArgs e) + { + var dialog = e.Dialog; + if (dialog == null) return; + + BeginOnUIThread(() => + { + var index = -1; + for (var i = 0; i < Items.Count; i++) + { + if (Items[i].Index == e.Dialog.Index + && Items[i].Peer.GetType() == e.Dialog.Peer.GetType()) + { + return; + } + + if (Items[i] == e.Dialog) + { + return; + } + + if (Items[i].GetDateIndexWithDraft() < dialog.GetDateIndexWithDraft()) + { + index = i; + break; + } + } + + if (e.Dialog.Peer is TLPeerChannel) + { + for (var i = 0; i < Items.Count; i++) + { + if (e.Dialog.Peer.GetType() == Items[i].Peer.GetType() + && e.Dialog.Peer.Id.Value == Items[i].Peer.Id.Value) + { + Items.RemoveAt(i); + Execute.ShowDebugMessage("OnDialogAdded RemoveAt=" + i); + break; + } + } + } + + if (index == -1) + { + Items.Add(dialog); + } + else + { + Items.Insert(index, dialog); + } + Status = Items.Count > 0 || LazyItems.Count > 0 ? string.Empty : Status; + }); + } + + public void Handle(DialogRemovedEventArgs args) + { + BeginOnUIThread(() => + { + var dialog = Items.FirstOrDefault(x => x.Index == args.Dialog.Index); + + if (dialog != null) + { + Items.Remove(dialog); + Status = Items.Count == 0 && LazyItems.Count == 0 ? AppResources.NoDialogsHere : string.Empty; + } + }); + } + + public void Handle(DownloadableItem item) + { + var photo = item.Owner as TLUserProfilePhoto; + if (photo != null) + { + var user = CacheService.GetUser(photo); + if (user != null) + { + user.NotifyOfPropertyChange(() => user.Photo); + } + else + { + Execute.ShowDebugMessage("Handle TLUserProfilePhoto user=null"); + } + return; + } + + var chatPhoto = item.Owner as TLChatPhoto; + if (chatPhoto != null) + { + var chat = CacheService.GetChat(chatPhoto); + if (chat != null) + { + chat.NotifyOfPropertyChange(() => chat.Photo); + return; + } + + var channel = CacheService.GetChannel(chatPhoto); + if (channel != null) + { + channel.NotifyOfPropertyChange(() => channel.Photo); + return; + } + + Execute.ShowDebugMessage("Handle TLChatPhoto chat=null"); + + return; + } + } + + public void Handle(string command) + { + if (string.Equals(command, Commands.LogOutCommand)) + { + LazyItems.Clear(); + BeginOnUIThread(() => Items.Clear()); + Status = string.Empty; + IsWorking = false; + } + } + + public void Handle(TLUpdateUserName userName) + { + Execute.BeginOnUIThread(() => + { + for (var i = 0; i < Items.Count; i++) + { + if (Items[i].WithId == userName.UserId.Value + && Items[i].With is TLUserBase) + { + var user = (TLUserBase)Items[i].With; + user.FirstName = userName.FirstName; + user.LastName = userName.LastName; + + var userWithUserName = user as IUserName; + if (userWithUserName != null) + { + userWithUserName.UserName = userName.UserName; + } + + Items[i].NotifyOfPropertyChange(() => Items[i].With); + break; + } + } + }); + } + + public void Handle(UploadableItem item) + { + var userBase = item.Owner as TLUserBase; + if (userBase != null && userBase.IsSelf) + { + MTProtoService.UploadProfilePhotoAsync( + new TLInputFile + { + Id = item.FileId, + MD5Checksum = new TLString(MD5Core.GetHashString(item.Bytes).ToLowerInvariant()), + Name = new TLString(Guid.NewGuid() + ".jpg"), + Parts = new TLInt(item.Parts.Count) + }, + result => + { + MTProtoService.GetFullUserAsync(new TLInputUserSelf(), + userFull => Execute.BeginOnUIThread(() => + { + userFull.User.NotifyOfPropertyChange(() => userFull.User.Photo); + }), + error => + { + + }); + }, + error => + { + + }); + return; + } + + var channel = item.Owner as TLChannel; + if (channel != null) + { + if (channel.Id != null) + { + MTProtoService.EditPhotoAsync( + channel, + new TLInputChatUploadedPhoto56 + { + File = new TLInputFile + { + Id = item.FileId, + MD5Checksum = new TLString(MD5Core.GetHashString(item.Bytes).ToLowerInvariant()), + Name = new TLString("channelPhoto.jpg"), + Parts = new TLInt(item.Parts.Count) + } + }, + result => + { + + }, + error => + { + Execute.ShowDebugMessage("messages.editChatPhoto error " + error); + }); + } + } + + var chat = item.Owner as TLChat; + if (chat != null) + { + MTProtoService.EditChatPhotoAsync( + chat.Id, + new TLInputChatUploadedPhoto56 + { + File = new TLInputFile + { + Id = item.FileId, + MD5Checksum = new TLString(MD5Core.GetHashString(item.Bytes).ToLowerInvariant()), + Name = new TLString("chatPhoto.jpg"), + Parts = new TLInt(item.Parts.Count) + } + }, + result => + { + + }, + error => + { + Execute.ShowDebugMessage("messages.editChatPhoto error " + error); + }); + } + } + + public void Handle(TLEncryptedChatBase chat) + { + Execute.BeginOnUIThread(() => + { + int index = -1; + TLDialogBase dialog = null; + for (int i = 0; i < Items.Count; i++) + { + if (Items[i].Peer is TLPeerEncryptedChat + && Items[i].Peer.Id.Value == chat.Id.Value) + { + index = i; + dialog = Items[i]; + break; + } + } + + if (index != -1 && dialog != null) + { + dialog.NotifyOfPropertyChange(() => dialog.Self); + } + }); + } + + public IList UpdateCompletedDialogs { get; set; } + + public void Handle(UpdateCompletedEventArgs args) + { + var dialogs = CacheService.GetDialogs(); + + var promoDialogs = dialogs.OfType().Where(x => x.IsPromo).ToList(); + if (promoDialogs.Count > 1) + { + var hasPromo = false; + for (var i = 0; i < dialogs.Count; i++) + { + var dialog71 = dialogs[i] as TLDialog71; + if (dialog71 != null && dialog71.IsPromo) + { + if (hasPromo) + { + dialogs.RemoveAt(i--); + } + else + { + hasPromo = true; + } + } + } + + var error = new StringBuilder(); + error.AppendLine("promo_count=" + promoDialogs.Count); + foreach (var promoDialog in promoDialogs) + { + error.AppendLine(string.Format("id={0} hash={1}", promoDialog.Index, promoDialog.GetHashCode())); + } + + Execute.ShowDebugMessage(error.ToString()); + } + + ReorderDrafts(dialogs); + + Execute.BeginOnUIThread(() => + { + var rootFrame = Application.Current.RootVisual as PhoneApplicationFrame; + if (rootFrame != null) + { + var shellView = rootFrame.Content as ShellView; + if (shellView == null) + { + UpdateCompletedDialogs = dialogs; + } + else + { + UpdateCompleted(dialogs); + } + } + }); + } + + public void UpdateCompleted(IList dialogs) + { + var count = Items.Count == 0 ? dialogs.Count : Items.Count; + + ((BindableCollection)Items).IsNotifying = false; + Items.Clear(); + foreach (var dialog in dialogs.Take(count)) + { + Items.Add(dialog); + } + ((BindableCollection)Items).IsNotifying = true; + ((BindableCollection)Items).Refresh(); + +#if DEBUG + if (Items.Count >= 2 && Items[0].Index == Items[1].Index) + { + Execute.ShowDebugMessage("UpdateCompleted same dialog"); + } +#endif + + Status = Items.Count > 0 || LazyItems.Count > 0 ? string.Empty : Status; + } + + private void HandleTypingCommon(TLInt chatId, TLSendMessageActionBase action, Dictionary typingCache) + { + Execute.BeginOnUIThread(() => + { + var frame = Application.Current.RootVisual as TelegramTransitionFrame; + if (frame != null) + { + var shellView = frame.Content as ShellView; + if (shellView == null) + { + return; + } + } + + TypingTuple tuple; + if (!typingCache.TryGetValue(chatId.Value, out tuple)) + { + for (var i = 0; i < Items.Count; i++) + { + var dialog = Items[i] as TLEncryptedDialog; + if (dialog != null && dialog.Peer.Id.Value == chatId.Value) + { + tuple = new TypingTuple(dialog, new InputTypingManager( + users => Execute.BeginOnUIThread(() => + { + dialog.Typing = GetTyping(dialog.Peer, users, CacheService.GetUser, GetFullInfoAsync); + dialog.NotifyOfPropertyChange(() => dialog.Self.Typing); + }), + () => Execute.BeginOnUIThread(() => + { + dialog.Typing = null; + dialog.NotifyOfPropertyChange(() => dialog.Self.Typing); + }))); + typingCache[chatId.Value] = tuple; + break; + } + } + } + + if (tuple != null) + { + if (action is TLSendMessageCancelAction) + { + tuple.Item2.RemoveTypingUser(tuple.Item1.WithId); + } + else + { + tuple.Item2.AddTypingUser(tuple.Item1.WithId, action); + } + } + }); + } + + private void HandleTypingCommon(TLUpdateTypingBase updateTyping, Dictionary typingCache) + { + Execute.BeginOnUIThread(() => + { + var frame = Application.Current.RootVisual as TelegramTransitionFrame; + if (frame != null) + { + var shellView = frame.Content as ShellView; + if (shellView == null) + { + return; + } + } + + var updateChatUserTyping = updateTyping as TLUpdateChatUserTyping; + var id = updateChatUserTyping != null ? updateChatUserTyping.ChatId : updateTyping.UserId; + TypingTuple tuple; + if (!typingCache.TryGetValue(id.Value, out tuple)) + { + for (var i = 0; i < Items.Count; i++) + { + if (updateChatUserTyping == null + && Items[i].Peer is TLPeerUser + && Items[i].Peer.Id.Value == id.Value + || (updateChatUserTyping != null + && Items[i].Peer is TLPeerChat + && Items[i].Peer.Id.Value == id.Value) + || (updateChatUserTyping != null + && Items[i].Peer is TLPeerChannel + && Items[i].Peer.Id.Value == id.Value)) + { + var dialog = Items[i] as TLDialog; + if (dialog != null) + { + tuple = new TypingTuple(dialog, new InputTypingManager( + users => Execute.BeginOnUIThread(() => + { + dialog.Typing = GetTyping(dialog.Peer, users, CacheService.GetUser, GetFullInfoAsync); + dialog.NotifyOfPropertyChange(() => dialog.Self.Typing); + }), + () => Execute.BeginOnUIThread(() => + { + dialog.Typing = null; + dialog.NotifyOfPropertyChange(() => dialog.Self.Typing); + }))); + typingCache[id.Value] = tuple; + } + break; + } + } + } + + if (tuple != null) + { + TLSendMessageActionBase action = null; + var typingAction = updateTyping as IUserTypingAction; + if (typingAction != null) + { + action = typingAction.Action; + } + + if (action is TLSendMessageCancelAction) + { + tuple.Item2.RemoveTypingUser(updateTyping.UserId.Value); + } + else + { + tuple.Item2.AddTypingUser(updateTyping.UserId.Value, action); + } + } + }); + } + + private readonly Dictionary _encryptedChatTypingCache = new Dictionary(); + + public void Handle(TLUpdateEncryptedChatTyping encryptedChatTyping) + { + HandleTypingCommon(encryptedChatTyping.ChatId, new TLSendMessageTypingAction(), _encryptedChatTypingCache); + } + + public void Handle(TLDecryptedMessageBase messageBase) + { + var serviceMessage = messageBase as TLDecryptedMessageService; + if (serviceMessage != null) + { + var typingAction = serviceMessage.Action as TLDecryptedMessageActionTyping; + if (typingAction != null) + { + HandleTypingCommon(messageBase.ChatId, typingAction.Action, _encryptedChatTypingCache); + } + } + } + + private readonly Dictionary _userTypingCache = new Dictionary(); + + public void Handle(TLUpdateUserTyping userTyping) + { + HandleTypingCommon(userTyping, _userTypingCache); + } + + private readonly Dictionary _chatUserTypingCache = new Dictionary(); + + public void Handle(TLUpdateChatUserTyping chatUserTyping) + { + HandleTypingCommon(chatUserTyping, _chatUserTypingCache); + } + + public static Typing GetTyping(TLPeerBase peer, IList typingUsers, Func getUser, Action getFullInfoAction) + { + if (peer is TLPeerUser + || peer is TLPeerEncryptedChat) + { + var typingUser = typingUsers.FirstOrDefault(); + if (typingUser != null) + { + var action = typingUser.Item2; + if (action is TLSendMessageUploadPhotoAction) + { + return new Typing(TypingType.Upload, AppResources.SendingPhoto.ToLower(CultureInfo.InvariantCulture)); + } + if (action is TLSendMessageRecordAudioAction) + { + return new Typing(TypingType.Record, AppResources.RecordingVoiceMessage.ToLower(CultureInfo.InvariantCulture)); + } + if (action is TLSendMessageUploadAudioAction) + { + return new Typing(TypingType.Record, AppResources.SendingAudio.ToLower(CultureInfo.InvariantCulture)); + } + if (action is TLSendMessageUploadDocumentAction) + { + return new Typing(TypingType.Upload, AppResources.SendingFile.ToLower(CultureInfo.InvariantCulture)); + } + if (action is TLSendMessageRecordVideoAction) + { + return new Typing(TypingType.Upload, AppResources.RecordingVideo.ToLower(CultureInfo.InvariantCulture)); + } + if (action is TLSendMessageUploadVideoAction) + { + return new Typing(TypingType.Upload, AppResources.SendingVideo.ToLower(CultureInfo.InvariantCulture)); + } + if (action is TLSendMessageGamePlayAction) + { + return new Typing(TypingType.Text, AppResources.PlayingGame.ToLower(CultureInfo.InvariantCulture)); + } + } + + return new Typing(TypingType.Text, AppResources.Typing.ToLower(CultureInfo.InvariantCulture)); + } + + if (typingUsers.Count == 1) + { + var userId = new TLInt(typingUsers[0].Item1); + var user = getUser(userId); + if (user == null) + { + getFullInfoAction.SafeInvoke(peer); + + return null; + } + + var userName = TLString.IsNullOrEmpty(user.FirstName) ? user.LastName : user.FirstName; + var typingUser = typingUsers.FirstOrDefault(); + if (typingUser != null) + { + var action = typingUser.Item2; + if (action is TLSendMessageUploadPhotoAction) + { + return new Typing(TypingType.Upload, string.Format("{0} {1}", userName, AppResources.IsSendingPhoto.ToLower(CultureInfo.InvariantCulture))); + } + if (action is TLSendMessageUploadAudioAction) + { + return new Typing(TypingType.Record, string.Format("{0} {1}", userName, AppResources.IsSendingAudio.ToLower(CultureInfo.InvariantCulture))); + } + if (action is TLSendMessageRecordAudioAction) + { + return new Typing(TypingType.Record, string.Format("{0} {1}", userName, AppResources.IsRecordingAudio.ToLower(CultureInfo.InvariantCulture))); + } + if (action is TLSendMessageUploadDocumentAction) + { + return new Typing(TypingType.Upload, string.Format("{0} {1}", userName, AppResources.IsSendingFile.ToLower(CultureInfo.InvariantCulture))); + } + if (action is TLSendMessageRecordVideoAction) + { + return new Typing(TypingType.Upload, string.Format("{0} {1}", userName, AppResources.IsRecordingVideo.ToLower(CultureInfo.InvariantCulture))); + } + if (action is TLSendMessageUploadVideoAction) + { + return new Typing(TypingType.Upload, string.Format("{0} {1}", userName, AppResources.IsSendingVideo.ToLower(CultureInfo.InvariantCulture))); + } + if (action is TLSendMessageGamePlayAction) + { + return new Typing(TypingType.Text, string.Format("{0} {1}", userName, AppResources.IsPlayingGame.ToLower(CultureInfo.InvariantCulture))); + } + } + + return new Typing(TypingType.Text, string.Format("{0} {1}", userName, AppResources.IsTyping.ToLower(CultureInfo.InvariantCulture))); + } + + if (typingUsers.Count <= 3) + { + var firstNames = new List(typingUsers.Count); + var missingUsers = new List(); + foreach (var typingUser in typingUsers) + { + var user = getUser(new TLInt(typingUser.Item1)); + if (user != null) + { + var userName = TLString.IsNullOrEmpty(user.FirstName) ? user.LastName : user.FirstName; + firstNames.Add(userName.ToString()); + } + else + { + missingUsers.Add(new TLInt(typingUser.Item1)); + } + } + + if (missingUsers.Count > 0) + { + getFullInfoAction.SafeInvoke(peer); + + return null; + } + + return new Typing(TypingType.Text, string.Format("{0} {1}", string.Join(", ", firstNames), + AppResources.AreTyping.ToLower(CultureInfo.InvariantCulture))); + } + + return new Typing(TypingType.Text, string.Format("{0} {1}", Language.Declension( + typingUsers.Count, + AppResources.CompanyNominativeSingular, + AppResources.CompanyNominativePlural, + AppResources.CompanyGenitiveSingular, + AppResources.CompanyGenitivePlural).ToLower(CultureInfo.CurrentUICulture), + AppResources.AreTyping.ToLower(CultureInfo.InvariantCulture))); + } + + private void GetFullInfoAsync(TLPeerBase peer) + { + var peerChat = peer as TLPeerChat; + if (peerChat != null) + { + MTProtoService.GetFullChatAsync(peerChat.Id, result => { }, error => { }); + } + } + + public void Handle(ClearCacheEventArgs args) + { + BeginOnUIThread(() => + { + foreach (var item in Items) + { + item.NotifyOfPropertyChange(() => item.With); + } + }); + } + + public void Handle(ClearLocalDatabaseEventArgs args) + { + BeginOnUIThread(() => + { + foreach (var item in Items) + { + if (item.With != null) + { + item.With.ClearBitmap(); + } + } + }); + } + + public void Handle(TLUpdateEditMessage update) + { + var message = update.Message as TLMessageCommon; + if (message == null) return; + + Execute.BeginOnUIThread(() => + { + int index; + if (message.ToId is TLPeerUser) + { + index = message.Out.Value ? message.ToId.Id.Value : message.FromId.Value; + } + else + { + index = message.ToId.Id.Value; + } + + for (var i = 0; i < Items.Count; i++) + { + if (Items[i].Index == index + && Items[i].TopMessageId != null + && Items[i].TopMessageId.Value == message.Index) + { + Items[i].NotifyOfPropertyChange(() => Items[i].Self); + } + } + }); + } + + public void Handle(TLUpdateEditChannelMessage update) + { + var message = update.Message as TLMessageCommon; + if (message == null) return; + + Execute.BeginOnUIThread(() => + { + for (var i = 0; i < Items.Count; i++) + { + if (Items[i].Index == message.ToId.Id.Value + && Items[i].TopMessageId != null + && Items[i].TopMessageId.Value == message.Index) + { + Items[i].NotifyOfPropertyChange(() => Items[i].Self); + } + } + }); + } + + public void Handle(TLUpdateChannel update) + { + Execute.BeginOnUIThread(() => + { + var dialog = Items.FirstOrDefault(x => x.Peer is TLPeerChannel && x.Peer.Id.Value == update.ChannelId.Value); + if (dialog != null) + { + dialog.NotifyOfPropertyChange(() => dialog.Self); // update draft on set current user as admin + } + }); + } + + public void Handle(ProxyDataChangedEventArgs args) + { + //Execute.BeginOnUIThread(() => + //{ + // var dataPromo = args.ProxyData as TLProxyDataPromo; + // if (dataPromo != null && dataPromo.Channel != null) + // { + // Handle(new DialogAddedEventArgs(dataPromo.Channel)); + // } + // else + // { + // var promoChannel = Items.OfType().FirstOrDefault(x => x.IsPromo); + // if (promoChannel != null) + // { + // Handle(new DialogRemovedEventArgs(promoChannel)); + // } + // } + //}); + } + } +} diff --git a/TelegramClient.WP8/ViewModels/Dialogs/SecretDialogDetailsViewModel.Audio.cs b/TelegramClient.WP8/ViewModels/Dialogs/SecretDialogDetailsViewModel.Audio.cs new file mode 100755 index 0000000..2c98aa8 --- /dev/null +++ b/TelegramClient.WP8/ViewModels/Dialogs/SecretDialogDetailsViewModel.Audio.cs @@ -0,0 +1,257 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections; +using System.IO; +using System.IO.IsolatedStorage; +using Windows.Storage; +using Caliburn.Micro; +using Telegram.Api.TL; +using TelegramClient.Views.Controls; + +namespace TelegramClient.ViewModels.Dialogs +{ + public partial class SecretDialogDetailsViewModel + { + private void SendAudioInternal(TLObject obj) + { + var message = GetDecryptedMessage(obj); + if (message == null) return; + + var mediaDocument = message.Media as TLDecryptedMessageMediaDocument45; + if (mediaDocument != null) + { + var fileLocation = mediaDocument.File as TLEncryptedFile; + if (fileLocation == null) return; + + var fileName = String.Format("audio{0}_{1}.mp3", + fileLocation.Id, + fileLocation.AccessHash); + + byte[] data; + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + using (var fileStream = store.OpenFile(fileName, FileMode.Open, FileAccess.Read)) + { + data = new byte[fileStream.Length]; + fileStream.Read(data, 0, data.Length); + } + } + + var encryptedBytes = Telegram.Api.Helpers.Utils.AesIge(data, mediaDocument.Key.Data, mediaDocument.IV.Data, true); + using (var storage = IsolatedStorageFile.GetUserStoreForApplication()) + { + using (var file = storage.OpenFile("encrypted." + fileName, FileMode.Create, FileAccess.Write)) + { + file.Write(encryptedBytes, 0, encryptedBytes.Length); + } + } + + UploadFileManager.UploadFile(fileLocation.Id, obj, encryptedBytes); + + return; + } + + var mediaAudio = message.Media as TLDecryptedMessageMediaAudio; + if (mediaAudio != null) + { + var fileLocation = mediaAudio.File as TLEncryptedFile; + if (fileLocation == null) return; + + var fileName = String.Format("audio{0}_{1}.mp3", + fileLocation.Id, + fileLocation.AccessHash); + + byte[] data; + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + using (var fileStream = store.OpenFile(fileName, FileMode.Open, FileAccess.Read)) + { + data = new byte[fileStream.Length]; + fileStream.Read(data, 0, data.Length); + } + } + + var encryptedBytes = Telegram.Api.Helpers.Utils.AesIge(data, mediaAudio.Key.Data, mediaAudio.IV.Data, true); + using (var storage = IsolatedStorageFile.GetUserStoreForApplication()) + { + using (var file = storage.OpenFile("encrypted." + fileName, FileMode.Create, FileAccess.Write)) + { + file.Write(encryptedBytes, 0, encryptedBytes.Length); + } + } + + UploadFileManager.UploadFile(fileLocation.Id, obj, encryptedBytes); + + return; + } + } + + public void SendAudio(AudioEventArgs args) + { + var chat = Chat as TLEncryptedChat; + if (chat == null) return; + + if (string.IsNullOrEmpty(args.OggFileName)) return; + + var dcId = TLInt.Random(); + var id = TLLong.Random(); + var accessHash = TLLong.Random(); + + var oggFileName = String.Format("audio{0}_{1}.mp3", id, accessHash); + var wavFileName = Path.GetFileNameWithoutExtension(oggFileName) + ".wav"; + + long size = 0; + using (var storage = IsolatedStorageFile.GetUserStoreForApplication()) + { + storage.MoveFile(args.OggFileName, oggFileName); + using (var file = storage.OpenFile(oggFileName, FileMode.Open, FileAccess.Read)) + { + size = file.Length; + } + + var wavStream = Wav.GetWavAsMemoryStream(args.PcmStream, 16000, 1, 16); + using (var file = new IsolatedStorageFileStream(wavFileName, FileMode.OpenOrCreate, storage)) + { + wavStream.Seek(0, SeekOrigin.Begin); + wavStream.CopyTo(file); + file.Flush(); + } + } + + var fileLocation = new TLEncryptedFile + { + Id = id, + AccessHash = accessHash, + DCId = dcId, + Size = new TLInt((int)size), + KeyFingerprint = new TLInt(0), + FileName = new TLString(Path.GetFileName(oggFileName)) + }; + + var keyIV = GenerateKeyIV(); + TLDecryptedMessageMediaBase decryptedMediaAudio; + var encryptedChat17 = chat as TLEncryptedChat17; + if (encryptedChat17 != null) + { + if (encryptedChat17.Layer.Value >= Constants.MinSecretChatWithAudioAsDocumentsLayer) + { + var opus = new TelegramClient_Opus.WindowsPhoneRuntimeComponent(); + var bytes = opus.GetWaveform(ApplicationData.Current.LocalFolder.Path + "\\" + oggFileName); + var resultSamples = bytes.Length; + var bites2 = new BitArray(5 * bytes.Length); + var count = 0; + for (var i = 0; i < bytes.Length; i++) + { + var result = bytes[i]; + var bit1 = result >> 0 & 0x1; + var bit2 = result >> 1 & 0x1; + var bit3 = result >> 2 & 0x1; + var bit4 = result >> 3 & 0x1; + var bit5 = result >> 4 & 0x1; + bites2[count] = Convert.ToBoolean(bit1); + bites2[count + 1] = Convert.ToBoolean(bit2); + bites2[count + 2] = Convert.ToBoolean(bit3); + bites2[count + 3] = Convert.ToBoolean(bit4); + bites2[count + 4] = Convert.ToBoolean(bit5); + count = count + 5; + } + + var bytesCount = (resultSamples * 5) / 8 + (((resultSamples * 5) % 8) == 0 ? 0 : 1); + var waveformBytes = new byte[bytesCount]; + bites2.CopyTo(waveformBytes, 0); + var waveform = waveformBytes != null ? TLString.FromBigEndianData(waveformBytes) : TLString.Empty; + + var audioAttribute = new TLDocumentAttributeAudio46 + { + Flags = new TLInt((int)DocumentAttributeAudioFlags.Voice), + Duration = new TLInt((int)args.Duration) + }; + + if (waveformBytes != null) + { + audioAttribute.Waveform = waveform; + } + + var attributes = new TLVector + { + audioAttribute + }; + + decryptedMediaAudio = new TLDecryptedMessageMediaDocument45 + { + Thumb = TLString.Empty, + ThumbW = new TLInt(0), + ThumbH = new TLInt(0), + MimeType = new TLString("audio/ogg"), + Size = new TLInt((int)size), + Key = keyIV.Item1, + IV = keyIV.Item2, + Attributes = attributes, + Caption = TLString.Empty, + NotListened = true, + + File = fileLocation, + + UploadingProgress = 0.001 + }; + } + else + { + decryptedMediaAudio = new TLDecryptedMessageMediaAudio17 + { + Duration = new TLInt((int)args.Duration), + MimeType = new TLString("audio/ogg"), + Size = new TLInt((int)size), + Key = keyIV.Item1, + IV = keyIV.Item2, + + UserId = new TLInt(StateService.CurrentUserId), + File = fileLocation, + + UploadingProgress = 0.001 + }; + } + } + else + { + decryptedMediaAudio = new TLDecryptedMessageMediaAudio + { + Duration = new TLInt((int)args.Duration), + //MimeType = new TLString("audio/ogg"), + Size = new TLInt((int)size), + Key = keyIV.Item1, + IV = keyIV.Item2, + + UserId = new TLInt(StateService.CurrentUserId), + File = fileLocation, + + UploadingProgress = 0.001 + }; + } + + var decryptedTuple = GetDecryptedMessageAndObject(TLString.Empty, decryptedMediaAudio, chat, true); + + //var message45 = decryptedTuple.Item1 as TLDecryptedMessage45; + //if (message45 != null && message45.IsVoice()) + //{ + // message45.NotListened = true; + //} + + BeginOnUIThread(() => + { + InsertSendingMessage(decryptedTuple.Item1); + NotifyOfPropertyChange(() => DescriptionVisibility); + }); + + BeginOnThreadPool(() => + CacheService.SyncDecryptedMessage(decryptedTuple.Item1, chat, + cachedMessage => SendAudioInternal(decryptedTuple.Item2))); + } + } +} diff --git a/TelegramClient.WP8/ViewModels/Media/MultiImageEditorViewModel.cs b/TelegramClient.WP8/ViewModels/Media/MultiImageEditorViewModel.cs new file mode 100755 index 0000000..60226fb --- /dev/null +++ b/TelegramClient.WP8/ViewModels/Media/MultiImageEditorViewModel.cs @@ -0,0 +1,743 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; +using System.Windows.Media; +using Windows.Storage; +using Windows.Storage.FileProperties; +using Windows.Storage.Pickers; +using Caliburn.Micro; +using Telegram.Api.Extensions; +using Telegram.Api.TL; +using Telegram.Logs; +using TelegramClient.Helpers; +using TelegramClient.Services; +using TelegramClient.ViewModels.Additional; +using TelegramClient.ViewModels.Contacts; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.Views.Media; +using PhotoFile = TelegramClient.Services.PhotoFile; + +namespace TelegramClient.ViewModels.Media +{ + public class MultiImageEditorViewModel : ViewAware + { + private bool _isGrouped = true; + + public bool IsGrouped + { + get { return _isGrouped; } + set + { + if (_isGrouped != value) + { + _isGrouped = value; + NotifyOfPropertyChange(() => IsGrouped); + } + } + } + + public Visibility TimerButtonVisibility + { + get { return _with is TLUser? Visibility.Visible : Visibility.Collapsed; } + } + + public Visibility GroupButtonVisibility + { + get + { + var encryptedChatBase = _with as TLEncryptedChatBase; + if (encryptedChatBase != null) + { + var encryptedChat = _with as TLEncryptedChat20; + if (encryptedChat != null && encryptedChat.Layer.Value >= Constants.MinSecretChatWithGroupedMediaLayer) + { + return Visibility.Visible; + } + + return Visibility.Collapsed; + } + + return Visibility.Visible; + } + } + + private IMultiImageEditorView _view; + + public IMultiImageEditorView View + { + get + { + _view = _view ?? GetView() as IMultiImageEditorView; + + return _view; + } + } + + public bool IsSecretChat { get; set; } + + private bool _isCaptionEnabled = true; + + public bool IsCaptionEnabled + { + get { return _isCaptionEnabled; } + set { _isCaptionEnabled = value; } + } + + private PhotoFile _currentItem; + + public PhotoFile CurrentItem + { + get { return _currentItem; } + set + { + if (_currentItem != value) + { + SwitchSelection(value, _currentItem); + _currentItem = value; + NotifyOfPropertyChange(() => CurrentItem); + NotifyOfPropertyChange(() => Caption); + } + } + } + + private void SwitchSelection(PhotoFile currentItem, PhotoFile previousItem) + { + if (currentItem != null) + { + currentItem.IsSelected = true; + } + + if (previousItem != null) + { + previousItem.IsSelected = false; + } + } + + public ObservableCollection Items { get; set; } + + private readonly Action> _sendPhotosAction; + + private readonly Func> _getUsernameHints; + + private readonly TLObject _with; + + public MultiImageEditorViewModel(Action> sendPhotosAction, Func> getUsernameHints, TLObject with) + { + _with = with; + _sendPhotosAction = sendPhotosAction; + _getUsernameHints = getUsernameHints; + + Items = new ObservableCollection(); + } + + #region Mentions + + public void ContinueLoadMentionHints() + { + if (!string.IsNullOrEmpty(Caption)) + { + var cachedResult = _getUsernameHints.Invoke(Caption); + if (cachedResult.Count > MaxResults) + { + CreateUsernameHints(); + + if (UsernameHints.Hints.Count == MaxResults) + { + var lastItem = UsernameHints.Hints.LastOrDefault(); + if (lastItem != null) + { + var lastIndex = cachedResult.IndexOf(lastItem); + if (lastIndex >= 0) + { + for (var i = lastIndex + 1; i < cachedResult.Count; i++) + { + UsernameHints.Hints.Add(cachedResult[i]); + } + } + } + } + } + } + } + + private void LoadMentionHints(string text) + { + if (_getUsernameHints != null) + { + var cachedResult = _getUsernameHints.Invoke(text); + + if (cachedResult.Count > 0) + { + CreateUsernameHints(); + + ClearUsernameHints(); + for (var i = 0; i < cachedResult.Count; i++) + { + if (UsernameHints.Hints.Count == MaxResults) break; + + UsernameHints.Hints.Add(cachedResult[i]); + } + } + else + { + ClearUsernameHints(); + } + } + } + + public void AddMention(TLUserBase userBase) + { + if (CurrentItem == null) return; + + CurrentItem.Mentions = CurrentItem.Mentions ?? new List(); + CurrentItem.Mentions.Add(userBase); + } + + private const int MaxResults = 10; + + public UsernameHintsViewModel UsernameHints { get; protected set; } + + private void CreateUsernameHints() + { + if (UsernameHints == null) + { + UsernameHints = new UsernameHintsViewModel(); + NotifyOfPropertyChange(() => UsernameHints); + } + } + + private void ClearUsernameHints() + { + if (UsernameHints != null) + { + UsernameHints.Hints.Clear(); + } + } + #endregion + + public IReadOnlyCollection Files { get; set; } + + public Action> ContinueAction { get; set; } + + public string Caption + { + get + { + if (_currentItem == null) return null; + + var message = _currentItem.Object as TLMessage; + if (message != null) + { + var media = message.Media as TLMessageMediaPhoto28; + if (media != null) + { + return message.Message.ToString(); + } + } + + var decryptedMessage = _currentItem.Object as TLDecryptedMessage; + if (decryptedMessage != null) + { + var media = decryptedMessage.Media as TLDecryptedMessageMediaPhoto45; + if (media != null) + { + return media.Caption.ToString(); + } + } + + return null; + } + set + { + var message = _currentItem.Object as TLMessage; + if (message != null) + { + var media = message.Media as TLMessageMediaPhoto28; + if (media != null) + { + if (!string.Equals(message.Message.ToString(), value)) + { + message.Message = new TLString(value); + + LoadMentionHints(value); + } + } + } + + var decryptedMessage = _currentItem.Object as TLDecryptedMessage; + if (decryptedMessage != null) + { + var media = decryptedMessage.Media as TLDecryptedMessageMediaPhoto45; + if (media != null) + { + if (!string.Equals(media.Caption.ToString(), value)) + { + media.Caption = new TLString(value); + + LoadMentionHints(value); + } + } + } + } + } + + private bool _isOpen; + + public bool IsOpen { get { return _isOpen; } } + + private bool _isDoneEnabled; + + public bool IsDoneEnabled + { + get { return _isDoneEnabled; } + set + { + if (_isDoneEnabled != value) + { + _isDoneEnabled = value; + NotifyOfPropertyChange(() => IsDoneEnabled); + } + } + } + + public bool IsDeleteEnabled + { + get { return Items.Count > 1; } + } + + public Func GetPhotoMessage { get; set; } + + public Func> GetDecryptedPhotoMessage { get; set; } + + public void Done() + { + _isOpen = false; + NotifyOfPropertyChange(() => IsOpen); + + var logString = new StringBuilder(); + logString.AppendLine("photos"); + var messages = new List(); + var randomIndex = new Dictionary(); + + var groupedId = IsGrouped && Items.Count(x => !x.IsButton) > 1 ? TLLong.Random() : null; + TLInt commonDate = null; + for (var i = 0; i < Items.Count; i++) + { + var item = Items[i]; + if (item.IsButton) continue; + + if (item.Message != null) + { + if (item.Message.RandomIndex == 0) + { + logString.AppendLine(string.Format("random_id=0 msg={0} original_file_name={1}", item.Message, + item.File.Name)); + continue; + } + + if (i % Constants.MaxGroupedMediaCount == 0) + { + groupedId = IsGrouped && Items.Count(x => !x.IsButton) > 1 ? TLLong.Random() : null; + } + + if (randomIndex.ContainsKey(item.Message.RandomIndex)) + { + logString.AppendLine(string.Format("random_id exists msg={0} original_file_name={1}", + item.Message, item.File.Name)); + continue; + } + + var message73 = item.Message as TLMessage73; + if (message73 != null) + { + if (commonDate == null) + { + commonDate = message73.Date; + } + message73.Date = commonDate; + message73.GroupedId = groupedId; + } + + randomIndex[item.Message.RandomIndex] = item.Message.RandomIndex; + + var mediaPhoto = item.Message.Media as TLMessageMediaPhoto28; + var photo = mediaPhoto.Photo as TLPhoto28; + var size = photo.Sizes.First() as TLPhotoSize; + var fileLocation = size.Location; + var fileName = String.Format("{0}_{1}_{2}.jpg", + fileLocation.VolumeId, + fileLocation.LocalId, + fileLocation.Secret); + + item.Message.Media.UploadingProgress = 0.001; + + if (item.TimerSpan != null && item.TimerSpan.Seconds > 0) + { + var message25 = item.Message as TLMessage25; + if (message25 != null) + { + message25.NotListened = true; + } + var ttlMessageMedia = item.Message.Media as ITTLMessageMedia; + if (ttlMessageMedia != null) + { + ttlMessageMedia.TTLSeconds = new TLInt(item.TimerSpan.Seconds); + } + } + + messages.Add(item); + logString.AppendLine(string.Format("msg={0} file_name={1}", item.Message, fileName)); + } + else if (item.DecryptedTuple != null) + { + if (item.DecryptedTuple.Item1.RandomIndex == 0) + { + logString.AppendLine(string.Format("random_id=0 msg={0} original_file_name={1}", item.DecryptedTuple.Item1, item.File.Name)); + continue; + } + + if (randomIndex.ContainsKey(item.DecryptedTuple.Item1.RandomIndex)) + { + logString.AppendLine(string.Format("random_id exists msg={0} original_file_name={1}", item.DecryptedTuple.Item1, item.File.Name)); + continue; + } + + var decryptedMessage73 = item.DecryptedTuple.Item1 as TLDecryptedMessage73; + if (decryptedMessage73 != null) + { + if (commonDate == null) + { + commonDate = decryptedMessage73.Date; + } + decryptedMessage73.Date = commonDate; + decryptedMessage73.GroupedId = groupedId; + } + + randomIndex[item.DecryptedTuple.Item1.RandomIndex] = item.DecryptedTuple.Item1.RandomIndex; + + var mediaPhoto = ((TLDecryptedMessage) item.DecryptedTuple.Item1).Media as TLDecryptedMessageMediaPhoto; + var fileLocation = mediaPhoto.Photo as TLEncryptedFile; + var fileName = String.Format("{0}_{1}_{2}.jpg", + fileLocation.Id, + fileLocation.DCId, + fileLocation.AccessHash); + + mediaPhoto.StorageFile = null; + mediaPhoto.UploadingProgress = 0.001; + + messages.Add(item); + logString.AppendLine(string.Format("msg={0} file_name={1}", item.DecryptedTuple.Item1, fileName)); + } + else + { + logString.AppendLine(string.Format("empty msg original_file_name={0}", item.File.Name)); + } + } + +#if MULTIPLE_PHOTOS + Log.Write(logString.ToString()); +#endif + + ContinueAction.SafeInvoke(messages); + } + + public void Cancel() + { + CloseEditor(); + } + + public void OpenEditor() + { + Items.Clear(); + //_items = new List { CurrentItem }; + //IsGrouped = true; + IsDoneEnabled = false; + _isOpen = CurrentItem != null; + NotifyOfPropertyChange(() => IsOpen); + NotifyOfPropertyChange(() => IsDeleteEnabled); + } + + public void CloseEditor() + { + if (View != null && View.IsExtendedImageEditorOpened) + { + View.CloseExtendedImageEditor(); + return; + } + + _isOpen = false; + NotifyOfPropertyChange(() => IsOpen); + + _currentItem = null; + } + + public async void OpenAnimationComplete() + { + Items.Add(CurrentItem); + Items.Add(new PhotoFile { IsButton = true }); + + Log.Write("send photos count=" + Files.Count); + + var files = new List(Files); + files.RemoveAt(0); + await AddFiles(files); + } + + public async Task AddFiles(IList files) + { + IsDoneEnabled = false; + + for (var i = 0; i < files.Count; i++) + { + var photoFile = new PhotoFile { File = files[i] }; + Items.Insert(Items.Count - 1, photoFile); + } + + if (CurrentItem == null) + { + CurrentItem = Items.FirstOrDefault(); + } + NotifyOfPropertyChange(() => IsDeleteEnabled); + + var maxCount = 9; + var counter = 0; + var firstSlice = new List(); + var secondSlice = new List(); + foreach (var item in Items) + { + if (item.IsButton) + { + continue; + } + + if (counter > maxCount) + { + secondSlice.Add(item); + } + else + { + firstSlice.Add(item); + } + counter++; + } + + //await UpdateThumbnails(firstSlice); + + var count = Items.Count; + if (count > 2) + { + var tasks = new List(); + for (var i = 0; i < count; i++) + { + var localItem = Items[i]; + if (localItem.Object != null) + { + continue; + } + if (localItem.IsButton) + { + continue; + } + + var task = Task.Run(() => + { + try + { + var file = localItem.File; + if (GetPhotoMessage != null) + { + var message = GetPhotoMessage(file); + localItem.Message = message; + } + else + { + var message = GetDecryptedPhotoMessage(file); + localItem.DecryptedTuple = message; + } + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + localItem.NotifyOfPropertyChange(() => localItem.Self); + }); + } + catch (Exception ex) + { + Log.Write(ex.ToString()); + } + }); + tasks.Add(task); + } + + await Task.WhenAll(tasks); + + if (!IsOpen) + { + return; + } + + NotifyOfPropertyChange(() => CurrentItem); + + var date = CurrentItem.Date; + foreach (var item in Items) + { + if (item != null && item.Message != null) + { + item.Date = date; + } + } + + IsDoneEnabled = true; + + //await UpdateThumbnails(secondSlice); + } + else + { + IsDoneEnabled = CurrentItem != null && CurrentItem.Object != null; + } + } + + private async Task UpdateThumbnails(IList items) + { + foreach (var item in items) + { + if (item.Thumbnail != null) continue; + + var thumbnail = await DialogDetailsViewModel.GetPhotoThumbnailAsync(item.File, ThumbnailMode.ListView, 99, ThumbnailOptions.None); + item.Thumbnail = thumbnail; + item.NotifyOfPropertyChange(() => item.Self); + } + } + + public async void PickPhoto() + { +#if WP81 + var photoPickerSettings = IoC.Get().GetPhotoPickerSettings(); + if (photoPickerSettings != null && photoPickerSettings.External) + { + ((App)Application.Current).ChooseFileInfo = new ChooseFileInfo(DateTime.Now); + var fileOpenPicker = new FileOpenPicker(); + fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary; + fileOpenPicker.ViewMode = PickerViewMode.Thumbnail; + fileOpenPicker.FileTypeFilter.Clear(); + fileOpenPicker.FileTypeFilter.Add(".bmp"); + fileOpenPicker.FileTypeFilter.Add(".png"); + fileOpenPicker.FileTypeFilter.Add(".jpeg"); + fileOpenPicker.FileTypeFilter.Add(".jpg"); + fileOpenPicker.ContinuationData.Add("From", IsSecretChat ? "SecretDialogDetailsView" : "DialogDetailsView"); + fileOpenPicker.ContinuationData.Add("Type", "Image"); + if (Environment.OSVersion.Version.Major >= 10) + { + var result = await fileOpenPicker.PickMultipleFilesAsync(); + if (result.Count > 0) + { + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + _sendPhotosAction.SafeInvoke(result); + }); + } + } + else + { + fileOpenPicker.PickMultipleFilesAndContinue(); + } + } + else + { + ChooseAttachmentViewModel.OpenPhotoPicker(false, (r1, r2) => _sendPhotosAction(r1)); + } +#endif + } + + public void SelectMessage(PhotoFile file) + { + CurrentItem = file; + } + + public void Delete(PhotoFile file) + { + var index = Items.IndexOf(file); + if (index == -1) + { + return; + } + Items.RemoveAt(index); + if (CurrentItem == file) + { + if (Items.Count > 1) + { + if (Items.Count > index + 1) + { + CurrentItem = Items[index]; + } + else + { + CurrentItem = Items[index - 1]; + } + } + else + { + CurrentItem = null; + } + } + + IsDoneEnabled = Items.FirstOrDefault(x => !x.IsButton) != null; + NotifyOfPropertyChange(() => IsDeleteEnabled); + + if (Items.Count == 1) + { + _isOpen = false; + NotifyOfPropertyChange(() => IsOpen); + } + } + } + + public class TimerSpanToBrushConverter : DependencyObject, IValueConverter + { + public static readonly DependencyProperty AccentBrushProperty = DependencyProperty.Register( + "AccentBrush", typeof(Brush), typeof(TimerSpanToBrushConverter), new PropertyMetadata(default(Brush))); + + public Brush AccentBrush + { + get { return (Brush) GetValue(AccentBrushProperty); } + set { SetValue(AccentBrushProperty, value); } + } + + public static readonly DependencyProperty NormalBrushProperty = DependencyProperty.Register( + "NormalBrush", typeof(Brush), typeof(TimerSpanToBrushConverter), new PropertyMetadata(default(Brush))); + + public Brush NormalBrush + { + get { return (Brush) GetValue(NormalBrushProperty); } + set { SetValue(NormalBrushProperty, value); } + } + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var timerSpan = value as TimerSpan; + if (timerSpan != null && timerSpan.Seconds > 0) + { + return AccentBrush; + } + + return NormalBrush; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/TelegramClient.WP8/Views/Additional/StartupView.xaml b/TelegramClient.WP8/Views/Additional/StartupView.xaml new file mode 100755 index 0000000..5c548f8 --- /dev/null +++ b/TelegramClient.WP8/Views/Additional/StartupView.xaml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Dialogs/DialogDetailsView.xaml.cs b/TelegramClient.WP8/Views/Dialogs/DialogDetailsView.xaml.cs new file mode 100755 index 0000000..deb6b68 --- /dev/null +++ b/TelegramClient.WP8/Views/Dialogs/DialogDetailsView.xaml.cs @@ -0,0 +1,4435 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.IO.IsolatedStorage; +using System.Linq; +using System.Reactive.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using Caliburn.Micro; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Controls.Extensions; +using Telegram.EmojiPanel; +using Telegram.EmojiPanel.Controls.Emoji; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; +using Telegram.Api.Aggregator; +using Telegram.Api.Services.Updates; +using Telegram.Api.TL; +using TelegramClient.Controls; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.Utils; +using TelegramClient.ViewModels; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.Views.Additional; +using TelegramClient.Views.Controls; +using TelegramClient.Views.Media; +using TelegramClient_Native; +using Action = System.Action; +using AudioEventArgs = TelegramClient.Views.Controls.AudioEventArgs; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; +using StickerSelectedEventArgs = Telegram.EmojiPanel.Controls.Emoji.StickerSelectedEventArgs; + +namespace TelegramClient.Views.Dialogs +{ + public partial class DialogDetailsView : IDialogDetailsView + { + public DialogDetailsViewModel ViewModel + { + get { return DataContext as DialogDetailsViewModel; } + } + + public void MoveCurretToEnd() + { + if (FocusManager.GetFocusedElement() != InputMessage) return; + + InputMessage.SelectionStart = InputMessage.Text.Length; + InputMessage.SelectionLength = 0; + } + + private readonly AppBarButton _doneButton = new AppBarButton + { + Text = AppResources.Done, + IconUri = new Uri("/Images/ApplicationBar/appbar.check.png", UriKind.Relative) + }; + + private readonly AppBarButton _cancelButton = new AppBarButton + { + Text = AppResources.Cancel, + IconUri = new Uri("/Images/ApplicationBar/appbar.cancel.rest.png", UriKind.Relative) + }; + + private readonly MenuItem _manageButton = new MenuItem + { + Header = AppResources.Select + }; + + private readonly MenuItem _searchMenuItem = new MenuItem + { + Header = AppResources.Search, + }; + + private readonly MenuItem _pinToStartMenuItem = new MenuItem + { + Header = AppResources.PinToStart + }; + + private readonly MenuItem _shareMyContactInfoMenuItem = new MenuItem + { + Header = AppResources.ShareMyContactInfo + }; + + private readonly MenuItem _helpMenuItem = new MenuItem + { + Header = AppResources.Help + }; + + private readonly MenuItem _reportSpamMenuItem = new MenuItem + { + Header = AppResources.ReportSpam + }; + + private readonly MenuItem _callMenuItem = new MenuItem + { + Header = AppResources.Call + }; + + private readonly MenuItem _debugMenuItem = new MenuItem + { + Header = "Debug" + }; + + private EmojiControl _emojiKeyboard; + + private TranslateTransform _frameTransform; + + public static readonly DependencyProperty RootFrameTransformProperty = DependencyProperty.Register( + "RootFrameTransformProperty", typeof(double), typeof(DialogDetailsView), new PropertyMetadata(OnRootFrameTransformChanged)); + + private static void OnRootFrameTransformChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var view = d as DialogDetailsView; + if (view != null) + { + view._frameTransform.Y = 0; + } + } + + public double RootFrameTransform + { + get { return (double)GetValue(RootFrameTransformProperty); } + set { SetValue(RootFrameTransformProperty, value); } + } + + private void SetRootFrameBinding() + { + var frame = (Frame)Application.Current.RootVisual; + _frameTransform = ((TranslateTransform)((TransformGroup)frame.RenderTransform).Children[0]); + var binding = new Binding("Y") + { + Source = _frameTransform + }; + SetBinding(RootFrameTransformProperty, binding); + } + + private void RemoveRootFrameBinding() + { + ClearValue(RootFrameTransformProperty); + } + + private void CloseEmojiPlaceholder() + { + InputMessage.ClosePlaceholder(); + + if (_emojiKeyboard != null) + { + _emojiKeyboard.ClosePreview(); + _emojiKeyboard.ReloadStickerSprites(); + } + } + + private void OpenCommandsPlaceholder() + { + CommandsControl.Visibility = Visibility.Visible; + InputMessage.KeyboardButtonImageString = GetReplyKeyboardImageString(); + } + + private void CloseCommandsPlaceholder() + { + CommandsControl.Visibility = Visibility.Collapsed; + InputMessage.KeyboardButtonImageString = GetReplyKeyboardImageString(); + } + + private string GetReplyKeyboardImageString() + { + if (ViewModel != null) + { + var replyMarkup = ViewModel.ReplyMarkup as TLReplyKeyboardMarkup; + if (replyMarkup != null) + { + if (CommandsControl.Visibility == Visibility.Visible) + { + return "/Images/W10M/ic_keyboard_2x.png"; + } + + return "/Images/W10M/ic_botkeyboard_2x.png"; + } + + if (ViewModel.HasBots) + { + return "/Images/W10M/ic_commands_2x.png"; + } + } + + return null; + } + + + private void InputMessage_OnEmojiClick(object sender, System.EventArgs e) + { + OnSmileButtonClick(); + } + + private void InputMessage_OnSendClick(object sender, System.EventArgs e) + { + if (ViewModel.IsEditingEnabled) + { + ViewModel.SaveMessage(); + } + else + { + ViewModel.Send(); + } + } + + private void InputMessage_OnAttachClick(object sender, System.EventArgs e) + { + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + CloseCommandsPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + if (_focusedElement == InputMessage) + { + ChooseAttachment.Focus(); + Telegram.Api.Helpers.Execute.BeginOnUIThread(TimeSpan.FromSeconds(.35), () => ViewModel.Attach()); + } + else + { + ChooseAttachment.Focus(); + ViewModel.Attach(); + } + } + + private object _previousFocusedElement; + + private object _focusedElement; + + public DialogDetailsView() + { + ShellViewModel.WriteTimer("View start ctor"); + + InitializeComponent(); + + CaptionBorder.Background = ShellView.CaptionBrush; + + ShellViewModel.WriteTimer("View start ctor InitializeComponent"); + + //Full HD + OptimizeFullHD(); + + ShellViewModel.WriteTimer("View start ctor OptimizeFullHD"); + + _doneButton.Click += (sender, args) => ViewModel.SaveMessage(); + _cancelButton.Click += (sender, args) => ViewModel.CancelSaveMessage(); + + _manageButton.Click += (sender, args) => ViewModel.IsSelectionEnabled = true; + + _pinToStartMenuItem.Click += (sender, args) => ViewModel.PinToStart(); + _shareMyContactInfoMenuItem.Click += (sender, args) => ViewModel.InvokeUserAction(); + _helpMenuItem.Click += (sender, args) => ViewModel.Help(); + _searchMenuItem.Click += (sender, args) => ViewModel.Search(); + _reportSpamMenuItem.Click += (sender, args) => ViewModel.ReportSpam(); + _callMenuItem.Click += (sender, args) => ViewModel.Call(); + _debugMenuItem.Click += (sender, args) => + { + var aggregator = IoC.Get(); + + aggregator.Publish(new UpdateCompletedEventArgs()); + }; + + ShellViewModel.WriteTimer("View start ctor set appbar"); + + GotFocus += (sender, args) => + { + System.Diagnostics.Debug.WriteLine(args.OriginalSource); + _previousFocusedElement = _focusedElement; + _focusedElement = args.OriginalSource; + }; + + var viewportChangedEvents = Observable.FromEventPattern( + keh => { MessagesList.ViewportChanged += keh; }, + keh => { MessagesList.ViewportChanged -= keh; }); + + _viewportChangedSubscription = viewportChangedEvents + .Sample(TimeSpan.FromSeconds(1.0)) + .ObserveOnDispatcher() + .Subscribe(e => MessagesList_OnViewportChanged()); + + Loaded += InitializeMTProtoService; + + Loaded += (sender, args) => + { + if (_viewportChangedSubscription == null) + { + _viewportChangedSubscription = viewportChangedEvents + .Sample(TimeSpan.FromSeconds(1.0)) + .ObserveOnDispatcher() + .Subscribe(e => MessagesList_OnViewportChanged()); + } + + ShellViewModel.WriteTimer("View start Loaded"); + ViewModel.OnLoaded(); +#if LOG_NAVIGATION + TLUtils.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + "DV Loaded", LogSeverity.Error); +#endif + InputMessage.KeyboardButtonImageString = GetReplyKeyboardImageString(); + InputMessage.KeyboardButtonVisibility = GetReplyKeyboardButtonVisibility(); + InputMessage.MuteButtonVisibility = GetMuteButtonVisibility(); + + SetRootFrameBinding(); + + RunAnimation(); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(TimeSpan.FromSeconds(1.0), () => + { + if (ViewModel.StateService.FocusOnInputMessage) + { + ViewModel.StateService.FocusOnInputMessage = false; + if (!ViewModel.IsAppBarCommandVisible) + { + InputMessage.Focus(); + } + } + }); + + if (ViewModel.ChooseAttachment != null) + { + ViewModel.ChooseAttachment.PropertyChanged += OnChooseAttachmentPropertyChanged; + } + if (ViewModel.ImageViewer != null) + { + ViewModel.ImageViewer.PropertyChanged += OnImageViewerPropertyChanged; + } + if (ViewModel.MultiImageEditor != null) + { + ViewModel.MultiImageEditor.PropertyChanged += OnMultiImageEditorPropertyChanged; + } + if (ViewModel.ImageEditor != null) + { + ViewModel.ImageEditor.PropertyChanged += OnImageEditorPropertyChanged; + } + if (ViewModel.AnimatedImageViewer != null) + { + ViewModel.AnimatedImageViewer.PropertyChanged += OnAnimatedImageViewerPropertyChanged; + } + if (ViewModel.VideoEditor != null) + { + ViewModel.VideoEditor.PropertyChanged += OnVideoEditorPropertyChanged; + } + if (ViewModel.LocationPicker != null) + { + ViewModel.LocationPicker.PropertyChanged += OnLocationPickerPropertyChanged; + } + if (ViewModel.ContactPicker != null) + { + ViewModel.ContactPicker.PropertyChanged += OnContactPickerPropertyChanged; + } + ViewModel.PropertyChanged += OnViewModelPropertyChanged; + ViewModel.ScrollToBottom += OnViewModelScrollToBottom; + ViewModel.ScrollTo += OnViewModelScrollTo; + + BuildLocalizedAppBar(); + + InputMessage.AudioRecorded += OnAudioRecorded; //AudioRecorder.AudioRecorded += OnAudioRecorded; + InputMessage.RecordStarted += OnRecordStarted; //AudioRecorder.RecordStarted += OnRecordStarted; + InputMessage.RecordingAudio += OnRecordingAudio; //AudioRecorder.RecordingAudio += OnRecordingAudio; + InputMessage.RecordCanceled += OnRecordCanceled; //AudioRecorder.RecordCanceled += OnRecordCanceled; + + BrowserNavigationService.TelegramLinkAction += ViewModel.OnTelegramLinkAction; + BrowserNavigationService.MentionNavigated += ViewModel.OnMentionNavigated; + BrowserNavigationService.SearchHashtag += ViewModel.OnSearchHashtag; + BrowserNavigationService.InvokeCommand += ViewModel.OnInvokeCommand; + BrowserNavigationService.OpenGame += ViewModel.OnOpenGame; + BrowserNavigationService.OpenPhone += ViewModel.OnOpenPhone; + + GifPlayerControl.MediaStateChanged += OnGifPlayerControlMediaStateChanged; + + ShellViewModel.WriteTimer("View end Loaded"); + }; + + Unloaded += (sender, args) => + { + if (_viewportChangedSubscription != null) + { + _viewportChangedSubscription.Dispose(); + _viewportChangedSubscription = null; + } + +#if LOG_NAVIGATION + TLUtils.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + "DV Unloaded", LogSeverity.Error); +#endif + + RemoveRootFrameBinding(); + + if (ViewModel.ChooseAttachment != null) + { + ViewModel.ChooseAttachment.PropertyChanged -= OnChooseAttachmentPropertyChanged; + } + if (ViewModel.ImageViewer != null) + { + ViewModel.ImageViewer.PropertyChanged -= OnImageViewerPropertyChanged; + } + if (ViewModel.MultiImageEditor != null) + { + ViewModel.MultiImageEditor.PropertyChanged -= OnMultiImageEditorPropertyChanged; + } + if (ViewModel.ImageEditor != null) + { + ViewModel.ImageEditor.PropertyChanged -= OnImageEditorPropertyChanged; + } + if (ViewModel.AnimatedImageViewer != null) + { + ViewModel.AnimatedImageViewer.PropertyChanged -= OnAnimatedImageViewerPropertyChanged; + } + if (ViewModel.VideoEditor != null) + { + ViewModel.VideoEditor.PropertyChanged -= OnVideoEditorPropertyChanged; + } + if (ViewModel.LocationPicker != null) + { + ViewModel.LocationPicker.PropertyChanged -= OnLocationPickerPropertyChanged; + } + if (ViewModel.ContactPicker != null) + { + ViewModel.ContactPicker.PropertyChanged -= OnContactPickerPropertyChanged; + } + ViewModel.PropertyChanged -= OnViewModelPropertyChanged; + ViewModel.ScrollToBottom -= OnViewModelScrollToBottom; + ViewModel.ScrollTo -= OnViewModelScrollTo; + + InputMessage.AudioRecorded -= OnAudioRecorded; //AudioRecorder.AudioRecorded -= OnAudioRecorded; + InputMessage.RecordStarted -= OnRecordStarted; //AudioRecorder.RecordStarted -= OnRecordStarted; + InputMessage.RecordingAudio -= OnRecordingAudio; //AudioRecorder.RecordingAudio -= OnRecordingAudio; + InputMessage.RecordCanceled -= OnRecordCanceled; //AudioRecorder.RecordCanceled -= OnRecordCanceled; + + BrowserNavigationService.TelegramLinkAction -= ViewModel.OnTelegramLinkAction; + BrowserNavigationService.MentionNavigated -= ViewModel.OnMentionNavigated; + BrowserNavigationService.SearchHashtag -= ViewModel.OnSearchHashtag; + BrowserNavigationService.InvokeCommand -= ViewModel.OnInvokeCommand; + BrowserNavigationService.OpenGame -= ViewModel.OnOpenGame; + BrowserNavigationService.OpenPhone -= ViewModel.OnOpenPhone; + + GifPlayerControl.MediaStateChanged -= OnGifPlayerControlMediaStateChanged; + }; + + ShellViewModel.WriteTimer("View stop ctor"); + } + + private void OnGifPlayerControlMediaStateChanged(object sender, MediaStateChangedEventArgs args) + { + switch (args.State) + { + case GifPlayerControlState.Opening: + { + var player = Player.Content as PlayerView; + if (player == null) + { + player = new PlayerView(); + player.Closed += (o, eventArgs) => + { + var frame = Application.Current.RootVisual as TelegramTransitionFrame; + if (frame != null) + { + frame.HidePlayer(); + } + player.Close(() => + { + GifPlayerControl.StopVideo(); + + Player.Content = null; + ResumeChatPlayers(); + }); + }; + player.Paused += (o, eventArgs) => + { + var gifPlayer = MessagePlayerControl.Player.Tag as GifPlayerControl; + if (gifPlayer != null) + { + if (gifPlayer.Media == player.Message.Media) + { + gifPlayer.ToggleVideoPlay(); + } + } + }; + player.Resumed += (o, eventArgs) => + { + var gifPlayer = MessagePlayerControl.Player.Tag as GifPlayerControl; + if (gifPlayer != null) + { + if (gifPlayer.Media == player.Message.Media) + { + gifPlayer.ToggleVideoPlay(); + } + } + }; + + Player.Content = player; + } + + player.Message = ViewModel.Items.OfType().FirstOrDefault(x => x.Media == args.Media); + + player.Resume(); + var frame1 = Application.Current.RootVisual as TelegramTransitionFrame; + if (frame1 != null) + { + frame1.HidePlayer(); + } + + break; + } + case GifPlayerControlState.Opened: + + break; + case GifPlayerControlState.Failed: + + break; + case GifPlayerControlState.Paused: + { + var player = Player.Content as PlayerView; + if (player != null) + { + player.Pause(); + } + break; + } + case GifPlayerControlState.Resumed: + { + var player = Player.Content as PlayerView; + if (player != null) + { + player.Resume(); + } + break; + } + case GifPlayerControlState.Ended: + { + var player = Player.Content as PlayerView; + if (player != null) + { + var frame = Application.Current.RootVisual as TelegramTransitionFrame; + if (frame != null) + { + frame.HidePlayer(); + } + + player.Close(() => + { + Player.Content = null; + ResumeChatPlayers(); + }); + } + else + { + ResumeChatPlayers(); + } + break; + } + } + } + + private void InitializeMTProtoService(object sender, RoutedEventArgs e) + { + Loaded -= InitializeMTProtoService; + + var mtProtoService = IoC.Get(); + mtProtoService.StartInitialize(); + } + + private TLAllStickers _allStickers; + + private void OnSmileButtonClick() + { + if (_emojiKeyboard == null) + { + _emojiKeyboard = EmojiControl.GetInstance(); + + var channel68 = ViewModel.With as TLChannel68; + if (channel68 != null) + { + _emojiKeyboard.SetGroupStickers(channel68, channel68.StickerSet); + } + else + { + _emojiKeyboard.SetGroupStickers(null, null); + } + + _allStickers = _allStickers ?? IoC.Get().GetAllStickers(); + var isStickersPanelVisible = true; + //var allStickers = _allStickers as TLAllStickers43; + //if (allStickers != null && allStickers.ShowStickersTab != null) + //{ + // isStickersPanelVisible = allStickers.ShowStickersTab.Value; + //} + _emojiKeyboard.BindTextBox(InputMessage.InnerTextBox, isStickersPanelVisible); + _emojiKeyboard.StickerSelected += OnStickerSelected; + _emojiKeyboard.StickerSetAdded += OnStickerSetAdded; + _emojiKeyboard.SettingsButtonClick += OnSettingsButtonClick; + _emojiKeyboard.OpenFullScreen += OnOpenFullScreen; + _emojiKeyboard.CloseFullScreen += OnCloseFullScreen; + InputMessage.EmojiPlaceholder.Content = _emojiKeyboard; + + _emojiKeyboard.IsOpen = true; + + //_emojiKeyboard.SetHeight(InputBox.KeyboardHeight > 0.0 ? InputBox.KeyboardHeight : _emojiKeyboard.Height); + } + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + //System.Diagnostics.Debug.WriteLine("Keyboard"); + + if (InputMessage.EmojiPlaceholder.Opacity == 0.0) + { + _smileButtonPressed = true; + + InputMessage.OpenPlaceholder(); + + if (_emojiKeyboard != null) + { + _emojiKeyboard.OpenStickerSprites(); + } + } + else + { + InputMessage.InnerTextBox.Focus(); + } + } + else + { + InputMessage.OpenPlaceholder(); + + if (_emojiKeyboard != null) + { + _emojiKeyboard.OpenStickerSprites(); + } + + SetCaptionVisibility(Visibility.Collapsed); + CloseEmptyDialogPlaceholder(); + CloseCommandsPlaceholder(); + } + } + + private void OptimizeFullHD() + { + //var appBar = new ApplicationBar(); + //var appBarDefaultSize = appBar.DefaultSize; + + //AppBarCommandPlaceholder.Height = appBarDefaultSize; + } + + private void OnViewModelScrollToBottom(object sender, System.EventArgs e) + { + if (ViewModel.Items.Count > 0) + { + MessagesList.ScrollToItem(ViewModel.Items[0]); + + HideScrollToBottomButton(); + } + } + + private void OnViewModelScrollTo(object sender, ScrollToEventArgs e) + { + if (ViewModel.Items.Count > 0) + { + MessagesList.ScrollToItem(e.Message); + } + } + + private Binding _visibilityBinding; + private double _previousAudioRecorderMinHeight; + + private static Binding SaveVisibilityBinding(FrameworkElement element) + { + var visibilityExpression = element.GetBindingExpression(VisibilityProperty); + if (visibilityExpression != null) + { + return visibilityExpression.ParentBinding; + } + + return null; + } + + private static void RestoreVisibilityBinding(FrameworkElement element, Binding binding, Visibility defaultValue) + { + if (binding != null) + { + element.SetBinding(VisibilityProperty, binding); + } + else + { + element.Visibility = defaultValue; + } + } + + private void OnRecordCanceled(object sender, System.EventArgs e) + { + //AudioRecorder.MinHeight = _previousAudioRecorderMinHeight; + //RestoreVisibilityBinding(InputMessage, _visibilityBinding, Visibility.Visible); + //InputMessage.AdditionalButtons.Visibility = Visibility.Visible; + + ViewModel.AudioTypingManager.CancelTyping(); + } + + private void OnRecordStarted(object sender, System.EventArgs e) + { + //_visibilityBinding = SaveVisibilityBinding(InputMessage); + //_previousAudioRecorderMinHeight = AudioRecorder.MinHeight; + + //AudioRecorder.MinHeight = InputMessage.ActualHeight; + //InputMessage.Visibility = Visibility.Collapsed; + //InputMessage.AdditionalButtons.Visibility = Visibility.Collapsed; + } + + private void OnRecordingAudio(object sender, System.EventArgs e) + { + ViewModel.AudioTypingManager.SetTyping(); + } + + private void OnAudioRecorded(object sender, AudioEventArgs e) + { + //AudioRecorder.MinHeight = _previousAudioRecorderMinHeight; + //RestoreVisibilityBinding(InputMessage, _visibilityBinding, Visibility.Visible); + //InputMessage.AdditionalButtons.Visibility = Visibility.Visible; + + // чтобы быстро обновить Visibility InputMessage переносим все остальное в фон + var viewModel = ViewModel; + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => viewModel.SendAudio(e)); + } + + public void OpenBitmapCache() + { + MessagesCache.Visibility = Visibility.Visible; + MessagesList.Visibility = Visibility.Collapsed; + } + + public void CloseBitmapCache() + { + MessagesCache.Visibility = Visibility.Collapsed; + MessagesList.Visibility = Visibility.Visible; + } + + private Storyboard _forwardInStoryboard; + + private void RunAnimation() + { + if (_isForwardInAnimation) + { + _isForwardInAnimation = false; + + if (ViewModel.With.Bitmap != null) + { + MessagesList.Visibility = Visibility.Collapsed; + } + + var storyboard = new Storyboard(); + + if (ViewModel != null + && ViewModel.StateService.AnimateTitle) + { + ViewModel.StateService.AnimateTitle = false; + + var continuumElementX = new DoubleAnimationUsingKeyFrames(); + continuumElementX.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 130.0 }); + continuumElementX.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(continuumElementX, Title); + Storyboard.SetTargetProperty(continuumElementX, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateX)")); + storyboard.Children.Add(continuumElementX); + + var continuumElementY = new DoubleAnimationUsingKeyFrames(); + continuumElementY.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = -40.0 }); + continuumElementY.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0 }); + Storyboard.SetTarget(continuumElementY, Title); + Storyboard.SetTargetProperty(continuumElementY, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(continuumElementY); + } + + var continuumLayoutRootY = new DoubleAnimationUsingKeyFrames(); + continuumLayoutRootY.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 150.0 }); + continuumLayoutRootY.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(continuumLayoutRootY, LayoutRoot); + Storyboard.SetTargetProperty(continuumLayoutRootY, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(continuumLayoutRootY); + + var continuumLayoutRootOpacity = new DoubleAnimation + { + From = 0.0, + To = 1.0, + Duration = TimeSpan.FromSeconds(0.25), + EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } + }; + Storyboard.SetTarget(continuumLayoutRootOpacity, LayoutRoot); + Storyboard.SetTargetProperty(continuumLayoutRootOpacity, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(continuumLayoutRootOpacity); + + _forwardInStoryboard = storyboard; + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + LayoutRoot.Opacity = 1.0; + storyboard.Completed += (o, e) => + { + if (_backKeyPressed) return; + + ViewModel.ForwardInAnimationComplete(); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(TimeSpan.FromSeconds(1.0), () => + { + Items_OnManipulationStateChanged(this, System.EventArgs.Empty); + }); + } + ; + storyboard.Begin(); + }); + } + else if (_isBackwardOutAnimation) + { + _isBackwardOutAnimation = false; + + LayoutRoot.CacheMode = new BitmapCache(); + + var storyboard = new Storyboard(); + + var translateAnimation = new DoubleAnimationUsingKeyFrames(); + translateAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.00), Value = 0.0 }); + translateAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 150.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 6.0 } }); + Storyboard.SetTarget(translateAnimation, LayoutRoot); + Storyboard.SetTargetProperty(translateAnimation, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateAnimation); + + var opacityAnimation = new DoubleAnimationUsingKeyFrames(); + opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.00), Value = 1.0 }); + opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.15), Value = 1.0 }); + opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0 }); + Storyboard.SetTarget(opacityAnimation, LayoutRoot); + Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(opacityAnimation); + + storyboard.Begin(); + } + else if (_isBackwardInAnimation) + { + _isBackwardInAnimation = false; + + var storyboard = TelegramTurnstileAnimations.GetAnimation(LayoutRoot, TurnstileTransitionMode.BackwardIn); + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + LayoutRoot.Opacity = 1.0; + MessagesCache.Visibility = Visibility.Visible; + MessagesList.Visibility = Visibility.Collapsed; + storyboard.Completed += (o, e) => + { + MessagesCache.Visibility = Visibility.Collapsed; + MessagesList.Visibility = Visibility.Visible; + ViewModel.BackwardInAnimationComplete(); + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + StartGifPlayers(); + }); + }; + storyboard.Begin(); + }); + } + } + + private void StartGifPlayers() + { + Items_OnManipulationStateChanged(this, System.EventArgs.Empty); + var inlineBotResultsView = InlineBotResults.FindChildOfType(); + if (inlineBotResultsView != null) + { + inlineBotResultsView.StartActivePlayers(); + } + } + +#if DEBUG + ~DialogDetailsView() + { + System.Diagnostics.Debug.WriteLine("~DialogDetailsView"); + } +#endif + + private bool _inputMessageDisabled; + private bool _focusInputMessage; + + private void OpenPeerDetails_OnTap(object sender, GestureEventArgs args) + { + if (ViewModel.With is TLChatForbidden) + { + return; + } + + if (CommandsControl.Visibility == Visibility.Visible) + { + OpenEmptyDialogPlaceholder(); + CloseCommandsPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + } + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + } + + StopPlayersAndCreateBitmapCache(() => ViewModel.OpenPeerDetails()); + } + + public void StopPlayersAndCreateBitmapCache(Action callback = null) + { + GifPlayerControl.StopActivePlayers(); + GifPlayerControl.StopInlineBotActivePlayers(); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + CreateBitmapCache(); + MessagesCache.Visibility = Visibility.Visible; + MessagesList.Visibility = Visibility.Collapsed; + + callback.SafeInvoke(); + }); + } + + public void CreateBitmapCache(Action callback = null) + { + try + { + if (MessagesList.Visibility == Visibility.Visible) + { + var stopwatch = Stopwatch.StartNew(); + var writeableBitmap = new WriteableBitmap(MessagesList, null); + ViewModel.With.SetBitmap(writeableBitmap); + } + } + catch (Exception ex) + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("WritableBitmap exception " + ex); + } + + callback.SafeInvoke(); + } + + private void MorePanel_OnTap(object sender, GestureEventArgs args) + { + var frameworkElement = sender as FrameworkElement; + if (frameworkElement == null) return; + + var message = frameworkElement.DataContext as TLMessage; + if (message == null) return; + + if (CommandsControl.Visibility == Visibility.Visible) + { + OpenEmptyDialogPlaceholder(); + CloseCommandsPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + } + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + } + + // чтобы клавиатура успела опуститься + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + CreateBitmapCache(); + MessagesCache.Visibility = Visibility.Visible; + MessagesList.Visibility = Visibility.Collapsed; + + ViewModel.OpenCropedMessage(message); + }); + } + + private bool _isBackwardOutAnimation; + private bool _isBackwardInAnimation; + private bool _isForwardInAnimation; + private bool _isForwardOutAnimation; + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + ShellViewModel.WriteTimer("OnNavigatedTo start"); + ViewModel.OnNavigatedTo(); +#if LOG_NAVIGATION + TLUtils.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + string.Format("DV OnNavigatedTo Mode={0} Uri={1}", e.NavigationMode, e.Uri), LogSeverity.Error); +#endif + //MediaControl.Content = MessagePlayerControl.Player; + + if (e.NavigationMode == NavigationMode.New) + { + LayoutRoot.Opacity = 0.0; + _isForwardInAnimation = true; + } + else if (e.NavigationMode == NavigationMode.Back) + { + if (!_fromExternalUri) + { + LayoutRoot.Opacity = 0.0; + _isBackwardInAnimation = true; + } + else + { + ViewModel.BackwardInAnimationComplete(); + Deployment.Current.Dispatcher.BeginInvoke(() => + { + StartGifPlayers(); + + if (LiveLocationProgress.Controls.Count > 0) + { + foreach (var control in LiveLocationProgress.Controls) + { + control.Update(); + } + } + }); + } + _fromExternalUri = false; + } + else if (e.NavigationMode == NavigationMode.Forward && e.Uri != ExternalUri) + { + _isForwardOutAnimation = true; + } + else if (e.NavigationMode == NavigationMode.Reset) + { + if (_fromExternalUri) + { + Deployment.Current.Dispatcher.BeginInvoke(() => + { + StartGifPlayers(); + }); + } + } + + base.OnNavigatedTo(e); + + ShellViewModel.WriteTimer("OnNavigatedTo stop"); + } + + private static readonly Uri ExternalUri = new Uri(@"app://external/"); + + private bool _fromExternalUri; + private bool _suppressNavigation; + + protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) + { + + if (CancelNavigatingFrom(e)) return; + +#if LOG_NAVIGATION + TLUtils.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + string.Format("DV OnNavigatingFrom Mode={0} Uri={1}", e.NavigationMode, e.Uri), LogSeverity.Error); +#endif + GifPlayerControl.StopActivePlayers(); + GifPlayerControl.StopInlineBotActivePlayers(); + if (_emojiKeyboard != null) + { + // Destroy EmojiControl + _emojiKeyboard.IsOpen = false; + _emojiKeyboard.UnbindTextBox(); + _emojiKeyboard.StickerSelected -= OnStickerSelected; + _emojiKeyboard.StickerSetAdded -= OnStickerSetAdded; + _emojiKeyboard.SettingsButtonClick -= OnSettingsButtonClick; + InputMessage.EmojiPlaceholder.Content = null; // Remove from view + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + _emojiKeyboard = null; + } + + var multiImageEditorView = MultiImageEditor.Content as MultiImageEditorView; + if (multiImageEditorView != null) + { + multiImageEditorView.ClosePreview(); + } + + if (CommandsControl.Visibility == Visibility.Visible) + { + OpenEmptyDialogPlaceholder(); + CloseCommandsPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + } + + if (e.Uri.OriginalString.EndsWith("VideoCaptureView.xaml") + || e.Uri.OriginalString.EndsWith("MapView.xaml") + || e.Uri.OriginalString.EndsWith("ShareContactView.xaml") + || e.Uri.OriginalString.EndsWith("ContactView.xaml") + || e.Uri.OriginalString.EndsWith("ChatView.xaml") + || e.Uri.OriginalString.EndsWith("Chat2View.xaml")) + { + + } + + var originalString = e.Uri.OriginalString; + var index = originalString.IndexOf('?'); + if (index != -1) + { + originalString = originalString.Substring(0, index); + } + + if (originalString.EndsWith("ChatView.xaml") + || originalString.EndsWith("ProfilePhotoViewerView.xaml") + || originalString.EndsWith("SearchShellView.xaml") + || originalString.EndsWith("ChooseDialogView.xaml") + || originalString.EndsWith("StickersView.xaml") + || originalString.EndsWith("CancelConfirmResetView.xaml")) + { + CreateBitmapCache(); + MessagesList.Visibility = Visibility.Collapsed; + MessagesCache.Visibility = Visibility.Visible; + } + else if (e.Uri.OriginalString.EndsWith("ContactView.xaml") + || originalString.EndsWith("EditVideoView.xaml") + || originalString.EndsWith("MapView.xaml") + || originalString.EndsWith("WebView.xaml") + || originalString.EndsWith("ShippingInfoView.xaml") + || originalString.EndsWith("ShippingMethodView.xaml") + || originalString.EndsWith("WebCardInfoView.xaml") + || originalString.EndsWith("CheckoutView.xaml")) + { + if (ViewModel.With.Bitmap != null) + { + MessagesList.Visibility = Visibility.Collapsed; + MessagesCache.Visibility = Visibility.Visible; + } + } + + if (originalString.EndsWith("DialogDetailsView.xaml")) + { + //new TelegramNavigationOutTransition { Forward = new SlideTransition { Mode = SlideTransitionMode.SlideDownFadeOut } }); + } + + base.OnNavigatingFrom(e); + } + + private void OnSettingsButtonClick(object sender, System.EventArgs e) + { + if (CommandsControl.Visibility == Visibility.Visible) + { + OpenEmptyDialogPlaceholder(); + CloseCommandsPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + } + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + } + + // чтобы клавиатура успела опуститься + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + CreateBitmapCache(); + MessagesCache.Visibility = Visibility.Visible; + MessagesList.Visibility = Visibility.Collapsed; + + ViewModel.OpenStickerSettings(); + }); + } + + private void SetCaptionVisibility(Visibility visibility) + { + return; + + DialogPhoto.Visibility = visibility; + Title.Visibility = visibility; + ContextMenuIcon.Visibility = visibility; + CaptionBorder.Height = visibility == Visibility.Visible ? 105.0 : 71.0; + } + + private bool CancelNavigatingFrom(NavigatingCancelEventArgs e) + { + if (e.Uri.OriginalString.StartsWith("/Views/Dialogs/DialogDetailsView.xaml")) + { + if (ViewModel.With == ViewModel.StateService.With) + { + var channel = ViewModel.With as TLChannel; + if (channel != null) + { + var postString = ViewModel.StateService.Post; + ViewModel.StateService.With = null; + ViewModel.StateService.Post = null; + ViewModel.StateService.RemoveBackEntries = false; + + int post; + if (Int32.TryParse(postString, out post)) + { + ViewModel.OpenMessage(null, new TLInt(post)); + } + + e.Cancel = true; + return true; + } + + var user = ViewModel.With as TLUser; + if (user != null && user.IsBot) + { + var accessToken = ViewModel.StateService.AccessToken; + ViewModel.StateService.With = null; + ViewModel.StateService.AccessToken = null; + ViewModel.StateService.RemoveBackEntries = false; + ViewModel.StateService.Bot = null; + + user.AccessToken = accessToken; + ViewModel.StartSwitchPMBotWithParam(); + + e.Cancel = true; + return true; + } + } + } + else if (e.Uri.OriginalString.StartsWith("/Views/ShellView.xaml")) + { + if (e.Uri.OriginalString.Contains("from_id")) + { + var user = ViewModel.With as TLUserBase; + if (user != null) + { + try + { + var uriParams = TelegramUriMapper.ParseQueryString(e.Uri.OriginalString); + var fromId = Convert.ToInt32(uriParams["from_id"]); + if (user.Index == fromId) + { + e.Cancel = true; + return true; + } + } + catch (Exception ex) + { + } + } + } + + if (e.Uri.OriginalString.Contains("chat_id")) + { + var chat = ViewModel.With as TLChatBase; + if (chat != null) + { + try + { + var uriParams = TelegramUriMapper.ParseQueryString(e.Uri.OriginalString); + var chatId = Convert.ToInt32(uriParams["chat_id"]); + if (chat.Index == chatId) + { + e.Cancel = true; + return true; + } + } + catch (Exception ex) + { + } + } + } + + if (e.Uri.OriginalString.Contains("channel_id")) + { + var chat = ViewModel.With as TLChatBase; + if (chat != null) + { + try + { + var uriParams = TelegramUriMapper.ParseQueryString(e.Uri.OriginalString); + var chatId = Convert.ToInt32(uriParams["channel_id"]); + if (chat.Index == chatId) + { + e.Cancel = true; + return true; + } + } + catch (Exception ex) + { + } + } + } + } + return false; + } + + private void OnStickerSetAdded(object sender, StickerSetAddedEventArgs e) + { + if (e.Set == null) return; + } + + private void OnStickerSelected(object sender, StickerSelectedEventArgs e) + { + if (e.Sticker == null) return; + + var document22 = e.Sticker.Document as TLDocument22; + if (document22 == null) return; + + ViewModel.SendSticker(document22); + + //Execute.BeginOnUIThread(() => + { + if (InputMessage.IsFullScreen) + { + InputMessage.CloseFullScreen(); + } + } + //); + } + + private double _messageListHeight; + + private void OnOpenFullScreen(object sender, System.EventArgs e) + { + InputMessage.OpenFullScreen(MessagesList.ActualHeight); + //MessagesList.Visibility = Visibility.Collapsed; + } + + private void OnCloseFullScreen(object sender, System.EventArgs e) + { + InputMessage.CloseFullScreen(); + //MessagesList.Visibility = Visibility.Visible; + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + ViewModel.OnNavigatedFrom(); +#if LOG_NAVIGATION + TLUtils.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture) + string.Format("DV OnNavigatedFrom Mode={0} Uri={1}", e.NavigationMode, e.Uri), LogSeverity.Error); +#endif + _fromExternalUri = e.Uri == ExternalUri; + + //if (_fromExternalUri) + //{ + // foreach (var control in LiveLocationProgress.Controls) + // { + // control.StopTimer(); + // } + //} + + MessagePlayerControl.Stop(); + GifPlayerControl.StopVideo(); + + base.OnNavigatedFrom(e); + } + + private void OnChooseAttachmentPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.ChooseAttachment.IsOpen)) + { + MessagesList.IsHitTestVisible = IsItemsHitTestVisible(); + } + } + + private bool IsItemsHitTestVisible() + { + return (ViewModel.ChooseAttachment == null || !ViewModel.ChooseAttachment.IsOpen) + && (ViewModel.ImageViewer == null || !ViewModel.ImageViewer.IsOpen) + && (ViewModel.MultiImageEditor == null || !ViewModel.MultiImageEditor.IsOpen) + && (ViewModel.AnimatedImageViewer == null || !ViewModel.AnimatedImageViewer.IsOpen) + && (ViewModel.VideoEditor == null || !ViewModel.VideoEditor.IsOpen) + && (ViewModel.LocationPicker == null || !ViewModel.LocationPicker.IsOpen) + && (ViewModel.ContactPicker == null || !ViewModel.ContactPicker.IsOpen); + } + + private IApplicationBar _prevApplicationBar; + + private void OnImageViewerPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.ImageViewer.IsOpen)) + { + MessagesList.IsHitTestVisible = IsItemsHitTestVisible(); + //MessagesList.Visibility = MessagesList.IsHitTestVisible ? Visibility.Visible : Visibility.Collapsed; + + if (ViewModel.ImageViewer.IsOpen) + { + var message70 = ViewModel.ImageViewer.CurrentItem as TLMessage70; + IsScreenCaptureEnabled = message70 == null || !message70.HasTTL(); + + _prevApplicationBar = ApplicationBar; + ApplicationBar = ((ImageViewerView)ImageViewer.Content).ApplicationBar; + } + else + { + IsScreenCaptureEnabled = true; + + if (_prevApplicationBar != null) + { + ApplicationBar = _prevApplicationBar; + } + } + } + } + + private void OnMultiImageEditorPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.MultiImageEditor.IsOpen)) + { + MessagesList.IsHitTestVisible = IsItemsHitTestVisible(); + + if (ViewModel.MultiImageEditor.IsOpen) + { + _prevApplicationBar = ApplicationBar; + ApplicationBar = ((MultiImageEditorView)MultiImageEditor.Content).ApplicationBar; + } + else + { + if (_prevApplicationBar != null) + { + ApplicationBar = _prevApplicationBar; + } + } + } + } + + private void OnImageEditorPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.ImageEditor.IsOpen)) + { + MessagesList.IsHitTestVisible = IsItemsHitTestVisible(); + + if (ViewModel.ImageEditor.IsOpen) + { + _prevApplicationBar = ApplicationBar; + ApplicationBar = ((ImageEditorView)ImageEditor.Content).ApplicationBar; + } + else + { + if (_prevApplicationBar != null) + { + ApplicationBar = _prevApplicationBar; + } + } + } + } + + private void OnAnimatedImageViewerPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.AnimatedImageViewer.IsOpen)) + { + MessagesList.IsHitTestVisible = IsItemsHitTestVisible(); + + if (ViewModel.AnimatedImageViewer.IsOpen) + { + _prevApplicationBar = ApplicationBar; + ApplicationBar = ((AnimatedImageViewerView)AnimatedImageViewer.Content).ApplicationBar; + } + else + { + if (_prevApplicationBar != null) + { + ApplicationBar = _prevApplicationBar; + } + } + } + } + + private void OnVideoEditorPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.VideoEditor.IsOpen)) + { + MessagesList.IsHitTestVisible = IsItemsHitTestVisible(); + } + } + + private void OnLocationPickerPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.LocationPicker.IsOpen)) + { + MessagesList.IsHitTestVisible = IsItemsHitTestVisible(); + } + } + + private void OnContactPickerPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.ContactPicker.IsOpen)) + { + MessagesList.IsHitTestVisible = IsItemsHitTestVisible(); + } + } + + private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) + { + //System.Diagnostics.Debug.WriteLine("VM changed " + e.PropertyName); + + //if (ViewModel._debugTimer != null) System.Diagnostics.Debug.WriteLine("start view property changed " + ViewModel._debugTimer.Elapsed); + + if (Property.NameEquals(e.PropertyName, () => ViewModel.Text)) + { + + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.IsAppBarCommandVisible)) + { + if (ApplicationBar != null) + { + ApplicationBar.IsVisible = false;//!ViewModel.IsAppBarCommandVisible && !ViewModel.IsChooseAttachmentOpen && !ViewModel.IsMassDeleteReportSpamOpen; + } + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.HasBots)) + { + InputMessage.KeyboardButtonVisibility = GetReplyKeyboardButtonVisibility(); + InputMessage.KeyboardButtonImageString = GetReplyKeyboardImageString(); + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.ReplyMarkup)) + { + InputMessage.KeyboardButtonVisibility = GetReplyKeyboardButtonVisibility(); + InputMessage.KeyboardButtonImageString = GetReplyKeyboardImageString(); + + var replyMarkup = ViewModel.ReplyMarkup as TLReplyKeyboardMarkup; + if (replyMarkup != null) + { + if (ViewModel.SuppressOpenCommandsKeyboard) + { + ViewModel.SuppressOpenCommandsKeyboard = false; + OpenEmptyDialogPlaceholder(); + CloseCommandsPlaceholder(); + + return; + } + + if (!replyMarkup.HasResponse) + { + if (!ViewModel.IsAppBarCommandVisible) + { + CloseEmojiPlaceholder(); + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + SelfView.Focus(); + OpenCommandsPlaceholder(); + CloseEmptyDialogPlaceholder(); + SetCaptionVisibility(Visibility.Collapsed); + }); + } + } + else + { + OpenEmptyDialogPlaceholder(); + CloseCommandsPlaceholder(); + } + } + + var keyboardHide = ViewModel.ReplyMarkup as TLReplyKeyboardHide; + if (keyboardHide != null) + { + SetCaptionVisibility(Visibility.Visible); + } + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.IsGroupActionEnabled)) + { + var count = DialogDetailsViewModel.UngroupEnumerator(ViewModel.Items).Count(x => x.IsSelected); + var noneTTLCount = DialogDetailsViewModel.UngroupEnumerator(ViewModel.Items).Count(x => x.IsSelected && !x.HasTTL()); + if (_selectionCaption != null) + { + _selectionCaption.Text = string.Format(count == 1 ? AppResources.ItemsSelectedSingular : AppResources.ItemsSelectedPlural, count).ToUpperInvariant(); + } + + InputMessage.IsGroupActionEnabled = new Tuple(count > 0, count > 0 && noneTTLCount == count); + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.HoldScrollingPosition)) + { + if (ViewModel.HoldScrollingPosition) + { + MessagesList.HoldScrollingPosition(); + } + else + { + MessagesList.UnholdScrollingPosition(); + } + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.IsSelectionEnabled)) + { + if (ViewModel.IsSelectionEnabled) + { + SwitchToSelectionMode(); + } + else + { + SwitchToNonSelectionMode(); + } + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.IsEditingEnabled)) + { + if (ViewModel.IsEditingEnabled) + { + SwitchToEditingMode(); + } + else + { + SwitchToNormalMode(); + } + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.ChooseAttachment) + && ViewModel.ChooseAttachment != null) + { + ViewModel.ChooseAttachment.PropertyChanged += OnChooseAttachmentPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.ImageViewer) + && ViewModel.ImageViewer != null) + { + ViewModel.ImageViewer.PropertyChanged += OnImageViewerPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.MultiImageEditor) + && ViewModel.MultiImageEditor != null) + { + ViewModel.MultiImageEditor.PropertyChanged += OnMultiImageEditorPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.ImageEditor) + && ViewModel.ImageEditor != null) + { + ViewModel.ImageEditor.PropertyChanged += OnImageEditorPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.AnimatedImageViewer) + && ViewModel.AnimatedImageViewer != null) + { + ViewModel.AnimatedImageViewer.PropertyChanged += OnAnimatedImageViewerPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.VideoEditor) + && ViewModel.VideoEditor != null) + { + ViewModel.VideoEditor.PropertyChanged += OnVideoEditorPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.LocationPicker) + && ViewModel.LocationPicker != null) + { + ViewModel.LocationPicker.PropertyChanged += OnLocationPickerPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.ContactPicker) + && ViewModel.ContactPicker != null) + { + ViewModel.ContactPicker.PropertyChanged += OnContactPickerPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.With)) + { + ViewModel.ChangeUserAction(); + if (ApplicationBar != null) + { + ApplicationBar.IsVisible = false;//!ViewModel.IsAppBarCommandVisible && !ViewModel.IsChooseAttachmentOpen && !ViewModel.IsMassDeleteReportSpamOpen; + } + ChangeShareInfo(); + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.StartGifPlayers)) + { + Deployment.Current.Dispatcher.BeginInvoke(() => + { + Items_OnManipulationStateChanged(this, System.EventArgs.Empty); + }); + } + //if (ViewModel._debugTimer != null) System.Diagnostics.Debug.WriteLine("end view property changed " + ViewModel._debugTimer.Elapsed); + } + + private void ChangeShareInfo() + { + if (ApplicationBar == null) return; + + var userBase = ViewModel.With as TLUserBase; + if (userBase != null && userBase.IsForeign) + { + ContextMenu.Items.Remove(_shareMyContactInfoMenuItem); + ContextMenu.Items.Insert(0, _shareMyContactInfoMenuItem); + } + else + { + ContextMenu.Items.Remove(_shareMyContactInfoMenuItem); + } + } + + private void SwitchToEditingMode() + { + //InputMessage.IsEditing = true; + + //ApplicationBar.Buttons.Clear(); + + //InputMessage.Padding = new Thickness(11.0, 2.0, 36.0, 2.0); + + Execute.BeginOnUIThread(() => + { + InputMessage.FocusInput(); + InputMessage.SelectionStart = InputMessage.Text.Length; + InputMessage.SelectionLength = 0; + //ApplicationBar.Buttons.Add(_doneButton); + //ApplicationBar.Buttons.Add(_cancelButton); + }); + } + + private TextBlock _selectionCaption; + + private void SwitchToSelectionMode() + { + InputMessage.SwitchToSelectionMode(); + + MessagesList.Focus(); + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + CloseCommandsPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + + if (_selectionCaption == null) + { + _selectionCaption = new TextBlock + { + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top, + Margin = new Thickness(18.0, 52.0, 18.0, 21.0), + Foreground = new SolidColorBrush(Colors.White), + RenderTransform = new TranslateTransform(), + Style = (Style)Application.Current.Resources["ApplicationTitleStyle"] + }; + + ContentPanel.Children.Add(_selectionCaption); + } + + CaptionGrid.RenderTransform = new TranslateTransform(); + + var storyboard = new Storyboard(); + + var transformAnimaion2 = new DoubleAnimation { From = 0.0, To = -72.0, Duration = TimeSpan.FromSeconds(0.2), EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 6.0 } }; + Storyboard.SetTarget(transformAnimaion2, CaptionGrid); + Storyboard.SetTargetProperty(transformAnimaion2, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(transformAnimaion2); + + var opacityAnimaion2 = new DoubleAnimation { From = 1.0, To = 0.0, Duration = TimeSpan.FromSeconds(0.2) }; + Storyboard.SetTarget(opacityAnimaion2, CaptionGrid); + Storyboard.SetTargetProperty(opacityAnimaion2, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityAnimaion2); + + var opacityAnimaion = new DoubleAnimation { From = 0.0, To = 1.0, Duration = TimeSpan.FromSeconds(0.2) }; + Storyboard.SetTarget(opacityAnimaion, _selectionCaption); + Storyboard.SetTargetProperty(opacityAnimaion, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityAnimaion); + + storyboard.Begin(); + storyboard.Completed += (o, e) => + { + //((TranslateTransform) CaptionGrid.RenderTransform).Y = 0.0; + //CaptionGrid.Opacity = 1.0; + //DialogPhoto.Visibility = Visibility.Collapsed; + //Caption.Visibility = Visibility.Collapsed; + //ContextMenuIcon.Visibility = Visibility.Collapsed; + }; + + //DialogPhoto.Visibility = Visibility.Collapsed; + //Caption.Visibility = Visibility.Collapsed; + //ContextMenuIcon.Visibility = Visibility.Collapsed; + var count = DialogDetailsViewModel.UngroupEnumerator(ViewModel.Items).Count(x => x.IsSelected); + var noneTTLCount = ViewModel.Items.Count(x => x.IsSelected && !x.HasTTL()); + + _selectionCaption.Text = string.Format(count == 1 ? AppResources.ItemsSelectedSingular : AppResources.ItemsSelectedPlural, count).ToUpperInvariant(); + _selectionCaption.Visibility = Visibility.Visible; + + ApplicationBar.Buttons.Clear(); + Execute.BeginOnUIThread(() => + { + var channel = ViewModel.With as TLChannel; + + InputMessage.IsDeleteActionVisible = channel == null || channel.Creator; + InputMessage.IsGroupActionEnabled = new Tuple(count > 0, count > 0 && noneTTLCount == count); + ApplicationBar.IsVisible = false; + }); + } + + private void SwitchToNonSelectionMode() + { + InputMessage.SwitchToNormalMode(); + + InputMessage.MuteButtonVisibility = GetMuteButtonVisibility(); + + var storyboard = new Storyboard(); + + var transformAnimaion2 = new DoubleAnimation { From = -72.0, To = 0.0, Duration = TimeSpan.FromSeconds(0.2), EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } }; + Storyboard.SetTarget(transformAnimaion2, CaptionGrid); + Storyboard.SetTargetProperty(transformAnimaion2, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(transformAnimaion2); + + var opacityAnimaion2 = new DoubleAnimation { From = 0.0, To = 1.0, Duration = TimeSpan.FromSeconds(0.2) }; + Storyboard.SetTarget(opacityAnimaion2, CaptionGrid); + Storyboard.SetTargetProperty(opacityAnimaion2, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityAnimaion2); + + var opacityAnimaion = new DoubleAnimation { From = 1.0, To = 0.0, Duration = TimeSpan.FromSeconds(0.2) }; + Storyboard.SetTarget(opacityAnimaion, _selectionCaption); + Storyboard.SetTargetProperty(opacityAnimaion, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityAnimaion); + + storyboard.Begin(); + storyboard.Completed += (o, e) => + { + _selectionCaption.Opacity = 1.0; + _selectionCaption.Visibility = Visibility.Collapsed; + }; + + DialogPhoto.Visibility = Visibility.Visible; + Caption.Visibility = Visibility.Visible; + ContextMenuIcon.Visibility = Visibility.Visible; + + ApplicationBar.Buttons.Clear(); + ApplicationBar.IsVisible = false; + } + + private void SwitchToNormalMode() + { + InputMessage.SwitchToNormalMode(); + + InputMessage.MuteButtonVisibility = GetMuteButtonVisibility(); + + DialogPhoto.Visibility = Visibility.Visible; + Caption.Visibility = Visibility.Visible; + ContextMenuIcon.Visibility = Visibility.Visible; + if (_selectionCaption != null) _selectionCaption.Visibility = Visibility.Collapsed; + + //InputMessage.IsEditing = false; + ApplicationBar.Buttons.Clear(); + ApplicationBar.IsVisible = false; + } + + private bool _firstRun = true; + + private void BuildLocalizedAppBar() + { + if (!_firstRun) return; + _firstRun = false; + + ApplicationBar = new ApplicationBar(); + ApplicationBar.Opacity = 0.99; + + var broadcast = ViewModel.With as TLBroadcastChat; + var channel = ViewModel.With as TLChannel; + var chat = ViewModel.With as TLChat41; + var user = ViewModel.With as TLUser; + + if (user != null && !user.IsBot && !user.IsSelf) + { + ContextMenu.Items.Add(_callMenuItem); + } + + //ContextMenu.Items.Add(_debugMenuItem); + + ContextMenu.Items.Add(_manageButton); + if (broadcast == null || channel != null) + { + var addReportSpam = true; + if (chat != null && chat.Creator) + { + addReportSpam = false; + } + + if (user != null && user.IsSelf) + { + addReportSpam = false; + } + + if (channel != null && channel.Creator) + { + addReportSpam = false; + } + if (addReportSpam) + { + ContextMenu.Items.Add(_reportSpamMenuItem); + } + } + if (broadcast == null || channel != null) + { + ContextMenu.Items.Add(_searchMenuItem); + } + + if (user != null && user.IsBot) + { + ContextMenu.Items.Add(_helpMenuItem); + } + ContextMenu.Items.Add(_pinToStartMenuItem); + + var userBase = ViewModel.With as TLUserBase; + if (userBase != null && userBase.IsForeign) + { + ContextMenu.Items.Add(_shareMyContactInfoMenuItem); + } + + ApplicationBar.IsVisible = false; //!ViewModel.IsAppBarCommandVisible && !ViewModel.IsChooseAttachmentOpen && !ViewModel.IsMassDeleteReportSpamOpen; + } + + private ShareMessagePicker _shareMessagePicker; + + private WeakEventListener _weakEventListener; + + public void OpenShareMessagePicker(string link, Action callback = null) + { + var isVisible = false; + var frame = Application.Current.RootVisual as PhoneApplicationFrame; + PhoneApplicationPage page = null; + if (frame != null) + { + page = frame.Content as PhoneApplicationPage; + if (page != null) + { + page.IsHitTestVisible = false; + var applicationBar = page.ApplicationBar; + if (applicationBar != null) + { + isVisible = applicationBar.IsVisible; + applicationBar.IsVisible = false; + } + } + + var weakEventListener = new WeakEventListener(this, frame); + frame.Navigating += weakEventListener.OnEvent; + + weakEventListener.OnEventAction = (view, o, args) => + { + view.Frame_Navigating(o, args); + }; + weakEventListener.OnDetachAction = (listener, source) => + { + var f = source as PhoneApplicationFrame; + if (f != null) + { + f.Navigating -= listener.OnEvent; + } + }; + + _weakEventListener = weakEventListener; + } + + if (page == null) return; + + var popup = new Popup(); + var sharePicker = new ShareMessagePicker + { + Width = page.ActualWidth, + Height = page.ActualHeight, + Link = link + }; + _shareMessagePicker = sharePicker; + page.SizeChanged += Page_SizeChanged; + + sharePicker.Close += (sender, args) => + { + _shareMessagePicker = null; + _weakEventListener.Detach(); + _weakEventListener = null; + + popup.IsOpen = false; + popup.Child = null; + + frame = Application.Current.RootVisual as PhoneApplicationFrame; + if (frame != null) + { + page = frame.Content as PhoneApplicationPage; + if (page != null) + { + page.SizeChanged -= Page_SizeChanged; + page.IsHitTestVisible = true; + var applicationBar = page.ApplicationBar; + if (applicationBar != null) + { + applicationBar.IsVisible = isVisible; + } + } + } + }; + _shareMessagePicker.Pick += (sender, args) => + { + callback.SafeInvoke(args); + }; + + popup.Child = sharePicker; + popup.IsOpen = true; + } + + private void Frame_Navigating(object sender, NavigatingCancelEventArgs e) + { + if (_shareMessagePicker != null) + { + _shareMessagePicker.ForceClose(); + } + } + + private void Page_SizeChanged(object sender, SizeChangedEventArgs e) + { + + } + + private void DialogDetailsView_OnBackKeyPress(object sender, CancelEventArgs e) + { + var popups = VisualTreeHelper.GetOpenPopups().ToList(); + var popup = popups.FirstOrDefault(); + if (popup != null) + { + e.Cancel = true; + + var multiplePhotoPicker = popup.Child as OpenPhotoPicker; + if (multiplePhotoPicker != null) + { + multiplePhotoPicker.TryClose(); + } + + var shareMessagePicker = popup.Child as ShareMessagePicker; + if (shareMessagePicker != null) + { + shareMessagePicker.TryClose(); + } + + return; + } + + if (_lastMessagePrompt != null + && _lastMessagePrompt.IsOpen) + { + _lastMessagePrompt.Hide(); + e.Cancel = true; + + return; + } + + if (ViewModel == null) return; + + if (ViewModel.SearchMessages != null + && ViewModel.SearchMessages.IsOpen) + { + ViewModel.SearchMessages.Close(); + e.Cancel = true; + + return; + } + + if (ViewModel.MultiImageEditor != null + && ViewModel.MultiImageEditor.IsOpen) + { + ViewModel.MultiImageEditor.CloseEditor(); + e.Cancel = true; + + return; + } + + if (ViewModel.LocationPicker != null + && ViewModel.LocationPicker.IsOpen) + { + ViewModel.LocationPicker.CloseEditor(); + e.Cancel = true; + + return; + } + + if (ViewModel.ContactPicker != null + && ViewModel.ContactPicker.IsOpen) + { + ViewModel.ContactPicker.CloseEditor(); + e.Cancel = true; + + return; + } + + if (ViewModel.VideoEditor != null + && ViewModel.VideoEditor.IsOpen) + { + ViewModel.VideoEditor.CloseEditor(); + e.Cancel = true; + + return; + } + + if (ViewModel.ImageEditor != null + && ViewModel.ImageEditor.IsOpen) + { + ViewModel.ImageEditor.CloseEditor(); + e.Cancel = true; + + return; + } + + if (ViewModel.ImageViewer != null + && ViewModel.ImageViewer.IsOpen) + { + ViewModel.ImageViewer.CloseViewer(); + e.Cancel = true; + + return; + } + + if (ViewModel.AnimatedImageViewer != null + && ViewModel.AnimatedImageViewer.IsOpen) + { + ViewModel.AnimatedImageViewer.CloseViewer(); + e.Cancel = true; + + return; + } + + if (_lastContextMenu != null && _lastContextMenu.IsOpen) + { + _lastContextMenu.IsOpen = false; + e.Cancel = true; + + return; + } + + if (_emojiKeyboard != null && _emojiKeyboard.IsPreviewMenuOpened) + { + _emojiKeyboard.ClosePreviewMenu(); + e.Cancel = true; + + return; + } + + if (InputMessage.IsFullScreen) + { + InputMessage.CloseFullScreen(); + e.Cancel = true; + + return; + } + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible + || CommandsControl.Visibility == Visibility.Visible) + { + SelfView.Focus(); + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + CloseCommandsPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + e.Cancel = true; + + return; + } + + if (ViewModel.ChooseAttachment != null + && ViewModel.ChooseAttachment.IsOpen) + { + ViewModel.ChooseAttachment.Close(); + ResumeChatPlayers(); + + e.Cancel = true; + + return; + } + + if (ViewModel.IsEditingEnabled) + { + ViewModel.StopEditMessage(); + ApplicationBar.IsVisible = false;//!ViewModel.IsAppBarCommandVisible; + e.Cancel = true; + + return; + } + + if (ViewModel.IsSelectionEnabled) + { + ViewModel.IsSelectionEnabled = false; + ApplicationBar.IsVisible = false;//!ViewModel.IsAppBarCommandVisible; + e.Cancel = true; + + return; + } + + if (!NavigationService.BackStack.Any()) + { + e.Cancel = true; + ViewModel.NavigateToShellViewModel(); + + return; + } + + _isBackwardOutAnimation = true; + + CreateBitmapCache(); + MessagesCache.Visibility = Visibility.Visible; + MessagesList.Visibility = Visibility.Collapsed; + var result = ContentPanel.Children.Remove(MessagesList); + + ShellViewModel.WriteTimer("DialogDetailsView OnBackKeyPress"); + + _backKeyPressed = true; + + if (_forwardInStoryboard != null && _forwardInStoryboard.GetCurrentState() != ClockState.Stopped) + { + _forwardInStoryboard.Stop(); + } + + RunAnimation(); + + LiveLocationProgress.Controls.Clear(); + ViewModel.StopChannelScheduler(); + ViewModel.CancelDownloading(); + } + + private void UIElement_OnHold(object sender, GestureEventArgs e) + { + e.Handled = true; + } + + private void MentionButton_OnClick(object sender, RoutedEventArgs e) + { + ViewModel.ReadNextMention(); + return; + GifPlayerControl.PauseActivePlayers(); + GifPlayerControl.StopInlineBotActivePlayers(); + + HideScrollToBottomButton(); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + if (ViewModel.Items.Count > 0) + { + ViewModel.ProcessScroll(); + } + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + Items_OnManipulationStateChanged(sender, System.EventArgs.Empty); + }); + }); + } + + private void ScrollButton_OnClick(object sender, RoutedEventArgs e) + { + GifPlayerControl.PauseActivePlayers(); + GifPlayerControl.StopInlineBotActivePlayers(); + + HideScrollToBottomButton(); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + if (ViewModel.Items.Count > 0) + { + ViewModel.ProcessScroll(); + } + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + Items_OnManipulationStateChanged(sender, System.EventArgs.Empty); + }); + }); + } + + private void InputMessage_OnKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + if (ViewModel.StateService.SendByEnter) + { + ViewModel.Send(); + e.Handled = true; + } + } + else if (e.Key == Key.Space) + { + var text = InputMessage.Text.Trim(); + if (text.Length <= Constants.UsernameMaxLength && BrowserNavigationService.IsValidUsername(text)) + { + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => ViewModel.ResolveUsername(text)); + } + } + else if (e.Key == Key.T) + { + var text = (InputMessage.Text + "t").Trim(); + if (text.Length <= Constants.UsernameMaxLength && text.EndsWith("bot", StringComparison.OrdinalIgnoreCase) && BrowserNavigationService.IsValidUsername(text)) + { + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => ViewModel.ResolveUsername(text)); + } + } + else if (e.Key == Key.Back) + { + if (InputMessage.Text.Length == 0) return; + + var text = InputMessage.Text.Substring(0, InputMessage.Text.Length - 1).Trim(); + if (text.Length <= Constants.UsernameMaxLength && text.EndsWith("bot", StringComparison.OrdinalIgnoreCase) && BrowserNavigationService.IsValidUsername(text)) + { + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => ViewModel.ResolveUsername(text)); + } + } + } + + private ContextMenu _lastContextMenu; + + private void ContextMenu_OnOpened(object sender, RoutedEventArgs e) + { + var menu = (ContextMenu)sender; + var owner = (FrameworkElement)menu.Owner; + + if (owner.DataContext != menu.DataContext) + { + menu.DataContext = owner.DataContext; + } + + if (_innerMessage != null && _innerMessage != menu.DataContext) + { + menu.DataContext = _innerMessage; + } + + var serviceMessage = menu.DataContext as TLMessageService; + if (serviceMessage != null) + { + menu.IsOpen = false; + return; + } + + _lastContextMenu = sender as ContextMenu; + } + + private void InputMessage_OnGotFocus(object sender, RoutedEventArgs e) + { + SetCaptionVisibility(Visibility.Collapsed); + CloseCommandsPlaceholder(); + CloseEmptyDialogPlaceholder(); + + PauseChatPlayers(); + } + + private bool _smileButtonPressed; + + private void InputMessage_OnLostFocus(object sender, RoutedEventArgs e) + { + if (!_smileButtonPressed) + { + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + CloseEmojiPlaceholder(); + } + } + _smileButtonPressed = false; + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Collapsed) + { + SetCaptionVisibility(Visibility.Visible); + } + + OpenEmptyDialogPlaceholder(); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + ResumeChatPlayers(); + }); + } + + private Binding _emptyPlaceholderVisibilityBinding; + + private void OpenEmptyDialogPlaceholder() + { + var user = ViewModel.With as TLUser; + if (user != null && user.IsSelf) + { + RestoreVisibilityBinding(EmptyDialogPlaceholder, _emptyPlaceholderVisibilityBinding, Visibility.Collapsed); + } + } + + private void CloseEmptyDialogPlaceholder() + { + var user = ViewModel.With as TLUser; + if (user != null && user.IsSelf) + { + _emptyPlaceholderVisibilityBinding = SaveVisibilityBinding(EmptyDialogPlaceholder); + EmptyDialogPlaceholder.Visibility = Visibility.Collapsed; + } + } + + private bool _once = true; + + private void Items_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + if (ViewModel.SliceLoaded) return; + if (ViewModel.IsSelectionEnabled) return; + + ViewModel.LoadNextSlice(); + ViewModel.LoadPreviousSlice(); + } + + private void InputMessage_OnTap(object sender, MouseButtonEventArgs mouseButtonEventArgs) + { + if (_inputMessageDisabled) + { + _focusInputMessage = true; + } + } + + private void InputMessage_OnTextChanged(object sender, TextChangedEventArgs e) + { + InputMessage.KeyboardButtonVisibility = GetReplyKeyboardButtonVisibility(); + InputMessage.MuteButtonVisibility = GetMuteButtonVisibility(); + + if (ViewModel.IsEditingEnabled) return; + } + + private void StickerHints_OnTap(object sender, GestureEventArgs e) + { + var frameworkElement = e.OriginalSource as FrameworkElement; + if (frameworkElement == null) return; + + var stickerItem = frameworkElement.DataContext as TLStickerItem; + if (stickerItem == null) return; + + var document22 = stickerItem.Document as TLDocument22; + if (document22 == null) return; + + if (_emojiKeyboard != null) + { + _emojiKeyboard.UpdateRecentStickers(new StickerSelectedEventArgs { Sticker = stickerItem }); + } + + ViewModel.SendSticker(document22); + } + + private ObservableCollection _stickers; + + private Visibility GetMuteButtonVisibility() + { + if (InputMessage.Text.Length > 0) + { + return Visibility.Collapsed; + } + + if (ViewModel == null) return Visibility.Collapsed; + + if (ViewModel.IsEditingEnabled) return Visibility.Collapsed; + + var channel = ViewModel.With as TLChannel44; + + return channel != null && channel.IsBroadcast && (channel.Creator || channel.IsEditor) + ? Visibility.Visible + : Visibility.Collapsed; + } + + private Visibility GetReplyKeyboardButtonVisibility() + { + if (InputMessage.Text.Length > 0) + { + return Visibility.Collapsed; + } + + if (ViewModel != null) + { + var replyMarkup = ViewModel.ReplyMarkup as TLReplyKeyboardMarkup; + if (replyMarkup == null) + { + if (!ViewModel.HasBots) + { + return Visibility.Collapsed; + } + } + } + + return Visibility.Visible; + } + + private Visibility GetAudioRecorderVisibility() + { + if (FocusManager.GetFocusedElement() == InputMessage) + { + return Visibility.Collapsed; + } + + if (InputMessage.Text.Length > 0) + { + return Visibility.Collapsed; + } + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + return Visibility.Collapsed; + } + + if (CommandsControl.Visibility == Visibility.Visible) + { + return Visibility.Collapsed; + } + + if (ViewModel != null) + { + if (ViewModel.IsEditingEnabled) + { + return Visibility.Collapsed; + } + + var chatForbidden = ViewModel.With as TLChatForbidden; + var chat = ViewModel.With as TLChat; + + var isForbidden = chatForbidden != null || (chat != null && chat.Left.Value); + if (isForbidden) + { + return Visibility.Collapsed; + } + } + + return Visibility.Visible; + } + + private void EmojiHint_OnTap(object sender, GestureEventArgs e) + { + var view = EmojiHints.Content as EmojiHintsView; + if (view != null) + { + EmojiSuggestionParams parameters = null; + var viewModel = view.DataContext as EmojiHintsViewModel; + if (viewModel != null) + { + parameters = viewModel.Parameters; + viewModel.SetParameters(null); + } + + if (parameters != null) + { + var frameworkElement = e.OriginalSource as FrameworkElement; + if (frameworkElement != null) + { + var suggestion = frameworkElement.DataContext as EmojiSuggestion; + if (suggestion != null) + { + var text = InputMessage.Text; + if (string.Equals(InputMessage.Text, parameters.Text, StringComparison.Ordinal) + && InputMessage.SelectionStart == parameters.SelectionStart) + { + var firstPart = text.Substring(0, parameters.Index); + var middlePart = suggestion.Emoji; + var lastPart = text.Substring(parameters.Index + parameters.Length); + InputMessage.Text = firstPart + middlePart + lastPart; + InputMessage.SelectionStart = firstPart.Length + middlePart.Length; + InputMessage.FocusInput(); + + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + var emoji = new EmojiDataItem(suggestion.Emoji, 1); + emoji.Uri = EmojiDataItem.BuildUri(emoji.String); + EmojiData.AddToRecents(emoji); + }); + } + } + } + } + } + } + + private void CommandHint_OnTap(object sender, GestureEventArgs e) + { + InputMessage.FocusInput(); + + var frameworkElement = e.OriginalSource as FrameworkElement; + if (frameworkElement != null) + { + var botCommand = frameworkElement.DataContext as TLBotCommand; + if (botCommand != null) + { + var command = !ViewModel.IsSingleBot + ? string.Format("{0}@{1}", botCommand.Command, ((IUserName)botCommand.Bot).UserName) + : botCommand.Command.ToString(); + + InputMessage.Text = string.Empty; + Execute.BeginOnUIThread(() => ViewModel.Send(new TLString("/" + command))); + } + } + } + + private void InlineBotResults_OnTap(object sender, GestureEventArgs e) + { + var frameworkElement = e.OriginalSource as FrameworkElement; + if (frameworkElement != null) + { + var result = frameworkElement.DataContext as TLBotInlineResultBase; + if (result != null) + { + if (_previousFocusedElement == InputMessage) + { + InputMessage.FocusInput(); + } + + GifPlayerControl.StopInlineBotActivePlayers(); + ViewModel.SendBotInlineResult(result); + } + else + { + TelegramTransitionService.SetNavigationOutTransition(this, null); + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + var textBlock = frameworkElement as TextBlock; + if (textBlock != null) + { + if (_previousFocusedElement == InputMessage) + { + Telegram.Api.Helpers.Execute.BeginOnUIThread(TimeSpan.FromSeconds(.15), () => + { + ViewModel.Switch(ViewModel.InlineBotResults.SwitchPM); + }); + } + else + { + ViewModel.Switch(ViewModel.InlineBotResults.SwitchPM); + } + } + }); + } + } + } + + private void UsernameHint_OnTap(object sender, GestureEventArgs e) + { + InputMessage.FocusInput(); + + var frameworkElement = e.OriginalSource as FrameworkElement; + if (frameworkElement != null) + { + var user = frameworkElement.DataContext as IUserName; + if (user != null) + { + var user45 = user as TLUser45; + var userBase = user as TLUserBase; + if (user45 != null && user45.IsInlineBot) + { + ViewModel._currentInlineBot = user45; + } + + var index = 0; + for (var i = InputMessage.Text.Length - 1; i >= 0; i--) + { + if (InputMessage.Text[i] == '@') + { + index = i; + break; + } + } + + if (TLString.IsNullOrEmpty(user.UserName)) + { + if (userBase != null) + { + ViewModel.AddMention(userBase); + + InputMessage.Text = string.Format("{0}({1})", InputMessage.Text.Substring(0, index + 1), userBase.FullName); + InputMessage.SelectionStart = InputMessage.Text.Length - userBase.FullName.Length - 1; + InputMessage.SelectionLength = userBase.FullName.Length; + } + } + else + { + InputMessage.Text = string.Format("{0}{1} ", InputMessage.Text.Substring(0, index + 1), user.UserName); + InputMessage.SelectionStart = InputMessage.Text.Length; + InputMessage.SelectionLength = 0; + } + + if (user45 != null && user45.IsInlineBot) + { + ViewModel.SetBotInlinePlaceholder(); + } + } + } + } + + private void HashtagHint_OnTap(object sender, GestureEventArgs e) + { + InputMessage.FocusInput(); + + var frameworkElement = e.OriginalSource as FrameworkElement; + if (frameworkElement != null) + { + var hashtag = frameworkElement.DataContext as TLHashtagItem; + if (hashtag != null) + { + var index = 0; + for (var i = InputMessage.Text.Length - 1; i >= 0; i--) + { + if (InputMessage.Text[i] == '#') + { + index = i; + break; + } + } + + InputMessage.Text = string.Format("{0}{1} ", InputMessage.Text.Substring(0, index + 1), hashtag.Hashtag); + InputMessage.SelectionStart = InputMessage.Text.Length; + InputMessage.SelectionLength = 0; + } + } + } + + private void StickerHints_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + ViewModel.ContinueStickerHints(); + } + + private void UsernameHints_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + ViewModel.ContinueUsernameHints(); + } + + private void InlineBotResults_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + ViewModel.ContinueInlineBotResults(); + } + + private void CommandHints_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + ViewModel.ContinueCommandHints(); + } + + private void HashtagHints_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + ViewModel.ContinueHashtagHints(); + } + + private void EmojiHints_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + //ViewModel.ContinueEmojiHints(); + } + + private void Items_OnBegin(object sender, System.EventArgs e) + { + // repeat messages on first load with unread history + if (!ViewModel.IsFirstSliceLoaded && ViewModel._previousScrollPosition != null) + { + ViewModel.LoadPreviousSlice("Items_OnBegin"); + } + else + { + if (!ViewModel.SuppressHideScrollToBottom) + { + ViewModel.MentionsCounter = 0; + } + HideScrollToBottomButton(); + } + } + + public bool IsScrollToBottomButtonVisible + { + get { return ScrollButton.Visibility == Visibility.Visible; } + } + + public void HideMentionButton() + { + if (MentionButton.Visibility == Visibility.Collapsed) return; + if (ViewModel.SuppressHideScrollToBottom) return; + + var storyboard = new Storyboard(); + + if (MentionButton.Visibility == Visibility.Visible) + { + var translateAnimation1 = new DoubleAnimationUsingKeyFrames(); + translateAnimation1.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 0.0 }); + translateAnimation1.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 150.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(translateAnimation1, MentionButton); + Storyboard.SetTargetProperty(translateAnimation1, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateAnimation1); + + var opacityAnimation1 = new DoubleAnimation + { + From = 1.0, + To = 0.0, + Duration = TimeSpan.FromSeconds(0.25), + EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } + }; + Storyboard.SetTarget(opacityAnimation1, MentionButton); + Storyboard.SetTargetProperty(opacityAnimation1, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(opacityAnimation1); + } + + storyboard.Completed += (sender, args) => + { + MentionButton.Visibility = Visibility.Collapsed; + }; + + storyboard.Begin(); + } + + public void HideScrollToBottomButton() + { + if (ScrollButton.Visibility == Visibility.Collapsed + && MentionButton.Visibility == Visibility.Collapsed) return; + if (ViewModel.SuppressHideScrollToBottom) return; + + var storyboard = new Storyboard(); + if (ScrollButton.Visibility == Visibility.Visible) + { + var translateAnimation2 = new DoubleAnimationUsingKeyFrames(); + translateAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 0.0 }); + translateAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 150.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(translateAnimation2, ScrollButton); + Storyboard.SetTargetProperty(translateAnimation2, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateAnimation2); + + var opacityAnimation2 = new DoubleAnimation + { + From = 1.0, + To = 0.0, + Duration = TimeSpan.FromSeconds(0.25), + EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } + }; + Storyboard.SetTarget(opacityAnimation2, ScrollButton); + Storyboard.SetTargetProperty(opacityAnimation2, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(opacityAnimation2); + + var visibilityAnimation2 = new ObjectAnimationUsingKeyFrames(); + visibilityAnimation2.KeyFrames.Add(new DiscreteObjectKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = Visibility.Collapsed }); + Storyboard.SetTarget(visibilityAnimation2, ScrollButton); + Storyboard.SetTargetProperty(visibilityAnimation2, new PropertyPath("(UIElement.Visibility)")); + storyboard.Children.Add(visibilityAnimation2); + } + + if (ViewModel.MentionsCounter == 0 && MentionButton.Visibility == Visibility.Visible) + { + var translateAnimation1 = new DoubleAnimationUsingKeyFrames(); + translateAnimation1.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 0.0 }); + translateAnimation1.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 150.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(translateAnimation1, MentionButton); + Storyboard.SetTargetProperty(translateAnimation1, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateAnimation1); + + var opacityAnimation1 = new DoubleAnimation + { + From = 1.0, + To = 0.0, + Duration = TimeSpan.FromSeconds(0.25), + EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } + }; + Storyboard.SetTarget(opacityAnimation1, MentionButton); + Storyboard.SetTargetProperty(opacityAnimation1, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(opacityAnimation1); + + var visibilityAnimation = new ObjectAnimationUsingKeyFrames(); + visibilityAnimation.KeyFrames.Add(new DiscreteObjectKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = Visibility.Collapsed }); + Storyboard.SetTarget(visibilityAnimation, MentionButton); + Storyboard.SetTargetProperty(visibilityAnimation, new PropertyPath("(UIElement.Visibility)")); + storyboard.Children.Add(visibilityAnimation); + } + + storyboard.Completed += (sender, args) => + { + ViewModel.Counter = 0; + }; + + storyboard.Begin(); + } + + public void ShowMentionButton() + { + if (MentionButton.Visibility == Visibility.Visible) return; + if (ViewModel.SuppressHideScrollToBottom) return; + var dialog71 = ViewModel.CurrentDialog as TLDialog71; + if (dialog71 != null && (dialog71.UnreadMentions == null || dialog71.UnreadMentionsCount.Value == 0)) return; + + MentionButton.Visibility = Visibility.Visible; + MentionButton.Opacity = 0.0; + + var storyboard = new Storyboard(); + var translateAnimation = new DoubleAnimationUsingKeyFrames(); + translateAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 150.0 }); + translateAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(translateAnimation, MentionButton); + Storyboard.SetTargetProperty(translateAnimation, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateAnimation); + + var opacityAnimation = new DoubleAnimation + { + From = 0.0, + To = 1.0, + Duration = TimeSpan.FromSeconds(0.25), + EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } + }; + Storyboard.SetTarget(opacityAnimation, MentionButton); + Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(opacityAnimation); + + storyboard.Begin(); + } + + public void ShowScrollToBottomButton() + { + var storyboard = new Storyboard(); + if (ScrollButton.Visibility == Visibility.Collapsed) + { + ScrollButton.Visibility = Visibility.Visible; + ScrollButton.Opacity = 0.0; + + var translateAnimation2 = new DoubleAnimationUsingKeyFrames(); + translateAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 150.0 }); + translateAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(translateAnimation2, ScrollButton); + Storyboard.SetTargetProperty(translateAnimation2, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateAnimation2); + + var opacityAnimation2 = new DoubleAnimation + { + From = 0.0, + To = 1.0, + Duration = TimeSpan.FromSeconds(0.25), + EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } + }; + Storyboard.SetTarget(opacityAnimation2, ScrollButton); + Storyboard.SetTargetProperty(opacityAnimation2, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(opacityAnimation2); + } + + if (MentionButton.Visibility == Visibility.Collapsed && ViewModel.MentionsCounter > 0) + { + MentionButton.Visibility = Visibility.Visible; + MentionButton.Opacity = 0.0; + + var translateAnimation = new DoubleAnimationUsingKeyFrames(); + translateAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 150.0 }); + translateAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(translateAnimation, MentionButton); + Storyboard.SetTargetProperty(translateAnimation, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateAnimation); + + var opacityAnimation = new DoubleAnimation + { + From = 0.0, + To = 1.0, + Duration = TimeSpan.FromSeconds(0.25), + EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } + }; + Storyboard.SetTarget(opacityAnimation, MentionButton); + Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(opacityAnimation); + } + + if (storyboard.Children.Count > 0) + { + storyboard.Begin(); + } + } + + private static Storyboard _storyboard; + private static UIElement _element; + + public static readonly DependencyProperty AnimatedVisibilityProperty = + DependencyProperty.RegisterAttached("AnimatedVisibility", typeof(bool), typeof(DialogDetailsView), + new PropertyMetadata(OnAnimagedVisibilityChanged)); + + private StickerSpriteItem _stickerSpriteItem; + + private bool _backKeyPressed; + + private IDisposable _viewportChangedSubscription; + + private static void OnAnimagedVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var element = d as UIElement; + if (element != null) + { + if (_storyboard != null) + { + + _storyboard.Stop(); + } + if (_element != null) + { + _element.Opacity = 0.0; + _element.Visibility = Visibility.Collapsed; + } + + if ((bool)e.NewValue) + { + + element.Opacity = 1.0; + element.Visibility = Visibility.Visible; + } + else + { + var storyboard = new Storyboard(); + var continuumLayoutRootOpacity = new DoubleAnimation + { + From = 1.0, + To = 0.0, + Duration = TimeSpan.FromSeconds(1.0), + }; + Storyboard.SetTarget(continuumLayoutRootOpacity, element); + Storyboard.SetTargetProperty(continuumLayoutRootOpacity, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(continuumLayoutRootOpacity); + + storyboard.Begin(); + storyboard.Completed += (sender, args) => + { + _storyboard = null; + _element = null; + }; + + _storyboard = storyboard; + _element = element; + } + } + } + + + public static bool GetAnimatedVisibility(UIElement element) + { + return (bool)element.GetValue(AnimatedVisibilityProperty); + } + + public static void SetAnimatedVisibility(UIElement element, bool value) + { + element.SetValue(AnimatedVisibilityProperty, value); + } + + private void HashtagHintsPanel_OnHold(object sender, GestureEventArgs e) + { + ViewModel.ClearHashtags(); + } + + private void CommandsControl_OnButtonClick(object sender, KeyboardButtonEventArgs e) + { + TLMessageBase message = null; + var frameworkElement = sender as FrameworkElement; + if (frameworkElement != null) + { + message = frameworkElement.DataContext as TLMessageBase; + } + + ViewModel.Send(message, e.Button); + + if (e.ReplyMarkup != null + && e.ReplyMarkup == ViewModel.ReplyMarkup + && e.ReplyMarkup.IsSingleUse) + { + InputMessage.FocusInput(); + } + } + + private void InputMessage_OnMuteButtonClick(object sender, System.EventArgs e) + { + var channel = ViewModel.With as TLChannel44; + if (channel != null) + { + channel.Silent = !channel.Silent; + ViewModel.NotifyOfPropertyChange(() => ViewModel.MuteButtonImageSource); + + if (InputMessageHintPlaceholder.Content == null) + { + var control = new InputMessageHint(); + control.Closed += OnInputMessageHintClosed; + + InputMessageHintPlaceholder.Content = control; + } + + var inputMessageHint = InputMessageHintPlaceholder.Content as InputMessageHint; + if (inputMessageHint != null) + { + inputMessageHint.Hint = channel.Silent ? AppResources.MuteChannelPostHint : AppResources.UnmuteChannelPostHint; + } + } + } + + private void OnInputMessageHintClosed(object sender, System.EventArgs e) + { + var control = sender as InputMessageHint; + if (control != null) + { + control.Closed -= OnInputMessageHintClosed; + } + + InputMessageHintPlaceholder.Content = null; + } + + private void InputMessage_OnKeyboardButtonClick(object sender, System.EventArgs e) + { + var replyKeyboard = ViewModel.ReplyMarkup as TLReplyKeyboardMarkup; + + if (ViewModel.HasBots && replyKeyboard == null) + { + InputMessage.Text = "/"; + InputMessage.SelectionStart = 1; + InputMessage.FocusInput(); + + return; + } + + if (_emojiKeyboard != null + && InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + + if (replyKeyboard != null) + { + //OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => OpenCommandsPlaceholder()); + + return; + } + } + + if (CommandsControl.Visibility == Visibility.Visible) + { + if (_emojiKeyboard != null + && InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + OpenEmptyDialogPlaceholder(); + CloseCommandsPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + } + else + { + CloseCommandsPlaceholder(); + InputMessage.FocusInput(); + //Telegram.Api.Helpers.Execute.BeginOnUIThread(() => InputMessage.FocusInput()); + } + } + else + { + if (replyKeyboard != null) + { + CloseEmptyDialogPlaceholder(); + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => OpenCommandsPlaceholder()); + SetCaptionVisibility(Visibility.Collapsed); + } + } + } + + private void AddToFavedStickers_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem != null) + { + menuItem.Visibility = Visibility.Collapsed; + var message = menuItem.DataContext as TLMessage; + if (message != null && message.IsSticker()) + { + var mediaDocument = message.Media as TLMessageMediaDocument; + if (mediaDocument == null) return; + + var document = mediaDocument.Document as TLDocument22; + if (document != null) + { + var inputStickerSet = document.StickerSet; + if (inputStickerSet != null && !(inputStickerSet is TLInputStickerSetEmpty)) + { + var allStickers = ViewModel.Stickers as TLAllStickers43; + if (allStickers != null && allStickers.FavedStickers != null) + { + if (allStickers.Sets.Count >= Constants.MinSetsToAddFavedSticker || allStickers.FavedStickers.Documents.Count > 0) + { + var exists = allStickers.FavedStickers.Documents.FirstOrDefault(x => x.Id.Value == document.Id.Value); + if (exists != null) + { + menuItem.Visibility = Visibility.Visible; + menuItem.Header = AppResources.DeleteFromFavorites; + } + else + { + menuItem.Visibility = Visibility.Visible; + menuItem.Header = AppResources.AddToFavorites; + } + } + } + } + } + } + } + } + + private void AddToStickers_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem != null) + { + menuItem.Visibility = Visibility.Collapsed; + var message = menuItem.DataContext as TLMessage; + if (message != null && message.IsSticker()) + { + var mediaDocument = message.Media as TLMessageMediaDocument; + if (mediaDocument == null) return; + + var document = mediaDocument.Document as TLDocument22; + if (document != null) + { + var inputStickerSet = document.StickerSet; + if (inputStickerSet != null && !(inputStickerSet is TLInputStickerSetEmpty)) + { + var allStickers = ViewModel.Stickers as TLAllStickers29; + if (allStickers != null) + { + var set = + allStickers.Sets.FirstOrDefault( + x => x.Id.Value.ToString() == inputStickerSet.Name.ToString()); + if (set != null) + { + menuItem.Visibility = Visibility.Collapsed; + menuItem.Header = AppResources.ViewStickers; + } + else + { + menuItem.Visibility = Visibility.Visible; + menuItem.Header = AppResources.AddToStickers; + } + } + } + } + } + } + } + + private void StickerContextMenu_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element != null) + { + element.Visibility = Visibility.Visible; + } + } + + private void ServiceMessageContextMenu_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as ContextMenu; + if (element != null) + { + if (ViewModel.IsAppBarCommandVisible) + { + element.Visibility = Visibility.Collapsed; + element.IsOpen = false; + + return; + } + } + } + + private void DeleteMenuItem_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element != null) + { + var message = element.DataContext as TLMessage40; + if (message != null && message.Out.Value) + { + element.Visibility = Visibility.Visible; + return; + } + + var channel = ViewModel.With as TLChannel; + if (channel != null + && (channel.Creator || channel.IsEditor)) + { + element.Visibility = Visibility.Visible; + return; + } + + element.Visibility = Visibility.Collapsed; + } + } + + private void ReplyMenuItem_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + element.Visibility = ViewModel.IsAppBarCommandVisible ? Visibility.Collapsed : Visibility.Visible; + } + + private void ForwardMenuItem_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + var broadcast = ViewModel.With as TLBroadcastChat; + var channel = ViewModel.With as TLChannel; + if (broadcast != null + && channel == null) + { + element.Visibility = Visibility.Collapsed; + return; + } + + element.Visibility = Visibility.Visible; + } + + private void MoreMenuItem_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + element.Visibility = ViewModel.IsAppBarCommandVisible ? Visibility.Visible : Visibility.Collapsed; + } + + private void MoreMenuItem_OnClick(object sender, RoutedEventArgs e) + { + ViewModel.IsSelectionEnabled = true; + ApplicationBar.IsVisible = false;// true; + } + + private void ReportMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + element.Visibility = Visibility.Collapsed; + var message = element.DataContext as TLMessageCommon; + var user = ViewModel.With as TLUser; + var channel = ViewModel.With as TLChannel; + + if (message != null + && !message.Out.Value + && (user != null && user.IsBot || channel != null)) + { + element.Visibility = Visibility.Visible; + } + } + + private void ResendMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + element.Visibility = Visibility.Collapsed; + var message = element.DataContext as TLMessageCommon; + if (message != null) + { + element.Visibility = message.Status == MessageStatus.Failed ? Visibility.Visible : Visibility.Collapsed; + } + } + + private void ReplyMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + element.Visibility = Visibility.Visible; + + if (ViewModel.IsAppBarCommandVisible) + { + element.Visibility = Visibility.Collapsed; + return; + } + + var message = element.DataContext as TLMessage; + if (message != null && message.IsExpired()) + { + element.Visibility = Visibility.Collapsed; + return; + } + + var channel = ViewModel.With as TLChannel; + if (channel != null && channel.MigratedFromChatId != null) + { + var messageCommon = element.DataContext as TLMessageCommon; + if (messageCommon != null) + { + if (messageCommon.ToId is TLPeerChat) + { + element.Visibility = messageCommon.ToId.Id.Value == channel.MigratedFromChatId.Value ? Visibility.Collapsed : Visibility.Visible; + } + } + } + } + + private void PinMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as MenuItem; + if (element == null) return; + + element.Visibility = Visibility.Collapsed; + + var channel = ViewModel.With as TLChannel; + if (channel != null && channel.CanPinMessages) + { + var message = element.DataContext as TLMessageCommon; + if (message != null) + { + if (message.ToId is TLPeerChannel) + { + element.Visibility = Visibility.Visible; + element.Header = ViewModel.PinnedMessage != null && ViewModel.PinnedMessage.Message == message ? AppResources.UnpinMessage : AppResources.PinMessage; + } + } + } + } + private void EditMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + element.Visibility = Visibility.Collapsed; + + var channel = ViewModel.With as TLChannel76; + var user = ViewModel.With as TLUser66; + var message = element.DataContext as TLMessage48; + + if (message != null + && message.FwdHeader == null + && message.ViaBotId == null + && (message.Out.Value || (channel != null && channel.Creator && channel.IsEditor)) + && (message.Media is IMediaCaption || message.Media is TLMessageMediaWebPage || message.Media is TLMessageMediaEmpty)) + { + if (message.IsExpired()) + { + return; + } + + if (message.IsVoice()) + { + return; + } + + if (message.IsSticker()) + { + return; + } + + var time = TLUtils.DateToUniversalTimeTLInt(ViewModel.MTProtoService.ClientTicksDelta, DateTime.Now); + var config = IoC.Get().GetConfig() as TLConfig48; + if (config != null && config.EditTimeLimit != null && (message.DateIndex + config.EditTimeLimit.Value) < time.Value) + { + // channel admins with 'pin message' right can edit as long as possible + if (channel != null + && channel.AdminRights != null + && channel.AdminRights.PinMessages) + { + + } + else if (user != null && user.IsSelf) + { + + } + else + { + return; + } + } + + element.Visibility = Visibility.Visible; + } + } + + private void DeleteMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + element.Visibility = Visibility.Visible; + + var channel = ViewModel.With as TLChannel; + if (channel != null) + { + var message = element.DataContext as TLMessageCommon; + if (message != null) + { + if (message.Index == 1 && message.ToId is TLPeerChannel) + { + element.Visibility = Visibility.Collapsed; + } + + if (!channel.Creator && !channel.IsEditor) + { + if (message.FromId.Value != IoC.Get().CurrentUserId) + { + element.Visibility = Visibility.Collapsed; + } + } + } + } + } + + private void ForwardMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) + { + return; + } + + element.Visibility = Visibility.Collapsed; + + if (ViewModel == null) + { + return; + } + + var message = element.DataContext as TLMessage; + if (message != null && message.HasTTL()) + { + return; + } + + element.Visibility = ViewModel.IsBroadcast && !ViewModel.IsChannel ? Visibility.Collapsed : Visibility.Visible; + } + + private void CopyMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + element.Visibility = Visibility.Collapsed; + + var message = element.DataContext as TLMessage; + if (message != null) + { + if (!TLString.IsNullOrEmpty(message.Message)) + { + element.Visibility = Visibility.Visible; + return; + } + } + } + + private void EmojiMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + element.Visibility = +#if DEBUG + Visibility.Visible; +#else + Visibility.Collapsed; +#endif + } + + private void SaveMedia_OnLoaded(object sender, RoutedEventArgs e) + { + var frameworkElement = sender as FrameworkElement; + if (frameworkElement == null) return; + + frameworkElement.Visibility = Visibility.Collapsed; + + var message = frameworkElement.DataContext as TLMessage; + if (message == null) return; + if (message.HasTTL() || message.IsSticker() || message.IsRoundVideo() || message.IsGif()) return; + +#if WP8 + var mediaDocument = message.Media as TLMessageMediaDocument; + if (mediaDocument != null) + { + var file = mediaDocument.File; + + if (file == null) + { + var document = mediaDocument.Document as TLDocument; + if (document != null) + { + var localFileName = document.GetFileName() ?? string.Empty; + var globalFileName = mediaDocument.IsoFileName ?? string.Empty; + var store = IsolatedStorageFile.GetUserStoreForApplication(); + if (store.FileExists(localFileName) + || store.FileExists(globalFileName) +#if WP81 + || File.Exists(globalFileName) +#endif +) + { + frameworkElement.Visibility = Visibility.Visible; + return; + } + } + } + + frameworkElement.Visibility = file != null ? Visibility.Visible : Visibility.Collapsed; + return; + } + + var mediaVideo = message.Media as TLMessageMediaVideo; + if (mediaVideo != null) + { + var file = mediaVideo.File; + + if (file == null) + { + var video = mediaVideo.Video as TLVideo; + if (video != null) + { + var localFileName = video.GetFileName() ?? string.Empty; + var globalFileName = mediaVideo.IsoFileName ?? string.Empty; + var store = IsolatedStorageFile.GetUserStoreForApplication(); + if (store.FileExists(localFileName) + || store.FileExists(globalFileName) +#if WP81 + || File.Exists(globalFileName) +#endif +) + { + frameworkElement.Visibility = Visibility.Visible; + return; + } + } + } + + frameworkElement.Visibility = file != null ? Visibility.Visible : Visibility.Collapsed; + return; + } +#endif + } + + private void MessagesList_OnViewportChanged() + { + //return; + System.Diagnostics.Debug.WriteLine("ViewportChanged date={0}", DateTime.Now.TimeOfDay); + if (Player.Content != null) + { + var gifPlayer = MessagePlayerControl.Player.Tag as GifPlayerControl; + if (gifPlayer != null && gifPlayer.Mode == GifPlayerMode.RoundVideo) + { + var frame = Application.Current.RootVisual as TelegramTransitionFrame; + if (frame != null) + { + var itemsInView = MessagesList.GetItemsInView(); + foreach (var item in itemsInView) + { + var message = item.DataContext as TLMessage; + if (message != null && message.Media == gifPlayer.Media) + { + frame.HidePlayer(); + return; + } + } + + var videoBrush = new VideoBrush(); + videoBrush.SetSource(MessagePlayerControl.Player); + + frame.ShowPlayer(videoBrush); + } + } + } + var dialog = ViewModel.CurrentDialog as TLDialog71; + if (dialog != null && dialog.UnreadMentions != null && dialog.UnreadMentions.Count > 0) + { + var itemsInView = MessagesList.GetItemsInView(); + var maxId = 0; + foreach (var item in itemsInView) + { + var message = item.DataContext as TLMessage; + if (message != null) + { + maxId = Math.Max(maxId, message.Index); + } + } + + if (maxId > 0) + { + ViewModel.ReadMentions(maxId); + } + } + } + + private void Items_OnItemUnrealized(object sender, ItemRealizationEventArgs e) + { + var message = e.Container.Content as TLMessage; + if (message != null) + { + + TLFileLocation profilePhotoFileLocation = null; + + var photoMedia = message.Media as TLMessageMediaPhoto; + if (photoMedia != null) + { + var photo = photoMedia.Photo as TLPhoto; + if (photo != null) + { + var viewModel = ViewModel; + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + viewModel.DownloadFileManager.CancelDownloadFile(photo); + if (profilePhotoFileLocation != null) viewModel.DownloadFileManager.CancelDownloadFile(profilePhotoFileLocation); + }); + } + } + } + } + + public void StartChatPlayer(StartGifPlayerEventArgs e) + { + if (MessagesList.ManipulationState != ManipulationState.Idle) return; + if (ViewModel.ChooseAttachment != null && ViewModel.ChooseAttachment.IsOpen) return; + if (MessagePlayerControl.Player != null + && MessagePlayerControl.Player.CurrentState == MediaElementState.Playing + && MessagePlayerControl.Player.Tag is GifPlayerControl) return; + + var settings = ViewModel.StateService.GetChatSettings(); + var newItems = MessagesList.GetItemsInView(); + + foreach (var item in newItems) + { + var message = item.DataContext as TLMessage; + if (message != null && message == e.Message && (message.IsGif() || message.IsRoundVideo())) + { + var media = message.Media; + if ((media != null && media.AutoPlayGif == true) || (settings != null && settings.AutoPlayGif && media != null && media.AutoPlayGif != false)) + { + var gifPlayer = item.FindChildOfType(); + if (gifPlayer != null) + { + gifPlayer.Start(); + } + } + return; + } + } + } + + public void ResumeChatPlayers() + { + if (MessagesList.ManipulationState != ManipulationState.Idle) return; + if (ViewModel.ChooseAttachment != null && ViewModel.ChooseAttachment.IsOpen) return; + if (MessagePlayerControl.Player != null + && MessagePlayerControl.Player.CurrentState == MediaElementState.Playing + && MessagePlayerControl.Player.Tag is GifPlayerControl) return; + if (FocusManager.GetFocusedElement() == InputMessage.Input) return; + if (ViewModel.InlineBotResults != null && ViewModel.InlineBotResults.Results.Count > 0) return; + + var settings = ViewModel.StateService.GetChatSettings(); + var newItems = MessagesList.GetItemsInView(); + + var activePlayers = new List(); + foreach (var item in newItems) + { + var message = item.DataContext as TLMessage; + if (message != null && (message.IsGif() || message.IsRoundVideo())) + { + var media = message.Media; + if ((media != null && media.AutoPlayGif == true) || (settings != null && settings.AutoPlayGif && media != null && media.AutoPlayGif != false)) + { + var gifPlayer = item.FindChildOfType(); + if (gifPlayer != null) + { + activePlayers.Add(gifPlayer); + } + } + } + } + + GifPlayerControl.ResumeActivePlayers(activePlayers); + } + + public void PauseChatPlayers() + { + GifPlayerControl.PauseActivePlayers(); + } + + private void Items_OnManipulationStateChanged(object sender, System.EventArgs e) + { + GifPlayerControl.ManipulationState = MessagesList.ManipulationState; + if (MessagesList.ManipulationState == ManipulationState.Idle) + { + ResumeChatPlayers(); + } + else + { + PauseChatPlayers(); + } +#if DEBUG + var count = GifPlayerControl.ActivePlayers.Count; + Debug.Text = string.Format("{0} {1}", count, GifPlayerControl.ActivePlayers.Count); +#endif + } + + private void ViaBot_Tap(object sender, GestureEventArgs e) + { + var frameworkElement = sender as FrameworkElement; + if (frameworkElement == null) return; + + var message = frameworkElement.DataContext as TLMessage45; + if (message == null) return; + + SetInlineBot(message.ViaBot); + } + + public void SetInlineBot(TLUserBase bot) + { + var user = bot as TLUser; + if (user == null || !user.IsInlineBot) return; + + InputMessage.Text = string.Format("@{0} ", user.UserName); + InputMessage.FocusInput(); + InputMessage.SelectionStart = InputMessage.Text.Length; + InputMessage.SelectionLength = 0; + + ViewModel.CurrentInlineBot = user; + ViewModel.GetInlineBotResults(string.Empty); + } + + private void ForwardMessage_OnClick(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + var message = element.DataContext as TLMessageBase; + // find common grouped message to resend + var message73 = message as TLMessage73; + if (message73 != null + && message73.GroupedId != null) + { + var mediaGroup = message73.Media as TLMessageMediaGroup; + if (mediaGroup == null) + { + var groupedMessage = ViewModel.FindGroupedMessage(message73) as TLMessage45; + if (groupedMessage != null) + { + message = groupedMessage; + } + } + } + + if (message == null) return; + var selectedItems = new List { message }; + if (selectedItems.Count == 0) return; + + ViewModel.FastForwardMessages(selectedItems); + } + + private void ShareButton_OnClick(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + var message = element.DataContext as TLMessageBase; + if (message == null) return; + + var message73 = message as TLMessage73; + if (message73 != null) + { + var fwdHeader = message73.FwdHeader as TLMessageFwdHeader73; + if (fwdHeader != null && fwdHeader.SavedFromPeer != null && fwdHeader.SavedFromMsgId != null) + { + TLObject with = null; + var peerUser = fwdHeader.SavedFromPeer as TLPeerUser; + var peerChat = fwdHeader.SavedFromPeer as TLPeerChat; + var peerChannel = fwdHeader.SavedFromPeer as TLPeerChannel; + if (peerUser != null) + { + with = IoC.Get().GetUser(peerUser.Id); + } + else if (peerChat != null) + { + with = IoC.Get().GetChat(peerChat.Id); + } + else if (peerChannel != null) + { + with = IoC.Get().GetChat(peerChannel.Id); + } + + if (with == null) + { + return; + } + + Execute.BeginOnUIThread(() => + { + IoC.Get().With = with; + IoC.Get().MessageId = fwdHeader.SavedFromMsgId; + IoC.Get().RemoveBackEntries = true; + IoC.Get().Navigate(new Uri("/Views/Dialogs/DialogDetailsView.xaml?rndParam=" + TLInt.Random(), UriKind.Relative)); + }); + + return; + } + } + + var selectedItems = new List { message }; + if (selectedItems.Count == 0) return; + + ViewModel.FastForwardMessages(selectedItems); + } + + private void EmojiMessage_OnClick(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + var message = element.DataContext as TLMessage48; + if (message == null) return; + + var fwdHeader = message.FwdHeader; + MessageBox.Show( + string.Format("TLMessageFwdHeader flags={0} from_id={1} date={2} channel_id={3} channel_post={4}", + fwdHeader.Flags, fwdHeader.FromId, fwdHeader.Date, fwdHeader.ChannelId, fwdHeader.ChannelPost)); + return; + + var resultString = string.Empty; + var text = message.Message.ToString(); + var textEnumerator = StringInfo.GetTextElementEnumerator(text); + + var symbols = new List(); + while (textEnumerator.MoveNext()) + { + var text2 = textEnumerator.GetTextElement(); + var bytes2 = Encoding.BigEndianUnicode.GetBytes(text2); + var bytesStr2 = BrowserNavigationService.ConvertToHexString(bytes2); + + symbols.Add(bytesStr2); + } + + var dict = new Dictionary(); + var builder = new StringBuilder(); + for (var i = 0; i < symbols.Count; ) + { + builder.AppendLine(string.Format("_dict[\"{0}\"] = \"{0}\";", symbols[i] + symbols[i + 1])); + dict[symbols[i]] = symbols[i]; + i += 2; + + if (i % 20 == 0) + { + builder.AppendLine(); + } + } + builder.AppendLine(); + foreach (var item in dict) + { + builder.AppendLine(item.Value); + } + + MessageBox.Show(builder.ToString()); + Clipboard.SetText(builder.ToString()); + } + + private void ShowUserProfile_OnTap(object sender, GestureEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + var message = element.DataContext as TLMessage; + if (message == null) return; + + Execute.BeginOnUIThread(() => + { + CreateBitmapCache(); + MessagesList.Visibility = Visibility.Collapsed; + MessagesCache.Visibility = Visibility.Visible; + ViewModel.ShowUserProfile(message); + }); + } + + private void CopyLink_OnLoaded(object sender, RoutedEventArgs e) + { + var contextMenu = sender as ContextMenu; + if (contextMenu == null) return; + + var message = contextMenu.DataContext as TLMessageBase; + if (message == null) + { + contextMenu.IsOpen = false; + return; + } + if (message.Index == 0) + { + contextMenu.IsOpen = false; + return; + } + + var channel = ViewModel.With as TLChannel; + if (channel == null) + { + contextMenu.IsOpen = false; + return; + } + + if (TLString.IsNullOrEmpty(channel.UserName)) + { + contextMenu.IsOpen = false; + return; + } + } + + private void CopyLink_OnClick(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + var message = element.DataContext as TLMessageBase; + if (message == null) return; + if (message.Index == 0) return; + + var selectedItems = new List { message }; + if (selectedItems.Count == 0) return; + + var channel = ViewModel.With as TLChannel; + if (channel == null) return; + if (TLString.IsNullOrEmpty(channel.UserName)) return; + + Clipboard.SetText(String.Format(Constants.UsernameLinkPlaceholder + "/{1}", channel.UserName, message.Id)); + } + + private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + Telegram.Api.Helpers.Execute.ShowDebugMessage("ActualHeight=" + element.ActualWidth); + } + + private void InputMessage_OnDeleteReplyButtonClick(object sender, System.EventArgs eventArgs) + { + var container = ViewModel.Reply as TLMessagesContainter; + if (container != null) + { + var editMessage = container.EditMessage; + if (editMessage != null) + { + if (container.WebPageMedia != null) + { + ViewModel.DeleteReply(); + + return; + } + + ViewModel.CancelSaveMessage(); + + return; + } + } + + ViewModel.DeleteReply(); + } + + private void KeepFocusedInputMessage() + { + if (_focusedElement == InputMessage) + { + InputMessage.FocusInput(); + } + } + + private void InputMessage_OnOpenReplyButtonClick(object sender, System.EventArgs eventArgs) + { + ViewModel.OpenEditMessage(); + } + + private void MessagesList_OnShowScrollButton(object sender, System.EventArgs e) + { + ShowScrollToBottomButton(); + } + + private void MessagesList_OnSizeChanged(object sender, SizeChangedEventArgs e) + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("MessagesList.OnSizeChanged"); + } + + private void ContextMenu_OnHold(object sender, GestureEventArgs e) + { + e.Handled = true; + } + + private void ContextMenu_OnTap(object sender, GestureEventArgs e) + { + ContextMenu.IsOpen = true; + } + + private void InputMessage_OnAppBarCommandClick(object sender, System.EventArgs e) + { + ViewModel.AppBarCommand(); + } + + private void InputMessage_OnCancelSelectionButtonClick(object sender, System.EventArgs e) + { + ViewModel.IsSelectionEnabled = false; + } + + private void InputMessage_OnForwardButtonClick(object sender, System.EventArgs e) + { + var selectedItems = DialogDetailsViewModel.UngroupEnumerator(ViewModel.Items).Where(x => x.Index > 0 && x.IsSelected).ToList(); + if (selectedItems.Count == 0) return; + + ViewModel.IsSelectionEnabled = false; + + Telegram.Api.Helpers.Execute.BeginOnUIThread(TimeSpan.FromSeconds(0.55), () => // waiting to complete animation + { + CreateBitmapCache(); + MessagesList.Visibility = Visibility.Collapsed; + MessagesCache.Visibility = Visibility.Visible; + ViewModel.ForwardMessages(selectedItems); + }); + } + + private void SelectMessages_OnClick(object sender, RoutedEventArgs e) + { + var frameworkElement = sender as FrameworkElement; + if (frameworkElement != null) + { + var message = frameworkElement.DataContext as TLMessageBase; + if (message != null && message.SelectionVisibility == Visibility.Visible) + { + ViewModel.ChangeSelection(message); + } + } + + ViewModel.IsSelectionEnabled = true; + } + + private void InputMessage_OnDeleteButtonClick(object sender, System.EventArgs e) + { + ViewModel.DeleteMessages(); + } + + private void InputMessage_OnShowEmojiHints(object sender, EmojiHintsEventArgs e) + { + var emojiHintsView = EmojiHints.Content as EmojiHintsView; + if (emojiHintsView == null) + { + emojiHintsView = new EmojiHintsView { DataContext = new EmojiHintsViewModel() }; + EmojiHints.Content = emojiHintsView; + } + + var emojiHintsViewModel = emojiHintsView.DataContext as EmojiHintsViewModel; + if (emojiHintsViewModel != null) + { + emojiHintsViewModel.SetParameters(e.Parameters); + } + } + + private void InputMessage_OnHideEmojiHints(object sender, System.EventArgs e) + { + var emojiHintsView = EmojiHints.Content as EmojiHintsView; + if (emojiHintsView != null) + { + var emojiHintsViewModel = emojiHintsView.DataContext as EmojiHintsViewModel; + if (emojiHintsViewModel != null) + { + emojiHintsViewModel.SetParameters(null); + } + } + } + + private void SelectMessages_OnLoaded(object sender, RoutedEventArgs e) + { + var frameworkElement = sender as FrameworkElement; + if (frameworkElement != null) + { + frameworkElement.Visibility = Visibility.Visible; + + var message = frameworkElement.DataContext as TLMessageBase; + if (message != null && message.IsExpired()) + { + frameworkElement.Visibility = Visibility.Collapsed; + return; + } + } + } + + public void ScrollTo(TLObject obj) + { + MessagesList.ScrollToItem(obj); + } + + private void MentionButton_OnHold(object sender, GestureEventArgs e) + { + ViewModel.ClearUnreadMentions(); + } + + private void SelectionBorder_OnTap(object sender, GestureEventArgs e) + { + var element = sender as FrameworkElement; + if (element != null) + { + var groupedMessage = element.DataContext as TLMessage73; + if (groupedMessage != null) + { + var selectionChanged = false; + + var messageMediaGroup = groupedMessage.Media as TLMessageMediaGroup; + if (messageMediaGroup != null) + { + var message = GetInnerMessage(element, e); + if (message != null) + { + ViewModel.ChangeSelection(message); + + selectionChanged = true; + if (messageMediaGroup.Group.All(x => x.IsSelected) && !groupedMessage.IsSelected + || messageMediaGroup.Group.All(x => !x.IsSelected) && groupedMessage.IsSelected) + { + selectionChanged = false; + } + } + } + + if (!selectionChanged) + { + ViewModel.ChangeSelection(groupedMessage); + } + } + else + { + ViewModel.ChangeSelection(element.DataContext as TLMessageBase); + } + } + } + + private void MessageControl_OnTapMedia(object sender, GestureEventArgs e) + { + var messageControl = sender as MessageControl; + if (messageControl != null) + { + var message = GetInnerMessage(messageControl, e); + if (message != null) + { + ViewModel.OpenMedia(message); + } + } + } + + private TLMessageBase _innerMessage; + + private void MessageControl_OnHold(object sender, GestureEventArgs e) + { + var messageControl = sender as MessageControl; + if (messageControl != null) + { + _innerMessage = GetInnerMessage(messageControl, e); + } + } + + private TLMessageBase GetInnerMessage(FrameworkElement element, GestureEventArgs e) + { + var groupedMessage = element.DataContext as TLMessage73; + if (groupedMessage != null) + { + var messageMediaGroup = groupedMessage.Media as TLMessageMediaGroup; + if (messageMediaGroup != null) + { + var point = e.GetPosition(Application.Current.RootVisual); + var elements = VisualTreeHelper.FindElementsInHostCoordinates(point, MessagesList); + var mediaPhotoControl = elements.OfType().FirstOrDefault(); + if (mediaPhotoControl != null) + { + var message = messageMediaGroup.Group.OfType().FirstOrDefault(x => x.Media == mediaPhotoControl.Media); + if (message != null) + { + return message; + } + } + } + } + + return element.DataContext as TLMessageBase; + } + + private void MessageControl_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + if (FocusManager.GetFocusedElement() == InputMessage.Input) + { + return; + } + + var messageControl = sender as MessageControl; + if (messageControl != null) + { + var messageService = messageControl.DataContext as TLMessageService; + if (messageService != null) + { + return; + } + } + + System.Diagnostics.Debug.WriteLine(" Manipulation started"); + _skipFirstManipulationDelta = true; + e.Handled = true; + } + + private bool _skipFirstManipulationDelta; + + private void MessageControl_OnManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + if (_skipFirstManipulationDelta) + { + _skipFirstManipulationDelta = false; + return; + } + + if (FocusManager.GetFocusedElement() == InputMessage.Input) + { + return; + } + + var messageControl = sender as MessageControl; + if (messageControl != null) + { + var decryptedMessageService = messageControl.DataContext as TLMessageService; + if (decryptedMessageService != null) + { + return; + } + + var transform = messageControl.RenderTransform as TranslateTransform; + if (transform == null) + { + return; + } + + var translationX = transform.X - e.DeltaManipulation.Translation.X; + + if (translationX < -100.0) + { + translationX = -100.0; + } + else if (translationX > 100.0) + { + translationX = 100.0; + } + + if (messageControl.CacheMode == null) messageControl.CacheMode = new BitmapCache(); + messageControl.RenderTransform = new TranslateTransform + { + X = translationX + }; + + e.Handled = true; + } + } + + private void MessageControl_OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + _skipFirstManipulationDelta = false; + System.Diagnostics.Debug.WriteLine(" Manipulation completed State={0}", MessagesList.Viewport.ManipulationState); + if (FocusManager.GetFocusedElement() == InputMessage.Input) + { + return; + } + + var messageControl = sender as MessageControl; + if (messageControl != null) + { + var decryptedMessageService = messageControl.DataContext as TLMessageService; + if (decryptedMessageService != null) + { + return; + } + var transform = messageControl.RenderTransform as TranslateTransform; + if (transform != null) + { + var translateX = transform.X; + + var storyboard = new Storyboard(); + var doubleAnimation = new DoubleAnimation(); + doubleAnimation.To = 0.0; + doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.15)); + Storyboard.SetTarget(doubleAnimation, messageControl.RenderTransform); + Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("X")); + storyboard.Children.Add(doubleAnimation); + + storyboard.Begin(); + storyboard.Completed += (o, args) => + { + messageControl.CacheMode = null; + if (translateX >= 75.0) + { + var messageBase = messageControl.DataContext as TLMessageBase; + var innerMessage = GetInnerMessage(e, messageBase); + if (innerMessage != null) + { + messageBase = innerMessage; + } + + if (messageBase == null) return; + + ViewModel.ReplyMessage(messageBase); + InputMessage.FocusInput(); + } + else if (translateX <= -75.0) + { + var messageBase = messageControl.DataContext as TLMessageBase; + + if (messageBase == null) return; + + ViewModel.FastForwardMessages(new List { messageBase }); + SelfView.Focus(); + } + }; + } + } + } + + private TLMessageBase GetInnerMessage(ManipulationCompletedEventArgs e, TLMessageBase messageBase) + { + var message = messageBase as TLMessage73; + if (message != null) + { + var mediaGroup = message.Media as TLMessageMediaGroup; + if (mediaGroup != null) + { + var source = e.OriginalSource as FrameworkElement; + if (source != null) + { + var media = source.DataContext as TLMessageMediaBase; + for (int i = 0; i < mediaGroup.Group.Count; i++) + { + var m = mediaGroup.Group[i] as TLMessage; + if (m != null && m.Media == media) + { + return m; + } + } + } + } + } + + return null; + } + + private void Items_OnItemRealized(object sender, ItemRealizationEventArgs e) + { + + } + } + + public interface IDialogDetailsView + { + void ScrollTo(TLObject item); + + void OpenBitmapCache(); + + void CloseBitmapCache(); + + void SetInlineBot(TLUserBase bot); + + void MoveCurretToEnd(); + + bool IsScrollToBottomButtonVisible { get; } + + void HideMentionButton(); + + void ShowMentionButton(); + + void HideScrollToBottomButton(); + + void ShowScrollToBottomButton(); + + void CreateBitmapCache(Action action); + + void StopPlayersAndCreateBitmapCache(Action action); + + void ResumeChatPlayers(); + + void PauseChatPlayers(); + + void StartChatPlayer(StartGifPlayerEventArgs args); + } + + public class TLStickerItem : TLObject + { + public TLDocumentBase Document { get; set; } + + public TLStickerItem Self + { + get { return this; } + } + + public override string ToString() + { + return string.Format("TLStickerItem document={0}", Document); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Dialogs/DialogsView.xaml b/TelegramClient.WP8/Views/Dialogs/DialogsView.xaml new file mode 100755 index 0000000..70161ac --- /dev/null +++ b/TelegramClient.WP8/Views/Dialogs/DialogsView.xaml @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Dialogs/DialogsView.xaml.cs b/TelegramClient.WP8/Views/Dialogs/DialogsView.xaml.cs new file mode 100755 index 0000000..ddef8d7 --- /dev/null +++ b/TelegramClient.WP8/Views/Dialogs/DialogsView.xaml.cs @@ -0,0 +1,462 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Input; +using System.Windows.Interactivity; +using System.Windows.Media; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using Telegram.Controls; +using Telegram.Controls.Extensions; +using Telegram.Controls.Triggers; +using Telegram.Controls.VirtualizedView; +using Telegram.EmojiPanel.Controls.Utilites; +using TelegramClient.Converters; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Dialogs; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Dialogs +{ + public partial class DialogsView + { + public DialogsViewModel ViewModel + { + get { return (DialogsViewModel)DataContext; } + } + + public DialogsView() + { + App.Log("start DialogsView.ctor"); + + InitializeComponent(); + + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + ((SolidColorBrush)Resources["PinnedBackground"]).Color = isLightTheme + ? ((SolidColorBrush)Resources["PinnedBackgroundLight"]).Color + : ((SolidColorBrush)Resources["PinnedBackgroundDark"]).Color; + + //VirtPanel.InitializeWithScrollViewer(CSV); + //VirtPanel.CreateFunc = o => + //{ + // return new DialogItem(o as TLDialogBase, 480.0, Resources["DialogTemplate"] as DataTemplate); + //}; + + App.Log("stop DialogsView.ctor"); + } + + private void Items_OnCloseToEnd(object sender, System.EventArgs e) + { + ((DialogsViewModel)DataContext).LoadNextSlice(); + } + + public FrameworkElement TapedItem; + + private void MainItemGrid_OnTap(object sender, GestureEventArgs e) + { + TapedItem = (FrameworkElement)sender; + + var tapedItemContainer = TapedItem.FindParentOfType(); + + var result = ViewModel.OpenDialogDetails(TapedItem.DataContext as TLDialogBase); + if (result) + { + ShellView.StartContinuumForwardOutAnimation(TapedItem, tapedItemContainer); + } + } + + private void MainItemGrid_OnDoubleTap(object sender, GestureEventArgs gestureEventArgs) + { + TapedItem = (FrameworkElement)sender; + + var tapedItemContainer = TapedItem.FindParentOfType(); + + var result = ViewModel.OpenFastDialogDetails(TapedItem.DataContext as TLDialogBase); + //if (result) + //{ + // ShellView.StartContinuumForwardOutAnimation(TapedItem, tapedItemContainer); + + // } + } + + private void DeleteAndStop_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem == null) return; + + var dialog = menuItem.DataContext as TLDialogBase; + if (dialog == null) return; + + var user = dialog.With as TLUser; + + menuItem.Visibility = user != null && user.IsBot && (user.Blocked == null || !user.Blocked.Value) + ? Visibility.Visible + : Visibility.Collapsed; + } + + private void ClearHistory_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem == null) return; + + var dialog = menuItem.DataContext as TLDialogBase; + if (dialog == null) return; + + var channel = dialog.With as TLChannel; + + menuItem.Visibility = channel != null && (!channel.IsMegaGroup || !TLString.IsNullOrEmpty(channel.UserName)) + ? Visibility.Collapsed + : Visibility.Visible; + } + + private void Pin_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem == null) return; + + var dialog = menuItem.DataContext as TLDialog53; + if (dialog == null) + { + menuItem.Visibility = Visibility.Collapsed; + return; + } + + var dialog71 = menuItem.DataContext as TLDialog71; + if (dialog71 != null && dialog71.IsPromo) + { + menuItem.Visibility = Visibility.Collapsed; + return; + } + + var messageService = dialog.TopMessage as TLMessageService; + if (messageService != null && messageService.Action is TLMessageActionContactRegistered) + { + menuItem.Visibility = Visibility.Collapsed; + return; + } + + var isPinned = dialog.IsPinned; + if (!isPinned) + { + var config = IoC.Get().GetConfig() as TLConfig61; + if (config != null) + { + var pinnedCount = ViewModel.Items.Count(x => x.IsPinned); + if (pinnedCount >= config.PinnedDialogsCountMax.Value) + { + menuItem.Visibility = Visibility.Collapsed; + } + } + } + + if (isPinned) + { + menuItem.Header = AppResources.UnpinDialog; + } + else + { + menuItem.Header = AppResources.PinDialog; + } + } + + private void Group_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem == null) return; + + menuItem.Visibility = Visibility.Collapsed; + return; + + var dialog = menuItem.DataContext as TLDialog; + if (dialog == null) + { + menuItem.Visibility = Visibility.Collapsed; + return; + } + + var dialog71 = menuItem.DataContext as TLDialog71; + if (dialog71 == null && dialog71.IsPromo) + { + menuItem.Visibility = Visibility.Collapsed; + return; + } + + var channel = dialog.With as TLChannel76; + if (channel == null) + { + menuItem.Visibility = Visibility.Collapsed; + return; + } + + menuItem.Header = channel.FeedId != null ? AppResources.Ungroup : AppResources.Group; + } + + private void ChangeUnreadMark_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem == null) return; + + var dialog = menuItem.DataContext as TLDialog71; + if (dialog == null) + { + menuItem.Visibility = Visibility.Collapsed; + return; + } + + menuItem.Header = + dialog.UnreadMark + || dialog.UnreadCount != null && dialog.UnreadCount.Value > 0 + || dialog.UnreadMentionsCount != null && dialog.UnreadMentionsCount.Value > 0 ? + AppResources.MarkRead : + AppResources.MarkUnread; + } + + private void PinToStart_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem == null) return; + + var dialog = menuItem.DataContext as TLDialogBase; + if (dialog == null) return; + + var tileNavigationParam = DialogsViewModel.GetTileNavigationParam(dialog); + if (tileNavigationParam == null) + { + menuItem.Visibility = Visibility.Collapsed; + return; + } + + var tileExists = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains(tileNavigationParam)) != null; + if (tileExists) + { + menuItem.Header = AppResources.UnpinFromStart; + } + else + { + menuItem.Header = AppResources.PinToStart; + } + } + + private void ContextMenu_OnLoaded(object sender, RoutedEventArgs e) + { + var contextMenu = sender as ContextMenu; + if (contextMenu == null) return; + + var dialog = contextMenu.DataContext as TLDialogBase; + if (dialog == null) return; + + //var channel = dialog.With as TLChannel; + + //contextMenu.Visibility = channel != null && !channel.IsMegaGroup + // ? Visibility.Collapsed + // : Visibility.Visible; + } + + private void DeleteDialog_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem == null) return; + + menuItem.Visibility = Visibility.Collapsed; + + var dialog = menuItem.DataContext as TLDialogBase; + if (dialog == null) return; + + var dialog71 = menuItem.DataContext as TLDialog71; + if (dialog71 != null && dialog71.IsPromo) return; + + var peerChannel = dialog.Peer as TLPeerChannel; + if (peerChannel != null) + { + var channel = dialog.With as TLChannel49; + if (channel != null) + { + menuItem.Header = channel.IsMegaGroup ? AppResources.LeaveGroup : AppResources.LeaveChannel; + } + + menuItem.Visibility = Visibility.Visible; + return; + } + + var peerUser = dialog.Peer as TLPeerUser; + if (peerUser != null) + { + menuItem.Visibility = Visibility.Visible; + return; + } + + var peerChat = dialog.Peer as TLPeerChat; + if (peerChat != null) + { + var isVisible = dialog.With is TLChatForbidden || dialog.With is TLChatEmpty; + + menuItem.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed; + return; + } + } + + private void DeleteAndExit_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem == null) return; + + menuItem.Visibility = Visibility.Collapsed; + + var dialog = menuItem.DataContext as TLDialogBase; + if (dialog == null) return; + + var peerChat = dialog.Peer as TLPeerChat; + if (peerChat != null) + { + menuItem.Visibility = Visibility.Visible; + return; + } + + //var peerChannel = dialog.Peer as TLPeerChannel; + //if (peerChannel != null) + //{ + // var channel = dialog.With as TLChannel; + // menuItem.Visibility = channel != null && channel.IsMegaGroup ? Visibility.Visible : Visibility.Collapsed; + // return; + //} + + var peerEncryptedChat = dialog.Peer as TLPeerEncryptedChat; + if (peerEncryptedChat != null) + { + menuItem.Header = AppResources.DeleteChat; + menuItem.Visibility = Visibility.Visible; + return; + } + + var peerBroadcast = dialog.Peer as TLPeerBroadcast; + if (peerBroadcast != null) + { + menuItem.Visibility = Visibility.Visible; + return; + } + } + + private void MainItemGrid_OnTapCommon(object sender, GestureEventArgs e) + { + if (!ViewModel.TestMode) + { + MainItemGrid_OnTap(sender, e); + } + else + { + //Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + //{ + MainItemGrid_OnDoubleTap(sender, e); + //}); + } + } + + private DateTime? _lastInvokeTime; + + private void Items_OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + //if (_lastInvokeTime != null && _lastInvokeTime.Value.AddSeconds(10.0) > DateTime.Now) return; + + //_lastInvokeTime = DateTime.Now; + //ViewModel.LoadNextSlice(); + this.Focus(); + } + + private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e) + { + var element = (FrameworkElement)sender; + MessageBox.Show("4 " + element.ActualHeight.ToString()); + } + + private bool _once = true; + + private void Items_OnManipulationStarted(object sender, ScrollingStateChangedEventArgs args) + { + if (!_once) return; + if (!args.NewValue) return; + + _once = false; + ViewModel.LoadNextSlice(); + } + } + + public class DialogItem : VListItemBase + { + public DialogItem(TLDialogBase dialog, double panelWidth, DataTemplate template) + { + _fixedHeight = 96.0; + + var contentControl = new ContentControl { Width = panelWidth, Content = dialog, HorizontalContentAlignment = HorizontalAlignment.Stretch, ContentTemplate = template }; + + //var binding = new Binding + //{ + // Mode = BindingMode.OneWay, + // Path = new PropertyPath("LineOne"), + // //Converter = new DefaultPhotoConverter(), + // //ConverterParameter = StickerHeight + //}; + //var panelMargin = new Thickness(0.0, 0.0, 0.0, 17.0); + //var panelActualWidth = panelWidth - panelMargin.Left - panelMargin.Right; + //var stackPanel = new StackPanel{ Width = panelActualWidth, Margin = panelMargin, Background = new SolidColorBrush(Colors.Transparent) }; + //var firstTextBlock = new TextBlock {TextWrapping = TextWrapping.Wrap, Text = item.LineOne, Style = Application.Current.Resources["PhoneTextExtraLargeStyle"] as Style }; + //firstTextBlock.SetBinding(TextBlock.TextProperty, binding); + //var secondTextBlock = new TextBlock + //{ + // TextWrapping = TextWrapping.Wrap, + // Text = item.LineTwo, + // Margin = new Thickness(12.0, -6.0, 12.0, 0.0), + // Style = Application.Current.Resources["PhoneTextSubtleStyle"] as Style + //}; + //stackPanel.Children.Add(firstTextBlock); + //stackPanel.Children.Add(secondTextBlock); + var listBoxItem = new ListBoxItem { Content = contentControl, DataContext = dialog }; + //listBoxItem.Tap += Item_OnTap; + + Children.Add(listBoxItem); + + View.Width = panelWidth; + } + + private double _fixedHeight; + + public override double FixedHeight + { + get { return _fixedHeight; } + set { _fixedHeight = value; } + } + } + + public class CheckDialogTypeConverter : IValueConverter + { + public string Type { get; set; } + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null || value.GetType() != typeof(DialogsViewModel)) + { + return value; + } + + return DependencyProperty.UnsetValue; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Dialogs/SecretDialogDetailsView.xaml b/TelegramClient.WP8/Views/Dialogs/SecretDialogDetailsView.xaml new file mode 100755 index 0000000..fa576f8 --- /dev/null +++ b/TelegramClient.WP8/Views/Dialogs/SecretDialogDetailsView.xaml @@ -0,0 +1,345 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Dialogs/SecretDialogDetailsView.xaml.cs b/TelegramClient.WP8/Views/Dialogs/SecretDialogDetailsView.xaml.cs new file mode 100755 index 0000000..f184e8c --- /dev/null +++ b/TelegramClient.WP8/Views/Dialogs/SecretDialogDetailsView.xaml.cs @@ -0,0 +1,2173 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using Caliburn.Micro; +using Microsoft.Devices; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using Telegram.Controls.Extensions; +using Telegram.EmojiPanel; +using Telegram.EmojiPanel.Controls.Emoji; +using TelegramClient.Controls; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.Views.Additional; +using TelegramClient.Views.Controls; +using TelegramClient.Views.Media; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; +using StickerSelectedEventArgs = Telegram.EmojiPanel.Controls.Emoji.StickerSelectedEventArgs; + +namespace TelegramClient.Views.Dialogs +{ + public partial class SecretDialogDetailsView : IDialogDetailsView + { + public SecretDialogDetailsViewModel ViewModel + { + get { return DataContext as SecretDialogDetailsViewModel; } + } + + public void MoveCurretToEnd() + { + if (FocusManager.GetFocusedElement() != InputMessage) return; + + InputMessage.SelectionStart = InputMessage.Text.Length; + InputMessage.SelectionLength = 0; + } + + private readonly Stopwatch _timer; + + #region ApplicationBar + + private bool _firstRun = true; + + private readonly MenuItem _callButton = new MenuItem + { + Header = AppResources.Call + }; + + private readonly MenuItem _manageButton = new MenuItem + { + Header = AppResources.Select + }; + + private void BuildLocalizedAppBar() + { + if (!_firstRun) return; + _firstRun = false; + + ApplicationBar = new ApplicationBar(); + ApplicationBar.Opacity = 0.99; + + ContextMenu.Items.Add(_callButton); + ContextMenu.Items.Add(_manageButton); + + ApplicationBar.IsVisible = false; //ViewModel.IsApplicationBarVisible && !ViewModel.IsChooseAttachmentOpen; + } + #endregion + + private EmojiControl _emojiKeyboard; + + private TranslateTransform _frameTransform; + + public static readonly DependencyProperty RootFrameTransformProperty = DependencyProperty.Register( + "RootFrameTransformProperty", typeof(double), typeof(SecretDialogDetailsView), new PropertyMetadata(OnRootFrameTransformChanged)); + + private static void OnRootFrameTransformChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var view = d as SecretDialogDetailsView; + if (view != null) + { + view._frameTransform.Y = 0; + } + } + + public double RootFrameTransform + { + get { return (double)GetValue(RootFrameTransformProperty); } + set { SetValue(RootFrameTransformProperty, value); } + } + + private void SetRootFrameBinding() + { + var frame = (Frame)Application.Current.RootVisual; + _frameTransform = ((TranslateTransform)((TransformGroup)frame.RenderTransform).Children[0]); + var binding = new Binding("Y") + { + Source = _frameTransform + }; + SetBinding(RootFrameTransformProperty, binding); + } + + private void RemoveRootFrameBinding() + { + ClearValue(RootFrameTransformProperty); + } + + private void CloseEmojiPlaceholder() + { + InputMessage.ClosePlaceholder(); + + if (_emojiKeyboard != null) + { + _emojiKeyboard.ClosePreview(); + _emojiKeyboard.ReloadStickerSprites(); + } + } + + private void OpenCommandsPlaceholder() + { + + } + + private void CloseCommandsPlaceholder() + { + + } + + private TLAllStickers _allStickers; + + private object _previousFocusedElement; + + private object _focusedElement; + + public SecretDialogDetailsView() + { + _timer = System.Diagnostics.Stopwatch.StartNew(); + + InitializeComponent(); + + CaptionBorder.Background = ShellView.CaptionBrush; + + //Full HD + OptimizeFullHD(); + + _callButton.Click += (sender, args) => ViewModel.Call(); + _manageButton.Click += (sender, args) => ViewModel.IsSelectionEnabled = true; + GotFocus += (sender, args) => + { + System.Diagnostics.Debug.WriteLine(args.OriginalSource); + _previousFocusedElement = _focusedElement; + _focusedElement = args.OriginalSource; + }; + + Loaded += InitializeMTProtoService; + + Loaded += OnLoaded; + Unloaded += OnUnloaded; + } + + private void InitializeMTProtoService(object sender, RoutedEventArgs e) + { + Loaded -= InitializeMTProtoService; + + var mtProtoService = IoC.Get(); + mtProtoService.StartInitialize(); + } + + private void OnSmileButtonClick() + { + if (_emojiKeyboard == null) + { + _emojiKeyboard = EmojiControl.GetInstance(); + + _emojiKeyboard.SetGroupStickers(null, null); + + _allStickers = _allStickers ?? IoC.Get().GetAllStickers(); + var isStickersPanelVisible = true; + //var allStickers = _allStickers as TLAllStickers43; + //if (allStickers != null && allStickers.ShowStickersTab != null) + //{ + // isStickersPanelVisible = allStickers.ShowStickersTab.Value; + //} + _emojiKeyboard.BindTextBox(InputMessage.InnerTextBox, isStickersPanelVisible); + _emojiKeyboard.StickerSelected += OnStickerSelected; + _emojiKeyboard.StickerSetAdded += OnStickerSetAdded; + _emojiKeyboard.SettingsButtonClick += OnSettingsButtonClick; + InputMessage.EmojiPlaceholder.Content = _emojiKeyboard; + + _emojiKeyboard.IsOpen = true; + + //_emojiKeyboard.SetHeight(InputBox.KeyboardHeight > 0.0 ? InputBox.KeyboardHeight : _emojiKeyboard.Height); + } + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + if (InputMessage.EmojiPlaceholder.Opacity == 0.0) + { + _smileButtonPressed = true; + + InputMessage.OpenPlaceholder(); + + if (_emojiKeyboard != null) + { + _emojiKeyboard.OpenStickerSprites(); + } + } + else + { + InputMessage.InnerTextBox.Focus(); + } + } + else + { + var awaitKeyboardDown = false; + if (InputMessage == FocusManager.GetFocusedElement()) + { + awaitKeyboardDown = true; + MessagesList.Focus(); + } + + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + if (awaitKeyboardDown) + { + Thread.Sleep(400); + } + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + InputMessage.OpenPlaceholder(); + + if (_emojiKeyboard != null) + { + _emojiKeyboard.OpenStickerSprites(); + } + + SetCaptionVisibility(Visibility.Collapsed); + CloseEmptyDialogPlaceholder(); + CloseCommandsPlaceholder(); + }); + }); + } + } + + private void SetCaptionVisibility(Visibility visibility) + { + return; + + DialogPhoto.Visibility = visibility; + Title.Visibility = visibility; + ContextMenuIcon.Visibility = visibility; + CaptionBorder.Height = visibility == Visibility.Visible ? 105.0 : 71.0; + } + + private Binding _emptyPlaceholderVisibilityBinding; + + private void OpenEmptyDialogPlaceholder() + { + RestoreVisibilityBinding(Description, _emptyPlaceholderVisibilityBinding, Visibility.Collapsed); + } + + private void CloseEmptyDialogPlaceholder() + { + _emptyPlaceholderVisibilityBinding = SaveVisibilityBinding(Description); + Description.Visibility = Visibility.Collapsed; + } +#if DEBUG + ~SecretDialogDetailsView() + { + System.Diagnostics.Debug.WriteLine("~SecretDialogDetailsView"); + } +#endif + + private void OptimizeFullHD() + { + //var appBar = new ApplicationBar(); + //var appBarDefaultSize = appBar.DefaultSize; + + //WaitingBar.Height = appBarDefaultSize; + } + + private void OnViewModelScrollToBottom(object sender, System.EventArgs e) + { + if (ViewModel.Items.Count > 0) + { + MessagesList.ScrollToItem(ViewModel.Items[0]); + } + } + + private void OnViewModelScrollTo(object sender, ScrollToEventArgs e) + { + if (ViewModel.Items.Count > 0) + { + MessagesList.ScrollToItem(e.DecryptedMessage); + } + } + private TextBlock _selectionCaption; + + private void SwitchToSelectionMode() + { + InputMessage.SwitchToSelectionMode(); + + MessagesList.Focus(); + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + CloseCommandsPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + + if (_selectionCaption == null) + { + _selectionCaption = new TextBlock + { + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top, + Margin = new Thickness(18.0, 52.0, 18.0, 21.0), + Foreground = new SolidColorBrush(Colors.White), + RenderTransform = new TranslateTransform(), + Style = (Style)Application.Current.Resources["ApplicationTitleStyle"] + }; + LayoutRoot.Children.Add(_selectionCaption); + } + + CaptionGrid.RenderTransform = new TranslateTransform(); + + var storyboard = new Storyboard(); + + var transformAnimaion2 = new DoubleAnimation { From = 0.0, To = -72.0, Duration = TimeSpan.FromSeconds(0.2), EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 6.0 } }; + Storyboard.SetTarget(transformAnimaion2, CaptionGrid); + Storyboard.SetTargetProperty(transformAnimaion2, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(transformAnimaion2); + + var opacityAnimaion2 = new DoubleAnimation { From = 1.0, To = 0.0, Duration = TimeSpan.FromSeconds(0.2) }; + Storyboard.SetTarget(opacityAnimaion2, CaptionGrid); + Storyboard.SetTargetProperty(opacityAnimaion2, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityAnimaion2); + + var opacityAnimaion = new DoubleAnimation { From = 0.0, To = 1.0, Duration = TimeSpan.FromSeconds(0.2) }; + Storyboard.SetTarget(opacityAnimaion, _selectionCaption); + Storyboard.SetTargetProperty(opacityAnimaion, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityAnimaion); + + storyboard.Begin(); + storyboard.Completed += (o, e) => + { + //((TranslateTransform)CaptionGrid.RenderTransform).Y = 0.0; + //CaptionGrid.Opacity = 1.0; + //DialogPhoto.Visibility = Visibility.Collapsed; + //Caption.Visibility = Visibility.Collapsed; + //ContextMenuIcon.Visibility = Visibility.Collapsed; + }; + + //DialogPhoto.Visibility = Visibility.Collapsed; + //Caption.Visibility = Visibility.Collapsed; + //ContextMenuIcon.Visibility = Visibility.Collapsed; + var count = SecretDialogDetailsViewModel.UngroupEnumerator(ViewModel.Items).Count(x => x.IsSelected); + var noneTTLCount = ViewModel.Items.Count(x => x.IsSelected); + + _selectionCaption.Text = string.Format(count == 1 ? AppResources.ItemsSelectedSingular : AppResources.ItemsSelectedPlural, count).ToUpperInvariant(); + _selectionCaption.Visibility = Visibility.Visible; + + ApplicationBar.Buttons.Clear(); + Execute.BeginOnUIThread(() => + { + InputMessage.IsDeleteActionVisible = true; + + InputMessage.IsGroupActionEnabled = new Tuple(count > 0, count > 0 && noneTTLCount == count); + ApplicationBar.IsVisible = false; + }); + } + + private void SwitchToNonSelectionMode() + { + InputMessage.SwitchToNormalMode(); + + InputMessage.MuteButtonVisibility = GetMuteButtonVisibility(); + + var storyboard = new Storyboard(); + + var transformAnimaion2 = new DoubleAnimation { From = -72.0, To = 0.0, Duration = TimeSpan.FromSeconds(0.2), EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } }; + Storyboard.SetTarget(transformAnimaion2, CaptionGrid); + Storyboard.SetTargetProperty(transformAnimaion2, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(transformAnimaion2); + + var opacityAnimaion2 = new DoubleAnimation { From = 0.0, To = 1.0, Duration = TimeSpan.FromSeconds(0.2) }; + Storyboard.SetTarget(opacityAnimaion2, CaptionGrid); + Storyboard.SetTargetProperty(opacityAnimaion2, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityAnimaion2); + + var opacityAnimaion = new DoubleAnimation { From = 1.0, To = 0.0, Duration = TimeSpan.FromSeconds(0.2) }; + Storyboard.SetTarget(opacityAnimaion, _selectionCaption); + Storyboard.SetTargetProperty(opacityAnimaion, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityAnimaion); + + storyboard.Begin(); + storyboard.Completed += (o, e) => + { + _selectionCaption.Opacity = 1.0; + _selectionCaption.Visibility = Visibility.Collapsed; + }; + + DialogPhoto.Visibility = Visibility.Visible; + Caption.Visibility = Visibility.Visible; + ContextMenuIcon.Visibility = Visibility.Visible; + + ApplicationBar.Buttons.Clear(); + ApplicationBar.IsVisible = false; + } + + private Visibility GetMuteButtonVisibility() + { + return Visibility.Collapsed; + } + + private void SwitchToNormalMode() + { + InputMessage.SwitchToNormalMode(); + } + + public static readonly DependencyProperty StopwatchProperty = + DependencyProperty.Register("Stopwatch", typeof(string), typeof(SecretDialogDetailsView), new PropertyMetadata(default(string))); + + public string Stopwatch + { + get { return (string)GetValue(StopwatchProperty); } + set { SetValue(StopwatchProperty, value); } + } + + private void OnLoaded(object sender, RoutedEventArgs routedEventArgs) + { + SetRootFrameBinding(); + + InputMessage.AudioRecorded += OnAudioRecorded; + InputMessage.RecordStarted += OnRecordStarted; + InputMessage.RecordCanceled += OnRecordCanceled; + + ViewModel.PropertyChanged += OnViewModelPropertyChanged; + ViewModel.ScrollToBottom += OnViewModelScrollToBottom; + ViewModel.ScrollTo += OnViewModelScrollTo; + + GifPlayerControl.MediaStateChanged += OnGifPlayerControlMediaStateChanged; + + if (ViewModel.MultiImageEditor != null) + { + ViewModel.MultiImageEditor.PropertyChanged += OnMultiImageEditorPropertyChanged; + } + if (ViewModel.LocationPicker != null) + { + ViewModel.LocationPicker.PropertyChanged += OnLocationPickerPropertyChanged; + } + + if (ViewModel.IsApplicationBarVisible) + { + BuildLocalizedAppBar(); + } + else if (ApplicationBar != null) + { + ApplicationBar.IsVisible = false;//ViewModel.IsApplicationBarVisible && !ViewModel.IsChooseAttachmentOpen; + } + + RunAnimation(); + Stopwatch = _timer.Elapsed.ToString(); + } + + private void OnGifPlayerControlMediaStateChanged(object sender, MediaStateChangedEventArgs args) + { + switch (args.State) + { + case GifPlayerControlState.Opening: + + break; + case GifPlayerControlState.Opened: + + break; + case GifPlayerControlState.Failed: + break; + case GifPlayerControlState.Paused: + break; + case GifPlayerControlState.Resumed: + break; + case GifPlayerControlState.Ended: + ResumeChatPlayers(); + break; + } + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + RemoveRootFrameBinding(); + + InputMessage.AudioRecorded -= OnAudioRecorded; + InputMessage.RecordStarted -= OnRecordStarted; + InputMessage.RecordCanceled -= OnRecordCanceled; + + ViewModel.PropertyChanged -= OnViewModelPropertyChanged; + ViewModel.ScrollToBottom -= OnViewModelScrollToBottom; + ViewModel.ScrollTo -= OnViewModelScrollTo; + + GifPlayerControl.MediaStateChanged -= OnGifPlayerControlMediaStateChanged; + + if (ViewModel.MultiImageEditor != null) + { + ViewModel.MultiImageEditor.PropertyChanged -= OnMultiImageEditorPropertyChanged; + } + if (ViewModel.LocationPicker != null) + { + ViewModel.LocationPicker.PropertyChanged -= OnLocationPickerPropertyChanged; + } + } + + private void OnMultiImageEditorPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.MultiImageEditor.IsOpen)) + { + MessagesList.IsHitTestVisible = IsItemsHitTestVisible(); + + if (ViewModel.MultiImageEditor.IsOpen) + { + _prevApplicationBar = ApplicationBar; + ApplicationBar = ((MultiImageEditorView)MultiImageEditor.Content).ApplicationBar; + } + else + { + if (_prevApplicationBar != null) + { + ApplicationBar = _prevApplicationBar; + } + } + } + } + + private void OnLocationPickerPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.LocationPicker.IsOpen)) + { + MessagesList.IsHitTestVisible = IsItemsHitTestVisible(); + } + } + + private bool IsItemsHitTestVisible() + { + return (ViewModel.ChooseAttachment == null || !ViewModel.ChooseAttachment.IsOpen) + && (ViewModel.ImageViewer == null || !ViewModel.ImageViewer.IsOpen) + && (ViewModel.MultiImageEditor == null || !ViewModel.MultiImageEditor.IsOpen) + //&& (ViewModel.AnimatedImageViewer == null || !ViewModel.AnimatedImageViewer.IsOpen) + //&& (ViewModel.VideoEditor == null || !ViewModel.VideoEditor.IsOpen) + && (ViewModel.LocationPicker == null || !ViewModel.LocationPicker.IsOpen); + } + + private Binding _visibilityBinding; + + private double _previousAudioRecorderMinHeight; + + private static Binding SaveVisibilityBinding(FrameworkElement element) + { + var visibilityExpression = element.GetBindingExpression(VisibilityProperty); + if (visibilityExpression != null) + { + return visibilityExpression.ParentBinding; + } + + return null; + } + + private static void RestoreVisibilityBinding(FrameworkElement element, Binding binding, Visibility defaultValue) + { + if (binding != null) + { + element.SetBinding(VisibilityProperty, binding); + } + else + { + //element.Visibility = defaultValue; + } + } + + private void OnRecordCanceled(object sender, System.EventArgs e) + { + + } + + private void OnRecordStarted(object sender, System.EventArgs e) + { + + } + + private void OnAudioRecorded(object sender, AudioEventArgs e) + { + var viewModel = ViewModel; + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => viewModel.SendAudio(e)); + } + + private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.IsGroupActionEnabled)) + { + var count = SecretDialogDetailsViewModel.UngroupEnumerator(ViewModel.Items).Count(x => x.IsSelected); + var noneTTLCount = ViewModel.Items.Count(x => x.IsSelected); + if (_selectionCaption != null) + { + _selectionCaption.Text = string.Format(count == 1 ? AppResources.ItemsSelectedSingular : AppResources.ItemsSelectedPlural, count).ToUpperInvariant(); + } + + InputMessage.IsGroupActionEnabled = new Tuple(count > 0, count > 0 && noneTTLCount == count); + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.Reply)) + { + if (ViewModel.Reply != null) + { + if (ViewModel.Reply is TLDecryptedMessagesContainter) + { + return; + } + + InputMessage.Focus(); + } + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.IsApplicationBarVisible) + && ViewModel.IsApplicationBarVisible) + { + BuildLocalizedAppBar(); + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.IsSelectionEnabled)) + { + if (ViewModel.IsSelectionEnabled) + { + SwitchToSelectionMode(); + } + else + { + SwitchToNonSelectionMode(); + } + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.ChooseAttachment) + && ViewModel.ChooseAttachment != null) + { + ViewModel.ChooseAttachment.PropertyChanged += OnChooseAttachmentPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.ImageViewer) + && ViewModel.ImageViewer != null) + { + ViewModel.ImageViewer.PropertyChanged += OnImageViewerPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.MultiImageEditor) + && ViewModel.MultiImageEditor != null) + { + ViewModel.MultiImageEditor.PropertyChanged += OnMultiImageEditorPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.LocationPicker) + && ViewModel.LocationPicker != null) + { + ViewModel.LocationPicker.PropertyChanged += OnLocationPickerPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.IsApplicationBarVisible)) + { + if (ApplicationBar != null) + { + ApplicationBar.IsVisible = false;//ViewModel.IsApplicationBarVisible && !ViewModel.IsChooseAttachmentOpen; + } + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.IsAppBarCommandVisible)) + { + if (ViewModel.IsAppBarCommandVisible) + { + InputMessage_OnLostFocus(this, null); + if (ViewModel.ChooseAttachment != null && ViewModel.ChooseAttachment.IsOpen) + { + ViewModel.ChooseAttachment.Close(); + ApplicationBar.IsVisible = false; + } + _prevApplicationBar = null; + } + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.StartGifPlayers)) + { + Deployment.Current.Dispatcher.BeginInvoke(() => + { + Items_OnManipulationStateChanged(this, System.EventArgs.Empty); + }); + } + } + + private void Items_OnBegin(object sender, System.EventArgs e) + { + if (MessagesList.Viewport.Bounds.Y == 0.0) return; + + HideScrollToBottomButton(); + } + + public bool IsScrollToBottomButtonVisible + { + get { return ScrollButton.Visibility == Visibility.Visible; } + } + + public void HideMentionButton() + { + + } + + public void HideScrollToBottomButton() + { + if (ScrollButton.Visibility == Visibility.Collapsed) return; + + //ScrollToBottomButton.Visibility = Visibility.Collapsed; + //return; + + var storyboard = new Storyboard(); + var continuumScrollToBottomButton = new DoubleAnimationUsingKeyFrames(); + continuumScrollToBottomButton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 0.0 }); + continuumScrollToBottomButton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 150.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(continuumScrollToBottomButton, ScrollButton); + Storyboard.SetTargetProperty(continuumScrollToBottomButton, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(continuumScrollToBottomButton); + + var continuumLayoutRootOpacity = new DoubleAnimation + { + From = 1.0, + To = 0.0, + Duration = TimeSpan.FromSeconds(0.25), + EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } + }; + Storyboard.SetTarget(continuumLayoutRootOpacity, ScrollButton); + Storyboard.SetTargetProperty(continuumLayoutRootOpacity, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(continuumLayoutRootOpacity); + storyboard.Completed += (sender, args) => + { + ScrollButton.Visibility = Visibility.Collapsed; + }; + + storyboard.Begin(); + //Telegram.Api.Helpers.Execute.BeginOnUIThread(() => storyboard.Begin()); + } + + public void ShowMentionButton() + { + + } + + public void ShowScrollToBottomButton() + { + if (ScrollButton.Visibility == Visibility.Visible) return; + + ScrollButton.Visibility = Visibility.Visible; + ScrollButton.Opacity = 0.0; + + var storyboard = new Storyboard(); + var continuumScrollToBottomButton = new DoubleAnimationUsingKeyFrames(); + continuumScrollToBottomButton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 150.0 }); + continuumScrollToBottomButton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(continuumScrollToBottomButton, ScrollButton); + Storyboard.SetTargetProperty(continuumScrollToBottomButton, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(continuumScrollToBottomButton); + + var continuumLayoutRootOpacity = new DoubleAnimation + { + From = 0.0, + To = 1.0, + Duration = TimeSpan.FromSeconds(0.25), + EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } + }; + Storyboard.SetTarget(continuumLayoutRootOpacity, ScrollButton); + Storyboard.SetTargetProperty(continuumLayoutRootOpacity, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(continuumLayoutRootOpacity); + + storyboard.Begin(); + //Telegram.Api.Helpers.Execute.BeginOnUIThread(() => storyboard.Begin()); + } + + private IApplicationBar _prevApplicationBar; + + private void OnImageViewerPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.ImageViewer.IsOpen)) + { + MessagesList.IsHitTestVisible = !ViewModel.ChooseAttachment.IsOpen && (ViewModel.ImageViewer == null || !ViewModel.ImageViewer.IsOpen); + + if (ViewModel.ImageViewer != null + && ViewModel.ImageViewer.IsOpen) + { + _prevApplicationBar = ApplicationBar; + ApplicationBar = ((DecryptedImageViewerView)ImageViewer.Content).ApplicationBar; + } + else + { + if (_prevApplicationBar != null) + { + ApplicationBar = _prevApplicationBar; + } + } + } + } + + private void OnChooseAttachmentPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.ChooseAttachment.IsOpen)) + { + MessagesList.IsHitTestVisible = !ViewModel.ChooseAttachment.IsOpen && (ViewModel.ImageViewer == null || !ViewModel.ImageViewer.IsOpen); + } + } + + private bool _isForwardInAnimation; + private bool _isBackwardInAnimation; + private bool _fromExternalUri; + private readonly Uri _externalUri = new Uri(@"app://external/"); + + public void OpenBitmapCache() + { + MessagesCache.Visibility = Visibility.Visible; + MessagesList.Visibility = Visibility.Collapsed; + } + + public void CloseBitmapCache() + { + MessagesCache.Visibility = Visibility.Collapsed; + MessagesList.Visibility = Visibility.Visible; + } + + private void RunAnimation() + { + if (_isForwardInAnimation) + { + _isForwardInAnimation = false; + + if (ViewModel.Chat.Bitmap != null) + { + MessagesList.Visibility = Visibility.Collapsed; + } + + var storyboard = new Storyboard(); + if (ViewModel != null + && ViewModel.StateService.AnimateTitle) + { + ViewModel.StateService.AnimateTitle = false; + + var continuumElementX = new DoubleAnimationUsingKeyFrames(); + continuumElementX.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 130.0 }); + continuumElementX.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(continuumElementX, Title); + Storyboard.SetTargetProperty(continuumElementX, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateX)")); + storyboard.Children.Add(continuumElementX); + + var continuumElementY = new DoubleAnimationUsingKeyFrames(); + continuumElementY.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = -40.0 }); + continuumElementY.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0 }); + Storyboard.SetTarget(continuumElementY, Title); + Storyboard.SetTargetProperty(continuumElementY, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(continuumElementY); + } + + var continuumLayoutRootY = new DoubleAnimationUsingKeyFrames(); + continuumLayoutRootY.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 150.0 }); + continuumLayoutRootY.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(continuumLayoutRootY, LayoutRoot); + Storyboard.SetTargetProperty(continuumLayoutRootY, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(continuumLayoutRootY); + + var continuumLayoutRootOpacity = new DoubleAnimation { From = 0.0, To = 1.0, Duration = TimeSpan.FromSeconds(0.25), EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } }; + Storyboard.SetTarget(continuumLayoutRootOpacity, LayoutRoot); + Storyboard.SetTargetProperty(continuumLayoutRootOpacity, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(continuumLayoutRootOpacity); + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + LayoutRoot.Opacity = 1.0; + storyboard.Completed += (o, e) => + { + + //Items.Opacity = 0.0; + MessagesList.Visibility = Visibility.Visible; + MessagesCache.Visibility = Visibility.Collapsed; + ViewModel.OnForwardInAnimationComplete(); + Telegram.Api.Helpers.Execute.BeginOnUIThread(TimeSpan.FromSeconds(1.0), () => + { + Items_OnManipulationStateChanged(this, System.EventArgs.Empty); + }); + //Deployment.Current.Dispatcher.BeginInvoke(() => CloseCacheStoryboard.Begin()); + }; + storyboard.Begin(); + }); + } + else if (_isBackwardOutAnimation) + { + _isBackwardOutAnimation = false; + + var storyboard = new Storyboard(); + + var translateAnimation = new DoubleAnimationUsingKeyFrames(); + translateAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.00), Value = 0.0 }); + translateAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 150.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 6.0 } }); + Storyboard.SetTarget(translateAnimation, LayoutRoot); + Storyboard.SetTargetProperty(translateAnimation, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateAnimation); + + var opacityAnimation = new DoubleAnimationUsingKeyFrames(); + opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.00), Value = 1.0 }); + opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 6.0 } }); + Storyboard.SetTarget(opacityAnimation, LayoutRoot); + Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("(UIElement.Opacity)")); + storyboard.Children.Add(opacityAnimation); + + storyboard.Begin(); + } + else if (_isBackwardInAnimation) + { + _isBackwardInAnimation = false; + + var storyboard = TelegramTurnstileAnimations.GetAnimation(LayoutRoot, TurnstileTransitionMode.BackwardIn); + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + LayoutRoot.Opacity = 1.0; + MessagesCache.Visibility = Visibility.Visible; + MessagesList.Visibility = Visibility.Collapsed; + storyboard.Completed += (o, e) => + { + MessagesCache.Visibility = Visibility.Collapsed; + MessagesList.Visibility = Visibility.Visible; + ViewModel.OnBackwardInAnimationComplete(); + + Deployment.Current.Dispatcher.BeginInvoke(() => + { + StartGifPlayers(); + }); + }; + storyboard.Begin(); + }); + } + } + + private void StartGifPlayers() + { + Items_OnManipulationStateChanged(this, System.EventArgs.Empty); + var inlineBotResultsView = InlineBotResults.FindChildOfType(); + if (inlineBotResultsView != null) + { + inlineBotResultsView.StartActivePlayers(); + } + } + + private void OpenPeerDetails_OnTap(object sender, GestureEventArgs args) + { + //if (ViewModel.With is TLChatForbidden) + //{ + // return; + //} + + //if (CommandsControl.Visibility == Visibility.Visible) + //{ + // OpenEmptyDialogPlaceholder(); + // CloseCommandsPlaceholder(); + // SetCaptionVisibility(Visibility.Visible); + //} + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + } + + StopPlayersAndCreateBitmapCache(() => ViewModel.OpenPeerDetails()); + } + + public void StopPlayersAndCreateBitmapCache(System.Action callback = null) + { + GifPlayerControl.StopActivePlayers(); + GifPlayerControl.StopInlineBotActivePlayers(); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + CreateBitmapCache(); + MessagesCache.Visibility = Visibility.Visible; + MessagesList.Visibility = Visibility.Collapsed; + + callback.SafeInvoke(); + }); + } + + public void CreateBitmapCache(System.Action callback = null) + { + try + { + if (MessagesList.Visibility == Visibility.Visible) + { + // var stopwatch = Stopwatch.StartNew(); + var writeableBitmap = new WriteableBitmap(MessagesList, null); + //var elapsed1 = stopwatch.Elapsed; + ViewModel.Chat.SetBitmap(writeableBitmap); + //var elapsed2 = stopwatch.Elapsed; + //MessageBox.Show("create bitmap render=" + elapsed1 + " set=" + elapsed2); + } + } + catch (Exception ex) + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("WritableBitmap exception " + ex); + } + + callback.SafeInvoke(); + } + + private bool _suppressCancel = true; + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + ViewModel.OnNavigatedTo(); + //MediaControl.Content = MessagePlayerControl.Player; + + // этот код выполняется до того, как происходит отрисовка экрана + // нельзя ставить сюда долгие операции + if (e.NavigationMode == NavigationMode.New) + { + LayoutRoot.Opacity = 0.0; + _isForwardInAnimation = true; + } + else if (e.NavigationMode == NavigationMode.Back) + { + if (!_fromExternalUri) + { + LayoutRoot.Opacity = 0.0; + _isBackwardInAnimation = true; + } + else + { + ViewModel.OnBackwardInAnimationComplete(); + Deployment.Current.Dispatcher.BeginInvoke(() => + { + StartGifPlayers(); + }); + } + _fromExternalUri = false; + } + else if (e.NavigationMode == NavigationMode.Reset) + { + if (_fromExternalUri) + { + Deployment.Current.Dispatcher.BeginInvoke(() => + { + StartGifPlayers(); + }); + } + } + + base.OnNavigatedTo(e); + } + + private void OnStickerSetAdded(object sender, StickerSetAddedEventArgs e) + { + if (e.Set == null) return; + } + + private void OnStickerSelected(object sender, StickerSelectedEventArgs e) + { + if (e.Sticker == null) return; + + var document22 = e.Sticker.Document as TLDocument22; + if (document22 == null) return; + + ViewModel.SendSticker(document22); + } + + private void OnSettingsButtonClick(object sender, System.EventArgs eventArgs) + { + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + } + + // чтобы клавиатура успела опуститься + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + CreateBitmapCache(); + MessagesCache.Visibility = Visibility.Visible; + MessagesList.Visibility = Visibility.Collapsed; + + ViewModel.OpenStickerSettings(); + }); + } + + private bool _isBackwardOutAnimation; + private bool _isForwardOutAnimation; + + protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) + { + GifPlayerControl.StopActivePlayers(); + GifPlayerControl.StopInlineBotActivePlayers(); + if (_emojiKeyboard != null) + { + // Destroy EmojiControl + _emojiKeyboard.IsOpen = false; + _emojiKeyboard.UnbindTextBox(); + _emojiKeyboard.StickerSelected -= OnStickerSelected; + _emojiKeyboard.StickerSetAdded -= OnStickerSetAdded; + _emojiKeyboard.SettingsButtonClick -= OnSettingsButtonClick; + InputMessage.EmojiPlaceholder.Content = null; // Remove from view + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + _emojiKeyboard = null; + } + + var multiImageEditorView = MultiImageEditor.Content as MultiImageEditorView; + if (multiImageEditorView != null) + { + multiImageEditorView.ClosePreview(); + } + + if (e.Uri.OriginalString.EndsWith("EditVideoView.xaml") + || e.Uri.OriginalString.EndsWith("MapView.xaml") + || e.Uri.OriginalString.EndsWith("ContactView.xaml") + || e.Uri.OriginalString.EndsWith("ChatView.xaml") + || e.Uri.OriginalString.EndsWith("ProfilePhotoViewerView.xaml") + || e.Uri.OriginalString.EndsWith("SearchShellView.xaml") + || e.Uri.OriginalString.EndsWith("ChooseDialogView.xaml") + || e.Uri.OriginalString.EndsWith("StickersView.xaml") + ) + { + CreateBitmapCache(); + MessagesList.Visibility = Visibility.Collapsed; + MessagesCache.Visibility = Visibility.Visible; + //e.Cancel = true; + //Deployment.Current.Dispatcher.BeginInvoke(() => NavigationService.Navigate(e.Uri)); + //return; + } + else + { + //TransitionService.SetNavigationOutTransition(Self, OutTransition); + } + + base.OnNavigatingFrom(e); + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + ViewModel.OnNavigatedFrom(); + + MessagePlayerControl.Stop(); + GifPlayerControl.StopVideo(); + + if (e.Uri == _externalUri) + { + _fromExternalUri = true; + } + else + { + _fromExternalUri = false; + } + + base.OnNavigatedFrom(e); + } + + protected override void OnBackKeyPress(CancelEventArgs e) + { + if (!NavigationService.BackStack.Any()) + { + e.Cancel = true; + ViewModel.NavigateToShellViewModel(); + + return; + } + + base.OnBackKeyPress(e); + } + + private void SecretDialogDetailsView_OnBackKeyPress(object sender, CancelEventArgs e) + { + var popups = VisualTreeHelper.GetOpenPopups().ToList(); + var popup = popups.FirstOrDefault(); + if (popup != null) + { + e.Cancel = true; + + var multiplePhotoPicker = popup.Child as OpenPhotoPicker; + if (multiplePhotoPicker != null) + { + multiplePhotoPicker.TryClose(); + } + + return; + } + + if (ViewModel.ImageViewer != null + && ViewModel.ImageViewer.IsOpen) + { + ViewModel.ImageViewer.CloseViewer(); + e.Cancel = true; + + return; + } + + if (ViewModel.MultiImageEditor != null + && ViewModel.MultiImageEditor.IsOpen) + { + ViewModel.MultiImageEditor.CloseEditor(); + e.Cancel = true; + + return; + } + + if (ViewModel.LocationPicker != null + && ViewModel.LocationPicker.IsOpen) + { + ViewModel.LocationPicker.CloseEditor(); + e.Cancel = true; + + return; + } + + if (ViewModel.IsSelectionEnabled) + { + ViewModel.IsSelectionEnabled = false; + ApplicationBar.IsVisible = false;//!ViewModel.IsAppBarCommandVisible; + e.Cancel = true; + + return; + } + + if (_emojiKeyboard != null && _emojiKeyboard.IsPreviewMenuOpened) + { + _emojiKeyboard.ClosePreviewMenu(); + e.Cancel = true; + + return; + } + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + SelfView.Focus(); + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + CloseCommandsPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + e.Cancel = true; + + return; + } + + if (ViewModel.ChooseAttachment != null + && ViewModel.ChooseAttachment.IsOpen) + { + e.Cancel = true; + ViewModel.ChooseAttachment.Close(); + ResumeChatPlayers(); + + return; + } + + if (_lastContextMenu != null && _lastContextMenu.IsOpen) + { + _lastContextMenu.IsOpen = false; + e.Cancel = true; + + return; + } + + _isBackwardOutAnimation = true; + + try + { + if (MessagesList.Visibility == Visibility.Visible) + { + var writeableBitmap = new WriteableBitmap(MessagesList, null); + ViewModel.Chat.SetBitmap(writeableBitmap); + } + } + catch (Exception ex) + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("WritableBitmap exception " + ex); + } + MessagesCache.Visibility = Visibility.Visible; + MessagesList.Visibility = Visibility.Collapsed; + + RunAnimation(); + } + + private void InputMessage_OnGotFocus(object sender, RoutedEventArgs e) + { + SetCaptionVisibility(Visibility.Collapsed); + CloseCommandsPlaceholder(); + CloseEmptyDialogPlaceholder(); + + PauseChatPlayers(); + } + + private bool _smileButtonPressed; + + private ContextMenu _lastContextMenu; + + private void ContextMenu_OnOpened(object sender, RoutedEventArgs e) + { + var menu = (ContextMenu)sender; + var owner = (FrameworkElement)menu.Owner; + + if (owner.DataContext != menu.DataContext) + { + menu.DataContext = owner.DataContext; + } + + if (_innerMessage != null && _innerMessage != menu.DataContext) + { + menu.DataContext = _innerMessage; + } + + var serviceMessage = menu.DataContext as TLDecryptedMessageService; + if (serviceMessage != null) + { + menu.IsOpen = false; + return; + } + + _lastContextMenu = sender as ContextMenu; + } + + private void InputMessage_OnLostFocus(object sender, RoutedEventArgs e) + { + if (!_smileButtonPressed) + { + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + CloseEmojiPlaceholder(); + } + } + _smileButtonPressed = false; + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Collapsed) + { + SetCaptionVisibility(Visibility.Visible); + } + + OpenEmptyDialogPlaceholder(); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + ResumeChatPlayers(); + }); + } + + private void UIElement_OnHold(object sender, GestureEventArgs e) + { + + } + + private void ScrollButton_OnClick(object sender, RoutedEventArgs e) + { + HideScrollToBottomButton(); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + if (ViewModel.Items.Count > 0) + { + ViewModel.ProcessScroll(); + } + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + Items_OnManipulationStateChanged(sender, System.EventArgs.Empty); + }); + }); + } + + private void InputMessage_OnKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + if (ViewModel.StateService.SendByEnter) + { + ViewModel.Send(); + e.Handled = true; + } + } + else if (e.Key == Key.Space) + { + var text = InputMessage.Text.Trim(); + if (BrowserNavigationService.IsValidUsername(text)) + { + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => ViewModel.ResolveUsername(text)); + } + } + } + + private void NavigationOutTransition_OnEndTransition(object sender, RoutedEventArgs e) + { + //Items.Visibility = Visibility.Collapsed; + } + + private void SecretPhotoPlaceholder_OnElapsed(object sender, System.EventArgs e) + { + return; + + var element = sender as FrameworkElement; + if (element != null) + { + var decryptedMessage = element.DataContext as TLDecryptedMessage; + if (decryptedMessage != null) + { + var decryptedMessageMediaPhoto = decryptedMessage.Media as TLDecryptedMessageMediaPhoto; + if (decryptedMessageMediaPhoto != null) + { + ViewModel.DeleteMessage(false, decryptedMessageMediaPhoto); + //SecretImageViewer.Visibility = Visibility.Collapsed; + //ApplicationBar.IsVisible = false; + } + } + } + } + + private void SecretPhotoPlaceholder_OnStartTimer(object sender, System.EventArgs e) + { + return; + + var element = sender as FrameworkElement; + if (element != null) + { + var decryptedMessage = element.DataContext as TLDecryptedMessage; + if (decryptedMessage != null) + { + var decryptedMessageMediaPhoto = decryptedMessage.Media as TLDecryptedMessageMediaPhoto; + if (decryptedMessageMediaPhoto != null) + { + var result = ViewModel.OpenSecretPhoto(decryptedMessageMediaPhoto); + if (result) + { + //SecretImageViewer.Visibility = Visibility.Visible; + //ApplicationBar.IsVisible = false; + } + } + } + } + } + + private void UIElement_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { +// var uielement = sender as FrameworkElement; +// if (uielement != null) +// { +// var decryptedMessage = uielement.DataContext as TLDecryptedMessage17; +// if (decryptedMessage != null) +// { +// var result = ViewModel.OpenSecretPhoto(decryptedMessage); +// if (result) +// { +// SecretImageViewer.Visibility = Visibility.Visible; +// ApplicationBar.IsVisible = false; +// } +// } +// } + } + + private void Items_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + if (ViewModel.SliceLoaded) return; + + ViewModel.LoadNextSlice(); + } + + private Visibility GetAudioRecorderVisibility() + { + if (FocusManager.GetFocusedElement() == InputMessage) + { + return Visibility.Collapsed; + } + + if (InputMessage.Text.Length > 0) + { + return Visibility.Collapsed; + } + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + return Visibility.Collapsed; + } + + //if (ViewModel != null) + //{ + // var chatForbidden = ViewModel.With as TLChatForbidden; + // var chat = ViewModel.With as TLChat; + + // var isForbidden = chatForbidden != null || (chat != null && chat.Left.Value); + // if (isForbidden) + // { + // return Visibility.Collapsed; + // } + //} + + return Visibility.Visible; + } + + private void InputMessage_OnTextChanged(object sender, TextChangedEventArgs e) + { + InputMessage.KeyboardButtonVisibility = GetReplyKeyboardButtonVisibility(); + InputMessage.MuteButtonVisibility = GetMuteButtonVisibility(); + } + + private Visibility GetReplyKeyboardButtonVisibility() + { + return Visibility.Collapsed; + } + + private void MorePanel_OnTap(object sender, GestureEventArgs e) + { + var frameworkElement = sender as FrameworkElement; + if (frameworkElement == null) return; + + var message = frameworkElement.DataContext as TLDecryptedMessage; + if (message == null) return; + + if (InputMessage.EmojiPlaceholder.Visibility == Visibility.Visible) + { + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + } + + // чтобы клавиатура успела опуститься + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + CreateBitmapCache(); + MessagesCache.Visibility = Visibility.Visible; + MessagesList.Visibility = Visibility.Collapsed; + + ViewModel.OpenCropedMessage(message); + }); + } + + private void InlineBotResults_OnTap(object sender, GestureEventArgs e) + { + InputMessage.Focus(); + + var frameworkElement = e.OriginalSource as FrameworkElement; + if (frameworkElement != null) + { + var result = frameworkElement.DataContext as TLBotInlineResultBase; + if (result != null) + { + GifPlayerControl.StopInlineBotActivePlayers(); + ViewModel.SendBotInlineResult(result); + } + } + } + + private void InlineBotResults_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + ViewModel.ContinueInlineBotResults(); + } + + private void StickerHints_OnTap(object sender, GestureEventArgs e) + { + var frameworkElement = e.OriginalSource as FrameworkElement; + if (frameworkElement == null) return; + + var stickerItem = frameworkElement.DataContext as TLStickerItem; + if (stickerItem == null) return; + + var document22 = stickerItem.Document as TLDocument22; + if (document22 == null) return; + + ViewModel.SendSticker(document22); + } + + private void StickerHints_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + ViewModel.ContinueStickerHints(); + } + + private void ContextMenu_OnLoaded(object sender, RoutedEventArgs e) + { + var contextMenu = (ContextMenu) sender; + if (contextMenu != null) + { + var decryptedMessage = contextMenu.DataContext as TLDecryptedMessage; + if (decryptedMessage != null) + { + + } + } + } + + private void ReplyMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem != null) + { + menuItem.Visibility = Visibility.Collapsed; + + var chat = ViewModel.Chat as TLEncryptedChat17; + if (chat != null && chat.Layer.Value >= Constants.MinSecretChatWithRepliesLayer) + { + menuItem.Visibility = Visibility.Visible; + } + } + } + + private void AddToStickers_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem != null) + { + menuItem.Visibility = Visibility.Collapsed; + var decryptedMessage = menuItem.DataContext as TLDecryptedMessage; + if (decryptedMessage != null && decryptedMessage.IsSticker()) + { + var mediaExternalDocument = decryptedMessage.Media as TLDecryptedMessageMediaExternalDocument; + if (mediaExternalDocument != null) + { + var stickerSet = mediaExternalDocument.StickerSet; + if (stickerSet != null && !(stickerSet is TLInputStickerSetEmpty)) + { + var allStickers = IoC.Get().GetAllStickers() as TLAllStickers29; + if (allStickers != null) + { + var set = allStickers.Sets.FirstOrDefault(x => string.Equals(x.ShortName.ToString(), stickerSet.Name.ToString(), StringComparison.Ordinal)); + if (set != null) + { + menuItem.Visibility = Visibility.Collapsed; + menuItem.Header = AppResources.ViewStickers; + } + else + { + menuItem.Visibility = Visibility.Visible; + menuItem.Header = AppResources.AddToStickers; + } + } + } + } + } + } + } + + public void StartChatPlayer(StartGifPlayerEventArgs e) + { + if (MessagesList.ManipulationState != ManipulationState.Idle) return; + if (ViewModel.ChooseAttachment != null && ViewModel.ChooseAttachment.IsOpen) return; + if (MessagePlayerControl.Player != null + && MessagePlayerControl.Player.CurrentState == MediaElementState.Playing + && MessagePlayerControl.Player.Tag is GifPlayerControl) return; + + var settings = ViewModel.StateService.GetChatSettings(); + var newItems = MessagesList.GetItemsInView(); + + foreach (var item in newItems) + { + var message = item.DataContext as TLDecryptedMessage; + if (message != null && message == e.DecryptedMessage && message.IsGif()) + { + var media = message.Media; + if ((media != null && media.AutoPlayGif == true) || (settings != null && settings.AutoPlayGif && media != null && media.AutoPlayGif != false)) + { + var gifPlayer = item.FindChildOfType(); + if (gifPlayer != null) + { + gifPlayer.Start(); + } + return; + } + } + } + } + + public void ResumeChatPlayers() + { + if (MessagesList.ManipulationState != ManipulationState.Idle) return; + if (ViewModel.ChooseAttachment != null && ViewModel.ChooseAttachment.IsOpen) return; + if (MessagePlayerControl.Player != null + && MessagePlayerControl.Player.CurrentState == MediaElementState.Playing + && MessagePlayerControl.Player.Tag is GifPlayerControl) return; + if (FocusManager.GetFocusedElement() == InputMessage.Input) return; + if (ViewModel.InlineBotResults != null && ViewModel.InlineBotResults.Results.Count > 0) return; + + var settings = ViewModel.StateService.GetChatSettings(); + var newItems = MessagesList.GetItemsInView(); + + var activePlayers = new List(); + foreach (var item in newItems) + { + var message = item.DataContext as TLDecryptedMessage; + if (message != null && message.IsGif()) + { + var media = message.Media; + if ((media != null && media.AutoPlayGif == true) || (settings != null && settings.AutoPlayGif && media != null && media.AutoPlayGif != false)) + { + var gifPlayer = item.FindChildOfType(); + if (gifPlayer != null) + { + activePlayers.Add(gifPlayer); + } + } + } + } + + GifPlayerControl.ResumeActivePlayers(activePlayers); + } + + public void PauseChatPlayers() + { + GifPlayerControl.PauseActivePlayers(); + } + + private void Items_OnManipulationStateChanged(object sender, System.EventArgs e) + { + GifPlayerControl.ManipulationState = MessagesList.ManipulationState; + if (MessagesList.ManipulationState == ManipulationState.Idle) + { + ResumeChatPlayers(); + } + else + { + PauseChatPlayers(); + } +#if DEBUG + var count = GifPlayerControl.ActivePlayers.Count; + Debug.Text = string.Format("{0} {1}", count, GifPlayerControl.ActivePlayers.Count); +#endif + } + + private void ViaBot_Tap(object sender, GestureEventArgs e) + { + var frameworkElement = sender as FrameworkElement; + if (frameworkElement == null) return; + + var message = frameworkElement.DataContext as TLDecryptedMessage45; + if (message == null) return; + + var viaBotName = message.ViaBotName; + if (viaBotName == null) return; + + SetInlineBotCommon(viaBotName.ToString()); + } + + public void SetInlineBot(TLUserBase bot) + { + var user = bot as TLUser; + if (user == null || !user.IsInlineBot || user.UserName == null) return; + + SetInlineBotCommon(user.UserName.ToString()); + } + + private void SetInlineBotCommon(string userName) + { + InputMessage.Text = string.Format("@{0} ", userName); + InputMessage.Focus(); + InputMessage.SelectionStart = InputMessage.Text.Length; + InputMessage.SelectionLength = 0; + + var text = InputMessage.Text.Trim(); + if (BrowserNavigationService.IsValidUsername(text)) + { + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => ViewModel.ResolveUsername(text)); + } + } + + private void ContextMenu_OnHold(object sender, GestureEventArgs e) + { + e.Handled = true; + } + + private void ContextMenu_OnTap(object sender, GestureEventArgs e) + { + ContextMenu.IsOpen = true; + } + + private void InputMessage_OnAppBarCommandClick(object sender, System.EventArgs e) + { + ViewModel.DeleteChat(); + } + + private void InputMessage_OnOpenReplyButtonClick(object sender, System.EventArgs e) + { + + } + + private void InputMessage_OnDeleteReplyButtonClick(object sender, System.EventArgs e) + { + ViewModel.DeleteReply(); + } + + private void InputMessage_OnDeleteButtonClick(object sender, System.EventArgs e) + { + ViewModel.DeleteMessages(); + } + + private void InputMessage_OnForwardButtonClick(object sender, System.EventArgs e) + { + + } + + private void InputMessage_OnCancelSelectionButtonClick(object sender, System.EventArgs e) + { + ViewModel.IsSelectionEnabled = false; + } + + private void InputMessage_OnSendClick(object sender, System.EventArgs e) + { + ViewModel.Send(); + } + + private void InputMessage_OnAttachClick(object sender, System.EventArgs e) + { + OpenEmptyDialogPlaceholder(); + CloseEmojiPlaceholder(); + CloseCommandsPlaceholder(); + SetCaptionVisibility(Visibility.Visible); + if (_focusedElement == InputMessage) + { + ChooseAttachment.Focus(); + Telegram.Api.Helpers.Execute.BeginOnUIThread(TimeSpan.FromSeconds(.35), () => ViewModel.Attach()); + } + else + { + ChooseAttachment.Focus(); + ViewModel.Attach(); + } + } + + private void InputMessage_OnMuteButtonClick(object sender, System.EventArgs e) + { + + } + + private void InputMessage_OnKeyboardButtonClick(object sender, System.EventArgs e) + { + + } + + private void InputMessage_OnEmojiClick(object sender, System.EventArgs e) + { + OnSmileButtonClick(); + } + + private void CopyMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + element.Visibility = Visibility.Collapsed; + + var message = element.DataContext as TLDecryptedMessage; + if (message != null) + { + if (!TLString.IsNullOrEmpty(message.Message)) + { + element.Visibility = Visibility.Visible; + return; + } + + var mediaCaption = message.Media as IMediaCaption; + if (mediaCaption != null && !TLString.IsNullOrEmpty(mediaCaption.Caption)) + { + element.Visibility = Visibility.Visible; + return; + } + } + } + + private void DeleteMessage_OnLoaded(object sender, RoutedEventArgs e) + { + + } + + private void SelectMessages_OnClick(object sender, RoutedEventArgs e) + { + var frameworkElement = sender as FrameworkElement; + if (frameworkElement != null) + { + var message = frameworkElement.DataContext as TLDecryptedMessageBase; + if (message != null && message.SelectionVisibility == Visibility.Visible) + { + ViewModel.ChangeSelection(message); + } + } + + ViewModel.IsSelectionEnabled = true; + } + + public void ScrollTo(TLObject obj) + { + MessagesList.ScrollToItem(obj); + } + + private void ResendMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element == null) return; + + element.Visibility = Visibility.Collapsed; + var message = element.DataContext as TLDecryptedMessageBase; + if (message != null) + { + element.Visibility = message.Status == MessageStatus.Failed ? Visibility.Visible : Visibility.Collapsed; + } + } + + private void MessageControl_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + if (FocusManager.GetFocusedElement() == InputMessage.Input) + { + return; + } + if (MessagesList.Viewport.ManipulationState != ManipulationState.Idle) + { + return; + } + + var messageControl = sender as DecryptedMessageControl; + if (messageControl != null) + { + var decryptedMessageService = messageControl.DataContext as TLDecryptedMessageService; + if (decryptedMessageService != null) + { + return; + } + } + _skipFirstManipulationDelta = true; + e.Handled = true; + } + + private bool _skipFirstManipulationDelta; + + private void MessageControl_OnManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + if (_skipFirstManipulationDelta) + { + _skipFirstManipulationDelta = false; + return; + } + if (FocusManager.GetFocusedElement() == InputMessage.Input) + { + return; + } + if (MessagesList.Viewport.ManipulationState != ManipulationState.Idle) + { + return; + } + + var messageControl = sender as DecryptedMessageControl; + if (messageControl != null) + { + var decryptedMessageService = messageControl.DataContext as TLDecryptedMessageService; + if (decryptedMessageService != null) + { + return; + } + + var translationX = -e.CumulativeManipulation.Translation.X; + + if (translationX < 0.0) + { + translationX = 0.0; + } + else if (translationX > 100.0) + { + translationX = 100.0; + } + + if (messageControl.CacheMode == null) messageControl.CacheMode = new BitmapCache(); + messageControl.RenderTransform = new TranslateTransform + { + X = translationX + }; + + e.Handled = true; + } + } + + private void MessageControl_OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + _skipFirstManipulationDelta = false; + if (FocusManager.GetFocusedElement() == InputMessage.Input) + { + return; + } + if (MessagesList.Viewport.ManipulationState != ManipulationState.Idle) + { + return; + } + + var messageControl = sender as DecryptedMessageControl; + if (messageControl != null) + { + var decryptedMessageService = messageControl.DataContext as TLDecryptedMessageService; + if (decryptedMessageService != null) + { + return; + } + + var transform = messageControl.RenderTransform as TranslateTransform; + if (transform != null) + { + var translateX = transform.X; + + var storyboard = new Storyboard(); + var doubleAnimation = new DoubleAnimation(); + doubleAnimation.To = 0.0; + doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.15)); + Storyboard.SetTarget(doubleAnimation, messageControl.RenderTransform); + Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("X")); + storyboard.Children.Add(doubleAnimation); + + storyboard.Begin(); + storyboard.Completed += (o, args) => + { + messageControl.CacheMode = null; + if (translateX >= 75.0) + { + var messageBase = messageControl.DataContext as TLDecryptedMessageBase; + var innerMessage = GetInnerMessage(e, messageBase); + if (innerMessage != null) + { + messageBase = innerMessage; + } + + if (messageBase == null) return; + + ViewModel.ReplyMessage(messageBase); + InputMessage.FocusInput(); + } + }; + } + } + } + + private TLDecryptedMessageBase GetInnerMessage(ManipulationCompletedEventArgs e, TLDecryptedMessageBase messageBase) + { + var message = messageBase as TLDecryptedMessage73; + if (message != null) + { + var mediaGroup = message.Media as TLDecryptedMessageMediaGroup; + if (mediaGroup != null) + { + var source = e.OriginalSource as FrameworkElement; + if (source != null) + { + var media = source.DataContext as TLDecryptedMessageMediaBase; + for (var i = 0; i < mediaGroup.Group.Count; i++) + { + var m = mediaGroup.Group[i] as TLDecryptedMessage; + if (m != null && m.Media == media) + { + return m; + } + } + } + } + } + + return messageBase; + } + + private void MessageControl_OnTapMedia(object sender, GestureEventArgs e) + { + var messageControl = sender as DecryptedMessageControl; + if (messageControl != null) + { + var message = GetInnerMessage(messageControl, e); + if (message != null) + { + ViewModel.OpenMedia(message); + } + } + } + + private TLDecryptedMessageBase _innerMessage; + + private void MessageControl_OnHold(object sender, GestureEventArgs e) + { + var messageControl = sender as DecryptedMessageControl; + if (messageControl != null) + { + _innerMessage = GetInnerMessage(messageControl, e); + } + } + + private TLDecryptedMessage GetInnerMessage(FrameworkElement element, GestureEventArgs e) + { + var groupedMessage = element.DataContext as TLDecryptedMessage73; + if (groupedMessage != null) + { + var messageMediaGroup = groupedMessage.Media as TLDecryptedMessageMediaGroup; + if (messageMediaGroup != null) + { + var point = e.GetPosition(Application.Current.RootVisual); + var elements = VisualTreeHelper.FindElementsInHostCoordinates(point, MessagesList); + var mediaPhotoControl = elements.OfType().FirstOrDefault(); + if (mediaPhotoControl != null) + { + var message = messageMediaGroup.Group.OfType().FirstOrDefault(x => x.Media == mediaPhotoControl.Media); + if (message != null) + { + return message; + } + } + } + } + + return element.DataContext as TLDecryptedMessage; + } + + private void SelectionBorder_OnTap(object sender, GestureEventArgs e) + { + var element = sender as FrameworkElement; + if (element != null) + { + var groupedMessage = element.DataContext as TLDecryptedMessage73; + if (groupedMessage != null) + { + var selectionChanged = false; + + var messageMediaGroup = groupedMessage.Media as TLDecryptedMessageMediaGroup; + if (messageMediaGroup != null) + { + var message = GetInnerMessage(element, e); + if (message != null) + { + ViewModel.ChangeSelection(message); + + selectionChanged = true; + if (messageMediaGroup.Group.All(x => x.IsSelected) && !groupedMessage.IsSelected + || messageMediaGroup.Group.All(x => !x.IsSelected) && groupedMessage.IsSelected) + { + selectionChanged = false; + } + } + } + + if (!selectionChanged) + { + ViewModel.ChangeSelection(groupedMessage); + } + } + else + { + ViewModel.ChangeSelection(element.DataContext as TLDecryptedMessageBase); + } + } + } + + private void DeleteMessage_OnClick(object sender, RoutedEventArgs e) + { + var element = sender as FrameworkElement; + if (element != null) + { + var message = element.DataContext as TLDecryptedMessageBase; + if (message != null) + { + ViewModel.DeleteMessage(true, message); + } + } + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Media/FilesView.xaml b/TelegramClient.WP8/Views/Media/FilesView.xaml new file mode 100755 index 0000000..318e53e --- /dev/null +++ b/TelegramClient.WP8/Views/Media/FilesView.xaml @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Media/FilesView.xaml.cs b/TelegramClient.WP8/Views/Media/FilesView.xaml.cs new file mode 100755 index 0000000..aeca679 --- /dev/null +++ b/TelegramClient.WP8/Views/Media/FilesView.xaml.cs @@ -0,0 +1,64 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Input; +using Microsoft.Phone.Controls; +using Telegram.Api.TL; +using Telegram.Api.TL.Interfaces; +using TelegramClient.ViewModels.Media; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Media +{ + public partial class FilesView + { + public FilesViewModel ViewModel { get { return DataContext as FilesViewModel; } } + + public FilesView() + { + InitializeComponent(); + } + + private void Items_OnCloseToEnd(object sender, System.EventArgs e) + { + ((ISliceLoadable)DataContext).LoadNextSlice(); + } + + private void Files_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + ((ISliceLoadable)DataContext).LoadNextSlice(); + } + + private void DeleteMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem == null) return; + + var channel = ViewModel.CurrentItem as TLChannel; + menuItem.Visibility = (channel == null || channel.Creator) + ? Visibility.Visible + : Visibility.Collapsed; + } + + private void SelectionBorder_OnTap(object sender, GestureEventArgs e) + { + e.Handled = true; + + var element = sender as FrameworkElement; + if (element != null) + { + var message = element.DataContext as TLMessage; + if (message != null) + { + message.IsSelected = !message.IsSelected; + ViewModel.ChangeGroupActionStatus(); + } + } + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Media/LinksView.xaml b/TelegramClient.WP8/Views/Media/LinksView.xaml new file mode 100755 index 0000000..13401fa --- /dev/null +++ b/TelegramClient.WP8/Views/Media/LinksView.xaml @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Media/LinksView.xaml.cs b/TelegramClient.WP8/Views/Media/LinksView.xaml.cs new file mode 100755 index 0000000..38d4bf6 --- /dev/null +++ b/TelegramClient.WP8/Views/Media/LinksView.xaml.cs @@ -0,0 +1,64 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Input; +using Microsoft.Phone.Controls; +using Telegram.Api.TL; +using Telegram.Api.TL.Interfaces; +using TelegramClient.ViewModels.Media; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Media +{ + public partial class LinksView + { + public LinksViewModel ViewModel { get { return DataContext as LinksViewModel; } } + + public LinksView() + { + InitializeComponent(); + } + + private void Items_OnCloseToEnd(object sender, System.EventArgs e) + { + ((ISliceLoadable)DataContext).LoadNextSlice(); + } + + private void Files_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + ((ISliceLoadable)DataContext).LoadNextSlice(); + } + + private void DeleteMessage_OnLoaded(object sender, RoutedEventArgs e) + { + var menuItem = sender as MenuItem; + if (menuItem == null) return; + + var channel = ViewModel.CurrentItem as TLChannel; + menuItem.Visibility = (channel == null || channel.Creator) + ? Visibility.Visible + : Visibility.Collapsed; + } + + private void SelectionBorder_OnTap(object sender, GestureEventArgs e) + { + e.Handled = true; + + var element = sender as FrameworkElement; + if (element != null) + { + var message = element.DataContext as TLMessage; + if (message != null) + { + message.IsSelected = !message.IsSelected; + ViewModel.ChangeGroupActionStatus(); + } + } + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Media/MediaView.xaml b/TelegramClient.WP8/Views/Media/MediaView.xaml new file mode 100755 index 0000000..fd88b06 --- /dev/null +++ b/TelegramClient.WP8/Views/Media/MediaView.xaml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Media/MediaView.xaml.cs b/TelegramClient.WP8/Views/Media/MediaView.xaml.cs new file mode 100755 index 0000000..aaed71e --- /dev/null +++ b/TelegramClient.WP8/Views/Media/MediaView.xaml.cs @@ -0,0 +1,148 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using Coding4Fun.Toolkit.Controls; +using Microsoft.Phone.Controls; +using Telegram.Api.TL; +using Telegram.Api.TL.Interfaces; +using TelegramClient.ViewModels.Media; + +namespace TelegramClient.Views.Media +{ + public partial class MediaView + { + public MediaViewModel ViewModel + { + get { return DataContext as MediaViewModel; } + } + + public MediaView() + { + InitializeComponent(); + + // FullHD + OptimizeFullHD(); + } + + ~MediaView() + { + + } + + private void OptimizeFullHD() + { + var isFullHD = Application.Current.Host.Content.ScaleFactor == 225; + if (!isFullHD) return; + + //BottomAppBarPlaceholder.Height = new GridLength(Constants.FullHDAppBarHeight); + } + + private void Items_OnCloseToEnd(object sender, System.EventArgs e) + { + ((ISliceLoadable)DataContext).LoadNextSlice(); + } + + private bool _once; + + private void Files_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + if (_once) return; + + _once = true; + ((ISliceLoadable)DataContext).LoadNextSlice(); + } + + public static IEnumerable FindVisualChildren(DependencyObject depObj) where T : DependencyObject + { + if (depObj != null) + { + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) + { + DependencyObject child = VisualTreeHelper.GetChild(depObj, i); + if (child != null && child is T) + { + yield return (T)child; + } + + foreach (T childOfChild in FindVisualChildren(child)) + { + yield return childOfChild; + } + } + } + } + + private List _unrealizedRows = new List(); + + private void LongListSelector_OnItemUnrealized(object sender, ItemRealizationEventArgs e) + { + return; + if (e.ItemKind == LongListSelectorItemKind.Item) + { + var element = e.Container as FrameworkElement; + if (element != null) + { + var messagesRow = element.DataContext as MessagesRow; + if (messagesRow != null) + { + _unrealizedRows.Add(messagesRow); + //System.Diagnostics.Debug.WriteLine("Unrealized row " + ViewModel.Items.IndexOf(messagesRow)); + } + return; + var images = FindVisualChildren(element); + foreach (var image in images) + { + if (image.Source == null) + { + var message = image.DataContext as TLMessage; + if (message != null) + { + var mediaPhoto = message.Media as TLMessageMediaPhoto; + if (mediaPhoto != null) + { + var photo = mediaPhoto.Photo as TLPhoto; + if (photo != null) + { + ViewModel.CancelDownloading(photo); + } + } + } + } + } + } + } + } + + private void LongListSelector_OnItemRealized(object sender, ItemRealizationEventArgs e) + { + return; + if (e.ItemKind == LongListSelectorItemKind.Item) + { + var element = e.Container as FrameworkElement; + if (element != null) + { + var messagesRow = element.DataContext as MessagesRow; + if (messagesRow != null) + { + _unrealizedRows.Remove(messagesRow); + + if (_unrealizedRows.Count > 0) + { + System.Diagnostics.Debug.WriteLine("Invoke unrealized row " + _unrealizedRows.Count); + } + } + return; + } + } + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Media/MultiImageEditorView.xaml b/TelegramClient.WP8/Views/Media/MultiImageEditorView.xaml new file mode 100755 index 0000000..b5d60a3 --- /dev/null +++ b/TelegramClient.WP8/Views/Media/MultiImageEditorView.xaml @@ -0,0 +1,331 @@ + + + + + + + + /Fonts/Segoe-MDL2-Assets-MetroUI.ttf#Segoe-MDL2-Assets-MetroUI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/Views/Media/MultiImageEditorView.xaml.cs b/TelegramClient.WP8/Views/Media/MultiImageEditorView.xaml.cs new file mode 100755 index 0000000..45303f2 --- /dev/null +++ b/TelegramClient.WP8/Views/Media/MultiImageEditorView.xaml.cs @@ -0,0 +1,667 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; +using Windows.UI.ViewManagement; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; +using Telegram.Api.Extensions; +using Telegram.Api.TL; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels; +using TelegramClient.ViewModels.Additional; +using TelegramClient.ViewModels.Contacts; +using TelegramClient.ViewModels.Media; +using TelegramClient.Views.Additional; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; +using PhotoFile = TelegramClient.Services.PhotoFile; + +namespace TelegramClient.Views.Media +{ + public partial class MultiImageEditorView : IMultiImageEditorView + { + private readonly AppBarButton _doneButton = new AppBarButton + { + Text = AppResources.Done, + IconUri = new Uri("/Images/ApplicationBar/appbar.check.png", UriKind.Relative) + }; + + private readonly AppBarButton _cancelButton = new AppBarButton + { + Text = AppResources.Cancel, + IconUri = new Uri("/Images/ApplicationBar/appbar.cancel.rest.png", UriKind.Relative) + }; + + public MultiImageEditorViewModel ViewModel + { + get { return DataContext as MultiImageEditorViewModel; } + } + + public MultiImageEditorView() + { + InitializeComponent(); + + Visibility = Visibility.Collapsed; + + BuildLocalizedAppBar(); + + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + if (isLightTheme) + { + TopBorder.Fill = (Brush)Resources["InputBorderBrushLight"]; + } + else + { + TopBorder.Fill = (Brush)Resources["InputBorderBrushDark"]; + } + + Loaded += OnLoadedOnce; + Loaded += OnLoaded; + Unloaded += OnUnloaded; + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + ViewModel.PropertyChanged += OnViewModelPropertyChanged; + InputPane.GetForCurrentView().Showing += InputPane_Showing; + InputPane.GetForCurrentView().Hiding += InputPane_Hiding; + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + ViewModel.PropertyChanged -= OnViewModelPropertyChanged; + InputPane.GetForCurrentView().Showing -= InputPane_Showing; + InputPane.GetForCurrentView().Hiding -= InputPane_Hiding; + } + + private void InputPane_Hiding(InputPane sender, InputPaneVisibilityEventArgs args) + { + CaptionWatermark.Visibility = string.IsNullOrEmpty(Caption.Text) ? Visibility.Visible : Visibility.Collapsed; + KeyboardPlaceholder.Height = 0.0; + KeyboardPlaceholder.Visibility = Visibility.Collapsed; + ImagesGrid.Margin = new Thickness(0.0); + + var easingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 5.0 }; + var storyboard = new Storyboard(); + var translateImageAniamtion = new DoubleAnimationUsingKeyFrames(); + translateImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.20), Value = 0.0, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateImageAniamtion, ImagesGrid); + Storyboard.SetTargetProperty(translateImageAniamtion, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateImageAniamtion); + + Deployment.Current.Dispatcher.BeginInvoke(storyboard.Begin); + } + + private void InputPane_Showing(InputPane sender, InputPaneVisibilityEventArgs args) + { + var keyboardHeight = 480.0 / args.OccludedRect.Width * args.OccludedRect.Height - AppBar.ActualHeight + 18.0; + + var height = GetKeyboardHeightDifference(keyboardHeight); + CaptionWatermark.Visibility = Visibility.Collapsed; + KeyboardPlaceholder.Height = keyboardHeight; + KeyboardPlaceholder.Visibility = Visibility.Visible; + ImagesGrid.Margin = new Thickness(0.0, 0.0, 0.0, -height); + + var easingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 5.0 }; + var storyboard = new Storyboard(); + var translateImageAniamtion = new DoubleAnimationUsingKeyFrames(); + translateImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = -height / 2.0, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateImageAniamtion, ImagesGrid); + Storyboard.SetTargetProperty(translateImageAniamtion, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateImageAniamtion); + + Deployment.Current.Dispatcher.BeginInvoke(storyboard.Begin); + } + + private void OnLoadedOnce(object sender, RoutedEventArgs e) + { + Loaded -= OnLoadedOnce; + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => ViewModel.OpenEditor()); + } + + private bool _isOpening; + + private void OpenExtendedImageEditorInternal() + { + _isOpening = true; + ExtendedImageEditorPlaceholder.Visibility = Visibility.Visible; + _extendedImageEditor.UpdateRecentButtonsVisibility(); + _extendedImageEditor.BeginOpenStoryboard(() => + { + _isOpening = false; + BackgroundBorder.Visibility = Visibility.Collapsed; + ImagesGrid.Visibility = Visibility.Collapsed; + Bar.Visibility = Visibility.Collapsed; + }); + } + + private void CloseExtendedImageEditorIntarnal(bool confirm = true) + { + var result = MessageBoxResult.OK; + if (confirm && _extendedImageEditor.PreviewCanvas.Children.Count > 1) + { + result = MessageBox.Show(AppResources.DiscardChangesConfirmation, AppResources.Confirm, MessageBoxButton.OKCancel); + } + if (result != MessageBoxResult.OK) return; + + BackgroundBorder.Visibility = Visibility.Visible; + ImagesGrid.Visibility = Visibility.Visible; + Bar.Visibility = Visibility.Visible; + _extendedImageEditor.BeginCloseStoryboard(() => + { + ExtendedImageEditorPlaceholder.Visibility = Visibility.Collapsed; + }); + + Focus(); + } + + private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.IsOpen)) + { + if (ViewModel.IsOpen) + { + BeginOpenStoryboard(); + } + else + { + BeginCloseStoryboard(); + } + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.IsDoneEnabled)) + { + _doneButton.IsEnabled = ViewModel.IsDoneEnabled; + } + } + + private void BuildLocalizedAppBar() + { + return; + + if (ApplicationBar != null) + { + return; + } + + ApplicationBar = new ApplicationBar { Opacity = 0.9999, IsVisible = false }; + //ApplicationBar.BackgroundColor = Colors.Black; + //ApplicationBar.ForegroundColor = Colors.White; + ApplicationBar.StateChanged += (o, e) => + { + ApplicationBar.Opacity = e.IsMenuVisible ? 0.9999 : 0.0; + }; + + _doneButton.Click += (sender, args) => AppBarAction(ViewModel.Done); + _doneButton.IsEnabled = false; + _cancelButton.Click += (sender, args) => AppBarAction(ViewModel.Cancel); + + ApplicationBar.Buttons.Add(_doneButton); + ApplicationBar.Buttons.Add(_cancelButton); + } + + private void AppBarAction(System.Action action) + { + if (FocusManager.GetFocusedElement() == Caption) + { + Items.Focus(); + Telegram.Api.Helpers.Execute.BeginOnUIThread(TimeSpan.FromSeconds(0.20), action.SafeInvoke); + } + else + { + action.SafeInvoke(); + } + } + + private void BeginCloseStoryboard() + { + SystemTray.IsVisible = true; + //ApplicationBar.IsVisible = false; + + var duration = TimeSpan.FromSeconds(0.25); + var easingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 5.0 }; + + var storyboard = new Storyboard(); + + var rootFrameHeight = ((PhoneApplicationFrame)Application.Current.RootVisual).ActualHeight; + var translateYTo = rootFrameHeight; + var translateImageAniamtion = new DoubleAnimationUsingKeyFrames(); + translateImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = duration, Value = translateYTo, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateImageAniamtion, ImagesGrid); + Storyboard.SetTargetProperty(translateImageAniamtion, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateImageAniamtion); + + var opacityImageAniamtion = new DoubleAnimationUsingKeyFrames(); + opacityImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = 0 }); + Storyboard.SetTarget(opacityImageAniamtion, BackgroundBorder); + Storyboard.SetTargetProperty(opacityImageAniamtion, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityImageAniamtion); + + var translateBarAniamtion = new DoubleAnimationUsingKeyFrames(); + translateBarAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.15), Value = 0.0 }); + translateBarAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = translateYTo, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateBarAniamtion, Bar); + Storyboard.SetTargetProperty(translateBarAniamtion, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateBarAniamtion); + + storyboard.Begin(); + storyboard.Completed += (o, args) => + { + Visibility = Visibility.Collapsed; + }; + } + + private void BeginOpenStoryboard() + { + SystemTray.IsVisible = false; + //ApplicationBar.IsVisible = true; + + var transparentBlack = Colors.Black; + transparentBlack.A = 0; + + CaptionWatermark.Visibility = Visibility.Visible; + Visibility = Visibility.Visible; + ImagesGrid.Opacity = 1.0; + ImagesGrid.RenderTransform = new CompositeTransform(); + BackgroundBorder.Opacity = 1.0; + + + var duration = TimeSpan.FromSeconds(0.25); + var easingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 5.0 }; + + var storyboard = new Storyboard(); + + var rootFrameHeight = ((PhoneApplicationFrame)Application.Current.RootVisual).ActualHeight; + var translateYTo = rootFrameHeight; + + ((CompositeTransform)ImagesGrid.RenderTransform).TranslateY = translateYTo; + var translateImageAniamtion = new DoubleAnimationUsingKeyFrames(); + translateImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = translateYTo }); + translateImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = duration, Value = 0.0, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateImageAniamtion, ImagesGrid); + Storyboard.SetTargetProperty(translateImageAniamtion, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateImageAniamtion); + + var translateBarAniamtion = new DoubleAnimationUsingKeyFrames(); + translateBarAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.15), Value = translateYTo }); + translateBarAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = 0.0, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateBarAniamtion, Bar); + Storyboard.SetTargetProperty(translateBarAniamtion, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateBarAniamtion); + + storyboard.Completed += (sender, args) => ViewModel.OpenAnimationComplete(); + Deployment.Current.Dispatcher.BeginInvoke(storyboard.Begin); + } + + private void Caption_OnGotFocus(object sender, RoutedEventArgs e) + { + return; + + } + + private double GetKeyboardHeightDifference(double keyboardHeight) + { + var heightDifference = keyboardHeight - Items.ActualHeight; + + return heightDifference; + } + + private void Caption_OnLostFocus(object sender, RoutedEventArgs e) + { + return; + } + + private void Caption_OnTextChanged(object sender, TextChangedEventArgs e) + { + CaptionWatermark.Visibility = string.IsNullOrEmpty(Caption.Text) && FocusManager.GetFocusedElement() != Caption ? Visibility.Visible : Visibility.Collapsed; + } + + private void Caption_OnKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + if (ViewModel.Items.Count == 1) + { + ViewModel.Done(); + } + else + { + Items.Focus(); + } + } + } + + private void Image_OnImageOpened(object sender, RoutedEventArgs e) + { + var image = (Image) sender; + image.Opacity = 0.0; + var storyboard = new Storyboard(); + + var opacityImageAniamtion = new DoubleAnimationUsingKeyFrames(); + opacityImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.5), Value = 1.0 }); + Storyboard.SetTarget(opacityImageAniamtion, image); + Storyboard.SetTargetProperty(opacityImageAniamtion, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityImageAniamtion); + + storyboard.Begin(); + } + + private static List> _imagesCache = new List>(); + + private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e) + { + var image = (Image) sender; + var photoFile = image.DataContext as PhotoFile; + _imagesCache.Add(new Telegram.Api.WindowsPhone.Tuple(photoFile, image)); + } + + public static void ImageOpened(PhotoFile photoFile) + { + var tuple = _imagesCache.LastOrDefault(x => x.Item1 == photoFile); + _imagesCache.Remove(tuple); + if (tuple != null) + { + var image = tuple.Item2; + image.Opacity = 0.0; + var storyboard = new Storyboard(); + + var opacityImageAniamtion = new DoubleAnimationUsingKeyFrames(); + opacityImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.5), Value = 1.0 }); + Storyboard.SetTarget(opacityImageAniamtion, image); + Storyboard.SetTargetProperty(opacityImageAniamtion, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityImageAniamtion); + + storyboard.Begin(); + } + } + + private void ContextMenu_OnLoaded(object sender, RoutedEventArgs e) + { + var menu = (ContextMenu) sender; + menu.Visibility = ViewModel.Items.FirstOrDefault(x => x.Message != null) != null ? Visibility.Visible : Visibility.Collapsed; + } + + private void MenuItem_OnClick(object sender, RoutedEventArgs e) + { + DeleteCurrentItem(); + } + + private void Delete_OnClick(object sender, RoutedEventArgs e) + { + DeleteCurrentItem(); + } + + private ExtendedImageEditor _extendedImageEditor; + + private void Edit_OnClick(object sender, RoutedEventArgs args) + { + var photoFile = ViewModel.CurrentItem; + if (photoFile != null) + { + if (photoFile.IsButton) return; + if (photoFile.File == null) return; + + var previewBitmap = Preview.Source as BitmapSource; + if (previewBitmap == null) return; + + if (_extendedImageEditor == null) + { + _extendedImageEditor = new ExtendedImageEditor(); + _extendedImageEditor.Done += (o, e) => + { + CloseExtendedImageEditorIntarnal(false); + }; + _extendedImageEditor.Cancel += (o, e) => + { + CloseExtendedImageEditorIntarnal(); + }; + ExtendedImageEditorPlaceholder.Content = _extendedImageEditor; + } + + OpenExtendedImageEditorInternal(); + _extendedImageEditor.Detect(photoFile, previewBitmap); + } + } + + private void DeleteCurrentItem() + { + var photoFile = ViewModel.CurrentItem; + if (photoFile != null) + { + if (photoFile.IsButton) return; + + var index = ViewModel.Items.IndexOf(photoFile); + if (index == -1) return; + + var container = Items.ContainerFromItem(photoFile); + if (container != null) + { + var storyboard = new Storyboard(); + + var opacityImageAniamtion = new DoubleAnimationUsingKeyFrames(); + opacityImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame + { + KeyTime = TimeSpan.FromSeconds(0.25), + Value = 0.0 + }); + Storyboard.SetTarget(opacityImageAniamtion, container); + Storyboard.SetTargetProperty(opacityImageAniamtion, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityImageAniamtion); + + storyboard.Begin(); + storyboard.Completed += (o, args) => ViewModel.Delete(photoFile); + } + } + } + + public bool IsExtendedImageEditorOpened + { + get { return _extendedImageEditor != null && ExtendedImageEditorPlaceholder.Visibility == Visibility.Visible; } + } + + public void CloseExtendedImageEditor() + { + if (_extendedImageEditor.IsStickerPanelOpened) + { + _extendedImageEditor.CloseStickerPanel(); + } + else if (_isOpening) + { + CloseExtendedImageEditorIntarnal(); + return; + } + else if (ExtendedImageEditorPlaceholder.Visibility == Visibility.Visible) + { + CloseExtendedImageEditorIntarnal(); + return; + } + } + + private void Done_Click(object sender, RoutedEventArgs e) + { + ViewModel.Done(); + + if (_extendedImageEditor != null) + { + var stickersControl = _extendedImageEditor.StickersPanel.Content as StickersControl; + if (stickersControl != null) + { + var viewModel = ViewModel; + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + var stickers = new List(); + var masks = new List(); + + foreach (var item in viewModel.Items) + { + var message = item.Message as TLMessage48; + if (message != null && message.Documents != null) + { + foreach (var document in message.Documents) + { + var document54 = document as TLDocument54; + if (document54 != null) + { + var attributeSticker = document54.Attributes.FirstOrDefault(x => x is TLDocumentAttributeSticker56) as TLDocumentAttributeSticker56; + if (attributeSticker != null) + { + if (attributeSticker.Mask) + { + masks.Add(document54); + } + else + { + stickers.Add(document54); + } + } + } + } + } + } + + stickersControl.UpdateRecentAsync(stickers, masks); + }); + } + } + } + + public void ClosePreview() + { + if (_extendedImageEditor != null) + { + _extendedImageEditor.ClosePreview(); + } + } + + private void Timer_OnClick(object sender, GestureEventArgs e) + { + var stateService = IoC.Get(); + stateService.SelectedTimerSpan = ViewModel.CurrentItem.TimerSpan; + var chooseTTLViewModel = IoC.Get(); + chooseTTLViewModel.Subtitle = AppResources.SelfDestructTimerPhotoSubtitle; + + var chooseTTLView = new ChooseTTLView { Height = 330.0, DataContext = chooseTTLViewModel, Margin = new Thickness(0.0, -34.0, 0.0, -6.0) }; + ShellViewModel.ShowCustomMessageBox(null, null, AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + result => + { + if (result == CustomMessageBoxResult.RightButton) + { + var selector = chooseTTLView.Selector; + + ViewModel.CurrentItem.TimerSpan = ((TimerSpan)selector.DataSource.SelectedItem); + } + }, + chooseTTLView); + } + + private void AddButton_OnTap(object sender, GestureEventArgs e) + { + ViewModel.PickPhoto(); + } + + private void GroupedIcon_OnTap(object sender, GestureEventArgs e) + { + ShowHint(); + } + + private void ShowHint() + { + if (InputMessageHintPlaceholder.Content == null) + { + var control = new InputMessageHint(true); + control.FontSize = new ScaledText().DefaultFontSize; + control.Closed += OnInputMessageHintClosed; + + InputMessageHintPlaceholder.Content = control; + } + + var inputMessageHint = InputMessageHintPlaceholder.Content as InputMessageHint; + if (inputMessageHint != null) + { + inputMessageHint.Hint = ViewModel.IsGrouped ? AppResources.GroupMediaDescription : AppResources.UngroupMediaDescription; + } + } + + private void OnInputMessageHintClosed(object sender, System.EventArgs e) + { + var control = sender as InputMessageHint; + if (control != null) + { + control.Closed -= OnInputMessageHintClosed; + } + + InputMessageHintPlaceholder.Content = null; + } + + private void UsernameHint_OnTap(object sender, GestureEventArgs e) + { + Caption.Focus(); + + var frameworkElement = e.OriginalSource as FrameworkElement; + if (frameworkElement != null) + { + var user = frameworkElement.DataContext as IUserName; + if (user != null) + { + var userBase = user as TLUserBase; + + var index = 0; + for (var i = Caption.Text.Length - 1; i >= 0; i--) + { + if (Caption.Text[i] == '@') + { + index = i; + break; + } + } + + if (TLString.IsNullOrEmpty(user.UserName)) + { + if (userBase != null) + { + ViewModel.AddMention(userBase); + + Caption.Text = string.Format("{0}({1})", Caption.Text.Substring(0, index + 1), userBase.FullName); + Caption.SelectionStart = Caption.Text.Length - userBase.FullName.Length - 1; + Caption.SelectionLength = userBase.FullName.Length; + } + } + else + { + Caption.Text = string.Format("{0}{1} ", Caption.Text.Substring(0, index + 1), user.UserName); + Caption.SelectionStart = Caption.Text.Length; + Caption.SelectionLength = 0; + } + } + } + } + + private void UsernameHints_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + ViewModel.ContinueLoadMentionHints(); + } + } + + public interface IMultiImageEditorView + { + bool IsExtendedImageEditorOpened { get; } + + void CloseExtendedImageEditor(); + } +} diff --git a/TelegramClient.WP8/app.config b/TelegramClient.WP8/app.config new file mode 100755 index 0000000..a17b4ec --- /dev/null +++ b/TelegramClient.WP8/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP8/packages.config b/TelegramClient.WP8/packages.config new file mode 100755 index 0000000..86b9051 --- /dev/null +++ b/TelegramClient.WP8/packages.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81.sln b/TelegramClient.WP81.sln new file mode 100755 index 0000000..3e366b7 --- /dev/null +++ b/TelegramClient.WP81.sln @@ -0,0 +1,816 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30501.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelegramClient.WP81", "TelegramClient.WP81\TelegramClient.WP81.csproj", "{B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegram.Api.WP8", "Telegram.Api.WP8\Telegram.Api.WP8.csproj", "{E79D5093-8038-4A5F-8A98-CA38C0D0886F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{414D6805-ADB9-4A47-850B-7A65131D7A23}" + ProjectSection(SolutionItems) = preProject + .nuget\NuGet.Config = .nuget\NuGet.Config + .nuget\NuGet.exe = .nuget\NuGet.exe + .nuget\NuGet.targets = .nuget\NuGet.targets + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TelegramClient.Opus", "TelegramClient.Opus\TelegramClient.Opus.vcxproj", "{5E327850-E16E-4642-957A-FD52BF8D3D02}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegram.Controls.WP8", "Telegram.Controls.WP8\Telegram.Controls.WP8.csproj", "{F04BE5A2-70DF-4E82-BFB5-CD03985C9746}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TelegramClient.WebP", "TelegramClient.WebP\TelegramClient.WebP.vcxproj", "{FAE12FD9-EDCA-433E-AD11-F1663A998F35}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelegramClient.Player.WP8", "TelegramClient.Player.WP8\TelegramClient.Player.WP8.csproj", "{62C14349-ED3B-4FF0-8635-F970AA1A8E32}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelegramClient.Tasks", "TelegramClient.Tasks\TelegramClient.Tasks.csproj", "{997BD0C4-68E8-4495-904A-EB798B166832}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegram.Api.PCL", "Telegram.Api.PCL\Telegram.Api.PCL.csproj", "{DE897F51-AF1F-48FE-9DBB-6B308F9740D1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenCVComponent", "OpenCVComponent\OpenCVComponent.vcxproj", "{EADFF7B8-E6C3-4F34-9B33-014B3035C595}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FFmpegInterop.Shared", "FFmpegInterop\Win8.1\FFmpegInterop.Shared\FFmpegInterop.Shared.vcxitems", "{B290D2CE-E857-4ACE-8541-D80A3B9AB04E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FFmpegInterop.WindowsPhone", "FFmpegInterop\Win8.1\FFmpegInterop.WindowsPhone\FFmpegInterop.WindowsPhone.vcxproj", "{EBC5CA98-87F1-4A01-A48D-69659C103E72}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtgvoip", "libtgvoip-public\libtgvoip.WP81.vcxproj", "{21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VoipBackendServerHost", "VoipBackendServerHost\VoipBackendServerHost.vcxproj", "{0A402E0E-CEE9-477E-B17A-A4B01BB1448C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BackEnd", "BackEnd\BackEnd.vcxproj", "{C8D75245-FFCF-4932-A228-C9CC8BB60B03}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BackEndProxyStub", "BackEndProxyStub\BackEndProxyStub.vcxproj", "{BBABEEA1-494C-4618-96E3-399873A5558B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Agents", "Agents\Agents.csproj", "{820034C1-645D-4340-8813-D980C1EF77DE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TelegramClient.Native", "TelegramClient.Native\TelegramClient.Native.vcxproj", "{B51DD8C5-335D-4A2D-B429-6D0F41ED0281}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtgnet", "libtgnet\libtgnet.vcxproj", "{CC7A35BF-AABC-411D-B911-AC037A781266}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + FFmpegInterop\Win8.1\FFmpegInterop.Shared\FFmpegInterop.Shared.vcxitems*{b290d2ce-e857-4ace-8541-d80a3b9ab04e}*SharedItemsImports = 9 + FFmpegInterop\Win8.1\FFmpegInterop.Shared\FFmpegInterop.Shared.vcxitems*{ebc5ca98-87f1-4a01-a48d-69659c103e72}*SharedItemsImports = 4 + EndGlobalSection + GlobalSection(SubversionScc) = preSolution + Svn-Managed = True + Manager = AnkhSVN - Subversion Support for Visual Studio + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug Private Beta|Any CPU = Debug Private Beta|Any CPU + Debug Private Beta|ARM = Debug Private Beta|ARM + Debug Private Beta|Mixed Platforms = Debug Private Beta|Mixed Platforms + Debug Private Beta|Win32 = Debug Private Beta|Win32 + Debug Private Beta|x64 = Debug Private Beta|x64 + Debug Private Beta|x86 = Debug Private Beta|x86 + Debug|Any CPU = Debug|Any CPU + Debug|ARM = Debug|ARM + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release Private Beta|Any CPU = Release Private Beta|Any CPU + Release Private Beta|ARM = Release Private Beta|ARM + Release Private Beta|Mixed Platforms = Release Private Beta|Mixed Platforms + Release Private Beta|Win32 = Release Private Beta|Win32 + Release Private Beta|x64 = Release Private Beta|x64 + Release Private Beta|x86 = Release Private Beta|x86 + Release|Any CPU = Release|Any CPU + Release|ARM = Release|ARM + Release|Mixed Platforms = Release|Mixed Platforms + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Any CPU + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug Private Beta|Any CPU.Build.0 = Debug|Any CPU + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug Private Beta|Win32.ActiveCfg = Debug|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug Private Beta|Win32.Build.0 = Debug|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug Private Beta|x64.ActiveCfg = Debug|Any CPU + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug Private Beta|x86.ActiveCfg = Debug|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug Private Beta|x86.Build.0 = Debug|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug|ARM.ActiveCfg = Debug|ARM + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug|Win32.ActiveCfg = Debug|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug|Win32.Build.0 = Debug|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug|x64.ActiveCfg = Debug|Any CPU + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug|x86.ActiveCfg = Debug|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Debug|x86.Build.0 = Debug|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release Private Beta|Any CPU.ActiveCfg = Release|Any CPU + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release Private Beta|Any CPU.Build.0 = Release|Any CPU + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release Private Beta|ARM.Build.0 = Release|ARM + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release Private Beta|Mixed Platforms.Build.0 = Release|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release Private Beta|Win32.ActiveCfg = Release|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release Private Beta|Win32.Build.0 = Release|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release Private Beta|x64.ActiveCfg = Release|Any CPU + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release Private Beta|x86.ActiveCfg = Release|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release Private Beta|x86.Build.0 = Release|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release|Any CPU.Build.0 = Release|Any CPU + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release|ARM.ActiveCfg = Release|ARM + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release|ARM.Build.0 = Release|ARM + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release|Mixed Platforms.Build.0 = Release|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release|Win32.ActiveCfg = Release|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release|Win32.Build.0 = Release|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release|x64.ActiveCfg = Release|Any CPU + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release|x86.ActiveCfg = Release|x86 + {E79D5093-8038-4A5F-8A98-CA38C0D0886F}.Release|x86.Build.0 = Release|x86 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug Private Beta|Win32.ActiveCfg = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug Private Beta|Win32.Build.0 = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug Private Beta|x64.ActiveCfg = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug Private Beta|x86.ActiveCfg = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug Private Beta|x86.Build.0 = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug|ARM.ActiveCfg = Debug|ARM + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug|Win32.ActiveCfg = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug|Win32.Build.0 = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug|x64.ActiveCfg = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug|x86.ActiveCfg = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Debug|x86.Build.0 = Debug|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release Private Beta|Any CPU.ActiveCfg = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release Private Beta|ARM.Build.0 = Release|ARM + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release Private Beta|Mixed Platforms.Build.0 = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release Private Beta|Win32.ActiveCfg = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release Private Beta|Win32.Build.0 = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release Private Beta|x64.ActiveCfg = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release Private Beta|x86.ActiveCfg = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release Private Beta|x86.Build.0 = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release|Any CPU.ActiveCfg = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release|ARM.ActiveCfg = Release|ARM + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release|ARM.Build.0 = Release|ARM + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release|Mixed Platforms.Build.0 = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release|Win32.ActiveCfg = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release|Win32.Build.0 = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release|x64.ActiveCfg = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release|x86.ActiveCfg = Release|Win32 + {5E327850-E16E-4642-957A-FD52BF8D3D02}.Release|x86.Build.0 = Release|Win32 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Any CPU + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug Private Beta|Any CPU.Build.0 = Debug|Any CPU + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug Private Beta|Win32.ActiveCfg = Debug|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug Private Beta|Win32.Build.0 = Debug|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug Private Beta|x64.ActiveCfg = Debug|Any CPU + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug Private Beta|x86.ActiveCfg = Debug|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug Private Beta|x86.Build.0 = Debug|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug|ARM.ActiveCfg = Debug|ARM + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug|ARM.Build.0 = Debug|ARM + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug|Win32.ActiveCfg = Debug|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug|Win32.Build.0 = Debug|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug|x64.ActiveCfg = Debug|Any CPU + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug|x86.ActiveCfg = Debug|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Debug|x86.Build.0 = Debug|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release Private Beta|Any CPU.ActiveCfg = Release|Any CPU + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release Private Beta|Any CPU.Build.0 = Release|Any CPU + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release Private Beta|ARM.Build.0 = Release|ARM + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release Private Beta|Mixed Platforms.Build.0 = Release|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release Private Beta|Win32.ActiveCfg = Release|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release Private Beta|Win32.Build.0 = Release|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release Private Beta|x64.ActiveCfg = Release|Any CPU + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release Private Beta|x86.ActiveCfg = Release|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release Private Beta|x86.Build.0 = Release|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release|Any CPU.Build.0 = Release|Any CPU + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release|ARM.ActiveCfg = Release|ARM + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release|ARM.Build.0 = Release|ARM + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release|Mixed Platforms.Build.0 = Release|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release|Win32.ActiveCfg = Release|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release|Win32.Build.0 = Release|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release|x64.ActiveCfg = Release|Any CPU + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release|x86.ActiveCfg = Release|x86 + {F04BE5A2-70DF-4E82-BFB5-CD03985C9746}.Release|x86.Build.0 = Release|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|Any CPU.ActiveCfg = Debug Private Beta|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|Any CPU.Build.0 = Debug Private Beta|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|Any CPU.Deploy.0 = Debug Private Beta|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|ARM.ActiveCfg = Debug Private Beta|ARM + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|ARM.Build.0 = Debug Private Beta|ARM + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|ARM.Deploy.0 = Debug Private Beta|ARM + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|Mixed Platforms.Build.0 = Debug Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|Mixed Platforms.Deploy.0 = Debug Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|Win32.ActiveCfg = Debug Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|Win32.Build.0 = Debug Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|Win32.Deploy.0 = Debug Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|x64.ActiveCfg = Debug Private Beta|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|x86.ActiveCfg = Debug Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|x86.Build.0 = Debug Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug Private Beta|x86.Deploy.0 = Debug Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|ARM.ActiveCfg = Debug|ARM + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|ARM.Build.0 = Debug|ARM + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|ARM.Deploy.0 = Debug|ARM + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|Mixed Platforms.Deploy.0 = Debug|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|Win32.ActiveCfg = Debug|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|Win32.Build.0 = Debug|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|Win32.Deploy.0 = Debug|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|x64.ActiveCfg = Debug|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|x86.ActiveCfg = Debug|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|x86.Build.0 = Debug|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Debug|x86.Deploy.0 = Debug|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|Any CPU.ActiveCfg = Release Private Beta|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|Any CPU.Build.0 = Release Private Beta|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|Any CPU.Deploy.0 = Release Private Beta|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|ARM.ActiveCfg = Release Private Beta|ARM + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|ARM.Build.0 = Release Private Beta|ARM + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|ARM.Deploy.0 = Release Private Beta|ARM + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|Mixed Platforms.ActiveCfg = Release Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|Mixed Platforms.Build.0 = Release Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|Mixed Platforms.Deploy.0 = Release Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|Win32.ActiveCfg = Release Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|Win32.Build.0 = Release Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|Win32.Deploy.0 = Release Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|x64.ActiveCfg = Release Private Beta|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|x86.ActiveCfg = Release Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|x86.Build.0 = Release Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release Private Beta|x86.Deploy.0 = Release Private Beta|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|Any CPU.Build.0 = Release|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|Any CPU.Deploy.0 = Release|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|ARM.ActiveCfg = Release|ARM + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|ARM.Build.0 = Release|ARM + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|ARM.Deploy.0 = Release|ARM + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|Mixed Platforms.Build.0 = Release|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|Mixed Platforms.Deploy.0 = Release|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|Win32.ActiveCfg = Release|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|Win32.Build.0 = Release|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|Win32.Deploy.0 = Release|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|x64.ActiveCfg = Release|Any CPU + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|x86.ActiveCfg = Release|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|x86.Build.0 = Release|x86 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3}.Release|x86.Deploy.0 = Release|x86 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug Private Beta|Win32.ActiveCfg = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug Private Beta|Win32.Build.0 = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug Private Beta|x64.ActiveCfg = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug Private Beta|x86.ActiveCfg = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug Private Beta|x86.Build.0 = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug|ARM.ActiveCfg = Debug|ARM + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug|Win32.ActiveCfg = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug|Win32.Build.0 = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug|x64.ActiveCfg = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug|x86.ActiveCfg = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Debug|x86.Build.0 = Debug|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release Private Beta|Any CPU.ActiveCfg = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release Private Beta|ARM.Build.0 = Release|ARM + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release Private Beta|Mixed Platforms.Build.0 = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release Private Beta|Win32.ActiveCfg = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release Private Beta|Win32.Build.0 = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release Private Beta|x64.ActiveCfg = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release Private Beta|x86.ActiveCfg = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release Private Beta|x86.Build.0 = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release|Any CPU.ActiveCfg = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release|ARM.ActiveCfg = Release|ARM + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release|ARM.Build.0 = Release|ARM + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release|Mixed Platforms.Build.0 = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release|Win32.ActiveCfg = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release|Win32.Build.0 = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release|x64.ActiveCfg = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release|x86.ActiveCfg = Release|Win32 + {FAE12FD9-EDCA-433E-AD11-F1663A998F35}.Release|x86.Build.0 = Release|Win32 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Any CPU + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug Private Beta|Any CPU.Build.0 = Debug|Any CPU + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug Private Beta|Win32.ActiveCfg = Debug|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug Private Beta|Win32.Build.0 = Debug|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug Private Beta|x64.ActiveCfg = Debug|Any CPU + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug Private Beta|x86.ActiveCfg = Debug|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug Private Beta|x86.Build.0 = Debug|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug|Any CPU.Build.0 = Debug|Any CPU + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug|ARM.ActiveCfg = Debug|ARM + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug|Win32.ActiveCfg = Debug|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug|Win32.Build.0 = Debug|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug|x64.ActiveCfg = Debug|Any CPU + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug|x86.ActiveCfg = Debug|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Debug|x86.Build.0 = Debug|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release Private Beta|Any CPU.ActiveCfg = Release|Any CPU + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release Private Beta|Any CPU.Build.0 = Release|Any CPU + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release Private Beta|ARM.Build.0 = Release|ARM + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release Private Beta|Mixed Platforms.Build.0 = Release|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release Private Beta|Win32.ActiveCfg = Release|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release Private Beta|Win32.Build.0 = Release|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release Private Beta|x64.ActiveCfg = Release|Any CPU + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release Private Beta|x86.ActiveCfg = Release|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release Private Beta|x86.Build.0 = Release|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release|Any CPU.ActiveCfg = Release|Any CPU + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release|Any CPU.Build.0 = Release|Any CPU + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release|ARM.ActiveCfg = Release|ARM + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release|ARM.Build.0 = Release|ARM + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release|Mixed Platforms.Build.0 = Release|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release|Win32.ActiveCfg = Release|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release|Win32.Build.0 = Release|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release|x64.ActiveCfg = Release|Any CPU + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release|x86.ActiveCfg = Release|x86 + {62C14349-ED3B-4FF0-8635-F970AA1A8E32}.Release|x86.Build.0 = Release|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Any CPU + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug Private Beta|Any CPU.Build.0 = Debug|Any CPU + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug Private Beta|Win32.ActiveCfg = Debug|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug Private Beta|Win32.Build.0 = Debug|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug Private Beta|x64.ActiveCfg = Debug|Any CPU + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug Private Beta|x86.ActiveCfg = Debug|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug Private Beta|x86.Build.0 = Debug|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug|Any CPU.Build.0 = Debug|Any CPU + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug|ARM.ActiveCfg = Debug|ARM + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug|Win32.ActiveCfg = Debug|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug|Win32.Build.0 = Debug|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug|x64.ActiveCfg = Debug|Any CPU + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug|x86.ActiveCfg = Debug|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Debug|x86.Build.0 = Debug|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Release Private Beta|Any CPU.ActiveCfg = Release|Any CPU + {997BD0C4-68E8-4495-904A-EB798B166832}.Release Private Beta|Any CPU.Build.0 = Release|Any CPU + {997BD0C4-68E8-4495-904A-EB798B166832}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {997BD0C4-68E8-4495-904A-EB798B166832}.Release Private Beta|ARM.Build.0 = Release|ARM + {997BD0C4-68E8-4495-904A-EB798B166832}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Release Private Beta|Mixed Platforms.Build.0 = Release|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Release Private Beta|Win32.ActiveCfg = Release|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Release Private Beta|Win32.Build.0 = Release|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Release Private Beta|x64.ActiveCfg = Release|Any CPU + {997BD0C4-68E8-4495-904A-EB798B166832}.Release Private Beta|x86.ActiveCfg = Release|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Release Private Beta|x86.Build.0 = Release|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Release|Any CPU.ActiveCfg = Release|Any CPU + {997BD0C4-68E8-4495-904A-EB798B166832}.Release|Any CPU.Build.0 = Release|Any CPU + {997BD0C4-68E8-4495-904A-EB798B166832}.Release|ARM.ActiveCfg = Release|ARM + {997BD0C4-68E8-4495-904A-EB798B166832}.Release|ARM.Build.0 = Release|ARM + {997BD0C4-68E8-4495-904A-EB798B166832}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Release|Mixed Platforms.Build.0 = Release|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Release|Win32.ActiveCfg = Release|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Release|Win32.Build.0 = Release|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Release|x64.ActiveCfg = Release|Any CPU + {997BD0C4-68E8-4495-904A-EB798B166832}.Release|x86.ActiveCfg = Release|x86 + {997BD0C4-68E8-4495-904A-EB798B166832}.Release|x86.Build.0 = Release|x86 + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug Private Beta|Any CPU.Build.0 = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug Private Beta|ARM.ActiveCfg = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug Private Beta|Win32.ActiveCfg = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug Private Beta|x64.ActiveCfg = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug Private Beta|x86.ActiveCfg = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug|ARM.ActiveCfg = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug|Win32.ActiveCfg = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug|x64.ActiveCfg = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Debug|x86.ActiveCfg = Debug|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release Private Beta|Any CPU.ActiveCfg = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release Private Beta|Any CPU.Build.0 = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release Private Beta|ARM.ActiveCfg = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release Private Beta|Mixed Platforms.Build.0 = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release Private Beta|Win32.ActiveCfg = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release Private Beta|x64.ActiveCfg = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release Private Beta|x86.ActiveCfg = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release|Any CPU.Build.0 = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release|ARM.ActiveCfg = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release|ARM.Build.0 = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release|Win32.ActiveCfg = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release|x64.ActiveCfg = Release|Any CPU + {DE897F51-AF1F-48FE-9DBB-6B308F9740D1}.Release|x86.ActiveCfg = Release|Any CPU + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug Private Beta|Win32.ActiveCfg = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug Private Beta|Win32.Build.0 = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug Private Beta|x64.ActiveCfg = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug Private Beta|x86.ActiveCfg = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug Private Beta|x86.Build.0 = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug|ARM.ActiveCfg = Debug|ARM + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug|Win32.ActiveCfg = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug|Win32.Build.0 = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug|x64.ActiveCfg = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug|x86.ActiveCfg = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Debug|x86.Build.0 = Debug|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release Private Beta|Any CPU.ActiveCfg = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release Private Beta|ARM.Build.0 = Release|ARM + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release Private Beta|Mixed Platforms.Build.0 = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release Private Beta|Win32.ActiveCfg = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release Private Beta|Win32.Build.0 = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release Private Beta|x64.ActiveCfg = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release Private Beta|x86.ActiveCfg = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release Private Beta|x86.Build.0 = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release|Any CPU.ActiveCfg = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release|ARM.ActiveCfg = Release|ARM + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release|ARM.Build.0 = Release|ARM + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release|Mixed Platforms.Build.0 = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release|Win32.ActiveCfg = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release|Win32.Build.0 = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release|x64.ActiveCfg = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release|x86.ActiveCfg = Release|Win32 + {EADFF7B8-E6C3-4F34-9B33-014B3035C595}.Release|x86.Build.0 = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug Private Beta|Win32.ActiveCfg = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug Private Beta|Win32.Build.0 = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug Private Beta|x64.ActiveCfg = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug Private Beta|x86.ActiveCfg = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug Private Beta|x86.Build.0 = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug|ARM.ActiveCfg = Debug|ARM + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug|ARM.Build.0 = Debug|ARM + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug|Win32.ActiveCfg = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug|Win32.Build.0 = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug|x64.ActiveCfg = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug|x86.ActiveCfg = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Debug|x86.Build.0 = Debug|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release Private Beta|Any CPU.ActiveCfg = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release Private Beta|ARM.Build.0 = Release|ARM + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release Private Beta|Mixed Platforms.Build.0 = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release Private Beta|Win32.ActiveCfg = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release Private Beta|Win32.Build.0 = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release Private Beta|x64.ActiveCfg = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release Private Beta|x86.ActiveCfg = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release Private Beta|x86.Build.0 = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release|Any CPU.ActiveCfg = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release|ARM.ActiveCfg = Release|ARM + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release|ARM.Build.0 = Release|ARM + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release|Mixed Platforms.Build.0 = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release|Win32.ActiveCfg = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release|Win32.Build.0 = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release|x64.ActiveCfg = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release|x86.ActiveCfg = Release|Win32 + {EBC5CA98-87F1-4A01-A48D-69659C103E72}.Release|x86.Build.0 = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug Private Beta|Win32.ActiveCfg = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug Private Beta|Win32.Build.0 = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug Private Beta|x64.ActiveCfg = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug Private Beta|x86.ActiveCfg = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug Private Beta|x86.Build.0 = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug|ARM.ActiveCfg = Debug|ARM + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug|ARM.Build.0 = Debug|ARM + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug|Win32.ActiveCfg = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug|Win32.Build.0 = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug|x64.ActiveCfg = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug|x86.ActiveCfg = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Debug|x86.Build.0 = Debug|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release Private Beta|Any CPU.ActiveCfg = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release Private Beta|ARM.Build.0 = Release|ARM + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release Private Beta|Mixed Platforms.Build.0 = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release Private Beta|Win32.ActiveCfg = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release Private Beta|Win32.Build.0 = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release Private Beta|x64.ActiveCfg = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release Private Beta|x86.ActiveCfg = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release Private Beta|x86.Build.0 = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release|Any CPU.ActiveCfg = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release|ARM.ActiveCfg = Release|ARM + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release|ARM.Build.0 = Release|ARM + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release|Mixed Platforms.Build.0 = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release|Win32.ActiveCfg = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release|Win32.Build.0 = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release|x64.ActiveCfg = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release|x86.ActiveCfg = Release|Win32 + {21F10158-C078-4BD7-A82A-9C4AEB8E2F8E}.Release|x86.Build.0 = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|ARM.Deploy.0 = Debug|ARM + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|Mixed Platforms.Deploy.0 = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|Win32.ActiveCfg = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|Win32.Build.0 = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|Win32.Deploy.0 = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|x64.ActiveCfg = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|x86.ActiveCfg = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|x86.Build.0 = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug Private Beta|x86.Deploy.0 = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|ARM.ActiveCfg = Debug|ARM + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|ARM.Build.0 = Debug|ARM + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|ARM.Deploy.0 = Debug|ARM + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|Mixed Platforms.Deploy.0 = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|Win32.ActiveCfg = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|Win32.Build.0 = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|Win32.Deploy.0 = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|x64.ActiveCfg = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|x86.ActiveCfg = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|x86.Build.0 = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Debug|x86.Deploy.0 = Debug|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|Any CPU.ActiveCfg = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|ARM.Build.0 = Release|ARM + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|ARM.Deploy.0 = Release|ARM + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|Mixed Platforms.Build.0 = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|Mixed Platforms.Deploy.0 = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|Win32.ActiveCfg = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|Win32.Build.0 = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|Win32.Deploy.0 = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|x64.ActiveCfg = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|x86.ActiveCfg = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|x86.Build.0 = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release Private Beta|x86.Deploy.0 = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|Any CPU.ActiveCfg = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|ARM.ActiveCfg = Release|ARM + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|ARM.Build.0 = Release|ARM + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|ARM.Deploy.0 = Release|ARM + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|Mixed Platforms.Build.0 = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|Mixed Platforms.Deploy.0 = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|Win32.ActiveCfg = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|Win32.Build.0 = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|Win32.Deploy.0 = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|x64.ActiveCfg = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|x86.ActiveCfg = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|x86.Build.0 = Release|Win32 + {0A402E0E-CEE9-477E-B17A-A4B01BB1448C}.Release|x86.Deploy.0 = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug Private Beta|Win32.ActiveCfg = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug Private Beta|Win32.Build.0 = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug Private Beta|x64.ActiveCfg = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug Private Beta|x86.ActiveCfg = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug Private Beta|x86.Build.0 = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug|ARM.ActiveCfg = Debug|ARM + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug|ARM.Build.0 = Debug|ARM + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug|Win32.ActiveCfg = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug|Win32.Build.0 = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug|x64.ActiveCfg = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug|x86.ActiveCfg = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Debug|x86.Build.0 = Debug|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release Private Beta|Any CPU.ActiveCfg = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release Private Beta|ARM.Build.0 = Release|ARM + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release Private Beta|Mixed Platforms.Build.0 = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release Private Beta|Win32.ActiveCfg = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release Private Beta|Win32.Build.0 = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release Private Beta|x64.ActiveCfg = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release Private Beta|x86.ActiveCfg = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release Private Beta|x86.Build.0 = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release|Any CPU.ActiveCfg = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release|ARM.ActiveCfg = Release|ARM + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release|ARM.Build.0 = Release|ARM + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release|Mixed Platforms.Build.0 = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release|Win32.ActiveCfg = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release|Win32.Build.0 = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release|x64.ActiveCfg = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release|x86.ActiveCfg = Release|Win32 + {C8D75245-FFCF-4932-A228-C9CC8BB60B03}.Release|x86.Build.0 = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug Private Beta|Win32.ActiveCfg = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug Private Beta|Win32.Build.0 = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug Private Beta|x64.ActiveCfg = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug Private Beta|x86.ActiveCfg = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug Private Beta|x86.Build.0 = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug|ARM.ActiveCfg = Debug|ARM + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug|ARM.Build.0 = Debug|ARM + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug|Win32.ActiveCfg = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug|Win32.Build.0 = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug|x64.ActiveCfg = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug|x86.ActiveCfg = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Debug|x86.Build.0 = Debug|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release Private Beta|Any CPU.ActiveCfg = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release Private Beta|ARM.Build.0 = Release|ARM + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release Private Beta|Mixed Platforms.Build.0 = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release Private Beta|Win32.ActiveCfg = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release Private Beta|Win32.Build.0 = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release Private Beta|x64.ActiveCfg = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release Private Beta|x86.ActiveCfg = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release Private Beta|x86.Build.0 = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release|Any CPU.ActiveCfg = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release|ARM.ActiveCfg = Release|ARM + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release|ARM.Build.0 = Release|ARM + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release|Mixed Platforms.Build.0 = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release|Win32.ActiveCfg = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release|Win32.Build.0 = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release|x64.ActiveCfg = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release|x86.ActiveCfg = Release|Win32 + {BBABEEA1-494C-4618-96E3-399873A5558B}.Release|x86.Build.0 = Release|Win32 + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Any CPU + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug Private Beta|Any CPU.Build.0 = Debug|Any CPU + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug Private Beta|Win32.ActiveCfg = Debug|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug Private Beta|Win32.Build.0 = Debug|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug Private Beta|x64.ActiveCfg = Debug|Any CPU + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug Private Beta|x86.ActiveCfg = Debug|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug Private Beta|x86.Build.0 = Debug|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug|ARM.ActiveCfg = Debug|ARM + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug|ARM.Build.0 = Debug|ARM + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug|Win32.ActiveCfg = Debug|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug|Win32.Build.0 = Debug|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug|x64.ActiveCfg = Debug|Any CPU + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug|x86.ActiveCfg = Debug|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Debug|x86.Build.0 = Debug|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Release Private Beta|Any CPU.ActiveCfg = Release|Any CPU + {820034C1-645D-4340-8813-D980C1EF77DE}.Release Private Beta|Any CPU.Build.0 = Release|Any CPU + {820034C1-645D-4340-8813-D980C1EF77DE}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {820034C1-645D-4340-8813-D980C1EF77DE}.Release Private Beta|ARM.Build.0 = Release|ARM + {820034C1-645D-4340-8813-D980C1EF77DE}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Release Private Beta|Mixed Platforms.Build.0 = Release|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Release Private Beta|Win32.ActiveCfg = Release|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Release Private Beta|Win32.Build.0 = Release|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Release Private Beta|x64.ActiveCfg = Release|Any CPU + {820034C1-645D-4340-8813-D980C1EF77DE}.Release Private Beta|x86.ActiveCfg = Release|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Release Private Beta|x86.Build.0 = Release|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {820034C1-645D-4340-8813-D980C1EF77DE}.Release|Any CPU.Build.0 = Release|Any CPU + {820034C1-645D-4340-8813-D980C1EF77DE}.Release|ARM.ActiveCfg = Release|ARM + {820034C1-645D-4340-8813-D980C1EF77DE}.Release|ARM.Build.0 = Release|ARM + {820034C1-645D-4340-8813-D980C1EF77DE}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Release|Mixed Platforms.Build.0 = Release|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Release|Win32.ActiveCfg = Release|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Release|Win32.Build.0 = Release|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Release|x64.ActiveCfg = Release|Any CPU + {820034C1-645D-4340-8813-D980C1EF77DE}.Release|x86.ActiveCfg = Release|x86 + {820034C1-645D-4340-8813-D980C1EF77DE}.Release|x86.Build.0 = Release|x86 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug Private Beta|Win32.ActiveCfg = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug Private Beta|Win32.Build.0 = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug Private Beta|x64.ActiveCfg = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug Private Beta|x86.ActiveCfg = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug Private Beta|x86.Build.0 = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug|ARM.ActiveCfg = Debug|ARM + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug|ARM.Build.0 = Debug|ARM + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug|Win32.ActiveCfg = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug|Win32.Build.0 = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug|x64.ActiveCfg = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug|x86.ActiveCfg = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Debug|x86.Build.0 = Debug|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release Private Beta|Any CPU.ActiveCfg = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release Private Beta|ARM.Build.0 = Release|ARM + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release Private Beta|Mixed Platforms.Build.0 = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release Private Beta|Win32.ActiveCfg = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release Private Beta|Win32.Build.0 = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release Private Beta|x64.ActiveCfg = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release Private Beta|x86.ActiveCfg = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release Private Beta|x86.Build.0 = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release|Any CPU.ActiveCfg = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release|ARM.ActiveCfg = Release|ARM + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release|ARM.Build.0 = Release|ARM + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release|Mixed Platforms.Build.0 = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release|Win32.ActiveCfg = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release|Win32.Build.0 = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release|x64.ActiveCfg = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release|x86.ActiveCfg = Release|Win32 + {B51DD8C5-335D-4A2D-B429-6D0F41ED0281}.Release|x86.Build.0 = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug Private Beta|Any CPU.ActiveCfg = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug Private Beta|ARM.ActiveCfg = Debug|ARM + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug Private Beta|ARM.Build.0 = Debug|ARM + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug Private Beta|Mixed Platforms.ActiveCfg = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug Private Beta|Mixed Platforms.Build.0 = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug Private Beta|Win32.ActiveCfg = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug Private Beta|Win32.Build.0 = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug Private Beta|x64.ActiveCfg = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug Private Beta|x86.ActiveCfg = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug Private Beta|x86.Build.0 = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug|ARM.ActiveCfg = Debug|ARM + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug|ARM.Build.0 = Debug|ARM + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug|Mixed Platforms.Build.0 = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug|Win32.ActiveCfg = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug|Win32.Build.0 = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug|x64.ActiveCfg = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug|x86.ActiveCfg = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Debug|x86.Build.0 = Debug|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release Private Beta|Any CPU.ActiveCfg = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release Private Beta|ARM.ActiveCfg = Release|ARM + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release Private Beta|ARM.Build.0 = Release|ARM + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release Private Beta|Mixed Platforms.ActiveCfg = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release Private Beta|Mixed Platforms.Build.0 = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release Private Beta|Win32.ActiveCfg = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release Private Beta|Win32.Build.0 = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release Private Beta|x64.ActiveCfg = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release Private Beta|x86.ActiveCfg = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release Private Beta|x86.Build.0 = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release|Any CPU.ActiveCfg = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release|ARM.ActiveCfg = Release|ARM + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release|ARM.Build.0 = Release|ARM + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release|Mixed Platforms.ActiveCfg = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release|Mixed Platforms.Build.0 = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release|Win32.ActiveCfg = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release|Win32.Build.0 = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release|x64.ActiveCfg = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release|x86.ActiveCfg = Release|Win32 + {CC7A35BF-AABC-411D-B911-AC037A781266}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/TelegramClient.WP81/ApplicationIcon106.png b/TelegramClient.WP81/ApplicationIcon106.png new file mode 100755 index 0000000..4376bbf Binary files /dev/null and b/TelegramClient.WP81/ApplicationIcon106.png differ diff --git a/TelegramClient.WP81/ApplicationIcon210.png b/TelegramClient.WP81/ApplicationIcon210.png new file mode 100755 index 0000000..038bb69 Binary files /dev/null and b/TelegramClient.WP81/ApplicationIcon210.png differ diff --git a/TelegramClient.WP81/Assets/emoji.faved-WXGA.png b/TelegramClient.WP81/Assets/emoji.faved-WXGA.png new file mode 100755 index 0000000..478d635 Binary files /dev/null and b/TelegramClient.WP81/Assets/emoji.faved-WXGA.png differ diff --git a/TelegramClient.WP81/Assets/emoji.stickers_none.png b/TelegramClient.WP81/Assets/emoji.stickers_none.png new file mode 100755 index 0000000..09de1a0 Binary files /dev/null and b/TelegramClient.WP81/Assets/emoji.stickers_none.png differ diff --git a/TelegramClient.WP81/Assets/light.emoji.faved-WXGA.png b/TelegramClient.WP81/Assets/light.emoji.faved-WXGA.png new file mode 100755 index 0000000..8b61034 Binary files /dev/null and b/TelegramClient.WP81/Assets/light.emoji.faved-WXGA.png differ diff --git a/TelegramClient.WP81/Assets/photo_flip.png b/TelegramClient.WP81/Assets/photo_flip.png new file mode 100755 index 0000000..79910ff Binary files /dev/null and b/TelegramClient.WP81/Assets/photo_flip.png differ diff --git a/TelegramClient.WP81/Assets/photo_paint.png b/TelegramClient.WP81/Assets/photo_paint.png new file mode 100755 index 0000000..300529d Binary files /dev/null and b/TelegramClient.WP81/Assets/photo_paint.png differ diff --git a/TelegramClient.WP81/Assets/photo_paint_brush.png b/TelegramClient.WP81/Assets/photo_paint_brush.png new file mode 100755 index 0000000..619dcf4 Binary files /dev/null and b/TelegramClient.WP81/Assets/photo_paint_brush.png differ diff --git a/TelegramClient.WP81/Assets/photo_paint_text.png b/TelegramClient.WP81/Assets/photo_paint_text.png new file mode 100755 index 0000000..6a8aa75 Binary files /dev/null and b/TelegramClient.WP81/Assets/photo_paint_text.png differ diff --git a/TelegramClient.WP81/Assets/photo_sticker.png b/TelegramClient.WP81/Assets/photo_sticker.png new file mode 100755 index 0000000..4bfd751 Binary files /dev/null and b/TelegramClient.WP81/Assets/photo_sticker.png differ diff --git a/TelegramClient.WP81/Assets/photo_undo.png b/TelegramClient.WP81/Assets/photo_undo.png new file mode 100755 index 0000000..1e1e3d8 Binary files /dev/null and b/TelegramClient.WP81/Assets/photo_undo.png differ diff --git a/TelegramClient.WP81/BackgroundProcess.cs b/TelegramClient.WP81/BackgroundProcess.cs new file mode 100755 index 0000000..56c8d76 --- /dev/null +++ b/TelegramClient.WP81/BackgroundProcess.cs @@ -0,0 +1,182 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading; +using Microsoft.Phone.Networking.Voip; +using PhoneVoIPApp.BackEnd; +using PhoneVoIPApp.BackEnd.OutOfProcess; + +namespace PhoneVoIPApp.UI +{ + /// + /// A class used by the VoIP UI to connect to and control the VoIP background agent host process. + /// + /// This class is a singleton. + public sealed class BackgroundProcessController + { + #region Properties + + /// + /// Get the single instance of this class + /// + public static BackgroundProcessController Instance + { + get + { + if (BackgroundProcessController.singleton == null) + { + BackgroundProcessController.singleton = new BackgroundProcessController(); + } + + return BackgroundProcessController.singleton; + } + } + + /// + /// Get the object that can be used to create and control VoIP calls. + /// + /// The returned object is a proxy object to the real call controller + /// object that exists in the VoIP background agent host process. + public CallController CallController + { + get + { + if (server != null) + { + return server.CallController; + } + + return null; + } + } + + #endregion + + #region Methods + + /// + /// A method that lets the VoIP background process know that the UI process is connected to it. + /// Call this method at the beginning of the Launching and Activated event handlers. + /// + public void ConnectUi() + { + if (this.isConnected) + { + // Nothing more to be done + return; + } + + // Start the VoIP background agent host process, if it is not started already + int backgroundProcessId; + try + { + VoipBackgroundProcess.Launch(out backgroundProcessId); + } + catch (Exception err) + { + Debug.WriteLine("[App] Error launching VoIP background process. UI may no longer be in the foreground. Exception: " + err.Message); + throw; + } + + // Wait for the background process to become ready + string backgroundProcessReadyEventName = Globals.GetBackgroundProcessReadyEventName((uint)backgroundProcessId); + using (EventWaitHandle backgroundProcessReadyEvent = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset, name: backgroundProcessReadyEventName)) + { + TimeSpan timeout = Debugger.IsAttached ? BackgroundProcessController.indefiniteWait : BackgroundProcessController.fifteenSeconds; + if (!backgroundProcessReadyEvent.WaitOne(timeout)) + { + // We timed out - something is wrong + throw new InvalidOperationException(string.Format("The background process did not become ready in {0} milliseconds", timeout.Milliseconds)); + } + else + { + Debug.WriteLine("[App] Background process {0} is ready", backgroundProcessId); + } + } + + // The background process is now ready. + // It is possible that the background process now becomes "not ready" again, but the chances of this happening are slim, + // and in that case, the following statement would fail - so, at this point, we don't explicitly guard against this condition. + + // Create an instance of the server in the background process. + this.server = (Server)WindowsRuntimeMarshal.GetActivationFactory(typeof(Server)).ActivateInstance(); + + // Un-set an event that indicates that the UI process is disconnected from the background process. + // The VoIP background process waits for this event to get set before shutting down. + // This ensures that the VoIP background agent host process doesn't shut down while the UI process is connected to it. + string uiDisconnectedEventName = Globals.GetUiDisconnectedEventName((uint)backgroundProcessId); + this.uiDisconnectedEvent = new EventWaitHandle(initialState: false, mode: EventResetMode.ManualReset, name: uiDisconnectedEventName); + this.uiDisconnectedEvent.Reset(); + + // The UI process is now connected to the background process + this.isConnected = true; + } + + /// + /// A method that lets the VoIP background process know that the UI is no longer connected to it. + /// Call this method at the end of the the Deactivated and Closing event handlers. + /// + public void DisconnectUi() + { + if (!this.isConnected) + { + // Nothing more to be done + return; + } + + // This process is no longer connected to the background process + this.isConnected = false; + + // From this point onwards, it is no longer safe to use any objects in the VoIP background process, + // or for the VoIP background process to call back into this process. + this.server = null; + + // Lastly, set the event that indicates that the UI is no longer connected to the background process. + if (this.uiDisconnectedEvent != null) + { + this.uiDisconnectedEvent.Set(); + this.uiDisconnectedEvent.Dispose(); + this.uiDisconnectedEvent = null; + } + } + + #endregion + + #region Private members + + /// + /// Private constructor + /// + private BackgroundProcessController() + { + // Nothing to do here + } + + // A timespan representing fifteen seconds + private static readonly TimeSpan fifteenSeconds = new TimeSpan(0, 0, 15); + + // A timespan representing an indefinite wait + private static readonly TimeSpan indefiniteWait = new TimeSpan(0, 0, 0, 0, -1); + + // The single instance of this class + private static BackgroundProcessController singleton; + + // Indicates if the UI process is in the foreground or not + private bool isConnected; + + // An event that indicates that the UI process is no longer connected to the background process + private EventWaitHandle uiDisconnectedEvent; + + // A proxy to the server object in the VoIP background agent host process + private Server server; + + #endregion + } +} diff --git a/TelegramClient.WP81/Behaviors/FocusNextElementOnEnterBehavior.cs b/TelegramClient.WP81/Behaviors/FocusNextElementOnEnterBehavior.cs new file mode 100755 index 0000000..15fbd21 --- /dev/null +++ b/TelegramClient.WP81/Behaviors/FocusNextElementOnEnterBehavior.cs @@ -0,0 +1,52 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Interactivity; + +namespace TelegramClient.Behaviors +{ + public class FocusNextElementOnEnterBehavior : Behavior + { + public static readonly DependencyProperty NextControlProperty = DependencyProperty.Register( + "NextControl", typeof (Control), typeof (FocusNextElementOnEnterBehavior), new PropertyMetadata(default(Control))); + + public Control NextControl + { + get { return (Control) GetValue(NextControlProperty); } + set { SetValue(NextControlProperty, value); } + } + + protected override void OnAttached() + { + base.OnAttached(); + + AssociatedObject.KeyDown += AssociatedObject_KeyDown; + } + + private void AssociatedObject_KeyDown(object sender, KeyEventArgs args) + { + if (args.Key == Key.Enter) + { + if (NextControl != null) + { + NextControl.Focus(); + } + } + } + + protected override void OnDetaching() + { + AssociatedObject.KeyDown -= AssociatedObject_KeyDown; + + base.OnDetaching(); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Behaviors/InfiniteScrollingBehavior.cs b/TelegramClient.WP81/Behaviors/InfiniteScrollingBehavior.cs new file mode 100755 index 0000000..486e9ac --- /dev/null +++ b/TelegramClient.WP81/Behaviors/InfiniteScrollingBehavior.cs @@ -0,0 +1,64 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows.Interactivity; +using Microsoft.Phone.Controls; + +namespace TelegramClient.Behaviors +{ + public class IncrementalLoadingTrigger : TriggerBase + { + private int _knob = 1; + + public int Knob + { + get { return _knob; } + set { _knob = value; } + } + + protected override void OnAttached() + { + base.OnAttached(); + AssociatedObject.ItemRealized += OnItemRealized; + } + + private void OnItemRealized(object sender, ItemRealizationEventArgs e) + { + var longListSelector = sender as LongListSelector; + if (longListSelector == null) + { + return; + } + + var item = e.Container.Content; + var items = longListSelector.ItemsSource; + var index = items.IndexOf(item); + + //if (items.Count >= Knob + // && e.Container.Content.Equals(longListSelector.ItemsSource[longListSelector.ItemsSource.Count - Knob])) + //{ + // InvokeActions(null); + //} + + if (items.Count - index <= Knob) + { + InvokeActions(null); + } + } + + protected override void OnDetaching() + { + base.OnDetaching(); + AssociatedObject.ItemRealized -= OnItemRealized; + } + } + + public class InfiniteScrollingBehavior : Behavior + { + + } +} diff --git a/TelegramClient.WP81/BugsenseWrapper.cs b/TelegramClient.WP81/BugsenseWrapper.cs new file mode 100755 index 0000000..da433fc --- /dev/null +++ b/TelegramClient.WP81/BugsenseWrapper.cs @@ -0,0 +1,83 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Windows; +using BugSense; +using Telegram.Api.TL; + +namespace TelegramClient +{ + class BugSenseWrapper + { + private static readonly List> _delayedErrors = new List>(); + + private static readonly object _bugSenseSyncRoot = new object(); + + private static bool _isInitialized; + + private BugSenseWrapper() + { + + } + + public static void LogError(Exception ex, string comment = null, NotificationOptions options = null) + { + lock (_bugSenseSyncRoot) + { + if (!_isInitialized) + { + _delayedErrors.Add(new Tuple(ex, comment, options)); + return; + } + } + + try + { + BugSenseHandler.Instance.LogError(ex, comment, options); + } + catch (Exception e) + { + Telegram.Logs.Log.Write("BugSenseWrapper\n" + e); + } + } + + public static void Init() + { +#if PRIVATE_BETA + const string apiKey = "b6f57378"; +#else + const string apiKey = "e715f5e8"; +#endif + BugSenseHandler.Instance.Init(Application.Current, apiKey, new NotificationOptions { Type = enNotificationType.None }); + BugSenseHandler.Instance.UnhandledException += (sender, args) => + { + TLUtils.WriteLine(args.ExceptionObject.ToString(), LogSeverity.Error); + + args.Handled = true; + }; + + lock (_bugSenseSyncRoot) + { + _isInitialized = true; + foreach (var error in _delayedErrors) + { + try + { + BugSenseHandler.Instance.LogError(error.Item1, error.Item2, error.Item3); + } + catch (Exception ex) + { + Telegram.Logs.Log.Write("BugSenseWrapper delayed\n" + ex); + } + } + _delayedErrors.Clear(); + } + } + } +} diff --git a/TelegramClient.WP81/Controls/GestureListener/GestureHelperEventArgs.cs b/TelegramClient.WP81/Controls/GestureListener/GestureHelperEventArgs.cs new file mode 100755 index 0000000..5174135 --- /dev/null +++ b/TelegramClient.WP81/Controls/GestureListener/GestureHelperEventArgs.cs @@ -0,0 +1,324 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +namespace TelegramClient.Controls.GestureListener +{ + /// + /// The base class for all gesture events. Also used by Tap, DoubleTap and Hold. + /// + public class GestureEventArgs : System.EventArgs + { + /// + /// The point, in unrotated screen coordinates, where the gesture occurred. + /// + protected Point GestureOrigin { get; private set; } + + /// + /// The point, in unrotated screen coordinates, where the first touchpoint is now. + /// + protected Point TouchPosition { get; private set; } + + internal GestureEventArgs(Point gestureOrigin, Point position) + { + GestureOrigin = gestureOrigin; + TouchPosition = position; + } + + /// + /// The first hit-testable item under the touch point. Determined by a combination of order in the tree and + /// Z-order. + /// + public object OriginalSource { get; internal set; } + + /// + /// If an event handler sets this to true, it stops event bubbling. + /// + public bool Handled { get; set; } + + /// + /// Returns the position of the gesture's starting point relative to a given UIElement. + /// + /// The return value will be relative to this element. + /// The gesture's starting point relative to the given UIElement. + public Point GetPosition(UIElement relativeTo) + { + return GetPosition(relativeTo, TouchPosition); + } + + /// + /// Returns the position of a given point relative to a given UIElement. + /// + /// The return value will be relative to this element. + /// The point to translate. + /// The given point relative to the given UIElement. + protected static Point GetPosition(UIElement relativeTo, Point point) + { + if (relativeTo == null) + { + // Transform relative to RootVisual + relativeTo = Application.Current.RootVisual; + } + if (relativeTo != null) + { + // Determine position + GeneralTransform transform = relativeTo.TransformToVisual(null).Inverse; + return transform.Transform(point); + } + else + { + // Unable to transform; return point as-is + return point; + } + } + } + + /// + /// The event args used in the DragStarted event. + /// + public class DragStartedGestureEventArgs : GestureEventArgs + { + internal DragStartedGestureEventArgs(Point gestureOrigin, Orientation direction) + : base(gestureOrigin, gestureOrigin) + { + Direction = direction; + } + + /// + /// The direction of the drag gesture, as determined by the initial drag change. + /// + public Orientation Direction { get; private set; } + } + + /// + /// The event args used by the DragDelta event. + /// + public class DragDeltaGestureEventArgs : GestureEventArgs + { + internal DragDeltaGestureEventArgs(Point gestureOrigin, Point currentPosition, Point change, Orientation direction) + : base(gestureOrigin, currentPosition) + { + HorizontalChange = change.X; + VerticalChange = change.Y; + Direction = direction; + } + + /// + /// The horizontal (X) change for this drag event. + /// + public double HorizontalChange { get; private set; } + + /// + /// The vertical (Y) change for this drag event. + /// + public double VerticalChange { get; private set; } + + /// + /// The direction of the drag gesture, as determined by the initial drag change. + /// + public Orientation Direction { get; private set; } + } + + /// + /// The event args used by the DragCompleted event. + /// + public class DragCompletedGestureEventArgs : GestureEventArgs + { + internal DragCompletedGestureEventArgs(Point gestureOrigin, Point currentPosition, Point change, Orientation direction, Point finalVelocity) + : base(gestureOrigin, currentPosition) + { + HorizontalChange = change.X; + VerticalChange = change.Y; + Direction = direction; + HorizontalVelocity = finalVelocity.X; + VerticalVelocity = finalVelocity.Y; + } + + /// + /// The total horizontal (X) change of the drag event. + /// + public double HorizontalChange { get; private set; } + + /// + /// The total vertical (Y) change of the drag event. + /// + public double VerticalChange { get; private set; } + + /// + /// The direction of the drag gesture, as determined by the initial drag change. + /// + public Orientation Direction { get; private set; } + + /// + /// The final horizontal (X) velocity of the drag, if the drag was inertial. + /// + public double HorizontalVelocity { get; private set; } + + /// + /// The final vertical (Y) velocity of the drag, if the drag was inertial. + /// + public double VerticalVelocity { get; private set; } + } + + /// + /// The event args used by the Flick event. + /// + public class FlickGestureEventArgs : GestureEventArgs + { + private Point _velocity; + + internal FlickGestureEventArgs(Point hostOrigin, Point velocity) + : base(hostOrigin, hostOrigin) + { + _velocity = velocity; + } + + /// + /// The horizontal (X) velocity of the flick. + /// + public double HorizontalVelocity { get { return _velocity.X; } } + + /// + /// The vertical (Y) velocity of the flick. + /// + public double VerticalVelocity { get { return _velocity.Y; } } + + /// + /// The angle of the flick. + /// + public double Angle + { + get { return MathHelpers.GetAngle(_velocity.X, _velocity.Y); } + } + + /// + /// The direction of the flick gesture, as determined by the flick velocities. + /// + public Orientation Direction + { + get { return Math.Abs(_velocity.X) >= Math.Abs(_velocity.Y) ? Orientation.Horizontal : Orientation.Vertical; } + } + } + + /// + /// The base class for multi-touch gesture event args. Currently used only for + /// two-finger (pinch) operations. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Multi")] + public class MultiTouchGestureEventArgs : GestureEventArgs + { + /// + /// The second touch point's initial position + /// + protected Point GestureOrigin2 { get; private set; } + + /// + /// The second touch point. The first is stored in GestureEventArgs. + /// + protected Point TouchPosition2 { get; private set; } + + internal MultiTouchGestureEventArgs(Point gestureOrigin, Point gestureOrigin2, Point position, Point position2) + : base(gestureOrigin, position) + { + GestureOrigin2 = gestureOrigin2; + TouchPosition2 = position2; + } + + /// + /// Returns the position of either of the two touch points (0 or 1) relative to + /// the UIElement provided. + /// + /// The return value will be relative to this element. + /// The touchpoint to use (0 or 1). + /// The gesture's starting point relative to the given UIElement. + public Point GetPosition(UIElement relativeTo, int index) + { + if (index == 0) + { + return GetPosition(relativeTo); + } + else if (index == 1) + { + return GetPosition(relativeTo, TouchPosition2); + } + else + throw new ArgumentOutOfRangeException("index"); + } + } + + /// + /// The event args used by the PinchStarted event. + /// + public class PinchStartedGestureEventArgs : MultiTouchGestureEventArgs + { + internal PinchStartedGestureEventArgs(Point gestureOrigin, Point gestureOrigin2, Point pinch, Point pinch2) + : base(gestureOrigin, gestureOrigin2, pinch, pinch2) + { + } + + /// + /// The distance between the two touch points. + /// + public double Distance + { + get { return MathHelpers.GetDistance(TouchPosition, TouchPosition2); } + } + + /// + /// The angle defined by the two touch points. + /// + public double Angle + { + get { return MathHelpers.GetAngle(TouchPosition2.X - TouchPosition.X, TouchPosition2.Y - TouchPosition.Y); } + } + } + + /// + /// The event args used by the PinchDelta and PinchCompleted events. + /// + public class PinchGestureEventArgs : MultiTouchGestureEventArgs + { + internal PinchGestureEventArgs(Point gestureOrigin, Point gestureOrigin2, Point position, Point position2) + : base(gestureOrigin, gestureOrigin2, position, position2) + { + } + + /// + /// Returns the ratio of the current distance between touchpoints / the original distance + /// between the touchpoints. + /// + public double DistanceRatio + { + get + { + double originalDistance = Math.Max(MathHelpers.GetDistance(GestureOrigin, GestureOrigin2), 1.0); + double newDistance = Math.Max(MathHelpers.GetDistance(TouchPosition, TouchPosition2), 1.0); + + return newDistance / originalDistance; + } + } + + /// + /// Returns the difference in angle between the current touch positions and the original + /// touch positions. + /// + public double TotalAngleDelta + { + get + { + double oldAngle = MathHelpers.GetAngle(GestureOrigin2.X - GestureOrigin.X, GestureOrigin2.Y - GestureOrigin.Y); + double newAngle = MathHelpers.GetAngle(TouchPosition2.X - TouchPosition.X, TouchPosition2.Y - TouchPosition.Y); + + return newAngle - oldAngle; + } + } + } +} diff --git a/TelegramClient.WP81/Controls/GestureListener/GestureListener.cs b/TelegramClient.WP81/Controls/GestureListener/GestureListener.cs new file mode 100755 index 0000000..04557cc --- /dev/null +++ b/TelegramClient.WP81/Controls/GestureListener/GestureListener.cs @@ -0,0 +1,90 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace TelegramClient.Controls.GestureListener +{ + //public enum GestureType + //{ + // None = 0, + // Tap = 1, + // DoubleTap = 2, + // Hold = 4, + // HorizontalDrag = 8, + // VerticalDrag = 16, + // FreeDrag = 32, + // PinchDelta = 64, + // Flick = 128, + // DragCompleted = 256, + // PinchCompleted = 512, + //} + + public partial class GestureListener + { + /// + /// The GestureBegin event. + /// + public event EventHandler GestureBegin; + + /// + /// The GestureCompleted event. + /// + public event EventHandler GestureCompleted; + + /// + /// The Tap event (touch, release, no movement). + /// + public event EventHandler Tap; + + /// + /// The DoubleTap event is raised instead of Tap if the time between two taps is short eonugh. + /// + public event EventHandler DoubleTap; + + /// + /// The Hold event (touch and hold for one second) + /// + public event EventHandler Hold; + + /// + /// The DragStarted event. + /// + public event EventHandler DragStarted; + + /// + /// The DragDelta event. + /// + public event EventHandler DragDelta; + + /// + /// The DragCompleted event. Will be raised on touch release after a drag, or + /// when a second touch point is added. + /// + public event EventHandler DragCompleted; + + /// + /// The Flick event. Raised when a drag that was fast enough ends with a release. + /// + public event EventHandler Flick; + + /// + /// The PinchStarted event. + /// + public event EventHandler PinchStarted; + + /// + /// Any two-touch point (two finger) operation. + /// + public event EventHandler PinchDelta; + + /// + /// The end of a pinch operation. + /// + public event EventHandler PinchCompleted; + } +} diff --git a/TelegramClient.WP81/Controls/GestureListener/GestureListenerStatic.cs b/TelegramClient.WP81/Controls/GestureListener/GestureListenerStatic.cs new file mode 100755 index 0000000..c6cf9a0 --- /dev/null +++ b/TelegramClient.WP81/Controls/GestureListener/GestureListenerStatic.cs @@ -0,0 +1,388 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Threading; +using Microsoft.Xna.Framework.Input.Touch; + +namespace TelegramClient.Controls.GestureListener +{ + /// + /// The GestureListener class raises events similar to those provided by the XNA TouchPanel, but it is designed for + /// XAML's event-driven model, rather than XNA's loop/polling model, and it also takes care of the hit testing + /// and event routing. + /// + public partial class GestureListener + { + private static DispatcherTimer _timer; + + private static bool _isInTouch; + + private static List _elements; + + private static Point _gestureOrigin; + private static bool _gestureOriginChanged; + private static Nullable _gestureOrientation; + + private static Point _cumulativeDelta; + private static Point _cumulativeDelta2; + + private static Point _finalVelocity; + + private static Point _pinchOrigin; + private static Point _pinchOrigin2; + + private static Point _lastSamplePosition; + private static Point _lastSamplePosition2; + + private static bool _isPinching; + private static bool _flicked; + private static bool _isDragging; + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Justification="Need static ctor for more than instantiation")] + static GestureListener() + { + Touch.FrameReported += OnTouchFrameReported; + + TouchPanel.EnabledGestures = + GestureType.Tap | + GestureType.DoubleTap | + GestureType.Hold | + GestureType.FreeDrag | + GestureType.DragComplete | + GestureType.Flick | + GestureType.Pinch | + GestureType.PinchComplete; + + _timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(100) }; + _timer.Tick += OnTimerTick; + } + + /// + /// Handle touch events. + /// + /// + /// + private static void OnTouchFrameReported(object sender, TouchFrameEventArgs e) + { + bool newIsInTouch = false; + Point gestureOrigin = new Point(0, 0); + + foreach (TouchPoint point in e.GetTouchPoints(null)) + { + if (point.Action != TouchAction.Up) + { + gestureOrigin = point.Position; + newIsInTouch = true; + break; + } + } + + if (!_isInTouch && newIsInTouch) + { + // The user was not in the middle of a gesture, but one has started. + _gestureOrigin = gestureOrigin; + TouchStart(); + } + else if (_isInTouch && !newIsInTouch) + { + // The user was in the middle of a gesture, but there are no active + // touch points anymore. + TouchComplete(); + } + else if (_isInTouch) + { + // The state has not changed, and the user was in the middle of a gesture. + TouchDelta(); + } + else + { + // Possible error condition? The user was not in the middle of a + // gesture, but a Touch.FrameReported event was received with no + // active touch points. We should poll the TouchPanel just to be + // safe, but do so in such a way that resets the state. + TouchStart(); + } + + _isInTouch = newIsInTouch; + } + + /// + /// A touch has started. + /// + private static void TouchStart() + { + _cumulativeDelta.X = _cumulativeDelta.Y = _cumulativeDelta2.X = _cumulativeDelta2.Y = 0; + _finalVelocity.X = _finalVelocity.Y = 0; + _isDragging = _flicked = false; + _elements = new List(VisualTreeHelper.FindElementsInHostCoordinates(_gestureOrigin, Application.Current.RootVisual)); + _gestureOriginChanged = false; + + RaiseGestureEvent((helper) => helper.GestureBegin, () => new TelegramClient.Controls.GestureListener.GestureEventArgs(_gestureOrigin, _gestureOrigin), false); + + ProcessTouchPanelEvents(); + _timer.Start(); + //System.Diagnostics.Debug.WriteLine("timer start"); + } + + /// + /// A touch is continuing... + /// + private static void TouchDelta() + { + ProcessTouchPanelEvents(); + } + + /// + /// A touch has ended. + /// + private static void TouchComplete() + { + ProcessTouchPanelEvents(); + + RaiseGestureEvent((helper) => helper.GestureCompleted, () => new TelegramClient.Controls.GestureListener.GestureEventArgs(_gestureOrigin, _lastSamplePosition), false); + + _elements = null; + _gestureOrientation = null; + _timer.Stop(); + //System.Diagnostics.Debug.WriteLine("timer stop"); + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification="Issue manifests as a varity of exceptions.")] + static void OnTimerTick(object sender, System.EventArgs e) + { + try + { + ProcessTouchPanelEvents(); + } + catch + { + // In certain rare conditions TouchPanel.IsGestureAvailable will + // throw an exception due to an internal race condition in XNA. + // The exception can be ignored and the next call to the method + // will succeed. + } + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] + private static void ProcessTouchPanelEvents() + { + Point delta = new Point(0, 0); + + GeneralTransform deltaTransform = null; + + while (TouchPanel.IsGestureAvailable) + { + GestureSample sample = TouchPanel.ReadGesture(); + + Point samplePosition = sample.Position.ToPoint(); + Point samplePosition2 = sample.Position2.ToPoint(); + + Point sampleDelta = sample.Delta.ToPoint(); + GetTranslatedDelta(ref deltaTransform, ref sampleDelta, ref _cumulativeDelta, sample.GestureType != GestureType.Flick); + Point sampleDelta2 = sample.Delta2.ToPoint(); + GetTranslatedDelta(ref deltaTransform, ref sampleDelta2, ref _cumulativeDelta2, sample.GestureType != GestureType.Flick); + + // Example: if a drag becomes a pinch, or vice-versa, we want to change the elements receiving the event + if (_elements == null || _gestureOriginChanged) + { + _gestureOrigin = samplePosition; + _elements = new List(VisualTreeHelper.FindElementsInHostCoordinates(_gestureOrigin, Application.Current.RootVisual)); + _gestureOriginChanged = false; + } + + if (!_gestureOrientation.HasValue && (sampleDelta.X != 0 || sampleDelta.Y != 0)) + { + _gestureOrientation = Math.Abs(sampleDelta.X) >= Math.Abs(sampleDelta.Y) ? Orientation.Horizontal : Orientation.Vertical; + } + + //System.Diagnostics.Debug.WriteLine(sample.GestureType); + switch (sample.GestureType) + { + case GestureType.Tap: + RaiseGestureEvent((helper) => helper.Tap, () => new TelegramClient.Controls.GestureListener.GestureEventArgs(_gestureOrigin, samplePosition), false); + break; + + case GestureType.DoubleTap: + RaiseGestureEvent((helper) => helper.DoubleTap, () => new TelegramClient.Controls.GestureListener.GestureEventArgs(_gestureOrigin, samplePosition), false); + break; + + case GestureType.Hold: + RaiseGestureEvent((helper) => helper.Hold, () => new TelegramClient.Controls.GestureListener.GestureEventArgs(_gestureOrigin, samplePosition), false); + break; + + case GestureType.FreeDrag: + if (sampleDelta.X != 0 || sampleDelta.Y != 0) + { + if (!_isDragging) + { + RaiseGestureEvent((helper) => helper.DragStarted, () => new TelegramClient.Controls.GestureListener.DragStartedGestureEventArgs(_gestureOrigin, _gestureOrientation.Value), true); + _isDragging = true; + } + + delta.X += sampleDelta.X; + delta.Y += sampleDelta.Y; + _lastSamplePosition = samplePosition; + } + break; + + case GestureType.DragComplete: + if (!_flicked) + { + if (delta.X != 0 || delta.Y != 0) + { + // raise drag + RaiseGestureEvent((helper) => helper.DragDelta, () => new TelegramClient.Controls.GestureListener.DragDeltaGestureEventArgs(_gestureOrigin, samplePosition, delta, _gestureOrientation.Value), false); + delta.X = delta.Y = 0; + } + } + + if (_isDragging) + { + RaiseGestureEvent((helper) => helper.DragCompleted, () => new TelegramClient.Controls.GestureListener.DragCompletedGestureEventArgs(_gestureOrigin, _lastSamplePosition, _cumulativeDelta, _gestureOrientation.Value, _finalVelocity), false); + delta.X = delta.Y = 0; + } + + _cumulativeDelta.X = _cumulativeDelta.Y = 0; + _flicked = _isDragging = false; + _gestureOriginChanged = true; + break; + + case GestureType.Flick: + // Do not raise any additional drag events that may be queued. + _flicked = true; + _finalVelocity = sampleDelta; + RaiseGestureEvent((helper) => helper.Flick, () => new TelegramClient.Controls.GestureListener.FlickGestureEventArgs(_gestureOrigin, sampleDelta), true); + break; + + case GestureType.Pinch: + { + if (!_isPinching) + { + _isPinching = true; + _pinchOrigin = samplePosition; + _pinchOrigin2 = samplePosition2; + RaiseGestureEvent((helper) => helper.PinchStarted, () => new TelegramClient.Controls.GestureListener.PinchStartedGestureEventArgs(_pinchOrigin, _pinchOrigin2, _pinchOrigin, _pinchOrigin2), true); + } + + _lastSamplePosition = samplePosition; + _lastSamplePosition2 = samplePosition2; + RaiseGestureEvent((helper) => helper.PinchDelta, () => new TelegramClient.Controls.GestureListener.PinchGestureEventArgs(_pinchOrigin, _pinchOrigin2, samplePosition, samplePosition2), false); + } + break; + + case GestureType.PinchComplete: + _isPinching = false; + RaiseGestureEvent((helper) => helper.PinchCompleted, () => new TelegramClient.Controls.GestureListener.PinchGestureEventArgs(_pinchOrigin, _pinchOrigin2, _lastSamplePosition, _lastSamplePosition2), false); + _cumulativeDelta.X = _cumulativeDelta.Y = _cumulativeDelta2.X = _cumulativeDelta2.Y = 0; + _gestureOriginChanged = true; + break; + } + } + + if (!_flicked && (delta.X != 0 || delta.Y != 0)) + { + RaiseGestureEvent((helper) => helper.DragDelta, () => new TelegramClient.Controls.GestureListener.DragDeltaGestureEventArgs(_gestureOrigin, _lastSamplePosition, delta, _gestureOrientation.Value), false); + } + } + + private static void GetTranslatedDelta( + ref GeneralTransform deltaTransform, + ref Point sampleDelta, + ref Point cumulativeDelta, + bool addToCumulative) + { + if (sampleDelta.X != 0 || sampleDelta.Y != 0) + { + if (deltaTransform == null && Application.Current.RootVisual != null) + { + deltaTransform = GetInverseRootTransformNoOffset(); + } + if (deltaTransform != null) + { + sampleDelta = deltaTransform.Transform(sampleDelta); + if (addToCumulative) + { + cumulativeDelta.X += sampleDelta.X; + cumulativeDelta.Y += sampleDelta.Y; + } + } + } + } + + private static GeneralTransform GetInverseRootTransformNoOffset() + { + GeneralTransform transform = Application.Current.RootVisual.TransformToVisual(null).Inverse; + + MatrixTransform matrixTransform = transform as MatrixTransform; + if (matrixTransform != null) + { + Matrix matrix = matrixTransform.Matrix; + matrix.OffsetX = matrix.OffsetY = 0; + matrixTransform.Matrix = matrix; + } + + return transform; + } + + /// + /// This method does all the necessary work to raise a gesture event. It sets the orginal source, does the routing, + /// handles Handled, and only creates the event args if they are needed. + /// + /// This is the type of event args that will be raised. + /// Gets the specific event to raise. + /// Lazy creator function for the event args. + /// Indicates whether the mouse capture should be released + private static void RaiseGestureEvent(Func> eventGetter, Func argsGetter, bool releaseMouseCapture) where T : TelegramClient.Controls.GestureListener.GestureEventArgs + { + T args = null; + + FrameworkElement originalSource = null; + bool handled = false; + + foreach (FrameworkElement element in _elements) + { + if (releaseMouseCapture) + { + element.ReleaseMouseCapture(); + } + + if (!handled) + { + if (originalSource == null) + { + originalSource = element; + } + + GestureListener helper = GestureService.GetGestureListenerInternal(element, false); + if (helper != null) + { + SafeRaise.Raise(eventGetter(helper), element, () => + { + if (args == null) + { + args = argsGetter(); + args.OriginalSource = originalSource; + } + return args; + }); + } + + if (args != null && args.Handled == true) + { + handled = true; + } + } + } + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Controls/GestureListener/GestureService.cs b/TelegramClient.WP81/Controls/GestureListener/GestureService.cs new file mode 100755 index 0000000..4baa014 --- /dev/null +++ b/TelegramClient.WP81/Controls/GestureListener/GestureService.cs @@ -0,0 +1,87 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; + +namespace TelegramClient.Controls.GestureListener +{ + /// + /// The GestureService class is the helper for getting and setting GestureListeners + /// on elements. + /// + public static class GestureService + { + /// + /// Gets a GestureListener for the new element. Will create a new one if necessary. + /// + /// The object to get the GestureListener from. + /// Either the previously existing GestureListener, or a new one. + public static TelegramClient.Controls.GestureListener.GestureListener GetGestureListener(DependencyObject obj) + { + if (obj == null) + { + throw new ArgumentNullException("obj"); + } + + return GetGestureListenerInternal(obj, true); + } + + /// + /// Gets the GestureListener on an element. If one is not set, can create a new one + /// so that this will never return null, depending on the state of the createIfMissing + /// flag. + /// + /// The object to get the GestureListener from. + /// When this is true, if the attached property was not set on the element, it will create one and set it on the element. + /// + internal static TelegramClient.Controls.GestureListener.GestureListener GetGestureListenerInternal(DependencyObject obj, bool createIfMissing) + { + TelegramClient.Controls.GestureListener.GestureListener listener = (TelegramClient.Controls.GestureListener.GestureListener)obj.GetValue(GestureListenerProperty); + if (listener == null && createIfMissing) + { + listener = new TelegramClient.Controls.GestureListener.GestureListener(); + SetGestureListenerInternal(obj, listener); + } + return listener; + } + + /// + /// Sets the GestureListener on an element. Needed for XAML, but should not be used in code. Use + /// GetGestureListener instead, which will create a new instance if one is not already set, to + /// add your handlers to an element. + /// + /// The object to set the GestureListener on. + /// The GestureListener. + [Obsolete("Do not add handlers using this method. Instead, use GetGestureListener, which will create a new instance if one is not already set, to add your handlers to an element.", true)] + public static void SetGestureListener(DependencyObject obj, TelegramClient.Controls.GestureListener.GestureListener value) + { + if (obj == null) + { + throw new ArgumentNullException("obj"); + } + + SetGestureListenerInternal(obj, value); + } + + /// + /// This is used to set the value of the attached DependencyProperty internally. + /// + /// The object to set the GestureListener on. + /// The GestureListener. + private static void SetGestureListenerInternal(DependencyObject obj, TelegramClient.Controls.GestureListener.GestureListener value) + { + obj.SetValue(GestureListenerProperty, value); + } + + /// + /// The definition of the GestureListener attached DependencyProperty. + /// + public static readonly DependencyProperty GestureListenerProperty = + DependencyProperty.RegisterAttached("GestureListener", typeof(TelegramClient.Controls.GestureListener.GestureListener), typeof(GestureService), new PropertyMetadata(null)); + } +} diff --git a/TelegramClient.WP81/Controls/GestureListener/MathHelpers.cs b/TelegramClient.WP81/Controls/GestureListener/MathHelpers.cs new file mode 100755 index 0000000..8e2ce2a --- /dev/null +++ b/TelegramClient.WP81/Controls/GestureListener/MathHelpers.cs @@ -0,0 +1,59 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define WP7 +using System; +using System.Windows; + +namespace TelegramClient.Controls.GestureListener +{ + internal static class MathHelpers + { + /// + /// Return the angle of the hypotenuse of a triangle with + /// sides defined by deltaX and deltaY. + /// + /// Change in X. + /// Change in Y. + /// The angle (in degrees). + public static double GetAngle(double deltaX, double deltaY) + { + double angle = Math.Atan2(deltaY, deltaX); + if (angle < 0) + { + angle = 2 * Math.PI + angle; + } + + return (angle * 360) / (2 * Math.PI); + } + + /// + /// Return the distance between two points + /// + /// The first point. + /// The second point. + /// The distance between the two points. + public static double GetDistance(Point p0, Point p1) + { + double dx = p0.X - p1.X; + double dy = p0.Y - p1.Y; + + return Math.Sqrt(dx * dx + dy * dy); + } +#if WP7 + /// + /// Helper extension method for turning XNA's Vector2 type into a Point + /// + /// The Vector2. + /// The point. + public static Point ToPoint(this Microsoft.Xna.Framework.Vector2 v) + { + return new Point(v.X, v.Y); + } +#endif + } +} diff --git a/TelegramClient.WP81/Controls/GestureListener/SafeRaise.cs b/TelegramClient.WP81/Controls/GestureListener/SafeRaise.cs new file mode 100755 index 0000000..cdd7bc4 --- /dev/null +++ b/TelegramClient.WP81/Controls/GestureListener/SafeRaise.cs @@ -0,0 +1,95 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics.CodeAnalysis; + +namespace TelegramClient.Controls.GestureListener +{ + /// + /// A helper class for raising events safely. + /// + internal static class SafeRaise + { + /// + /// Raises an event in a thread-safe manner, also does the null check. + /// + /// The event to raise. + /// The event sender. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")] + public static void Raise(EventHandler eventToRaise, object sender) + { + if (eventToRaise != null) + { + eventToRaise(sender, System.EventArgs.Empty); + } + } + + /// + /// Raises an event in a thread-safe manner, also does the null check. + /// + /// The event to raise. + /// The event sender. + public static void Raise(EventHandler eventToRaise, object sender) + { + Raise(eventToRaise, sender, System.EventArgs.Empty); + } + + /// + /// Raises an event in a thread-safe manner, also does the null check. + /// + /// The event args type. + /// The event to raise. + /// The event sender. + /// The event args. + public static void Raise(EventHandler eventToRaise, object sender, T args) where T : System.EventArgs + { + if (eventToRaise != null) + { + eventToRaise(sender, args); + } + } + + // Lazy event args creation example: + // + // public class MyEventArgs : EventArgs + // { + // public MyEventArgs(int x) { X = x; } + // public int X { get; set; } + // } + // + // event EventHandler Foo; + // + // public void Bar() + // { + // int y = 2; + // Raise(Foo, null, () => { return new MyEventArgs(y); }); + // } + + /// + /// This is a method that returns event args, used for lazy creation. + /// + /// The event type. + /// + public delegate T GetEventArgs() where T : System.EventArgs; + + /// + /// Raise an event in a thread-safe manner, with the required null check. Lazily creates event args. + /// + /// The event args type. + /// The event to raise. + /// The event sender. + /// The delegate to return the event args if needed. + public static void Raise(EventHandler eventToRaise, object sender, GetEventArgs getEventArgs) where T : System.EventArgs + { + if (eventToRaise != null) + { + eventToRaise(sender, getEventArgs()); + } + } + } +} diff --git a/TelegramClient.WP81/Controls/StartView/DragEventArgs.cs b/TelegramClient.WP81/Controls/StartView/DragEventArgs.cs new file mode 100755 index 0000000..9dac9ca --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/DragEventArgs.cs @@ -0,0 +1,40 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Diagnostics.CodeAnalysis; +using System.Windows; + +namespace TelegramClient.Controls.StartView +{ + internal class DragEventArgs : GestureEventArgs + { + public DragEventArgs() + { + } + + public DragEventArgs(InputDeltaArgs args) + { + if (args != null) + { + CumulativeDistance = args.CumulativeTranslation; + DeltaDistance = args.DeltaTranslation; + } + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + public bool IsTouchComplete { get; private set; } + + public Point DeltaDistance { get; private set; } + + public Point CumulativeDistance { get; internal set; } + + public void MarkAsFinalTouchManipulation() + { + IsTouchComplete = true; + } + } +} diff --git a/TelegramClient.WP81/Controls/StartView/FlickEventArgs.cs b/TelegramClient.WP81/Controls/StartView/FlickEventArgs.cs new file mode 100755 index 0000000..080f554 --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/FlickEventArgs.cs @@ -0,0 +1,14 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace TelegramClient.Controls.StartView +{ + internal class FlickEventArgs : GestureEventArgs + { + public double Angle { get; internal set; } + } +} diff --git a/TelegramClient.WP81/Controls/StartView/GestureEventArgs.cs b/TelegramClient.WP81/Controls/StartView/GestureEventArgs.cs new file mode 100755 index 0000000..61a8de6 --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/GestureEventArgs.cs @@ -0,0 +1,13 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace TelegramClient.Controls.StartView +{ + internal class GestureEventArgs : System.EventArgs + { + } +} diff --git a/TelegramClient.WP81/Controls/StartView/GestureHelper.cs b/TelegramClient.WP81/Controls/StartView/GestureHelper.cs new file mode 100755 index 0000000..8fee88b --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/GestureHelper.cs @@ -0,0 +1,208 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics.CodeAnalysis; +using System.Windows; +using System.Windows.Media; +using TelegramClient.Controls.StartView; +using DragEventArgs = TelegramClient.Controls.StartView.DragEventArgs; + +internal abstract class GestureHelper +{ + private readonly Size DeadZoneInPixels = new Size(12, 12); + + private DragLock _dragLock; + private bool _dragging; + private WeakReference _gestureSource; + private Point _gestureOrigin; + + protected GestureHelper(UIElement target, bool shouldHandleAllDrags) + { + Target = target; + ShouldHandleAllDrags = shouldHandleAllDrags; + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + protected bool ShouldHandleAllDrags { get; private set; } + + protected UIElement Target { get; private set; } + + public event EventHandler GestureStart; + + public event EventHandler Flick; + + public event EventHandler GestureEnd; + + public event EventHandler HorizontalDrag; + + public event EventHandler VerticalDrag; + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + public static GestureHelper Create(UIElement target) + { + return GestureHelper.Create(target, true); + } + + public static GestureHelper Create(UIElement target, bool shouldHandleAllDrags) + { + GestureHelper gestureHelper = new ManipulationGestureHelper(target, shouldHandleAllDrags); + gestureHelper.Start(); + return gestureHelper; + } + + protected abstract void HookEvents(); + + public void Start() + { + HookEvents(); + } + + protected void NotifyDown(InputBaseArgs args) + { + GestureEventArgs e = new GestureEventArgs(); + _gestureSource = new WeakReference(args.Source); + _gestureOrigin = args.Origin; + _dragLock = DragLock.Unset; + _dragging = false; + RaiseGestureStart(e); + } + + protected void NotifyMove(InputDeltaArgs args) + { + if (Math.Abs(args.CumulativeTranslation.X) > DeadZoneInPixels.Width || Math.Abs(args.CumulativeTranslation.Y) > DeadZoneInPixels.Height) + { + if (!_dragging) + { + ReleaseMouseCaptureAtGestureOrigin(); + } + + _dragging = true; + + if (_dragLock == DragLock.Unset) + { + double angle = GestureHelper.AngleFromVector(args.CumulativeTranslation.X, args.CumulativeTranslation.Y) % 180; + _dragLock = angle <= 45 || angle >= 135 ? DragLock.Horizontal : DragLock.Vertical; + } + } + + if (_dragging) + { + RaiseDragEvents(args); + } + } + + private void ReleaseMouseCaptureAtGestureOrigin() + { + if (_gestureSource != null) + { + FrameworkElement gestureSource = _gestureSource.Target as FrameworkElement; + if (gestureSource != null) + { + foreach (UIElement element in VisualTreeHelper.FindElementsInHostCoordinates( + gestureSource.TransformToVisual(null).Transform(_gestureOrigin), Application.Current.RootVisual)) + { + element.ReleaseMouseCapture(); + } + } + } + } + + protected void NotifyUp(InputCompletedArgs args) + { + EventArgs e = EventArgs.Empty; + _dragLock = DragLock.Unset; + _dragging = false; + + if (args.IsInertial) + { + double angle = GestureHelper.AngleFromVector(args.FinalLinearVelocity.X, args.FinalLinearVelocity.Y); + if (angle <= 45 || angle >= 315) + { + angle = 0; + } + else if (angle >= 135 && angle <= 225) + { + angle = 180; + } + + FlickEventArgs flickEventArgs = new FlickEventArgs + { + Angle = angle + }; + ReleaseMouseCaptureAtGestureOrigin(); + RaiseFlick(flickEventArgs); + } + else if (args.TotalTranslation.X != 0 || args.TotalTranslation.Y != 0) + { + DragEventArgs dragEventArgs = new DragEventArgs + { + CumulativeDistance = args.TotalTranslation + }; + dragEventArgs.MarkAsFinalTouchManipulation(); + e = dragEventArgs; + } + + RaiseGestureEnd(e); + } + + private void RaiseGestureStart(GestureEventArgs args) + { + SafeRaise.Raise(GestureStart, this, args); + } + + private void RaiseFlick(FlickEventArgs args) + { + SafeRaise.Raise(Flick, this, args); + } + + private void RaiseGestureEnd(EventArgs args) + { + SafeRaise.Raise(GestureEnd, this, args); + } + + private void RaiseDragEvents(InputDeltaArgs args) + { + DragEventArgs e = new DragEventArgs(args); + if (args.DeltaTranslation.X != 0 && _dragLock == DragLock.Horizontal) + { + RaiseHorizontalDrag(e); + } + else if (args.DeltaTranslation.Y != 0 && _dragLock == DragLock.Vertical) + { + RaiseVerticalDrag(e); + } + } + + private void RaiseHorizontalDrag(DragEventArgs args) + { + SafeRaise.Raise(HorizontalDrag, this, args); + } + + private void RaiseVerticalDrag(DragEventArgs args) + { + SafeRaise.Raise(VerticalDrag, this, args); + } + + private static double AngleFromVector(double x, double y) + { + double num = Math.Atan2(y, x); + if (num < 0) + { + num = 2 * Math.PI + num; + } + return num * 360 / (2 * Math.PI); + } + + private enum DragLock + { + Unset, + Free, + Vertical, + Horizontal, + } +} diff --git a/TelegramClient.WP81/Controls/StartView/InputBaseArgs.cs b/TelegramClient.WP81/Controls/StartView/InputBaseArgs.cs new file mode 100755 index 0000000..730aa74 --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/InputBaseArgs.cs @@ -0,0 +1,24 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; + +namespace TelegramClient.Controls.StartView +{ + internal class InputBaseArgs + { + protected InputBaseArgs(UIElement source, Point origin) + { + Source = source; + Origin = origin; + } + + public UIElement Source { get; private set; } + + public Point Origin { get; private set; } + } +} diff --git a/TelegramClient.WP81/Controls/StartView/InputCompletedArgs.cs b/TelegramClient.WP81/Controls/StartView/InputCompletedArgs.cs new file mode 100755 index 0000000..0966fb1 --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/InputCompletedArgs.cs @@ -0,0 +1,25 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; + +namespace TelegramClient.Controls.StartView +{ + internal abstract class InputCompletedArgs : InputBaseArgs + { + protected InputCompletedArgs(UIElement source, Point origin) + : base(source, origin) + { + } + + public abstract Point TotalTranslation { get; } + + public abstract Point FinalLinearVelocity { get; } + + public abstract bool IsInertial { get; } + } +} diff --git a/TelegramClient.WP81/Controls/StartView/InputDeltaArgs.cs b/TelegramClient.WP81/Controls/StartView/InputDeltaArgs.cs new file mode 100755 index 0000000..86208ac --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/InputDeltaArgs.cs @@ -0,0 +1,27 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; + +namespace TelegramClient.Controls.StartView +{ + internal abstract class InputDeltaArgs : InputBaseArgs + { + protected InputDeltaArgs(UIElement source, Point origin) + : base(source, origin) + { + } + + public abstract Point DeltaTranslation { get; } + + public abstract Point CumulativeTranslation { get; } + + public abstract Point ExpansionVelocity { get; } + + public abstract Point LinearVelocity { get; } + } +} diff --git a/TelegramClient.WP81/Controls/StartView/ManipulationGestureHelper.cs b/TelegramClient.WP81/Controls/StartView/ManipulationGestureHelper.cs new file mode 100755 index 0000000..94637f4 --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/ManipulationGestureHelper.cs @@ -0,0 +1,132 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Input; + +namespace TelegramClient.Controls.StartView +{ + internal class ManipulationGestureHelper : GestureHelper + { + public ManipulationGestureHelper(UIElement target, bool shouldHandleAllDrags) + : base(target, shouldHandleAllDrags) + { + } + + protected override void HookEvents() + { + Target.ManipulationStarted += Target_ManipulationStarted; + Target.ManipulationDelta += Target_ManipulationDelta; + Target.ManipulationCompleted += Target_ManipulationCompleted; + } + + private void Target_ManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + NotifyDown(new ManipulationBaseArgs(e)); + } + + private void Target_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + NotifyMove(new ManipulationDeltaArgs(e)); + } + + private void Target_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + NotifyUp(new ManiulationCompletedArgs(e)); + } + + private class ManipulationBaseArgs : InputBaseArgs + { + public ManipulationBaseArgs(ManipulationStartedEventArgs args) + : base(args.ManipulationContainer, args.ManipulationOrigin) + { + } + } + + private class ManipulationDeltaArgs : InputDeltaArgs + { + private ManipulationDeltaEventArgs _args; + + public ManipulationDeltaArgs(ManipulationDeltaEventArgs args) + : base(args.ManipulationContainer, args.ManipulationOrigin) + { + _args = args; + } + + + public override Point DeltaTranslation + { + get + { + return _args.DeltaManipulation.Translation; + } + } + + public override Point CumulativeTranslation + { + get + { + return _args.CumulativeManipulation.Translation; + } + } + + public override Point ExpansionVelocity + { + get + { + return _args.Velocities.ExpansionVelocity; + } + } + + public override Point LinearVelocity + { + get + { + return _args.Velocities.LinearVelocity; + } + } + } + + private class ManiulationCompletedArgs : InputCompletedArgs + { + private ManipulationCompletedEventArgs _args; + + public ManiulationCompletedArgs(ManipulationCompletedEventArgs args) + : base(args.ManipulationContainer, args.ManipulationOrigin) + { + _args = args; + } + + public override Point TotalTranslation + { + get + { + return _args.TotalManipulation.Translation; + } + } + + public override Point FinalLinearVelocity + { + get + { + if (_args.FinalVelocities != null) + return _args.FinalVelocities.LinearVelocity; + else + return new Point(0, 0); + } + } + + public override bool IsInertial + { + get + { + return _args.IsInertial; + } + } + } + } +} diff --git a/TelegramClient.WP81/Controls/StartView/SafeRaise.cs b/TelegramClient.WP81/Controls/StartView/SafeRaise.cs new file mode 100755 index 0000000..24d6e54 --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/SafeRaise.cs @@ -0,0 +1,95 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics.CodeAnalysis; + +namespace TelegramClient.Controls.StartView +{ + /// + /// A helper class for raising events safely. + /// + internal static class SafeRaise + { + /// + /// Raises an event in a thread-safe manner, also does the null check. + /// + /// The event to raise. + /// The event sender. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")] + public static void Raise(EventHandler eventToRaise, object sender) + { + if (eventToRaise != null) + { + eventToRaise(sender, System.EventArgs.Empty); + } + } + + /// + /// Raises an event in a thread-safe manner, also does the null check. + /// + /// The event to raise. + /// The event sender. + public static void Raise(EventHandler eventToRaise, object sender) + { + Raise(eventToRaise, sender, System.EventArgs.Empty); + } + + /// + /// Raises an event in a thread-safe manner, also does the null check. + /// + /// The event args type. + /// The event to raise. + /// The event sender. + /// The event args. + public static void Raise(EventHandler eventToRaise, object sender, T args) where T : System.EventArgs + { + if (eventToRaise != null) + { + eventToRaise(sender, args); + } + } + + // Lazy event args creation example: + // + // public class MyEventArgs : EventArgs + // { + // public MyEventArgs(int x) { X = x; } + // public int X { get; set; } + // } + // + // event EventHandler Foo; + // + // public void Bar() + // { + // int y = 2; + // Raise(Foo, null, () => { return new MyEventArgs(y); }); + // } + + /// + /// This is a method that returns event args, used for lazy creation. + /// + /// The event type. + /// + public delegate T GetEventArgs() where T : System.EventArgs; + + /// + /// Raise an event in a thread-safe manner, with the required null check. Lazily creates event args. + /// + /// The event args type. + /// The event to raise. + /// The event sender. + /// The delegate to return the event args if needed. + public static void Raise(EventHandler eventToRaise, object sender, GetEventArgs getEventArgs) where T : System.EventArgs + { + if (eventToRaise != null) + { + eventToRaise(sender, getEventArgs()); + } + } + } +} diff --git a/TelegramClient.WP81/Controls/StartView/StartView.cs b/TelegramClient.WP81/Controls/StartView/StartView.cs new file mode 100755 index 0000000..b0f02d0 --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/StartView.cs @@ -0,0 +1,605 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Animation; +using Microsoft.Phone.Controls.Primitives; + +namespace TelegramClient.Controls.StartView +{ + /// + /// Creates a panoramic view of items that can be panned side-to-side, similar to the Start screen. + /// + [TemplatePart(Name = PanningTransformName, Type = typeof(TranslateTransform))] + [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(StartViewItem))] + public class StartView : TemplatedItemsControl, ISupportInitialize + { + internal static readonly Duration Immediately = TimeSpan.Zero; + private static readonly Duration DefaultDuration = TimeSpan.FromMilliseconds(300); + private static readonly Duration FlickDuration = DefaultDuration; + private static readonly Duration SnapDuration = DefaultDuration; + private static readonly Duration PanDuration = TimeSpan.FromMilliseconds(300); + + private const string PanningTransformName = "PanningTransform"; + + private readonly IEasingFunction _easingFunction = new ExponentialEase { Exponent = 5 }; + + private int _cumulativeDragDelta; + private int _effectiveDragDelta; + private int _flickDirection; + private int _targetOffset; + private bool _dragged; + private bool _adjustSelectedRequested; + private bool _suppressSelectionChangedEvent; + private bool _loaded; + private TransformAnimator _animator; + private bool _suppressAnimation; + private bool _ignorePropertyChange; + private bool _isDesignTime; + private InitializingData _initializingData; + + /// + /// Initializes a new instance of the StartView class. + /// + public StartView() + { + DefaultStyleKey = typeof(StartView); + + GestureHelper gestureHelper = GestureHelper.Create(this, true); + gestureHelper.GestureStart += (sender, args) => GestureStart(); + gestureHelper.HorizontalDrag += (sender, args) => HorizontalDrag(args); + gestureHelper.Flick += (sender, args) => Flick(args); + gestureHelper.GestureEnd += (sender, args) => GestureEnd(); + + SizeChanged += OnSizeChanged; + + Loaded += OnLoaded; + Unloaded += OnUnloaded; + + _isDesignTime = DesignerProperties.IsInDesignTool; + } + + internal StartViewPanel Panel { get; set; } + + internal int ItemsWidth { get; set; } + + internal int ViewportWidth { get; private set; } + + internal int ViewportHeight { get; private set; } + + private TranslateTransform PanningTransform { get; set; } + + private int ActualOffset + { + get { return PanningTransform == null ? 0 : (int)PanningTransform.X; } + } + + private int SelectionOffset + { + get + { + StartViewItem container = GetContainer(SelectedItem); + if (container != null) + { + return -container.StartPosition; + } + return 0; + } + } + + private bool IsInit + { + get { return _initializingData != null; } + } + + /// + /// Identifies the SelectedItem dependency property. + /// + public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register( + "SelectedItem", + typeof(object), + typeof(StartView), + new PropertyMetadata(null, (d, e) => ((StartView)d).OnSelectedItemChanged(e))); + + /// + /// Gets the selected item. + /// + /// + /// + /// Returns . + /// + public object SelectedItem + { + get { return GetValue(SelectedItemProperty); } + set { SetValue(SelectedItemProperty, value); } + } + + /// + /// Identifies the SelectedIndex dependency property. + /// + public static readonly DependencyProperty SelectedIndexProperty = DependencyProperty.Register( + "SelectedIndex", + typeof(int), + typeof(StartView), + new PropertyMetadata(-1, (d, e) => ((StartView)d).OnSelectedIndexChanged(e))); + + /// + /// Gets the selected index. + /// + /// + /// + /// Returns . + /// + public int SelectedIndex + { + get { return (int)GetValue(SelectedIndexProperty); } + set { SetValue(SelectedIndexProperty, value); } + } + + /// + /// Event that is invoked when selection changes. + /// + public event EventHandler SelectionChanged; + + /// + /// Event that is invoked when selection changes. + /// + public event EventHandler SelectionCanceled; + + protected virtual void RaiseSelectionCanceled() + { + EventHandler handler = SelectionCanceled; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + /// + /// Handles the application of a new Template. + /// + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + PanningTransform = GetTemplateChild(PanningTransformName) as TranslateTransform; + + _animator = PanningTransform != null ? new TransformAnimator(PanningTransform) : null; + } + + /// + /// Handles the measurement of the control. + /// + /// + /// + /// Desired size. + /// + /// Available size. + protected override Size MeasureOverride(Size availableSize) + { + if (Application.Current.Host.Content.ActualWidth > 0) + { + ViewportWidth = !double.IsInfinity(availableSize.Width) ? (int)availableSize.Width : (int)Application.Current.Host.Content.ActualWidth; + ViewportHeight = !double.IsInfinity(availableSize.Height) ? (int)availableSize.Height : (int)Application.Current.Host.Content.ActualHeight; + } + else + { + ViewportWidth = (int)Math.Min(availableSize.Width, 480); + ViewportHeight = (int)Math.Min(availableSize.Height, 800); + } + + base.MeasureOverride(new Size(double.PositiveInfinity, ViewportHeight)); + + if (double.IsInfinity(availableSize.Width)) + { + availableSize.Width = ViewportWidth; + } + + if (double.IsInfinity(availableSize.Height)) + { + availableSize.Height = ViewportHeight; + } + + return availableSize; + } + + /// + /// Handles the arrange pass for the control. + /// + /// + /// + /// Render size. + /// + /// Final size. + protected override Size ArrangeOverride(Size finalSize) + { + finalSize.Width = DesiredSize.Width; + base.ArrangeOverride(finalSize); + return finalSize; + } + + /// + /// When the items have changed, we need to adjust the selection. + /// + /// The changed item. + protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) + { + base.OnItemsChanged(e); + + if (!IsInit) + { + RequestAdjustSelection(); + } + } + + internal void RequestAdjustSelection() + { + if (_adjustSelectedRequested) + { + return; + } + + LayoutUpdated += LayoutUpdatedAdjustSelection; + _adjustSelectedRequested = true; + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + _loaded = true; + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + _loaded = false; + } + + private void LayoutUpdatedAdjustSelection(object sender, System.EventArgs e) + { + _adjustSelectedRequested = false; + LayoutUpdated -= LayoutUpdatedAdjustSelection; + AdjustSelection(); + } + + private void AdjustSelection() + { + if (_isDesignTime) + { + if (_loaded) + { + _targetOffset = 0; + GoTo(_targetOffset, Immediately); + } + } + else + { + object oldSelectedItem = SelectedItem; + object newSelectedItem = null; + + if (Panel != null && Panel.VisibleChildren.Count > 0) + { + if (oldSelectedItem == null) + { + newSelectedItem = GetItem(Panel.VisibleChildren[0]); + } + else + { + StartViewItem oldContainer = GetContainer(oldSelectedItem); + newSelectedItem = oldContainer == null || !Panel.VisibleChildren.Contains(oldContainer) ? GetItem(Panel.VisibleChildren[0]) : oldSelectedItem; + } + } + else + { + _targetOffset = 0; + GoTo(_targetOffset, Immediately); + } + + SetSelectionInternal(newSelectedItem); + + StartViewItem newContainer = GetContainer(newSelectedItem); + if (newContainer != null) + { + _targetOffset = -newContainer.StartPosition; + GoTo(_targetOffset, Immediately); + } + } + } + + private void GestureStart() + { + _targetOffset = ActualOffset; + _flickDirection = 0; + _cumulativeDragDelta = 0; + _effectiveDragDelta = 0; + _dragged = false; + } + + private void HorizontalDrag(DragEventArgs args) + { + if (_flickDirection == 0) + { + _cumulativeDragDelta = (int)args.CumulativeDistance.X; + _effectiveDragDelta += (int)args.DeltaDistance.X; + _targetOffset += (int)args.DeltaDistance.X; + if (Math.Abs(_cumulativeDragDelta) <= ViewportWidth) + { + if (_effectiveDragDelta > 0 && SelectedIndex == 0 || _effectiveDragDelta < 0 && SelectedIndex == Items.Count - 1) + { + _effectiveDragDelta = 0; + _targetOffset = ActualOffset; + return; + } + + _dragged = true; + GoTo(_targetOffset, PanDuration); + } + } + } + + private void Flick(FlickEventArgs e) + { + if (e.Angle == 180) + { + _flickDirection = -1; + } + else if (e.Angle == 0) + { + _flickDirection = 1; + } + } + + private void GestureEnd() + { + if (_flickDirection == 0) + { + if (_dragged) + { + int snapTo; + int newDirection; + StartViewItem newSelection; + + Panel.GetSnapOffset(_targetOffset, ViewportWidth, Math.Sign(_cumulativeDragDelta), out snapTo, out newDirection, out newSelection); + + object newSelectedItem = GetItem(newSelection); + if (SelectedItem == newSelectedItem) + { + RaiseSelectionCanceled(); + } + + if (newSelectedItem != null) + { + _suppressAnimation = true; + SelectedItem = newSelectedItem; + _suppressAnimation = false; + } + + GoTo(snapTo, SnapDuration); + } + } + else + { + ProcessFlick(); + } + } + + private void ProcessFlick() + { + if (_flickDirection != 0) + { + StartViewPanel.ItemStop previous; + StartViewPanel.ItemStop current; + StartViewPanel.ItemStop next; + + Panel.GetStops(SelectionOffset, ItemsWidth, out previous, out current, out next); + + if (previous == current && current == next && next == null) + { + return; + } + + if (_flickDirection < 0 && next == null || _flickDirection > 0 && previous == null) + { + if (current != null) + { + GoTo(-current.Position, Immediately); + } + + return; + } + + _targetOffset = _flickDirection < 0 ? -next.Position : -previous.Position; + + _suppressAnimation = true; + SelectedItem = GetItem(_flickDirection < 0 ? next.Item : previous.Item); + _suppressAnimation = false; + + GoTo(_targetOffset, FlickDuration); + } + } + + private void GoTo(int offset, Duration duration, Action completionAction) + { + if (_animator != null) + { + _animator.GoTo(offset, duration, _easingFunction, completionAction); + } + } + + private void GoTo(int offset) + { + GoTo(offset, null); + } + + private void GoTo(int offset, Action completionAction) + { + int delta = Math.Abs(ActualOffset - offset); + GoTo(offset, TimeSpan.FromMilliseconds(delta * 2), completionAction); + } + + private void GoTo(int offset, Duration duration) + { + GoTo(offset, duration, null); + } + + private void SetSelectionInternal(object selectedItem) + { + _suppressSelectionChangedEvent = true; + SelectedItem = selectedItem; + _suppressSelectionChangedEvent = false; + } + + private void OnSelectedItemChanged(DependencyPropertyChangedEventArgs args) + { + if (IsInit) + { + return; + } + + if (_ignorePropertyChange) + { + _ignorePropertyChange = false; + return; + } + + if (!_isDesignTime) + { + if (args.NewValue == null && Items.Count > 0) + { + _ignorePropertyChange = true; + SelectedItem = args.OldValue; + throw new ArgumentException("SelectedItem"); + } + else if (args.NewValue != null && !Items.Contains(args.NewValue)) + { + _ignorePropertyChange = true; + SelectedItem = args.OldValue; + return; + } + } + + SelectedIndex = Items.IndexOf(args.NewValue); + + if (_suppressSelectionChangedEvent) + { + return; + } + + SafeRaise.Raise(SelectionChanged, this, (() => + { + object[] unselected; + if (args.OldValue != null) + { + unselected = new object[1] { args.OldValue }; + } + else + { + unselected = new object[0]; + } + + object[] selected; + if (args.NewValue != null) + { + selected = new object[1] { args.NewValue }; + } + else + { + selected = new object[0]; + } + + return new SelectionChangedEventArgs(unselected, selected); + })); + + if (!_suppressAnimation) + { + GoTo(SelectionOffset, _loaded ? DefaultDuration : Immediately); + } + } + + [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")] + private void OnSelectedIndexChanged(DependencyPropertyChangedEventArgs args) + { + if (IsInit) + { + return; + } + + if (_ignorePropertyChange) + { + _ignorePropertyChange = false; + return; + } + + int newSelectedIndex = (int)args.NewValue; + int itemsCount = Items.Count; + + if (newSelectedIndex >= 0 && newSelectedIndex < itemsCount) + { + SelectedItem = Items[newSelectedIndex]; + } + else if (newSelectedIndex == -1 && itemsCount == 0) + { + SelectedItem = null; + } + else if (!_isDesignTime) + { + _ignorePropertyChange = true; + SelectedIndex = (int)args.OldValue; + throw new ArgumentOutOfRangeException("SelectedIndex"); + } + } + + private void OnSizeChanged(object sender, SizeChangedEventArgs e) + { + ViewportWidth = (int)e.NewSize.Width; + ViewportHeight = (int)e.NewSize.Height; + ItemsWidth = (int)Panel.ActualWidth; + } + + void ISupportInitialize.BeginInit() + { + _initializingData = new InitializingData + { + InitialItem = SelectedItem, + InitialIndex = SelectedIndex + }; + } + + void ISupportInitialize.EndInit() + { + if (_initializingData == null) + { + throw new InvalidOperationException(); + } + + int selectedIndex = SelectedIndex; + object selectedItem = SelectedItem; + + if (_initializingData.InitialIndex != selectedIndex) + { + SelectedIndex = _initializingData.InitialIndex; + _initializingData = null; + SelectedIndex = selectedIndex; + } + else if (!ReferenceEquals(_initializingData.InitialItem, selectedItem)) + { + SelectedItem = _initializingData.InitialItem; + _initializingData = null; + SelectedItem = selectedItem; + } + + _initializingData = null; + } + + private class InitializingData + { + public int InitialIndex; + public object InitialItem; + } + } +} diff --git a/TelegramClient.WP81/Controls/StartView/StartViewItem.cs b/TelegramClient.WP81/Controls/StartView/StartViewItem.cs new file mode 100755 index 0000000..1190b10 --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/StartViewItem.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows.Controls; + +namespace TelegramClient.Controls.StartView +{ + /// + /// Represents an item in a StartView control. + /// + public class StartViewItem : ContentControl + { + /// + /// Initializes a new instance of the StartViewItem class. + /// + public StartViewItem() + { + DefaultStyleKey = typeof(StartViewItem); + } + + internal int StartPosition { get; set; } + + internal int ItemWidth { get; set; } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Controls/StartView/StartViewPanel.cs b/TelegramClient.WP81/Controls/StartView/StartViewPanel.cs new file mode 100755 index 0000000..3754e9f --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/StartViewPanel.cs @@ -0,0 +1,378 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +namespace TelegramClient.Controls.StartView +{ + /// + /// Implements a custom Panel for the StartView control. + /// + public class StartViewPanel : Panel + { + private const int SnapThresholdDivisor = 2; + + private readonly List _visibleChildren = new List(); + private readonly List _itemStops = new List(); + private StartView _owner; + private StartViewItem _selectedItem; + + internal IList VisibleChildren + { + get { return _visibleChildren; } + } + + private StartView Owner + { + get { return _owner; } + set + { + if (_owner != value) + { + if (_owner != null) + { + _owner.Panel = null; + } + + _owner = value; + + if (_owner != null) + { + _owner.Panel = this; + } + } + } + } + + /// + /// Initializes a new instance of the StartViewPanel class. + /// + public StartViewPanel() + { + SizeChanged += OnSizeChanged; + Unloaded += OnUnloaded; + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + _owner = null; + } + + private void OnSizeChanged(object sender, SizeChangedEventArgs e) + { + Owner.ItemsWidth = (int)e.NewSize.Width; + } + + /// + /// Handles the measure pass for the control. + /// + /// + /// + /// Desired size. + /// + /// Available size. + protected override Size MeasureOverride(Size availableSize) + { + if (_owner == null) + { + FindOwner(); + } + + Size desiredSize = new Size(0, availableSize.Height); + + int childWidth = Owner.ViewportWidth; + int childHeight = (int)Math.Min(availableSize.Height, Owner.ViewportHeight); + Size childSize = new Size(childWidth, childHeight); + + _visibleChildren.Clear(); + + foreach (StartViewItem child in Children) + { + if (child.Visibility == Visibility.Visible) + { + _visibleChildren.Add(child); + child.Measure(childSize); + desiredSize.Width += childWidth; + } + } + + return desiredSize; + } + + /// + /// Handles the arrange pass for the control. + /// + /// + /// + /// Render size. + /// + /// Final size. + protected override Size ArrangeOverride(Size finalSize) + { + _itemStops.Clear(); + double x = 0; + Rect finalRect = new Rect(0, 0, 0, finalSize.Height); + + for (int index = 0; index < _visibleChildren.Count; ++index) + { + StartViewItem child = _visibleChildren[index]; + finalRect.X = child.StartPosition = (int)x; + _itemStops.Add(new ItemStop(child, child.StartPosition)); + finalRect.Width = Owner.ViewportWidth; + child.ItemWidth = (int)finalRect.Width; + child.Arrange(finalRect); + x += finalRect.Width; + } + + Owner.RequestAdjustSelection(); + + return finalSize; + } + + private void GetItemsInView(int offset, int viewportWidth, out int leftIndex, out int leftInView, out int centerIndex, out int rightIndex, out int rightInView) + { + leftIndex = leftInView = centerIndex = rightIndex = rightInView = -1; + + int count = VisibleChildren.Count; + if (count == 0) + { + return; + } + + for (int index = 0; index < count; ++index) + { + StartViewItem child = _visibleChildren[index]; + + int leftOffset = child.StartPosition + offset; + int rightOffset = leftOffset + child.ItemWidth - 1; + + if (leftOffset <= 0 && rightOffset >= 0) + { + leftIndex = index; + leftInView = Math.Min(viewportWidth, child.ItemWidth + leftOffset); + } + + if (leftOffset < viewportWidth && rightOffset >= viewportWidth) + { + rightIndex = index; + rightInView = Math.Min(viewportWidth, viewportWidth - leftOffset); + } + + if (leftOffset > 0 && rightOffset < viewportWidth) + { + centerIndex = index; + } + + if (index == 0 && leftInView == -1) + { + leftInView = leftOffset; + } + + if (index == count - 1 && rightInView == -1) + { + rightInView = viewportWidth - rightOffset - 1; + } + } + } + + internal void GetStops(int offset, int totalWidth, out ItemStop previous, out ItemStop current, out ItemStop next) + { + next = current = previous = null; + + if (VisibleChildren.Count == 0) + { + return; + } + + int nextIndex = -1; + int currentIndex = -1; + int previousIndex = -1; + + int position = -offset % totalWidth; + int itemStopIndex = 0; + + foreach (ItemStop itemStop in _itemStops) + { + if (itemStop.Position < position) + { + previousIndex = itemStopIndex; + } + else if (itemStop.Position > position) + { + nextIndex = itemStopIndex; + break; + } + else if (itemStop.Position == position) + { + currentIndex = itemStopIndex; + } + + ++itemStopIndex; + } + + if (previousIndex != -1) + { + previous = _itemStops[previousIndex]; + } + + if (currentIndex != -1) + { + current = _itemStops[currentIndex]; + } + + if (nextIndex != -1) + { + next = _itemStops[nextIndex]; + } + } + + internal void GetSnapOffset(int offset, int viewportWidth, int direction, out int snapTo, out int newDirection, out StartViewItem newSelection) + { + int snapThreshold = viewportWidth / SnapThresholdDivisor; + + snapTo = offset; + newDirection = direction; + newSelection = _selectedItem; + + if (VisibleChildren.Count == 0) + { + return; + } + + foreach (ItemStop itemStop in _itemStops) + { + if (itemStop.Position == -offset) + { + newSelection = itemStop.Item; + return; + } + } + + int leftIndex; + int leftInView; + int centerIndex; + int rightIndex; + int rightInView; + + GetItemsInView(offset, viewportWidth, out leftIndex, out leftInView, out centerIndex, out rightIndex, out rightInView); + + if (leftIndex == rightIndex && leftIndex != -1) + { + newSelection = _selectedItem = _visibleChildren[leftIndex]; + } + else + { + if (leftIndex == -1) + { + leftIndex = _visibleChildren.Count - 1; + } + + if (rightIndex == -1) + { + rightIndex = 0; + } + + int index; + if (direction < 0) + { + if (rightInView > snapThreshold) + { + index = GetBestIndex(centerIndex, rightIndex, leftIndex); + newDirection = -1; + } + else + { + index = GetBestIndex(leftIndex, centerIndex, rightIndex); + newDirection = 1; + } + } + else if (direction > 0) + { + if (leftInView > snapThreshold) + { + index = StartViewPanel.GetBestIndex(leftIndex, centerIndex, rightIndex); + newDirection = 1; + } + else + { + index = StartViewPanel.GetBestIndex(centerIndex, rightIndex, leftIndex); + newDirection = -1; + } + } + else if (centerIndex != -1) + { + index = centerIndex; + newDirection = -1; + } + else if (leftInView > rightInView) + { + index = leftIndex; + newDirection = -1; + } + else + { + index = rightIndex; + newDirection = 1; + } + + _selectedItem = _visibleChildren[index]; + snapTo = -_selectedItem.StartPosition; + newSelection = _selectedItem; + } + } + + private static int GetBestIndex(int n0, int n1, int n2) + { + if (n0 >= 0) + { + return n0; + } + + if (n1 >= 0) + { + return n1; + } + + if (n2 >= 0) + { + return n2; + } + + throw new InvalidOperationException("No best index."); + } + + private void FindOwner() + { + FrameworkElement frameworkElement = this; + StartView owner; + do + { + frameworkElement = (FrameworkElement)VisualTreeHelper.GetParent(frameworkElement); + owner = frameworkElement as StartView; + } + while (frameworkElement != null && owner == null); + Owner = owner; + } + + internal class ItemStop + { + public ItemStop(StartViewItem item, int position) + { + Item = item; + Position = position; + } + + public int Position { get; private set; } + + public StartViewItem Item { get; private set; } + } + } +} diff --git a/TelegramClient.WP81/Controls/StartView/TransformAnimator.cs b/TelegramClient.WP81/Controls/StartView/TransformAnimator.cs new file mode 100755 index 0000000..a661ba6 --- /dev/null +++ b/TelegramClient.WP81/Controls/StartView/TransformAnimator.cs @@ -0,0 +1,221 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Windows; +using System.Windows.Media; +using System.Windows.Media.Animation; + +namespace TelegramClient.Controls.StartView +{ + /// + /// A utility for animating a horizontal translation value. + /// + internal sealed class TransformAnimator + { + /// + /// Single static instance of a PropertyPath with string path "X". + /// + private static readonly PropertyPath TranslateXPropertyPath = new PropertyPath("X"); + + /// + /// The Storyboard instance for the animation. + /// + private readonly Storyboard _sbRunning = new Storyboard(); + + /// + /// The DoubleAnimation instance for a running animation. + /// + private readonly DoubleAnimation _daRunning = new DoubleAnimation(); + + /// + /// The target translate transform instance. + /// + private TranslateTransform _transform; + + /// + /// A one-time action for the current GoTo statement only. Cleared if + /// GoTo is called before the action runs. + /// + private Action _oneTimeAction; + + /// + /// Initializes a new instance of the TransformAnimator class. + /// + /// TranslateTransform instance. + public TransformAnimator(TranslateTransform translateTransform) + { + Debug.Assert(translateTransform != null); + _transform = translateTransform; + + _sbRunning.Completed += OnCompleted; + _sbRunning.Children.Add(_daRunning); + Storyboard.SetTarget(_daRunning, _transform); + Storyboard.SetTargetProperty(_daRunning, TranslateXPropertyPath); + } + + /// + /// Gets the current offset value from the translate transform object. + /// + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public double CurrentOffset + { + get { return _transform.X; } + } + + /// + /// Targets a new horizontal offset over a specified duration. + /// + /// The target offset value. + /// The duration for the animation. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public void GoTo(double targetOffset, Duration duration) + { + GoTo(targetOffset, duration, null, null); + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public void GoTo(double targetOffset, Duration duration, Action completionAction) + { + GoTo(targetOffset, duration, null, completionAction); + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public void GoTo(double targetOffset, Duration duration, IEasingFunction easingFunction) + { + GoTo(targetOffset, duration, easingFunction, null); + } + + public void GoTo(double targetOffset, Duration duration, IEasingFunction easingFunction, Action completionAction) + { + _daRunning.To = targetOffset; + _daRunning.Duration = duration; + _daRunning.EasingFunction = easingFunction; + _sbRunning.Begin(); + _sbRunning.SeekAlignedToLastTick(TimeSpan.Zero); + _oneTimeAction = completionAction; + } + + /// + /// Updates the easing function of the double animation. + /// + /// The easing funciton, if any, to use. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping existing implementation.")] + public void UpdateEasingFunction(IEasingFunction ease) + { + if (_daRunning != null && _daRunning.EasingFunction != ease) + { + _daRunning.EasingFunction = ease; + } + } + + /// + /// Immediately updates the duration of the running double animation. + /// + /// The new duration value to use. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public void UpdateDuration(Duration duration) + { + if (_daRunning != null) + { + _daRunning.Duration = duration; + } + } + + /// + /// Handles animation completed + /// + /// Event source. + /// Event arguments. + private void OnCompleted(object sender, System.EventArgs e) + { + // Make sure the action is called when the animation is Stopped + // The complete event is triggered when it changes to Filling + // This is also called before the state has been changed so the state + // is still Active when switching to Filling + Action action = _oneTimeAction; + if (action != null && _sbRunning.GetCurrentState() != ClockState.Active) + { + _oneTimeAction = null; + action(); + } + } + + /// + /// Ensures and creates if needed the animator for an element. Will also + /// verify that a translate transform is present. + /// + /// The target element. + /// The animator reference. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public static void EnsureAnimator(FrameworkElement targetElement, ref TransformAnimator animator) + { + if (animator == null) + { + TranslateTransform transform = TransformAnimator.GetTranslateTransform(targetElement); + if (transform != null) + { + animator = new TransformAnimator(transform); + } + } + if (animator == null) + { + throw new InvalidOperationException("The animation system could not be prepared for the target element."); + } + } + + /// + /// Find a translate transform for the container or create one. + /// + /// The container. + /// Returns the TranslateTransform reference. + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Keeping the public API available.")] + public static TranslateTransform GetTranslateTransform(UIElement container) + { + if (container == null) + { + throw new ArgumentNullException("container"); + } + + TranslateTransform transform = container.RenderTransform as TranslateTransform; + if (transform == null) + { + if (container.RenderTransform == null) + { + transform = new TranslateTransform(); + container.RenderTransform = transform; + } + else if (container.RenderTransform is TransformGroup) + { + TransformGroup g = container.RenderTransform as TransformGroup; + transform = (from t in g.Children + where t is TranslateTransform + select (TranslateTransform)t).FirstOrDefault(); + if (transform == null) + { + transform = new TranslateTransform(); + g.Children.Add(transform); + } + } + else + { + TransformGroup tg = new TransformGroup(); + var existing = container.RenderTransform; + container.RenderTransform = null; + tg.Children.Add(existing); + transform = new TranslateTransform(); + tg.Children.Add(transform); + container.RenderTransform = tg; + } + } + return transform; + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Converters/ChannelParticipantsCountConverter.cs b/TelegramClient.WP81/Converters/ChannelParticipantsCountConverter.cs new file mode 100755 index 0000000..7e3ea8a --- /dev/null +++ b/TelegramClient.WP81/Converters/ChannelParticipantsCountConverter.cs @@ -0,0 +1,40 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.Windows.Data; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.Utils; + +namespace TelegramClient.Converters +{ + public class ChannelParticipantsCountConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var channel = value as TLChannel73; + if (channel != null && channel.ParticipantsCount != null) + { + return ", " + Language.Declension( + channel.ParticipantsCount.Value, + AppResources.SubscriberNominativeSingular, + AppResources.SubscriberNominativePlural, + AppResources.SubscriberGenitiveSingular, + AppResources.SubscriberGenitivePlural).ToLower(CultureInfo.CurrentUICulture); + } + + return string.Empty; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/TelegramClient.WP81/Converters/SecureFilePreviewConverter.cs b/TelegramClient.WP81/Converters/SecureFilePreviewConverter.cs new file mode 100755 index 0000000..a8ddc92 --- /dev/null +++ b/TelegramClient.WP81/Converters/SecureFilePreviewConverter.cs @@ -0,0 +1,153 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.IO; +using System.IO.IsolatedStorage; +using System.Windows.Data; +using System.Windows.Media.Imaging; +using Windows.Storage; +using Caliburn.Micro; +using Telegram.Api.Services.FileManager; +using Telegram.Api.TL; +using TelegramClient.Utils; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.ViewModels.Passport; + +namespace TelegramClient.Converters +{ + public class SecureFilePreviewConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var secureFile = value as TLSecureFile; + if (secureFile != null) + { + var inputFileLocation = new TLInputDocumentFileLocation54 + { + Id = secureFile.Id, + AccessHash = secureFile.AccessHash, + Version = new TLInt(0) + }; + + var localFileName = string.Format("secureid_{0}.dat", secureFile.Id); + var previewFileName = string.Format("secureid_preview_{0}.dat", secureFile.Id); + + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (store.FileExists(previewFileName)) + { + BitmapImage imageSource; + + try + { + using (var stream = store.OpenFile(previewFileName, FileMode.Open, FileAccess.Read)) + { + stream.Seek(0, SeekOrigin.Begin); + var image = new BitmapImage(); + image.CreateOptions |= BitmapCreateOptions.BackgroundCreation; + image.SetSource(stream); + imageSource = image; + } + } + catch (Exception) + { + return null; + } + + return imageSource; + } + if (store.FileExists(inputFileLocation.GetFileName())) + { + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + DecryptFile(secureFile, inputFileLocation, localFileName, previewFileName); + }); + + return null; + } + } + + IoC.Get().DownloadFileAsync( + new TLString(localFileName), + secureFile.DCId, + inputFileLocation, + secureFile, + secureFile.Size, + progress => + { + + }, + item => + { + DecryptFile(secureFile, inputFileLocation, localFileName, previewFileName); + }); + } + + var secureFileUploaded = value as TLSecureFileUploaded; + if (secureFileUploaded != null) + { + var previewFileName = string.Format("secureid_preview_{0}.dat", secureFileUploaded.Id); + + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (store.FileExists(previewFileName)) + { + BitmapImage imageSource; + + try + { + using (var stream = store.OpenFile(previewFileName, FileMode.Open, FileAccess.Read)) + { + stream.Seek(0, SeekOrigin.Begin); + var image = new BitmapImage(); + image.CreateOptions |= BitmapCreateOptions.BackgroundCreation; + image.SetSource(stream); + imageSource = image; + } + } + catch (Exception) + { + return null; + } + + return imageSource; + } + } + } + + return null; + } + + private static async void DecryptFile(TLSecureFile secureFile, TLInputFileLocationBase inputFileLocation, string localFileName, string previewFileName) + { + var fileSecret = Passport.DecryptValueSecret( + secureFile.Secret, + EnterPasswordViewModel.Secret, + secureFile.FileHash); + + var encryptedFile = await ApplicationData.Current.LocalFolder.GetFileAsync(inputFileLocation.GetFileName("document")); + + var decryptedTuple = await Passport.DecryptFile(localFileName, encryptedFile, fileSecret, secureFile.FileHash); + + var stream = await decryptedTuple.Item1.OpenReadAsync(); + + await DialogDetailsViewModel.ResizeJpeg(stream, 180, localFileName, previewFileName); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + secureFile.NotifyOfPropertyChange(() => secureFile.Self); + }); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/TelegramClient.WP81/Converters/ShippingOptionToStringConverter.cs b/TelegramClient.WP81/Converters/ShippingOptionToStringConverter.cs new file mode 100755 index 0000000..8fe62cc --- /dev/null +++ b/TelegramClient.WP81/Converters/ShippingOptionToStringConverter.cs @@ -0,0 +1,60 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.Linq; +using System.Windows.Data; +using Telegram.Api.TL; + +namespace TelegramClient.Converters +{ + public class ShippingOptionToStringConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var shippingOption = value as TLShippingOption; + if (shippingOption != null) + { + if (shippingOption.Prices.Count > 0) + { + var currency = shippingOption.Prices[0].Currency ?? TLString.Empty; + return string.Format("{0} - {1}", Telegram.Controls.Utils.Currency.GetString(shippingOption.Prices.Sum(x => x.Amount.Value), currency.ToString()), shippingOption.Title); + } + + return shippingOption.Title.ToString(); + } + + return null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class LabeledPriceToStringConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var labeledPrice = value as TLLabeledPrice; + if (labeledPrice != null) + { + var currency = labeledPrice.Currency ?? TLString.Empty; + return Telegram.Controls.Utils.Currency.GetString(labeledPrice.Amount.Value, currency.ToString()); + } + + return null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/TelegramClient.WP81/Converters/TTLMediaToVisibilityConverter.cs b/TelegramClient.WP81/Converters/TTLMediaToVisibilityConverter.cs new file mode 100755 index 0000000..56b155b --- /dev/null +++ b/TelegramClient.WP81/Converters/TTLMediaToVisibilityConverter.cs @@ -0,0 +1,57 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; +using Telegram.Api.TL; + +namespace TelegramClient.Converters +{ + public class TTLMediaToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return TLMessageBase.HasTTL(value as TLMessageMediaBase) ? Visibility.Collapsed : Visibility.Visible; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class TTLMediaToTimerStringConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var ttlSeconds = value as TLInt; + if (ttlSeconds != null && ttlSeconds.Value >= 0) + { + if (ttlSeconds.Value >= 60 * 60) + { + return string.Format("{0}h", ttlSeconds.Value / (60 * 60)); + } + + if (ttlSeconds.Value >= 60) + { + return string.Format("{0}m", ttlSeconds.Value / 60); + } + + return string.Format("{0}s", ttlSeconds.Value); + } + + return null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/TelegramClient.WP81/FFMpegBuild.txt b/TelegramClient.WP81/FFMpegBuild.txt new file mode 100755 index 0000000..d2b53da --- /dev/null +++ b/TelegramClient.WP81/FFMpegBuild.txt @@ -0,0 +1,42 @@ +mkdir -p Output/WindowsPhone8.1/ARM + +cd Output/WindowsPhone8.1/ARM + +../../../configure \ +--toolchain=msvc \ +--disable-programs \ +--disable-d3d11va \ +--disable-dxva2 \ +--disable-doc \ +--disable-avx \ +--disable-everything \ +--disable-network \ +--disable-zlib \ +--disable-avfilter \ +--disable-avdevice \ +--disable-postproc \ +--disable-debug \ +--disable-network \ +--arch=arm \ +--as=armasm \ +--cpu=armv7 \ +--enable-thumb \ +--enable-version3 \ +--enable-gpl \ +--enable-protocol=file \ +--enable-decoder=h264 \ +--enable-decoder=gif \ +--enable-demuxer=mov \ +--enable-demuxer=gif \ +--enable-hwaccels \ +--enable-asm \ +--enable-shared \ +--enable-cross-compile \ +--target-os=win32 \ +--extra-cflags="-MD -DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP -D_WIN32_WINNT=0x0603 -D__ARM_PCS_VFP" \ +--extra-ldflags="-APPCONTAINER -MACHINE:ARM -subsystem:console -opt:ref WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib -NODEFAULTLIB:kernel32.lib -NODEFAULTLIB:ole32.lib" \ +--prefix=../../../Build/WindowsPhone8.1/ARM + +make + +make install \ No newline at end of file diff --git a/TelegramClient.WP81/Fonts/Segoe-MDL2-Assets-MetroUI.ttf b/TelegramClient.WP81/Fonts/Segoe-MDL2-Assets-MetroUI.ttf new file mode 100755 index 0000000..a05a841 Binary files /dev/null and b/TelegramClient.WP81/Fonts/Segoe-MDL2-Assets-MetroUI.ttf differ diff --git a/TelegramClient.WP81/Helpers/TemplateSelectors/ImageViewerTemplateSelector.cs b/TelegramClient.WP81/Helpers/TemplateSelectors/ImageViewerTemplateSelector.cs new file mode 100755 index 0000000..585675f --- /dev/null +++ b/TelegramClient.WP81/Helpers/TemplateSelectors/ImageViewerTemplateSelector.cs @@ -0,0 +1,71 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; +using Telegram.Api.TL; + +namespace TelegramClient.Helpers.TemplateSelectors +{ + public class ImageViewerTemplateSelector : IValueConverter + { + public DataTemplate PhotoTemplate { get; set; } + + public DataTemplate VideoTemplate { get; set; } + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var message = value as TLMessage; + if (message != null) + { + if (message.Media is TLMessageMediaVideo || message.IsVideo()) + { + return VideoTemplate; + } + + return PhotoTemplate; + } + + return null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class DecryptedImageViewerTemplateSelector : IValueConverter + { + public DataTemplate PhotoTemplate { get; set; } + + public DataTemplate VideoTemplate { get; set; } + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var message = value as TLDecryptedMessage; + if (message != null) + { + if (message.Media is TLDecryptedMessageMediaVideo || message.IsVideo()) + { + return VideoTemplate; + } + + return PhotoTemplate; + } + + return null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/TelegramClient.WP81/Helpers/WeakEventListener.cs b/TelegramClient.WP81/Helpers/WeakEventListener.cs new file mode 100755 index 0000000..a72ec48 --- /dev/null +++ b/TelegramClient.WP81/Helpers/WeakEventListener.cs @@ -0,0 +1,79 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace TelegramClient.Helpers +{ + internal class WeakEventListener where TInstance : class where TSource : class + { + private readonly WeakReference _instance; + + private readonly WeakReference _source; + + private Action _onEventAction; + + public Action OnEventAction + { + get { return _onEventAction; } + set + { + if (value != null && !value.Method.IsStatic) + { + throw new ArgumentException("OnEventAction method must be static otherwise the event WeakEventListner class does not prevent memory leaks."); + } + + _onEventAction = value; + } + } + + private Action, TSource> _onDetachAction; + + public Action, TSource> OnDetachAction + { + get { return _onDetachAction; } + set + { + if (value != null && !value.Method.IsStatic) + { + throw new ArgumentException("OnDetachAction method must be static otherwise the event WeakEventListner class does not prevent memory leaks."); + } + + _onDetachAction = value; + } + } + + public WeakEventListener(TInstance instance, TSource source) + { + _instance = new WeakReference(instance); + _source = new WeakReference(source); + } + + public void OnEvent(TSource source, TEventArgs args) + { + var instance = _instance.Target; + if (instance != null) + { + if (OnEventAction != null) OnEventAction((TInstance)instance, source, args); + } + else + { + Detach(); + } + } + + public void Detach() + { + var source = _source.Target as TSource; + if (source != null && OnDetachAction != null) + { + OnDetachAction(this, source); + OnDetachAction = null; + } + } + } +} diff --git a/TelegramClient.WP81/IconicSmall110.png b/TelegramClient.WP81/IconicSmall110.png new file mode 100755 index 0000000..b6b9174 Binary files /dev/null and b/TelegramClient.WP81/IconicSmall110.png differ diff --git a/TelegramClient.WP81/IconicTileMedium202.png b/TelegramClient.WP81/IconicTileMedium202.png new file mode 100755 index 0000000..074f04d Binary files /dev/null and b/TelegramClient.WP81/IconicTileMedium202.png differ diff --git a/TelegramClient.WP81/Images/ApplicationBar/ic_more_2x.png b/TelegramClient.WP81/Images/ApplicationBar/ic_more_2x.png new file mode 100755 index 0000000..8aa9f85 Binary files /dev/null and b/TelegramClient.WP81/Images/ApplicationBar/ic_more_2x.png differ diff --git a/TelegramClient.WP81/Images/ApplicationBar/ic_plus_2x.png b/TelegramClient.WP81/Images/ApplicationBar/ic_plus_2x.png new file mode 100755 index 0000000..76acfd0 Binary files /dev/null and b/TelegramClient.WP81/Images/ApplicationBar/ic_plus_2x.png differ diff --git a/TelegramClient.WP81/Images/ApplicationBar/ic_search_2x.png b/TelegramClient.WP81/Images/ApplicationBar/ic_search_2x.png new file mode 100755 index 0000000..d36cca9 Binary files /dev/null and b/TelegramClient.WP81/Images/ApplicationBar/ic_search_2x.png differ diff --git a/TelegramClient.WP81/Images/Audio/microphone.dark.png b/TelegramClient.WP81/Images/Audio/microphone.dark.png new file mode 100755 index 0000000..de5605e Binary files /dev/null and b/TelegramClient.WP81/Images/Audio/microphone.dark.png differ diff --git a/TelegramClient.WP81/Images/Audio/microphone.light.png b/TelegramClient.WP81/Images/Audio/microphone.light.png new file mode 100755 index 0000000..1ecea23 Binary files /dev/null and b/TelegramClient.WP81/Images/Audio/microphone.light.png differ diff --git a/TelegramClient.WP81/Images/Messages/roundvideo.muted.png b/TelegramClient.WP81/Images/Messages/roundvideo.muted.png new file mode 100755 index 0000000..80d8adc Binary files /dev/null and b/TelegramClient.WP81/Images/Messages/roundvideo.muted.png differ diff --git a/TelegramClient.WP81/Images/Placeholder/ic_bookmark.png b/TelegramClient.WP81/Images/Placeholder/ic_bookmark.png new file mode 100755 index 0000000..b701a5e Binary files /dev/null and b/TelegramClient.WP81/Images/Placeholder/ic_bookmark.png differ diff --git a/TelegramClient.WP81/Images/Settings/noapps.black-WXGA.png b/TelegramClient.WP81/Images/Settings/noapps.black-WXGA.png new file mode 100755 index 0000000..3a9ac72 Binary files /dev/null and b/TelegramClient.WP81/Images/Settings/noapps.black-WXGA.png differ diff --git a/TelegramClient.WP81/Images/Settings/noapps.white-WXGA.png b/TelegramClient.WP81/Images/Settings/noapps.white-WXGA.png new file mode 100755 index 0000000..0d613f5 Binary files /dev/null and b/TelegramClient.WP81/Images/Settings/noapps.white-WXGA.png differ diff --git a/TelegramClient.WP81/Images/W10M/authorize_2x.png b/TelegramClient.WP81/Images/W10M/authorize_2x.png new file mode 100755 index 0000000..8ff8278 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/authorize_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/default.png b/TelegramClient.WP81/Images/W10M/default.png new file mode 100755 index 0000000..e52464b Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/default.png differ diff --git a/TelegramClient.WP81/Images/W10M/group_placeholder.png b/TelegramClient.WP81/Images/W10M/group_placeholder.png new file mode 100755 index 0000000..d3eaa2b Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/group_placeholder.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_1check_2x.png b/TelegramClient.WP81/Images/W10M/ic_1check_2x.png new file mode 100755 index 0000000..2977fce Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_1check_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_2checks_2x.png b/TelegramClient.WP81/Images/W10M/ic_2checks_2x.png new file mode 100755 index 0000000..1506386 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_2checks_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_attach_2x.png b/TelegramClient.WP81/Images/W10M/ic_attach_2x.png new file mode 100755 index 0000000..e9e0f25 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_attach_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_bio_2x.png b/TelegramClient.WP81/Images/W10M/ic_bio_2x.png new file mode 100755 index 0000000..b42abf2 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_bio_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_botkeyboard_2x.png b/TelegramClient.WP81/Images/W10M/ic_botkeyboard_2x.png new file mode 100755 index 0000000..f93167f Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_botkeyboard_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_call_answer_2x.png b/TelegramClient.WP81/Images/W10M/ic_call_answer_2x.png new file mode 100755 index 0000000..70708a4 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_call_answer_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_call_answer_blue_2x.png b/TelegramClient.WP81/Images/W10M/ic_call_answer_blue_2x.png new file mode 100755 index 0000000..b80ddc5 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_call_answer_blue_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_call_cancel_2x.png b/TelegramClient.WP81/Images/W10M/ic_call_cancel_2x.png new file mode 100755 index 0000000..72fccf2 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_call_cancel_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_call_chat_2x.png b/TelegramClient.WP81/Images/W10M/ic_call_chat_2x.png new file mode 100755 index 0000000..c1c280f Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_call_chat_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_call_ignore_2x.png b/TelegramClient.WP81/Images/W10M/ic_call_ignore_2x.png new file mode 100755 index 0000000..16567b2 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_call_ignore_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_call_mute_2x.png b/TelegramClient.WP81/Images/W10M/ic_call_mute_2x.png new file mode 100755 index 0000000..c46abfd Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_call_mute_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_call_speaker_2x.png b/TelegramClient.WP81/Images/W10M/ic_call_speaker_2x.png new file mode 100755 index 0000000..72ca840 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_call_speaker_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_camera_photo_2x.png b/TelegramClient.WP81/Images/W10M/ic_camera_photo_2x.png new file mode 100755 index 0000000..5720c74 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_camera_photo_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_camera_stop_2x.png b/TelegramClient.WP81/Images/W10M/ic_camera_stop_2x.png new file mode 100755 index 0000000..7641c86 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_camera_stop_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_camera_switch_2x.png b/TelegramClient.WP81/Images/W10M/ic_camera_switch_2x.png new file mode 100755 index 0000000..72c8fc3 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_camera_switch_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_camera_video_2x.png b/TelegramClient.WP81/Images/W10M/ic_camera_video_2x.png new file mode 100755 index 0000000..3260060 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_camera_video_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_cancel_2x.png b/TelegramClient.WP81/Images/W10M/ic_cancel_2x.png new file mode 100755 index 0000000..6fd4ee0 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_cancel_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_chats_2x.png b/TelegramClient.WP81/Images/W10M/ic_chats_2x.png new file mode 100755 index 0000000..a8e73bf Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_chats_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_commands_2x.png b/TelegramClient.WP81/Images/W10M/ic_commands_2x.png new file mode 100755 index 0000000..69f43cb Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_commands_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_delete_2x.png b/TelegramClient.WP81/Images/W10M/ic_delete_2x.png new file mode 100755 index 0000000..0f9b06b Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_delete_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_done_2x.png b/TelegramClient.WP81/Images/W10M/ic_done_2x.png new file mode 100755 index 0000000..1c66f25 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_done_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_edit_2x.png b/TelegramClient.WP81/Images/W10M/ic_edit_2x.png new file mode 100755 index 0000000..8e5de8e Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_edit_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_emoji_2x.png b/TelegramClient.WP81/Images/W10M/ic_emoji_2x.png new file mode 100755 index 0000000..a21327c Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_emoji_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_flash_auto_2x.png b/TelegramClient.WP81/Images/W10M/ic_flash_auto_2x.png new file mode 100755 index 0000000..e31fc89 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_flash_auto_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_flash_disabled_2x.png b/TelegramClient.WP81/Images/W10M/ic_flash_disabled_2x.png new file mode 100755 index 0000000..8735f4c Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_flash_disabled_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_flash_enabled_2x.png b/TelegramClient.WP81/Images/W10M/ic_flash_enabled_2x.png new file mode 100755 index 0000000..3bdd0ec Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_flash_enabled_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_gif_2x.png b/TelegramClient.WP81/Images/W10M/ic_gif_2x.png new file mode 100755 index 0000000..99d1fe9 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_gif_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_keyboard_2x.png b/TelegramClient.WP81/Images/W10M/ic_keyboard_2x.png new file mode 100755 index 0000000..80eacf1 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_keyboard_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_livelocation_2x.png b/TelegramClient.WP81/Images/W10M/ic_livelocation_2x.png new file mode 100755 index 0000000..125d2f2 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_livelocation_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_location_2x.png b/TelegramClient.WP81/Images/W10M/ic_location_2x.png new file mode 100755 index 0000000..20fd31b Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_location_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_masks_msk1.png b/TelegramClient.WP81/Images/W10M/ic_masks_msk1.png new file mode 100755 index 0000000..ddc0e1d Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_masks_msk1.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_microphone_2x.png b/TelegramClient.WP81/Images/W10M/ic_microphone_2x.png new file mode 100755 index 0000000..c8b5264 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_microphone_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_more_2x.png b/TelegramClient.WP81/Images/W10M/ic_more_2x.png new file mode 100755 index 0000000..8aa9f85 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_more_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_mutechannel_2x.png b/TelegramClient.WP81/Images/W10M/ic_mutechannel_2x.png new file mode 100755 index 0000000..8168e9d Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_mutechannel_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_muted_2x.png b/TelegramClient.WP81/Images/W10M/ic_muted_2x.png new file mode 100755 index 0000000..61bcc38 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_muted_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_notifications_2x.png b/TelegramClient.WP81/Images/W10M/ic_notifications_2x.png new file mode 100755 index 0000000..3bf330a Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_notifications_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_phone_2x.png b/TelegramClient.WP81/Images/W10M/ic_phone_2x.png new file mode 100755 index 0000000..3e82d1e Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_phone_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_photo_2x.png b/TelegramClient.WP81/Images/W10M/ic_photo_2x.png new file mode 100755 index 0000000..e5fce46 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_photo_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_pic_2x.png b/TelegramClient.WP81/Images/W10M/ic_pic_2x.png new file mode 100755 index 0000000..ca8cbcd Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_pic_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_pinnedchat_2x.png b/TelegramClient.WP81/Images/W10M/ic_pinnedchat_2x.png new file mode 100755 index 0000000..82e318b Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_pinnedchat_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_proxy_off_2x.png b/TelegramClient.WP81/Images/W10M/ic_proxy_off_2x.png new file mode 100755 index 0000000..6fca279 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_proxy_off_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_proxy_on_2x.png b/TelegramClient.WP81/Images/W10M/ic_proxy_on_2x.png new file mode 100755 index 0000000..9bdbe4f Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_proxy_on_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_quality1080_2x.png b/TelegramClient.WP81/Images/W10M/ic_quality1080_2x.png new file mode 100755 index 0000000..0ff9aa8 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_quality1080_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_quality2160_2x.png b/TelegramClient.WP81/Images/W10M/ic_quality2160_2x.png new file mode 100755 index 0000000..0e9fbf0 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_quality2160_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_quality240_2x.png b/TelegramClient.WP81/Images/W10M/ic_quality240_2x.png new file mode 100755 index 0000000..a438b80 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_quality240_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_quality360_2x.png b/TelegramClient.WP81/Images/W10M/ic_quality360_2x.png new file mode 100755 index 0000000..4f9129c Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_quality360_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_quality480_2x.png b/TelegramClient.WP81/Images/W10M/ic_quality480_2x.png new file mode 100755 index 0000000..536cdb5 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_quality480_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_quality720_2x.png b/TelegramClient.WP81/Images/W10M/ic_quality720_2x.png new file mode 100755 index 0000000..6cd4c4e Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_quality720_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_quality_auto_2x.png b/TelegramClient.WP81/Images/W10M/ic_quality_auto_2x.png new file mode 100755 index 0000000..524a866 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_quality_auto_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_sadsticker_2x.png b/TelegramClient.WP81/Images/W10M/ic_sadsticker_2x.png new file mode 100755 index 0000000..15b4ade Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_sadsticker_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_search_2x.png b/TelegramClient.WP81/Images/W10M/ic_search_2x.png new file mode 100755 index 0000000..d36cca9 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_search_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_searchinput_2x.png b/TelegramClient.WP81/Images/W10M/ic_searchinput_2x.png new file mode 100755 index 0000000..dfe8f5a Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_searchinput_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_secretchat_2x.png b/TelegramClient.WP81/Images/W10M/ic_secretchat_2x.png new file mode 100755 index 0000000..c4da13b Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_secretchat_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_select_2x.png b/TelegramClient.WP81/Images/W10M/ic_select_2x.png new file mode 100755 index 0000000..f740702 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_select_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_send_2x.png b/TelegramClient.WP81/Images/W10M/ic_send_2x.png new file mode 100755 index 0000000..8673a0c Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_send_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_sesurity_2x.png b/TelegramClient.WP81/Images/W10M/ic_sesurity_2x.png new file mode 100755 index 0000000..3e11a0a Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_sesurity_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_share_2x.png b/TelegramClient.WP81/Images/W10M/ic_share_2x.png new file mode 100755 index 0000000..6d68e42 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_share_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_stickers_2x.png b/TelegramClient.WP81/Images/W10M/ic_stickers_2x.png new file mode 100755 index 0000000..24f98fc Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_stickers_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_time_2x.png b/TelegramClient.WP81/Images/W10M/ic_time_2x.png new file mode 100755 index 0000000..e1ab008 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_time_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_timer_2x.png b/TelegramClient.WP81/Images/W10M/ic_timer_2x.png new file mode 100755 index 0000000..b23519e Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_timer_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_unmutechannel_2x.png b/TelegramClient.WP81/Images/W10M/ic_unmutechannel_2x.png new file mode 100755 index 0000000..74f449e Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_unmutechannel_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_updateapp_2x.png b/TelegramClient.WP81/Images/W10M/ic_updateapp_2x.png new file mode 100755 index 0000000..4260295 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_updateapp_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_username_2x.png b/TelegramClient.WP81/Images/W10M/ic_username_2x.png new file mode 100755 index 0000000..c2ca7f7 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_username_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/ic_verification_2x.png b/TelegramClient.WP81/Images/W10M/ic_verification_2x.png new file mode 100755 index 0000000..d068678 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/ic_verification_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/no_passport_2x.png b/TelegramClient.WP81/Images/W10M/no_passport_2x.png new file mode 100755 index 0000000..c5cc6cf Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/no_passport_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/no_password_2x.png b/TelegramClient.WP81/Images/W10M/no_password_2x.png new file mode 100755 index 0000000..66ee9e7 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/no_password_2x.png differ diff --git a/TelegramClient.WP81/Images/W10M/user_placeholder.png b/TelegramClient.WP81/Images/W10M/user_placeholder.png new file mode 100755 index 0000000..a0211d1 Binary files /dev/null and b/TelegramClient.WP81/Images/W10M/user_placeholder.png differ diff --git a/TelegramClient.WP81/Package.appxmanifest b/TelegramClient.WP81/Package.appxmanifest new file mode 100755 index 0000000..6afd5a1 --- /dev/null +++ b/TelegramClient.WP81/Package.appxmanifest @@ -0,0 +1,143 @@ + + + + + + Telegram Messenger + Telegram Messenger LLP + ApplicationIcon106.png + + + 6.3.1 + 6.3.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + .jpeg + .png + .jpg + .bmp + .mp4 + + Weblink + StorageItems + + + + + + + + + + + + + + + + + + + + + + + + + AgHostSvcs.dll + + + + + + PhoneVoIP.BackEnd.HostServer.exe + singleInstance + + + + + + PhoneVoIPApp.BackEndProxyStub.DLL + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/PhoneVoIP.BackEnd.HostServer.exe b/TelegramClient.WP81/PhoneVoIP.BackEnd.HostServer.exe new file mode 100755 index 0000000..976ae6a Binary files /dev/null and b/TelegramClient.WP81/PhoneVoIP.BackEnd.HostServer.exe differ diff --git a/TelegramClient.WP81/Properties/AppManifest.xml b/TelegramClient.WP81/Properties/AppManifest.xml new file mode 100755 index 0000000..a955232 --- /dev/null +++ b/TelegramClient.WP81/Properties/AppManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/TelegramClient.WP81/Properties/AssemblyInfo.cs b/TelegramClient.WP81/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..215761e --- /dev/null +++ b/TelegramClient.WP81/Properties/AssemblyInfo.cs @@ -0,0 +1,44 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// 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("TelegramClient.WP8")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TelegramClient.WP8")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[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("71105f98-f9d4-469f-a185-640c6024c9a0")] + +// 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")] +[assembly: NeutralResourcesLanguageAttribute("en")] diff --git a/TelegramClient.WP81/Properties/WMAppManifest.Private.xml b/TelegramClient.WP81/Properties/WMAppManifest.Private.xml new file mode 100755 index 0000000..c9b00a1 --- /dev/null +++ b/TelegramClient.WP81/Properties/WMAppManifest.Private.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + ApplicationIcon106.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IconicSmall110.png + 0 + IconicTileMedium202.png + Telegram + true + Images\LockScreen\lockscreen.png + + + + + + + + + + + + + + PhoneVoIPApp.BackEnd.DLL + + + + + + + + + + + + PhoneVoIPApp.BackEnd.DLL + multipleInstances + + + + PhoneVoIPApp.BackEndProxyStub.DLL + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Properties/WMAppManifest.Public.xml b/TelegramClient.WP81/Properties/WMAppManifest.Public.xml new file mode 100755 index 0000000..2b22011 --- /dev/null +++ b/TelegramClient.WP81/Properties/WMAppManifest.Public.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + ApplicationIcon106.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IconicSmall110.png + 0 + IconicTileMedium202.png + Telegram Messenger + true + Images\LockScreen\lockscreen.png + + + + + + + + + + + + + + PhoneVoIPApp.BackEnd.DLL + + + + + + + + + + + + PhoneVoIPApp.BackEnd.DLL + multipleInstances + + + + PhoneVoIPApp.BackEndProxyStub.DLL + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Properties/WMAppManifest.xml b/TelegramClient.WP81/Properties/WMAppManifest.xml new file mode 100755 index 0000000..2b22011 --- /dev/null +++ b/TelegramClient.WP81/Properties/WMAppManifest.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + ApplicationIcon106.png + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IconicSmall110.png + 0 + IconicTileMedium202.png + Telegram Messenger + true + Images\LockScreen\lockscreen.png + + + + + + + + + + + + + + PhoneVoIPApp.BackEnd.DLL + + + + + + + + + + + + PhoneVoIPApp.BackEnd.DLL + multipleInstances + + + + PhoneVoIPApp.BackEndProxyStub.DLL + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/PushNotificationsBackgroundTask.cs b/TelegramClient.WP81/PushNotificationsBackgroundTask.cs new file mode 100755 index 0000000..6542f8c --- /dev/null +++ b/TelegramClient.WP81/PushNotificationsBackgroundTask.cs @@ -0,0 +1,81 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Threading; +using Windows.ApplicationModel.Background; +#if WNS_PUSH_SERVICE +using Windows.Networking.PushNotifications; +#endif +using Telegram.Api.Extensions; + +namespace TelegramClient.Tasks +{ + public sealed class PushNotificationsBackgroundTask : IBackgroundTask + { + private readonly Mutex _appOpenMutex = new Mutex(false, Telegram.Api.Constants.TelegramMessengerMutexName); + + private static bool _logEnabled = true; + + private static readonly int _id = new Random().Next(999); + + private static void Log(string message, Action callback = null) + { + if (!_logEnabled) return; + + Telegram.Logs.Log.Write(string.Format("::PushNotificationsBackgroundTask {0} {1}", _id, message), callback.SafeInvoke); +#if DEBUG + //PushUtils.AddToast("push", message, string.Empty, string.Empty, null, null); +#endif + } + + public void Run(IBackgroundTaskInstance taskInstance) + { +#if WNS_PUSH_SERVICE + Telegram.Logs.Log.WriteSync = true; + + var stopwatch = Stopwatch.StartNew(); + + var rawNotification = taskInstance.TriggerDetails as RawNotification; + var payload = rawNotification != null ? rawNotification.Content : null; + var rootObject = payload != null ? PushUtils.GetRootObject(payload) : null; + var data = rootObject != null ? rootObject.data : null; + var locKey = data != null ? data.loc_key : null; + + Log(string.Format("start locKey={0}", locKey)); + if (!_appOpenMutex.WaitOne(0)) + { + Log("cancel"); + + return; + } + _appOpenMutex.ReleaseMutex(); + + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (!isAuthorized) + { + Log(string.Format("cancel isAuthorized=false\npayload={0}", payload)); + } + + //var culture = Utils.CurrentUICulture(); + //var resourceLoader = new ResourceLoader("TelegramClient.Tasks/Resources"); + //var str = resourceLoader.GetString("MESSAGE_TEXT"); + //PushUtils.AddToast("resource", str + " " + culture, string.Empty); + try + { + PushUtils.UpdateToastAndTiles(taskInstance.TriggerDetails as RawNotification); + } + catch (Exception ex) + { + Log(string.Format("ex={0}\npayload={1}", ex, payload)); + } + + Log(string.Format("stop elapsed={0}", stopwatch.Elapsed)); +#endif + } + } +} diff --git a/TelegramClient.WP81/Services/Cache.cs b/TelegramClient.WP81/Services/Cache.cs new file mode 100755 index 0000000..99e1046 --- /dev/null +++ b/TelegramClient.WP81/Services/Cache.cs @@ -0,0 +1,344 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; + +namespace TelegramClient.Services +{ + internal class LinkedDictionary + { + private readonly LinkedList _queue = new LinkedList(); + + private readonly Dictionary, TValue>> _cache = new Dictionary, TValue>>(); + + public LinkedDictionary() + { + + } + + public void AddFirst(TKey key, TValue value) + { + try + { + var node = _queue.AddFirst(key); + _cache[key] = new KeyValuePair, TValue>(node, value); + } + catch (Exception ex) + { + + } + } + + public void RemoveLast() + { + var last = _queue.Last; + + _queue.RemoveLast(); + _cache.Remove(last.Value); + } + + public KeyValuePair First + { + get + { + var node = _queue.First; + + KeyValuePair, TValue> result; + if (node != null && _cache.TryGetValue(node.Value, out result)) + { + return new KeyValuePair(node.Value, result.Value); + } + + return new KeyValuePair(); + } + } + + public KeyValuePair Last + { + get + { + var node = _queue.Last; + + KeyValuePair, TValue> result; + if (node != null && _cache.TryGetValue(node.Value, out result)) + { + return new KeyValuePair(node.Value, result.Value); + } + + return new KeyValuePair(); + } + } + + public int Count + { + get { return _queue.Count; } + } + + public void Add(TKey key, TValue value) + { + KeyValuePair, TValue> tuple; + if (!_cache.TryGetValue(key, out tuple)) + { + var node = _queue.AddLast(key); // O(1) + _cache[key] = new KeyValuePair, TValue>(node, value); // O(1) + } + } + + public bool Remove(TKey key) + { + KeyValuePair, TValue> tuple; + if (_cache.TryGetValue(key, out tuple)) + { + _cache.Remove(key); // O(1) + _queue.Remove(tuple.Key); // O(1) + + return true; + } + + return false; + } + + public bool TryGetValue(TKey key, out TValue value) + { + KeyValuePair, TValue> tuple; + if (_cache.TryGetValue(key, out tuple)) + { + value = tuple.Value; + + return true; + } + + value = default(TValue); + + return false; + } + + public TValue this[TKey key] + { + get + { + TValue value; + if (TryGetValue(key, out value)) + { + return value; + } + + throw new KeyNotFoundException(); + } + set + { + Add(key, value); + } + } + } + + public class LRUCache + { + private readonly LinkedList _queue = new LinkedList(); + + private readonly Dictionary, TValue>> _cache; + + private readonly int _capacity; + + private readonly object _syncRoot = new object(); + + public LRUCache(int capacity) + { + _capacity = capacity; + _cache = new Dictionary, TValue>>(capacity); + } + + public void Add(TKey key, TValue value) + { + lock (_syncRoot) + { + KeyValuePair, TValue> tuple; + if (_cache.TryGetValue(key, out tuple)) + { + _queue.Remove(tuple.Key); // O(1) + var node = _queue.AddLast(key); // O(1) + _cache[key] = new KeyValuePair, TValue>(node, value); + } + else + { + if (_cache.Count == _capacity) + { + var first = _queue.First; + + _queue.RemoveFirst(); // O(1) + _cache.Remove(first.Value); // O(1) + } + + var node = _queue.AddLast(key); + _cache[key] = new KeyValuePair, TValue>(node, value); + } + } + } + + public void Remove(TKey key) + { + lock (_syncRoot) + { + KeyValuePair, TValue> tuple; + if (_cache.TryGetValue(key, out tuple)) + { + _cache.Remove(key); // O(1) + _queue.Remove(tuple.Key); // O(1) + } + } + } + + public bool TryGetValue(TKey key, out TValue value) + { + lock (_syncRoot) + { + KeyValuePair, TValue> tuple; + if (_cache.TryGetValue(key, out tuple)) + { + value = tuple.Value; + + _queue.Remove(tuple.Key); // O(1) + _queue.AddLast(tuple.Key); // O(1) + + return true; + } + + value = default(TValue); + + return false; + } + } + + public TValue this[TKey key] + { + get + { + TValue value; + if (TryGetValue(key, out value)) + { + return value; + } + + throw new KeyNotFoundException(); + } + set + { + Add(key, value); + } + } + } + + /// https://pdfs.semanticscholar.org/d62d/e5f995164fff50f5ce61c0113f6bc9f04225.pdf + /// A1 - _inQueue, _outQueue + /// Am - _cache + public class TwoQueueCache + { + private readonly LRUCache _cache; + + private readonly LinkedDictionary _inQueue = new LinkedDictionary(); + + private readonly LinkedDictionary _outQueue = new LinkedDictionary(); + + private readonly int _cacheCapacity; + + private readonly int _inQueueCapacity; + + private readonly int _outQueueCapacity; + + private readonly object _syncRoot = new object(); + + public TwoQueueCache(int capacity) + { + _inQueueCapacity = (int)(0.25 * capacity); + _outQueueCapacity = (int)(0.5 * capacity); + _cacheCapacity = capacity - _inQueueCapacity - _outQueueCapacity; + + _cache = new LRUCache(_cacheCapacity); + } + + public void Add(TKey key, TValue value) + { + lock (_syncRoot) + { + // make room + if (_inQueue.Count > _inQueueCapacity) + { + if (_outQueue.Count > _outQueueCapacity) + { + _outQueue.RemoveLast(); // O(1) + } + + var last = _inQueue.Last; + _inQueue.RemoveLast(); // O(1) + _outQueue.AddFirst(last.Key, last.Value); // O(1) + } + + // add + _inQueue.AddFirst(key, value); // O(1) + } + } + + public bool Remove(TKey key) + { + lock (_syncRoot) + { + _inQueue.Remove(key); // O(1) + _outQueue.Remove(key); // O(1) + _cache.Remove(key); // O(1) + } + + return true; + } + + public bool TryGetValue(TKey key, out TValue value) + { + lock (_syncRoot) + { + if (_inQueue.TryGetValue(key, out value)) + { + return true; + } + + if (_outQueue.TryGetValue(key, out value)) + { + _outQueue.Remove(key); // O(1) + _cache.Add(key, value); // O(1) + + return true; + } + + if (_cache.TryGetValue(key, out value)) + { + return true; + } + + value = default(TValue); + + return false; + } + } + + public TValue this[TKey key] + { + get + { + TValue value; + if (TryGetValue(key, out value)) + { + return value; + } + + throw new KeyNotFoundException(); + } + set + { + Add(key, value); + } + } + } +} diff --git a/TelegramClient.WP81/Services/IProxyChecker.cs b/TelegramClient.WP81/Services/IProxyChecker.cs new file mode 100755 index 0000000..8bcc761 --- /dev/null +++ b/TelegramClient.WP81/Services/IProxyChecker.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.TL; + +namespace TelegramClient.Services +{ + public interface IProxyChecker + { + //void CheckAsync(IList list, double timeout); + void CheckAsync(TLProxyBase proxy, double timeout, Action callback); + void CancelAsync(TLProxyBase proxy); + } +} diff --git a/TelegramClient.WP81/Services/IVoIPService.cs b/TelegramClient.WP81/Services/IVoIPService.cs new file mode 100755 index 0000000..041613d --- /dev/null +++ b/TelegramClient.WP81/Services/IVoIPService.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Telegram.Api.TL; + +namespace TelegramClient.Services +{ + public interface IVoIPService + { + long AcceptedCallId { get; set; } + TLPhoneCallBase Call { get; } + TLInt UserId { get; } + void StartOutgoingCall(TLUser user, Action callback); + void AcceptIncomingCall(TLPhoneCallRequested64 requestedCall); + string GetDebugString(); + string GetDebugLog(long callId); + string GetVersion(); + void HangUp(); + string[] GetEmojis(); + void SwitchSpeaker(bool external); + void Mute(bool muted); + int GetSignalBarsCount(); + } +} diff --git a/TelegramClient.WP81/Services/IWindowsPhoneStoreUpdateService.cs b/TelegramClient.WP81/Services/IWindowsPhoneStoreUpdateService.cs new file mode 100755 index 0000000..73bae80 --- /dev/null +++ b/TelegramClient.WP81/Services/IWindowsPhoneStoreUpdateService.cs @@ -0,0 +1,16 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace TelegramClient.Services +{ + interface IWindowsPhoneStoreUpdateService + { + void CheckForUpdatedVersion(string updateDialogText, string updateDialogTitle); + + void LaunchAppUpdateAsync(); + } +} diff --git a/TelegramClient.WP81/Services/ProxyChecker.cs b/TelegramClient.WP81/Services/ProxyChecker.cs new file mode 100755 index 0000000..3d0c894 --- /dev/null +++ b/TelegramClient.WP81/Services/ProxyChecker.cs @@ -0,0 +1,110 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.TL; +using Telegram.Api.Transport; + +namespace TelegramClient.Services +{ + public class ProxyChecker : IProxyChecker + { + private object _syncRoot = new object(); + + private readonly ITransportService _transportService; + + private readonly IMTProtoService _mtProtoService; + + private List _list = new List(); + + //private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(4); + + public ProxyChecker(ITransportService transportService, IMTProtoService mtProtoService) + { + _transportService = transportService; + _mtProtoService = mtProtoService; + } + + private TLInt CheckProxyInternal(ProxyItem item) + { + TLInt ping = null; + var handler = new ManualResetEvent(false); + _mtProtoService.PingProxyAsync(item.Proxy, + result => + { + ping = result; + handler.Set(); + }, + error => + { + handler.Set(); + }); + +#if DEBUG + var complete = handler.WaitOne(Timeout.Infinite); +#else + var complete = handler.WaitOne(TimeSpan.FromSeconds(item.Timeout)); +#endif + + return ping; + } + + public void CheckAsync(TLProxyBase proxy, double timeout, Action callback) + { + var proxyItem = new ProxyItem + { + Proxy = proxy, + Timeout = timeout + }; + + var cts = new CancellationTokenSource(); + var task = new Task(() => + { + var ping = CheckProxyInternal(proxyItem); + _list.Remove(proxyItem); + if (!cts.Token.IsCancellationRequested) + { + callback.SafeInvoke(proxyItem, ping); + } + }); + + proxyItem.TokenSource = cts; + proxyItem.Task = task; + + _list.Add(proxyItem); + + task.Start(); + } + + public void CancelAsync(TLProxyBase proxy) + { + var item = _list.FirstOrDefault(x => x.Proxy == proxy); + if (item != null) + { + _list.Remove(item); + item.TokenSource.Cancel(); + } + } + } + + public class ProxyItem + { + public TLProxyBase Proxy { get; set; } + + public double Timeout { get; set; } + + public CancellationTokenSource TokenSource { get; set; } + + public Task Task { get; set; } + } +} diff --git a/TelegramClient.WP81/Services/VoIPService.cs b/TelegramClient.WP81/Services/VoIPService.cs new file mode 100755 index 0000000..7d1cc91 --- /dev/null +++ b/TelegramClient.WP81/Services/VoIPService.cs @@ -0,0 +1,1507 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Threading; +using Windows.Data.Json; +using Windows.Networking.Connectivity; +using Windows.Phone.Media.Devices; +using Windows.Phone.Networking.Voip; +using Windows.Storage; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Microsoft.Xna.Framework.Audio; +using TelegramClient.Controls; +using TelegramClient.ViewModels; +using PhoneVoIPApp.BackEnd; +using PhoneVoIPApp.UI; +using Org.BouncyCastle.Security; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using Telegram.Api.Transport; +using TelegramClient.ViewModels.Additional; +using TelegramClient.Views.Additional; +using TelegramClient.Views.Controls; +using Action = System.Action; +using Execute = Telegram.Api.Helpers.Execute; + +namespace TelegramClient.Services +{ + public class VoIPService : IVoIPService, Telegram.Api.Aggregator.IHandle, IDisposable, ICallControllerStatusListener + { + public long AcceptedCallId { get; set; } + + private PhoneCallSound _spPlayId; + + private TLInt _userId; + + public TLInt UserId { get { return _userId; } } + + public TLPhoneCallBase Call { get { return _call; } } + + private readonly IMTProtoService _mtProtoService; + + private readonly ITelegramEventAggregator _eventAggregator; + + private readonly ICacheService _cacheService; + + private readonly IStateService _stateService; + + private readonly ITransportService _transportService; + + private Action _timeoutRunnable; + + private readonly DispatcherTimer _timer = new DispatcherTimer(); + + public VoIPService(IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator, ICacheService cacheService, IStateService stateService, ITransportService transportService) + { + _mtProtoService = mtProtoService; + _eventAggregator = eventAggregator; + _cacheService = cacheService; + _stateService = stateService; + _transportService = transportService; + + NetworkInformation.NetworkStatusChanged += UpdateNetworkType; + _timer.Tick += OnTimerTick; + + if (BackgroundProcessController.Instance != null + && BackgroundProcessController.Instance.CallController != null) + { + var callController = BackgroundProcessController.Instance.CallController; + Telegram.Logs.Log.Write(string.Format("VoIPService.ctor call={0} user_id={1} callController call_status={2} key={3} call_id={4}", _call != null, _userId != null, callController.CallStatus, callController.Key != null, callController.CallId)); + BackgroundProcessController.Instance.CallController.SetStatusCallback(this); + + if (_call == null || _userId == null) + { + if (BackgroundProcessController.Instance.CallController.CallStatus == CallStatus.InProgress + || BackgroundProcessController.Instance.CallController.CallStatus == CallStatus.Held + || BackgroundProcessController.Instance.CallController.CallStatus == CallStatus.None) + { + if (BackgroundProcessController.Instance.CallController.Key != null) + { + lock (__callSyncRoot) + { + SetCall(new TLPhoneCall + { + Id = new TLLong(BackgroundProcessController.Instance.CallController.CallId), + AccessHash = + new TLLong(BackgroundProcessController.Instance.CallController.CallAccessHash) + }); + } + + _userId = new TLInt((int) BackgroundProcessController.Instance.CallController.OtherPartyId); + _authKey = BackgroundProcessController.Instance.CallController.Key; + _outgoing = BackgroundProcessController.Instance.CallController.Outgoing; + _emojis = BackgroundProcessController.Instance.CallController.Emojis; + + var frame = Application.Current.RootVisual as TelegramTransitionFrame; + if (frame != null) + { + frame.ShowCallPlaceholder(ShellViewModel.OpenCurrentCall); + } + } + } + } + } + else + { + Telegram.Logs.Log.Write("VoIPService.ctor empty"); + } + + _eventAggregator.Subscribe(this); + } + + ~VoIPService() + { + BackgroundProcessController.Instance.CallController.SetStatusCallback(null); + } + + private void SetCall(TLPhoneCallBase newCall) + { + lock (__callSyncRoot) + { + var callDiscarded = _call as TLPhoneCallDiscarded61; + if (callDiscarded != null + && newCall != null + && callDiscarded.Id.Value == newCall.Id.Value) + { + Telegram.Logs.Log.Write(string.Format("SetCall skip\ncurrent={0}\nnew={1}", _call, newCall)); + return; + } + + _call = newCall; + } + } + + private void RunTimer(TimeSpan interval) + { + _timer.Stop(); + _timer.Interval = interval; + _timer.Start(); + } + + private void CancelTimer() + { + _timer.Stop(); + } + + private void OnTimerTick(object sender, System.EventArgs e) + { + _timer.Stop(); + if (_timeoutRunnable != null) + { + _timeoutRunnable(); + } + } + + private void UpdateNetworkType(object sender) + { + //return; + //var networkType = GetNetworkType(); + + //if (_controller != null) + //{ + // _controller.SetNetworkType(networkType); + //} + } + + private NetworkType GetNetworkType() + { + var profile = NetworkInformation.GetInternetConnectionProfile(); + if (profile != null) + { + if (profile.NetworkAdapter.IanaInterfaceType == 6) + { + return NetworkType.Ethernet; + } + + if (profile.IsWlanConnectionProfile) + { + //wi-fi + return NetworkType.WiFi; + } + + if (profile.IsWwanConnectionProfile) + { + //mobile + var connectionClass = profile.WwanConnectionProfileDetails.GetCurrentDataClass(); + switch (connectionClass) + { + //2G-equivalent + case WwanDataClass.Edge: + return NetworkType.EDGE; + case WwanDataClass.Gprs: + return NetworkType.GPRS; + //3G-equivalent + case WwanDataClass.Cdma1xEvdo: + case WwanDataClass.Cdma1xEvdoRevA: + case WwanDataClass.Cdma1xEvdoRevB: + case WwanDataClass.Cdma1xEvdv: + case WwanDataClass.Cdma1xRtt: + case WwanDataClass.Cdma3xRtt: + case WwanDataClass.CdmaUmb: + case WwanDataClass.Umts: + return NetworkType.UMTS; + case WwanDataClass.Hsdpa: + case WwanDataClass.Hsupa: + return NetworkType.HSPA; + //4G-equivalent + case WwanDataClass.LteAdvanced: + return NetworkType.LTE; + + //not connected + case WwanDataClass.None: + return NetworkType.Unknown; + + //unknown + case WwanDataClass.Custom: + default: + return NetworkType.OtherMobile; + } + } + } + + return NetworkType.Unknown; + } + + private const int CALL_MIN_LAYER = 65; + private const int CALL_MAX_LAYER = 74; + + private TLString _secretP; + + private TLString _secretRandom; + + private TLInt _secretG; + + private TLInt _lastVersion; + + private byte[] _ga; + + private readonly object __callSyncRoot = new object(); + + private TLPhoneCallBase _call; + private byte[] _aOrB; + private byte[] _authKey; + private bool _outgoing = true; + + //private VoIPControllerWrapper _controller; + //private CallController _controller; + //BackgroundProcessController.Instance.CallController + private Error _lastError; + + private bool _controllerStarted; + private DateTime? _startCallTime; + private bool _needSendDebugLog; + private PhoneCallState _currentState; + private int _signal; + private bool _endCallAfterRequest; + private string[] _emojis; + private bool _needPlayEndSound; + private IList _pendingUpdates = new List(); + private byte[] _gb; + private string _debugLog; + private long _debugCallId; + + //private VoipPhoneCall _voipPhoneCall; + + public void StartOutgoingCall(TLUser user, Action callback) + { + SetCall(null); + _authKey = null; + + if (user == null) + { + return; + } + + var inputUser = user.ToInputUser(); + if (inputUser == null) + { + return; + } + + _userId = user.Id; + + ConfigureDeviceForCall(); + ShowNotifications(); + StartConnectingSound(); + DispatchStateChanged(PhoneCallState.STATE_REQUESTING); + _outgoing = true; + + var salt = new Byte[256]; + var random = new SecureRandom(); + random.NextBytes(salt); + + var version = _lastVersion ?? new TLInt(0); + var randomLength = new TLInt(256); + + _mtProtoService.GetDHConfigAsync(version, randomLength, + result => + { + var dhConfig = result as TLDHConfig; + if (dhConfig != null) + { + if (!TLUtils.CheckPrime(dhConfig.P.Data, dhConfig.G.Value)) + { + CallFailed(); + return; + } + + _secretP = dhConfig.P; + _secretG = dhConfig.G; + _secretRandom = dhConfig.Random; + } + + for (var i = 0; i < 256; i++) + { + salt[i] = (byte) (salt[i] ^ _secretRandom.Data[i]); + } + + var gaBytes = MTProtoService.GetGB(salt, _secretG, _secretP); + + var protocol = new TLPhoneCallProtocol + { + Flags = new TLInt(0), + UdpP2P = true, + UdpReflector = true, + MinLayer = new TLInt(CALL_MIN_LAYER), + MaxLayer = new TLInt(CALL_MAX_LAYER) + }; + _ga = gaBytes; + var gaHash = Telegram.Api.Helpers.Utils.ComputeSHA256(_ga); + + _mtProtoService.RequestCallAsync(user.ToInputUser(), TLInt.Random(), TLString.FromBigEndianData(gaHash), protocol, + result2 => + { + SetCall(result2.PhoneCall); + _aOrB = salt; + DispatchStateChanged(PhoneCallState.STATE_WAITING); + + if (_pendingUpdates.Count > 0 && _call != null) + { + foreach (var updatePhoneCall in _pendingUpdates) + { + Handle(updatePhoneCall); + } + _pendingUpdates.Clear(); + } + + callback.SafeInvoke(result2.PhoneCall.Id); + + Execute.BeginOnUIThread(() => + { + _timeoutRunnable = () => + { + _timeoutRunnable = null; + + var inputPhoneCall = _call as IInputPhoneCall; + if (inputPhoneCall != null) + { + var duration = _controllerStarted ? (GetCallDuration() / 1000) : 0; + var connectionId = _controllerStarted ? BackgroundProcessController.Instance.CallController.GetPreferredRelayID() : 0; + + _mtProtoService.DiscardCallAsync(inputPhoneCall.ToInputPhoneCall(), new TLInt(duration), new TLPhoneCallDiscardReasonMissed(), new TLLong(connectionId), + result3 => + { + Telegram.Logs.Log.Write("phone.discardCall result " + result3); + }, + error3 => + { + Telegram.Logs.Log.Write("phone.discardCall error " + error3); + CallFailed(); + }); + } + }; + + var config = _cacheService.GetConfig() as TLConfig63; + var timeout = config != null ? config.CallReceiveTimeoutMs.Value : 30000; + RunTimer(TimeSpan.FromMilliseconds(timeout)); + }); + }, + error2 => + { + + }); + }, + error => + { + Telegram.Logs.Log.Write("messages.getDHConfig error " + error); + CallFailed(); + }); + } + + public void AcceptIncomingCall(TLPhoneCallRequested64 callRequested) + { + if (callRequested == null) return; + + _authKey = null; + + StopRinging(); + ShowNotification(); + ConfigureDeviceForCall(); + StartConnectingSound(); + DispatchStateChanged(PhoneCallState.STATE_EXCHANGING_KEYS); + + var salt = new Byte[256]; + var random = new SecureRandom(); + random.NextBytes(salt); + + var version = _lastVersion ?? new TLInt(0); + var randomLength = new TLInt(256); + + _mtProtoService.GetDHConfigAsync(version, randomLength, + result => + { + var dhConfig = result as TLDHConfig; + if (dhConfig != null) + { + if (!TLUtils.CheckPrime(dhConfig.P.Data, dhConfig.G.Value)) + { + CallFailed(); + return; + } + + _secretP = dhConfig.P; + _secretG = dhConfig.G; + _secretRandom = dhConfig.Random; + } + + for (var i = 0; i < 256; i++) + { + salt[i] = (byte)(salt[i] ^ _secretRandom.Data[i]); + } + + _aOrB = salt; + var gbBytes = MTProtoService.GetGB(salt, _secretG, _secretP); + + var protocol = new TLPhoneCallProtocol + { + Flags = new TLInt(0), + UdpP2P = true, + UdpReflector = true, + MinLayer = new TLInt(CALL_MIN_LAYER), + MaxLayer = new TLInt(CALL_MAX_LAYER) + }; + _gb = gbBytes; + + _mtProtoService.AcceptCallAsync(callRequested.ToInputPhoneCall(), TLString.FromBigEndianData(gbBytes), protocol, + result2 => + { + Telegram.Logs.Log.Write(string.Format("phone.acceptCall result={0} current={1}", result2, _call)); + SetCall(result2.PhoneCall); + + if (result2.PhoneCall is TLPhoneCallDiscarded61) + { + Handle(new TLUpdatePhoneCall { PhoneCall = result2.PhoneCall }); + } + }, + error2 => + { + Telegram.Logs.Log.Write("phone.acceptCall error=" + error2); + CallFailed(); + }); + }, + error => + { + Telegram.Logs.Log.Write("messages.getDHConfig error " + error); + CallFailed(); + }); + } + + private void ShowNotification() + { + + } + + private void StopRinging() + { + Execute.BeginOnUIThread(() => + { + _maxLoopedCount = 0; + _lastLoopedUri = null; + MessagePlayerControl.Player.Stop(); + }); + } + + + private void VoipPhoneCall_RejectRequested(VoipPhoneCall sender, CallRejectEventArgs args) + { + + } + + private void VoipPhoneCall_AnswerRequested(VoipPhoneCall sender, CallAnswerEventArgs args) + { + + } + + private void DispatchStateChanged(PhoneCallState callState) + { + System.Diagnostics.Debug.WriteLine(" DispatchSateChanged state=" + callState); + _currentState = callState; + _eventAggregator.Publish(new PhoneCallStateChangedEventArgs{CallState = callState, Call = Call }); + } + + private void StartConnectingSound() + { + PlaySound(PhoneCallSound.Connecting, -1); + } + + private void ShowNotifications() + { + + + } + + private void ConfigureDeviceForCall() + { + _needPlayEndSound = true; + } + + private void CallFailed() + { + CallFailed(_controllerStarted ? BackgroundProcessController.Instance.CallController.GetLastError() : 0); + } + + private void CallFailed(Error errorCode) + { + Telegram.Logs.Log.Write("Call " + (_call != null ? _call.Id.Value : 0)+" failed with error code " + errorCode); + + _lastError = errorCode; + if (_call != null) + { + Telegram.Logs.Log.Write("Discarding failed call"); + + var phoneCall = _call as IInputPhoneCall; + if (phoneCall != null) + { + var peer = phoneCall.ToInputPhoneCall(); + var duration = _controllerStarted ? (GetCallDuration() / 1000) : 0; + var connectionId = _controllerStarted ? BackgroundProcessController.Instance.CallController.GetPreferredRelayID() : 0; + var reason = new TLPhoneCallDiscardReasonDisconnect(); + + _mtProtoService.DiscardCallAsync(peer, new TLInt(duration), reason, new TLLong(connectionId), + result => + { + Telegram.Logs.Log.Write("phone.discardCall result=" + result); + }, + error => + { + Telegram.Logs.Log.Write("phone.discardCall error=" + error); + }); + } + } + DispatchStateChanged(PhoneCallState.STATE_FAILED); + PlaySound(PhoneCallSound.Failed, 0); + + BackgroundProcessController.Instance.CallController.EndCall(); + + StopSelf(); + + //if(errorCode!=VoIPController.ERROR_LOCALIZED && soundPool!=null){ + // playingSound=true; + // soundPool.play(spFailedID, 1, 1, 0, 0, 1); + // AndroidUtilities.runOnUIThread(new Runnable(){ + // @Override + // public void run(){ + // soundPool.release(); + // if(isBtHeadsetConnected) + // ((AudioManager) ApplicationLoader.applicationContext.getSystemService(AUDIO_SERVICE)).stopBluetoothSco(); + // } + // }, 1000); + //} + //StopSelf(); + } + + private void CallEnded() + { + Telegram.Logs.Log.Write("Call " + (_call != null ? _call.Id.Value : 0) + " ended"); + DispatchStateChanged(PhoneCallState.STATE_ENDED); + if (_needPlayEndSound) + { + _needPlayEndSound = false; + PlaySound(PhoneCallSound.End, 0); + + //playingSound = true; + //soundPool.play(spEndId, 1, 1, 0, 0, 1); + //AndroidUtilities.runOnUIThread(new Runnable() { + // @Override + // public void run() { + // soundPool.release(); + // if(isBtHeadsetConnected) + // ((AudioManager)ApplicationLoader.applicationContext.getSystemService(AUDIO_SERVICE)).stopBluetoothSco(); + // } + //}, 1000); + } + else + { + StopRinging(); + } + Execute.BeginOnUIThread(() => + { + if (_timeoutRunnable != null) + { + CancelTimer(); + _timeoutRunnable = null; + } + }); + + BackgroundProcessController.Instance.CallController.EndCall(); + + StopSelf(); + } + + private int GetCallDuration() + { + if (_startCallTime.HasValue) + { + return (int) (DateTime.Now - _startCallTime.Value).TotalMilliseconds; + } + + return 0; + } + + public void Handle(TLUpdatePhoneCall updatePhoneCall) + { + Telegram.Logs.Log.Write(string.Format("VoIPService.Handle\nupdated_call={0}\ncurrent_call={1}", updatePhoneCall.PhoneCall, _call)); + //if (_call == null) + //{ + // _pendingUpdates.Add(updatePhoneCall); + // return; + //} + + if (updatePhoneCall == null) + { + return; + } + + if (Call != null + && !(Call is TLPhoneCallDiscarded) + && Call.Id.Value != updatePhoneCall.PhoneCall.Id.Value) + { + if (updatePhoneCall.PhoneCall is TLPhoneCallRequestedBase) + { + DeclineIncomingCallInternal(PhoneDiscardReason.DISCARD_REASON_LINE_BUSY, () => { }, updatePhoneCall.PhoneCall); + } + + return; + } + //if (updatePhoneCall.PhoneCall.Id.Value != _call.PhoneCall.Id.Value) + //{ + // var error = "onCallUpdated called with wrong call id (got " + updatePhoneCall.PhoneCall.Id.Value + ", expected " + _call.PhoneCall.Id.Value + ")"; + // Telegram.Logs.Log.Write(error); + // Execute.ShowDebugMessage(error); + // return; + //} + + var phoneCallBase = updatePhoneCall.PhoneCall; + + var phoneCallAccepted = phoneCallBase as TLPhoneCallAccepted; + if (phoneCallAccepted != null) + { + if (_authKey == null) + { + ProcessAcceptedCall(phoneCallAccepted); + } + + return; + } + + var phoneCall = phoneCallBase as TLPhoneCall; + if (phoneCall != null) + { + if (_authKey == null) + { + ProcessIncomingCall(phoneCall); + } + + return; + } + + var phoneCallDiscarded = phoneCallBase as TLPhoneCallDiscarded61; + if (phoneCallDiscarded != null) + { + var currentCall = _call; + if (currentCall != null) + { + SetCall(phoneCallDiscarded); + _needSendDebugLog = phoneCallDiscarded.NeedDebug; + Telegram.Logs.Log.Write("call discarded, stopping service"); + if (phoneCallDiscarded.Reason is TLPhoneCallDiscardReasonBusy) + { + DispatchStateChanged(PhoneCallState.STATE_BUSY); + + PlaySound(PhoneCallSound.Busy, 2); + StopSelf(); + //playingSound = true; + //soundPool.play(spBusyId, 1, 1, 0, -1, 1); + //AndroidUtilities.runOnUIThread(new Runnable() { + // @Override + // public void run() { + // soundPool.release(); + // if(isBtHeadsetConnected) + // ((AudioManager)ApplicationLoader.applicationContext.getSystemService(AUDIO_SERVICE)).stopBluetoothSco(); + // } + //}, 2500); + //stopSelf(); + } + else + { + CallEnded(); + } + + if (phoneCallDiscarded.NeedDebug) + { + _debugCallId = _call.Id.Value; + _debugLog = BackgroundProcessController.Instance.CallController.GetDebugLog(); + } + + BackgroundProcessController.Instance.CallController.DeleteVoIPControllerWrapper(); + //if (_controller != null) + //{ + // _controller.Dispose(); + // _controller = null; + //} + _eventAggregator.Publish(new PhoneCallDiscardedEventArgs { Call = currentCall, DiscardedCall = phoneCallDiscarded, Outgoing = _outgoing }); + + if (phoneCallDiscarded.NeedRating) + { + StartRatingActivity(); + } + } + } + + var phoneCallRequested = phoneCallBase as TLPhoneCallRequested64; + if (phoneCallRequested != null) + { + SetCall(phoneCallRequested); + _outgoing = false; + OnStartCommand(); + _eventAggregator.Publish(new PhoneCallRequestedEventArgs{ RequestedCall = phoneCallRequested }); + + Execute.BeginOnUIThread(() => + { + if (_timeoutRunnable != null) + { + _timeoutRunnable = null; + CancelTimer(); + } + + _timeoutRunnable = () => + { + _timeoutRunnable = null; + DeclineIncomingCall(PhoneDiscardReason.DISCARD_REASON_MISSED, null); + }; + var config = _cacheService.GetConfig() as TLConfig63; + var timeout = config != null ? config.CallRingTimeoutMs.Value : 30000; + RunTimer(TimeSpan.FromMilliseconds(timeout)); + }); + } + + var phoneCallWaiting = phoneCallBase as TLPhoneCallWaiting; + if (phoneCallWaiting != null) + { + if (_currentState == PhoneCallState.STATE_WAITING && phoneCallWaiting.ReceiveDate != null) + { + DispatchStateChanged(PhoneCallState.STATE_RINGING); + PlaySound(PhoneCallSound.Ringback, -1); + + //Execute.BeginOnUIThread(() => + //{ + // if (_timeoutRunnable != null) + // { + // _timeoutRunnable = null; + // CancelTimer(); + // } + + // _timeoutRunnable = () => + // { + // _timeoutRunnable = null; + // DeclineIncomingCall(PhoneDiscardReason.DISCARD_REASON_MISSED, null); + // }; + // RunTimer(TimeSpan.FromSeconds(Constants.CallRingTimeout)); + //}); + } + } + } + + private void OnStartCommand() + { + if (_outgoing) + { + //StartOutgoingCall(); + } + else + { + AcknowledgeCallAndStartRinging(); + } + } + + private void AcknowledgeCallAndStartRinging() + { + var phoneCallDiscarded = _call as TLPhoneCallDiscarded; + if (phoneCallDiscarded != null) + { + Telegram.Logs.Log.Write("Call " + phoneCallDiscarded.Id + " was discarded before the service started, stopping"); + StopSelf(); + return; + } + + var inputPhoneCall = _call as IInputPhoneCall; + if (inputPhoneCall != null) + { + _mtProtoService.ReceivedCallAsync(inputPhoneCall.ToInputPhoneCall(), + result => + { + Telegram.Logs.Log.Write("phone.receivedCall result=" + result.Value); + StartRinging(); + }, + error => + { + Telegram.Logs.Log.Write("phone.receivedCall error=" + error); + StopSelf(); + }); + } + } + + private void StartRinging() + { + Telegram.Logs.Log.Write("starting ringing for call " + (_call != null ? _call.Id : null)); + DispatchStateChanged(PhoneCallState.STATE_WAITING_INCOMING); + PlaySound(PhoneCallSound.Call, -1); + } + + private static Uri _lastLoopedUri; + + private static int _loopedCount; + + private static int _maxLoopedCount; + + /// + /// + /// + /// + /// -1 -- forewer, 0 -- once, 1 -- twice + public static void PlaySound(PhoneCallSound sound, int loopedCount) + { + Execute.BeginOnUIThread(() => + { + MessagePlayerControl.Stop(); + GifPlayerControl.StopVideo(); + + var source = GetSoundSource(sound); + + MessagePlayerControl.Player.Volume = 0.75; + MessagePlayerControl.Player.Source = new Uri(source, UriKind.Relative); + MessagePlayerControl.Player.MediaOpened += MessagePlayerControl_OnMediaOpened; + MessagePlayerControl.Player.MediaFailed += MessagePlayerControl_OnMediaFailed; + + MessagePlayerControl.Player.MediaEnded -= MessagePlayerControl_OnMediaEnded; + _maxLoopedCount = loopedCount; + _loopedCount = 0; + _lastLoopedUri = MessagePlayerControl.Player.Source; + MessagePlayerControl.Player.MediaEnded += MessagePlayerControl_OnMediaEnded; + }); + } + + private static void MessagePlayerControl_OnMediaEnded(object sender, RoutedEventArgs e) + { + if (_loopedCount > _maxLoopedCount - 1 && _maxLoopedCount != -1) + { + return; + } + + if (_lastLoopedUri == MessagePlayerControl.Player.Source) + { + MessagePlayerControl.Player.Position = TimeSpan.FromSeconds(0.0); + MessagePlayerControl.Player.Play(); + _loopedCount++; + } + } + + private static void MessagePlayerControl_OnMediaFailed(object sender, ExceptionRoutedEventArgs e) + { + MessagePlayerControl.Player.MediaOpened -= MessagePlayerControl_OnMediaOpened; + MessagePlayerControl.Player.MediaFailed -= MessagePlayerControl_OnMediaFailed; + } + + private static void MessagePlayerControl_OnMediaOpened(object sender, RoutedEventArgs e) + { + MessagePlayerControl.Player.MediaOpened -= MessagePlayerControl_OnMediaOpened; + MessagePlayerControl.Player.MediaFailed -= MessagePlayerControl_OnMediaFailed; + MessagePlayerControl.Player.Play(); + } + + private static string GetSoundSource(PhoneCallSound sound) + { + switch (sound) + { + case PhoneCallSound.Call: + return "/Sounds/voip_call2.mp3"; + case PhoneCallSound.Ringback: + return "/Sounds/voip_ringback.mp3"; + case PhoneCallSound.Failed: + return "/Sounds/voip_failed.mp3"; + case PhoneCallSound.End: + return "/Sounds/voip_end.mp3"; + case PhoneCallSound.Busy: + return "/Sounds/voip_busy.mp3"; + case PhoneCallSound.Connecting: + return "/Sounds/voip_connecting.mp3"; + } + + return null; + } + + private void StopSelf() + { + + } + + private void StartRatingActivity() + { + + } + + private void ProcessIncomingCall(TLPhoneCall call) + { + if(call.GAorB == null){ + Telegram.Logs.Log.Write("stopping VoIP service, Ga == null"); + CallFailed(); + return; + } + + //if(!Arrays.equals(g_a_hash, Utils.ComputeSHA256(call.GAorB.Data))){ + // Telegram.Logs.Log.Write("stopping VoIP service, Ga hash doesn't match"); + // CallFailed(); + // return; + //} + + _ga=call.GAorB.Data; + + if (_secretP == null + || !TLUtils.CheckGaAndGb(call.GAorB.Data, _secretP.Data)) + { + CallFailed(); + return; + } + + _authKey = MTProtoService.GetAuthKey(_aOrB, call.GAorB.ToBytes(), _secretP.ToBytes()); + var buffer = TLUtils.Combine(_authKey, _ga); + var sha256 = Telegram.Api.Helpers.Utils.ComputeSHA256(buffer); + + _emojis = EncryptionKeyEmojifier.EmojifyForCall(sha256); + + var keyHash = Telegram.Api.Helpers.Utils.ComputeSHA1(_authKey); + var keyFingerprint = new TLLong(BitConverter.ToInt64(keyHash, 12)); + + + if (keyFingerprint.Value != call.KeyFingerprint.Value) + { + Telegram.Logs.Log.Write("key fingerprints don't match"); + CallFailed(); + return; + } + + SetCall(call); + _outgoing = false; + InitiateActualEncryptedCall(); + } + + private void ProcessAcceptedCall(TLPhoneCallAccepted phoneCallAccepted) + { + DispatchStateChanged(PhoneCallState.STATE_EXCHANGING_KEYS); + + if (!TLUtils.CheckGaAndGb(phoneCallAccepted.GB.Data, _secretP.Data)) + { + CallFailed(); + return; + } + + _authKey = MTProtoService.GetAuthKey(_aOrB, phoneCallAccepted.GB.ToBytes(), _secretP.ToBytes()); + var buffer = TLUtils.Combine(_authKey, _ga); + var sha256 = Telegram.Api.Helpers.Utils.ComputeSHA256(buffer); + + _emojis = EncryptionKeyEmojifier.EmojifyForCall(sha256); + + var keyHash = Telegram.Api.Helpers.Utils.ComputeSHA1(_authKey); + var keyFingerprint = new TLLong(BitConverter.ToInt64(keyHash, 12)); + + var peer = new TLInputPhoneCall + { + Id = phoneCallAccepted.Id, + AccessHash = phoneCallAccepted.AccessHash + }; + + var protocol = new TLPhoneCallProtocol + { + Flags = new TLInt(0), + UdpP2P = true, + UdpReflector = true, + MinLayer = new TLInt(CALL_MIN_LAYER), + MaxLayer = new TLInt(CALL_MAX_LAYER) + }; + + _mtProtoService.ConfirmCallAsync(peer, TLString.FromBigEndianData(_ga), keyFingerprint, protocol, + result => + { + Telegram.Logs.Log.Write(string.Format("phone.confirmCall result={0} current={1}", result, _call)); + SetCall(result.PhoneCall); + //_voipPhoneCall.NotifyCallActive(); + InitiateActualEncryptedCall(); + }, + error => + { + Telegram.Logs.Log.Write(string.Format("phone.confirmCall error={0} current={1}", error, _call)); + CallFailed(); + }); + + } + + private EndpointStruct ToEndpoint(TLPhoneConnection connection) + { + var connection61 = connection as TLPhoneConnection61; + if (connection61 != null) + { + return new EndpointStruct + { + id = connection61.Id.Value, + ipv4 = connection61.Ip.ToString(), + ipv6 = connection61.IpV6.ToString(), + port = (ushort) connection61.Port.Value, + peerTag = connection61.PeerTag.ToString() + }; + } + + return new EndpointStruct + { + id = 0, + ipv4 = connection.Ip.ToString(), + ipv6 = connection.IpV6.ToString(), + port = (ushort)connection.Port.Value, + peerTag = connection.PeerTag.ToString() + }; + } + + private void InitiateActualEncryptedCall() + { + Execute.BeginOnUIThread(() => + { + if (_timeoutRunnable != null) + { + _timeoutRunnable = null; + CancelTimer(); + } + }); + + _mtProtoService.GetCallConfigAsync(result => + { + var jobject = JsonValue.Parse(result.Data.ToString()).GetObject(); + foreach (var obj in jobject) + { + System.Diagnostics.Debug.WriteLine(obj.Value.Stringify()); + } + + + //VoIPControllerWrapper.UpdateServerConfig(result.Data.ToString()); + BackgroundProcessController.Instance.CallController.UpdateServerConfig(result.Data.ToString()); + + var logFile = ApplicationData.Current.LocalFolder.Path + "\\tgvoip.logFile.txt"; + var statsDumpFile = ApplicationData.Current.LocalFolder.Path + "\\tgvoip.statsDump.txt"; + + _cacheService.GetConfigAsync(config => + { + var config60 = config as TLConfig60; + if (config60 != null) + { + var phoneCall = _call as TLPhoneCall; + if (phoneCall != null) + { + var protocol = phoneCall.Protocol; + + var callConfig = new Config + { + InitTimeout = config60.CallPacketTimeoutMs.Value/1000.0, + RecvTimeout = config60.CallConnectTimeoutMs.Value/1000.0, + DataSavingMode = DataSavingMode.Never, + EnableAEC = true, + EnableNS = true, + EnableAGC = true, + LogFilePath = logFile, + StatsDumpFilePath = statsDumpFile + }; + + var connection = phoneCall.Connection; + var endpoints = new EndpointStruct[phoneCall.AlternativeConnections.Count + 1]; + endpoints[0] = ToEndpoint(connection); + + for (int i = 0; i < phoneCall.AlternativeConnections.Count; i++) + { + connection = phoneCall.AlternativeConnections[i]; + endpoints[i + 1] = ToEndpoint(connection); + } + + //BackgroundProcessController.Instance.CallController.DeleteVoIPControllerWrapper(); + //BackgroundProcessController.Instance.CallController.CreateVoIPControllerWrapper(); + //BackgroundProcessController.Instance.CallController.SetConfig(callConfig); + //BackgroundProcessController.Instance.CallController.SetStatusCallback(this); + //BackgroundProcessController.Instance.CallController.SetEncryptionKey(_authKey, _outgoing); + //BackgroundProcessController.Instance.CallController.SetPublicEndpoints(endpoints, phoneCall.Protocol.UdpP2P); + //BackgroundProcessController.Instance.CallController.Start(); + //UpdateNetworkType(null); + //BackgroundProcessController.Instance.CallController.Connect(); + + var config82 = config as TLConfig82; + var defaultP2PContacts = config82 == null || config82.DefaultP2PContacts; + var callsSecurity = _stateService.GetCallsSecurity(defaultP2PContacts); + + var proxy = new ProxyStruct + { + protocol = ProxyProtocol.None, + address = string.Empty, + port = 1080, + password = string.Empty, + username = string.Empty + }; + var proxyConfig = _transportService.GetProxyConfig() as TLProxyConfig76; + if (proxyConfig != null + && proxyConfig.IsEnabled.Value + && !proxyConfig.IsEmpty + && proxyConfig.UseForCalls.Value + && proxyConfig.SelectedIndex != null + && proxyConfig.SelectedIndex.Value >= 0 + && proxyConfig.SelectedIndex.Value < proxyConfig.Items.Count) + { + var socks5Proxy = proxyConfig.Items[proxyConfig.SelectedIndex.Value] as TLSocks5Proxy; + if (socks5Proxy != null) + { + proxy = new ProxyStruct + { + protocol = ProxyProtocol.SOCKS5, + address = socks5Proxy.Server.ToString(), + port = (ushort) socks5Proxy.Port.Value, + username = socks5Proxy.Username.ToString(), + password = socks5Proxy.Password.ToString() + }; + } + } + + var userId = !_outgoing ? phoneCall.AdminId : phoneCall.ParticipantId; + var user = _cacheService.GetUser(userId) as TLUser; + if (user != null) + { + var allowP2P = false; + if (callsSecurity != null) + { + allowP2P = callsSecurity.PeerToPeerEverybody + || callsSecurity.PeerToPeerContacts && user.IsContact + || callsSecurity.PeerToPeerContacts && user.IsContactMutual; + } + + _userId = user.Id; + + var initiated = BackgroundProcessController.Instance.CallController.InitiateOutgoingCall( + user.FullName2, user.Index, + phoneCall.Id.Value, phoneCall.AccessHash.Value, + callConfig, + _authKey, _outgoing, + _emojis, + endpoints, + phoneCall.Protocol.UdpP2P && allowP2P, + protocol.MaxLayer.Value, + proxy); + + if (initiated) + { + _controllerStarted = true; + _startCallTime = DateTime.Now; + + _eventAggregator.Publish(new PhoneCallStartedEventArgs { Call = phoneCall, Emojis = _emojis }); + } + } + //_controller.SetSpeakerphoneEndpoint(); + } + } + }); + + }, + error => + { + + }); + } + + public void OnSignalBarsChanged(int newSignal) + { + System.Diagnostics.Debug.WriteLine(" OnSignalBarsChanged newSignal=" + newSignal); + _signal = newSignal; + _eventAggregator.Publish(new SignalBarsChangedEventArgs { Signal = newSignal }); + } + + public void OnCallStateChanged(CallState newState) + { + System.Diagnostics.Debug.WriteLine("==OnCallStateChanged new_state=" + newState); + DispatchStateChanged((PhoneCallState)newState); + + if (newState == CallState.Failed) + { + CallFailed(); + return; + } + + if (newState == CallState.Established) + { + return; + } + } + + public void Dispose() + { + //_eventAggregator.Unsubscribe(this); + } + + public void HangUp() + { + DeclineIncomingCall(_currentState == PhoneCallState.STATE_RINGING || (_currentState == PhoneCallState.STATE_WAITING && _outgoing) ? PhoneDiscardReason.DISCARD_REASON_MISSED : PhoneDiscardReason.DISCARD_REASON_HANGUP, null); + } + + public string[] GetEmojis() + { + return _emojis; + } + + private void DeclineIncomingCall(PhoneDiscardReason discardReason, Action callback) + { + if (_currentState == PhoneCallState.STATE_REQUESTING) + { + _endCallAfterRequest = true; + return; + } + + if (_currentState == PhoneCallState.STATE_HANGING_UP || _currentState == PhoneCallState.STATE_ENDED) + { + return; + } + + DispatchStateChanged(PhoneCallState.STATE_HANGING_UP); + if (_call == null) + { + callback.SafeInvoke(); + CallEnded(); + return; + } + + if (_call != null) + { + DeclineIncomingCallInternal(discardReason, callback, _call); + } + } + + private void DeclineIncomingCallInternal(PhoneDiscardReason discardReason, Action callback, TLPhoneCallBase call) + { + var phoneCall = call as IInputPhoneCall; + if (phoneCall != null) + { + var peer = phoneCall.ToInputPhoneCall(); + var duration = _controllerStarted ? (GetCallDuration()/1000) : 0; + var connectionId = _controllerStarted ? BackgroundProcessController.Instance.CallController.GetPreferredRelayID() : 0; + TLPhoneCallDiscardReasonBase reason; + switch (discardReason) + { + case PhoneDiscardReason.DISCARD_REASON_DISCONNECT: + reason = new TLPhoneCallDiscardReasonDisconnect(); + break; + case PhoneDiscardReason.DISCARD_REASON_MISSED: + reason = new TLPhoneCallDiscardReasonMissed(); + break; + case PhoneDiscardReason.DISCARD_REASON_LINE_BUSY: + reason = new TLPhoneCallDiscardReasonBusy(); + break; + case PhoneDiscardReason.DISCARD_REASON_HANGUP: + default: + reason = new TLPhoneCallDiscardReasonHangup(); + break; + } + + _mtProtoService.DiscardCallAsync(peer, new TLInt(duration), reason, new TLLong(connectionId), + result => + { + Telegram.Logs.Log.Write("phone.discardCall result " + result); + + callback.SafeInvoke(); + }, + error => + { + Telegram.Logs.Log.Write("phone.discardCall error " + error); + + callback.SafeInvoke(); + }); + } + } + + public void SwitchSpeaker(bool external) + { + BackgroundProcessController.Instance.CallController.SwitchSpeaker(external); + } + + public void Mute(bool muted) + { + BackgroundProcessController.Instance.CallController.SetMicMute(muted); + } + + public string GetDebugString() + { + return BackgroundProcessController.Instance.CallController.GetDebugString() ?? string.Empty; + } + + public string GetDebugLog(long callId) + { + return callId == _debugCallId ? _debugLog ?? string.Empty : string.Empty; + } + + public string GetVersion() + { + return BackgroundProcessController.Instance.CallController.GetVersion(); + } + + public int GetSignalBarsCount() + { + return BackgroundProcessController.Instance.CallController.GetSignalBarsCount(); + } + + public void OnCallStatusChanged(CallStatus newStatus) + { + + } + + public void OnCallAudioRouteChanged(CallAudioRoute newRoute) + { + + } + + public void OnMediaOperationsChanged(MediaOperations newOperations) + { + + } + + public void OnCameraLocationChanged(CameraLocation newCameraLocation) + { + + } + } + + public class PhoneCallStartedEventArgs + { + public TLPhoneCall Call { get; set; } + + public string[] Emojis { get; set; } + } + + public class PhoneCallDiscardedEventArgs + { + public TLPhoneCallBase Call { get; set; } + + public TLPhoneCallDiscarded61 DiscardedCall { get; set; } + + public bool Outgoing { get; set; } + } + + public class PhoneCallRequestedEventArgs + { + public TLPhoneCallRequested64 RequestedCall { get; set; } + } + + public class PhoneCallStateChangedEventArgs + { + public TLPhoneCallBase Call { get; set; } + + public PhoneCallState CallState { get; set; } + } + + public class SignalBarsChangedEventArgs + { + public int Signal { get; set; } + } + + public enum PhoneCallSound + { + Call, + Ringback, + Failed, + End, + Busy, + Connecting + } + + public enum PhoneCallState + { + STATE_WAIT_INIT = 1, + STATE_WAIT_INIT_ACK = 2, + STATE_ESTABLISHED = 3, + STATE_FAILED = 4, + STATE_HANGING_UP = 5, + STATE_ENDED = 6, + STATE_EXCHANGING_KEYS = 7, + STATE_WAITING = 8, + STATE_REQUESTING = 9, + STATE_WAITING_INCOMING = 10, + STATE_RINGING = 11, + STATE_BUSY = 12, + } + + public enum PhoneDiscardReason + { + DISCARD_REASON_HANGUP = 1, + DISCARD_REASON_DISCONNECT = 2, + DISCARD_REASON_MISSED = 3, + DISCARD_REASON_LINE_BUSY = 4, + } + + public class EncryptionKeyEmojifier + { + private static readonly string[] _emojis = + { + "\uD83D\uDE09","\uD83D\uDE0D","\uD83D\uDE1B","\uD83D\uDE2D","\uD83D\uDE31","\uD83D\uDE21","\uD83D\uDE0E","\uD83D\uDE34", + "\uD83D\uDE35","\uD83D\uDE08","\uD83D\uDE2C","\uD83D\uDE07","\uD83D\uDE0F","\uD83D\uDC6E","\uD83D\uDC77","\uD83D\uDC82","\uD83D\uDC76","\uD83D\uDC68", + "\uD83D\uDC69","\uD83D\uDC74","\uD83D\uDC75","\uD83D\uDE3B","\uD83D\uDE3D","\uD83D\uDE40","\uD83D\uDC7A","\uD83D\uDE48","\uD83D\uDE49","\uD83D\uDE4A", + "\uD83D\uDC80","\uD83D\uDC7D","\uD83D\uDCA9","\uD83D\uDD25","\uD83D\uDCA5","\uD83D\uDCA4","\uD83D\uDC42","\uD83D\uDC40","\uD83D\uDC43","\uD83D\uDC45", + "\uD83D\uDC44","\uD83D\uDC4D","\uD83D\uDC4E","\uD83D\uDC4C","\uD83D\uDC4A","✌","✋","\uD83D\uDC50","\uD83D\uDC46","\uD83D\uDC47","\uD83D\uDC49", + "\uD83D\uDC48","\uD83D\uDE4F","\uD83D\uDC4F","\uD83D\uDCAA","\uD83D\uDEB6","\uD83C\uDFC3","\uD83D\uDC83","\uD83D\uDC6B","\uD83D\uDC6A","\uD83D\uDC6C", + "\uD83D\uDC6D","\uD83D\uDC85","\uD83C\uDFA9","\uD83D\uDC51","\uD83D\uDC52","\uD83D\uDC5F","\uD83D\uDC5E","\uD83D\uDC60","\uD83D\uDC55","\uD83D\uDC57", + "\uD83D\uDC56","\uD83D\uDC59","\uD83D\uDC5C","\uD83D\uDC53","\uD83C\uDF80","\uD83D\uDC84","\uD83D\uDC9B","\uD83D\uDC99","\uD83D\uDC9C","\uD83D\uDC9A", + "\uD83D\uDC8D","\uD83D\uDC8E","\uD83D\uDC36","\uD83D\uDC3A","\uD83D\uDC31","\uD83D\uDC2D","\uD83D\uDC39","\uD83D\uDC30","\uD83D\uDC38","\uD83D\uDC2F", + "\uD83D\uDC28","\uD83D\uDC3B","\uD83D\uDC37","\uD83D\uDC2E","\uD83D\uDC17","\uD83D\uDC34","\uD83D\uDC11","\uD83D\uDC18","\uD83D\uDC3C","\uD83D\uDC27", + "\uD83D\uDC25","\uD83D\uDC14","\uD83D\uDC0D","\uD83D\uDC22","\uD83D\uDC1B","\uD83D\uDC1D","\uD83D\uDC1C","\uD83D\uDC1E","\uD83D\uDC0C","\uD83D\uDC19", + "\uD83D\uDC1A","\uD83D\uDC1F","\uD83D\uDC2C","\uD83D\uDC0B","\uD83D\uDC10","\uD83D\uDC0A","\uD83D\uDC2B","\uD83C\uDF40","\uD83C\uDF39","\uD83C\uDF3B", + "\uD83C\uDF41","\uD83C\uDF3E","\uD83C\uDF44","\uD83C\uDF35","\uD83C\uDF34","\uD83C\uDF33","\uD83C\uDF1E","\uD83C\uDF1A","\uD83C\uDF19","\uD83C\uDF0E", + "\uD83C\uDF0B","⚡","☔","❄","⛄","\uD83C\uDF00","\uD83C\uDF08","\uD83C\uDF0A","\uD83C\uDF93","\uD83C\uDF86","\uD83C\uDF83","\uD83D\uDC7B","\uD83C\uDF85", + "\uD83C\uDF84","\uD83C\uDF81","\uD83C\uDF88","\uD83D\uDD2E","\uD83C\uDFA5","\uD83D\uDCF7","\uD83D\uDCBF","\uD83D\uDCBB","☎","\uD83D\uDCE1","\uD83D\uDCFA", + "\uD83D\uDCFB","\uD83D\uDD09","\uD83D\uDD14","⏳","⏰","⌚","\uD83D\uDD12","\uD83D\uDD11","\uD83D\uDD0E","\uD83D\uDCA1","\uD83D\uDD26","\uD83D\uDD0C", + "\uD83D\uDD0B","\uD83D\uDEBF","\uD83D\uDEBD","\uD83D\uDD27","\uD83D\uDD28","\uD83D\uDEAA","\uD83D\uDEAC","\uD83D\uDCA3","\uD83D\uDD2B","\uD83D\uDD2A", + "\uD83D\uDC8A","\uD83D\uDC89","\uD83D\uDCB0","\uD83D\uDCB5","\uD83D\uDCB3","✉","\uD83D\uDCEB","\uD83D\uDCE6","\uD83D\uDCC5","\uD83D\uDCC1","✂","\uD83D\uDCCC", + "\uD83D\uDCCE","✒","✏","\uD83D\uDCD0","\uD83D\uDCDA","\uD83D\uDD2C","\uD83D\uDD2D","\uD83C\uDFA8","\uD83C\uDFAC","\uD83C\uDFA4","\uD83C\uDFA7","\uD83C\uDFB5", + "\uD83C\uDFB9","\uD83C\uDFBB","\uD83C\uDFBA","\uD83C\uDFB8","\uD83D\uDC7E","\uD83C\uDFAE","\uD83C\uDCCF","\uD83C\uDFB2","\uD83C\uDFAF","\uD83C\uDFC8", + "\uD83C\uDFC0","⚽","⚾","\uD83C\uDFBE","\uD83C\uDFB1","\uD83C\uDFC9","\uD83C\uDFB3","\uD83C\uDFC1","\uD83C\uDFC7","\uD83C\uDFC6","\uD83C\uDFCA","\uD83C\uDFC4", + "☕","\uD83C\uDF7C","\uD83C\uDF7A","\uD83C\uDF77","\uD83C\uDF74","\uD83C\uDF55","\uD83C\uDF54","\uD83C\uDF5F","\uD83C\uDF57","\uD83C\uDF71","\uD83C\uDF5A", + "\uD83C\uDF5C","\uD83C\uDF61","\uD83C\uDF73","\uD83C\uDF5E","\uD83C\uDF69","\uD83C\uDF66","\uD83C\uDF82","\uD83C\uDF70","\uD83C\uDF6A","\uD83C\uDF6B", + "\uD83C\uDF6D","\uD83C\uDF6F","\uD83C\uDF4E","\uD83C\uDF4F","\uD83C\uDF4A","\uD83C\uDF4B","\uD83C\uDF52","\uD83C\uDF47","\uD83C\uDF49","\uD83C\uDF53", + "\uD83C\uDF51","\uD83C\uDF4C","\uD83C\uDF50","\uD83C\uDF4D","\uD83C\uDF46","\uD83C\uDF45","\uD83C\uDF3D","\uD83C\uDFE1","\uD83C\uDFE5","\uD83C\uDFE6", + "⛪","\uD83C\uDFF0","⛺","\uD83C\uDFED","\uD83D\uDDFB","\uD83D\uDDFD","\uD83C\uDFA0","\uD83C\uDFA1","⛲","\uD83C\uDFA2","\uD83D\uDEA2","\uD83D\uDEA4", + "⚓","\uD83D\uDE80","✈","\uD83D\uDE81","\uD83D\uDE82","\uD83D\uDE8B","\uD83D\uDE8E","\uD83D\uDE8C","\uD83D\uDE99","\uD83D\uDE97","\uD83D\uDE95","\uD83D\uDE9B", + "\uD83D\uDEA8","\uD83D\uDE94","\uD83D\uDE92","\uD83D\uDE91","\uD83D\uDEB2","\uD83D\uDEA0","\uD83D\uDE9C","\uD83D\uDEA6","⚠","\uD83D\uDEA7","⛽","\uD83C\uDFB0", + "\uD83D\uDDFF","\uD83C\uDFAA","\uD83C\uDFAD","\uD83C\uDDEF\uD83C\uDDF5","\uD83C\uDDF0\uD83C\uDDF7","\uD83C\uDDE9\uD83C\uDDEA","\uD83C\uDDE8\uD83C\uDDF3", + "\uD83C\uDDFA\uD83C\uDDF8","\uD83C\uDDEB\uD83C\uDDF7","\uD83C\uDDEA\uD83C\uDDF8","\uD83C\uDDEE\uD83C\uDDF9","\uD83C\uDDF7\uD83C\uDDFA","\uD83C\uDDEC\uD83C\uDDE7", + "1⃣","2⃣","3⃣","4⃣","5⃣","6⃣","7⃣","8⃣","9⃣","0⃣","\uD83D\uDD1F","❗","❓","♥","♦","\uD83D\uDCAF","\uD83D\uDD17","\uD83D\uDD31","\uD83D\uDD34", + "\uD83D\uDD35","\uD83D\uDD36","\uD83D\uDD37" + }; + + private static readonly int[] _offsets = { 0, 4, 8, 12, 16 }; + + private static int BytesToInt(byte[] arr, int offset) + { + return (((int)arr[offset] & 0x7F) << 24) | (((int)arr[offset + 1] & 0xFF) << 16) | (((int)arr[offset + 2] & 0xFF) << 8) | ((int)arr[offset + 3] & 0xFF); + } + + private static long BytesToLong(byte[] arr, int offset) + { + return (((long)arr[offset] & 0x7F) << 56) | (((long)arr[offset + 1] & 0xFF) << 48) | (((long)arr[offset + 2] & 0xFF) << 40) | (((long)arr[offset + 3] & 0xFF) << 32) | + (((long)arr[offset + 4] & 0xFF) << 24) | (((long)arr[offset + 5] & 0xFF) << 16) | (((long)arr[offset + 6] & 0xFF) << 8) | (((long)arr[offset + 7] & 0xFF)); + + } + + public static String[] Emojify(byte[] sha256) + { + if (sha256.Length != 32) + { + throw new ArgumentException("sha256 needs to be exactly 32 bytes", "sha256"); + } + + var result = new string[5]; + for (int i = 0; i < 5; i++) + { + result[i] = _emojis[BytesToInt(sha256, _offsets[i]) % _emojis.Length]; + } + + return result; + } + + public static String[] EmojifyForCall(byte[] sha256) + { + var result = new string[4]; + for (int i = 0; i < 4; i++) + { + result[i] = _emojis[(int)(BytesToLong(sha256, 8 * i) % _emojis.Length)]; + } + + return result; + } + } +} diff --git a/TelegramClient.WP81/Services/WNSPushService.cs b/TelegramClient.WP81/Services/WNSPushService.cs new file mode 100755 index 0000000..1a6ef4d --- /dev/null +++ b/TelegramClient.WP81/Services/WNSPushService.cs @@ -0,0 +1,55 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace TelegramClient.Services +{ + /*public class WNSPushService : PushServiceBase + { + protected override string GetPushChannelUri() + { + return _pushChannel != null ? _pushChannel.Uri : null; + } + + private PushNotificationChannel _pushChannel; + + public WNSPushService(IMTProtoService service) : base(service) + { + LoadOrCreateChannelAsync(); + } + + private void LoadOrCreateChannelAsync(Action callback = null) + { + Execute.BeginOnThreadPool(async () => + { + _pushChannel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync(); + + //var hub = new NotificationHub("WNS" + Constants.ToastNotificationChannelName, + // "Endpoint=sb://testdemopushhub-ns.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=z2Sj7sgwGpkvTyE/H5QyiffCpwCjV/PmJBY1h4WhXac="); + + //var result = await hub.RegisterNativeAsync(_pushChannel.Uri); + + //if (result.RegistrationId != null) + //{ + // Execute.ShowDebugMessage("Registration successful: " + result.RegistrationId); + //} + + callback.SafeInvoke(); + }); + } + + + public override void RegisterDeviceAsync() + { + + } + + public override void UnregisterDeviceAsync(Action callback) + { + + } + }*/ +} diff --git a/TelegramClient.WP81/Services/WindowsPhoneStoreUpdateService.cs b/TelegramClient.WP81/Services/WindowsPhoneStoreUpdateService.cs new file mode 100755 index 0000000..dcb3071 --- /dev/null +++ b/TelegramClient.WP81/Services/WindowsPhoneStoreUpdateService.cs @@ -0,0 +1,111 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.IO; +using System.Net; +using System.Text; +using System.Windows; +using System.Xml; +using Windows.System; +using TelegramClient.Converters; + +namespace TelegramClient.Services +{ + public class WindowsPhoneStoreUpdateService : IWindowsPhoneStoreUpdateService + { + + private string GetManifestAttributeValue(string attributeName) + { + var xmlReaderSettings = new XmlReaderSettings + { + XmlResolver = new XmlXapResolver() + }; + + using (var xmlReader = XmlReader.Create("WMAppManifest.xml", xmlReaderSettings)) + { + xmlReader.ReadToDescendant("App"); + + return xmlReader.GetAttribute(attributeName); + } + } + + public void LaunchAppUpdateAsync() + { + Launcher.LaunchUriAsync(PrivateBetaIdentityToVisibilityConverter.IsPrivateBeta + ? new Uri(Constants.PreviewUpdateUri) + : new Uri(Constants.UpdateUri)); + } + + /// + /// Checks the Windows Phone Store to see if a newer version of the app is available + /// If it is, a dialog is shown + /// + /// Dialog text + /// Dialog title + public void CheckForUpdatedVersion(string updateDialogText, string updateDialogTitle) + { + Windows.System.Launcher.LaunchUriAsync(new Uri("ms-windows-store://pdp/?productid=9WZDNCRDZHS0")); + return; + Windows.System.Launcher.LaunchUriAsync(new Uri("ms-windows-store:navigate?appid=0872b696-d84b-4279-8627-7ed8b15bf4f0")); + return; + var cultureInfoName = CultureInfo.CurrentUICulture.Name; + + var url = + string.Format( + "http://marketplaceedgeservice.windowsphone.com/v8/catalog/apps/{0}?os={1}&cc={2}&oc=&lang={3}​", + "0872b696-d84b-4279-8627-7ed8b15bf4f0",//GetManifestAttributeValue("ProductID"), + Environment.OSVersion.Version, + cultureInfoName.Substring(cultureInfoName.Length - 2).ToUpperInvariant(), + cultureInfoName); + + var wc = new WebClient(); + wc.DownloadStringCompleted += (s, e) => + { + if (e.Error != null) return; + var content = e.Result; + + try + { + using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(content))) + { + using (var reader = XmlReader.Create(ms)) + { + reader.MoveToContent(); + + var aNamespace = reader.LookupNamespace("a"); + reader.ReadToFollowing("entry", aNamespace); + reader.ReadToDescendant("version"); + + var updatedVersion = new Version(reader.ReadElementContentAsString()); + var currentVersion = new Version(GetManifestAttributeValue("Version")); + if (updatedVersion > currentVersion + && + MessageBox.Show(updateDialogText, updateDialogTitle, MessageBoxButton.OKCancel) == + MessageBoxResult.OK) + { + Windows.System.Launcher.LaunchUriAsync(new Uri("ms-windows-store:navigate?appid=0872b696-d84b-4279-8627-7ed8b15bf4f0")); + //WebBrowserTask task = new WebBrowserTask(); + //task.URL = "http://windowsphone.com/s?appid=0872b696-d84b-4279-8627-7ed8b15bf4f0"; + //task.Show(); + //new MarketplaceDetailTask().Show(); + } + } + } + } + catch + { + + } + }; + wc.DownloadStringAsync(new Uri(url)); + + + } + } +} diff --git a/TelegramClient.WP81/Sounds/voip_busy.mp3 b/TelegramClient.WP81/Sounds/voip_busy.mp3 new file mode 100755 index 0000000..1d6741e Binary files /dev/null and b/TelegramClient.WP81/Sounds/voip_busy.mp3 differ diff --git a/TelegramClient.WP81/Sounds/voip_call.mp3 b/TelegramClient.WP81/Sounds/voip_call.mp3 new file mode 100755 index 0000000..645c45c Binary files /dev/null and b/TelegramClient.WP81/Sounds/voip_call.mp3 differ diff --git a/TelegramClient.WP81/Sounds/voip_call2.mp3 b/TelegramClient.WP81/Sounds/voip_call2.mp3 new file mode 100755 index 0000000..932a00b Binary files /dev/null and b/TelegramClient.WP81/Sounds/voip_call2.mp3 differ diff --git a/TelegramClient.WP81/Sounds/voip_connecting.mp3 b/TelegramClient.WP81/Sounds/voip_connecting.mp3 new file mode 100755 index 0000000..fc425ba Binary files /dev/null and b/TelegramClient.WP81/Sounds/voip_connecting.mp3 differ diff --git a/TelegramClient.WP81/Sounds/voip_end.mp3 b/TelegramClient.WP81/Sounds/voip_end.mp3 new file mode 100755 index 0000000..1d6741e Binary files /dev/null and b/TelegramClient.WP81/Sounds/voip_end.mp3 differ diff --git a/TelegramClient.WP81/Sounds/voip_failed.mp3 b/TelegramClient.WP81/Sounds/voip_failed.mp3 new file mode 100755 index 0000000..3b596db Binary files /dev/null and b/TelegramClient.WP81/Sounds/voip_failed.mp3 differ diff --git a/TelegramClient.WP81/Sounds/voip_ringback.mp3 b/TelegramClient.WP81/Sounds/voip_ringback.mp3 new file mode 100755 index 0000000..a92325b Binary files /dev/null and b/TelegramClient.WP81/Sounds/voip_ringback.mp3 differ diff --git a/TelegramClient.WP81/SquareTile150x150.png b/TelegramClient.WP81/SquareTile150x150.png new file mode 100755 index 0000000..ca69926 Binary files /dev/null and b/TelegramClient.WP81/SquareTile150x150.png differ diff --git a/TelegramClient.WP81/SquareTile71x71.png b/TelegramClient.WP81/SquareTile71x71.png new file mode 100755 index 0000000..086e714 Binary files /dev/null and b/TelegramClient.WP81/SquareTile71x71.png differ diff --git a/TelegramClient.WP81/TelegramClient.WP81.csproj b/TelegramClient.WP81/TelegramClient.WP81.csproj new file mode 100755 index 0000000..11b40f4 --- /dev/null +++ b/TelegramClient.WP81/TelegramClient.WP81.csproj @@ -0,0 +1,10591 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {B4E6EEEF-5819-4528-8234-EA4A0EC7B6E3} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TelegramClient + TelegramClient.WP8 + v8.1 + + + + + WindowsPhone + true + ru%3bde%3bes%3bpt%3bnl%3bit + true + true + Telegram_3.2.0.0_wp8.1.xap + Properties\AppManifest.xml + TelegramClient.App + true + true + ..\ + true + 12.0 + en + + + true + full + false + Bin\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8;WP81;LOG_REGISTRATION;MULTIPLE_PHOTOS + true + true + prompt + 4 + false + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8;WP81;LOG_REGISTRATION;MULTIPLE_PHOTOS + true + true + prompt + 4 + false + + + true + Bin\x86\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8;WP81;LOG_REGISTRATION;MULTIPLE_PHOTOS + true + full + + + prompt + MinimumRecommendedRules.ruleset + false + + + Bin\x86\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8;WP81;LOG_REGISTRATION;MULTIPLE_PHOTOS + true + true + pdbonly + + + prompt + MinimumRecommendedRules.ruleset + + + true + Bin\ARM\Debug + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8;WP81;LOG_REGISTRATION;MULTIPLE_PHOTOS + true + full + + + prompt + MinimumRecommendedRules.ruleset + false + + + Bin\ARM\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8;WP81;LOG_REGISTRATION;MULTIPLE_PHOTOS + true + true + pdbonly + + + prompt + MinimumRecommendedRules.ruleset + + + true + bin\Debug Private Beta\ + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8;WP81;PRIVATE_BETA;LOG_REGISTRATION;MULTIPLE_PHOTOS + true + full + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + true + bin\x86\Debug Private Beta\ + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8;WP81;PRIVATE_BETA;LOG_REGISTRATION;MULTIPLE_PHOTOS + true + full + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + true + bin\ARM\Debug Private Beta\ + TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8;WP81;PRIVATE_BETA;LOG_REGISTRATION;MULTIPLE_PHOTOS + true + full + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + bin\Release Private Beta\ + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8;WP81;PRIVATE_BETA;LOG_REGISTRATION;MULTIPLE_PHOTOS + true + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release Private Beta\ + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8;WP81;PRIVATE_BETA;LOG_REGISTRATION;MULTIPLE_PHOTOS + true + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + bin\ARM\Release Private Beta\ + TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8;WP81;PRIVATE_BETA;LOG_REGISTRATION;MULTIPLE_PHOTOS + true + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + ..\Libraries\BugSense.dll + + + False + ..\packages\Caliburn.Micro.Core.3.0.3\lib\portable-net45+win8+wp8+wpa81+MonoAndroid10+Xamarin.iOS10+MonoTouch10+uap10.0\Caliburn.Micro.dll + + + ..\packages\Caliburn.Micro.3.0.3\lib\wp8\Caliburn.Micro.Platform.dll + + + ..\packages\Caliburn.Micro.3.0.3\lib\wp8\Caliburn.Micro.Platform.Core.dll + + + ..\packages\Coding4Fun.Toolkit.Controls.2.0.7\lib\wp71\Coding4Fun.Toolkit.Controls.dll + + + False + ..\packages\Portable.BouncyCastle.1.7.0.2\lib\portable-net4+sl5+wp8+win8+wpa81+MonoTouch10+MonoAndroid10+xamarinmac20+xamarinios10\crypto.dll + + + ..\packages\ID3.0.3.0\lib\sl4-wp71\Id3.dll + + + ..\packages\ImageTools.0.3.1\lib\sl3-wp\ImageTools.dll + + + ..\packages\ImageTools.0.3.1\lib\sl3-wp\ImageTools.Controls.dll + + + ..\packages\ImageTools.0.3.1\lib\sl3-wp\ImageTools.IO.Gif.dll + + + + + + False + ..\packages\WPtoolkit.4.2013.08.16\lib\wp8\Microsoft.Phone.Controls.Toolkit.dll + + + ..\packages\Microsoft.Net.Http.2.2.29\lib\sl4-windowsphone71\System.Net.Http.dll + True + + + ..\packages\Microsoft.Net.Http.2.2.29\lib\sl4-windowsphone71\System.Net.Http.Extensions.dll + True + + + ..\packages\Microsoft.Net.Http.2.2.29\lib\sl4-windowsphone71\System.Net.Http.Primitives.dll + True + + + ..\packages\Rx-Core.2.2.2\lib\windowsphone71\System.Reactive.Core.dll + + + ..\packages\Rx-Interfaces.2.2.2\lib\windowsphone71\System.Reactive.Interfaces.dll + + + ..\packages\Rx-Linq.2.2.2\lib\windowsphone71\System.Reactive.Linq.dll + + + ..\packages\Rx-XAML.2.2.2\lib\windowsphone71\System.Reactive.Windows.Threading.dll + + + + + + LongListSelectorEx.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Audio.cs + + + ViewModels\Dialogs\DialogsViewModel.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Audio.cs + + + ViewModels\Media\MultiImageEditorViewModel.cs + + + Views\Contacts\ContactsView.xaml.cs + ContactsView.xaml + + + Views\Controls\AudioRecorderControl.xaml.cs + AudioRecorderControl.xaml + + + Views\Dialogs\DialogDetailsView.xaml.cs + DialogDetailsView.xaml + + + Views\Dialogs\DialogsView.xaml.cs + DialogsView.xaml + + + Views\Dialogs\SecretDialogDetailsView.xaml.cs + SecretDialogDetailsView.xaml + + + Views\Media\FilesView.xaml.cs + FilesView.xaml + + + Views\Media\LinksView.xaml.cs + LinksView.xaml + + + Views\Media\MediaView.xaml.cs + MediaView.xaml + + + Views\Media\MultiImageEditorView.xaml.cs + MultiImageEditorView.xaml + + + Analytics\AnalyticsProperties.cs + + + Analytics\AnalyticsService.cs + + + Analytics\AnalyticsTracker.cs + + + Analytics\ReviewRequester.cs + + + Animation\LinqToVisualTree.cs + + + Animation\MetroInMotion.cs + + + Animation\Navigation\AnimatedBasePage.cs + + + Animation\Navigation\AnimatorHelperBase.cs + + + Animation\Navigation\ContinuumAnimator.cs + + + Animation\Navigation\SlideAnimator.cs + + + Animation\Navigation\Storyboards.cs + + + Animation\Navigation\SwivelAnimator.cs + + + Animation\Navigation\TurnstileAnimator.cs + + + Animation\Navigation\TurnstileFeatherAnimator.cs + + + App.xaml.cs + + + Behaviors\MarkTapAsHandledBehavior.cs + + + Behaviors\PanAndZoomBehavior.cs + + + Behaviors\ProgressBarSmoother.cs + + + Behaviors\SelectionBehavior.cs + + + Behaviors\ThemeToStateBehavior.cs + + + Behaviors\ToggleSwitchLocalizedContentBehavior.cs + + + Behaviors\UpdateTextBindingBehavior.cs + + + Bootstrapper.cs + + + CapabilityPlaceholder.cs + + + Commands.cs + + + Constants.cs + + + Controls\BrowserNavigationService.cs + + + Controls\TelegramNavigationInTransition.cs + + + Controls\TelegramNavigationOutTransition.cs + + + Controls\TelegramNavigationTransition.cs + + + Controls\TelegramRichTextBox.cs + + + Controls\TelegramTransitionFrame.cs + + + Controls\TelegramTransitionService.cs + + + Controls\TelegramTurnstileTransition.cs + + + Controls\TestScrollableTextBlock.cs + + + Controls\TransitionFrame.cs + + + Converters\BackgroundImageConverter.cs + + + Converters\BooleanToValueConverter.cs + + + Converters\BooleanToVisibilityConverter.cs + + + Converters\ChatForbiddenToVisibilityConverter.cs + + + Converters\ChatToMaxHeight.cs + + + Converters\ChatToVisibilityConverter.cs + + + Converters\CountToVisibilityConverter.cs + + + Converters\DebugVisibilityConverter.cs + + + Converters\DefaultPhotoConverter.cs + + + Converters\DialogCaptionConverter.cs + + + Converters\DialogDetailsBackgroundConverter.cs + + + Converters\DialogMessageFromConverter.cs + + + Converters\DistanceAwayConverter.cs + + + Converters\EmptyDialogMessageConverter.cs + + + Converters\EmptyPhotoToVisibilityConverter.cs + + + Converters\EmptyStringToVisibilityConverter.cs + + + Converters\ExistsToVisibilityConverter.cs + + + Converters\ExtendedImageConverter.cs + + + Converters\FileExtToColorConverter.cs + + + Converters\FileNameConverter.cs + + + Converters\FileSizeConverter.cs + + + Converters\ForwardedMessageConverter.cs + + + Converters\GeoLocationToVisibilityConverter.cs + + + Converters\GeoPointToStaticGoogleMapsConverter.cs + + + Converters\GroupToBackgroundBrushValueConverter.cs + + + Converters\GroupToForegroundBrushValueConverter.cs + + + Converters\IdToPlaceholderBackgroundConverter.cs + + + Converters\IntToVisibilityConverter.cs + + + Converters\InvertBooleanConverter.cs + + + Converters\IsSelectedToBackgroundConverter.cs + + + Converters\LowercaseConverter.cs + + + Converters\MaskConverter.cs + + + Converters\MediaContactToPhotoConverter.cs + + + Converters\MediaEmptyToVisibilityConverter.cs + + + Converters\MediaSizeConverter.cs + + + Converters\MergeBrushesConverter.cs + + + Converters\MessageStateToForegroundConverter.cs + + + Converters\MessageStatusConverter.cs + + + Converters\MessageToBriefInfoConverter.cs + + + Converters\MessageToFontFamilyConverter.cs + + + Converters\MuteUntilToStringConverter.cs + + + Converters\NotifySettingsToVisibilityConverter.cs + + + Converters\NotServiceMessageToVisibilityConverter.cs + + + Converters\OverlayAccentBrushConverter.cs + + + Converters\PhoneNumberConverter.cs + + + Converters\PhotoBytesToImageConverter.cs + + + Converters\PhotoToDimensionConverter.cs + + + Converters\PhotoToThumbConverter.cs + + + Converters\PlaceholderDefaultImageConverter.cs + + + Converters\PrivateBetaToVisibilityConverter.cs + + + Converters\ProgressToVisibilityConverter.cs + + + Converters\ReplyMarkupButtonVisibilityConverter.cs + + + Converters\SecretChatsAvailabilityConverter.cs + + + Converters\SecretChatsForegroundConverter.cs + + + Converters\ServiceMessageToTextConverter.cs + + + Converters\StatusToImageConverter.cs + + + Converters\StickerSetToCountStringConverter.cs + + + Converters\StringEqualsToVisibilityConverter.cs + + + Converters\StringFormatConverter.cs + + + Converters\TestBindingConverter.cs + + + Converters\TextMessageToVisibilityConverter.cs + + + Converters\TextSizeToVisibilityConverter.cs + + + Converters\TLIntToDateTimeConverter.cs + + + Converters\UnreadCountToVisibilityConverter.cs + + + Converters\UnreadMessageConverter.cs + + + Converters\UnregisteredUserIdToVisibilityConverter.cs + + + Converters\UppercaseConverter.cs + + + Converters\UserStatusToBrushConverter.cs + + + Converters\UserStatusToStringConverter.cs + + + Converters\UserStatusToVisibilityConverter.cs + + + Converters\UserToActionStringConverter.cs + + + Converters\WP8VisibilityConverter.cs + + + EmojiPanel\Controls\Emoji\EmojiControl.xaml.cs + + + EmojiPanel\Controls\Emoji\EmojiData.cs + + + EmojiPanel\Controls\Emoji\EmojiSpriteItem.cs + + + EmojiPanel\Controls\Emoji\StickerSpriteItem.cs + + + EmojiPanel\Controls\Utilities\DelayedExecutor.cs + + + EmojiPanel\Controls\Utilities\Helpers.cs + + + EmojiPanel\Controls\Utilities\MyListItemBase.cs + + + EmojiPanel\Controls\Utilities\MyVirtualizingPanel.cs + + + EmojiPanel\Controls\Utilities\VirtSegment.cs + + + EmojiPanel\Controls\Utilities\VListItemBase.cs + + + EventArgs\UpdateChatTitleEventArgs.cs + + + Extensions\ApplicationExtensions.cs + + + Extensions\CollectionExtensions.cs + + + Helpers\Clip.cs + + + Helpers\CollectionHelper.cs + + + Helpers\ImageUtils.cs + + + Helpers\ItemsControlHelper.cs + + + Helpers\Property.cs + + + Helpers\TemplateSelectors\DocumentTemplateSelector.cs + + + Helpers\TemplateSelectors\EmptyDialogToDescriptionConverter.cs + + + Helpers\TemplateSelectors\ItemsPanelTemplateSelector.cs + + + Helpers\TemplateSelectors\LocationTemplateSelector.cs + + + Helpers\TemplateSelectors\MediaTemplateSelector.cs + + + Helpers\TemplateSelectors\MessageTemplateSelector.cs + + + Helpers\TemplateSelectors\SearchContactsTemplateSelector.cs + + + ViewModels\Contacts\AlphaKeyGroup.cs + + + Models\ContactsByLastName.cs + + + Models\Country.cs + + + Models\InAppNotifications.cs + + + Models\Settings.cs + + + Models\UsersByFirstName.cs + + + Models\UsersByLastName.cs + + + Resources\AppResources.de.Designer.cs + True + True + AppResources.de.resx + + + Resources\AppResources.Designer.cs + True + True + AppResources.resx + + + Resources\AppResources.es.Designer.cs + True + True + AppResources.es.resx + + + Resources\AppResources.it.Designer.cs + True + True + AppResources.it.resx + + + Resources\AppResources.nl.Designer.cs + True + True + AppResources.nl.resx + + + Resources\AppResources.pt.Designer.cs + True + True + AppResources.pt.resx + + + Resources\AppResources.ru.Designer.cs + True + True + AppResources.ru.resx + + + Resources\LocalizationConverter.cs + + + Resources\LocalizedStrings.cs + + + Services\CommonErrorHandler.cs + + + Services\HttpDocumentFileManager.cs + + + Services\ICommonErrorHandler.cs + + + Services\IPushService.cs + + + Services\IStateService.cs + + + Services\IUploadService.cs + + + Services\PhoneInfoService.cs + + + Services\PushService.cs + + + Services\PushServiceBase.cs + + + Services\StateService.cs + + + Services\UploadService.cs + + + Themes\Default\Templates\Media.xaml.cs + Media.xaml + + + Utils\Color.cs + + + Utils\Language.cs + + + Utils\TelegramUriMapper.cs + + + ViewModels\Additional\AboutViewModel.cs + + + ViewModels\Additional\AccountSelfDestructsViewModel.cs + + + ViewModels\Additional\AddChatParticipantConfirmationViewModel.cs + + + ViewModels\Additional\AllowUsersViewModel.cs + + + ViewModels\Additional\ArchivedStickersViewModel.cs + + + ViewModels\Additional\AskQuestionConfirmationViewModel.cs + + + ViewModels\Additional\BlockedContactsViewModel.cs + + + ViewModels\Additional\CacheViewModel.cs + + + ViewModels\Additional\ChangePasscodeViewModel.cs + + + ViewModels\Additional\ChangePasswordEmailViewModel.cs + + + ViewModels\Additional\ChangePasswordHintViewModel.cs + + + ViewModels\Additional\ChangePasswordViewModel.cs + + + ViewModels\Additional\ChangePhoneNumberViewModel.cs + + + ViewModels\Additional\ChannelBlockedContactsViewModel.cs + + + ViewModels\Additional\ChatInviteViewModel.cs + + + ViewModels\Additional\ChatSettingsViewModel.cs + + + ViewModels\Additional\ChooseAttachmentViewModel.cs + + + ViewModels\Additional\ChooseBackgroundViewModel.cs + + + ViewModels\Additional\ChooseCountryViewModel.cs + + + ViewModels\Additional\ChooseNotificationSpanViewModel.cs + + + ViewModels\Additional\ChooseTTLViewModel.cs + + + ViewModels\Additional\ClearCacheSettingsViewModel.cs + + + ViewModels\Additional\EditCurrentUserViewModel.cs + + + ViewModels\Additional\EditPhoneNumberViewModel.cs + + + ViewModels\Additional\EditUsernameViewModel.cs + + + ViewModels\Additional\EncryptionKeyViewModel.cs + + + ViewModels\Additional\EnterPasscodeViewModel.cs + + + ViewModels\Additional\EnterPasswordViewModel.cs + + + ViewModels\Additional\FeaturedStickersViewModel.cs + + + ViewModels\Additional\GroupsViewModel.cs + + + ViewModels\Additional\LastSeenViewModel.cs + + + ViewModels\Additional\LockscreenViewModel.cs + + + ViewModels\Additional\MasksViewModel.cs + + + ViewModels\Additional\MassDeleteReportSpamViewModel.cs + + + ViewModels\Additional\NotificationsViewModel.cs + + + ViewModels\Additional\PasscodeViewModel.cs + + + ViewModels\Additional\PasswordRecoveryViewModel.cs + + + ViewModels\Additional\PasswordViewModel.cs + + + ViewModels\Additional\PrivacySecureViewModel.cs + + + ViewModels\Additional\PrivacyStatementViewModel.cs + + + ViewModels\Additional\SecretChatsViewModel.cs + + + ViewModels\Additional\SelectMultipleUsersViewModel.cs + + + ViewModels\Additional\SessionsViewModel.cs + + + ViewModels\Additional\SettingsViewModel.cs + + + ViewModels\Additional\ShareViewModel.cs + + + ViewModels\Additional\SnapshotsViewModel.cs + + + ViewModels\Additional\SpecialThanksViewModel.cs + + + ViewModels\Additional\StartupViewModel.cs + + + ViewModels\Additional\StickersViewModel.cs + + + ViewModels\Additional\WebViewModel.cs + + + ViewModels\Auth\CancelConfirmResetViewModel.cs + + + ViewModels\Auth\ConfirmPasswordViewModel.cs + + + ViewModels\Auth\ConfirmViewModel.cs + + + ViewModels\Auth\ResetAccountViewModel.cs + + + ViewModels\Auth\SignInViewModel.cs + + + ViewModels\Auth\SignUpViewModel.cs + + + ViewModels\Chats\AddAdminsViewModel.cs + + + ViewModels\Chats\AddChannelManagerViewModel.cs + + + ViewModels\Chats\AddChatParticipantViewModel.cs + + + ViewModels\Chats\AddSecretChatParticipantViewModel.cs + + + ViewModels\Chats\ChannelAdministratorsViewModel.cs + + + ViewModels\Chats\ChannelIntroViewModel.cs + + + ViewModels\Chats\ChannelMembersViewModel.cs + + + ViewModels\Chats\Chat2ViewModel.cs + + + ViewModels\Chats\ChatViewModel.cs + + + ViewModels\Chats\ConvertToSupergroupViewModel.cs + + + ViewModels\Chats\EditChatViewModel.cs + + + ViewModels\Chats\EditGroupTypeViewModel.cs + + + ViewModels\Chats\GroupsInCommonViewModel.cs + + + ViewModels\Chats\InviteLinkViewModel.cs + + + ViewModels\Contacts\ContactInfoViewModel.cs + + + ViewModels\Contacts\ContactsViewModel.cs + + + ViewModels\Contacts\ContactViewModel.cs + + + ViewModels\Contacts\EditContactViewModel.cs + + + ViewModels\Contacts\SecretContactDetailsViewModel.cs + + + ViewModels\Contacts\SecretContactViewModel.cs + + + ViewModels\Contacts\ShareContactViewModel.cs + + + ViewModels\Debug\DebugViewModel.cs + + + ViewModels\Debug\LogViewModel.cs + + + ViewModels\Debug\LongPollViewModel.cs + + + ViewModels\Debug\PerformanceViewModel.cs + + + ViewModels\Dialogs\ChooseDialogViewModel.cs + + + ViewModels\Dialogs\ChooseParticipantsViewModel.cs + + + ViewModels\Dialogs\CommandHintsViewModel.cs + + + ViewModels\Dialogs\CreateBroadcastViewModel.cs + + + ViewModels\Dialogs\CreateChannelStep1ViewModel.cs + + + ViewModels\Dialogs\CreateChannelStep2ViewModel.cs + + + ViewModels\Dialogs\CreateChannelStep3ViewModel.cs + + + ViewModels\Dialogs\CreateDialogViewModel.cs + + + ViewModels\Dialogs\DialogDetailsMode.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Actions.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Channel.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Contact.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Document.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Edit.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.GeoPoint.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Handle.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.InlineBots.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Mass.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Media.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Photo.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Reply.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Search.cs + + + ViewModels\Dialogs\DialogDetailsViewModel.Video.cs + + + ViewModels\Dialogs\DialogSearchMessagesViewModel.cs + + + ViewModels\Dialogs\DialogsViewModel.Common.cs + + + ViewModels\Dialogs\FastDialogDetailsViewModel.cs + + + ViewModels\Dialogs\HashtagHintsViewModel.cs + + + ViewModels\Dialogs\InlineBotResultsViewModel.cs + + + ViewModels\Dialogs\MessageViewerViewModel.cs + + + ViewModels\Dialogs\PinnedMessageViewModel.cs + + + ViewModels\Dialogs\SecretChatDebugViewModel.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Actions.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Document.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.GeoPoint.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Handle.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.InlineBots.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Media.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Photo.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Reply.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Text.cs + + + ViewModels\Dialogs\SecretDialogDetailsViewModel.Video.cs + + + ViewModels\Dialogs\StickerHintsViewModel.cs + + + ViewModels\Dialogs\UserActionViewModel.cs + + + ViewModels\Dialogs\UsernameHintsViewModel.cs + + + ViewModels\ItemDetailsViewModelBase.cs + + + ViewModels\ItemsViewModelBase.cs + + + ViewModels\Media\AnimatedImageViewerViewModel.cs + + + ViewModels\Media\DecryptedImageViewerViewModel.cs + + + ViewModels\Media\FilesViewModel.cs + + + ViewModels\Media\FullMediaViewModel.cs + + + ViewModels\Media\ImageEditorViewModel.cs + + + ViewModels\Media\ImageViewerViewModel.cs + + + ViewModels\Media\LinksViewModel.cs + + + ViewModels\Media\MapViewModel.cs + + + ViewModels\Media\MediaViewModel.cs + + + ViewModels\Media\MusicViewModel.cs + + + ViewModels\Media\ProfilePhotoViewerViewModel.cs + + + ViewModels\Media\SecretMediaViewModel.cs + + + ViewModels\Media\VideoCaptureViewModel.cs + + + ViewModels\Media\VideoPlayerViewModel.cs + + + ViewModels\Search\ISearch.cs + + + ViewModels\Search\SearchContactsViewModel.cs + + + ViewModels\Search\SearchDialogsViewModel.cs + + + ViewModels\Search\SearchFilesViewModel.cs + + + ViewModels\Search\SearchItemsViewModelBase.cs + + + ViewModels\Search\SearchLinksViewModel.cs + + + ViewModels\Search\SearchMessagesViewModel.cs + + + ViewModels\Search\SearchMusicViewModel.cs + + + ViewModels\Search\SearchShellViewModel.cs + + + ViewModels\Search\SearchVenuesViewModel.cs + + + ViewModels\Search\SearchViewModel.cs + + + ViewModels\ShellViewModel.cs + + + ViewModels\ViewModelBase.cs + + + Views\Additional\AboutView.xaml.cs + + + Views\Additional\AccountSelfDestructsView.xaml.cs + AccountSelfDestructsView.xaml + + + Views\Additional\AddChatParticipantConfirmationView.xaml.cs + AddChatParticipantConfirmationView.xaml + + + Views\Additional\AllowUsersView.xaml.cs + AllowUsersView.xaml + + + Views\Additional\ArchivedStickersView.xaml.cs + ArchivedStickersView.xaml + + + Views\Additional\AskQuestionConfirmationView.xaml.cs + AskQuestionConfirmationView.xaml + + + Views\Additional\BlockedContactsView.xaml.cs + + + Views\Additional\BubbleBackgroundControl.xaml.cs + BubbleBackgroundControl.xaml + + + Views\Additional\CacheView.xaml.cs + CacheView.xaml + + + Views\Additional\ChangePasscodeView.xaml.cs + ChangePasscodeView.xaml + + + Views\Additional\ChangePasswordEmailView.xaml.cs + ChangePasswordEmailView.xaml + + + Views\Additional\ChangePasswordHintView.xaml.cs + ChangePasswordHintView.xaml + + + Views\Additional\ChangePasswordView.xaml.cs + ChangePasswordView.xaml + + + Views\Additional\ChangePhoneNumberView.xaml.cs + ChangePhoneNumberView.xaml + + + Views\Additional\ChannelBlockedContactsView.xaml.cs + ChannelBlockedContactsView.xaml + + + Views\Additional\ChatSettingsView.xaml.cs + ChatSettingsView.xaml + + + Views\Additional\ChooseAttachmentView.xaml.cs + ChooseAttachmentView.xaml + + + Views\Additional\ChooseBackgroundView.xaml.cs + + + Views\Additional\ChooseCountryView.xaml.cs + + + Views\Additional\ChooseNotificationSpanView.xaml.cs + ChooseNotificationSpanView.xaml + + + Views\Additional\ChooseTTLView.xaml.cs + ChooseTTLView.xaml + + + Views\Additional\ClearCacheSettingsView.xaml.cs + ClearCacheSettingsView.xaml + + + Views\Additional\EditCurrentUserView.xaml.cs + + + Views\Additional\EditPhoneNumberView.xaml.cs + EditPhoneNumberView.xaml + + + Views\Additional\EditUsernameView.xaml.cs + EditUsernameView.xaml + + + Views\Additional\EncryptionKeyView.xaml.cs + EncryptionKeyView.xaml + + + Views\Additional\EnterPasscodeView.xaml.cs + EnterPasscodeView.xaml + + + Views\Additional\EnterPasswordView.xaml.cs + EnterPasswordView.xaml + + + Views\Additional\FallingSnowControl.xaml.cs + FallingSnowControl.xaml + + + Views\Additional\FeaturedStickersView.xaml.cs + FeaturedStickersView.xaml + + + Views\Additional\GroupsView.xaml.cs + GroupsView.xaml + + + Views\Additional\InputMessageHint.xaml.cs + InputMessageHint.xaml + + + Views\Additional\LastSeenView.xaml.cs + LastSeenView.xaml + + + Views\Additional\LockscreenView.xaml.cs + LockscreenView.xaml + + + Views\Additional\MasksView.xaml.cs + MasksView.xaml + + + Views\Additional\MassDeleteReportSpamView.xaml.cs + MassDeleteReportSpamView.xaml + + + Views\Additional\NotificationsView.xaml.cs + + + Views\Additional\NumericKeyboard.xaml.cs + NumericKeyboard.xaml + + + Views\Additional\PasscodeView.xaml.cs + PasscodeView.xaml + + + Views\Additional\PasswordRecoveryView.xaml.cs + PasswordRecoveryView.xaml + + + Views\Additional\PasswordView.xaml.cs + PasswordView.xaml + + + Views\Additional\PrivacySecurityView.xaml.cs + PrivacySecurityView.xaml + + + Views\Additional\PrivacyStatementView.xaml.cs + + + Views\Additional\SecretChatsView.xaml.cs + SecretChatsView.xaml + + + Views\Additional\SelectMultipleUsersView.xaml.cs + SelectMultipleUsersView.xaml + + + Views\Additional\SessionsView.xaml.cs + SessionsView.xaml + + + Views\Additional\SettingsView.xaml.cs + + + Views\Additional\ShareView.xaml.cs + ShareView.xaml + + + Views\Additional\SnapshotsView.xaml.cs + SnapshotsView.xaml + + + Views\Additional\SpecialThanksView.xaml.cs + SpecialThanksView.xaml + + + Views\Additional\StickersView.xaml.cs + StickersView.xaml + + + Views\Additional\TelegramPasswordBox.xaml.cs + TelegramPasswordBox.xaml + + + Views\Additional\WebView.xaml.cs + WebView.xaml + + + Views\Auth\CancelConfirmResetView.xaml.cs + CancelConfirmResetView.xaml + + + Views\Auth\ConfirmPasswordView.xaml.cs + ConfirmPasswordView.xaml + + + Views\Auth\ConfirmView.xaml.cs + + + Views\Auth\ResetAccountView.xaml.cs + ResetAccountView.xaml + + + Views\Auth\SignInView.xaml.cs + + + Views\Auth\SignUpView.xaml.cs + + + Views\Chats\AddAdminsView.xaml.cs + AddAdminsView.xaml + + + Views\Chats\AddChannelManagerView.xaml.cs + AddChannelManagerView.xaml + + + Views\Chats\AddChatParticipantView.xaml.cs + + + Views\Chats\AddSecretChatParticipantView.xaml.cs + AddSecretChatParticipantView.xaml + + + Views\Chats\ChannelAdministratorsView.xaml.cs + ChannelAdministratorsView.xaml + + + Views\Chats\ChannelIntroView.xaml.cs + ChannelIntroView.xaml + + + Views\Chats\ChannelMembersView.xaml.cs + ChannelMembersView.xaml + + + Views\Chats\Chat2View.xaml.cs + Chat2View.xaml + + + Views\Chats\ChatView.xaml.cs + + + Views\Chats\ConvertToSupergroupView.xaml.cs + ConvertToSupergroupView.xaml + + + Views\Chats\EditChatView.xaml.cs + + + Views\Chats\EditGroupTypeView.xaml.cs + EditGroupTypeView.xaml + + + Views\Chats\GroupsInCommonView.xaml.cs + GroupsInCommonView.xaml + + + Views\Chats\InviteLinkView.xaml.cs + InviteLinkView.xaml + + + Views\Contacts\ContactInfoView.xaml.cs + ContactInfoView.xaml + + + Views\Contacts\ContactView.xaml.cs + + + Views\Contacts\EditContactView.xaml.cs + + + Views\Contacts\SecretContactDetailsView.xaml.cs + SecretContactDetailsView.xaml + + + Views\Contacts\SecretContactView.xaml.cs + SecretContactView.xaml + + + Views\Contacts\ShareContactView.xaml.cs + + + Views\Controls\ChatInviteControl.xaml.cs + ChatInviteControl.xaml + + + Views\Controls\ConversationTileControl.xaml.cs + + + Views\Controls\FeaturedStickerSetControl.xaml.cs + FeaturedStickerSetControl.xaml + + + Views\Controls\MessagePlayerControl.xaml.cs + MessagePlayerControl.xaml + + + Views\Controls\MessageStatusControl.xaml.cs + + + Views\Controls\PieSlice.cs + + + Views\Controls\SecretPhotoPlaceholder.xaml.cs + SecretPhotoPlaceholder.xaml + + + Views\Controls\StickerSetControl.xaml.cs + StickerSetControl.xaml + + + Views\Controls\UserTileControl.xaml.cs + UserTileControl.xaml + + + Views\Debug\DebugView.xaml.cs + + + Views\Debug\LongPollView.xaml.cs + + + Views\Debug\PerformanceView.xaml.cs + + + Views\Dialogs\ChooseDialogView.xaml.cs + ChooseDialogView.xaml + + + Views\Dialogs\ChooseParticipantsView.xaml.cs + + + Views\Dialogs\CommandHintsView.xaml.cs + CommandHintsView.xaml + + + Views\Dialogs\CommandsControl.xaml.cs + CommandsControl.xaml + + + Views\Dialogs\CreateBroadcastView.xaml.cs + CreateBroadcastView.xaml + + + Views\Dialogs\CreateChannelStep1View.xaml.cs + CreateChannelStep1View.xaml + + + Views\Dialogs\CreateChannelStep2View.xaml.cs + CreateChannelStep2View.xaml + + + Views\Dialogs\CreateChannelStep3View.xaml.cs + CreateChannelStep3View.xaml + + + Views\Dialogs\CreateDialogView.xaml.cs + + + Views\Dialogs\DialogSearchMessagesView.xaml.cs + DialogSearchMessagesView.xaml + + + Views\Dialogs\EmojiKeyboardControl.xaml.cs + EmojiKeyboardControl.xaml + + + Views\Dialogs\FastDialogDetailsView.xaml.cs + FastDialogDetailsView.xaml + + + Views\Dialogs\HashtagHintsView.xaml.cs + HashtagHintsView.xaml + + + Views\Dialogs\InlineBotResultsView.xaml.cs + InlineBotResultsView.xaml + + + Views\Dialogs\MessageViewerView.xaml.cs + MessageViewerView.xaml + + + Views\Dialogs\PinnedMessageView.xaml.cs + PinnedMessageView.xaml + + + Views\Dialogs\SecretChatDebugView.xaml.cs + SecretChatDebugView.xaml + + + Views\Dialogs\StickerHintsView.xaml.cs + StickerHintsView.xaml + + + Views\Dialogs\StickerPreviewMenu.xaml.cs + StickerPreviewMenu.xaml + + + Views\Dialogs\UserActionView.xaml.cs + UserActionView.xaml + + + Views\Dialogs\UsernameHintsView.xaml.cs + UsernameHintsView.xaml + + + Views\Media\AnimatedImageViewerView.xaml.cs + AnimatedImageViewerView.xaml + + + Views\Media\DecryptedImageViewerView.xaml.cs + DecryptedImageViewerView.xaml + + + Views\Media\FullMediaView.xaml.cs + FullMediaView.xaml + + + Views\Media\ImageEditorView.xaml.cs + ImageEditorView.xaml + + + Views\Media\ImageViewerView.xaml.cs + + + Views\Media\MapTileSources\GoogleMapsTileSource.cs + + + Views\Media\MapTileSources\OpenAeralMapTileSource.cs + + + Views\Media\MapTileSources\OpenStreetMapTileSource.cs + + + Views\Media\MapView.xaml.cs + + + Views\Media\MusicView.xaml.cs + MusicView.xaml + + + Views\Media\ProfilePhotoViewerView.xaml.cs + + + Views\Media\SecretMediaView.xaml.cs + SecretMediaView.xaml + + + Views\Media\VideoCaptureView.xaml.cs + + + Views\Media\VideoPlayerView.xaml.cs + + + Views\Search\SearchContactsView.xaml.cs + + + Views\Search\SearchDialogsView.xaml.cs + + + Views\Search\SearchFilesView.xaml.cs + SearchFilesView.xaml + + + Views\Search\SearchLinksView.xaml.cs + SearchLinksView.xaml + + + Views\Search\SearchMessagesView.xaml.cs + + + Views\Search\SearchMusicView.xaml.cs + SearchMusicView.xaml + + + Views\Search\SearchShellView.xaml.cs + + + Views\Search\SearchVenuesView.xaml.cs + SearchVenuesView.xaml + + + Views\Search\SearchView.xaml.cs + SearchView.xaml + + + Views\ShellView.xaml.cs + + + Views\TelegramViewBase.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BioView.xaml + + + CallsPrivacyView.xaml + + + CallsSecurityView.xaml + + + ChooseGeoLivePeriodView.xaml + + + ChooseVideoQualityView.xaml + + + PassportSettingsView.xaml + + + ContactsSecurityView.xaml + + + LoggedInView.xaml + + + PhotoPickerView.xaml + + + CameraView.xaml + + + GifPlayerControl.xaml + + + ProxyListView.xaml + + + ProxyView.xaml + + + StartupView.xaml + + + CallDebugControl.xaml + + + CallRatingControl.xaml + + + CallsView.xaml + + + CallView.xaml + + + ReturnToCallControl.xaml + + + SignalBarsControl.xaml + + + GroupStickersView.xaml + + + ShareContactDetailsView.xaml + + + + CropControl.xaml + + + CameraControl.xaml + + + + DialogControl.xaml + + + GroupedMessageControl.xaml + + + + LabeledTextBox.xaml + + + LiveLocationIcon.xaml + + + LiveLocationProgress.xaml + + + LiveLocationsControl.xaml + + + MediaPhotoControl.xaml + + + MediaVideoControl.xaml + + + OpenPhotoPicker.xaml + + + PhotoControl.xaml + + + ProxyStatusControl.xaml + + + RecordingControl.xaml + + + RibbonControl.xaml + + + RibbonImageControl.xaml + + + SelectionControl.xaml + + + ShareMessagePicker.xaml + + + TelegramDatePickerPage.xaml + + + + TextingControl.xaml + + + TypingControl.xaml + + + UpdateAppControl.xaml + + + UploadingControl.xaml + + + LiveLocationBadgeView.xaml + + + UnreadCounter.xaml + + + EmojiHintsView.xaml + + + PlayerView.xaml + + + SearchUserControl.xaml + + + FeedView.xaml + + + MainPage.xaml + + + MapUserTileControl.xaml + + + StaticMapControl.xaml + + + EmailCodeView.xaml + + + PasswordIntroView.xaml + + + EmailView.xaml + + + PersonalDetailsView.xaml + + + CardInfoView.xaml + + + CheckoutView.xaml + + + PasswordEmailView.xaml + + + SavedCardInfoView.xaml + + + ShippingMethodView.xaml + + + ShippingInfoView.xaml + + + WebVerificationView.xaml + + + WebCardInfoView.xaml + + + InputBox.xaml + + + LabeledPasswordBox.xaml + + + MessageControl.xaml + + + DecryptedMessageControl.xaml + + + OpacityMaskBorder.xaml + + + Progress.xaml + + + StatusControl.xaml + + + TelegramApplicationBar.xaml + + + TelegramAppBarButton.xaml + + + VideoTimelineControl.xaml + + + + DocumentTileControl.xaml + + + PhotoTileControl.xaml + + + ColorPicker.xaml + + + EditVideoView.xaml + + + ExtendedImageEditor.xaml + + + + Sticker.xaml + + + + StickersControl.xaml + + + TextLabel.xaml + + + SearchSharedContactsView.xaml + + + PhoneNumberCodeView.xaml + + + PhoneNumberView.xaml + + + ResidentialAddressView.xaml + + + EnterPasswordView.xaml + + + PassportView.xaml + + + + + + Designer + + + Always + + + Designer + + + + Designer + + + + + Themes\Default\LongListSelector.xaml + MSBuild:Compile + Designer + + + Themes\Generic.xaml + MSBuild:Compile + Designer + + + Views\Contacts\ContactsView.xaml + MSBuild:Compile + Designer + + + Views\Controls\AudioRecorderControl.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\DialogDetailsView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\DialogsView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\SecretDialogDetailsView.xaml + MSBuild:Compile + Designer + + + Views\Media\FilesView.xaml + MSBuild:Compile + Designer + + + Views\Media\LinksView.xaml + MSBuild:Compile + Designer + + + Views\Media\MediaView.xaml + MSBuild:Compile + Designer + + + Views\Media\MultiImageEditorView.xaml + MSBuild:Compile + Designer + + + App.xaml + MSBuild:Compile + Designer + + + EmojiPanel\Controls\Emoji\EmojiControl.xaml + MSBuild:Compile + Designer + + + Themes\Default\Button.xaml + MSBuild:Compile + Designer + + + Themes\Default\CheckBox.xaml + MSBuild:Compile + Designer + + + Themes\Default\ListBox.xaml + MSBuild:Compile + Designer + + + Themes\Default\ScrollViewer.xaml + MSBuild:Compile + Designer + + + Themes\Default\Slider.xaml + MSBuild:Compile + Designer + + + Themes\Default\Templates\DataTemplates.xaml + MSBuild:Compile + Designer + + + Themes\Default\Templates\ItemsPanel.xaml + MSBuild:Compile + Designer + + + Themes\Default\Templates\Media.xaml + MSBuild:Compile + Designer + + + Themes\Default\TextBlock.xaml + MSBuild:Compile + Designer + + + Themes\Default\TextBox.xaml + MSBuild:Compile + Designer + + + Themes\Default\Theme.xaml + MSBuild:Compile + Designer + + + Themes\Default\ToggleButton.xaml + MSBuild:Compile + Designer + + + Themes\Default\Transitions.xaml + MSBuild:Compile + Designer + + + Views\Additional\AboutView.xaml + MSBuild:Compile + Designer + + + Views\Additional\AccountSelfDestructsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\AddChatParticipantConfirmationView.xaml + MSBuild:Compile + Designer + + + Views\Additional\AllowUsersView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ArchivedStickersView.xaml + MSBuild:Compile + Designer + + + Views\Additional\AskQuestionConfirmationView.xaml + MSBuild:Compile + Designer + + + Views\Additional\BlockedContactsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\BubbleBackgroundControl.xaml + MSBuild:Compile + Designer + + + Views\Additional\CacheView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChangePasscodeView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChangePasswordEmailView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChangePasswordHintView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChangePasswordView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChangePhoneNumberView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChannelBlockedContactsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChatSettingsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChooseAttachmentView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChooseBackgroundView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChooseCountryView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChooseNotificationSpanView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ChooseTTLView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ClearCacheSettingsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\EditCurrentUserView.xaml + MSBuild:Compile + Designer + + + Views\Additional\EditPhoneNumberView.xaml + MSBuild:Compile + Designer + + + Views\Additional\EditUsernameView.xaml + MSBuild:Compile + Designer + + + Views\Additional\EncryptionKeyView.xaml + MSBuild:Compile + Designer + + + Views\Additional\EnterPasscodeView.xaml + MSBuild:Compile + Designer + + + Views\Additional\EnterPasswordView.xaml + MSBuild:Compile + Designer + + + Views\Additional\FallingSnowControl.xaml + MSBuild:Compile + Designer + + + Views\Additional\FeaturedStickersView.xaml + MSBuild:Compile + Designer + + + Views\Additional\GroupsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\InputMessageHint.xaml + MSBuild:Compile + Designer + + + Views\Additional\LastSeenView.xaml + MSBuild:Compile + Designer + + + Views\Additional\LockscreenView.xaml + MSBuild:Compile + Designer + + + Views\Additional\MasksView.xaml + MSBuild:Compile + Designer + + + Views\Additional\MassDeleteReportSpamView.xaml + MSBuild:Compile + Designer + + + Views\Additional\NotificationsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\NumericKeyboard.xaml + MSBuild:Compile + Designer + + + Views\Additional\PasscodeView.xaml + MSBuild:Compile + Designer + + + Views\Additional\PasswordRecoveryView.xaml + MSBuild:Compile + Designer + + + Views\Additional\PasswordView.xaml + MSBuild:Compile + Designer + + + Views\Additional\PrivacySecurityView.xaml + MSBuild:Compile + Designer + + + Views\Additional\PrivacyStatementView.xaml + MSBuild:Compile + Designer + + + Views\Additional\SecretChatsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\SelectMultipleUsersView.xaml + MSBuild:Compile + Designer + + + Views\Additional\SessionsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\SettingsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\ShareView.xaml + MSBuild:Compile + Designer + + + Views\Additional\SnapshotsView.xaml + MSBuild:Compile + Designer + + + Views\Additional\SpecialThanksView.xaml + MSBuild:Compile + Designer + + + Views\Additional\StickersView.xaml + MSBuild:Compile + Designer + + + Views\Additional\TelegramPasswordBox.xaml + MSBuild:Compile + Designer + + + Views\Additional\WebView.xaml + MSBuild:Compile + Designer + + + Views\Auth\CancelConfirmResetView.xaml + MSBuild:Compile + Designer + + + Views\Auth\ConfirmPasswordView.xaml + MSBuild:Compile + Designer + + + Views\Auth\ConfirmView.xaml + MSBuild:Compile + Designer + + + Views\Auth\ResetAccountView.xaml + MSBuild:Compile + Designer + + + Views\Auth\SignInView.xaml + MSBuild:Compile + Designer + + + Views\Auth\SignUpView.xaml + MSBuild:Compile + Designer + + + Views\Chats\AddAdminsView.xaml + MSBuild:Compile + Designer + + + Views\Chats\AddChannelManagerView.xaml + MSBuild:Compile + Designer + + + Views\Chats\AddChatParticipantView.xaml + MSBuild:Compile + Designer + + + Views\Chats\AddSecretChatParticipantView.xaml + MSBuild:Compile + Designer + + + Views\Chats\ChannelAdministratorsView.xaml + MSBuild:Compile + Designer + + + Views\Chats\ChannelIntroView.xaml + MSBuild:Compile + Designer + + + Views\Chats\ChannelMembersView.xaml + MSBuild:Compile + Designer + + + Views\Chats\Chat2View.xaml + MSBuild:Compile + Designer + + + Views\Chats\ChatView.xaml + MSBuild:Compile + Designer + + + Views\Chats\ConvertToSupergroupView.xaml + MSBuild:Compile + Designer + + + Views\Chats\EditChatView.xaml + MSBuild:Compile + Designer + + + Views\Chats\EditGroupTypeView.xaml + MSBuild:Compile + Designer + + + Views\Chats\GroupsInCommonView.xaml + MSBuild:Compile + Designer + + + Views\Chats\InviteLinkView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\ContactInfoView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\ContactView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\EditContactView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\SecretContactDetailsView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\SecretContactView.xaml + MSBuild:Compile + Designer + + + Views\Contacts\ShareContactView.xaml + MSBuild:Compile + Designer + + + Views\Controls\ChatInviteControl.xaml + MSBuild:Compile + Designer + + + Views\Controls\ConversationTileControl.xaml + MSBuild:Compile + Designer + + + Views\Controls\FeaturedStickerSetControl.xaml + MSBuild:Compile + Designer + + + Views\Controls\MessagePlayerControl.xaml + MSBuild:Compile + Designer + + + Views\Controls\MessageStatusControl.xaml + MSBuild:Compile + Designer + + + Views\Controls\SecretPhotoPlaceholder.xaml + MSBuild:Compile + Designer + + + Views\Controls\StickerSetControl.xaml + MSBuild:Compile + Designer + + + Views\Controls\UserTileControl.xaml + MSBuild:Compile + Designer + + + Views\Debug\DebugView.xaml + MSBuild:Compile + Designer + + + Views\Debug\LongPollView.xaml + MSBuild:Compile + Designer + + + Views\Debug\PerformanceView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\ChooseDialogView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\ChooseParticipantsView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\CommandHintsView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\CommandsControl.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\CreateBroadcastView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\CreateChannelStep1View.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\CreateChannelStep2View.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\CreateChannelStep3View.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\CreateDialogView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\DialogSearchMessagesView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\EmojiKeyboardControl.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\FastDialogDetailsView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\HashtagHintsView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\InlineBotResultsView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\MessageViewerView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\PinnedMessageView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\SecretChatDebugView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\StickerHintsView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\StickerPreviewMenu.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\UserActionView.xaml + MSBuild:Compile + Designer + + + Views\Dialogs\UsernameHintsView.xaml + MSBuild:Compile + Designer + + + Views\Media\AnimatedImageViewerView.xaml + MSBuild:Compile + Designer + + + Views\Media\DecryptedImageViewerView.xaml + MSBuild:Compile + Designer + + + Views\Media\FullMediaView.xaml + MSBuild:Compile + Designer + + + Views\Media\ImageEditorView.xaml + MSBuild:Compile + Designer + + + Views\Media\ImageViewerView.xaml + MSBuild:Compile + Designer + + + Views\Media\MapView.xaml + MSBuild:Compile + Designer + + + Views\Media\MusicView.xaml + MSBuild:Compile + Designer + + + Views\Media\ProfilePhotoViewerView.xaml + MSBuild:Compile + Designer + + + Views\Media\SecretMediaView.xaml + MSBuild:Compile + Designer + + + Views\Media\VideoCaptureView.xaml + MSBuild:Compile + Designer + + + Views\Media\VideoPlayerView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchContactsView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchDialogsView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchFilesView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchLinksView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchMessagesView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchMusicView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchShellView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchVenuesView.xaml + MSBuild:Compile + Designer + + + Views\Search\SearchView.xaml + MSBuild:Compile + Designer + + + Views\ShellView.xaml + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + + + avcodec-57.dll + + + avformat-57.dll + + + avutil-55.dll + + + swresample-2.dll + + + swscale-4.dll + + + ARM\libwebp.dll + PreserveNewest + + + Assets\emoji.abc-WXGA.png + + + Assets\emoji.backspace-WXGA.png + + + Assets\emoji.category.1-WXGA.png + + + Assets\emoji.category.2-WXGA.png + + + Assets\emoji.category.3-WXGA.png + + + Assets\emoji.category.4-WXGA.png + + + Assets\emoji.category.5-WXGA.png + + + Assets\emoji.featured-WXGA.png + + + Assets\emoji.recent-WXGA.png + + + Assets\emoji.settings-WXGA.png + + + Assets\emoji.sticker-WXGA.png + + + Assets\Emoji\Separated\002320E3.png + + + Assets\Emoji\Separated\002A20E3.png + + + Assets\Emoji\Separated\003020E3.png + + + Assets\Emoji\Separated\003120E3.png + + + Assets\Emoji\Separated\003220E3.png + + + Assets\Emoji\Separated\003320E3.png + + + Assets\Emoji\Separated\003420E3.png + + + Assets\Emoji\Separated\003520E3.png + + + Assets\Emoji\Separated\003620E3.png + + + Assets\Emoji\Separated\003720E3.png + + + Assets\Emoji\Separated\003820E3.png + + + Assets\Emoji\Separated\003920E3.png + + + Assets\Emoji\Separated\00a9.png + + + Assets\Emoji\Separated\00ae.png + + + Assets\Emoji\Separated\203C.png + + + Assets\Emoji\Separated\2049.png + + + Assets\Emoji\Separated\2122.png + + + Assets\Emoji\Separated\2139.png + + + Assets\Emoji\Separated\2194.png + + + Assets\Emoji\Separated\2195.png + + + Assets\Emoji\Separated\2196.png + + + Assets\Emoji\Separated\2197.png + + + Assets\Emoji\Separated\2198.png + + + Assets\Emoji\Separated\2199.png + + + Assets\Emoji\Separated\21A9.png + + + Assets\Emoji\Separated\21AA.png + + + Assets\Emoji\Separated\231A.png + + + Assets\Emoji\Separated\231B.png + + + Assets\Emoji\Separated\2328.png + + + Assets\Emoji\Separated\23e9.png + + + Assets\Emoji\Separated\23ea.png + + + Assets\Emoji\Separated\23eb.png + + + Assets\Emoji\Separated\23ec.png + + + Assets\Emoji\Separated\23ED.png + + + Assets\Emoji\Separated\23EE.png + + + Assets\Emoji\Separated\23EF.png + + + Assets\Emoji\Separated\23f0.png + + + Assets\Emoji\Separated\23F1.png + + + Assets\Emoji\Separated\23F2.png + + + Assets\Emoji\Separated\23f3.png + + + Assets\Emoji\Separated\23F8.png + + + Assets\Emoji\Separated\23F9.png + + + Assets\Emoji\Separated\23FA.png + + + Assets\Emoji\Separated\24C2.png + + + Assets\Emoji\Separated\25AA.png + + + Assets\Emoji\Separated\25AB.png + + + Assets\Emoji\Separated\25B6.png + + + Assets\Emoji\Separated\25C0.png + + + Assets\Emoji\Separated\25FB.png + + + Assets\Emoji\Separated\25FC.png + + + Assets\Emoji\Separated\25FD.png + + + Assets\Emoji\Separated\25FE.png + + + Assets\Emoji\Separated\2600.png + + + Assets\Emoji\Separated\2601.png + + + Assets\Emoji\Separated\2602.png + + + Assets\Emoji\Separated\2603.png + + + Assets\Emoji\Separated\2604.png + + + Assets\Emoji\Separated\260E.png + + + Assets\Emoji\Separated\2611.png + + + Assets\Emoji\Separated\2614.png + + + Assets\Emoji\Separated\2615.png + + + Assets\Emoji\Separated\2618.png + + + Assets\Emoji\Separated\261D.png + + + Assets\Emoji\Separated\261DD83CDFFB.png + + + Assets\Emoji\Separated\261DD83CDFFC.png + + + Assets\Emoji\Separated\261DD83CDFFD.png + + + Assets\Emoji\Separated\261DD83CDFFE.png + + + Assets\Emoji\Separated\261DD83CDFFF.png + + + Assets\Emoji\Separated\2620.png + + + Assets\Emoji\Separated\2622.png + + + Assets\Emoji\Separated\2623.png + + + Assets\Emoji\Separated\2626.png + + + Assets\Emoji\Separated\262A.png + + + Assets\Emoji\Separated\262E.png + + + Assets\Emoji\Separated\262F.png + + + Assets\Emoji\Separated\2638.png + + + Assets\Emoji\Separated\2639.png + + + Assets\Emoji\Separated\2639FE0F.png + + + Assets\Emoji\Separated\263A.png + + + Assets\Emoji\Separated\2648.png + + + Assets\Emoji\Separated\2649.png + + + Assets\Emoji\Separated\264A.png + + + Assets\Emoji\Separated\264B.png + + + Assets\Emoji\Separated\264C.png + + + Assets\Emoji\Separated\264D.png + + + Assets\Emoji\Separated\264E.png + + + Assets\Emoji\Separated\264F.png + + + Assets\Emoji\Separated\2650.png + + + Assets\Emoji\Separated\2651.png + + + Assets\Emoji\Separated\2652.png + + + Assets\Emoji\Separated\2653.png + + + Assets\Emoji\Separated\2660.png + + + Assets\Emoji\Separated\2663.png + + + Assets\Emoji\Separated\2665.png + + + Assets\Emoji\Separated\2666.png + + + Assets\Emoji\Separated\2668.png + + + Assets\Emoji\Separated\267B.png + + + Assets\Emoji\Separated\267F.png + + + Assets\Emoji\Separated\2692.png + + + Assets\Emoji\Separated\2693.png + + + Assets\Emoji\Separated\2694.png + + + Assets\Emoji\Separated\2696.png + + + Assets\Emoji\Separated\2697.png + + + Assets\Emoji\Separated\2699.png + + + Assets\Emoji\Separated\269B.png + + + Assets\Emoji\Separated\269C.png + + + Assets\Emoji\Separated\26A0.png + + + Assets\Emoji\Separated\26A1.png + + + Assets\Emoji\Separated\26AA.png + + + Assets\Emoji\Separated\26AB.png + + + Assets\Emoji\Separated\26B0.png + + + Assets\Emoji\Separated\26B1.png + + + Assets\Emoji\Separated\26BD.png + + + Assets\Emoji\Separated\26BE.png + + + Assets\Emoji\Separated\26C4.png + + + Assets\Emoji\Separated\26C5.png + + + Assets\Emoji\Separated\26C8.png + + + Assets\Emoji\Separated\26ce.png + + + Assets\Emoji\Separated\26CF.png + + + Assets\Emoji\Separated\26D1.png + + + Assets\Emoji\Separated\26D3.png + + + Assets\Emoji\Separated\26D4.png + + + Assets\Emoji\Separated\26E9.png + + + Assets\Emoji\Separated\26EA.png + + + Assets\Emoji\Separated\26F0.png + + + Assets\Emoji\Separated\26F1.png + + + Assets\Emoji\Separated\26F2.png + + + Assets\Emoji\Separated\26F3.png + + + Assets\Emoji\Separated\26F4.png + + + Assets\Emoji\Separated\26F5.png + + + Assets\Emoji\Separated\26F7.png + + + Assets\Emoji\Separated\26F8.png + + + Assets\Emoji\Separated\26F9.png + + + Assets\Emoji\Separated\26F9200D2640.png + + + Assets\Emoji\Separated\26F9D83CDFFB.png + + + Assets\Emoji\Separated\26F9D83CDFFB200D2640.png + + + Assets\Emoji\Separated\26F9D83CDFFC.png + + + Assets\Emoji\Separated\26F9D83CDFFC200D2640.png + + + Assets\Emoji\Separated\26F9D83CDFFD.png + + + Assets\Emoji\Separated\26F9D83CDFFD200D2640.png + + + Assets\Emoji\Separated\26F9D83CDFFE.png + + + Assets\Emoji\Separated\26F9D83CDFFE200D2640.png + + + Assets\Emoji\Separated\26F9D83CDFFF.png + + + Assets\Emoji\Separated\26F9D83CDFFF200D2640.png + + + Assets\Emoji\Separated\26FA.png + + + Assets\Emoji\Separated\26FD.png + + + Assets\Emoji\Separated\2702.png + + + Assets\Emoji\Separated\2705.png + + + Assets\Emoji\Separated\2708.png + + + Assets\Emoji\Separated\2709.png + + + Assets\Emoji\Separated\270a.png + + + Assets\Emoji\Separated\270AD83CDFFB.png + + + Assets\Emoji\Separated\270AD83CDFFC.png + + + Assets\Emoji\Separated\270AD83CDFFD.png + + + Assets\Emoji\Separated\270AD83CDFFE.png + + + Assets\Emoji\Separated\270AD83CDFFF.png + + + Assets\Emoji\Separated\270b.png + + + Assets\Emoji\Separated\270BD83CDFFB.png + + + Assets\Emoji\Separated\270BD83CDFFC.png + + + Assets\Emoji\Separated\270BD83CDFFD.png + + + Assets\Emoji\Separated\270BD83CDFFE.png + + + Assets\Emoji\Separated\270BD83CDFFF.png + + + Assets\Emoji\Separated\270C.png + + + Assets\Emoji\Separated\270CD83CDFFB.png + + + Assets\Emoji\Separated\270CD83CDFFC.png + + + Assets\Emoji\Separated\270CD83CDFFD.png + + + Assets\Emoji\Separated\270CD83CDFFE.png + + + Assets\Emoji\Separated\270CD83CDFFF.png + + + Assets\Emoji\Separated\270D.png + + + Assets\Emoji\Separated\270DD83CDFFB.png + + + Assets\Emoji\Separated\270DD83CDFFC.png + + + Assets\Emoji\Separated\270DD83CDFFD.png + + + Assets\Emoji\Separated\270DD83CDFFE.png + + + Assets\Emoji\Separated\270DD83CDFFF.png + + + Assets\Emoji\Separated\270F.png + + + Assets\Emoji\Separated\2712.png + + + Assets\Emoji\Separated\2714.png + + + Assets\Emoji\Separated\2716.png + + + Assets\Emoji\Separated\271D.png + + + Assets\Emoji\Separated\2721.png + + + Assets\Emoji\Separated\2728.png + + + Assets\Emoji\Separated\2733.png + + + Assets\Emoji\Separated\2734.png + + + Assets\Emoji\Separated\2744.png + + + Assets\Emoji\Separated\2747.png + + + Assets\Emoji\Separated\274c.png + + + Assets\Emoji\Separated\274e.png + + + Assets\Emoji\Separated\2753.png + + + Assets\Emoji\Separated\2754.png + + + Assets\Emoji\Separated\2755.png + + + Assets\Emoji\Separated\2757.png + + + Assets\Emoji\Separated\2763.png + + + Assets\Emoji\Separated\2764.png + + + Assets\Emoji\Separated\2795.png + + + Assets\Emoji\Separated\2796.png + + + Assets\Emoji\Separated\2797.png + + + Assets\Emoji\Separated\27A1.png + + + Assets\Emoji\Separated\27b0.png + + + Assets\Emoji\Separated\27bf.png + + + Assets\Emoji\Separated\2934.png + + + Assets\Emoji\Separated\2935.png + + + Assets\Emoji\Separated\2B05.png + + + Assets\Emoji\Separated\2B06.png + + + Assets\Emoji\Separated\2B07.png + + + Assets\Emoji\Separated\2B1B.png + + + Assets\Emoji\Separated\2B1C.png + + + Assets\Emoji\Separated\2B50.png + + + Assets\Emoji\Separated\2B55.png + + + Assets\Emoji\Separated\3030.png + + + Assets\Emoji\Separated\303D.png + + + Assets\Emoji\Separated\3297.png + + + Assets\Emoji\Separated\3299.png + + + Assets\Emoji\Separated\D83CDC04.png + + + Assets\Emoji\Separated\D83CDCCF.png + + + Assets\Emoji\Separated\D83CDD70.png + + + Assets\Emoji\Separated\D83CDD71.png + + + Assets\Emoji\Separated\D83CDD7E.png + + + Assets\Emoji\Separated\D83CDD7F.png + + + Assets\Emoji\Separated\D83CDD8E.png + + + Assets\Emoji\Separated\D83CDD91.png + + + Assets\Emoji\Separated\D83CDD92.png + + + Assets\Emoji\Separated\D83CDD93.png + + + Assets\Emoji\Separated\D83CDD94.png + + + Assets\Emoji\Separated\D83CDD95.png + + + Assets\Emoji\Separated\D83CDD96.png + + + Assets\Emoji\Separated\D83CDD97.png + + + Assets\Emoji\Separated\D83CDD98.png + + + Assets\Emoji\Separated\D83CDD99.png + + + Assets\Emoji\Separated\D83CDD9A.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDE9.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDEA.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDEB.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDEC.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDEE.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDF1.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDF2.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDF4.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDF6.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDF7.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDF8.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDF9.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDFA.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDFC.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDFD.png + + + Assets\Emoji\Separated\D83CDDE6D83CDDFF.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDE6.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDE7.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDE9.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDEA.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDEB.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDEC.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDED.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDEE.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDEF.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDF1.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDF2.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDF3.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDF4.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDF6.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDF7.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDF8.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDF9.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDFC.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDFE.png + + + Assets\Emoji\Separated\D83CDDE7D83CDDFF.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDE6.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDE8.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDE9.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDEB.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDEC.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDED.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDEE.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDF0.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDF1.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDF2.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDF3.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDF4.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDF7.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDFA.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDFB.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDFC.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDFD.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDFE.png + + + Assets\Emoji\Separated\D83CDDE8D83CDDFF.png + + + Assets\Emoji\Separated\D83CDDE9D83CDDEA.png + + + Assets\Emoji\Separated\D83CDDE9D83CDDEF.png + + + Assets\Emoji\Separated\D83CDDE9D83CDDF0.png + + + Assets\Emoji\Separated\D83CDDE9D83CDDF2.png + + + Assets\Emoji\Separated\D83CDDE9D83CDDF4.png + + + Assets\Emoji\Separated\D83CDDE9D83CDDFF.png + + + Assets\Emoji\Separated\D83CDDEAD83CDDE8.png + + + Assets\Emoji\Separated\D83CDDEAD83CDDEA.png + + + Assets\Emoji\Separated\D83CDDEAD83CDDEC.png + + + Assets\Emoji\Separated\D83CDDEAD83CDDED.png + + + Assets\Emoji\Separated\D83CDDEAD83CDDF7.png + + + Assets\Emoji\Separated\D83CDDEAD83CDDF8.png + + + Assets\Emoji\Separated\D83CDDEAD83CDDF9.png + + + Assets\Emoji\Separated\D83CDDEAD83CDDFA.png + + + Assets\Emoji\Separated\D83CDDEBD83CDDEE.png + + + Assets\Emoji\Separated\D83CDDEBD83CDDEF.png + + + Assets\Emoji\Separated\D83CDDEBD83CDDF0.png + + + Assets\Emoji\Separated\D83CDDEBD83CDDF2.png + + + Assets\Emoji\Separated\D83CDDEBD83CDDF4.png + + + Assets\Emoji\Separated\D83CDDEBD83CDDF7.png + + + Assets\Emoji\Separated\D83CDDECD83CDDE6.png + + + Assets\Emoji\Separated\D83CDDECD83CDDE7.png + + + Assets\Emoji\Separated\D83CDDECD83CDDE9.png + + + Assets\Emoji\Separated\D83CDDECD83CDDEA.png + + + Assets\Emoji\Separated\D83CDDECD83CDDEB.png + + + Assets\Emoji\Separated\D83CDDECD83CDDEC.png + + + Assets\Emoji\Separated\D83CDDECD83CDDED.png + + + Assets\Emoji\Separated\D83CDDECD83CDDEE.png + + + Assets\Emoji\Separated\D83CDDECD83CDDF1.png + + + Assets\Emoji\Separated\D83CDDECD83CDDF2.png + + + Assets\Emoji\Separated\D83CDDECD83CDDF3.png + + + Assets\Emoji\Separated\D83CDDECD83CDDF5.png + + + Assets\Emoji\Separated\D83CDDECD83CDDF6.png + + + Assets\Emoji\Separated\D83CDDECD83CDDF7.png + + + Assets\Emoji\Separated\D83CDDECD83CDDF8.png + + + Assets\Emoji\Separated\D83CDDECD83CDDF9.png + + + Assets\Emoji\Separated\D83CDDECD83CDDFA.png + + + Assets\Emoji\Separated\D83CDDECD83CDDFC.png + + + Assets\Emoji\Separated\D83CDDECD83CDDFE.png + + + Assets\Emoji\Separated\D83CDDEDD83CDDF0.png + + + Assets\Emoji\Separated\D83CDDEDD83CDDF3.png + + + Assets\Emoji\Separated\D83CDDEDD83CDDF7.png + + + Assets\Emoji\Separated\D83CDDEDD83CDDF9.png + + + Assets\Emoji\Separated\D83CDDEDD83CDDFA.png + + + Assets\Emoji\Separated\D83CDDEED83CDDE8.png + + + Assets\Emoji\Separated\D83CDDEED83CDDE9.png + + + Assets\Emoji\Separated\D83CDDEED83CDDEA.png + + + Assets\Emoji\Separated\D83CDDEED83CDDF1.png + + + Assets\Emoji\Separated\D83CDDEED83CDDF2.png + + + Assets\Emoji\Separated\D83CDDEED83CDDF3.png + + + Assets\Emoji\Separated\D83CDDEED83CDDF4.png + + + Assets\Emoji\Separated\D83CDDEED83CDDF6.png + + + Assets\Emoji\Separated\D83CDDEED83CDDF7.png + + + Assets\Emoji\Separated\D83CDDEED83CDDF8.png + + + Assets\Emoji\Separated\D83CDDEED83CDDF9.png + + + Assets\Emoji\Separated\D83CDDEFD83CDDEA.png + + + Assets\Emoji\Separated\D83CDDEFD83CDDF2.png + + + Assets\Emoji\Separated\D83CDDEFD83CDDF4.png + + + Assets\Emoji\Separated\D83CDDEFD83CDDF5.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDEA.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDEC.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDED.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDEE.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDF2.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDF3.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDF5.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDF7.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDFC.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDFE.png + + + Assets\Emoji\Separated\D83CDDF0D83CDDFF.png + + + Assets\Emoji\Separated\D83CDDF1D83CDDE6.png + + + Assets\Emoji\Separated\D83CDDF1D83CDDE7.png + + + Assets\Emoji\Separated\D83CDDF1D83CDDE8.png + + + Assets\Emoji\Separated\D83CDDF1D83CDDEE.png + + + Assets\Emoji\Separated\D83CDDF1D83CDDF0.png + + + Assets\Emoji\Separated\D83CDDF1D83CDDF7.png + + + Assets\Emoji\Separated\D83CDDF1D83CDDF8.png + + + Assets\Emoji\Separated\D83CDDF1D83CDDF9.png + + + Assets\Emoji\Separated\D83CDDF1D83CDDFA.png + + + Assets\Emoji\Separated\D83CDDF1D83CDDFB.png + + + Assets\Emoji\Separated\D83CDDF1D83CDDFE.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDE6.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDE8.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDE9.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDEA.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDEC.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDED.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDF0.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDF1.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDF2.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDF3.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDF4.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDF5.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDF6.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDF7.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDF8.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDF9.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDFA.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDFB.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDFC.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDFD.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDFE.png + + + Assets\Emoji\Separated\D83CDDF2D83CDDFF.png + + + Assets\Emoji\Separated\D83CDDF3D83CDDE6.png + + + Assets\Emoji\Separated\D83CDDF3D83CDDE8.png + + + Assets\Emoji\Separated\D83CDDF3D83CDDEA.png + + + Assets\Emoji\Separated\D83CDDF3D83CDDEB.png + + + Assets\Emoji\Separated\D83CDDF3D83CDDEC.png + + + Assets\Emoji\Separated\D83CDDF3D83CDDEE.png + + + Assets\Emoji\Separated\D83CDDF3D83CDDF1.png + + + Assets\Emoji\Separated\D83CDDF3D83CDDF4.png + + + Assets\Emoji\Separated\D83CDDF3D83CDDF5.png + + + Assets\Emoji\Separated\D83CDDF3D83CDDF7.png + + + Assets\Emoji\Separated\D83CDDF3D83CDDFA.png + + + Assets\Emoji\Separated\D83CDDF3D83CDDFF.png + + + Assets\Emoji\Separated\D83CDDF4D83CDDF2.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDE6.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDEA.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDEB.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDEC.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDED.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDF0.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDF1.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDF2.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDF3.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDF7.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDF8.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDF9.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDFC.png + + + Assets\Emoji\Separated\D83CDDF5D83CDDFE.png + + + Assets\Emoji\Separated\D83CDDF6D83CDDE6.png + + + Assets\Emoji\Separated\D83CDDF7D83CDDEA.png + + + Assets\Emoji\Separated\D83CDDF7D83CDDF4.png + + + Assets\Emoji\Separated\D83CDDF7D83CDDF8.png + + + Assets\Emoji\Separated\D83CDDF7D83CDDFA.png + + + Assets\Emoji\Separated\D83CDDF7D83CDDFC.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDE6.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDE7.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDE8.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDE9.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDEA.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDEC.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDED.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDEE.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDF0.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDF1.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDF2.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDF3.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDF4.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDF7.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDF8.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDF9.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDFB.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDFD.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDFE.png + + + Assets\Emoji\Separated\D83CDDF8D83CDDFF.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDE8.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDE9.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDEB.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDEC.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDED.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDEF.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDF0.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDF1.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDF2.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDF3.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDF4.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDF7.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDF9.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDFB.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDFC.png + + + Assets\Emoji\Separated\D83CDDF9D83CDDFF.png + + + Assets\Emoji\Separated\D83CDDFAD83CDDE6.png + + + Assets\Emoji\Separated\D83CDDFAD83CDDEC.png + + + Assets\Emoji\Separated\D83CDDFAD83CDDF8.png + + + Assets\Emoji\Separated\D83CDDFAD83CDDFE.png + + + Assets\Emoji\Separated\D83CDDFAD83CDDFF.png + + + Assets\Emoji\Separated\D83CDDFBD83CDDE6.png + + + Assets\Emoji\Separated\D83CDDFBD83CDDE8.png + + + Assets\Emoji\Separated\D83CDDFBD83CDDEA.png + + + Assets\Emoji\Separated\D83CDDFBD83CDDEC.png + + + Assets\Emoji\Separated\D83CDDFBD83CDDEE.png + + + Assets\Emoji\Separated\D83CDDFBD83CDDF3.png + + + Assets\Emoji\Separated\D83CDDFBD83CDDFA.png + + + Assets\Emoji\Separated\D83CDDFCD83CDDEB.png + + + Assets\Emoji\Separated\D83CDDFCD83CDDF8.png + + + Assets\Emoji\Separated\D83CDDFDD83CDDF0.png + + + Assets\Emoji\Separated\D83CDDFED83CDDEA.png + + + Assets\Emoji\Separated\D83CDDFED83CDDF9.png + + + Assets\Emoji\Separated\D83CDDFFD83CDDE6.png + + + Assets\Emoji\Separated\D83CDDFFD83CDDF2.png + + + Assets\Emoji\Separated\D83CDDFFD83CDDFC.png + + + Assets\Emoji\Separated\D83CDE01.png + + + Assets\Emoji\Separated\D83CDE02.png + + + Assets\Emoji\Separated\D83CDE1A.png + + + Assets\Emoji\Separated\D83CDE2F.png + + + Assets\Emoji\Separated\D83CDE32.png + + + Assets\Emoji\Separated\D83CDE33.png + + + Assets\Emoji\Separated\D83CDE34.png + + + Assets\Emoji\Separated\D83CDE35.png + + + Assets\Emoji\Separated\D83CDE36.png + + + Assets\Emoji\Separated\D83CDE37.png + + + Assets\Emoji\Separated\D83CDE38.png + + + Assets\Emoji\Separated\D83CDE39.png + + + Assets\Emoji\Separated\D83CDE3A.png + + + Assets\Emoji\Separated\D83CDE50.png + + + Assets\Emoji\Separated\D83CDE51.png + + + Assets\Emoji\Separated\D83CDF00.png + + + Assets\Emoji\Separated\D83CDF01.png + + + Assets\Emoji\Separated\D83CDF02.png + + + Assets\Emoji\Separated\D83CDF03.png + + + Assets\Emoji\Separated\D83CDF04.png + + + Assets\Emoji\Separated\D83CDF05.png + + + Assets\Emoji\Separated\D83CDF06.png + + + Assets\Emoji\Separated\D83CDF07.png + + + Assets\Emoji\Separated\D83CDF08.png + + + Assets\Emoji\Separated\D83CDF09.png + + + Assets\Emoji\Separated\D83CDF0A.png + + + Assets\Emoji\Separated\D83CDF0B.png + + + Assets\Emoji\Separated\D83CDF0C.png + + + Assets\Emoji\Separated\D83CDF0D.png + + + Assets\Emoji\Separated\D83CDF0E.png + + + Assets\Emoji\Separated\D83CDF0F.png + + + Assets\Emoji\Separated\D83CDF10.png + + + Assets\Emoji\Separated\D83CDF11.png + + + Assets\Emoji\Separated\D83CDF12.png + + + Assets\Emoji\Separated\D83CDF13.png + + + Assets\Emoji\Separated\D83CDF14.png + + + Assets\Emoji\Separated\D83CDF15.png + + + Assets\Emoji\Separated\D83CDF16.png + + + Assets\Emoji\Separated\D83CDF17.png + + + Assets\Emoji\Separated\D83CDF18.png + + + Assets\Emoji\Separated\D83CDF19.png + + + Assets\Emoji\Separated\D83CDF1A.png + + + Assets\Emoji\Separated\D83CDF1B.png + + + Assets\Emoji\Separated\D83CDF1C.png + + + Assets\Emoji\Separated\D83CDF1D.png + + + Assets\Emoji\Separated\D83CDF1E.png + + + Assets\Emoji\Separated\D83CDF1F.png + + + Assets\Emoji\Separated\D83CDF20.png + + + Assets\Emoji\Separated\D83CDF21.png + + + Assets\Emoji\Separated\D83CDF24.png + + + Assets\Emoji\Separated\D83CDF25.png + + + Assets\Emoji\Separated\D83CDF26.png + + + Assets\Emoji\Separated\D83CDF27.png + + + Assets\Emoji\Separated\D83CDF28.png + + + Assets\Emoji\Separated\D83CDF29.png + + + Assets\Emoji\Separated\D83CDF2A.png + + + Assets\Emoji\Separated\D83CDF2B.png + + + Assets\Emoji\Separated\D83CDF2C.png + + + Assets\Emoji\Separated\D83CDF2D.png + + + Assets\Emoji\Separated\D83CDF2E.png + + + Assets\Emoji\Separated\D83CDF2F.png + + + Assets\Emoji\Separated\D83CDF30.png + + + Assets\Emoji\Separated\D83CDF31.png + + + Assets\Emoji\Separated\D83CDF32.png + + + Assets\Emoji\Separated\D83CDF33.png + + + Assets\Emoji\Separated\D83CDF34.png + + + Assets\Emoji\Separated\D83CDF35.png + + + Assets\Emoji\Separated\D83CDF36.png + + + Assets\Emoji\Separated\D83CDF37.png + + + Assets\Emoji\Separated\D83CDF38.png + + + Assets\Emoji\Separated\D83CDF39.png + + + Assets\Emoji\Separated\D83CDF3A.png + + + Assets\Emoji\Separated\D83CDF3B.png + + + Assets\Emoji\Separated\D83CDF3C.png + + + Assets\Emoji\Separated\D83CDF3D.png + + + Assets\Emoji\Separated\D83CDF3E.png + + + Assets\Emoji\Separated\D83CDF3F.png + + + Assets\Emoji\Separated\D83CDF40.png + + + Assets\Emoji\Separated\D83CDF41.png + + + Assets\Emoji\Separated\D83CDF42.png + + + Assets\Emoji\Separated\D83CDF43.png + + + Assets\Emoji\Separated\D83CDF44.png + + + Assets\Emoji\Separated\D83CDF45.png + + + Assets\Emoji\Separated\D83CDF46.png + + + Assets\Emoji\Separated\D83CDF47.png + + + Assets\Emoji\Separated\D83CDF48.png + + + Assets\Emoji\Separated\D83CDF49.png + + + Assets\Emoji\Separated\D83CDF4A.png + + + Assets\Emoji\Separated\D83CDF4B.png + + + Assets\Emoji\Separated\D83CDF4C.png + + + Assets\Emoji\Separated\D83CDF4D.png + + + Assets\Emoji\Separated\D83CDF4E.png + + + Assets\Emoji\Separated\D83CDF4F.png + + + Assets\Emoji\Separated\D83CDF50.png + + + Assets\Emoji\Separated\D83CDF51.png + + + Assets\Emoji\Separated\D83CDF52.png + + + Assets\Emoji\Separated\D83CDF53.png + + + Assets\Emoji\Separated\D83CDF54.png + + + Assets\Emoji\Separated\D83CDF55.png + + + Assets\Emoji\Separated\D83CDF56.png + + + Assets\Emoji\Separated\D83CDF57.png + + + Assets\Emoji\Separated\D83CDF58.png + + + Assets\Emoji\Separated\D83CDF59.png + + + Assets\Emoji\Separated\D83CDF5A.png + + + Assets\Emoji\Separated\D83CDF5B.png + + + Assets\Emoji\Separated\D83CDF5C.png + + + Assets\Emoji\Separated\D83CDF5D.png + + + Assets\Emoji\Separated\D83CDF5E.png + + + Assets\Emoji\Separated\D83CDF5F.png + + + Assets\Emoji\Separated\D83CDF60.png + + + Assets\Emoji\Separated\D83CDF61.png + + + Assets\Emoji\Separated\D83CDF62.png + + + Assets\Emoji\Separated\D83CDF63.png + + + Assets\Emoji\Separated\D83CDF64.png + + + Assets\Emoji\Separated\D83CDF65.png + + + Assets\Emoji\Separated\D83CDF66.png + + + Assets\Emoji\Separated\D83CDF67.png + + + Assets\Emoji\Separated\D83CDF68.png + + + Assets\Emoji\Separated\D83CDF69.png + + + Assets\Emoji\Separated\D83CDF6A.png + + + Assets\Emoji\Separated\D83CDF6B.png + + + Assets\Emoji\Separated\D83CDF6C.png + + + Assets\Emoji\Separated\D83CDF6D.png + + + Assets\Emoji\Separated\D83CDF6E.png + + + Assets\Emoji\Separated\D83CDF6F.png + + + Assets\Emoji\Separated\D83CDF70.png + + + Assets\Emoji\Separated\D83CDF71.png + + + Assets\Emoji\Separated\D83CDF72.png + + + Assets\Emoji\Separated\D83CDF73.png + + + Assets\Emoji\Separated\D83CDF74.png + + + Assets\Emoji\Separated\D83CDF75.png + + + Assets\Emoji\Separated\D83CDF76.png + + + Assets\Emoji\Separated\D83CDF77.png + + + Assets\Emoji\Separated\D83CDF78.png + + + Assets\Emoji\Separated\D83CDF79.png + + + Assets\Emoji\Separated\D83CDF7A.png + + + Assets\Emoji\Separated\D83CDF7B.png + + + Assets\Emoji\Separated\D83CDF7C.png + + + Assets\Emoji\Separated\D83CDF7D.png + + + Assets\Emoji\Separated\D83CDF7E.png + + + Assets\Emoji\Separated\D83CDF7F.png + + + Assets\Emoji\Separated\D83CDF80.png + + + Assets\Emoji\Separated\D83CDF81.png + + + Assets\Emoji\Separated\D83CDF82.png + + + Assets\Emoji\Separated\D83CDF83.png + + + Assets\Emoji\Separated\D83CDF84.png + + + Assets\Emoji\Separated\D83CDF85.png + + + Assets\Emoji\Separated\D83CDF85D83CDFFB.png + + + Assets\Emoji\Separated\D83CDF85D83CDFFC.png + + + Assets\Emoji\Separated\D83CDF85D83CDFFD.png + + + Assets\Emoji\Separated\D83CDF85D83CDFFE.png + + + Assets\Emoji\Separated\D83CDF85D83CDFFF.png + + + Assets\Emoji\Separated\D83CDF86.png + + + Assets\Emoji\Separated\D83CDF87.png + + + Assets\Emoji\Separated\D83CDF88.png + + + Assets\Emoji\Separated\D83CDF89.png + + + Assets\Emoji\Separated\D83CDF8A.png + + + Assets\Emoji\Separated\D83CDF8B.png + + + Assets\Emoji\Separated\D83CDF8C.png + + + Assets\Emoji\Separated\D83CDF8D.png + + + Assets\Emoji\Separated\D83CDF8E.png + + + Assets\Emoji\Separated\D83CDF8F.png + + + Assets\Emoji\Separated\D83CDF90.png + + + Assets\Emoji\Separated\D83CDF91.png + + + Assets\Emoji\Separated\D83CDF92.png + + + Assets\Emoji\Separated\D83CDF93.png + + + Assets\Emoji\Separated\D83CDF96.png + + + Assets\Emoji\Separated\D83CDF97.png + + + Assets\Emoji\Separated\D83CDF99.png + + + Assets\Emoji\Separated\D83CDF9A.png + + + Assets\Emoji\Separated\D83CDF9B.png + + + Assets\Emoji\Separated\D83CDF9E.png + + + Assets\Emoji\Separated\D83CDF9F.png + + + Assets\Emoji\Separated\D83CDFA0.png + + + Assets\Emoji\Separated\D83CDFA1.png + + + Assets\Emoji\Separated\D83CDFA2.png + + + Assets\Emoji\Separated\D83CDFA3.png + + + Assets\Emoji\Separated\D83CDFA4.png + + + Assets\Emoji\Separated\D83CDFA5.png + + + Assets\Emoji\Separated\D83CDFA6.png + + + Assets\Emoji\Separated\D83CDFA7.png + + + Assets\Emoji\Separated\D83CDFA8.png + + + Assets\Emoji\Separated\D83CDFA9.png + + + Assets\Emoji\Separated\D83CDFAA.png + + + Assets\Emoji\Separated\D83CDFAB.png + + + Assets\Emoji\Separated\D83CDFAC.png + + + Assets\Emoji\Separated\D83CDFAD.png + + + Assets\Emoji\Separated\D83CDFAE.png + + + Assets\Emoji\Separated\D83CDFAF.png + + + Assets\Emoji\Separated\D83CDFB0.png + + + Assets\Emoji\Separated\D83CDFB1.png + + + Assets\Emoji\Separated\D83CDFB2.png + + + Assets\Emoji\Separated\D83CDFB3.png + + + Assets\Emoji\Separated\D83CDFB4.png + + + Assets\Emoji\Separated\D83CDFB5.png + + + Assets\Emoji\Separated\D83CDFB6.png + + + Assets\Emoji\Separated\D83CDFB7.png + + + Assets\Emoji\Separated\D83CDFB8.png + + + Assets\Emoji\Separated\D83CDFB9.png + + + Assets\Emoji\Separated\D83CDFBA.png + + + Assets\Emoji\Separated\D83CDFBB.png + + + Assets\Emoji\Separated\D83CDFBC.png + + + Assets\Emoji\Separated\D83CDFBD.png + + + Assets\Emoji\Separated\D83CDFBE.png + + + Assets\Emoji\Separated\D83CDFBF.png + + + Assets\Emoji\Separated\D83CDFC0.png + + + Assets\Emoji\Separated\D83CDFC1.png + + + Assets\Emoji\Separated\D83CDFC2.png + + + Assets\Emoji\Separated\D83CDFC3.png + + + Assets\Emoji\Separated\D83CDFC3200D2640.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFB.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFC.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFD.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFE.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFF.png + + + Assets\Emoji\Separated\D83CDFC3D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83CDFC4.png + + + Assets\Emoji\Separated\D83CDFC4200D2640.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFB.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFC.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFD.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFE.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFF.png + + + Assets\Emoji\Separated\D83CDFC4D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83CDFC5.png + + + Assets\Emoji\Separated\D83CDFC6.png + + + Assets\Emoji\Separated\D83CDFC7.png + + + Assets\Emoji\Separated\D83CDFC7D83CDFFB.png + + + Assets\Emoji\Separated\D83CDFC7D83CDFFC.png + + + Assets\Emoji\Separated\D83CDFC7D83CDFFD.png + + + Assets\Emoji\Separated\D83CDFC7D83CDFFE.png + + + Assets\Emoji\Separated\D83CDFC7D83CDFFF.png + + + Assets\Emoji\Separated\D83CDFC8.png + + + Assets\Emoji\Separated\D83CDFC9.png + + + Assets\Emoji\Separated\D83CDFCA.png + + + Assets\Emoji\Separated\D83CDFCA200D2640.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFB.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFC.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFD.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFE.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFF.png + + + Assets\Emoji\Separated\D83CDFCAD83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83CDFCB.png + + + Assets\Emoji\Separated\D83CDFCB200D2640.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFB.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFC.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFD.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFE.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFF.png + + + Assets\Emoji\Separated\D83CDFCBD83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83CDFCC.png + + + Assets\Emoji\Separated\D83CDFCC200D2640.png + + + Assets\Emoji\Separated\D83CDFCCD83CDFFB.png + + + Assets\Emoji\Separated\D83CDFCCD83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83CDFCCD83CDFFC.png + + + Assets\Emoji\Separated\D83CDFCCD83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83CDFCCD83CDFFD.png + + + Assets\Emoji\Separated\D83CDFCCD83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83CDFCCD83CDFFE.png + + + Assets\Emoji\Separated\D83CDFCCD83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83CDFCCD83CDFFF.png + + + Assets\Emoji\Separated\D83CDFCCD83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83CDFCD.png + + + Assets\Emoji\Separated\D83CDFCE.png + + + Assets\Emoji\Separated\D83CDFCF.png + + + Assets\Emoji\Separated\D83CDFD0.png + + + Assets\Emoji\Separated\D83CDFD1.png + + + Assets\Emoji\Separated\D83CDFD2.png + + + Assets\Emoji\Separated\D83CDFD3.png + + + Assets\Emoji\Separated\D83CDFD4.png + + + Assets\Emoji\Separated\D83CDFD5.png + + + Assets\Emoji\Separated\D83CDFD6.png + + + Assets\Emoji\Separated\D83CDFD7.png + + + Assets\Emoji\Separated\D83CDFD8.png + + + Assets\Emoji\Separated\D83CDFD9.png + + + Assets\Emoji\Separated\D83CDFDA.png + + + Assets\Emoji\Separated\D83CDFDB.png + + + Assets\Emoji\Separated\D83CDFDC.png + + + Assets\Emoji\Separated\D83CDFDD.png + + + Assets\Emoji\Separated\D83CDFDE.png + + + Assets\Emoji\Separated\D83CDFDF.png + + + Assets\Emoji\Separated\D83CDFE0.png + + + Assets\Emoji\Separated\D83CDFE1.png + + + Assets\Emoji\Separated\D83CDFE2.png + + + Assets\Emoji\Separated\D83CDFE3.png + + + Assets\Emoji\Separated\D83CDFE4.png + + + Assets\Emoji\Separated\D83CDFE5.png + + + Assets\Emoji\Separated\D83CDFE6.png + + + Assets\Emoji\Separated\D83CDFE7.png + + + Assets\Emoji\Separated\D83CDFE8.png + + + Assets\Emoji\Separated\D83CDFE9.png + + + Assets\Emoji\Separated\D83CDFEA.png + + + Assets\Emoji\Separated\D83CDFEB.png + + + Assets\Emoji\Separated\D83CDFEC.png + + + Assets\Emoji\Separated\D83CDFED.png + + + Assets\Emoji\Separated\D83CDFEE.png + + + Assets\Emoji\Separated\D83CDFEF.png + + + Assets\Emoji\Separated\D83CDFF0.png + + + Assets\Emoji\Separated\D83CDFF3.png + + + Assets\Emoji\Separated\D83CDFF3200DD83CDF08.png + + + Assets\Emoji\Separated\D83CDFF4.png + + + Assets\Emoji\Separated\D83CDFF5.png + + + Assets\Emoji\Separated\D83CDFF7.png + + + Assets\Emoji\Separated\D83CDFF8.png + + + Assets\Emoji\Separated\D83CDFF9.png + + + Assets\Emoji\Separated\D83CDFFA.png + + + Assets\Emoji\Separated\D83DDC00.png + + + Assets\Emoji\Separated\D83DDC01.png + + + Assets\Emoji\Separated\D83DDC02.png + + + Assets\Emoji\Separated\D83DDC03.png + + + Assets\Emoji\Separated\D83DDC04.png + + + Assets\Emoji\Separated\D83DDC05.png + + + Assets\Emoji\Separated\D83DDC06.png + + + Assets\Emoji\Separated\D83DDC07.png + + + Assets\Emoji\Separated\D83DDC08.png + + + Assets\Emoji\Separated\D83DDC09.png + + + Assets\Emoji\Separated\D83DDC0A.png + + + Assets\Emoji\Separated\D83DDC0B.png + + + Assets\Emoji\Separated\D83DDC0C.png + + + Assets\Emoji\Separated\D83DDC0D.png + + + Assets\Emoji\Separated\D83DDC0E.png + + + Assets\Emoji\Separated\D83DDC0F.png + + + Assets\Emoji\Separated\D83DDC10.png + + + Assets\Emoji\Separated\D83DDC11.png + + + Assets\Emoji\Separated\D83DDC12.png + + + Assets\Emoji\Separated\D83DDC13.png + + + Assets\Emoji\Separated\D83DDC14.png + + + Assets\Emoji\Separated\D83DDC15.png + + + Assets\Emoji\Separated\D83DDC16.png + + + Assets\Emoji\Separated\D83DDC17.png + + + Assets\Emoji\Separated\D83DDC18.png + + + Assets\Emoji\Separated\D83DDC19.png + + + Assets\Emoji\Separated\D83DDC1A.png + + + Assets\Emoji\Separated\D83DDC1B.png + + + Assets\Emoji\Separated\D83DDC1C.png + + + Assets\Emoji\Separated\D83DDC1D.png + + + Assets\Emoji\Separated\D83DDC1E.png + + + Assets\Emoji\Separated\D83DDC1F.png + + + Assets\Emoji\Separated\D83DDC20.png + + + Assets\Emoji\Separated\D83DDC21.png + + + Assets\Emoji\Separated\D83DDC22.png + + + Assets\Emoji\Separated\D83DDC23.png + + + Assets\Emoji\Separated\D83DDC24.png + + + Assets\Emoji\Separated\D83DDC25.png + + + Assets\Emoji\Separated\D83DDC26.png + + + Assets\Emoji\Separated\D83DDC27.png + + + Assets\Emoji\Separated\D83DDC28.png + + + Assets\Emoji\Separated\D83DDC29.png + + + Assets\Emoji\Separated\D83DDC2A.png + + + Assets\Emoji\Separated\D83DDC2B.png + + + Assets\Emoji\Separated\D83DDC2C.png + + + Assets\Emoji\Separated\D83DDC2D.png + + + Assets\Emoji\Separated\D83DDC2E.png + + + Assets\Emoji\Separated\D83DDC2F.png + + + Assets\Emoji\Separated\D83DDC30.png + + + Assets\Emoji\Separated\D83DDC31.png + + + Assets\Emoji\Separated\D83DDC32.png + + + Assets\Emoji\Separated\D83DDC33.png + + + Assets\Emoji\Separated\D83DDC34.png + + + Assets\Emoji\Separated\D83DDC35.png + + + Assets\Emoji\Separated\D83DDC36.png + + + Assets\Emoji\Separated\D83DDC37.png + + + Assets\Emoji\Separated\D83DDC38.png + + + Assets\Emoji\Separated\D83DDC39.png + + + Assets\Emoji\Separated\D83DDC3A.png + + + Assets\Emoji\Separated\D83DDC3B.png + + + Assets\Emoji\Separated\D83DDC3C.png + + + Assets\Emoji\Separated\D83DDC3D.png + + + Assets\Emoji\Separated\D83DDC3E.png + + + Assets\Emoji\Separated\D83DDC3F.png + + + Assets\Emoji\Separated\D83DDC40.png + + + Assets\Emoji\Separated\D83DDC41.png + + + Assets\Emoji\Separated\D83DDC41200DD83DDDE8.png + + + Assets\Emoji\Separated\D83DDC42.png + + + Assets\Emoji\Separated\D83DDC42D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC42D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC42D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC42D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC42D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC43.png + + + Assets\Emoji\Separated\D83DDC43D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC43D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC43D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC43D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC43D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC44.png + + + Assets\Emoji\Separated\D83DDC45.png + + + Assets\Emoji\Separated\D83DDC46.png + + + Assets\Emoji\Separated\D83DDC46D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC46D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC46D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC46D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC46D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC47.png + + + Assets\Emoji\Separated\D83DDC47D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC47D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC47D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC47D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC47D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC48.png + + + Assets\Emoji\Separated\D83DDC48D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC48D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC48D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC48D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC48D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC49.png + + + Assets\Emoji\Separated\D83DDC49D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC49D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC49D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC49D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC49D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC4A.png + + + Assets\Emoji\Separated\D83DDC4AD83CDFFB.png + + + Assets\Emoji\Separated\D83DDC4AD83CDFFC.png + + + Assets\Emoji\Separated\D83DDC4AD83CDFFD.png + + + Assets\Emoji\Separated\D83DDC4AD83CDFFE.png + + + Assets\Emoji\Separated\D83DDC4AD83CDFFF.png + + + Assets\Emoji\Separated\D83DDC4B.png + + + Assets\Emoji\Separated\D83DDC4BD83CDFFB.png + + + Assets\Emoji\Separated\D83DDC4BD83CDFFC.png + + + Assets\Emoji\Separated\D83DDC4BD83CDFFD.png + + + Assets\Emoji\Separated\D83DDC4BD83CDFFE.png + + + Assets\Emoji\Separated\D83DDC4BD83CDFFF.png + + + Assets\Emoji\Separated\D83DDC4C.png + + + Assets\Emoji\Separated\D83DDC4CD83CDFFB.png + + + Assets\Emoji\Separated\D83DDC4CD83CDFFC.png + + + Assets\Emoji\Separated\D83DDC4CD83CDFFD.png + + + Assets\Emoji\Separated\D83DDC4CD83CDFFE.png + + + Assets\Emoji\Separated\D83DDC4CD83CDFFF.png + + + Assets\Emoji\Separated\D83DDC4D.png + + + Assets\Emoji\Separated\D83DDC4DD83CDFFB.png + + + Assets\Emoji\Separated\D83DDC4DD83CDFFC.png + + + Assets\Emoji\Separated\D83DDC4DD83CDFFD.png + + + Assets\Emoji\Separated\D83DDC4DD83CDFFE.png + + + Assets\Emoji\Separated\D83DDC4DD83CDFFF.png + + + Assets\Emoji\Separated\D83DDC4E.png + + + Assets\Emoji\Separated\D83DDC4ED83CDFFB.png + + + Assets\Emoji\Separated\D83DDC4ED83CDFFC.png + + + Assets\Emoji\Separated\D83DDC4ED83CDFFD.png + + + Assets\Emoji\Separated\D83DDC4ED83CDFFE.png + + + Assets\Emoji\Separated\D83DDC4ED83CDFFF.png + + + Assets\Emoji\Separated\D83DDC4F.png + + + Assets\Emoji\Separated\D83DDC4FD83CDFFB.png + + + Assets\Emoji\Separated\D83DDC4FD83CDFFC.png + + + Assets\Emoji\Separated\D83DDC4FD83CDFFD.png + + + Assets\Emoji\Separated\D83DDC4FD83CDFFE.png + + + Assets\Emoji\Separated\D83DDC4FD83CDFFF.png + + + Assets\Emoji\Separated\D83DDC50.png + + + Assets\Emoji\Separated\D83DDC50D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC50D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC50D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC50D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC50D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC51.png + + + Assets\Emoji\Separated\D83DDC52.png + + + Assets\Emoji\Separated\D83DDC53.png + + + Assets\Emoji\Separated\D83DDC54.png + + + Assets\Emoji\Separated\D83DDC55.png + + + Assets\Emoji\Separated\D83DDC56.png + + + Assets\Emoji\Separated\D83DDC57.png + + + Assets\Emoji\Separated\D83DDC58.png + + + Assets\Emoji\Separated\D83DDC59.png + + + Assets\Emoji\Separated\D83DDC5A.png + + + Assets\Emoji\Separated\D83DDC5B.png + + + Assets\Emoji\Separated\D83DDC5C.png + + + Assets\Emoji\Separated\D83DDC5D.png + + + Assets\Emoji\Separated\D83DDC5E.png + + + Assets\Emoji\Separated\D83DDC5F.png + + + Assets\Emoji\Separated\D83DDC60.png + + + Assets\Emoji\Separated\D83DDC61.png + + + Assets\Emoji\Separated\D83DDC62.png + + + Assets\Emoji\Separated\D83DDC63.png + + + Assets\Emoji\Separated\D83DDC64.png + + + Assets\Emoji\Separated\D83DDC65.png + + + Assets\Emoji\Separated\D83DDC66.png + + + Assets\Emoji\Separated\D83DDC66D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC66D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC66D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC66D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC66D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC67.png + + + Assets\Emoji\Separated\D83DDC67D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC67D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC67D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC67D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC67D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC68.png + + + Assets\Emoji\Separated\D83DDC68200D2695.png + + + Assets\Emoji\Separated\D83DDC68200D2696.png + + + Assets\Emoji\Separated\D83DDC68200D2708.png + + + Assets\Emoji\Separated\D83DDC68200D2764200DD83DDC68.png + + + Assets\Emoji\Separated\D83DDC68200D2764200DD83DDC8B200DD83DDC68.png + + + Assets\Emoji\Separated\D83DDC68200D2764FE0F200DD83DDC68.png + + + Assets\Emoji\Separated\D83DDC68200D2764FE0F200DD83DDC8B200DD83DDC68.png + + + Assets\Emoji\Separated\D83DDC68200DD83CDF3E.png + + + Assets\Emoji\Separated\D83DDC68200DD83CDF73.png + + + Assets\Emoji\Separated\D83DDC68200DD83CDF93.png + + + Assets\Emoji\Separated\D83DDC68200DD83CDFA4.png + + + Assets\Emoji\Separated\D83DDC68200DD83CDFA8.png + + + Assets\Emoji\Separated\D83DDC68200DD83CDFEB.png + + + Assets\Emoji\Separated\D83DDC68200DD83CDFED.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC66200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC67.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC67200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC67200DD83DDC67.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC68200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC68200DD83DDC66200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC68200DD83DDC67.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC68200DD83DDC67200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC68200DD83DDC67200DD83DDC67.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC69200DD83DDC66200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC69200DD83DDC67.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC69200DD83DDC67200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDC69200DD83DDC67200DD83DDC67.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDCBB.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDCBC.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDD27.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDD2C.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDE80.png + + + Assets\Emoji\Separated\D83DDC68200DD83DDE92.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200D2695.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200D2696.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200D2708.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83CDF3E.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83CDF73.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83CDF93.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83CDFA4.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83CDFA8.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83CDFEB.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83CDFED.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83DDCBB.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83DDCBC.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83DDD27.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83DDD2C.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83DDE80.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFB200DD83DDE92.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200D2695.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200D2696.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200D2708.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83CDF3E.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83CDF73.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83CDF93.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83CDFA4.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83CDFA8.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83CDFEB.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83CDFED.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83DDCBB.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83DDCBC.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83DDD27.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83DDD2C.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83DDE80.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFC200DD83DDE92.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200D2695.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200D2696.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200D2708.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83CDF3E.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83CDF73.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83CDF93.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83CDFA4.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83CDFA8.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83CDFEB.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83CDFED.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83DDCBB.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83DDCBC.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83DDD27.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83DDD2C.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83DDE80.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFD200DD83DDE92.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200D2695.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200D2696.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200D2708.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83CDF3E.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83CDF73.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83CDF93.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83CDFA4.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83CDFA8.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83CDFEB.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83CDFED.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83DDCBB.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83DDCBC.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83DDD27.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83DDD2C.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83DDE80.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFE200DD83DDE92.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200D2695.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200D2696.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200D2708.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83CDF3E.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83CDF73.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83CDF93.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83CDFA4.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83CDFA8.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83CDFEB.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83CDFED.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83DDCBB.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83DDCBC.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83DDD27.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83DDD2C.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83DDE80.png + + + Assets\Emoji\Separated\D83DDC68D83CDFFF200DD83DDE92.png + + + Assets\Emoji\Separated\D83DDC69.png + + + Assets\Emoji\Separated\D83DDC69200D2695.png + + + Assets\Emoji\Separated\D83DDC69200D2696.png + + + Assets\Emoji\Separated\D83DDC69200D2708.png + + + Assets\Emoji\Separated\D83DDC69200D2764200DD83DDC69.png + + + Assets\Emoji\Separated\D83DDC69200D2764200DD83DDC8B200DD83DDC69.png + + + Assets\Emoji\Separated\D83DDC69200D2764FE0F200DD83DDC69.png + + + Assets\Emoji\Separated\D83DDC69200D2764FE0F200DD83DDC8B200DD83DDC69.png + + + Assets\Emoji\Separated\D83DDC69200DD83CDF3E.png + + + Assets\Emoji\Separated\D83DDC69200DD83CDF73.png + + + Assets\Emoji\Separated\D83DDC69200DD83CDF93.png + + + Assets\Emoji\Separated\D83DDC69200DD83CDFA4.png + + + Assets\Emoji\Separated\D83DDC69200DD83CDFA8.png + + + Assets\Emoji\Separated\D83DDC69200DD83CDFEB.png + + + Assets\Emoji\Separated\D83DDC69200DD83CDFED.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDC66200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDC67.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDC67200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDC67200DD83DDC67.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDC69200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDC69200DD83DDC66200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDC69200DD83DDC67.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDC69200DD83DDC67200DD83DDC66.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDC69200DD83DDC67200DD83DDC67.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDCBB.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDCBC.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDD27.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDD2C.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDE80.png + + + Assets\Emoji\Separated\D83DDC69200DD83DDE92.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200D2695.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200D2696.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200D2708.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83CDF3E.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83CDF73.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83CDF93.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83CDFA4.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83CDFA8.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83CDFEB.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83CDFED.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83DDCBB.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83DDCBC.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83DDD27.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83DDD2C.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83DDE80.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFB200DD83DDE92.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200D2695.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200D2696.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200D2708.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83CDF3E.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83CDF73.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83CDF93.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83CDFA4.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83CDFA8.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83CDFEB.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83CDFED.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83DDCBB.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83DDCBC.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83DDD27.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83DDD2C.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83DDE80.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFC200DD83DDE92.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200D2695.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200D2696.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200D2708.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83CDF3E.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83CDF73.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83CDF93.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83CDFA4.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83CDFA8.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83CDFEB.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83CDFED.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83DDCBB.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83DDCBC.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83DDD27.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83DDD2C.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83DDE80.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFD200DD83DDE92.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200D2695.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200D2696.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200D2708.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83CDF3E.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83CDF73.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83CDF93.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83CDFA4.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83CDFA8.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83CDFEB.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83CDFED.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83DDCBB.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83DDCBC.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83DDD27.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83DDD2C.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83DDE80.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFE200DD83DDE92.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200D2695.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200D2696.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200D2708.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83CDF3E.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83CDF73.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83CDF93.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83CDFA4.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83CDFA8.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83CDFEB.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83CDFED.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83DDCBB.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83DDCBC.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83DDD27.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83DDD2C.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83DDE80.png + + + Assets\Emoji\Separated\D83DDC69D83CDFFF200DD83DDE92.png + + + Assets\Emoji\Separated\D83DDC6A.png + + + Assets\Emoji\Separated\D83DDC6B.png + + + Assets\Emoji\Separated\D83DDC6C.png + + + Assets\Emoji\Separated\D83DDC6D.png + + + Assets\Emoji\Separated\D83DDC6E.png + + + Assets\Emoji\Separated\D83DDC6E200D2640.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFB.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFC.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFD.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFE.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFF.png + + + Assets\Emoji\Separated\D83DDC6ED83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83DDC6F.png + + + Assets\Emoji\Separated\D83DDC6F200D2642.png + + + Assets\Emoji\Separated\D83DDC70.png + + + Assets\Emoji\Separated\D83DDC70D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC70D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC70D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC70D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC70D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC71.png + + + Assets\Emoji\Separated\D83DDC71200D2640.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC71D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83DDC72.png + + + Assets\Emoji\Separated\D83DDC72D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC72D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC72D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC72D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC72D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC73.png + + + Assets\Emoji\Separated\D83DDC73200D2640.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC73D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83DDC74.png + + + Assets\Emoji\Separated\D83DDC74D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC74D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC74D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC74D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC74D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC75.png + + + Assets\Emoji\Separated\D83DDC75D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC75D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC75D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC75D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC75D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC76.png + + + Assets\Emoji\Separated\D83DDC76D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC76D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC76D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC76D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC76D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC77.png + + + Assets\Emoji\Separated\D83DDC77200D2640.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC77D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83DDC78.png + + + Assets\Emoji\Separated\D83DDC78D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC78D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC78D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC78D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC78D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC79.png + + + Assets\Emoji\Separated\D83DDC7A.png + + + Assets\Emoji\Separated\D83DDC7B.png + + + Assets\Emoji\Separated\D83DDC7C.png + + + Assets\Emoji\Separated\D83DDC7CD83CDFFB.png + + + Assets\Emoji\Separated\D83DDC7CD83CDFFC.png + + + Assets\Emoji\Separated\D83DDC7CD83CDFFD.png + + + Assets\Emoji\Separated\D83DDC7CD83CDFFE.png + + + Assets\Emoji\Separated\D83DDC7CD83CDFFF.png + + + Assets\Emoji\Separated\D83DDC7D.png + + + Assets\Emoji\Separated\D83DDC7E.png + + + Assets\Emoji\Separated\D83DDC7F.png + + + Assets\Emoji\Separated\D83DDC80.png + + + Assets\Emoji\Separated\D83DDC81.png + + + Assets\Emoji\Separated\D83DDC81200D2642.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC81D83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83DDC82.png + + + Assets\Emoji\Separated\D83DDC82200D2640.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC82D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83DDC83.png + + + Assets\Emoji\Separated\D83DDC83D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC83D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC83D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC83D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC83D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC84.png + + + Assets\Emoji\Separated\D83DDC85.png + + + Assets\Emoji\Separated\D83DDC85D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC85D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC85D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC85D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC85D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC86.png + + + Assets\Emoji\Separated\D83DDC86200D2642.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC86D83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83DDC87.png + + + Assets\Emoji\Separated\D83DDC87200D2642.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFB.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFC.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFD.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFE.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFF.png + + + Assets\Emoji\Separated\D83DDC87D83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83DDC88.png + + + Assets\Emoji\Separated\D83DDC89.png + + + Assets\Emoji\Separated\D83DDC8A.png + + + Assets\Emoji\Separated\D83DDC8B.png + + + Assets\Emoji\Separated\D83DDC8C.png + + + Assets\Emoji\Separated\D83DDC8D.png + + + Assets\Emoji\Separated\D83DDC8E.png + + + Assets\Emoji\Separated\D83DDC8F.png + + + Assets\Emoji\Separated\D83DDC90.png + + + Assets\Emoji\Separated\D83DDC91.png + + + Assets\Emoji\Separated\D83DDC92.png + + + Assets\Emoji\Separated\D83DDC93.png + + + Assets\Emoji\Separated\D83DDC94.png + + + Assets\Emoji\Separated\D83DDC95.png + + + Assets\Emoji\Separated\D83DDC96.png + + + Assets\Emoji\Separated\D83DDC97.png + + + Assets\Emoji\Separated\D83DDC98.png + + + Assets\Emoji\Separated\D83DDC99.png + + + Assets\Emoji\Separated\D83DDC9A.png + + + Assets\Emoji\Separated\D83DDC9B.png + + + Assets\Emoji\Separated\D83DDC9C.png + + + Assets\Emoji\Separated\D83DDC9D.png + + + Assets\Emoji\Separated\D83DDC9E.png + + + Assets\Emoji\Separated\D83DDC9F.png + + + Assets\Emoji\Separated\D83DDCA0.png + + + Assets\Emoji\Separated\D83DDCA1.png + + + Assets\Emoji\Separated\D83DDCA2.png + + + Assets\Emoji\Separated\D83DDCA3.png + + + Assets\Emoji\Separated\D83DDCA4.png + + + Assets\Emoji\Separated\D83DDCA5.png + + + Assets\Emoji\Separated\D83DDCA6.png + + + Assets\Emoji\Separated\D83DDCA7.png + + + Assets\Emoji\Separated\D83DDCA8.png + + + Assets\Emoji\Separated\D83DDCA9.png + + + Assets\Emoji\Separated\D83DDCAA.png + + + Assets\Emoji\Separated\D83DDCAAD83CDFFB.png + + + Assets\Emoji\Separated\D83DDCAAD83CDFFC.png + + + Assets\Emoji\Separated\D83DDCAAD83CDFFD.png + + + Assets\Emoji\Separated\D83DDCAAD83CDFFE.png + + + Assets\Emoji\Separated\D83DDCAAD83CDFFF.png + + + Assets\Emoji\Separated\D83DDCAB.png + + + Assets\Emoji\Separated\D83DDCAC.png + + + Assets\Emoji\Separated\D83DDCAD.png + + + Assets\Emoji\Separated\D83DDCAE.png + + + Assets\Emoji\Separated\D83DDCAF.png + + + Assets\Emoji\Separated\D83DDCB0.png + + + Assets\Emoji\Separated\D83DDCB1.png + + + Assets\Emoji\Separated\D83DDCB2.png + + + Assets\Emoji\Separated\D83DDCB3.png + + + Assets\Emoji\Separated\D83DDCB4.png + + + Assets\Emoji\Separated\D83DDCB5.png + + + Assets\Emoji\Separated\D83DDCB6.png + + + Assets\Emoji\Separated\D83DDCB7.png + + + Assets\Emoji\Separated\D83DDCB8.png + + + Assets\Emoji\Separated\D83DDCB9.png + + + Assets\Emoji\Separated\D83DDCBA.png + + + Assets\Emoji\Separated\D83DDCBB.png + + + Assets\Emoji\Separated\D83DDCBC.png + + + Assets\Emoji\Separated\D83DDCBD.png + + + Assets\Emoji\Separated\D83DDCBE.png + + + Assets\Emoji\Separated\D83DDCBF.png + + + Assets\Emoji\Separated\D83DDCC0.png + + + Assets\Emoji\Separated\D83DDCC1.png + + + Assets\Emoji\Separated\D83DDCC2.png + + + Assets\Emoji\Separated\D83DDCC3.png + + + Assets\Emoji\Separated\D83DDCC4.png + + + Assets\Emoji\Separated\D83DDCC5.png + + + Assets\Emoji\Separated\D83DDCC6.png + + + Assets\Emoji\Separated\D83DDCC7.png + + + Assets\Emoji\Separated\D83DDCC8.png + + + Assets\Emoji\Separated\D83DDCC9.png + + + Assets\Emoji\Separated\D83DDCCA.png + + + Assets\Emoji\Separated\D83DDCCB.png + + + Assets\Emoji\Separated\D83DDCCC.png + + + Assets\Emoji\Separated\D83DDCCD.png + + + Assets\Emoji\Separated\D83DDCCE.png + + + Assets\Emoji\Separated\D83DDCCF.png + + + Assets\Emoji\Separated\D83DDCD0.png + + + Assets\Emoji\Separated\D83DDCD1.png + + + Assets\Emoji\Separated\D83DDCD2.png + + + Assets\Emoji\Separated\D83DDCD3.png + + + Assets\Emoji\Separated\D83DDCD4.png + + + Assets\Emoji\Separated\D83DDCD5.png + + + Assets\Emoji\Separated\D83DDCD6.png + + + Assets\Emoji\Separated\D83DDCD7.png + + + Assets\Emoji\Separated\D83DDCD8.png + + + Assets\Emoji\Separated\D83DDCD9.png + + + Assets\Emoji\Separated\D83DDCDA.png + + + Assets\Emoji\Separated\D83DDCDB.png + + + Assets\Emoji\Separated\D83DDCDC.png + + + Assets\Emoji\Separated\D83DDCDD.png + + + Assets\Emoji\Separated\D83DDCDE.png + + + Assets\Emoji\Separated\D83DDCDF.png + + + Assets\Emoji\Separated\D83DDCE0.png + + + Assets\Emoji\Separated\D83DDCE1.png + + + Assets\Emoji\Separated\D83DDCE2.png + + + Assets\Emoji\Separated\D83DDCE3.png + + + Assets\Emoji\Separated\D83DDCE4.png + + + Assets\Emoji\Separated\D83DDCE5.png + + + Assets\Emoji\Separated\D83DDCE6.png + + + Assets\Emoji\Separated\D83DDCE7.png + + + Assets\Emoji\Separated\D83DDCE8.png + + + Assets\Emoji\Separated\D83DDCE9.png + + + Assets\Emoji\Separated\D83DDCEA.png + + + Assets\Emoji\Separated\D83DDCEB.png + + + Assets\Emoji\Separated\D83DDCEC.png + + + Assets\Emoji\Separated\D83DDCED.png + + + Assets\Emoji\Separated\D83DDCEE.png + + + Assets\Emoji\Separated\D83DDCEF.png + + + Assets\Emoji\Separated\D83DDCF0.png + + + Assets\Emoji\Separated\D83DDCF1.png + + + Assets\Emoji\Separated\D83DDCF2.png + + + Assets\Emoji\Separated\D83DDCF3.png + + + Assets\Emoji\Separated\D83DDCF4.png + + + Assets\Emoji\Separated\D83DDCF5.png + + + Assets\Emoji\Separated\D83DDCF6.png + + + Assets\Emoji\Separated\D83DDCF7.png + + + Assets\Emoji\Separated\D83DDCF8.png + + + Assets\Emoji\Separated\D83DDCF9.png + + + Assets\Emoji\Separated\D83DDCFA.png + + + Assets\Emoji\Separated\D83DDCFB.png + + + Assets\Emoji\Separated\D83DDCFC.png + + + Assets\Emoji\Separated\D83DDCFD.png + + + Assets\Emoji\Separated\D83DDCFF.png + + + Assets\Emoji\Separated\D83DDD00.png + + + Assets\Emoji\Separated\D83DDD01.png + + + Assets\Emoji\Separated\D83DDD02.png + + + Assets\Emoji\Separated\D83DDD03.png + + + Assets\Emoji\Separated\D83DDD04.png + + + Assets\Emoji\Separated\D83DDD05.png + + + Assets\Emoji\Separated\D83DDD06.png + + + Assets\Emoji\Separated\D83DDD07.png + + + Assets\Emoji\Separated\D83DDD08.png + + + Assets\Emoji\Separated\D83DDD09.png + + + Assets\Emoji\Separated\D83DDD0A.png + + + Assets\Emoji\Separated\D83DDD0B.png + + + Assets\Emoji\Separated\D83DDD0C.png + + + Assets\Emoji\Separated\D83DDD0D.png + + + Assets\Emoji\Separated\D83DDD0E.png + + + Assets\Emoji\Separated\D83DDD0F.png + + + Assets\Emoji\Separated\D83DDD10.png + + + Assets\Emoji\Separated\D83DDD11.png + + + Assets\Emoji\Separated\D83DDD12.png + + + Assets\Emoji\Separated\D83DDD13.png + + + Assets\Emoji\Separated\D83DDD14.png + + + Assets\Emoji\Separated\D83DDD15.png + + + Assets\Emoji\Separated\D83DDD16.png + + + Assets\Emoji\Separated\D83DDD17.png + + + Assets\Emoji\Separated\D83DDD18.png + + + Assets\Emoji\Separated\D83DDD19.png + + + Assets\Emoji\Separated\D83DDD1A.png + + + Assets\Emoji\Separated\D83DDD1B.png + + + Assets\Emoji\Separated\D83DDD1C.png + + + Assets\Emoji\Separated\D83DDD1D.png + + + Assets\Emoji\Separated\D83DDD1E.png + + + Assets\Emoji\Separated\D83DDD1F.png + + + Assets\Emoji\Separated\D83DDD20.png + + + Assets\Emoji\Separated\D83DDD21.png + + + Assets\Emoji\Separated\D83DDD22.png + + + Assets\Emoji\Separated\D83DDD23.png + + + Assets\Emoji\Separated\D83DDD24.png + + + Assets\Emoji\Separated\D83DDD25.png + + + Assets\Emoji\Separated\D83DDD26.png + + + Assets\Emoji\Separated\D83DDD27.png + + + Assets\Emoji\Separated\D83DDD28.png + + + Assets\Emoji\Separated\D83DDD29.png + + + Assets\Emoji\Separated\D83DDD2A.png + + + Assets\Emoji\Separated\D83DDD2B.png + + + Assets\Emoji\Separated\D83DDD2C.png + + + Assets\Emoji\Separated\D83DDD2D.png + + + Assets\Emoji\Separated\D83DDD2E.png + + + Assets\Emoji\Separated\D83DDD2F.png + + + Assets\Emoji\Separated\D83DDD30.png + + + Assets\Emoji\Separated\D83DDD31.png + + + Assets\Emoji\Separated\D83DDD32.png + + + Assets\Emoji\Separated\D83DDD33.png + + + Assets\Emoji\Separated\D83DDD34.png + + + Assets\Emoji\Separated\D83DDD35.png + + + Assets\Emoji\Separated\D83DDD36.png + + + Assets\Emoji\Separated\D83DDD37.png + + + Assets\Emoji\Separated\D83DDD38.png + + + Assets\Emoji\Separated\D83DDD39.png + + + Assets\Emoji\Separated\D83DDD3A.png + + + Assets\Emoji\Separated\D83DDD3B.png + + + Assets\Emoji\Separated\D83DDD3C.png + + + Assets\Emoji\Separated\D83DDD3D.png + + + Assets\Emoji\Separated\D83DDD49.png + + + Assets\Emoji\Separated\D83DDD4A.png + + + Assets\Emoji\Separated\D83DDD4B.png + + + Assets\Emoji\Separated\D83DDD4C.png + + + Assets\Emoji\Separated\D83DDD4D.png + + + Assets\Emoji\Separated\D83DDD4E.png + + + Assets\Emoji\Separated\D83DDD50.png + + + Assets\Emoji\Separated\D83DDD51.png + + + Assets\Emoji\Separated\D83DDD52.png + + + Assets\Emoji\Separated\D83DDD53.png + + + Assets\Emoji\Separated\D83DDD54.png + + + Assets\Emoji\Separated\D83DDD55.png + + + Assets\Emoji\Separated\D83DDD56.png + + + Assets\Emoji\Separated\D83DDD57.png + + + Assets\Emoji\Separated\D83DDD58.png + + + Assets\Emoji\Separated\D83DDD59.png + + + Assets\Emoji\Separated\D83DDD5A.png + + + Assets\Emoji\Separated\D83DDD5B.png + + + Assets\Emoji\Separated\D83DDD5C.png + + + Assets\Emoji\Separated\D83DDD5D.png + + + Assets\Emoji\Separated\D83DDD5E.png + + + Assets\Emoji\Separated\D83DDD5F.png + + + Assets\Emoji\Separated\D83DDD60.png + + + Assets\Emoji\Separated\D83DDD61.png + + + Assets\Emoji\Separated\D83DDD62.png + + + Assets\Emoji\Separated\D83DDD63.png + + + Assets\Emoji\Separated\D83DDD64.png + + + Assets\Emoji\Separated\D83DDD65.png + + + Assets\Emoji\Separated\D83DDD66.png + + + Assets\Emoji\Separated\D83DDD67.png + + + Assets\Emoji\Separated\D83DDD6F.png + + + Assets\Emoji\Separated\D83DDD70.png + + + Assets\Emoji\Separated\D83DDD73.png + + + Assets\Emoji\Separated\D83DDD74.png + + + Assets\Emoji\Separated\D83DDD74D83CDFFB.png + + + Assets\Emoji\Separated\D83DDD74D83CDFFC.png + + + Assets\Emoji\Separated\D83DDD74D83CDFFD.png + + + Assets\Emoji\Separated\D83DDD74D83CDFFE.png + + + Assets\Emoji\Separated\D83DDD74D83CDFFF.png + + + Assets\Emoji\Separated\D83DDD75.png + + + Assets\Emoji\Separated\D83DDD75200D2640.png + + + Assets\Emoji\Separated\D83DDD75D83CDFFB.png + + + Assets\Emoji\Separated\D83DDD75D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83DDD75D83CDFFC.png + + + Assets\Emoji\Separated\D83DDD75D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83DDD75D83CDFFD.png + + + Assets\Emoji\Separated\D83DDD75D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83DDD75D83CDFFE.png + + + Assets\Emoji\Separated\D83DDD75D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83DDD75D83CDFFF.png + + + Assets\Emoji\Separated\D83DDD75D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83DDD76.png + + + Assets\Emoji\Separated\D83DDD77.png + + + Assets\Emoji\Separated\D83DDD78.png + + + Assets\Emoji\Separated\D83DDD79.png + + + Assets\Emoji\Separated\D83DDD7A.png + + + Assets\Emoji\Separated\D83DDD7AD83CDFFB.png + + + Assets\Emoji\Separated\D83DDD7AD83CDFFC.png + + + Assets\Emoji\Separated\D83DDD7AD83CDFFD.png + + + Assets\Emoji\Separated\D83DDD7AD83CDFFE.png + + + Assets\Emoji\Separated\D83DDD7AD83CDFFF.png + + + Assets\Emoji\Separated\D83DDD87.png + + + Assets\Emoji\Separated\D83DDD8A.png + + + Assets\Emoji\Separated\D83DDD8B.png + + + Assets\Emoji\Separated\D83DDD8C.png + + + Assets\Emoji\Separated\D83DDD8D.png + + + Assets\Emoji\Separated\D83DDD90.png + + + Assets\Emoji\Separated\D83DDD90D83CDFFB.png + + + Assets\Emoji\Separated\D83DDD90D83CDFFC.png + + + Assets\Emoji\Separated\D83DDD90D83CDFFD.png + + + Assets\Emoji\Separated\D83DDD90D83CDFFE.png + + + Assets\Emoji\Separated\D83DDD90D83CDFFF.png + + + Assets\Emoji\Separated\D83DDD95.png + + + Assets\Emoji\Separated\D83DDD95D83CDFFB.png + + + Assets\Emoji\Separated\D83DDD95D83CDFFC.png + + + Assets\Emoji\Separated\D83DDD95D83CDFFD.png + + + Assets\Emoji\Separated\D83DDD95D83CDFFE.png + + + Assets\Emoji\Separated\D83DDD95D83CDFFF.png + + + Assets\Emoji\Separated\D83DDD96.png + + + Assets\Emoji\Separated\D83DDD96D83CDFFB.png + + + Assets\Emoji\Separated\D83DDD96D83CDFFC.png + + + Assets\Emoji\Separated\D83DDD96D83CDFFD.png + + + Assets\Emoji\Separated\D83DDD96D83CDFFE.png + + + Assets\Emoji\Separated\D83DDD96D83CDFFF.png + + + Assets\Emoji\Separated\D83DDDA4.png + + + Assets\Emoji\Separated\D83DDDA5.png + + + Assets\Emoji\Separated\D83DDDA8.png + + + Assets\Emoji\Separated\D83DDDB1.png + + + Assets\Emoji\Separated\D83DDDB2.png + + + Assets\Emoji\Separated\D83DDDBC.png + + + Assets\Emoji\Separated\D83DDDC2.png + + + Assets\Emoji\Separated\D83DDDC3.png + + + Assets\Emoji\Separated\D83DDDC4.png + + + Assets\Emoji\Separated\D83DDDD1.png + + + Assets\Emoji\Separated\D83DDDD2.png + + + Assets\Emoji\Separated\D83DDDD3.png + + + Assets\Emoji\Separated\D83DDDDC.png + + + Assets\Emoji\Separated\D83DDDDD.png + + + Assets\Emoji\Separated\D83DDDDE.png + + + Assets\Emoji\Separated\D83DDDE1.png + + + Assets\Emoji\Separated\D83DDDE3.png + + + Assets\Emoji\Separated\D83DDDE8.png + + + Assets\Emoji\Separated\D83DDDEF.png + + + Assets\Emoji\Separated\D83DDDF3.png + + + Assets\Emoji\Separated\D83DDDFA.png + + + Assets\Emoji\Separated\D83DDDFB.png + + + Assets\Emoji\Separated\D83DDDFC.png + + + Assets\Emoji\Separated\D83DDDFD.png + + + Assets\Emoji\Separated\D83DDDFE.png + + + Assets\Emoji\Separated\D83DDDFF.png + + + Assets\Emoji\Separated\D83DDE00.png + + + Assets\Emoji\Separated\D83DDE01.png + + + Assets\Emoji\Separated\D83DDE02.png + + + Assets\Emoji\Separated\D83DDE03.png + + + Assets\Emoji\Separated\D83DDE04.png + + + Assets\Emoji\Separated\D83DDE05.png + + + Assets\Emoji\Separated\D83DDE06.png + + + Assets\Emoji\Separated\D83DDE07.png + + + Assets\Emoji\Separated\D83DDE08.png + + + Assets\Emoji\Separated\D83DDE09.png + + + Assets\Emoji\Separated\D83DDE0A.png + + + Assets\Emoji\Separated\D83DDE0B.png + + + Assets\Emoji\Separated\D83DDE0C.png + + + Assets\Emoji\Separated\D83DDE0D.png + + + Assets\Emoji\Separated\D83DDE0E.png + + + Assets\Emoji\Separated\D83DDE0F.png + + + Assets\Emoji\Separated\D83DDE10.png + + + Assets\Emoji\Separated\D83DDE11.png + + + Assets\Emoji\Separated\D83DDE12.png + + + Assets\Emoji\Separated\D83DDE13.png + + + Assets\Emoji\Separated\D83DDE14.png + + + Assets\Emoji\Separated\D83DDE15.png + + + Assets\Emoji\Separated\D83DDE16.png + + + Assets\Emoji\Separated\D83DDE17.png + + + Assets\Emoji\Separated\D83DDE18.png + + + Assets\Emoji\Separated\D83DDE19.png + + + Assets\Emoji\Separated\D83DDE1A.png + + + Assets\Emoji\Separated\D83DDE1B.png + + + Assets\Emoji\Separated\D83DDE1C.png + + + Assets\Emoji\Separated\D83DDE1D.png + + + Assets\Emoji\Separated\D83DDE1E.png + + + Assets\Emoji\Separated\D83DDE1F.png + + + Assets\Emoji\Separated\D83DDE20.png + + + Assets\Emoji\Separated\D83DDE21.png + + + Assets\Emoji\Separated\D83DDE22.png + + + Assets\Emoji\Separated\D83DDE23.png + + + Assets\Emoji\Separated\D83DDE24.png + + + Assets\Emoji\Separated\D83DDE25.png + + + Assets\Emoji\Separated\D83DDE26.png + + + Assets\Emoji\Separated\D83DDE27.png + + + Assets\Emoji\Separated\D83DDE28.png + + + Assets\Emoji\Separated\D83DDE29.png + + + Assets\Emoji\Separated\D83DDE2A.png + + + Assets\Emoji\Separated\D83DDE2B.png + + + Assets\Emoji\Separated\D83DDE2C.png + + + Assets\Emoji\Separated\D83DDE2D.png + + + Assets\Emoji\Separated\D83DDE2E.png + + + Assets\Emoji\Separated\D83DDE2F.png + + + Assets\Emoji\Separated\D83DDE30.png + + + Assets\Emoji\Separated\D83DDE31.png + + + Assets\Emoji\Separated\D83DDE32.png + + + Assets\Emoji\Separated\D83DDE33.png + + + Assets\Emoji\Separated\D83DDE34.png + + + Assets\Emoji\Separated\D83DDE35.png + + + Assets\Emoji\Separated\D83DDE36.png + + + Assets\Emoji\Separated\D83DDE37.png + + + Assets\Emoji\Separated\D83DDE38.png + + + Assets\Emoji\Separated\D83DDE39.png + + + Assets\Emoji\Separated\D83DDE3A.png + + + Assets\Emoji\Separated\D83DDE3B.png + + + Assets\Emoji\Separated\D83DDE3C.png + + + Assets\Emoji\Separated\D83DDE3D.png + + + Assets\Emoji\Separated\D83DDE3E.png + + + Assets\Emoji\Separated\D83DDE3F.png + + + Assets\Emoji\Separated\D83DDE40.png + + + Assets\Emoji\Separated\D83DDE41.png + + + Assets\Emoji\Separated\D83DDE42.png + + + Assets\Emoji\Separated\D83DDE43.png + + + Assets\Emoji\Separated\D83DDE44.png + + + Assets\Emoji\Separated\D83DDE45.png + + + Assets\Emoji\Separated\D83DDE45200D2642.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFB.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFC.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFD.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFE.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFF.png + + + Assets\Emoji\Separated\D83DDE45D83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83DDE46.png + + + Assets\Emoji\Separated\D83DDE46200D2642.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFB.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFC.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFD.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFE.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFF.png + + + Assets\Emoji\Separated\D83DDE46D83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83DDE47.png + + + Assets\Emoji\Separated\D83DDE47200D2640.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFB.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFC.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFD.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFE.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFF.png + + + Assets\Emoji\Separated\D83DDE47D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83DDE48.png + + + Assets\Emoji\Separated\D83DDE49.png + + + Assets\Emoji\Separated\D83DDE4A.png + + + Assets\Emoji\Separated\D83DDE4B.png + + + Assets\Emoji\Separated\D83DDE4B200D2642.png + + + Assets\Emoji\Separated\D83DDE4BD83CDFFB.png + + + Assets\Emoji\Separated\D83DDE4BD83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83DDE4BD83CDFFC.png + + + Assets\Emoji\Separated\D83DDE4BD83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83DDE4BD83CDFFD.png + + + Assets\Emoji\Separated\D83DDE4BD83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83DDE4BD83CDFFE.png + + + Assets\Emoji\Separated\D83DDE4BD83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83DDE4BD83CDFFF.png + + + Assets\Emoji\Separated\D83DDE4BD83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83DDE4C.png + + + Assets\Emoji\Separated\D83DDE4CD83CDFFB.png + + + Assets\Emoji\Separated\D83DDE4CD83CDFFC.png + + + Assets\Emoji\Separated\D83DDE4CD83CDFFD.png + + + Assets\Emoji\Separated\D83DDE4CD83CDFFE.png + + + Assets\Emoji\Separated\D83DDE4CD83CDFFF.png + + + Assets\Emoji\Separated\D83DDE4D.png + + + Assets\Emoji\Separated\D83DDE4D200D2642.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFB.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFC.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFD.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFE.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFF.png + + + Assets\Emoji\Separated\D83DDE4DD83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83DDE4E.png + + + Assets\Emoji\Separated\D83DDE4E200D2642.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFB.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFC.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFD.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFE.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFF.png + + + Assets\Emoji\Separated\D83DDE4ED83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83DDE4F.png + + + Assets\Emoji\Separated\D83DDE4FD83CDFFB.png + + + Assets\Emoji\Separated\D83DDE4FD83CDFFC.png + + + Assets\Emoji\Separated\D83DDE4FD83CDFFD.png + + + Assets\Emoji\Separated\D83DDE4FD83CDFFE.png + + + Assets\Emoji\Separated\D83DDE4FD83CDFFF.png + + + Assets\Emoji\Separated\D83DDE80.png + + + Assets\Emoji\Separated\D83DDE81.png + + + Assets\Emoji\Separated\D83DDE82.png + + + Assets\Emoji\Separated\D83DDE83.png + + + Assets\Emoji\Separated\D83DDE84.png + + + Assets\Emoji\Separated\D83DDE85.png + + + Assets\Emoji\Separated\D83DDE86.png + + + Assets\Emoji\Separated\D83DDE87.png + + + Assets\Emoji\Separated\D83DDE88.png + + + Assets\Emoji\Separated\D83DDE89.png + + + Assets\Emoji\Separated\D83DDE8A.png + + + Assets\Emoji\Separated\D83DDE8B.png + + + Assets\Emoji\Separated\D83DDE8C.png + + + Assets\Emoji\Separated\D83DDE8D.png + + + Assets\Emoji\Separated\D83DDE8E.png + + + Assets\Emoji\Separated\D83DDE8F.png + + + Assets\Emoji\Separated\D83DDE90.png + + + Assets\Emoji\Separated\D83DDE91.png + + + Assets\Emoji\Separated\D83DDE92.png + + + Assets\Emoji\Separated\D83DDE93.png + + + Assets\Emoji\Separated\D83DDE94.png + + + Assets\Emoji\Separated\D83DDE95.png + + + Assets\Emoji\Separated\D83DDE96.png + + + Assets\Emoji\Separated\D83DDE97.png + + + Assets\Emoji\Separated\D83DDE98.png + + + Assets\Emoji\Separated\D83DDE99.png + + + Assets\Emoji\Separated\D83DDE9A.png + + + Assets\Emoji\Separated\D83DDE9B.png + + + Assets\Emoji\Separated\D83DDE9C.png + + + Assets\Emoji\Separated\D83DDE9D.png + + + Assets\Emoji\Separated\D83DDE9E.png + + + Assets\Emoji\Separated\D83DDE9F.png + + + Assets\Emoji\Separated\D83DDEA0.png + + + Assets\Emoji\Separated\D83DDEA1.png + + + Assets\Emoji\Separated\D83DDEA2.png + + + Assets\Emoji\Separated\D83DDEA3.png + + + Assets\Emoji\Separated\D83DDEA3200D2640.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFB.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFC.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFD.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFE.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFF.png + + + Assets\Emoji\Separated\D83DDEA3D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83DDEA4.png + + + Assets\Emoji\Separated\D83DDEA5.png + + + Assets\Emoji\Separated\D83DDEA6.png + + + Assets\Emoji\Separated\D83DDEA7.png + + + Assets\Emoji\Separated\D83DDEA8.png + + + Assets\Emoji\Separated\D83DDEA9.png + + + Assets\Emoji\Separated\D83DDEAA.png + + + Assets\Emoji\Separated\D83DDEAB.png + + + Assets\Emoji\Separated\D83DDEAC.png + + + Assets\Emoji\Separated\D83DDEAD.png + + + Assets\Emoji\Separated\D83DDEAE.png + + + Assets\Emoji\Separated\D83DDEAF.png + + + Assets\Emoji\Separated\D83DDEB0.png + + + Assets\Emoji\Separated\D83DDEB1.png + + + Assets\Emoji\Separated\D83DDEB2.png + + + Assets\Emoji\Separated\D83DDEB3.png + + + Assets\Emoji\Separated\D83DDEB4.png + + + Assets\Emoji\Separated\D83DDEB4200D2640.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFB.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFC.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFD.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFE.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFF.png + + + Assets\Emoji\Separated\D83DDEB4D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83DDEB5.png + + + Assets\Emoji\Separated\D83DDEB5200D2640.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFB.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFC.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFD.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFE.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFF.png + + + Assets\Emoji\Separated\D83DDEB5D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83DDEB6.png + + + Assets\Emoji\Separated\D83DDEB6200D2640.png + + + Assets\Emoji\Separated\D83DDEB6D83CDFFB.png + + + Assets\Emoji\Separated\D83DDEB6D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83DDEB6D83CDFFC.png + + + Assets\Emoji\Separated\D83DDEB6D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83DDEB6D83CDFFD.png + + + Assets\Emoji\Separated\D83DDEB6D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83DDEB6D83CDFFE.png + + + Assets\Emoji\Separated\D83DDEB6D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83DDEB6D83CDFFF.png + + + Assets\Emoji\Separated\D83DDEB6D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83DDEB7.png + + + Assets\Emoji\Separated\D83DDEB8.png + + + Assets\Emoji\Separated\D83DDEB9.png + + + Assets\Emoji\Separated\D83DDEBA.png + + + Assets\Emoji\Separated\D83DDEBB.png + + + Assets\Emoji\Separated\D83DDEBC.png + + + Assets\Emoji\Separated\D83DDEBD.png + + + Assets\Emoji\Separated\D83DDEBE.png + + + Assets\Emoji\Separated\D83DDEBF.png + + + Assets\Emoji\Separated\D83DDEC0.png + + + Assets\Emoji\Separated\D83DDEC0D83CDFFB.png + + + Assets\Emoji\Separated\D83DDEC0D83CDFFC.png + + + Assets\Emoji\Separated\D83DDEC0D83CDFFD.png + + + Assets\Emoji\Separated\D83DDEC0D83CDFFE.png + + + Assets\Emoji\Separated\D83DDEC0D83CDFFF.png + + + Assets\Emoji\Separated\D83DDEC1.png + + + Assets\Emoji\Separated\D83DDEC2.png + + + Assets\Emoji\Separated\D83DDEC3.png + + + Assets\Emoji\Separated\D83DDEC4.png + + + Assets\Emoji\Separated\D83DDEC5.png + + + Assets\Emoji\Separated\D83DDECB.png + + + Assets\Emoji\Separated\D83DDECC.png + + + Assets\Emoji\Separated\D83DDECD.png + + + Assets\Emoji\Separated\D83DDECE.png + + + Assets\Emoji\Separated\D83DDECF.png + + + Assets\Emoji\Separated\D83DDED0.png + + + Assets\Emoji\Separated\D83DDED1.png + + + Assets\Emoji\Separated\D83DDED2.png + + + Assets\Emoji\Separated\D83DDEE0.png + + + Assets\Emoji\Separated\D83DDEE1.png + + + Assets\Emoji\Separated\D83DDEE2.png + + + Assets\Emoji\Separated\D83DDEE3.png + + + Assets\Emoji\Separated\D83DDEE4.png + + + Assets\Emoji\Separated\D83DDEE5.png + + + Assets\Emoji\Separated\D83DDEE9.png + + + Assets\Emoji\Separated\D83DDEEB.png + + + Assets\Emoji\Separated\D83DDEEC.png + + + Assets\Emoji\Separated\D83DDEF0.png + + + Assets\Emoji\Separated\D83DDEF3.png + + + Assets\Emoji\Separated\D83DDEF4.png + + + Assets\Emoji\Separated\D83DDEF5.png + + + Assets\Emoji\Separated\D83DDEF6.png + + + Assets\Emoji\Separated\D83EDD10.png + + + Assets\Emoji\Separated\D83EDD11.png + + + Assets\Emoji\Separated\D83EDD12.png + + + Assets\Emoji\Separated\D83EDD13.png + + + Assets\Emoji\Separated\D83EDD14.png + + + Assets\Emoji\Separated\D83EDD15.png + + + Assets\Emoji\Separated\D83EDD16.png + + + Assets\Emoji\Separated\D83EDD17.png + + + Assets\Emoji\Separated\D83EDD18.png + + + Assets\Emoji\Separated\D83EDD18D83CDFFB.png + + + Assets\Emoji\Separated\D83EDD18D83CDFFC.png + + + Assets\Emoji\Separated\D83EDD18D83CDFFD.png + + + Assets\Emoji\Separated\D83EDD18D83CDFFE.png + + + Assets\Emoji\Separated\D83EDD18D83CDFFF.png + + + Assets\Emoji\Separated\D83EDD19.png + + + Assets\Emoji\Separated\D83EDD19D83CDFFB.png + + + Assets\Emoji\Separated\D83EDD19D83CDFFC.png + + + Assets\Emoji\Separated\D83EDD19D83CDFFD.png + + + Assets\Emoji\Separated\D83EDD19D83CDFFE.png + + + Assets\Emoji\Separated\D83EDD19D83CDFFF.png + + + Assets\Emoji\Separated\D83EDD1A.png + + + Assets\Emoji\Separated\D83EDD1AD83CDFFB.png + + + Assets\Emoji\Separated\D83EDD1AD83CDFFC.png + + + Assets\Emoji\Separated\D83EDD1AD83CDFFD.png + + + Assets\Emoji\Separated\D83EDD1AD83CDFFE.png + + + Assets\Emoji\Separated\D83EDD1AD83CDFFF.png + + + Assets\Emoji\Separated\D83EDD1B.png + + + Assets\Emoji\Separated\D83EDD1BD83CDFFB.png + + + Assets\Emoji\Separated\D83EDD1BD83CDFFC.png + + + Assets\Emoji\Separated\D83EDD1BD83CDFFD.png + + + Assets\Emoji\Separated\D83EDD1BD83CDFFE.png + + + Assets\Emoji\Separated\D83EDD1BD83CDFFF.png + + + Assets\Emoji\Separated\D83EDD1C.png + + + Assets\Emoji\Separated\D83EDD1CD83CDFFB.png + + + Assets\Emoji\Separated\D83EDD1CD83CDFFC.png + + + Assets\Emoji\Separated\D83EDD1CD83CDFFD.png + + + Assets\Emoji\Separated\D83EDD1CD83CDFFE.png + + + Assets\Emoji\Separated\D83EDD1CD83CDFFF.png + + + Assets\Emoji\Separated\D83EDD1D.png + + + Assets\Emoji\Separated\D83EDD1E.png + + + Assets\Emoji\Separated\D83EDD1ED83CDFFB.png + + + Assets\Emoji\Separated\D83EDD1ED83CDFFC.png + + + Assets\Emoji\Separated\D83EDD1ED83CDFFD.png + + + Assets\Emoji\Separated\D83EDD1ED83CDFFE.png + + + Assets\Emoji\Separated\D83EDD1ED83CDFFF.png + + + Assets\Emoji\Separated\D83EDD20.png + + + Assets\Emoji\Separated\D83EDD21.png + + + Assets\Emoji\Separated\D83EDD22.png + + + Assets\Emoji\Separated\D83EDD23.png + + + Assets\Emoji\Separated\D83EDD24.png + + + Assets\Emoji\Separated\D83EDD25.png + + + Assets\Emoji\Separated\D83EDD26200D2640.png + + + Assets\Emoji\Separated\D83EDD26200D2642.png + + + Assets\Emoji\Separated\D83EDD26D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83EDD26D83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83EDD26D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83EDD26D83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83EDD26D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83EDD26D83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83EDD26D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83EDD26D83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83EDD26D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83EDD26D83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83EDD27.png + + + Assets\Emoji\Separated\D83EDD30.png + + + Assets\Emoji\Separated\D83EDD30D83CDFFB.png + + + Assets\Emoji\Separated\D83EDD30D83CDFFC.png + + + Assets\Emoji\Separated\D83EDD30D83CDFFD.png + + + Assets\Emoji\Separated\D83EDD30D83CDFFE.png + + + Assets\Emoji\Separated\D83EDD30D83CDFFF.png + + + Assets\Emoji\Separated\D83EDD33.png + + + Assets\Emoji\Separated\D83EDD34.png + + + Assets\Emoji\Separated\D83EDD34D83CDFFB.png + + + Assets\Emoji\Separated\D83EDD34D83CDFFC.png + + + Assets\Emoji\Separated\D83EDD34D83CDFFD.png + + + Assets\Emoji\Separated\D83EDD34D83CDFFE.png + + + Assets\Emoji\Separated\D83EDD34D83CDFFF.png + + + Assets\Emoji\Separated\D83EDD35.png + + + Assets\Emoji\Separated\D83EDD35D83CDFFB.png + + + Assets\Emoji\Separated\D83EDD35D83CDFFC.png + + + Assets\Emoji\Separated\D83EDD35D83CDFFD.png + + + Assets\Emoji\Separated\D83EDD35D83CDFFE.png + + + Assets\Emoji\Separated\D83EDD35D83CDFFF.png + + + Assets\Emoji\Separated\D83EDD36.png + + + Assets\Emoji\Separated\D83EDD36D83CDFFB.png + + + Assets\Emoji\Separated\D83EDD36D83CDFFC.png + + + Assets\Emoji\Separated\D83EDD36D83CDFFD.png + + + Assets\Emoji\Separated\D83EDD36D83CDFFE.png + + + Assets\Emoji\Separated\D83EDD36D83CDFFF.png + + + Assets\Emoji\Separated\D83EDD37200D2640.png + + + Assets\Emoji\Separated\D83EDD37200D2642.png + + + Assets\Emoji\Separated\D83EDD37D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83EDD37D83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83EDD37D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83EDD37D83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83EDD37D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83EDD37D83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83EDD37D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83EDD37D83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83EDD37D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83EDD37D83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83EDD38200D2640.png + + + Assets\Emoji\Separated\D83EDD38200D2642.png + + + Assets\Emoji\Separated\D83EDD38D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83EDD38D83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83EDD38D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83EDD38D83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83EDD38D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83EDD38D83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83EDD38D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83EDD38D83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83EDD38D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83EDD38D83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83EDD39200D2640.png + + + Assets\Emoji\Separated\D83EDD39200D2642.png + + + Assets\Emoji\Separated\D83EDD39D83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83EDD39D83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83EDD39D83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83EDD39D83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83EDD39D83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83EDD39D83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83EDD39D83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83EDD39D83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83EDD39D83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83EDD39D83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83EDD3A.png + + + Assets\Emoji\Separated\D83EDD3C200D2640.png + + + Assets\Emoji\Separated\D83EDD3C200D2642.png + + + Assets\Emoji\Separated\D83EDD3D200D2640.png + + + Assets\Emoji\Separated\D83EDD3D200D2642.png + + + Assets\Emoji\Separated\D83EDD3DD83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83EDD3DD83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83EDD3DD83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83EDD3DD83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83EDD3DD83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83EDD3DD83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83EDD3DD83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83EDD3DD83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83EDD3DD83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83EDD3DD83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83EDD3E200D2640.png + + + Assets\Emoji\Separated\D83EDD3E200D2642.png + + + Assets\Emoji\Separated\D83EDD3ED83CDFFB200D2640.png + + + Assets\Emoji\Separated\D83EDD3ED83CDFFB200D2642.png + + + Assets\Emoji\Separated\D83EDD3ED83CDFFC200D2640.png + + + Assets\Emoji\Separated\D83EDD3ED83CDFFC200D2642.png + + + Assets\Emoji\Separated\D83EDD3ED83CDFFD200D2640.png + + + Assets\Emoji\Separated\D83EDD3ED83CDFFD200D2642.png + + + Assets\Emoji\Separated\D83EDD3ED83CDFFE200D2640.png + + + Assets\Emoji\Separated\D83EDD3ED83CDFFE200D2642.png + + + Assets\Emoji\Separated\D83EDD3ED83CDFFF200D2640.png + + + Assets\Emoji\Separated\D83EDD3ED83CDFFF200D2642.png + + + Assets\Emoji\Separated\D83EDD40.png + + + Assets\Emoji\Separated\D83EDD41.png + + + Assets\Emoji\Separated\D83EDD42.png + + + Assets\Emoji\Separated\D83EDD43.png + + + Assets\Emoji\Separated\D83EDD44.png + + + Assets\Emoji\Separated\D83EDD45.png + + + Assets\Emoji\Separated\D83EDD47.png + + + Assets\Emoji\Separated\D83EDD48.png + + + Assets\Emoji\Separated\D83EDD49.png + + + Assets\Emoji\Separated\D83EDD4A.png + + + Assets\Emoji\Separated\D83EDD4B.png + + + Assets\Emoji\Separated\D83EDD50.png + + + Assets\Emoji\Separated\D83EDD51.png + + + Assets\Emoji\Separated\D83EDD52.png + + + Assets\Emoji\Separated\D83EDD53.png + + + Assets\Emoji\Separated\D83EDD54.png + + + Assets\Emoji\Separated\D83EDD55.png + + + Assets\Emoji\Separated\D83EDD56.png + + + Assets\Emoji\Separated\D83EDD57.png + + + Assets\Emoji\Separated\D83EDD58.png + + + Assets\Emoji\Separated\D83EDD59.png + + + Assets\Emoji\Separated\D83EDD5A.png + + + Assets\Emoji\Separated\D83EDD5B.png + + + Assets\Emoji\Separated\D83EDD5C.png + + + Assets\Emoji\Separated\D83EDD5D.png + + + Assets\Emoji\Separated\D83EDD5E.png + + + Assets\Emoji\Separated\D83EDD80.png + + + Assets\Emoji\Separated\D83EDD81.png + + + Assets\Emoji\Separated\D83EDD82.png + + + Assets\Emoji\Separated\D83EDD83.png + + + Assets\Emoji\Separated\D83EDD84.png + + + Assets\Emoji\Separated\D83EDD85.png + + + Assets\Emoji\Separated\D83EDD86.png + + + Assets\Emoji\Separated\D83EDD87.png + + + Assets\Emoji\Separated\D83EDD88.png + + + Assets\Emoji\Separated\D83EDD89.png + + + Assets\Emoji\Separated\D83EDD8A.png + + + Assets\Emoji\Separated\D83EDD8B.png + + + Assets\Emoji\Separated\D83EDD8C.png + + + Assets\Emoji\Separated\D83EDD8D.png + + + Assets\Emoji\Separated\D83EDD8E.png + + + Assets\Emoji\Separated\D83EDD8F.png + + + Assets\Emoji\Separated\D83EDD90.png + + + Assets\Emoji\Separated\D83EDD91.png + + + Assets\Emoji\Separated\D83EDDC0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part3.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part4.png + + + Assets\Emoji\SpacedSprites\sprite64_cat0_part5.png + + + Assets\Emoji\SpacedSprites\sprite64_cat1_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat1_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat1_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat1_part3.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part3.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part4.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part5.png + + + Assets\Emoji\SpacedSprites\sprite64_cat2_part6.png + + + Assets\Emoji\SpacedSprites\sprite64_cat3_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat3_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat3_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part0.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part1.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part2.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part3.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part4.png + + + Assets\Emoji\SpacedSprites\sprite64_cat4_part5.png + + + Assets\light.emoji.abc-WXGA.png + + + Assets\light.emoji.backspace-WXGA.png + + + Assets\light.emoji.category.1-WXGA.png + + + Assets\light.emoji.category.2-WXGA.png + + + Assets\light.emoji.category.3-WXGA.png + + + Assets\light.emoji.category.4-WXGA.png + + + Assets\light.emoji.category.5-WXGA.png + + + Assets\light.emoji.featured-WXGA.png + + + Assets\light.emoji.recent-WXGA.png + + + Assets\light.emoji.settings-WXGA.png + + + Assets\light.emoji.sticker-WXGA.png + + + Images\ApplicationBar\appbar.add.rest.png + + + Images\ApplicationBar\appbar.attach.png + + + Images\ApplicationBar\appbar.back.png + + + Images\ApplicationBar\appbar.basecircle.light.png + + + Images\ApplicationBar\appbar.basecircle.png + + + Images\ApplicationBar\appbar.cancel.rest.png + + + Images\ApplicationBar\appbar.check.png + + + Images\ApplicationBar\appbar.delete.png + + + Images\ApplicationBar\appbar.edit.png + + + Images\ApplicationBar\appbar.feature.search.rest.png + + + Images\ApplicationBar\appbar.feature.video.rest.png + + + Images\ApplicationBar\appbar.forwardmessage.png + + + Images\ApplicationBar\appbar.manage.rest.png + + + Images\ApplicationBar\appbar.map.centerme.png + + + Images\ApplicationBar\appbar.map.checkin.png + + + Images\ApplicationBar\appbar.map.direction.png + + + Images\ApplicationBar\appbar.next.light.png + + + Images\ApplicationBar\appbar.next.png + + + Images\ApplicationBar\appbar.refresh.rest.png + + + Images\ApplicationBar\appbar.save.png + + + Images\ApplicationBar\appbar.send.text.rest.png + + + Images\ApplicationBar\appbar.share.png + + + Images\ApplicationBar\appbar.smile.png + + + Images\ApplicationBar\appbar.stop.rest.png + + + Images\ApplicationBar\appbar.transport.play.light.png + + + Images\ApplicationBar\appbar.transport.play.png + + + Images\ApplicationBar\appbar.user.dark.png + + + Images\ApplicationBar\appbar.user.light.png + + + Images\ApplicationBar\feature.calendar.light.png + + + Images\ApplicationBar\feature.calendar.png + + + Images\Audio\appbar.basecircle.rest.png + + + Images\Audio\appbar.download.rest.png + + + Images\Audio\appbar.transport.pause.rest.png + + + Images\Audio\appbar.transport.play.rest.png + + + Images\Backgrounds\gallery_WXGA.png + + + Images\Backgrounds\wallpapercheck_WXGA.png + + + Images\Dialogs\broadcast-WXGA.png + + + Images\Dialogs\channel.check-WXGA.png + + + Images\Dialogs\channel.muted.png + + + Images\Dialogs\channel.unmuted.png + + + Images\Dialogs\chat.check-WXGA.png + + + Images\Dialogs\chat.commands-WXGA.png + + + Images\Dialogs\chat.customkeyboard-WXGA.png + + + Images\Dialogs\chat.draft-WXGA.png + + + Images\Dialogs\chat.gas-WXGA.png + + + Images\Dialogs\chat.keyboard-WXGA.png + + + Images\Dialogs\chat.masks.png + + + Images\Dialogs\chat.mute-WXGA.png + + + Images\Dialogs\chat.smile-black.png + + + Images\Dialogs\chat.smile-white.png + + + Images\Dialogs\chat.smile.png + + + Images\Dialogs\chat.state.read-black-WXGA.png + + + Images\Dialogs\chat.state.sent-black-WXGA.png + + + Images\Dialogs\group-WXGA.png + + + Images\Dialogs\passcode.close-WXGA.png + + + Images\Dialogs\passcode.open-WXGA.png + + + Images\Dialogs\secretchat-black-WXGA.png + + + Images\Dialogs\secretchat-white-WXGA.png + + + Images\Dialogs\secretchat-WXGA.png + + + Images\LockScreen\lockscreen.logo.png + + + Images\LockScreen\lockscreen.logo.white.png + + + Images\LockScreen\lockscreen.png + + + Images\Maps\4SQ.png + + + Images\Maps\attach-location-black.png + + + Images\Maps\Map_Pin.png + + + Images\Messages\channel.broadcast-WXGA.png + + + Images\Messages\channel.share.black.png + + + Images\Messages\channel.share.white.png + + + Images\Messages\chat.cloudstorage-white-WXGA.png + + + Images\Messages\chat.cloudstorage-WXGA.png.png + + + Images\Messages\chat.nomessages-white-WXGA.png + + + Images\Messages\chat.nomessages-WXGA.png + + + Images\Messages\chat_doc-WXGA.png + + + Images\Messages\doc.cancel.png + + + Images\Messages\doc.download.png + + + Images\Messages\doc.pause.png + + + Images\Messages\file.black-WXGA.png + + + Images\Messages\file.white-WXGA.png + + + Images\Messages\inline.openweb.light.png + + + Images\Messages\inline.openweb.png + + + Images\Messages\inline.share.light.png + + + Images\Messages\inline.share.png + + + Images\Messages\link.png + + + Images\Messages\media.black-WXGA.png + + + Images\Messages\media.canceldownload.png + + + Images\Messages\media.download-WXGA.png + + + Images\Messages\media.download.png + + + Images\Messages\media.download.white-WXGA.png + + + Images\Messages\media.white-WXGA.png + + + Images\Messages\message.deletereply.png + + + Images\Messages\message.state.broadcast.png + + + Images\Messages\message.state.read-WXGA.png + + + Images\Messages\message.state.sending-WXGA.png + + + Images\Messages\message.state.sent-WXGA.png + + + Images\Messages\message.state.views-WXGA.png + + + Images\Messages\movestickerpack.png + + + Images\Messages\nomusic.png + + + Images\Messages\unreadmessages.png + + + Images\NumericKeyboard\back.png + + + Images\NumericKeyboard\back.white.png + + + Images\PhoneNumber\changenumber_2x.png + + + Images\Placeholder\placeholder.broadcast.png + + + Images\Placeholder\placeholder.group.transparent-WXGA.png + + + Images\Placeholder\placeholder.user.transparent-WXGA.png + + + Images\Startup\intro.1-720p.png + + + Images\Startup\intro.2-WXGA.png + + + Images\Startup\intro.3-WXGA.png + + + Images\Startup\intro.4-WXGA.png + + + Images\Startup\intro.5-WXGA.png + + + Images\Startup\intro.6-WXGA.png + + + Images\Startup\intro.channel.black-WXGA.png + + + Images\Startup\intro.channel.white-WXGA.png + + + Sounds\Default.wav + + + Sounds\Sound1.wav + + + Sounds\Sound2.wav + + + Sounds\Sound3.wav + + + Sounds\Sound4.wav + + + Sounds\Sound5.wav + + + Sounds\Sound6.wav + + + ToastPromptIcon.png + + + + + + + + + + + + + + + + + + + + + Always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Designer + + + Designer + + + + + + + {eadff7b8-e6c3-4f34-9b33-014b3035c595} + OpenCVComponent + + + {ebc5ca98-87f1-4a01-a48d-69659c103e72} + FFmpegInterop.WindowsPhone + + + {21f10158-c078-4bd7-a82a-9c4aeb8e2f8e} + libtgvoip + + + {820034c1-645d-4340-8813-d980c1ef77de} + Agents + + + {c8d75245-ffcf-4932-a228-c9cc8bb60b03} + BackEnd + + + {cc7a35bf-aabc-411d-b911-ac037a781266} + libtgnet + + + {e79d5093-8038-4a5f-8a98-ca38c0d0886f} + Telegram.Api.WP8 + + + {f04be5a2-70df-4e82-bfb5-cd03985c9746} + Telegram.Controls.WP8 + + + {b51dd8c5-335d-4a2d-b429-6d0f41ed0281} + TelegramClient.Native + + + {5E327850-E16E-4642-957A-FD52BF8D3D02} + TelegramClient.Opus + + + {997bd0c4-68e8-4495-904a-eb798b166832} + TelegramClient.Tasks + + + {fae12fd9-edca-433e-ad11-f1663a998f35} + TelegramClient.WebP + + + + + Resources\AppResources.de.resx + Designer + PublicResXFileCodeGenerator + AppResources.de.Designer.cs + + + Resources\AppResources.es.resx + Designer + PublicResXFileCodeGenerator + AppResources.es.Designer.cs + + + Resources\AppResources.it.resx + Designer + PublicResXFileCodeGenerator + AppResources.it.Designer.cs + + + Resources\AppResources.nl.resx + Designer + PublicResXFileCodeGenerator + AppResources.nl.Designer.cs + + + Resources\AppResources.pt.resx + Designer + PublicResXFileCodeGenerator + AppResources.pt.Designer.cs + + + Resources\AppResources.resx + PublicResXFileCodeGenerator + AppResources.Designer.cs + Designer + + + Resources\AppResources.ru.resx + Designer + PublicResXFileCodeGenerator + AppResources.ru.Designer.cs + + + + + + + + + + + + + + + + + + + + + + $(FilesToXapDependsOn);BeforeFilesToXap + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Themes/Default/ToggleSwitch.xaml b/TelegramClient.WP81/Themes/Default/ToggleSwitch.xaml new file mode 100755 index 0000000..8b451cf --- /dev/null +++ b/TelegramClient.WP81/Themes/Default/ToggleSwitch.xaml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Themes/Default/W10M.xaml b/TelegramClient.WP81/Themes/Default/W10M.xaml new file mode 100755 index 0000000..689e4db --- /dev/null +++ b/TelegramClient.WP81/Themes/Default/W10M.xaml @@ -0,0 +1,1462 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Themes/Default/W10MCommon.xaml b/TelegramClient.WP81/Themes/Default/W10MCommon.xaml new file mode 100755 index 0000000..ebed7ae --- /dev/null +++ b/TelegramClient.WP81/Themes/Default/W10MCommon.xaml @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Themes/SharedResourceDictionary.cs b/TelegramClient.WP81/Themes/SharedResourceDictionary.cs new file mode 100755 index 0000000..763fe89 --- /dev/null +++ b/TelegramClient.WP81/Themes/SharedResourceDictionary.cs @@ -0,0 +1,53 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections; +using System.Collections.Generic; +using System.Windows; + +namespace TelegramClient.Themes +{ + public class SharedResourceDictionary : ResourceDictionary + { + public static Dictionary _sharedDictionaries = new Dictionary(); + + private Uri _sourceUri; + + public new Uri Source + { + get { return _sourceUri; } + set + { + _sourceUri = value; + if (!_sharedDictionaries.ContainsKey(value)) + { + Application.LoadComponent(this, value); + _sharedDictionaries.Add(value, this); + } + else + { + CopyInto(this, _sharedDictionaries[value]); + } + } + } + + private static void CopyInto(ResourceDictionary copy, ResourceDictionary original) + { + foreach (var dictionary in original.MergedDictionaries) + { + var mergedCopy = new ResourceDictionary(); + CopyInto(mergedCopy, dictionary); + copy.MergedDictionaries.Add(mergedCopy); + } + foreach (DictionaryEntry pair in original) + { + copy.Add(pair.Key, pair.Value); + } + } + } +} diff --git a/TelegramClient.WP81/Utils/Passport.cs b/TelegramClient.WP81/Utils/Passport.cs new file mode 100755 index 0000000..9700d92 --- /dev/null +++ b/TelegramClient.WP81/Utils/Passport.cs @@ -0,0 +1,1266 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using System.Threading.Tasks; +using Windows.Security.Cryptography.Core; +using Windows.Storage; +using Windows.Storage.Streams; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.OpenSsl; +using Org.BouncyCastle.Security; +using Telegram.Api.Helpers; +using Telegram.Api.TL; +using TelegramClient.Utils.SecureCredentials; +using TelegramClient.ViewModels.Passport; +using Buffer = Windows.Storage.Streams.Buffer; +using File = TelegramClient.Utils.SecureCredentials.File; + +namespace TelegramClient.Utils +{ + static class Passport + { + public static bool IsValidPostCode(string postcode) + { + foreach (var symbol in postcode) + { + if (!IsValidPostCodeSymbol(symbol)) return false; + } + + return true; + } + + private static bool IsValidPostCodeSymbol(char symbol) + { + if (symbol >= 'a' && symbol <= 'z' + || symbol >= 'A' && symbol <= 'Z' + || symbol >= '0' && symbol <= '9' + || symbol == '-') + { + return true; + } + + return false; + } + + public static bool IsValidName(string postcode) + { + foreach (var symbol in postcode) + { + if (!IsValidNameSymbol(symbol)) return false; + } + + return true; + } + + private static bool IsValidNameSymbol(char symbol) + { + if (symbol >= 'a' && symbol <= 'z' + || symbol >= 'A' && symbol <= 'Z' + || symbol >= '0' && symbol <= '9' + || symbol == '-' + || symbol == '.' + || symbol == ',' + || symbol == '/' + || symbol == '&' + || symbol == '\'' + || symbol == ' ') + { + return true; + } + + return false; + } + + private static TLString DoFinal(bool forEncryption, TLString data, byte[] hash) + { + var secretKey = hash.SubArray(0, 32); + var iv = hash.SubArray(32, 16); + + var cipher = CipherUtilities.GetCipher("AES/CBC/NOPADDING"); + var param = new KeyParameter(secretKey); + cipher.Init(forEncryption, new ParametersWithIV(param, iv)); + var result = cipher.DoFinal(data.Data); + + return TLString.FromBigEndianData(result); + } + + private static TLString EncryptSecureData(TLString data, TLString valueSecret, TLString hash) + { + var sha512 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512); + var secretHash = sha512.HashData(TLUtils.Combine(valueSecret.Data, hash.Data).AsBuffer()).ToArray(); + + var result = DoFinal(true, data, secretHash); + + return result; + } + + private static TLString DecryptSecureData(TLString data, TLString valueSecret, TLString hash) + { + var sha512 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512); + var secretHash = sha512.HashData(TLUtils.Combine(valueSecret.Data, hash.Data).AsBuffer()).ToArray(); + + var result = DoFinal(false, data, secretHash); + + return result; + } + + public static TLString EncryptValueSecret(TLString valueSecret, TLString secret, TLString hash) + { + var sha512 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512); + var secretHash = sha512.HashData(TLUtils.Combine(secret.Data, hash.Data).AsBuffer()).ToArray(); + + return DoFinal(true, valueSecret, secretHash); + } + + public static TLString DecryptValueSecret(TLString secureValueSecret, TLString secret, TLString hash) + { + var sha512 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512); + var secretHash = sha512.HashData(TLUtils.Combine(secret.Data, hash.Data).AsBuffer()).ToArray(); + + return DoFinal(false, secureValueSecret, secretHash); + } + + public static TLSecureValue EncryptSecureValue(TLSecureValue secureValue, TLString innerData, TLString valueSecret, TLString secret) + { + var length = innerData.Data.Length % 16; + var paddingLength = 16 - length + 32; + var padding = new byte[paddingLength]; + + var randomGenerator = new SecureRandom(TLString.Empty.Data); + randomGenerator.NextBytes(padding); + + padding[0] = (byte)paddingLength; + var decryptedData = TLString.FromBigEndianData(TLUtils.Combine(padding, innerData.Data)); + + secureValue.Data = new TLSecureData(); + + var dataHash = Telegram.Api.Helpers.Utils.ComputeSHA256(decryptedData.Data); + secureValue.Data.DataHash = TLString.FromBigEndianData(dataHash); + + var data = EncryptSecureData( + decryptedData, + valueSecret, + secureValue.Data.DataHash); + secureValue.Data.Data = data; + + var secureValueSecret = EncryptValueSecret( + valueSecret, + secret, + secureValue.Data.DataHash); + secureValue.Data.Secret = secureValueSecret; + + return secureValue; + } + + public static TLSecureCredentialsEncrypted EncryptSecureCredentials(TLString innerData, TLString credentialsSecret) + { + var credentials = new TLSecureCredentialsEncrypted(); + + var length = innerData.Data.Length % 16; + var paddingLength = 16 - length + 32; + var padding = new byte[paddingLength]; + + var randomGenerator = new SecureRandom(TLString.Empty.Data); + randomGenerator.NextBytes(padding); + + padding[0] = (byte)paddingLength; + var decryptedData = TLString.FromBigEndianData(TLUtils.Combine(padding, innerData.Data)); + + var dataHash = Telegram.Api.Helpers.Utils.ComputeSHA256(decryptedData.Data); + credentials.Hash = TLString.FromBigEndianData(dataHash); + + var data = EncryptSecureData( + decryptedData, + credentialsSecret, + credentials.Hash); + credentials.Data = data; + + return credentials; + } + + public static TLString DecryptSecureValue(TLSecureValue secureValue, TLString secret) + { + var value = DecryptValueSecret( + secureValue.Data.Secret, + secret, + secureValue.Data.DataHash); + + if (!IsGoodSecret(value)) return null; + + var data = DecryptSecureData( + secureValue.Data.Data, + value, + secureValue.Data.DataHash); + + if (data.Data.Length == 0) return null; + + var dataHash = Telegram.Api.Helpers.Utils.ComputeSHA256(data.Data); + if (!TLUtils.ByteArraysEqual(secureValue.Data.DataHash.Data, dataHash)) return null; + + var length = data.Data[0]; + if (length < 32 || length > 255) return null; + + var innerData = data.Data.SubArray(length, data.Data.Length - length); + + return TLString.FromBigEndianData(innerData); + } + + public static TLString GenerateSecret(TLString secretRandom) + { + var randomGenerator = new SecureRandom(secretRandom.Data); + var secret = new byte[32]; + randomGenerator.NextBytes(secret); + + var sum = secret.Sum(x => x) % 255; + var diff = secret[secret.Length - 1] + 239 - sum; + secret[secret.Length - 1] = (byte)(diff % 255); + + return TLString.FromBigEndianData(secret); + } + + public static bool IsGoodSecret(TLString secret) + { + if (secret == null) return false; + if (secret.Data.Length != 32) return false; + + var sum = secret.Data.Sum(x => x) % 255; + if (sum != 239) return false; + + return true; + } + + public static void EncryptSecret(out TLString secureSecret, out TLString secureSalt, out TLLong secureHash, TLString secret, TLString secretRandom, TLSecurePasswordKdfAlgoBase algoBase, TLString password) + { + // only this algo is possible to encrypt secret + var algo2 = algoBase as TLSecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000; + if (algo2 != null) + { + // generate secure hash + var secureSecretHash = Telegram.Api.Helpers.Utils.ComputeSHA256(secret.Data); + var secureSecretHash2 = secureSecretHash.SubArray(0, 8); + secureHash = new TLLong(BitConverter.ToInt64(secureSecretHash2, 0)); + + // generate secure salt + var randomGenerator = new SecureRandom(secretRandom.Data); + var random = new byte[8]; + randomGenerator.NextBytes(random); + var newSecureSaltData = TLUtils.Combine(algo2.Salt.Data, random); + secureSalt = TLString.FromBigEndianData(newSecureSaltData); + + // generate secure secret + var passwordHash = PBKDF2.GetHash(password.Data.AsBuffer(), newSecureSaltData.AsBuffer()).ToArray(); + secureSecret = DoFinal(true, secret, passwordHash); + + return; + } + + var algo1 = algoBase as TLSecurePasswordKdfAlgoSHA512; + if (algo1 != null) + { + secureSecret = null; + secureSalt = null; + secureHash = null; + + return; + + // generate secure hash + var secureSecretHash = Telegram.Api.Helpers.Utils.ComputeSHA256(secret.Data); + var secureSecretHash2 = secureSecretHash.SubArray(0, 8); + secureHash = new TLLong(BitConverter.ToInt64(secureSecretHash2, 0)); + + // generate secure salt + var randomGenerator = new SecureRandom(secretRandom.Data); + var random = new byte[8]; + randomGenerator.NextBytes(random); + var newSecureSaltData = TLUtils.Combine(algo1.Salt.Data, random); + secureSalt = TLString.FromBigEndianData(newSecureSaltData); + + // generate secure secret + var sha512 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512); + var passwordHash = sha512.HashData(TLUtils.Combine(newSecureSaltData, password.Data, newSecureSaltData).AsBuffer()).ToArray(); + secureSecret = DoFinal(true, secret, passwordHash); + + return; + } + + secureSecret = null; + secureSalt = null; + secureHash = null; + } + + public static TLString DecryptSecureSecret(TLString secureSecret, TLString password, TLSecurePasswordKdfAlgoBase algoBase) + { + var algo1 = algoBase as TLSecurePasswordKdfAlgoSHA512; + if (algo1 != null) + { + var sha512 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512); + var passwordHash = sha512.HashData(TLUtils.Combine(algo1.Salt.Data, password.Data, algo1.Salt.Data).AsBuffer()).ToArray(); + + var secret = DoFinal(false, secureSecret, passwordHash); + + if (!IsGoodSecret(secret)) return null; + + return secret; + } + + var algo2 = algoBase as TLSecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000; + if (algo2 != null) + { + var passwordHash = PBKDF2.GetHash(password.Data.AsBuffer(), algo2.Salt.Data.AsBuffer()).ToArray(); + + var secret = DoFinal(false, secureSecret, passwordHash); + + if (!IsGoodSecret(secret)) return null; + + return secret; + } + + return null; + } + + private static async Task> DoFinal(bool forEncryption, string fileName, StorageFile file, byte[] hash, byte[] padding) + { + var localFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); + var inputStream = await file.OpenStreamForReadAsync(); + var outputStream = await localFile.OpenStreamForWriteAsync(); + + var secretKey = hash.SubArray(0, 32); + var iv = hash.SubArray(32, 16); + + var cipher = CipherUtilities.GetCipher("AES/CBC/NOPADDING"); + var param = new KeyParameter(secretKey); + cipher.Init(forEncryption, new ParametersWithIV(param, iv)); + + var processPadding = true; + var bytesRead = 0; + var bytesProcessed = 0; + var input = new byte[1 * 1024 * 1024]; + var output = new byte[1 * 1024 * 1024]; + + if (processPadding && forEncryption) + { + processPadding = false; + + // add random padding [32..255] + Array.Copy(padding, input, padding.Length); + bytesRead = inputStream.Read(input, padding.Length, input.Length - padding.Length) + padding.Length; + bytesProcessed = cipher.ProcessBytes(input, 0, bytesRead, output, 0); + outputStream.Write(output, 0, bytesProcessed); + } + + while ((bytesRead = inputStream.Read(input, 0, input.Length)) > 0) + { + // process padding + if (processPadding && !forEncryption) + { + processPadding = false; + + // remove random padding [32..255] + bytesProcessed = cipher.ProcessBytes(input, 0, bytesRead, output, 0); + var paddingLength = output[0]; + padding = new byte[paddingLength]; + Array.Copy(output, padding, paddingLength); + outputStream.Write(output, paddingLength, bytesProcessed - paddingLength); + } + else + { + bytesProcessed = cipher.ProcessBytes(input, 0, bytesRead, output, 0); + outputStream.Write(output, 0, bytesProcessed); + } + } + + bytesProcessed = cipher.DoFinal(output, 0); + outputStream.Write(output, 0, bytesProcessed); + + outputStream.Flush(); + outputStream.Dispose(); + inputStream.Dispose(); + + return new Tuple(localFile, padding); + } + + public static async Task EncryptFile(string fileName, StorageFile file, TLString fileSecret, TLString fileHash, byte[] padding) + { + var sha512 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512); + var secretHash = sha512.HashData(TLUtils.Combine(fileSecret.Data, fileHash.Data).AsBuffer()).ToArray(); + + var result = await DoFinal(true, fileName, file, secretHash, padding); + + return result.Item1; + } + + public static async Task> DecryptFile(string fileName, StorageFile file, TLString fileSecret, TLString fileHash) + { + var sha512 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha512); + var secretHash = sha512.HashData(TLUtils.Combine(fileSecret.Data, fileHash.Data).AsBuffer()).ToArray(); + + var result = await DoFinal(false, fileName, file, secretHash, null); + + return result; + } + + public static async Task GetSha256(byte[] padding, StorageFile file) + { + var provider = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); + var inputStream = await file.OpenSequentialReadAsync(); + uint capacity = 10 * 1024 * 1024; + var buffer = new Buffer(capacity); + var hash = provider.CreateHash(); + + if (padding != null) + { + hash.Append(padding.AsBuffer()); + } + + while (true) + { + await inputStream.ReadAsync(buffer, capacity, InputStreamOptions.None); + if (buffer.Length > 0) + hash.Append(buffer); + else + break; + } + + var hashValue = hash.GetValueAndReset(); + + inputStream.Dispose(); + + return hashValue.ToArray(); + } + + public static TLSecureCredentialsEncrypted GenerateSecureCredentialsEncrypted(IList requiredTypes, TLAuthorizationForm authorizationForm, TLString credentialsSecret, TLString secret) + { + var @switch = new Dictionary> + { + { + typeof(TLSecureValueTypePersonalDetails), + (obj, requiredType, value) => + { + obj.personal_details = new PersonalDetails + { + data = + new Data + { + data_hash = Convert.ToBase64String(value.Data.DataHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(value.Data.Secret, secret, value.Data.DataHash).Data) + } + }; + } + }, + { + typeof(TLSecureValueTypePassport), + (obj, requiredType, value) => + { + File frontSide = null; + var secureFile = value.FrontSide as TLSecureFile; + if (secureFile != null) + { + frontSide = new File + { + file_hash = Convert.ToBase64String(secureFile.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(secureFile.Secret, secret, secureFile.FileHash).Data) + }; + } + + File selfie = null; + secureFile = value.Selfie as TLSecureFile; + if (requiredType.SelfieRequired && secureFile != null) + { + selfie = new File + { + file_hash = Convert.ToBase64String(secureFile.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(secureFile.Secret, secret, secureFile.FileHash).Data) + }; + } + + List translation = null; + if (requiredType.TranslationRequired) + { + translation = new List(); + foreach (var file in value.Translation.OfType()) + { + translation.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + } + + obj.passport = new SecureCredentials.Passport + { + data = + new Data + { + data_hash = Convert.ToBase64String(value.Data.DataHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(value.Data.Secret, secret, value.Data.DataHash).Data) + }, + front_side = frontSide, + selfie = selfie, + translation = translation + }; + } + }, + { + typeof(TLSecureValueTypeInternalPassport), + (obj, requiredType, value) => + { + File frontSide = null; + var secureFile = value.FrontSide as TLSecureFile; + if (secureFile != null) + { + frontSide = new File + { + file_hash = Convert.ToBase64String(secureFile.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(secureFile.Secret, secret, secureFile.FileHash).Data) + }; + } + + File selfie = null; + secureFile = value.Selfie as TLSecureFile; + if (requiredType.SelfieRequired && secureFile != null) + { + selfie = new File + { + file_hash = Convert.ToBase64String(secureFile.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(secureFile.Secret, secret, secureFile.FileHash).Data) + }; + } + + List translation = null; + if (requiredType.TranslationRequired) + { + translation = new List(); + foreach (var file in value.Translation.OfType()) + { + translation.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + } + + obj.internal_passport = new InternalPassport + { + data = + new Data + { + data_hash = Convert.ToBase64String(value.Data.DataHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(value.Data.Secret, secret, value.Data.DataHash).Data) + }, + front_side = frontSide, + selfie = selfie, + translation = translation + }; + } + }, + { + typeof(TLSecureValueTypeDriverLicense), + (obj, requiredType, value) => + { + File frontSide = null; + var secureFile = value.FrontSide as TLSecureFile; + if (secureFile != null) + { + frontSide = new File + { + file_hash = Convert.ToBase64String(secureFile.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(secureFile.Secret, secret, secureFile.FileHash).Data) + }; + } + + File reverseSide = null; + secureFile = value.ReverseSide as TLSecureFile; + if (secureFile != null) + { + reverseSide = new File + { + file_hash = Convert.ToBase64String(secureFile.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(secureFile.Secret, secret, secureFile.FileHash).Data) + }; + } + + File selfie = null; + secureFile = value.Selfie as TLSecureFile; + if (requiredType.SelfieRequired && secureFile != null) + { + selfie = new File + { + file_hash = Convert.ToBase64String(secureFile.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(secureFile.Secret, secret, secureFile.FileHash).Data) + }; + } + + List translation = null; + if (requiredType.TranslationRequired) + { + translation = new List(); + foreach (var file in value.Translation.OfType()) + { + translation.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + } + + obj.driver_license = new DriverLicense + { + data = + new Data + { + data_hash = Convert.ToBase64String(value.Data.DataHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(value.Data.Secret, secret, value.Data.DataHash).Data) + }, + front_side = frontSide, + reverse_side = reverseSide, + selfie = selfie, + translation = translation + }; + } + }, + { + typeof(TLSecureValueTypeIdentityCard), + (obj, requiredType, value) => + { + File frontSide = null; + var secureFile = value.FrontSide as TLSecureFile; + if (secureFile != null) + { + frontSide = new File + { + file_hash = Convert.ToBase64String(secureFile.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(secureFile.Secret, secret, secureFile.FileHash).Data) + }; + } + + File reverseSide = null; + secureFile = value.ReverseSide as TLSecureFile; + if (secureFile != null) + { + reverseSide = new File + { + file_hash = Convert.ToBase64String(secureFile.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(secureFile.Secret, secret, secureFile.FileHash).Data) + }; + } + + File selfie = null; + secureFile = value.Selfie as TLSecureFile; + if (requiredType.SelfieRequired && secureFile != null) + { + selfie = new File + { + file_hash = Convert.ToBase64String(secureFile.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(secureFile.Secret, secret, secureFile.FileHash).Data) + }; + } + + List translation = null; + if (requiredType.TranslationRequired) + { + translation = new List(); + foreach (var file in value.Translation.OfType()) + { + translation.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + } + + obj.identity_card = new IdentityCard + { + data = + new Data + { + data_hash = Convert.ToBase64String(value.Data.DataHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(value.Data.Secret, secret, value.Data.DataHash).Data) + }, + front_side = frontSide, + reverse_side = reverseSide, + selfie = selfie, + translation = translation + }; + } + }, + { + typeof(TLSecureValueTypeAddress), + (obj, requiredType, value) => + { + obj.address = new Address + { + data = + new Data + { + data_hash = Convert.ToBase64String(value.Data.DataHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(value.Data.Secret, secret, value.Data.DataHash).Data) + } + }; + } + }, + { + typeof(TLSecureValueTypeUtilityBill), + (obj, requiredType, value) => + { + var files = new List(); + foreach (var file in value.Files.OfType()) + { + files.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + + List translation = null; + if (requiredType.TranslationRequired) + { + translation = new List(); + foreach (var file in value.Translation.OfType()) + { + translation.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + } + + obj.utility_bill = new UtilityBill + { + files = files, + translation = translation + }; + } + }, + { + typeof(TLSecureValueTypeBankStatement), + (obj, requiredType, value) => + { + var files = new List(); + foreach (var file in value.Files.OfType()) + { + files.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + + List translation = null; + if (requiredType.TranslationRequired) + { + translation = new List(); + foreach (var file in value.Translation.OfType()) + { + translation.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + } + + obj.bank_statement = new BankStatement + { + files = files, + translation = translation + }; + } + }, + { + typeof(TLSecureValueTypeRentalAgreement), + (obj, requiredType, value) => + { + var files = new List(); + foreach (var file in value.Files.OfType()) + { + files.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + + List translation = null; + if (requiredType.TranslationRequired) + { + translation = new List(); + foreach (var file in value.Translation.OfType()) + { + translation.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + } + + obj.rental_agreement = new RentalAgreement + { + files = files, + translation = translation + }; + } + }, + { + typeof(TLSecureValueTypePassportRegistration), + (obj, requiredType, value) => + { + var files = new List(); + foreach (var file in value.Files.OfType()) + { + files.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + + List translation = null; + if (requiredType.TranslationRequired) + { + translation = new List(); + foreach (var file in value.Translation.OfType()) + { + translation.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + } + + obj.passport_registration = new PassportRegistration + { + files = files, + translation = translation + }; + } + }, + { + typeof(TLSecureValueTypeTemporaryRegistration), + (obj, requiredType, value) => + { + var files = new List(); + foreach (var file in value.Files.OfType()) + { + files.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + + List translation = null; + if (requiredType.TranslationRequired) + { + translation = new List(); + foreach (var file in value.Translation.OfType()) + { + translation.Add(new File + { + file_hash = Convert.ToBase64String(file.FileHash.Data), + secret = Convert.ToBase64String(DecryptValueSecret(file.Secret, secret, file.FileHash).Data) + }); + } + } + + obj.temporary_registration = new TemporaryRegistration + { + files = files, + translation = translation + }; + } + } + }; + + var secureData = new SecureData(); + + foreach (var requiredType in requiredTypes) + { + if (requiredType.DataValue != null) + { + var type = requiredType.DataValue.Type.GetType(); + + if (@switch.ContainsKey(type)) + { + @switch[type](secureData, requiredType.DataRequiredType, requiredType.DataValue); + } + } + if (requiredType.DataProofValue != null) + { + var type = requiredType.DataProofValue.Type.GetType(); + + if (@switch.ContainsKey(type)) + { + @switch[type](secureData, requiredType.SelectedDataProofRequiredType, requiredType.DataProofValue); + } + } + } + + var scopeRootObject = JsonUtils.FromJSON(authorizationForm.Scope.Data); + + var rootObject = new RootObject + { + payload = scopeRootObject == null ? authorizationForm.Payload.ToString() : null, + nonce = scopeRootObject != null && scopeRootObject.v == 1 && authorizationForm.Payload != null ? authorizationForm.Payload.ToString() : null, + secure_data = secureData + }; + + var data = JsonUtils.ToJSON(rootObject); + + var secureCredentials = EncryptSecureCredentials( + new TLString(data), + credentialsSecret); + + var secureCredentialsSecret = RSAEncryption.EncryptWithPublic(credentialsSecret.Data, authorizationForm.PublicKey.ToString()); + secureCredentials.Secret = TLString.FromBigEndianData(secureCredentialsSecret); + + return secureCredentials; + } + + public static TLVector GenerateValueHashes(IList requiredTypes) + { + var result = new TLVector(); + + foreach (var requiredType in requiredTypes) + { + if (requiredType.DataValue != null) + { + result.Add(new TLSecureValueHash { Type = requiredType.DataValue.Type, Hash = requiredType.DataValue.Hash }); + } + if (requiredType.DataProofValue != null) + { + result.Add(new TLSecureValueHash { Type = requiredType.DataProofValue.Type, Hash = requiredType.DataProofValue.Hash }); + } + } + + return result; + } + + public static async Task GenerateRandomPadding(StorageFile decryptedFile) + { + byte[] padding; + var basicProperties = await decryptedFile.GetBasicPropertiesAsync(); + var inputLength = basicProperties.Size % 16; + var paddingLength = 16 - inputLength + 32; + padding = new byte[paddingLength]; + + var randomGenerator = new SecureRandom(TLString.Empty.Data); + randomGenerator.NextBytes(padding, 0, padding.Length); + padding[0] = (byte)padding.Length; + + return padding; + } + } + + namespace SecureCredentials + { + [DataContract] + public class Data + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public string data_hash { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public string secret { get; set; } + } + + [DataContract] + public class File + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public string file_hash { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public string secret { get; set; } + } + + [DataContract] + public class PersonalDetails + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public Data data { get; set; } + } + + [DataContract] + public class Passport + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public Data data { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public File front_side { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 3)] + public File selfie { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 4)] + public List translation { get; set; } + } + + [DataContract] + public class InternalPassport + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public Data data { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public File front_side { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 3)] + public File selfie { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 4)] + public List translation { get; set; } + } + + [DataContract] + public class DriverLicense + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public Data data { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public File front_side { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 3)] + public File reverse_side { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 4)] + public File selfie { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 5)] + public List translation { get; set; } + } + + [DataContract] + public class IdentityCard + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public Data data { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public File front_side { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 3)] + public File reverse_side { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 4)] + public File selfie { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 5)] + public List translation { get; set; } + } + + [DataContract] + public class Address + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public Data data { get; set; } + } + + [DataContract] + public class UtilityBill + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public List files { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public List translation { get; set; } + } + + [DataContract] + public class BankStatement + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public List files { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public List translation { get; set; } + } + + [DataContract] + public class RentalAgreement + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public List files { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public List translation { get; set; } + } + + [DataContract] + public class PassportRegistration + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public List files { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public List translation { get; set; } + } + + [DataContract] + public class TemporaryRegistration + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public List files { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public List translation { get; set; } + } + + [DataContract] + public class SecureData + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public PersonalDetails personal_details { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public Passport passport { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 3)] + public InternalPassport internal_passport { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 4)] + public DriverLicense driver_license { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 5)] + public IdentityCard identity_card { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 6)] + public Address address { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 7)] + public UtilityBill utility_bill { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 8)] + public BankStatement bank_statement { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 9)] + public RentalAgreement rental_agreement { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 10)] + public PassportRegistration passport_registration { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 11)] + public TemporaryRegistration temporary_registration { get; set; } + } + + [DataContract] + public class RootObject + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public SecureData secure_data { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public string payload { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 3)] + public string nonce { get; set; } + } + + [DataContract] + public class ScopeRootObject + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public List data { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public int v { get; set; } + } + } + + public static class RSAEncryption + { + public static byte[] EncryptWithPublic(byte[] bytesToEncrypt, string publicKey) + { + var encryptEngine = new OaepEncoding(new RsaEngine(), new Sha1Digest()); + + using (var txtreader = new StringReader(publicKey)) + { + var keyParameter = (AsymmetricKeyParameter)new PemReader(txtreader).ReadObject(); + + encryptEngine.Init(true, keyParameter); + } + + var encrypted = encryptEngine.ProcessBlock(bytesToEncrypt, 0, bytesToEncrypt.Length); + return encrypted; + + } + + public static byte[] EncryptWithPrivate(byte[] bytesToEncrypt, string privateKey) + { + var encryptEngine = new OaepEncoding(new RsaEngine(), new Sha1Digest()); + + using (var txtreader = new StringReader(privateKey)) + { + var keyPair = (AsymmetricCipherKeyPair)new PemReader(txtreader).ReadObject(); + + encryptEngine.Init(true, keyPair.Private); + } + + var encrypted = encryptEngine.ProcessBlock(bytesToEncrypt, 0, bytesToEncrypt.Length); + return encrypted; + } + } + + public static class JsonUtils + { + public static string ToJSON(object rootObject) + { + try + { + var stream = new MemoryStream(); + + var ser = new DataContractJsonSerializer(rootObject.GetType()); + ser.WriteObject(stream, rootObject); + stream.Position = 0; + var sr = new StreamReader(stream); + + return sr.ReadToEnd(); + } + catch (Exception) + { + return null; + } + } + + public static T FromJSON(byte[] data) where T : class + { + try + { + var serializer = new DataContractJsonSerializer(typeof(T)); + using (var stream = new MemoryStream(data)) + { + return serializer.ReadObject(stream) as T; + } + } + catch (Exception) + { + return null; + } + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Utils/Password.cs b/TelegramClient.WP81/Utils/Password.cs new file mode 100755 index 0000000..ad77d23 --- /dev/null +++ b/TelegramClient.WP81/Utils/Password.cs @@ -0,0 +1,188 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Security.Cryptography.Core; +using Windows.Storage.Streams; +using Org.BouncyCastle.Security; +using Telegram.Api.TL; + +namespace TelegramClient.Utils +{ + static class Password + { + public static TLString GetHash(TLString currentSalt, TLString password) + { + var passwordHash = Telegram.Api.Helpers.Utils.ComputeSHA256(TLUtils.Combine(currentSalt.Data, password.Data, currentSalt.Data)); + + return TLString.FromBigEndianData(passwordHash); + } + + public static TLString GetHash(TLPasswordBase passwordBase, TLString pwd) + { + var password83 = passwordBase as TLPassword83; + if (password83 != null) + { + return GetNewHash(password83.CurrentAlgo, pwd); + } + + var password = passwordBase as TLPassword; + if (password != null) + { + return GetHash(password.CurrentSalt, pwd); + } + + return null; + } + + public static TLString GetOldHash(TLPasswordKdfAlgoBase kdfAlgoBase, TLString password) + { + var algo = kdfAlgoBase as TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow; + if (algo != null) + { + var salt1 = algo.Salt1; + + var hash1 = GetHash(salt1, password); + + return hash1; + } + + return null; + } + + public static TLString GetNewHash(TLPasswordKdfAlgoBase kdfAlgoBase, TLString password) + { + var algo = kdfAlgoBase as TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow; + if (algo != null) + { + var salt1 = algo.Salt1; + var salt2 = algo.Salt2; + + var hash1 = GetHash(salt1, password); + var hash2 = GetHash(salt2, hash1); + var hash3 = PBKDF2.GetHash(hash2.Data.AsBuffer(), salt1.Data.AsBuffer()); + var hash4 = GetHash(salt2, TLString.FromBigEndianData(hash3.ToArray())); + + return hash4; + } + + return null; + } + + public static void AddClientSalt(TLPasswordKdfAlgoBase algoBase) + { + var algo = algoBase as TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow; + if (algo == null) return; + + var secureRandom = new SecureRandom(); + var clientSalt1 = new byte[32]; + secureRandom.NextBytes(clientSalt1); + + var newSalt1Data = TLUtils.Combine(algo.Salt1.Data, clientSalt1); + var newSalt1 = TLString.FromBigEndianData(newSalt1Data); + + algo.Salt1 = newSalt1; + } + + public static void AddRandomSecureSecret(TLPasswordInputSettings83 inputSettings, IPasswordSecret passwordSecret, TLString password) + { + var secret = Passport.GenerateSecret(passwordSecret.SecretRandom); + + var newSecureAlgo = passwordSecret.NewSecureAlgo as TLSecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000; + if (newSecureAlgo == null) return; + + TLString newSecureSalt; + TLString newSecureSecret; + TLLong newSecureSecretId; + Passport.EncryptSecret(out newSecureSecret, out newSecureSalt, out newSecureSecretId, secret, passwordSecret.SecretRandom, newSecureAlgo, password); + + inputSettings.NewSecureSettings = new TLSecureSecretSettings + { + SecureAlgo = new TLSecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000 { Salt = newSecureSalt }, + SecureSecret = newSecureSecret, + SecureSecretId = newSecureSecretId + }; + + //inputSettings.NewSecureSalt = newSecureSalt; + //inputSettings.NewSecureSecret = newSecureSecret; + //inputSettings.NewSecureSecretId = newSecureSecretId; + } + + public static void AddSecureSecret(TLString secret, TLPasswordInputSettings83 inputSettings, IPasswordSecret passwordSecret, TLString password) + { + var newSecureAlgo = passwordSecret.NewSecureAlgo as TLSecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000; + if (newSecureAlgo == null) return; + + TLString newSecureSalt; + TLString newSecureSecret; + TLLong newSecureSecretId; + Passport.EncryptSecret(out newSecureSecret, out newSecureSalt, out newSecureSecretId, secret, passwordSecret.SecretRandom, newSecureAlgo, password); + + inputSettings.NewSecureSettings = new TLSecureSecretSettings + { + SecureAlgo = new TLSecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000 { Salt = newSecureSalt }, + SecureSecret = newSecureSecret, + SecureSecretId = newSecureSecretId + }; + + //inputSettings.NewSecureSalt = newSecureSalt; + //inputSettings.NewSecureSecret = newSecureSecret; + //inputSettings.NewSecureSecretId = newSecureSecretId; + } + } + + public class PBKDF2 + { + /** + * The algorithm to use + * @var string algorithm + */ + private static string _algorithm = KeyDerivationAlgorithmNames.Pbkdf2Sha512; + + /** + * Generate a PBDFK hash + * @param string password + * @param string salt + * @param string algorithm + * @param uint iterationCountIn + * @param uint target size + */ + public static IBuffer GetHash(IBuffer buffSecret, IBuffer buffSalt, uint targetSize = 64, uint iterationCountIn = 100000, string algorithm = null) + { + // Use the provide KeyDerivationAlgorithm if provided, otherwise default to PBKDF2-SHA256 + if (algorithm == null) + algorithm = _algorithm; + + KeyDerivationAlgorithmProvider provider = KeyDerivationAlgorithmProvider.OpenAlgorithm(algorithm); + + // This is our secret password + //IBuffer buffSecret = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8); + + // Use the provided salt + //IBuffer buffSalt = CryptographicBuffer.ConvertStringToBinary(salt, BinaryStringEncoding.Utf8); + + // Create the derivation parameters. + KeyDerivationParameters pbkdf2Params = KeyDerivationParameters.BuildForPbkdf2(buffSalt, iterationCountIn); + + // Create a key from the secret value. + CryptographicKey keyOriginal = provider.CreateKey(buffSecret); + + // Derive a key based on the original key and the derivation parameters. + IBuffer keyDerived = CryptographicEngine.DeriveKeyMaterial( + keyOriginal, + pbkdf2Params, + targetSize + ); + + return keyDerived; + + // Encode the key to a hexadecimal value (for display) + // return CryptographicBuffer.EncodeToHexString(keyDerived); + } + } +} diff --git a/TelegramClient.WP81/Utils/SRP.cs b/TelegramClient.WP81/Utils/SRP.cs new file mode 100755 index 0000000..4263228 --- /dev/null +++ b/TelegramClient.WP81/Utils/SRP.cs @@ -0,0 +1,156 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Telegram.Api.TL; + +namespace TelegramClient.Utils +{ + static class SRP + { + /// to big-endian data + public static byte[] GetBigIntegerBytes(BigInteger value) + { + byte[] bytes = value.ToByteArray(); + if (bytes.Length > 256) + { + byte[] correctedAuth = new byte[256]; + System.Array.Copy(bytes, 1, correctedAuth, 0, 256); + return correctedAuth; + } + if (bytes.Length < 256) + { + byte[] correctedAuth = new byte[256]; + System.Array.Copy(bytes, 0, correctedAuth, 256 - bytes.Length, bytes.Length); + for (int a = 0; a < 256 - bytes.Length; a++) + { + correctedAuth[a] = 0; + } + return correctedAuth; + } + return bytes; + } + + public static TLString GetX(TLString password, TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow algo) + { + var x_bytes = Telegram.Api.Helpers.Utils.ComputeSHA256(TLUtils.Combine(algo.Salt1.Data, password.Data, algo.Salt1.Data)); + x_bytes = Telegram.Api.Helpers.Utils.ComputeSHA256(TLUtils.Combine(algo.Salt2.Data, x_bytes, algo.Salt2.Data)); + x_bytes = PBKDF2.GetHash(x_bytes.AsBuffer(), algo.Salt1.Data.AsBuffer()).ToArray(); + x_bytes = Telegram.Api.Helpers.Utils.ComputeSHA256(TLUtils.Combine(algo.Salt2.Data, x_bytes, algo.Salt2.Data)); + + return TLString.FromBigEndianData(x_bytes); + } + + private static BigInteger GetV(TLString passwordBytes, TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow algo) + { + var g = BigInteger.ValueOf(algo.G.Value); + var p = new BigInteger(1, algo.P.Data); + + var x_bytes = GetX(passwordBytes, algo); + var x = new BigInteger(1, x_bytes.Data); + + return g.ModPow(x, p); + } + + public static TLString GetVBytes(TLString passwordBytes, TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow algo) + { + if (!TLUtils.CheckPrime(algo.P.Data, algo.G.Value)) + { + return null; + } + + return TLString.FromBigEndianData(GetBigIntegerBytes(GetV(passwordBytes, algo))); + } + + public static TLInputCheckPasswordBase GetCheck(TLString xStr, TLLong srpId, TLString srpB, TLPasswordKdfAlgoBase algoBase) + { + var algo = algoBase as TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow; + if (algo != null) + { + if (xStr == null || srpB == null || srpB.Data.Length == 0 || !TLUtils.CheckPrime(algo.P.Data, algo.G.Value)) + { + return new TLInputCheckPasswordEmpty(); + } + + var g = new BigInteger(1, algo.G.ToBytes().Reverse().ToArray()); // from big-endian to BI (ToBytes - little endian output) + var g_bytes = GetBigIntegerBytes(g); + + var p = new BigInteger(1, algo.P.Data); + var p_bytes = GetBigIntegerBytes(p); + + var k_bytes = Telegram.Api.Helpers.Utils.ComputeSHA256(TLUtils.Combine(p_bytes, g_bytes)); + var k = new BigInteger(1, k_bytes); + + var x = new BigInteger(1, xStr.Data); + + var a_bytes = new byte[256]; + var secureRandom = new SecureRandom(); + secureRandom.NextBytes(a_bytes); + var a = new BigInteger(1, a_bytes); + + var A = g.ModPow(a, p); + var A_bytes = GetBigIntegerBytes(A); + + var B = new BigInteger(1, srpB.Data); + if (B.CompareTo(BigInteger.Zero) <= 0 || B.CompareTo(p) >= 0) + { + return null; + } + var B_bytes = GetBigIntegerBytes(B); + + var u_bytes = Telegram.Api.Helpers.Utils.ComputeSHA256(TLUtils.Combine(A_bytes, B_bytes)); + var u = new BigInteger(1, u_bytes); + if (u.CompareTo(BigInteger.Zero) == 0) + { + return null; + } + + var B_kgx = B.Subtract(k.Multiply(g.ModPow(x, p)).Mod(p)); + if (B_kgx.CompareTo(BigInteger.Zero) < 0) + { + B_kgx = B_kgx.Add(p); + } + if (!TLUtils.CheckGaAndGb(B_kgx, p)) + { + return null; + } + var S = B_kgx.ModPow(a.Add(u.Multiply(x)), p); + var S_bytes = GetBigIntegerBytes(S); + + var K_bytes = Telegram.Api.Helpers.Utils.ComputeSHA256(S_bytes); + + var p_hash = Telegram.Api.Helpers.Utils.ComputeSHA256(algo.P.Data); + var g_hash = Telegram.Api.Helpers.Utils.ComputeSHA256(g_bytes); + for (var i = 0; i < p_hash.Length; i++) + { + p_hash[i] = (byte)(g_hash[i] ^ p_hash[i]); + } + + var M1 = Telegram.Api.Helpers.Utils.ComputeSHA256(TLUtils.Combine( + p_hash, + Telegram.Api.Helpers.Utils.ComputeSHA256(algo.Salt1.Data), + Telegram.Api.Helpers.Utils.ComputeSHA256(algo.Salt2.Data), + A_bytes, + B_bytes, + K_bytes)); + + return new TLInputCheckPasswordSRP + { + SRPId = srpId, + A = TLString.FromBigEndianData(A_bytes), + M1 = TLString.FromBigEndianData(M1) + }; + } + + return new TLInputCheckPasswordEmpty(); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Additional/BioViewModel.cs b/TelegramClient.WP81/ViewModels/Additional/BioViewModel.cs new file mode 100755 index 0000000..52089a9 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Additional/BioViewModel.cs @@ -0,0 +1,60 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Services; + +namespace TelegramClient.ViewModels.Additional +{ + public class BioViewModel : ViewModelBase + { + public string About { get; set; } + + private TLUser45 _currentUser; + + public BioViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _currentUser = stateService.CurrentContact as TLUser45; + stateService.CurrentContact = null; + + About = _currentUser != null && _currentUser.About != null ? _currentUser.About.ToString() : string.Empty; + } + + public void Done() + { + if (IsWorking) return; + + //_currentUser.About = new TLString(About); + //_currentUser.NotifyOfPropertyChange(() => _currentUser.About); + //NavigationService.GoBack(); + //return; + IsWorking = true; + MTProtoService.UpdateProfileAsync(null, null, new TLString(About), + user => BeginOnUIThread(() => + { + IsWorking = false; + _currentUser.About = new TLString(About); + _currentUser.NotifyOfPropertyChange(() => _currentUser.About); + NavigationService.GoBack(); + }), + error => BeginOnUIThread(() => + { + IsWorking = false; + })); + } + + public void Cancel() + { + NavigationService.GoBack(); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Additional/CallsPrivacyViewModel.cs b/TelegramClient.WP81/ViewModels/Additional/CallsPrivacyViewModel.cs new file mode 100755 index 0000000..0c18499 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Additional/CallsPrivacyViewModel.cs @@ -0,0 +1,357 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Windows; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.Services; +using Execute = Telegram.Api.Helpers.Execute; +using Language = TelegramClient.Utils.Language; + +namespace TelegramClient.ViewModels.Additional +{ + public class CallsPrivacyViewModel : ViewModelBase, Telegram.Api.Aggregator.IHandle + { + private string _allowUsersSubtitle = AppResources.NoUsers; + + public string AllowUsersSubtitle + { + get { return _allowUsersSubtitle; } + set { SetField(ref _allowUsersSubtitle, value, () => AllowUsersSubtitle); } + } + + private Visibility _allowUsersVisibility; + + public Visibility AllowUsersVisibility + { + get { return _allowUsersVisibility; } + set { SetField(ref _allowUsersVisibility, value, () => AllowUsersVisibility); } + } + + private string _disallowUsersSubtitle = AppResources.NoUsers; + + public string DisallowUsersSubtitle + { + get { return _disallowUsersSubtitle; } + set { SetField(ref _disallowUsersSubtitle, value, () => DisallowUsersSubtitle); } + } + + private Visibility _disallowUsersVisibility; + + public Visibility DisallowUsersVisibility + { + get { return _disallowUsersVisibility; } + set { SetField(ref _disallowUsersVisibility, value, () => DisallowUsersVisibility); } + } + + private TLPrivacyRuleBase _selectedMainRule; + + public TLPrivacyRuleBase SelectedMainRule + { + get { return _selectedMainRule; } + set { SetField(ref _selectedMainRule, value, () => SelectedMainRule); } + } + + public List MainRules { get; set; } + + private TLPrivacyRules _rules; + private TLPrivacyValueAllowUsers _selectedAllowUsers; + private TLPrivacyValueDisallowUsers _selectedDisallowUsers; + + public CallsPrivacyViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + EventAggregator.Subscribe(this); + + _rules = StateService.PrivacyRules; + StateService.PrivacyRules = null; + + MainRules = new List + { + new TLPrivacyValueAllowAll{ Label = AppResources.Everybody }, + new TLPrivacyValueAllowContacts{ Label = AppResources.MyContacts }, + new TLPrivacyValueDisallowAll{ Label = AppResources.Nobody } + }; + + _selectedMainRule = GetSelectedMainRule(MainRules, _rules, MainRules[0], MainRules[2]); + _selectedMainRule.IsChecked = true; + _selectedAllowUsers = GetSelectedRule(_rules) ?? new TLPrivacyValueAllowUsers { Users = new TLVector() }; + _selectedDisallowUsers = GetSelectedRule(_rules) ?? new TLPrivacyValueDisallowUsers { Users = new TLVector() }; + SwitchUsersVisibility(true); + PropertyChanged += OnPropertyChanged; + } + + protected override void OnActivate() + { + BeginOnThreadPool(() => + { + if (StateService.UsersRule != null) + { + var allowUsersRule = StateService.UsersRule as TLPrivacyValueAllowUsers; + if (allowUsersRule != null) + { + _selectedAllowUsers = allowUsersRule; + + CleanupUsers(_selectedAllowUsers, _selectedDisallowUsers); + } + var disallowUsersRule = StateService.UsersRule as TLPrivacyValueDisallowUsers; + if (disallowUsersRule != null) + { + _selectedDisallowUsers = disallowUsersRule; + + CleanupUsers(_selectedDisallowUsers, _selectedAllowUsers); + } + StateService.UsersRule = null; + } + + UpdateSubtitles(); + }); + + base.OnActivate(); + } + + private void CleanupUsers(IPrivacyValueUsersRule sourceList, IPrivacyValueUsersRule cleaningList) + { + var sourceDict = new Dictionary(); + foreach (var userId in sourceList.Users) + { + sourceDict[userId.Value] = userId.Value; + } + + for (var i = 0; i < cleaningList.Users.Count; i++) + { + if (sourceDict.ContainsKey(cleaningList.Users[i].Value)) + { + cleaningList.Users.RemoveAt(i--); + } + } + } + + private void UpdateSubtitles() + { + var allowCount = _selectedAllowUsers.Users.Count; + + AllowUsersSubtitle = allowCount == 0 + ? AppResources.NoUsers + : Language.Declension( + allowCount, + AppResources.UserNominativeSingular, + AppResources.UserNominativePlural, + AppResources.UserGenitiveSingular, + AppResources.UserGenitivePlural).ToLower(CultureInfo.CurrentUICulture); + + var disallowCount = _selectedDisallowUsers.Users.Count; + + DisallowUsersSubtitle = disallowCount == 0 + ? AppResources.NoUsers + : Language.Declension( + disallowCount, + AppResources.UserNominativeSingular, + AppResources.UserNominativePlural, + AppResources.UserGenitiveSingular, + AppResources.UserGenitivePlural).ToLower(CultureInfo.CurrentUICulture); + } + + private T GetSelectedRule(TLPrivacyRules rules) where T : TLPrivacyRuleBase + { + T allowUsers = null; + if (_rules != null) + { + allowUsers = (T)rules.Rules.FirstOrDefault(x => x is T); + } + + return allowUsers; + } + + private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => SelectedMainRule)) + { + SwitchUsersVisibility(false); + } + } + + private void SwitchUsersVisibility(bool silent) + { + if (SelectedMainRule is TLPrivacyValueAllowAll) + { + _allowUsersVisibility = Visibility.Collapsed; + _disallowUsersVisibility = Visibility.Visible; + } + + if (SelectedMainRule is TLPrivacyValueAllowContacts) + { + _allowUsersVisibility = Visibility.Visible; + _disallowUsersVisibility = Visibility.Visible; + } + + if (SelectedMainRule is TLPrivacyValueDisallowAll) + { + _allowUsersVisibility = Visibility.Visible; + _disallowUsersVisibility = Visibility.Collapsed; + } + + if (!silent) + { + NotifyOfPropertyChange(() => AllowUsersVisibility); + NotifyOfPropertyChange(() => DisallowUsersVisibility); + } + } + + public void OpenAllowUsers() + { + var allowUsersRule = _rules != null ? _rules.Rules.FirstOrDefault(x => x is TLPrivacyValueAllowUsers) : null; + + //if (allowUsersRule == null) + //{ + // NavigationService.UriFor().Navigate(); + //} + //else + { + StateService.UsersRule = _selectedAllowUsers; + NavigationService.UriFor().Navigate(); + } + } + + public void OpenDisallowUsers() + { + var disallowUsersRule = _rules != null ? _rules.Rules.FirstOrDefault(x => x is TLPrivacyValueDisallowUsers) : null; + + //if (allowUsersRule == null) + //{ + // NavigationService.UriFor().Navigate(); + //} + //else + { + StateService.UsersRule = _selectedDisallowUsers; + NavigationService.UriFor().Navigate(); + } + } + + private TLPrivacyRuleBase GetSelectedMainRule(List mainRules, TLPrivacyRules rules, TLPrivacyRuleBase defaultRule, TLPrivacyRuleBase noRules) + { + if (rules == null) + { + + } + else + { + foreach (var rule in rules.Rules) + { + var mainRule = mainRules.FirstOrDefault(x => x.GetType() == rule.GetType()); + if (mainRule != null) + { + return mainRule; + } + } + + return noRules; + } + + return defaultRule; + } + + public void Done() + { + if (SelectedMainRule == null) return; + + var rules = new TLVector(); + + if (_selectedDisallowUsers != null + && _selectedDisallowUsers.Users != null + && _selectedDisallowUsers.Users.Count > 0) + { + var inputDisallowUsers = (TLInputPrivacyValueDisallowUsers)_selectedDisallowUsers.ToInputRule(); + + foreach (var userId in _selectedDisallowUsers.Users) + { + var user = CacheService.GetUser(userId); + + if (user != null) + { + inputDisallowUsers.Users.Add(user.ToInputUser()); + } + } + + rules.Add(inputDisallowUsers); + } + + if (_selectedAllowUsers != null + && _selectedAllowUsers.Users != null + && _selectedAllowUsers.Users.Count > 0) + { + var inputAllowUsers = (TLInputPrivacyValueAllowUsers)_selectedAllowUsers.ToInputRule(); + + foreach (var userId in _selectedAllowUsers.Users) + { + var user = CacheService.GetUser(userId); + + if (user != null) + { + inputAllowUsers.Users.Add(user.ToInputUser()); + } + } + + rules.Add(inputAllowUsers); + } + + var inputMainRule = SelectedMainRule.ToInputRule(); + rules.Add(inputMainRule); + + IsWorking = true; + MTProtoService.SetPrivacyAsync(new TLInputPrivacyKeyPhoneCall(), + rules, + result => + { + IsWorking = false; + + //EventAggregator.Publish(new TLUpdatePrivacy{Key = new TLPrivacyKeyStatusTimestamp(), Rules = result.Rules}); + BeginOnUIThread(() => NavigationService.GoBack()); + }, + error => + { + IsWorking = false; + if (error.CodeEquals(ErrorCode.FLOOD)) + { + MessageBox.Show(AppResources.FloodWaitString + Environment.NewLine + "(" + error.Message + ")", AppResources.Error, MessageBoxButton.OK); + } + + Execute.ShowDebugMessage("account.setPrivacy error " + error); + }); + } + + public void Cancel() + { + NavigationService.GoBack(); + } + + public void Handle(TLUpdatePrivacy privacy) + { + if (privacy.Key is TLPrivacyKeyPhoneCall) + { + _rules = new TLPrivacyRules { Rules = privacy.Rules }; + + SelectedMainRule = GetSelectedMainRule(MainRules, _rules, MainRules[0], MainRules[2]); + _selectedAllowUsers = GetSelectedRule(_rules) ?? new TLPrivacyValueAllowUsers { Users = new TLVector() }; + _selectedDisallowUsers = GetSelectedRule(_rules) ?? new TLPrivacyValueDisallowUsers { Users = new TLVector() }; + SwitchUsersVisibility(false); + + UpdateSubtitles(); + } + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Additional/CallsSecurityViewModel.cs b/TelegramClient.WP81/ViewModels/Additional/CallsSecurityViewModel.cs new file mode 100755 index 0000000..2d56ab0 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Additional/CallsSecurityViewModel.cs @@ -0,0 +1,40 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Services; + +namespace TelegramClient.ViewModels.Additional +{ + public class CallsSecurityViewModel : ViewModelBase + { + private TLCallsSecurity _callsSecurity; + + public TLCallsSecurity CallsSecurity + { + get { return _callsSecurity; } + set { SetField(ref _callsSecurity, value, () => CallsSecurity); } + } + + public CallsSecurityViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _callsSecurity = StateService.GetCallsSecurity(true); + } + + protected override void OnDeactivate(bool close) + { + base.OnDeactivate(close); + + StateService.SaveCallsSecurity(_callsSecurity); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Additional/CameraViewModel.cs b/TelegramClient.WP81/ViewModels/Additional/CameraViewModel.cs new file mode 100755 index 0000000..70049a1 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Additional/CameraViewModel.cs @@ -0,0 +1,64 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using System.ComponentModel; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.Services; + +namespace TelegramClient.ViewModels.Additional +{ + public class CameraViewModel : ViewModelBase + { + private TLPrivacyRuleBase _selectedMainRule; + + public TLPrivacyRuleBase SelectedMainRule + { + get { return _selectedMainRule; } + set { SetField(ref _selectedMainRule, value, () => SelectedMainRule); } + } + + public List MainRules { get; set; } + + private TLCameraSettings _settings; + + public CameraViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _settings = StateService.GetCameraSettings(); + + MainRules = new List + { + new TLPrivacyValueAllowAll{ Label = AppResources.InAppCamera }, + new TLPrivacyValueAllowContacts{ Label = AppResources.ExternalCamera } + }; + + _selectedMainRule = _settings.External ? MainRules[1] : MainRules[0]; + _selectedMainRule.IsChecked = true; + + PropertyChanged += OnPropertyChanged; + } + + private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) + { + + } + + protected override void OnDeactivate(bool close) + { + _settings.External = SelectedMainRule == MainRules[1]; + StateService.SaveCameraSettings(_settings); + + base.OnDeactivate(close); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Additional/ChooseGeoLivePeriodViewModel.cs b/TelegramClient.WP81/ViewModels/Additional/ChooseGeoLivePeriodViewModel.cs new file mode 100755 index 0000000..b46a911 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Additional/ChooseGeoLivePeriodViewModel.cs @@ -0,0 +1,64 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Linq; +using Caliburn.Micro; +using TelegramClient.Services; +using TelegramClient.ViewModels.Contacts; + +namespace TelegramClient.ViewModels.Additional +{ + public class ChooseGeoLivePeriodViewModel : Screen + { + public LoopingObservableCollection Items { get; private set; } + + private readonly IStateService _stateService; + + public string Subtitle { get; set; } + + public ChooseGeoLivePeriodViewModel(IStateService stateService) + { + _stateService = stateService; + + var selectedTimerSpan = _stateService.SelectedTimerSpan; + _stateService.SelectedTimerSpan = null; + + var timerSpans = _stateService.TimerSpans; + _stateService.TimerSpans = null; + + TimerSpan defaultSpan = null; + Items = new LoopingObservableCollection(); + if (timerSpans != null) + { + foreach (var timerSpan in timerSpans) + { + Items.Add(timerSpan); + } + } + defaultSpan = Items[0]; + + if (selectedTimerSpan != null) + { + Items.SelectedItem = Items.FirstOrDefault(x => x.Seconds == selectedTimerSpan.Seconds); + } + if (Items.SelectedItem == null) + { + Items.SelectedItem = defaultSpan; + } + } + + public void Done() + { + _stateService.SelectedTimerSpan = (TimerSpan)Items.SelectedItem; + } + + public void Cancel() + { + + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/ViewModels/Additional/ChooseVideoQualityViewModel.cs b/TelegramClient.WP81/ViewModels/Additional/ChooseVideoQualityViewModel.cs new file mode 100755 index 0000000..2561403 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Additional/ChooseVideoQualityViewModel.cs @@ -0,0 +1,74 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Linq; +using Caliburn.Micro; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Contacts; + +namespace TelegramClient.ViewModels.Additional +{ + public class ChooseVideoQualityViewModel : Screen + { + public LoopingObservableCollection Items { get; private set; } + + private readonly IStateService _stateService; + + public string Subtitle { get; set; } + + public ChooseVideoQualityViewModel(IStateService stateService) + { + _stateService = stateService; + + var selectedTimerSpan = _stateService.SelectedTimerSpan; + _stateService.SelectedTimerSpan = null; + + var timerSpans = _stateService.TimerSpans; + _stateService.TimerSpans = null; + + TimerSpan defaultSpan = null; + Items = new LoopingObservableCollection(); + if (timerSpans != null) + { + foreach (var timerSpan in timerSpans) + { + Items.Add(timerSpan); + } + } + else + { + Items.Add(new TimerSpan(string.Empty, AppResources.Auto, 0)); + Items.Add(new TimerSpan(string.Empty, "240", 240)); + Items.Add(new TimerSpan(string.Empty, "360", 360)); + Items.Add(new TimerSpan(string.Empty, "480", 480)); + Items.Add(new TimerSpan(string.Empty, "720", 720)); + Items.Add(new TimerSpan(string.Empty, "1080", 1080)); + } + defaultSpan = Items[0]; + + if (selectedTimerSpan != null) + { + Items.SelectedItem = Items.FirstOrDefault(x => x.Seconds == selectedTimerSpan.Seconds); + } + if (Items.SelectedItem == null) + { + Items.SelectedItem = defaultSpan; + } + } + + public void Done() + { + _stateService.SelectedTimerSpan = (TimerSpan)Items.SelectedItem; + } + + public void Cancel() + { + + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Additional/ContactsSecurityViewModel.cs b/TelegramClient.WP81/ViewModels/Additional/ContactsSecurityViewModel.cs new file mode 100755 index 0000000..f513993 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Additional/ContactsSecurityViewModel.cs @@ -0,0 +1,127 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Windows.ApplicationModel.Contacts; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Contacts; + +namespace TelegramClient.ViewModels.Additional +{ + public class ContactsSecurityViewModel : ViewModelBase + { + protected string _syncContactsSubtitle; + + public string SyncContactsSubtitle + { + get { return _syncContactsSubtitle; } + set { SetField(ref _syncContactsSubtitle, value, () => SyncContactsSubtitle); } + } + + protected string _syncContactsHint; + + public string SyncContactsHint + { + get { return _syncContactsHint; } + set { SetField(ref _syncContactsHint, value, () => SyncContactsHint); } + } + + protected bool _suggestFrequentContacts; + + public bool SuggestFrequentContacts + { + get { return _suggestFrequentContacts; } + set { SetField(ref _suggestFrequentContacts, value, () => SuggestFrequentContacts); } + } + + public ContactsSecurityViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _suggestFrequentContacts = StateService.GetTopPeers() is TLTopPeers; + + PropertyChanged += (sender, args) => + { + if (Property.NameEquals(args.PropertyName, () => SuggestFrequentContacts)) + { + if (!SuggestFrequentContacts) + { + ShellViewModel.ShowCustomMessageBox( + AppResources.SuggestFrequentContactsNotification, + AppResources.AppName, + AppResources.Ok, null, + dismissed => + { + + }); + } + + MTProtoService.ToggleTopPeersAsync( + new TLBool(SuggestFrequentContacts), + result => Execute.BeginOnUIThread(() => + { + if (!SuggestFrequentContacts) + { + StateService.SaveTopPeers(new TLTopPeersDisabled()); + EventAggregator.Publish(new ClearTopPeersEventArgs()); + } + })); + } + }; + } + + protected override void OnActivate() + { + EventAggregator.Subscribe(this); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(async () => + { + var contactStore = await ContactManager.RequestStoreAsync(); + SyncContactsSubtitle = contactStore != null ? AppResources.Enabled : AppResources.Disabled; + SyncContactsHint = contactStore != null + ? AppResources.SyncContactsInfoOn + : AppResources.SyncContactsInfoOff; + }); + } + + protected override void OnDeactivate(bool close) + { + EventAggregator.Unsubscribe(this); + } + + public void DeleteSyncedContacts() + { + ShellViewModel.ShowCustomMessageBox( + AppResources.DeleteSyncedContactsConfirmation, AppResources.AppName, + AppResources.Ok.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + EventAggregator.Publish(new InvokeDeleteContacts()); + } + }); + } + + public async void SyncContacts() + { + await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-contacts")); + } + } + + public class ClearTopPeersEventArgs + { + + } +} diff --git a/TelegramClient.WP81/ViewModels/Additional/LoggedInViewModel.cs b/TelegramClient.WP81/ViewModels/Additional/LoggedInViewModel.cs new file mode 100755 index 0000000..7df468e --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Additional/LoggedInViewModel.cs @@ -0,0 +1,239 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Threading; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.Services; +using Execute = Telegram.Api.Helpers.Execute; + +namespace TelegramClient.ViewModels.Additional +{ + public class LoggedInViewModel : ItemsViewModelBase + { + public bool IsEmptyList { get; protected set; } + + public string EmptyListImageSource + { + get + { + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + + if (isLightTheme) + { + return "/Images/Settings/noapps.white-WXGA.png"; + } + + return "/Images/Settings/noapps.black-WXGA.png"; + } + } + + private readonly DispatcherTimer _getAuthorizationsTimer = new DispatcherTimer(); + + private void StartTimer() + { + _getAuthorizationsTimer.Start(); + } + + private void StopTimer() + { + _getAuthorizationsTimer.Stop(); + } + + public LoggedInViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _getAuthorizationsTimer.Tick += OnGetAuthorizations; + _getAuthorizationsTimer.Interval = TimeSpan.FromSeconds(10.0); + + EventAggregator.Subscribe(this); + + Status = AppResources.Loading; + + UpdateSessionsAsync(); + } + + private void OnGetAuthorizations(object sender, System.EventArgs e) + { + UpdateSessionsAsync(); + } + + protected override void OnActivate() + { + StartTimer(); + + base.OnActivate(); + } + + protected override void OnDeactivate(bool close) + { + StopTimer(); + + base.OnDeactivate(close); + } + + private Dictionary _authorizationsCache = new Dictionary(); + + private bool _firstRun = true; + + private void UpdateSessionsAsync() + { + BeginOnThreadPool(() => + { + IsWorking = true; + MTProtoService.GetWebAuthorizationsAsync( + result => Execute.BeginOnUIThread(() => + { + Status = string.Empty; + IsEmptyList = result.Authorizations.Count == 0; + NotifyOfPropertyChange(() => IsEmptyList); + IsWorking = false; + + if (_firstRun) + { + _firstRun = false; + Items.Clear(); + var firstChunkSize = 4; + var count = 0; + var delayedItems = new List(); + for (var i = 0; i < result.Authorizations.Count; i++) + { + var authorization = result.Authorizations[i]; + _authorizationsCache[authorization.Hash.Value] = authorization; + if (count < firstChunkSize) + { + Items.Add(authorization); + count++; + } + else + { + delayedItems.Add(authorization); + } + } + + BeginOnUIThread(TimeSpan.FromSeconds(0.5), () => + { + foreach (var authorization in delayedItems) + { + Items.Add(authorization); + } + }); + } + else + { + var newAuthorizationsCache = new Dictionary(); + var itemsToAdd = new List(); + for (var i = 0; i < result.Authorizations.Count; i++) + { + var authorization = result.Authorizations[i]; + TLWebAuthorization cachedAuthorization; + if (!_authorizationsCache.TryGetValue(authorization.Hash.Value, out cachedAuthorization)) + { + itemsToAdd.Add(authorization); + newAuthorizationsCache[authorization.Hash.Value] = authorization; + } + else + { + cachedAuthorization.Update(authorization); + cachedAuthorization.NotifyOfPropertyChange(() => cachedAuthorization.Domain); + cachedAuthorization.NotifyOfPropertyChange(() => cachedAuthorization.Browser); + cachedAuthorization.NotifyOfPropertyChange(() => cachedAuthorization.DateActive); + cachedAuthorization.NotifyOfPropertyChange(() => cachedAuthorization.Ip); + cachedAuthorization.NotifyOfPropertyChange(() => cachedAuthorization.Region); + + newAuthorizationsCache[authorization.Hash.Value] = cachedAuthorization; + } + } + + for (var i = 0; i < Items.Count; i++) + { + if (!newAuthorizationsCache.ContainsKey(Items[i].Hash.Value)) + { + Items.RemoveAt(i--); + } + } + + for (var i = 0; i < itemsToAdd.Count; i++) + { + Items.Insert(0, itemsToAdd[i]); + } + + _authorizationsCache = newAuthorizationsCache; + } + + }), + error => + { + Status = string.Empty; + IsEmptyList = Items.Count == 0; + NotifyOfPropertyChange(() => IsEmptyList); + IsWorking = false; + Execute.ShowDebugMessage("account.getWebAuthorizations error " + error); + }); + }); + } + + public void Terminate(TLWebAuthorization authorization) + { + if (authorization == null) return; + + IsWorking = true; + MTProtoService.ResetWebAuthorizationAsync( + authorization.Hash, + result => BeginOnUIThread(() => + { + IsWorking = false; + Items.Remove(authorization); + IsEmptyList = Items.Count == 0; + _authorizationsCache.Remove(authorization.Hash.Value); + NotifyOfPropertyChange(() => IsEmptyList); + }), + error => + { + IsWorking = false; + Execute.ShowDebugMessage("account.resetWebAuthotization error " + error); + }); + } + + public void TerminateWebAuthorizations() + { + var confirmation = MessageBox.Show(AppResources.LogOutAllApplicationsConfirmation, AppResources.Confirm, MessageBoxButton.OKCancel); + if (confirmation != MessageBoxResult.OK) + { + return; + } + + IsWorking = true; + MTProtoService.ResetWebAuthorizationsAsync( + result => BeginOnUIThread(() => + { + IsWorking = false; + Items.Clear(); + IsEmptyList = Items.Count == 0; + _authorizationsCache.Clear(); + NotifyOfPropertyChange(() => IsEmptyList); + }), + error => + { + IsWorking = false; + Execute.ShowDebugMessage("account.resetWebAuthotizations error " + error); + }); + } + + public void Handle(TLUpdateNewAuthorization update) + { + UpdateSessionsAsync(); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Additional/PassportSettingsViewModel.cs b/TelegramClient.WP81/ViewModels/Additional/PassportSettingsViewModel.cs new file mode 100755 index 0000000..1518b73 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Additional/PassportSettingsViewModel.cs @@ -0,0 +1,285 @@ +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Extensions; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Passport; +using TelegramClient.Views.Additional; + +namespace TelegramClient.ViewModels.Additional +{ + public class PassportSettingsViewModel : ItemsViewModelBase, + Telegram.Api.Aggregator.IHandle, + Telegram.Api.Aggregator.IHandle + { + private readonly TLPasswordBase _passwordBase; + + public PassportSettingsViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _passwordBase = stateService.Password; + stateService.Password = null; + + Items.Clear(); + if (stateService.SecureValues != null) + { + Items.AddRange(stateService.SecureValues); + stateService.SecureValues = null; + } + + EventAggregator.Subscribe(this); + } + + protected override void OnActivate() + { + base.OnActivate(); + + if (StateService.RemoveBackEntry) + { + StateService.RemoveBackEntry = false; + NavigationService.RemoveBackEntry(); + } + } + + public void Edit(TLSecureValue value) + { + if (value == null) return; + + if (PhoneNumberViewModel.IsValidType(value.Type)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PassportDeletePhoneNumberAlert, AppResources.AppName, + AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + IsWorking = true; + MTProtoService.DeleteSecureValueAsync(new TLVector { new TLSecureValueTypePhone() }, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + + for (var i = 0; i < Items.Count; i++) + { + if (PhoneNumberViewModel.IsValidType(Items[i].Type)) + { + Items.RemoveAt(i--); + } + } + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + })); + } + }); + } + else if (EmailViewModel.IsValidType(value.Type)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PassportDeleteEmailAlert, AppResources.AppName, + AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + IsWorking = true; + MTProtoService.DeleteSecureValueAsync(new TLVector { new TLSecureValueTypeEmail() }, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + + for (var i = 0; i < Items.Count; i++) + { + if (EmailViewModel.IsValidType(Items[i].Type)) + { + Items.RemoveAt(i--); + } + } + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + })); + } + }); + } + else if (ResidentialAddressViewModel.IsValidType(value.Type)) + { + StateService.SecureValue = value; + StateService.Password = _passwordBase; + NavigationService.UriFor().Navigate(); + } + else if (PersonalDetailsViewModel.IsValidType(value.Type)) + { + StateService.SecureValue = value; + StateService.Password = _passwordBase; + NavigationService.UriFor().Navigate(); + } + } + + public void AddDocument() + { + var items = new List + { + new TLSecureValueTypePhone(), + new TLSecureValueTypeEmail(), + new TLSecureValueTypePersonalDetails(), + new TLSecureValueTypePassport(), + new TLSecureValueTypeDriverLicense(), + new TLSecureValueTypeIdentityCard(), + new TLSecureValueTypeInternalPassport(), + new TLSecureValueTypeAddress(), + new TLSecureValueTypePassportRegistration(), + new TLSecureValueTypeUtilityBill(), + new TLSecureValueTypeBankStatement(), + new TLSecureValueTypeRentalAgreement(), + new TLSecureValueTypeTemporaryRegistration(), + }; + + var dict = new Dictionary(); + foreach (var item in Items) + { + dict[item.Type.GetType()] = item.Type.GetType(); + } + + var panel = new StackPanel{ Margin = new Thickness(0.0, 12.0, 0.0, 0.0) }; + var messageBox = ShellViewModel.ShowCustomMessageBox( + null, AppResources.PassportNoDocumentsAdd, + null, null, + dismissed => + { + + }, + items.Count > 10 ? + (object) new ScrollViewer { MaxHeight = 650.0, Content = panel, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled } : + panel); + + for (var i = 0; i < items.Count; i++) + { + if (!dict.ContainsKey(items[i].GetType())) + { + var listBoxItem = new ListBoxItem + { + Content = + new TextBlock + { + Text = SecureRequiredTypeToCaptionConverter.Convert(items[i]), + FontSize = 27, + Margin = new Thickness(12.0) + }, + DataContext = items[i] + }; + TiltEffect.SetIsTiltEnabled(listBoxItem, true); + listBoxItem.Tap += (sender, args) => + { + messageBox.Dismiss(); + var item = sender as ListBoxItem; + if (item != null) + { + var secureValueType = item.DataContext as TLSecureValueTypeBase; + if (secureValueType != null) + { + if (PhoneNumberViewModel.IsValidType(secureValueType)) + { + StateService.SecureType = secureValueType; + StateService.Password = _passwordBase; + NavigationService.UriFor().Navigate(); + } + else if (EmailViewModel.IsValidType(secureValueType)) + { + StateService.SecureType = secureValueType; + StateService.Password = _passwordBase; + NavigationService.UriFor().Navigate(); + } + else if (ResidentialAddressViewModel.IsValidType(secureValueType)) + { + StateService.SecureType = secureValueType; + StateService.Password = _passwordBase; + NavigationService.UriFor().Navigate(); + } + else if (PersonalDetailsViewModel.IsValidType(secureValueType)) + { + StateService.SecureType = secureValueType; + StateService.Password = _passwordBase; + NavigationService.UriFor().Navigate(); + } + } + } + + }; + + panel.Children.Add(listBoxItem); + } + } + } + + public void DeletePassport() + { + if (Items.Count == 0) return; + + ShellViewModel.ShowCustomMessageBox( + AppResources.PassportDeleteConfirmation, AppResources.AppName, + AppResources.Delete, AppResources.Cancel, + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + var items = new TLVector(); + foreach (var item in Items) + { + items.Add(item.Type); + } + if (items.Count > 0) + { + MTProtoService.DeleteSecureValueAsync( + items, + result => BeginOnUIThread(() => + { + IsWorking = false; + + Items.Clear(); + }), + error => BeginOnUIThread(() => + { + IsWorking = false; + })); + } + } + }); + } + + public void Handle(DeleteSecureValueEventArgs args) + { + foreach (var value in args.Values) + { + Items.Remove(value); + } + } + + public void Handle(AddSecureValueEventArgs args) + { + foreach (var value in args.Values) + { + Items.Add(value); + } + } + } + + public class DeleteSecureValueEventArgs + { + public IList Values { get; set; } + } + + public class AddSecureValueEventArgs + { + public IList Values { get; set; } + } +} diff --git a/TelegramClient.WP81/ViewModels/Additional/PhotoPickerViewModel.cs b/TelegramClient.WP81/ViewModels/Additional/PhotoPickerViewModel.cs new file mode 100755 index 0000000..0c990e7 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Additional/PhotoPickerViewModel.cs @@ -0,0 +1,64 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using System.ComponentModel; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.Services; + +namespace TelegramClient.ViewModels.Additional +{ + public class PhotoPickerViewModel : ViewModelBase + { + private TLPrivacyRuleBase _selectedMainRule; + + public TLPrivacyRuleBase SelectedMainRule + { + get { return _selectedMainRule; } + set { SetField(ref _selectedMainRule, value, () => SelectedMainRule); } + } + + public List MainRules { get; set; } + + private TLPhotoPickerSettings _settings; + + public PhotoPickerViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _settings = StateService.GetPhotoPickerSettings(); + + MainRules = new List + { + new TLPrivacyValueAllowAll{ Label = AppResources.InAppPhotoPicker }, + new TLPrivacyValueAllowContacts{ Label = AppResources.ExternalPhotoPicker } + }; + + _selectedMainRule = _settings.External ? MainRules[1] : MainRules[0]; + _selectedMainRule.IsChecked = true; + + PropertyChanged += OnPropertyChanged; + } + + private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) + { + + } + + protected override void OnDeactivate(bool close) + { + _settings.External = SelectedMainRule == MainRules[1]; + StateService.SavePhotoPickerSettings(_settings); + + base.OnDeactivate(close); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Additional/ProxyListViewModel.cs b/TelegramClient.WP81/ViewModels/Additional/ProxyListViewModel.cs new file mode 100755 index 0000000..07769f4 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Additional/ProxyListViewModel.cs @@ -0,0 +1,494 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Helpers; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.Cache.EventArgs; +using Telegram.Api.TL; +using Telegram.Api.Transport; +using TelegramClient.Helpers; +using TelegramClient.Services; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.Views.Additional; +using Execute = Caliburn.Micro.Execute; + +namespace TelegramClient.ViewModels.Additional +{ + public class ProxyListViewModel : ItemsViewModelBase + { + private bool _isEnabled; + + public bool IsEnabled + { + get { return _isEnabled; } + set { SetField(ref _isEnabled, value, () => IsEnabled); } + } + + private bool _useForCalls; + + public bool UseForCalls + { + get { return _useForCalls; } + set { SetField(ref _useForCalls, value, () => UseForCalls); } + } + + private readonly ITransportService _transportService; + + public bool SuppressSharing { get; protected set; } + + private TLProxyConfig76 _proxyConfig; + + private readonly IProxyChecker _proxyChecker; + + public ProxyListViewModel(IProxyChecker proxyChecker, ITransportService transportService, ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + SuppressSharing = StateService.SuppressProxySharing; + StateService.SuppressProxySharing = false; + + _proxyChecker = proxyChecker; + _transportService = transportService; + + PropertyChanged += (sender, args) => + { + if (Property.NameEquals(args.PropertyName, () => IsEnabled)) + { + var proxy = _proxyConfig.GetProxy(); + _proxyConfig.IsEnabled = new TLBool(IsEnabled); + if (proxy != null) + { + proxy.NotifyOfPropertyChange(() => proxy.Self); + } + SetReconnect(!_proxyConfig.IsEmpty, _proxyConfig, null); + } + else if (Property.NameEquals(args.PropertyName, () => UseForCalls)) + { + var proxy = _proxyConfig.GetProxy(); + _proxyConfig.UseForCalls = new TLBool(UseForCalls); + if (proxy != null) + { + proxy.NotifyOfPropertyChange(() => proxy.Self); + } + SetReconnect(false, _proxyConfig, null); + } + }; + } + + protected override void OnActivate() + { + base.OnActivate(); + + _proxyConfig = _transportService.GetProxyConfig() as TLProxyConfig76; + if (_proxyConfig != null) + { + _isEnabled = _proxyConfig.IsEnabled.Value; + _useForCalls = _proxyConfig.UseForCalls.Value; + + var now = TLUtils.DateToUniversalTimeTLInt(MTProtoService.ClientTicksDelta, DateTime.Now); + Items.Clear(); + for (var i = 0; i < _proxyConfig.Items.Count; i++) + { + var item = _proxyConfig.Items[i]; + item.IsSelected = i == _proxyConfig.SelectedIndex.Value; + Items.Add(item); + + if (CheckProxy(item)) + { + item.Status = ProxyStatus.Connecting; + item.Ping = null; + _proxyChecker.CheckAsync(item, 10.0, + (proxyItem, ping) => Execute.BeginOnUIThread(() => + { + proxyItem.Proxy.CheckTime = now; + proxyItem.Proxy.Ping = ping; + proxyItem.Proxy.Status = item.Ping != null ? ProxyStatus.Available : ProxyStatus.Unavailable; + + Set(_proxyConfig); + })); + } + } + } + + _transportService.TransportConnected += OnTransportConnected; + _transportService.TransportConnecting += OnTransportConnecting; + } + + private bool CheckProxy(TLProxyBase item) + { + var lastCheckTime = item.CheckTime; + if (lastCheckTime == null) + { + return true; + } + + var now = TLUtils.DateToUniversalTimeTLInt(MTProtoService.ClientTicksDelta, DateTime.Now); + if (lastCheckTime.Value + 60 * 2 < now.Value) + { + return true; + } + + return false; + } + + private void OnTransportConnecting(object sender, TransportEventArgs e) + { + if (e.Transport.MTProtoType == MTProtoTransportType.Main + && e.Transport.ProxyConfig != null + && !e.Transport.ProxyConfig.IsEmpty + && e.Transport.ProxyConfig.IsEnabled.Value) + { + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + if (_proxyConfig != null) + { + foreach (var item in _proxyConfig.Items) + { + if (item == e.Transport.ProxyConfig.GetProxy()) + { + item.Status = ProxyStatus.Connecting; + item.Ping = null; + } + } + } + }); + } + } + + private void OnTransportConnected(object sender, TransportEventArgs e) + { + if (e.Transport.MTProtoType == MTProtoTransportType.Main + && e.Transport.ProxyConfig != null + && !e.Transport.ProxyConfig.IsEmpty + && e.Transport.ProxyConfig.IsEnabled.Value) + { + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + if (_proxyConfig != null) + { + for (var i = 0; i < _proxyConfig.Items.Count; i++) + { + var item = _proxyConfig.Items[i]; + if (item == e.Transport.ProxyConfig.GetProxy()) + { + var now = TLUtils.DateToUniversalTimeTLInt(MTProtoService.ClientTicksDelta, DateTime.Now); + item.CheckTime = now; + item.Status = ProxyStatus.Available; + item.Ping = e.Transport.Ping > 0 ? new TLInt((int) e.Transport.Ping) : null; + if (item.Ping == null) + { + PingMainTransportAsync(item, e.Transport); + } + + Set(_proxyConfig); + } + } + } + }); + } + } + + private void PingMainTransportAsync(TLProxyBase item, ITransport transport) + { + MTProtoService.PingAsync(TLLong.Random(), + pong => Execute.BeginOnUIThread(() => + { + item.Ping = transport.Ping > 0 + ? new TLInt((int)transport.Ping) + : null; + + Set(_proxyConfig); + })); + } + + protected override void OnDeactivate(bool close) + { + _transportService.TransportConnected -= OnTransportConnected; + _transportService.TransportConnecting -= OnTransportConnecting; + + base.OnDeactivate(close); + } + + public void Select(TLProxyBase proxy) + { + var proxyConfig = _proxyConfig; + if (proxyConfig == null) return; + if (proxyConfig.IsEnabled.Value && proxyConfig.GetProxy() == proxy) return; + + var currentProxy = proxyConfig.GetProxy(); + proxyConfig.IsEnabled = TLBool.True; + if (currentProxy != null) + { + currentProxy.NotifyOfPropertyChange(() => currentProxy.Self); + } + IsEnabled = true; + proxyConfig.SelectedIndex = new TLInt(proxyConfig.Items.IndexOf(proxy)); + foreach (var item in proxyConfig.Items) + { + item.IsSelected = item == proxy; + item.Ping = item.IsSelected ? null : item.Ping; + item.Status = item.IsSelected ? ProxyStatus.Connecting : (item.Status == ProxyStatus.Connecting ? ProxyStatus.Unavailable : item.Status); + } + + SetReconnect(true, proxyConfig, proxy); + } + + private static void Set(TLProxyConfigBase proxyConfig) + { + var transportService = IoC.Get(); + transportService.SetProxyConfig(proxyConfig); + } + + private static void SetReconnect(bool reconnect, TLProxyConfigBase proxyConfig, TLProxyBase proxy) + { + Telegram.Api.Helpers.Execute.ShowDebugMessage(string.Format("SetRecconect recconect={0} proxyConfig={1}", reconnect, proxyConfig)); + if (proxyConfig == null) return; + + Set(proxyConfig); + + var transportService = IoC.Get(); + var mtProtoService = IoC.Get(); + var cacheService = IoC.Get(); + var eventAggregator = IoC.Get(); + + if (reconnect) + { + var promoDialogs = cacheService.GetDialogs().OfType().Where(x => x.IsPromo).ToList(); + foreach (var dialog in promoDialogs) + { + cacheService.UpdateDialogPromo(dialog, false); + } + + cacheService.SyncProxyData(null, result => { }); + + transportService.Close(); + mtProtoService.PingAsync(TLLong.Random(), + result => Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + if (proxy != null) + { + var now = TLUtils.DateToUniversalTimeTLInt(mtProtoService.ClientTicksDelta, DateTime.Now); + proxy.CheckTime = now; + proxy.Status = ProxyStatus.Available; + proxy.Ping = mtProtoService.GetActiveTransport().Ping > 0 + ? new TLInt((int)mtProtoService.GetActiveTransport().Ping) + : null; + + Set(proxyConfig); + } + + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + if (isAuthorized) + { + mtProtoService.GetProxyDataAsync( + result2 => + { + var proxyDataPromo = result2 as TLProxyDataPromo; + if (proxyDataPromo != null) + { + mtProtoService.GetPromoDialogAsync(mtProtoService.PeerToInputPeer(proxyDataPromo.Peer), + result3 => + { + if (result3.Dialogs.Count > 0) + { + eventAggregator.Publish(new ProxyDataChangedEventArgs(proxyDataPromo)); + } + }); + } + else + { + + } + + Telegram.Api.Helpers.Execute.ShowDebugMessage(result2.ToString()); + }); + } + })); + } + + eventAggregator.Publish(new ProxyChangedEventArgs(proxyConfig)); + } + + public static void ApplySettings(TLProxyConfigBase proxyConfigBase, bool isEnabled, TLProxyBase proxy) + { + var proxyConfig = proxyConfigBase ?? TLProxyConfigBase.Empty; + + var proxyConfig76 = proxyConfig as TLProxyConfig76; + if (proxyConfig76 == null) return; + + proxyConfig.IsEnabled = new TLBool(isEnabled); + + var added = false; + for (var i = 0; i < proxyConfig76.Items.Count; i++) + { + var proxyItem = proxyConfig76.Items[i]; + if (TLProxyBase.ProxyEquals(proxyItem, proxy)) + { + proxyConfig76.SelectedIndex = new TLInt(i); + added = true; + break; + } + } + if (!added) + { + proxyConfig76.Items.Insert(0, proxy); + proxyConfig76.SelectedIndex = new TLInt(0); + } + + SetReconnect(true, proxyConfig76, proxy); + } + + public void Add() + { + StateService.SuppressProxySharing = SuppressSharing; + NavigationService.UriFor().Navigate(); + } + + public void Delete(TLProxyBase proxy) + { + var proxyConfig = _proxyConfig; + if (proxyConfig == null) return; + + var selectedProxy = proxyConfig.Items[proxyConfig.SelectedIndex.Value]; + var reconnect = selectedProxy == proxy; + + Items.Remove(proxy); + proxyConfig.Items.Remove(proxy); + proxyConfig.SelectedIndex = new TLInt(proxyConfig.Items.IndexOf(selectedProxy)); + if (proxyConfig.SelectedIndex.Value < 0) + { + if (proxyConfig.Items.Count > 0) + { + proxyConfig.SelectedIndex = new TLInt(0); + selectedProxy = proxyConfig.Items[proxyConfig.SelectedIndex.Value]; + } + else if (proxyConfig.IsEnabled.Value) + { + proxyConfig.IsEnabled = TLBool.False; + IsEnabled = false; // SetReconnect will be invoked here + + return; + } + } + + foreach (var item in proxyConfig.Items) + { + item.IsSelected = item == selectedProxy; + } + + SetReconnect(reconnect, proxyConfig, selectedProxy); + } + + public void Open(TLProxyBase proxy) + { + StateService.Proxy = proxy; + StateService.SuppressProxySharing = SuppressSharing; + NavigationService.UriFor().Navigate(); + } + + public void Done() + { + var proxyConfig = _proxyConfig ?? TLProxyConfigBase.Empty as TLProxyConfig76; + if (proxyConfig == null) return; + + proxyConfig.IsEnabled = new TLBool(IsEnabled); + proxyConfig.UseForCalls = new TLBool(UseForCalls); + + SetReconnect(true, proxyConfig, proxyConfig.GetProxy()); + + NavigationService.GoBack(); + } + + public void Share() + { + if (SuppressSharing) return; + if (_proxyConfig == null || _proxyConfig.IsEmpty) return; + + var view = GetView() as ProxyListView; + if (view != null) + { + view.OpenShareMessagePicker(string.Empty, + args => + { + if (args.Dialogs.Count == 0) return; + + var prefix = Constants.DefaultMeUrlPrefix; + var config63 = CacheService.GetConfig() as TLConfig63; + if (config63 != null && !TLString.IsNullOrEmpty(config63.MeUrlPrefix)) + { + prefix = config63.MeUrlPrefix.ToString(); + } + + var text = string.IsNullOrEmpty(args.Comment) + ? GetProxyListString(prefix) + : args.Comment + "\n\n" + GetProxyListString(prefix); + + var messages = new List(); + foreach (var dialog in args.Dialogs) + { + var with = dialog.With; + if (with != null) + { + with.ClearBitmap(); + } + + var date = TLUtils.DateToUniversalTimeTLInt(MTProtoService.ClientTicksDelta, DateTime.Now); + + var message = TLUtils.GetMessage( + new TLInt(StateService.CurrentUserId), + dialog.Peer, + MessageStatus.Sending, + TLBool.True, + TLBool.True, + date, + new TLString(text), + new TLMessageMediaEmpty(), + TLLong.Random(), + new TLInt(0) + ); + + messages.Add(message); + } + + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + foreach (var message in messages) + { + CacheService.SyncSendingMessage( + message, null, + result => DialogDetailsViewModel.SendInternal(message, MTProtoService)); + } + }); + }); + } + + return; + //StateService.Url = GetProxyListString(prefix); + //NavigationService.UriFor().Navigate(); + } + + private string GetProxyListString(string prefix) + { + var url = string.Empty; + + foreach (var item in _proxyConfig.Items) + { + if (!item.IsEmpty) + { + url += string.Format("{0}\n\n", item.GetUrl(prefix)); + } + } + + return url.Trim('\n'); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Additional/ProxyViewModel.cs b/TelegramClient.WP81/ViewModels/Additional/ProxyViewModel.cs new file mode 100755 index 0000000..bcb11b1 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Additional/ProxyViewModel.cs @@ -0,0 +1,357 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Globalization; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using Telegram.Api.Transport; +using TelegramClient.Services; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.Views.Additional; + +namespace TelegramClient.ViewModels.Additional +{ + public class ProxyViewModel : ViewModelBase + { + private bool _isSocks5Proxy = true; + + public bool IsSocks5Proxy + { + get { return _isSocks5Proxy; } + set { SetField(ref _isSocks5Proxy, value, () => IsSocks5Proxy); } + } + + public string Server { get; set; } + + public string Port { get; set; } + + public string Username { get; set; } + + public string Password { get; set; } + + public string Secret { get; set; } + + private readonly ITransportService _transportService; + + public bool SuppressSharing { get; protected set; } + + private TLProxyBase _proxy; + + public ProxyViewModel(ITransportService transportService, ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + SuppressSharing = StateService.SuppressProxySharing; + StateService.SuppressProxySharing = false; + + _transportService = transportService; + + _proxy = StateService.Proxy; + StateService.Proxy = null; + + if (_proxy != null) + { + Server = _proxy.Server.ToString(); + Port = _proxy.Port.Value >= 0 ? _proxy.Port.Value.ToString(CultureInfo.InvariantCulture) : string.Empty; + + var socks5Proxy = _proxy as TLSocks5Proxy; + if (socks5Proxy != null) + { + Username = socks5Proxy.Username.ToString(); + Password = socks5Proxy.Password.ToString(); + _isSocks5Proxy = true; + } + + var mtProtoProxy = _proxy as TLMTProtoProxy; + if (mtProtoProxy != null) + { + Secret = mtProtoProxy.Secret.ToString(); + _isSocks5Proxy = false; + } + } + } + + public bool IsDoneEnabled + { + get + { + if (string.IsNullOrEmpty(Server) || string.IsNullOrEmpty(Port)) return false; + if (!IsSocks5Proxy && string.IsNullOrEmpty(Secret)) return false; + + return true; + } + } + + public void Done() + { + var proxyConfig = _transportService.GetProxyConfig() as TLProxyConfig76 ?? TLProxyConfigBase.Empty as TLProxyConfig76; + if (proxyConfig == null) return; + if (!IsDoneEnabled) return; + + if (IsSocks5Proxy) + { + TLSocks5Proxy proxy = null; + // new proxy + if (_proxy == null) + { + proxy = new TLSocks5Proxy { CustomFlags = new TLLong(0) }; + proxy.Server = new TLString(Server); + var port = 0; + proxy.Port = int.TryParse(Port, out port) ? new TLInt(port) : new TLInt(0); + proxy.Username = new TLString(Username); + proxy.Password = new TLString(Password); + + _proxy = proxy; + proxyConfig.Items.Add(_proxy); + proxyConfig.SelectedIndex = new TLInt(proxyConfig.Items.IndexOf(_proxy)); + proxyConfig.IsEnabled = TLBool.True; + + _transportService.SetProxyConfig(proxyConfig); + _transportService.Close(); + MTProtoService.PingAsync(TLLong.Random(), result => { }); + + EventAggregator.Publish(new ProxyChangedEventArgs(proxyConfig)); + NavigationService.GoBack(); + + return; + } + + proxy = _proxy as TLSocks5Proxy; + // change type + if (proxy == null) + { + proxy = new TLSocks5Proxy { CustomFlags = new TLLong(0) }; + proxy.Server = new TLString(Server); + var port = 0; + proxy.Port = int.TryParse(Port, out port) ? new TLInt(port) : new TLInt(0); + proxy.Username = new TLString(Username); + proxy.Password = new TLString(Password); + + _proxy = proxy; + proxyConfig.Items.Add(_proxy); + proxyConfig.SelectedIndex = new TLInt(proxyConfig.Items.IndexOf(_proxy)); + + _transportService.SetProxyConfig(proxyConfig); + _transportService.Close(); + MTProtoService.PingAsync(TLLong.Random(), result => { }); + + EventAggregator.Publish(new ProxyChangedEventArgs(proxyConfig)); + NavigationService.GoBack(); + + return; + } + // same type + else + { + proxy.Server = new TLString(Server); + var port = 0; + proxy.Port = int.TryParse(Port, out port) ? new TLInt(port) : new TLInt(0); + proxy.Username = new TLString(Username); + proxy.Password = new TLString(Password); + + _proxy = proxy; + if (proxyConfig.SelectedIndex.Value == proxyConfig.Items.IndexOf(_proxy)) + { + _transportService.SetProxyConfig(proxyConfig); + _transportService.Close(); + MTProtoService.PingAsync(TLLong.Random(), result => { }); + } + + EventAggregator.Publish(new ProxyChangedEventArgs(proxyConfig)); + NavigationService.GoBack(); + + return; + } + + } + else + { + TLMTProtoProxy proxy = null; + // new proxy + if (_proxy == null) + { + proxy = new TLMTProtoProxy { CustomFlags = new TLLong(0) }; + proxy.Server = new TLString(Server); + var port = 0; + proxy.Port = int.TryParse(Port, out port) ? new TLInt(port) : new TLInt(0); + proxy.Secret = new TLString(Secret); + + _proxy = proxy; + proxyConfig.Items.Add(_proxy); + proxyConfig.SelectedIndex = new TLInt(proxyConfig.Items.IndexOf(_proxy)); + proxyConfig.IsEnabled = TLBool.True; + + _transportService.SetProxyConfig(proxyConfig); + _transportService.Close(); + MTProtoService.PingAsync(TLLong.Random(), result => { }); + + EventAggregator.Publish(new ProxyChangedEventArgs(proxyConfig)); + NavigationService.GoBack(); + + return; + } + + proxy = _proxy as TLMTProtoProxy; + // change type + if (proxy == null) + { + proxy = new TLMTProtoProxy { CustomFlags = new TLLong(0) }; + proxy.Server = new TLString(Server); + var port = 0; + proxy.Port = int.TryParse(Port, out port) ? new TLInt(port) : new TLInt(0); + proxy.Secret = new TLString(Secret); + + _proxy = proxy; + proxyConfig.Items.Add(_proxy); + proxyConfig.SelectedIndex = new TLInt(proxyConfig.Items.IndexOf(_proxy)); + + _transportService.SetProxyConfig(proxyConfig); + _transportService.Close(); + MTProtoService.PingAsync(TLLong.Random(), result => { }); + + EventAggregator.Publish(new ProxyChangedEventArgs(proxyConfig)); + NavigationService.GoBack(); + + return; + } + // same type + else + { + proxy.Server = new TLString(Server); + var port = 0; + proxy.Port = int.TryParse(Port, out port) ? new TLInt(port) : new TLInt(0); + proxy.Secret = new TLString(Secret); + + _proxy = proxy; + if (proxyConfig.SelectedIndex.Value == proxyConfig.Items.IndexOf(_proxy)) + { + _transportService.SetProxyConfig(proxyConfig); + _transportService.Close(); + MTProtoService.PingAsync(TLLong.Random(), result => { }); + } + + EventAggregator.Publish(new ProxyChangedEventArgs(proxyConfig)); + NavigationService.GoBack(); + + return; + } + } + } + + public void Share() + { + if (SuppressSharing) return; + if (string.IsNullOrEmpty(Server) || string.IsNullOrEmpty(Port)) return; + if (!IsSocks5Proxy && string.IsNullOrEmpty(Secret)) return; + + var view = GetView() as ProxyView; + if (view != null) + { + view.OpenShareMessagePicker(string.Empty, + args => + { + if (args.Dialogs.Count == 0) return; + + var prefix = Constants.DefaultMeUrlPrefix; + var config63 = CacheService.GetConfig() as TLConfig63; + if (config63 != null && !TLString.IsNullOrEmpty(config63.MeUrlPrefix)) + { + prefix = config63.MeUrlPrefix.ToString(); + } + + var text = string.IsNullOrEmpty(args.Comment) + ? prefix + GetProxyString() + : args.Comment + "\n\n" + prefix + GetProxyString(); + + var messages = new List(); + foreach (var dialog in args.Dialogs) + { + var with = dialog.With; + if (with != null) + { + with.ClearBitmap(); + } + + var date = TLUtils.DateToUniversalTimeTLInt(MTProtoService.ClientTicksDelta, DateTime.Now); + + var message = TLUtils.GetMessage( + new TLInt(StateService.CurrentUserId), + dialog.Peer, + MessageStatus.Sending, + TLBool.True, + TLBool.True, + date, + new TLString(text), + new TLMessageMediaEmpty(), + TLLong.Random(), + new TLInt(0) + ); + + messages.Add(message); + } + + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + foreach (var message in messages) + { + CacheService.SyncSendingMessage( + message, null, + result => DialogDetailsViewModel.SendInternal(message, MTProtoService)); + } + }); + }); + } + + return; + //StateService.Url = prefix + GetProxyString(); + //NavigationService.UriFor().Navigate(); + } + + private string GetProxyString() + { + var proxyString = string.Empty; + if (IsSocks5Proxy) + { + proxyString = string.Format("socks?server={0}&port={1}", Server, Port); + if (!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password)) + { + proxyString += string.Format("&user={0}&pass={1}", Username, Password); + } + } + else + { + proxyString = string.Format("proxy?server={0}&port={1}&secret={2}", Server, Port, Secret); + } + + return proxyString; + } + } + + public class ProxyChangedEventArgs + { + public TLProxyConfigBase ProxyConfig { get; set; } + + public ProxyChangedEventArgs(TLProxyConfigBase proxyConfig) + { + ProxyConfig = proxyConfig; + } + } + + public class ProxyDataChangedEventArgs + { + public TLProxyDataBase ProxyData { get; set; } + + public ProxyDataChangedEventArgs(TLProxyDataBase proxyData) + { + ProxyData = proxyData; + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Calls/CallViewModel.cs b/TelegramClient.WP81/ViewModels/Calls/CallViewModel.cs new file mode 100755 index 0000000..a65e153 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Calls/CallViewModel.cs @@ -0,0 +1,249 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Linq; +using System.Windows; +using System.Windows.Threading; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Telegram.Api.TL; +using TelegramClient.Controls; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.Views.Calls; +using TelegramClient.Views.Contacts; +using TelegramClient.Views.Dialogs; + +namespace TelegramClient.ViewModels.Calls +{ + public class CallViewModel : PropertyChangedBase + { + public TLUserBase User { get; set; } + + public string Status { get; set; } + + public string Emojis { get; set; } + + public string EmojiKeyDescription + { + get { return string.Format(AppResources.EmojiKeyDescription, User != null ? User.ShortName : string.Empty); } + } + + private readonly DispatcherTimer _callTimer; + + private DateTime _callStartTime; + + private CallViewState _viewState; + + public CallViewState ViewState + { + get { return _viewState; } + set + { + if (_viewState != value) + { + _viewState = value; + NotifyOfPropertyChange(() => ViewState); + } + } + } + + private int _signal; + + public int Signal + { + get { return _signal; } + set + { + if (_signal != value) + { + _signal = value; + NotifyOfPropertyChange(() => Signal); + } + } + } + + private readonly IVoIPService _voipService; + + public TLLong CallId { get; set; } + + public CallViewModel(TLUserBase user, IVoIPService voipService) + { + _callTimer = new DispatcherTimer(); + _callTimer.Interval = TimeSpan.FromSeconds(0.33); + _callTimer.Tick += CallTimer_Tick; + _voipService = voipService; + + User = user; + } + + public void ChangeCallState(PhoneCallState state) + { + System.Diagnostics.Debug.WriteLine(state); + if (state == PhoneCallState.STATE_WAITING_INCOMING) + { + Status = AppResources.VoipIncoming; + } + else if (state == PhoneCallState.STATE_WAIT_INIT || state == PhoneCallState.STATE_WAIT_INIT_ACK) + { + Status = AppResources.VoipConnecting; + ViewState = CallViewState.CallConnecting; + } + else if (state == PhoneCallState.STATE_EXCHANGING_KEYS) + { + Status = AppResources.VoipExchangingKeys; + ViewState = CallViewState.CallConnecting; + } + else if (state == PhoneCallState.STATE_WAITING) + { + Status = AppResources.VoipWaiting; + } + else if (state == PhoneCallState.STATE_RINGING) + { + Status = AppResources.VoipRinging; + } + else if (state == PhoneCallState.STATE_REQUESTING) + { + Status = AppResources.VoipRequesting; + } + else if (state == PhoneCallState.STATE_HANGING_UP) + { + Status = AppResources.VoipHangingUp; + } + else if (state == PhoneCallState.STATE_ENDED) + { + Status = AppResources.VoipEnded; + } + else if (state == PhoneCallState.STATE_BUSY) + { + Status = AppResources.VoipBusy; + } + else if (state == PhoneCallState.STATE_ESTABLISHED) + { + StartTimer(); + ViewState = CallViewState.Call; + } + else if (state == PhoneCallState.STATE_FAILED) + { + Status = AppResources.VoipFailed; + } + + NotifyOfPropertyChange(() => Status); + } + + public void StartTimer() + { + _callStartTime = DateTime.Now; + _callTimer.Start(); + } + + public void StartTimer(DateTime callStartTime) + { + _callStartTime = callStartTime; + _callTimer.Start(); + } + + public void StopTimer() + { + _callTimer.Stop(); + } + + private void CallTimer_Tick(object sender, System.EventArgs eventArgs) + { + var callTime = DateTime.Now - _callStartTime; + if (callTime.TotalHours >= 10.0) + { + Status = callTime.ToString(@"hh\:mm\:ss"); + } + else if (callTime.TotalHours >= 1.0) + { + Status = callTime.ToString(@"h\:mm\:ss"); + } + else if (callTime.TotalMinutes >= 10.0) + { + Status = callTime.ToString(@"mm\:ss"); + } + else + { + Status = callTime.ToString(@"m\:ss"); + } + + NotifyOfPropertyChange(() => Status); + } + + public void SwitchSpeaker(bool external) + { + _voipService.SwitchSpeaker(external); + } + + public void Mute(bool muted) + { + _voipService.Mute(muted); + } + + public void OpenChat() + { + if (User == null) return; + + var contactView = ((PhoneApplicationFrame)Application.Current.RootVisual).Content as ContactView; + if (contactView != null) + { + var withUser = contactView.ViewModel.CurrentContact as TLUser; + if (withUser != null && withUser.Index == User.Index) + { + var navigationService = IoC.Get(); + if (navigationService != null) + { + var backEntry = navigationService.BackStack.FirstOrDefault(); + if (backEntry != null && backEntry.Source.ToString().Contains("DialogDetailsView.xaml")) + { + navigationService.GoBack(); + + return; + } + } + } + } + + var dialogDetailsView = ((PhoneApplicationFrame)Application.Current.RootVisual).Content as DialogDetailsView; + if (dialogDetailsView != null) + { + if (dialogDetailsView.ViewModel != null) + { + var withUser = dialogDetailsView.ViewModel.With as TLUser; + if (withUser != null && withUser.Index == User.Index) + { + return; + } + } + + TelegramTransitionService.SetNavigationOutTransition(dialogDetailsView, null); + } + + var secretDialogDetailsView = ((PhoneApplicationFrame)Application.Current.RootVisual).Content as SecretDialogDetailsView; + if (secretDialogDetailsView != null) + { + if (secretDialogDetailsView.ViewModel != null) + { + var withUser = secretDialogDetailsView.ViewModel.With as TLUser; + if (withUser != null && withUser.Index == User.Index) + { + return; + } + } + + TelegramTransitionService.SetNavigationOutTransition(secretDialogDetailsView, null); + } + + IoC.Get().With = User; + IoC.Get().RemoveBackEntries = true; + IoC.Get().UriFor().WithParam(x => x.RandomParam, Guid.NewGuid().ToString()).Navigate(); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Calls/CallsViewModel.cs b/TelegramClient.WP81/ViewModels/Calls/CallsViewModel.cs new file mode 100755 index 0000000..df810c1 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Calls/CallsViewModel.cs @@ -0,0 +1,278 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using Caliburn.Micro; +using Coding4Fun.Toolkit.Controls; +using Telegram.Api.Aggregator; +using Telegram.Api.Helpers; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Converters; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.ViewModels.Media; +using TelegramClient.ViewModels.Search; +using Execute = Caliburn.Micro.Execute; + +namespace TelegramClient.ViewModels.Calls +{ + public class CallsViewModel : ItemsViewModelBase + { + public bool FirstRun { get; set; } + + public CallsViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + DisplayName = LowercaseConverter.Convert(AppResources.Calls); + Status = AppResources.Loading; + FirstRun = true; + } + + public bool OpenDialogDetails(TLDialogBase dialog) + { + ShellViewModel.StartNewTimer(); + //Execute.ShowDebugMessage("OpenDialogDetails"); + + if (dialog == null) + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("OpenDialogDetails dialog=null"); + return false; + } + if (dialog.With == null) + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("OpenDialogDetails dialog.With=null"); + return false; + } + + if (dialog.IsEncryptedChat) + { + var encryptedChat = CacheService.GetEncryptedChat(dialog.Peer.Id); + + var user = dialog.With as TLUserBase; + if (user == null) + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("OpenDialogDetails encrypted dialog.With=null"); + return false; + } + + var cachedUser = CacheService.GetUser(user.Id); + StateService.Participant = cachedUser ?? user; + StateService.With = encryptedChat; + StateService.Dialog = dialog; + StateService.AnimateTitle = true; + NavigationService.UriFor().Navigate(); + } + else + { + var settings = dialog.With as INotifySettings; + if (settings != null) + { + settings.NotifySettings = settings.NotifySettings ?? dialog.NotifySettings; + } + + StateService.With = dialog.With; + StateService.AnimateTitle = true; + NavigationService.UriFor().Navigate(); + } + + return true; + } + + protected override void OnActivate() + { + base.OnActivate(); + + //if (FirstRun) + { + LoadCalls(); + } + } + + private volatile bool _isUpdated; + + private int _offset = 0; + + private void LoadCalls() + { + var timespan = Items.Count > 0 ? 1.0 : 0.0; + + BeginOnThreadPool(TimeSpan.FromSeconds(timespan), () => + { + var isAuthorized = SettingsHelper.GetValue(Constants.IsAuthorizedKey); + //if (!FirstRun) + //{ + // return; + //} + if (!isAuthorized) + { + return; + } + + FirstRun = false; + + Status = Items.Count == 0 && LazyItems.Count == 0 ? AppResources.Loading : string.Empty; + var limit = 50;//Constants.DialogsSlice; + MTProtoService.SearchAsync( + new TLInputPeerEmpty(), + TLString.Empty, + null, + new TLInputMessagesFilterPhoneCalls{ Flags = new TLInt(0) }, + new TLInt(0), + new TLInt(0), + new TLInt(0), + new TLInt(0), + new TLInt(limit), + new TLInt(0), + result => + { + CacheService.AddChats(result.Chats, results => { }); + CacheService.AddUsers(result.Users, results => { }); + + var items = new List(); + var newMessages = result as TLMessages; + if (newMessages != null) + { + var usersCache = new Dictionary(); + foreach (var user in newMessages.Users) + { + usersCache[user.Index] = user; + } + + var chatsCache = new Dictionary(); + foreach (var chat in newMessages.Chats) + { + chatsCache[chat.Index] = chat; + } + + foreach (var message in newMessages.Messages.OfType()) + { + var dialog = new TLDialog { TopMessage = message }; + var peer = TLUtils.GetPeerFromMessage(message); + if (peer is TLPeerUser) + { + TLUserBase user; + if (!usersCache.TryGetValue(peer.Id.Value, out user)) + { + continue; + } + dialog.With = user; + items.Add(dialog); + } + } + } + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + IsLastSliceLoaded = result.Messages.Count < limit; + _offset = Constants.DialogsSlice; + + _isUpdated = true; + + const int maxMessagesSlice = 8; + Items.Clear(); + for (var i = 0; i < items.Count; i++) + { + if (i < maxMessagesSlice) + { + Items.Add(items[i]); + } + else + { + LazyItems.Add(items[i]); + } + } + + Status = Items.Count == 0 && LazyItems.Count == 0 ? AppResources.NoCallsHere : string.Empty; + + if (LazyItems.Count > 0) + { + BeginOnUIThread(() => + { + for (var i = 0; i < LazyItems.Count; i++) + { + Items.Add(LazyItems[i]); + } + LazyItems.Clear(); + }); + } + }); + }, + error => Execute.BeginOnUIThread(() => + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("messages.getDialogs error " + error); + //_isUpdated = true; + Status = string.Empty; + })); + }); + + base.OnInitialize(); + } + + public void LoadNextSlice() + { + + } + + public void DeleteDialog(TLDialogBase dialogBase) + { + var dialog = dialogBase as TLDialog; + if (dialog == null) return; + + var message = dialog.TopMessage as TLMessageCommon; + if (message == null) return; + + var messages = new List { message }; + + var owner = message.Out.Value ? CacheService.GetUser(message.ToId.Id) : message.From; + + if ((message.Id == null || message.Id.Value == 0) && message.RandomIndex != 0) + { + DeleteMessagesInternal(owner, null, messages); + return; + } + + DialogDetailsViewModel.DeleteMessages(MTProtoService, false, null, null, messages, null, (result1, result2) => DeleteMessagesInternal(owner, result1, result2)); + } + + private void DeleteMessagesInternal(TLObject owner, TLMessageBase lastMessage, IList messages) + { + var ids = new TLVector(); + for (int i = 0; i < messages.Count; i++) + { + ids.Add(messages[i].Id); + } + + // duplicate: deleting performed through updates + CacheService.DeleteMessages(ids); + + BeginOnUIThread(() => + { + for (var i = 0; i < messages.Count; i++) + { + for (var j = 0; j < Items.Count; j++) + { + var dialog = Items[j] as TLDialog; + if (dialog != null + && dialog.TopMessage != null + && dialog.TopMessage.Id.Value == messages[i].Index) + { + Items.RemoveAt(j); + break; + } + } + } + }); + + EventAggregator.Publish(new DeleteMessagesEventArgs { Owner = owner, Messages = messages }); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Chats/GroupStickersViewModel.cs b/TelegramClient.WP81/ViewModels/Chats/GroupStickersViewModel.cs new file mode 100755 index 0000000..9fa11ff --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Chats/GroupStickersViewModel.cs @@ -0,0 +1,426 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using Caliburn.Micro; +using Coding4Fun.Toolkit.Controls; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.Utils; +using TelegramClient.Views; +using TelegramClient.Views.Chats; +using TelegramClient.Views.Dialogs; +using Execute = Telegram.Api.Helpers.Execute; + +namespace TelegramClient.ViewModels.Chats +{ + public class TLStickerSetNotFound : TLStickerSetBase + { + + } + + public class GroupStickersViewModel : ItemsViewModelBase + { + private string _text; + + public string Text + { + get { return _text; } + set { SetField(ref _text, value, () => Text); } + } + + private TLStickerSetBase _stickerSet; + + public TLStickerSetBase StickerSet + { + get { return _stickerSet; } + set { SetField(ref _stickerSet, value, () => StickerSet); } + } + + private TLChatBase _channel; + + private readonly Dictionary> _stickerSets = new Dictionary>(); + + private readonly Dictionary _emoticons = new Dictionary(); + + private TLAllStickers _allStickers; + + public GroupStickersViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _channel = StateService.CurrentChat; + var channel68 = _channel as TLChannel68; + if (channel68 != null) + { + _stickerSet = channel68.StickerSet; + _text = _stickerSet != null && !TLString.IsNullOrEmpty(_stickerSet.ShortName) + ? _stickerSet.ShortName.ToString() + : null; + + var stickerSet32 = StickerSet as TLStickerSet32; + if (stickerSet32 != null && stickerSet32.Stickers == null) + { + MTProtoService.GetStickerSetAsync(new TLInputStickerSetShortName{ ShortName = stickerSet32.ShortName}, + result => Execute.BeginOnUIThread(() => + { + var objects = new TLVector(); + foreach (var sticker in result.Documents) + { + objects.Add(new TLStickerItem { Document = sticker }); + } + + stickerSet32.Stickers = objects; + stickerSet32.NotifyOfPropertyChange(() => stickerSet32.Stickers); + }), + error => + { + + }); + } + } + StateService.CurrentChat = null; + + PropertyChanged += (sender, args) => + { + if (Property.NameEquals(args.PropertyName, () => Text)) + { + if (string.IsNullOrEmpty(Text)) + { + Remove(false); + } + else if (StickerSet is TLStickerSet32 && string.Equals(StickerSet.ShortName.ToString(), Text)) + { + + } + else if (Text.Contains("/addstickers")) + { + var shortNameStartIndex = Text.TrimEnd('/').LastIndexOf("/", StringComparison.OrdinalIgnoreCase); + if (shortNameStartIndex != -1) + { + var shortName = Text.Substring(shortNameStartIndex).Replace("/", string.Empty); + + if (!string.IsNullOrEmpty(shortName)) + { + Text = shortName; + var view = GetView() as GroupStickersView; + if (view != null) + { + view.MoveCursorToEnd(); + } + } + } + } + else + { + var text = Text; + Execute.BeginOnUIThread(TimeSpan.FromSeconds(0.5), () => + { + if (string.Equals(text, Text)) + { + SearchStickerSet(text); + } + }); + } + } + }; + } + + public void Open() + { + var stickerSet = StickerSet as TLStickerSet32; + if (stickerSet == null) return; + + TelegramViewBase.NavigateToStickers(MTProtoService, StateService, new TLInputStickerSetShortName{ ShortName = stickerSet.ShortName }, + () => + { + Items.Insert(0, stickerSet); + }, + () => + { + for (var index = 0; index < Items.Count; index++) + { + var item = Items[index]; + if (TLString.Equals(stickerSet.ShortName, item.ShortName, StringComparison.Ordinal)) + { + Items.RemoveAt(index); + break; + } + } + }); + } + + private void SearchStickerSet(string text) + { + IsWorking = true; + MTProtoService.GetStickerSetAsync(new TLInputStickerSetShortName{ ShortName = new TLString(text)}, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + + var objects = new TLVector(); + foreach (var sticker in result.Documents) + { + objects.Add(new TLStickerItem { Document = sticker }); + } + + result.Set.Stickers = objects; + + Set(result.Set, false); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + Set(new TLStickerSetNotFound(), false); + })); + } + + public void Set(TLStickerSetBase set) + { + Set(set, true); + } + + private void Set(TLStickerSetBase set, bool updateText) + { + StickerSet = set; + set.IsSelected = true; + set.NotifyOfPropertyChange(() => set.IsSelected); + foreach (var item in Items) + { + if (TLString.Equals(StickerSet.ShortName, item.ShortName, StringComparison.OrdinalIgnoreCase)) + { + item.IsSelected = true; + item.NotifyOfPropertyChange(() => item.IsSelected); + } + else + { + item.IsSelected = false; + item.NotifyOfPropertyChange(() => item.IsSelected); + } + } + if (updateText) Text = set.ShortName.ToString(); + } + + public void Remove() + { + Remove(true); + } + + private void Remove(bool clearText) + { + StickerSet = null; + foreach (var item in Items) + { + if (StickerSet != item) + { + item.IsSelected = false; + item.NotifyOfPropertyChange(() => item.IsSelected); + } + } + if (clearText) Text = string.Empty; + } + + public void Done() + { + var channel68 = _channel as TLChannel68; + if (channel68 != null) + { + if (channel68.StickerSet != StickerSet) + { + TLInputStickerSetBase inputStickerSet; + if (!(StickerSet is TLStickerSet32)) + { + inputStickerSet = new TLInputStickerSetEmpty(); + } + else + { + inputStickerSet = new TLInputStickerSetShortName{ ShortName = StickerSet.ShortName }; + } + IsWorking = true; + MTProtoService.SetStickersAsync(channel68.ToInputChannel(), inputStickerSet, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + channel68.StickerSet = StickerSet; + channel68.NotifyOfPropertyChange(() => channel68.StickerSet); + NavigationService.GoBack(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + })); + } + } + } + + public void ForwardInAnimationComplete() + { + StateService.GetAllStickersAsync(cachedAllStickers => BeginOnUIThread(() => + { + _allStickers = cachedAllStickers; + + var allStickers = _allStickers as TLAllStickers43; + if (allStickers != null) + { + UpdateSets(allStickers, () => UpdateAllStickersAsync(allStickers)); + Status = string.Empty; + } + else + { + UpdateAllStickersAsync(null); + } + })); + } + + private void UpdateAllStickersAsync(TLAllStickers cachedStickers) + { + var hash = cachedStickers != null ? cachedStickers.Hash : TLString.Empty; + + IsWorking = true; + MTProtoService.GetAllStickersAsync(hash, + result => BeginOnUIThread(() => + { + Execute.ShowDebugMessage(result.ToString()); + + Status = string.Empty; + IsWorking = false; + + var allStickers = result as TLAllStickers43; + if (allStickers != null) + { + Items.Clear(); + + var cachedStickers29 = cachedStickers as TLAllStickers29; + if (cachedStickers29 != null) + { + allStickers.ShowStickersTab = cachedStickers29.ShowStickersTab; + allStickers.RecentlyUsed = cachedStickers29.RecentlyUsed; + allStickers.Date = TLUtils.DateToUniversalTimeTLInt(0, DateTime.Now); + } + var cachedStickers43 = cachedStickers as TLAllStickers43; + if (cachedStickers43 != null) + { + allStickers.RecentStickers = cachedStickers43.RecentStickers; + allStickers.FavedStickers = cachedStickers43.FavedStickers; + } + + cachedStickers = allStickers; + StateService.SaveAllStickersAsync(cachedStickers); + + UpdateSets(allStickers, () => { }); + } + }), + error => BeginOnUIThread(() => + { + Status = string.Empty; + IsWorking = false; + Execute.ShowDebugMessage("messages.getAllStickers error " + error); + })); + } + private void UpdateSets(TLAllStickers29 allStickers, System.Action callback) + { + _allStickers = allStickers; + + _emoticons.Clear(); + _stickerSets.Clear(); + + for (var i = 0; i < allStickers.Documents.Count; i++) + { + var document22 = allStickers.Documents[i] as TLDocument22; + if (document22 != null) + { + if (document22.StickerSet != null) + { + var setId = document22.StickerSet.Name; + TLVector stickers; + if (_stickerSets.TryGetValue(setId, out stickers)) + { + stickers.Add(new TLStickerItem { Document = document22 }); + } + else + { + _stickerSets[setId] = new TLVector { new TLStickerItem { Document = document22 } }; + } + } + } + } + + Items.Clear(); + + var firstChunkSize = 10; + var count = 0; + var delayedItems = new List(); + for (var i = 0; i < allStickers.Sets.Count; i++) + { + var set = allStickers.Sets[i]; + var setName = set.Id.ToString(); + TLVector stickers; + if (_stickerSets.TryGetValue(setName, out stickers)) + { + + var objects = new TLVector(); + foreach (var sticker in stickers) + { + objects.Add(sticker); + } + + set.IsSelected = StickerSet != null && TLString.Equals(StickerSet.ShortName, set.ShortName, StringComparison.OrdinalIgnoreCase); + set.Stickers = objects; + if (set.Stickers.Count > 0) + { + if (count < firstChunkSize) + { + Items.Add(set); + count++; + } + else + { + delayedItems.Add(set); + } + } + } + } + + AddItemsChunk(25, delayedItems, callback); + } + + private void AddItemsChunk(int chunkSize, List delayedItems, System.Action callback) + { + BeginOnUIThread(() => + { + for (var i = 0; i < delayedItems.Count && i < chunkSize; i++) + { + var stickerSet = delayedItems[i] as TLStickerSet; + if (stickerSet != null) + { + stickerSet.IsSelected = StickerSet != null && TLString.Equals(StickerSet.ShortName, stickerSet.ShortName, StringComparison.OrdinalIgnoreCase); + } + + Items.Add(delayedItems[0]); + delayedItems.RemoveAt(0); + } + + if (delayedItems.Count > 0) + { + AddItemsChunk(25, delayedItems, callback); + } + else + { + callback.SafeInvoke(); + } + }); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Contacts/ShareContactDetailsViewModel.cs b/TelegramClient.WP81/ViewModels/Contacts/ShareContactDetailsViewModel.cs new file mode 100755 index 0000000..a44c98f --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Contacts/ShareContactDetailsViewModel.cs @@ -0,0 +1,142 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.ObjectModel; +using System.Linq; +using System.Windows; +using Caliburn.Micro; +using Microsoft.Phone.Tasks; +using Telegram.Api.Extensions; +using Telegram.Api.TL; +using TelegramClient.Resources; + +namespace TelegramClient.ViewModels.Contacts +{ + public class ShareContactDetailsViewModel : PropertyChangedBase + { + public Visibility ShareVisibility + { + get { return Mode == ShareContactDetailsMode.Share ? Visibility.Visible : Visibility.Collapsed; } + } + + public string ActionString + { + get { return Mode == ShareContactDetailsMode.Share ? AppResources.ShareContact : AppResources.AddContact; } + } + + public TLUserBase CurrentItem { get; set; } + + public ObservableCollection Items { get; set; } + + public ShareContactDetailsViewModel(TLUserBase contact) + { + Items = new ObservableCollection(); + SetContact(contact); + } + + public void ForwardInAnimationBegin() + { + + } + + public void ForwardInAnimationComplete() + { + + } + + public Action Callback { get; set; } + + public ShareContactDetailsMode Mode { get; set; } + + public bool IsSharingEnabled { get { return Items.OfType().Any(x => x.IsSelected); } } + + public void Send() + { + if (CurrentItem == null) return; + + var userPhone = Items.OfType().FirstOrDefault(x => x.IsSelected); + if (userPhone == null) return; + + var media = new TLMessageMediaContact82 + { + UserId = CurrentItem.Id, + FirstName = CurrentItem.FirstName, + LastName = CurrentItem.LastName, + PhoneNumber = userPhone.Number, + VCard = ToVCard(CurrentItem) + }; + + Callback.SafeInvoke(media); + } + + private TLString ToVCard(TLUserBase currentItem) + { + return TLString.Empty; + } + + public void Call(TLUserPhone userPhone) + { + if (Mode != ShareContactDetailsMode.View) return; + if (userPhone == null) return; + + var phoneNumber = userPhone.Number.ToString(); + if (!string.IsNullOrEmpty(phoneNumber)) + { + if (!phoneNumber.StartsWith("+")) + { + phoneNumber = "+" + phoneNumber; + } + + var task = new PhoneCallTask(); + task.DisplayName = CurrentItem.FullName2; + task.PhoneNumber = phoneNumber; + task.Show(); + } + } + + public void SetContact(TLUserBase userBase) + { + CurrentItem = userBase; + NotifyOfPropertyChange(() => CurrentItem); + + Items.Clear(); + var userNotRegistered = userBase as TLUserNotRegistered; + if (userNotRegistered != null) + { + if (userNotRegistered.Phones != null) + { + foreach (var phone in userNotRegistered.Phones) + { + Items.Add(phone); + } + } + } + + if (Items.Count == 0) + { + Items.Add(new TLUserPhone + { + Kind = new TLInt(1), + Number = userBase.Phone, + Description = TLString.Empty + }); + } + + + for (var index = 0; index < Items.Count; index++) + { + var userPhone = Items[index] as TLUserPhone; + if (userPhone != null) + { + userPhone.IsSelected = index == 0; + userPhone.IsIconVisible = index == 0; + } + } + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Dialogs/DialogDetailsViewModel.Mentions.cs b/TelegramClient.WP81/ViewModels/Dialogs/DialogDetailsViewModel.Mentions.cs new file mode 100755 index 0000000..7b06320 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Dialogs/DialogDetailsViewModel.Mentions.cs @@ -0,0 +1,328 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using Telegram.Api.Helpers; +using Telegram.Api.TL; +using Telegram.Api.TL.Interfaces; +using TelegramClient.Resources; + +namespace TelegramClient.ViewModels.Dialogs +{ + public partial class DialogDetailsViewModel + { + private int _mentionsCounter; + + public int MentionsCounter + { + get { return _mentionsCounter; } + set { SetField(ref _mentionsCounter, value, () => MentionsCounter); } + } + + private TLMessageBase _currentMention; + + private void GetUnreadMentionsAsync() + { + var dialog = CurrentDialog as TLDialog71; + if (dialog == null) return; + if (dialog.UnreadMentionsCount.Value <= 0) return; + + var peer = With as IInputPeer; + if (peer != null) + { + MTProtoService.GetUnreadMentionsAsync( + peer.ToInputPeer(), + new TLInt(0), + new TLInt(0), + new TLInt(0), + new TLInt(0), + new TLInt(0), + result => Execute.BeginOnUIThread(() => + { + dialog.UnreadMentionsCount = new TLInt(result.Messages.Count); + dialog.UnreadMentions = result.Messages; + MentionsCounter = dialog.UnreadMentionsCount.Value; + + if (MentionsCounter == 0) + { + Execute.BeginOnUIThread(() => + { + View.HideMentionButton(); + }); + } + }), + error => + { + Execute.ShowDebugMessage("messages.getUnreadMentions error " + error); + }); + } + } + + public void ClearUnreadMentions() + { + var dialog = CurrentDialog as TLDialog71; + if (dialog == null) return; + if (dialog.UnreadMentions == null || dialog.UnreadMentions.Count == 0) + { + dialog.UnreadMentionsCount = new TLInt(0); + dialog.NotifyOfPropertyChange(() => dialog.UnreadMentionsCount); + + return; + } + + var confirmation = MessageBox.Show(AppResources.ClearUnreadMentionsConfirmation, AppResources.Confirm, MessageBoxButton.OKCancel); + if (confirmation != MessageBoxResult.OK) return; + + MentionsCounter = 0; + Execute.BeginOnUIThread(() => + { + View.HideMentionButton(); + }); + + var channel = dialog.With as TLChannel68; + if (channel != null) + { + MTProtoService.ReadMessageContentsAsync(channel.ToInputChannel(), new TLVector(dialog.UnreadMentions.Select(x => x.Id).ToList()), + result => Execute.BeginOnUIThread(() => + { + dialog.UnreadMentionsCount = new TLInt(0); + dialog.NotifyOfPropertyChange(() => dialog.UnreadMentionsCount); + + var mentionsCache = dialog.UnreadMentions.ToDictionary(x => x.Index); + dialog.UnreadMentions.Clear(); + + foreach (var item in Items) + { + if (mentionsCache.ContainsKey(item.Index)) + { + var message = item as TLMessage25; + if (message != null && message.IsVoice()) + { + message.SetListened(); + message.Media.NotListened = false; + message.Media.NotifyOfPropertyChange(() => message.Media.NotListened); + } + } + } + })); + } + else + { + MTProtoService.ReadMessageContentsAsync(new TLVector(dialog.UnreadMentions.Select(x => x.Id).ToList()), + result => Execute.BeginOnUIThread(() => + { + dialog.UnreadMentionsCount = new TLInt(0); + dialog.NotifyOfPropertyChange(() => dialog.UnreadMentionsCount); + var mentionsCache = dialog.UnreadMentions.ToDictionary(x => x.Index); + dialog.UnreadMentions.Clear(); + + foreach (var item in Items) + { + if (mentionsCache.ContainsKey(item.Index)) + { + var message = item as TLMessage25; + if (message != null && message.IsVoice()) + { + message.SetListened(); + message.Media.NotListened = false; + message.Media.NotifyOfPropertyChange(() => message.Media.NotListened); + } + } + } + })); + } + } + + public void ReadMentions(int maxId) + { + if (maxId <= 0) return; + + var dialog = CurrentDialog as TLDialog71; + if (dialog == null) return; + if (dialog.UnreadMentions == null) return; + if (dialog.UnreadMentions.Count == 0) return; + + var mentions = new List(); + for (int i = dialog.UnreadMentions.Count - 1; i >= 0; i--) + { + var message = dialog.UnreadMentions[i] as TLMessage; + if (message != null && message.IsVoice()) continue; + + + if (dialog.UnreadMentions[i].Index <= maxId) + { + mentions.Add(dialog.UnreadMentions[i]); + } + else + { + break; + } + } + + if (mentions.Count > 0) + { + MentionsCounter = Math.Max(0, MentionsCounter - mentions.Count); + + if (MentionsCounter == 0) + { + Execute.BeginOnUIThread(() => + { + View.HideMentionButton(); + }); + } + + var channel = dialog.With as TLChannel68; + if (channel != null) + { + MTProtoService.ReadMessageContentsAsync(channel.ToInputChannel(), new TLVector(mentions.Select(x => x.Id).ToList()), + result => Execute.BeginOnUIThread(() => + { + dialog.UnreadMentionsCount = new TLInt(Math.Max(0, dialog.UnreadMentions.Count - mentions.Count)); + dialog.NotifyOfPropertyChange(() => dialog.UnreadMentionsCount); + foreach (var mention in mentions) + { + dialog.UnreadMentions.Remove(mention); + } + })); + } + else + { + MTProtoService.ReadMessageContentsAsync(new TLVector(mentions.Select(x => x.Id).ToList()), + result => Execute.BeginOnUIThread(() => + { + dialog.UnreadMentionsCount = new TLInt(Math.Max(0, dialog.UnreadMentions.Count - mentions.Count)); + dialog.NotifyOfPropertyChange(() => dialog.UnreadMentionsCount); + foreach (var mention in mentions) + { + dialog.UnreadMentions.Remove(mention); + } + })); + } + } + } + + public void ReadNextMention() + { + var dialog = CurrentDialog as TLDialog71; + if (dialog == null) return; + if (dialog.UnreadMentions == null) return; + if (dialog.UnreadMentions.Count == 0) return; + + _currentMention = GetNextMention(_currentMention, dialog.UnreadMentions); + if (_currentMention == null) return; + + var message = _currentMention as TLMessage; + if (message != null && message.IsVoice()) + { + Execute.BeginOnUIThread(() => + { + OpenMessage(null, _currentMention.Id); + }); + return; + } + + MentionsCounter = Math.Max(0, MentionsCounter - 1); + + if (MentionsCounter == 0) + { + Execute.BeginOnUIThread(() => + { + if (_currentMention != null && _currentMention.Index == dialog.TopMessageId.Value) + { + View.HideScrollToBottomButton(); + } + else + { + View.HideMentionButton(); + } + }); + } + + Execute.BeginOnUIThread(() => + { + OpenMessage(null, _currentMention.Id); + }); + + var channel = dialog.With as TLChannel68; + if (channel != null) + { + MTProtoService.ReadMessageContentsAsync(channel.ToInputChannel(), new TLVector{ _currentMention.Id }, + result => Execute.BeginOnUIThread(() => + { + dialog.UnreadMentionsCount = new TLInt(Math.Max(0, dialog.UnreadMentions.Count - 1)); + dialog.NotifyOfPropertyChange(() => dialog.UnreadMentionsCount); + dialog.UnreadMentions.Remove(_currentMention); + })); + } + else + { + MTProtoService.ReadMessageContentsAsync(new TLVector { _currentMention.Id }, + result => Execute.BeginOnUIThread(() => + { + dialog.UnreadMentionsCount = new TLInt(Math.Max(0, dialog.UnreadMentions.Count - 1)); + dialog.NotifyOfPropertyChange(() => dialog.UnreadMentionsCount); + dialog.UnreadMentions.Remove(_currentMention); + })); + } + } + + private TLMessageBase GetNextMention(TLMessageBase currentMention, TLVector mentions) + { + if (mentions == null) return null; + if (currentMention == null) return mentions.LastOrDefault(); + + for (var i = mentions.Count - 1; i >= 0; i--) + { + if (mentions[i].Index == currentMention.Index) + { + if (i >= 1) + { + return mentions[i - 1]; + } + break; + } + } + + if (mentions.Count > 0) + { + return mentions.LastOrDefault(); + } + + return null; + } + + private void ListenMention(int id) + { + var dialog71 = CurrentDialog as TLDialog71; + if (dialog71 != null && dialog71.UnreadMentions != null) + { + for (var i = 0; i < dialog71.UnreadMentions.Count; i++) + { + if (id == dialog71.UnreadMentions[i].Index) + { + dialog71.UnreadMentions.RemoveAt(i); + dialog71.UnreadMentionsCount = new TLInt(Math.Max(0, dialog71.UnreadMentions.Count - 1)); + dialog71.NotifyOfPropertyChange(() => dialog71.UnreadMentionsCount); + MentionsCounter = dialog71.UnreadMentionsCount.Value; + + if (MentionsCounter == 0) + { + Execute.BeginOnUIThread(() => + { + View.HideMentionButton(); + }); + } + break; + } + } + } + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Dialogs/EmojiHintsViewModel.cs b/TelegramClient.WP81/ViewModels/Dialogs/EmojiHintsViewModel.cs new file mode 100755 index 0000000..9dda92e --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Dialogs/EmojiHintsViewModel.cs @@ -0,0 +1,42 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.ObjectModel; +using TelegramClient.Views.Controls; +using TelegramClient_Native; + +namespace TelegramClient.ViewModels.Dialogs +{ + public class EmojiHintsViewModel + { + public ObservableCollection Hints { get; protected set; } + + public EmojiSuggestionParams Parameters { get; protected set; } + + public EmojiHintsViewModel() + { + Hints = new ObservableCollection(); + } + + public void SetParameters(EmojiSuggestionParams parameters) + { + Parameters = parameters; + + Hints.Clear(); + if (Parameters != null + && Parameters.Results != null) + { + int maxCount = 5; + for (int index = 0; index < parameters.Results.Length && index < maxCount; index++) + { + var result = parameters.Results[index]; + Hints.Add(result); + } + } + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Dialogs/LiveLocationBadgeViewModel.cs b/TelegramClient.WP81/ViewModels/Dialogs/LiveLocationBadgeViewModel.cs new file mode 100755 index 0000000..f2caf7b --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Dialogs/LiveLocationBadgeViewModel.cs @@ -0,0 +1,211 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using Caliburn.Micro; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.Location; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.Utils; + +namespace TelegramClient.ViewModels.Dialogs +{ + public class LiveLocationBadgeViewModel : PropertyChangedBase + { + public TLMessage Message { get; set; } + + public IList Messages { get; set; } + + public string Subtitle + { + get + { + if (IsChatListBadge) + { + var messages = _liveLocationsService.Get(); + if (messages.Count == 1) + { + var peerUser = messages[0].ToId as TLPeerUser; + if (peerUser != null) + { + var user = _cacheService.GetUser(peerUser.Id); + if (user != null) + { + return string.Format(" " + AppResources.AttachLiveLocationIsSharing, user.ShortName); + } + } + + var peerChat = messages[0].ToId as TLPeerChat; + if (peerChat != null) + { + var chat = _cacheService.GetChat(peerChat.Id); + if (chat != null) + { + return string.Format(" " + AppResources.AttachLiveLocationIsSharing, chat.FullName); + } + } + + var peerChannel = messages[0].ToId as TLPeerChannel; + if (peerChannel != null) + { + var chat = _cacheService.GetChat(peerChannel.Id); + if (chat != null) + { + return string.Format(" " + AppResources.AttachLiveLocationIsSharing, chat.FullName); + } + } + + return string.Format(" " + AppResources.AttachLiveLocationIsSharing, Language.Declension( + 1, + AppResources.ChatNominativeSingular, + AppResources.ChatNominativePlural, + AppResources.ChatGenitiveSingular, + AppResources.ChatGenitivePlural).ToLower(CultureInfo.CurrentUICulture)); + } + if (messages.Count > 1) + { + return string.Format(" " + AppResources.AttachLiveLocationIsSharing, Language.Declension( + messages.Count, + AppResources.ChatNominativeSingular, + AppResources.ChatNominativePlural, + AppResources.ChatGenitiveSingular, + AppResources.ChatGenitivePlural).ToLower(CultureInfo.CurrentUICulture)); + } + + return string.Empty; + } + else + { + if (Messages == null || Messages.Count == 0) + { + return string.Format(" - {0}", AppResources.You); + } + + var usersIndex = new Dictionary(); + var shortNames = new List(); + foreach (var messageBase in Messages) + { + var message = messageBase as TLMessage70; + if (message != null && !message.Out.Value) + { + var mediaGeoLive = message.Media as TLMessageMediaGeoLive; + if (mediaGeoLive != null) + { + mediaGeoLive.Date = message.Date; + mediaGeoLive.EditDate = message.EditDate; + if (mediaGeoLive.Active) + { + var user = message.From as TLUser; + if (user != null && !usersIndex.ContainsKey(user.Index)) + { + usersIndex[user.Index] = user.Index; + shortNames.Add(user.ShortName); + } + } + } + } + } + + if (shortNames.Count == 1) + { + return string.Format(" - " + AppResources.SharingYouAndOtherName, shortNames[0]); + } + + if (shortNames.Count > 1) + { + return string.Format(" - " + AppResources.SharingYouAndOtherName, Language.Declension( + shortNames.Count, + AppResources.CompanyNominativeSingular, + AppResources.CompanyNominativePlural, + AppResources.CompanyGenitiveSingular, + AppResources.CompanyGenitivePlural).ToLower(CultureInfo.CurrentUICulture)); + } + + return string.Format(" - {0}", AppResources.You); + } + } + } + + public bool IsChatListBadge { get; protected set; } + + private readonly ILiveLocationService _liveLocationsService; + + private readonly ICacheService _cacheService; + + public LiveLocationBadgeViewModel(ILiveLocationService liveLocationsService, ICacheService cacheService, bool chatListBadge) + { + _liveLocationsService = liveLocationsService; + _cacheService = cacheService; + + IsChatListBadge = chatListBadge; + + Messages = new ObservableCollection(); + } + + public event EventHandler Closed; + + public virtual void RaiseClosed() + { + var handler = Closed; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler OpenMessage; + + public virtual void RaiseOpenMessage() + { + var handler = OpenMessage; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public void UpdateLiveLocations(IList messages) + { + Messages.Clear(); + foreach (var m in messages) + { + Messages.Add(m); + } + NotifyOfPropertyChange(() => Subtitle); + } + + public void UpdateLiveLocation(TLMessage message) + { + var updated = false; + for (var i = 0; i < Messages.Count; i++) + { + var m = Messages[i] as TLMessage70; + if (m != null && m.Index == message.Index) + { + Messages[i] = message; + updated = true; + break; + } + } + + if (!updated) + { + Messages.Add(message); + } + + NotifyOfPropertyChange(() => Subtitle); + } + + public void RemoveLiveLocations(IList messages) + { + foreach (var m in messages) + { + Messages.Remove(m); + } + + NotifyOfPropertyChange(() => Subtitle); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Dialogs/PlayerViewModel.cs b/TelegramClient.WP81/ViewModels/Dialogs/PlayerViewModel.cs new file mode 100755 index 0000000..69ea316 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Dialogs/PlayerViewModel.cs @@ -0,0 +1,16 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Telegram.Api.TL; + +namespace TelegramClient.ViewModels.Dialogs +{ + public class PlayerViewModel + { + public TLMessageBase Message { get; set; } + } +} diff --git a/TelegramClient.WP81/ViewModels/Feed/FeedViewModel.cs b/TelegramClient.WP81/ViewModels/Feed/FeedViewModel.cs new file mode 100755 index 0000000..6e63f7d --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Feed/FeedViewModel.cs @@ -0,0 +1,125 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Windows; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.Utils; +using TelegramClient.ViewModels.Dialogs; + +namespace TelegramClient.ViewModels.Feed +{ + public class FeedViewModel : ItemsViewModelBase + { + public TLVector CurrentItem { get; set; } + + private string _subtitle; + + public string Subtitle + { + get { return _subtitle; } + set { SetField(ref _subtitle, value, () => Subtitle); } + } + + public FeedViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + CurrentItem = stateService.CurrentFeed; + stateService.CurrentFeed = null; + } + + protected override void OnActivate() + { + base.OnActivate(); + + UpdateSubtitles(); + } + + public void ForwardInAnimationComplete() + { + var channels = CurrentItem; + if (channels != null) + { + UpdateChannels(channels, UpdateItems); + } + } + + private void UpdateItems() + { + + } + + private void UpdateChannels(TLVector channels, System.Action callback) + { + const int firstSliceCount = 3; + var secondSlice = new List(); + for (var i = 0; i < channels.Count; i++) + { + if (i < firstSliceCount) + { + //users[i].IsAdmin = false; + Items.Add(channels[i]); + } + else + { + secondSlice.Add(channels[i]); + } + } + + Execute.BeginOnUIThread(() => + { + foreach (var user in secondSlice) + { + //user.IsAdmin = false; + Items.Add(user); + } + callback.SafeInvoke(); + }); + } + + public void ViewChannel(TLChatBase channel) + { + if (channel == null) return; + + StateService.With = channel; + StateService.RemoveBackEntries = true; + NavigationService.UriFor().Navigate(); + } + + public void UpdateSubtitles() + { + Subtitle = GetChatSubtitle(); + } + + private string GetChatSubtitle() + { + var channels = CurrentItem; + if (channels != null) + { + var channelsCount = channels.Count; + + return Language.Declension( + channelsCount, + AppResources.ChannelNominativeSingular, + AppResources.ChannelNominativePlural, + AppResources.ChannelGenitiveSingular, + AppResources.ChannelGenitivePlural).ToLower(CultureInfo.CurrentUICulture); + } + + return null; + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Media/EditVideoViewModel.cs b/TelegramClient.WP81/ViewModels/Media/EditVideoViewModel.cs new file mode 100755 index 0000000..768dde7 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Media/EditVideoViewModel.cs @@ -0,0 +1,757 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Threading.Tasks; +using System.Windows; +using Windows.Media.MediaProperties; +using Windows.Storage; +using Windows.Storage.FileProperties; +using Windows.Storage.Streams; +using Windows.System; +using Caliburn.Micro; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.TL; +using TelegramClient.Converters; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Additional; +using TelegramClient.ViewModels.Contacts; +using TelegramClient.ViewModels.Dialogs; + +namespace TelegramClient.ViewModels.Media +{ + public class EditVideoViewModel : ViewAware + { + protected bool SetField(ref T field, T value, string propertyName) + { + if (EqualityComparer.Default.Equals(field, value)) return false; + field = value; + NotifyOfPropertyChange(propertyName); + return true; + } + + protected bool SetField(ref T field, T value, Expression> selectorExpression) + { + if (EqualityComparer.Default.Equals(field, value)) return false; + field = value; + NotifyOfPropertyChange(selectorExpression); + return true; + } + + public TimerSpan SelectedQuality { get; set; } + + public Uri QualityButtonImageSource + { + get + { + if (SelectedQuality != null) + { + if (SelectedQuality.Seconds == 0) + { + return new Uri("/Images/W10M/ic_quality_auto_2x.png", UriKind.Relative); + } + if (SelectedQuality.Seconds <= 240) + { + return new Uri("/Images/W10M/ic_quality240_2x.png", UriKind.Relative); + } + if (SelectedQuality.Seconds <= 360) + { + return new Uri("/Images/W10M/ic_quality360_2x.png", UriKind.Relative); + } + if (SelectedQuality.Seconds <= 480) + { + return new Uri("/Images/W10M/ic_quality480_2x.png", UriKind.Relative); + } + if (SelectedQuality.Seconds <= 720) + { + return new Uri("/Images/W10M/ic_quality720_2x.png", UriKind.Relative); + } + if (SelectedQuality.Seconds <= 1080) + { + return new Uri("/Images/W10M/ic_quality1080_2x.png", UriKind.Relative); + } + } + + return new Uri("/Images/W10M/ic_quality_auto_2x.png", UriKind.Relative); + } + } + + public List QualityList { get; set; } + + private string _caption; + + public string Caption + { + get { return _caption; } + set { SetField(ref _caption, value, () => Caption); } + } + + public Visibility TimerButtonVisibility + { + get { return _with is TLUser ? Visibility.Visible : Visibility.Collapsed; } + } + + public TimerSpan TimerSpan { get; set; } + + private TimeSpan? _trimLeft; + + public TimeSpan? TrimLeft + { + get { return _trimLeft; } + set { SetField(ref _trimLeft, value, () => TrimLeft); } + } + + private TimeSpan? _trimRight; + + public TimeSpan? TrimRight + { + get { return _trimRight; } + set { SetField(ref _trimRight, value, () => TrimRight); } + } + + private bool _compression = false; + + public bool Compression + { + get { return _compression; } + set { SetField(ref _compression, value, () => Compression); } + } + + private bool _mute = true; + + public bool Mute + { + get { return _mute; } + set { SetField(ref _mute, value, () => Mute); } + } + + public Visibility TimerVisibility { get; set; } + + public ulong Size { get; set; } + + public ulong EditedSize { get; set; } + + public double Width { get; set; } + + public double Height { get; set; } + + public VideoOrientation Orientation { get; set; } + + public TimeSpan Duration { get; set; } + + public string DurationString { get; set; } + + public StorageFile VideoFile { get; set; } + + public TLPhotoSizeBase ThumbPhoto { get; set; } + + private TLPhotoSizeBase _previewPhoto; + + public TLPhotoSizeBase PreviewPhoto + { + get { return _previewPhoto; } + set { _previewPhoto = value; } + } + + public string OriginalVideoParameters { get; protected set; } + + public string EditedVideoParameters { get; protected set; } + + private bool _isMuteEnabled; + + public bool IsMuteEnabled + { + get { return _isMuteEnabled; } + set { SetField(ref _isMuteEnabled, value, () => IsMuteEnabled); } + } + + private bool _isOpen; + + public bool IsOpen + { + get { return _isOpen; } + set { SetField(ref _isOpen, value, () => IsOpen); } + } + + private Tuple _properties; + + public readonly Action _sendVideoAction; + + private readonly Func> _getUsernameHints; + + public readonly TLObject _with; + + public EditVideoViewModel(Action sendVideoAction, Func> getUsernameHints, TLObject with) + { + _with = with; + _getUsernameHints = getUsernameHints; + _sendVideoAction = sendVideoAction; + + PropertyChanged += (sender, args) => + { + if (Property.NameEquals(args.PropertyName, () => SelectedQuality)) + { + UpdateEditedVideoParameters(); + + NotifyOfPropertyChange(() => EditedVideoParameters); + } + else if (Property.NameEquals(args.PropertyName, () => IsMuteEnabled)) + { + UpdateEditedVideoParameters(); + + NotifyOfPropertyChange(() => EditedVideoParameters); + } + else if (Property.NameEquals(args.PropertyName, () => Caption)) + { + LoadMentionHints(Caption); + } + }; + } + + #region Mentions + + private IList _mentions; + + public void ContinueLoadMentionHints() + { + if (!string.IsNullOrEmpty(Caption)) + { + var cachedResult = _getUsernameHints.Invoke(Caption); + if (cachedResult.Count > MaxResults) + { + CreateUsernameHints(); + + if (UsernameHints.Hints.Count == MaxResults) + { + var lastItem = UsernameHints.Hints.LastOrDefault(); + if (lastItem != null) + { + var lastIndex = cachedResult.IndexOf(lastItem); + if (lastIndex >= 0) + { + for (var i = lastIndex + 1; i < cachedResult.Count; i++) + { + UsernameHints.Hints.Add(cachedResult[i]); + } + } + } + } + } + } + } + + private void LoadMentionHints(string text) + { + if (_getUsernameHints != null) + { + var cachedResult = _getUsernameHints.Invoke(text); + if (cachedResult.Count > 0) + { + CreateUsernameHints(); + + ClearUsernameHints(); + for (var i = 0; i < cachedResult.Count; i++) + { + if (UsernameHints.Hints.Count == MaxResults) break; + + UsernameHints.Hints.Add(cachedResult[i]); + } + } + else + { + ClearUsernameHints(); + } + } + } + + public void AddMention(TLUserBase userBase) + { + _mentions = _mentions ?? new List(); + _mentions.Add(userBase); + } + + private const int MaxResults = 10; + + public UsernameHintsViewModel UsernameHints { get; protected set; } + + private void CreateUsernameHints() + { + if (UsernameHints == null) + { + UsernameHints = new UsernameHintsViewModel(); + NotifyOfPropertyChange(() => UsernameHints); + } + } + + private void ClearUsernameHints() + { + if (UsernameHints != null) + { + UsernameHints.Hints.Clear(); + } + } + #endregion + + public void SetVideoFile(StorageFile file) + { + _mentions = null; + _encodingProfile = null; + VideoFile = file; + NotifyOfPropertyChange(() => VideoFile); + PreviewPhoto = null; + NotifyOfPropertyChange(() => PreviewPhoto); + Caption = string.Empty; + Compression = false; + Mute = true; + IsMuteEnabled = false; + SelectedQuality = null; + QualityList = null; + TimerSpan = null; + + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + _properties = GetProperties(VideoFile).Result; + + var properties = _properties.Item1; + var videoProperties = _properties.Item2; + + Size = properties.Size; + Duration = videoProperties.Duration; + Orientation = videoProperties.Orientation; + Width = Orientation == VideoOrientation.Normal || Orientation == VideoOrientation.Rotate180 ? videoProperties.Width : videoProperties.Height; + Height = Orientation == VideoOrientation.Normal || Orientation == VideoOrientation.Rotate180 ? videoProperties.Height : videoProperties.Width; + + DurationString = GetDurationString(Duration); + var originalSizeString = FileSizeConverter.Convert((long)properties.Size); + + OriginalVideoParameters = string.Format("{0}x{1}, {2}, {3}", Width, Height, DurationString, originalSizeString); + + var minLength = Math.Min(Width, Height); + SelectedQuality = GetSelectedQuality(minLength); + QualityList = GetQualityList(minLength); + + UpdateEditedVideoParameters(); + + var tuple = GetFilePreviewAndThumbAsync(VideoFile).Result; + PreviewPhoto = tuple.Item1; + ThumbPhoto = tuple.Item2; + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + NotifyOfPropertyChange(() => SelectedQuality); + NotifyOfPropertyChange(() => QualityButtonImageSource); + NotifyOfPropertyChange(() => DurationString); + NotifyOfPropertyChange(() => OriginalVideoParameters); + if (QualityList.Count > 1) + { + Compression = true; + } + + NotifyOfPropertyChange(() => EditedVideoParameters); + NotifyOfPropertyChange(() => PreviewPhoto); + + var musicProperties = _properties.Item3; + if (musicProperties == null || musicProperties.Bitrate == 0) + { + IsMuteEnabled = true; + Mute = false; + } + }); + }); + } + + private TimerSpan GetSelectedQuality(double minLength) + { + if (minLength > 360) + { + return new TimerSpan(string.Empty, "360", 360); + } + + return new TimerSpan(string.Empty, AppResources.Auto, 0); + } + + private List GetQualityList(double minLength) + { + var list = new List { new TimerSpan(string.Empty, AppResources.Auto, 0) }; + if (minLength > 240) + { + list.Add(new TimerSpan(string.Empty, "240", 240)); + } + if (minLength > 360) + { + list.Add(new TimerSpan(string.Empty, "360", 360)); + } + //if (minLength > 480) + //{ + // list.Add(new TimerSpan(string.Empty, "480", 480)); + //} + if (minLength > 720) + { + list.Add(new TimerSpan(string.Empty, "720", 720)); + } + if (minLength > 1080) + { + list.Add(new TimerSpan(string.Empty, "1080", 1080)); + } + + return list; + } + + private async Task> GetProperties(StorageFile videoFile) + { + var properties = await videoFile.GetBasicPropertiesAsync(); + var videoProperties = await videoFile.Properties.GetVideoPropertiesAsync(); + var musicProperties = await videoFile.Properties.GetMusicPropertiesAsync(); + + return new Tuple(properties, videoProperties, musicProperties); + } + + public void UpdateEditedVideoDuration() + { + var duration = GetEditedDuration(TrimLeft, TrimRight, Duration); + if (IsMuteEnabled) // gif + { + EditedSize = (ulong)(_editedBitrate * duration.TotalSeconds) / 8; + } + else if (SelectedQuality != null && SelectedQuality.Seconds > 0) // compressed quality + { + EditedSize = (ulong)(_editedBitrate * duration.TotalSeconds) / 8; + } + else // default quality + { + EditedSize = (ulong)(Size / Duration.TotalSeconds * duration.TotalSeconds); + } + + var editedSizeString = FileSizeConverter.Convert((long)EditedSize); + + EditedVideoParameters = string.Format("{0}x{1}, {2}, ~{3}", _editedWidth, _editedHeight, GetDurationString(duration), editedSizeString); + NotifyOfPropertyChange(() => EditedVideoParameters); + } + + private void UpdateEditedVideoParameters() + { + var minLength = Math.Min(Width, Height); + var scaleFactor = SelectedQuality != null && SelectedQuality.Seconds != 0 ? SelectedQuality.Seconds / minLength : 1.0; + var duration = GetEditedDuration(TrimLeft, TrimRight, Duration); + _editedBitrate = SetEditedBitrate(); + + if (IsMuteEnabled) // gif + { + EditedSize = (ulong)(_editedBitrate * duration.TotalSeconds) / 8; + } + else if (SelectedQuality != null && SelectedQuality.Seconds > 0) // compressed quality + { + EditedSize = (ulong)(_editedBitrate * duration.TotalSeconds) / 8; + } + else // default quality + { + EditedSize = (ulong)(Size / Duration.TotalSeconds * duration.TotalSeconds); + } + + var editedSizeString = FileSizeConverter.Convert((long)EditedSize); + _editedHeight = (uint)(Height * scaleFactor); + _editedWidth = (uint)(Width * scaleFactor); + if (_encodingProfile != null) + { + _encodingProfile.Video.Height = _properties.Item2.Orientation == VideoOrientation.Normal || _properties.Item2.Orientation == VideoOrientation.Rotate180? _editedHeight : _editedWidth; + _encodingProfile.Video.Width = _properties.Item2.Orientation == VideoOrientation.Normal || _properties.Item2.Orientation == VideoOrientation.Rotate180 ? _editedWidth : _editedHeight; + } + + EditedVideoParameters = string.Format("{0}x{1}, {2}, ~{3}", _editedWidth, _editedHeight, GetDurationString(duration), editedSizeString); + } + + private MediaEncodingProfile _encodingProfile; + private ulong _editedBitrate; + private uint _editedHeight; + private uint _editedWidth; + + private ulong SetEditedBitrate() + { + ulong bitrate = 0; + if (IsMuteEnabled) + { + int targetVideoBitrate = 900000; + _encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Vga); + var minLength = Math.Min(Width, Height); + var scaleFactor = SelectedQuality != null && SelectedQuality.Seconds != 0 ? SelectedQuality.Seconds / minLength : 1.0; + var originalVideoBitrate = _properties != null && _properties.Item2 != null + ? _properties.Item2.Bitrate + : uint.MaxValue; + _encodingProfile.Video.Bitrate = (uint)Math.Min(targetVideoBitrate, (int)(originalVideoBitrate * scaleFactor)); + _encodingProfile.Audio = null; + bitrate += _encodingProfile.Video.Bitrate; + } + else if (SelectedQuality != null && SelectedQuality.Seconds > 0) + { + int targetVideoBitrate = 0; + int targetAudioBitrate = 90000; + switch (SelectedQuality.Seconds) + { + case 240: + _encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Qvga); + targetVideoBitrate = 400000; + break; + case 360: + _encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Vga); + targetVideoBitrate = 900000; + break; + case 480: + _encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Vga); + targetVideoBitrate = 900000; + break; + case 720: + _encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD720p); + targetVideoBitrate = 1100000; + break; + default: + _encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD1080p); + targetVideoBitrate = 1600000; + break; + } + + var minLength = Math.Min(Width, Height); + var scaleFactor = SelectedQuality != null && SelectedQuality.Seconds != 0 ? SelectedQuality.Seconds / minLength : 1.0; + var originalVideoBitrate = _properties != null && _properties.Item2 != null + ? _properties.Item2.Bitrate + : uint.MaxValue; + _encodingProfile.Video.Bitrate = (uint)Math.Min(targetVideoBitrate, (int)(originalVideoBitrate * scaleFactor)); + bitrate += _encodingProfile.Video.Bitrate; + if (!IsMuteEnabled) + { + var originalAudioBitrate = _properties != null && _properties.Item3 != null + ? _properties.Item3.Bitrate + : uint.MaxValue; + _encodingProfile.Audio.ChannelCount = 1; + _encodingProfile.Audio.Bitrate = (uint)Math.Min(targetAudioBitrate, originalAudioBitrate); + bitrate += _encodingProfile.Audio.Bitrate; + } + else + { + _encodingProfile.Audio = null; + } + } + else + { + _encodingProfile = null; + if (_properties != null && _properties.Item2 != null) + { + bitrate += _properties.Item2.Bitrate; + } + if (_properties != null && _properties.Item3 != null && !IsMuteEnabled) + { + bitrate += _properties.Item3.Bitrate; + } + } + + return bitrate; + } + + + + public void OpenVideo() + { + Launcher.LaunchFileAsync(VideoFile); + } + + private static async Task> GetFilePreviewAndThumbAsync(StorageFile file) + { + try + { + var preview = await file.GetThumbnailAsync(ThumbnailMode.SingleItem, 480, ThumbnailOptions.ResizeThumbnail); + + var thumbLocation = new TLFileLocation + { + DCId = new TLInt(0), + VolumeId = TLLong.Random(), + LocalId = TLInt.Random(), + Secret = TLLong.Random(), + }; + + var thumbFileName = String.Format("{0}_{1}_{2}.jpg", + thumbLocation.VolumeId, + thumbLocation.LocalId, + thumbLocation.Secret); + + var previewLocation = new TLFileLocation + { + DCId = new TLInt(0), + VolumeId = TLLong.Random(), + LocalId = TLInt.Random(), + Secret = TLLong.Random(), + }; + + var previewFileName = String.Format("{0}_{1}_{2}.jpg", + previewLocation.VolumeId, + previewLocation.LocalId, + previewLocation.Secret); + + var previewFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(previewFileName, CreationCollisionOption.ReplaceExisting); + var previewBuffer = new Windows.Storage.Streams.Buffer(Convert.ToUInt32(preview.Size)); + var iBuf = await preview.ReadAsync(previewBuffer, previewBuffer.Capacity, InputStreamOptions.None); + + var filePreview = new TLPhotoSize + { + W = new TLInt((int) preview.OriginalWidth), + H = new TLInt((int) preview.OriginalHeight), + Size = new TLInt((int) preview.Size), + Type = TLString.Empty, + Location = previewLocation, + }; + + Photo thumb; + using (var previewStream = await previewFile.OpenAsync(FileAccessMode.ReadWrite)) + { + await previewStream.WriteAsync(iBuf); + + thumb = await ChooseAttachmentViewModel.ResizeJpeg(previewStream, 90, thumbFileName); + } + + var thumbFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(thumbFileName, CreationCollisionOption.ReplaceExisting); + var iBuf2 = thumb.Bytes.AsBuffer(); + using (var thumbStream = await thumbFile.OpenAsync(FileAccessMode.ReadWrite)) + { + await thumbStream.WriteAsync(iBuf2); + } + + var fileThumb = new TLPhotoSize + { + W = new TLInt(thumb.Width), + H = new TLInt(thumb.Height), + Size = new TLInt(thumb.Bytes.Length), + Type = new TLString("s"), + Location = thumbLocation, + }; + + return new Tuple(filePreview, fileThumb); + } + catch (Exception ex) + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("GetFilePreviewAndThumbAsync exception " + ex); + } + + return new Tuple(null, null); + } + + private static TimeSpan GetEditedDuration(TimeSpan? leftTrim, TimeSpan? rightTrim, TimeSpan duration) + { + var start = leftTrim ?? TimeSpan.Zero; + var end = rightTrim ?? duration; + + return end - start; + } + + private static string GetDurationString(TimeSpan duration) + { + if (duration.Hours > 0) + { + return duration.ToString(@"h\:mm\:ss"); + } + + if (duration.TotalSeconds < 1.0) + { + return duration.ToString(@"m\:ss\.fff"); + } + + return duration.ToString(@"m\:ss"); + } + + public void Done() + { + CloseEditor(); + + var videoFile = new CompressingVideoFile + { + EncodingProfile = _encodingProfile, + TimerSpan = TimerSpan, + Size = EditedSize, + Duration = GetEditedDuration(TrimLeft, TrimRight, Duration).TotalSeconds, + Width = Width, + Height = Height, + Orientation = Orientation, + Source = VideoFile, + ThumbPhoto = ThumbPhoto, + TrimStartTime = TrimLeft ?? TimeSpan.Zero, + TrimStopTime = TrimRight ?? TimeSpan.Zero, + Caption = Caption, + Mentions = _mentions + }; + + DeletePreviewAsync(); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(TimeSpan.FromSeconds(0.25), () => _sendVideoAction.SafeInvoke(videoFile)); + } + + public void Cancel() + { + DeletePreviewAsync(); + } + + private void DeletePreviewAsync() + { + var preview = PreviewPhoto as TLPhotoSize; + if (preview != null) + { + var fileLocation = preview.Location as TLFileLocation; + if (fileLocation != null) + { + var fileName = String.Format("{0}_{1}_{2}.jpg", + fileLocation.VolumeId, + fileLocation.LocalId, + fileLocation.Secret); + + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => FileUtils.Delete(new object(), fileName)); + } + } + } + + public void OpenEditor() + { + IsOpen = true; + } + + public void CloseEditor() + { + IsOpen = false; + } + } + + public class CompressingVideoFile + { + public MediaEncodingProfile EncodingProfile { get; set; } + + public TimeSpan TrimStartTime { get; set; } + + public TimeSpan TrimStopTime { get; set; } + + public TimerSpan TimerSpan { get; set; } + + public ulong Size { get; set; } + + public double Duration { get; set; } + + public double Width { get; set; } + + public double Height { get; set; } + + public VideoOrientation Orientation { get; set; } + + public StorageFile Source { get; set; } + + public TLPhotoSizeBase ThumbPhoto { get; set; } + + public string Caption { get; set; } + + public IList Mentions { get; set; } + } +} diff --git a/TelegramClient.WP81/ViewModels/Passport/EmailCodeViewModel.cs b/TelegramClient.WP81/ViewModels/Passport/EmailCodeViewModel.cs new file mode 100755 index 0000000..ac804c2 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Passport/EmailCodeViewModel.cs @@ -0,0 +1,228 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Additional; + +namespace TelegramClient.ViewModels.Passport +{ + public class EmailCodeViewModel : ViewModelBase + { + private string _code; + + public string Code + { + get { return _code; } + set { SetField(ref _code, value, () => Code); } + } + + public string Subtitle { get; set; } + + public int CodeLength { get; set; } + + public TLString CurrentEmail { get; set; } + + private TLSentEmailCode _sentCode; + + private readonly TLSecureValue _emailValue; + + private readonly TLPasswordBase _passwordBase; + + private readonly TLAuthorizationForm _authorizationForm; + + private readonly IList _secureValues; + + private readonly TLSecureValueTypeBase _secureType; + + private readonly SecureRequiredType _secureRequiredType; + + public EmailCodeViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _passwordBase = stateService.Password; + stateService.Password = null; + + _authorizationForm = stateService.AuthorizationForm; + stateService.AuthorizationForm = null; + + _secureValues = stateService.SecureValues; + stateService.SecureValues = null; + + _secureType = stateService.SecureType; + stateService.SecureType = null; + + _secureRequiredType = stateService.SecureRequiredType; + stateService.SecureRequiredType = null; + + CurrentEmail = stateService.CurrentEmail; + stateService.CurrentEmail = null; + + _emailValue = _secureRequiredType != null ? _secureRequiredType.DataValue : null; + + _sentCode = stateService.SentEmailCode; + stateService.SentEmailCode = null; + + Subtitle = GetSubtitle(); + + var length = _sentCode as ILength; + CodeLength = length != null ? length.Length.Value : Constants.DefaultCodeLength; + } + + private string GetSubtitle() + { + return string.Format(AppResources.PassportEmailVerifyInfo, CurrentEmail); + } + + public void Confirm() + { + IsWorking = true; + MTProtoService.VerifyEmailAsync( + CurrentEmail, + new TLString(Code), + auth => BeginOnUIThread(() => + { + var emailValue = _emailValue; + if (emailValue == null) + { + var secureType = _authorizationForm != null + ? _authorizationForm.RequiredTypes.FirstOrDefault(EmailViewModel.IsValidType) + : null; + + // add new email from passport settings + if (_secureType != null && EmailViewModel.IsValidType(_secureType)) + { + emailValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = _secureType + }; + } + // add new email from authorization form + else if (secureType != null) + { + emailValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = secureType + }; + } + else + { + return; + } + } + + IsWorking = + EmailViewModel.SaveEmailAsync( + CurrentEmail, _passwordBase as TLPassword, MTProtoService, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + if (_authorizationForm != null) + { + _authorizationForm.Values.Remove(emailValue); + _authorizationForm.Values.Add(result); + } + + emailValue.Update(result); + emailValue.NotifyOfPropertyChange(() => emailValue.Self); + + if (_secureType != null) + { + EventAggregator.Publish(new AddSecureValueEventArgs { Values = new List { emailValue } }); + } + + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + + NavigationService.RemoveBackEntry(); + NavigationService.GoBack(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + + if (error.CodeEquals(ErrorCode.BAD_REQUEST) + && error.TypeEquals(ErrorType.EMAIL_VERIFICATION_NEEDED)) + { + MTProtoService.SendVerifyEmailCodeAsync(CurrentEmail, + sentCode => BeginOnUIThread(() => + { + _sentCode = sentCode; + + Subtitle = GetSubtitle(); + NotifyOfPropertyChange(() => Subtitle); + + var length = _sentCode as ILength; + CodeLength = length != null ? length.Length.Value : Constants.DefaultCodeLength; + NotifyOfPropertyChange(() => CodeLength); + }), + error2 => BeginOnUIThread(() => + { + if (error.TypeEquals(ErrorType.EMAIL_INVALID)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.EmailInvalidString, AppResources.Error, AppResources.Ok); + } + else if (error.CodeEquals(ErrorCode.FLOOD)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.FloodWaitString + Environment.NewLine + "(" + error.Message + ")", AppResources.Error, AppResources.Ok); + } + else + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("account.sendVerifyEmailCode error " + error); + } + })); + } + else if (error.TypeEquals(ErrorType.EMAIL_INVALID)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.EmailInvalidString, AppResources.Error, AppResources.Ok); + } + })); + }), + error => BeginOnUIThread(() => + { + IsWorking = false; + if (error.TypeEquals(ErrorType.CODE_INVALID)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.EmailCodeInvalidString, AppResources.Error, AppResources.Ok); + } + else if (error.TypeEquals(ErrorType.CODE_EMPTY)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.EmailCodeEmpty, AppResources.Error, AppResources.Ok); + } + else if (error.TypeEquals(ErrorType.EMAIL_VERIFY_EXPIRED)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.EmailCodeExpiredString, AppResources.Error, AppResources.Ok); + } + else if (error.TypeEquals(ErrorType.EMAIL_INVALID)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.EmailInvalidString, AppResources.Error, AppResources.Ok); + } + else if (error.CodeEquals(ErrorCode.FLOOD)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.FloodWaitString + Environment.NewLine + "(" + error.Message + ")", AppResources.Error, AppResources.Ok); + } + else + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("account.verifyEmail error " + error); + } + })); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Passport/EmailViewModel.cs b/TelegramClient.WP81/ViewModels/Passport/EmailViewModel.cs new file mode 100755 index 0000000..aa88589 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Passport/EmailViewModel.cs @@ -0,0 +1,243 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; +using System.Collections.Generic; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Additional; + +namespace TelegramClient.ViewModels.Passport +{ + public class EmailViewModel : ViewModelBase + { + public string UseCurrentEmailCommand + { + get { return string.Format(AppResources.PassportPhoneUseSame, CurrentEmail); } + } + + public string Email { get; set; } + + public string CurrentEmail { get; set; } + + public static bool IsValidType(TLSecureValueTypeBase type) + { + return type is TLSecureValueTypeEmail; + } + + private readonly TLSecureValue _emailValue; + + private readonly TLPasswordBase _passwordBase; + + private readonly TLAuthorizationForm _authorizationForm; + + private readonly IList _secureValues; + + private readonly TLSecureValueTypeBase _secureType; + + private readonly SecureRequiredType _secureRequiredType; + + public EmailViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _passwordBase = stateService.Password; + stateService.Password = null; + + _authorizationForm = stateService.AuthorizationForm; + stateService.AuthorizationForm = null; + + _secureValues = stateService.SecureValues; + stateService.SecureValues = null; + + _secureType = stateService.SecureType; + stateService.SecureType = null; + + _secureRequiredType = stateService.SecureRequiredType; + stateService.SecureRequiredType = null; + + var password = _passwordBase as TLPassword81; + if (password != null) + { + var passwordSettings = password.Settings as TLPasswordSettings83; + if (passwordSettings != null) + { + CurrentEmail = TLString.IsNullOrEmpty(passwordSettings.Email)? string.Empty : passwordSettings.Email.ToString(); + } + } + + _emailValue = _secureRequiredType != null ? _secureRequiredType.DataValue : null; + } + + public void UseCurrentEmail() + { + if (!IsEmailValid(CurrentEmail)) return; + + SaveEmailAsync(new TLString(CurrentEmail)); + } + + public void Done() + { + if (!IsEmailValid(Email)) return; + if (IsWorking) return; + + SaveEmailAsync(new TLString(Email)); + } + + public bool IsEmailValid(string email) + { + return !IsWorking && !string.IsNullOrEmpty(email); + } + + public static bool SaveEmailAsync(TLString email, TLPassword password, IMTProtoService mtProtoService, Action callback, Action faultCallback = null) + { + if (password == null) + { + return false; + } + + var passwordSettings = password.Settings as TLPasswordSettings83; + if (passwordSettings == null) + { + return false; + } + + var inputSecureValue = new TLInputSecureValue85 + { + Flags = new TLInt(0), + Type = new TLSecureValueTypeEmail(), + PlainData = new TLSecurePlainEmail { Email = email } + }; + + var secureSecretId = passwordSettings.SecureSettings.SecureSecretId; + + mtProtoService.SaveSecureValueAsync( + inputSecureValue, secureSecretId, + callback.SafeInvoke, + faultCallback.SafeInvoke); + + return true; + } + + private void SaveEmailAsync(TLString email) + { + var emailValue = _emailValue; + if (emailValue == null) + { + var secureRequiredType = _secureRequiredType != null ? _secureRequiredType.DataRequiredType as TLSecureRequiredType : null; + var secureType = secureRequiredType != null && IsValidType(secureRequiredType.Type) + ? secureRequiredType.Type + : null; + + // add new email from passport settings + if (_secureType != null && IsValidType(_secureType)) + { + emailValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = _secureType + }; + } + // add new email from authorization form + else if (secureType != null) + { + emailValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = secureType + }; + } + else + { + return; + } + } + + IsWorking = + SaveEmailAsync( + email, _passwordBase as TLPassword, MTProtoService, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + if (_authorizationForm != null) + { + _authorizationForm.Values.Remove(emailValue); + _authorizationForm.Values.Add(result); + } + + emailValue.Update(result); + emailValue.NotifyOfPropertyChange(() => emailValue.Self); + + if (_secureType != null) + { + EventAggregator.Publish(new AddSecureValueEventArgs { Values = new List { emailValue } }); + } + + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + + NavigationService.GoBack(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + + if (error.CodeEquals(ErrorCode.BAD_REQUEST) + && error.TypeEquals(ErrorType.EMAIL_VERIFICATION_NEEDED)) + { + MTProtoService.SendVerifyEmailCodeAsync(email, + result2 => BeginOnUIThread(() => + { + StateService.SentEmailCode = result2; + StateService.CurrentEmail = email; + + StateService.Password = _passwordBase; + StateService.AuthorizationForm = _authorizationForm; + StateService.SecureValues = _secureValues; + StateService.SecureType = _secureType; + StateService.SecureRequiredType = _secureRequiredType; + NavigationService.UriFor().Navigate(); + }), + error2 => BeginOnUIThread(() => + { + if (error.TypeEquals(ErrorType.EMAIL_INVALID)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.EmailInvalidString, AppResources.Error, AppResources.Ok); + } + else if (error.CodeEquals(ErrorCode.FLOOD)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.FloodWaitString + Environment.NewLine + "(" + error.Message + ")", AppResources.Error, AppResources.Ok); + } + else + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("account.sendVerifyEmailCode error " + error); + } + })); + } + else if (error.TypeEquals(ErrorType.EMAIL_INVALID)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.EmailInvalidString, AppResources.Error, AppResources.Ok); + } + else if (error.CodeEquals(ErrorCode.BAD_REQUEST)) + { + ShellViewModel.ShowCustomMessageBox( + "account.saveSecureValue" + Environment.NewLine + error.Message, + AppResources.AppName, + AppResources.Ok); + } + })); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Passport/EnterPasswordViewModel.cs b/TelegramClient.WP81/ViewModels/Passport/EnterPasswordViewModel.cs new file mode 100755 index 0000000..f09b7dc --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Passport/EnterPasswordViewModel.cs @@ -0,0 +1,320 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.Utils; +using TelegramClient.ViewModels.Additional; +using TelegramClient.ViewModels.Dialogs; + +namespace TelegramClient.ViewModels.Passport +{ + public class EnterPasswordViewModel : PasswordViewModelBase + { + public TLUserBase Bot { get; set; } + + public string Hint + { + get + { + if (_authorizationForm == null) + { + return AppResources.PassportSelfRequest; + } + + return Bot == null + ? string.Empty + : string.Format(AppResources.PassportHint, Bot.FullName); + } + } + + public string BottomHint + { + get + { + if (_authorizationForm == null) + { + return AppResources.PassportRequestPasswordInfo; + } + + return null; + } + } + + public string RandomParam { get; set; } + + private readonly TLAuthorizationForm _authorizationForm; + + private readonly IList _secureValues; + + public static TLString Secret { get; protected set; } + + public EnterPasswordViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _authorizationForm = stateService.AuthorizationForm; + stateService.AuthorizationForm = null; + + _secureValues = stateService.SecureValues; + stateService.SecureValues = null; + + if (_authorizationForm != null) + { + Bot = _authorizationForm.Users.LastOrDefault(); + } + else + { + Bot = CacheService.GetUser(new TLInt(StateService.CurrentUserId)); + } + } + + protected override void OnActivate() + { + base.OnActivate(); + + var backEntry = NavigationService.BackStack.FirstOrDefault(); + while (backEntry != null + && !backEntry.Source.ToString().EndsWith("ShellView.xaml") + && !DialogDetailsViewModel.IsFirstEntryFromPeopleHub(backEntry, NavigationService.BackStack) + && !DialogDetailsViewModel.IsFirstEntryFromTelegramUrl(backEntry, NavigationService.BackStack)) + { + NavigationService.RemoveBackEntry(); + backEntry = NavigationService.BackStack.FirstOrDefault(); + } + } + + protected override void OnSucceded(TLPasswordSettings passwordSettings) + { + NavigateToPassportCommon( + passwordSettings, PasswordBase, new TLString(Password), + _authorizationForm, _secureValues, + MTProtoService, StateService, NavigationService); + } + + public static void NavigateToPassportCommon( + TLPasswordSettings passwordSettings, TLPassword passwordBase, TLString password, + TLAuthorizationForm authorizationForm, IList secureValues, + IMTProtoService mtProtoService, IStateService stateService, INavigationService navigationService) + { + var passwordSettings83 = passwordSettings as TLPasswordSettings83; + if (passwordSettings83 == null) return; + + var secureSettings = passwordSettings83.SecureSettings; + + passwordBase.Settings = passwordSettings83; + + var password84 = passwordBase as TLPassword84; + if (password84 == null) return; + + var algo = password84.CurrentAlgo as TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow; + if (algo == null) return; + + //passwordBase.CurrentPasswordHash = Utils.Password.GetHash(passwordBase.CurrentSalt, password); + var passwordHash = SRP.GetX(password, algo); + + passwordBase.CurrentPasswordHash = passwordHash; + + // create secure_secret + if (secureSettings == null || TLString.IsNullOrEmpty(secureSettings.SecureSecret)) + { + AddSecureSecret(passwordSettings, passwordBase, password, authorizationForm, secureValues, mtProtoService, stateService, navigationService); + return; + } + + var values = authorizationForm != null ? authorizationForm.Values : secureValues; + if (values == null) return; + + var decrypted = SetSecretAndDecryptSecureValues(passwordSettings83, password, values); + if (!decrypted) + { + Execute.BeginOnUIThread(() => + { + ShellViewModel.ShowCustomMessageBox( + AppResources.PassportDataCorrupted, AppResources.AppName, + AppResources.Reset, AppResources.Cancel, + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + ResetSecureSecret(passwordSettings, passwordBase, password, authorizationForm, secureValues, mtProtoService, stateService, navigationService); + values.Clear(); + } + }); + }); + + return; + } + + stateService.RemoveBackEntry = true; + stateService.AuthorizationForm = authorizationForm; + stateService.SecureValues = secureValues; + stateService.Password = passwordBase; + Execute.BeginOnUIThread(() => + { + if (authorizationForm != null) + { + navigationService.UriFor().Navigate(); + } + else if (secureValues != null) + { + navigationService.UriFor().Navigate(); + } + }); + } + + private static void ResetSecureSecret( + TLPasswordSettings passwordSettings, TLPassword passwordBase, TLString password, + TLAuthorizationForm authorizationForm, IList secureValues, + IMTProtoService mtProtoService, IStateService stateService, INavigationService navigationService) + { + var passwordSettings83 = passwordSettings as TLPasswordSettings83; + if (passwordSettings83 == null) return; + + var password84 = passwordBase as TLPassword84; + if (password84 == null) return; + + var newSecureSettings = new TLSecureSecretSettings + { + SecureAlgo = new TLSecurePasswordKdfAlgoUnknown(), + SecureSecret = TLString.Empty, + SecureSecretId = new TLLong(0) + }; + + var newSettings = new TLPasswordInputSettings83 + { + Flags = new TLInt(0), + NewSecureSettings = newSecureSettings, + }; + + mtProtoService.GetPasswordAsync( + resul1 => + { + var srpParams = resul1 as IPasswordSRPParams; + if (srpParams == null) return; + + var currentPasswordHash = passwordBase.CurrentPasswordHash ?? TLString.Empty; + mtProtoService.UpdatePasswordSettingsAsync(SRP.GetCheck(currentPasswordHash, srpParams.SRPId, srpParams.SRPB, srpParams.CurrentAlgo), newSettings, + result2 => + { + passwordSettings83.SecureSettings = newSettings.NewSecureSettings; + + NavigateToPassportCommon( + passwordSettings83, passwordBase, password, + authorizationForm, secureValues, + mtProtoService, stateService, navigationService); + }, + error2 => { }); + }, + error1 => { }); + } + + private static void AddSecureSecret( + TLPasswordSettings passwordSettings, TLPassword passwordBase, TLString password, + TLAuthorizationForm authorizationForm, IList secureValues, + IMTProtoService mtProtoService, IStateService stateService, INavigationService navigationService) + { + var passwordSettings83 = passwordSettings as TLPasswordSettings83; + if (passwordSettings83 == null) return; + + var password84 = passwordBase as TLPassword84; + if (password84 == null) return; + + var newSettings = new TLPasswordInputSettings83 { Flags = new TLInt(0) }; + + Utils.Password.AddRandomSecureSecret(newSettings, password84, password); + + mtProtoService.GetPasswordAsync( + resul1 => + { + var srpParams = resul1 as IPasswordSRPParams; + if (srpParams == null) return; + + var currentPasswordHash = passwordBase.CurrentPasswordHash ?? TLString.Empty; + mtProtoService.UpdatePasswordSettingsAsync(SRP.GetCheck(currentPasswordHash, srpParams.SRPId, srpParams.SRPB, srpParams.CurrentAlgo), newSettings, + result2 => + { + passwordSettings83.SecureSettings = newSettings.NewSecureSettings; + + NavigateToPassportCommon( + passwordSettings83, passwordBase, password, + authorizationForm, secureValues, + mtProtoService, stateService, navigationService); + }, + error2 => { }); + }, + error1 => { }); + } + + protected static bool SetSecretAndDecryptSecureValues(TLPasswordSettings83 passwordSettings, TLString password, IList values) + { + if (passwordSettings == null) return false; + + var secureSettings = passwordSettings.SecureSettings; + if (secureSettings == null) return false; + + var secureAlgo = secureSettings.SecureAlgo; + if (secureAlgo == null) return false; + + Secret = Utils.Passport.DecryptSecureSecret( + secureSettings.SecureSecret, + password, + secureAlgo); + + // cannot decrypt secureSecret, corrupt data + if (Secret == null) return false; + + if (values == null) return true; + + foreach (var value in values) + { + try + { + if (value.Data != null) + { + var decryptedData = Utils.Passport.DecryptSecureValue(value, Secret); + + if (!TLString.IsNullOrEmpty(decryptedData)) + { + if (ResidentialAddressViewModel.IsValidDataType(value.Type)) + { + value.Data.DecryptedData = JsonUtils.FromJSON(decryptedData.Data); + } + else if (PersonalDetailsViewModel.IsValidProofType(value.Type)) + { + value.Data.DecryptedData = JsonUtils.FromJSON(decryptedData.Data); + } + else if (PersonalDetailsViewModel.IsValidDataType(value.Type)) + { + value.Data.DecryptedData = JsonUtils.FromJSON(decryptedData.Data); + } + else + { + value.Data.DecryptedData = decryptedData; + } + } + } + } + catch (Exception ex) + { + Telegram.Api.Helpers.Execute.ShowDebugMessage(ex.ToString()); + } + } + + return true; + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Passport/PassportViewModel.cs b/TelegramClient.WP81/ViewModels/Passport/PassportViewModel.cs new file mode 100755 index 0000000..97bc4c7 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Passport/PassportViewModel.cs @@ -0,0 +1,1210 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using Windows.Data.Json; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Tasks; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.Utils; +using TelegramClient.Views.Additional; + +namespace TelegramClient.ViewModels.Passport +{ + public class PassportViewModel : ViewModelBase + { + public TLUserBase Bot { get; set; } + + public string Hint + { + get + { + return Bot == null + ? string.Empty + : string.Format(AppResources.PassportHint, Bot.FullName); + } + } + + public string AuthorizationFormHint + { + get + { + var username = Bot as IUserName; + + return username == null + ? string.Empty + : string.Format(AppResources.PassportNoPolicy, Bot.FullName, username.UserName); + } + } + + public Visibility ResidentialAddressVisibility + { + get + { + return _authorizationForm.RequiredTypes.FirstOrDefault(ResidentialAddressViewModel.IsValidType) != null + ? Visibility.Visible + : Visibility.Collapsed; + } + } + + public Visibility ResidentialAddressCheckVisibility + { + get + { + var dataType = _authorizationForm.RequiredTypes.FirstOrDefault(ResidentialAddressViewModel.IsValidDataType); + if (dataType != null) + { + var data = _authorizationForm.Values.FirstOrDefault(x => x.Type.GetType() == dataType.GetType()); + if (data == null) + { + return Visibility.Collapsed; + } + } + + var dataProofType = _authorizationForm.RequiredTypes.FirstOrDefault(ResidentialAddressViewModel.IsValidProofType); + if (dataProofType != null) + { + var dataProof = _authorizationForm.Values.FirstOrDefault(x => x.Type.GetType() == dataProofType.GetType()); + if (dataProof == null) + { + return Visibility.Collapsed; + } + } + + var type = _authorizationForm.RequiredTypes.FirstOrDefault(ResidentialAddressViewModel.IsValidType); + if (type == null) + { + return Visibility.Collapsed; + } + + var error = _authorizationForm.Errors.FirstOrDefault(x => ResidentialAddressViewModel.IsValidType(x.Type)); + if (error != null) + { + return Visibility.Collapsed; + } + + return Visibility.Visible; + } + } + + public string ResidentialAddressHint + { + get + { + var value = _authorizationForm.Values.FirstOrDefault(x => ResidentialAddressViewModel.IsValidDataType(x.Type)); + if (value != null) + { + return SecureValueToHintConverter.Convert(value); + } + + return AppResources.PassportAddressInfo; + } + } + + public string ResidentialAddressError + { + get + { + var value = _authorizationForm.Errors.FirstOrDefault(x => ResidentialAddressViewModel.IsValidType(x.Type)); + if (value != null) + { + return AppResources.PassportCorrectErrors; + } + + return null; + } + } + + public ObservableCollection RequiredTypes { get; set; } + + private readonly TLAuthorizationForm _authorizationForm; + + private readonly TLPasswordBase _passwordBase; + + public PassportViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + RequiredTypes = new ObservableCollection(); + + _authorizationForm = stateService.AuthorizationForm; + stateService.AuthorizationForm = null; + + _passwordBase = stateService.Password; + stateService.Password = null; + + if (_authorizationForm != null) + { + Bot = _authorizationForm.Users.LastOrDefault(); + } + + GetRequiredTypes(); + } + + private void GetRequiredTypes() + { + var authorizationForm85 = _authorizationForm as TLAuthorizationForm85; + if (authorizationForm85 != null) + { + var hasPersonalDetails = false; + var hasResidentialAddress = false; + var personalDetailsProofCount = 0; + var residentialAddressProofCount = 0; + foreach (var requiredTypeBase in authorizationForm85.NewRequiredTypes) + { + var requiredType = requiredTypeBase as TLSecureRequiredType; + if (requiredType != null) + { + if (PersonalDetailsViewModel.IsValidDataType(requiredType.Type)) + { + hasPersonalDetails = true; + } + else if (ResidentialAddressViewModel.IsValidDataType(requiredType.Type)) + { + hasResidentialAddress = true; + } + else if (PersonalDetailsViewModel.IsValidProofType(requiredType.Type)) + { + personalDetailsProofCount++; + } + else if (ResidentialAddressViewModel.IsValidProofType(requiredType.Type)) + { + residentialAddressProofCount++; + } + } + + var requiredTypeOneOf = requiredTypeBase as TLSecureRequiredTypeOneOf; + if (requiredTypeOneOf != null && requiredTypeOneOf.Types.Count > 0) + { + requiredType = requiredTypeOneOf.Types[0] as TLSecureRequiredType; + if (requiredType != null) + { + if (PersonalDetailsViewModel.IsValidProofType(requiredType.Type)) + { + personalDetailsProofCount++; + } + else if (ResidentialAddressViewModel.IsValidProofType(requiredType.Type)) + { + residentialAddressProofCount++; + } + } + } + } + + var joinPersonalDetails = hasPersonalDetails && personalDetailsProofCount == 1; + var joinResidentialAddress = hasResidentialAddress && residentialAddressProofCount == 1; + + SecureRequiredType personalDetails = null; + SecureRequiredType residentialAddress = null; + var requiredTypes = new ObservableCollection(); + foreach (var requiredTypeBase in authorizationForm85.NewRequiredTypes) + { + var requiredTypeOneOf = requiredTypeBase as TLSecureRequiredTypeOneOf; + if (requiredTypeOneOf != null && requiredTypeOneOf.Types.Count > 0) + { + var firstRequiredType = requiredTypeOneOf.Types[0] as TLSecureRequiredType; + if (firstRequiredType != null) + { + if (PersonalDetailsViewModel.IsValidType(firstRequiredType.Type)) + { + personalDetails = AddPersonalDetailsType(joinPersonalDetails, requiredTypes, requiredTypeOneOf, authorizationForm85, personalDetails, PersonalDetailsViewModel.IsValidDataType(firstRequiredType.Type)); + } + else if (ResidentialAddressViewModel.IsValidType(firstRequiredType.Type)) + { + residentialAddress = AddResidentialAddressType(joinResidentialAddress, requiredTypes, requiredTypeOneOf, authorizationForm85, residentialAddress, ResidentialAddressViewModel.IsValidDataType(firstRequiredType.Type)); + } + } + } + + var requiredType = requiredTypeBase as TLSecureRequiredType; + if (requiredType != null) + { + if (PhoneNumberViewModel.IsValidType(requiredType.Type)) + { + requiredTypes.Add(new SecureRequiredType(requiredType, null, authorizationForm85)); + } + else if (EmailViewModel.IsValidType(requiredType.Type)) + { + requiredTypes.Add(new SecureRequiredType(requiredType, null, authorizationForm85)); + } + else if (PersonalDetailsViewModel.IsValidType(requiredType.Type)) + { + personalDetails = AddPersonalDetailsType(joinPersonalDetails, requiredTypes, requiredType, authorizationForm85, personalDetails, PersonalDetailsViewModel.IsValidDataType(requiredType.Type)); + } + else if (ResidentialAddressViewModel.IsValidType(requiredType.Type)) + { + residentialAddress = AddResidentialAddressType(joinResidentialAddress, requiredTypes, requiredType, authorizationForm85, residentialAddress, ResidentialAddressViewModel.IsValidDataType(requiredType.Type)); + } + } + } + + RequiredTypes = requiredTypes; + } + } + + private static SecureRequiredType AddResidentialAddressType( + bool joinResidentialAddress, ObservableCollection requiredTypes, + TLSecureRequiredTypeBase requiredType, TLAuthorizationForm85 authorizationForm85, SecureRequiredType residentialAddress, + bool isValidDataType) + { + if (!joinResidentialAddress) + { + requiredTypes.Add(isValidDataType + ? new SecureRequiredType(requiredType as TLSecureRequiredType, null, authorizationForm85) + : new SecureRequiredType(null, requiredType, authorizationForm85)); + } + else + { + if (residentialAddress == null) + { + residentialAddress = isValidDataType + ? new SecureRequiredType(requiredType as TLSecureRequiredType, null, authorizationForm85) + : new SecureRequiredType(null, requiredType, authorizationForm85); + + requiredTypes.Add(residentialAddress); + } + else + { + if (isValidDataType) + { + residentialAddress.SetData(requiredType as TLSecureRequiredType); + } + else + { + residentialAddress.SetDataProof(requiredType); + } + } + } + return residentialAddress; + } + + private static SecureRequiredType AddPersonalDetailsType( + bool joinPersonalDetails, ObservableCollection requiredTypes, + TLSecureRequiredTypeBase requiredType, TLAuthorizationForm85 authorizationForm85, SecureRequiredType personalDetails, + bool isValidDataType) + { + if (!joinPersonalDetails) + { + requiredTypes.Add(isValidDataType + ? new SecureRequiredType(requiredType as TLSecureRequiredType, null, authorizationForm85) + : new SecureRequiredType(null, requiredType, authorizationForm85)); + } + else + { + if (personalDetails == null) + { + personalDetails = isValidDataType + ? new SecureRequiredType(requiredType as TLSecureRequiredType, null, authorizationForm85) + : new SecureRequiredType(null, requiredType, authorizationForm85); + + requiredTypes.Add(personalDetails); + } + else + { + if (isValidDataType) + { + personalDetails.SetData(requiredType as TLSecureRequiredType); + } + else + { + personalDetails.SetDataProof(requiredType); + } + } + } + return personalDetails; + } + + protected override void OnActivate() + { + base.OnActivate(); + + NotifyOfPropertyChange(() => ResidentialAddressHint); + NotifyOfPropertyChange(() => ResidentialAddressCheckVisibility); + NotifyOfPropertyChange(() => ResidentialAddressError); + + if (StateService.RemoveBackEntry) + { + StateService.RemoveBackEntry = false; + NavigationService.RemoveBackEntry(); + } + } + + public void EditPersonalDetails(SecureRequiredType secureRequiredType) + { + var requiredProofTypes = secureRequiredType.DataProofRequiredType as TLSecureRequiredTypeOneOf; + if (requiredProofTypes != null && requiredProofTypes.Types.Count > 1) + { + var addressProof = secureRequiredType.DataProofValue; + if (addressProof == null) + { + var panel = new StackPanel { Margin = new Thickness(0.0, 12.0, 0.0, 0.0) }; + var messageBox = ShellViewModel.ShowCustomMessageBox( + null, AppResources.PassportAddress, + null, null, + dismissed => + { + + }, + requiredProofTypes.Types.Count > 10 ? + (object)new ScrollViewer { MaxHeight = 650.0, Content = panel, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled } : + panel); + + for (var i = 0; i < requiredProofTypes.Types.Count; i++) + { + var requiredProofType = requiredProofTypes.Types[i] as TLSecureRequiredType; + if (requiredProofType != null) + { + var listBoxItem = new ListBoxItem + { + Content = + new TextBlock + { + Text = SecureRequiredTypeToCaptionConverter.Convert(requiredProofType.Type), + FontSize = 27, + Margin = new Thickness(12.0) + }, + DataContext = requiredProofType + }; + TiltEffect.SetIsTiltEnabled(listBoxItem, true); + listBoxItem.Tap += (sender, args) => + { + messageBox.Dismiss(); + var item = sender as ListBoxItem; + if (item != null) + { + requiredProofType = item.DataContext as TLSecureRequiredType; + if (requiredProofType != null) + { + secureRequiredType.SetSelectedDataProof(requiredProofType); + EditPersonalDetailsInternal(secureRequiredType); + } + } + + }; + + panel.Children.Add(listBoxItem); + } + } + } + else + { + EditPersonalDetailsInternal(secureRequiredType); + } + } + else + { + EditPersonalDetailsInternal(secureRequiredType); + } + } + + private void EditPersonalDetailsInternal(SecureRequiredType secureRequiredType) + { + var authorizationForm85 = _authorizationForm as TLAuthorizationForm85; + if (authorizationForm85 != null && authorizationForm85.Config != null && authorizationForm85.Config.CountriesLangsObject == null) + { + JsonObject result; + if (JsonObject.TryParse(authorizationForm85.Config.CountriesLangs.Data.ToString(), out result)) + { + authorizationForm85.Config.CountriesLangsObject = result; + } + } + + StateService.SecureRequiredType = secureRequiredType; + StateService.AuthorizationForm = _authorizationForm; + StateService.Password = _passwordBase; + NavigationService.UriFor().Navigate(); + } + + public void EditResidentialAddress(SecureRequiredType secureRequiredType) + { + var requiredProofTypes = secureRequiredType.DataProofRequiredType as TLSecureRequiredTypeOneOf; + if (requiredProofTypes != null && requiredProofTypes.Types.Count > 1) + { + var addressProof = secureRequiredType.DataProofValue; + if (addressProof == null) + { + var panel = new StackPanel { Margin = new Thickness(0.0, 12.0, 0.0, 0.0) }; + var messageBox = ShellViewModel.ShowCustomMessageBox( + null, AppResources.PassportAddress, + null, null, + dismissed => + { + + }, + requiredProofTypes.Types.Count > 10 ? + (object)new ScrollViewer { MaxHeight = 650.0, Content = panel, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled } : + panel); + + for (var i = 0; i < requiredProofTypes.Types.Count; i++) + { + var requiredProofType = requiredProofTypes.Types[i] as TLSecureRequiredType; + if (requiredProofType != null) + { + var listBoxItem = new ListBoxItem + { + Content = + new TextBlock + { + Text = SecureRequiredTypeToCaptionConverter.Convert(requiredProofType.Type), + FontSize = 27, + Margin = new Thickness(12.0) + }, + DataContext = requiredProofType + }; + TiltEffect.SetIsTiltEnabled(listBoxItem, true); + listBoxItem.Tap += (sender, args) => + { + messageBox.Dismiss(); + var item = sender as ListBoxItem; + if (item != null) + { + requiredProofType = item.DataContext as TLSecureRequiredType; + if (requiredProofType != null) + { + secureRequiredType.SetSelectedDataProof(requiredProofType); + EditResidentialAddressInternal(secureRequiredType); + } + } + + }; + + panel.Children.Add(listBoxItem); + } + } + } + else + { + EditResidentialAddressInternal(secureRequiredType); + } + } + else + { + EditResidentialAddressInternal(secureRequiredType); + } + } + + private void EditResidentialAddressInternal(SecureRequiredType secureRequiredType) + { + StateService.SecureRequiredType = secureRequiredType; + StateService.AuthorizationForm = _authorizationForm; + StateService.Password = _passwordBase; + NavigationService.UriFor().Navigate(); + } + + public void EditPhoneNumber(SecureRequiredType secureRequiredType) + { + if (secureRequiredType == null) return; + + if (secureRequiredType.IsCompleted) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PassportDeletePhoneNumberAlert, AppResources.AppName, + AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + IsWorking = true; + MTProtoService.DeleteSecureValueAsync(new TLVector{ new TLSecureValueTypePhone() }, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + + for (var i = 0; i < _authorizationForm.Values.Count; i++) + { + if (PhoneNumberViewModel.IsValidType(_authorizationForm.Values[i].Type)) + { + _authorizationForm.Values.RemoveAt(i--); + } + } + + secureRequiredType.UpdateValue(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + })); + } + }); + } + else + { + StateService.SecureRequiredType = secureRequiredType; + StateService.AuthorizationForm = _authorizationForm; + StateService.Password = _passwordBase; + NavigationService.UriFor().Navigate(); + } + } + + public void EditEmail(SecureRequiredType secureRequiredType) + { + if (secureRequiredType == null) return; + + if (secureRequiredType.IsCompleted) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PassportDeleteEmailAlert, AppResources.AppName, + AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + IsWorking = true; + MTProtoService.DeleteSecureValueAsync(new TLVector { new TLSecureValueTypeEmail() }, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + + for (var i = 0; i < _authorizationForm.Values.Count; i++) + { + if (EmailViewModel.IsValidType(_authorizationForm.Values[i].Type)) + { + _authorizationForm.Values.RemoveAt(i--); + } + } + + secureRequiredType.UpdateValue(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + })); + } + }); + } + else + { + StateService.SecureRequiredType = secureRequiredType; + StateService.AuthorizationForm = _authorizationForm; + StateService.Password = _passwordBase; + NavigationService.UriFor().Navigate(); + } + } + + public void Edit(SecureRequiredType secureRequiredType) + { + TLSecureRequiredType requiredType = null; + var requiredTypeOneOf = secureRequiredType.DataProofRequiredType as TLSecureRequiredTypeOneOf; + if (requiredTypeOneOf != null) + { + var firstRequiredType = requiredTypeOneOf.Types.FirstOrDefault() as TLSecureRequiredType; + if (firstRequiredType != null) + { + requiredType = firstRequiredType; + } + } + + requiredType = requiredType ?? secureRequiredType.DataProofRequiredType as TLSecureRequiredType; + requiredType = requiredType ?? secureRequiredType.DataRequiredType ?? secureRequiredType.SelectedDataProofRequiredType; + + if (requiredType != null) + { + if (PersonalDetailsViewModel.IsValidType(requiredType.Type)) + { + EditPersonalDetails(secureRequiredType); + return; + } + + if (ResidentialAddressViewModel.IsValidType(requiredType.Type)) + { + EditResidentialAddress(secureRequiredType); + return; + } + + if (PhoneNumberViewModel.IsValidType(requiredType.Type)) + { + EditPhoneNumber(secureRequiredType); + return; + } + + if (EmailViewModel.IsValidType(requiredType.Type)) + { + EditEmail(secureRequiredType); + return; + } + } + } + + public string Error { get; set; } + + private bool HasErrors() + { + foreach (var requiredType in RequiredTypes) + { + if (!requiredType.IsCompleted) + { + Error = "REQUIRED_TYPE"; + NotifyOfPropertyChange(() => Error); + return true; + } + } + + Error = null; + NotifyOfPropertyChange(() => Error); + return false; + } + + public void Authorize() + { + if (HasErrors()) + { + return; + } + + var password = _passwordBase as TLPassword; + if (password == null) + { + return; + } + + var passwordSettings = password.Settings as TLPasswordSettings81; + if (passwordSettings == null) + { + return; + } + + var credentialSecret = Utils.Passport.GenerateSecret(TLString.Empty); + + var credentials = Utils.Passport.GenerateSecureCredentialsEncrypted(RequiredTypes, _authorizationForm, credentialSecret, EnterPasswordViewModel.Secret); + if (credentials == null) return; + + var valueHashes = Utils.Passport.GenerateValueHashes(RequiredTypes); + + IsWorking = true; + MTProtoService.AcceptAuthorizationAsync( + _authorizationForm.BotId, + _authorizationForm.Scope, + _authorizationForm.PublicKey, + valueHashes, + credentials, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + if (!TLString.IsNullOrEmpty(_authorizationForm.CallbackUrl)) + { + var uriBuilder = new UriBuilder(new Uri(_authorizationForm.CallbackUrl.ToString())); + var query = TelegramUriMapper.ParseQueryString(uriBuilder.Query); + query["tg_passport"] = "success"; + var queryBuilder = new List(); + foreach (var item in query) + { + queryBuilder.Add(string.Format("{0}={1}", item.Key, item.Value)); + } + uriBuilder.Query = string.Join("&", queryBuilder); + var url = uriBuilder.ToString(); + + var task = new WebBrowserTask(); + task.URL = HttpUtility.UrlEncode(url); + task.Show(); + } + NavigationService.GoBack(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + + if (error.CodeEquals(ErrorCode.BAD_REQUEST)) + { + ShellViewModel.ShowCustomMessageBox( + "account.acceptAuthorization" + Environment.NewLine + error.Message, + AppResources.AppName, + AppResources.Ok); + } + })); + } + + public bool IsCancelConfirmed { get; protected set; } + + public void Cancel() + { + IsCancelConfirmed = true; + + if (!TLString.IsNullOrEmpty(_authorizationForm.CallbackUrl)) + { + var uriBuilder = new UriBuilder(new Uri(_authorizationForm.CallbackUrl.ToString())); + var query = TelegramUriMapper.ParseQueryString(uriBuilder.Query); + query["tg_passport"] = "cancel"; + var queryBuilder = new List(); + foreach (var item in query) + { + queryBuilder.Add(string.Format("{0}={1}", item.Key, item.Value)); + } + uriBuilder.Query = string.Join("&", queryBuilder); + var url = HttpUtility.UrlEncode(uriBuilder.ToString()); + + var handled = false; + ShellViewModel.ShowCustomMessageBox( + string.Format(AppResources.OpenUrlConfirmation, HttpUtility.UrlDecode(url)), + AppResources.AppName, + AppResources.Ok, + AppResources.Cancel, + dismissed => + { + if (handled) + { + return; + } + + handled = true; + if (dismissed == CustomMessageBoxResult.RightButton) + { + var task = new WebBrowserTask(); + task.URL = url; + task.Show(); + NavigationService.GoBack(); + } + else + { + BeginOnUIThread(TimeSpan.FromSeconds(0.15), () => + { + NavigationService.GoBack(); + }); + } + }); + } + } + } + + public class SecureRequiredType : PropertyChangedBase + { + public string Caption + { + get + { + TLSecureRequiredType requiredType = null; + + var requiredTypeOneOf = DataProofRequiredType as TLSecureRequiredTypeOneOf; + if (requiredTypeOneOf != null && requiredTypeOneOf.Types.Count > 0) + { + if (requiredTypeOneOf.Types.Count == 1) + { + requiredType = requiredTypeOneOf.Types[0] as TLSecureRequiredType; + if (requiredType != null) + { + return SecureRequiredTypeToCaptionConverter.Convert(requiredType.Type); + } + } + else if (requiredTypeOneOf.Types.Count == 2) + { + requiredType = requiredTypeOneOf.Types[0] as TLSecureRequiredType; + var requiredType2 = requiredTypeOneOf.Types[1] as TLSecureRequiredType; + if (requiredType != null && requiredType2 != null) + { + return string.Format(AppResources.PassportOr, SecureRequiredTypeToCaptionConverter.Convert(requiredType.Type), SecureRequiredTypeToCaptionConverter.Convert(requiredType2.Type)); + } + } + else + { + requiredType = requiredTypeOneOf.Types[0] as TLSecureRequiredType; + if (requiredType != null) + { + if (PersonalDetailsViewModel.IsValidType(requiredType.Type)) + { + return AppResources.PassportIdentityDocument; + } + if (ResidentialAddressViewModel.IsValidType(requiredType.Type)) + { + return AppResources.PassportResidentialAddress; + } + if (PhoneNumberViewModel.IsValidType(requiredType.Type)) + { + return AppResources.PassportPhoneNumber; + } + if (EmailViewModel.IsValidType(requiredType.Type)) + { + return AppResources.PassportEmail; + } + } + } + } + + requiredType = DataProofRequiredType as TLSecureRequiredType; + if (requiredType != null) + { + return SecureRequiredTypeToCaptionConverter.Convert(requiredType.Type); + } + + requiredType = DataRequiredType as TLSecureRequiredType; + if (requiredType != null) + { + return SecureRequiredTypeToCaptionConverter.Convert(requiredType.Type); + } + +#if DEBUG + return DataRequiredType != null ? DataRequiredType.ToString() : null; +#endif + + return string.Empty; + } + } + + public string Hint + { + get + { + if (DataValue != null) + { + return SecureValueToHintConverter.Convert(DataValue); + } + + if (DataProofValue != null) + { + return SecureValueToHintConverter.Convert(DataProofValue); + } + + TLSecureRequiredType requiredType = null; + + var requiredTypeOneOf = DataProofRequiredType as TLSecureRequiredTypeOneOf; + if (requiredTypeOneOf != null && requiredTypeOneOf.Types.Count > 0) + { + if (requiredTypeOneOf.Types.Count == 1) + { + requiredType = requiredTypeOneOf.Types[0] as TLSecureRequiredType; + if (requiredType != null) + { + return SecureRequiredTypeToHintConverter.Convert(requiredType.Type); + } + } + else + { + requiredType = requiredTypeOneOf.Types[0] as TLSecureRequiredType; + if (requiredType != null) + { + if (PersonalDetailsViewModel.IsValidType(requiredType.Type)) + { + return AppResources.PassportIdentityDocumentInfo; + } + if (ResidentialAddressViewModel.IsValidType(requiredType.Type)) + { + return AppResources.PassportAddressInfo; + } + if (PhoneNumberViewModel.IsValidType(requiredType.Type)) + { + return AppResources.PassportPhoneInfo; + } + if (EmailViewModel.IsValidType(requiredType.Type)) + { + return AppResources.PassportEmailInfo; + } + } + } + } + + requiredType = DataProofRequiredType as TLSecureRequiredType; + if (requiredType != null) + { + return SecureRequiredTypeToHintConverter.Convert(requiredType.Type); + } + + requiredType = DataRequiredType as TLSecureRequiredType; + if (requiredType != null) + { + return SecureRequiredTypeToHintConverter.Convert(requiredType.Type); + } + + return string.Empty; + } + } + + public string Error + { + get + { + if (DataRequiredType != null && PersonalDetailsViewModel.IsValidType(DataRequiredType.Type)) + { + var error = GetFirstOrDefaultError(AuthorizationForm.Errors.Where(x => PersonalDetailsViewModel.IsValidDataType(x.Type))); + + return error != null ? error.Text.ToString() : null; + } + if (SelectedDataProofRequiredType != null && PersonalDetailsViewModel.IsValidType(SelectedDataProofRequiredType.Type)) + { + var error = GetFirstOrDefaultError(AuthorizationForm.Errors.Where(x => PersonalDetailsViewModel.IsValidProofType(x.Type))); + + return error != null ? error.Text.ToString() : null; + } + if (DataRequiredType != null && ResidentialAddressViewModel.IsValidType(DataRequiredType.Type)) + { + var error = GetFirstOrDefaultError(AuthorizationForm.Errors.Where(x => ResidentialAddressViewModel.IsValidDataType(x.Type))); + + return error != null ? error.Text.ToString() : null; + } + if (SelectedDataProofRequiredType != null && ResidentialAddressViewModel.IsValidType(SelectedDataProofRequiredType.Type)) + { + var error = GetFirstOrDefaultError(AuthorizationForm.Errors.Where(x => ResidentialAddressViewModel.IsValidProofType(x.Type))); + + return error != null ? error.Text.ToString() : null; + } + if (DataRequiredType != null && PhoneNumberViewModel.IsValidType(DataRequiredType.Type)) + { + var error = GetFirstOrDefaultError(AuthorizationForm.Errors.Where(x => PhoneNumberViewModel.IsValidType(x.Type))); + + return error != null ? error.Text.ToString() : null; + } + if (DataRequiredType != null && EmailViewModel.IsValidType(DataRequiredType.Type)) + { + var error = GetFirstOrDefaultError(AuthorizationForm.Errors.Where(x => EmailViewModel.IsValidType(x.Type))); + + return error != null ? error.Text.ToString() : null; + } + + return null; + } + } + + public bool IsCompleted + { + get + { + var dataRequiredType = DataRequiredType; + var dataProofRequiredType = DataProofRequiredType; + var selectedDataProofRequiredType = SelectedDataProofRequiredType; + + if (dataRequiredType != null) + { + if (PersonalDetailsViewModel.IsValidDataType(dataRequiredType.Type)) + { + if (DataValue == null) + { + return false; + } + + if (dataRequiredType.NativeNames) + { + var personalDetails = DataValue.Data.DecryptedData as PersonalDetailsRootObject; + if (personalDetails != null) + { + if (string.IsNullOrEmpty(personalDetails.first_name_native)) return false; + if (string.IsNullOrEmpty(personalDetails.last_name_native)) return false; + } + } + + var error = AuthorizationForm.Errors.FirstOrDefault(x => PersonalDetailsViewModel.IsValidDataType(x.Type)); + if (error != null) + { + return false; + } + } + else if (ResidentialAddressViewModel.IsValidDataType(dataRequiredType.Type)) + { + if (DataValue == null) + { + return false; + } + + var error = AuthorizationForm.Errors.FirstOrDefault(x => ResidentialAddressViewModel.IsValidDataType(x.Type)); + if (error != null) + { + return false; + } + } + else if (PhoneNumberViewModel.IsValidType(dataRequiredType.Type)) + { + if (DataValue != null) + { + var plainData = DataValue.PlainData as TLSecurePlainPhone; + if (plainData != null && !TLString.IsNullOrEmpty(plainData.Phone)) + { + return true; + } + } + + return false; + } + else if (EmailViewModel.IsValidType(dataRequiredType.Type)) + { + if (DataValue != null) + { + var plainData = DataValue.PlainData as TLSecurePlainEmail; + if (plainData != null && !TLString.IsNullOrEmpty(plainData.Email)) + { + return true; + } + } + + return false; + } + } + + if (dataProofRequiredType != null && selectedDataProofRequiredType == null) + { + return false; + } + + if (selectedDataProofRequiredType != null) + { + if (PersonalDetailsViewModel.IsValidProofType(selectedDataProofRequiredType.Type)) + { + if (DataProofValue == null) + { + return false; + } + + if (selectedDataProofRequiredType.SelfieRequired && DataProofValue.Selfie == null) + { + return false; + } + + if (selectedDataProofRequiredType.TranslationRequired && (DataProofValue.Translation == null || DataProofValue.Translation.Count == 0)) + { + return false; + } + + var error = AuthorizationForm.Errors.FirstOrDefault(x => PersonalDetailsViewModel.IsValidProofType(x.Type)); + if (error != null) + { + return false; + } + } + else if (ResidentialAddressViewModel.IsValidProofType(selectedDataProofRequiredType.Type)) + { + if (DataProofValue == null) + { + return false; + } + + if (selectedDataProofRequiredType.SelfieRequired && DataProofValue.Selfie == null) + { + return false; + } + + if (selectedDataProofRequiredType.TranslationRequired && (DataProofValue.Translation == null || DataProofValue.Translation.Count == 0)) + { + return false; + } + + var error = AuthorizationForm.Errors.FirstOrDefault(x => ResidentialAddressViewModel.IsValidProofType(x.Type)); + if (error != null) + { + return false; + } + } + } + + return true; + } + } + + public TLSecureRequiredType DataRequiredType { get; protected set; } + + public TLSecureValue85 DataValue { get; protected set; } + + public TLSecureRequiredTypeBase DataProofRequiredType { get; protected set; } + + public TLSecureRequiredType SelectedDataProofRequiredType { get; protected set; } + + public TLSecureValue85 DataProofValue { get; protected set; } + + public TLAuthorizationForm85 AuthorizationForm { get; protected set; } + + public SecureRequiredType(TLSecureRequiredType dataRequiredType, TLSecureRequiredTypeBase dataProofRequiredType, TLAuthorizationForm85 authorizationForm) + { + AuthorizationForm = authorizationForm; + + SetData(dataRequiredType); + SetDataProof(dataProofRequiredType); + } + + private static TLSecureValueErrorBase GetFirstOrDefaultError(IEnumerable errors) + { + if (errors == null) return null; + + return errors.OrderBy(x => x.Priority).FirstOrDefault(); + } + + public void SetData(TLSecureRequiredType dataRequiredType) + { + DataRequiredType = dataRequiredType; + DataValue = GetValue(dataRequiredType, AuthorizationForm); + } + + public void SetDataProof(TLSecureRequiredTypeBase dataProofRequiredTypeBase) + { + DataProofRequiredType = dataProofRequiredTypeBase; + DataProofValue = GetValue(dataProofRequiredTypeBase, AuthorizationForm); + + if (DataProofValue != null) + { + var dataProofRequiredType = dataProofRequiredTypeBase as TLSecureRequiredType; + var dataProofRequiredTypeOneOf = dataProofRequiredTypeBase as TLSecureRequiredTypeOneOf; + if (dataProofRequiredType != null) + { + SetSelectedDataProof(dataProofRequiredType); + } + else if (dataProofRequiredTypeOneOf != null) + { + foreach (var type in dataProofRequiredTypeOneOf.Types.OfType()) + { + if (DataProofValue.Type.GetType() == type.Type.GetType()) + { + SetSelectedDataProof(type); + } + } + } + } + else if (DataProofRequiredType is TLSecureRequiredType) + { + SelectedDataProofRequiredType = (TLSecureRequiredType)DataProofRequiredType; + } + } + + public void SetSelectedDataProof(TLSecureRequiredType selectedDataProofRequiredType) + { + SelectedDataProofRequiredType = selectedDataProofRequiredType; + } + + private static TLSecureValue85 GetValue(TLSecureRequiredTypeBase requiredTypeBase, TLAuthorizationForm85 authorizationForm) + { + if (requiredTypeBase == null) + { + return null; + } + + if (authorizationForm.Values.Count > 0) + { + var requiredType = requiredTypeBase as TLSecureRequiredType; + if (requiredType != null) + { + return authorizationForm.Values.FirstOrDefault(x => requiredType.Type.GetType() == x.Type.GetType()) as TLSecureValue85; + } + + var requiredTypeOneOf = requiredTypeBase as TLSecureRequiredTypeOneOf; + if (requiredTypeOneOf != null) + { + var dict = new Dictionary(); + foreach (var type in requiredTypeOneOf.Types.OfType()) + { + dict[type.Type.GetType()] = type.Type.GetType(); + } + + return authorizationForm.Values.FirstOrDefault(x => dict.ContainsKey(x.Type.GetType())) as TLSecureValue85; + } + } + + return null; + } + + public void UpdateValue() + { + DataValue = GetValue(DataRequiredType, AuthorizationForm); + DataProofValue = GetValue(DataProofRequiredType, AuthorizationForm); + + NotifyOfPropertyChange(() => Hint); + NotifyOfPropertyChange(() => Error); + NotifyOfPropertyChange(() => IsCompleted); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/ViewModels/Passport/PasswordIntroViewModel.cs b/TelegramClient.WP81/ViewModels/Passport/PasswordIntroViewModel.cs new file mode 100755 index 0000000..c9a66b5 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Passport/PasswordIntroViewModel.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Services; +using TelegramClient.ViewModels.Additional; + +namespace TelegramClient.ViewModels.Passport +{ + public class PasswordIntroViewModel : ViewModelBase + { + private readonly TLPasswordBase _passwordBase; + + private readonly TLAuthorizationForm _authorizationForm; + + private readonly IList _secureValues; + + public PasswordIntroViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _passwordBase = StateService.Password; + StateService.Password = null; + + _authorizationForm = StateService.AuthorizationForm; + StateService.AuthorizationForm = null; + + _secureValues = StateService.SecureValues; + StateService.SecureValues = null; + } + + public void CreatePassword() + { + StateService.RemoveBackEntry = true; + StateService.Password = _passwordBase; + StateService.AuthorizationForm = _authorizationForm; + StateService.SecureValues = _secureValues; + NavigationService.UriFor().Navigate(); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Passport/PersonalDetailsViewModel.cs b/TelegramClient.WP81/ViewModels/Passport/PersonalDetailsViewModel.cs new file mode 100755 index 0000000..1192b6f --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Passport/PersonalDetailsViewModel.cs @@ -0,0 +1,2313 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.IO.IsolatedStorage; +using System.Linq; +using System.Runtime.Serialization; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using Windows.Data.Json; +using Windows.Storage; +using Windows.Storage.Pickers; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Controls.Primitives; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.FileManager; +using Telegram.Api.TL; +using TelegramClient.Models; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.Utils; +using TelegramClient.ViewModels.Additional; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.ViewModels.Media; +using TelegramClient.Views.Additional; +using TelegramClient.Views.Controls; +using TelegramClient.Views.Passport; + +namespace TelegramClient.ViewModels.Passport +{ + public class PersonalDetailsViewModel : ViewModelBase, Telegram.Api.Aggregator.IHandle, Telegram.Api.Aggregator.IHandle + { + public ObservableCollection Errors { get; protected set; } + + public string DataProofCaption + { + get + { + return _authorizationForm != null + ? AppResources.PassportRequiredDocuments + : AppResources.PassportDocuments; + } + } + + private string _firstNameNative; + + public string FirstNameNative + { + get { return _firstNameNative; } + set + { + if (_firstNameNative != value) + { + _firstNameNative = value; + + if (!string.IsNullOrEmpty(FirstNameNativeError)) + { + FirstNameNativeError = null; + NotifyOfPropertyChange(() => FirstNameNativeError); + } + } + } + } + + public string FirstNameNativeHint + { + get { return _selectedResidenceCountry != null ? string.Format(AppResources.PassportNameCountry, _selectedResidenceCountry.Name) : null; } + } + + public string FirstNameNativeError { get; set; } + + private string _middleNameNative; + + public string MiddleNameNative + { + get { return _middleNameNative; } + set + { + if (_middleNameNative != value) + { + _middleNameNative = value; + + if (!string.IsNullOrEmpty(MiddleNameNativeError)) + { + MiddleNameNativeError = null; + NotifyOfPropertyChange(() => MiddleNameNativeError); + } + } + } + } + + public string MiddleNameNativeHint + { + get { return _selectedResidenceCountry != null ? string.Format(AppResources.PassportMidnameCountry, _selectedResidenceCountry.Name) : null; } + } + + public string MiddleNameNativeError { get; set; } + + private string _lastNameNative; + + public string LastNameNative + { + get { return _lastNameNative; } + set + { + if (_lastNameNative != value) + { + _lastNameNative = value; + + if (!string.IsNullOrEmpty(LastNameNativeError)) + { + LastNameNativeError = null; + NotifyOfPropertyChange(() => LastNameNativeError); + } + } + } + } + + public string LastNameNativeHint + { + get + { + return _selectedResidenceCountry != null ? string.Format(AppResources.PassportSurnameCountry, _selectedResidenceCountry.Name) : null; + } + } + + public string LastNameNativeError { get; set; } + + public string PassportNativeFooter + { + get { return _selectedResidenceCountry != null ? string.Format(AppResources.PassportNativeInfo, _selectedResidenceCountry.Name) : null; } + } + + private string _firstName; + + public string FirstName + { + get { return _firstName; } + set + { + if (_firstName != value) + { + _firstName = value; + + if (!Utils.Passport.IsValidName(_firstName)) + { + FirstNameError = AppResources.PassportUseLatinOnly; + NotifyOfPropertyChange(() => FirstNameError); + } + else if (!string.IsNullOrEmpty(FirstNameError)) + { + FirstNameError = null; + NotifyOfPropertyChange(() => FirstNameError); + } + } + } + } + + public string FirstNameHint + { + get { return IsDataNativeNamesEnabled ? AppResources.PassportNameLatin : AppResources.PassportName; } + } + + public string FirstNameError { get; set; } + + private string _middleName; + + public string MiddleName + { + get { return _middleName; } + set + { + if (_middleName != value) + { + _middleName = value; + if (!Utils.Passport.IsValidName(_middleName)) + { + MiddleNameError = AppResources.PassportUseLatinOnly; + NotifyOfPropertyChange(() => MiddleNameError); + } + else if (!string.IsNullOrEmpty(MiddleNameError)) + { + MiddleNameError = null; + NotifyOfPropertyChange(() => MiddleNameError); + } + } + } + } + + public string MiddleNameHint + { + get { return IsDataNativeNamesEnabled ? AppResources.PassportMidnameLatin : AppResources.PassportMidname; } + } + + public string MiddleNameError { get; set; } + + private string _lastName; + + public string LastName + { + get { return _lastName; } + set + { + if (_lastName != value) + { + _lastName = value; + if (!Utils.Passport.IsValidName(_lastName)) + { + LastNameError = AppResources.PassportUseLatinOnly; + NotifyOfPropertyChange(() => LastNameError); + } + else if (!string.IsNullOrEmpty(LastNameError)) + { + LastNameError = null; + NotifyOfPropertyChange(() => LastNameError); + } + } + } + } + + public string LastNameHint + { + get { return IsDataNativeNamesEnabled ? AppResources.PassportSurnameLatin : AppResources.PassportSurname; } + } + + public string LastNameError { get; set; } + + private string _birthDate; + + public string BirthDate + { + get { return _birthDate; } + set + { + if (_birthDate != value) + { + _birthDate = value; + if (!string.IsNullOrEmpty(BirthDateError)) + { + BirthDateError = null; + NotifyOfPropertyChange(() => BirthDateError); + } + } + } + } + + public string BirthDateError { get; set; } + + private string _gender; + + public string Gender + { + get { return _gender; } + set + { + if (_gender != value) + { + _gender = value; + if (!string.IsNullOrEmpty(GenderError)) + { + GenderError = null; + NotifyOfPropertyChange(() => GenderError); + } + } + } + } + + public string GenderError { get; set; } + + private Country _selectedCountry; + + public Country SelectedCountry + { + get { return _selectedCountry; } + set + { + if (_selectedCountry != value) + { + SetField(ref _selectedCountry, value, () => SelectedCountry); + if (!string.IsNullOrEmpty(SelectedCountryError)) + { + SelectedCountryError = null; + NotifyOfPropertyChange(() => SelectedCountryError); + } + } + } + } + + public string SelectedCountryError { get; set; } + + private Country _selectedResidenceCountry; + + public Country SelectedResidenceCountry + { + get { return _selectedResidenceCountry; } + set + { + if (_selectedResidenceCountry != value) + { + SetField(ref _selectedResidenceCountry, value, () => SelectedResidenceCountry); + + NotifyOfPropertyChange(() => IsDataNativeNamesVisible); + NotifyOfPropertyChange(() => FirstNameNativeHint); + NotifyOfPropertyChange(() => MiddleNameNativeHint); + NotifyOfPropertyChange(() => LastNameNativeHint); + NotifyOfPropertyChange(() => PassportNativeFooter); + + if (!string.IsNullOrEmpty(SelectedResidenceCountryError)) + { + SelectedResidenceCountryError = null; + NotifyOfPropertyChange(() => SelectedResidenceCountryError); + } + } + } + } + + public string SelectedResidenceCountryError { get; set; } + + private string _documentNumber; + + public string DocumentNumber + { + get { return _documentNumber; } + set + { + if (_documentNumber != value) + { + _documentNumber = value; + if (!string.IsNullOrEmpty(DocumentNumberError)) + { + DocumentNumberError = null; + NotifyOfPropertyChange(() => DocumentNumberError); + } + } + } + } + + public string DocumentNumberError { get; set; } + + private string _expiryDate; + + public string ExpiryDate + { + get { return _expiryDate; } + set + { + if (_expiryDate != value) + { + _expiryDate = value; + if (!string.IsNullOrEmpty(ExpiryDateError)) + { + ExpiryDateError = null; + NotifyOfPropertyChange(() => ExpiryDateError); + } + } + } + } + + public string ExpiryDateError { get; set; } + + public string TranslationsError { get; set; } + + public TLRPCError Error { get; set; } + + public string Caption + { + get + { + if (_secureType != null) + { + return SecureRequiredTypeToCaptionConverter.Convert(_secureType); + } + if (_dataProofValue != null) + { + return SecureRequiredTypeToCaptionConverter.Convert(_dataProofValue.Type); + } + if (_dataValue != null) + { + return SecureRequiredTypeToCaptionConverter.Convert(_dataValue.Type); + } + if (_secureRequiredType != null) + { + var type = _secureRequiredType.SelectedDataProofRequiredType; + if (type != null) + { + return SecureRequiredTypeToCaptionConverter.Convert(type.Type); + } + } + //if (_authorizationForm != null) + //{ + // var type = _authorizationForm.RequiredTypes.FirstOrDefault(IsValidProofType); + // if (type != null) + // { + // return SecureRequiredTypeToCaptionConverter.Convert(type); + // } + //} + + return AppResources.PassportResidentialAddress; + } + } + + public string DeleteCommand + { + get + { + if (_dataValue != null && _dataProofValue == null) + { + return AppResources.PassportDelete; + } + + return AppResources.PassportDeleteDocument; + } + } + + public TLSecureFileBase FrontSide { get; set; } + + public string FrontSideError { get; set; } + + public string FrontSideTitle + { + get + { + TLSecureValueTypeBase type = null; + if (_secureType != null) + { + type = _secureType; + } + if (_dataProofValue != null) + { + type = _dataProofValue.Type; + } + + if (type is TLSecureValueTypePassport + || type is TLSecureValueTypeInternalPassport) + { + return AppResources.PassportMainPage; + } + + return AppResources.PassportFrontSide; + } + } + + public string FrontSideSubtitle + { + get + { + TLSecureValueTypeBase type = null; + if (_secureType != null) + { + type = _secureType; + } + if (_dataProofValue != null) + { + type = _dataProofValue.Type; + } + + if (type is TLSecureValueTypePassport + || type is TLSecureValueTypeInternalPassport) + { + return AppResources.PassportMainPageInfo; + } + + return AppResources.PassportFrontSideInfo; + } + } + + public TLSecureFileBase ReverseSide { get; set; } + + public string ReverseSideError { get; set; } + + public TLSecureFileBase Selfie { get; set; } + + public string SelfieError { get; set; } + + public IEnumerable GetFiles() + { + if (FrontSide != null) yield return FrontSide; + if (ReverseSide != null) yield return ReverseSide; + if (Selfie != null) yield return Selfie; + + foreach (var file in Translations) + { + yield return file; + } + } + + public string AttachTranslationHint + { + get + { + TLSecureValueTypeBase type = null; + if (_secureType != null) + { + type = _secureType; + } + else if (_dataProofValue != null) + { + type = _dataProofValue.Type; + } + else if (_secureRequiredType != null && _secureRequiredType.SelectedDataProofRequiredType != null) + { + type = _secureRequiredType.SelectedDataProofRequiredType.Type; + } + //else if (_authorizationForm != null) + //{ + // type = _authorizationForm.RequiredTypes.FirstOrDefault(IsValidProofType); + //} + + if (type != null) + { + if (type is TLSecureValueTypeDriverLicense) + { + return AppResources.PassportAddTranslationDriverLicenceInfo; + } + if (type is TLSecureValueTypeIdentityCard) + { + return AppResources.PassportAddTranslationIdentityCardInfo; + } + if (type is TLSecureValueTypeInternalPassport) + { + return AppResources.PassportAddTranslationInternalPassportInfo; + } + if (type is TLSecureValueTypePassport) + { + return AppResources.PassportAddTranslationPassportInfo; + } + } + + return AppResources.PassportAddTranslationUploadInfo; + } + } + + public string AttachDocumentCommand + { + get + { + if (Translations.Count > 0) + { + return AppResources.PassportUploadAdditinalDocument; + } + + return AppResources.PassportUploadDocument; + } + } + + public ObservableCollection Translations { get; set; } + + public bool IsFileUploading + { + get + { + foreach (var file in GetFiles()) + { + if (file.UploadingProgress > 0.0 && file.UploadingProgress < 1.0) + { + return true; + } + } + + return false; + } + } + + public bool IsDataProofEnabled + { + get + { + if (_secureRequiredType != null && _secureRequiredType.SelectedDataProofRequiredType != null) + { + return IsValidProofType(_secureRequiredType.SelectedDataProofRequiredType.Type); + } + //if (_authorizationForm != null) + //{ + // return _authorizationForm.RequiredTypes.Any(IsValidProofType); + //} + if (_secureType != null) + { + return IsValidProofType(_secureType); + } + + return _dataProofValue != null; + } + } + + public bool IsDataProofReverseEnabled + { + get + { + if (_secureRequiredType != null && _secureRequiredType.SelectedDataProofRequiredType != null) + { + return IsValidReversedProofType(_secureRequiredType.SelectedDataProofRequiredType.Type); + } + if (_dataProofValue != null) + { + return IsValidReversedProofType(_dataProofValue.Type); + } + if (_secureType != null) + { + return IsValidReversedProofType(_secureType); + } + + return false; + } + } + + public bool IsDataProofSelfieEnabled + { + get + { + if (_secureRequiredType != null && _secureRequiredType.SelectedDataProofRequiredType != null) + { + return _secureRequiredType.SelectedDataProofRequiredType.SelfieRequired; + } + if (_secureType != null) + { + return true; + } + if (_dataProofValue != null) + { + return true; + } + + return false; + } + } + + public bool IsDataProofTranslationEnabled + { + get + { + if (_secureRequiredType != null && _secureRequiredType.SelectedDataProofRequiredType != null) + { + return _secureRequiredType.SelectedDataProofRequiredType.TranslationRequired; + } + if (_secureType != null) + { + return true; + } + if (_dataProofValue != null) + { + return true; + } + + return false; + } + } + + public bool IsDataEnabled + { + get + { + if (_secureRequiredType != null) + { + return _secureRequiredType.DataRequiredType != null; + } + //if (_authorizationForm != null) + //{ + // return _authorizationForm.RequiredTypes.Any(IsValidDataType); + //} + if (_secureType != null) + { + return IsValidDataType(_secureType); + } + + return _dataValue != null; + } + } + + public bool IsDataNativeNamesEnabled + { + get + { + if (_secureRequiredType != null && _secureRequiredType.DataRequiredType != null) + { + return _secureRequiredType.DataRequiredType.NativeNames; + } + + return false; + } + } + + public bool IsDataNativeNamesVisible + { + get + { + if (IsDataNativeNamesEnabled) + { + if (!string.IsNullOrEmpty(FirstNameNativeError)) return true; + if (!string.IsNullOrEmpty(MiddleNameNativeError)) return true; + if (!string.IsNullOrEmpty(LastNameNativeError)) return true; + + IJsonValue langCode; + if (_secureRequiredType != null + && _secureRequiredType.AuthorizationForm != null + && _secureRequiredType.AuthorizationForm.Config != null + && _secureRequiredType.AuthorizationForm.Config.CountriesLangsObject != null + && _selectedResidenceCountry != null + && _secureRequiredType.AuthorizationForm.Config.CountriesLangsObject.TryGetValue(_selectedResidenceCountry.Code.ToUpperInvariant(), out langCode) + && string.Equals(langCode.GetString(), "en", StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + return true; + } + + return false; + } + } + + public bool IsDeleteEnabled + { + get { return _dataValue != null || _dataProofValue != null; } + } + + public static bool IsValidType(TLSecureValueTypeBase type) + { + return IsValidDataType(type) + || IsValidProofType(type); + } + + public static bool IsValidDataType(TLSecureValueTypeBase type) + { + return type is TLSecureValueTypePersonalDetails; + } + + public static bool IsValidProofType(TLSecureValueTypeBase type) + { + return type is TLSecureValueTypePassport + || type is TLSecureValueTypeInternalPassport + || type is TLSecureValueTypeDriverLicense + || type is TLSecureValueTypeIdentityCard; + } + + public static bool IsValidReversedProofType(TLSecureValueTypeBase type) + { + return type is TLSecureValueTypeDriverLicense + || type is TLSecureValueTypeIdentityCard; + } + + private readonly TLAuthorizationForm _authorizationForm; + + private readonly TLPasswordBase _passwordBase; + + private readonly TLSecureValue _dataValue; + + private readonly TLSecureValue _dataProofValue; + + private readonly TLSecureValueTypeBase _secureType; + + private readonly SecureRequiredType _secureRequiredType; + + public PersonalDetailsViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, + IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, + ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + Errors = new ObservableCollection(); + + Translations = new ObservableCollection(); + Translations.CollectionChanged += (sender, args) => + { + NotifyOfPropertyChange(() => AttachDocumentCommand); + }; + + _authorizationForm = StateService.AuthorizationForm; + StateService.AuthorizationForm = null; + + _passwordBase = stateService.Password; + stateService.Password = null; + + var secureValue = StateService.SecureValue; + StateService.SecureValue = null; + + _secureType = StateService.SecureType; + StateService.SecureType = null; + + _secureRequiredType = StateService.SecureRequiredType; + StateService.SecureRequiredType = null; + + _dataValue = GetData(_secureRequiredType, secureValue); + if (_dataValue != null && _dataValue.Data != null) + { + var rootObject = _dataValue.Data.DecryptedData as PersonalDetailsRootObject; + if (rootObject != null) + { + _firstName = rootObject.first_name; + _middleName = rootObject.middle_name; + _lastName = rootObject.last_name; + _birthDate = rootObject.birth_date; + _gender = rootObject.gender; + if (!string.IsNullOrEmpty(rootObject.country_code)) + { + var country = + CountryUtils.CountriesSource.FirstOrDefault( + x => string.Equals(rootObject.country_code, x.Code, StringComparison.OrdinalIgnoreCase)); + _selectedCountry = country; + } + if (!string.IsNullOrEmpty(rootObject.residence_country_code)) + { + var country = + CountryUtils.CountriesSource.FirstOrDefault( + x => + string.Equals(rootObject.residence_country_code, x.Code, + StringComparison.OrdinalIgnoreCase)); + _selectedResidenceCountry = country; + } + + _firstNameNative = rootObject.first_name_native; + _middleNameNative = rootObject.middle_name_native; + _lastNameNative = rootObject.last_name_native; + } + } + + _dataProofValue = GetDataProof(_secureRequiredType, secureValue); + if (_dataProofValue != null) + { + FrontSide = _dataProofValue.FrontSide; + ReverseSide = _dataProofValue.ReverseSide; + Selfie = _dataProofValue.Selfie; + + var dataProofValue85 = _dataProofValue as TLSecureValue85; + if (dataProofValue85 != null && dataProofValue85.Translation != null) + { + Translations.Clear(); + foreach (var translation in dataProofValue85.Translation) + { + Translations.Add(translation); + } + } + + var rootObject = _dataProofValue.Data.DecryptedData as PersonalDetailsDocumentRootObject; + if (rootObject != null) + { + _documentNumber = rootObject.document_no; + _expiryDate = rootObject.expiry_date; + } + } + + GetErrors(_authorizationForm); + } + + private bool HasErrors() + { + if (IsDataProofEnabled) + { + var frontSideError = FrontSide as ISecureFileError; + if (frontSideError != null && !string.IsNullOrEmpty(frontSideError.Error)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.FRONT_SIDE_REQUIRED.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (FrontSide == null) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.FRONT_SIDE_REQUIRED.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (IsDataProofReverseEnabled) + { + var reverseSideError = ReverseSide as ISecureFileError; + if (reverseSideError != null && !string.IsNullOrEmpty(reverseSideError.Error)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.REVERSE_SIDE_REQUIRED.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (ReverseSide == null) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.REVERSE_SIDE_REQUIRED.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + } + + if (IsDataProofSelfieEnabled) + { + var selfieSideError = Selfie as ISecureFileError; + if (selfieSideError != null && !string.IsNullOrEmpty(selfieSideError.Error)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.SELFIE_REQUIRED.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (Selfie == null) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.SELFIE_REQUIRED.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + } + + if (IsDataProofTranslationEnabled) + { + if (Translations != null && Translations.Count > 0) + { + foreach (var file in Translations.OfType()) + { + if (!string.IsNullOrEmpty(file.Error)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) + { + Message = new TLString(ErrorType.TRANSLATION_ERROR.ToString()) + }; + NotifyOfPropertyChange(() => Error); + return true; + } + } + } + else + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.TRANSLATION_EMPTY.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(TranslationsError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.TRANSLATION_EMPTY.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + } + } + + if (IsDataEnabled) + { + if (!string.IsNullOrEmpty(FirstNameError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.FIRSTNAME_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (string.IsNullOrEmpty(FirstName)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.FIRSTNAME_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + + if (!string.IsNullOrEmpty(MiddleNameError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.MIDDLENAME_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(LastNameError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.LASTNAME_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (string.IsNullOrEmpty(LastName)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.LASTNAME_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(BirthDateError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.BIRTHDATE_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (string.IsNullOrEmpty(BirthDate)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.BIRTHDATE_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(GenderError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.GENDER_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (string.IsNullOrEmpty(Gender)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.GENDER_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(SelectedCountryError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.ADDRESS_COUNTRY_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (_selectedCountry == null) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.ADDRESS_COUNTRY_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(SelectedResidenceCountryError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.ADDRESS_RESIDENCE_COUNTRY_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (_selectedResidenceCountry == null) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.ADDRESS_RESIDENCE_COUNTRY_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + } + + if (IsDataProofEnabled) + { + if (!string.IsNullOrEmpty(DocumentNumberError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.DOCUMENT_NUMBER_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (string.IsNullOrEmpty(DocumentNumber)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.DOCUMENT_NUMBER_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(ExpiryDateError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.EXPIRYDATE_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + } + + if (IsDataNativeNamesVisible) + { + if (!string.IsNullOrEmpty(FirstNameNativeError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.FIRSTNAMENATIVE_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (string.IsNullOrEmpty(FirstNameNative)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.FIRSTNAMENATIVE_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(MiddleNameNativeError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.MIDDLENAMENATIVE_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(LastNameNativeError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.LASTNAMENATIVE_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (string.IsNullOrEmpty(LastNameNative)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.LASTNAMENATIVE_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + } + + Error = null; + NotifyOfPropertyChange(() => Error); + return false; + } + + private void GetErrors(TLAuthorizationForm form) + { + if (form == null) return; + if (form.Errors == null || form.Errors.Count == 0) return; + + var dataFieldAction = new Dictionary> + { + {"first_name", error => { FirstNameError = error.Text.ToString(); }}, + {"middle_name", error => { MiddleNameError = error.Text.ToString(); }}, + {"last_name", error => { LastNameError = error.Text.ToString(); }}, + {"birth_date", error => { BirthDateError = error.Text.ToString(); }}, + {"gender", error => { GenderError = error.Text.ToString(); }}, + {"country_code", error => { SelectedCountryError = error.Text.ToString(); }}, + {"residence_country_code", error => { SelectedResidenceCountryError = error.Text.ToString(); }}, + {"document_no", error => { DocumentNumberError = error.Text.ToString(); }}, + {"expiry_date", error => { ExpiryDateError = error.Text.ToString(); }}, + {"first_name_native", error => { FirstNameNativeError = error.Text.ToString(); }}, + {"middle_name_native", error => { MiddleNameNativeError = error.Text.ToString(); }}, + {"last_name_native", error => { LastNameNativeError = error.Text.ToString(); }}, + }; + + var errorTypeAction = new Dictionary> + { + { + typeof(TLSecureValueError), errorBase => + { + var error = errorBase as TLSecureValueError; + if (error != null) + { + if (_secureRequiredType != null) + { + if (_secureRequiredType.DataRequiredType != null + && _secureRequiredType.DataRequiredType.Type.GetType() == error.Type.GetType()) + { + Errors.Add(error.Text.ToString()); + } + else if (_secureRequiredType.SelectedDataProofRequiredType != null + && _secureRequiredType.SelectedDataProofRequiredType.Type.GetType() == error.Type.GetType()) + { + Errors.Add(error.Text.ToString()); + } + } + } + } + }, + { + typeof(TLSecureValueErrorData), errorBase => + { + var error = errorBase as TLSecureValueErrorData; + if (error != null) + { + Action fieldAction; + if (dataFieldAction.TryGetValue(error.Field.ToString(), out fieldAction)) + { + fieldAction.SafeInvoke(error); + } + } + } + }, + { + typeof(TLSecureValueErrorFile), errorBase => + { + var error = errorBase as TLSecureValueErrorFile; + if (error != null) + { + var frontSideError = FrontSide as ISecureFileError; + if (frontSideError != null && TLString.Equals(frontSideError.FileHash, error.FileHash, StringComparison.OrdinalIgnoreCase)) + { + frontSideError.Error = error.Text.ToString(); + } + var reverseSideError = ReverseSide as ISecureFileError; + if (reverseSideError != null && TLString.Equals(reverseSideError.FileHash, error.FileHash, StringComparison.OrdinalIgnoreCase)) + { + reverseSideError.Error = error.Text.ToString(); + } + var selfieError = Selfie as ISecureFileError; + if (selfieError != null && TLString.Equals(selfieError.FileHash, error.FileHash, StringComparison.OrdinalIgnoreCase)) + { + selfieError.Error = error.Text.ToString(); + } + } + } + }, + { + typeof(TLSecureValueErrorFrontSide), errorBase => + { + var error = errorBase as TLSecureValueErrorFrontSide; + if (error != null) + { + var frontSideError = FrontSide as ISecureFileError; + if (frontSideError != null && TLString.Equals(frontSideError.FileHash, error.FileHash, StringComparison.OrdinalIgnoreCase)) + { + frontSideError.Error = error.Text.ToString(); + } + } + } + }, + { + typeof(TLSecureValueErrorReverseSide), errorBase => + { + var error = errorBase as TLSecureValueErrorReverseSide; + if (error != null) + { + var reverseSideError = ReverseSide as ISecureFileError; + if (reverseSideError != null && TLString.Equals(reverseSideError.FileHash, error.FileHash, StringComparison.OrdinalIgnoreCase)) + { + reverseSideError.Error = error.Text.ToString(); + } + } + } + }, + { + typeof(TLSecureValueErrorSelfie), errorBase => + { + var error = errorBase as TLSecureValueErrorSelfie; + if (error != null) + { + var selfieError = Selfie as ISecureFileError; + if (selfieError != null && TLString.Equals(selfieError.FileHash, error.FileHash, StringComparison.OrdinalIgnoreCase)) + { + selfieError.Error = error.Text.ToString(); + } + } + } + }, + { + typeof(TLSecureValueErrorTranslationFile), errorBase => + { + var error = errorBase as TLSecureValueErrorTranslationFile; + if (error != null) + { + foreach (var file in Translations.OfType()) + { + if (TLString.Equals(file.FileHash, error.FileHash, StringComparison.OrdinalIgnoreCase)) + { + file.Error = error.Text.ToString(); + break; + } + } + } + } + }, + { + typeof(TLSecureValueErrorTranslationFiles), errorBase => + { + var error = errorBase as TLSecureValueErrorTranslationFiles; + if (error != null) + { + TranslationsError = error.Text.ToString(); + } + } + } + }; + + Errors.Clear(); + foreach (var error in _authorizationForm.Errors) + { + Action action; + if ((_dataValue != null && _dataValue.Type.GetType() == error.Type.GetType() + || _dataProofValue != null && _dataProofValue.Type.GetType() == error.Type.GetType()) + && errorTypeAction.TryGetValue(error.GetType(), out action)) + { + action.SafeInvoke(error); + } + } + } + + private void RemoveDataErrors() + { + if (_authorizationForm != null && _authorizationForm.Errors != null) + { + for (var i = 0; i < _authorizationForm.Errors.Count; i++) + { + var error = _authorizationForm.Errors[i]; + if (error != null && IsValidDataType(error.Type)) + { + _authorizationForm.Errors.RemoveAt(i--); + } + } + } + } + + private void RemoveProofErrors() + { + if (_authorizationForm != null && _authorizationForm.Errors != null) + { + for (var i = 0; i < _authorizationForm.Errors.Count; i++) + { + var error = _authorizationForm.Errors[i]; + if (error != null && IsValidProofType(error.Type)) + { + _authorizationForm.Errors.RemoveAt(i--); + } + } + } + } + + private TLSecureValue GetData(SecureRequiredType requiredType, TLSecureValue secureValue) + { + if (requiredType != null) + { + return requiredType.DataValue; + } + + return secureValue != null && IsValidDataType(secureValue.Type) ? secureValue : null; + } + + private TLSecureValue GetDataProof(SecureRequiredType requiredType, TLSecureValue secureValue) + { + if (requiredType != null) + { + return requiredType.DataProofValue; + } + + return secureValue != null && IsValidProofType(secureValue.Type) ? secureValue : null; + } + + public void AttachFrontSide() + { + AttachDocument("FrontSide"); + } + + public void AttachReverseSide() + { + AttachDocument("ReverseSide"); + } + + public void AttachSelfie() + { + AttachDocument("Selfie"); + } + + public void AttachTranslation() + { + if (Translations.Count >= Constants.MaxPassportFilesCount) + { + ShellViewModel.ShowCustomMessageBox(string.Format(AppResources.PassportUploadMaxReached, Constants.MaxPassportFilesCount), AppResources.AppName, + AppResources.Ok.ToLowerInvariant(), null, + dismissed => + { + + }); + + return; + } + + AttachDocument("Translation"); + } + + public async void AttachDocument(string type) + { + ((App)Application.Current).ChooseFileInfo = new ChooseFileInfo(DateTime.Now); + var picker = new FileOpenPicker(); + picker.FileTypeFilter.Add(".bmp"); + picker.FileTypeFilter.Add(".jpg"); + picker.FileTypeFilter.Add(".jpeg"); + picker.FileTypeFilter.Add(".png"); + picker.ContinuationData.Add("From", "PersonalDetailsView"); + picker.ContinuationData.Add("Type", type); + + if (Environment.OSVersion.Version.Major >= 10) + { + var result = await picker.PickSingleFileAsync(); + if (result != null) + { + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + SendDocument(type, result); + }); + } + } + else + { + picker.PickSingleFileAndContinue(); + } + } + + public async void SendDocument(string type, StorageFile file) + { + if (string.IsNullOrEmpty(type)) return; + if (file == null) return; + + var password = _passwordBase as TLPassword; + if (password == null) return; + + var passwordSettings = password.Settings as TLPasswordSettings83; + if (passwordSettings == null) return; + + var fileId = TLLong.Random(); + var compressedFileName = string.Format("secureid_compressed_{0}.dat", fileId); + var fileName = string.Format("secureid_{0}.dat", fileId); + var previewFileName = string.Format("secureid_preview_{0}.dat", fileId); + var localFileName = string.Format("document{0}_{1}.dat", fileId, 0); + + var inputStream = await file.OpenReadAsync(); + + await DialogDetailsViewModel.ResizeJpeg(inputStream, Constants.DefaultPassportImageSize, file.DisplayName, compressedFileName, 0.89); + + file = await ApplicationData.Current.LocalFolder.GetFileAsync(compressedFileName); + + var padding = await Utils.Passport.GenerateRandomPadding(file); + var fileSecret = Utils.Passport.GenerateSecret(TLString.Empty); + var fileHash = TLString.FromBigEndianData(await Utils.Passport.GetSha256(padding, file)); + + var fileSecureSecret = Utils.Passport.EncryptValueSecret( + fileSecret, + EnterPasswordViewModel.Secret, + fileHash); + + var encryptedFile = await Utils.Passport.EncryptFile(fileName, file, fileSecret, fileHash, padding); + var stream = await file.OpenReadAsync(); + + await DialogDetailsViewModel.ResizeJpeg(stream, 180, localFileName, previewFileName); + + int length; + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + using (var fileStream = store.OpenFile(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + length = (int)fileStream.Length; + } + } + + var secureFileUploaded = new TLSecureFileUploaded + { + Id = fileId, + Parts = null, + MD5Checksum = TLString.Empty, + Size = new TLInt(length), + Date = TLUtils.DateToUniversalTimeTLInt(MTProtoService.ClientTicksDelta, DateTime.Now), + FileHash = fileHash, + Secret = fileSecureSecret + }; + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + switch (type) + { + case "FrontSide": + FrontSide = secureFileUploaded; + NotifyOfPropertyChange(() => FrontSide); + break; + case "ReverseSide": + ReverseSide = secureFileUploaded; + NotifyOfPropertyChange(() => ReverseSide); + break; + case "Selfie": + Selfie = secureFileUploaded; + NotifyOfPropertyChange(() => Selfie); + break; + case "Translation": + Translations.Add(secureFileUploaded); + TranslationsError = null; + NotifyOfPropertyChange(() => TranslationsError); + break; + } + + NotifyOfPropertyChange(() => IsFileUploading); + secureFileUploaded.UploadingProgress = 0.01; + secureFileUploaded.UploadingSize = (int)(secureFileUploaded.Size.Value * secureFileUploaded.UploadingProgress); + var documentFileManager = IoC.Get(); + documentFileManager.UploadFile(fileId, secureFileUploaded, encryptedFile); + }); + } + + public void DeleteFrontSide() + { + DeleteFile(FrontSide); + } + + public void DeleteReverseSide() + { + DeleteFile(ReverseSide); + } + + public void DeleteSelfie() + { + DeleteFile(Selfie); + } + + public void DeleteFile(TLSecureFileBase file) + { + if (file == null) return; + + ShellViewModel.ShowCustomMessageBox(AppResources.PassportDeleteScanAlert, AppResources.AppName, + AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + if (FrontSide == file) + { + FrontSide = null; + NotifyOfPropertyChange(() => FrontSide); + } + else if (ReverseSide == file) + { + ReverseSide = null; + NotifyOfPropertyChange(() => ReverseSide); + } + else if (Selfie == file) + { + Selfie = null; + NotifyOfPropertyChange(() => Selfie); + } + else + { + Translations.Remove(file); + } + } + }); + } + + public void Delete() + { + if (_dataValue == null && _dataProofValue == null) + { + NavigationService.GoBack(); + return; + } + + if (_dataValue != null && _dataProofValue != null) + { + object content = null; + var textBlock = new TextBlock { IsHitTestVisible = false }; + var checkBox = new CheckBox { IsChecked = true, IsHitTestVisible = false }; + if (_dataValue != null) + { + textBlock.SetValue(TextBlock.FontSizeProperty, DependencyProperty.UnsetValue); + + var text = AppResources.PassportDeleteDocumentPersonal; + textBlock.Margin = new Thickness(-18.0, 0.0, 12.0, 0.0); + textBlock.Text = text; + textBlock.VerticalAlignment = VerticalAlignment.Center; + + var panel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0.0, -2.0, 0.0, -20.0), Background = new SolidColorBrush(Colors.Transparent) }; + panel.Tap += (sender, args) => + { + checkBox.IsChecked = !checkBox.IsChecked; + }; + panel.Children.Add(checkBox); + panel.Children.Add(textBlock); + content = panel; + } + ShellViewModel.ShowCustomMessageBox(AppResources.PassportDeleteDocumentAlert, AppResources.AppName, + AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + var deleteData = _dataValue != null && checkBox.IsChecked == true; + var values = new TLVector { _dataProofValue }; + var types = new TLVector { _dataProofValue.Type }; + if (deleteData) + { + values.Add(_dataValue); + types.Add(_dataValue.Type); + } + IsWorking = true; + MTProtoService.DeleteSecureValueAsync( + types, + result => BeginOnUIThread(() => + { + IsWorking = false; + if (_authorizationForm != null) + { + foreach (var value in values) + { + _authorizationForm.Values.Remove(value); + } + } + RemoveDataErrors(); + RemoveProofErrors(); + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + EventAggregator.Publish(new DeleteSecureValueEventArgs { Values = values }); + NavigationService.GoBack(); + }), + error => BeginOnUIThread(() => + { + IsWorking = false; + })); + } + }, + content); + + return; + } + + // delete data + if (_dataValue != null) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PassportDeleteAddressAlert, AppResources.AppName, + AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + IsWorking = true; + MTProtoService.DeleteSecureValueAsync( + new TLVector { _dataValue.Type }, + result => BeginOnUIThread(() => + { + IsWorking = false; + if (_authorizationForm != null) + { + _authorizationForm.Values.Remove(_dataValue); + } + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + RemoveDataErrors(); + EventAggregator.Publish(new DeleteSecureValueEventArgs { Values = new List { _dataValue } }); + NavigationService.GoBack(); + }), + error => BeginOnUIThread(() => + { + IsWorking = false; + })); + } + }); + + return; + } + + // delete proof + if (_dataProofValue != null) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PassportDeleteDocumentAlert, AppResources.AppName, + AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + IsWorking = true; + MTProtoService.DeleteSecureValueAsync( + new TLVector { _dataProofValue.Type }, + result => BeginOnUIThread(() => + { + IsWorking = false; + RemoveProofErrors(); + if (_authorizationForm != null) + { + _authorizationForm.Values.Remove(_dataProofValue); + } + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + EventAggregator.Publish(new DeleteSecureValueEventArgs { Values = new List { _dataProofValue } }); + NavigationService.GoBack(); + }), + error => BeginOnUIThread(() => + { + IsWorking = false; + })); + } + }); + + return; + } + } + + public void Done() + { + if (IsFileUploading) return; + if (IsWorking) return; + + SaveDataAsync( + () => SaveProofAsync( + () => NavigationService.GoBack())); + } + + private bool UseSameNativeNames() + { + IJsonValue langCode; + if (_secureRequiredType != null + && _secureRequiredType.AuthorizationForm != null + && _secureRequiredType.AuthorizationForm.Config != null + && _secureRequiredType.AuthorizationForm.Config.CountriesLangsObject != null + && _selectedResidenceCountry != null + && _secureRequiredType.AuthorizationForm.Config.CountriesLangsObject.TryGetValue(_selectedResidenceCountry.Code.ToUpperInvariant(), out langCode) + && string.Equals(langCode.GetString(), "en", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + return false; + } + + private void SaveDataAsync(System.Action callback, System.Action faultCallback = null) + { + var password = _passwordBase as TLPassword; + if (password == null) + { + faultCallback.SafeInvoke(); + return; + } + + var passwordSettings = password.Settings as TLPasswordSettings83; + if (passwordSettings == null) + { + faultCallback.SafeInvoke(); + return; + } + + var dataValue = _dataValue; + if (dataValue == null) + { + var secureType = + _secureRequiredType != null && _secureRequiredType.DataRequiredType != null + ? _secureRequiredType.DataRequiredType.Type + : null; + + //_authorizationForm != null + //? _authorizationForm.RequiredTypes.FirstOrDefault(IsValidDataType) + //: null; + + // add new address from passport settings + if (_secureType != null && IsValidDataType(_secureType)) + { + dataValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = _secureType + }; + } + // add new address from authorization form + else if (secureType != null) + { + dataValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = secureType + }; + } + else + { + callback.SafeInvoke(); + return; + } + } + + if (HasErrors()) + { + faultCallback.SafeInvoke(); + return; + } + + var rootObject = new PersonalDetailsRootObject + { + first_name = FirstName, + middle_name = MiddleName, + last_name = LastName, + birth_date = BirthDate, + gender = Gender, + country_code = _selectedCountry.Code.ToUpperInvariant(), + residence_country_code = _selectedResidenceCountry.Code.ToUpperInvariant() + }; + + if (IsDataNativeNamesEnabled) + { + if (UseSameNativeNames()) + { + rootObject.first_name_native = FirstName; + rootObject.middle_name_native = MiddleName; + rootObject.last_name_native = LastName; + } + else + { + rootObject.first_name_native = FirstNameNative; + rootObject.middle_name_native = MiddleNameNative; + rootObject.last_name_native = LastNameNative; + } + } + + var data = JsonUtils.ToJSON(rootObject); + if (data == null) return; + + var valueSecret = Utils.Passport.GenerateSecret(TLString.Empty); + var newSecureValue = Utils.Passport.EncryptSecureValue( + dataValue, + new TLString(data), + valueSecret, + EnterPasswordViewModel.Secret); + var secureSecretHash = passwordSettings.SecureSettings.SecureSecretId; + + IsWorking = true; + MTProtoService.SaveSecureValueAsync( + newSecureValue.ToInputSecureValue(), secureSecretHash, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + result.Data.DecryptedData = rootObject; + if (_authorizationForm != null) + { + _authorizationForm.Values.Remove(dataValue); + _authorizationForm.Values.Add(result); + } + RemoveDataErrors(); + + dataValue.Update(result); + dataValue.NotifyOfPropertyChange(() => dataValue.Self); + + if (_secureType != null) + { + EventAggregator.Publish(new AddSecureValueEventArgs { Values = new List { dataValue } }); + } + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + + callback.SafeInvoke(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + + if (error.CodeEquals(ErrorCode.BAD_REQUEST)) + { + ShellViewModel.ShowCustomMessageBox( + "account.saveSecureValue" + Environment.NewLine + error.Message, + AppResources.AppName, + AppResources.Ok); + } + + faultCallback.SafeInvoke(); + })); + } + + private void SaveProofAsync(System.Action callback, System.Action faultCallback = null) + { + var password = _passwordBase as TLPassword; + if (password == null) + { + callback.SafeInvoke(); + return; + } + + var passwordSettings = password.Settings as TLPasswordSettings83; + if (passwordSettings == null) + { + callback.SafeInvoke(); + return; + } + + var dataProofValue = _dataProofValue; + if (dataProofValue == null) + { + var secureType = + _secureRequiredType != null && _secureRequiredType.SelectedDataProofRequiredType != null + ? _secureRequiredType.SelectedDataProofRequiredType.Type + : null; + + //_authorizationForm != null ? + //_authorizationForm.RequiredTypes.FirstOrDefault(IsValidProofType) + //: null; + + if (_secureType != null && IsValidProofType(_secureType)) + { + dataProofValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = _secureType + }; + } + else if (secureType != null) + { + dataProofValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = secureType + }; + } + else + { + callback.SafeInvoke(); + return; + } + } + + if (HasErrors()) + { + faultCallback.SafeInvoke(); + return; + } + + var rootObject = new PersonalDetailsDocumentRootObject + { + document_no = DocumentNumber, + expiry_date = ExpiryDate + }; + + var data = JsonUtils.ToJSON(rootObject); + if (data == null) return; + + var valueSecret = Utils.Passport.GenerateSecret(TLString.Empty); + var newSecureValue = Utils.Passport.EncryptSecureValue( + dataProofValue, + new TLString(data), + valueSecret, + EnterPasswordViewModel.Secret); + + var inputSecureValue = newSecureValue.ToInputSecureValue(); + inputSecureValue.FrontSide = FrontSide != null ? FrontSide.ToInputSecureFile() : null; + inputSecureValue.ReverseSide = ReverseSide != null ? ReverseSide.ToInputSecureFile() : null; + inputSecureValue.Selfie = Selfie != null ? Selfie.ToInputSecureFile() : null; + + var inputSecureValue85 = inputSecureValue as TLInputSecureValue85; + if (inputSecureValue85 != null) + { + if (Translations.Count > 0) + { + var translation = new TLVector(); + foreach (var file in Translations) + { + translation.Add(file.ToInputSecureFile()); + } + inputSecureValue85.Translation = translation; + } + } + + var secureSecretId = passwordSettings.SecureSettings.SecureSecretId; + + IsWorking = true; + MTProtoService.SaveSecureValueAsync( + inputSecureValue, secureSecretId, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + result.Data.DecryptedData = rootObject; + if (_authorizationForm != null) + { + _authorizationForm.Values.Remove(dataProofValue); + _authorizationForm.Values.Add(result); + } + RemoveProofErrors(); + + dataProofValue.Update(result); + dataProofValue.NotifyOfPropertyChange(() => dataProofValue.Self); + + if (_secureType != null) + { + EventAggregator.Publish(new AddSecureValueEventArgs { Values = new List { dataProofValue } }); + } + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + + callback.SafeInvoke(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + if (error.TypeEquals(ErrorType.FILES_EMPTY)) + { + Error = error; + NotifyOfPropertyChange(() => Error); + } + else if (error.TypeEquals(ErrorType.FRONT_SIDE_REQUIRED)) + { + Error = error; + NotifyOfPropertyChange(() => Error); + } + else if (error.TypeEquals(ErrorType.REVERSE_SIDE_REQUIRED)) + { + Error = error; + NotifyOfPropertyChange(() => Error); + } + else if (error.TypeEquals(ErrorType.SELFIE_REQUIRED)) + { + Error = error; + NotifyOfPropertyChange(() => Error); + } + else if (error.TypeEquals(ErrorType.FILES_TOO_MUCH)) + { + ShellViewModel.ShowCustomMessageBox( + string.Format(AppResources.PassportUploadMaxReached, Constants.MaxPassportFilesCount), + AppResources.AppName, + AppResources.Ok.ToLowerInvariant()); + } + else if (error.CodeEquals(ErrorCode.BAD_REQUEST)) + { + ShellViewModel.ShowCustomMessageBox( + "account.saveSecureValue" + Environment.NewLine + error.Message, + AppResources.AppName, + AppResources.Ok); + } + + faultCallback.SafeInvoke(); + })); + } + + public void OpenScan(TLSecureFileBase file) + { + return; + StateService.CurrentPhotoMessage = new TLMessage { Status = MessageStatus.Confirmed }; + OpenImageViewer(); + } + + public void SelectBirthDate() + { + DateTime currentDate; + if (!DateTime.TryParse(BirthDate, out currentDate)) + { + currentDate = DateTime.Now.Date; + } + + var datePickerPage = new TelegramDatePickerPage(new YearDataSource{ MaxYear = DateTime.Now.Year, MinYear = 1900 }) { Height = 160.0, Value = currentDate, Margin = new Thickness(0.0, 18.0, 0.0, 6.0) }; + ShellViewModel.ShowCustomMessageBox(null, AppResources.PassportSelectDate.ToUpperInvariant(), AppResources.Ok.ToLowerInvariant(), null, + result => + { + if (result == CustomMessageBoxResult.RightButton) + { + var selector = GetChildOfType(datePickerPage); + if (selector != null) + { + var value = ((DateTimeWrapper)selector.DataSource.SelectedItem).DateTime; + value = value > DateTime.Now.Date ? DateTime.Now.Date : value; + BirthDate = value.ToString("dd.MM.yyyy"); + NotifyOfPropertyChange(() => BirthDate); + } + } + }, + datePickerPage); + } + + public static T GetChildOfType(DependencyObject depObj) where T : DependencyObject + { + if (depObj == null) return null; + + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) + { + var child = VisualTreeHelper.GetChild(depObj, i); + + var result = (child as T) ?? GetChildOfType(child); + if (result != null) return result; + } + return null; + } + + public void SelectGender() + { + var types = new [] { "male", "female" }; + + var panel = new StackPanel { Margin = new Thickness(0.0, 12.0, 0.0, 0.0) }; + var messageBox = ShellViewModel.ShowCustomMessageBox( + null, AppResources.PassportSelectGender.ToUpperInvariant(), + null, null, + dismissed => + { + + }, + panel); + + for (var i = 0; i < types.Length; i++) + { + var listBoxItem = new ListBoxItem + { + Content = + new TextBlock + { + Text = GenderToStringConverter.Convert(types[i]), + FontSize = 27, + Margin = new Thickness(12.0) + }, + DataContext = types[i] + }; + TiltEffect.SetIsTiltEnabled(listBoxItem, true); + listBoxItem.Tap += (sender, args) => + { + messageBox.Dismiss(); + var item = sender as ListBoxItem; + if (item != null) + { + var gender = item.DataContext as string; + if (gender != null) + { + Gender = gender; + NotifyOfPropertyChange(() => Gender); + } + } + + }; + + panel.Children.Add(listBoxItem); + } + } + + public void SelectCountry() + { + StateService.HideCountryCode = true; + NavigationService.UriFor().Navigate(); + } + + private void OnCountrySelected(Country country) + { + SelectedCountry = country; + } + + public void SelectResidenceCountry() + { + StateService.HideCountryCode = true; + StateService.ResidenceCountry = true; + NavigationService.UriFor().Navigate(); + } + + private void OnResidenceCountrySelected(Country country) + { + SelectedResidenceCountry = country; + } + + public void SelectExpiryDate() + { + DateTime currentDate; + if (!DateTime.TryParse(ExpiryDate, out currentDate)) + { + currentDate = DateTime.Now.Date; + } + + var datePickerPage = new TelegramDatePickerPage(new YearDataSource { MaxYear = DateTime.Now.Year + 20, MinYear = 1900 }) { Height = 160.0, Value = currentDate, Margin = new Thickness(0.0, 18.0, 0.0, 6.0) }; + ShellViewModel.ShowCustomMessageBox(null, AppResources.PassportSelectDate.ToUpperInvariant(), AppResources.Ok.ToLowerInvariant(), AppResources.PassportSelectNotExpire, + result => + { + if (result == CustomMessageBoxResult.RightButton) + { + var selector = GetChildOfType(datePickerPage); + if (selector != null) + { + var value = ((DateTimeWrapper)selector.DataSource.SelectedItem).DateTime; + ExpiryDate = value.ToString("dd.MM.yyyy"); + NotifyOfPropertyChange(() => ExpiryDate); + } + } + else if (result == CustomMessageBoxResult.LeftButton) + { + ExpiryDate = string.Empty; + NotifyOfPropertyChange(() => ExpiryDate); + } + }, + datePickerPage); + } + + public ImageViewerViewModel ImageViewer { get; set; } + + public void OpenImageViewer() + { + if (ImageViewer == null) + { + ImageViewer = new ImageViewerViewModel(StateService, null, false, true) + { + //DialogDetails = this + }; + NotifyOfPropertyChange(() => ImageViewer); + } + BeginOnUIThread(() => ImageViewer.OpenViewer()); + } + + protected override void OnActivate() + { + if (StateService.SelectedCountry != null) + { + var country = StateService.SelectedCountry; + StateService.SelectedCountry = null; + OnCountrySelected(country); + } + + if (StateService.SelectedResidenceCountry != null) + { + var country = StateService.SelectedResidenceCountry; + StateService.SelectedResidenceCountry = null; + OnResidenceCountrySelected(country); + } + + EventAggregator.Subscribe(this); + base.OnActivate(); + } + + protected override void OnDeactivate(bool close) + { + EventAggregator.Unsubscribe(this); + base.OnDeactivate(close); + } + + public void Handle(UploadableItem item) + { + var secureFileUploaded = item.Owner as TLSecureFileUploaded; + if (secureFileUploaded != null) + { + Execute.BeginOnUIThread(() => + { + secureFileUploaded.UploadingProgress = 1.0; + secureFileUploaded.UploadingSize = (int)(secureFileUploaded.Size.Value * secureFileUploaded.UploadingProgress); + secureFileUploaded.Parts = new TLInt(item.Parts.Count); + NotifyOfPropertyChange(() => IsFileUploading); + }); + } + } + + public void Handle(UploadProgressChangedEventArgs args) + { + var secureFileUploaded = args.Item.Owner as TLSecureFileUploaded; + if (secureFileUploaded != null) + { + Execute.BeginOnUIThread(() => + { + secureFileUploaded.UploadingProgress = args.Progress; + secureFileUploaded.UploadingSize = (int)(secureFileUploaded.Size.Value * secureFileUploaded.UploadingProgress); + NotifyOfPropertyChange(() => IsFileUploading); + }); + } + } + } + + public class PersonalDetailsDocumentRootObject + { + public string document_no { get; set; } + public string expiry_date { get; set; } + + public IEnumerable Fields() + { + if (!string.IsNullOrEmpty(document_no)) yield return document_no; + if (!string.IsNullOrEmpty(expiry_date)) yield return expiry_date; + } + + public override string ToString() + { + return string.Join(", ", Fields()); + } + } + + [DataContract] + public class PersonalDetailsRootObject + { + [DataMember(EmitDefaultValue = false, Order = 1)] + public string first_name { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 2)] + public string middle_name { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 3)] + public string last_name { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 4)] + public string birth_date { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 5)] + public string gender { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 6)] + public string country_code { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 7)] + public string residence_country_code { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 8)] + public string first_name_native { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 9)] + public string middle_name_native { get; set; } + + [DataMember(EmitDefaultValue = false, Order = 10)] + public string last_name_native { get; set; } + + public IEnumerable Fields() + { + if (!string.IsNullOrEmpty(first_name)) yield return first_name; + if (!string.IsNullOrEmpty(middle_name)) yield return middle_name; + if (!string.IsNullOrEmpty(last_name)) yield return last_name; + if (!string.IsNullOrEmpty(birth_date)) yield return birth_date; + if (!string.IsNullOrEmpty(gender)) yield return gender; + if (!string.IsNullOrEmpty(country_code)) yield return country_code; + if (!string.IsNullOrEmpty(residence_country_code)) yield return residence_country_code; + if (!string.IsNullOrEmpty(first_name_native)) yield return first_name_native; + if (!string.IsNullOrEmpty(middle_name_native)) yield return middle_name_native; + if (!string.IsNullOrEmpty(last_name_native)) yield return last_name_native; + } + + public override string ToString() + { + return string.Join(", ", Fields()); + } + + public IEnumerable Fields(Func getGenderByCode, Func getCountryByCode) + { + if (!string.IsNullOrEmpty(first_name)) yield return first_name; + if (!string.IsNullOrEmpty(middle_name)) yield return middle_name; + if (!string.IsNullOrEmpty(last_name)) yield return last_name; + if (!string.IsNullOrEmpty(birth_date)) yield return birth_date; + if (!string.IsNullOrEmpty(gender)) yield return getGenderByCode(gender) ?? gender; + if (!string.IsNullOrEmpty(country_code)) yield return getCountryByCode(country_code) ?? country_code; + if (!string.IsNullOrEmpty(residence_country_code)) yield return getCountryByCode(residence_country_code) ?? residence_country_code; + if (!string.IsNullOrEmpty(first_name_native)) yield return first_name_native; + if (!string.IsNullOrEmpty(middle_name_native)) yield return middle_name_native; + if (!string.IsNullOrEmpty(last_name_native)) yield return last_name_native; + } + + public string ToString(Func getGenderByCode, Func getCountryByCode) + { + return string.Join(", ", Fields(getGenderByCode, getCountryByCode)); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/ViewModels/Passport/PhoneNumberCodeViewModel.cs b/TelegramClient.WP81/ViewModels/Passport/PhoneNumberCodeViewModel.cs new file mode 100755 index 0000000..bf41cc3 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Passport/PhoneNumberCodeViewModel.cs @@ -0,0 +1,443 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Windows; +using System.Windows.Threading; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Converters; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Additional; + +namespace TelegramClient.ViewModels.Passport +{ + public class PhoneNumberCodeViewModel : ViewModelBase + { + private DateTime _startTime; + + private readonly DispatcherTimer _callTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0.5) }; + + private int _timeCounter = Constants.SendCallDefaultTimeout; + + public int TimeCounter + { + get { return _timeCounter; } + set { SetField(ref _timeCounter, value, () => TimeCounter); } + } + + private string _timeCounterString = " "; + + public string TimeCounterString + { + get { return _timeCounterString; } + set { SetField(ref _timeCounterString, value, () => TimeCounterString); } + } + + private string _code; + + public string Code + { + get { return _code; } + set { SetField(ref _code, value, () => Code); } + } + + private Visibility _helpVisibility = Visibility.Collapsed; + + public Visibility HelpVisibility + { + get { return _helpVisibility; } + set { SetField(ref _helpVisibility, value, () => HelpVisibility); } + } + + private Visibility _resendCodeVisibility = Visibility.Collapsed; + + public Visibility ResendCodeVisibility + { + get { return _resendCodeVisibility; } + set { SetField(ref _resendCodeVisibility, value, () => ResendCodeVisibility); } + } + + public string Subtitle { get; set; } + + public TLInt Timeout { get; set; } + + public int CodeLength { get; set; } + + private TLSentCodeTypeBase _type; + + private TLCodeTypeBase _nextType; + + public string Caption + { + get { return TLString.IsNullOrEmpty(StateService.PhoneNumber) ? null : "+" + StateService.PhoneNumber; } + } + + private readonly TLSecureValue _phoneNumberValue; + + private readonly TLPasswordBase _passwordBase; + + private readonly TLAuthorizationForm _authorizationForm; + + private readonly IList _secureValues; + + private readonly TLSecureValueTypeBase _secureType; + + private readonly SecureRequiredType _secureRequiredType; + + public PhoneNumberCodeViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _passwordBase = stateService.Password; + stateService.Password = null; + + _authorizationForm = stateService.AuthorizationForm; + stateService.AuthorizationForm = null; + + _secureValues = stateService.SecureValues; + stateService.SecureValues = null; + + _secureType = stateService.SecureType; + stateService.SecureType = null; + + _secureRequiredType = stateService.SecureRequiredType; + stateService.SecureRequiredType = null; + + _phoneNumberValue = _secureRequiredType != null ? _secureRequiredType.DataValue : null; + + _type = stateService.Type; + stateService.Type = null; + + _nextType = stateService.NextType; + stateService.NextType = null; + + Subtitle = GetSubtitle(); + + var length = _type as ILength; + CodeLength = length != null ? length.Length.Value : Constants.DefaultCodeLength; + + Timeout = stateService.SendCallTimeout; + ResendCodeVisibility = stateService.SendCallTimeout != null && stateService.SendCallTimeout.Value > 0 + ? Visibility.Collapsed + : Visibility.Visible; + + SuppressUpdateStatus = true; + + EventAggregator.Subscribe(this); + + PropertyChanged += (sender, args) => + { + if (Property.NameEquals(args.PropertyName, () => Code)) + { + NotifyOfPropertyChange(() => CanConfirm); + + if (!string.IsNullOrEmpty(Code) && Code.Length == CodeLength) + { + Confirm(); + } + } + }; + + _callTimer.Tick += (sender, args) => + { + _timeCounter = Timeout == null? 0 : (int)(Timeout.Value - (DateTime.Now - _startTime).TotalSeconds); + + if (_timeCounter > 0) + { +#if DEBUG + TimeCounterString = _timeCounter.ToString(CultureInfo.InvariantCulture); +#endif + + if (_nextType is TLCodeTypeCall) + { + TimeCounterString = string.Format(AppResources.WeWillCallYou, TimeSpan.FromSeconds(TimeCounter).ToString(@"m\:ss")); + } + } + else + { + _timeCounter = 0; + if (_nextType is TLCodeTypeCall) + { + TimeCounterString = AppResources.TelegramDialedYourNumber; + } + + HelpVisibility = Visibility.Visible; + ResendCodeVisibility = Visibility.Visible; + _callTimer.Stop(); + } + + NotifyOfPropertyChange(() => TimeCounter); + }; + } + + private bool _isResending; + + public void Resend() + { + if (_isResending) + { + return; + } + + if (_nextType == null) + { + return; + } + + _isResending = true; + IsWorking = true; + MTProtoService.ResendCodeAsync(StateService.PhoneNumber, StateService.PhoneCodeHash, + sentCode => BeginOnUIThread(() => + { + _isResending = false; + IsWorking = false; + + StateService.PhoneCodeHash = sentCode.PhoneCodeHash; + StateService.PhoneRegistered = sentCode.PhoneRegistered; + + Timeout = sentCode.SendCallTimeout; + ResendCodeVisibility = Timeout != null && Timeout.Value > 0 + ? Visibility.Collapsed + : Visibility.Visible; + + var sentCode50 = sentCode as TLSentCode50; + if (sentCode50 != null) + { + _type = sentCode50.Type; + _nextType = sentCode50.NextType; + + Subtitle = GetSubtitle(); + NotifyOfPropertyChange(() => Subtitle); + + var length = _type as ILength; + CodeLength = length != null ? length.Length.Value : Constants.DefaultCodeLength; + NotifyOfPropertyChange(() => CodeLength); + } + + _startTime = DateTime.Now; + _callTimer.Start(); + }), + error => BeginOnUIThread(() => + { + _isResending = false; + IsWorking = false; + Telegram.Api.Helpers.Execute.ShowDebugMessage("auth.resendCode error " + error); + })); + } + + private string GetSubtitle() + { + if (_type is TLSentCodeTypeApp) + { + return AppResources.CodeSentToTelegramApp; + } + + if (_type is TLSentCodeTypeSms) + { + return string.Format(AppResources.ConfirmMessage, PhoneNumberConverter.Convert(StateService.PhoneNumber)); + } + + if (_type is TLSentCodeTypeCall) + { + return string.Format(AppResources.CodeSentViaCallingPhone, PhoneNumberConverter.Convert(StateService.PhoneNumber)); + } + + return string.Empty; + } + + public bool CanConfirm + { + get { return !string.IsNullOrEmpty(Code); } + } + + public void Confirm() + { + IsWorking = true; + StateService.PhoneCode = new TLString(Code); + MTProtoService.VerifyPhoneAsync( + StateService.PhoneNumber, + StateService.PhoneCodeHash, + StateService.PhoneCode, + auth => BeginOnUIThread(() => + { + TimeCounterString = string.Empty; + HelpVisibility = Visibility.Collapsed; + _callTimer.Stop(); + + _isProcessing = false; + + var phoneNumberValue = _phoneNumberValue; + if (phoneNumberValue == null) + { + var secureRequiredType = _secureRequiredType != null ? _secureRequiredType.DataRequiredType as TLSecureRequiredType : null; + var secureType = secureRequiredType != null && PhoneNumberViewModel.IsValidType(secureRequiredType.Type) + ? secureRequiredType.Type + : null; + + // add new phone number from passport settings + if (_secureType != null && PhoneNumberViewModel.IsValidType(_secureType)) + { + phoneNumberValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = _secureType + }; + } + // add new phone number from authorization form + else if (secureType != null) + { + phoneNumberValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = secureType + }; + } + else + { + return; + } + } + + IsWorking = + PhoneNumberViewModel.SavePhoneAsync( + StateService.PhoneNumber, _passwordBase as TLPassword, MTProtoService, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + if (_authorizationForm != null) + { + _authorizationForm.Values.Remove(_phoneNumberValue); + _authorizationForm.Values.Add(result); + } + + phoneNumberValue.Update(result); + phoneNumberValue.NotifyOfPropertyChange(() => phoneNumberValue.Self); + + if (_secureType != null) + { + EventAggregator.Publish(new AddSecureValueEventArgs { Values = new List { phoneNumberValue } }); + } + + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + + NavigationService.RemoveBackEntry(); + NavigationService.GoBack(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + + if (error.CodeEquals(ErrorCode.BAD_REQUEST) + && error.TypeEquals(ErrorType.PHONE_VERIFICATION_NEEDED)) + { + MTProtoService.SendVerifyPhoneCodeAsync(StateService.PhoneNumber, null, + sentCode => BeginOnUIThread(() => + { + StateService.PhoneCodeHash = sentCode.PhoneCodeHash; + StateService.PhoneRegistered = sentCode.PhoneRegistered; + + Timeout = sentCode.SendCallTimeout; + ResendCodeVisibility = Timeout != null && Timeout.Value > 0 + ? Visibility.Collapsed + : Visibility.Visible; + + var sentCode50 = sentCode as TLSentCode50; + if (sentCode50 != null) + { + _type = sentCode50.Type; + _nextType = sentCode50.NextType; + + Subtitle = GetSubtitle(); + NotifyOfPropertyChange(() => Subtitle); + + var length = _type as ILength; + CodeLength = length != null ? length.Length.Value : Constants.DefaultCodeLength; + NotifyOfPropertyChange(() => CodeLength); + } + }), + error2 => BeginOnUIThread(() => + { + if (error.TypeEquals(ErrorType.PHONE_NUMBER_INVALID)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PhoneNumberInvalidString, AppResources.Error, AppResources.Ok); + } + else if (error.CodeEquals(ErrorCode.FLOOD)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.FloodWaitString + Environment.NewLine + "(" + error.Message + ")", AppResources.Error, AppResources.Ok); + } + else + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("account.sendVerifyPhoneCode error " + error); + } + })); + } + })); + }), + error => BeginOnUIThread(() => + { + IsWorking = false; + if (error.TypeEquals(ErrorType.PHONE_CODE_INVALID)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PhoneCodeInvalidString, AppResources.Error, AppResources.Ok); + } + else if (error.TypeEquals(ErrorType.PHONE_CODE_EMPTY)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PhoneCodeEmpty, AppResources.Error, AppResources.Ok); + } + else if (error.TypeEquals(ErrorType.PHONE_NUMBER_INVALID)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PhoneNumberInvalidString, AppResources.Error, AppResources.Ok); + } + else if (error.CodeEquals(ErrorCode.FLOOD)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.FloodWaitString + Environment.NewLine + "(" + error.Message + ")", AppResources.Error, AppResources.Ok); + } + else + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("account.verifyPhone error " + error); + } + })); + } + + private bool _isProcessing; + + protected override void OnActivate() + { + if (_isProcessing) return; + + _isProcessing = true; + + Subtitle = GetSubtitle(); + + if (Timeout != null) + { + TimeCounter = Timeout.Value; + } + _startTime = DateTime.Now; + _callTimer.Start(); + + base.OnActivate(); + } + + public void OnBackKeyPress() + { + _isProcessing = false; + Code = string.Empty; + _callTimer.Stop(); + TimeCounterString = " "; +#if DEBUG + HelpVisibility = Visibility.Visible; +#else + HelpVisibility = Visibility.Collapsed; +#endif + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Passport/PhoneNumberViewModel.cs b/TelegramClient.WP81/ViewModels/Passport/PhoneNumberViewModel.cs new file mode 100755 index 0000000..0973e90 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Passport/PhoneNumberViewModel.cs @@ -0,0 +1,333 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Converters; +using TelegramClient.Models; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Additional; + +namespace TelegramClient.ViewModels.Passport +{ + public class PhoneNumberViewModel : ViewModelBase + { + private Country _selectedCountry; + + public Country SelectedCountry + { + get { return _selectedCountry; } + set { SetField(ref _selectedCountry, value, () => SelectedCountry); } + } + + public bool IsPhoneCodeInvalid + { + get { return string.IsNullOrEmpty(PhoneCode) || CountryUtils.CountriesSource.FirstOrDefault(x => x.PhoneCode == PhoneCode) == null; } + } + + private string _phoneCode; + + public string PhoneCode + { + get { return _phoneCode; } + set + { + SetField(ref _phoneCode, value, () => PhoneCode); + Country country = null; + foreach (var c in CountryUtils.CountriesSource) + { + if (c.PhoneCode == PhoneCode) + { + if (c.PhoneCode == "1" && c.Code != "us") + { + continue; + } + + if (c.PhoneCode == "7" && c.Code != "ru") + { + continue; + } + + country = c; + break; + } + } + + if (country != null) + { + SelectedCountry = country; + } + + NotifyOfPropertyChange(() => IsPhoneCodeInvalid); + } + } + + private string _phoneNumber; + + public string PhoneNumber + { + get { return _phoneNumber; } + set { SetField(ref _phoneNumber, value, () => PhoneNumber); } + } + + public string UseCurrentPhoneCommand + { + get { return string.Format(AppResources.PassportPhoneUseSame, "+" + CurrentPhone); } + } + + public string CurrentPhone { get; set; } + + public TLRPCError Error { get; set; } + + public static bool IsValidType(TLSecureValueTypeBase type) + { + return type is TLSecureValueTypePhone; + } + + private readonly TLSecureValue _phoneNumberValue; + + private readonly TLPasswordBase _passwordBase; + + private readonly TLAuthorizationForm _authorizationForm; + + private readonly IList _secureValues; + + private readonly TLSecureValueTypeBase _secureType; + + private readonly SecureRequiredType _secureRequiredType; + + public PhoneNumberViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _passwordBase = stateService.Password; + stateService.Password = null; + + _authorizationForm = stateService.AuthorizationForm; + stateService.AuthorizationForm = null; + + _secureValues = stateService.SecureValues; + stateService.SecureValues = null; + + _secureType = stateService.SecureType; + stateService.SecureType = null; + + _secureRequiredType = stateService.SecureRequiredType; + stateService.SecureRequiredType = null; + + var user = CacheService.GetUser(new TLInt(StateService.CurrentUserId)); + if (user != null && user.HasPhone) + { + CurrentPhone = user.Phone.ToString(); + } + + _phoneNumberValue = _secureRequiredType != null ? _secureRequiredType.DataValue : null; + } + + protected override void OnActivate() + { + if (StateService.SelectedCountry != null) + { + var country = StateService.SelectedCountry; + StateService.SelectedCountry = null; + OnCountrySelected(country); + } + base.OnActivate(); + } + + public void SelectCountry() + { + StateService.HideCountryCode = true; + NavigationService.UriFor().Navigate(); + } + + private void OnCountrySelected(Country country) + { + SelectedCountry = country; + _phoneCode = SelectedCountry.PhoneCode; + NotifyOfPropertyChange(() => PhoneCode); + } + + public void UseCurrentPhone() + { + if (!IsPhoneNumberValid(CurrentPhone)) return; + + SavePhoneAsync(new TLString(CurrentPhone)); + } + + public void Done() + { + if (!IsPhoneNumberValid(PhoneCode + PhoneNumber)) return; + if (IsWorking) return; + + SavePhoneAsync(new TLString(PhoneCode + PhoneNumber)); + } + + public bool IsPhoneNumberValid(string phoneNumber) + { + var phoneNumberLength = string.IsNullOrEmpty(phoneNumber) ? 0 : phoneNumber.Length; + return !IsWorking && phoneNumberLength >= 3; + } + + public static bool SavePhoneAsync(TLString phone, TLPassword password, IMTProtoService mtProtoService, Action callback, Action faultCallback = null) + { + if (password == null) + { + return false; + } + + var passwordSettings = password.Settings as TLPasswordSettings83; + if (passwordSettings == null) + { + return false; + } + + var inputSecureValue = new TLInputSecureValue85 + { + Flags = new TLInt(0), + Type = new TLSecureValueTypePhone(), + PlainData = new TLSecurePlainPhone { Phone = phone } + }; + + var secureSecretId = passwordSettings.SecureSettings.SecureSecretId; + + mtProtoService.SaveSecureValueAsync( + inputSecureValue, secureSecretId, + callback.SafeInvoke, + faultCallback.SafeInvoke); + + return true; + } + + private void SavePhoneAsync(TLString phone) + { + var phoneNumberValue = _phoneNumberValue; + if (phoneNumberValue == null) + { + var secureRequiredType = _secureRequiredType != null ? _secureRequiredType.DataRequiredType as TLSecureRequiredType : null; + var secureType = secureRequiredType != null && IsValidType(secureRequiredType.Type) + ? secureRequiredType.Type + : null; + + // add new phone number from passport settings + if (_secureType != null && IsValidType(_secureType)) + { + phoneNumberValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = _secureType + }; + } + // add new phone number from authorization form + else if (secureType != null) + { + phoneNumberValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = secureType + }; + } + else + { + return; + } + } + + IsWorking = + SavePhoneAsync( + phone, _passwordBase as TLPassword, MTProtoService, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + if (_authorizationForm != null) + { + _authorizationForm.Values.Remove(phoneNumberValue); + _authorizationForm.Values.Add(result); + } + + phoneNumberValue.Update(result); + phoneNumberValue.NotifyOfPropertyChange(() => phoneNumberValue.Self); + + if (_secureType != null) + { + EventAggregator.Publish(new AddSecureValueEventArgs { Values = new List { phoneNumberValue } }); + } + + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + + NavigationService.GoBack(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + + if (error.CodeEquals(ErrorCode.BAD_REQUEST) + && error.TypeEquals(ErrorType.PHONE_VERIFICATION_NEEDED)) + { + MTProtoService.SendVerifyPhoneCodeAsync(phone, null, + result2 => BeginOnUIThread(() => + { + StateService.PhoneNumber = phone; + StateService.PhoneNumberString = string.Format(AppResources.ConfirmMessage, PhoneNumberConverter.Convert(StateService.PhoneNumber)); + StateService.PhoneCodeHash = result2.PhoneCodeHash; + StateService.PhoneRegistered = result2.PhoneRegistered; + StateService.SendCallTimeout = result2.SendCallTimeout; + var sentCode50 = result2 as TLSentCode50; + if (sentCode50 != null) + { + StateService.Type = sentCode50.Type; + StateService.NextType = sentCode50.NextType; + } + StateService.Password = _passwordBase; + StateService.AuthorizationForm = _authorizationForm; + StateService.SecureValues = _secureValues; + StateService.SecureType = _secureType; + StateService.SecureRequiredType = _secureRequiredType; + NavigationService.UriFor().Navigate(); + }), + error2 => BeginOnUIThread(() => + { + if (error.TypeEquals(ErrorType.PHONE_NUMBER_INVALID)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PhoneNumberInvalidString, AppResources.Error, AppResources.Ok); + } + else if (error.CodeEquals(ErrorCode.FLOOD)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.FloodWaitString + Environment.NewLine + "(" + error.Message + ")", AppResources.Error, AppResources.Ok); + } + else + { + Telegram.Api.Helpers.Execute.ShowDebugMessage("account.sendVerifyPhoneCode error " + error); + } + })); + } + else if (error.TypeEquals(ErrorType.PHONE_NUMBER_INVALID)) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PhoneNumberInvalidString, AppResources.Error, AppResources.Ok); + } + else if (error.CodeEquals(ErrorCode.BAD_REQUEST)) + { + ShellViewModel.ShowCustomMessageBox( + "account.saveSecureValue" + Environment.NewLine + error.Message, + AppResources.AppName, + AppResources.Ok); + } + })); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Passport/ResidentialAddressViewModel.cs b/TelegramClient.WP81/ViewModels/Passport/ResidentialAddressViewModel.cs new file mode 100755 index 0000000..e63002d --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Passport/ResidentialAddressViewModel.cs @@ -0,0 +1,1550 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.IO.IsolatedStorage; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using Windows.Storage; +using Windows.Storage.Pickers; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.Services.FileManager; +using Telegram.Api.TL; +using TelegramClient.Models; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.Utils; +using TelegramClient.ViewModels.Additional; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.ViewModels.Media; +using TelegramClient.Views.Additional; +using Execute = Telegram.Api.Helpers.Execute; + +namespace TelegramClient.ViewModels.Passport +{ + public class ResidentialAddressViewModel : ViewModelBase, Telegram.Api.Aggregator.IHandle, Telegram.Api.Aggregator.IHandle + { + public ObservableCollection Errors { get; protected set; } + + private string _streetLine1; + + public string StreetLine1 + { + get { return _streetLine1; } + set + { + if (_streetLine1 != value) + { + _streetLine1 = value; + if (!string.IsNullOrEmpty(StreetLine1Error)) + { + StreetLine1Error = null; + NotifyOfPropertyChange(() => StreetLine1Error); + } + } + } + } + + public string StreetLine1Error { get; set; } + + private string _streetLine2; + + public string StreetLine2 + { + get { return _streetLine2; } + set + { + if (_streetLine2 != value) + { + _streetLine2 = value; + if (!string.IsNullOrEmpty(StreetLine2Error)) + { + StreetLine2Error = null; + NotifyOfPropertyChange(() => StreetLine2Error); + } + } + } + } + + public string StreetLine2Error { get; set; } + + private string _postCode; + + public string PostCode + { + get { return _postCode; } + set + { + if (_postCode != value) + { + _postCode = value; + if (!Utils.Passport.IsValidPostCode(_postCode)) + { + PostCodeError = AppResources.PassportUseLatinOnly; + NotifyOfPropertyChange(() => PostCodeError); + } + else if (!string.IsNullOrEmpty(PostCodeError)) + { + PostCodeError = null; + NotifyOfPropertyChange(() => PostCodeError); + } + } + } + } + + public string PostCodeError { get; set; } + + private string _city; + + public string City + { + get { return _city; } + set + { + if (_city != value) + { + _city = value; + if (!string.IsNullOrEmpty(CityError)) + { + CityError = null; + NotifyOfPropertyChange(() => CityError); + } + } + } + } + + public string CityError { get; set; } + + private string _state; + + public string State + { + get { return _state; } + set + { + if (_state != value) + { + _state = value; + if (!string.IsNullOrEmpty(StateError)) + { + StateError = null; + NotifyOfPropertyChange(() => StateError); + } + } + } + } + + public string StateError { get; set; } + + private Country _selectedCountry; + + public Country SelectedCountry + { + get { return _selectedCountry; } + set + { + if (_selectedCountry != value) + { + SetField(ref _selectedCountry, value, () => SelectedCountry); + if (!string.IsNullOrEmpty(SelectedCountryError)) + { + SelectedCountryError = null; + NotifyOfPropertyChange(() => SelectedCountryError); + } + } + } + } + + public string SelectedCountryError { get; set; } + + public string FilesError { get; set; } + + public string TranslationsError { get; set; } + + public TLRPCError Error { get; set; } + + public string Caption + { + get + { + if (_secureType != null) + { + return SecureRequiredTypeToCaptionConverter.Convert(_secureType); + } + if (_dataProofValue != null) + { + return SecureRequiredTypeToCaptionConverter.Convert(_dataProofValue.Type); + } + if (_dataValue != null) + { + return SecureRequiredTypeToCaptionConverter.Convert(_dataValue.Type); + } + if (_secureRequiredType != null) + { + var type = _secureRequiredType.SelectedDataProofRequiredType; + if (type != null) + { + return SecureRequiredTypeToCaptionConverter.Convert(type.Type); + } + } + //if (_authorizationForm != null) + //{ + // var type = _authorizationForm.RequiredTypes.FirstOrDefault(IsValidProofType); + // if (type != null) + // { + // return SecureRequiredTypeToCaptionConverter.Convert(type); + // } + //} + + return AppResources.PassportResidentialAddress; + } + } + + public string AttachDocumentHint + { + get + { + TLSecureValueTypeBase type = null; + if (_secureType != null) + { + type = _secureType; + } + else if (_dataProofValue != null) + { + type = _dataProofValue.Type; + } + else if (_secureRequiredType != null && _secureRequiredType.SelectedDataProofRequiredType != null) + { + type = _secureRequiredType.SelectedDataProofRequiredType.Type; + } + //else if (_authorizationForm != null) + //{ + // type = _authorizationForm.RequiredTypes.FirstOrDefault(IsValidProofType); + //} + + if (type != null) + { + if (type is TLSecureValueTypeUtilityBill) + { + return AppResources.PassportAddBillInfo; + } + if (type is TLSecureValueTypeBankStatement) + { + return AppResources.PassportAddBankInfo; + } + if (type is TLSecureValueTypeRentalAgreement) + { + return AppResources.PassportAddAgreementInfo; + } + if (type is TLSecureValueTypePassportRegistration) + { + return AppResources.PassportAddPassportRegistrationInfo; + } + if (type is TLSecureValueTypeTemporaryRegistration) + { + return AppResources.PassportAddTemporaryRegistrationInfo; + } + } + + return null; + } + } + + public string AttachDocumentCommand + { + get + { + if (Files.Count > 0) + { + return AppResources.PassportUploadAdditinalDocument; + } + + return AppResources.PassportUploadDocument; + } + } + + public string DeleteCommand + { + get + { + if (_dataValue != null && _dataProofValue == null) + { + return AppResources.PassportDelete; + } + + return AppResources.PassportDeleteDocument; + } + } + + public ObservableCollection Files { get; set; } + + public string AttachTranslationHint + { + get + { + TLSecureValueTypeBase type = null; + if (_secureType != null) + { + type = _secureType; + } + else if (_dataProofValue != null) + { + type = _dataProofValue.Type; + } + else if (_secureRequiredType != null && _secureRequiredType.SelectedDataProofRequiredType != null) + { + type = _secureRequiredType.SelectedDataProofRequiredType.Type; + } + //else if (_authorizationForm != null) + //{ + // type = _authorizationForm.RequiredTypes.FirstOrDefault(IsValidProofType); + //} + + if (type != null) + { + if (type is TLSecureValueTypeUtilityBill) + { + return AppResources.PassportAddTranslationBillInfo; + } + if (type is TLSecureValueTypeBankStatement) + { + return AppResources.PassportAddTranslationBankInfo; + } + if (type is TLSecureValueTypeRentalAgreement) + { + return AppResources.PassportAddTranslationAgreementInfo; + } + if (type is TLSecureValueTypePassportRegistration) + { + return AppResources.PassportAddTranslationPassportRegistrationInfo; + } + if (type is TLSecureValueTypeTemporaryRegistration) + { + return AppResources.PassportAddTranslationTemporaryRegistrationInfo; + } + } + + return AppResources.PassportAddTranslationUploadInfo; + } + } + + public string AttachTranslationCommand + { + get + { + if (Translations.Count > 0) + { + return AppResources.PassportUploadAdditinalDocument; + } + + return AppResources.PassportUploadDocument; + } + } + + public ObservableCollection Translations { get; set; } + + public bool IsFileUploading + { + get + { + foreach (var file in Files) + { + if (file.UploadingProgress > 0.0 && file.UploadingProgress < 1.0) + { + return true; + } + } + + foreach (var file in Translations) + { + if (file.UploadingProgress > 0.0 && file.UploadingProgress < 1.0) + { + return true; + } + } + + return false; + } + } + + public bool IsDataProofEnabled + { + get + { + if (_secureRequiredType != null && _secureRequiredType.SelectedDataProofRequiredType != null) + { + return IsValidProofType(_secureRequiredType.SelectedDataProofRequiredType.Type); + } + //if (_authorizationForm != null) + //{ + // return _authorizationForm.RequiredTypes.Any(IsValidProofType); + //} + if (_secureType != null) + { + return IsValidProofType(_secureType); + } + + return _dataProofValue != null; + } + } + + public bool IsDataProofTranslationEnabled + { + get + { + if (_secureRequiredType != null && _secureRequiredType.SelectedDataProofRequiredType != null) + { + return _secureRequiredType.SelectedDataProofRequiredType.TranslationRequired; + } + if (_secureType != null) + { + return false; // Important: default value from Passport Settings page + } + if (_dataProofValue != null && _secureRequiredType == null) + { + return false; // Important: default value from Passport Settings page + } + if (_dataProofValue != null) + { + return true; + } + + return false; + } + } + + public bool IsDataEnabled + { + get + { + if (_secureRequiredType != null) + { + return _secureRequiredType.DataRequiredType != null; + } + //if (_authorizationForm != null) + //{ + // return _authorizationForm.RequiredTypes.Any(IsValidDataType); + //} + if (_secureType != null) + { + return IsValidDataType(_secureType); + } + + return _dataValue != null; + } + } + + public bool IsDeleteEnabled + { + get { return _dataValue != null || _dataProofValue != null; } + } + + public static bool IsValidType(TLSecureValueTypeBase type) + { + return IsValidDataType(type) + || IsValidProofType(type); + } + + public static bool IsValidDataType(TLSecureValueTypeBase type) + { + return type is TLSecureValueTypeAddress; + } + + public static bool IsValidProofType(TLSecureValueTypeBase type) + { + return type is TLSecureValueTypeUtilityBill + || type is TLSecureValueTypeBankStatement + || type is TLSecureValueTypeRentalAgreement + || type is TLSecureValueTypePassportRegistration + || type is TLSecureValueTypeTemporaryRegistration; + } + + private readonly TLAuthorizationForm _authorizationForm; + + private readonly TLPasswordBase _passwordBase; + + private readonly TLSecureValue _dataValue; + + private readonly TLSecureValue _dataProofValue; + + private readonly TLSecureValueTypeBase _secureType; + + private readonly SecureRequiredType _secureRequiredType; + + public ResidentialAddressViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + Errors = new ObservableCollection(); + + Translations = new ObservableCollection(); + Translations.CollectionChanged += (sender, args) => + { + NotifyOfPropertyChange(() => AttachTranslationCommand); + }; + + Files = new ObservableCollection(); + Files.CollectionChanged += (sender, args) => + { + NotifyOfPropertyChange(() => AttachDocumentCommand); + }; + + _authorizationForm = stateService.AuthorizationForm; + stateService.AuthorizationForm = null; + + _passwordBase = stateService.Password; + stateService.Password = null; + + var secureValue = StateService.SecureValue; + StateService.SecureValue = null; + + _secureType = StateService.SecureType; + StateService.SecureType = null; + + _secureRequiredType = StateService.SecureRequiredType; + StateService.SecureRequiredType = null; + + _dataValue = GetData(_secureRequiredType, secureValue); + if (_dataValue != null && _dataValue.Data != null) + { + var rootObject = _dataValue.Data.DecryptedData as ResidentialAddressRootObject; + if (rootObject != null) + { + _streetLine1 = rootObject.street_line1; + _streetLine2 = rootObject.street_line2; + _postCode = rootObject.post_code; + _city = rootObject.city; + _state = rootObject.state; + if (!string.IsNullOrEmpty(rootObject.country_code)) + { + var country = CountryUtils.CountriesSource.FirstOrDefault(x => string.Equals(rootObject.country_code, x.Code, StringComparison.OrdinalIgnoreCase)); + _selectedCountry = country; + } + } + } + + _dataProofValue = GetDataProof(_secureRequiredType, secureValue); + if (_dataProofValue != null) + { + foreach (var file in _dataProofValue.Files) + { + Files.Add(file); + } + } + var dataProofValue85 = _dataProofValue as TLSecureValue85; + if (dataProofValue85 != null && dataProofValue85.Translation != null) + { + Translations.Clear(); + foreach (var translation in dataProofValue85.Translation) + { + Translations.Add(translation); + } + } + + + GetErrors(_authorizationForm); + } + + private bool HasErrors() + { + if (IsDataProofEnabled) + { + if (Files != null && Files.Count > 0) + { + foreach (var file in Files.OfType()) + { + if (!string.IsNullOrEmpty(file.Error)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.FILE_ERROR.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + } + } + else + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.FILES_EMPTY.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(FilesError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.FILES_EMPTY.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (IsDataProofTranslationEnabled) + { + if (Translations != null && Translations.Count > 0) + { + foreach (var file in Translations.OfType()) + { + if (!string.IsNullOrEmpty(file.Error)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) + { + Message = new TLString(ErrorType.TRANSLATION_ERROR.ToString()) + }; + NotifyOfPropertyChange(() => Error); + return true; + } + } + } + else + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.TRANSLATION_EMPTY.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(TranslationsError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.TRANSLATION_EMPTY.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + } + } + + if (IsDataEnabled) + { + if (string.IsNullOrEmpty(StreetLine1) || !string.IsNullOrEmpty(StreetLine1Error)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.ADDRESS_STREET_LINE1_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(StreetLine2Error)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.ADDRESS_STREET_LINE2_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (string.IsNullOrEmpty(PostCode) || !string.IsNullOrEmpty(PostCodeError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.ADDRESS_POSTCODE_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (string.IsNullOrEmpty(City) || !string.IsNullOrEmpty(CityError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.ADDRESS_CITY_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (!string.IsNullOrEmpty(StateError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.ADDRESS_STATE_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + + if (_selectedCountry == null || !string.IsNullOrEmpty(SelectedCountryError)) + { + Error = new TLRPCError((int)ErrorCode.BAD_REQUEST) { Message = new TLString(ErrorType.ADDRESS_COUNTRY_INVALID.ToString()) }; + NotifyOfPropertyChange(() => Error); + return true; + } + } + + Error = null; + NotifyOfPropertyChange(() => Error); + return false; + } + + private void GetErrors(TLAuthorizationForm form) + { + if (form == null) return; + if (form.Errors == null || form.Errors.Count == 0) return; + + var dataFieldAction = new Dictionary> + { + {"street_line1", error => { StreetLine1Error = error.Text.ToString(); }}, + {"street_line2", error => { StreetLine2Error = error.Text.ToString(); }}, + {"post_code", error => { PostCodeError = error.Text.ToString(); }}, + {"state", error => { StateError = error.Text.ToString(); }}, + {"city", error => { CityError = error.Text.ToString(); }}, + {"country_code", error => { SelectedCountryError = error.Text.ToString(); }} + }; + + var errorTypeAction = new Dictionary> + { + { + typeof(TLSecureValueError), errorBase => + { + var error = errorBase as TLSecureValueError; + if (error != null) + { + if (_secureRequiredType != null) + { + if (_secureRequiredType.DataRequiredType != null + && _secureRequiredType.DataRequiredType.Type.GetType() == error.Type.GetType()) + { + Errors.Add(error.Text.ToString()); + } + else if (_secureRequiredType.SelectedDataProofRequiredType != null + && _secureRequiredType.SelectedDataProofRequiredType.Type.GetType() == error.Type.GetType()) + { + Errors.Add(error.Text.ToString()); + } + } + } + } + }, + { + typeof(TLSecureValueErrorData), errorBase => + { + var error = errorBase as TLSecureValueErrorData; + if (error != null) + { + Action fieldAction; + if (dataFieldAction.TryGetValue(error.Field.ToString(), out fieldAction)) + { + fieldAction.SafeInvoke(error); + } + } + } + }, + { + typeof(TLSecureValueErrorFile), errorBase => + { + var error = errorBase as TLSecureValueErrorFile; + if (error != null) + { + foreach (var file in Files.OfType()) + { + if (TLString.Equals(file.FileHash, error.FileHash, StringComparison.OrdinalIgnoreCase)) + { + file.Error = error.Text.ToString(); + break; + } + } + } + } + }, + { + typeof(TLSecureValueErrorFiles), errorBase => + { + var error = errorBase as TLSecureValueErrorFiles; + if (error != null) + { + FilesError = error.Text.ToString(); + } + } + }, + { + typeof(TLSecureValueErrorTranslationFile), errorBase => + { + var error = errorBase as TLSecureValueErrorTranslationFile; + if (error != null) + { + foreach (var file in Translations.OfType()) + { + if (TLString.Equals(file.FileHash, error.FileHash, StringComparison.OrdinalIgnoreCase)) + { + file.Error = error.Text.ToString(); + break; + } + } + } + } + }, + { + typeof(TLSecureValueErrorTranslationFiles), errorBase => + { + var error = errorBase as TLSecureValueErrorTranslationFiles; + if (error != null) + { + TranslationsError = error.Text.ToString(); + } + } + } + }; + + Errors.Clear(); + foreach (var error in _authorizationForm.Errors) + { + Action action; + if ((_dataValue != null && _dataValue.Type.GetType() == error.Type.GetType() + || _dataProofValue != null && _dataProofValue.Type.GetType() == error.Type.GetType()) + && errorTypeAction.TryGetValue(error.GetType(), out action)) + { + action.SafeInvoke(error); + } + } + } + + private void RemoveDataErrors() + { + if (_authorizationForm != null && _authorizationForm.Errors != null) + { + for (var i = 0; i < _authorizationForm.Errors.Count; i++) + { + var error = _authorizationForm.Errors[i]; + if (error != null && IsValidDataType(error.Type)) + { + _authorizationForm.Errors.RemoveAt(i--); + } + } + } + } + + private void RemoveProofErrors() + { + if (_authorizationForm != null && _authorizationForm.Errors != null) + { + for (var i = 0; i < _authorizationForm.Errors.Count; i++) + { + var error = _authorizationForm.Errors[i]; + if (error != null && IsValidProofType(error.Type)) + { + _authorizationForm.Errors.RemoveAt(i--); + } + } + } + } + + private TLSecureValue GetData(SecureRequiredType requiredType, TLSecureValue secureValue) + { + if (requiredType != null) + { + return requiredType.DataValue; + } + + return secureValue != null && IsValidDataType(secureValue.Type) ? secureValue : null; + } + + private TLSecureValue GetDataProof(SecureRequiredType requiredType, TLSecureValue secureValue) + { + if (requiredType != null) + { + return requiredType.DataProofValue; + } + + return secureValue != null && IsValidProofType(secureValue.Type) ? secureValue : null; + } + + public void AttachTranslation() + { + if (Translations.Count >= Constants.MaxPassportFilesCount) + { + ShellViewModel.ShowCustomMessageBox(string.Format(AppResources.PassportUploadMaxReached, Constants.MaxPassportFilesCount), AppResources.AppName, + AppResources.Ok.ToLowerInvariant(), null, + dismissed => + { + + }); + + return; + } + + AttachDocument("Translation"); + } + + public void AttachDocument() + { + if (Files.Count >= Constants.MaxPassportFilesCount) + { + ShellViewModel.ShowCustomMessageBox(string.Format(AppResources.PassportUploadMaxReached, Constants.MaxPassportFilesCount), AppResources.AppName, + AppResources.Ok.ToLowerInvariant(), null, + dismissed => + { + + }); + + return; + } + + AttachDocument("Document"); + } + + public async void AttachDocument(string type) + { + + ((App)Application.Current).ChooseFileInfo = new ChooseFileInfo(DateTime.Now); + var picker = new FileOpenPicker(); + picker.FileTypeFilter.Add(".bmp"); + picker.FileTypeFilter.Add(".jpg"); + picker.FileTypeFilter.Add(".jpeg"); + picker.FileTypeFilter.Add(".png"); + picker.ContinuationData.Add("From", "ResidentialAddressView"); + picker.ContinuationData.Add("Type", type); + + if (Environment.OSVersion.Version.Major >= 10) + { + var result = await picker.PickSingleFileAsync(); + if (result != null) + { + Execute.BeginOnThreadPool(() => + { + SendDocument(type, result); + }); + } + } + else + { + picker.PickSingleFileAndContinue(); + } + } + + public async void SendDocument(string type, StorageFile file) + { + if (file == null) return; + + var password = _passwordBase as TLPassword; + if (password == null) return; + + var passwordSettings = password.Settings as TLPasswordSettings81; + if (passwordSettings == null) return; + + var fileId = TLLong.Random(); + var compressedFileName = string.Format("secureid_compressed_{0}.dat", fileId); + var fileName = string.Format("secureid_{0}.dat", fileId); + var previewFileName = string.Format("secureid_preview_{0}.dat", fileId); + var localFileName = string.Format("document{0}_{1}.dat", fileId, 0); + + var inputStream = await file.OpenReadAsync(); + + await DialogDetailsViewModel.ResizeJpeg(inputStream, Constants.DefaultPassportImageSize, file.DisplayName, compressedFileName, 0.89); + + file = await ApplicationData.Current.LocalFolder.GetFileAsync(compressedFileName); + + var padding = await Utils.Passport.GenerateRandomPadding(file); + var fileSecret = Utils.Passport.GenerateSecret(TLString.Empty); + var fileHash = TLString.FromBigEndianData(await Utils.Passport.GetSha256(padding, file)); + + var fileSecureSecret = Utils.Passport.EncryptValueSecret( + fileSecret, + EnterPasswordViewModel.Secret, + fileHash); + + var encryptedFile = await Utils.Passport.EncryptFile(fileName, file, fileSecret, fileHash, padding); + var stream = await file.OpenReadAsync(); + + await DialogDetailsViewModel.ResizeJpeg(stream, 180, localFileName, previewFileName); + + int length; + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + using (var fileStream = store.OpenFile(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + length = (int)fileStream.Length; + } + } + + var secureFileUploaded = new TLSecureFileUploaded + { + Id = fileId, + Parts = null, + MD5Checksum = TLString.Empty, + Size = new TLInt(length), + Date = TLUtils.DateToUniversalTimeTLInt(MTProtoService.ClientTicksDelta, DateTime.Now), + FileHash = fileHash, + Secret = fileSecureSecret + }; + + Execute.BeginOnUIThread(() => + { + switch (type) + { + case "Document": + Files.Add(secureFileUploaded); + FilesError = null; + NotifyOfPropertyChange(() => FilesError); + break; + case "Translation": + Translations.Add(secureFileUploaded); + TranslationsError = null; + NotifyOfPropertyChange(() => TranslationsError); + break; + } + + NotifyOfPropertyChange(() => IsFileUploading); + secureFileUploaded.UploadingProgress = 0.01; + secureFileUploaded.UploadingSize = (int)(secureFileUploaded.Size.Value * secureFileUploaded.UploadingProgress); + var documentFileManager = IoC.Get(); + documentFileManager.UploadFile(fileId, secureFileUploaded, encryptedFile); + }); + } + + public void DeleteFile(TLSecureFileBase file) + { + if (file == null) return; + + ShellViewModel.ShowCustomMessageBox(AppResources.PassportDeleteScanAlert, AppResources.AppName, + AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + Files.Remove(file); + Translations.Remove(file); + } + }); + } + + public void Delete() + { + if (_dataValue == null && _dataProofValue == null) + { + NavigationService.GoBack(); + return; + } + + if (_dataValue != null && _dataProofValue != null) + { + object content = null; + var textBlock = new TextBlock { IsHitTestVisible = false }; + var checkBox = new CheckBox { IsChecked = true, IsHitTestVisible = false }; + if (_dataValue != null) + { + textBlock.SetValue(TextBlock.FontSizeProperty, DependencyProperty.UnsetValue); + + var text = AppResources.PassportDeleteAddressDetails; + textBlock.Margin = new Thickness(-18.0, 0.0, 12.0, 0.0); + textBlock.Text = text; + textBlock.VerticalAlignment = VerticalAlignment.Center; + + var panel = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0.0, -2.0, 0.0, -20.0), Background = new SolidColorBrush(Colors.Transparent) }; + panel.Tap += (sender, args) => + { + checkBox.IsChecked = !checkBox.IsChecked; + }; + panel.Children.Add(checkBox); + panel.Children.Add(textBlock); + content = panel; + } + ShellViewModel.ShowCustomMessageBox(AppResources.PassportDeleteDocumentAlert, AppResources.AppName, + AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + var deleteData = _dataValue != null && checkBox.IsChecked == true; + var values = new TLVector { _dataProofValue }; + var types = new TLVector { _dataProofValue.Type }; + if (deleteData) + { + values.Add(_dataValue); + types.Add(_dataValue.Type); + } + IsWorking = true; + MTProtoService.DeleteSecureValueAsync( + types, + result => BeginOnUIThread(() => + { + IsWorking = false; + if (_authorizationForm != null) + { + foreach (var value in values) + { + _authorizationForm.Values.Remove(value); + } + } + RemoveDataErrors(); + RemoveProofErrors(); + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + EventAggregator.Publish(new DeleteSecureValueEventArgs { Values = values }); + NavigationService.GoBack(); + }), + error => BeginOnUIThread(() => + { + IsWorking = false; + })); + } + }, + content); + + return; + } + + // delete data + if (_dataValue != null) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PassportDeleteAddressAlert, AppResources.AppName, + AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + IsWorking = true; + MTProtoService.DeleteSecureValueAsync( + new TLVector { _dataValue.Type }, + result => BeginOnUIThread(() => + { + IsWorking = false; + if (_authorizationForm != null) + { + _authorizationForm.Values.Remove(_dataValue); + } + RemoveDataErrors(); + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + EventAggregator.Publish(new DeleteSecureValueEventArgs { Values = new List { _dataValue } }); + NavigationService.GoBack(); + }), + error => BeginOnUIThread(() => + { + IsWorking = false; + })); + } + }); + + return; + } + + // delete proof + if (_dataProofValue != null) + { + ShellViewModel.ShowCustomMessageBox(AppResources.PassportDeleteDocumentAlert, AppResources.AppName, + AppResources.Done.ToLowerInvariant(), AppResources.Cancel.ToLowerInvariant(), + dismissed => + { + if (dismissed == CustomMessageBoxResult.RightButton) + { + IsWorking = true; + MTProtoService.DeleteSecureValueAsync( + new TLVector { _dataProofValue.Type }, + result => BeginOnUIThread(() => + { + IsWorking = false; + if (_authorizationForm != null) + { + _authorizationForm.Values.Remove(_dataProofValue); + } + RemoveProofErrors(); + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + EventAggregator.Publish(new DeleteSecureValueEventArgs { Values = new List { _dataProofValue } }); + NavigationService.GoBack(); + }), + error => BeginOnUIThread(() => + { + IsWorking = false; + })); + } + }); + + return; + } + } + + public void Done() + { + if (IsFileUploading) return; + if (IsWorking) return; + + SaveDataAsync( + () => SaveProofAsync( + () => NavigationService.GoBack())); + } + + private void SaveDataAsync(System.Action callback, System.Action faultCallback = null) + { + var password = _passwordBase as TLPassword; + if (password == null) + { + faultCallback.SafeInvoke(); + return; + } + + var passwordSettings = password.Settings as TLPasswordSettings83; + if (passwordSettings == null) + { + faultCallback.SafeInvoke(); + return; + } + + var dataValue = _dataValue; + if (dataValue == null) + { + var secureType = + _secureRequiredType != null && _secureRequiredType.DataRequiredType != null + ? _secureRequiredType.DataRequiredType.Type + : null; + + //_authorizationForm != null + //? _authorizationForm.RequiredTypes.FirstOrDefault(IsValidDataType) + //: null; + + // add new address from passport settings + if (_secureType != null && IsValidDataType(_secureType)) + { + dataValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = _secureType + }; + } + // add new address from authorization form + else if (secureType != null) + { + dataValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = secureType + }; + } + else + { + callback.SafeInvoke(); + return; + } + } + + if (HasErrors()) + { + faultCallback.SafeInvoke(); + return; + } + + var rootObject = new ResidentialAddressRootObject + { + street_line1 = StreetLine1, + street_line2 = StreetLine2, + post_code = PostCode, + city = City, + state = State, + country_code = _selectedCountry.Code.ToUpperInvariant() + }; + + var data = JsonUtils.ToJSON(rootObject); + if (data == null) return; + + var valueSecret = Utils.Passport.GenerateSecret(TLString.Empty); + var newSecureValue = Utils.Passport.EncryptSecureValue( + dataValue, + new TLString(data), + valueSecret, + EnterPasswordViewModel.Secret); + var secureSecretHash = passwordSettings.SecureSettings.SecureSecretId; + + IsWorking = true; + MTProtoService.SaveSecureValueAsync( + newSecureValue.ToInputSecureValue(), secureSecretHash, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + result.Data.DecryptedData = rootObject; + if (_authorizationForm != null) + { + _authorizationForm.Values.Remove(dataValue); + _authorizationForm.Values.Add(result); + } + + RemoveDataErrors(); + + dataValue.Update(result); + dataValue.NotifyOfPropertyChange(() => dataValue.Self); + + if (_secureType != null) + { + EventAggregator.Publish(new AddSecureValueEventArgs{ Values = new List { dataValue }}); + } + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + + callback.SafeInvoke(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + + if (error.CodeEquals(ErrorCode.BAD_REQUEST)) + { + ShellViewModel.ShowCustomMessageBox( + "account.saveSecureValue" + Environment.NewLine + error.Message, + AppResources.AppName, + AppResources.Ok); + } + + faultCallback.SafeInvoke(); + })); + } + + private void SaveProofAsync(System.Action callback, System.Action faultCallback = null) + { + var password = _passwordBase as TLPassword; + if (password == null) + { + callback.SafeInvoke(); + return; + } + + var passwordSettings = password.Settings as TLPasswordSettings83; + if (passwordSettings == null) + { + callback.SafeInvoke(); + return; + } + + var dataProofValue = _dataProofValue; + if (dataProofValue == null) + { + var secureType = + _secureRequiredType != null && _secureRequiredType.SelectedDataProofRequiredType != null + ? _secureRequiredType.SelectedDataProofRequiredType.Type + : null; + + //_authorizationForm != null ? + //_authorizationForm.RequiredTypes.FirstOrDefault(IsValidProofType) + //: null; + + if (_secureType != null && IsValidProofType(_secureType)) + { + dataProofValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = _secureType + }; + } + else if (secureType != null) + { + dataProofValue = new TLSecureValue85 + { + Flags = new TLInt(0), + Type = secureType + }; + } + else + { + callback.SafeInvoke(); + return; + } + } + + if (HasErrors()) + { + faultCallback.SafeInvoke(); + return; + } + + var files = new TLVector(); + foreach (var file in Files) + { + files.Add(file.ToInputSecureFile()); + } + + var secureSecretId = passwordSettings.SecureSettings.SecureSecretId; + var inputSecureValue = dataProofValue.ToInputSecureValue(); + inputSecureValue.Files = files; + + var inputSecureValue85 = inputSecureValue as TLInputSecureValue85; + if (inputSecureValue85 != null) + { + if (Translations.Count > 0) + { + var translation = new TLVector(); + foreach (var file in Translations) + { + translation.Add(file.ToInputSecureFile()); + } + inputSecureValue85.Translation = translation; + } + } + + IsWorking = true; + MTProtoService.SaveSecureValueAsync( + inputSecureValue, secureSecretId, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + if (_authorizationForm != null) + { + _authorizationForm.Values.Remove(dataProofValue); + _authorizationForm.Values.Add(result); + } + RemoveProofErrors(); + + dataProofValue.Update(result); + dataProofValue.NotifyOfPropertyChange(() => dataProofValue.Self); + + if (_secureType != null) + { + EventAggregator.Publish(new AddSecureValueEventArgs { Values = new List { dataProofValue } }); + } + if (_secureRequiredType != null) + { + _secureRequiredType.UpdateValue(); + } + + callback.SafeInvoke(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + if (error.TypeEquals(ErrorType.FILES_EMPTY)) + { + Error = error; + NotifyOfPropertyChange(() => Error); + } + else if (error.TypeEquals(ErrorType.FILES_TOO_MUCH)) + { + ShellViewModel.ShowCustomMessageBox( + string.Format(AppResources.PassportUploadMaxReached, Constants.MaxPassportFilesCount), + AppResources.AppName, + AppResources.Ok.ToLowerInvariant()); + } + else if (error.CodeEquals(ErrorCode.BAD_REQUEST)) + { + ShellViewModel.ShowCustomMessageBox( + "account.saveSecureValue" + Environment.NewLine + error.Message, + AppResources.AppName, + AppResources.Ok); + } + + faultCallback.SafeInvoke(); + })); + } + + public void OpenScan(TLSecureFileBase file) + { + return; + StateService.CurrentPhotoMessage = new TLMessage{Status = MessageStatus.Confirmed}; + OpenImageViewer(); + } + + public void SelectCountry() + { + StateService.HideCountryCode = true; + NavigationService.UriFor().Navigate(); + } + + private void OnCountrySelected(Country country) + { + SelectedCountry = country; + } + + public ImageViewerViewModel ImageViewer { get; set; } + + public void OpenImageViewer() + { + if (ImageViewer == null) + { + ImageViewer = new ImageViewerViewModel(StateService, null, false, true) + { + //DialogDetails = this + }; + NotifyOfPropertyChange(() => ImageViewer); + } + BeginOnUIThread(() => ImageViewer.OpenViewer()); + } + + protected override void OnActivate() + { + if (StateService.SelectedCountry != null) + { + var country = StateService.SelectedCountry; + StateService.SelectedCountry = null; + OnCountrySelected(country); + } + + EventAggregator.Subscribe(this); + base.OnActivate(); + } + + protected override void OnDeactivate(bool close) + { + EventAggregator.Unsubscribe(this); + base.OnDeactivate(close); + } + + public void Handle(UploadableItem item) + { + var secureFileUploaded = item.Owner as TLSecureFileUploaded; + if (secureFileUploaded != null) + { + Execute.BeginOnUIThread(() => + { + secureFileUploaded.UploadingProgress = 1.0; + secureFileUploaded.UploadingSize = (int)(secureFileUploaded.Size.Value * secureFileUploaded.UploadingProgress); + secureFileUploaded.Parts = new TLInt(item.Parts.Count); + NotifyOfPropertyChange(() => IsFileUploading); + }); + } + } + + public void Handle(UploadProgressChangedEventArgs args) + { + var secureFileUploaded = args.Item.Owner as TLSecureFileUploaded; + if (secureFileUploaded != null) + { + Execute.BeginOnUIThread(() => + { + secureFileUploaded.UploadingProgress = args.Progress; + secureFileUploaded.UploadingSize = (int)(secureFileUploaded.Size.Value * secureFileUploaded.UploadingProgress); + NotifyOfPropertyChange(() => IsFileUploading); + }); + } + } + } + + public class ResidentialAddressRootObject + { + public string street_line1 { get; set; } + public string street_line2 { get; set; } + public string city { get; set; } + public string state { get; set; } + public string country_code { get; set; } + public string post_code { get; set; } + + public IEnumerable Fields() + { + if (!string.IsNullOrEmpty(street_line1)) yield return street_line1; + if (!string.IsNullOrEmpty(street_line2)) yield return street_line2; + if (!string.IsNullOrEmpty(post_code)) yield return post_code; + if (!string.IsNullOrEmpty(city)) yield return city; + if (!string.IsNullOrEmpty(state)) yield return state; + if (!string.IsNullOrEmpty(country_code)) yield return country_code; + } + + public IEnumerable Fields(Func getCountryByCode) + { + if (!string.IsNullOrEmpty(street_line1)) yield return street_line1; + if (!string.IsNullOrEmpty(street_line2)) yield return street_line2; + if (!string.IsNullOrEmpty(post_code)) yield return post_code; + if (!string.IsNullOrEmpty(city)) yield return city; + if (!string.IsNullOrEmpty(state)) yield return state; + if (!string.IsNullOrEmpty(country_code)) yield return getCountryByCode(country_code) ?? country_code; + } + + public override string ToString() + { + return string.Join(", ", Fields()); + } + + public string ToString(Func getCountryByCode) + { + return string.Join(", ", Fields(getCountryByCode)); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/CardInfoViewModel.cs b/TelegramClient.WP81/ViewModels/Payments/CardInfoViewModel.cs new file mode 100755 index 0000000..53ba785 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/CardInfoViewModel.cs @@ -0,0 +1,373 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Linq; +using System.Windows; +using System.Windows.Threading; +using Windows.Data.Json; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Models; +using TelegramClient.Services; +using TelegramClient.ViewModels.Additional; +using TelegramClient.ViewModels.Payments.Stripe; +using Execute = Telegram.Api.Helpers.Execute; + +namespace TelegramClient.ViewModels.Payments +{ + public class CardInfoViewModel : PaymentViewModelBase, Telegram.Api.Aggregator.IHandle + { + public bool NeedCountry { get; set; } + + public bool NeedZip { get; set; } + + public bool NeedCardholderName { get; set; } + + private readonly string _publishableKey ; + + public string CardNumber { get; set; } + + public string ExpirationDate { get; set; } + + public string CardholderName { get; set; } + + public string SecurityCode { get; set; } + + private Country _selectedCountry; + + public Country SelectedCountry + { + get { return _selectedCountry; } + set { SetField(ref _selectedCountry, value, () => SelectedCountry); } + } + + public string PostCode { get; set; } + + public Visibility SavePaymentInformationVisibility { get; set; } + + public bool SavePaymentInformation { get; set; } + + public string Error { get; set; } + + private bool _removeCheckoutView; + + private TLPasswordBase _password; + + private readonly DispatcherTimer _checkPasswordSettingsTimer = new DispatcherTimer(); + + private void StartTimer() + { + if (_password != null && !TLString.IsNullOrEmpty(_password.EmailUnconfirmedPattern)) + { + _checkPasswordSettingsTimer.Start(); + } + } + + private void StopTimer() + { + _checkPasswordSettingsTimer.Stop(); + } + + public CardInfoViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + _checkPasswordSettingsTimer.Tick += OnCheckPasswordSettings; + _checkPasswordSettingsTimer.Interval = TimeSpan.FromSeconds(5.0); + + EventAggregator.Subscribe(this); + + if (PaymentInfo != null && PaymentInfo.Form != null && PaymentInfo.Form.IsNativeProvider) + { + try + { + var jsonObject = JsonObject.Parse(PaymentInfo.Form.NativeParams.Data.ToString()); + + NeedCountry = jsonObject.GetNamedBoolean("need_country", false); + NeedZip = jsonObject.GetNamedBoolean("need_zip", false); + NeedCardholderName = jsonObject.GetNamedBoolean("need_cardholder_name", false); + + _publishableKey = jsonObject.GetNamedString("publishable_key", string.Empty); + } + catch (Exception ex) + { + Telegram.Logs.Log.Write(string.Format("Can't read Form.NativeParams ex={0}\nparams={1}", ex, PaymentInfo.Form.NativeParams.Data)); + } + + SavePaymentInformation = PaymentInfo.Form.CanSaveCredentials; + SavePaymentInformationVisibility = PaymentInfo.Form.PasswordMissing || + PaymentInfo.Form.CanSaveCredentials ? Visibility.Visible : Visibility.Collapsed; + } + + _removeCheckoutView = StateService.RemoveCheckoutAndCardView; + StateService.RemoveCheckoutAndCardView = false; + } + + private void OnCheckPasswordSettings(object sender, System.EventArgs e) + { + Execute.ShowDebugMessage("account.getPasswordSettings"); + + MTProtoService.GetPasswordAsync( + result => BeginOnUIThread(() => + { + var password = result as TLPassword; + if (password != null && password.HasRecovery.Value) + { + var currentPassword = _password as TLPassword; + if (currentPassword != null) + { + password.CurrentPasswordHash = currentPassword.CurrentPasswordHash; + } + + _password = password; + + Handle(password); + + StopTimer(); + } + }), + error => + { + Execute.ShowDebugMessage("account.getPasswordSettings error " + error); + }); + } + + public void SelectCountry() + { + StateService.HideCountryCode = true; + NavigationService.UriFor().Navigate(); + } + + protected override void OnActivate() + { + StartTimer(); + + if (StateService.SelectedCountry != null) + { + var country = StateService.SelectedCountry; + StateService.SelectedCountry = null; + OnCountrySelected(country); + } + if (StateService.Password != null) + { + _password = StateService.Password; + StateService.Password = null; + + Handle(_password); + + StartTimer(); + } + + base.OnActivate(); + } + + protected override void OnDeactivate(bool close) + { + StopTimer(); + + base.OnDeactivate(close); + } + + private void OnCountrySelected(Country country) + { + SelectedCountry = country; + } + + public async void Validate() + { + if (PaymentInfo.Form.SavedCredentials != null && !SavePaymentInformation && PaymentInfo.Form.CanSaveCredentials) + { + PaymentInfo.Form.SavedCredentials = null; + + StateService.SaveTmpPassword(null); + MTProtoService.ClearSavedInfoAsync(false, true, + result => + { + + }, + error => + { + + }); + } + + var month = 0; + var year = 0; + + try + { + if (ExpirationDate != null) + { + var args = ExpirationDate.Split('/'); + if (args.Length == 2) + { + month = int.Parse(args[0]); + year = int.Parse(args[1]); + } + } + } + catch (Exception ex) + { + Error = "CARD_EXPIRE_DATE_INVALID"; + NotifyOfPropertyChange(() => Error); + return; + } + + var card = new Card( + CardNumber, + month, + year, + SecurityCode, + CardholderName, + null, null, null, null, + PostCode, + SelectedCountry != null ? _selectedCountry.Code.ToUpperInvariant() : null, + null); + + if (!card.ValidateNumber()) + { + Error = "CARD_NUMBER_INVALID"; + NotifyOfPropertyChange(() => Error); + return; + } + + if (!card.ValidateExpireDate()) + { + Error = "CARD_EXPIRE_DATE_INVALID"; + NotifyOfPropertyChange(() => Error); + return; + } + + if (NeedCardholderName && string.IsNullOrWhiteSpace(CardholderName)) + { + Error = "CARD_HOLDER_NAME_INVALID"; + NotifyOfPropertyChange(() => Error); + return; + } + if (!card.ValidateCVC()) + { + Error = "CARD_CVC_INVALID"; + NotifyOfPropertyChange(() => Error); + return; + } + if (NeedCountry && _selectedCountry == null) + { + Error = "CARD_COUNTRY_INVALID"; + NotifyOfPropertyChange(() => Error); + return; + } + if (NeedZip && string.IsNullOrWhiteSpace(PostCode)) + { + Error = "CARD_ZIP_INVALID"; + NotifyOfPropertyChange(() => Error); + return; + } + + IsWorking = true; + + using (var stripe = new StripeClient(_publishableKey)) + { + var token = await stripe.CreateTokenAsync(card); + + IsWorking = false; + + if (token != null) + { + if (token.Error != null) + { + Error = token.Error.code; + NotifyOfPropertyChange(() => Error); + return; + } + + if (!string.IsNullOrEmpty(token.Id) + && !string.IsNullOrEmpty(token.Type)) + { + var title = card.GetBrand() + " *" + card.GetLast4(); + var credentials = string.Format("{{\"type\":\"{0}\", \"id\":\"{1}\"}}", token.Type, token.Id); + + PaymentInfo.CredentialsTitle = title; + var paymentCredentials = new TLInputPaymentCredentials + { + Flags = new TLInt(0), + Data = new TLDataJSON + { + Data = new TLString(credentials) + }, + Save = SavePaymentInformation + }; + PaymentInfo.Credentials = paymentCredentials; + NavigateToNextStep(); + return; + } + } + + Error = "invalid_button"; + NotifyOfPropertyChange(() => Error); + } + } + + public void OpenTwoStepVerification() + { + MTProtoService.GetPasswordAsync( + result => BeginOnUIThread(() => + { + if (result != null && result.HasPassword) + { + StateService.Password = result; + NavigationService.UriFor().Navigate(); + return; + } + + StateService.Password = result; + NavigationService.UriFor().Navigate(); + }), + error => + { + Execute.ShowDebugMessage("account.getPassword error " + error); + }); + } + + public override void NavigateToNextStep() + { + if (_removeCheckoutView) + { + var backEntry = NavigationService.BackStack.FirstOrDefault(); + if (backEntry != null && backEntry.Source.ToString().Contains("CheckoutView.xaml")) + { + NavigationService.RemoveBackEntry(); + } + + backEntry = NavigationService.BackStack.FirstOrDefault(); + if (backEntry != null && (backEntry.Source.ToString().Contains("SavedCardInfoView.xaml") || backEntry.Source.ToString().Contains("CardInfoView.xaml") || backEntry.Source.ToString().Contains("WebCardInfoView.xaml"))) + { + NavigationService.RemoveBackEntry(); + } + } + + StateService.PaymentInfo = PaymentInfo; + NavigationService.UriFor().Navigate(); + } + + public void Handle(TLPasswordBase passwordBase) + { + if (PaymentInfo != null && PaymentInfo.Form != null) + { + PaymentInfo.Form.PasswordMissing = passwordBase == null || !passwordBase.HasPassword; + PaymentInfo.Form.NotifyOfPropertyChange(() => PaymentInfo.Form.PasswordMissing); + SavePaymentInformation = PaymentInfo.Form.CanSaveCredentials; + NotifyOfPropertyChange(() => SavePaymentInformation); + SavePaymentInformationVisibility = PaymentInfo.Form.PasswordMissing || + PaymentInfo.Form.CanSaveCredentials ? Visibility.Visible : Visibility.Collapsed; + NotifyOfPropertyChange(() => SavePaymentInformationVisibility); + } + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/CheckoutViewModel.cs b/TelegramClient.WP81/ViewModels/Payments/CheckoutViewModel.cs new file mode 100755 index 0000000..4a436d6 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/CheckoutViewModel.cs @@ -0,0 +1,357 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Windows; +using Caliburn.Micro; +using Microsoft.Phone.Tasks; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using Telegram.Controls.Utils; +using TelegramClient.Converters; +using TelegramClient.Resources; +using TelegramClient.Services; + +namespace TelegramClient.ViewModels.Payments +{ + public class CheckoutViewModel : PaymentViewModelBase + { + public TLInvoice Invoice { get; set; } + + public TLPaymentRequestedInfo SavedInfo { get; set; } + + public string Title + { + get + { + if (PaymentInfo != null) + { + if (PaymentInfo.Receipt != null) + { + if (PaymentInfo.Receipt.Invoice.Test) + { + return AppResources.TestReceipt; + } + + return AppResources.Receipt; + } + + if (PaymentInfo.Form != null) + { + if (PaymentInfo.Form.Invoice.Test) + { + return AppResources.TestCheckout; + } + + return AppResources.Checkout; + } + } + + return AppResources.Checkout; + } + } + + public string PaymentProvider + { + get + { + if (PaymentInfo != null) + { + if (PaymentInfo.Receipt != null) + { + var providerId = PaymentInfo.Receipt.ProviderId; + var paymentProvider = PaymentInfo.Receipt.Users.FirstOrDefault(x => x.Id.Value == providerId.Value) as TLUser; + if (paymentProvider != null) + { + return paymentProvider.FullName2; + } + + return string.Empty; + } + + if (PaymentInfo.Form != null) + { + var providerId = PaymentInfo.Form.ProviderId; + var paymentProvider = PaymentInfo.Form.Users.FirstOrDefault(x => x.Id.Value == providerId.Value) as TLUser; + if (paymentProvider != null) + { + return paymentProvider.FullName2; + } + + return string.Empty; + } + } + + return AppResources.Checkout; + } + } + + public List Prices { get; set; } + + public long TotalAmount + { + get + { + if (Prices != null) + { + return Prices.Sum(x => x.Amount.Value); + } + + return 0; + } + } + + public TLLabeledPrice Total + { + get + { + var price = new TLLabeledPrice + { + Amount = new TLLong(TotalAmount), + Label = new TLString(AppResources.Total), + Currency = PaymentInfo != null && PaymentInfo.Form != null ? PaymentInfo.Form.Invoice.Currency : null + }; + + if (PaymentInfo != null) + { + if (PaymentInfo.Form != null) + { + price.Currency = PaymentInfo.Form.Invoice.Currency; + } + else if (PaymentInfo.Receipt != null) + { + price.Currency = PaymentInfo.Receipt.Invoice.Currency; + } + } + + return price; + } + } + + public string PayString + { + get + { + return string.Format("{0} {1}", AppResources.Pay, new LabeledPriceToStringConverter().Convert(Total, null, null, null)); + } + } + + private TLUserBase _bot; + + public TLUserBase Bot + { + get + { + if (_bot == null && PaymentInfo != null) + { + if (PaymentInfo.Form != null) + { + _bot = CacheService.GetUser(PaymentInfo.Form.BotId); + } + else if (PaymentInfo.Receipt != null) + { + _bot = CacheService.GetUser(PaymentInfo.Receipt.BotId); + } + } + + return _bot; + } + } + + public TLShippingOption ShippingOption { get; set; } + + public CheckoutViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + Prices = new List(); + + if (PaymentInfo != null) + { + if (PaymentInfo.Form != null) + { + Invoice = PaymentInfo.Form.Invoice; + SavedInfo = PaymentInfo.Form.SavedInfo; + foreach (var price in PaymentInfo.Form.Invoice.Prices) + { + price.Currency = PaymentInfo.Form.Invoice.Currency; + Prices.Add(price); + } + + if (PaymentInfo.ValidatedInfo != null + && PaymentInfo.ValidatedInfo.ShippingOptions != null) + { + foreach (var shippingOption in PaymentInfo.ValidatedInfo.ShippingOptions) + { + if (shippingOption.IsSelected) + { + ShippingOption = shippingOption; + foreach (var price in shippingOption.Prices) + { + price.Currency = PaymentInfo.Form.Invoice.Currency; + Prices.Add(price); + } + break; + } + } + } + } + else if (PaymentInfo.Receipt != null) + { + Invoice = PaymentInfo.Receipt.Invoice; + SavedInfo = PaymentInfo.Receipt.SavedInfo; + PaymentInfo.CredentialsTitle = PaymentInfo.Receipt.CredentialsTitle.ToString(); + + foreach (var price in PaymentInfo.Receipt.Invoice.Prices) + { + price.Currency = PaymentInfo.Receipt.Invoice.Currency; + Prices.Add(price); + } + + var shippingOption = PaymentInfo.Receipt.Shipping; + if (shippingOption != null) + { + ShippingOption = shippingOption; + foreach (var price in shippingOption.Prices) + { + price.Currency = PaymentInfo.Receipt.Invoice.Currency; + Prices.Add(price); + } + } + } + } + } + + public void Validate() + { + if (PaymentInfo == null) return; + if (PaymentInfo.Form == null) return; + if (PaymentInfo.Message == null) return; + if (PaymentInfo.Credentials == null) return; + + var paymentCredentials = PaymentInfo.Credentials; + TLString validatedInfoId = null; + TLString shippingOptionId = null; + if (PaymentInfo.ValidatedInfo != null) + { + validatedInfoId = PaymentInfo.ValidatedInfo.Id; + + if (PaymentInfo.ValidatedInfo.ShippingOptions != null) + { + foreach (var shippingOption in PaymentInfo.ValidatedInfo.ShippingOptions) + { + if (shippingOption.IsSelected) + { + shippingOptionId = shippingOption.Id; + break; + } + } + } + } + + var mediaInvoice = PaymentInfo.Message.Media as TLMessageMediaInvoice; + if (mediaInvoice == null) return; + + var bot = CacheService.GetUser(PaymentInfo.Form.BotId) as TLUser45; + if (bot == null) return; + + if (!bot.IsVerified && !bot.BotPaymentsPermission) + { + MessageBox.Show(string.Format(AppResources.PaymentsWarning, bot.FullName), string.Empty, MessageBoxButton.OK); + bot.BotPaymentsPermission = true; + } + + var confirmation = MessageBox.Show(string.Format(AppResources.TransactionConfirmation, Currency.GetString(TotalAmount, PaymentInfo.Form.Invoice.Currency.ToString()), bot.FullName, mediaInvoice.Title), AppResources.TransactionReview, MessageBoxButton.OKCancel); + if (confirmation != MessageBoxResult.OK) return; + + IsWorking = true; + MTProtoService.SendPaymentFormAsync(PaymentInfo.Message.Id, validatedInfoId, shippingOptionId, paymentCredentials, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + PaymentInfo.Result = result; + NavigateToNextStep(); + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + })); + } + + public void ChangeCredentials() + { + if (PaymentInfo.Receipt != null) return; + if (PaymentInfo.Form == null) return; + + StateService.PaymentInfo = PaymentInfo; + + if (PaymentInfo.Form.IsNativeProvider) + { + StateService.RemoveCheckoutAndCardView = true; + NavigationService.UriFor().Navigate(); + } + else + { + StateService.RemoveCheckoutAndCardView = true; + NavigationService.UriFor().Navigate(); + } + } + + public override void NavigateToNextStep() + { + var paymentResult = PaymentInfo.Result as TLPaymentResult; + if (paymentResult != null) + { + var backEnrty = NavigationService.BackStack.FirstOrDefault(); + while (backEnrty != null + && !backEnrty.Source.ToString().Contains("DialogDetailsView.xaml") + && !backEnrty.Source.ToString().Contains("ShellView.xaml")) + { + NavigationService.RemoveBackEntry(); + backEnrty = NavigationService.BackStack.FirstOrDefault(); + } + if (backEnrty != null && backEnrty.Source.ToString().Contains("DialogDetailsView.xaml")) + { + StateService.ShowScrollDownButton = true; + } + NavigationService.GoBack(); + + return; + } + + var paymentVerificationNeeded = PaymentInfo.Result as TLPaymentVerificationNeeded; + if (paymentVerificationNeeded != null) + { + if (!TLString.IsNullOrEmpty(paymentVerificationNeeded.Url)) + { + var backEnrty = NavigationService.BackStack.FirstOrDefault(); + while (backEnrty != null + && !backEnrty.Source.ToString().Contains("DialogDetailsView.xaml") + && !backEnrty.Source.ToString().Contains("ShellView.xaml")) + { + NavigationService.RemoveBackEntry(); + backEnrty = NavigationService.BackStack.FirstOrDefault(); + } + if (backEnrty != null && backEnrty.Source.ToString().Contains("DialogDetailsView.xaml")) + { + StateService.ShowScrollDownButton = true; + } + + StateService.RemoveBackEntry = true; + StateService.Url = paymentVerificationNeeded.Url.ToString(); + StateService.PaymentInfo = PaymentInfo; + NavigationService.UriFor().Navigate(); + } + return; + } + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/PasswordEmailViewModel.cs b/TelegramClient.WP81/ViewModels/Payments/PasswordEmailViewModel.cs new file mode 100755 index 0000000..42be069 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/PasswordEmailViewModel.cs @@ -0,0 +1,102 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Services; +using TelegramClient.ViewModels.Additional; + +namespace TelegramClient.ViewModels.Payments +{ + public class PasswordEmailViewModel : ChangePasswordViewModelBase + { + private string _password; + + public string Password + { + get { return _password; } + set { SetField(ref _password, value, () => Password); } + } + + private string _confirmPassword; + + public string ConfirmPassword + { + get { return _confirmPassword; } + set { SetField(ref _confirmPassword, value, () => ConfirmPassword); } + } + + private string _recoveryEmail; + + public string RecoveryEmail + { + get { return _recoveryEmail; } + set { SetField(ref _recoveryEmail, value, () => RecoveryEmail); } + } + + public PasswordEmailViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, + IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, + ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + + } + + public void Create() + { + if (_passwordBase == null) return; + + HasError = false; + Error = " "; + + if (string.IsNullOrEmpty(_password)) + { + HasError = true; + Error = "invalid_password"; + return; + } + + if (!string.Equals(_password, _confirmPassword)) + { + HasError = true; + Error = "invalid_confirmpassword"; + return; + } + + if (!ChangePasswordEmailViewModel.IsValidEmail(_recoveryEmail)) + { + HasError = true; + Error = "invalid_email"; + return; + } + + var password84 = _passwordBase as TLPassword84; + if (password84 == null) return; + + var newAlgo = password84.NewAlgo as TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow; + if (newAlgo == null) return; + + Utils.Password.AddClientSalt(newAlgo); + + var newSettings = new TLPasswordInputSettings83 + { + Flags = new TLInt(0), + NewAlgo = newAlgo, + NewPasswordHash = null, + Hint = TLString.Empty, + Email = new TLString(RecoveryEmail), + NewPassword = _password + }; + + UpdatePasswordSettings(password84, newSettings); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/PaymentInfo.cs b/TelegramClient.WP81/ViewModels/Payments/PaymentInfo.cs new file mode 100755 index 0000000..5d2567d --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/PaymentInfo.cs @@ -0,0 +1,30 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Telegram.Api.TL; + +namespace TelegramClient.ViewModels.Payments +{ + public class PaymentInfo + { + public TLMessage Message { get; set; } + + public TLPaymentForm Form { get; set; } + + public TLValidatedRequestedInfo ValidatedInfo { get; set; } + + public string CredentialsTitle { get; set; } + + public TLInputPaymentCredentialsBase Credentials { get; set; } + + public TLPaymentResultBase Result { get; set; } + + public TLPaymentReceipt Receipt { get; set; } + + public TLObject With { get; set; } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/ViewModels/Payments/PaymentViewModelBase.cs b/TelegramClient.WP81/ViewModels/Payments/PaymentViewModelBase.cs new file mode 100755 index 0000000..27a8c0e --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/PaymentViewModelBase.cs @@ -0,0 +1,99 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Services; +using TelegramClient.Views.Dialogs; + +namespace TelegramClient.ViewModels.Payments +{ + public abstract class PaymentViewModelBase : ViewModelBase + { + public PaymentInfo PaymentInfo { get; set; } + + protected PaymentViewModelBase(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + PaymentInfo = stateService.PaymentInfo; + stateService.PaymentInfo = null; + } + + public abstract void NavigateToNextStep(); + + public static void NavigateToCardInfo(IDialogDetailsView view, PaymentInfo paymentInfo, Func getTmpPassword, + INavigationService navigationService) + { + if (paymentInfo == null) return; + + var form = paymentInfo.Form; + if (form == null) return; + + var useSavedCredentials = false; + var savedCredentialsCard = form.SavedCredentials as TLPaymentSavedCredentialsCard; + TLTmpPassword tmpPassword = null; + if (savedCredentialsCard != null && !form.PasswordMissing) + { + tmpPassword = getTmpPassword.Invoke(); + if (tmpPassword != null) + { + var now = TLUtils.DateToUniversalTimeTLInt(IoC.Get().ClientTicksDelta, DateTime.Now); + if (tmpPassword.ValidUntil.Value - 60 > now.Value) + { + useSavedCredentials = true; + } + } + } + + if (useSavedCredentials) + { + paymentInfo.Credentials = new TLInputPaymentCredentialsSaved + { + Id = savedCredentialsCard.Id, + TmpPassword = tmpPassword.TmpPassword + }; + paymentInfo.CredentialsTitle = savedCredentialsCard.Title.ToString(); + + Navigate(view, navigationService); + } + else if (savedCredentialsCard != null && !form.PasswordMissing) + { + Navigate(view, navigationService); + } + else + { + if (form.IsNativeProvider) + { + Navigate(view, navigationService); + } + else + { + Navigate(view, navigationService); + } + } + } + + private static void Navigate(IDialogDetailsView view, INavigationService navigationService) + { + if (view != null) + { + view.StopPlayersAndCreateBitmapCache(() => + { + navigationService.UriFor().Navigate(); + }); + } + else + { + navigationService.UriFor().Navigate(); + } + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/ReceiptViewModel.cs b/TelegramClient.WP81/ViewModels/Payments/ReceiptViewModel.cs new file mode 100755 index 0000000..ce8896c --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/ReceiptViewModel.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using TelegramClient.Services; + +namespace TelegramClient.ViewModels.Payments +{ + public class ReceiptViewModel : PaymentViewModelBase + { + public ReceiptViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + } + + public override void NavigateToNextStep() + { + + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/SavedCardInfoViewModel.cs b/TelegramClient.WP81/ViewModels/Payments/SavedCardInfoViewModel.cs new file mode 100755 index 0000000..497f21f --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/SavedCardInfoViewModel.cs @@ -0,0 +1,159 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Security.Cryptography; +using System.Text; +using System.Windows; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.Utils; +using Execute = Telegram.Api.Helpers.Execute; + +namespace TelegramClient.ViewModels.Payments +{ + public class SavedCardInfoViewModel : PaymentViewModelBase + { + private readonly TLPaymentSavedCredentialsCard _savedCredentialsCard; + + public string Title { get; set; } + + public string Password { get; set; } + + public string Error { get; set; } + + public string SavedCardHint + { + get { return string.Format(AppResources.SavedCardHint, Title); } + } + + public SavedCardInfoViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + if (PaymentInfo != null && PaymentInfo.Form != null && PaymentInfo.Form.SavedCredentials != null) + { + _savedCredentialsCard = PaymentInfo.Form.SavedCredentials as TLPaymentSavedCredentialsCard; + if (_savedCredentialsCard != null) + { + Title = _savedCredentialsCard.Title.ToString(); + } + } + } + + public void ChangeCredentials() + { + if (PaymentInfo.Receipt != null) return; + if (PaymentInfo.Form == null) return; + + StateService.PaymentInfo = PaymentInfo; + + if (PaymentInfo.Form.IsNativeProvider) + { + StateService.RemoveCheckoutAndCardView = true; + NavigationService.UriFor().Navigate(); + } + else + { + StateService.RemoveCheckoutAndCardView = true; + NavigationService.UriFor().Navigate(); + } + } + + public void Validate() + { + if (_savedCredentialsCard == null) return; + + if (string.IsNullOrEmpty(Password)) + { + Error = "PASSWORD"; + NotifyOfPropertyChange(() => Error); + return; + } + + IsWorking = true; + MTProtoService.GetPasswordAsync( + result => + { + var password84 = result as TLPassword84; + if (password84 == null) + { + return; + } + + var algo = password84.CurrentAlgo as TLPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow; + if (algo == null) + { + return; + } + //var passwordHash = Utils.Password.GetHash(password.CurrentSalt, new TLString(Password)); + var passwordHash = SRP.GetX(new TLString(Password), algo); + var password = SRP.GetCheck(passwordHash, password84.SRPId, password84.SRPB, algo); + + MTProtoService.GetTmpPasswordAsync( + password, new TLInt(Constants.DefaultTmpPasswordLifetime), + result2 => Execute.BeginOnUIThread(() => + { + IsWorking = false; + PaymentInfo.Credentials = new TLInputPaymentCredentialsSaved + { + Id = _savedCredentialsCard.Id, + TmpPassword = result2.TmpPassword + }; + PaymentInfo.CredentialsTitle = Title; + StateService.SaveTmpPassword(result2); + NavigateToNextStep(); + }), + error2 => Execute.BeginOnUIThread(() => + { + IsWorking = false; + var messageBuilder = new StringBuilder(); + messageBuilder.AppendLine("Method: account.getTmpPassword"); + messageBuilder.AppendLine("Result: " + error2); + + if (TLRPCError.CodeEquals(error2, ErrorCode.FLOOD)) + { + Execute.BeginOnUIThread(() => MessageBox.Show(AppResources.FloodWaitString, AppResources.Error, MessageBoxButton.OK)); + } + else if (TLRPCError.CodeEquals(error2, ErrorCode.INTERNAL)) + { + Execute.BeginOnUIThread(() => MessageBox.Show(messageBuilder.ToString(), AppResources.ServerError, MessageBoxButton.OK)); + } + else if (TLRPCError.CodeEquals(error2, ErrorCode.BAD_REQUEST)) + { + if (TLRPCError.TypeEquals(error2, ErrorType.PASSWORD_HASH_INVALID)) + { + Error = string.Format("PASSWORD"); + NotifyOfPropertyChange(() => Error); + } + else + { + Execute.BeginOnUIThread(() => MessageBox.Show(messageBuilder.ToString(), AppResources.Error, MessageBoxButton.OK)); + } + } + else + { + Execute.ShowDebugMessage("account.getTmpPassword error " + error2); + } + })); + }, + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + })); + } + + public override void NavigateToNextStep() + { + StateService.PaymentInfo = PaymentInfo; + NavigationService.UriFor().Navigate(); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/ShippingInfoViewModel.cs b/TelegramClient.WP81/ViewModels/Payments/ShippingInfoViewModel.cs new file mode 100755 index 0000000..967541c --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/ShippingInfoViewModel.cs @@ -0,0 +1,223 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Linq; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Models; +using TelegramClient.Services; +using TelegramClient.ViewModels.Additional; + +namespace TelegramClient.ViewModels.Payments +{ + public class ShippingInfoViewModel : PaymentViewModelBase + { + public bool IsPhoneCodeInvalid + { + get { return string.IsNullOrEmpty(PhoneCode) || CountryUtils.CountriesSource.FirstOrDefault(x => x.PhoneCode == PhoneCode) == null; } + } + + public string Name { get; set; } + + public string PhoneCode { get; set; } + + public string PhoneNumber { get; set; } + + public string Email { get; set; } + + #region Shipping Address + + public string StreetLine1 { get; set; } + + public string StreetLine2 { get; set; } + + public string City { get; set; } + + public string State { get; set; } + + private Country _selectedCountry; + + public Country SelectedCountry + { + get { return _selectedCountry; } + set { SetField(ref _selectedCountry, value, () => SelectedCountry); } + } + + public string PostCode { get; set; } + #endregion + + public bool SaveShippingInformation { get; set; } + + public TLRPCError Error { get; set; } + + public ShippingInfoViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + if (PaymentInfo != null && PaymentInfo.Form != null) + { + var savedInfo = PaymentInfo.Form.SavedInfo; + if (savedInfo != null) + { + Name = savedInfo.Name != null? savedInfo.Name.ToString() : null; + var phone = TLString.IsNullOrEmpty(savedInfo.Phone) ? string.Empty : savedInfo.Phone.ToString(); + if (!string.IsNullOrEmpty(phone)) + { + var codeCounty = CountryUtils.CountriesSource.FirstOrDefault(x => phone.StartsWith(x.PhoneCode, StringComparison.OrdinalIgnoreCase)); + if (codeCounty != null) + { + PhoneCode = codeCounty.PhoneCode; + var index = phone.IndexOf(PhoneCode, StringComparison.OrdinalIgnoreCase); + var phoneNumber = (index < 0) + ? phone + : phone.Remove(index, PhoneCode.Length); + PhoneNumber = phoneNumber; + } + else + { + PhoneNumber = phone; + } + } + Email = savedInfo.Email != null ? savedInfo.Email.ToString() : null; + + if (savedInfo.ShippingAddress != null) + { + var country = CountryUtils.CountriesSource.FirstOrDefault(x => string.Equals(savedInfo.ShippingAddress.CountryIso2.ToString(), x.Code, StringComparison.OrdinalIgnoreCase)); + + StreetLine1 = savedInfo.ShippingAddress.StreetLine1.ToString(); + StreetLine2 = savedInfo.ShippingAddress.StreetLine2.ToString(); + City = savedInfo.ShippingAddress.City.ToString(); + State = savedInfo.ShippingAddress.State.ToString(); + _selectedCountry = country; + PostCode = savedInfo.ShippingAddress.PostCode.ToString(); + } + } + } + + SaveShippingInformation = true; + } + + public void SelectCountry() + { + StateService.HideCountryCode = true; + NavigationService.UriFor().Navigate(); + } + + protected override void OnActivate() + { + if (StateService.SelectedCountry != null) + { + var country = StateService.SelectedCountry; + StateService.SelectedCountry = null; + OnCountrySelected(country); + } + base.OnActivate(); + } + + private void OnCountrySelected(Country country) + { + SelectedCountry = country; + } + + public void Validate() + { + if (PaymentInfo == null) return; + if (PaymentInfo.Message == null) return; + if (PaymentInfo.Form == null) return; + + var info = new TLPaymentRequestedInfo + { + Flags = new TLInt(0) + }; + if (PaymentInfo.Form.Invoice.NameRequested) + { + info.Name = new TLString(Name); + } + if (PaymentInfo.Form.Invoice.PhoneRequested) + { + info.Phone = new TLString(PhoneCode + PhoneNumber); + } + if (PaymentInfo.Form.Invoice.EmailRequested) + { + info.Email = new TLString(Email); + } + if (PaymentInfo.Form.Invoice.ShippingAddressRequested) + { + info.ShippingAddress = new TLPostAddress + { + StreetLine1 = new TLString(StreetLine1), + StreetLine2 = new TLString(StreetLine2), + City = new TLString(City), + State = new TLString(State), + CountryIso2 = new TLString(SelectedCountry != null ? SelectedCountry.Code : string.Empty), + PostCode = new TLString(PostCode) + }; + } + + IsWorking = true; + MTProtoService.ValidateRequestedInfoAsync( + SaveShippingInformation, + PaymentInfo.Message.Id, + info, + result => Execute.BeginOnUIThread(() => + { + IsWorking = false; + PaymentInfo.ValidatedInfo = result; + PaymentInfo.Form.SavedInfo = info; + + if (!SaveShippingInformation + && PaymentInfo != null + && PaymentInfo.Form != null + && PaymentInfo.Form.SavedInfo != null) + { + IsWorking = true; + MTProtoService.ClearSavedInfoAsync(false, true, + result2 =>Execute.BeginOnUIThread(() => + { + IsWorking = false; + NavigateToNextStep(); + }), + error2 => Execute.BeginOnUIThread(() => + { + IsWorking = false; + Telegram.Api.Helpers.Execute.ShowDebugMessage("payments.clearInfo error " + error2); + })); + } + else + { + NavigateToNextStep(); + } + }), + error => Execute.BeginOnUIThread(() => + { + IsWorking = false; + Error = error; + NotifyOfPropertyChange(() => Error); + Telegram.Api.Helpers.Execute.ShowDebugMessage("payments.validateRequestedInfo error " + error); + })); + } + + public override void NavigateToNextStep() + { + StateService.PaymentInfo = PaymentInfo; + + if (PaymentInfo.Form.Invoice.Flexible + && PaymentInfo.ValidatedInfo.ShippingOptions != null + && PaymentInfo.ValidatedInfo.ShippingOptions.Count > 0) + { + NavigationService.UriFor().Navigate(); + } + else + { + NavigateToCardInfo(null, StateService.PaymentInfo, () => StateService.GetTmpPassword(), NavigationService); + } + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/ShippingMethodViewModel.cs b/TelegramClient.WP81/ViewModels/Payments/ShippingMethodViewModel.cs new file mode 100755 index 0000000..531b25a --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/ShippingMethodViewModel.cs @@ -0,0 +1,48 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using TelegramClient.Services; + +namespace TelegramClient.ViewModels.Payments +{ + public class ShippingMethodViewModel : PaymentViewModelBase + { + public ShippingMethodViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + if (PaymentInfo != null + && PaymentInfo.Form != null + && PaymentInfo.ValidatedInfo != null + && PaymentInfo.ValidatedInfo.ShippingOptions != null) + { + for (var i = 0; i < PaymentInfo.ValidatedInfo.ShippingOptions.Count; i++) + { + PaymentInfo.ValidatedInfo.ShippingOptions[i].IsSelected = i == 0; + foreach (var price in PaymentInfo.ValidatedInfo.ShippingOptions[i].Prices) + { + price.Currency = PaymentInfo.Form.Invoice.Currency; + } + } + } + } + + public void Validate() + { + NavigateToNextStep(); + } + + public override void NavigateToNextStep() + { + StateService.PaymentInfo = PaymentInfo; + NavigateToCardInfo(null, StateService.PaymentInfo, () => StateService.GetTmpPassword(), NavigationService); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/Stripe/Card.cs b/TelegramClient.WP81/ViewModels/Payments/Stripe/Card.cs new file mode 100755 index 0000000..f79bf18 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/Stripe/Card.cs @@ -0,0 +1,378 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Text.RegularExpressions; + +namespace TelegramClient.ViewModels.Payments.Stripe +{ + public class Card + { + public enum StringDef + { + AMERICAN_EXPRESS, + DISCOVER, + JCB, + DINERS_CLUB, + VISA, + MASTERCARD, + UNKNOWN + }; + public const String AMERICAN_EXPRESS = "American Express"; + public const String DISCOVER = "Discover"; + public const String JCB = "JCB"; + public const String DINERS_CLUB = "Diners Club"; + public const String VISA = "Visa"; + public const String MASTERCARD = "MasterCard"; + public const String UNKNOWN = "Unknown"; + + public enum FUNDING + { + FUNDING_CREDIT, + FUNDING_DEBIT, + FUNDING_PREPAID, + FUNDING_UNKNOWN + }; + public const String FUNDING_CREDIT = "credit"; + public const String FUNDING_DEBIT = "debit"; + public const String FUNDING_PREPAID = "prepaid"; + public const String FUNDING_UNKNOWN = "unknown"; + + // Based on http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29 + public static String[] PREFIXES_AMERICAN_EXPRESS = { "34", "37" }; + public static String[] PREFIXES_DISCOVER = { "60", "62", "64", "65" }; + public static String[] PREFIXES_JCB = { "35" }; + public static String[] PREFIXES_DINERS_CLUB = { "300", "301", "302", "303", "304", "305", "309", "36", "38", "39" }; + public static String[] PREFIXES_VISA = { "4" }; + public static String[] PREFIXES_MASTERCARD = { + "2221", "2222", "2223", "2224", "2225", "2226", "2227", "2228", "2229", + "223", "224", "225", "226", "227", "228", "229", + "23", "24", "25", "26", + "270", "271", "2720", + "50", "51", "52", "53", "54", "55" + }; + + public static int MAX_LENGTH_STANDARD = 16; + public static int MAX_LENGTH_AMERICAN_EXPRESS = 15; + public static int MAX_LENGTH_DINERS_CLUB = 14; + + public String Number { get; private set; } + public String CVC { get; private set; } + public int ExpiryMonth { get; private set; } + public int ExpiryYear { get; private set; } + public String Name { get; set; } + public String AddressLine1 { get; set; } + public String AddressLine2 { get; set; } + public String AddressCity { get; set; } + public String AddressState { get; set; } + public String AddressZip { get; set; } + public String AddressCountry { get; set; } + public String Last4 { get; private set; } + public String Brand { get; private set; } // @CardBrand + public String Funding { get; private set; } // @FundingType + public String Fingerprint { get; private set; } + public String Country { get; private set; } + public String Currency { get; set; } + public String Id { get; private set; } + + /// + /// Card constructor with all available fields. + /// + /// the card number + /// the expiry month + /// the expiry year + /// the CVC code + /// the cardholder name + /// the first line of the billing address + /// the second line of the billing address + /// the city of the billing address + /// the state of the billing address + /// the zip code of the billing address + /// the country of the billing address + /// brand of this card + /// last 4 digits of the card + /// the card fingerprint + /// the funding type of the card + /// ISO country code of the card itself + /// the currency of the card + /// the cardId + public Card( + String number, + int expMonth, + int expYear, + string cvc, + string name, + string addressLine1, + string addressLine2, + string addressCity, + string addressState, + string addressZip, + string addressCountry, + string brand, + string last4, + string fingerprint, + string funding, + string country, + string currency, + string id) + { + Number = StripeTextUtils.NullIfBlank(NormalizeCardNumber(number)); + ExpiryMonth = expMonth; + ExpiryYear = expYear; + CVC = StripeTextUtils.NullIfBlank(cvc); + Name = StripeTextUtils.NullIfBlank(name); + AddressLine1 = StripeTextUtils.NullIfBlank(addressLine1); + AddressLine2 = StripeTextUtils.NullIfBlank(addressLine2); + AddressCity = StripeTextUtils.NullIfBlank(addressCity); + AddressState = StripeTextUtils.NullIfBlank(addressState); + AddressZip = StripeTextUtils.NullIfBlank(addressZip); + AddressCountry = StripeTextUtils.NullIfBlank(addressCountry); + Brand = StripeTextUtils.AsCardBrand(brand) == null ? GetBrand() : brand; + Last4 = StripeTextUtils.NullIfBlank(last4) == null ? GetLast4() : last4; + Fingerprint = StripeTextUtils.NullIfBlank(fingerprint); + Funding = StripeTextUtils.AsFundingType(funding); + Country = StripeTextUtils.NullIfBlank(country); + Currency = StripeTextUtils.NullIfBlank(currency); + Id = StripeTextUtils.NullIfBlank(id); + } + + /// + /// Convenience constructor with address and currency. + /// + /// the card number + /// the expiry month + /// the expiry year + /// the CVC code + /// the cardholder name + /// the first line of the billing address + /// the second line of the billing address + /// the city of the billing address + /// the state of the billing address + /// the zip code of the billing address + /// the country of the billing address + /// the currency of the card + public Card( + string number, + int expMonth, + int expYear, + string cvc, + string name, + string addressLine1, + string addressLine2, + string addressCity, + string addressState, + string addressZip, + string addressCountry, + string currency) + : this(number, + expMonth, + expYear, + cvc, + name, + addressLine1, + addressLine2, + addressCity, + addressState, + addressZip, + addressCountry, + null, + null, + null, + null, + null, + currency, + null) + { + } + + /// + /// Convenience constructor for a Card object with a minimum number of inputs. + /// + /// the card number + /// the expiry month + /// the expiry year + /// the CVC code + public Card(String number, int expMonth, int expYear, String cvc) + : this(number, + expMonth, + expYear, + cvc, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null) + { + } + + /// + /// Checks whether represents a valid card. + /// + /// if valid, otherwise. + public bool ValidateCard() + { + if (CVC == null) + { + return ValidateNumber() && ValidateExpireDate(); + } + else + { + return ValidateNumber() && ValidateExpireDate() && ValidateCVC(); + } + } + + /// + /// Checks whether or not the property is valid. + /// + /// if valid, otherwise. + public bool ValidateNumber() + { + return CardUtils.IsValidCardNumber(Number); + } + + /// + /// Checks whether or not the and properties represent a valid + /// + /// if valid, otherwise + public bool ValidateExpireDate() + { + if (!ValidateExpiryMonth()) + { + return false; + } + if (!ValidateExpiryYear()) + { + return false; + } + return !DateUtils.HasMonthPassed(ExpiryYear, ExpiryMonth); + } + + /// + /// Checks whether or not the property is valid. + /// + /// if valid, otherwise + public bool ValidateCVC() + { + if (string.IsNullOrWhiteSpace(CVC)) + { + return false; + } + String cvcValue = CVC.Trim(); + String updatedType = GetBrand(); + bool validLength = + (updatedType == null && cvcValue.Length >= 3 && cvcValue.Length <= 4) + || (AMERICAN_EXPRESS.Equals(updatedType) && cvcValue.Length == 4) + || cvcValue.Length == 3; + + return StripeTextUtils.IsWholePositiveNumber(cvcValue) && validLength; + } + + /// + /// Checks whether or not the property is valid. + /// + /// if valid, otherwise. + public bool ValidateExpiryMonth() + { + return ExpiryMonth >= 1 && ExpiryMonth <= 12; + } + + /// + /// Checks whether or not the property is valid. + /// + /// if valid, otherwise. + public bool ValidateExpiryYear() + { + return !DateUtils.HasYearPassed(ExpiryYear); + } + + /// + /// + /// + /// the digits of this card. Sets the value based on the + /// if it has not already been set. + public string GetLast4() + { + if (!string.IsNullOrWhiteSpace(Last4)) + { + return Last4; + } + + if (Number != null && Number.Length > 4) + { + Last4 = Number.Substring(Number.Length - 4); + return Last4; + } + + return null; + } + + /// + /// Gets the of this card. Updates the value if none has yet been set, or + /// if the has been changed. + /// + /// the of this card + public string GetBrand() + { + if (string.IsNullOrWhiteSpace(Brand) && !string.IsNullOrWhiteSpace(Number)) + { + /*@CardBrand*/ + String evaluatedType; + if (StripeTextUtils.HasAnyPrefix(Number, PREFIXES_AMERICAN_EXPRESS)) + { + evaluatedType = AMERICAN_EXPRESS; + } + else if (StripeTextUtils.HasAnyPrefix(Number, PREFIXES_DISCOVER)) + { + evaluatedType = DISCOVER; + } + else if (StripeTextUtils.HasAnyPrefix(Number, PREFIXES_JCB)) + { + evaluatedType = JCB; + } + else if (StripeTextUtils.HasAnyPrefix(Number, PREFIXES_DINERS_CLUB)) + { + evaluatedType = DINERS_CLUB; + } + else if (StripeTextUtils.HasAnyPrefix(Number, PREFIXES_VISA)) + { + evaluatedType = VISA; + } + else if (StripeTextUtils.HasAnyPrefix(Number, PREFIXES_MASTERCARD)) + { + evaluatedType = MASTERCARD; + } + else + { + evaluatedType = UNKNOWN; + } + + Brand = evaluatedType; + } + + return Brand; + } + + private String NormalizeCardNumber(String number) + { + if (number == null) + { + return null; + } + + return Regex.Replace(number.Trim(), "\\s+|-", ""); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/ViewModels/Payments/Stripe/CardUtils.cs b/TelegramClient.WP81/ViewModels/Payments/Stripe/CardUtils.cs new file mode 100755 index 0000000..b0159ec --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/Stripe/CardUtils.cs @@ -0,0 +1,229 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace TelegramClient.ViewModels.Payments.Stripe +{ + public class CardUtils + { + public static int LENGTH_COMMON_CARD = 16; + public static int LENGTH_AMERICAN_EXPRESS = 15; + public static int LENGTH_DINERS_CLUB = 14; + + public static int CVC_LENGTH_COMMON = 3; + public static int CVC_LENGTH_AMEX = 4; + + public static bool IsValidCardNumber(string cardNumber) + { + var normalizedNumber = StripeTextUtils.RemoveSpacesAndHyphens(cardNumber); + return IsValidLuhnNumber(normalizedNumber) && IsValidCardLength(normalizedNumber); + } + + /// + /// Checks the input string to see whether or not it is a valid Luhn number. + /// + /// a String that may or may not represent a valid Luhn number + /// if and only if the input value is a valid Luhn number + public static bool IsValidLuhnNumber(string cardNumber) + { + if (cardNumber == null) + { + return false; + } + + bool isOdd = true; + int sum = 0; + + for (int index = cardNumber.Length - 1; index >= 0; index--) + { + char c = cardNumber[index]; + if (!char.IsDigit(c)) + { + return false; + } + + int digitInteger = c - '0'; + isOdd = !isOdd; + + if (isOdd) + { + digitInteger *= 2; + } + + if (digitInteger > 9) + { + digitInteger -= 9; + } + + sum += digitInteger; + } + + return sum % 10 == 0; + } + + /// + /// Checks to see whether the input number is of the correct length, after determining its brand. + /// This function does not perform a Luhn check. + /// + /// the card number with no spaces or dashes + /// if the card number is of known type and the correct length + public static bool IsValidCardLength(string cardNumber) + { + if (cardNumber == null) + { + return false; + } + + return IsValidCardLength(cardNumber, GetPossibleCardType(cardNumber, false)); + } + + /// + /// Checks to see whether the input number is of the correct length, given the assumed brand of + /// the card. This function does not perform a Luhn check. + /// + /// the card number with no spaces or dashes + /// a {@link CardBrand} used to get the correct size + /// if the card number is the correct length for the assumed brand + public static bool IsValidCardLength(string cardNumber, string cardBrand) + { + if (cardNumber == null || Card.UNKNOWN.Equals(cardBrand)) + { + return false; + } + + int length = cardNumber.Length; + switch (cardBrand) + { + case Card.AMERICAN_EXPRESS: + return length == LENGTH_AMERICAN_EXPRESS; + case Card.DINERS_CLUB: + return length == LENGTH_DINERS_CLUB; + default: + return length == LENGTH_COMMON_CARD; + } + } + + /// + /// Returns a {@link CardBrand} corresponding to a partial card number, + /// or {@link Card#UNKNOWN} if the card brand can't be determined from the input value. + /// + /// a credit card number or partial card number + /// the {@link CardBrand} corresponding to that number, + /// or {@link Card#UNKNOWN} if it can't be determined + public static string GetPossibleCardType(string cardNumber) + { + return GetPossibleCardType(cardNumber, true); + } + + //@NonNull + //@CardBrand + private static string GetPossibleCardType(string cardNumber, bool shouldNormalize) + { + if (string.IsNullOrWhiteSpace(cardNumber)) + { + return Card.UNKNOWN; + } + + var spacelessCardNumber = cardNumber; + if (shouldNormalize) + { + spacelessCardNumber = StripeTextUtils.RemoveSpacesAndHyphens(cardNumber); + } + + if (StripeTextUtils.HasAnyPrefix(spacelessCardNumber, Card.PREFIXES_AMERICAN_EXPRESS)) + { + return Card.AMERICAN_EXPRESS; + } + else if (StripeTextUtils.HasAnyPrefix(spacelessCardNumber, Card.PREFIXES_DISCOVER)) + { + return Card.DISCOVER; + } + else if (StripeTextUtils.HasAnyPrefix(spacelessCardNumber, Card.PREFIXES_JCB)) + { + return Card.JCB; + } + else if (StripeTextUtils.HasAnyPrefix(spacelessCardNumber, Card.PREFIXES_DINERS_CLUB)) + { + return Card.DINERS_CLUB; + } + else if (StripeTextUtils.HasAnyPrefix(spacelessCardNumber, Card.PREFIXES_VISA)) + { + return Card.VISA; + } + else if (StripeTextUtils.HasAnyPrefix(spacelessCardNumber, Card.PREFIXES_MASTERCARD)) + { + return Card.MASTERCARD; + } + else + { + return Card.UNKNOWN; + } + } + + /// + /// Separates a card number according to the brand requirements, including prefixes of card + /// numbers, so that the groups can be easily displayed if the user is typing them in. + /// Note that this does not verify that the card number is valid, or even that it is a number. + /// + /// the raw card number, without spaces + /// the {@link CardBrand} to use as a separating scheme + /// an array of strings with the number groups, in order. If the number is not complete, + /// some of the array entries may be . + public static String[] SeparateCardNumberGroups(string spacelessCardNumber, string brand) + { + String[] numberGroups; + if (brand.Equals(Card.AMERICAN_EXPRESS)) + { + numberGroups = new String[3]; + + int length = spacelessCardNumber.Length; + int lastUsedIndex = 0; + if (length > 4) + { + numberGroups[0] = spacelessCardNumber.Substring(0, 4); + lastUsedIndex = 4; + } + + if (length > 10) + { + numberGroups[1] = spacelessCardNumber.Substring(4, 6); + lastUsedIndex = 10; + } + + for (int i = 0; i < 3; i++) + { + if (numberGroups[i] != null) + { + continue; + } + numberGroups[i] = spacelessCardNumber.Substring(lastUsedIndex); + break; + } + + } + else + { + numberGroups = new String[4]; + int i = 0; + int previousStart = 0; + while ((i + 1) * 4 < spacelessCardNumber.Length) + { + String group = spacelessCardNumber.Substring(previousStart, ((i + 1) * 4) - previousStart); + numberGroups[i] = group; + previousStart = (i + 1) * 4; + i++; + } + // Always stuff whatever is left into the next available array entry. This handles + // incomplete numbers, full 16-digit numbers, and full 14-digit numbers + numberGroups[i] = spacelessCardNumber.Substring(previousStart); + } + return numberGroups; + } + + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/Stripe/DateUtils.cs b/TelegramClient.WP81/ViewModels/Payments/Stripe/DateUtils.cs new file mode 100755 index 0000000..1ef77fd --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/Stripe/DateUtils.cs @@ -0,0 +1,56 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; + +namespace TelegramClient.ViewModels.Payments.Stripe +{ + public class DateUtils + { + /// + /// Determines whether or not the input year has already passed. + /// + /// the input year, as a two or four-digit integer + /// if the year has passed, otherwise. + public static bool HasYearPassed(int year) + { + var normalized = NormalizeYear(year); + return normalized < DateTime.Now.Year; + } + + /// + /// Determines whether the input year-month pair has passed. + /// + /// the input year, as a two or four-digit integer + /// the input month + /// if the input time has passed, otherwise. + public static bool HasMonthPassed(int year, int month) + { + if (HasYearPassed(year)) + { + return true; + } + + // Expires at end of specified month, Calendar month starts at 0 + return NormalizeYear(year) == DateTime.Now.Year + && month < (DateTime.Now.Month + 1); + } + + // Convert two-digit year to full year if necessary + private static int NormalizeYear(int year) + { + if (year < 100 && year >= 0) + { + var currentYear = DateTime.Now.Year.ToString(); + var prefix = currentYear.Substring(0, currentYear.Length - 2); + year = int.Parse(String.Format("{0}{1}", prefix, year)); + } + + return year; + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/Stripe/JSON/Response.cs b/TelegramClient.WP81/ViewModels/Payments/Stripe/JSON/Response.cs new file mode 100755 index 0000000..7e1d4d7 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/Stripe/JSON/Response.cs @@ -0,0 +1,59 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace TelegramClient.ViewModels.Payments.Stripe.JSON +{ + public class Error + { + public string message { get; set; } + public string type { get; set; } + public string param { get; set; } + public string code { get; set; } + } + + public class RootObject + { + public Error error { get; set; } + public string id { get; set; } + public string @object { get; set; } + public Card card { get; set; } + public string client_ip { get; set; } + public int created { get; set; } + public bool livemode { get; set; } + public string type { get; set; } + public bool used { get; set; } + } + + public class Metadata + { + } + + public class Card + { + public string id { get; set; } + public string @object { get; set; } + public object address_city { get; set; } + public string address_country { get; set; } + public object address_line1 { get; set; } + public object address_line1_check { get; set; } + public object address_line2 { get; set; } + public object address_state { get; set; } + public string address_zip { get; set; } + public string address_zip_check { get; set; } + public string brand { get; set; } + public string country { get; set; } + public string cvc_check { get; set; } + public object dynamic_last4 { get; set; } + public int exp_month { get; set; } + public int exp_year { get; set; } + public string funding { get; set; } + public string last4 { get; set; } + public Metadata metadata { get; set; } + public string name { get; set; } + public object tokenization_method { get; set; } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/Stripe/StripeClient.cs b/TelegramClient.WP81/ViewModels/Payments/Stripe/StripeClient.cs new file mode 100755 index 0000000..242f4a5 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/Stripe/StripeClient.cs @@ -0,0 +1,93 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.IO; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Runtime.Serialization.Json; +using System.Text; +using System.Threading.Tasks; +using Windows.Data.Json; +using TelegramClient.ViewModels.Payments.Stripe.JSON; + +namespace TelegramClient.ViewModels.Payments.Stripe +{ + public class StripeClient : IDisposable + { + private readonly string _publishableKey; + + private HttpClient _client; + + public StripeClient(string publishableKey) + { + _publishableKey = publishableKey; + _client = new HttpClient(); + } + + public async Task CreateTokenAsync(Card card) + { + if (card == null) + { + throw new ArgumentNullException("card"); + } + + if (_client != null) + { + try + { + var parameters = StripeNetworkUtils.HashMapFromCard(card); + + var request = new HttpRequestMessage(HttpMethod.Post, "https://api.stripe.com/v1/tokens"); + var requestContent = new FormUrlEncodedContent(parameters); + + request.Headers.Authorization = new AuthenticationHeaderValue("Basic", GetAuthorizationHeaderValue(_publishableKey)); + request.Content = requestContent; + + var response = await _client.SendAsync(request); + var content = await response.Content.ReadAsStringAsync(); + var json = GetRootObject(content); + var token = new StripeToken {Id = json.id, Type = json.type, Error = json.error, Content = content}; + + return token; + } + catch + { + + } + } + + return null; + } + + public static RootObject GetRootObject(string payload) + { + var serializer = new DataContractJsonSerializer(typeof(RootObject)); + RootObject rootObject; + using (var stream = new MemoryStream(Encoding.Unicode.GetBytes(payload))) + { + rootObject = serializer.ReadObject(stream) as RootObject; + } + + return rootObject; + } + + private string GetAuthorizationHeaderValue(string apiKey) + { + return Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:", apiKey))); + } + + public void Dispose() + { + if (_client != null) + { + _client.Dispose(); + _client = null; + } + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/Stripe/StripeNetworkUtils.cs b/TelegramClient.WP81/ViewModels/Payments/Stripe/StripeNetworkUtils.cs new file mode 100755 index 0000000..ca79451 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/Stripe/StripeNetworkUtils.cs @@ -0,0 +1,64 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; + +namespace TelegramClient.ViewModels.Payments.Stripe +{ + /// + /// Utility class for static functions useful for networking and data transfer. You probably will + /// not need to call functions from this class in your code. + /// + public class StripeNetworkUtils + { + /// + /// A utility function to map the fields of a object into a we + /// can use in network communications. + /// + /// the to be read + /// a containing the appropriate values read from the card + public static Dictionary HashMapFromCard(Card card) + { + var cardParams = new Dictionary(); + cardParams["card[number]"] = StripeTextUtils.NullIfBlank(card.Number); + cardParams["card[cvc]"] = StripeTextUtils.NullIfBlank(card.CVC); + cardParams["card[exp_month]"] = card.ExpiryMonth.ToString(); + cardParams["card[exp_year]"] = card.ExpiryYear.ToString(); + cardParams["card[name]"] = StripeTextUtils.NullIfBlank(card.Name); + cardParams["card[currency]"] = StripeTextUtils.NullIfBlank(card.Currency); + cardParams["card[address_line1]"] = StripeTextUtils.NullIfBlank(card.AddressLine1); + cardParams["card[address_line2]"] = StripeTextUtils.NullIfBlank(card.AddressLine2); + cardParams["card[address_city]"] = StripeTextUtils.NullIfBlank(card.AddressCity); + cardParams["card[address_zip]"] = StripeTextUtils.NullIfBlank(card.AddressZip); + cardParams["card[address_state]"] = StripeTextUtils.NullIfBlank(card.AddressState); + cardParams["card[address_country]"] = StripeTextUtils.NullIfBlank(card.AddressCountry); + + // Remove all null values; they cause validation errors + RemoveNullParams(cardParams); + + return cardParams; + } + + /// + /// Remove null values from a map. This helps with JSON conversion and validation. + /// + /// a from which to remove the keys that have values + private static void RemoveNullParams(Dictionary mapToEdit) + { + // Remove all null values; they cause validation errors + foreach (String key in mapToEdit.Keys.ToList()) + { + if (mapToEdit[key] == null) + { + mapToEdit.Remove(key); + } + } + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/ViewModels/Payments/Stripe/StripeTextUtils.cs b/TelegramClient.WP81/ViewModels/Payments/Stripe/StripeTextUtils.cs new file mode 100755 index 0000000..f3e0062 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/Stripe/StripeTextUtils.cs @@ -0,0 +1,164 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Text.RegularExpressions; + +namespace TelegramClient.ViewModels.Payments.Stripe +{ + public class StripeTextUtils + { + /// + /// Check to see if the input number has any of the given prefixes. + /// + /// the number to test + /// the prefixes to test against + /// if number begins with any of the input prefixes + public static bool HasAnyPrefix(String number, params String[] prefixes) + { + if (number == null) + { + return false; + } + + foreach (String prefix in prefixes) + { + if (number.StartsWith(prefix)) + { + return true; + } + } + return false; + } + + /// + /// Check to see whether the input string is a whole, positive number. + /// + /// the input string to test + /// if the input value consists entirely of integers + public static bool IsWholePositiveNumber(String value) + { + if (value == null) + { + return false; + } + + // Refraining from using android's TextUtils in order to avoid + // depending on another package. + for (int i = 0; i < value.Length; i++) + { + if (!char.IsDigit(value[i])) + { + return false; + } + } + return true; + } + + /// + /// Swap for blank text values. + /// + /// an input string that may or may not be entirely whitespace + /// if the string is entirely whitespace, or the original value if not + public static string NullIfBlank(String value) + { + if (string.IsNullOrWhiteSpace(value)) + { + return null; + } + return value; + } + + /// + /// Converts a card number that may have spaces between the numbers into one without any spaces. + /// Note: method does not check that all characters are digits or spaces. + /// + /// a card number, for instance "4242 4242 4242 4242" + /// the input number minus any spaces, for instance "4242424242424242". + /// Returns if the input was or all spaces. + public static String RemoveSpacesAndHyphens(string cardNumberWithSpaces) + { + if (string.IsNullOrWhiteSpace(cardNumberWithSpaces)) + { + return null; + } + return Regex.Replace(cardNumberWithSpaces, "\\s|-", ""); + } + + /// + /// Converts an unchecked String value to a {@link CardBrand} or . + /// + /// a String that might match a {@link CardBrand} or be empty. + /// if the input is blank, else the appropriate {@link CardBrand}. + public static string AsCardBrand(string possibleCardType) + { + if (string.IsNullOrWhiteSpace(possibleCardType)) + { + return null; + } + + if (Card.AMERICAN_EXPRESS.Equals(possibleCardType, StringComparison.OrdinalIgnoreCase)) + { + return Card.AMERICAN_EXPRESS; + } + else if (Card.MASTERCARD.Equals(possibleCardType, StringComparison.OrdinalIgnoreCase)) + { + return Card.MASTERCARD; + } + else if (Card.DINERS_CLUB.Equals(possibleCardType, StringComparison.OrdinalIgnoreCase)) + { + return Card.DINERS_CLUB; + } + else if (Card.DISCOVER.Equals(possibleCardType, StringComparison.OrdinalIgnoreCase)) + { + return Card.DISCOVER; + } + else if (Card.JCB.Equals(possibleCardType, StringComparison.OrdinalIgnoreCase)) + { + return Card.JCB; + } + else if (Card.VISA.Equals(possibleCardType, StringComparison.OrdinalIgnoreCase)) + { + return Card.VISA; + } + else + { + return Card.UNKNOWN; + } + } + + /// + /// Converts an unchecked String value to a {@link FundingType} or . + /// + /// a String that might match a {@link FundingType} or be empty + /// if the input is blank, else the appropriate {@link FundingType} + public static string AsFundingType(string possibleFundingType) + { + if (string.IsNullOrWhiteSpace(possibleFundingType)) + { + return null; + } + + if (Card.FUNDING_CREDIT.Equals(possibleFundingType, StringComparison.OrdinalIgnoreCase)) + { + return Card.FUNDING_CREDIT; + } + else if (Card.FUNDING_DEBIT.Equals(possibleFundingType, StringComparison.OrdinalIgnoreCase)) + { + return Card.FUNDING_DEBIT; + } + else if (Card.FUNDING_PREPAID.Equals(possibleFundingType, StringComparison.OrdinalIgnoreCase)) + { + return Card.FUNDING_PREPAID; + } + else + { + return Card.FUNDING_UNKNOWN; + } + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/Stripe/StripeToken.cs b/TelegramClient.WP81/ViewModels/Payments/Stripe/StripeToken.cs new file mode 100755 index 0000000..bb80e7d --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/Stripe/StripeToken.cs @@ -0,0 +1,20 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using TelegramClient.ViewModels.Payments.Stripe.JSON; + +namespace TelegramClient.ViewModels.Payments.Stripe +{ + public class StripeToken + { + public string Id { get; set; } + public string Type { get; set; } + public Error Error { get; set; } + + public string Content { get; set; } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/ViewModels/Payments/WebCardInfoViewModel.cs b/TelegramClient.WP81/ViewModels/Payments/WebCardInfoViewModel.cs new file mode 100755 index 0000000..97988fe --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/WebCardInfoViewModel.cs @@ -0,0 +1,117 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Linq; +using System.Windows; +using Windows.Data.Json; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Services; + +namespace TelegramClient.ViewModels.Payments +{ + public class WebCardInfoViewModel : PaymentViewModelBase + { + public Uri Url { get; set; } + + private bool _removeCheckoutView; + + public WebCardInfoViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + if (PaymentInfo != null && PaymentInfo.Form != null && !TLString.IsNullOrEmpty(PaymentInfo.Form.Url)) + { + Url = new Uri(PaymentInfo.Form.Url.ToString(), UriKind.Absolute); + } + + _removeCheckoutView = StateService.RemoveCheckoutAndCardView; + StateService.RemoveCheckoutAndCardView = false; + } + + public void ScriptNotify(string value) + { + try + { + var obj = JsonObject.Parse(value); + IJsonValue eventType; + if (obj.TryGetValue("eventType", out eventType)) + { + if (string.Equals(eventType.GetString(), "payment_form_submit", StringComparison.OrdinalIgnoreCase)) + { + IJsonValue eventData; + if (obj.TryGetValue("eventData", out eventData)) + { + if (PaymentInfo != null) + { + var eventDataObject = eventData.GetObject(); + if (eventDataObject != null) + { + IJsonValue title; + if (eventDataObject.TryGetValue("title", out title)) + { + PaymentInfo.CredentialsTitle = title.Stringify().Trim('\"'); + } + + IJsonValue credentials; + if (eventDataObject.TryGetValue("credentials", out credentials)) + { + var paymentCredentials = new TLInputPaymentCredentials + { + Flags = new TLInt(0), + Data = new TLDataJSON + { + Data = new TLString(credentials.Stringify()) + } + }; + PaymentInfo.Credentials = paymentCredentials; + NavigateToNextStep(); + return; + } + } + } + + return; + } + + return; + } + } + + MessageBox.Show(value); + } + catch (Exception ex) + { + Telegram.Api.Helpers.Execute.ShowDebugMessage(string.Format("WebViewModel.ScriptNotify {0} exception {1}", value, ex)); + } + } + + public override void NavigateToNextStep() + { + if (_removeCheckoutView) + { + var backEntry = NavigationService.BackStack.FirstOrDefault(); + if (backEntry != null && backEntry.Source.ToString().Contains("CheckoutView.xaml")) + { + NavigationService.RemoveBackEntry(); + } + + backEntry = NavigationService.BackStack.FirstOrDefault(); + if (backEntry != null && (backEntry.Source.ToString().Contains("SavedCardInfoView.xaml") || backEntry.Source.ToString().Contains("CardInfoView.xaml") || backEntry.Source.ToString().Contains("WebCardInfoView.xaml"))) + { + NavigationService.RemoveBackEntry(); + } + } + + StateService.PaymentInfo = PaymentInfo; + NavigationService.UriFor().Navigate(); + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Payments/WebVerificationViewModel.cs b/TelegramClient.WP81/ViewModels/Payments/WebVerificationViewModel.cs new file mode 100755 index 0000000..bc12f41 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Payments/WebVerificationViewModel.cs @@ -0,0 +1,76 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.Services; + +namespace TelegramClient.ViewModels.Payments +{ + public class WebVerificationViewModel : PaymentViewModelBase + { + + public string Title + { + get + { + if (PaymentInfo != null) + { + if (PaymentInfo.Receipt != null) + { + if (PaymentInfo.Receipt.Invoice.Test) + { + return AppResources.TestReceipt; + } + + return AppResources.Receipt; + } + + if (PaymentInfo.Form != null) + { + if (PaymentInfo.Form.Invoice.Test) + { + return AppResources.TestCheckout; + } + + return AppResources.Checkout; + } + } + + return AppResources.Checkout; + } + } + + public Uri Url { get; set; } + + public WebVerificationViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + if (StateService.Url != null) + { + Url = new Uri(StateService.Url, UriKind.Absolute); + StateService.Url = null; + } + + if (StateService.RemoveBackEntry) + { + StateService.RemoveBackEntry = false; + NavigationService.RemoveBackEntry(); + } + } + + public override void NavigateToNextStep() + { + + } + } +} diff --git a/TelegramClient.WP81/ViewModels/Search/SearchSharedContactsViewModel.cs b/TelegramClient.WP81/ViewModels/Search/SearchSharedContactsViewModel.cs new file mode 100755 index 0000000..5036795 --- /dev/null +++ b/TelegramClient.WP81/ViewModels/Search/SearchSharedContactsViewModel.cs @@ -0,0 +1,157 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Caliburn.Micro; +using Telegram.Api.Aggregator; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.Services; +using Execute = Telegram.Api.Helpers.Execute; + +namespace TelegramClient.ViewModels.Search +{ + public class SearchSharedContactsViewModel : ItemsViewModelBase + { + private string _text; + + public string Text + { + get { return _text; } + set { SetField(ref _text, value, () => Text); } + } + + public Action AttachAction; + + public SearchSharedContactsViewModel(ICacheService cacheService, ICommonErrorHandler errorHandler, IStateService stateService, INavigationService navigationService, IMTProtoService mtProtoService, ITelegramEventAggregator eventAggregator) + : base(cacheService, errorHandler, stateService, navigationService, mtProtoService, eventAggregator) + { + Items = new ObservableCollection(); + Status = AppResources.NoResults; + + PropertyChanged += (sender, args) => + { + if (Property.NameEquals(args.PropertyName, () => Text)) + { + if (string.IsNullOrEmpty(Text)) + { + Search(); + } + else + { + var text = Text; + BeginOnUIThread(TimeSpan.FromSeconds(0.2), () => + { + if (!string.Equals(Text, text)) return; + + Search(); + }); + } + } + }; + } + + public void UserAction(TLUserBase user) + { + if (user == null) return; + + AttachAction.SafeInvoke(user); + } + + private SearchUsersRequest _lastUsersRequest; + + public IList Source { get; set; } + + private readonly LRUCache _searchResultsCache = new LRUCache(Constants.MaxCacheCapacity); + + public void Search() + { + if (_lastUsersRequest != null) + { + _lastUsersRequest.Cancel(); + } + + var text = Text.Trim(); + + if (string.IsNullOrEmpty(text)) + { + System.Diagnostics.Debug.WriteLine("EmptyText text={0} canceled={1} items_count={2} current_text={3}", text, _lastUsersRequest != null ? _lastUsersRequest.IsCanceled.ToString() : "null", LazyItems.Count, Text); + + LazyItems.Clear(); + Items.Clear(); + Status = string.Empty; + return; + } + + SearchUsersRequest nextUsersRequest; + if (!_searchResultsCache.TryGetValue(text, out nextUsersRequest)) + { + IList source; + + if (_lastUsersRequest != null + && text.IndexOf(_lastUsersRequest.Text, StringComparison.OrdinalIgnoreCase) != -1) + { + source = _lastUsersRequest.Source; + } + else + { + source = Source; + } + + nextUsersRequest = new SearchUsersRequest(text, source); + } + + IsWorking = true; + nextUsersRequest.ProcessAsync(results => + Execute.BeginOnUIThread(() => + { + if (nextUsersRequest.IsCanceled) return; + + Items.Clear(); + LazyItems.Clear(); + for (var i = 0; i < results.Count; i++) + { + if (i < 6) + { + Items.Add(results[i]); + } + else + { + LazyItems.Add(results[i]); + } + } + Status = Items.Count > 0 ? string.Empty : AppResources.NoResults; + + IsWorking = false; + if (LazyItems.Count > 0) + { + Execute.BeginOnUIThread(() => + { + if (nextUsersRequest.IsCanceled) return; + + System.Diagnostics.Debug.WriteLine("ContinueResults text={0} canceled={1} items_count={2} current_text={3}", nextUsersRequest.Text, nextUsersRequest.IsCanceled, LazyItems.Count, Text); + + foreach (var item in LazyItems) + { + Items.Add(item); + } + LazyItems.Clear(); + Status = Items.Count > 0 ? string.Empty : AppResources.NoResults; + }); + } + })); + _searchResultsCache[nextUsersRequest.Text] = nextUsersRequest; + _lastUsersRequest = nextUsersRequest; + } + } +} diff --git a/TelegramClient.WP81/Views/Additional/BioView.xaml b/TelegramClient.WP81/Views/Additional/BioView.xaml new file mode 100755 index 0000000..44dce2a --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/BioView.xaml @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/BioView.xaml.cs b/TelegramClient.WP81/Views/Additional/BioView.xaml.cs new file mode 100755 index 0000000..9d4f264 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/BioView.xaml.cs @@ -0,0 +1,77 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using Caliburn.Micro; +using Microsoft.Phone.Shell; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.ViewModels.Additional; + +namespace TelegramClient.Views.Additional +{ + public partial class BioView + { + private readonly AppBarButton _doneButton = new AppBarButton + { + Text = AppResources.Done, + IconUri = new Uri("/Images/ApplicationBar/appbar.check.png", UriKind.Relative) + }; + + private readonly AppBarButton _cancelButton = new AppBarButton + { + Text = AppResources.Cancel, + IconUri = new Uri("/Images/ApplicationBar/appbar.cancel.rest.png", UriKind.Relative) + }; + + public BioViewModel ViewModel + { + get { return DataContext as BioViewModel; } + } + + public BioView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + + _doneButton.Click += (sender, args) => ViewModel.Done(); + _cancelButton.Click += (sender, args) => ViewModel.Cancel(); + + Loaded += (sender, args) => + { + Counter.Text = (Input.MaxLength - Input.Text.Length).ToString(CultureInfo.InvariantCulture); + + BuildLocalizedAppBar(); + }; + } + + private void BuildLocalizedAppBar() + { + return; + if (ApplicationBar != null) return; + + ApplicationBar = new ApplicationBar(); + ApplicationBar.Buttons.Add(_doneButton); + ApplicationBar.Buttons.Add(_cancelButton); + } + + private void TextBox_OnTextChanged(object sender, TextChangedEventArgs e) + { + Counter.Text = (Input.MaxLength - Input.Text.Length).ToString(CultureInfo.InvariantCulture); + } + + private void DoneButton_OnClick(object sender, GestureEventArgs e) + { + ViewModel.Done(); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/CallsPrivacyView.xaml b/TelegramClient.WP81/Views/Additional/CallsPrivacyView.xaml new file mode 100755 index 0000000..e10ece8 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/CallsPrivacyView.xaml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/CallsPrivacyView.xaml.cs b/TelegramClient.WP81/Views/Additional/CallsPrivacyView.xaml.cs new file mode 100755 index 0000000..d2e1e71 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/CallsPrivacyView.xaml.cs @@ -0,0 +1,75 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Controls; +using Caliburn.Micro; +using Microsoft.Phone.Shell; +using Telegram.Api.TL; +using TelegramClient.Resources; +using TelegramClient.ViewModels.Additional; + +namespace TelegramClient.Views.Additional +{ + public partial class CallsPrivacyView + { + private readonly AppBarButton _doneButton = new AppBarButton + { + Text = AppResources.Done, + IconUri = new Uri("/Images/ApplicationBar/appbar.check.png", UriKind.Relative) + }; + + private readonly AppBarButton _cancelButton = new AppBarButton + { + Text = AppResources.Cancel, + IconUri = new Uri("/Images/ApplicationBar/appbar.cancel.rest.png", UriKind.Relative) + }; + + public CallsPrivacyViewModel ViewModel + { + get { return DataContext as CallsPrivacyViewModel; } + } + + public CallsPrivacyView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + + _doneButton.Click += (sender, args) => ViewModel.Done(); + _cancelButton.Click += (sender, args) => ViewModel.Cancel(); + + Loaded += (sender, args) => + { + BuildLocalizedAppBar(); + }; + } + + private void BuildLocalizedAppBar() + { + if (ApplicationBar != null) return; + + ApplicationBar = new ApplicationBar(); + ApplicationBar.Buttons.Add(_doneButton); + ApplicationBar.Buttons.Add(_cancelButton); + } + + private void ToggleButton_OnChecked(object sender, RoutedEventArgs e) + { + var radioButton = sender as RadioButton; + if (radioButton != null) + { + var privacyRule = radioButton.DataContext as TLPrivacyRuleBase; + if (privacyRule != null) + { + ViewModel.SelectedMainRule = privacyRule; + } + } + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/CallsSecurityView.xaml b/TelegramClient.WP81/Views/Additional/CallsSecurityView.xaml new file mode 100755 index 0000000..0a545f7 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/CallsSecurityView.xaml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/CallsSecurityView.xaml.cs b/TelegramClient.WP81/Views/Additional/CallsSecurityView.xaml.cs new file mode 100755 index 0000000..222b810 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/CallsSecurityView.xaml.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace TelegramClient.Views.Additional +{ + public partial class CallsSecurityView + { + public CallsSecurityView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/CameraView.xaml b/TelegramClient.WP81/Views/Additional/CameraView.xaml new file mode 100755 index 0000000..e007178 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/CameraView.xaml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/CameraView.xaml.cs b/TelegramClient.WP81/Views/Additional/CameraView.xaml.cs new file mode 100755 index 0000000..b43a9cb --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/CameraView.xaml.cs @@ -0,0 +1,42 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Controls; +using Telegram.Api.TL; +using TelegramClient.ViewModels.Additional; + +namespace TelegramClient.Views.Additional +{ + public partial class CameraView + { + public CameraViewModel ViewModel + { + get { return DataContext as CameraViewModel; } + } + + public CameraView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + } + + private void ToggleButton_OnChecked(object sender, RoutedEventArgs e) + { + var radioButton = sender as RadioButton; + if (radioButton != null) + { + var privacyRule = radioButton.DataContext as TLPrivacyRuleBase; + if (privacyRule != null) + { + ViewModel.SelectedMainRule = privacyRule; + } + } + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/ChooseGeoLivePeriodView.xaml b/TelegramClient.WP81/Views/Additional/ChooseGeoLivePeriodView.xaml new file mode 100755 index 0000000..b41f7f9 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/ChooseGeoLivePeriodView.xaml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/ChooseGeoLivePeriodView.xaml.cs b/TelegramClient.WP81/Views/Additional/ChooseGeoLivePeriodView.xaml.cs new file mode 100755 index 0000000..86bb828 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/ChooseGeoLivePeriodView.xaml.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; + +namespace TelegramClient.Views.Additional +{ + public partial class ChooseGeoLivePeriodView + { + public ChooseGeoLivePeriodView() + { + InitializeComponent(); + + var isFullHD = Application.Current.Host.Content.ScaleFactor == 225; + if (isFullHD || Environment.OSVersion.Version.Major >= 10) + { + Period15Minutes.FontSize = 20.0; + Period1Hour.FontSize = 20.0; + Period8Hours.FontSize = 20.0; + } + } + } +} diff --git a/TelegramClient.WP81/Views/Additional/ChooseVideoQualityView.xaml b/TelegramClient.WP81/Views/Additional/ChooseVideoQualityView.xaml new file mode 100755 index 0000000..64b4e3c --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/ChooseVideoQualityView.xaml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/ChooseVideoQualityView.xaml.cs b/TelegramClient.WP81/Views/Additional/ChooseVideoQualityView.xaml.cs new file mode 100755 index 0000000..0ef3c0c --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/ChooseVideoQualityView.xaml.cs @@ -0,0 +1,27 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Navigation; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; + +namespace TelegramClient.Views.Additional +{ + public partial class ChooseVideoQualityView : UserControl + { + public ChooseVideoQualityView() + { + InitializeComponent(); + } + } +} diff --git a/TelegramClient.WP81/Views/Additional/ContactsSecurityView.xaml b/TelegramClient.WP81/Views/Additional/ContactsSecurityView.xaml new file mode 100755 index 0000000..a72b4c4 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/ContactsSecurityView.xaml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/ContactsSecurityView.xaml.cs b/TelegramClient.WP81/Views/Additional/ContactsSecurityView.xaml.cs new file mode 100755 index 0000000..a4aece0 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/ContactsSecurityView.xaml.cs @@ -0,0 +1,19 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace TelegramClient.Views.Additional +{ + public partial class ContactsSecurityView + { + public ContactsSecurityView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/GifPlayerControl.xaml b/TelegramClient.WP81/Views/Additional/GifPlayerControl.xaml new file mode 100755 index 0000000..1b87201 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/GifPlayerControl.xaml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/GifPlayerControl.xaml.cs b/TelegramClient.WP81/Views/Additional/GifPlayerControl.xaml.cs new file mode 100755 index 0000000..6f0dd54 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/GifPlayerControl.xaml.cs @@ -0,0 +1,1779 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.IsolatedStorage; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Threading; +using Windows.Foundation.Metadata; +using Windows.Graphics.Imaging; +using Windows.Storage; +using Caliburn.Micro; +using FFmpegInterop; +using Microsoft.Devices; +using Microsoft.Phone; +using Telegram.Api.Services.FileManager; +using Telegram.Api.TL; +using Telegram.Controls.Extensions; +using TelegramClient.Controls; +using TelegramClient.Converters; +using TelegramClient.Helpers; +using TelegramClient.Services; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.Views.Controls; +using TelegramClient.Views.Dialogs; +using Buffer = System.Buffer; +using Execute = Telegram.Api.Helpers.Execute; + +namespace TelegramClient.Views.Additional +{ + public partial class GifPlayerControl + { + #region Dispatcher Timer + + private static readonly DispatcherTimer _dispatcherTimer; + + static GifPlayerControl() + { + _dispatcherTimer = new DispatcherTimer{ Interval = TimeSpan.FromMilliseconds(50.0) }; + _dispatcherTimer.Tick += (sender, args) => + { + //VibrateController.Default.Start(TimeSpan.FromMilliseconds(15.0)); + foreach (var player in ActivePlayers) + { + player.UpdateFrame(); + } + + foreach (var inlinePlayer in InlineBotActivePlayers) + { + inlinePlayer.UpdateFrame(); + } + }; + } + + private void UpdateFrame() + { + var pixels = _frame; + if (pixels != null) + { + _frame = null; + + try + { + if (PlayButton.Visibility == Visibility.Visible) return; + + var bitmap = Frame.Source as WriteableBitmap; + if (bitmap == null || bitmap.PixelWidth != _w || bitmap.PixelHeight != _h) + { + bitmap = new WriteableBitmap(_w, _h); + + Frame.Source = bitmap; + } + for (var j = 0; j < bitmap.Pixels.Length; j++) + { + bitmap.Pixels[j] = + (pixels[j * 4 + 3] << 24) | //b + (pixels[j * 4 + 2] << 0) | //g + (pixels[j * 4 + 1] << 8) | //r + (pixels[j * 4] << 16); //a + + //bitmap.Pixels[j] = pixels[j]; + } + + bitmap.Invalidate(); + + if (Mode == GifPlayerMode.Normal) + { + //Debug.Text = string.Format("pts={0}\nptsDelta={1}\ntimeDelta={2}\nelapsed={3}", _pts, _ptsDelta, _timeDelta, _elapsed.TotalMilliseconds); + } + } + catch(Exception ex) + { + Execute.ShowDebugMessage("UpdateFrame exception " + ex); + } + } + } + + private static void StartUpdateFrames() + { + if (!_dispatcherTimer.IsEnabled) + { + _dispatcherTimer.Start(); + } + } + + private static void StopUpdateFrames() + { + if (_dispatcherTimer.IsEnabled) + { + _dispatcherTimer.Stop(); + } + } + #endregion + + private static readonly IList _inlineBotActivePlayers = new List(); + + public static IList InlineBotActivePlayers + { + get { return _inlineBotActivePlayers; } + } + + public static void StopInlineBotActivePlayers() + { + var players = new List(_inlineBotActivePlayers); + foreach (var player in players) + { + player.Stop(); + } + } + + private static readonly IList _activePlayers = new List(); + + public static IList ActivePlayers + { + get { return _activePlayers; } + } + + public static void ResumeActivePlayers(IList activePlayers) + { + var players = new List(_activePlayers); + _activePlayers.Clear(); + + var stoppedPlayers = new List(); + + foreach (var player in players) + { + if (!activePlayers.Contains(player)) + { + stoppedPlayers.Add(player); + } + } + + foreach (var player in activePlayers) + { + player.Resume(); + _activePlayers.Add(player); + } + + var autoPlayGif = false; + var stateService = IoC.Get(); + if (stateService != null) + { + var chatSettings = stateService.GetChatSettings(); + if (chatSettings != null) + { + autoPlayGif = chatSettings.AutoPlayGif; + } + + foreach (var player in stoppedPlayers) + { + if (!autoPlayGif) + { + if ((player.Media != null && player.Media.AutoPlayGif == true)) + { + autoPlayGif = true; + } + } + + player.Stop(autoPlayGif); + } + } + + if (_activePlayers.Count > 0) + { + StartUpdateFrames(); + } + } + + public static void PauseActivePlayers() + { + var players = new List(_activePlayers); + if (players.Count > 0) + { + foreach (var player in players) + { + player.Pause(); + } + } + + StopUpdateFrames(); + } + + public static void StopActivePlayers(bool scroll = false) + { + var players = new List(_activePlayers); + if (players.Count > 0) + { + var autoPlayGif = false; + var stateService = IoC.Get(); + if (stateService != null) + { + var chatSettings = stateService.GetChatSettings(); + if (chatSettings != null) + { + autoPlayGif = chatSettings.AutoPlayGif; + } + + foreach (var player in players) + { + if (!autoPlayGif) + { + if (player.Media != null && player.Media.AutoPlayGif == true) + { + autoPlayGif = true; + } + } + + player.Stop(autoPlayGif); + } + } + } + } + + public static readonly DependencyProperty ModeProperty = DependencyProperty.Register( + "Mode", typeof (GifPlayerMode), typeof (GifPlayerControl), new PropertyMetadata(default(GifPlayerMode), OnModeChanged)); + + private static void OnModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var player = d as GifPlayerControl; + if (player != null) + { + var mode = (GifPlayerMode) e.NewValue; + if (mode == GifPlayerMode.InlineResult) + { + player.Button.RenderTransform = new ScaleTransform { ScaleX = 0.5, ScaleY = 0.5, CenterX = 23.5, CenterY = 23.5 }; + player.Play.Opacity = 0.0; + player.PlayCircle.Opacity = 0.0; + player.DownloadButton.Opacity = 0.0; + player.CancelDownloadButton.CancelVisibility = Visibility.Collapsed; + } + else if (mode == GifPlayerMode.RoundVideo) + { + + } + else + { + player.Button.RenderTransform = null; + } + } + } + + public GifPlayerMode Mode + { + get { return (GifPlayerMode) GetValue(ModeProperty); } + set { SetValue(ModeProperty, value); } + } + + public static readonly DependencyProperty UploadingProgressProperty = DependencyProperty.Register( + "UploadingProgress", typeof(double), typeof(GifPlayerControl), new PropertyMetadata(default(double), OnUploadingProgressChanged)); + + public double UploadingProgress + { + get { return (double) GetValue(UploadingProgressProperty); } + set { SetValue(UploadingProgressProperty, value); } + } + + private static void OnUploadingProgressChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var player = d as GifPlayerControl; + if (player == null) return; + + if (e.NewValue is double) + { + var progress = (double)e.NewValue; + + player.CancelDownloadButton.Value = progress; + + var isComplete = e.NewValue != null + && e.OldValue != null + && (double)e.OldValue > 0.0 + && (double)e.OldValue < 1.0 + && (double)e.NewValue == 0.0; + if (isComplete) + { + return; + } + + var isVisible = progress > 0.0 && progress < 1.0; + OnProgressChangedInternal(isVisible, player, progress); + } + } + + public static readonly DependencyProperty ProgressProperty = DependencyProperty.Register( + "Progress", typeof (double), typeof (GifPlayerControl), new PropertyMetadata(default(double), OnProgressChanged)); + + public double Progress + { + get { return (double) GetValue(ProgressProperty); } + set { SetValue(ProgressProperty, value); } + } + + private void CancelDownloadButton_OnCompleted(object sender, System.EventArgs e) + { + OnProgressChangedInternal(false, this, 0.0); + } + + private static void OnProgressChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var player = d as GifPlayerControl; + if (player == null) return; + + if (e.NewValue is double) + { + var progress = (double)e.NewValue; + + player.CancelDownloadButton.Value = progress; + + var isVisible = progress > 0.0 && progress < 1.0; + OnProgressChangedInternal(isVisible, player, progress); + } + } + + private static void OnProgressChangedInternal(bool isVisible, GifPlayerControl player, double progress) + { + if (!isVisible) + { + var localFileName = GetLocalFileName(player.Media); + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (!store.FileExists(localFileName)) + { + player.ChangeButtonState(GifButtonState.Download); + } + else + { + player.ChangeButtonState(GifButtonState.Play, "OnProgressChangedInternal1"); + } + } + } + else + { + player.ChangeButtonState(GifButtonState.Cancel); + } + + if (!player._initialized && (progress == 0.0)) + { + if (player.Mode == GifPlayerMode.Normal && !ActivePlayers.Contains(player)) + { + if (player.ActualHeight > 0.0 && player.ActualWidth > 0.0) + { + // new messages + var startNewGifPlayer = false; + + var position = player.TransformToVisual(Application.Current.RootVisual).Transform(new Point(0.0, 0.0)); + if (player.ActualHeight + position.Y >= 2.0/3.0*player.ActualHeight + && + position.Y <= + ((FrameworkElement) Application.Current.RootVisual).ActualHeight - 2.0/3.0*player.ActualHeight) + { + startNewGifPlayer = true; + ActivePlayers.Add(player); + } + + if (!startNewGifPlayer) + { + return; + } + } + } + + if (player.Mode == GifPlayerMode.InlineResult) + { + if (!IsScrolling) + { + player.Start(); + } + else + { + player.ChangeButtonState(GifButtonState.Play, "OnProgressChangedInternal2"); + } + } + else + { + var stateService = IoC.Get(); + if (stateService != null) + { + var chatSettings = stateService.GetChatSettings(); + if (ManipulationState == ManipulationState.Idle + && (chatSettings != null && chatSettings.AutoPlayGif && player.Media != null && player.Media.AutoPlayGif != false) + || (player.Media != null && player.Media.AutoPlayGif == true)) + { + player.Start(); + } + else + { + var localFileName = GetLocalFileName(player.Media); + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (!store.FileExists(localFileName)) + { + player.ChangeButtonState(GifButtonState.Download); + } + else + { + player.ChangeButtonState(GifButtonState.Play, "OnProgressChangedInternal3"); + } + } + } + } + } + } + } + + //public static async Task ExtractFirstFrame(IMediaGifBase mediaGifBase) + //{ + // if (mediaGifBase == null) return; + + // var fileName = GetLocalFileName(mediaGifBase); + + // var decoderParams = new int[3]; + // var handler = FFmpegGifDecoder.CreateDecoder(Path.Combine(ApplicationData.Current.LocalFolder.Path, fileName), decoderParams); + // if (handler != 0) + // { + // var w = decoderParams[0]; + // var h = decoderParams[1]; + + // if (w > 0 && h > 0) + // { + // var frame = FFmpegGifDecoder.GetVideoFrame(handler, decoderParams); + // if (frame != null) + // { + // var pixels = new byte[frame.Length * sizeof(int)]; + // Buffer.BlockCopy(frame, 0, pixels, 0, pixels.Length); + + // var previewFileName = GetFrameFileName(mediaGifBase); + // var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(previewFileName, CreationCollisionOption.ReplaceExisting); + // using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite)) + // { + // var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream); + // encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)w, (uint)h, 96.0, 96.0, pixels); + // await encoder.FlushAsync(); + // } + + // } + // } + + // FFmpegGifDecoder.DestroyDecoder(handler); + // } + //} + + public static readonly DependencyProperty MediaProperty = DependencyProperty.Register( + "Media", typeof(IMediaGifBase), typeof(GifPlayerControl), new PropertyMetadata(default(IMediaGifBase), OnMediaChanged)); + + public IMediaGifBase Media + { + get { return (IMediaGifBase)GetValue(MediaProperty); } + set { SetValue(MediaProperty, value); } + } + + public static ManipulationState ManipulationState { get; set; } + + public static bool IsScrolling { get; set; } + + private static void OnMediaChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var player = d as GifPlayerControl; + if (player != null) + { + player.Stop(); + player.Release(); + + var mediaBase = e.NewValue as IMediaGifBase; + if (mediaBase != null) + { + // preview + SetMediaPreview(player, mediaBase); + + // round video playing + if (player.Mode == GifPlayerMode.RoundVideo) + { + if (MessagePlayerControl.Player.CurrentState == MediaElementState.Playing) + { + var gifPlayerControl = MessagePlayerControl.Player.Tag as GifPlayerControl; + if (gifPlayerControl != null + && gifPlayerControl.Media == mediaBase) + { + var videoBrush = new VideoBrush(); + videoBrush.SetSource(MessagePlayerControl.Player); + player.MediaPlaceholder.Background = videoBrush; + player.MuteIcon.Visibility = Visibility.Collapsed; + + MessagePlayerControl.Player.Tag = player; + } + } + } + + // button state/downloading + var localFileName = GetLocalFileName(mediaBase); + + if (!string.IsNullOrEmpty(localFileName)) + { + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (store.FileExists(localFileName)) + { + var stateService = IoC.Get(); + var chatSettings = stateService.GetChatSettings(); + if (ManipulationState == ManipulationState.Idle + && (chatSettings != null && chatSettings.AutoPlayGif && player.Media != null && player.Media.AutoPlayGif != false) + || (player.Media != null && player.Media.AutoPlayGif == true)) + { + player.ChangeButtonState(GifButtonState.None, "OnMediaChanged"); + } + else + { + player.ChangeButtonState(GifButtonState.Play, "OnMediaChanged"); + } + + if (player.Mode == GifPlayerMode.Normal && !ActivePlayers.Contains(player)) + { + if (player.ActualHeight > 0.0 && player.ActualWidth > 0.0) + { + // new messages + var startNewGifPlayer = false; + + var position = player.TransformToVisual(Application.Current.RootVisual).Transform(new Point(0.0, 0.0)); + if (player.ActualHeight + position.Y >= 2.0 / 3.0 * player.ActualHeight + && position.Y <= ((FrameworkElement)Application.Current.RootVisual).ActualHeight - 2.0 / 3.0 * player.ActualHeight) + { + startNewGifPlayer = true; + ActivePlayers.Add(player); + } + + if (!startNewGifPlayer) + { + return; + } + } + } + } + else + { + player.ChangeButtonState(GifButtonState.Download); + + TLObject with = null; + var navigationService = IoC.Get(); + var dialogDetailsView = navigationService.CurrentContent as DialogDetailsView; + if (dialogDetailsView != null) + { + var dialogDetailsViewModel = dialogDetailsView.DataContext as DialogDetailsViewModel; + if (dialogDetailsViewModel != null) + { + with = dialogDetailsViewModel.With; + } + } + + var stateService = IoC.Get(); + var chatSettings = stateService.GetChatSettings(); + var downloadGif = true; + if (chatSettings != null) + { + if (with is TLUserBase && !chatSettings.AutoDownloadGifPrivateChats) + { + downloadGif = false; + } + + if (with is TLChatBase && !chatSettings.AutoDownloadGifGroups) + { + downloadGif = false; + } + } + + if (downloadGif && CheckDocumentParams(mediaBase)) + { + if (player.Mode == GifPlayerMode.InlineResult) + { + return; // suppress autodownload on media changed for inline bots + } + + DownloadGifAsync(mediaBase); + } + } + + return; + } + } + } + } + } + + private static string GetFrameFileName(IMediaGifBase mediaGifBase) + { + var frameFileName = string.Empty; + + var mediaGif = mediaGifBase as IMediaGif; + if (mediaGif != null) + { + var document = mediaGif.Document as TLDocument; + if (document != null) + { + frameFileName = string.Format("frame{0}.jpg", document.Id); + } + + var documentExternal = mediaGif.Document as TLDocumentExternal; + if (documentExternal != null) + { + frameFileName = string.Format("frame{0}.jpg", documentExternal.Id); + } + } + + var decryptedMediaGif = mediaGifBase as IDecryptedMediaGif; + if (decryptedMediaGif != null) + { + var document = decryptedMediaGif.Document; + if (document != null) + { + var fileLocatioin = document.File as TLEncryptedFile; + if (fileLocatioin != null) + { + frameFileName = string.Format("frame{0}.jpg", fileLocatioin.Id); + } + } + } + + return frameFileName; + } + + private static string GetLocalFileName(IMediaGifBase mediaGifBase) + { + var localFileName = string.Empty; + + var mediaGif = mediaGifBase as IMediaGif; + if (mediaGif != null) + { + var document = mediaGif.Document as TLDocument; + if (document != null) + { + localFileName = document.GetFileName(); + } + + var documentExternal = mediaGif.Document as TLDocumentExternal; + if (documentExternal != null) + { + localFileName = documentExternal.GetFileName(); + } + } + + var decryptedMediaGif = mediaGifBase as IDecryptedMediaGif; + if (decryptedMediaGif != null) + { + var document = decryptedMediaGif.Document; + if (document != null) + { + localFileName = document.GetFileName(); + } + } + + return localFileName; + } + + private static bool CheckDocumentParams(IMediaGifBase mediaGifBase) + { + var mediaGif = mediaGifBase as IMediaGif; + if (mediaGif != null) + { + var document = mediaGif.Document as TLDocument; + if (document != null) + { + return document.Size.Value <= Telegram.Api.Constants.AutoDownloadGifMaxSize; + } + } + + var decryptedMediaGif = mediaGifBase as IDecryptedMediaGif; + if (decryptedMediaGif != null) + { + var document = decryptedMediaGif.Document; + if (document != null) + { + return document.Size.Value <= Telegram.Api.Constants.AutoDownloadGifMaxSize; + } + } + + return true; + } + + private static void DownloadGifAsync(IMediaGifBase owner) + { + if (owner.Forbidden) return; + + var decryptedMediaGif = owner as IDecryptedMediaGif; + if (decryptedMediaGif != null) + { + var encryptedFile = decryptedMediaGif.Document.File as TLEncryptedFile; + if (encryptedFile != null) + { + owner.DownloadingProgress = 0.01; + + Execute.BeginOnThreadPool(() => + { + var fileManager = IoC.Get(); + fileManager.DownloadFile( + encryptedFile, + owner as TLObject, + async item => + { + var fileName = item.IsoFileName; + + var newFileName = String.Format("{0}_{1}_{2}.{3}", + encryptedFile.Id, + encryptedFile.DCId, + encryptedFile.AccessHash, + encryptedFile.FileExt ?? decryptedMediaGif.Document.FileExt); + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + byte[] buffer; + using (var file = store.OpenFile(fileName, FileMode.Open, FileAccess.Read)) + { + buffer = new byte[file.Length]; + file.Read(buffer, 0, buffer.Length); + } + + var decryptedBuffer = Telegram.Api.Helpers.Utils.AesIge(buffer, decryptedMediaGif.Document.Key.Data, decryptedMediaGif.Document.IV.Data, false); + + using (var file = store.OpenFile(newFileName, FileMode.OpenOrCreate, FileAccess.Write)) + { + file.Write(decryptedBuffer, 0, decryptedBuffer.Length); + } + + store.DeleteFile(fileName); + } + + //await ExtractFirstFrame(owner); + + Execute.BeginOnUIThread(() => + { + owner.IsCanceled = false; + owner.LastProgress = 0.0; + owner.DownloadingProgress = 0.0; + owner.IsoFileName = newFileName; + }); + }); + }); + } + + return; + } + + var mediaGif = owner as IMediaGif; + if (mediaGif != null) + { + var documentBase = mediaGif.Document; + + var documentExternal = documentBase as TLDocumentExternal; + if (documentExternal != null) + { + owner.DownloadingProgress = 0.01; + + var fileName = documentExternal.GetFileName(); + + var webClient = new WebClient(); + webClient.OpenReadAsync(new Uri(documentExternal.ContentUrl.ToString(), UriKind.Absolute)); + webClient.OpenReadCompleted += (sender2, args2) => Execute.BeginOnThreadPool(async () => + { + if (args2.Cancelled) + { + Execute.BeginOnUIThread(() => + { + owner.IsCanceled = false; + owner.LastProgress = 0.0; + owner.DownloadingProgress = 0.0; + }); + + Execute.ShowDebugMessage(args2.Cancelled.ToString()); + return; + } + if (args2.Error != null) + { + var webException = args2.Error as WebException; + if (webException != null) + { + var response = webException.Response as HttpWebResponse; + if (response != null) + { + if (response.StatusCode == HttpStatusCode.Forbidden) + { + Execute.BeginOnUIThread(() => + { + owner.Forbidden = true; + owner.IsCanceled = false; + owner.LastProgress = 0.0; + owner.DownloadingProgress = 0.0; + }); + } + else if (response.StatusCode == HttpStatusCode.NotFound) + { + Execute.BeginOnUIThread(TimeSpan.FromSeconds(5.0), () => + { + owner.IsCanceled = false; + owner.LastProgress = 0.0; + owner.DownloadingProgress = 0.0; + }); + } + + return; + } + } + + Execute.BeginOnUIThread(() => + { + owner.IsCanceled = false; + owner.LastProgress = 0.0; + owner.DownloadingProgress = 0.0; + }); + + Execute.ShowDebugMessage(args2.Error.ToString()); + return; + } + + try + { + using (var stream = args2.Result) + { + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (store.FileExists(fileName)) + { + store.DeleteFile(fileName); + } + + using (var file = store.OpenFile(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read)) + { + const int BUFFER_SIZE = 128 * 1024; + var buf = new byte[BUFFER_SIZE]; + + var bytesRead = 0; + while ((bytesRead = stream.Read(buf, 0, BUFFER_SIZE)) > 0) + { + file.Write(buf, 0, bytesRead); + } + } + } + } + + //await ExtractFirstFrame(owner); + + Execute.BeginOnUIThread(() => + { + owner.IsCanceled = false; + owner.LastProgress = 0.0; + owner.DownloadingProgress = 0.0; + }); + } + catch (Exception ex) + { + Execute.BeginOnUIThread(() => + { + owner.IsCanceled = false; + owner.LastProgress = 0.0; + owner.DownloadingProgress = 0.0; + }); + + Execute.ShowDebugMessage(ex.ToString()); + } + }); + + + return; + } + + var document = documentBase as TLDocument; + if (document != null) + { + owner.DownloadingProgress = 0.01; + + var fileManager = IoC.Get(); + fileManager.DownloadFileAsync( + document.FileName, + document.DCId, + document.ToInputFileLocation(), + owner as TLObject, + document.Size, + null, + async item => + { + //await ExtractFirstFrame(owner); + + Execute.BeginOnUIThread(() => + { + owner.IsCanceled = false; + owner.LastProgress = 0.0; + owner.DownloadingProgress = 0.0; + owner.IsoFileName = item.IsoFileName; + }); + }); + + return; + } + } + } + + private static void SetMediaPreview(GifPlayerControl player, IMediaGifBase mediaGifBase) + { + var frameFileName = GetFrameFileName(mediaGifBase); + player._firstFrameFileName = frameFileName; + player._extractFirstFrame = true; + + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (store.FileExists(frameFileName)) + { + player._extractFirstFrame = false; + try + { + using (var stream = store.OpenFile(frameFileName, FileMode.Open, FileAccess.Read)) + { + if (stream.Length > 0) + { + var bitmapImage = new BitmapImage(); + //bitmapImage.CreateOptions = BitmapCreateOptions.BackgroundCreation; + bitmapImage.SetSource(stream); + + player.Thumb.Source = bitmapImage; + return; + } + } + } + catch (Exception) + { + + } + } + } + + var decryptedMediaGif = mediaGifBase as IDecryptedMediaGif; + if (decryptedMediaGif != null) + { + var document = decryptedMediaGif.Document; + if (document != null) + { + var thumbCachedSize = document.Thumb; + if (thumbCachedSize != null + && thumbCachedSize.Data != null + && thumbCachedSize.Data.Length > 0 + && document.ThumbW.Value > 0 + && document.ThumbH.Value > 0) + { + BitmapImage preview; + try + { + var buffer = thumbCachedSize.Data; + var bitmap = PictureDecoder.DecodeJpeg(new MemoryStream(buffer)); + + new PhotoToThumbConverter().BlurBitmap(bitmap, false); + + var blurredStream = new MemoryStream(); + bitmap.SaveJpeg(blurredStream, document.ThumbW.Value, document.ThumbH.Value, 0, 100); + + player.Thumb.Source = ImageUtils.CreateImage(blurredStream); + } + catch (Exception ex) + { + + } + } + else + { + player.Thumb.Source = null; + } + } + } + + var mediaGif = mediaGifBase as IMediaGif; + if (mediaGif != null) + { + var documentBase = mediaGif.Document; + + var documentExternal = documentBase as TLDocumentExternal; + if (documentExternal != null) + { + if (!TLString.IsNullOrEmpty(documentExternal.ThumbUrl)) + { + player.Thumb.Source = new BitmapImage(new Uri(documentExternal.ThumbUrl.ToString(), UriKind.Absolute)); + } + else + { + player.Thumb.Source = null; + } + + return; + } + + var document = documentBase as TLDocument; + if (document != null) + { + var options = BitmapCreateOptions.DelayCreation | BitmapCreateOptions.BackgroundCreation; + var thumbCachedSize = document.Thumb as TLPhotoCachedSize; + if (thumbCachedSize != null) + { + BitmapImage preview; + if (PhotoToThumbConverter.TryGetPhotoPreview(document.Id, out preview, options)) + { + player.Thumb.Source = preview; + } + else + { + if (thumbCachedSize.Bytes != null + && thumbCachedSize.Bytes.Data != null + && thumbCachedSize.Bytes.Data.Length > 0 + && thumbCachedSize.W.Value > 0 + && thumbCachedSize.H.Value > 0) + { + try + { + var buffer = thumbCachedSize.Bytes.Data; + var bitmap = PictureDecoder.DecodeJpeg(new MemoryStream(buffer)); + + new PhotoToThumbConverter().BlurBitmap(bitmap, false); + + var blurredStream = new MemoryStream(); + bitmap.SaveJpeg(blurredStream, thumbCachedSize.W.Value, thumbCachedSize.H.Value, 0, 100); + + var previewFileName = string.Format("preview{0}.jpg", document.Id); + + Execute.BeginOnThreadPool(() => PhotoToThumbConverter.SaveFile(previewFileName, blurredStream)); + + player.Thumb.Source = ImageUtils.CreateImage(blurredStream); + } + catch (Exception ex) + { + + } + } + else + { + player.Thumb.Source = null; + } + } + } + else + { + var photoSize = document.Thumb as TLPhotoSize; + if (photoSize != null) + { + BitmapImage preview; + if (PhotoToThumbConverter.TryGetPhotoPreview(document.Id, out preview, options)) + { + player.Thumb.Source = preview; + } + else + { + var fileLocation = photoSize.Location as TLFileLocation; + if (fileLocation != null) + { + var previewFileName = string.Format("preview{0}.jpg", document.Id); + var previewSourceFileName = String.Format("{0}_{1}_{2}.jpg", + fileLocation.VolumeId, + fileLocation.LocalId, + fileLocation.Secret); + + if (!CreatePreview(player, mediaGif as TLObject, previewSourceFileName, previewFileName, photoSize)) + { + var fileManager = IoC.Get(); + fileManager.DownloadFile(fileLocation, mediaGif as TLObject, photoSize.Size, + item => Execute.BeginOnUIThread(() => + { + CreatePreview(player, item.Owner, previewSourceFileName, previewFileName, photoSize); + })); + } + } + } + } + } + } + + + return; + } + } + + private static bool CreatePreview(GifPlayerControl player, TLObject previewOwner, string previewSourceFileName, string previewFileName, TLPhotoSize photoSize) + { + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (!store.FileExists(previewSourceFileName)) return false; + + try + { + using (var stream = store.OpenFile(previewSourceFileName, FileMode.Open, FileAccess.Read)) + { + if (stream.Length == 0) return false; + + stream.Seek(0, SeekOrigin.Begin); + + var bitmap = PictureDecoder.DecodeJpeg(stream); + + new PhotoToThumbConverter().BlurBitmap(bitmap, false); + + var blurredStream = new MemoryStream(); + bitmap.SaveJpeg(blurredStream, photoSize.W.Value, photoSize.H.Value, 0, 100); + + if (player.Media == previewOwner) + { + player.Thumb.Source = ImageUtils.CreateImage(blurredStream); + } + + Execute.BeginOnThreadPool(() => PhotoToThumbConverter.SaveFile(previewFileName, blurredStream)); + } + } + catch (Exception) + { + return false; + } + } + + return true; + } + + private static void InitializePlayer(IMediaGifBase mediaBase, GifPlayerControl player) + { + var mediaDocument = mediaBase; + if (mediaDocument != null) + { + var fileName = GetLocalFileName(mediaDocument); + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (!string.IsNullOrEmpty(fileName)) + { + if (store.FileExists(fileName)) + { + player.ChangeButtonState(GifButtonState.Play, "InitializePlayer"); + player._decoderParams = new int[3]; + try + { + lock (player._ffmpegLock) + { + player._handler = FFmpegGifDecoder.CreateDecoder(Path.Combine(ApplicationData.Current.LocalFolder.Path, fileName), player._decoderParams); + if (player._handler != 0) + { + player._w = player._decoderParams[0]; + player._h = player._decoderParams[1]; + + if (player._w > 0 && player._h > 0) + { + player._initialized = true; + } + } + } + } + catch (FileNotFoundException ex) + { + player.Width = 323.0; + player.Height = 150.0; + player.PlayButton.Opacity = 0.5; + } + catch (Exception ex) + { + player.Width = 323.0; + player.Height = 150.0; + player.PlayButton.Opacity = 0.5; +#if DEBUG + MessageBox.Show("OnFileNameChanged " + ex); +#endif + } + } + else + { + if (player.Progress > 0.0 && player.Progress < 1.0) + { + player.ChangeButtonState(GifButtonState.Cancel); + } + else + { + if (player.Mode == GifPlayerMode.InlineResult) + { + if (mediaBase.Forbidden) + { + player.ChangeButtonState(GifButtonState.None); + } + else + { + DownloadGifAsync(mediaBase); + + player.ChangeButtonState(GifButtonState.Cancel); + } + + return; + } + + player.ChangeButtonState(GifButtonState.Download); + } + } + } + } + } + + } + + private int _handler; + + private readonly Timer _frameTimer; + + private int[] _decoderParams; + + private int _w; + + private int _h; + + public double _ptsDelta; + + public double _timeDelta; + + public double _pts; + + public TimeSpan _elapsed; + + private bool _isPlaying; + + private bool _initialized; + + private string _firstFrameFileName; + + private bool _extractFirstFrame; + + private byte[] _frame; + + private bool _destroyDecoder; + + private bool _pauseDecoder; + + private DateTime _startTime; + + private object _ffmpegLock = new object(); + + public GifPlayerControl() + { + InitializeComponent(); + + _frameTimer = new Timer(FrameTimer_OnTick, this, Timeout.Infinite, Timeout.Infinite); + } + + public bool Start() + { + if (Mode == GifPlayerMode.InlineResult) + { + if (!_inlineBotActivePlayers.Contains(this)) + { + _inlineBotActivePlayers.Add(this); + } + } + else + { + if (!_activePlayers.Contains(this)) + { + _activePlayers.Add(this); + } + } + + if (_activePlayers.Count > 0 || _inlineBotActivePlayers.Count > 0) + { + StartUpdateFrames(); + } + + if (!_initialized) + { + InitializePlayer(Media, this); + if (!_initialized) + { + if (Progress > 0.0 && Progress < 1.0) + { + return true; + } + + return false; + } + } + + var pts = _ptsDelta == 0 ? 50 : _ptsDelta; + _startTime = DateTime.Now; + _frameTimer.Change(TimeSpan.FromMilliseconds(pts), Timeout.InfiniteTimeSpan); + _isPlaying = true; + + _frame = null; + ChangeButtonState(GifButtonState.None); + + return true; + } + + private void Pause() + { + if (!_initialized) return; + + lock (_ffmpegLock) + { + _pauseDecoder = true; + } + } + + private void Resume() + { + if (!_initialized) + { + Start(); + return; + } + + lock (_ffmpegLock) + { + _pauseDecoder = false; + } + _frameTimer.Change(TimeSpan.FromMilliseconds(1.0), Timeout.InfiniteTimeSpan); + ChangeButtonState(GifButtonState.None); + } + + public bool Stop(bool autoPlayGif = false) + { + if (Mode == GifPlayerMode.InlineResult) + { + _inlineBotActivePlayers.Remove(this); + } + else + { + _activePlayers.Remove(this); + } + + if (_activePlayers.Count == 0 && _inlineBotActivePlayers.Count == 0) + { + StopUpdateFrames(); + } + + if (!_initialized) return false; + + lock (_ffmpegLock) + { + _destroyDecoder = true; + _frameTimer.Change(TimeSpan.FromMilliseconds(1.0), Timeout.InfiniteTimeSpan); + } + ChangeButtonState(GifButtonState.Play, "Stop autoplay=" + autoPlayGif, autoPlayGif); + + Frame.Source = null; + return true; + } + + public void Release() + { + Frame.Source = null; + PlayButton.Opacity = 1.0; + Debug.Text = null; + _isPlaying = false; + _initialized = false; + _w = 0; + _h = 0; + _pts = 0; + } + + private void FrameTimer_OnTick(object state) + { + lock (_ffmpegLock) + { + if (_destroyDecoder) + { + _destroyDecoder = false; + _pauseDecoder = false; + _isPlaying = false; + + try + { + if (_handler != 0) + { + FFmpegGifDecoder.DestroyDecoder(_handler); + _handler = 0; + } + _initialized = false; + } + catch (Exception ex) + { + Execute.ShowDebugMessage("FrameTime_OnTick.DestroyDecoder exception\n" + ex); + } + + return; + } + + if (_pauseDecoder) + { + _pauseDecoder = false; + _frameTimer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); + return; + } + } + + var stopwatch = Stopwatch.StartNew(); + + var frameParams = new int[3]; + lock (_ffmpegLock) + { + _frame = FFmpegGifDecoder.GetVideoFrame(_handler, frameParams); + } + + if (_frame == null) + { + var pts = _pts; + + Execute.BeginOnUIThread(() => + { + Execute.ShowDebugMessage("GifPlayer.GetVideoFrame=null pts=" + pts + " frame_params=" + string.Join(",", frameParams)); + + Stop(); + }); + return; + } + + _ptsDelta = 0.0; + if (frameParams[2] <= 0) + { + _startTime = DateTime.Now; + _ptsDelta = 1.0; + _pts = 0.0; + + ExtractFirstFrame(_frame); + } + else + { + _pts = frameParams[2]; + _timeDelta = (DateTime.Now - _startTime).TotalMilliseconds; + var delta = (frameParams[2] - _timeDelta); + _ptsDelta = delta < 0.0 ? 1.0 : delta; + } + + _elapsed = stopwatch.Elapsed; + + lock (_ffmpegLock) + { + _frameTimer.Change(TimeSpan.FromMilliseconds(_ptsDelta), Timeout.InfiniteTimeSpan); + } + } + + private void ExtractFirstFrame(byte[] frame) + { + if (!_extractFirstFrame) return; + + _extractFirstFrame = false; + + Execute.BeginOnThreadPool(() => SaveFirstFrame(frame)); + } + + private async void SaveFirstFrame(byte[] frame) + { + var fileName = _firstFrameFileName; + + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (!store.FileExists(fileName) && frame.Length > 0) + { + var pixels = new int[frame.Length / sizeof(int)]; + for (var j = 0; j < pixels.Length; j++) + { + pixels[j] = + (frame[j * 4 + 3] << 24) + //b + (frame[j * 4 + 2] << 0) + //g + (frame[j * 4 + 1] << 8) + //r + (frame[j * 4] << 16); //a + + //bitmap.Pixels[j] = pixels[j]; + } + + Buffer.BlockCopy(pixels, 0, frame, 0, frame.Length); + + var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); + using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite)) + { + var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream); + encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)_w, (uint)_h, 96.0, 96.0, frame); + await encoder.FlushAsync(); + } + + Execute.BeginOnUIThread(() => + { + SetMediaPreview(this, Media); + }); + } + } + } + + public void ToggleVideoPlay() + { + if (MediaPlaceholder.Background != null) + { + if (MessagePlayerControl.Player.CurrentState == MediaElementState.Playing) + { + MessagePlayerControl.Player.Pause(); + RaiseMediaStateChanged(Media, GifPlayerControlState.Paused); + } + else if (MessagePlayerControl.Player.CurrentState == MediaElementState.Paused) + { + MessagePlayerControl.Player.Play(); + RaiseMediaStateChanged(Media, GifPlayerControlState.Resumed); + } + } + } + + private void LayoutRoot_OnTap(object sender, GestureEventArgs e) + { + if (Mode == GifPlayerMode.InlineResult) return; + + if (Mode == GifPlayerMode.RoundVideo) + { + // open external player for w10m + if (System.Environment.OSVersion.Version.Major >= 10) + { + return; + } + + // open in-app player for wp8.1 + var mediaBase = Media; + if (mediaBase != null) + { + var player = MessagePlayerControl.Player.Tag as GifPlayerControl; + if (player != null + && player == this + && MediaPlaceholder.Background != null) + { + ToggleVideoPlay(); + + e.Handled = true; + } + else + { + var localFileName = GetLocalFileName(mediaBase); + + if (!string.IsNullOrEmpty(localFileName)) + { + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (store.FileExists(localFileName)) + { + PauseActivePlayers(); + + if (player != null) + { + player.MuteIcon.Visibility = Visibility.Visible; + player.MediaPlaceholder.Background = null; + } + + MessagePlayerControl.Player.Tag = this; + MessagePlayerControl.Player.Position = TimeSpan.FromSeconds(0.0); + var videoBrush = new VideoBrush(); + videoBrush.SetSource(MessagePlayerControl.Player); + MediaPlaceholder.Background = videoBrush; + MuteIcon.Visibility = Visibility.Collapsed; + + var file = store.OpenFile(localFileName, FileMode.Open, FileAccess.Read); + + RaiseMediaStateChanged(Media, GifPlayerControlState.Opening); + + Execute.BeginOnUIThread(() => + { + MessagePlayerControl.Player.SetSource(file); + file.Dispose(); + //MessagePlayerControl.Player.MediaOpened += PlayerOnMediaOpened; + //MessagePlayerControl.Player.MediaFailed += PlayerOnMediaFailed; + //MessagePlayerControl.Player.MediaEnded += PlayerOnMediaEnded; + }); + + e.Handled = true; + } + } + } + } + } + + return; + } + + if (Mode == GifPlayerMode.Normal) + { + if (_isPlaying) + { + if (Media != null) Media.AutoPlayGif = false; + e.Handled = Stop(); + } + else + { + if (Media != null) Media.AutoPlayGif = true; + e.Handled = Start(); + } + + return; + } + } + + private void CancelDownloadButton_OnTap(object sender, GestureEventArgs e) + { + if (Mode == GifPlayerMode.InlineResult) return; + + e.Handled = true; + var localFileName = GetLocalFileName(Media); + using (var store = IsolatedStorageFile.GetUserStoreForApplication()) + { + if (!store.FileExists(localFileName)) + { + ChangeButtonState(GifButtonState.Download); + } + else + { + ChangeButtonState(GifButtonState.Play); + } + } + RaiseCancelDownload(); + } + + private enum GifButtonState + { + Play, + Download, + Cancel, + None + } + + private GifButtonState? _lastState; + + private void ChangeButtonState(GifButtonState state, string place = null, bool autoPlayGif = false) + { + if (_lastState == state) return; + +//#if DEBUG + //Debug2.Text = state + " place=" + place; +//#endif + _lastState = state; + if (Mode == GifPlayerMode.RoundVideo) + { + MuteIcon.Visibility = MediaPlaceholder.Background == null ? Visibility.Visible : Visibility.Collapsed; + PlayButton.Visibility = Visibility.Collapsed; + Play.Visibility = Visibility.Collapsed; + PlayCircle.Visibility = Visibility.Collapsed; + DownloadButton.Visibility = state == GifButtonState.Download ? Visibility.Visible : Visibility.Collapsed; + CancelDownloadButton.Visibility = state == GifButtonState.Cancel ? Visibility.Visible : Visibility.Collapsed; + } + else + { + MuteIcon.Visibility = Visibility.Collapsed; + PlayButton.Visibility = state == GifButtonState.Play ? Visibility.Visible : Visibility.Collapsed; + Play.Visibility = autoPlayGif ? Visibility.Collapsed : Visibility.Visible; + PlayCircle.Visibility = autoPlayGif ? Visibility.Collapsed : Visibility.Visible; + DownloadButton.Visibility = state == GifButtonState.Download ? Visibility.Visible : Visibility.Collapsed; + CancelDownloadButton.Visibility = state == GifButtonState.Cancel ? Visibility.Visible : Visibility.Collapsed; + } + } + + public event EventHandler CancelDownload; + + protected virtual void RaiseCancelDownload() + { + var handler = CancelDownload; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private bool _suppressManipulationStarted = true; // in order to suppress manipulationstarted event on longlistselector + + public bool SuppressManipulationStarted + { + get { return _suppressManipulationStarted; } + set { _suppressManipulationStarted = value; } + } + + public Geometry FrameClip + { + get { return FrameGrid.Clip; } + set + { + FrameGrid.Clip = value; + } + } + + private void LayoutRoot_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + e.Handled = SuppressManipulationStarted; + } + + public void OnMediaEnded() + { + MediaPlaceholder.Background = null; + MuteIcon.Visibility = Visibility.Visible; + + RaiseMediaStateChanged(Media, GifPlayerControlState.Ended); + } + + public void OnMediaFailed(ExceptionRoutedEventArgs e) + { + MuteIcon.Visibility = Visibility.Visible; + + RaiseMediaStateChanged(Media, GifPlayerControlState.Failed); + } + + public void OnMediaOpened() + { + MessagePlayerControl.Player.Play(); + + RaiseMediaStateChanged(Media, GifPlayerControlState.Opened); + } + + public static event EventHandler MediaStateChanged; + + public static void RaiseMediaStateChanged(IMediaGifBase media, GifPlayerControlState state) + { + var handler = MediaStateChanged; + if (handler != null) handler(null, new MediaStateChangedEventArgs(media, state)); + } + + public static void StopVideo() + { + var player = MessagePlayerControl.Player.Tag as GifPlayerControl; + if (player != null) + { + if (MessagePlayerControl.Player.CurrentState == MediaElementState.Playing) + { + MessagePlayerControl.Player.Stop(); + } + + player.MediaPlaceholder.Background = null; + player.MuteIcon.Visibility = Visibility.Visible; + + RaiseMediaStateChanged(player.Media, GifPlayerControlState.Ended); + } + } + } + + public enum GifPlayerMode + { + Normal, + InlineResult, + RoundVideo + } + + public enum GifPlayerControlState + { + Opening, + Opened, + Failed, + Ended, + Paused, + Resumed + } + + public class MediaStateChangedEventArgs : System.EventArgs + { + public GifPlayerControlState State { get; protected set; } + + public IMediaGifBase Media { get; protected set; } + + public MediaStateChangedEventArgs(IMediaGifBase media, GifPlayerControlState state) + { + Media = media; + State = state; + } + } +} diff --git a/TelegramClient.WP81/Views/Additional/LoggedInView.xaml b/TelegramClient.WP81/Views/Additional/LoggedInView.xaml new file mode 100755 index 0000000..3173bd8 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/LoggedInView.xaml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/LoggedInView.xaml.cs b/TelegramClient.WP81/Views/Additional/LoggedInView.xaml.cs new file mode 100755 index 0000000..6363d0f --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/LoggedInView.xaml.cs @@ -0,0 +1,28 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using Microsoft.Phone.Controls; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Additional +{ + public partial class LoggedInView + { + public LoggedInView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + } + + private void MainItemGrid_OnTap(object sender, GestureEventArgs e) + { + ContextMenuService.GetContextMenu((DependencyObject)sender).IsOpen = true; + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/PassportSettingsView.xaml b/TelegramClient.WP81/Views/Additional/PassportSettingsView.xaml new file mode 100755 index 0000000..c9c8fc6 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/PassportSettingsView.xaml @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/ProxyListView.xaml.cs b/TelegramClient.WP81/Views/Additional/ProxyListView.xaml.cs new file mode 100755 index 0000000..a52c82b --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/ProxyListView.xaml.cs @@ -0,0 +1,327 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Media; +using System.Windows.Navigation; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.TL; +using Telegram.Api.Transport; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.ViewModels.Additional; +using TelegramClient.ViewModels.Dialogs; +using TelegramClient.Views.Controls; +using TelegramClient.Views.Dialogs; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Additional +{ + public partial class ProxyListView + { + public ProxyListViewModel ViewModel + { + get { return DataContext as ProxyListViewModel; } + } + + private TranslateTransform _frameTransform; + + public static readonly DependencyProperty RootFrameTransformProperty = DependencyProperty.Register( + "RootFrameTransformProperty", typeof(double), typeof(ProxyListView), new PropertyMetadata(OnRootFrameTransformChanged)); + + private static void OnRootFrameTransformChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var view = d as ProxyListView; + if (view != null) + { + view._frameTransform.Y = 0; + } + } + + public double RootFrameTransform + { + get { return (double)GetValue(RootFrameTransformProperty); } + set { SetValue(RootFrameTransformProperty, value); } + } + + private void SetRootFrameBinding() + { + var frame = (Frame)Application.Current.RootVisual; + _frameTransform = ((TranslateTransform)((TransformGroup)frame.RenderTransform).Children[0]); + var binding = new Binding("Y") + { + Source = _frameTransform + }; + SetBinding(RootFrameTransformProperty, binding); + } + + private void RemoveRootFrameBinding() + { + ClearValue(RootFrameTransformProperty); + } + + public ProxyListView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + + Loaded += (sender, args) => + { + UpdateShareButton(); + SetRootFrameBinding(); + }; + Unloaded += (sender, args) => + { + RemoveRootFrameBinding(); + }; + } + + private void UpdateShareButton() + { + ShareMenuIcon.Opacity = ViewModel != null && !ViewModel.SuppressSharing + ? 1.0 + : 0.5; + } + + private void DoneButton_OnClick(object sender, GestureEventArgs e) + { + ViewModel.Done(); + } + + private void Add_OnTap(object sender, GestureEventArgs e) + { + ViewModel.Add(); + } + + private void ShareIcon_OnTap(object sender, GestureEventArgs e) + { + ViewModel.Share(); + } + + protected override void OnBackKeyPress(CancelEventArgs e) + { + var popups = VisualTreeHelper.GetOpenPopups().ToList(); + var popup = popups.FirstOrDefault(); + if (popup != null) + { + e.Cancel = true; + + var shareMessagePicker = popup.Child as ShareMessagePicker; + if (shareMessagePicker != null) + { + shareMessagePicker.TryClose(); + } + + return; + } + + base.OnBackKeyPress(e); + } + + private ShareMessagePicker _shareMessagePicker; + + private WeakEventListener _weakEventListener; + + public void OpenShareMessagePicker(string link, Action callback = null) + { + var isVisible = false; + var frame = Application.Current.RootVisual as PhoneApplicationFrame; + PhoneApplicationPage page = null; + if (frame != null) + { + page = frame.Content as PhoneApplicationPage; + if (page != null) + { + page.IsHitTestVisible = false; + var applicationBar = page.ApplicationBar; + if (applicationBar != null) + { + isVisible = applicationBar.IsVisible; + applicationBar.IsVisible = false; + } + } + + var weakEventListener = new WeakEventListener(this, frame); + frame.Navigating += weakEventListener.OnEvent; + + weakEventListener.OnEventAction = (view, o, args) => + { + view.Frame_Navigating(o, args); + }; + weakEventListener.OnDetachAction = (listener, source) => + { + var f = source as PhoneApplicationFrame; + if (f != null) + { + f.Navigating -= listener.OnEvent; + } + }; + + _weakEventListener = weakEventListener; + } + + if (page == null) return; + + var popup = new Popup(); + var sharePicker = new ShareMessagePicker + { + Width = page.ActualWidth, + Height = page.ActualHeight, + Link = link + }; + _shareMessagePicker = sharePicker; + page.SizeChanged += Page_SizeChanged; + + sharePicker.Close += (sender, args) => + { + _shareMessagePicker = null; + _weakEventListener.Detach(); + _weakEventListener = null; + + popup.IsOpen = false; + popup.Child = null; + + frame = Application.Current.RootVisual as PhoneApplicationFrame; + if (frame != null) + { + page = frame.Content as PhoneApplicationPage; + if (page != null) + { + page.SizeChanged -= Page_SizeChanged; + page.IsHitTestVisible = true; + var applicationBar = page.ApplicationBar; + if (applicationBar != null) + { + applicationBar.IsVisible = isVisible; + } + } + } + }; + _shareMessagePicker.Pick += (sender, args) => + { + callback.SafeInvoke(args); + }; + + popup.Child = sharePicker; + popup.IsOpen = true; + } + + private void Frame_Navigating(object sender, NavigatingCancelEventArgs e) + { + if (_shareMessagePicker != null) + { + _shareMessagePicker.ForceClose(); + } + } + + private void Page_SizeChanged(object sender, SizeChangedEventArgs e) + { + + } + } + + public class ProxyTypeToStringConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var mtProtoProxy = value as TLMTProtoProxy; + if (mtProtoProxy != null) + { + return AppResources.MTProto; + } + + return AppResources.Socks5; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + public class ProxyToStatusConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var transportService = IoC.Get(); + if (transportService == null) return null; + + var proxyConfig = transportService.GetProxyConfig(); + if (proxyConfig == null) return null; + + var proxyBase = value as TLProxyBase; + if (proxyBase != null) + { + switch (proxyBase.Status) + { + case ProxyStatus.Available: + return proxyConfig.IsEnabled.Value && proxyBase.IsSelected ? AppResources.Connected : AppResources.Available; + case ProxyStatus.Unavailable: + return AppResources.Unavailable; + case ProxyStatus.Connecting: + return proxyConfig.IsEnabled.Value && proxyBase.IsSelected ? AppResources.Connecting + "..." : AppResources.Checking + "..."; + } + } + + return null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class ProxyToForegroundConverter : IValueConverter + { + public Brush AccentBrush { get; set; } + + public Brush AvailableBrush { get; set; } + + public Brush UnavailableBrush { get; set; } + + public Brush RegularBrush { get; set; } + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var proxyBase = value as TLProxyBase; + if (proxyBase != null) + { + if (proxyBase.IsSelected) + { + return AccentBrush; + } + if (proxyBase.Status == ProxyStatus.Available) + { + return AvailableBrush; + } + if (proxyBase.Status == ProxyStatus.Unavailable) + { + return UnavailableBrush; + } + } + + return RegularBrush; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/ProxyView.xaml b/TelegramClient.WP81/Views/Additional/ProxyView.xaml new file mode 100755 index 0000000..c56fad8 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/ProxyView.xaml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/ProxyView.xaml.cs b/TelegramClient.WP81/Views/Additional/ProxyView.xaml.cs new file mode 100755 index 0000000..c68947a --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/ProxyView.xaml.cs @@ -0,0 +1,284 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.ComponentModel; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Navigation; +using Microsoft.Phone.Controls; +using Telegram.Api.Extensions; +using TelegramClient.Helpers; +using TelegramClient.ViewModels.Additional; +using TelegramClient.Views.Controls; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Additional +{ + public partial class ProxyView + { + public ProxyViewModel ViewModel + { + get { return DataContext as ProxyViewModel; } + } + + private TranslateTransform _frameTransform; + + public static readonly DependencyProperty RootFrameTransformProperty = DependencyProperty.Register( + "RootFrameTransformProperty", typeof(double), typeof(ProxyView), new PropertyMetadata(OnRootFrameTransformChanged)); + + private static void OnRootFrameTransformChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var view = d as ProxyView; + if (view != null) + { + view._frameTransform.Y = 0; + } + } + + public double RootFrameTransform + { + get { return (double)GetValue(RootFrameTransformProperty); } + set { SetValue(RootFrameTransformProperty, value); } + } + + private void SetRootFrameBinding() + { + var frame = (Frame)Application.Current.RootVisual; + _frameTransform = ((TranslateTransform)((TransformGroup)frame.RenderTransform).Children[0]); + var binding = new Binding("Y") + { + Source = _frameTransform + }; + SetBinding(RootFrameTransformProperty, binding); + } + + private void RemoveRootFrameBinding() + { + ClearValue(RootFrameTransformProperty); + } + + public ProxyView() + { + InitializeComponent(); + + ServerLabel.TextBox.TextChanged += (sender, args) => + { + UpdateShareButton(); + }; + PortLabel.TextBox.TextChanged += (sender, args) => + { + UpdateShareButton(); + }; + + Caption.Background = ShellView.CaptionBrush; + + Loaded += (sender, args) => + { + UpdateShareButton(); + SetRootFrameBinding(); + }; + Unloaded += (sender, args) => + { + RemoveRootFrameBinding(); + }; + } + + private void UpdateShareButton() + { + ShareMenuIcon.Opacity = ViewModel != null && !ViewModel.SuppressSharing && ViewModel.IsDoneEnabled + ? 1.0 + : 0.5; + } + + private void DoneButton_OnClick(object sender, GestureEventArgs e) + { + ViewModel.Done(); + } + + private void ServerLabel_OnKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + PortLabel.Focus(); + } + } + + private void PortLabel_OnKeyDown(object sender, KeyEventArgs e) + { + if ((e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9) + || (e.Key >= Key.D0 && e.Key <= Key.D9)) + { + + } + else if (e.Key == Key.Enter) + { + if (ViewModel.IsSocks5Proxy) + { + UsernameLabel.Focus(); + } + else + { + SecretLabel.Focus(); + } + } + else + { + e.Handled = true; + } + } + + private void Username_OnKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + PasswordLabel.Focus(); + } + } + + private void Done_OnKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + ViewModel.Done(); + } + } + + private void ShareIcon_OnTap(object sender, GestureEventArgs e) + { + if (ShareMenuIcon.Opacity < 1.0) return; + + ViewModel.Share(); + } + + protected override void OnBackKeyPress(CancelEventArgs e) + { + var popups = VisualTreeHelper.GetOpenPopups().ToList(); + var popup = popups.FirstOrDefault(); + if (popup != null) + { + e.Cancel = true; + + var shareMessagePicker = popup.Child as ShareMessagePicker; + if (shareMessagePicker != null) + { + shareMessagePicker.TryClose(); + } + + return; + } + + base.OnBackKeyPress(e); + } + + private ShareMessagePicker _shareMessagePicker; + + private WeakEventListener _weakEventListener; + + public void OpenShareMessagePicker(string link, Action callback = null) + { + var isVisible = false; + var frame = Application.Current.RootVisual as PhoneApplicationFrame; + PhoneApplicationPage page = null; + if (frame != null) + { + page = frame.Content as PhoneApplicationPage; + if (page != null) + { + page.IsHitTestVisible = false; + var applicationBar = page.ApplicationBar; + if (applicationBar != null) + { + isVisible = applicationBar.IsVisible; + applicationBar.IsVisible = false; + } + } + + var weakEventListener = new WeakEventListener(this, frame); + frame.Navigating += weakEventListener.OnEvent; + + weakEventListener.OnEventAction = (view, o, args) => + { + view.Frame_Navigating(o, args); + }; + weakEventListener.OnDetachAction = (listener, source) => + { + var f = source as PhoneApplicationFrame; + if (f != null) + { + f.Navigating -= listener.OnEvent; + } + }; + + _weakEventListener = weakEventListener; + } + + if (page == null) return; + + var popup = new Popup(); + var sharePicker = new ShareMessagePicker + { + Width = page.ActualWidth, + Height = page.ActualHeight, + Link = link + }; + _shareMessagePicker = sharePicker; + page.SizeChanged += Page_SizeChanged; + + sharePicker.Close += (sender, args) => + { + _shareMessagePicker = null; + _weakEventListener.Detach(); + _weakEventListener = null; + + popup.IsOpen = false; + popup.Child = null; + + frame = Application.Current.RootVisual as PhoneApplicationFrame; + if (frame != null) + { + page = frame.Content as PhoneApplicationPage; + if (page != null) + { + page.SizeChanged -= Page_SizeChanged; + page.IsHitTestVisible = true; + var applicationBar = page.ApplicationBar; + if (applicationBar != null) + { + applicationBar.IsVisible = isVisible; + } + } + } + }; + _shareMessagePicker.Pick += (sender, args) => + { + callback.SafeInvoke(args); + }; + + popup.Child = sharePicker; + popup.IsOpen = true; + } + + private void Frame_Navigating(object sender, NavigatingCancelEventArgs e) + { + if (_shareMessagePicker != null) + { + _shareMessagePicker.ForceClose(); + } + } + + private void Page_SizeChanged(object sender, SizeChangedEventArgs e) + { + + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/StartupView.xaml b/TelegramClient.WP81/Views/Additional/StartupView.xaml new file mode 100755 index 0000000..1b9db42 --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/StartupView.xaml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Additional/StartupView.xaml.cs b/TelegramClient.WP81/Views/Additional/StartupView.xaml.cs new file mode 100755 index 0000000..750a75c --- /dev/null +++ b/TelegramClient.WP81/Views/Additional/StartupView.xaml.cs @@ -0,0 +1,157 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using Microsoft.Phone.Shell; + +namespace TelegramClient.Views.Additional +{ + public partial class StartupView + { + private const double ScreenWidth = 480.0; + + private const double MarginWidth = 174.0; + + private const double ScrollIndicatorWidth = 12.0; + + private const int LastIndex = 5; + + private const double ScrollIndicatorTranslationX = (ScreenWidth - MarginWidth - MarginWidth - ScrollIndicatorWidth) / LastIndex; + + + public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached( + "FormattedText", typeof(string), typeof(StartupView), new PropertyMetadata(default(string), OnFormattedTextChanged)); + + public static void SetFormattedText(DependencyObject element, string value) + { + element.SetValue(FormattedTextProperty, value); + } + + public static string GetFormattedText(DependencyObject element) + { + return (string)element.GetValue(FormattedTextProperty); + } + + private static void OnFormattedTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var r = d as TextBlock; + if (r != null) + { + var text = e.NewValue as string; + if (text != null) + { + r.Inlines.Clear(); + var splittedText = text.Split(new[] { "**" }, StringSplitOptions.None); + for (var i = 0; i < splittedText.Length; i++) + { + if (i % 2 == 1) + { + var bold = new Run(); + bold.FontWeight = FontWeights.SemiBold; + bold.Text = splittedText[i]; + r.Inlines.Add(bold); + } + else + { + r.Inlines.Add(splittedText[i]); + } + } + } + } + } + + public StartupView() + { + InitializeComponent(); + + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + IndicatorBorder.Background = isLightTheme + ? (Brush) Resources["IndicatorBrushLight"] + : (Brush) Resources["IndicatorBrushDark"]; + PositionBorder.Background = isLightTheme + ? (Brush) Resources["PositionBrushLight"] + : (Brush) Resources["PositionBrushDark"]; + + OptimizeFullHD(); + } + + private void OptimizeFullHD() + { + return; + var appBar = new ApplicationBar(); + var appBarDefaultSize = appBar.DefaultSize; + + StartMessagingPanel.Height = appBarDefaultSize; + } + + private void StartView_OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + var index = StartView.SelectedIndex; + + var storyboard = new Storyboard(); + + var timeline = new DoubleAnimationUsingKeyFrames(); + timeline.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = index * ScrollIndicatorTranslationX, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } }); + Storyboard.SetTarget(timeline, BorderPosition); + Storyboard.SetTargetProperty(timeline, new PropertyPath("X")); + storyboard.Children.Add(timeline); + + storyboard.Begin(); + } + + private void StartView_OnSelectionCanceled(object sender, System.EventArgs e) + { + var index = StartView.SelectedIndex; + + var storyboard = new Storyboard(); + + var timeline = new DoubleAnimationUsingKeyFrames(); + timeline.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = index * ScrollIndicatorTranslationX, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } }); + Storyboard.SetTarget(timeline, BorderPosition); + Storyboard.SetTargetProperty(timeline, new PropertyPath("X")); + storyboard.Children.Add(timeline); + + storyboard.Begin(); + } + + private void StartView_OnManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + if (StartView.SelectedIndex == 0 && e.DeltaManipulation.Translation.X > 0.0 && BorderPosition.X == 0.0) + { + return; + } + + if (StartView.SelectedIndex == LastIndex && e.DeltaManipulation.Translation.X < 0.0 && BorderPosition.X == ScrollIndicatorTranslationX * LastIndex) + { + return; + } + + BorderPosition.X -= e.DeltaManipulation.Translation.X / ScreenWidth * ScrollIndicatorTranslationX; + if (BorderPosition.X < 0.0) BorderPosition.X = 0.0; + if (BorderPosition.X > ScrollIndicatorTranslationX * LastIndex) BorderPosition.X = ScrollIndicatorTranslationX * LastIndex; + } + + private void IndicatorBorder_OnTap(object sender, GestureEventArgs e) + { + var selectedIndex = StartView.SelectedIndex; + if (selectedIndex >= StartView.Items.Count - 1) + { + StartView.SelectedIndex = 0; + } + else if (StartView.SelectedIndex < StartView.Items.Count - 1) + { + StartView.SelectedIndex++; + } + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Calls/CallDebugControl.xaml b/TelegramClient.WP81/Views/Calls/CallDebugControl.xaml new file mode 100755 index 0000000..decb1fb --- /dev/null +++ b/TelegramClient.WP81/Views/Calls/CallDebugControl.xaml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Calls/CallDebugControl.xaml.cs b/TelegramClient.WP81/Views/Calls/CallDebugControl.xaml.cs new file mode 100755 index 0000000..607f48d --- /dev/null +++ b/TelegramClient.WP81/Views/Calls/CallDebugControl.xaml.cs @@ -0,0 +1,50 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Navigation; +using System.Windows.Threading; +using Windows.Phone.Networking.Voip; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; +using TelegramClient.Services; + +namespace TelegramClient.Views.Calls +{ + public partial class CallDebugControl : UserControl + { + private DispatcherTimer _debugTimer = new DispatcherTimer{ Interval = TimeSpan.FromSeconds(0.5) }; + + public CallDebugControl() + { + InitializeComponent(); + + _debugTimer.Tick += DebugTimer_Tick; + } + + private void DebugTimer_Tick(object sender, System.EventArgs eventArgs) + { + Debug.Text = IoC.Get().GetDebugString(); + } + + public void Start() + { + _debugTimer.Start(); + } + + public void Stop() + { + _debugTimer.Stop(); + } + } +} diff --git a/TelegramClient.WP81/Views/Calls/CallRatingControl.xaml b/TelegramClient.WP81/Views/Calls/CallRatingControl.xaml new file mode 100755 index 0000000..c0dccc2 --- /dev/null +++ b/TelegramClient.WP81/Views/Calls/CallRatingControl.xaml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Calls/CallRatingControl.xaml.cs b/TelegramClient.WP81/Views/Calls/CallRatingControl.xaml.cs new file mode 100755 index 0000000..0bc506a --- /dev/null +++ b/TelegramClient.WP81/Views/Calls/CallRatingControl.xaml.cs @@ -0,0 +1,32 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; + +namespace TelegramClient.Views.Calls +{ + public partial class CallRatingControl + { + public CallRatingControl() + { + InitializeComponent(); + + Comment.FontSize = 20; + Comment.TextBox.FontSize = 20; + Comment.Input.TextWrapping = TextWrapping.Wrap; + Comment.Input.AcceptsReturn = true; + } + + private void Rating_OnValueChanged(object sender, System.EventArgs e) + { + if (Comment == null) return; + if (Rating == null) return; + + Comment.Visibility = Rating.Value < 5.0 ? Visibility.Visible : Visibility.Collapsed; + } + } +} diff --git a/TelegramClient.WP81/Views/Calls/CallView.xaml b/TelegramClient.WP81/Views/Calls/CallView.xaml new file mode 100755 index 0000000..7751557 --- /dev/null +++ b/TelegramClient.WP81/Views/Calls/CallView.xaml @@ -0,0 +1,536 @@ + + + + + + + + + + + + + + + + + + + + Visible + + + + + + + Visible + + + + + + + Visible + + + + + + + Collapsed + + + + + + + Visible + + + + + + + + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Visible + + + + + + + Collapsed + + + + + + + + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Visible + + + + + + + Collapsed + + + + + + + + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + Collapsed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Calls/CallView.xaml.cs b/TelegramClient.WP81/Views/Calls/CallView.xaml.cs new file mode 100755 index 0000000..4efde33 --- /dev/null +++ b/TelegramClient.WP81/Views/Calls/CallView.xaml.cs @@ -0,0 +1,180 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.ComponentModel; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media.Animation; +using Caliburn.Micro; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.Services; +using TelegramClient.ViewModels.Calls; + +namespace TelegramClient.Views.Calls +{ + public partial class CallView + { + public CallViewModel ViewModel + { + get { return DataContext as CallViewModel; } + } + + private bool _initState; + + public CallView() + { + InitializeComponent(); + + LayoutRoot.Background = ShellView.CaptionBrush; + + Loaded += (sender, args) => + { + if (!_initState) + { + _initState = true; + GoToState(ViewModel.ViewState); + } + ViewModel.PropertyChanged += ViewModel_PropertyChanged; + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + ViewModel.Signal = IoC.Get().GetSignalBarsCount(); + }); + }; + Unloaded += (sender, args) => + { + ViewModel.PropertyChanged -= ViewModel_PropertyChanged; + }; + } + + private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs args) + { + if (Property.NameEquals(args.PropertyName, () => ViewModel.ViewState)) + { + GoToState(ViewModel.ViewState); + } + } + + public void GoToState(CallViewState state) + { + System.Diagnostics.Debug.WriteLine("GoToState state=" + state); + BottomCommand.IsEnabled = true; + IgnoreButton.IsEnabled = true; + VisualStateManager.GoToState(this, state.ToString(), false); + switch (state) + { + case CallViewState.Call: + BottomCommandLabel.Text = AppResources.EndCall; + IgnoreButtonLabel.Text = AppResources.Ignore; + break; + case CallViewState.CallConnecting: + BottomCommandLabel.Text = AppResources.EndCall; + IgnoreButtonLabel.Text = AppResources.Ignore; + break; + case CallViewState.IncomingCall: + BottomCommandLabel.Text = AppResources.Answer; + IgnoreButtonLabel.Text = AppResources.Ignore; + break; + case CallViewState.IncomingCallBusy: + BottomCommandLabel.Text = AppResources.Answer; + IgnoreButtonLabel.Text = AppResources.Ignore; + break; + case CallViewState.OutgoingCall: + BottomCommandLabel.Text = AppResources.Cancel; + IgnoreButtonLabel.Text = AppResources.Ignore; + break; + case CallViewState.OutgoingCallBusy: + BottomCommandLabel.Text = AppResources.Call; + IgnoreButtonLabel.Text = AppResources.Cancel; + break; + } + } + + private void EmojisPanel_OnTap(object sender, GestureEventArgs e) + { + var expanded = EmojisTransform.TranslateX == 0.0; + var scaleX = expanded ? 2.5 : 1.0; + var scaleY = expanded ? 2.5 : 1.0; + var labelOpacity = expanded ? 1.0 : 0.0; + + var pointFrom = EmojisPanel.TransformToVisual(this).Transform(new Point(EmojisPanel.ActualWidth / 2.0, EmojisPanel.ActualHeight / 2.0)); + var pointTo = EmojiKeyLabel.TransformToVisual(this).Transform(new Point(EmojiKeyLabel.ActualWidth / 2.0, 0.0 - EmojisPanel.ActualHeight * scaleY));//new Point(480.0/2.0, 800.0/2.0); + + var storyboard = new Storyboard(); + + var translateX = expanded ? pointTo.X - pointFrom.X : 0.0; + var translateXAnimation = new DoubleAnimationUsingKeyFrames(); + translateXAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = translateX }); + Storyboard.SetTargetProperty(translateXAnimation, new PropertyPath("TranslateX")); + storyboard.Children.Add(translateXAnimation); + + var translateY = expanded ? pointTo.Y - pointFrom.Y : 0.0; + var translateYAnimation = new DoubleAnimationUsingKeyFrames(); + translateYAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = translateY }); + Storyboard.SetTargetProperty(translateYAnimation, new PropertyPath("TranslateY")); + storyboard.Children.Add(translateYAnimation); + + var scaleXAnimation = new DoubleAnimationUsingKeyFrames(); + scaleXAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = scaleX }); + Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath("ScaleX")); + storyboard.Children.Add(scaleXAnimation); + + var scaleYAnimation = new DoubleAnimationUsingKeyFrames(); + scaleYAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = scaleY }); + Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath("ScaleY")); + storyboard.Children.Add(scaleYAnimation); + + var labelOpacityAnimation = new DoubleAnimationUsingKeyFrames(); + labelOpacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = labelOpacity }); + Storyboard.SetTargetProperty(labelOpacityAnimation, new PropertyPath("Opacity")); + Storyboard.SetTarget(labelOpacityAnimation, EmojiKeyLabel); + storyboard.Children.Add(labelOpacityAnimation); + + var backgroundOpacityAnimation = new DoubleAnimationUsingKeyFrames(); + backgroundOpacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = labelOpacity }); + Storyboard.SetTargetProperty(backgroundOpacityAnimation, new PropertyPath("Opacity")); + Storyboard.SetTarget(backgroundOpacityAnimation, PhotoBorder); + storyboard.Children.Add(backgroundOpacityAnimation); + + Storyboard.SetTarget(storyboard, EmojisTransform); + + storyboard.Begin(); + } + + private void Speaker_OnChecked(object sender, RoutedEventArgs e) + { + ViewModel.SwitchSpeaker(true); + } + + private void Speaker_OnUnchecked(object sender, RoutedEventArgs e) + { + ViewModel.SwitchSpeaker(false); + } + + private void Mute_OnChecked(object sender, RoutedEventArgs e) + { + ViewModel.Mute(true); + } + + private void Mute_OnUnchecked(object sender, RoutedEventArgs e) + { + ViewModel.Mute(false); + } + } + + public enum CallViewState + { + Call, + CallConnecting, + OutgoingCall, + OutgoingCallBusy, + IncomingCall, + IncomingCallBusy + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Calls/CallsView.xaml b/TelegramClient.WP81/Views/Calls/CallsView.xaml new file mode 100755 index 0000000..805b790 --- /dev/null +++ b/TelegramClient.WP81/Views/Calls/CallsView.xaml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Calls/CallsView.xaml.cs b/TelegramClient.WP81/Views/Calls/CallsView.xaml.cs new file mode 100755 index 0000000..23499a9 --- /dev/null +++ b/TelegramClient.WP81/Views/Calls/CallsView.xaml.cs @@ -0,0 +1,66 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using Telegram.Api.TL; +using Telegram.Controls; +using Telegram.Controls.Extensions; +using TelegramClient.ViewModels.Calls; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Calls +{ + public partial class CallsView + { + public CallsViewModel ViewModel + { + get { return DataContext as CallsViewModel; } + } + + public CallsView() + { + InitializeComponent(); + } + + public FrameworkElement TapedItem; + + private void MainItemGrid_OnTap(object sender, GestureEventArgs e) + { + TapedItem = (FrameworkElement) sender; + + var tapedItemContainer = TapedItem.FindParentOfType(); + + var result = ViewModel.OpenDialogDetails(TapedItem.DataContext as TLDialogBase); + if (result) + { + ShellView.StartContinuumForwardOutAnimation(TapedItem, tapedItemContainer); + } + } + + private void Items_OnCloseToEnd(object sender, System.EventArgs e) + { + + } + + private void Items_OnManipulationStarted(object sender, ScrollingStateChangedEventArgs e) + { + + } + + private void Items_OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Calls/ReturnToCallControl.xaml b/TelegramClient.WP81/Views/Calls/ReturnToCallControl.xaml new file mode 100755 index 0000000..f1a6b6f --- /dev/null +++ b/TelegramClient.WP81/Views/Calls/ReturnToCallControl.xaml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Calls/ReturnToCallControl.xaml.cs b/TelegramClient.WP81/Views/Calls/ReturnToCallControl.xaml.cs new file mode 100755 index 0000000..523ec0b --- /dev/null +++ b/TelegramClient.WP81/Views/Calls/ReturnToCallControl.xaml.cs @@ -0,0 +1,27 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Navigation; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; + +namespace TelegramClient.Views.Calls +{ + public partial class ReturnToCallControl : UserControl + { + public ReturnToCallControl() + { + InitializeComponent(); + } + } +} diff --git a/TelegramClient.WP81/Views/Calls/SignalBarsControl.xaml b/TelegramClient.WP81/Views/Calls/SignalBarsControl.xaml new file mode 100755 index 0000000..20a48d6 --- /dev/null +++ b/TelegramClient.WP81/Views/Calls/SignalBarsControl.xaml @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Calls/SignalBarsControl.xaml.cs b/TelegramClient.WP81/Views/Calls/SignalBarsControl.xaml.cs new file mode 100755 index 0000000..78b4647 --- /dev/null +++ b/TelegramClient.WP81/Views/Calls/SignalBarsControl.xaml.cs @@ -0,0 +1,35 @@ +using System.Windows; + +namespace TelegramClient.Views.Calls +{ + public partial class SignalBarsControl + { + public static readonly DependencyProperty SignalProperty = DependencyProperty.Register( + "Signal", typeof(int), typeof(SignalBarsControl), new PropertyMetadata(OnSignalChanged)); + + private static void OnSignalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as SignalBarsControl; + if (control != null) + { + var signal = (int) e.NewValue; + + control.Bar1.Opacity = signal >= 1 ? 1.0 : 0.5; + control.Bar2.Opacity = signal >= 2 ? 1.0 : 0.5; + control.Bar3.Opacity = signal >= 3 ? 1.0 : 0.5; + control.Bar4.Opacity = signal >= 4 ? 1.0 : 0.5; + } + } + + public int Signal + { + get { return (int) GetValue(SignalProperty); } + set { SetValue(SignalProperty, value); } + } + + public SignalBarsControl() + { + InitializeComponent(); + } + } +} diff --git a/TelegramClient.WP81/Views/Chats/GroupStickersView.xaml b/TelegramClient.WP81/Views/Chats/GroupStickersView.xaml new file mode 100755 index 0000000..916bcf3 --- /dev/null +++ b/TelegramClient.WP81/Views/Chats/GroupStickersView.xaml @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Chats/GroupStickersView.xaml.cs b/TelegramClient.WP81/Views/Chats/GroupStickersView.xaml.cs new file mode 100755 index 0000000..361e9df --- /dev/null +++ b/TelegramClient.WP81/Views/Chats/GroupStickersView.xaml.cs @@ -0,0 +1,122 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Input; +using Telegram.Api.TL; +using TelegramClient.ViewModels.Chats; + +namespace TelegramClient.Views.Chats +{ + public partial class GroupStickersView + { + public GroupStickersViewModel ViewModel + { + get { return DataContext as GroupStickersViewModel; } + } + + public GroupStickersView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + } + + private bool _once; + + private TextBox _searchBox; + + private Border _removeButton; + + private void ForwardTransition_OnEndTransition(object sender, RoutedEventArgs e) + { + if (!_once) + { + _once = true; + ViewModel.ForwardInAnimationComplete(); + } + } + + private void DoneButton_OnClick(object sender, GestureEventArgs e) + { + ViewModel.Done(); + } + + private void Remove_OnClick(object sender, RoutedEventArgs e) + { + ViewModel.Remove(); + } + + private void TextBox_OnTextChanged(object sender, TextChangedEventArgs e) + { + if (_removeButton == null) return; + if (_searchBox == null) return; + + _removeButton.Visibility = string.IsNullOrEmpty(_searchBox.Text) ? Visibility.Collapsed : Visibility.Visible; + } + + private void LongListSelector_OnScrollingStarted(object sender, System.EventArgs e) + { + if (_searchBox == null) return; + + var focusedElement = FocusManager.GetFocusedElement(); + if (focusedElement == _searchBox) + { + Main.Focus(); + } + } + + private void SearchBox_OnLoaded(object sender, RoutedEventArgs e) + { + _searchBox = sender as TextBox; + } + + private void RemoveButton_OnLoaded(object sender, RoutedEventArgs e) + { + _removeButton = sender as Border; + } + + public void MoveCursorToEnd() + { + if (_searchBox == null) return; + + _searchBox.Select(_searchBox.Text.Length, 0); + } + } + + public class StickerSetTemplateSelector : IValueConverter + { + public DataTemplate StickerSetTemplate { get; set; } + + public DataTemplate NotFoundStickerSetTemplate { get; set; } + + public DataTemplate EmptyStickerSetTemplate { get; set; } + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is TLStickerSet32) + { + return StickerSetTemplate; + } + if (value is TLStickerSetNotFound) + { + return NotFoundStickerSetTemplate; + } + + return EmptyStickerSetTemplate; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Contacts/ShareContactDetailsView.xaml b/TelegramClient.WP81/Views/Contacts/ShareContactDetailsView.xaml new file mode 100755 index 0000000..2213722 --- /dev/null +++ b/TelegramClient.WP81/Views/Contacts/ShareContactDetailsView.xaml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/CameraControl.xaml.cs b/TelegramClient.WP81/Views/Controls/CameraControl.xaml.cs new file mode 100755 index 0000000..b57c398 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/CameraControl.xaml.cs @@ -0,0 +1,1532 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Threading; +using Windows.Devices.Enumeration; +using Windows.Foundation; +using Windows.Graphics.Display; +using Windows.Graphics.Imaging; +using Windows.Media.Capture; +using Windows.Media.Devices; +using Windows.Media.MediaProperties; +using Windows.Phone.Media.Capture; +using Windows.Storage; +using Windows.Storage.AccessCache; +using Windows.Storage.Streams; +using Caliburn.Micro; +using Microsoft.Devices; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; +using Microsoft.Xna.Framework; +using Telegram.Api.TL; +using TelegramClient.Resources; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; +using MediaStreamType = Windows.Media.Capture.MediaStreamType; +using Point = Windows.Foundation.Point; +using Rect = Windows.Foundation.Rect; + +namespace TelegramClient.Views.Controls +{ + public partial class CameraPage + { + public event EventHandler VideoCaptured; + + protected virtual void RaiseVideoCaptured(FileEventArgs e) + { + var handler = VideoCaptured; + if (handler != null) handler(this, e); + } + + public event EventHandler PhotoCaptured; + + protected virtual void RaisePhotoCaptured(FileEventArgs e) + { + var handler = PhotoCaptured; + if (handler != null) handler(this, e); + } + + private bool _mediaCaptureManagerInitialized; + + private LowLagPhotoCapture _lowLagPhotoCapture; + + private LowLagMediaRecording _lowLagMediaRecording; + + private MediaCapture _mediaCaptureManager; + + private MediaCapturePreviewSink _previewSink; + + private MediaEncodingProfile _currentProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD720p); + + private PageOrientation _previousOrientation; + + public CameraPage() + { + InitializeComponent(); + + // Sample code to localize the ApplicationBar + //BuildLocalizedApplicationBar(); + + _timer.Tick += TimerOnTick; + + LayoutUpdated += OnLayoutUpdated; + + _previousOrientation = PageOrientation.PortraitUp; + Loaded += (sender, args) => + { + CameraButtons.ShutterKeyPressed += CameraButtonsOnShutterKeyPressed; + CameraButtons.ShutterKeyHalfPressed += CameraButtonsOnShutterKeyHalfPressed; + //Windows.Graphics.Display.DisplayOrientations. + DisplayProperties.OrientationChanged += DisplayProperties_OrientationChanged; + }; + Unloaded += (sender, args) => + { + CameraButtons.ShutterKeyPressed -= CameraButtonsOnShutterKeyPressed; + CameraButtons.ShutterKeyHalfPressed -= CameraButtonsOnShutterKeyHalfPressed; + DisplayProperties.OrientationChanged -= DisplayProperties_OrientationChanged; + }; + } + + private void DisplayProperties_OrientationChanged(object sender) + { + System.Diagnostics.Debug.WriteLine("current={0} native={1}", DisplayProperties.CurrentOrientation, DisplayProperties.NativeOrientation); + } + + ~CameraPage() + { + + } + + public static readonly DependencyProperty ParentPageOrientationProperty = DependencyProperty.Register( + "ParentPageOrientation", typeof (PageOrientation), typeof (CameraPage), new PropertyMetadata(default(PageOrientation), OnParentPageOrientationChanged)); + + private static void OnParentPageOrientationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var cameraPage = d as CameraPage; + if (cameraPage != null) + { + cameraPage.MainPage_OnOrientationChanged(cameraPage, new OrientationChangedEventArgs((PageOrientation)e.NewValue)); + } + } + + public PageOrientation ParentPageOrientation + { + get { return (PageOrientation) GetValue(ParentPageOrientationProperty); } + set { SetValue(ParentPageOrientationProperty, value); } + } + + private void OnLayoutUpdated(object sender, System.EventArgs e) + { + LayoutUpdated -= OnLayoutUpdated; + + InitializeCameraAsync(); + } + + private void CameraButtonsOnShutterKeyHalfPressed(object sender, System.EventArgs eventArgs) + { + Focus_OnClick(null, null); + } + + private void CameraButtonsOnShutterKeyPressed(object sender, System.EventArgs eventArgs) + { + RecordButton_OnClick(null, null); + } + + private void DisposeInternal() + { + _initialized = false; + if (_mediaCaptureManager != null) + { + _mediaCaptureManager.RecordLimitationExceeded -= RecordLimitationExceeded; + _mediaCaptureManager.Failed -= Failed; + _mediaCaptureManager.Dispose(); + } + if (_previewSink != null) _previewSink.Dispose(); + + //Preview.Background = null; + } + + private DeviceInformation _frontCamera; + + private DeviceInformation _rearCamera; + + private bool _isRearCamera = true; + + private async Task InitializeCameraAsync() + { + RecordButton.IsEnabled = true; + SwitchModeButton.IsEnabled = true; + FlashButton.IsEnabled = true; + + SwitchMode(CameraMode.Photo); + + Focus.IsHitTestVisible = false; + Focus.Opacity = 0.0; + _mediaCaptureManager = new MediaCapture(); + + if (_rearCamera == null && _frontCamera == null) + { + var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture); + + foreach (var device in devices) + { + switch (device.EnclosureLocation.Panel) + { + case Windows.Devices.Enumeration.Panel.Front: + _frontCamera = device; + + break; + case Windows.Devices.Enumeration.Panel.Back: + _rearCamera = device; + + break; + default: + //you can also check for Top, Left, right and Bottom + break; + } + } + } + + if (_frontCamera == null || _rearCamera == null) + { + SwitchCameraButton.IsEnabled = false; + } + if (_isRearCamera && _rearCamera == null) + { + _isRearCamera = false; + } + if (!_isRearCamera && _frontCamera == null) + { + _isRearCamera = true; + } + + var currentCamera = _isRearCamera ? _rearCamera : _frontCamera; + + _mediaCaptureManagerInitialized = false; + + var photoCaptureSource = PhotoCaptureSource.Auto; + try + { + //if (_isRearCamera) + //{ + // throw new Exception("Initialization exception"); + //} + + var settings = new MediaCaptureInitializationSettings + { + VideoDeviceId = currentCamera.Id, + PhotoCaptureSource = photoCaptureSource, + //StreamingCaptureMode = StreamingCaptureMode.Video, + //AudioDeviceId = "" + //VideoSource = screenCapture.VideoSource + }; + + await _mediaCaptureManager.InitializeAsync(settings); + + _mediaCaptureManagerInitialized = true; + } + catch (Exception ex) + { + HandleCameraException(ex); + } + + if (!_mediaCaptureManagerInitialized) + { + Preview.Background = null; + RecordButton.IsEnabled = false; + SwitchModeButton.IsEnabled = false; + FlashButton.IsEnabled = false; + MessageBox.Show(AppResources.AccessCameraException, AppResources.Error, MessageBoxButton.OK); + return; + } + + if (!string.IsNullOrEmpty(_mediaCaptureManager.MediaCaptureSettings.VideoDeviceId) + && !string.IsNullOrEmpty(_mediaCaptureManager.MediaCaptureSettings.AudioDeviceId)) + { + //hook into MediaCapture events + _mediaCaptureManager.RecordLimitationExceeded += RecordLimitationExceeded; + _mediaCaptureManager.Failed += Failed; + + //device initialized successfully + } + else + { + Preview.Background = null; + RecordButton.IsEnabled = false; + SwitchModeButton.IsEnabled = false; + FlashButton.IsEnabled = false; + MessageBox.Show(AppResources.AccessCameraException, AppResources.Error, MessageBoxButton.OK); + _mediaCaptureManagerInitialized = false; + return; + //no cam found + } + + //return; + // List of supported video preview formats to be used by the default preview format selector. + + //var previewFormat = _currentProfile.Video; + var mediaStreamType = MediaStreamType.VideoPreview; + var previewFormat = GetStreamFormat(_currentProfile.Video, mediaStreamType, true); + + var scale = previewFormat.Width / Application.Current.Host.Content.ActualHeight; + var width = Application.Current.Host.Content.ActualHeight; + var height = previewFormat.Height / scale; + + Preview.Width = width * 0.75; + Preview.Height = height * 0.75; + + + await _mediaCaptureManager.VideoDeviceController.SetMediaStreamPropertiesAsync(mediaStreamType, previewFormat); + + if (_mediaCaptureManager.MediaCaptureSettings.VideoDeviceCharacteristic != VideoDeviceCharacteristic.AllStreamsIdentical + && _mediaCaptureManager.MediaCaptureSettings.VideoDeviceCharacteristic != VideoDeviceCharacteristic.PreviewRecordStreamsIdentical + && _mediaCaptureManager.MediaCaptureSettings.VideoDeviceCharacteristic != VideoDeviceCharacteristic.RecordPhotoStreamsIdentical) + { + mediaStreamType = MediaStreamType.VideoRecord; + var recordFormat = GetStreamFormat(previewFormat, mediaStreamType, true); + await _mediaCaptureManager.VideoDeviceController.SetMediaStreamPropertiesAsync(mediaStreamType, recordFormat); + + if (photoCaptureSource != PhotoCaptureSource.VideoPreview) + { + mediaStreamType = MediaStreamType.Photo; + recordFormat = GetStreamFormat(previewFormat, mediaStreamType); + await _mediaCaptureManager.VideoDeviceController.SetMediaStreamPropertiesAsync(mediaStreamType, recordFormat); + } + } + + //return; + var previewSink = new MediaCapturePreviewSink(); + _previewSink = previewSink; + await _mediaCaptureManager.StartPreviewToCustomSinkAsync(new MediaEncodingProfile { Video = previewFormat }, previewSink); + + + // Set the source of the VideoBrush used for your preview + var videoBrush = new VideoBrush(); + //videoBrush.Stretch = Stretch.UniformToFill; + Preview.Background = videoBrush; + + videoBrush.SetSource(previewSink); + + + var scaleX = Application.Current.Host.Content.ActualHeight / Preview.Width; + var scaleY = Application.Current.Host.Content.ActualWidth / Preview.Height; + var scaleMax = Math.Max(scaleX, scaleY); + Transform.ScaleX = scaleMax; + Transform.ScaleY = scaleMax; + + if (_isRearCamera) + { + Transform.ScaleX = Math.Abs(Transform.ScaleX); + } + else + { + Transform.ScaleX = -Math.Abs(Transform.ScaleX); + } + + try + { + _flashControlMode = _isRearCamera ? FlashControlMode.Auto : FlashControlMode.Disabled; //GetFlashControlMode(_mediaCaptureManager.VideoDeviceController.FlashControl); + SwitchFlashControlMode(_flashControlMode, _mediaCaptureManager.VideoDeviceController.FlashControl); + FlashButton.IsEnabled = _mediaCaptureManager.VideoDeviceController.FlashControl.Supported; + } + catch (Exception ex) + { + HandleCameraException(ex); + } + + try + { + if (_mediaCaptureManager.VideoDeviceController.FocusControl.Supported) + { + var modes = _mediaCaptureManager.VideoDeviceController.FocusControl.SupportedFocusModes; + if (modes.Contains(FocusMode.Continuous)) + { + _mediaCaptureManager.VideoDeviceController.FocusControl.Configure(new FocusSettings + { + Mode = FocusMode.Continuous, + DisableDriverFallback = true + }); + } + else + { + _mediaCaptureManager.VideoDeviceController.FocusControl.Configure(new FocusSettings + { + Mode = FocusMode.Auto + }); + } + + await _mediaCaptureManager.VideoDeviceController.FocusControl.FocusAsync(); + } + } + catch (Exception ex) + { + HandleCameraException(ex); + } + + try + { + _mediaCaptureManager.VideoDeviceController.LowLagPhoto.ThumbnailEnabled = false; + _lowLagPhotoCapture = await _mediaCaptureManager.PrepareLowLagPhotoCaptureAsync(ImageEncodingProperties.CreateJpeg()); + } + catch (Exception ex) + { + HandleCameraException(ex); + } + } + + private static void HandleCameraException(Exception ex) + { + TLUtils.WriteException("In-App Camera", ex); + } + + private VideoEncodingProperties GetStreamFormat(VideoEncodingProperties encodingProperties, MediaStreamType mediaStreamType, bool debug = false) + { + var supportedVideoFormats = new List { "nv12", "rgb32" }; + + // Find the supported preview format + var properties = _mediaCaptureManager.VideoDeviceController.GetAvailableMediaStreamProperties(mediaStreamType) + .OfType() + .Where(p => p != null && !String.IsNullOrEmpty(p.Subtype) && supportedVideoFormats.Contains(p.Subtype.ToLower())) + .ToList(); + + if (properties == null || properties.Count == 0) return null; + + var aspectRatio = (double)encodingProperties.Height / encodingProperties.Width; + var currentFormat = properties.First(); + var widthDelta = encodingProperties.Width >= currentFormat.Width ? encodingProperties.Width - currentFormat.Width : currentFormat.Width - encodingProperties.Width; + foreach (var p in properties) + { + var propertyRatio = (double)p.Height / p.Width; + var propertyWidthDelta = encodingProperties.Width >= p.Width ? encodingProperties.Width - p.Width : p.Width - encodingProperties.Width; + if (Math.Abs(aspectRatio - propertyRatio) <= 0.05 + && propertyWidthDelta < widthDelta) + { + widthDelta = propertyWidthDelta; + currentFormat = p; + } + } + + var builder = new StringBuilder(); + builder.AppendLine(string.Format("mediaStreamType={0}", mediaStreamType)); + builder.AppendLine(string.Format("CAPTUREPROFILE={0}x{1} {2} {3}", encodingProperties.Width, encodingProperties.Height, (double)encodingProperties.Height / encodingProperties.Width, encodingProperties.FrameRate.Numerator / encodingProperties.FrameRate.Denominator)); + foreach (var p in properties) + { + builder.AppendLine(string.Format("availableFormat={0}x{1} {2} {3}", p.Width, p.Height, (double)p.Height / p.Width, p.FrameRate.Numerator / p.FrameRate.Denominator)); + } + builder.AppendLine(string.Format("SELECTEDFORMAT={0}x{1} {2} {3}", currentFormat.Width, currentFormat.Height, (double)currentFormat.Height / currentFormat.Width, currentFormat.FrameRate.Numerator / currentFormat.FrameRate.Denominator)); + + if (debug) + { + SetDebugText(builder.ToString(), 45000); + } + + DebugWriteLine("mediaStreamType={0}", mediaStreamType); + DebugWriteLine("captureProfile={0}x{1} {2} {3}", encodingProperties.Width, encodingProperties.Height, (double)encodingProperties.Height / encodingProperties.Width, encodingProperties.FrameRate.Numerator / encodingProperties.FrameRate.Denominator); + foreach (var p in properties) + { + DebugWriteLine("availableFormat={0}x{1} {2} {3}", p.Width, p.Height, (double)p.Height / p.Width, p.FrameRate.Numerator / p.FrameRate.Denominator); + } + DebugWriteLine("selectedFormat={0}x{1} {2} {3}", currentFormat.Width, currentFormat.Height, (double)currentFormat.Height / currentFormat.Width, currentFormat.FrameRate.Numerator / currentFormat.FrameRate.Denominator); + + return currentFormat; + } + + private static void DebugWriteLine(string str, params object[] args) + { + System.Diagnostics.Debug.WriteLine(str, args); + } + + private async void Focus_OnClick(object sender, RoutedEventArgs e) + { + if (!_mediaCaptureManagerInitialized) + { + return; + } + + if (!_mediaCaptureManager.VideoDeviceController.FocusControl.Supported) + { + return; + } + + try + { + await _mediaCaptureManager.VideoDeviceController.FocusControl.FocusAsync(); + } + catch (Exception ex) + { + HandleCameraException(ex); + } + } + + #region Flash Control + private FlashControlMode _flashControlMode; + + private void Flash_OnClick(object sender, RoutedEventArgs e) + { + if (!_mediaCaptureManagerInitialized) + { + return; + } + + var flashControl = _mediaCaptureManager.VideoDeviceController.FlashControl; + if (!flashControl.Supported) return; + + _flashControlMode = GetNextFlashControlMode(_flashControlMode); + SwitchFlashControlMode(_flashControlMode, flashControl); + } + + private FlashControlMode GetFlashControlMode(FlashControl flashControl) + { + if (!flashControl.Supported) + { + return FlashControlMode.Disabled; + } + + if (!flashControl.Enabled) + { + return FlashControlMode.Disabled; + } + + if (flashControl.Auto) + { + return FlashControlMode.Auto; + } + + return FlashControlMode.Enabled; + } + + private FlashControlMode GetNextFlashControlMode(FlashControlMode flashControlMode) + { + if (flashControlMode == FlashControlMode.Auto) + { + return FlashControlMode.Disabled; + } + + if (flashControlMode == FlashControlMode.Disabled) + { + return FlashControlMode.Enabled; + } + + return FlashControlMode.Auto; + } + + private void SwitchFlashControlMode(FlashControlMode mode, FlashControl flashControl) + { + if (mode == FlashControlMode.Auto) + { + if (flashControl.Supported) + { + flashControl.Enabled = true; + flashControl.Auto = true; + if (flashControl.AssistantLightSupported) + { + flashControl.AssistantLightEnabled = false; + } + FlashButtonImage.Source = new BitmapImage(new Uri("/Images/W10M/ic_flash_auto_2x.png", UriKind.Relative)); + } + } + else if (mode == FlashControlMode.Disabled) + { + if (flashControl.Supported) + { + flashControl.Enabled = false; + flashControl.Auto = false; + if (flashControl.AssistantLightSupported) + { + flashControl.AssistantLightEnabled = false; + } + } + FlashButtonImage.Source = new BitmapImage(new Uri("/Images/W10M/ic_flash_disabled_2x.png", UriKind.Relative)); + } + else + { + if (flashControl.Supported) + { + flashControl.Enabled = true; + flashControl.Auto = false; + if (flashControl.AssistantLightSupported) + { + flashControl.AssistantLightEnabled = true; + } + FlashButtonImage.Source = new BitmapImage(new Uri("/Images/W10M/ic_flash_enabled_2x.png", UriKind.Relative)); + } + } + } + #endregion + + private void Failed(MediaCapture sender, MediaCaptureFailedEventArgs erroreventargs) + { + if (_isRecording) + { + StopRecording(); + } + } + + private void RecordLimitationExceeded(MediaCapture sender) + { + if (_isRecording) + { + StopRecording(); + } + } + + public void MainPage_OnOrientationChanged(object sender, OrientationChangedEventArgs e) + { + if (e.Orientation == PageOrientation.LandscapeLeft) + { + // Width = Application.Current.Host.Content.ActualHeight; + // Height = Application.Current.Host.Content.ActualWidth; + + // FlashButton.VerticalAlignment = VerticalAlignment.Top; + // FlashButton.HorizontalAlignment = HorizontalAlignment.Center; + + // BottomBorder.HorizontalAlignment = HorizontalAlignment.Right; + // BottomBorder.VerticalAlignment = VerticalAlignment.Stretch; + // BottomBorderTranslate.X = 72.0; + // BottomBorderTranslate.Y = 0.0; + + ContentPanel.Children.Remove(ProgressText); + ButtonsPanel.Children.Remove(ProgressText); + ContentPanel.Children.Add(ProgressText); + ProgressText.Margin = new Thickness(0.0); + ProgressTextTransform.Rotation = 90.0; + ProgressTextTransform.TranslateX = -200.0; + + // ButtonsPanel.ColumnDefinitions.Clear(); + // ButtonsPanel.RowDefinitions.Clear(); + // ButtonsPanel.RowDefinitions.Add(new RowDefinition()); + // ButtonsPanel.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + // ButtonsPanel.RowDefinitions.Add(new RowDefinition()); + + // Grid.SetRow(SwitchModeButton, 2); + // Grid.SetRow(ProgressCircle, 1); + // Grid.SetRow(RecordButton, 1); + // Grid.SetRow(SwitchCameraButton, 0); + + // Transform.Rotation = 0; + + // ButtonsPanel.HorizontalAlignment = HorizontalAlignment.Right; + // ButtonsPanel.VerticalAlignment = VerticalAlignment.Center; + } + else if (e.Orientation == PageOrientation.LandscapeRight) + { + // Width = Application.Current.Host.Content.ActualHeight; + // Height = Application.Current.Host.Content.ActualWidth; + + // FlashButton.VerticalAlignment = VerticalAlignment.Bottom; + // FlashButton.HorizontalAlignment = HorizontalAlignment.Center; + + // BottomBorder.HorizontalAlignment = HorizontalAlignment.Left; + // BottomBorder.VerticalAlignment = VerticalAlignment.Stretch; + // BottomBorderTranslate.X = -72.0; + // BottomBorderTranslate.Y = 0.0; + + ContentPanel.Children.Remove(ProgressText); + ButtonsPanel.Children.Remove(ProgressText); + ContentPanel.Children.Add(ProgressText); + ProgressText.Margin = new Thickness(0.0); + ProgressTextTransform.Rotation = -90.0; + ProgressTextTransform.TranslateX = 200.0; + + // ButtonsPanel.ColumnDefinitions.Clear(); + // ButtonsPanel.RowDefinitions.Clear(); + // ButtonsPanel.RowDefinitions.Add(new RowDefinition()); + // ButtonsPanel.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + // ButtonsPanel.RowDefinitions.Add(new RowDefinition()); + + // Grid.SetRow(SwitchModeButton, 0); + // Grid.SetRow(ProgressCircle, 1); + // Grid.SetRow(RecordButton, 1); + // Grid.SetRow(SwitchCameraButton, 2); + + // Transform.Rotation = 180; + + // ButtonsPanel.HorizontalAlignment = HorizontalAlignment.Left; + // ButtonsPanel.VerticalAlignment = VerticalAlignment.Center; + } + else + { + // Width = Application.Current.Host.Content.ActualWidth; + // Height = Application.Current.Host.Content.ActualHeight; + + // FlashButton.VerticalAlignment = VerticalAlignment.Center; + // FlashButton.HorizontalAlignment = HorizontalAlignment.Right; + + // BottomBorder.HorizontalAlignment = HorizontalAlignment.Stretch; + // BottomBorder.VerticalAlignment = VerticalAlignment.Bottom; + // BottomBorderTranslate.X = 0.0; + // BottomBorderTranslate.Y = 72.0; + + ContentPanel.Children.Remove(ProgressText); + ButtonsPanel.Children.Remove(ProgressText); + ButtonsPanel.Children.Add(ProgressText); + ProgressText.Margin = new Thickness(-8.0); + ProgressTextTransform.Rotation = 0.0; + ProgressTextTransform.TranslateX = 0.0; + + // ButtonsPanel.ColumnDefinitions.Clear(); + // ButtonsPanel.RowDefinitions.Clear(); + // ButtonsPanel.RowDefinitions.Add(new RowDefinition()); + // ButtonsPanel.RowDefinitions.Add(new RowDefinition()); + // ButtonsPanel.ColumnDefinitions.Add(new ColumnDefinition()); + // ButtonsPanel.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + // ButtonsPanel.ColumnDefinitions.Add(new ColumnDefinition()); + + // Grid.SetRow(SwitchModeButton, 1); + // Grid.SetRow(ProgressCircle, 1); + // Grid.SetRow(RecordButton, 1); + // Grid.SetRow(SwitchCameraButton, 1); + + // Transform.Rotation = 90; + + // RotateTransform.Angle = 0; + // ButtonsPanel.VerticalAlignment = VerticalAlignment.Bottom; + // ButtonsPanel.HorizontalAlignment = HorizontalAlignment.Center; + } + + StartRotateAnimation(e.Orientation); + + //SetFocusTranslation(_previousOrientation, e.Orientation); + + _previousOrientation = e.Orientation; + } + + private void SetFocusTranslation(PageOrientation previousOrientation, PageOrientation orientation) + { + double translateX = 0.0; + double translateY = 0.0; + + var contentWidth = (_previousOrientation & PageOrientation.Portrait) == PageOrientation.Portrait + ? Application.Current.Host.Content.ActualWidth + : Application.Current.Host.Content.ActualHeight; + var contentHeight = (_previousOrientation & PageOrientation.Portrait) == PageOrientation.Portrait + ? Application.Current.Host.Content.ActualHeight + : Application.Current.Host.Content.ActualWidth; + + if (previousOrientation == PageOrientation.PortraitUp) + { + if (orientation == PageOrientation.LandscapeLeft) + { + translateX = FocusTransform.TranslateY; + translateY = contentHeight - FocusTransform.TranslateX - Focus.ActualHeight; + } + else if (orientation == PageOrientation.LandscapeRight) + { + translateX = contentWidth - FocusTransform.TranslateY - Focus.ActualWidth; + translateY = FocusTransform.TranslateX; + } + } + else if (previousOrientation == PageOrientation.LandscapeLeft) + { + if (orientation == PageOrientation.PortraitUp) + { + translateX = contentWidth - FocusTransform.TranslateY - Focus.ActualWidth; + translateY = FocusTransform.TranslateX; + } + else if (orientation == PageOrientation.LandscapeRight) + { + translateX = contentWidth - FocusTransform.TranslateX - Focus.ActualHeight; + translateY = contentHeight - FocusTransform.TranslateY - Focus.ActualWidth; + } + } + else if (previousOrientation == PageOrientation.LandscapeRight) + { + if (orientation == PageOrientation.PortraitUp) + { + translateX = FocusTransform.TranslateY; + translateY = contentHeight - FocusTransform.TranslateX - Focus.ActualHeight; + } + else if (orientation == PageOrientation.LandscapeLeft) + { + translateX = contentWidth - FocusTransform.TranslateX - Focus.ActualHeight; + translateY = contentHeight - FocusTransform.TranslateY - Focus.ActualWidth; + } + } + + FocusTransform.TranslateX = translateX; + FocusTransform.TranslateY = translateY; + } + + private Storyboard _rotateStoryboard; + + private void StartRotateAnimation(PageOrientation orientation) + { + if (_rotateStoryboard != null) + { + _rotateStoryboard.Stop(); + } + + double from = 0.0; + if (orientation == PageOrientation.PortraitUp) + { + from = 0.0; + } + else if (orientation == PageOrientation.LandscapeLeft) + { + from = 90.0; + } + else if (orientation == PageOrientation.LandscapeRight) + { + from = -90.0; + } + + _rotateStoryboard = new Storyboard(); + + var progressCircleAnimation = new DoubleAnimation { To = from, Duration = TimeSpan.FromSeconds(0.3) }; + Storyboard.SetTarget(progressCircleAnimation, ProgressCircleTransform); + Storyboard.SetTargetProperty(progressCircleAnimation, new PropertyPath("Angle")); + _rotateStoryboard.Children.Add(progressCircleAnimation); + + var recordAnimation = new DoubleAnimation { To = from, Duration = TimeSpan.FromSeconds(0.3) }; + Storyboard.SetTarget(recordAnimation, RecordTransform); + Storyboard.SetTargetProperty(recordAnimation, new PropertyPath("Angle")); + _rotateStoryboard.Children.Add(recordAnimation); + + var switchCameraAnimation = new DoubleAnimation { To = from, Duration = TimeSpan.FromSeconds(0.3) }; + Storyboard.SetTarget(switchCameraAnimation, SwitchCameraTransform); + Storyboard.SetTargetProperty(switchCameraAnimation, new PropertyPath("Angle")); + _rotateStoryboard.Children.Add(switchCameraAnimation); + + var switchModeAnimation = new DoubleAnimation { To = from, Duration = TimeSpan.FromSeconds(0.3) }; + Storyboard.SetTarget(switchModeAnimation, SwitchModeTransform); + Storyboard.SetTargetProperty(switchModeAnimation, new PropertyPath("Angle")); + _rotateStoryboard.Children.Add(switchModeAnimation); + + var focusAnimation = new DoubleAnimation { To = from, Duration = TimeSpan.FromSeconds(0.3) }; + Storyboard.SetTarget(focusAnimation, FlashTransform); + Storyboard.SetTargetProperty(focusAnimation, new PropertyPath("Rotation")); + _rotateStoryboard.Children.Add(focusAnimation); + + Deployment.Current.Dispatcher.BeginInvoke(() => _rotateStoryboard.Begin()); + } + + // Rotation metadata to apply to the preview stream and recorded videos (MF_MT_VIDEO_ROTATION) + // Reference: http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh868174.aspx + private static readonly Guid RotationKey = new Guid("C380465D-2271-428C-9B83-ECEA3B4A85C1"); + + private bool _isSwitchingMode; + + private async void Switch_OnClick(object sender, RoutedEventArgs e) + { + if (_isSwitchingMode) + { + return; + } + + try + { + _isSwitchingMode = true; + if (_previewSink != null) _previewSink.Dispose(); + if (_mediaCaptureManager != null) _mediaCaptureManager.Dispose(); + + _isRearCamera = !_isRearCamera; + + await InitializeCameraAsync(); + } + catch (Exception ex) + { + HandleCameraException(ex); + } + finally + { + _isSwitchingMode = false; + } + } + + private bool _isCapturingPhoto; + + private async void RecordButton_OnClick(object sender, RoutedEventArgs e) + { + DebugWriteLine("RecordButton_OnClick " + _mode); + + if (!_mediaCaptureManagerInitialized) + { + return; + } + + if (_isHolded) + { + return; + } + + if (_mode == CameraMode.Recording) + { + StopRecording(); + } + else if (_mode == CameraMode.Video) + { + await StartRecording(); + } + else + { + if (_isCapturingPhoto) return; + + _isCapturingPhoto = true; + try + { + LayoutRoot.IsHitTestVisible = false; + var stopwatch = Stopwatch.StartNew(); + //declare string for filename + string captureFileName = string.Empty; + //declare image format + //ImageEncodingProperties format = ImageEncodingProperties.CreateJpeg(); + //format.Width = 3840; + //format.Height = 2160; + + DebugWriteLine("Before CapturePhotoToStreamAsync " + stopwatch.Elapsed); + //generate stream from MediaCapture + + var storyboard = new Storyboard(); + var translateXAnimation = new DoubleAnimation { From = 0.0, To = FlashButton.ActualWidth + FlashButton.Margin.Right + FlashButton.Margin.Left, Duration = TimeSpan.FromSeconds(1.5), EasingFunction = new ExponentialEase{ Exponent = 5.0, EasingMode = EasingMode.EaseOut }}; + Storyboard.SetTarget(translateXAnimation, FlashTransform); + Storyboard.SetTargetProperty(translateXAnimation, new PropertyPath("TranslateX")); + storyboard.Children.Add(translateXAnimation); + + var translateYAnimation = new DoubleAnimation { From = 0.0, To = ButtonsPanel.ActualHeight, Duration = TimeSpan.FromSeconds(1.5), EasingFunction = new ExponentialEase { Exponent = 5.0, EasingMode = EasingMode.EaseOut } }; + Storyboard.SetTarget(translateYAnimation, ButtonsPanelTransform); + Storyboard.SetTargetProperty(translateYAnimation, new PropertyPath("TranslateY")); + storyboard.Children.Add(translateYAnimation); + + storyboard.Begin(); + storyboard.Completed += (o, args) => + { + RaisePhotoCaptured(new FileEventArgs { File = null }); + }; + + var rotation = GetRotation(); + //await _mediaCaptureManager.StopPreviewAsync(); + Telegram.Api.Helpers.Execute.BeginOnThreadPool(async () => + { + var capturedPhoto = await _lowLagPhotoCapture.CaptureAsync(); + + var elapsed2 = stopwatch.Elapsed; + await _mediaCaptureManager.StopPreviewAsync(); + var elapsed = stopwatch.Elapsed; + DebugWriteLine("CapturePhotoToStreamAsync " + elapsed); + + var text = string.Format("StopPreview {3}\nCaptured {0}x{1} {2}", 0, 0, elapsed, elapsed2); + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => SetDebugText(text)); + //SetDebugText(text); + //return; + using (var imageStream = new InMemoryRandomAccessStream()) + { + + await RandomAccessStream.CopyAsync(capturedPhoto.Frame, imageStream); + + //create decoder and encoder + var dec = await BitmapDecoder.CreateAsync(imageStream); + var enc = await BitmapEncoder.CreateForTranscodingAsync(imageStream, dec); + + // fix for front camera mirroring + if (!_isRearCamera) + { + if (rotation == BitmapRotation.None) + { + rotation = BitmapRotation.Clockwise180Degrees; + } + else if (rotation == BitmapRotation.Clockwise180Degrees) + { + rotation = BitmapRotation.None; + } + enc.BitmapTransform.Flip = BitmapFlip.Vertical; + } + + //roate the image + enc.BitmapTransform.Rotation = rotation; + + //write changes to the image stream + await enc.FlushAsync(); + + var elapsed3 = stopwatch.Elapsed; + DebugWriteLine("FlushAsync " + stopwatch.Elapsed); + + //save the image + + var folder = KnownFolders.CameraRoll; + var capturefile = await folder.CreateFileAsync("photo_" + DateTime.Now.Ticks + ".jpg", CreationCollisionOption.ReplaceExisting); + + //store stream in file + using (var fileStream = await capturefile.OpenStreamForWriteAsync()) + { + try + { + //because of using statement stream will be closed automatically after copying finished + await RandomAccessStream.CopyAsync(imageStream, fileStream.AsOutputStream()); + DebugWriteLine("CopyAsync " + stopwatch.Elapsed); + } + catch (Exception ex) + { + HandleCameraException(ex); + } + } + + text = string.Format("StopPreview {3}\nCaptured {0}x{1} {2}\nRotate {4}\nSave {5}", capturedPhoto.Frame.Width, capturedPhoto.Frame.Height, elapsed, elapsed2, elapsed3, stopwatch.Elapsed); + + Execute.BeginOnUIThread(() => + { + SetDebugText(text); + RaisePhotoCaptured(new FileEventArgs { File = capturefile }); + }); + + Dispose(); + } + }); + } + catch (Exception ex) + { + HandleCameraException(ex); + } + finally + { + _isCapturingPhoto = false; + LayoutRoot.IsHitTestVisible = true; + } + } + } + + private void SetDebugText(string text, int millisecondsTimeout = 5000) + { +#if DEBUG + TimerLabel.Visibility = Visibility.Visible; + TimerLabel.Text = text; + ThreadPool.QueueUserWorkItem(state => + { + Thread.Sleep(5000); + Deployment.Current.Dispatcher.BeginInvoke(() => { TimerLabel.Visibility = Visibility.Collapsed; }); + }); +#endif + } + + private BitmapRotation GetRotation() + { + if (_previousOrientation == PageOrientation.LandscapeLeft) + { + return BitmapRotation.None; + } + else if (_previousOrientation == PageOrientation.LandscapeRight) + { + return BitmapRotation.Clockwise180Degrees; + } + else + { + if (_isRearCamera) + { + return BitmapRotation.Clockwise90Degrees; + } + else + { + return BitmapRotation.Clockwise270Degrees; + } + } + } + + private int GetVideoRotation() + { + if (_previousOrientation == PageOrientation.LandscapeLeft) + { + return 0; + } + else if (_previousOrientation == PageOrientation.LandscapeRight) + { + return 180; + } + else + { + if (_isRearCamera) + { + return 90; + } + else + { + return 270; + } + } + } + + private bool _isFocusing; + + private async void Preview_OnTap(object sender, GestureEventArgs e) + { + if (!_mediaCaptureManager.VideoDeviceController.FocusControl.Supported) + { + return; + } + + if (_isFocusing) + { + return; + } + + try + { + _isFocusing = true; + if (_mediaCaptureManager.VideoDeviceController.RegionsOfInterestControl.AutoFocusSupported + && _mediaCaptureManager.VideoDeviceController.RegionsOfInterestControl.MaxRegions > 0) + { + var properties = _mediaCaptureManager.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties; + var previewWidth = properties.Width; + var previewHeight = properties.Height; + + var scaleFactor = Math.Max(previewWidth, previewHeight) / Math.Max(Preview.ActualWidth, Preview.ActualHeight); + + var previewPosition = e.GetPosition(Preview); + var absolutePosition = e.GetPosition(ContentPanel); + System.Diagnostics.Debug.WriteLine("absolutePosition x={0} y={1}", absolutePosition.X, absolutePosition.Y); + var focusTransformX = absolutePosition.X - Focus.ActualWidth / 2.0; + var focusTransformY = absolutePosition.Y - Focus.ActualHeight / 2.0; + + var contentWidth = (_previousOrientation & PageOrientation.Portrait) == PageOrientation.Portrait + ? Application.Current.Host.Content.ActualWidth + : Application.Current.Host.Content.ActualHeight; + var contentHeight = (_previousOrientation & PageOrientation.Portrait) == PageOrientation.Portrait + ? Application.Current.Host.Content.ActualHeight + : Application.Current.Host.Content.ActualWidth; + + if (focusTransformX < 0) + { + focusTransformX = 0; + } + else if (focusTransformX > (contentWidth - Focus.ActualWidth)) + { + focusTransformX = (contentWidth - Focus.ActualWidth); + } + if (focusTransformY < 0) + { + focusTransformY = 0; + } + else if (focusTransformY > (contentHeight - Focus.ActualHeight)) + { + focusTransformY = (contentHeight - Focus.ActualHeight); + } + FocusTransform.TranslateX = focusTransformX; + FocusTransform.TranslateY = focusTransformY; + System.Diagnostics.Debug.WriteLine("focusTransform x={0} y={1}", focusTransformX, focusTransformY); + + Focus.IsHitTestVisible = true; + Focus.Opacity = 1.0; + + //System.Diagnostics.Debug.WriteLine("preview w={0} h={1}", previewWidth, previewHeight); + //System.Diagnostics.Debug.WriteLine("pos={0} w={1} h={2}", pos, Preview.ActualWidth, Preview.ActualHeight); + + var point1 = new Point((previewPosition.X - 25) * scaleFactor, (previewPosition.Y - 25) * scaleFactor); + if (point1.X < 0) + point1.X = 0; + if (point1.Y < 0) + point1.Y = 0; + + var point2 = new Point((previewPosition.X + 25) * scaleFactor, (previewPosition.Y + 25) * scaleFactor); + if (point2.X > previewWidth) + point2.X = previewWidth; + if (point2.Y > previewHeight) + point2.Y = previewHeight; + + var region = new RegionOfInterest(); + region.Bounds = new Rect(point1, point2); + System.Diagnostics.Debug.WriteLine("bounds x={0} y={1} of with={2} height={3}", region.Bounds.X, region.Bounds.Y, previewWidth, previewHeight); + region.BoundsNormalized = false; + region.AutoFocusEnabled = true; + region.AutoExposureEnabled = false; //this will make exposure for roi + region.AutoWhiteBalanceEnabled = false; //this will make wb for roi + + _mediaCaptureManager.VideoDeviceController.FocusControl.Configure(new FocusSettings + { + Mode = FocusMode.Single + }); + + await _mediaCaptureManager.VideoDeviceController.RegionsOfInterestControl.ClearRegionsAsync(); + await _mediaCaptureManager.VideoDeviceController.RegionsOfInterestControl.SetRegionsAsync(new List { region }, true); + + //note: before focusing, make sure or set single focus mode. That part of code not here. + await _mediaCaptureManager.VideoDeviceController.FocusControl.FocusAsync(); + } + else + { + var modes = _mediaCaptureManager.VideoDeviceController.FocusControl.SupportedFocusModes; + if (modes.Contains(FocusMode.Continuous)) + { + _mediaCaptureManager.VideoDeviceController.FocusControl.Configure(new FocusSettings + { + Mode = FocusMode.Continuous, + DisableDriverFallback = true + }); + } + else + { + _mediaCaptureManager.VideoDeviceController.FocusControl.Configure(new FocusSettings + { + Mode = FocusMode.Auto + }); + } + + await _mediaCaptureManager.VideoDeviceController.FocusControl.FocusAsync(); + } + } + catch (Exception ex) + { + HandleCameraException(ex); + } + finally + { + _isFocusing = false; + } + } + + private void Preview_OnManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + if (e.PinchManipulation == null) return; + + var zoomControl = _mediaCaptureManager.VideoDeviceController.ZoomControl; + if (!zoomControl.Supported) return; + + var zoomFactor = zoomControl.Value * e.PinchManipulation.DeltaScale; + + if (zoomFactor < zoomControl.Min) zoomFactor = zoomControl.Min; + if (zoomFactor > zoomControl.Max) zoomFactor = zoomControl.Max; + zoomFactor = zoomFactor - (zoomFactor % zoomControl.Step); + + _mediaCaptureManager.VideoDeviceController.ZoomControl.Value = (float)zoomFactor; + } + + private bool _isHolded = false; + + private bool _isRecording = false; + private bool _initialized; + private DateTime _startRecordTime; + + private DispatcherTimer _timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0.3) }; + + + private void TimerOnTick(object sender, System.EventArgs eventArgs) + { + if (!_isRecording) return; + + var time = (DateTime.Now - _startRecordTime); + + ProgressText.Text = time.ToString(@"mm\:ss"); + } + + private async void RecordButton_OnHold(object sender, GestureEventArgs e) + { + System.Diagnostics.Debug.WriteLine("RecordButton_OnHold " + _mode); + if (!_mediaCaptureManagerInitialized) + { + return; + } + + _isHolded = true; + + await StartRecording(); + } + + private Storyboard _progressStoryboard; + + private async Task StartRecording() + { + SwitchIdleDetectionMode(false); + + if (_isHolded) + { + Overlay.Background = new SolidColorBrush(Colors.White); + } + + _isRecordCanceled = false; + _isRecording = true; + var videoFolder = KnownFolders.CameraRoll; + _captureVideofile = await videoFolder.CreateFileAsync("video_" + DateTime.Now.Ticks + ".mp4", CreationCollisionOption.ReplaceExisting); + + var profile = _currentProfile; + profile.Video.Properties.Remove(RotationKey); + profile.Video.Properties.Add(RotationKey, PropertyValue.CreateInt32(GetVideoRotation())); + + System.Diagnostics.Debug.WriteLine("profile={0}x{1}", profile.Video.Width, profile.Video.Height); + + //await _mediaCaptureManager.StartRecordToStorageFileAsync(profile, _captureVideofile); + await _lowLagPhotoCapture.FinishAsync(); + + _lowLagMediaRecording = await _mediaCaptureManager.PrepareLowLagRecordToStorageFileAsync(profile, _captureVideofile); + await _lowLagMediaRecording.StartAsync(); + + + SetDebugText("Recording...", 30000); + _timer.Start(); + _startRecordTime = DateTime.Now; + + _progressStoryboard = new Storyboard(); + var progressAnimation = new DoubleAnimation { From = 0.0, To = 359.9, Duration = TimeSpan.FromSeconds(30.0) }; + Storyboard.SetTarget(progressAnimation, ProgressRing); + Storyboard.SetTargetProperty(progressAnimation, new PropertyPath("Angle")); + _progressStoryboard.Children.Add(progressAnimation); + + _progressStoryboard.Begin(); + _progressStoryboard.Completed += OnProgressStoryboardCompleted; + + SwitchMode(CameraMode.Recording); + } + + private void OnProgressStoryboardCompleted(object sender, System.EventArgs e) + { + if (_isRecording) + { + StopRecording(); + } + } + + private void RecordButton_OnMouseLeave(object sender, MouseEventArgs e) + { + DebugWriteLine("RecordButton_OnMouseLeave " + _mode); + if (_isRecording && _isHolded) + { + StopRecording(); + } + + _isHolded = false; + } + + private async Task StopRecording() + { + SwitchIdleDetectionMode(true); + + Overlay.Background = new SolidColorBrush(Colors.Transparent); + + _isRecording = false; + + TimerLabel.Visibility = Visibility.Collapsed; + _timer.Stop(); + ProgressText.Text = "00:00"; + + SwitchMode(CameraMode.Video); + + _progressStoryboard.Stop(); + + //await _mediaCaptureManager.StopRecordAsync(); + await _lowLagMediaRecording.StopAsync(); + await _lowLagMediaRecording.FinishAsync(); + _lowLagPhotoCapture = await _mediaCaptureManager.PrepareLowLagPhotoCaptureAsync(ImageEncodingProperties.CreateJpeg()); + + if (_isRecordCanceled) + { + _isRecordCanceled = false; + await _captureVideofile.DeleteAsync(StorageDeleteOption.PermanentDelete); + } + else + { + RaiseVideoCaptured(new FileEventArgs{ File = _captureVideofile }); + } + } + + private CameraMode _mode = CameraMode.Photo; + + private void SwitchMode(CameraMode mode) + { + _mode = mode; + + switch (mode) + { + case CameraMode.Photo: + ProgressText.Foreground = new SolidColorBrush(Colors.White); + ProgressText.Visibility = Visibility.Collapsed; + SwitchCameraButton.Visibility = Visibility.Visible; + SwitchModeButton.Visibility = Visibility.Visible; + FlashButton.Visibility = Visibility.Visible; + SwitchModeImage.Source = new BitmapImage(new Uri("/Images/W10M/ic_camera_video_2x.png", UriKind.Relative)); + RecordImage.Source = new BitmapImage(new Uri("/Images/W10M/ic_camera_photo_2x.png", UriKind.Relative)); + ProgressCircle.Opacity = 0.0; + return; + case CameraMode.Video: + ProgressText.Foreground = new SolidColorBrush(Colors.White); + ProgressText.Visibility = Visibility.Visible; + SwitchCameraButton.Visibility = Visibility.Visible; + SwitchModeButton.Visibility = Visibility.Visible; + FlashButton.Visibility = Visibility.Collapsed; + SwitchModeImage.Source = new BitmapImage(new Uri("/Images/W10M/ic_camera_photo_2x.png", UriKind.Relative)); + RecordImage.Source = new BitmapImage(new Uri("/Images/W10M/ic_camera_video_2x.png", UriKind.Relative)); + ProgressCircle.Opacity = 0.0; + return; + case CameraMode.Recording: + ProgressText.Foreground = new SolidColorBrush(Colors.White); + ProgressText.Visibility = Visibility.Visible; + SwitchCameraButton.Visibility = Visibility.Collapsed; + SwitchModeButton.Visibility = Visibility.Collapsed; + FlashButton.Visibility = Visibility.Collapsed; + RecordImage.Source = new BitmapImage(new Uri("/Images/W10M/ic_camera_stop_2x.png", UriKind.Relative)); + ProgressCircle.Opacity = 1.0; + return; + } + } + + private void SwitchMode_OnClick(object sender, RoutedEventArgs e) + { + if (_mode == CameraMode.Photo) + { + SwitchMode(CameraMode.Video); + } + else if (_mode == CameraMode.Video) + { + SwitchMode(CameraMode.Photo); + } + } + + private bool _isRecordCanceled; + private StorageFile _captureVideofile; + + private void RecordButton_OnManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + if (!_isHolded) + { + return; + } + + if (e.CumulativeManipulation == null) + { + return; + } + + var distance = + Math.Sqrt(e.CumulativeManipulation.Translation.X * e.CumulativeManipulation.Translation.X + + e.CumulativeManipulation.Translation.Y * e.CumulativeManipulation.Translation.Y); + + System.Diagnostics.Debug.WriteLine(e.CumulativeManipulation.Translation); + + if (distance >= 70.0) + { + _isRecordCanceled = true; + ProgressText.Foreground = (Brush)Resources["CancelForeground"]; + } + else + { + _isRecordCanceled = false; + ProgressText.Foreground = new SolidColorBrush(Colors.White); + } + } + + private async void Focus_OnTap(object sender, GestureEventArgs e) + { + if (!_mediaCaptureManager.VideoDeviceController.FocusControl.Supported) + { + return; + } + + if (_isFocusing) + { + return; + } + + Focus.Opacity = 0.0; + Focus.IsHitTestVisible = false; + + try + { + _isFocusing = true; + + await _mediaCaptureManager.VideoDeviceController.RegionsOfInterestControl.ClearRegionsAsync(); + + var modes = _mediaCaptureManager.VideoDeviceController.FocusControl.SupportedFocusModes; + if (modes.Contains(FocusMode.Continuous)) + { + _mediaCaptureManager.VideoDeviceController.FocusControl.Configure(new FocusSettings + { + Mode = FocusMode.Continuous, + DisableDriverFallback = true + }); + } + else + { + _mediaCaptureManager.VideoDeviceController.FocusControl.Configure(new FocusSettings + { + Mode = FocusMode.Auto + }); + } + await _mediaCaptureManager.VideoDeviceController.FocusControl.FocusAsync(); + } + catch (Exception ex) + { + HandleCameraException(ex); + } + finally + { + _isFocusing = false; + } + } + + public static void SwitchIdleDetectionMode(bool enabled) + { +#if WINDOWS_PHONE + var mode = enabled ? IdleDetectionMode.Enabled : IdleDetectionMode.Disabled; + try + { + PhoneApplicationService.Current.UserIdleDetectionMode = mode; + } + catch (Exception ex) + { + HandleCameraException(ex); + } +#endif + } + + private void SwitchCameraButton_OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + DebugWriteLine("SwitchCameraButton_OnManipulationCompleted"); + } + + private void SwitchCameraButton_OnMouseLeave(object sender, MouseEventArgs e) + { + DebugWriteLine("SwitchCameraButton_OnMouseLeave"); + } + + private void CameraPage_OnBackKeyPress(object sender, CancelEventArgs e) + { + Preview.Background = null; + } + + public void Dispose() + { + DisposeInternal(); + } + + public void DisposeAsync() + { + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + DisposeInternal(); + }); + } + } + + public enum CameraMode + { + Photo, + Video, + Recording, + } + + public enum FlashControlMode + { + Auto, + Disabled, + Enabled, + } + + public class FileEventArgs : System.EventArgs + { + public StorageFile File { get; set; } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/CardTextBox.cs b/TelegramClient.WP81/Views/Controls/CardTextBox.cs new file mode 100755 index 0000000..7c55926 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/CardTextBox.cs @@ -0,0 +1,225 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Text; +using System.Windows.Controls; + +namespace TelegramClient.Views.Controls +{ + public class CardTextBox : TextBox + { + public String[] PREFIXES_15 = new[] { "34", "37" }; + public String[] PREFIXES_14 = new[] { "300", "301", "302", "303", "304", "305", "309", "36", "38", "39" }; + public String[] PREFIXES_16 = new[] + { + "2221", "2222", "2223", "2224", "2225", "2226", "2227", "2228", "2229", + "223", "224", "225", "226", "227", "228", "229", + "23", "24", "25", "26", + "270", "271", "2720", + "50", "51", "52", "53", "54", "55", + + "4", + + "60", "62", "64", "65", + + "35" + }; + + public static int MAX_LENGTH_STANDARD = 16; + public static int MAX_LENGTH_AMERICAN_EXPRESS = 15; + public static int MAX_LENGTH_DINERS_CLUB = 14; + + private string previousText = string.Empty; + private int selectionStart; + + private int characterAction = -1; + private int actionPosition; + + private bool ignoreOnCardChange; + + public CardTextBox() + { + TextChanged += OnTextChanged; + } + + private void Started() + { + var start = SelectionStart; + var after = Math.Max(0, Text.Length - previousText.Length); + var count = Math.Max(0, previousText.Length - Text.Length); + + if (count == 0 && after == 1) + { + characterAction = 1; + } + else if (count == 1 && after == 0) + { + if (previousText[start] == ' ' && start > 0) + { + characterAction = 3; + actionPosition = start - 1; + } + else + { + characterAction = 2; + } + } + else + { + characterAction = -1; + } + } + + private void OnTextChanging() + { + Started(); + + if (ignoreOnCardChange) + { + return; + } + + int start = SelectionStart; + String str = Text; + if (characterAction == 3) + { + str = str.Substring(0, actionPosition) + str.Substring(actionPosition + 1); + start--; + } + StringBuilder builder = new StringBuilder(str.Length); + for (int a = 0; a < str.Length; a++) + { + char ch = str[a]; + if (char.IsDigit(ch)) + { + builder.Append(ch); + } + } + ignoreOnCardChange = true; + String hint = null; + int maxLength = 100; + if (builder.Length > 0) + { + String currentString = builder.ToString(); + for (int a = 0; a < 3; a++) + { + String[] checkArr; + String resultHint; + int resultMaxLength; + switch (a) + { + case 0: + checkArr = PREFIXES_16; + resultMaxLength = 16; + resultHint = "xxxx xxxx xxxx xxxx"; + break; + case 1: + checkArr = PREFIXES_15; + resultMaxLength = 15; + resultHint = "xxxx xxxx xxxx xxx"; + break; + case 2: + default: + checkArr = PREFIXES_14; + resultMaxLength = 14; + resultHint = "xxxx xxxx xxxx xx"; + break; + } + for (int b = 0; b < checkArr.Length; b++) + { + String prefix = checkArr[b]; + if (currentString.Length <= prefix.Length) + { + if (prefix.StartsWith(currentString)) + { + hint = resultHint; + maxLength = resultMaxLength; + break; + } + } + else + { + if (currentString.StartsWith(prefix)) + { + hint = resultHint; + maxLength = resultMaxLength; + break; + } + } + } + if (hint != null) + { + break; + } + } + if (maxLength != 0) + { + if (builder.Length > maxLength) + { + builder.Length = maxLength; + } + } + } + if (hint != null) + { + if (maxLength != 0) + { + if (builder.Length == maxLength) + { + //inputFields[FIELD_EXPIRE_DATE].requestFocus(); + } + } + //phoneField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + for (int a = 0; a < builder.Length; a++) + { + if (a < hint.Length) + { + if (hint[a] == ' ') + { + builder.Insert(a, ' '); + a++; + if (start == a && characterAction != 2 && characterAction != 3) + { + start++; + } + } + } + else + { + builder.Insert(a, ' '); + if (start == a + 1 && characterAction != 2 && characterAction != 3) + { + start++; + } + break; + } + } + } + else + { + //phoneField.setTextColor(builder.length() > 0 ? Theme.getColor(Theme.key_windowBackgroundWhiteRedText4) : Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + } + Text = builder.ToString(); + if (start >= 0) + { + //phoneField.setSelection(start <= phoneField.length() ? start : phoneField.length()); + selectionStart = start <= Text.Length ? start : Text.Length; + SelectionStart = selectionStart; + } + ignoreOnCardChange = false; + previousText = Text; + } + + private void OnTextChanged(object sender, TextChangedEventArgs e) + { + OnTextChanging(); + + SelectionStart = selectionStart; + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/CropControl.xaml b/TelegramClient.WP81/Views/Controls/CropControl.xaml new file mode 100755 index 0000000..9dffc4c --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/CropControl.xaml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/CropControl.xaml.cs b/TelegramClient.WP81/Views/Controls/CropControl.xaml.cs new file mode 100755 index 0000000..b5968c2 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/CropControl.xaml.cs @@ -0,0 +1,346 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; +using Windows.Graphics.Imaging; +using Windows.Storage; +using Windows.Storage.FileProperties; +using Windows.Storage.Streams; +using Microsoft.Phone.Controls; +using TelegramClient.ViewModels.Additional; +using TelegramClient.ViewModels.Dialogs; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Controls +{ + public partial class CropControl + { + public event EventHandler Close; + + protected virtual void RaiseClose() + { + var handler = Close; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler Crop; + + protected virtual void RaiseCrop(CropEventArgs e) + { + var handler = Crop; + if (handler != null) handler(this, e); + } + + public CropControl() + { + InitializeComponent(); + + Loaded += OnLoaded; + } + + ~CropControl() + { + + } + + public bool TryClose() + { + BeginCloseStoryboard(RaiseClose); + + return true; + } + + private void BeginCloseStoryboard(Action callback) + { + var frame = Application.Current.RootVisual as PhoneApplicationFrame; + if (frame != null) + { + var page = frame.Content as PhoneApplicationPage; + if (page != null) + { + page.IsHitTestVisible = true; + } + } + + var duration = TimeSpan.FromSeconds(0.25); + var easingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 5.0 }; + + var storyboard = new Storyboard(); + + var rootFrameHeight = ((PhoneApplicationFrame)Application.Current.RootVisual).ActualHeight; + var translateYTo = rootFrameHeight; + var translateImageAniamtion = new DoubleAnimationUsingKeyFrames(); + translateImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = duration, Value = translateYTo, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateImageAniamtion, LayoutRoot); + Storyboard.SetTargetProperty(translateImageAniamtion, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateImageAniamtion); + + var opacityImageAniamtion = new ObjectAnimationUsingKeyFrames(); + opacityImageAniamtion.KeyFrames.Add(new DiscreteObjectKeyFrame{ KeyTime = TimeSpan.FromSeconds(0.25), Value = 0 }); + Storyboard.SetTarget(opacityImageAniamtion, ImageBorder); + Storyboard.SetTargetProperty(opacityImageAniamtion, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityImageAniamtion); + + var translateBarAniamtion = new DoubleAnimationUsingKeyFrames(); + translateBarAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.15), Value = 0.0 }); + translateBarAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = translateYTo, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateBarAniamtion, Bar); + Storyboard.SetTargetProperty(translateBarAniamtion, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateBarAniamtion); + + if (callback != null) + { + storyboard.Completed += (o, e) => callback(); + } + + Deployment.Current.Dispatcher.BeginInvoke(storyboard.Begin); + } + + private StorageFile _result; + private uint _width; + private uint _height; + private Stopwatch _stopwatch; + + + public async void SetFile(StorageFile result, PhotoFile file) + { + if (result == null) return; + + _result = result; + var properties = await result.Properties.GetImagePropertiesAsync(); + if (properties != null + && properties.Width > 0 + && properties.Height > 0) + { + _width = properties.Width; + _height = properties.Height; + if (_width == 0 || _height == 0) return; + + var minDimension = Math.Min(_width, _height); + ImageBorder.Width = _width*400.0/minDimension; + ImageBorder.Height = _height*400.0/minDimension; + ImageBorder.Margin = new Thickness((400.0 - ImageBorder.Width)/2.0, (400.0 - ImageBorder.Height)/2.0, + (400.0 - ImageBorder.Width)/2.0, (400.0 - ImageBorder.Height)/2.0); + + _stopwatch = Stopwatch.StartNew(); + var stream = await result.GetThumbnailAsync(ThumbnailMode.SingleItem, 800); + + System.Diagnostics.Debug.WriteLine("Picture.OpenReadAsync=" + _stopwatch.Elapsed); + + var thumbnailSource = new BitmapImage(); + //thumbnailSource.DecodePixelHeight = (int) ImageBorder.Height * 3; + //thumbnailSource.DecodePixelWidth = (int) ImageBorder.Width * 3; + thumbnailSource.CreateOptions = BitmapCreateOptions.BackgroundCreation; + thumbnailSource.SetSource(stream.AsStream()); + Image.Source = thumbnailSource; + } + else + { + var sourceStream = await result.OpenReadAsync(); + var decoder = await BitmapDecoder.CreateAsync(sourceStream); + + _width = decoder.OrientedPixelWidth; + _height = decoder.OrientedPixelHeight; + if (_width == 0 || _height == 0) return; + + var minDimension = Math.Min(_width, _height); + ImageBorder.Width = _width * 400.0 / minDimension; + ImageBorder.Height = _height * 400.0 / minDimension; + ImageBorder.Margin = new Thickness((400.0 - ImageBorder.Width) / 2.0, (400.0 - ImageBorder.Height) / 2.0, + (400.0 - ImageBorder.Width) / 2.0, (400.0 - ImageBorder.Height) / 2.0); + + _stopwatch = Stopwatch.StartNew(); + var resizedJpeg = await DialogDetailsViewModel.ResizeJpeg(sourceStream, 800, string.Empty, string.Empty); + var stream = new MemoryStream(resizedJpeg.Bytes); + + System.Diagnostics.Debug.WriteLine("Picture.OpenReadAsync=" + _stopwatch.Elapsed); + + var thumbnailSource = new BitmapImage(); + //thumbnailSource.DecodePixelHeight = (int) ImageBorder.Height * 3; + //thumbnailSource.DecodePixelWidth = (int) ImageBorder.Width * 3; + thumbnailSource.CreateOptions = BitmapCreateOptions.BackgroundCreation; + thumbnailSource.SetSource(stream); + Image.Source = thumbnailSource; + } + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + Loaded -= OnLoaded; + + Rect.Rect = new Rect(0.0, 0.0, 480, 800); + Ellipse.Center = new Point(480 / 2.0, 800 / 2.0); + + BeginOpenStoryboard(); + } + + private void BeginOpenStoryboard() + { + var frame = Application.Current.RootVisual as PhoneApplicationFrame; + if (frame != null) + { + var page = frame.Content as PhoneApplicationPage; + if (page != null) + { + page.IsHitTestVisible = false; + } + } + + var rootFrameHeight = ((PhoneApplicationFrame)Application.Current.RootVisual).ActualHeight; + var translateYFrom = rootFrameHeight; + + var storyboard = new Storyboard(); + + var translateImageAniamtion = new DoubleAnimationUsingKeyFrames(); + translateImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = translateYFrom }); + translateImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { Exponent = 5.0, EasingMode = EasingMode.EaseOut } }); + Storyboard.SetTarget(translateImageAniamtion, LayoutRoot); + Storyboard.SetTargetProperty(translateImageAniamtion, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateImageAniamtion); + + + var translateAnimaiton = new DoubleAnimationUsingKeyFrames(); + translateAnimaiton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = translateYFrom }); + translateAnimaiton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = 0.0, EasingFunction = new ExponentialEase { Exponent = 5.0, EasingMode = EasingMode.EaseOut } }); + Storyboard.SetTarget(translateAnimaiton, Bar); + Storyboard.SetTargetProperty(translateAnimaiton, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateAnimaiton); + + LayoutRoot.Visibility = Visibility.Collapsed; + Deployment.Current.Dispatcher.BeginInvoke(() => + { + LayoutRoot.Visibility = Visibility.Visible; + storyboard.Begin(); + }); + } + + private async void DoneButton_OnClick(object sender, GestureEventArgs e) + { + var transform = CropCircle.TransformToVisual(ImageBorder); + + var point = transform.Transform(new Point(0, 0)); + + var scaleFactor = _width / (ImageBorder.Width * PanAndZoom.CurrentScaleX); + var originalCropPointX = Math.Floor(point.X * PanAndZoom.CurrentScaleX * scaleFactor); + var originalCropPointY = Math.Floor(point.Y * PanAndZoom.CurrentScaleY * scaleFactor); + var originalCropSize = Math.Floor(400.0 * scaleFactor); + + var finalMaxSize = 800.0; + var scale = Math.Min(finalMaxSize / originalCropSize, 1.0); + + var cropedImage = await GetCroppedImageAsync(_result, new Point(originalCropPointX, originalCropPointY), new Size(originalCropSize, originalCropSize), scale); + + + RaiseCrop(new CropEventArgs{ File = cropedImage }); + } + + /// + /// Get cropped image + /// + /// Original image + /// Crop start point at original image coords + /// Crop size at original image coords + /// Scaling for final crop image respect to original size + /// + public static async Task GetCroppedImageAsync(StorageFile originalImgFile, Point startPoint, Size cropSize, double scale) + { + if (double.IsNaN(scale) || double.IsInfinity(scale)) + { + scale = 1.0; + } + + // Convert start point and size to integer. + uint startPointX = (uint)Math.Floor(startPoint.X * scale); + uint startPointY = (uint)Math.Floor(startPoint.Y * scale); + uint height = (uint)Math.Floor(cropSize.Height * scale); + uint width = (uint)Math.Floor(cropSize.Width * scale); + + + using (IRandomAccessStream stream = await originalImgFile.OpenReadAsync()) + { + // Create a decoder from the stream. With the decoder, we can get + // the properties of the image. + BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream); + + // The scaledSize of original image. + uint orientedScaledWidth = (uint)Math.Floor(decoder.OrientedPixelWidth * scale); + uint orientedScaledHeight = (uint)Math.Floor(decoder.OrientedPixelHeight * scale); + + uint scaledWidth = (uint)Math.Floor(decoder.PixelWidth * scale); + uint scaledHeight = (uint)Math.Floor(decoder.PixelHeight * scale); + + // Refine the start point and the size. + if (startPointX + width > orientedScaledWidth) + { + startPointX = orientedScaledWidth - width; + } + + if (startPointY + height > orientedScaledHeight) + { + startPointY = orientedScaledHeight - height; + } + + // Create cropping BitmapTransform and define the bounds. + BitmapTransform transform = new BitmapTransform(); + BitmapBounds bounds = new BitmapBounds(); + bounds.X = startPointX; + bounds.Y = startPointY; + bounds.Height = height; + bounds.Width = width; + transform.Bounds = bounds; + transform.InterpolationMode = BitmapInterpolationMode.Fant; + + transform.ScaledWidth = scaledWidth; + transform.ScaledHeight = scaledHeight; + + // Get the cropped pixels within the bounds of transform. + PixelDataProvider pix = await decoder.GetPixelDataAsync( + BitmapPixelFormat.Bgra8, + BitmapAlphaMode.Straight, + transform, + ExifOrientationMode.RespectExifOrientation, + ColorManagementMode.ColorManageToSRgb); + + using (var destinationStream = new InMemoryRandomAccessStream()) + { + var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, destinationStream); + encoder.SetPixelData(decoder.BitmapPixelFormat, decoder.BitmapAlphaMode, width, height, decoder.DpiX, decoder.DpiY, pix.DetachPixelData()); + await encoder.FlushAsync(); + + var reader = new DataReader(destinationStream.GetInputStreamAt(0)); + var bytes = new byte[destinationStream.Size]; + await reader.LoadAsync((uint)destinationStream.Size); + reader.ReadBytes(bytes); + + return bytes; + } + } + } + + private void ImageBorder_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + + } + + private void Image_OnImageOpened(object sender, RoutedEventArgs e) + { + LoadingLabel.Visibility = Visibility.Collapsed; + } + } + + public class CropEventArgs + { + public byte[] File { get; set; } + } +} diff --git a/TelegramClient.WP81/Views/Controls/DateTextBox.cs b/TelegramClient.WP81/Views/Controls/DateTextBox.cs new file mode 100755 index 0000000..7207dae --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/DateTextBox.cs @@ -0,0 +1,183 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Text; +using System.Windows.Controls; + +namespace TelegramClient.Views.Controls +{ + public class DateTextBox : TextBox + { + private string previousText = string.Empty; + private int selectionStart; + + private int characterAction = -1; + private bool isYear; + private int actionPosition; + + private bool ignoreOnCardChange; + + public DateTextBox() + { + //TextChanging += OnTextChanging; + TextChanged += OnTextChanged; + } + + private void Started() + { + var start = SelectionStart; + var after = Math.Max(0, Text.Length - previousText.Length); + var count = Math.Max(0, previousText.Length - Text.Length); + + if (count == 0 && after == 1) + { + isYear = Text.IndexOf('/') != -1; + characterAction = 1; + } + else if (count == 1 && after == 0) + { + if (previousText[start] == '/' && start > 0) + { + isYear = false; + characterAction = 3; + actionPosition = start - 1; + } + else + { + characterAction = 2; + } + } + else + { + characterAction = -1; + } + } + + private void OnTextChanging() + { + Started(); + + if (ignoreOnCardChange) + { + return; + } + + int start = SelectionStart; + String str = Text; + if (characterAction == 3) + { + str = str.Substring(0, actionPosition) + str.Substring(actionPosition + 1); + start--; + } + StringBuilder builder = new StringBuilder(str.Length); + for (int a = 0; a < str.Length; a++) + { + char ch = str[a]; + if (char.IsDigit(ch)) + { + builder.Append(ch); + } + } + ignoreOnCardChange = true; + //inputFields[FIELD_EXPIRE_DATE].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + if (builder.Length > 4) + { + builder.Length = 4; + } + if (builder.Length < 2) + { + isYear = false; + } + bool isError = false; + if (isYear) + { + String[] args = new String[builder.Length > 2 ? 2 : 1]; + args[0] = builder.ToString().Substring(0, 2); + if (args.Length == 2) + { + args[1] = builder.ToString().Substring(2); + } + if (builder.Length == 4 && args.Length == 2) + { + int month = int.Parse(args[0]); + int year = int.Parse(args[1]) + 2000; + DateTime rightNow = DateTime.Now; + int currentYear = rightNow.Year; + int currentMonth = rightNow.Month + 1; + if (year < currentYear || year == currentYear && month < currentMonth) + { + //inputFields[FIELD_EXPIRE_DATE].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText4)); + isError = true; + } + } + else + { + int value = int.Parse(args[0]); + if (value > 12 || value == 0) + { + //inputFields[FIELD_EXPIRE_DATE].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText4)); + isError = true; + } + } + } + else + { + if (builder.Length == 1) + { + int value = int.Parse(builder.ToString()); + if (value != 1 && value != 0) + { + builder.Insert(0, "0"); + start++; + } + } + else if (builder.Length == 2) + { + int value = int.Parse(builder.ToString()); + if (value > 12 || value == 0) + { + //inputFields[FIELD_EXPIRE_DATE].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText4)); + isError = true; + } + start++; + } + } + if (!isError && builder.Length == 4) + { + //inputFields[need_card_name ? FIELD_CARDNAME : FIELD_CVV].requestFocus(); + } + if (builder.Length == 2) + { + builder.Append('/'); + start++; + } + else if (builder.Length > 2 && builder[2] != '/') + { + builder.Insert(2, '/'); + start++; + } + + Text = builder.ToString(); + if (start >= 0) + { + selectionStart = start <= Text.Length ? start : Text.Length; + SelectionStart = selectionStart; + } + ignoreOnCardChange = false; + + previousText = Text; + } + + private void OnTextChanged(object sender, TextChangedEventArgs e) + { + OnTextChanging(); + + SelectionStart = selectionStart; + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/DecryptedMessageControl.xaml b/TelegramClient.WP81/Views/Controls/DecryptedMessageControl.xaml new file mode 100755 index 0000000..a420308 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/DecryptedMessageControl.xaml @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/DecryptedMessageControl.xaml.cs b/TelegramClient.WP81/Views/Controls/DecryptedMessageControl.xaml.cs new file mode 100755 index 0000000..62854db --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/DecryptedMessageControl.xaml.cs @@ -0,0 +1,919 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using Telegram.EmojiPanel; +using TelegramClient.Converters; +using TelegramClient.Views.Dialogs; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Controls +{ + public partial class DecryptedMessageControl + { + + public static readonly DependencyProperty MessageProperty = DependencyProperty.Register( + "Message", typeof (TLDecryptedMessageBase), typeof (DecryptedMessageControl), new PropertyMetadata(default(TLDecryptedMessageBase), OnMessageChanged)); + + private static void OnMessageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var messageControl = d as DecryptedMessageControl; + if (messageControl != null) + { + messageControl._isChannelMessage = false; + + messageControl.UpdateBinding(e.NewValue as TLDecryptedMessageBase); + //messageControl.ClearBinding(e.NewValue as TLDecryptedMessageBase); + //messageControl.SetBinding(e.NewValue as TLDecryptedMessageBase); + + var messageBase = e.NewValue as TLDecryptedMessageBase; + if (messageBase != null) + { + var message = messageBase as TLDecryptedMessage; + var messageService = messageBase as TLDecryptedMessageService; + if (message != null) + { + messageControl.ToMessageTemplate(message); + } + else if (messageService != null) + { + messageControl.ToServiceTemplate(messageService); + } + else + { + messageControl.ToEmptyTemplate(); + } + } + else + { + messageControl.ToEmptyTemplate(); + } + } + } + + private void ToMessageTemplate(TLDecryptedMessage message) + { + DrawBubble(message); + } + + private static bool GetIsChannelMessage(TLDecryptedMessageBase messageCommon) + { + return false; + } + + private static bool IsDocument(TLDecryptedMessage message) + { + if (message == null) return false; + + var mediaDocument = message.Media as TLDecryptedMessageMediaDocument45; + if (mediaDocument == null) return false; + + var document = mediaDocument.Document as IAttributes; + if (document == null) return false; + + foreach (var attribute in document.Attributes) + { + if (attribute is TLDocumentAttributeAnimated + || attribute is TLDocumentAttributeSticker + || attribute is TLDocumentAttributeVideo + ) + { + return false; + } + + var documentAttributeAudio = attribute as TLDocumentAttributeAudio46; + if (documentAttributeAudio != null && documentAttributeAudio.Voice) + { + return false; + } + + } + + return true; + } + + private bool GetOutput(TLDecryptedMessageBase message) + { + return message != null && message.Out.Value && !_isChannelMessage; + } + + private void DrawBubble(TLDecryptedMessageBase messageCommon) + { + var isLightTheme = (Visibility) Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + var message = messageCommon as TLDecryptedMessage; + var messageService = messageCommon as TLDecryptedMessageService; + var unreadSeparator = false;//messageService != null && messageService.Action is TLDecryptedMessageActionUnreadMessages; + var sticker = message != null && message.IsSticker(); + _isChannelMessage = GetIsChannelMessage(messageCommon); + var output = GetOutput(messageCommon); + var grouped = message != null && message.Media is TLDecryptedMessageMediaGroup; + + FromLabel.Visibility = Visibility.Collapsed; + Tile.Visibility = Visibility.Collapsed; + + SetBackgroundAndBorder(messageCommon); + + Brush foreground; + if (messageService != null) + { + foreground = (Brush)Resources["ServiceMessageForegroundBrush"]; + } + else + { + foreground = isLightTheme + ? (output + ? (Brush)Resources["OutputForegroundBrushLight"] + : (Brush)Resources["InputForegroundBrushLight"]) + : (output + ? (Brush)Resources["OutputForegroundBrushDark"] + : (Brush)Resources["InputForegroundBrushDark"]); + } + + Brush footerForeground; + if (!sticker) + { + footerForeground = isLightTheme + ? (output + ? (Brush)Resources["OutputSubtleBrushLight"] + : (Brush)Resources["InputSubtleBrushLight"]) + : (output + ? (Brush)Resources["OutputSubtleBrushDark"] + : (Brush)Resources["InputSubtleBrushDark"]); + } + else + { + footerForeground = isLightTheme + ? (Brush)Resources["StickerFooterSubtleBrushLight"] + : (Brush)Resources["StickerFooterSubtleBrushDark"]; + } + + Brush footerBackground; + if (!sticker) + { + footerBackground = new SolidColorBrush(Colors.Transparent); + } + else + { + footerBackground = isLightTheme + ? (Brush)Resources["StickerFooterBackgroundBrushLight"] + : (Brush)Resources["StickerFooterBackgroundBrushDark"]; + } + + Foreground = foreground; + InputMessage.SetForeground(foreground); + + var beforeLastGridLength = output && messageService == null + ? new GridLength(1.0, GridUnitType.Star) + : GridLength.Auto; + + var lastGridLength = output && messageService == null + ? GridLength.Auto + : new GridLength(1.0, GridUnitType.Star); + + var bubbleGridColumn = output && messageService == null + ? 4 + : 3; + + var cornerGridColumn = output && messageService == null + ? 5 + : 2; + + Corner.Margin = output + ? new Thickness(-1.0, 12.0, 0.0, 0.0) + : new Thickness(0.0, 12.0, -1.0, 0.0); + Corner.HorizontalAlignment = output + ? HorizontalAlignment.Left + : HorizontalAlignment.Right; + PathScaleTransform.ScaleX = output ? -1.0 : 1.0; + Corner.Visibility = messageService != null ? Visibility.Collapsed : Visibility.Visible; + CornerBorder.Visibility = messageService != null ? Visibility.Collapsed : Visibility.Visible; + if (unreadSeparator) + { + MainBorder.Margin = new Thickness(-18.0, 0.0, -18.0, 6.0); + MainBorder.HorizontalAlignment = HorizontalAlignment.Stretch; + Panel.HorizontalAlignment = HorizontalAlignment.Center; + } + else if (messageService != null) + { + MainBorder.Margin = new Thickness(0.0, 0.0, 0.0, 6.0); + MainBorder.HorizontalAlignment = HorizontalAlignment.Center; + Panel.HorizontalAlignment = HorizontalAlignment.Center; + } + else + { + MainBorder.Margin = new Thickness(0.0, 0.0, 0.0, 6.0); + MainBorder.HorizontalAlignment = HorizontalAlignment.Left; + Panel.HorizontalAlignment = HorizontalAlignment.Left; + } + Grid.SetColumnSpan(MainBorder, messageService != null ? 2 : 1); + InputMessage.TextAlignment = messageService != null ? TextAlignment.Center : TextAlignment.Left; + + MainBorder.BorderThickness = output + ? new Thickness(1.0, 1.0, 0.0, 1.0) + : new Thickness(0.0, 1.0, 1.0, 1.0); + CornerBorder.BorderThickness = output + ? new Thickness(1.0, 0.0, 0.0, 0.0) + : new Thickness(0.0, 0.0, 1.0, 0.0); + + BeforeLastColumn.Width = beforeLastGridLength; + LastColumn.Width = lastGridLength; + Grid.SetColumn(MainBorder, bubbleGridColumn); + Grid.SetColumn(Corner, cornerGridColumn); + Grid.SetColumn(CornerBorder, cornerGridColumn); + + Header.MaxWidth = messageCommon != null ? messageCommon.MediaWidth : 12.0 + 311.0 + 12.0; + //FwdFromGrid.Visibility = Visibility.Collapsed; + + var message45 = message as TLDecryptedMessage45; + ViaBotGrid.Visibility = message45 != null && !TLString.IsNullOrEmpty(message45.ViaBotName) ? Visibility.Visible : Visibility.Collapsed; + ReplyContent.Visibility = message != null ? message.ReplyVisibility : Visibility.Collapsed; + if (FromLabel.Visibility == Visibility.Visible + //|| FwdFromGrid.Visibility == Visibility.Visible + || ViaBotGrid.Visibility == Visibility.Visible + || ReplyContent.Visibility == Visibility.Visible) + { + Header.Visibility = Visibility.Visible; + } + else + { + Header.Visibility = Visibility.Collapsed; + } + if (FromLabel.Visibility == Visibility.Visible + //&& FwdFromGrid.Visibility == Visibility.Collapsed + && ViaBotGrid.Visibility == Visibility.Collapsed + && ReplyContent.Visibility == Visibility.Collapsed + && message != null + && !TLString.IsNullOrEmpty(message.Message)) + { + FromLabel.Margin = new Thickness(0.0, 2.0, 0.0, -4.0); + } + else if (FromLabel.Visibility == Visibility.Visible + //&& FwdFromGrid.Visibility == Visibility.Collapsed + && ViaBotGrid.Visibility == Visibility.Collapsed + && message != null && message.ReplyInfo != null) + { + FromLabel.Margin = new Thickness(0.0, 2.0, 0.0, 6.0); + } + else + { + FromLabel.Margin = new Thickness(0.0, 2.0, 0.0, 0.0); + } + CaptionPanel.Children.Remove(ViaBotGrid); + FromLabelPanel.Children.Remove(ViaBotGrid); + if (FromLabel.Visibility == Visibility.Visible + && ViaBotGrid.Visibility == Visibility.Visible) + { + ViaBotGrid.Margin = FromLabel.Margin; + FromLabel.Margin = new Thickness(FromLabel.Margin.Left, FromLabel.Margin.Top, FromLabel.Margin.Right + 6.0, FromLabel.Margin.Bottom); + FromLabelPanel.Children.Add(ViaBotGrid); + } + else + { + ViaBotGrid.Margin = new Thickness(0.0, -6.0, 0.0, 0.0); + CaptionPanel.Children.Insert(2, ViaBotGrid); + } + + Status.Visibility = output? Visibility.Visible : Visibility.Collapsed; + + MessageGrid.MaxWidth = messageCommon != null ? messageCommon.MediaWidth : 12.0 + 311.0 + 12.0; + + Panel.Children.Remove(Header); + MainItemGrid.Children.Remove(Header); + if (messageService != null) + { + MessageGrid.Margin = new Thickness(0.0, 2.0, 0.0, 7.0); + } + else if (sticker) + { + ReplyContent.Foreground = footerForeground; + ViaBotGrid.Foreground = new SolidColorBrush(Colors.White); + Header.Background = footerBackground; + Grid.SetRow(Header, 1); + Grid.SetColumn(Header, output ? bubbleGridColumn - 1 : bubbleGridColumn + 1); + Header.HorizontalAlignment = output ? HorizontalAlignment.Right : HorizontalAlignment.Left; + Header.Margin = new Thickness(6.0); + MainItemGrid.Children.Add(Header); + } + else + { + ReplyContent.Foreground = foreground; + ViaBotGrid.Foreground = (Brush) Application.Current.Resources["TelegramBadgeAccentBrush"]; + Header.SetValue(Grid.RowProperty, DependencyProperty.UnsetValue); + Header.SetValue(Grid.ColumnProperty, DependencyProperty.UnsetValue); + Header.HorizontalAlignment = HorizontalAlignment.Left; + Header.Margin = new Thickness(0.0, 0.0, 0.0, -6.0); + Panel.Children.Insert(0, Header); + } + + SetFooter(messageCommon); + } + + private void SetBackgroundAndBorder(TLDecryptedMessageBase messageCommon) + { + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + var messageService = messageCommon as TLDecryptedMessageService; + var sticker = messageCommon != null && messageCommon.IsSticker(); + var output = GetOutput(messageCommon); + + Brush border; + if (messageService != null) + { + border = (Brush)Resources["ServiceMessageBorderBrush"]; + } + else if (sticker) + { + border = new SolidColorBrush(Colors.Transparent); + } + else + { + border = isLightTheme + ? (output + ? (Brush)Resources["OutputBorderBrushLight"] + : (Brush)Resources["InputBorderBrushLight"]) + : (output + ? (Brush)Resources["OutputBorderBrushDark"] + : (Brush)Resources["InputBorderBrushDark"]); + } + + Brush background; + if (messageService != null) + { + background = (Brush)Resources["ServiceMessageBackgroundBrush"]; + } + else if (sticker) + { + background = new SolidColorBrush(Colors.Transparent); + } + else + { + background = isLightTheme + ? (output + ? (Brush)Resources["OutputBackgroundBrushLight"] + : (Brush)Resources["InputBackgroundBrushLight"]) + : (output + ? (Brush)Resources["OutputBackgroundBrushDark"] + : (Brush)Resources["InputBackgroundBrushDark"]); + } + + Corner.Fill = background; + Corner.Stroke = border; + CornerBorder.BorderBrush = border; + + MainBorder.Background = background; + MainBorder.BorderBrush = border; + MorePanel.Background = background; + Header.Background = background; + } + + private bool _isChannelMessage; + + private void ToServiceTemplate(TLDecryptedMessageService messageService) + { + _isChannelMessage = false; + FromLabel.Visibility = Visibility.Collapsed; + Tile.Visibility = Visibility.Collapsed; + + var serviceMessageToTextConverter = new DecryptedServiceMessageToTextConverter(); + InputMessage.Text = (string)serviceMessageToTextConverter.Convert(messageService.Self, null, null, null); + + DrawBubble(messageService); + + //var unreadMessagesAction = messageService.Action as TLDecryptedMessageActionUnreadMessages; + //if (unreadMessagesAction != null) + //{ + // ToUnreadMessagesTemplate(); + //} + } + + private Binding _authorBinding; + private Binding _viaBotNameBinding; + private Binding _inputMessageTextBinding; + private Binding _inputMessageEntitiesBinding; + private Binding _inputMessageVisibilityBinding; + private Binding _mediaContentControlContentBinding; + private Binding _mediaContentControlContentTemplateBinding; + private Binding _commandsReplyMarkupBinding; + private Binding _editLabelVisibilityBinding; + + private void SaveBinding(ref Binding binding, FrameworkElement element, DependencyProperty dp) + { + if (binding == null) + { + var bindingExpression = element.GetBindingExpression(dp); + if (bindingExpression != null) + { + binding = bindingExpression.ParentBinding; + } + element.ClearValue(dp); + } + } + + private void RestoreBinding(ref Binding binding, FrameworkElement element, DependencyProperty dp) + { + if (binding != null) + { + element.SetBinding(dp, binding); + binding = null; + } + } + + private void UpdateBinding(TLDecryptedMessageBase messageBase) + { + var serviceMessage = messageBase as TLDecryptedMessageService; + if (serviceMessage != null) + { + //SaveBinding(ref _fwdFromLabelTextBinding, FwdFromLabel, Run.TextProperty); + SaveBinding(ref _inputMessageVisibilityBinding, InputMessage, TelegramRichTextBox.VisibilityProperty); + SaveBinding(ref _inputMessageEntitiesBinding, InputMessage, TelegramRichTextBox.EntitiesProperty); + SaveBinding(ref _inputMessageTextBinding, InputMessage, TelegramRichTextBox.TextProperty); + SaveBinding(ref _mediaContentControlContentBinding, MediaContentControl, ContentControl.ContentProperty); + SaveBinding(ref _mediaContentControlContentTemplateBinding, MediaContentControl, ContentControl.ContentTemplateProperty); + SaveBinding(ref _viaBotNameBinding, ViaBotGrid, TextBlock.TextProperty); + //SaveBinding(ref _authorBinding, AuthorLabel, TextBlock.TextProperty); + //SaveBinding(ref _editLabelVisibilityBinding, EditLabel, TextBlock.VisibilityProperty); + //SaveBinding(ref _commandsReplyMarkupBinding, Commands, CommandsControl.ReplyMarkupProperty); + + + //System.Diagnostics.Debug.WriteLine("ClearMediaBinding id=" + messageBase.Id); + _suppressFooterReplacement = true; + ClearValue(MediaProperty); + ClearValue(MediaCaptionProperty); + _suppressFooterReplacement = false; + //SaveBinding(ref _mediaBinding, this, MediaProperty); + } + + var message = messageBase as TLDecryptedMessage; + if (message != null) + { + var stopwatch = Stopwatch.StartNew(); + RestoreBinding(ref _inputMessageVisibilityBinding, InputMessage, TelegramRichTextBox.VisibilityProperty); + RestoreBinding(ref _inputMessageEntitiesBinding, InputMessage, TelegramRichTextBox.EntitiesProperty); + RestoreBinding(ref _inputMessageTextBinding, InputMessage, TelegramRichTextBox.TextProperty); + RestoreBinding(ref _mediaContentControlContentBinding, MediaContentControl, ContentControl.ContentProperty); + RestoreBinding(ref _mediaContentControlContentTemplateBinding, MediaContentControl, ContentControl.ContentTemplateProperty); + RestoreBinding(ref _viaBotNameBinding, ViaBotGrid, TextBlock.TextProperty); + //RestoreBinding(ref _authorBinding, AuthorLabel, TextBlock.TextProperty); + //RestoreBinding(ref _editLabelVisibilityBinding, EditLabel, TextBlock.VisibilityProperty); + //RestoreBinding(ref _commandsReplyMarkupBinding, Commands, CommandsControl.ReplyMarkupProperty); + + //System.Diagnostics.Debug.WriteLine("RestoreBinding elapsed=" + stopwatch.Elapsed); + + _suppressFooterReplacement = true; + var mediaBinding = new Binding("Media") { Source = message, Mode = BindingMode.OneWay }; + SetBinding(MediaProperty, mediaBinding); + var mediaCaption = message.Media as IMediaCaption; + if (mediaCaption != null) + { + var mediaCaptionBinding = new Binding("Media.Caption") { Source = message, Mode = BindingMode.OneWay }; + SetBinding(MediaCaptionProperty, mediaCaptionBinding); + } + _suppressFooterReplacement = false; + } + } + + private bool _suppressFooterReplacement; + + public static readonly DependencyProperty MediaCaptionProperty = DependencyProperty.Register( + "MediaCaption", typeof (string), typeof (DecryptedMessageControl), new PropertyMetadata(default(string), OnMediaCaptionChanged)); + + private static void OnMediaCaptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var messageControl = d as DecryptedMessageControl; + if (messageControl != null && !messageControl._suppressFooterReplacement) + { + var oldCaption = e.OldValue as string; + var newCaption = e.NewValue as string; + if (!string.Equals(oldCaption, newCaption, StringComparison.Ordinal)) + { + messageControl.SetFooter(messageControl.Message); + } + } + } + + public string MediaCaption + { + get { return (string) GetValue(MediaCaptionProperty); } + set { SetValue(MediaCaptionProperty, value); } + } + + public static readonly DependencyProperty MediaProperty = DependencyProperty.Register( + "Media", typeof (TLDecryptedMessageMediaBase), typeof (DecryptedMessageControl), new PropertyMetadata(default(TLDecryptedMessageMediaBase), OnMediaChanged)); + + private static void OnMediaChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var messageControl = d as DecryptedMessageControl; + if (messageControl != null && !messageControl._suppressFooterReplacement) + { + var oldWebPage = e.OldValue as TLDecryptedMessageMediaWebPage; + var newWebPage = e.NewValue as TLDecryptedMessageMediaWebPage; + if (oldWebPage != null + || newWebPage != null) + { + messageControl.SetFooter(messageControl.Message); + } + } + } + + private void SetFooter(TLDecryptedMessageBase messageBase) + { + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + + var message = messageBase as TLDecryptedMessage; + var service = messageBase as TLDecryptedMessageService; + var output = GetOutput(messageBase); + + var isGroupedMedia = message != null && message.Media is TLDecryptedMessageMediaGroup; + var isPhoto = message != null && message.Media is TLDecryptedMessageMediaPhoto; + var isVideo = message != null && message.IsVideo(); + var isGeoPoint = message != null && message.Media is TLDecryptedMessageMediaGeoPoint; + var isVenue = message != null && message.Media is TLDecryptedMessageMediaVenue; + var isDocument = message != null && IsDocument(message); + var isVoice = message != null && message.IsVoice(); + var isSticker = message != null && message.IsSticker(); + var isWebPage = message != null && message.Media is TLDecryptedMessageMediaWebPage; + var isEmptyMedia = message != null && (message.Media == null || message.Media is TLDecryptedMessageMediaEmpty); + + //var isGif = message != null && message.IsGif(); + var isShortFooter = IsShortFooter(message, isGroupedMedia, isPhoto, isVideo, isGeoPoint, isDocument, isVoice, isSticker, isWebPage, isEmptyMedia); + + Brush background = new SolidColorBrush(Colors.Transparent); + if (service != null) + { + background = (Brush)Resources["ServiceMessageBackgroundBrush"]; + } + else if (!isSticker) + { + background = isLightTheme + ? (output + ? (Brush)Resources["OutputBackgroundBrushLight"] + : (Brush)Resources["InputBackgroundBrushLight"]) + : (output + ? (Brush)Resources["OutputBackgroundBrushDark"] + : (Brush)Resources["InputBackgroundBrushDark"]); + } + + Brush footerForeground; + if (isSticker) + { + footerForeground = isLightTheme + ? (Brush)Resources["StickerFooterSubtleBrushLight"] + : (Brush)Resources["StickerFooterSubtleBrushDark"]; + } + else if (isShortFooter && (isGroupedMedia || isPhoto || (isGeoPoint && !isVenue) || isVideo)) + { + footerForeground = new SolidColorBrush(Colors.White); + } + else + { + footerForeground = isLightTheme + ? (output + ? (Brush)Resources["OutputSubtleBrushLight"] + : (Brush)Resources["InputSubtleBrushLight"]) + : (output + ? (Brush)Resources["OutputSubtleBrushDark"] + : (Brush)Resources["InputSubtleBrushDark"]); + } + + Brush footerBackground; + if (isSticker) + { + footerBackground = isLightTheme + ? (Brush)Resources["StickerFooterBackgroundBrushLight"] + : (Brush)Resources["StickerFooterBackgroundBrushDark"]; + } + else if (isShortFooter && (isGroupedMedia || isPhoto || (isGeoPoint && !isVenue) || isVideo)) + { + footerBackground = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)); + } + else + { + footerBackground = new SolidColorBrush(Colors.Transparent); + } + + FooterContent.Foreground = footerForeground; + FooterContentGrid.Background = footerBackground; + Footer.MaxWidth = message != null ? message.MediaWidth : 12.0 + 311.0 + 12.0; + Status.Fill = footerForeground; + //ViewsIcon.Stroke = footerForeground; + + if (messageBase != null && messageBase.Reply != null && (isGroupedMedia || isPhoto || isVideo)) + { + MediaContentControl.Margin = new Thickness(12.0, 3.0, 12.0, 0.0); + } + else + { + MediaContentControl.Margin = new Thickness(12.0, 0.0, 12.0, 0.0); + } + + // setup message and media position + //MessageGrid.Visibility = message != null && !TLString.IsNullOrEmpty(message.Message) || showAsServiceMessage + // ? Visibility.Visible + // : Visibility.Collapsed; + //Panel.Children.Remove(MessageGrid); + //Panel.Children.Remove(MediaGrid); + //if (message != null && (message.Media is TLMessageMediaWebPage || message.Media is TLMessageMediaEmpty) || showAsServiceMessage) + //{ + // MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 0.0); + // MediaGrid.Margin = new Thickness(0.0, 0.0, 0.0, 0.0); + + // Panel.Children.Add(MessageGrid); + // Panel.Children.Add(MediaGrid); + //} + //else + //{ + // MessageGrid.Margin = new Thickness(0.0, 0.0, 0.0, 0.0); + // MediaGrid.Margin = new Thickness(0.0, 6.0, 0.0, 0.0); + + // Panel.Children.Add(MediaGrid); + // Panel.Children.Add(MessageGrid); + //} + + // setup footer position + Panel.Children.Remove(Footer); + MediaGrid.Children.Remove(Footer); + MessageGrid.Children.Remove(Footer); + if (service != null) + { + // remove footer + } + else if (!isShortFooter) + { + Footer.Margin = new Thickness(0.0, -1.0, 0.0, 0.0); + Footer.Background = background; + Footer.HorizontalAlignment = HorizontalAlignment.Stretch; + Footer.VerticalAlignment = VerticalAlignment.Stretch; + Panel.Children.Add(Footer); + MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 0.0); + } + else + { + if (isSticker) + { + Footer.Margin = new Thickness(0.0, -1.0, 0.0, 0.0); + Footer.Background = new SolidColorBrush(Colors.Transparent); + Footer.HorizontalAlignment = HorizontalAlignment.Right; + Footer.VerticalAlignment = VerticalAlignment.Bottom; + MediaGrid.Children.Add(Footer); + MessageGrid.Margin = new Thickness(0.0, 0.0, 0.0, 0.0); + } + else if (isEmptyMedia) + { + Footer.Margin = new Thickness(0.0, -1.0, 0.0, -11.0); + Footer.Background = new SolidColorBrush(Colors.Transparent); + Footer.HorizontalAlignment = HorizontalAlignment.Stretch; + Footer.VerticalAlignment = VerticalAlignment.Bottom; + MessageGrid.Children.Add(Footer); + MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 11.0); + } + else if (isGroupedMedia || isPhoto || isGeoPoint || isVideo || isVoice || isDocument) + { + Footer.Margin = new Thickness(0.0, -1.0, 0.0, 0.0); + Footer.Background = new SolidColorBrush(Colors.Transparent); + Footer.HorizontalAlignment = HorizontalAlignment.Right; + Footer.VerticalAlignment = VerticalAlignment.Bottom; + MediaGrid.Children.Add(Footer); + MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 0.0); + } + else + { + Footer.Margin = new Thickness(0.0, -1.0, 0.0, 0.0); + Footer.Background = background; + Footer.HorizontalAlignment = HorizontalAlignment.Stretch; + Footer.VerticalAlignment = VerticalAlignment.Stretch; + Panel.Children.Add(Footer); + MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 0.0); + } + } + + if (message != null + && (message.Media == null || message.Media is TLDecryptedMessageMediaEmpty)) + { + var messageDateTimeConverter = (IValueConverter) Application.Current.Resources["MessageDateTimeConverter"]; + var dateText = messageDateTimeConverter.Convert(message.Date, null, null, null); + + var footerBuilder = new StringBuilder(); + if (FlowDirection == FlowDirection.RightToLeft) + { + footerBuilder.Append("د"); + } + else + { + footerBuilder.Append("a"); + } + footerBuilder.Append("/ " + dateText); + if (message.Out.Value) + { + footerBuilder.Append(" W"); + } + + InputMessage.Footer = footerBuilder.ToString(); + } + else + { + InputMessage.Footer = string.Empty; + } + + if (isVoice) + { + MediaContentControl.Foreground = footerForeground; + } + else + { + MediaContentControl.SetValue(Control.ForegroundProperty, DependencyProperty.UnsetValue); + } + } + + private static bool IsShortFooter(TLDecryptedMessage message, bool isGrouped, bool isPhoto, bool isVideo, bool isGeoPoint, bool isDocument, bool isVoice, bool isSticker, bool isWebPage, bool isEmptyMedia) + { + if (message != null) + { + var mediaCaption = message.Media as IMediaCaption; + if (mediaCaption != null && !TLString.IsNullOrEmpty(mediaCaption.Caption)) + { + return false; + } + + if (isWebPage) + { + return false; + } + + if (isGrouped || isPhoto || isVideo || isGeoPoint) + { + return true; + } + + if (isSticker) + { + return true; + } + + if (isEmptyMedia) + { + return true; + } + + if (isDocument || isVoice) + { + return true; + } + } + + return false; + } + + protected TLDecryptedMessageMediaBase Media + { + get { return (TLDecryptedMessageMediaBase) GetValue(MediaProperty); } + set { SetValue(MediaProperty, value); } + } + + private void ToUnreadMessagesTemplate() + { + + } + + private void ToEmptyTemplate() + { + + } + + public TLDecryptedMessageBase Message + { + get { return (TLDecryptedMessageBase) GetValue(MessageProperty); } + set { SetValue(MessageProperty, value); } + } + + private static int _count; + + public DecryptedMessageControl() + { + InitializeComponent(); + + //System.Diagnostics.Debug.WriteLine("ctor " + _count++); + } + + public event EventHandler TapViaBot; + + protected virtual void RaiseTapViaBot(object sender, GestureEventArgs args) + { + var handler = TapViaBot; + if (handler != null) handler(sender, args); + } + + private void ViaBot_Tap(object sender, GestureEventArgs args) + { + RaiseTapViaBot(sender, args); + } + + public event EventHandler TapMorePanel; + + protected virtual void RaiseTapMorePanel(object sender, GestureEventArgs args) + { + var handler = TapMorePanel; + if (handler != null) handler(sender, args); + } + + private void MorePanel_OnTap(object sender, GestureEventArgs args) + { + RaiseTapMorePanel(sender, args); + } + + public event EventHandler TapUserTile; + + protected virtual void RaiseTapUserTile(object sender, GestureEventArgs args) + { + var handler = TapUserTile; + if (handler != null) handler(sender, args); + } + + private void Tile_OnTap(object sender, GestureEventArgs args) + { + RaiseTapUserTile(sender, args); + } + + public event EventHandler CommandsControlButtonClick; + + protected virtual void RaiseCommandsControlButtonClick(object sender, KeyboardButtonEventArgs e) + { + var handler = CommandsControlButtonClick; + if (handler != null) handler(sender, e); + } + + private void CommandsControl_OnButtonClick(object sender, KeyboardButtonEventArgs e) + { + RaiseCommandsControlButtonClick(sender, e); + } + + public event EventHandler ShareButtonClick; + + protected virtual void RaiseShareButtonClick(object sender, RoutedEventArgs e) + { + var handler = ShareButtonClick; + if (handler != null) handler(sender, e); + } + + private void ShareButton_OnClick(object sender, RoutedEventArgs e) + { + RaiseShareButtonClick(sender, e); + } + + #region Encrypted Timer + + public event EventHandler StartTimer; + + protected virtual void RaiseStartTimer() + { + var handler = StartTimer; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private void SecretPhotoPlaceholder_OnStartTimer(object sender, System.EventArgs e) + { + RaiseStartTimer(); + } + + public event EventHandler Elapsed; + + protected virtual void RaiseElapsed() + { + var handler = Elapsed; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private void SecretPhotoPlaceholder_OnElapsed(object sender, System.EventArgs e) + { + RaiseElapsed(); + } + #endregion + + public event EventHandler TapMedia; + + private void MediaContentControl_OnTap(object sender, GestureEventArgs e) + { + e.Handled = true; + RaiseTapMedia(e); + } + + protected virtual void RaiseTapMedia(GestureEventArgs e) + { + var handler = TapMedia; + if (handler != null) handler(this, e); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/DialogControl.xaml b/TelegramClient.WP81/Views/Controls/DialogControl.xaml new file mode 100755 index 0000000..8724377 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/DialogControl.xaml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/DialogControl.xaml.cs b/TelegramClient.WP81/Views/Controls/DialogControl.xaml.cs new file mode 100755 index 0000000..d91b6c8 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/DialogControl.xaml.cs @@ -0,0 +1,167 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Media; +using Telegram.Api.TL; + +namespace TelegramClient.Views.Controls +{ + public partial class DialogControl + { + public static readonly DependencyProperty ObjectProperty = DependencyProperty.Register( + "Object", typeof(TLObject), typeof(DialogControl), new PropertyMetadata(default(TLObject), OnObjectChanged)); + + private static void OnObjectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as DialogControl; + if (control != null) + { + control.Tile.Object = e.NewValue as TLObject; + } + } + + public TLObject Object + { + get { return (TLObject) GetValue(ObjectProperty); } + set { SetValue(ObjectProperty, value); } + } + + public static readonly DependencyProperty FillProperty = DependencyProperty.Register( + "Fill", typeof(Brush), typeof(DialogControl), new PropertyMetadata(default(Brush), OnFillChanged)); + + private static void OnFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as DialogControl; + if (control != null) + { + control.Tile.Fill = e.NewValue as Brush; + } + } + + public Brush Fill + { + get { return (Brush) GetValue(FillProperty); } + set { SetValue(FillProperty, value); } + } + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register( + "Text", typeof(string), typeof(DialogControl), new PropertyMetadata(default(string), OnTextChanged)); + + private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as DialogControl; + if (control != null) + { + control.Tile.Text = e.NewValue as string; + } + } + + public string Text + { + get { return (string) GetValue(TextProperty); } + set { SetValue(TextProperty, value); } + } + + public static readonly DependencyProperty SourceProperty = DependencyProperty.Register( + "Source", typeof(ImageSource), typeof(DialogControl), new PropertyMetadata(default(ImageSource), OnSourceChanged)); + + private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as DialogControl; + if (control != null) + { + control.Tile.Source = e.NewValue as ImageSource; + } + } + + public ImageSource Source + { + get { return (ImageSource) GetValue(SourceProperty); } + set { SetValue(SourceProperty, value); } + } + + public static readonly DependencyProperty ShortNameProperty = DependencyProperty.Register( + "ShortName", typeof(string), typeof(DialogControl), new PropertyMetadata(default(string), OnShortNameChanged)); + + private static void OnShortNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as DialogControl; + if (control != null) + { + control.Title.Text = e.NewValue as string; + } + } + + public string ShortName + { + get { return (string) GetValue(ShortNameProperty); } + set { SetValue(ShortNameProperty, value); } + } + + public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register( + "IsSelected", typeof(bool), typeof(DialogControl), new PropertyMetadata(default(bool), OnIsSelectedChanged)); + + private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as DialogControl; + if (control != null) + { + var isSelected = (bool)e.NewValue; + control.SelectionControl.SuppressAnimation = control.DataContext is DialogItem && ((DialogItem)control.DataContext).SuppressAnimation; + control.SelectionControl.IsSelected = isSelected; + } + } + + public bool IsSelected + { + get { return (bool)GetValue(IsSelectedProperty); } + set { SetValue(IsSelectedProperty, value); } + } + + public static readonly DependencyProperty SelectedBorderBrushProperty = DependencyProperty.Register( + "SelectedBorderBrush", typeof(Brush), typeof(DialogControl), new PropertyMetadata(default(Brush), OnSelectedBorderBrushChanged)); + + public Brush SelectedBorderBrush + { + get { return (Brush) GetValue(SelectedBorderBrushProperty); } + set { SetValue(SelectedBorderBrushProperty, value); } + } + + private static void OnSelectedBorderBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as DialogControl; + if (control != null) + { + control.SelectionControl.SelectedBorderBrush = e.NewValue as Brush; + } + } + + public static readonly DependencyProperty UnselectedBorderBrushProperty = DependencyProperty.Register( + "UnselectedBorderBrush", typeof(Brush), typeof(DialogControl), new PropertyMetadata(default(Brush), OnUnselectedBorderBrushChanged)); + + public Brush UnselectedBorderBrush + { + get { return (Brush) GetValue(UnselectedBorderBrushProperty); } + set { SetValue(UnselectedBorderBrushProperty, value); } + } + + private static void OnUnselectedBorderBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as DialogControl; + if (control != null) + { + control.SelectionControl.UnselectedBorderBrush = e.NewValue as Brush; + } + } + + public DialogControl() + { + InitializeComponent(); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/GroupedMessageControl.xaml b/TelegramClient.WP81/Views/Controls/GroupedMessageControl.xaml new file mode 100755 index 0000000..e474d78 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/GroupedMessageControl.xaml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/GroupedMessageControl.xaml.cs b/TelegramClient.WP81/Views/Controls/GroupedMessageControl.xaml.cs new file mode 100755 index 0000000..5cbe35b --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/GroupedMessageControl.xaml.cs @@ -0,0 +1,479 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Media; +using Telegram.Api.TL; +using TelegramClient.Converters; + +namespace TelegramClient.Views.Controls +{ + public partial class GroupedMessageControl + { + //~GroupedMessageControl() + //{ + + //} + + public static readonly DependencyProperty MediaProperty = DependencyProperty.Register( + "Media", typeof(IMessageMediaGroup), typeof(GroupedMessageControl), new PropertyMetadata(default(IMessageMediaGroup), OnMediaChanged)); + + public IMessageMediaGroup Media + { + get { return (IMessageMediaGroup)GetValue(MediaProperty); } + set { SetValue(MediaProperty, value); } + } + + private static void OnMediaChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as GroupedMessageControl; + if (control != null) + { + var oldMedia = e.OldValue as IMessageMediaGroup; + if (oldMedia != null) + { + oldMedia.Calculate -= control.OnMediaCalculate; + } + + control.UpdatePhotoLayout(e.NewValue as IMessageMediaGroup); + + var newMedia = e.NewValue as IMessageMediaGroup; + if (newMedia != null) + { + newMedia.Calculate += control.OnMediaCalculate; + } + } + } + + private void OnMediaCalculate(object sender, System.EventArgs e) + { + UpdatePhotoLayout(Media as IMessageMediaGroup); + } + + private StackPanel _previousPanel; + + private void UpdatePhotoLayout(IMessageMediaGroup media) + { + if (LayoutRoot.Children.Count > 0) + { + _previousPanel = LayoutRoot.Children.FirstOrDefault() as StackPanel; + } + LayoutRoot.Children.Clear(); + + if (media != null && media.GroupCommon != null && media.GroupCommon.Count > 0) + { + var groupedMessages = new GroupedMessages(); + foreach (var messageBase in media.GroupCommon) + { + var message = messageBase as TLMessage; + if (message != null) + { + if (message.IsExpired()) + { + continue; + } + + groupedMessages.Messages.Add(message); + } + var decryptedMessage = messageBase as TLDecryptedMessage; + if (decryptedMessage != null) + { + //if (decryptedMessage.IsExpired()) + //{ + // continue; + //} + + groupedMessages.Messages.Add(decryptedMessage); + } + } + + if (groupedMessages.Messages.Count == 0) + { + + } + else if (groupedMessages.Messages.Count == 1) + { + var decryptedMessage = groupedMessages.Messages[0] as TLDecryptedMessage; + if (decryptedMessage != null) + { + var mediaPhoto = decryptedMessage.Media as TLDecryptedMessageMediaPhoto; + if (mediaPhoto != null) + { + var stackPanel = new StackPanel { Background = new SolidColorBrush(Colors.Transparent) }; + + var converter = new PhotoToDimensionConverter(); + var width = (double)converter.Convert(mediaPhoto, null, "Width", null); + var height = (double)converter.Convert(mediaPhoto, null, "Height", null); + + var groupedMessagePosition = new GroupedMessagePosition(); + groupedMessagePosition.Set(0, 0, 0, 0, (int)width, 1.0f, 0); + var position = new KeyValuePair(groupedMessages.Messages[0], groupedMessagePosition); + + var border = GetControl(_previousPanel, position, 1.0, height, 0.0, 0.0); + + stackPanel.Children.Add(border); + + if (stackPanel.Children.Count > 0) + { + LayoutRoot.Children.Add(stackPanel); + } + } + + if (decryptedMessage.IsVideo()) + { + var stackPanel = new StackPanel { Background = new SolidColorBrush(Colors.Transparent) }; + + var width = 230.0; + var height = 145.0; + + var groupedMessagePosition = new GroupedMessagePosition(); + groupedMessagePosition.Set(0, 0, 0, 0, (int)width, 1.0f, 0); + var position = new KeyValuePair(groupedMessages.Messages[0], groupedMessagePosition); + + var border = GetControl(_previousPanel, position, 1.0, height, 0.0, 0.0); + + stackPanel.Children.Add(border); + + if (stackPanel.Children.Count > 0) + { + LayoutRoot.Children.Add(stackPanel); + } + } + } + + var message = groupedMessages.Messages[0] as TLMessage; + if (message != null) + { + var mediaPhoto = message.Media as TLMessageMediaPhoto; + if (mediaPhoto != null) + { + var stackPanel = new StackPanel { Background = new SolidColorBrush(Colors.Transparent) }; + + var converter = new PhotoToDimensionConverter(); + var width = (double)converter.Convert(mediaPhoto, null, "Width", null); + var height = (double)converter.Convert(mediaPhoto, null, "Height", null); + + var groupedMessagePosition = new GroupedMessagePosition(); + groupedMessagePosition.Set(0, 0, 0, 0, (int)width, 1.0f, 0); + var position = new KeyValuePair(groupedMessages.Messages[0], groupedMessagePosition); + + var border = GetControl(_previousPanel, position, 1.0, height, 0.0, 0.0); + + stackPanel.Children.Add(border); + + if (stackPanel.Children.Count > 0) + { + LayoutRoot.Children.Add(stackPanel); + } + } + + var mediaDocument = message.Media as TLMessageMediaDocument; + if (mediaDocument != null) + { + var stackPanel = new StackPanel { Background = new SolidColorBrush(Colors.Transparent) }; + + var width = 230.0; + var height = 145.0; + + var groupedMessagePosition = new GroupedMessagePosition(); + groupedMessagePosition.Set(0, 0, 0, 0, (int)width, 1.0f, 0); + var position = new KeyValuePair(groupedMessages.Messages[0], groupedMessagePosition); + + var border = GetControl(_previousPanel, position, 1.0, height, 0.0, 0.0); + + stackPanel.Children.Add(border); + + if (stackPanel.Children.Count > 0) + { + LayoutRoot.Children.Add(stackPanel); + } + } + } + } + else if (groupedMessages.Messages.Count > 0) + { + var height = 320; + groupedMessages.Calculate(height); + + var stackPanel = new StackPanel { Background = new SolidColorBrush(Colors.Transparent) }; + + var positions = groupedMessages.Positions.ToList(); + + for (var i = 0; i < positions.Count; i++) + { + var position = positions[i]; + + var top = 0.0; + var left = 0.0; + + if (i > 0) + { + var pos = positions[i - 1]; + // in one row + if (pos.Value.MinY == position.Value.MinY) + { + top = -(height * pos.Value.Height); + + for (var j = i - 1; j >= 0; j--) + { + pos = positions[j]; + if (pos.Value.MinY == position.Value.MinY) + { + left += pos.Value.Width; + } + } + } + // in one column + else if (position.Value.SpanSize == groupedMessages.MaxSizeWidth) + { + left = position.Value.LeftSpanOffset; + // find common big message + KeyValuePair? leftColumn = null; + for (var j = i - 1; j >= 0; j--) + { + pos = positions[j]; + if (pos.Value.SiblingHeights != null) + { + leftColumn = pos; + break; + } + else + { + top += (height * pos.Value.Height); + } + } + // set top + if (leftColumn != null) + { + top -= (leftColumn.Value.Value.Height * height); + } + else + { + top = 0; + } + } + } + + var border = GetControl(_previousPanel, position, 0.65, height, left, top); + + stackPanel.Children.Add(border); + } + + if (stackPanel.Children.Count > 0) + { + LayoutRoot.Children.Add(stackPanel); + } + } + } + } + + private static bool IsVideo(TLObject obj) + { + var message = obj as TLMessage; + if (message != null && message.IsVideo()) + { + return true; + } + + var decryptedMessage = obj as TLDecryptedMessage; + if (decryptedMessage != null && decryptedMessage.IsVideo()) + { + return true; + } + + return false; + } + + private static UIElement GetControl(StackPanel previousPanel, KeyValuePair position, double scale, double height, double left, double top) + { + if (IsVideo(position.Key)) + { + return GetVideoControl(previousPanel, position, scale, height, left, top); + } + + return GetPhotoControl(previousPanel, position, scale, height, left, top); + } + + private static UIElement GetVideoControl(StackPanel previousPanel, KeyValuePair position, double scale, double height, double left, double top) + { + TLObject media = null; + var message = position.Key as TLMessage; + if (message != null) + { + media = message.Media; + } + var decryptedMessage = position.Key as TLDecryptedMessage; + if (decryptedMessage != null) + { + media = decryptedMessage.Media; + } + + var element = GetCachedControl(previousPanel, media); + var created = false; + if (element == null) + { + created = true; + element = new MediaVideoControl(); + element.DataContext = media; + } + + var margin = 1.0; + + element.Stretch = Stretch.UniformToFill; + element.ProgressScale = scale; + element.HorizontalAlignment = HorizontalAlignment.Left; + element.VerticalAlignment = VerticalAlignment.Top; + element.Width = position.Value.Width - 2.0 * margin; + element.Height = height * position.Value.Height - 2 * margin; + element.Margin = new Thickness(left + margin, top + margin, 0.0 + margin, 0.0 + margin); + + if (!created) return element; + + Caliburn.Micro.Message.SetAttach(element, "[Event CancelUploading] = [Action CancelUploading($DataContext)]; [Event CancelDownloading] = [Action CancelVideoDownloading($DataContext)]"); + + var mediaBinding = new Binding(""); + element.SetBinding(MediaVideoControl.MediaProperty, mediaBinding); + + if (message != null && message.HasTTL() + || decryptedMessage != null && decryptedMessage.TTL.Value > 0) + { + var previewSourceBinding = new Binding("ThumbSelf"); + previewSourceBinding.Converter = new PhotoToThumbConverter { Secret = true }; + element.SetBinding(MediaVideoControl.SourceProperty, previewSourceBinding); + } + else + { + var sourceBinding = new Binding("ThumbSelf"); + sourceBinding.Converter = new PhotoToThumbConverter(); + element.SetBinding(MediaVideoControl.SourceProperty, sourceBinding); + } + + var downloadIconVisibilityBinding = new Binding("Self"); + downloadIconVisibilityBinding.Converter = new DownloadMediaToVisibilityConverter(); + element.SetBinding(MediaVideoControl.DownloadIconVisibilityProperty, downloadIconVisibilityBinding); + + var downloadingProgressBinding = new Binding("DownloadingProgress"); + element.SetBinding(MediaVideoControl.DownloadingProgressProperty, downloadingProgressBinding); + + var uploadingProgressBinding = new Binding("UploadingProgress"); + element.SetBinding(MediaVideoControl.UploadingProgressProperty, uploadingProgressBinding); + + var isSelectedBinding = new Binding("IsSelected") { Source = position.Key }; + element.SetBinding(MediaVideoControl.IsSelectedProperty, isSelectedBinding); + + var ttlParamsBinding = new Binding("TTLParams"); + element.SetBinding(MediaVideoControl.TTLParamsProperty, ttlParamsBinding); + + return element; + } + + private static UIElement GetPhotoControl(StackPanel previousPanel, KeyValuePair position, double scale, double height, double left, double top) + { + TLObject media = null; + var message = position.Key as TLMessage; + if (message != null) + { + media = message.Media; + } + var decryptedMessage = position.Key as TLDecryptedMessage; + if (decryptedMessage != null) + { + media = decryptedMessage.Media; + } + + var element = GetCachedControl(previousPanel, media); + var created = false; + if (element == null) + { + created = true; + element = new MediaPhotoControl(); + element.DataContext = media; + } + + var margin = 1.0; + + element.ProgressScale = scale; + element.HorizontalAlignment = HorizontalAlignment.Left; + element.VerticalAlignment = VerticalAlignment.Top; + element.Width = position.Value.Width - 2.0 * margin; + element.Height = height * position.Value.Height - 2 * margin; + element.Margin = new Thickness(left + margin, top + margin, 0.0 + margin, 0.0 + margin); + + if (!created) return element; + + Caliburn.Micro.Message.SetAttach(element, "[Event CancelUploading] = [Action CancelUploading($DataContext)]; [Event CancelDownloading] = [Action CancelPhotoDownloading($DataContext)]"); + + var mediaBinding = new Binding(""); + element.SetBinding(MediaPhotoControl.MediaProperty, mediaBinding); + + if (message != null && message.HasTTL() + || decryptedMessage != null && decryptedMessage.TTL.Value > 0) + { + element.ClearValue(MediaPhotoControl.SourceProperty); + //var sourceBinding = new Binding("Self"); + //sourceBinding.Converter = new DefaultPhotoConverter(); + //element.SetBinding(MediaPhotoControl.SourceProperty, sourceBinding); + + var previewSourceBinding = new Binding("ThumbSelf"); + previewSourceBinding.Converter = new PhotoToThumbConverter{ Secret = true }; + element.SetBinding(MediaPhotoControl.PreviewSourceProperty, previewSourceBinding); + } + else + { + var sourceBinding = new Binding("Self"); + sourceBinding.Converter = new DefaultPhotoConverter(); + sourceBinding.ConverterParameter = "311_Background"; + element.SetBinding(MediaPhotoControl.SourceProperty, sourceBinding); + + var previewSourceBinding = new Binding("ThumbSelf"); + previewSourceBinding.Converter = new PhotoToThumbConverter(); + element.SetBinding(MediaPhotoControl.PreviewSourceProperty, previewSourceBinding); + } + + var downloadingProgressBinding = new Binding("DownloadingProgress"); + element.SetBinding(MediaPhotoControl.DownloadingProgressProperty, downloadingProgressBinding); + + var uploadingProgressBinding = new Binding("UploadingProgress"); + element.SetBinding(MediaPhotoControl.UploadingProgressProperty, uploadingProgressBinding); + + var isSelectedBinding = new Binding("IsSelected") { Source = position.Key }; + element.SetBinding(MediaPhotoControl.IsSelectedProperty, isSelectedBinding); + + var ttlParamsBinding = new Binding("TTLParams"); + element.SetBinding(MediaPhotoControl.TTLParamsProperty, ttlParamsBinding); + + return element; + } + + private static T GetCachedControl(StackPanel panel, TLObject dataContext) where T : FrameworkElement + { + if (panel != null) + { + for (var i = 0; i < panel.Children.Count; i++) + { + var control = panel.Children[i] as T; + if (control != null && control.DataContext == dataContext) + { + panel.Children.RemoveAt(i); + return control; + } + } + } + + return null; + } + + public GroupedMessageControl() + { + InitializeComponent(); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/GroupedMessages.cs b/TelegramClient.WP81/Views/Controls/GroupedMessages.cs new file mode 100755 index 0000000..916c010 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/GroupedMessages.cs @@ -0,0 +1,714 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Text; +using Telegram.Api.TL; + +namespace TelegramClient.Views.Controls +{ + public class GroupedMessagePosition + { + public float AspectRatio { get; set; } + public bool IsEdge { get; set; } + public int Flags { get; private set; } + public bool IsLast { get; set; } + public int LeftSpanOffset { get; set; } + public byte MaxX { get; private set; } + public byte MaxY { get; private set; } + public byte MinX { get; private set; } + public byte MinY { get; private set; } + public float Height { get; private set; } + public int Width { get; set; } + public float[] SiblingHeights { get; set; } + public int SpanSize { get; set; } + + public void Set(int minX, int maxX, int minY, int maxY, int w, float h, int flags) + { + MinX = (byte)minX; + MaxX = (byte)maxX; + MinY = (byte)minY; + MaxY = (byte)maxY; + SpanSize = w; + Width = w; + Height = h; + Flags = (byte)flags; + } + + public override string ToString() + { + return + string.Format( + "AspectRatio={0} IsEdge={1} Flags={2} IsLast={3} LeftSpanOffset={4} MaxX={5} MaxY={6} MinX={7} MinY={8} Height={9} Width={10} SiblingHeights=[{11}] SpanSize={12}", + AspectRatio, IsEdge, GetFlagsString(Flags), IsLast, LeftSpanOffset, MaxX, MaxY, MinX, MinY, Height, Width, string.Join(",", SiblingHeights ?? new float[] { }), SpanSize); + } + + private string GetFlagsString(int flags) + { + var sb = new StringBuilder(); + if ((flags & GroupedMessages.POSITION_FLAG_LEFT) == GroupedMessages.POSITION_FLAG_LEFT) sb.Append("l "); + if ((flags & GroupedMessages.POSITION_FLAG_RIGHT) == GroupedMessages.POSITION_FLAG_RIGHT) sb.Append("r "); + if ((flags & GroupedMessages.POSITION_FLAG_TOP) == GroupedMessages.POSITION_FLAG_TOP) sb.Append("t "); + if ((flags & GroupedMessages.POSITION_FLAG_BOTTOM) == GroupedMessages.POSITION_FLAG_BOTTOM) sb.Append("b "); + + return sb.ToString(); + } + } + + public class GroupedMessages + { + public const int POSITION_FLAG_LEFT = 1; + public const int POSITION_FLAG_RIGHT = 2; + public const int POSITION_FLAG_TOP = 4; + public const int POSITION_FLAG_BOTTOM = 8; + + private int _maxSizeWidth = 800; + public int MaxSizeWidth + { + get { return _maxSizeWidth; } + } + + private List _posArray = new List(); + + public long GroupedId { get; set; } + public bool HasSibling { get; private set; } + + public float Height { get; private set; } + public int Width { get; private set; } + + public List Messages = new List(); + public Dictionary Positions = new Dictionary(); + private float _scale; + + private class MessageGroupedLayoutAttempt + { + public float[] Heights { get; private set; } + public int[] LineCounts { get; private set; } + + public MessageGroupedLayoutAttempt(int i1, int i2, float f1, float f2) + { + LineCounts = new int[] { i1, i2 }; + Heights = new float[] { f1, f2 }; + } + + public MessageGroupedLayoutAttempt(int i1, int i2, int i3, float f1, float f2, float f3) + { + LineCounts = new int[] { i1, i2, i3 }; + Heights = new float[] { f1, f2, f3 }; + } + + public MessageGroupedLayoutAttempt(int i1, int i2, int i3, int i4, float f1, float f2, float f3, float f4) + { + LineCounts = new int[] { i1, i2, i3, i4 }; + Heights = new float[] { f1, f2, f3, f4 }; + } + } + + private float MultiHeight(float[] array, int start, int end) + { + float sum = 0.0f; + for (int a = start; a < end; a++) + { + sum += array[a]; + } + + return 800.0f * _scale / sum; + } + + public void Calculate(int desiredWidth) + { + _posArray.Clear(); + Positions.Clear(); + int count = Messages.Count; + if (count <= 1) + { + return; + } + + int totalWidth = 0; + float totalHeight = 0.0f; + + _scale = (float)desiredWidth / _maxSizeWidth; + _maxSizeWidth = desiredWidth; + int firstSpanAdditionalSize = (int)(200 * _scale); + int minHeight = (int)(120 * _scale); + int minWidth = (int)(96 * _scale); + int paddingsWidth = (int)(32 * _scale); + float maxSizeHeight = 814.0f * _scale; + StringBuilder proportions = new StringBuilder(); + float averageAspectRatio = 1.0f; + bool isOut = false; + int maxX = 0; + bool forceCalc = false; + + for (int a = 0; a < count; a++) + { + int w = 0; + int h = 0; + var decryptedMessageObject = Messages[a] as TLDecryptedMessage; + if (decryptedMessageObject != null) + { + TLVector photoThumbs = null; + var photoMedia = decryptedMessageObject.Media as TLDecryptedMessageMediaPhoto; + var documentMedia = decryptedMessageObject.Media as TLDecryptedMessageMediaDocument; + var videoMedia = decryptedMessageObject.Media as TLDecryptedMessageMediaVideo; + if (photoMedia != null) + { + photoThumbs = new TLVector { new TLPhotoSize { W = photoMedia.W, H = photoMedia.H } }; + } + else if (documentMedia != null) + { + photoThumbs = new TLVector { new TLPhotoSize { W = documentMedia.ThumbW.Value > 0 ? documentMedia.ThumbW : new TLInt(90), H = documentMedia.ThumbH.Value > 0 ? documentMedia.ThumbH : new TLInt(90) } }; + } + else if (videoMedia != null) + { + photoThumbs = new TLVector { new TLPhotoSize { W = videoMedia.W.Value > 0 ? videoMedia.W : new TLInt(90), H = videoMedia.H.Value > 0 ? videoMedia.H : new TLInt(90) } }; + } + TLPhotoSizeBase photoSize = GetClosestPhotoSizeWithSize(photoThumbs, 1280); + var size = photoSize as TLPhotoSize; + var cachedSize = photoSize as TLPhotoCachedSize; + if (size != null) + { + w = size.W.Value; + h = size.H.Value; + } + else if (cachedSize != null) + { + w = cachedSize.W.Value; + h = cachedSize.H.Value; + } + GroupedMessagePosition position = new GroupedMessagePosition(); + position.IsLast = a == count - 1; + position.AspectRatio = w / (float)h; + + if (position.AspectRatio > 1.2f) + { + proportions.Append("w"); + } + else if (position.AspectRatio < 0.8f) + { + proportions.Append("n"); + } + else + { + proportions.Append("q"); + } + + averageAspectRatio += position.AspectRatio; + + if (position.AspectRatio > 2.0f) + { + forceCalc = true; + } + + Positions[decryptedMessageObject] = position; + _posArray.Add(position); + } + + var messageObject = Messages[a] as TLMessage; + if (messageObject != null) + { + TLVector photoThumbs = null; + var photoMedia = messageObject.Media as TLMessageMediaPhoto; + var documentMedia = messageObject.Media as TLMessageMediaDocument; + if (photoMedia != null) + { + var photo = photoMedia.Photo as TLPhoto; + if (photo != null) + { + photoThumbs = photo.Sizes; + } + } + else if (documentMedia != null) + { + var document = documentMedia.Document as TLDocument; + if (document != null) + { + photoThumbs = new TLVector { document.Thumb }; + } + } + TLPhotoSizeBase photoSize = GetClosestPhotoSizeWithSize(photoThumbs, 1280); + var size = photoSize as TLPhotoSize; + var cachedSize = photoSize as TLPhotoCachedSize; + if (size != null) + { + w = size.W.Value; + h = size.H.Value; + } + else if (cachedSize != null) + { + w = cachedSize.W.Value; + h = cachedSize.H.Value; + } + GroupedMessagePosition position = new GroupedMessagePosition(); + position.IsLast = a == count - 1; + position.AspectRatio = w / (float)h; + + if (position.AspectRatio > 1.2f) + { + proportions.Append("w"); + } + else if (position.AspectRatio < 0.8f) + { + proportions.Append("n"); + } + else + { + proportions.Append("q"); + } + + averageAspectRatio += position.AspectRatio; + + if (position.AspectRatio > 2.0f) + { + forceCalc = true; + } + + Positions[messageObject] = position; + _posArray.Add(position); + } + } + + //int minHeight = AndroidUtilities.dp(120); + //int minWidth = (int)(AndroidUtilities.dp(120) / (Math.Min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) / (float)_maxSizeWidth)); + //int paddingsWidth = (int)(AndroidUtilities.dp(40) / (Math.Min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) / (float)_maxSizeWidth)); + + + float maxAspectRatio = _maxSizeWidth / maxSizeHeight; + averageAspectRatio = averageAspectRatio / count; + + if (!forceCalc && (count == 2 || count == 3 || count == 4)) + { + if (count == 2) + { + GroupedMessagePosition position1 = _posArray[0]; + GroupedMessagePosition position2 = _posArray[1]; + String pString = proportions.ToString(); + if (pString.Equals("ww") && averageAspectRatio > 1.4 * maxAspectRatio && position1.AspectRatio - position2.AspectRatio < 0.2) + { + float height = (float)Math.Round(Math.Min(_maxSizeWidth / position1.AspectRatio, Math.Min(_maxSizeWidth / position2.AspectRatio, maxSizeHeight / 2.0f))) / maxSizeHeight; + position1.Set(0, 0, 0, 0, _maxSizeWidth, height, POSITION_FLAG_LEFT | POSITION_FLAG_RIGHT | POSITION_FLAG_TOP); + position2.Set(0, 0, 1, 1, _maxSizeWidth, height, POSITION_FLAG_LEFT | POSITION_FLAG_RIGHT | POSITION_FLAG_BOTTOM); + + totalWidth = _maxSizeWidth; + totalHeight = height * 2; + } + else if (pString.Equals("ww") || pString.Equals("qq")) + { + int width = _maxSizeWidth / 2; + float height = (float)Math.Round(Math.Min(width / position1.AspectRatio, Math.Min(width / position2.AspectRatio, maxSizeHeight))) / maxSizeHeight; + position1.Set(0, 0, 0, 0, width, height, POSITION_FLAG_LEFT | POSITION_FLAG_BOTTOM | POSITION_FLAG_TOP); + position2.Set(1, 1, 0, 0, width, height, POSITION_FLAG_RIGHT | POSITION_FLAG_BOTTOM | POSITION_FLAG_TOP); + maxX = 1; + + totalWidth = width + width; + totalHeight = height; + } + else + { + int secondWidth = (int)Math.Max(0.4f * _maxSizeWidth, Math.Round((_maxSizeWidth / position1.AspectRatio / (1.0f / position1.AspectRatio + 1.0f / position2.AspectRatio)))); + int firstWidth = _maxSizeWidth - secondWidth; + if (firstWidth < minWidth) + { + int diff = minWidth - firstWidth; + firstWidth = minWidth; + secondWidth -= diff; + } + + float height = (float)Math.Min(maxSizeHeight, Math.Round(Math.Min(firstWidth / position1.AspectRatio, secondWidth / position2.AspectRatio))) / maxSizeHeight; + position1.Set(0, 0, 0, 0, firstWidth, height, POSITION_FLAG_LEFT | POSITION_FLAG_BOTTOM | POSITION_FLAG_TOP); + position2.Set(1, 1, 0, 0, secondWidth, height, POSITION_FLAG_RIGHT | POSITION_FLAG_BOTTOM | POSITION_FLAG_TOP); + maxX = 1; + + totalWidth = firstWidth + secondWidth; + totalHeight = height; + } + } + else if (count == 3) + { + GroupedMessagePosition position1 = _posArray[0]; + GroupedMessagePosition position2 = _posArray[1]; + GroupedMessagePosition position3 = _posArray[2]; + if (proportions[0] == 'n') + { + float thirdHeight = (float)Math.Min(maxSizeHeight * 0.5f, Math.Round(position2.AspectRatio * _maxSizeWidth / (position3.AspectRatio + position2.AspectRatio))); + float secondHeight = maxSizeHeight - thirdHeight; + int rightWidth = (int)Math.Max(minWidth, Math.Min(_maxSizeWidth * 0.5f, Math.Round(Math.Min(thirdHeight * position3.AspectRatio, secondHeight * position2.AspectRatio)))); + + int leftWidth = (int)Math.Round(Math.Min(maxSizeHeight * position1.AspectRatio + paddingsWidth, _maxSizeWidth - rightWidth)); + position1.Set(0, 0, 0, 1, leftWidth, 1.0f, POSITION_FLAG_LEFT | POSITION_FLAG_BOTTOM | POSITION_FLAG_TOP); + + position2.Set(1, 1, 0, 0, rightWidth, secondHeight / maxSizeHeight, POSITION_FLAG_RIGHT | POSITION_FLAG_TOP); + + position3.Set(0, 1, 1, 1, rightWidth, thirdHeight / maxSizeHeight, POSITION_FLAG_RIGHT | POSITION_FLAG_BOTTOM); + position3.SpanSize = _maxSizeWidth; + + position1.SiblingHeights = new float[] { thirdHeight / maxSizeHeight, secondHeight / maxSizeHeight }; + + if (isOut) + { + position1.SpanSize = _maxSizeWidth - rightWidth; + } + else + { + position2.SpanSize = _maxSizeWidth - leftWidth; + position3.LeftSpanOffset = leftWidth; + } + HasSibling = true; + maxX = 1; + + totalWidth = leftWidth + rightWidth; + totalHeight = 1.0f; + } + else + { + float firstHeight = (float)Math.Round(Math.Min(_maxSizeWidth / position1.AspectRatio, (maxSizeHeight) * 0.66f)) / maxSizeHeight; + position1.Set(0, 1, 0, 0, _maxSizeWidth, firstHeight, POSITION_FLAG_LEFT | POSITION_FLAG_RIGHT | POSITION_FLAG_TOP); + + int width = _maxSizeWidth / 2; + float secondHeight = (float)Math.Min(maxSizeHeight - firstHeight, Math.Round(Math.Min(width / position2.AspectRatio, width / position3.AspectRatio))) / maxSizeHeight; + position2.Set(0, 0, 1, 1, width, secondHeight, POSITION_FLAG_LEFT | POSITION_FLAG_BOTTOM); + position3.Set(1, 1, 1, 1, width, secondHeight, POSITION_FLAG_RIGHT | POSITION_FLAG_BOTTOM); + maxX = 1; + + totalWidth = _maxSizeWidth; + totalHeight = firstHeight + secondHeight; + } + } + else if (count == 4) + { + GroupedMessagePosition position1 = _posArray[0]; + GroupedMessagePosition position2 = _posArray[1]; + GroupedMessagePosition position3 = _posArray[2]; + GroupedMessagePosition position4 = _posArray[3]; + if (proportions[0] == 'w') + { + float h0 = (float)Math.Round(Math.Min(_maxSizeWidth / position1.AspectRatio, maxSizeHeight * 0.66f)) / maxSizeHeight; + position1.Set(0, 2, 0, 0, _maxSizeWidth, h0, POSITION_FLAG_LEFT | POSITION_FLAG_RIGHT | POSITION_FLAG_TOP); + + float h = (float)Math.Round(_maxSizeWidth / (position2.AspectRatio + position3.AspectRatio + position4.AspectRatio)); + int w0 = (int)Math.Max(minWidth, Math.Min(_maxSizeWidth * 0.4f, h * position2.AspectRatio)); + int w2 = (int)Math.Max(Math.Max(minWidth, _maxSizeWidth * 0.33f), h * position4.AspectRatio); + int w1 = _maxSizeWidth - w0 - w2; + h = Math.Min(maxSizeHeight - h0, h); + h /= maxSizeHeight; + position2.Set(0, 0, 1, 1, w0, h, POSITION_FLAG_LEFT | POSITION_FLAG_BOTTOM); + position3.Set(1, 1, 1, 1, w1, h, POSITION_FLAG_BOTTOM); + position4.Set(2, 2, 1, 1, w2, h, POSITION_FLAG_RIGHT | POSITION_FLAG_BOTTOM); + maxX = 2; + + totalWidth = _maxSizeWidth; + totalHeight = h0 + h; + } + else + { + int w = (int)Math.Max(minWidth, Math.Round(maxSizeHeight / (1.0f / position2.AspectRatio + 1.0f / position3.AspectRatio + 1.0f / _posArray[3].AspectRatio))); + float h0 = Math.Min(0.33f, Math.Max(minHeight, w / position2.AspectRatio) / maxSizeHeight); + float h1 = Math.Min(0.33f, Math.Max(minHeight, w / position3.AspectRatio) / maxSizeHeight); + float h2 = 1.0f - h0 - h1; + int w0 = (int)Math.Round(Math.Min(maxSizeHeight * position1.AspectRatio + paddingsWidth, _maxSizeWidth - w)); + + position1.Set(0, 0, 0, 2, w0, h0 + h1 + h2, POSITION_FLAG_LEFT | POSITION_FLAG_TOP | POSITION_FLAG_BOTTOM); + + position2.Set(1, 1, 0, 0, w, h0, POSITION_FLAG_RIGHT | POSITION_FLAG_TOP); + + position3.Set(0, 1, 1, 1, w, h1, POSITION_FLAG_RIGHT); + position3.SpanSize = _maxSizeWidth; + + position4.Set(0, 1, 2, 2, w, h2, POSITION_FLAG_RIGHT | POSITION_FLAG_BOTTOM); + position4.SpanSize = _maxSizeWidth; + + if (isOut) + { + position1.SpanSize = _maxSizeWidth - w; + } + else + { + position2.SpanSize = _maxSizeWidth - w0; + position3.LeftSpanOffset = w0; + position4.LeftSpanOffset = w0; + } + position1.SiblingHeights = new float[] { h0, h1, h2 }; + HasSibling = true; + maxX = 1; + + totalWidth = w + w0; + totalHeight = h0 + h1 + h2; + } + } + } + else + { + float[] croppedRatios = new float[_posArray.Count]; + for (int a = 0; a < count; a++) + { + if (averageAspectRatio > 1.1f) + { + croppedRatios[a] = Math.Max(1.0f, _posArray[a].AspectRatio); + } + else + { + croppedRatios[a] = Math.Min(1.0f, _posArray[a].AspectRatio); + } + croppedRatios[a] = Math.Max(0.66667f, Math.Min(1.7f, croppedRatios[a])); + } + + int firstLine; + int secondLine; + int thirdLine; + int fourthLine; + List attempts = new List(); + for (firstLine = 1; firstLine < croppedRatios.Length; firstLine++) + { + secondLine = croppedRatios.Length - firstLine; + if (firstLine > 3 || secondLine > 3) + { + continue; + } + attempts.Add(new MessageGroupedLayoutAttempt(firstLine, secondLine, MultiHeight(croppedRatios, 0, firstLine), MultiHeight(croppedRatios, firstLine, croppedRatios.Length))); + } + + for (firstLine = 1; firstLine < croppedRatios.Length - 1; firstLine++) + { + for (secondLine = 1; secondLine < croppedRatios.Length - firstLine; secondLine++) + { + thirdLine = croppedRatios.Length - firstLine - secondLine; + if (firstLine > 3 || secondLine > (averageAspectRatio < 0.85f ? 4 : 3) || thirdLine > 3) + { + continue; + } + attempts.Add(new MessageGroupedLayoutAttempt(firstLine, secondLine, thirdLine, MultiHeight(croppedRatios, 0, firstLine), MultiHeight(croppedRatios, firstLine, firstLine + secondLine), MultiHeight(croppedRatios, firstLine + secondLine, croppedRatios.Length))); + } + } + + for (firstLine = 1; firstLine < croppedRatios.Length - 2; firstLine++) + { + for (secondLine = 1; secondLine < croppedRatios.Length - firstLine; secondLine++) + { + for (thirdLine = 1; thirdLine < croppedRatios.Length - firstLine - secondLine; thirdLine++) + { + fourthLine = croppedRatios.Length - firstLine - secondLine - thirdLine; + if (firstLine > 3 || secondLine > 3 || thirdLine > 3 || fourthLine > 3) + { + continue; + } + attempts.Add(new MessageGroupedLayoutAttempt(firstLine, secondLine, thirdLine, fourthLine, MultiHeight(croppedRatios, 0, firstLine), MultiHeight(croppedRatios, firstLine, firstLine + secondLine), MultiHeight(croppedRatios, firstLine + secondLine, firstLine + secondLine + thirdLine), MultiHeight(croppedRatios, firstLine + secondLine + thirdLine, croppedRatios.Length))); + } + } + } + + MessageGroupedLayoutAttempt optimal = null; + float optimalDiff = 0.0f; + float maxHeight = _maxSizeWidth / 3 * 4; + for (int a = 0; a < attempts.Count; a++) + { + MessageGroupedLayoutAttempt attempt = attempts[a]; + float height = 0; + float minLineHeight = float.MaxValue; + for (int b = 0; b < attempt.Heights.Length; b++) + { + height += attempt.Heights[b]; + if (attempt.Heights[b] < minLineHeight) + { + minLineHeight = attempt.Heights[b]; + } + } + + float diff = Math.Abs(height - maxHeight); + if (attempt.LineCounts.Length > 1) + { + if (attempt.LineCounts[0] > attempt.LineCounts[1] || (attempt.LineCounts.Length > 2 && attempt.LineCounts[1] > attempt.LineCounts[2]) || (attempt.LineCounts.Length > 3 && attempt.LineCounts[2] > attempt.LineCounts[3])) + { + diff *= 1.5f; + } + } + + if (minLineHeight < minWidth) + { + diff *= 1.5f; + } + + if (optimal == null || diff < optimalDiff) + { + optimal = attempt; + optimalDiff = diff; + } + } + if (optimal == null) + { + return; + } + + int index = 0; + float y = 0.0f; + + for (int i = 0; i < optimal.LineCounts.Length; i++) + { + int c = optimal.LineCounts[i]; + float lineHeight = optimal.Heights[i]; + int spanLeft = _maxSizeWidth; + GroupedMessagePosition posToFix = null; + maxX = Math.Max(maxX, c - 1); + for (int k = 0; k < c; k++) + { + float ratio = croppedRatios[index]; + int width = (int)(ratio * lineHeight); + spanLeft -= width; + GroupedMessagePosition pos = _posArray[index]; + int flags = 0; + if (i == 0) + { + flags |= POSITION_FLAG_TOP; + } + if (i == optimal.LineCounts.Length - 1) + { + flags |= POSITION_FLAG_BOTTOM; + } + if (k == 0) + { + flags |= POSITION_FLAG_LEFT; + if (isOut) + { + posToFix = pos; + } + } + if (k == c - 1) + { + flags |= POSITION_FLAG_RIGHT; + if (!isOut) + { + posToFix = pos; + } + } + pos.Set(k, k, i, i, width, lineHeight / maxSizeHeight, flags); + index++; + } + posToFix.Width += spanLeft; + posToFix.SpanSize += spanLeft; + y += lineHeight; + } + + totalWidth = _maxSizeWidth; + totalHeight = y / maxSizeHeight; + } + int avatarOffset = 108; + for (int a = 0; a < count; a++) + { + //GroupedMessagePosition pos = _posArray[a]; + //if (isOut) + //{ + // if (pos.MinX == 0) + // { + // pos.SpanSize += firstSpanAdditionalSize; + // } + // if ((pos.Flags & POSITION_FLAG_RIGHT) != 0) + // { + // pos.IsEdge = true; + // } + //} + //else + //{ + // if (pos.MaxX == maxX || (pos.Flags & POSITION_FLAG_RIGHT) != 0) + // { + // pos.SpanSize += firstSpanAdditionalSize; + // } + // if ((pos.Flags & POSITION_FLAG_LEFT) != 0) + // { + // pos.IsEdge = true; + // } + //} + //TLMessage messageObject = Messages[a]; + //if (!isOut && messageObject.needDrawAvatar()) + //{ + // if (pos.IsEdge) + // { + // if (pos.SpanSize != 1000) + // { + // pos.SpanSize += avatarOffset; + // } + // pos.Width += avatarOffset; + // } + // else if ((pos.Flags & POSITION_FLAG_RIGHT) != 0) + // { + // if (pos.SpanSize != 1000) + // { + // pos.SpanSize -= avatarOffset; + // } + // else if (pos.LeftSpanOffset != 0) + // { + // pos.LeftSpanOffset += avatarOffset; + // } + // } + //} + } + + Width = totalWidth; + Height = totalHeight; + } + + public static TLPhotoSizeBase GetClosestPhotoSizeWithSize(TLVector sizes, int side) + { + return GetClosestPhotoSizeWithSize(sizes, side, false); + } + + public static TLPhotoSizeBase GetClosestPhotoSizeWithSize(TLVector sizes, int side, bool byMinSide) + { + if (sizes == null || sizes.Count == 0) + { + return null; + } + int lastSide = 0; + TLPhotoSizeBase closestObject = null; + for (int a = 0; a < sizes.Count; a++) + { + TLPhotoSizeBase obj = sizes[a]; + if (obj == null) + { + continue; + } + + int w = 0; + int h = 0; + var size = obj as TLPhotoSize; + var cachedSize = obj as TLPhotoCachedSize; + if (size != null) + { + w = size.W.Value; + h = size.H.Value; + } + else if (cachedSize != null) + { + w = cachedSize.W.Value; + h = cachedSize.H.Value; + } + + if (byMinSide) + { + int currentSide = h >= w ? w : h; + var closestSize = closestObject as TLPhotoSize; + if (closestObject == null || side > 100 && closestSize != null && closestSize.Location is TLFileLocation && ((TLFileLocation)closestSize.Location).DCId.Value == int.MinValue || obj is TLPhotoCachedSize || side > lastSide && lastSide < currentSide) + { + closestObject = obj; + lastSide = currentSide; + } + } + else + { + int currentSide = w >= h ? w : h; + var closestSize = closestObject as TLPhotoSize; + if (closestObject == null || side > 100 && closestSize != null && closestSize.Location is TLFileLocation && ((TLFileLocation)closestSize.Location).DCId.Value == int.MinValue || obj is TLPhotoCachedSize || currentSide <= side && lastSide < currentSide) + { + closestObject = obj; + lastSide = currentSide; + } + } + } + return closestObject; + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/InputBox.xaml b/TelegramClient.WP81/Views/Controls/InputBox.xaml new file mode 100755 index 0000000..cf4b45d --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/InputBox.xaml @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/InputBox.xaml.cs b/TelegramClient.WP81/Views/Controls/InputBox.xaml.cs new file mode 100755 index 0000000..bd31543 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/InputBox.xaml.cs @@ -0,0 +1,2178 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reactive.Linq; +using System.Text; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using Windows.Storage; +using Windows.System; +using Windows.UI.ViewManagement; +using Caliburn.Micro; +using Microsoft.Devices; +using Microsoft.Phone.Controls.Maps.Overlays; +using Microsoft.Phone.Shell; +using Microsoft.Xna.Framework.Audio; +using Microsoft.Xna.Framework.GamerServices; +using Telegram.Api.Extensions; +using Telegram.Api.Helpers; +using Telegram.Api.Services; +using Telegram.Api.Services.FileManager; +using Telegram.Api.TL; +using Telegram.Controls; +using Telegram.EmojiPanel.Controls.Emoji; +using TelegramClient.Resources; +using TelegramClient.ViewModels; +using TelegramClient_Native; +using TelegramClient_Opus; +using Action = System.Action; +using Execute = Telegram.Api.Helpers.Execute; + +namespace TelegramClient.Views.Controls +{ + public partial class InputBox + { + public Visibility ForwardButtonVisibility { get; set; } + + #region ReplyMarkup + + public static readonly DependencyProperty ReplyMarkupProperty = DependencyProperty.Register( + "ReplyMarkup", typeof (TLReplyKeyboardBase), typeof (InputBox), new PropertyMetadata(default(TLReplyKeyboardBase), OnReplyMarkupChanged)); + + private static void OnReplyMarkupChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var inputBox = d as InputBox; + if (inputBox != null) + { + //var replyKeyboardBase = e.NewValue as TLReplyKeyboardBase; + //if (replyKeyboardBase != null) + //{ + // inputBox.Debug.Text = replyKeyboardBase + " " + DateTime.Now; + //} + //else + //{ + // inputBox.Debug.Text = "null"; + //} + } + } + + public TLReplyKeyboardBase ReplyMarkup + { + get { return (TLReplyKeyboardBase) GetValue(ReplyMarkupProperty); } + set { SetValue(ReplyMarkupProperty, value); } + } + + #endregion + + #region Reply/Forward/Edit + + private bool _isEditing; + + private bool _isForwarding; + + public event EventHandler OpenReplyButtonClick; + + protected virtual void RaiseOpenReply() + { + EventHandler handler = OpenReplyButtonClick; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private void OpenReply_OnTap(object sender, GestureEventArgs e) + { + e.Handled = true; + + SaveInputFocus(); + RaiseOpenReply(); + } + + public event EventHandler DeleteReplyButtonClick; + + protected virtual void RaiseDeleteReply() + { + EventHandler handler = DeleteReplyButtonClick; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private void DeleteReply_OnTap(object sender, GestureEventArgs e) + { + e.Handled = true; + + SaveInputFocus(); + RaiseDeleteReply(); + } + + public static readonly DependencyProperty ReplyTemplateProperty = DependencyProperty.Register( + "ReplyTemplate", typeof (DataTemplate), typeof (InputBox), new PropertyMetadata(default(DataTemplate), OnReplyTemplateChanged)); + + private static void OnReplyTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var inputBox = d as InputBox; + if (inputBox != null) + { + inputBox.ReplyContentControl.ContentTemplate = e.NewValue as DataTemplate; + } + } + + public DataTemplate ReplyTemplate + { + get { return (DataTemplate) GetValue(ReplyTemplateProperty); } + set { SetValue(ReplyTemplateProperty, value); } + } + + public static readonly DependencyProperty ReplyProperty = DependencyProperty.Register( + "Reply", typeof (object), typeof (InputBox), new PropertyMetadata(default(object), OnReplyChanged)); + + private static void OnReplyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var inputBox = d as InputBox; + if (inputBox != null) + { + inputBox.ReplyGrid.Visibility = e.NewValue != null && !inputBox.IsAppBarCommandVisible + ? Visibility.Visible + : Visibility.Collapsed; + inputBox.ReplyContentControl.Content = e.NewValue; + + inputBox._isEditing = false; + inputBox._isForwarding = false; + var messagesContainer = e.NewValue as TLMessagesContainter; + if (messagesContainer != null) + { + // forward + if (messagesContainer.FwdMessages != null) + { + inputBox._isForwarding = true; + inputBox.SendButtonImage.Source = inputBox.SendSource; + inputBox.SendButton.Visibility = System.Windows.Visibility.Visible; + inputBox.RecordButton.Visibility = System.Windows.Visibility.Collapsed; + } + // edit + else if (messagesContainer.EditMessage != null) + { + inputBox._isEditing = true; + inputBox.AdditionalButtons.Visibility = Visibility.Collapsed; + inputBox.SendButtonImage.Source = inputBox.DoneSource; + inputBox.SendButton.Visibility = System.Windows.Visibility.Visible; + inputBox.RecordButton.Visibility = System.Windows.Visibility.Collapsed; + } + } + // reply + else if (e.NewValue is TLMessageBase) + { + //inputBox.AdditionalButtons.Visibility = Visibility.Collapsed; + //inputBox.SendButton.Source = inputBox.SendSource; + } + else + { + inputBox.AdditionalButtons.Visibility = Visibility.Visible; + var textExists = !string.IsNullOrEmpty(inputBox.Input.Text); + inputBox.SetSendButtonSource(textExists); + } + } + } + + public object Reply + { + get { return GetValue(ReplyProperty); } + set { SetValue(ReplyProperty, value); } + } + + #endregion + + + #region ApplicationBar + + public event EventHandler AppBarCommandClick; + + protected virtual void RaiseAppBarCommandClick() + { + EventHandler handler = AppBarCommandClick; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private Button _appBarButton; + + public static readonly DependencyProperty CommandProperty = DependencyProperty.Register( + "Command", typeof (string), typeof (InputBox), new PropertyMetadata(default(string), OnCommandChanged)); + + private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var inputBox = d as InputBox; + if (inputBox != null) + { + if (inputBox._appBarButton == null) + { + inputBox._appBarButton = new Button { Style = (Style) inputBox.Resources["ButtonStyle1"] }; + inputBox._appBarButton.Click += (sender, args) => inputBox.RaiseAppBarCommandClick(); + inputBox.AppBarCommandPlaceholder.Child = inputBox._appBarButton; + + var scaledText = (ScaledText)Application.Current.Resources["ScaledText"]; + var fontSize = scaledText.DefaultFontSize; + + inputBox._appBarButton.FontSize = fontSize; + } + + + inputBox._appBarButton.Content = e.NewValue; + } + } + + public string Command + { + get { return (string) GetValue(CommandProperty); } + set { SetValue(CommandProperty, value); } + } + + public static readonly DependencyProperty IsAppBarCommandVisibleProperty = DependencyProperty.Register( + "IsAppBarCommandVisible", typeof (bool), typeof (InputBox), new PropertyMetadata(default(bool), OnIsAppBarCommandVisibleChanged)); + + private static void OnIsAppBarCommandVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var inputBox = d as InputBox; + if (inputBox != null) + { + var isAppBarCommandVisible = (bool) e.NewValue; + + //if (isAppBarCommandVisible) + //{ + // //var storyboard = inputBox.GetOpenStoryboard(inputBox.AppBarCommandTransform); + // //var storyboard2 = inputBox.GetCloseStoryboard(inputBox.InputBoxTranslate); + // //storyboard.Begin(); + // //storyboard2.Begin(); + //} + //else + //{ + // //var storyboard = inputBox.GetCloseStoryboard(inputBox.AppBarCommandTransform); + // //var storyboard2 = inputBox.GetOpenStoryboard(inputBox.InputBoxTranslate); + // //storyboard.Begin(); + // //storyboard2.Begin(); + //} + + inputBox.ReplyGrid.Visibility = !isAppBarCommandVisible && inputBox.Reply != null ? Visibility.Visible : Visibility.Collapsed; + inputBox.InputGrid.Visibility = isAppBarCommandVisible ? Visibility.Collapsed : Visibility.Visible; + inputBox.AppBarCommandPlaceholder.Visibility = isAppBarCommandVisible ? Visibility.Visible : Visibility.Collapsed; + } + } + + public bool IsAppBarCommandVisible + { + get { return (bool) GetValue(IsAppBarCommandVisibleProperty); } + set { SetValue(IsAppBarCommandVisibleProperty, value); } + } + #endregion + + private BitmapSource _doneSource; + + private BitmapSource DoneSource + { + get + { + _doneSource = _doneSource ?? new BitmapImage(new Uri("/Images/W10M/ic_done_2x.png", UriKind.Relative)); + + return _doneSource; + } + } + + private BitmapSource _emojiSource; + + private BitmapSource EmojiSource + { + get + { + _emojiSource = _emojiSource ?? new BitmapImage(new Uri("/Images/W10M/ic_emoji_2x.png", UriKind.Relative)); + + return _emojiSource; + } + } + + private BitmapSource _keyboardSource; + + private BitmapSource KeyboardSource + { + get + { + _keyboardSource = _keyboardSource ?? new BitmapImage(new Uri("/Images/W10M/ic_keyboard_2x.png", UriKind.Relative)); + + return _keyboardSource; + } + } + + private BitmapSource _sendSource; + + private BitmapSource SendSource + { + get + { + _sendSource = _sendSource ?? new BitmapImage(new Uri("/Images/W10M/ic_send_2x.png", UriKind.Relative)); + + return _sendSource; + } + } + + private BitmapSource _microphoneSource; + + private BitmapSource MicrophoneSource + { + get + { + _microphoneSource = _microphoneSource ?? new BitmapImage(new Uri("/Images/W10M/ic_microphone_2x.png", UriKind.Relative)); + + return _microphoneSource; + } + } + + public event RoutedEventHandler InputLostFocus; + + protected virtual void RaiseInputLostFocus(RoutedEventArgs e) + { + RoutedEventHandler handler = InputLostFocus; + if (handler != null) handler(this, e); + } + + public event RoutedEventHandler InputGotFocus; + + protected virtual void RaiseInputGotFocus(RoutedEventArgs args) + { + RoutedEventHandler handler = InputGotFocus; + if (handler != null) handler(this, args); + } + + public event KeyEventHandler InputKeyDown; + + protected virtual void RaiseInputKeyDown(KeyEventArgs e) + { + KeyEventHandler handler = InputKeyDown; + if (handler != null) handler(this, e); + } + + public event TextChangedEventHandler InputTextChanged; + + protected virtual void RaiseInputTextChanged(TextChangedEventArgs e) + { + TextChangedEventHandler handler = InputTextChanged; + if (handler != null) handler(this, e); + } + + public ContentControl EmojiPlaceholder { get { return KeyboardPlaceholder; } } + + public TextBox InnerTextBox { get { return Input; } } + + public int SelectionStart + { + get { return Input.SelectionStart; } + set { Input.SelectionStart = value; } + } + + public int SelectionLength + { + get { return Input.SelectionLength; } + set { Input.SelectionLength = value; } + } + + public Visibility MuteButtonVisibility + { + get { return MuteButtonBorder.Visibility; } + set { MuteButtonBorder.Visibility = value; } + } + + public Visibility KeyboardButtonVisibility + { + get { return KeyboardButtonBorder.Visibility; } + set { KeyboardButtonBorder.Visibility = value; } + } + + public static readonly DependencyProperty KeyboardButtonImageStringProperty = DependencyProperty.Register( + "KeyboardButtonImageString", typeof (string), typeof (InputBox), new PropertyMetadata(default(string), OnKeyboardButtonImageStringChanged)); + + private static void OnKeyboardButtonImageStringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var inputBox = d as InputBox; + if (inputBox != null) + { + var str = e.NewValue as string; + inputBox.KeyboardButton.Source = str != null ? new BitmapImage(new Uri(str, UriKind.Relative)) : null; + } + } + + public string KeyboardButtonImageString + { + get { return (string) GetValue(KeyboardButtonImageStringProperty); } + set { SetValue(KeyboardButtonImageStringProperty, value); } + } + + public static readonly DependencyProperty MuteButtonImageSourceProperty = DependencyProperty.Register( + "MuteButtonImageSource", typeof (ImageSource), typeof (InputBox), new PropertyMetadata(default(ImageSource), OnMuteButtonImageSourceChanged)); + + private static void OnMuteButtonImageSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var inputBox = d as InputBox; + if (inputBox != null) + { + inputBox.MuteButton.Source = (ImageSource) e.NewValue; + } + } + + public ImageSource MuteButtonImageSource + { + get { return (ImageSource) GetValue(MuteButtonImageSourceProperty); } + set { SetValue(MuteButtonImageSourceProperty, value); } + } + + public static readonly DependencyProperty TextScaleFactorProperty = DependencyProperty.Register( + "TextScaleFactor", typeof(double), typeof(InputBox), new PropertyMetadata(default(double), OnTextScaleFactorChanged)); + + private static void OnTextScaleFactorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var inputBox = d as InputBox; + if (inputBox != null) + { + inputBox.Input.TextScaleFactor = (double)e.NewValue; + } + } + + public double TextScaleFactor + { + get { return (double)GetValue(TextScaleFactorProperty); } + set { SetValue(TextScaleFactorProperty, value); } + } + + public static readonly DependencyProperty InlineWatermarkProperty = DependencyProperty.Register( + "InlineWatermark", typeof(string), typeof(InputBox), new PropertyMetadata(default(string), OnInlineWatermarkChanged)); + + private static void OnInlineWatermarkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var inputBox = d as InputBox; + if (inputBox != null) + { + inputBox.Input.InlineWatermark = e.NewValue as string; + } + } + + public string InlineWatermark + { + get { return (string)GetValue(InlineWatermarkProperty); } + set { SetValue(InlineWatermarkProperty, value); } + } + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register( + "Text", typeof(string), typeof(InputBox), new PropertyMetadata("", OnTextPropertyChanged)); + + private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var inputBox = d as InputBox; + if (inputBox != null && e.NewValue != null) + { + inputBox.Input.Text = e.NewValue as string; + } + } + + public string Text + { + get + { + return (string)GetValue(TextProperty) ?? ""; + } + set + { + var text = value ?? ""; + SetValue(TextProperty, text); + } + } + + public event EventHandler SendButtonClick; + + protected virtual void RaiseSendButtonClick() + { + var handler = SendButtonClick; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler AttachButtonClick; + + protected virtual void RaiseAttachButtonClick() + { + var handler = AttachButtonClick; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler MuteButtonClick; + + protected virtual void RaiseMuteButtonClick() + { + var handler = MuteButtonClick; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler KeyboardButtonClick; + + protected virtual void RaiseKeyboardButtonClick() + { + var handler = KeyboardButtonClick; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler EmojiButtonClick; + + protected virtual void RaiseEmojiButtonClick() + { + var handler = EmojiButtonClick; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private Control _gotFocusControl; + + private bool _isFocused; + + private double _applicationBarDefaultSize = 72.0; + + private double _iconMargin = 20.0; + + private double _iconSize = 32.0; + + private double _iconLabelFontSize = 18.0; + + public InputBox() + { + InitializeComponent(); + + if (DesignerProperties.IsInDesignTool) return; + + var applicationBar = new ApplicationBar(); + _applicationBarDefaultSize = applicationBar.DefaultSize; + + KeyboardHeight = EmojiControl.PortraitOrientationHeight; + + KeyboardPlaceholder.Visibility = Visibility.Collapsed; + KeyboardPlaceholder.Height = KeyboardHeight; + //var control = KeyboardPlaceholder.Content as FrameworkElement; + //if (control != null) + //{ + // control.Height = KeyboardHeight; + //} + + if (_applicationBarDefaultSize < 72.0) + { + var scaleFactor = _applicationBarDefaultSize / 72.0; + _iconMargin = 20.0 * scaleFactor; + _iconSize = _applicationBarDefaultSize - 2.0 * _iconMargin; + _iconLabelFontSize = 18.0 * scaleFactor; + RecordButtonIcon.Margin = new Thickness(20.0, _iconMargin, 20.0, _iconMargin); + RecordButtonIcon.Width = _iconSize; + RecordButtonIcon.Height = _iconSize; + SendButtonImage.Margin = new Thickness(20.0, _iconMargin, 20.0, _iconMargin); + SendButtonImage.Width = _iconSize; + SendButtonImage.Height = _iconSize; + KeyboardButton.Margin = new Thickness(20.0, _iconMargin, 20.0, _iconMargin); + KeyboardButton.Width = _iconSize; + KeyboardButton.Height = _iconSize; + MuteButton.Margin = new Thickness(20.0, _iconMargin, 20.0, _iconMargin); + MuteButton.Width = _iconSize; + MuteButton.Height = _iconSize; + AttachButton.Margin = new Thickness(20.0, _iconMargin, 20.0, _iconMargin); + AttachButton.Width = _iconSize; + AttachButton.Height = _iconSize; + EmojiButtonImage.Margin = new Thickness(20.0, _iconMargin, 20.0, _iconMargin); + EmojiButtonImage.Width = _iconSize; + EmojiButtonImage.Height = _iconSize; + } + HintGrid.Height = _applicationBarDefaultSize; + + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + if (isLightTheme) + { + TopBorder.Fill = (Brush)Resources["InputBorderBrushLight"]; + } + else + { + TopBorder.Fill = (Brush)Resources["InputBorderBrushDark"]; + Input.CaretBrush = new SolidColorBrush(Colors.White); + } + + var keyPressEvents = Observable.FromEventPattern( + keh => { Input.TextChanged += keh; }, + keh => { Input.TextChanged -= keh; }); + + _keyPressSubscription = keyPressEvents + .Throttle(TimeSpan.FromSeconds(0.15)) + .ObserveOnDispatcher() + .Subscribe(e => UpdateEmojiHints()); + + Loaded += OnLoaded; + Loaded += OnLoadedOnce; + Unloaded += OnUnloaded; + + GotFocus += (sender, args) => + { + _isFocused = true; + _gotFocusControl = args.OriginalSource as Control; + }; + LostFocus += (sender, args) => + { + _isFocused = false; + }; + } +#if DEBUG + ~InputBox() + { + + } +#endif + + private void OnLoadedOnce(object sender, RoutedEventArgs e) + { + Loaded -= OnLoadedOnce; + + Text = Input.Text; + var textExists = !string.IsNullOrEmpty(Input.Text); + + Scroll.VerticalScrollBarVisibility = textExists ? ScrollBarVisibility.Auto : ScrollBarVisibility.Disabled; + AttachButtonBorder.Visibility = textExists ? Visibility.Collapsed : Visibility.Visible; + SetSendButtonSource(textExists); + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + if (_microphone != null) _microphone.BufferReady += Microphone_OnBufferReady; + + InputPane.GetForCurrentView().Showing += OnInputPaneShowing; + InputPane.GetForCurrentView().Hiding += OnInputPaneHiding; + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + if (_microphone != null) _microphone.BufferReady -= Microphone_OnBufferReady; + + InputPane.GetForCurrentView().Showing -= OnInputPaneShowing; + InputPane.GetForCurrentView().Hiding -= OnInputPaneHiding; + } + + private void Input_OnSizeChanged(object sender, SizeChangedEventArgs e) + { + if (e.NewSize.Height > e.PreviousSize.Height) + { + Scroll.ScrollToVerticalOffset(Scroll.VerticalOffset + e.NewSize.Height - e.PreviousSize.Height); + } + } + + private void Input_OnTextChanged(object sender, TextChangedEventArgs e) + { + if (_suppressNotifyTextChanged) + { + _suppressNotifyTextChanged = false; + return; + } + + //RaiseHideEmojiHints(); + //UpdateEmojiHints(); + + Text = Input.Text; + var textExists = !string.IsNullOrEmpty(Input.Text); + + Scroll.VerticalScrollBarVisibility = textExists ? ScrollBarVisibility.Auto : ScrollBarVisibility.Disabled; + AttachButtonBorder.Visibility = textExists ? Visibility.Collapsed : Visibility.Visible; + SetSendButtonSource(textExists); + + RaiseInputTextChanged(e); + } + + private EmojiSuggestionParams _parameters; + + public event EventHandler ShowEmojiHints; + + protected virtual void RaiseShowEmojiHints(EmojiHintsEventArgs e) + { + System.Diagnostics.Debug.WriteLine("ShowEmojiHints selectionStart={0} text={1} parameters=[{2}]", Input.SelectionStart, Input.Text, e.Parameters); + + _parameters = e.Parameters; + + var handler = ShowEmojiHints; + if (handler != null) handler(this, e); + } + + public event EventHandler HideEmojiHints; + + protected virtual void RaiseHideEmojiHints() + { + //System.Diagnostics.Debug.WriteLine("HideEmojiHints selectionStart={0} text={1} parameters=[{2}]", Input.SelectionStart, Input.Text, _parameters); + _parameters = null; + + var handler = HideEmojiHints; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private void UpdateEmojiHints() + { + //RaiseHideEmojiHints(); + + var index = SuggestionIndex(Input.Text, Input.SelectionStart, EmojiSuggestion.GetSuggestionMaxLength()); + if (index != -1) + { + var p = new EmojiSuggestionParams + { + Text = Input.Text, + SelectionStart = Input.SelectionStart, + Index = index, + Length = Input.SelectionStart - index + }; + + var query = p.Text.Substring(p.Index + 1, p.Length - 1); + if (!string.IsNullOrEmpty(query)) + { + Execute.BeginOnThreadPool(() => + { + var stopwatch = Stopwatch.StartNew(); + p.Results = EmojiSuggestion.GetSuggestions(query); + var elapsed = stopwatch.Elapsed; + + Execute.BeginOnUIThread(() => + { + if (p.Results != null + && string.Equals(Input.Text, p.Text, StringComparison.Ordinal) + && p.SelectionStart == Input.SelectionStart) + { + RaiseShowEmojiHints(new EmojiHintsEventArgs(p)); + } + else + { + RaiseHideEmojiHints(); + } + }); + }); + } + else + { + RaiseHideEmojiHints(); + } + } + else + { + RaiseHideEmojiHints(); + } + } + + private static bool IsSuggestionChar(char ch) + { + return (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '_') || (ch == '-') || (ch == '+'); + } + + private int SuggestionIndex(string str, int start, int maxLength) + { + var index = start - 1; + while (index >= 0 && ((start - maxLength) <= index)) + { + if (str[index] == ':') + { + if (index != start - 1 + && (index == 0 || !IsSuggestionChar(str[index - 1]))) + { + return index; + } + } + else if (!IsSuggestionChar(str[index])) + { + return -1; + } + index--; + } + + return -1; + } + + private void Input_OnSelectionChanged(object sender, RoutedEventArgs e) + { + if (_parameters != null + && string.Equals(_parameters.Text, Input.Text, StringComparison.Ordinal) + && _parameters.SelectionStart != Input.SelectionStart) + { + RaiseHideEmojiHints(); + } + } + + private void SetSendButtonSource(bool textExists) + { + if (_isEditing) + { + SendButtonImage.Source = DoneSource; + } + else if (_isForwarding) + { + SendButtonImage.Source = SendSource; + } + else + { + SendButtonImage.Source = SendSource; + if (textExists) + { + SendButton.Visibility = Visibility.Visible; + RecordButton.Visibility = Visibility.Collapsed; + } + else + { + SendButton.Visibility = Visibility.Collapsed; + RecordButton.Visibility = Visibility.Visible; + } + } + } + + private void SaveInputFocus() + { + if (_isFocused + && _gotFocusControl == Input) + { + Input.Focus(); + } + } + + private void SendButton_OnTap(object sender, GestureEventArgs gestureEventArgs) + { + SaveInputFocus(); + + _suppressNotifyTextChanged = true; + Input.Text = string.Empty; + ReplyGrid.Visibility = Visibility.Collapsed; + Scroll.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled; + AttachButtonBorder.Visibility = Visibility.Visible; + AdditionalButtons.Visibility = Visibility.Visible; + _isEditing = false; + _isForwarding = false; + SetSendButtonSource(false); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + RaiseSendButtonClick(); + }); + } + + private void AttachButton_OnTap(object sender, GestureEventArgs e) + { + RaiseAttachButtonClick(); + } + + private void KeyboardButton_OnTap(object sender, GestureEventArgs e) + { + RaiseKeyboardButtonClick(); + } + + private void MuteButton_OnTap(object sender, GestureEventArgs e) + { + SaveInputFocus(); + RaiseMuteButtonClick(); + } + + private bool _suppressHiding; + private bool _suppressNotifyTextChanged; + + private void EmojiButton_OnTap(object sender, MouseButtonEventArgs mouseButtonEventArgs) + { + RaiseEmojiButtonClick(); + } + + private void OnInputPaneHiding(InputPane sender, InputPaneVisibilityEventArgs args) + { + if (KeyboardPlaceholder.Opacity == 1.0) return; + + KeyboardPlaceholder.Visibility = Visibility.Collapsed; + } + + public static double KeyboardHeight { get; protected set; } + + private void OnInputPaneShowing(InputPane sender, InputPaneVisibilityEventArgs args) + { + if (!_isFocused || _gotFocusControl != Input) return; + + KeyboardHeight = 480.0 / args.OccludedRect.Width * args.OccludedRect.Height; + + KeyboardPlaceholder.Visibility = Visibility.Visible; + KeyboardPlaceholder.Height = KeyboardHeight; + //var control = KeyboardPlaceholder.Content as FrameworkElement; + //if (control != null) + //{ + // control.Height = KeyboardHeight; + //} + } + + private void Input_OnKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter + && System.Windows.Input.Keyboard.Modifiers == ModifierKeys.Control) + { + RaiseSendButtonClick(); + } + + RaiseInputKeyDown(e); + } + + private void Input_OnGotFocus(object sender, RoutedEventArgs e) + { + KeyboardPlaceholder.Visibility = Visibility.Visible; + KeyboardPlaceholder.Opacity = 0.0; + EmojiButtonImage.Source = EmojiSource; + + RaiseInputGotFocus(e); + } + + private void Input_OnLostFocus(object sender, RoutedEventArgs e) + { + RaiseInputLostFocus(e); + } + + public void OpenPlaceholder() + { + KeyboardPlaceholder.Visibility = Visibility.Visible; + KeyboardPlaceholder.Opacity = 1.0; + EmojiButtonImage.Source = KeyboardSource; + } + + public void ClosePlaceholder() + { + KeyboardPlaceholder.Visibility = Visibility.Collapsed; + EmojiButtonImage.Source = EmojiSource; + + if (IsFullScreen) + { + CloseFullScreen(); + } + } + + public void FocusInput() + { + Input.Focus(); + } + + public void SwitchToSelectionMode() + { + if (InputBoxTranslate.Y == 72.0) return; + + if (_applicationBarBorder == null) + { + _applicationBarBorder = CreateApplicationBar(); + + CommonGrid.Children.Insert(0, _applicationBarBorder); + } + + _deleteButton.IsHitTestVisible = false; + _deleteButton.Opacity = 0.5; + + _forwardButton.IsHitTestVisible = false; + _forwardButton.Opacity = 0.5; + _forwardButton.Visibility = ForwardButtonVisibility; + + _appBarOpened = false; + _cancelLabel.Visibility = Visibility.Collapsed; + _deleteLabel.Visibility = Visibility.Collapsed; + _forwardLabel.Visibility = Visibility.Collapsed; + + var storyboard = GetCloseStoryboard(InputBoxTranslate, BackgroundBorder, _applicationBarBorder); + storyboard.Begin(); + //LayoutRoot.Visibility = Visibility.Collapsed; + //BackgroundBorder.Background = new SolidColorBrush(Colors.Transparent); + } + + public event EventHandler CancelSelectionButtonClick; + + protected virtual void RaiseCancelSelectionButtonClick() + { + EventHandler handler = CancelSelectionButtonClick; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler ForwardButtonClick; + + protected virtual void RaiseForwardButtonClick() + { + EventHandler handler = ForwardButtonClick; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler DeleteButtonClick; + + protected virtual void RaiseDeleteButtonClick() + { + EventHandler handler = DeleteButtonClick; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private Border CreateApplicationBar() + { + var border = new Border(); + border.Height = 18.0 + _applicationBarDefaultSize; + border.Margin = new Thickness(0.0, 0.0, 0.0, -18.0); + border.VerticalAlignment = VerticalAlignment.Bottom; + border.RenderTransform = new TranslateTransform{ Y = 0.0 }; + + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + border.Background = isLightTheme ? (SolidColorBrush)Resources["AppBarPanelLight"] : (SolidColorBrush)Resources["AppBarPanelDark"]; + + var grid = new Grid(); + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(72.0) }); + grid.ColumnDefinitions.Add(new ColumnDefinition()); + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(72.0) }); + grid.ColumnDefinitions.Add(new ColumnDefinition()); + grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(72.0) }); + + border.Child = grid; + + var moreButton = CreateButton("/Images/W10M/ic_more_2x.png", null, null).Item1; + moreButton.Tap += (sender, args) => + { + if (_appBarOpened) + { + CloseMorePanel(); + } + else + { + OpenMorePanel(); + } + + _appBarOpened = !_appBarOpened; + }; + Grid.SetColumn(moreButton, 4); + grid.Children.Add(moreButton); + + var cancelButtonTuple = CreateButton("/Images/W10M/ic_cancel_2x.png", AppResources.Cancel, RaiseCancelSelectionButtonClick); + _cancelLabel = cancelButtonTuple.Item2; + Grid.SetColumn(cancelButtonTuple.Item1, 3); + grid.Children.Add(cancelButtonTuple.Item1); + + var deleteButtonTuple = CreateButton("/Images/W10M/ic_delete_2x.png", AppResources.Delete, RaiseDeleteButtonClick); + _deleteButton = deleteButtonTuple.Item1; + _deleteLabel = deleteButtonTuple.Item2; + Grid.SetColumn(_deleteButton, 2); + grid.Children.Add(_deleteButton); + + var forwardButtonTuple = CreateButton("/Images/W10M/ic_share_2x.png", AppResources.Forward, RaiseForwardButtonClick); + _forwardButton = forwardButtonTuple.Item1; + _forwardLabel = forwardButtonTuple.Item2; + Grid.SetColumn(_forwardButton, 1); + grid.Children.Add(_forwardButton); + + return border; + } + + private Tuple CreateButton(string iconPath, string title, Action callback) + { + var grid = new Grid(); + grid.Background = new SolidColorBrush(Colors.Transparent); + + var border = new Border(); + border.VerticalAlignment = VerticalAlignment.Top; + border.Background = (Brush) Application.Current.Resources["PhoneForegroundBrush"]; + border.Margin = new Thickness(20.0, _iconMargin, 20.0, _iconMargin); + border.Width = _iconSize; + border.Height = _iconSize; + var brush = new ImageBrush { ImageSource = new BitmapImage(new Uri(iconPath, UriKind.Relative)) }; + border.OpacityMask = brush; + grid.Children.Add(border); + + TextBlock label = null; + if (!string.IsNullOrEmpty(title)) + { + label = new TextBlock(); + label.Text = title; + label.VerticalAlignment = VerticalAlignment.Bottom; + label.Visibility = Visibility.Collapsed; + label.Margin = new Thickness(-12.0, 0.0, -12.0, 9.0); + label.MaxWidth = 96.0; + label.TextWrapping = TextWrapping.NoWrap; + label.TextTrimming = TextTrimming.WordEllipsis; + label.TextAlignment = TextAlignment.Center; + label.FontSize = _iconLabelFontSize; + label.IsHitTestVisible = false; + + grid.Children.Add(label); + } + + border.Tap += (sender, args) => callback.SafeInvoke(); + + return new Tuple(grid, label); + } + + public void SwitchToNormalMode() + { + if (InputBoxTranslate.Y == 0.0) return; + + var storyboard = GetOpenStoryboard(InputBoxTranslate, BackgroundBorder, _applicationBarBorder); + storyboard.Begin(); + //LayoutRoot.Visibility = Visibility.Visible; + //BackgroundBorder.Background = (Brush) Application.Current.Resources["PhoneBackgroundBrush"]; + } + + private static Storyboard GetOpenStoryboard(TranslateTransform transform, UIElement element, UIElement element2) + { + var storyboard = new Storyboard(); + + var transformAnimaion = new DoubleAnimation { To = 0.0, Duration = TimeSpan.FromSeconds(0.2), EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } }; + Storyboard.SetTarget(transformAnimaion, transform); + Storyboard.SetTargetProperty(transformAnimaion, new PropertyPath("Y")); + storyboard.Children.Add(transformAnimaion); + + var opacityAnimaion = new DoubleAnimation { To = 1.0, Duration = TimeSpan.FromSeconds(0.2) }; + Storyboard.SetTarget(opacityAnimaion, element); + Storyboard.SetTargetProperty(opacityAnimaion, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityAnimaion); + + var visibilityAnimation2 = new ObjectAnimationUsingKeyFrames(); + visibilityAnimation2.KeyFrames.Add(new DiscreteObjectKeyFrame { KeyTime = TimeSpan.FromSeconds(0.2), Value = Visibility.Collapsed }); + Storyboard.SetTarget(visibilityAnimation2, element2); + Storyboard.SetTargetProperty(visibilityAnimation2, new PropertyPath("Visibility")); + storyboard.Children.Add(visibilityAnimation2); + + var transformAnimaion2 = new DoubleAnimationUsingKeyFrames(); + transformAnimaion2.KeyFrames.Add(new DiscreteDoubleKeyFrame{KeyTime = TimeSpan.FromSeconds(0.0), Value = 0.0}); + Storyboard.SetTarget(transformAnimaion2, element2.RenderTransform); + Storyboard.SetTargetProperty(transformAnimaion2, new PropertyPath("Y")); + storyboard.Children.Add(transformAnimaion2); + + var visibilityAnimation = new ObjectAnimationUsingKeyFrames(); + visibilityAnimation.KeyFrames.Add(new DiscreteObjectKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = Visibility.Visible }); + Storyboard.SetTarget(visibilityAnimation, element); + Storyboard.SetTargetProperty(visibilityAnimation, new PropertyPath("Visibility")); + storyboard.Children.Add(visibilityAnimation); + + return storyboard; + } + + private static Storyboard GetCloseStoryboard(TranslateTransform transform, UIElement element, UIElement element2) + { + var storyboard = new Storyboard(); + + var transformAnimaion = new DoubleAnimation { To = 72.0, Duration = TimeSpan.FromSeconds(0.2), EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 6.0 } }; + Storyboard.SetTarget(transformAnimaion, transform); + Storyboard.SetTargetProperty(transformAnimaion, new PropertyPath("Y")); + storyboard.Children.Add(transformAnimaion); + + var opacityAnimaion = new DoubleAnimation { To = 0.0, Duration = TimeSpan.FromSeconds(0.2) }; + Storyboard.SetTarget(opacityAnimaion, element); + Storyboard.SetTargetProperty(opacityAnimaion, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityAnimaion); + + var visibilityAnimation2 = new ObjectAnimationUsingKeyFrames(); + visibilityAnimation2.KeyFrames.Add(new DiscreteObjectKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = Visibility.Visible }); + Storyboard.SetTarget(visibilityAnimation2, element2); + Storyboard.SetTargetProperty(visibilityAnimation2, new PropertyPath("Visibility")); + storyboard.Children.Add(visibilityAnimation2); + + var visibilityAnimation = new ObjectAnimationUsingKeyFrames(); + visibilityAnimation.KeyFrames.Add(new DiscreteObjectKeyFrame { KeyTime = TimeSpan.FromSeconds(0.2), Value = Visibility.Collapsed }); + Storyboard.SetTarget(visibilityAnimation, element); + Storyboard.SetTargetProperty(visibilityAnimation, new PropertyPath("Visibility")); + storyboard.Children.Add(visibilityAnimation); + + return storyboard; + } + + #region ApplicationBar + + private Border _applicationBarBorder; + + private FrameworkElement _deleteButton; + + private FrameworkElement _forwardButton; + + private TextBlock _deleteLabel; + + private TextBlock _forwardLabel; + + private TextBlock _cancelLabel; + + public Tuple IsGroupActionEnabled + { + set + { + if (_deleteButton != null) + { + _deleteButton.Opacity = value.Item1 ? 1.0 : 0.5; + _deleteButton.IsHitTestVisible = value.Item1; + } + + if (_forwardButton != null) + { + _forwardButton.Opacity = value.Item2 ? 1.0 : 0.5; + _forwardButton.IsHitTestVisible = value.Item2; + } + } + } + + public bool IsDeleteActionVisible + { + set + { + if (_deleteButton != null) + { + _deleteButton.Visibility = value ? Visibility.Visible : Visibility.Collapsed; + } + + if (_forwardButton != null) + { + Grid.SetColumn(_forwardButton, value ? 1 : 2); + } + } + } + + private bool _appBarOpened; + + private void OpenMorePanel() + { + var storyboard = new Storyboard(); + + var translateAppBarPanelAnimation = new DoubleAnimationUsingKeyFrames(); + translateAppBarPanelAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = -16.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(translateAppBarPanelAnimation, _applicationBarBorder); + Storyboard.SetTargetProperty(translateAppBarPanelAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateAppBarPanelAnimation); + + _cancelLabel.Visibility = Visibility.Visible; + _deleteLabel.Visibility = Visibility.Visible; + _forwardLabel.Visibility = Visibility.Visible; + + storyboard.Begin(); + } + + private void CloseMorePanel() + { + var storyboard = new Storyboard(); + + var translateAppBarPanelAnimation = new DoubleAnimationUsingKeyFrames(); + translateAppBarPanelAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 6.0 } }); + Storyboard.SetTarget(translateAppBarPanelAnimation, _applicationBarBorder); + Storyboard.SetTargetProperty(translateAppBarPanelAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateAppBarPanelAnimation); + + storyboard.Begin(); + storyboard.Completed += (sender, args) => + { + _cancelLabel.Visibility = Visibility.Collapsed; + _deleteLabel.Visibility = Visibility.Collapsed; + _forwardLabel.Visibility = Visibility.Collapsed; + }; + } + #endregion + + #region Recording + + public bool UploadFileDuringRecording { get; set; } + + private bool _isLogEnabled = false; + + private void Log(string str) + { + if (!_isLogEnabled) return; + + System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString(" HH:mm:ss.fff ") + str); + } + + private DateTime? _lastUpdateTime; + private DateTime? _lastTypingTime; + private bool _isHintStoryboardPlaying; + private bool _isSliding; + private Microphone _microphone; + private byte[] _buffer; + private TimeSpan _duration; + private TimeSpan _recordedDuration; + private DateTime _startTime; + private volatile bool _stopRequested; + private volatile bool _cancelRequested; + + private MemoryStream _stream; + private XnaAsyncDispatcher _asyncDispatcher; + private string _fileName = "audio.mp3"; + + private WindowsPhoneRuntimeComponent _component; + + protected WindowsPhoneRuntimeComponent Component + { + get + { + if (DesignerProperties.IsInDesignTool) return null; + + _component = _component ?? new WindowsPhoneRuntimeComponent(); + + return _component; + } + } + + private long _uploadingLength; + private volatile bool _isPartReady; + private int _skipBuffersCount; + private TLLong _fileId; + private readonly List _uploadableParts = new List(); + + private TextBlock Duration; + + private Grid SliderPanel; + + private StackPanel Slider; + + private Grid TimerPanel; + + private Grid CreateTimerPanel() + { + var timerPanel = new Grid { Margin = new Thickness(0.0, 2.0, 0.0, 0.0), Visibility = Visibility.Collapsed, Background = (Brush)Application.Current.Resources["PhoneBackgroundBrush"], MinWidth = 120.0, IsHitTestVisible = false }; + timerPanel.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + timerPanel.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); + + timerPanel.RenderTransform = new TranslateTransform(); + + var scaledText = (ScaledText) Application.Current.Resources["ScaledText"]; + var fontSize = scaledText.DefaultFontSize; + + Duration = new TextBlock + { + CacheMode = new BitmapCache(), + VerticalAlignment = VerticalAlignment.Center, + Margin = new Thickness(12.0, 0.0, 12.0, 3.0), + Text = "0:00,0", + FontSize = fontSize + }; + Grid.SetColumn(Duration, 1); + var border = new Ellipse + { + VerticalAlignment = VerticalAlignment.Center, + Margin = new Thickness(20.0, 0.0, 0.0, 2.0), + Width = 10.0, + Height = 10.0, + Fill = new SolidColorBrush(Color.FromArgb(255, 255, 83, 83)) + }; + Grid.SetColumn(border, 0); + + _recordingStoryboard = GetRecordingStoryboard(border); + + timerPanel.Children.Add(Duration); + timerPanel.Children.Add(border); + + Grid.SetColumn(timerPanel, 0); + + return timerPanel; + } + + private TranslateTransform _sliderTextTransform; + + private CompositeTransform _sliderPathTransform; + + private Grid CreateSliderPanel() + { + Brush fill; + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + if (isLightTheme) + { + fill = (Brush)Resources["InputForegroundBrushLight"]; + } + else + { + fill = (Brush)Resources["InputForegroundBrushDark"]; + } + + var clipGrid = new Grid { Visibility = Visibility.Collapsed, IsHitTestVisible = false }; + Grid.SetColumn(clipGrid, 0); + Grid.SetColumnSpan(clipGrid, 5); + + Slider = new StackPanel + { + CacheMode = new BitmapCache(), + VerticalAlignment = VerticalAlignment.Center, + Orientation = Orientation.Horizontal, + HorizontalAlignment = HorizontalAlignment.Center, + Margin = new Thickness(6.0, 0.0, 0.0, 0.0), + RenderTransform = new TranslateTransform() + }; + + var scaledText = (ScaledText)Application.Current.Resources["ScaledText"]; + var fontSize = scaledText.DefaultFontSize; + + _sliderTextTransform = new TranslateTransform(); + var textBlock = new TextBlock + { + Foreground = fill, + VerticalAlignment = VerticalAlignment.Center, + Text = AppResources.SlideToCancel, + FontSize = fontSize, + Margin = new Thickness(4.0, 0.0, 0.0, 3.0), + RenderTransform = _sliderTextTransform, + }; + + _sliderPathTransform = new CompositeTransform{ Rotation = 45.0 }; + var path = new System.Windows.Shapes.Path + { + Stroke = fill, + VerticalAlignment = VerticalAlignment.Center, + Margin = new Thickness(72.0, 0.0, 0.0, 0.0), + StrokeThickness = 2.0, + RenderTransformOrigin = new Point(0.5, 0.5), + RenderTransform = _sliderPathTransform + }; + var dataBinding = new System.Windows.Data.Binding { Source = "M 0,0 0,16 16,16" }; + path.SetBinding(System.Windows.Shapes.Path.DataProperty, dataBinding); + + Slider.Children.Add(path); + Slider.Children.Add(textBlock); + + clipGrid.Children.Add(Slider); + + return clipGrid; + } + + private void RecordButton_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + SaveInputFocus(); + + var microphoneState = _microphone != null ? _microphone.State : (MicrophoneState?)null; + if (microphoneState == MicrophoneState.Started) return; + if (_isHintStoryboardPlaying) return; + + Log(string.Format("microphone_state={0} storyboard_state={1}", microphoneState, _isHintStoryboardPlaying)); + + if (Component == null) return; + if (_asyncDispatcher == null) + { + _asyncDispatcher = new XnaAsyncDispatcher(TimeSpan.FromMilliseconds(50), OnTimerTick); + } + + if (_microphone == null) + { + try + { + _microphone = Microphone.Default; + _microphone.BufferReady += Microphone_OnBufferReady; + } + catch (Exception ex) + { + TLUtils.WriteException(ex); + + RecordButton.Opacity = 0.5; + RecordButton.IsHitTestVisible = false; + + ShowMicrophonePrivacy(); + + return; + } + } + + try + { + _microphone.BufferDuration = TimeSpan.FromMilliseconds(120); + _duration = _microphone.BufferDuration; + _buffer = new byte[_microphone.GetSampleSizeInBytes(_microphone.BufferDuration)]; + } + catch (Exception ex) + { + TLUtils.WriteException(ex); + + RecordButton.Opacity = 0.5; + RecordButton.IsHitTestVisible = false; + + ShowMicrophonePrivacy(); + + return; + } + + if (_scalingStoryboard == null) + { + _scalingStoryboard = GetScalingStoryboard(VolumeEllipse); + } + + if (TimerPanel == null) + { + TimerPanel = CreateTimerPanel(); + InputGrid.Children.Insert(3, TimerPanel); + } + + if (SliderPanel == null) + { + SliderPanel = CreateSliderPanel(); + InputGrid.Children.Insert(3, SliderPanel); + } + + _skipBuffersCount = 0; + _fileId = TLLong.Random(); + _fileName = _fileId.Value + ".mp3"; + _isPartReady = true; + _uploadingLength = 0; + _uploadableParts.Clear(); + + _isSliding = true; + _stopRequested = false; + _cancelRequested = false; + + RaiseRecordStarted(); + + if (Duration != null) Duration.Text = "0:00,0"; + if (Slider != null) ((TranslateTransform)Slider.RenderTransform).X = 0.0; + Component.StartRecord(ApplicationData.Current.LocalFolder.Path + "\\" + _fileName); + + _stream = new MemoryStream(); + _startTime = DateTime.Now; + Vibrate(); + + Execute.BeginOnUIThread(TimeSpan.FromMilliseconds(25.0), () => + { + if (!_isSliding) + { + if (_stopRequested) + { + _stopRequested = false; + _cancelRequested = false; + + _isHintStoryboardPlaying = true; + HintStoryboard.Begin(); + return; + } + Log("_isSliding=false return"); + return; + } + + if (Slider != null) SliderPanel.Visibility = Visibility.Visible; + if (TimerPanel != null) TimerPanel.Visibility = Visibility.Visible; + + _asyncDispatcher.StartService(null); + _microphone.Start(); + _recordingStoryboard.Begin(); + + StartRecordingStoryboard(); + + _bufferReady = false; + + Execute.BeginOnUIThread(TimeSpan.FromSeconds(2.0), () => + { + if (!_bufferReady) + { + RecordButton.Opacity = 0.5; + RecordButton.IsHitTestVisible = false; + + ShowMicrophonePrivacy(); + + CancelRecording(); + + RaiseRecordCanceled(); + + _cancelRequested = false; + _microphone.Stop(); + _recordingStoryboard.Stop(); + _asyncDispatcher.StopService(); + Component.StopRecord(); + } + }); + }); + } + + private static void ShowMicrophonePrivacy() + { + try + { + var result = Guide.BeginShowMessageBox( + AppResources.MicrophoneAccessDenied, + AppResources.MicrophoneAccessDeniedDescription, + new [] { AppResources.Ok, AppResources.Settings }, + 0, + MessageBoxIcon.Alert, + null, + null); + + result.AsyncWaitHandle.WaitOne(); + + int? choice = Guide.EndShowMessageBox(result); + + if (choice == 1) + { + Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-microphone")); + } + } + catch (Exception ex) + { + TLUtils.WriteException(ex); + } + } + + private static void Vibrate() + { + if (Debugger.IsAttached) return; + + VibrateController.Default.Start(TimeSpan.FromMilliseconds(25)); + } + + private void RecordButton_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + Log("RecordButton_OnMouseLeftButtonUp"); + StopRecording(); + } + + private void LayoutRoot_OnManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + if (!_isSliding) return; + if (Slider == null) return; + + + var transform = (TranslateTransform) Slider.RenderTransform; + transform.X += e.DeltaManipulation.Translation.X; + + var scaleTransform = (ScaleTransform) CoverEllipse.RenderTransform; + var minScale = 2.5; + var scale = 5.0 + (5.0 - minScale) * transform.X / 75.0; + if (scale < minScale) scale = minScale; + if (scale > 5.0) scale = 5.0; + scaleTransform.ScaleX = scale; + scaleTransform.ScaleY = scale; + + if (transform.X > 0) + { + transform.X = 0; + } + if (transform.X < -150) + { + //SliderTransform.X = 0; + _isSliding = false; + + CancelRecordingStoryboard.Begin(); + } + } + + private void LayoutRoot_OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + if (e.OriginalSource == RecordButtonIcon) + { + if (!_isSliding) + { + SaveInputFocus(); + return; + } + + if (!_cancelRequested && Hint.Visibility == Visibility.Collapsed) + { + StopRecording(); + } + } + } + + private void OnTimerTick() + { + //if (_lastUpdateTime.HasValue && (DateTime.Now - _lastUpdateTime.Value).TotalMilliseconds < 50.0) return; + + _lastUpdateTime = DateTime.Now; + + if (Duration == null) return; + + var duration = DateTime.Now - _startTime; + Duration.Text = duration.ToString(duration.TotalHours >= 1.0 ? @"h\:mm\:ss\,f" : @"m\:ss\,f"); + } + + private bool _bufferReady; + + private void Microphone_OnBufferReady(object sender, System.EventArgs e) + { + _bufferReady = true; + //var duration = DateTime.Now - _startTime; + //System.Diagnostics.Debug.WriteLine("OnBufferReady {0}", duration.ToString(@"h\:mm\:ss\.fff")); + + const int skipStartBuffersCount = 3; + + if (Component == null) return; + + var dataLength = _microphone.GetData(_buffer); + if (_skipBuffersCount < skipStartBuffersCount) + { + _skipBuffersCount++; + return; + } + + var volume = GetCurrentVolume(); + var scale = 5.0 + volume / 100.0 * 10.0; + var prevScale = ((ScaleTransform)VolumeEllipse.RenderTransform).ScaleX; + if (prevScale < scale) + { + _scalingStoryboard.Stop(); + + _scalingXKeyFrame.Value = scale; + _scalingYKeyFrame.Value = scale; + + _scalingStoryboard.Begin(); + } + + //VolumeEllipseTransform.ScaleX = 5.0 + volume / 100.0 * 5.0; + //VolumeEllipseTransform.ScaleY = 5.0 + volume / 100.0 * 5.0; + + System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + " -volume : " + volume + " scale : " + scale + " prevScale : " + prevScale); + + const int frameLength = 1920; + var partsCount = dataLength / frameLength; + _stream.Write(_buffer, 0, _buffer.Length); + for (var i = 0; i < partsCount; i++) + { + var count = frameLength * (i + 1) > _buffer.Length ? _buffer.Length - frameLength * i : frameLength; + var result = Component.WriteFrame(_buffer.SubArray(frameLength * i, count), count); + } + + if (_stopRequested || _cancelRequested) + { + _microphone.Stop(); + _recordingStoryboard.Stop(); + _asyncDispatcher.StopService(); + Component.StopRecord(); + + if (UploadFileDuringRecording) + { + UploadAudioFileAsync(true); + } + + if (_stopRequested) + { + if ((DateTime.Now - _startTime).TotalMilliseconds < 1000.0) + { + _stopRequested = false; + _cancelRequested = false; + //Log("HintStoryboard_OnCompleted._stopRequested=false"); + + _isHintStoryboardPlaying = true; + HintStoryboard.Begin(); + return; + } + + RaiseAudioRecorded(_stream, (DateTime.Now - _startTime - TimeSpan.FromTicks(_microphone.BufferDuration.Ticks * skipStartBuffersCount)).TotalSeconds, _fileName, _fileId, _uploadableParts); + return; + } + + if (_cancelRequested) + { + RaiseRecordCanceled(); + return; + } + } + else + { + var now = DateTime.Now; + if (!_lastTypingTime.HasValue + || _lastTypingTime.Value.AddSeconds(1.0) < now) + { + _lastTypingTime = DateTime.Now; + RaiseRecordingAudio(); + } + + if (UploadFileDuringRecording) + { + UploadAudioFileAsync(false); + } + } + } + + private float GetCurrentVolume() + { + double rms = 0; + ushort byte1 = 0; + ushort byte2 = 0; + short value = 0; + float volume = 0; + rms = (short) (byte1 | (byte2 << 8)); + + for (int i = 0; i < _buffer.Length - 1; i += 2) + { + byte1 = _buffer[i]; + byte2 = _buffer[i + 1]; + value = (short) (byte1 | (byte2 << 8)); + rms += Math.Pow(value, 2); + } + rms /= (double) (_buffer.Length/2); + volume = (int) Math.Floor(Math.Sqrt(rms)); + if (volume > 10000) + { + volume = 10000; + } + else if (volume < 700) + { + volume = 0; + } + volume = (float) (volume/100); + return volume; + } + + private void UploadAudioFileAsync(bool isLastPart) + { + Execute.BeginOnThreadPool(() => + { + if (!_isPartReady) return; + + _isPartReady = false; + + var uploadablePart = GetUploadablePart(_fileName, _uploadingLength, _uploadableParts.Count, isLastPart); + if (uploadablePart == null) + { + _isPartReady = true; + return; + } + + _uploadableParts.Add(uploadablePart); + _uploadingLength += uploadablePart.Count; + + //Execute.BeginOnUIThread(() => VibrateController.Default.Start(TimeSpan.FromSeconds(0.02))); + + if (!isLastPart) + { + var mtProtoService = IoC.Get(); + mtProtoService.SaveFilePartAsync(_fileId, uploadablePart.FilePart, + TLString.FromBigEndianData(uploadablePart.Bytes), + result => + { + if (result.Value) + { + uploadablePart.Status = PartStatus.Processed; + } + }, + error => Execute.ShowDebugMessage("upload.saveFilePart error " + error)); + } + + _isPartReady = true; + }); + } + + private static UploadablePart GetUploadablePart(string fileName, long position, int partId, bool isLastPart = false) + { + var fullFilePath = ApplicationData.Current.LocalFolder.Path + "\\" + fileName; + var fi = new FileInfo(fullFilePath); + if (!fi.Exists) + { + return null; + } + + const int minPartLength = 1024; + const int maxPartLength = 16 * 1024; + + var recordingLength = fi.Length - position; + if (!isLastPart && recordingLength < minPartLength) + { + return null; + } + + var subpartsCount = (int)recordingLength / minPartLength; + var uploadingBufferSize = 0; + if (isLastPart) + { + if (recordingLength > 0) + { + uploadingBufferSize = Math.Min(maxPartLength, (int)recordingLength); + } + } + else + { + uploadingBufferSize = Math.Min(maxPartLength, subpartsCount * minPartLength); + } + if (uploadingBufferSize == 0) + { + return null; + } + + var uploadingBuffer = new byte[uploadingBufferSize]; + + try + { + using (var fileStream = File.Open(fullFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + fileStream.Position = position; + fileStream.Read(uploadingBuffer, 0, uploadingBufferSize); + } + } + catch (Exception ex) + { + Execute.ShowDebugMessage("read file " + fullFilePath + " exception " + ex); + return null; + } + + return new UploadablePart(null, new TLInt(partId), uploadingBuffer, position, uploadingBufferSize); + } + + private void HintStoryboard_OnCompleted(object sender, System.EventArgs e) + { + _isHintStoryboardPlaying = false; + + RaiseRecordCanceled(); + } + + private void CancelRecordingStoryboard_OnCompleted(object sender, System.EventArgs e) + { + CancelRecording(); + } + + private Storyboard _scalingStoryboard; + private EasingDoubleKeyFrame _scalingXKeyFrame; + private EasingDoubleKeyFrame _scalingYKeyFrame; + + private Storyboard GetScalingStoryboard(UIElement element) + { + var storyboard = new Storyboard(); + + var scalingXAnimation = new DoubleAnimationUsingKeyFrames(); + _scalingXKeyFrame = new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 5.0 }; + scalingXAnimation.KeyFrames.Add(_scalingXKeyFrame); + scalingXAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.5), Value = 5.0 }); + Storyboard.SetTarget(scalingXAnimation, element); + Storyboard.SetTargetProperty(scalingXAnimation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleX)")); + storyboard.Children.Add(scalingXAnimation); + + var scalingYAnimation = new DoubleAnimationUsingKeyFrames(); + _scalingYKeyFrame = new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 5.0 }; + scalingYAnimation.KeyFrames.Add(_scalingYKeyFrame); + scalingYAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.5), Value = 5.0 }); + Storyboard.SetTarget(scalingYAnimation, element); + Storyboard.SetTargetProperty(scalingYAnimation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleY)")); + storyboard.Children.Add(scalingYAnimation); + + return storyboard; + } + + private Storyboard _recordingStoryboard; + + private IDisposable _keyPressSubscription; + + private Storyboard GetRecordingStoryboard(UIElement element) + { + var storyboard = new Storyboard(); + + var opacityAnimation = new DoubleAnimationUsingKeyFrames { RepeatBehavior = RepeatBehavior.Forever }; + opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 1.0 }); + opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(1.0), Value = 0.0 }); + Storyboard.SetTarget(opacityAnimation, element); + Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("Opacity")); + storyboard.Children.Add(opacityAnimation); + + return storyboard; + } + + private void StartRecordingStoryboard() + { + var storyboard = new Storyboard(); + + var recordEllipseAnimation = new DoubleAnimationUsingKeyFrames(); + recordEllipseAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 2.5 }); + recordEllipseAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 5.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 5.0 } }); + Storyboard.SetTarget(recordEllipseAnimation, CoverEllipse); + Storyboard.SetTargetProperty(recordEllipseAnimation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleX)")); + storyboard.Children.Add(recordEllipseAnimation); + + var recordEllipseAnimation2 = new DoubleAnimationUsingKeyFrames(); + recordEllipseAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 2.5 }); + recordEllipseAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 5.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 5.0 } }); + Storyboard.SetTarget(recordEllipseAnimation2, CoverEllipse); + Storyboard.SetTargetProperty(recordEllipseAnimation2, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleY)")); + storyboard.Children.Add(recordEllipseAnimation2); + + var volumeEllipseAnimation = new DoubleAnimationUsingKeyFrames(); + volumeEllipseAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 2.5 }); + volumeEllipseAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 5.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 5.0 } }); + Storyboard.SetTarget(volumeEllipseAnimation, VolumeEllipse); + Storyboard.SetTargetProperty(volumeEllipseAnimation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleX)")); + storyboard.Children.Add(volumeEllipseAnimation); + + var volumeEllipseAnimation2 = new DoubleAnimationUsingKeyFrames(); + volumeEllipseAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 2.5 }); + volumeEllipseAnimation2.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 5.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 5.0 } }); + Storyboard.SetTarget(volumeEllipseAnimation2, VolumeEllipse); + Storyboard.SetTargetProperty(volumeEllipseAnimation2, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleY)")); + storyboard.Children.Add(volumeEllipseAnimation2); + + var timerAnimation = new DoubleAnimationUsingKeyFrames(); + timerAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = -100.0 }); + timerAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase{ EasingMode = EasingMode.EaseOut, Exponent = 5.0 }}); + Storyboard.SetTarget(timerAnimation, TimerPanel); + Storyboard.SetTargetProperty(timerAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)")); + storyboard.Children.Add(timerAnimation); + + var sliderTextAnimation = new DoubleAnimationUsingKeyFrames(); + sliderTextAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.05), Value = 100.0 }); + sliderTextAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.30), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 5.0 } }); + Storyboard.SetTarget(sliderTextAnimation, _sliderTextTransform); + Storyboard.SetTargetProperty(sliderTextAnimation, new PropertyPath("X")); + storyboard.Children.Add(sliderTextAnimation); + + var sliderPathAnimation = new DoubleAnimationUsingKeyFrames(); + sliderPathAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = 100.0 }); + sliderPathAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 5.0 } }); + Storyboard.SetTarget(sliderPathAnimation, _sliderPathTransform); + Storyboard.SetTargetProperty(sliderPathAnimation, new PropertyPath("TranslateX")); + storyboard.Children.Add(sliderPathAnimation); + + storyboard.Begin(); + } + + private void CancelRecording() + { + if (Slider != null) SliderPanel.Visibility = Visibility.Collapsed; + if (TimerPanel != null) TimerPanel.Visibility = Visibility.Collapsed; + + if (!_stopRequested) + { + _cancelRequested = true; + } + _isSliding = false; + _lastTypingTime = null; + } + + private void StopRecording() + { + Vibrate(); + + if (Slider != null) SliderPanel.Visibility = Visibility.Collapsed; + if (TimerPanel != null) TimerPanel.Visibility = Visibility.Collapsed; + _stopRequested = true; + _isSliding = false; + _lastTypingTime = null; + } + + public event EventHandler AudioRecorded; + + protected virtual void RaiseAudioRecorded(MemoryStream stream, double duration, string fileName, TLLong fileId, IList parts) + { + SetInputVisibility(Visibility.Visible); + + var stringBuilder = new StringBuilder(); + stringBuilder.AppendLine("parts"); + foreach (var part in parts) + { + stringBuilder.AppendLine(string.Format("file_part={0} position={1} count={2} status={3}", part.FilePart, part.Position, part.Count, part.Status)); + } + + Telegram.Logs.Log.Write(string.Format("AudioRecorderControl.AudioRecorded duration={0} file_name={1}\n{2}", duration, fileName, stringBuilder)); + + var handler = AudioRecorded; + if (handler != null) handler(this, new AudioEventArgs(stream, duration, fileName, fileId, parts)); + } + + public event EventHandler RecordCanceled; + + protected virtual void RaiseRecordCanceled() + { + SetInputVisibility(Visibility.Visible); + + Telegram.Logs.Log.Write("AudioRecorderControl.AudioRecordCanceled"); + + var handler = RecordCanceled; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler RecordStarted; + + protected virtual void RaiseRecordStarted() + { + SetInputVisibility(Visibility.Collapsed); + Telegram.Logs.Log.Write("AudioRecorderControl.AudioRecordStarted"); + + var handler = RecordStarted; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler RecordingAudio; + + protected virtual void RaiseRecordingAudio() + { + var handler = RecordingAudio; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private void SetInputVisibility(Visibility visibility) + { + System.Diagnostics.Debug.WriteLine("SetInputVisibility " + visibility); + //Scroll.IsHitTestVisible = visibility == Visibility.Visible; + //EmojiButton.IsHitTestVisible = visibility == Visibility.Visible; + //AdditionalButtons.IsHitTestVisible = visibility == Visibility.Visible; + EmojiButton.Visibility = visibility; + Scroll.Visibility = visibility; + AdditionalButtons.Visibility = visibility; + if (visibility == Visibility.Collapsed) + { + RecordButtonIcon.Background = new SolidColorBrush(Colors.White); + VolumeEllipse.Visibility = Visibility.Visible; + ((ScaleTransform) VolumeEllipse.RenderTransform).ScaleX = 2.5; + ((ScaleTransform) VolumeEllipse.RenderTransform).ScaleY = 2.5; + CoverEllipse.Visibility = Visibility.Visible; + ((ScaleTransform) CoverEllipse.RenderTransform).ScaleX = 2.5; + ((ScaleTransform) CoverEllipse.RenderTransform).ScaleY = 2.5; + } + else + { + RecordButtonIcon.Background = (Brush) Resources["InputForegroundBrushLight"]; + VolumeEllipse.Visibility = Visibility.Collapsed; + CoverEllipse.Visibility = Visibility.Collapsed; + } + SaveInputFocus(); + } + #endregion + + private void EmojiButton_OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + e.Handled = true; + } + + public bool IsFullScreen { get; protected set; } + + public void OpenFullScreen(double addHeight) + { + if (IsFullScreen) return; + + addHeight = addHeight > 7.0 ? addHeight : 0.0; + + Margin = new Thickness(0.0, -7.0, 0.0, 0.0); + KeyboardPlaceholder.Height = KeyboardPlaceholder.Height + addHeight; + IsFullScreen = true; + + var emojiControl = KeyboardPlaceholder.Content as EmojiControl; + if (emojiControl != null) + { + emojiControl.OpenSearch(); + } + } + + public void CloseFullScreen() + { + Margin = new Thickness(0.0, 0.0, 0.0, 0.0); + KeyboardPlaceholder.Height = KeyboardHeight; + IsFullScreen = false; + + var emojiControl = KeyboardPlaceholder.Content as EmojiControl; + if (emojiControl != null) + { + emojiControl.CloseSearch(); + } + } + } + + public class EmojiHintsEventArgs + { + public EmojiSuggestionParams Parameters { get; protected set; } + + public EmojiHintsEventArgs(EmojiSuggestionParams parameters) + { + Parameters = parameters; + } + } + + public class EmojiSuggestionParams + { + public int Index { get; set; } + + public int Length { get; set; } + + public int SelectionStart { get; set; } + + public string Text { get; set; } + + public string Query { get; set; } + + public EmojiSuggestion[] Results { get; set; } + + public override string ToString() + { + return string.Format("text={0} selectionStart={1} query={2} results={3}", Text, SelectionStart, Query, Results != null ? Results.Length : 0); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/LabeledPasswordBox.xaml b/TelegramClient.WP81/Views/Controls/LabeledPasswordBox.xaml new file mode 100755 index 0000000..53ee613 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/LabeledPasswordBox.xaml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/LabeledPasswordBox.xaml.cs b/TelegramClient.WP81/Views/Controls/LabeledPasswordBox.xaml.cs new file mode 100755 index 0000000..c3968da --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/LabeledPasswordBox.xaml.cs @@ -0,0 +1,93 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Controls; + +namespace TelegramClient.Views.Controls +{ + public partial class LabeledPasswordBox + { + public static readonly DependencyProperty LabelProperty = DependencyProperty.Register( + "Label", typeof (string), typeof (LabeledPasswordBox), new PropertyMetadata(default(string), OnLabelChanged)); + + private static void OnLabelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var labeledTextBox = d as LabeledPasswordBox; + if (labeledTextBox != null) + { + labeledTextBox.TextBlock.Text = (string) e.NewValue; + } + } + + public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register( + "Password", typeof (string), typeof (LabeledPasswordBox), new PropertyMetadata(default(string), OnTextChanged)); + + private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var labeledTextBox = d as LabeledPasswordBox; + if (labeledTextBox != null) + { + labeledTextBox.TextBox.Password = (string)e.NewValue; + labeledTextBox.TextBlock.Visibility = string.IsNullOrEmpty((string) e.NewValue) + ? Visibility.Visible + : Visibility.Collapsed; + } + } + + public string Password + { + get { return (string) GetValue(PasswordProperty); } + set { SetValue(PasswordProperty, value); } + } + + public string Label + { + get { return (string) GetValue(LabelProperty); } + set { SetValue(LabelProperty, value); } + } + + public int MaxLength + { + get { return TextBox.MaxLength; } + set { TextBox.MaxLength = value; } + } + + public PasswordBox Input { get { return TextBox; } } + + public LabeledPasswordBox() + { + InitializeComponent(); + + TextBox.LostFocus += (sender, args) => + { + Password = Input.Password; + }; + + GotFocus += (o, e) => + { + TextBox.Focus(); + if (!string.IsNullOrEmpty(TextBox.Password)) + { + TextBox.SelectAll(); + } + }; + } + + private void TextBox_OnGotFocus(object sender, RoutedEventArgs e) + { + TextBlock.Visibility = Visibility.Collapsed; + } + + private void TextBox_OnLostFocus(object sender, RoutedEventArgs e) + { + TextBlock.Visibility = string.IsNullOrEmpty(TextBox.Password) + ? Visibility.Visible + : Visibility.Collapsed; + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/LabeledTextBox.xaml b/TelegramClient.WP81/Views/Controls/LabeledTextBox.xaml new file mode 100755 index 0000000..995cd0b --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/LabeledTextBox.xaml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/LabeledTextBox.xaml.cs b/TelegramClient.WP81/Views/Controls/LabeledTextBox.xaml.cs new file mode 100755 index 0000000..42abb1d --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/LabeledTextBox.xaml.cs @@ -0,0 +1,163 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; + +namespace TelegramClient.Views.Controls +{ + public partial class LabeledTextBox + { + public static readonly DependencyProperty ErrorProperty = DependencyProperty.Register( + "Error", typeof(string), typeof(LabeledTextBox), new PropertyMetadata(default(string), OnErrorChanged)); + + private static void OnErrorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var labeledTextBox = d as LabeledTextBox; + if (labeledTextBox != null) + { + labeledTextBox.ErrorTextBlock.Text = (string)e.NewValue; + labeledTextBox.ErrorTextBlock.Visibility = string.IsNullOrEmpty(labeledTextBox.ErrorTextBlock.Text) + ? Visibility.Collapsed + : Visibility.Visible; + } + } + + public string Error + { + get { return (string) GetValue(ErrorProperty); } + set { SetValue(ErrorProperty, value); } + } + + public static readonly DependencyProperty LabelProperty = DependencyProperty.Register( + "Label", typeof (string), typeof (LabeledTextBox), new PropertyMetadata(default(string), OnLabelChanged)); + + private static void OnLabelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var labeledTextBox = d as LabeledTextBox; + if (labeledTextBox != null) + { + labeledTextBox.TextBlock.Text = (string) e.NewValue; + } + } + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register( + "Text", typeof (string), typeof (LabeledTextBox), new PropertyMetadata(default(string), OnTextChanged)); + + private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var labeledTextBox = d as LabeledTextBox; + if (labeledTextBox != null) + { + labeledTextBox.TextBox.Text = (string)e.NewValue; + labeledTextBox.TextBlock.Visibility = string.IsNullOrEmpty((string) e.NewValue) + ? Visibility.Visible + : Visibility.Collapsed; + } + } + + public string Text + { + get { return (string) GetValue(TextProperty); } + set { SetValue(TextProperty, value); } + } + + public string Label + { + get { return (string) GetValue(LabelProperty); } + set { SetValue(LabelProperty, value); } + } + + public InputScope InputScope + { + get { return TextBox.InputScope; } + set { TextBox.InputScope = value; } + } + + public int MaxLength + { + get { return TextBox.MaxLength; } + set { TextBox.MaxLength = value; } + } + + public int SelectionStart + { + get { return TextBox.SelectionStart; } + set { TextBox.SelectionStart = value; } + } + + public TextWrapping TextWrapping + { + get { return TextBox.TextWrapping; } + set { TextBox.TextWrapping = value; } + } + + public bool AcceptReturn + { + get { return TextBox.AcceptsReturn; } + set { TextBox.AcceptsReturn = value; } + } + + public TextBox Input { get { return TextBox; } } + + public LabeledTextBox() + { + InitializeComponent(); + + GotFocus += (o, e) => + { + TextBox.Focus(); + if (!string.IsNullOrEmpty(TextBox.Text)) + { + TextBox.SelectionStart = TextBox.Text.Length; + } + }; + } + + public void SetTextBox(TextBox textBox) + { + var inputScope = TextBox.InputScope; + var maxLength = TextBox.MaxLength; + LayoutRoot.Children.Remove(TextBox); + TextBox.GotFocus -= TextBox_OnGotFocus; + TextBox.LostFocus -= TextBox_OnLostFocus; + TextBox = textBox; + LayoutRoot.Children.Insert(0, textBox); + textBox.GotFocus += TextBox_OnGotFocus; + textBox.LostFocus += TextBox_OnLostFocus; + textBox.Style = (Style) Resources["TextBoxStyle1"]; + textBox.InputScope = inputScope; + textBox.MaxLength = maxLength; + } + + private void TextBox_OnGotFocus(object sender, RoutedEventArgs e) + { + TextBlock.Visibility = string.IsNullOrEmpty(TextBox.Text) + ? Visibility.Visible + : Visibility.Collapsed; + TextBlock.Foreground = (Brush)Application.Current.Resources["PhoneTextBoxForegroundBrush"]; + } + + private void TextBox_OnLostFocus(object sender, RoutedEventArgs e) + { + Text = TextBox.Text; + TextBlock.Visibility = string.IsNullOrEmpty(TextBox.Text) + ? Visibility.Visible + : Visibility.Collapsed; + TextBlock.Foreground = (Brush) Application.Current.Resources["PhoneForegroundBrush"]; + } + + private void TextBox_OnTextChanged(object sender, TextChangedEventArgs e) + { + TextBlock.Visibility = string.IsNullOrEmpty(TextBox.Text) + ? Visibility.Visible + : Visibility.Collapsed; + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/LiveLocationIcon.xaml b/TelegramClient.WP81/Views/Controls/LiveLocationIcon.xaml new file mode 100755 index 0000000..17d48f0 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/LiveLocationIcon.xaml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/LiveLocationIcon.xaml.cs b/TelegramClient.WP81/Views/Controls/LiveLocationIcon.xaml.cs new file mode 100755 index 0000000..894137f --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/LiveLocationIcon.xaml.cs @@ -0,0 +1,29 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace TelegramClient.Views.Controls +{ + public partial class LiveLocationIcon + { + public LiveLocationIcon() + { + InitializeComponent(); + + Loaded += (sender, args) => + { + Storyboard1.Begin(); + Storyboard2.Begin(); + }; + + Unloaded += (sender, args) => + { + Storyboard1.Stop(); + Storyboard2.Stop(); + }; + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/LiveLocationProgress.xaml b/TelegramClient.WP81/Views/Controls/LiveLocationProgress.xaml new file mode 100755 index 0000000..ff6dc72 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/LiveLocationProgress.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/LiveLocationProgress.xaml.cs b/TelegramClient.WP81/Views/Controls/LiveLocationProgress.xaml.cs new file mode 100755 index 0000000..42eb5a7 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/LiveLocationProgress.xaml.cs @@ -0,0 +1,211 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Threading; +using System.Windows; +using System.Windows.Media.Animation; +using Caliburn.Micro; +using Telegram.Api.Services; +using Telegram.Api.TL; +using TelegramClient.Resources; + +namespace TelegramClient.Views.Controls +{ + public partial class LiveLocationProgress + { + public static List Controls = new List(); + + public static readonly DependencyProperty MediaProperty = DependencyProperty.Register( + "Media", typeof(TLMessageMediaBase), typeof(LiveLocationProgress), new PropertyMetadata(default(TLMessageMediaBase), OnMediaChanged)); + + private static void OnMediaChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var progress = d as LiveLocationProgress; + if (progress != null) + { + var mediaGeoLive = e.NewValue as TLMessageMediaGeoLive; + if (mediaGeoLive != null) + { + progress.UpdateAnimation(mediaGeoLive); + } + } + } + + public void Update() + { + UpdateAnimation(Media as TLMessageMediaGeoLive); + } + + private void UpdateAnimation(TLMessageMediaGeoLive mediaGeoLive) + { + if (mediaGeoLive == null || mediaGeoLive.Date == null) + { + Label.Text = "0"; + Progress.Angle = 0.0; + if (_storyboard.GetCurrentState() == ClockState.Active) + { + _storyboard.SkipToFill(); // will invoke storyboard.Completed + } + return; + } + + var date = TLUtils.DateToUniversalTimeTLInt(IoC.Get().ClientTicksDelta, DateTime.Now); + + var lastPartSeconds = (double)mediaGeoLive.Date.Value + mediaGeoLive.Period.Value - date.Value; + if (lastPartSeconds <= 0) + { + Label.Text = "0"; + Progress.Angle = 0.0; + if (_storyboard.GetCurrentState() == ClockState.Active) + { + _storyboard.SkipToFill(); // will invoke storyboard.Completed + } + return; + } + if (lastPartSeconds > mediaGeoLive.Period.Value) + { + lastPartSeconds = mediaGeoLive.Period.Value - 1.0; + } + + Label.Text = GetLabelText(lastPartSeconds); + + var percent = lastPartSeconds / mediaGeoLive.Period.Value; + var angle = 359.0 * percent; + + _progressAnimation.From = angle; + _progressAnimation.Duration = TimeSpan.FromSeconds(lastPartSeconds); + + Progress.Angle = angle; + _storyboard.Begin(); + + SetNextTimer(lastPartSeconds); + } + + private string GetLabelText(double lastPartTotalSeconds) + { + if (lastPartTotalSeconds < 0) + { + return "0"; + } + if (lastPartTotalSeconds < 60) + { + return Math.Ceiling(lastPartTotalSeconds).ToString(); + } + if (lastPartTotalSeconds < 60 * 60) + { + return Math.Ceiling(lastPartTotalSeconds / 60).ToString(); + } + + return string.Format("{0}{1}", Math.Ceiling(lastPartTotalSeconds / 60 / 60), AppResources.HourShort.ToLowerInvariant()); + } + + public TLMessageMediaBase Media + { + get { return (TLMessageMediaBase) GetValue(MediaProperty); } + set { SetValue(MediaProperty, value); } + } + + public event EventHandler Completed; + + protected virtual void RaiseCompleted() + { + var handler = Completed; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private readonly Storyboard _storyboard; + + private readonly DoubleAnimation _progressAnimation; + + private readonly Timer _timer; + + public LiveLocationProgress() + { + InitializeComponent(); + + _timer = new Timer(Timer_OnTick); + + _storyboard = new Storyboard(); + _storyboard.Completed += (sender, args) => + { + RaiseCompleted(); + }; + _progressAnimation = new DoubleAnimation{ To = 0.0 }; + Storyboard.SetTarget(_progressAnimation, Progress); + Storyboard.SetTargetProperty(_progressAnimation, new PropertyPath(ProgressPieSlice.AngleProperty)); + _storyboard.Children.Add(_progressAnimation); + + Loaded += (sender, args) => + { + Controls.Add(this); + + UpdateAnimation(Media as TLMessageMediaGeoLive); + }; + Unloaded += (sender, args) => + { + Controls.Remove(this); + + _storyboard.Stop(); + _timer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); + }; + } + + private void Timer_OnTick(object state) + { + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + var mediaGeoLive = Media as TLMessageMediaGeoLive; + if (mediaGeoLive == null || mediaGeoLive.Date == null) + { + Label.Text = "0"; + Progress.Angle = 0.0; + + return; + } + + var date = TLUtils.DateToUniversalTimeTLInt(IoC.Get().ClientTicksDelta, DateTime.Now); + + var lastPartSeconds = (double)mediaGeoLive.Date.Value + mediaGeoLive.Period.Value - date.Value; + if (lastPartSeconds <= 0) + { + Label.Text = "0"; + Progress.Angle = 0.0; + + return; + } + + Label.Text = GetLabelText(lastPartSeconds); + + SetNextTimer(lastPartSeconds); + }); + } + + private void SetNextTimer(double lastPartSeconds) + { + if (lastPartSeconds < 60) + { + _timer.Change(TimeSpan.FromSeconds(0.5), Timeout.InfiniteTimeSpan); + return; + } + if (lastPartSeconds < 60 * 2) + { + _timer.Change(TimeSpan.FromSeconds(lastPartSeconds - 60.0), Timeout.InfiniteTimeSpan); + return; + } + + if (lastPartSeconds <= 60 * 60) + { + _timer.Change(TimeSpan.FromSeconds(lastPartSeconds - (int)(lastPartSeconds / 60.0) * 60.0), Timeout.InfiniteTimeSpan); + return; + } + + _timer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/LiveLocationsControl.xaml b/TelegramClient.WP81/Views/Controls/LiveLocationsControl.xaml new file mode 100755 index 0000000..e1a39aa --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/LiveLocationsControl.xaml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/LiveLocationsControl.xaml.cs b/TelegramClient.WP81/Views/Controls/LiveLocationsControl.xaml.cs new file mode 100755 index 0000000..0380b76 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/LiveLocationsControl.xaml.cs @@ -0,0 +1,43 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows.Input; +using Telegram.Api.TL; + +namespace TelegramClient.Views.Controls +{ + public partial class LiveLocationsControl + { + public LiveLocationsControl() + { + InitializeComponent(); + } + + public event EventHandler LiveLocationCompleted; + + private void LiveLocationProgress_OnCompleted(object sender, System.EventArgs e) + { + var progress = sender as LiveLocationProgress; + if (progress != null) + { + RaiseCompleted(new MediaEventArgs{ Media = progress.Media }); + } + } + + protected virtual void RaiseCompleted(MediaEventArgs e) + { + var handler = LiveLocationCompleted; + if (handler != null) handler(this, e); + } + } + + public class MediaEventArgs : System.EventArgs + { + public TLMessageMediaBase Media { get; set; } + } +} diff --git a/TelegramClient.WP81/Views/Controls/MediaPhotoControl.xaml b/TelegramClient.WP81/Views/Controls/MediaPhotoControl.xaml new file mode 100755 index 0000000..256a294 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/MediaPhotoControl.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/MediaPhotoControl.xaml.cs b/TelegramClient.WP81/Views/Controls/MediaPhotoControl.xaml.cs new file mode 100755 index 0000000..d7868ab --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/MediaPhotoControl.xaml.cs @@ -0,0 +1,302 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using Telegram.Api.TL; + +namespace TelegramClient.Views.Controls +{ + public partial class MediaPhotoControl : IMediaControl + { + public static readonly DependencyProperty TTLParamsProperty = DependencyProperty.Register( + "TTLParams", typeof(TTLParams), typeof(MediaPhotoControl), new PropertyMetadata(default(TTLParams), OnTTLParamsChanged)); + + private static void OnTTLParamsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaPhotoControl; + if (control != null) + { + if (control._secretPhotoPlaceholder != null) + { + control._secretPhotoPlaceholder.TTLParams = e.NewValue as TTLParams; + } + } + } + + public TTLParams TTLParams + { + get { return (TTLParams) GetValue(TTLParamsProperty); } + set { SetValue(TTLParamsProperty, value); } + } + + public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register( + "IsSelected", typeof(bool), typeof(MediaPhotoControl), new PropertyMetadata(default(bool), OnIsSelectedChanged)); + + private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaPhotoControl; + if (control != null) + { + control.SelectionBorder.Visibility = (bool) e.NewValue ? Visibility.Visible : Visibility.Collapsed; + } + } + + public bool IsSelected + { + get { return (bool) GetValue(IsSelectedProperty); } + set { SetValue(IsSelectedProperty, value); } + } + + public static readonly DependencyProperty ProgressScaleProperty = DependencyProperty.Register( + "ProgressScale", typeof(double), typeof(MediaPhotoControl), new PropertyMetadata(default(double), OnProgressScaleChanged)); + + private static void OnProgressScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaPhotoControl; + if (control != null) + { + control.Progress.RenderTransform = new ScaleTransform { ScaleX = (double)e.NewValue, ScaleY = (double)e.NewValue }; + control.DownloadIcon.RenderTransform = new ScaleTransform { ScaleX = (double)e.NewValue, ScaleY = (double)e.NewValue }; + if (control._secretPhotoPlaceholder != null) + { + control._secretPhotoPlaceholder.RenderTransform = new ScaleTransform { ScaleX = (double)e.NewValue, ScaleY = (double)e.NewValue }; + } + } + } + + public double ProgressScale + { + get { return (double) GetValue(ProgressScaleProperty); } + set { SetValue(ProgressScaleProperty, value); } + } + + public static readonly DependencyProperty MediaProperty = DependencyProperty.Register( + "Media", typeof(TLObject), typeof(MediaPhotoControl), new PropertyMetadata(default(TLObject), OnMediaChanged)); + + private static void OnMediaChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaPhotoControl; + if (control != null) + { + //System.Diagnostics.Debug.WriteLine(" Change Media old={0} new={1}", e.OldValue != null ? e.OldValue.GetHashCode() : 0, e.NewValue != null ? e.NewValue.GetHashCode() : 0); + + var isDownloading = control.DownloadingProgress > 0.0 && control.DownloadingProgress < 1.0; + var isUploading = control.UploadingProgress > 0.0 && control.UploadingProgress < 1.0; + + control.SetDownloadIconVisibility(isDownloading || isUploading, control.Photo.Source); + var mediaPhoto = e.NewValue as TLMessageMediaPhoto70; + if (mediaPhoto != null) + { + if (mediaPhoto.TTLSeconds != null) + { + control.GoToSecretMediaState(); + } + else + { + control.GoToNormalMediaState(); + } + } + + var decryptedMedia = e.NewValue as TLDecryptedMessageMediaBase; + if (decryptedMedia != null) + { + if (decryptedMedia.TTLSeconds != null && decryptedMedia.TTLSeconds.Value > 0) + { + control.GoToSecretMediaState(); + } + else + { + control.GoToNormalMediaState(); + } + } + } + } + + private void GoToNormalMediaState() + { + Root.Children.Remove(DownloadIcon); + Root.Children.Remove(Progress); + if (_secretPhotoPlaceholder != null) Root.Children.Remove(_secretPhotoPlaceholder); + + Root.Children.Insert(1, Progress); + Root.Children.Insert(1, DownloadIcon); + } + + private SecretPhotoPlaceholder _secretPhotoPlaceholder; + + private void GoToSecretMediaState() + { + Root.Children.Remove(DownloadIcon); + Root.Children.Remove(Progress); + if (_secretPhotoPlaceholder != null) Root.Children.Remove(_secretPhotoPlaceholder); + + _secretPhotoPlaceholder = _secretPhotoPlaceholder ?? new SecretPhotoPlaceholder + { + IsHitTestVisible = false, + ShowHint = false, + TTLParams = TTLParams, + RenderTransformOrigin = new Point(0.5, 0.5), + RenderTransform = new ScaleTransform { ScaleX = ProgressScale, ScaleY = ProgressScale }, + Margin = new Thickness(-12.0), + VerticalAlignment = VerticalAlignment.Center, + HorizontalAlignment = HorizontalAlignment.Center + }; + + Root.Children.Insert(1, _secretPhotoPlaceholder); + } + + public TLObject Media + { + get { return (TLObject)GetValue(MediaProperty); } + set { SetValue(MediaProperty, value); } + } + + public static readonly DependencyProperty PreviewSourceProperty = DependencyProperty.Register( + "PreviewSource", typeof(ImageSource), typeof(MediaPhotoControl), new PropertyMetadata(default(ImageSource), OnPreviewSourceChanged)); + + private static void OnPreviewSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaPhotoControl; + if (control != null) + { + //System.Diagnostics.Debug.WriteLine(" Change PreviewSource control={0}", control.DataContext != null ? control.DataContext.GetHashCode() : 0); + if (control.Source == null) // large image not loaded + { + control.Photo.Source = e.NewValue as ImageSource; + } + } + } + + public ImageSource PreviewSource + { + get { return (ImageSource) GetValue(PreviewSourceProperty); } + set { SetValue(PreviewSourceProperty, value); } + } + + public static readonly DependencyProperty SourceProperty = DependencyProperty.Register( + "Source", typeof(ImageSource), typeof(MediaPhotoControl), new PropertyMetadata(default(ImageSource), OnImageSourceChanged)); + + private static void OnImageSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaPhotoControl; + if (control != null) + { + //System.Diagnostics.Debug.WriteLine(" Change Source control={0}", control.DataContext != null ? control.DataContext.GetHashCode() : 0); + var source = e.NewValue as ImageSource; + + control.Photo.Source = source; + + var isDownloading = control.DownloadingProgress > 0.0 && control.DownloadingProgress < 1.0; + var isUploading = control.UploadingProgress > 0.0 && control.UploadingProgress < 1.0; + + control.SetDownloadIconVisibility(isDownloading || isUploading, source); + } + } + + private void SetDownloadIconVisibility(bool inProgress, ImageSource source) + { + if (!inProgress) + { + DownloadIcon.Visibility = source == null || Photo.Source != source + ? Visibility.Visible + : Visibility.Collapsed; + } + else + { + DownloadIcon.Visibility = Visibility.Collapsed; + } + } + + public ImageSource Source + { + get { return (ImageSource) GetValue(SourceProperty); } + set { SetValue(SourceProperty, value); } + } + + public static readonly DependencyProperty DownloadingProgressProperty = DependencyProperty.Register( + "DownloadingProgress", typeof(double), typeof(MediaPhotoControl), new PropertyMetadata(default(double), OnProgressChanged)); + + public double DownloadingProgress + { + get { return (double) GetValue(DownloadingProgressProperty); } + set { SetValue(DownloadingProgressProperty, value); } + } + + public static readonly DependencyProperty UploadingProgressProperty = DependencyProperty.Register( + "UploadingProgress", typeof(double), typeof(MediaPhotoControl), new PropertyMetadata(default(double), OnProgressChanged)); + + public double UploadingProgress + { + get { return (double) GetValue(UploadingProgressProperty); } + set { SetValue(UploadingProgressProperty, value); } + } + + private static void OnProgressChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaPhotoControl; + if (control != null) + { + var progress = (double)e.NewValue; + var source = control.Source; + + //System.Diagnostics.Debug.WriteLine("newValue=" + newValue); + control.Progress.Value = progress; + if (control._secretPhotoPlaceholder != null) + { + control._secretPhotoPlaceholder.DownloadingProgress = progress; + } + + var inProgress = progress > 0.0 && progress < 1.0; + + control.SetDownloadIconVisibility(inProgress, source); + } + } + + public MediaPhotoControl() + { + InitializeComponent(); + } + + public event EventHandler CancelDownloading; + + protected virtual void RaiseCancelDownloading() + { + var handler = CancelDownloading; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler CancelUploading; + + protected virtual void RaiseCancelUploading() + { + var handler = CancelUploading; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private void LayoutRoot_OnTap(object sender, GestureEventArgs e) + { + if (DownloadingProgress > 0.0 && DownloadingProgress < 1.0) + { + e.Handled = true; + RaiseCancelDownloading(); + } + else if (UploadingProgress > 0.0 && UploadingProgress < 1.0) + { + e.Handled = true; + RaiseCancelUploading(); + } + } + } + + public interface IMediaControl + { + TLObject Media { get; set; } + } +} diff --git a/TelegramClient.WP81/Views/Controls/MediaVideoControl.xaml b/TelegramClient.WP81/Views/Controls/MediaVideoControl.xaml new file mode 100755 index 0000000..acf8347 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/MediaVideoControl.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/MediaVideoControl.xaml.cs b/TelegramClient.WP81/Views/Controls/MediaVideoControl.xaml.cs new file mode 100755 index 0000000..01f33db --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/MediaVideoControl.xaml.cs @@ -0,0 +1,271 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Media; +using Telegram.Api.TL; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Controls +{ + public partial class MediaVideoControl : IMediaControl + { + public static readonly DependencyProperty TTLParamsProperty = DependencyProperty.Register( + "TTLParams", typeof(TTLParams), typeof(MediaVideoControl), new PropertyMetadata(default(TTLParams), OnTTLParamsChanged)); + + private static void OnTTLParamsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaVideoControl; + if (control != null) + { + if (control._secretPhotoPlaceholder != null) + { + control._secretPhotoPlaceholder.TTLParams = e.NewValue as TTLParams; + } + } + } + + public TTLParams TTLParams + { + get { return (TTLParams)GetValue(TTLParamsProperty); } + set { SetValue(TTLParamsProperty, value); } + } + + public static readonly DependencyProperty StretchProperty = DependencyProperty.Register( + "Stretch", typeof(Stretch), typeof(MediaVideoControl), new PropertyMetadata(default(Stretch), OnStretchChanged)); + + private static void OnStretchChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaVideoControl; + if (control != null) + { + control.Video.Stretch = (Stretch) e.NewValue; + } + } + + public Stretch Stretch + { + get { return (Stretch) GetValue(StretchProperty); } + set { SetValue(StretchProperty, value); } + } + + public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register( + "IsSelected", typeof(bool), typeof(MediaVideoControl), new PropertyMetadata(default(bool), OnIsSelectedChanged)); + + private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaVideoControl; + if (control != null) + { + control.SelectionBorder.Visibility = (bool)e.NewValue ? Visibility.Visible : Visibility.Collapsed; + } + } + + public bool IsSelected + { + get { return (bool)GetValue(IsSelectedProperty); } + set { SetValue(IsSelectedProperty, value); } + } + + public static readonly DependencyProperty ProgressScaleProperty = DependencyProperty.Register( + "ProgressScale", typeof(double), typeof(MediaVideoControl), new PropertyMetadata(default(double), OnProgressScaleChanged)); + + private static void OnProgressScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaVideoControl; + if (control != null) + { + control.Progress.RenderTransform = new ScaleTransform { ScaleX = (double)e.NewValue, ScaleY = (double)e.NewValue }; + } + } + + public double ProgressScale + { + get { return (double)GetValue(ProgressScaleProperty); } + set { SetValue(ProgressScaleProperty, value); } + } + + public static readonly DependencyProperty MediaProperty = DependencyProperty.Register( + "Media", typeof(TLObject), typeof(MediaVideoControl), new PropertyMetadata(default(TLObject), OnMediaChanged)); + + private static void OnMediaChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaVideoControl; + if (control != null) + { + //System.Diagnostics.Debug.WriteLine(" Change Media old={0} new={1}", e.OldValue != null ? e.OldValue.GetHashCode() : 0, e.NewValue != null ? e.NewValue.GetHashCode() : 0); + //control.DownloadIcon.Visibility = Visibility.Visible; + var mediaPhoto = e.NewValue as TLMessageMediaDocument70; + if (mediaPhoto != null) + { + if (mediaPhoto.TTLSeconds != null) + { + control.GoToSecretMediaState(); + } + else + { + control.GoToNormalMediaState(); + } + } + + var decryptedMedia = e.NewValue as TLDecryptedMessageMediaBase; + if (decryptedMedia != null) + { + if (decryptedMedia.TTLSeconds != null && decryptedMedia.TTLSeconds.Value > 0) + { + control.GoToSecretMediaState(); + } + else + { + control.GoToNormalMediaState(); + } + } + } + } + + private void GoToNormalMediaState() + { + Root.Children.Remove(Progress); + if (_secretPhotoPlaceholder != null) Root.Children.Remove(_secretPhotoPlaceholder); + + Root.Children.Insert(1, Progress); + } + + private SecretPhotoPlaceholder _secretPhotoPlaceholder; + + private void GoToSecretMediaState() + { + Root.Children.Remove(Progress); + if (_secretPhotoPlaceholder != null) Root.Children.Remove(_secretPhotoPlaceholder); + + _secretPhotoPlaceholder = _secretPhotoPlaceholder ?? new SecretPhotoPlaceholder + { + IsHitTestVisible = false, + ShowHint = false, + TTLParams = TTLParams, + RenderTransformOrigin = new Point(0.5, 0.5), + RenderTransform = new ScaleTransform { ScaleX = ProgressScale, ScaleY = ProgressScale }, + Margin = new Thickness(-12.0), + VerticalAlignment = VerticalAlignment.Center, + HorizontalAlignment = HorizontalAlignment.Center + }; + + Root.Children.Insert(1, _secretPhotoPlaceholder); + } + + public TLObject Media + { + get { return (TLObject)GetValue(MediaProperty); } + set { SetValue(MediaProperty, value); } + } + + public static readonly DependencyProperty SourceProperty = DependencyProperty.Register( + "Source", typeof(ImageSource), typeof(MediaVideoControl), new PropertyMetadata(default(ImageSource), OnSourceChanged)); + + private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaVideoControl; + if (control != null) + { + control.Video.Source = e.NewValue as ImageSource; + } + } + + public ImageSource Source + { + get { return (ImageSource) GetValue(SourceProperty); } + set { SetValue(SourceProperty, value); } + } + + public static readonly DependencyProperty DownloadIconVisibilityProperty = DependencyProperty.Register( + "DownloadIconVisibility", typeof(Visibility), typeof(MediaVideoControl), new PropertyMetadata(default(Visibility), OnDownloadIconVisibilityChanged)); + + private static void OnDownloadIconVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaVideoControl; + if (control != null) + { + control.Progress.DownloadIconVisibility = (Visibility) e.NewValue; + } + } + + public Visibility DownloadIconVisibility + { + get { return (Visibility) GetValue(DownloadIconVisibilityProperty); } + set { SetValue(DownloadIconVisibilityProperty, value); } + } + + public static readonly DependencyProperty DownloadingProgressProperty = DependencyProperty.Register( + "DownloadingProgress", typeof(double), typeof(MediaVideoControl), new PropertyMetadata(default(double), OnProgressChanged)); + + public double DownloadingProgress + { + get { return (double) GetValue(DownloadingProgressProperty); } + set { SetValue(DownloadingProgressProperty, value); } + } + + public static readonly DependencyProperty UploadingProgressProperty = DependencyProperty.Register( + "UploadingProgress", typeof(double), typeof(MediaVideoControl), new PropertyMetadata(default(double), OnProgressChanged)); + + public double UploadingProgress + { + get { return (double) GetValue(UploadingProgressProperty); } + set { SetValue(UploadingProgressProperty, value); } + } + + private static void OnProgressChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as MediaVideoControl; + if (control != null) + { + var progress = (double)e.NewValue; + + control.Progress.DownloadingProgress = progress; + if (control._secretPhotoPlaceholder != null) + { + control._secretPhotoPlaceholder.DownloadingProgress = progress; + } + } + } + + public MediaVideoControl() + { + InitializeComponent(); + } + + public event EventHandler CancelDownloading; + + protected virtual void RaiseCancelDownloading() + { + var handler = CancelDownloading; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler CancelUploading; + + protected virtual void RaiseCancelUploading() + { + var handler = CancelUploading; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private void LayoutRoot_OnTap(object sender, GestureEventArgs e) + { + if (DownloadingProgress > 0.0 && DownloadingProgress < 1.0) + { + e.Handled = true; + RaiseCancelDownloading(); + } + else if (UploadingProgress > 0.0 && UploadingProgress < 1.0) + { + e.Handled = true; + RaiseCancelUploading(); + } + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/MessageControl.xaml b/TelegramClient.WP81/Views/Controls/MessageControl.xaml new file mode 100755 index 0000000..d727122 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/MessageControl.xaml @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/MessageControl.xaml.cs b/TelegramClient.WP81/Views/Controls/MessageControl.xaml.cs new file mode 100755 index 0000000..fd4ce89 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/MessageControl.xaml.cs @@ -0,0 +1,1183 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Diagnostics; +using System.Globalization; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Windows.Phone.Media.Devices; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using Telegram.EmojiPanel; +using TelegramClient.Converters; +using TelegramClient.Resources; +using TelegramClient.Views.Dialogs; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Controls +{ + public partial class MessageControl + { + //~MessageControl() + //{ + + //} + + public static readonly DependencyProperty ShareButtonContextMenuProperty = DependencyProperty.Register( + "ShareButtonContextMenu", typeof (ContextMenu), typeof (MessageControl), new PropertyMetadata(default(ContextMenu), OnShareButtonContextMenuChanged)); + + private static void OnShareButtonContextMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var messageControl = d as MessageControl; + if (messageControl != null) + { + ContextMenuService.SetContextMenu(messageControl.ShareButton, e.NewValue as ContextMenu); + } + } + + public ContextMenu ShareButtonContextMenu + { + get { return (ContextMenu) GetValue(ShareButtonContextMenuProperty); } + set { SetValue(ShareButtonContextMenuProperty, value); } + } + + public static readonly DependencyProperty MessageProperty = DependencyProperty.Register( + "Message", typeof (TLMessageBase), typeof (MessageControl), new PropertyMetadata(default(TLMessageBase), OnMessageChanged)); + + private static void OnMessageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var messageControl = d as MessageControl; + if (messageControl != null) + { + OnMessageChangedInternal(messageControl, e.NewValue as TLMessageBase); + } + } + + private static void OnMessageChangedInternal(MessageControl messageControl, TLMessageBase newMessage) + { + messageControl._isChannelMessage = false; + + messageControl.SetupBinding(newMessage); + + var messageCommon = newMessage as TLMessageCommon; + if (messageCommon != null) + { + var showAsService = IsServiceMessage(messageCommon); + if (!showAsService) + { + messageControl.ToMessageTemplate(messageCommon); + } + else + { + messageControl.ToServiceTemplate(messageCommon); + } + } + else + { + messageControl.ToEmptyTemplate(); + } + } + + private void ToMessageTemplate(TLMessageCommon message) + { + DrawBubble(message); + } + + private static bool GetIsChannelMessage(TLMessageCommon messageCommon) + { + var message = messageCommon as TLMessage; + if (message != null) + { + var message40 = message as TLMessage40; + if (message40 != null) + { + if (message40.FromId == null || message40.FromId.Value < 0) return true; + + if (message40.ToId is TLPeerChannel) // with signatures + { + var channel = IoC.Get().GetChat(message40.ToId.Id) as TLChannel; + if (channel != null && !channel.IsMegaGroup) + { + return true; + } + } + } + } + + return false; + } + + private static bool IsDocument(TLMessage message) + { + if (message == null) return false; + + var mediaDocument = message.Media as TLMessageMediaDocument45; + if (mediaDocument == null) return false; + + var document = mediaDocument.Document as IAttributes; + if (document == null) return false; + + foreach (var attribute in document.Attributes) + { + if (attribute is TLDocumentAttributeAnimated + || attribute is TLDocumentAttributeSticker + || attribute is TLDocumentAttributeVideo + ) + { + return false; + } + + var documentAttributeAudio = attribute as TLDocumentAttributeAudio46; + if (documentAttributeAudio != null && documentAttributeAudio.Voice) + { + return false; + } + + } + + return true; + } + + private static bool IsServiceMessage(TLMessageBase messageBase) + { + var messageService = messageBase as TLMessageService; + var phoneCall = messageService != null && messageService.Action is TLMessageActionPhoneCall; + var mediaExpired = messageBase != null && messageBase.IsExpired(); + var serviceMessage = (messageService != null && !phoneCall) || mediaExpired; + + return serviceMessage; + } + + private static bool IsSelfInputMessage(TLMessageCommon messageCommon) + { + var message = messageCommon as TLMessage73; + if (message != null && message.IsSelf()) + { + var fwdHeader = message.FwdHeader as TLMessageFwdHeader73; + if (fwdHeader != null) + { + var user = fwdHeader.From as TLUser; + if (user == null || !user.IsSelf) + { + return true; + } + } + } + + return false; + } + + private void DrawBubble(TLMessageCommon messageCommon) + { + //System.Diagnostics.Debug.WriteLine("DrawBubble id=" + messageCommon.Index); + + var isLightTheme = (Visibility) Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + var message = messageCommon as TLMessage48; + var messageService = messageCommon as TLMessageService; + var showAsServiceMessage = IsServiceMessage(messageCommon); + var unreadSeparator = messageService != null && messageService.Action is TLMessageActionUnreadMessages; + var sticker = message != null && message.IsSticker(); + var photo = message != null && message.Media is TLMessageMediaPhoto; + var grouped = message != null && message.Media is TLMessageMediaGroup; + var roundVideo = message != null && message.IsRoundVideo(); + + _isChannelMessage = GetIsChannelMessage(messageCommon); + var output = GetOutput(messageCommon); + + FromLabel.Visibility = (message != null && !output && (message.ToId is TLPeerChannel || message.ToId is TLPeerChat || message.ToId is TLPeerBroadcast) && !sticker && !photo && !grouped) || IsSelfInputMessage(message) + ? Visibility.Visible + : Visibility.Collapsed; + + Tile.Visibility = (message != null && !output && (message.ToId is TLPeerChannel || message.ToId is TLPeerChat || message.ToId is TLPeerBroadcast) && !_isChannelMessage) || IsSelfInputMessage(message) + ? Visibility.Visible + : Visibility.Collapsed; + + SetBackgroundAndBorder(messageCommon); + + Brush foreground; + if (showAsServiceMessage) + { + foreground = (Brush)Resources["ServiceMessageForegroundBrush"]; + } + else + { + foreground = isLightTheme + ? (output + ? (Brush)Resources["OutputForegroundBrushLight"] + : (Brush)Resources["InputForegroundBrushLight"]) + : (output + ? (Brush)Resources["OutputForegroundBrushDark"] + : (Brush)Resources["InputForegroundBrushDark"]); + } + + Brush footerForeground; + if (!sticker) + { + footerForeground = isLightTheme + ? (output + ? (Brush)Resources["OutputSubtleBrushLight"] + : (Brush)Resources["InputSubtleBrushLight"]) + : (output + ? (Brush)Resources["OutputSubtleBrushDark"] + : (Brush)Resources["InputSubtleBrushDark"]); + } + else + { + footerForeground = isLightTheme + ? (Brush)Resources["StickerFooterSubtleBrushLight"] + : (Brush)Resources["StickerFooterSubtleBrushDark"]; + } + + Brush footerBackground; + if (!sticker) + { + footerBackground = new SolidColorBrush(Colors.Transparent); + } + else + { + footerBackground = isLightTheme + ? (Brush)Resources["StickerFooterBackgroundBrushLight"] + : (Brush)Resources["StickerFooterBackgroundBrushDark"]; + } + + Foreground = foreground; + InputMessage.SetForeground(foreground); + + var beforeLastGridLength = output && !showAsServiceMessage + ? new GridLength(1.0, GridUnitType.Star) + : GridLength.Auto; + + var lastGridLength = output && !showAsServiceMessage + ? GridLength.Auto + : new GridLength(1.0, GridUnitType.Star); + + var bubbleGridColumn = output && !showAsServiceMessage + ? 4 + : 3; + + var cornerGridColumn = output && !showAsServiceMessage + ? 5 + : 2; + + var commandsGridColumn = bubbleGridColumn; + + Corner.Margin = output + ? new Thickness(-1.0, 12.0, 0.0, 0.0) + : new Thickness(0.0, 12.0, -1.0, 0.0); + Corner.HorizontalAlignment = output + ? HorizontalAlignment.Left + : HorizontalAlignment.Right; + PathScaleTransform.ScaleX = output ? -1.0 : 1.0; + Corner.Visibility = showAsServiceMessage ? Visibility.Collapsed : Visibility.Visible; + CornerBorder.Visibility = showAsServiceMessage ? Visibility.Collapsed : Visibility.Visible; + if (unreadSeparator) + { + MainBorder.Margin = new Thickness(-18.0, 0.0, -18.0, 6.0); + MainBorder.HorizontalAlignment = HorizontalAlignment.Stretch; + Panel.HorizontalAlignment = HorizontalAlignment.Center; + } + else if (showAsServiceMessage) + { + MainBorder.Margin = new Thickness(0.0, 0.0, 0.0, 6.0); + MainBorder.HorizontalAlignment = HorizontalAlignment.Center; + Panel.HorizontalAlignment = HorizontalAlignment.Center; + } + else + { + MainBorder.Margin = new Thickness(0.0, 0.0, 0.0, 6.0); + MainBorder.HorizontalAlignment = HorizontalAlignment.Left; + Panel.HorizontalAlignment = HorizontalAlignment.Left; + } + Grid.SetColumnSpan(MainBorder, showAsServiceMessage ? 2 : 1); + InputMessage.TextAlignment = showAsServiceMessage ? TextAlignment.Center : TextAlignment.Left; + + MainBorder.BorderThickness = output + ? new Thickness(1.0, 1.0, 0.0, 1.0) + : new Thickness(0.0, 1.0, 1.0, 1.0); + CornerBorder.BorderThickness = output + ? new Thickness(1.0, 0.0, 0.0, 0.0) + : new Thickness(0.0, 0.0, 1.0, 0.0); + + BeforeLastColumn.Width = beforeLastGridLength; + LastColumn.Width = lastGridLength; + Grid.SetColumn(MainBorder, bubbleGridColumn); + Grid.SetColumn(Corner, cornerGridColumn); + Grid.SetColumn(CornerBorder, cornerGridColumn); + + Header.MaxWidth = messageCommon != null ? messageCommon.MediaWidth : 12.0 + 311.0 + 12.0; + FwdFromGrid.Visibility = message != null && !message.IsSticker() && !message.IsRoundVideo() && !message.IsSelf() ? message.FwdFromPeerVisibility : Visibility.Collapsed; + + ViaBotGrid.Visibility = message != null ? message.ViaBotVisibility : Visibility.Collapsed; + ReplyContent.Visibility = messageCommon != null ? messageCommon.ReplyVisibility : Visibility.Collapsed; + if (FromLabel.Visibility == Visibility.Visible + || FwdFromGrid.Visibility == Visibility.Visible + || ViaBotGrid.Visibility == Visibility.Visible + || ReplyContent.Visibility == Visibility.Visible) + { + Header.Visibility = Visibility.Visible; + } + else + { + Header.Visibility = Visibility.Collapsed; + } + if (FromLabel.Visibility == Visibility.Visible + && FwdFromGrid.Visibility == Visibility.Collapsed + && ViaBotGrid.Visibility == Visibility.Collapsed + && ReplyContent.Visibility == Visibility.Collapsed + && message != null + && !TLString.IsNullOrEmpty(message.Message)) + { + FromLabel.Margin = new Thickness(0.0, 2.0, 0.0, -4.0); + } + else if (FromLabel.Visibility == Visibility.Visible + && FwdFromGrid.Visibility == Visibility.Collapsed + && ViaBotGrid.Visibility == Visibility.Collapsed + && messageCommon != null && messageCommon.ReplyInfo != null) + { + FromLabel.Margin = new Thickness(0.0, 2.0, 0.0, 6.0); + } + else + { + FromLabel.Margin = new Thickness(0.0, 2.0, 0.0, 0.0); + } + + if (FromLabel.Visibility == Visibility.Collapsed + && FwdFromGrid.Visibility == Visibility.Collapsed + && ViaBotGrid.Visibility == Visibility.Collapsed + && ReplyContent.Visibility == Visibility.Visible + && messageCommon != null && messageCommon.ReplyInfo != null) + { + ReplyContent.Margin = new Thickness(0.0, 6.0, 0.0, 0.0); + } + else + { + ReplyContent.Margin = new Thickness(0.0, 0.0, 0.0, 0.0); + } + + CaptionPanel.Children.Remove(ViaBotGrid); + FromLabelPanel.Children.Remove(ViaBotGrid); + if (FromLabel.Visibility == Visibility.Visible + && ViaBotGrid.Visibility == Visibility.Visible) + { + ViaBotGrid.Margin = FromLabel.Margin; + FromLabel.Margin = new Thickness(FromLabel.Margin.Left, FromLabel.Margin.Top, FromLabel.Margin.Right + 6.0, FromLabel.Margin.Bottom); + FromLabelPanel.Children.Add(ViaBotGrid); + } + else + { + ViaBotGrid.Margin = new Thickness(0.0, -6.0, 0.0, 0.0); + CaptionPanel.Children.Insert(2, ViaBotGrid); + } + + AuthorLabel.Visibility = _isChannelMessage && message != null? message.AuthorVisibility : Visibility.Collapsed; + ViewsGrid.Visibility = message != null ? message.ViewsVisibility : Visibility.Collapsed; + + Grid.SetColumn(Commands, commandsGridColumn); + + ShereButtonImage.Source = isLightTheme + ? new BitmapImage(new Uri("/Images/Messages/channel.share.white.png", UriKind.Relative)) + : new BitmapImage(new Uri("/Images/Messages/channel.share.white.png", UriKind.Relative)); + + ShareButton.Visibility = message != null + && ((!sticker && message.ToId is TLPeerChannel && _isChannelMessage) || (message.Media is TLMessageMediaInvoice && !message.Out.Value) || IsSelfInputMessage(message)) + ? Visibility.Visible + : Visibility.Collapsed; + + Status.Visibility = output? Visibility.Visible : Visibility.Collapsed; + + MessageGrid.MaxWidth = messageCommon != null ? messageCommon.MediaWidth : 12.0 + 311.0 + 12.0; + + Panel.Children.Remove(Header); + MainItemGrid.Children.Remove(Header); + if (showAsServiceMessage) + { + MessageGrid.Margin = new Thickness(0.0, 2.0, 0.0, 7.0); + } + else if (sticker) + { + ReplyContent.Foreground = footerForeground; + ViaBotGrid.Foreground = new SolidColorBrush(Colors.White); + Header.Background = footerBackground; + Grid.SetRow(Header, 1); + Grid.SetColumn(Header, output ? bubbleGridColumn - 1 : bubbleGridColumn + 1); + Header.HorizontalAlignment = output ? HorizontalAlignment.Right : HorizontalAlignment.Left; + Header.Margin = new Thickness(6.0); + MainItemGrid.Children.Add(Header); + } + else + { + ReplyContent.Foreground = foreground; + ViaBotGrid.Foreground = (Brush) Application.Current.Resources["TelegramBadgeAccentBrush"]; + Header.SetValue(Grid.RowProperty, DependencyProperty.UnsetValue); + Header.SetValue(Grid.ColumnProperty, DependencyProperty.UnsetValue); + Header.HorizontalAlignment = HorizontalAlignment.Left; + Header.Margin = new Thickness(0.0, 0.0, 0.0, -6.0); + Panel.Children.Insert(0, Header); + } + + SetFooter(messageCommon); + } + + private void SetBackgroundAndBorder(TLMessageCommon messageCommon) + { + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + var message = messageCommon as TLMessage48; + var messageService = messageCommon as TLMessageService; + var phoneCall = messageService != null && messageService.Action is TLMessageActionPhoneCall; + var mediaExpired = messageCommon != null && messageCommon.IsExpired(); + var serviceMessage = (messageService != null && !phoneCall) || mediaExpired; + var sticker = messageCommon != null && messageCommon.IsSticker(); + var roundVideo = messageCommon != null && messageCommon.IsRoundVideo(); + var output = GetOutput(messageCommon); + + Brush border; + if (serviceMessage) + { + border = (Brush)Resources["ServiceMessageBorderBrush"]; + } + else if (sticker) + { + border = new SolidColorBrush(Colors.Transparent); + } + else if (roundVideo) + { + border = new SolidColorBrush(Colors.Transparent); + } + else + { + border = isLightTheme + ? (output + ? (Brush)Resources["OutputBorderBrushLight"] + : (Brush)Resources["InputBorderBrushLight"]) + : (output + ? (Brush)Resources["OutputBorderBrushDark"] + : (Brush)Resources["InputBorderBrushDark"]); + } + + Brush background; + if (serviceMessage) + { + background = (Brush)Resources["ServiceMessageBackgroundBrush"]; + } + else if (sticker) + { + background = new SolidColorBrush(Colors.Transparent); + } + else if (roundVideo) + { + background = new SolidColorBrush(Colors.Transparent); + } + else + { + background = isLightTheme + ? (output + ? (Brush)Resources["OutputBackgroundBrushLight"] + : (Brush)Resources["InputBackgroundBrushLight"]) + : (output + ? (Brush)Resources["OutputBackgroundBrushDark"] + : (Brush)Resources["InputBackgroundBrushDark"]); + } + + Corner.Fill = background; + Corner.Stroke = border; + CornerBorder.BorderBrush = border; + + MainBorder.Background = background; + MainBorder.BorderBrush = border; + MorePanel.Background = background; + Header.Background = background; + } + + private bool _isChannelMessage; + + private void ToServiceTemplate(TLMessageCommon messageCommon) + { + _isChannelMessage = false; + FromLabel.Visibility = Visibility.Collapsed; + Tile.Visibility = Visibility.Collapsed; + + DrawBubble(messageCommon); + } + + private Binding _authorBinding; + private Binding _viewsBinding; + private Binding _inputMessageTextBinding; + private Binding _inputMessageEntitiesBinding; + private Binding _inputMessageVisibilityBinding; + private Binding _mediaContentControlContentBinding; + private Binding _mediaContentControlContentTemplateBinding; + private Binding _commandsReplyMarkupBinding; + private Binding _editLabelVisibilityBinding; + + private void SaveBinding(ref Binding binding, FrameworkElement element, DependencyProperty dp) + { + if (binding == null) + { + var bindingExpression = element.GetBindingExpression(dp); + if (bindingExpression != null) + { + binding = bindingExpression.ParentBinding; + } + element.ClearValue(dp); + } + } + + private void RestoreBinding(ref Binding binding, FrameworkElement element, DependencyProperty dp) + { + if (binding != null) + { + element.SetBinding(dp, binding); + binding = null; + } + } + + private void SetupBinding(TLMessageBase messageBase) + { + // exceptions: + // 1) message with TTL and Document=null, Photo=null is service message (video has expired, photo has expired) + // 2) service message with phone call is regular message + + var serviceMessage = messageBase as TLMessageService; + var message = messageBase as TLMessage; + + if (serviceMessage != null) + { + SaveBinding(ref _inputMessageEntitiesBinding, InputMessage, TelegramRichTextBox.EntitiesProperty); + SaveBinding(ref _inputMessageTextBinding, InputMessage, TelegramRichTextBox.TextProperty); + SaveBinding(ref _commandsReplyMarkupBinding, Commands, CommandsControl.ReplyMarkupProperty); + + var isPhoneCall = serviceMessage.Action is TLMessageActionPhoneCall; + if (!isPhoneCall) + { + var serviceMessageToTextConverter = new ServiceMessageToTextConverter(); + InputMessage.Text = (string)serviceMessageToTextConverter.Convert(serviceMessage.Self, null, "", null); + } + + ClearValue(MediaProperty); + } + else if (message != null && message.IsExpired()) // will be set manually to service message 'video has expired'/'photo has expired' + { + SaveBinding(ref _inputMessageEntitiesBinding, InputMessage, TelegramRichTextBox.EntitiesProperty); + SaveBinding(ref _inputMessageTextBinding, InputMessage, TelegramRichTextBox.TextProperty); + RestoreBinding(ref _commandsReplyMarkupBinding, Commands, CommandsControl.ReplyMarkupProperty); + + var mediaPhoto = message.Media as TLMessageMediaPhoto70; + var mediaDocument = message.Media as TLMessageMediaDocument70; + if (mediaPhoto != null) + { + InputMessage.Text = AppResources.MessageActionPhotoExpired; + } + else if (mediaDocument != null) + { + InputMessage.Text = AppResources.MessageActionVideoExpired; + } + + _suppressFooterReplacement = true; + SetBinding(MediaProperty, new Binding("Media") { Source = messageBase, Mode = BindingMode.OneWay }); // Media field of type TLMessageService for phone calls is not acceptable for dependency property of type TLMessageMediaBase + _suppressFooterReplacement = false; + } + else + { + RestoreBinding(ref _inputMessageEntitiesBinding, InputMessage, TelegramRichTextBox.EntitiesProperty); // there is no Entities field on TLMessageService with phone call + RestoreBinding(ref _inputMessageTextBinding, InputMessage, TelegramRichTextBox.TextProperty); // there is no Message field on TLMessageService with phone call + RestoreBinding(ref _commandsReplyMarkupBinding, Commands, CommandsControl.ReplyMarkupProperty); // there is no ReplyMarkup field on TLMessageService with phone call + + _suppressFooterReplacement = true; + SetBinding(MediaProperty, new Binding("Media") { Source = messageBase, Mode = BindingMode.OneWay }); // Media field of type TLMessageService for phone calls is not acceptable for dependency property of type TLMessageMediaBase + _suppressFooterReplacement = false; + } + + var showAsServiceMessage = IsServiceMessage(messageBase); + if (showAsServiceMessage) + { + //SaveBinding(ref _fwdFromLabelTextBinding, FwdFromLabel, Run.TextProperty); + SaveBinding(ref _inputMessageVisibilityBinding, InputMessage, TelegramRichTextBox.VisibilityProperty); + SaveBinding(ref _mediaContentControlContentBinding, MediaContentControl, ContentControl.ContentProperty); + SaveBinding(ref _mediaContentControlContentTemplateBinding, MediaContentControl, ContentControl.ContentTemplateProperty); + SaveBinding(ref _viewsBinding, ViewsLabel, TextBlock.TextProperty); + SaveBinding(ref _authorBinding, AuthorLabel, TextBlock.TextProperty); + SaveBinding(ref _editLabelVisibilityBinding, EditLabel, TextBlock.VisibilityProperty); + + _suppressFooterReplacement = true; + ClearValue(MediaCaptionProperty); + _suppressFooterReplacement = false; + + ClearValue(MediaUnreadProperty); + } + else + { + var stopwatch = Stopwatch.StartNew(); + RestoreBinding(ref _inputMessageVisibilityBinding, InputMessage, TelegramRichTextBox.VisibilityProperty); + RestoreBinding(ref _mediaContentControlContentBinding, MediaContentControl, ContentControl.ContentProperty); + RestoreBinding(ref _mediaContentControlContentTemplateBinding, MediaContentControl, ContentControl.ContentTemplateProperty); + RestoreBinding(ref _viewsBinding, ViewsLabel, TextBlock.TextProperty); + RestoreBinding(ref _authorBinding, AuthorLabel, TextBlock.TextProperty); + RestoreBinding(ref _editLabelVisibilityBinding, EditLabel, TextBlock.VisibilityProperty); + + _suppressFooterReplacement = true; + if (message != null) + { + var mediaCaption = message.Media as IMediaCaption; + if (mediaCaption != null) + { + var mediaCaptionBinding = new Binding("Message") { Source = message, Mode = BindingMode.OneWay }; + SetBinding(MediaCaptionProperty, mediaCaptionBinding); + } + } + _suppressFooterReplacement = false; + + var message70 = messageBase as TLMessage70; + if (message70 != null && message70.HasTTL()) + { + var notListenedBinding = new Binding("TTLMediaExpired") { Source = message, Mode = BindingMode.OneWay }; + SetBinding(MediaUnreadProperty, notListenedBinding); + } + } + } + + private bool _suppressFooterReplacement; + + public string MediaCaption + { + get { return (string)GetValue(MediaCaptionProperty); } + set { SetValue(MediaCaptionProperty, value); } + } + + public static readonly DependencyProperty MediaCaptionProperty = DependencyProperty.Register( + "MediaCaption", typeof (string), typeof (MessageControl), new PropertyMetadata(default(string), OnMediaCaptionChanged)); + + private static void OnMediaCaptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var messageControl = d as MessageControl; + if (messageControl != null && !messageControl._suppressFooterReplacement) + { + var oldCaption = e.OldValue as string; + var newCaption = e.NewValue as string; + if (!string.Equals(oldCaption, newCaption, StringComparison.Ordinal)) + { + messageControl.SetFooter(messageControl.Message); + } + } + } + + public static readonly DependencyProperty MediaUnreadProperty = DependencyProperty.Register( + "MediaUnread", typeof(bool), typeof(MessageControl), new PropertyMetadata(default(bool), OnMediaUnreadChanged)); + + private static void OnMediaUnreadChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var messageControl = d as MessageControl; + if (messageControl != null) + { + var message = messageControl.Message as TLMessage; + if (message != null && message.IsExpired()) + { + var oldMediaUnread = (bool) e.OldValue; + var newMediaUnread = (bool) e.NewValue; + if (!oldMediaUnread && newMediaUnread) + { + OnMessageChangedInternal(messageControl, messageControl.Message); + } + } + } + } + + public bool MediaUnread + { + get { return (bool) GetValue(MediaUnreadProperty); } + set { SetValue(MediaUnreadProperty, value); } + } + + protected TLMessageMediaBase Media + { + get { return (TLMessageMediaBase)GetValue(MediaProperty); } + set { SetValue(MediaProperty, value); } + } + + public static readonly DependencyProperty MediaProperty = DependencyProperty.Register( + "Media", typeof (TLMessageMediaBase), typeof (MessageControl), new PropertyMetadata(default(TLMessageMediaBase), OnMediaChanged)); + + private static void OnMediaChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var messageControl = d as MessageControl; + if (messageControl != null) + { + if (!messageControl._suppressFooterReplacement) + { + var oldWebPage = e.OldValue as TLMessageMediaWebPage; + var newWebPage = e.NewValue as TLMessageMediaWebPage; + if (oldWebPage != null + || newWebPage != null) + { + messageControl.SetFooter(messageControl.Message); + } + } + } + } + + private bool GetOutput(TLMessageCommon message) + { + if (IsSelfInputMessage(message)) + { + return false; + } + + return message != null && message.Out.Value && !_isChannelMessage; + } + + private void SetFooter(TLMessageBase messageBase) + { + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + + var messageCommon = messageBase as TLMessageCommon; + var message = messageBase as TLMessage48; + var service = messageBase as TLMessageService; + var phoneCall = service != null && service.Action is TLMessageActionPhoneCall; + var showAsServiceMessage = IsServiceMessage(messageBase); + var output = GetOutput(messageCommon); + + var hasCaption = message != null && !TLString.IsNullOrEmpty(message.Message); + var isGroupedMedia = message != null && message.Media is TLMessageMediaGroup; + var isPhoto = message != null && message.Media is TLMessageMediaPhoto; + var isVideo = message != null && message.IsVideo(); + var isGeo = message != null && message.Media is TLMessageMediaGeo && !(message.Media is TLMessageMediaGeoLive); + var isVenue = message != null && message.Media is TLMessageMediaVenue; + var isGeoLive = message != null && message.Media is TLMessageMediaGeoLive; + var isGif = message != null && message.IsGif() && !(message.Media is TLMessageMediaGame) && !(message.Media is TLMessageMediaWebPage); + var isDocument = message != null && IsDocument(message); + var isVoice = message != null && message.IsVoice(); + var isRoundVideo = message != null && message.IsRoundVideo(); + var isSticker = message != null && message.IsSticker(); + var isWebPage = message != null && message.Media is TLMessageMediaWebPage; + var isEmptyMedia = message != null && (message.Media == null || message.Media is TLMessageMediaEmpty); + var isUnsupported = message != null && message.Media is TLMessageMediaUnsupported; + + //var isGif = message != null && message.IsGif(); + var isShortFooter = IsShortFooter(message, isGroupedMedia, isPhoto, isVideo, isGeo, isGeoLive, isGif, isDocument, isVoice, isSticker, isWebPage, isEmptyMedia, isUnsupported); + + Brush background; + if (showAsServiceMessage) + { + background = (Brush)Resources["ServiceMessageBackgroundBrush"]; + } + if (isSticker) + { + background = new SolidColorBrush(Colors.Transparent); + } + if (isRoundVideo) + { + background = new SolidColorBrush(Colors.Transparent); + } + else + { + background = isLightTheme + ? (output + ? (Brush)Resources["OutputBackgroundBrushLight"] + : (Brush)Resources["InputBackgroundBrushLight"]) + : (output + ? (Brush)Resources["OutputBackgroundBrushDark"] + : (Brush)Resources["InputBackgroundBrushDark"]); + } + + Brush footerForeground; + if (isSticker) + { + footerForeground = isLightTheme + ? (Brush)Resources["StickerFooterSubtleBrushLight"] + : (Brush)Resources["StickerFooterSubtleBrushDark"]; + } + else if (isRoundVideo) + { + footerForeground = isLightTheme + ? (Brush)Resources["StickerFooterSubtleBrushLight"] + : (Brush)Resources["StickerFooterSubtleBrushDark"]; + } + else if (isShortFooter && !hasCaption && (isGroupedMedia || isPhoto || (isGeo && !isVenue) || isVideo || isGif)) + { + footerForeground = new SolidColorBrush(Colors.White); + } + else + { + footerForeground = isLightTheme + ? (output + ? (Brush)Resources["OutputSubtleBrushLight"] + : (Brush)Resources["InputSubtleBrushLight"]) + : (output + ? (Brush)Resources["OutputSubtleBrushDark"] + : (Brush)Resources["InputSubtleBrushDark"]); + } + + Brush footerBackground; + if (isSticker) + { + footerBackground = isLightTheme + ? (Brush)Resources["StickerFooterBackgroundBrushLight"] + : (Brush)Resources["StickerFooterBackgroundBrushDark"]; + } + else if (isRoundVideo) + { + footerBackground = isLightTheme + ? (Brush)Resources["StickerFooterBackgroundBrushLight"] + : (Brush)Resources["StickerFooterBackgroundBrushDark"]; + } + else if (isShortFooter && !hasCaption && (isGroupedMedia || isPhoto || isVideo || (isGeo && !isVenue) || isGif)) + { + footerBackground = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)); + } + else + { + footerBackground = new SolidColorBrush(Colors.Transparent); + } + + FooterContent.Foreground = footerForeground; + FooterContentGrid.Background = footerBackground; + Footer.MaxWidth = messageCommon != null ? messageCommon.MediaWidth : 12.0 + 311.0 + 12.0; + Status.Fill = footerForeground; + ViewsIcon.Stroke = footerForeground; + + if (messageCommon != null && messageCommon.Reply != null && (isGroupedMedia || isPhoto || isVideo || isGeo || isGif)) + { + MediaContentControl.Margin = new Thickness(12.0, 3.0, 12.0, 0.0); + } + else + { + MediaContentControl.Margin = new Thickness(12.0, 0.0, 12.0, 0.0); + } + + // setup message and media position + MessageGrid.Visibility = message != null && !TLString.IsNullOrEmpty(message.Message) || showAsServiceMessage + ? Visibility.Visible + : Visibility.Collapsed; + Panel.Children.Remove(MessageGrid); + Panel.Children.Remove(MediaGrid); + if (message != null && (message.Media is TLMessageMediaWebPage || message.Media is TLMessageMediaEmpty) || showAsServiceMessage) + { + MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 0.0); + MediaGrid.Margin = new Thickness(0.0, 0.0, 0.0, 0.0); + + Panel.Children.Add(MessageGrid); + Panel.Children.Add(MediaGrid); + } + else + { + MessageGrid.Margin = new Thickness(0.0, 0.0, 0.0, 0.0); + MediaGrid.Margin = new Thickness(0.0, 6.0, 0.0, 0.0); + + Panel.Children.Add(MediaGrid); + Panel.Children.Add(MessageGrid); + } + + // setup footer position + Panel.Children.Remove(Footer); + MediaGrid.Children.Remove(Footer); + MessageGrid.Children.Remove(Footer); + if (showAsServiceMessage) + { + // remove footer + MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 6.0); + } + else if (phoneCall) + { + MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 0.0); + } + else if (!isShortFooter) + { + Footer.Margin = new Thickness(0.0, -1.0, 0.0, 0.0); + Footer.Background = background; + Footer.HorizontalAlignment = HorizontalAlignment.Stretch; + Footer.VerticalAlignment = VerticalAlignment.Stretch; + Panel.Children.Add(Footer); + MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 0.0); + } + else + { + if (isSticker) + { + Footer.Margin = new Thickness(0.0, -1.0, 0.0, 0.0); + Footer.Background = new SolidColorBrush(Colors.Transparent); + Footer.HorizontalAlignment = HorizontalAlignment.Right; + Footer.VerticalAlignment = VerticalAlignment.Bottom; + MediaGrid.Children.Add(Footer); + MessageGrid.Margin = new Thickness(0.0, 0.0, 0.0, 0.0); + } + else if (isEmptyMedia || hasCaption) + { + Footer.Margin = new Thickness(0.0, -1.0, 0.0, -11.0); + Footer.Background = new SolidColorBrush(Colors.Transparent); + Footer.HorizontalAlignment = HorizontalAlignment.Stretch; + Footer.VerticalAlignment = VerticalAlignment.Bottom; + MessageGrid.Children.Add(Footer); + MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 11.0); + } + else if (isGeoLive) + { + Footer.Margin = new Thickness(0.0, -1.0, 0.0, 0.0); + Footer.Background = new SolidColorBrush(Colors.Transparent); + Footer.HorizontalAlignment = HorizontalAlignment.Right; + Footer.VerticalAlignment = VerticalAlignment.Bottom; + //MediaGrid.Children.Add(Footer); + MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 0.0); + } + else if (isGroupedMedia || isPhoto || isVideo || isGeo || isGif || isVoice || isDocument) + { + Footer.Margin = new Thickness(0.0, -1.0, 0.0, 0.0); + Footer.Background = new SolidColorBrush(Colors.Transparent); + Footer.HorizontalAlignment = HorizontalAlignment.Right; + Footer.VerticalAlignment = VerticalAlignment.Bottom; + MediaGrid.Children.Add(Footer); + MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 11.0); + } + else + { + Footer.Margin = new Thickness(0.0, -1.0, 0.0, 0.0); + Footer.Background = background; + Footer.HorizontalAlignment = HorizontalAlignment.Stretch; + Footer.VerticalAlignment = VerticalAlignment.Stretch; + Panel.Children.Add(Footer); + MessageGrid.Margin = new Thickness(0.0, 6.0, 0.0, 0.0); + } + } + + if (message != null + && !TLString.IsNullOrEmpty(message.Message) + && !(message.Media is TLMessageMediaWebPage)) + { + var messageDateTimeConverter = (IValueConverter) Application.Current.Resources["MessageDateTimeConverter"]; + var dateText = messageDateTimeConverter.Convert(message.Date, null, null, null); + + var footerBuilder = new StringBuilder(); + if (FlowDirection == FlowDirection.RightToLeft) + { + footerBuilder.Append("د"); + } + else + { + footerBuilder.Append("a"); + } + if (_isChannelMessage + && message.AuthorVisibility == Visibility.Visible + && message.Author != null) + { + footerBuilder.Append(string.Format("{0} ", message.Author)); + } + if (message.ViewsVisibility == Visibility.Visible) + { + footerBuilder.Append(string.Format("vc {0}, ", + new MessageViewsConverter().Convert(message.Views, null, null, null))); + } + footerBuilder.Append("/ " + dateText); + if (message.Out.Value) + { + footerBuilder.Append(" W"); + } + + InputMessage.Footer = footerBuilder.ToString(); + } + else + { + InputMessage.Footer = string.Empty; + } + + if (isVoice) + { + MediaContentControl.Foreground = footerForeground; + } + else + { + MediaContentControl.SetValue(Control.ForegroundProperty, DependencyProperty.UnsetValue); + } + } + + private static bool IsShortFooter(TLMessage48 message, bool isGrouped, bool isPhoto, bool isVideo, bool isGeo, bool isGeoLive, bool isGif, bool isDocument, bool isVoice, bool isSticker, bool isWebPage, bool isEmptyMedia, bool isUnsupported) + { + if (message != null) + { + if (isUnsupported) + { + return false; + } + + if (isWebPage) + { + return false; + } + + if (isGrouped || isPhoto || isVideo || isGeo || isGif) + { + return true; + } + + if (isSticker) + { + return true; + } + + if (isEmptyMedia) + { + return true; + } + + if (isDocument || isVoice || isGeoLive) + { + var clientDelta = IoC.Get().ClientTicksDelta; + //var utc0SecsLong = message.Date.Value * 4294967296 - clientDelta; + var utc0SecsInt = message.Date.Value - clientDelta / 4294967296.0; + + var dateTime = Telegram.Api.Helpers.Utils.UnixTimestampToDateTime(utc0SecsInt); + if (dateTime.Date.AddDays(365) < DateTime.Now.Date) + return false; + + if (message.AuthorVisibility == Visibility.Visible + && message.ToId is TLPeerChannel) + { + var channel = IoC.Get().GetChat(message.ToId.Id) as TLChannel; + if (channel != null && !channel.IsMegaGroup) + { + return false; + } + } + + return true; + } + } + + return false; + } + + private void ToEmptyTemplate() + { + + } + + public TLMessageBase Message + { + get { return (TLMessageBase) GetValue(MessageProperty); } + set { SetValue(MessageProperty, value); } + } + + private static int _count; + + public MessageControl() + { + InitializeComponent(); + + //System.Diagnostics.Debug.WriteLine("MessageControl " + _count++); + } + + public event EventHandler TapViaBot; + + protected virtual void RaiseTapViaBot(object sender, GestureEventArgs args) + { + var handler = TapViaBot; + if (handler != null) handler(sender, args); + } + + private void ViaBot_Tap(object sender, GestureEventArgs args) + { + RaiseTapViaBot(sender, args); + } + + public event EventHandler TapMorePanel; + + protected virtual void RaiseTapMorePanel(object sender, GestureEventArgs args) + { + var handler = TapMorePanel; + if (handler != null) handler(sender, args); + } + + private void MorePanel_OnTap(object sender, GestureEventArgs args) + { + RaiseTapMorePanel(sender, args); + } + + public event EventHandler TapUserTile; + + protected virtual void RaiseTapUserTile(object sender, GestureEventArgs args) + { + var handler = TapUserTile; + if (handler != null) handler(sender, args); + } + + private void Tile_OnTap(object sender, GestureEventArgs args) + { + RaiseTapUserTile(sender, args); + } + + public event EventHandler CommandsControlButtonClick; + + protected virtual void RaiseCommandsControlButtonClick(object sender, KeyboardButtonEventArgs e) + { + var handler = CommandsControlButtonClick; + if (handler != null) handler(sender, e); + } + + private void CommandsControl_OnButtonClick(object sender, KeyboardButtonEventArgs e) + { + RaiseCommandsControlButtonClick(sender, e); + } + + public event EventHandler ShareButtonClick; + + protected virtual void RaiseShareButtonClick(object sender, RoutedEventArgs e) + { + var handler = ShareButtonClick; + if (handler != null) handler(sender, e); + } + + private void ShareButton_OnTap(object sender, GestureEventArgs e) + { + e.Handled = true; + RaiseShareButtonClick(sender, e); + } + + public event EventHandler TapMedia; + + private void MediaContentControl_OnTap(object sender, GestureEventArgs e) + { + e.Handled = true; + RaiseTapMedia(e); + } + + protected virtual void RaiseTapMedia(GestureEventArgs e) + { + var handler = TapMedia; + if (handler != null) handler(this, e); + } + } + + public class NonBreakingStringConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return Convert(value); + } + + public static object Convert(object value) + { + var str = value as string; + if (str != null) + { + return str.Replace(' ', '\xA0').Replace("-", "\u2011"); + } + + return value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/OpacityMaskBorder.xaml b/TelegramClient.WP81/Views/Controls/OpacityMaskBorder.xaml new file mode 100755 index 0000000..a023ddb --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/OpacityMaskBorder.xaml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/OpacityMaskBorder.xaml.cs b/TelegramClient.WP81/Views/Controls/OpacityMaskBorder.xaml.cs new file mode 100755 index 0000000..ab5b1fa --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/OpacityMaskBorder.xaml.cs @@ -0,0 +1,70 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Media; + +namespace TelegramClient.Views.Controls +{ + public partial class OpacityMaskBorder + { + public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register( + "ImageSource", typeof (ImageSource), typeof (OpacityMaskBorder), new PropertyMetadata(default(ImageSource), OnImageSourceChanged)); + + private static void OnImageSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var opacityMaskBorder = d as OpacityMaskBorder; + if (opacityMaskBorder != null) + { + opacityMaskBorder.ImageBrush.ImageSource = e.NewValue as ImageSource; + } + } + + public static readonly DependencyProperty BorderBackgroundProperty = DependencyProperty.Register( + "BorderBackground", typeof (Brush), typeof (OpacityMaskBorder), new PropertyMetadata(default(Brush), OnBorderBackgroundChanged)); + + private static void OnBorderBackgroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var opacityMaskBorder = d as OpacityMaskBorder; + if (opacityMaskBorder != null) + { + opacityMaskBorder.Border.Background = e.NewValue as Brush; + } + } + + public Brush BorderBackground + { + get { return (Brush) GetValue(BorderBackgroundProperty); } + set { SetValue(BorderBackgroundProperty, value); } + } + + public ImageSource ImageSource + { + get { return (ImageSource) GetValue(ImageSourceProperty); } + set { SetValue(ImageSourceProperty, value); } + } + + public OpacityMaskBorder() + { + InitializeComponent(); + } + + private void ImageBrush_OnImageOpened(object sender, RoutedEventArgs e) + { + var opacityMaskBorder = sender as OpacityMaskBorder; + if (opacityMaskBorder != null) + { + opacityMaskBorder.Border.Opacity = 1.0; + } + } + + private void ImageBrush_OnImageFailed(object sender, ExceptionRoutedEventArgs e) + { + + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/OpenPhotoPicker.xaml b/TelegramClient.WP81/Views/Controls/OpenPhotoPicker.xaml new file mode 100755 index 0000000..f78b8c0 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/OpenPhotoPicker.xaml @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/OpenPhotoPicker.xaml.cs b/TelegramClient.WP81/Views/Controls/OpenPhotoPicker.xaml.cs new file mode 100755 index 0000000..a9f6021 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/OpenPhotoPicker.xaml.cs @@ -0,0 +1,811 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; +using Windows.Devices.Enumeration; +using Windows.Media.Capture; +using Windows.Storage; +using Microsoft.Phone.Controls; +using Microsoft.Xna.Framework.Media; +using Microsoft.Xna.Framework.Media.PhoneExtensions; +using Telegram.Logs; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Controls +{ + public partial class OpenPhotoPicker + { + public bool IsSingleItem { get; set; } + + private bool _isManipulating; + + private bool _hasManipulatingDelta; + + private readonly Dictionary _selectedPictures = new Dictionary(); + + private PictureAlbumCollection _allAlbums; + + public event EventHandler Pick; + + protected virtual void RaisePick(PickEventArgs e) + { + var handler = Pick; + if (handler != null) handler(this, e); + } + + public OpenPhotoPicker() + { + InitializeComponent(); + + InitilalizeMediaLibrary(); + + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + if (isLightTheme) + { + ((SolidColorBrush) Resources["BackgroundBrush"]).Color = ((SolidColorBrush) Resources["LightThemeBackgroundBrush"]).Color; + } + else + { + ((SolidColorBrush)Resources["BackgroundBrush"]).Color = ((SolidColorBrush)Resources["DarkThemeBackgroundBrush"]).Color; + } + + Loaded += OnLoaded; + } + + ~OpenPhotoPicker() + { + + } + + private TelegramAppBarButton _selectButton; + + private void OnLoaded(object sender, RoutedEventArgs e) + { + Loaded -= OnLoaded; + + _selectButton = AppBar.Buttons[0] as TelegramAppBarButton; + + BeginOpenStoryboard(); + } + + private void InitilalizeMediaLibrary() + { + MediaLibrary ml = null; + + foreach (MediaSource source in MediaSource.GetAvailableMediaSources()) + { + if (source.MediaSourceType == MediaSourceType.LocalDevice) + { + ml = new MediaLibrary(source); + _allAlbums = ml.RootPictureAlbum.Albums; + _enumerator = _allAlbums.GetEnumerator(); + if (_enumerator.MoveNext()) + { + CurrentAlbum = _enumerator.Current; + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + MakePhotoAlbum(_enumerator.Current); + }); + } + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + if (Folders.ItemsSource == null) + { + _albums = ml.RootPictureAlbum.Albums.ToList(); + Folders.ItemsSource = ml.RootPictureAlbum.Albums.ToList(); + Folders.SelectedIndex = 0; + } + }); + } + } + } + + public static readonly DependencyProperty CurrentAlbumProperty = DependencyProperty.Register( + "CurrentAlbum", typeof (PictureAlbum), typeof (OpenPhotoPicker), new PropertyMetadata(default(PictureAlbum))); + + public PictureAlbum CurrentAlbum + { + get { return (PictureAlbum) GetValue(CurrentAlbumProperty); } + set { SetValue(CurrentAlbumProperty, value); } + } + + private PictureAlbum _album; + + private void MakePhotoAlbum(PictureAlbum album) + { + PhotoRow currentRow = null; + var stopwatch = Stopwatch.StartNew(); + var photoFiles = new List(); + var photoRow = new ObservableCollection(); + var secondSlice = new List(); + _album = album; + if (_album.Pictures.Count > 0) + { + var cropedFiles = _album.Pictures.OrderByDescending(x => x.Date).ToList(); + var maxCount = 12; + for (var i = 0; i < cropedFiles.Count; i++) + { + var p = cropedFiles[i]; + var photoFile = new PhotoFile { Picture = p, SuppressAnimation = true, IsSelected = _selectedPictures.ContainsKey(p) }; + + if (i < maxCount) + { + if (i % 3 == 0) + { + currentRow = new PhotoRow(); + photoRow.Add(currentRow); + } + Stream thumbnail; + try + { + thumbnail = p.GetThumbnail(); + } + catch (Exception e) + { + Log.Write(string.Format("OpenPhotoPicker File getThumbnail exception album={0} file={1}\n{2}", album.Name, p.Name, e)); + cropedFiles.RemoveAt(i--); + continue; + } + + photoFile.IsForeground = true; + photoFile.Thumbnail = new WeakReference(thumbnail); + photoFiles.Add(photoFile); + currentRow.Add(photoFile); + photoFile.Row = currentRow; + } + else + { + secondSlice.Add(photoFile); + } + } + } + + System.Diagnostics.Debug.WriteLine(stopwatch.Elapsed); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + CurrentAlbum = album; + if (photoRow.Count < 4) + { + Photos.VerticalAlignment = VerticalAlignment.Bottom; + } + else + { + Photos.VerticalAlignment = VerticalAlignment.Stretch; + } + Photos.ItemsSource = photoRow; + //LayoutRoot.Background = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)); + + + Photos.Visibility = Visibility.Visible; + Photos.Opacity = 0.0; + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + Photos.Opacity = 1.0; + var storyboard = new Storyboard(); + var translateAnimaiton = new DoubleAnimationUsingKeyFrames(); + translateAnimaiton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = Photos.ActualHeight }); + translateAnimaiton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = 0.0, EasingFunction = new ExponentialEase { Exponent = 5.0, EasingMode = EasingMode.EaseOut } }); + Storyboard.SetTarget(translateAnimaiton, Photos); + Storyboard.SetTargetProperty(translateAnimaiton, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateAnimaiton); + + storyboard.Begin(); + + if (secondSlice.Count > 0) + { + storyboard.Completed += (o, e) => + { + for (var i = 0; i < secondSlice.Count; i++) + { + if (i % 3 == 0) + { + currentRow = new PhotoRow(); + photoRow.Add(currentRow); + } + + photoFiles.Add(secondSlice[i]); + currentRow.Add(secondSlice[i]); + secondSlice[i].Row = currentRow; + } + }; + } + }); + }); + } + + private void PhotoControl_OnTap(object sender, GestureEventArgs e) + { + var control = sender as PhotoControl; + if (control != null) + { + var file1 = control.File; + if (file1 != null) + { + ChangePictureSelection(file1, !file1.IsSelected); + } + } + } + + private PhotoFile _previousFile; + + private void ChangePictureSelection(PhotoFile file1, bool isSelected) + { + var index = 0; + // select middle item first of all + if (!IsSingleItem + && _hasManipulatingDelta + && _previousFile != null + && _previousFile.Row == file1.Row + && file1.Row.File2.IsSelected != isSelected) + { + var row = file1.Row; + if ( + (row.File1 == _previousFile && row.File3 == file1) + || (row.File3 == _previousFile && row.File1 == file1)) + { + if (isSelected) + { + _selectedPictures[row.File2.Picture] = row.File2; + + index = _selectedPictures.Count; + } + else + { + _selectedPictures.Remove(row.File2.Picture); + + foreach (var photoFile in _selectedPictures.Values) + { + if (photoFile.Index > row.File2.Index) + { + photoFile.Index--; + photoFile.RaisePropertyChanged("Index"); + } + } + + index = 0; + } + + row.File2.SuppressAnimation = false; + row.File2.IsSelected = isSelected; + row.File2.RaisePropertyChanged("IsSelected"); + row.File2.Index = index; + row.File2.RaisePropertyChanged("Index"); + } + } + + + if (isSelected) + { + _selectedPictures[file1.Picture] = file1; + + index = _selectedPictures.Count; + } + else + { + _selectedPictures.Remove(file1.Picture); + + foreach (var photoFile in _selectedPictures.Values) + { + if (photoFile.Index > file1.Index) + { + photoFile.Index--; + photoFile.RaisePropertyChanged("Index"); + } + } + + index = 0; + } + + file1.SuppressAnimation = false; + file1.IsSelected = isSelected; + file1.RaisePropertyChanged("IsSelected"); + file1.Index = index; + file1.RaisePropertyChanged("Index"); + + _previousFile = file1; + + _selectButton.IsEnabled = _selectedPictures.Any(); + + if (IsSingleItem) + { + ChooseButton_OnClick(null, null); + LayoutRoot.IsHitTestVisible = false; + } + } + + private void Photos_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + _hasManipulatingDelta = false; + } + + private void Photos_OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + _hasManipulatingDelta = false; + } + + private bool _isSelected; + private IEnumerator _enumerator; + + private void Photos_OnManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + if (IsSingleItem) return; + + if (!_hasManipulatingDelta) + { + var grid = e.OriginalSource as Grid; + + if (grid != null) + { + var control = grid.Parent as PhotoControl; + if (control != null) + { + var file1 = control.File; + if (file1 != null) + { + ChangePictureSelection(file1, !file1.IsSelected); + _isSelected = file1.IsSelected; + } + } + } + } + + _hasManipulatingDelta = true; + } + + private void PhotoControl_OnMouseEnter(object sender, MouseEventArgs e) + { + if (!_hasManipulatingDelta) return; + + var control = sender as PhotoControl; + if (control != null) + { + var file1 = control.File; + if (file1 != null && file1.IsSelected != _isSelected) + { + ChangePictureSelection(file1, _isSelected); + } + } + } + + public event EventHandler Close; + + protected virtual void RaiseClose() + { + EventHandler handler = Close; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private void UIElement_OnTap(object sender, GestureEventArgs e) + { + BeginCloseStoryboard(RaiseClose); + //RaiseClose(); + } + + public async void StartPreview() + { + var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture); + var deviceInfo = devices[0]; //grab first result + DeviceInformation rearCamera = null; + foreach (var device in devices) + { + if (device.Name.ToLowerInvariant().Contains("front")) + { + DeviceInformation frontCamera; + deviceInfo = frontCamera = device; + var hasFrontCamera = true; + } + if (device.Name.ToLowerInvariant().Contains("back")) + { + rearCamera = device; + } + } + + var mediaSettings = new MediaCaptureInitializationSettings + { + MediaCategory = MediaCategory.Communications, + StreamingCaptureMode = StreamingCaptureMode.AudioAndVideo, + VideoDeviceId = rearCamera.Id + }; + + var mediaCaptureManager = new Windows.Media.Capture.MediaCapture(); + await mediaCaptureManager.InitializeAsync(mediaSettings); + + var previewSink = new Windows.Phone.Media.Capture.MediaCapturePreviewSink(); + + // List of supported video preview formats to be used by the default preview format selector. + var supportedVideoFormats = new List { "nv12", "rgb32" }; + + // Find the supported preview format + var availableMediaStreamProperties = + mediaCaptureManager.VideoDeviceController.GetAvailableMediaStreamProperties( + Windows.Media.Capture.MediaStreamType.VideoPreview) + .OfType() + .Where(p => p != null + && !String.IsNullOrEmpty(p.Subtype) + && supportedVideoFormats.Contains(p.Subtype.ToLower())) + .ToList(); + var previewFormat = availableMediaStreamProperties.FirstOrDefault(); + foreach (var property in availableMediaStreamProperties) + { + if (previewFormat.Width < property.Width) + { + previewFormat = property; + } + } + //previewFormat.Width = 480; + //previewFormat.Height = 480; + // Start Preview stream + await mediaCaptureManager.VideoDeviceController.SetMediaStreamPropertiesAsync(Windows.Media.Capture.MediaStreamType.VideoPreview, previewFormat); + await mediaCaptureManager.StartPreviewToCustomSinkAsync(new Windows.Media.MediaProperties.MediaEncodingProfile { Video = previewFormat }, previewSink); + + var viewfinderBrush = new VideoBrush{ Stretch = Stretch.Uniform }; + // Set the source of the VideoBrush used for your preview + Microsoft.Devices.CameraVideoBrushExtensions.SetSource(viewfinderBrush, previewSink); + CameraPreview.Background = viewfinderBrush; + + + mediaCaptureManager.SetPreviewRotation(VideoRotation.Clockwise90Degrees); + } + + private async void ChooseButton_OnClick(object sender, RoutedEventArgs e) + { + var selectedPhoto = _selectedPictures.Values.OrderBy(x => x.Index).ToList(); + + var picturesLibrary = KnownFolders.PicturesLibrary; + if (picturesLibrary != null) + { + var folder = await picturesLibrary.GetFolderAsync(_album.Name); + var folders = await picturesLibrary.GetFoldersAsync(); + + if (folder != null) + { + var getFileOperations = new List>(); + + foreach (var file in selectedPhoto) + { + getFileOperations.Add(Task.Run(async () => + { + var f = new List(); + foreach (var storageFolder in folders) + { + if (storageFolder.Name == file.Picture.Album.Name) + { + f.Add(storageFolder); + try + { + var returnFile = await storageFolder.GetFileAsync(file.Picture.Name); + return returnFile; + } + catch (Exception ex) + { + } + } + } + + string filePath = string.Empty; + try + { + filePath = file.Picture.GetPath(); + } + catch (Exception ex) + { + + } + + Log.Write(string.Format("OpenPhotoPicker File '{0}' is missing at folder '{1}'\nPath={2}\nFolders\n{3}", file.Picture.Name, file.Picture.Album, filePath, string.Join(Environment.NewLine, folders.Select(x => string.Format("Name='{0}' DisplayName='{1}' Path='{2}'", x.Name, x.DisplayName, x.Path))))); + + try + { + using (var imageStream = file.Picture.GetImage()) + { + var localFileName = string.Format("{0}_{1}_{2}", imageStream.Length, file.Picture.Album.Name, file.Picture.Name); + try + { + var localFile = await ApplicationData.Current.LocalFolder.GetFileAsync(localFileName); + return localFile; + } + catch (Exception ex) + { + + } + + var newFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(localFileName, CreationCollisionOption.ReplaceExisting); + using (Stream outputStream = await newFile.OpenStreamForWriteAsync()) + { + await imageStream.CopyToAsync(outputStream); + } + return newFile; + } + } + catch (Exception ex) + { + + } + + try + { + using (var imageStream = file.Picture.GetThumbnail()) + { + var localFileName = string.Format("{0}_{1}_{2}", imageStream.Length, file.Picture.Album.Name, file.Picture.Name); + try + { + var localFile = await ApplicationData.Current.LocalFolder.GetFileAsync(localFileName); + return localFile; + } + catch (Exception ex) + { + + } + + var newFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(localFileName, CreationCollisionOption.ReplaceExisting); + using (Stream outputStream = await newFile.OpenStreamForWriteAsync()) + { + await imageStream.CopyToAsync(outputStream); + } + return newFile; + } + } + catch (Exception ex) + { + + } + + return null; + })); + } + // wait for all operations in parallel + var result = await Task.WhenAll(getFileOperations); + var files = new List(); + var photoFiles = new List(); + + for (var i = 0; i < result.Length; i++) + { + if (result[i] != null) + { + files.Add(result[i]); + photoFiles.Add(selectedPhoto[i]); + } + } + + RaisePick(new PickEventArgs{ Files = new ReadOnlyCollection(files), PhotoFiles = new ReadOnlyCollection(photoFiles)} ); + //MessageBox.Show("Files selected: " + files.Count(x => x != null)); + System.Diagnostics.Debug.WriteLine(files.Count()); + } + } + } + + private Popup _popup; + private List _albums; + + private void ChangeButton_OnClick(object sender, RoutedEventArgs e) + { + + return; + + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + if (_enumerator.MoveNext()) + { + MakePhotoAlbum(_enumerator.Current); + } + else + { + _enumerator.Reset(); + if (_enumerator.MoveNext()) + { + MakePhotoAlbum(_enumerator.Current); + } + } + }); + } + + private void BeginOpenStoryboard() + { + LayoutRoot.IsHitTestVisible = true; + Bar.Visibility = Visibility.Collapsed; + + var rootFrameHeight = ((PhoneApplicationFrame)Application.Current.RootVisual).ActualHeight; + var translateYTo = rootFrameHeight; + + var storyboard = new Storyboard(); + var translateAnimaiton = new DoubleAnimationUsingKeyFrames(); + translateAnimaiton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = translateYTo }); + translateAnimaiton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = 0.0, EasingFunction = new ExponentialEase { Exponent = 5.0, EasingMode = EasingMode.EaseOut } }); + Storyboard.SetTarget(translateAnimaiton, Bar); + Storyboard.SetTargetProperty(translateAnimaiton, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateAnimaiton); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + Bar.Visibility = Visibility.Visible; + storyboard.Begin(); + }); + } + + private void BeginCloseStoryboard(Action callback) + { + LayoutRoot.IsHitTestVisible = false; + var duration = TimeSpan.FromSeconds(0.25); + var easingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 5.0 }; + + var storyboard = new Storyboard(); + + var rootFrameHeight = ((PhoneApplicationFrame)Application.Current.RootVisual).ActualHeight; + var translateYTo = rootFrameHeight; + var translateImageAniamtion = new DoubleAnimationUsingKeyFrames(); + translateImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = duration, Value = translateYTo, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateImageAniamtion, Photos); + Storyboard.SetTargetProperty(translateImageAniamtion, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateImageAniamtion); + + var translateBarAniamtion = new DoubleAnimationUsingKeyFrames(); + translateBarAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.15), Value = 0.0 }); + translateBarAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = translateYTo, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateBarAniamtion, Bar); + Storyboard.SetTargetProperty(translateBarAniamtion, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateBarAniamtion); + + storyboard.Begin(); + if (callback != null) + { + storyboard.Completed += (o, e) => callback(); + } + } + + private void Album_OnTap(object sender, GestureEventArgs e) + { + //ToggleFoldersVisibility(); + + var frameworkElement = sender as FrameworkElement; + if (frameworkElement != null) + { + var album = frameworkElement.DataContext as PictureAlbum; + if (album != null) + { + Folders.SelectedItem = album; + + Folders.UpdateLayout(); + Folders.ScrollIntoView(album); + + + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + MakePhotoAlbum(album); + }); + } + } + } + + public bool TryClose() + { + BeginCloseStoryboard(RaiseClose); + + return true; + } + + private void Folders_OnTap(object sender, GestureEventArgs e) + { + e.Handled = true; + } + + private void Folders_OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + + } + } + + public class PhotoRow + { + public PhotoFile File1 { get; set; } + public PhotoFile File2 { get; set; } + public PhotoFile File3 { get; set; } + + public void Add(PhotoFile file) + { + if (File1 == null) File1 = file; + else if (File2 == null) File2 = file; + else if (File3 == null) File3 = file; + } + } + + public class PhotoFile : INotifyPropertyChanged + { + public int Index { get; set; } + public bool IsSelected { get; set; } + + public WeakReference Thumbnail { get; set; } + public Picture Picture { get; set; } + public PhotoFile Self { get { return this; } } + public bool IsForeground { get; set; } + public PhotoRow Row { get; set; } + + public bool SuppressAnimation { get; set; } + + public event PropertyChangedEventHandler PropertyChanged; + + public virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChangedEventHandler handler = PropertyChanged; + if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); + } + } + + public class PickEventArgs + { + public ReadOnlyCollection Files { get; set; } + + public ReadOnlyCollection PhotoFiles { get; set; } + } + + public class PhotoConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var photoFile = value as PhotoFile; + if (photoFile != null) + { + var picture = photoFile.Picture; + Stream thumbnail = null; + + if (photoFile.Thumbnail == null + || !photoFile.Thumbnail.TryGetTarget(out thumbnail)) + { + Telegram.Api.Helpers.Execute.BeginOnThreadPool(() => + { + thumbnail = picture.GetThumbnail(); + photoFile.Thumbnail = new WeakReference(thumbnail); + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + photoFile.RaisePropertyChanged("Self"); + }); + }); + + return null; + } + + var b = new BitmapImage(); + if (!photoFile.IsForeground) + { + b.CreateOptions = BitmapCreateOptions.BackgroundCreation; + } + + b.SetSource(thumbnail); + + return b; + } + + return null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/PhotoControl.xaml b/TelegramClient.WP81/Views/Controls/PhotoControl.xaml new file mode 100755 index 0000000..dbde99a --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/PhotoControl.xaml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/PhotoControl.xaml.cs b/TelegramClient.WP81/Views/Controls/PhotoControl.xaml.cs new file mode 100755 index 0000000..02ee752 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/PhotoControl.xaml.cs @@ -0,0 +1,118 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Media; + +namespace TelegramClient.Views.Controls +{ + public partial class PhotoControl + { + public static readonly DependencyProperty SourceProperty = DependencyProperty.Register( + "Source", typeof (ImageSource), typeof (PhotoControl), new PropertyMetadata(default(ImageSource), OnSourceChanged)); + + private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var photoControl = d as PhotoControl; + if (photoControl != null) + { + var source = (ImageSource) e.NewValue; + + photoControl.ImageControl.Source = source; + } + } + + public ImageSource Source + { + get { return (ImageSource) GetValue(SourceProperty); } + set { SetValue(SourceProperty, value); } + } + + public static readonly DependencyProperty IndexProperty = DependencyProperty.Register( + "Index", typeof(int), typeof(PhotoControl), new PropertyMetadata(default(int), OnIndexChanged)); + + private static void OnIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var photoControl = d as PhotoControl; + if (photoControl != null) + { + var index = (int) e.NewValue; + var isSelected = index > 0; + + photoControl.SelectionControl.SuppressAnimation = photoControl.File != null && photoControl.File.SuppressAnimation; + photoControl.SelectionControl.IsSelected = isSelected; + photoControl.SelectionControl.Index = index; + + photoControl.SelectionBorder.Visibility = isSelected + ? Visibility.Visible + : Visibility.Collapsed; + } + } + + public int Index + { + get { return (int) GetValue(IndexProperty); } + set { SetValue(IndexProperty, value); } + } + + public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register( + "IsSelected", typeof (bool), typeof (PhotoControl), new PropertyMetadata(default(bool), OnIsSelectedChanged)); + + private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var photoControl = d as PhotoControl; + if (photoControl != null) + { + var isSelected = (bool) e.NewValue; + + photoControl.SelectionControl.SuppressAnimation = photoControl.File != null && photoControl.File.SuppressAnimation; + photoControl.SelectionControl.IsSelected = isSelected; + + photoControl.SelectionBorder.Visibility = isSelected + ? Visibility.Visible + : Visibility.Collapsed; + } + } + + public bool IsSelected + { + get { return (bool) GetValue(IsSelectedProperty); } + set { SetValue(IsSelectedProperty, value); } + } + + public static readonly DependencyProperty FileProperty = DependencyProperty.Register( + "File", typeof (PhotoFile), typeof (PhotoControl), new PropertyMetadata(default(PhotoFile), OnFileChanged)); + + private static void OnFileChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var photoControl = d as PhotoControl; + if (photoControl != null) + { + var file = e.NewValue as PhotoFile; + + photoControl.LayoutRoot.Visibility = file != null + ? Visibility.Visible + : Visibility.Collapsed; + } + } + + public PhotoFile File + { + get { return (PhotoFile) GetValue(FileProperty); } + set { SetValue(FileProperty, value); } + } + + public PhotoControl() + { + InitializeComponent(); + + LayoutRoot.Visibility = Visibility.Collapsed; + SelectionBorder.Visibility = Visibility.Collapsed; + SelectionControl.IsSelected = false; + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/Progress.xaml b/TelegramClient.WP81/Views/Controls/Progress.xaml new file mode 100755 index 0000000..e39d908 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/Progress.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/Progress.xaml.cs b/TelegramClient.WP81/Views/Controls/Progress.xaml.cs new file mode 100755 index 0000000..93c3faf --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/Progress.xaml.cs @@ -0,0 +1,280 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; + +namespace TelegramClient.Views.Controls +{ + public partial class Progress + { + public Brush BackgroundBrush + { + get { return BackgrondElement.Background; } + set { BackgrondElement.Background = value; } + } + + public static readonly DependencyProperty CancelVisibilityProperty = DependencyProperty.Register( + "CancelVisibility", typeof (Visibility), typeof (Progress), new PropertyMetadata(default(Visibility), OnCancelVisibilityChanged)); + + private static void OnCancelVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var progress = (Progress)d; + if (progress != null) + { + progress.CancelButton.Visibility = (Visibility) e.NewValue; + } + } + + public Visibility CancelVisibility + { + get { return (Visibility) GetValue(CancelVisibilityProperty); } + set { SetValue(CancelVisibilityProperty, value); } + } + + public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( + "Value", typeof(double), typeof(Progress), new PropertyMetadata(default(double), OnValueChanged)); + + private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var progress = (Progress)d; + if (progress != null) + { + double newAngle = 0.0; + if (e.OldValue != null + && e.NewValue != null + && (double) e.OldValue > 0.0 + && (double) e.OldValue < 1.0 + && (double) e.NewValue == 0.0) + { + newAngle = 0.0; //359.0; + } + else + { + newAngle = (double)e.NewValue * 359.0; + if (newAngle < 0.0) + { + newAngle = 0.0; + } + else if (newAngle > 359.0) + { + newAngle = 359.0; + } + } + + if (newAngle != progress.Indicator.Angle) + { + if (newAngle > 0.0 && newAngle < 359.0) + { + progress.Visibility = Visibility.Visible; + } + + progress._angleStoryboard.Stop(); + if (newAngle > progress.Indicator.Angle) + { + var doubleAnimation = (DoubleAnimation)progress._angleStoryboard.Children[0]; + doubleAnimation.To = newAngle; + progress._angleStoryboard.Begin(); + } + else + { + progress.Indicator.Angle = newAngle; + if (progress.Value >= 1.0 || progress.Value <= 0.0) + { + progress.Visibility = Visibility.Collapsed; + } + } + } + } + } + + public double Value + { + get { return (double)GetValue(ValueProperty); } + set { SetValue(ValueProperty, value); } + } + + private readonly Storyboard _angleStoryboard; + + private readonly Storyboard _foreverStoryboard; + + public Progress() + { + InitializeComponent(); + + Visibility = Visibility.Collapsed; + + _foreverStoryboard = new Storyboard { RepeatBehavior = RepeatBehavior.Forever }; + var animation = new DoubleAnimation + { + From = 0, + To = 360, + Duration = TimeSpan.FromSeconds(3.0) + }; + Storyboard.SetTarget(animation, Rotation); + Storyboard.SetTargetProperty(animation, new PropertyPath("(RotateTransform.Angle)")); + _foreverStoryboard.Children.Add(animation); + _foreverStoryboard.Completed += OnForeverStoryboardCompleted; + + + _angleStoryboard = new Storyboard(); + var angleAnimation = new DoubleAnimation + { + Duration = TimeSpan.FromSeconds(.25), + }; + Storyboard.SetTarget(angleAnimation, Indicator); + Storyboard.SetTargetProperty(angleAnimation, new PropertyPath("Angle")); + _angleStoryboard.Children.Add(angleAnimation); + _angleStoryboard.Completed += OnAngleStoryboardCompleted; + + Loaded += (sender, args) => + { + _foreverStoryboard.RepeatBehavior = RepeatBehavior.Forever; + _foreverStoryboard.Begin(); + }; + Unloaded += (sender, args) => + { + _foreverStoryboard.RepeatBehavior = new RepeatBehavior(1.0); + }; + + } + + private void OnAngleStoryboardCompleted(object sender, System.EventArgs e) + { + if (Value >= 1.0 || Value <= 0.0) + { + Visibility = Visibility.Collapsed; + RaiseCompleted(); + } + } + + public event EventHandler Completed; + + protected virtual void RaiseCompleted() + { + var handler = Completed; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private void OnForeverStoryboardCompleted(object sender, System.EventArgs e) + { + + + } + + private void Border_OnTap(object sender, GestureEventArgs e) + { + if (Value > 0.0 && Value < 1.0) + { + RaiseCancel(e); + Visibility = Visibility.Collapsed; + } + } + + public event EventHandler Cancel; + + protected virtual void RaiseCancel(GestureEventArgs args) + { + var handler = Cancel; + if (handler != null) handler(this, args); + } + } + + public class ProgressPieSlice : Path + { + private bool m_HasLoaded = false; + + public ProgressPieSlice() + { + Loaded += (s, e) => + { + m_HasLoaded = true; + UpdatePath(); + }; + } + + // StartAngle + public static readonly DependencyProperty StartAngleProperty + = DependencyProperty.Register("StartAngle", typeof(double), typeof(ProgressPieSlice), + new PropertyMetadata(DependencyProperty.UnsetValue, (s, e) => { Changed(s as ProgressPieSlice); })); + public double StartAngle + { + get { return (double)GetValue(StartAngleProperty); } + set { SetValue(StartAngleProperty, value); } + } + + // Angle + public static readonly DependencyProperty AngleProperty + = DependencyProperty.Register("Angle", typeof(double), typeof(ProgressPieSlice), + new PropertyMetadata(DependencyProperty.UnsetValue, (s, e) => { Changed(s as ProgressPieSlice); })); + public double Angle + { + get { return (double)GetValue(AngleProperty); } + set { SetValue(AngleProperty, value); } + } + + // Radius + public static readonly DependencyProperty RadiusProperty + = DependencyProperty.Register("Radius", typeof(double), typeof(ProgressPieSlice), + new PropertyMetadata(DependencyProperty.UnsetValue, (s, e) => { Changed(s as ProgressPieSlice); })); + public double Radius + { + get { return (double)GetValue(RadiusProperty); } + set { SetValue(RadiusProperty, value); } + } + + private static void Changed(ProgressPieSlice pieSlice) + { + if (pieSlice.m_HasLoaded) + pieSlice.UpdatePath(); + } + + public void UpdatePath() + { + // ensure variables + if (GetValue(StartAngleProperty) == DependencyProperty.UnsetValue) + throw new ArgumentNullException("Start Angle is required"); + if (GetValue(RadiusProperty) == DependencyProperty.UnsetValue) + throw new ArgumentNullException("Radius is required"); + if (GetValue(AngleProperty) == DependencyProperty.UnsetValue) + throw new ArgumentNullException("Angle is required"); + + Width = Height = 2 * Radius + StrokeThickness; + var endAngle = StartAngle + Angle; + + // path container + var figure = new PathFigure + { + StartPoint = new Point(Radius + StrokeThickness / 2.0, 0 + StrokeThickness / 2.0), + IsClosed = false, + }; + + // outer arc + var arcX = Radius + Math.Sin(endAngle * Math.PI / 180) * Radius + StrokeThickness / 2.0; + var arcY = Radius - Math.Cos(endAngle * Math.PI / 180) * Radius + StrokeThickness / 2.0; + var arcSize = new Size(Radius, Radius); + var arcPoint = new Point(arcX, arcY); + var arc = new ArcSegment + { + IsLargeArc = Angle >= 180.0, + Point = arcPoint, + Size = arcSize, + SweepDirection = SweepDirection.Clockwise, + }; + figure.Segments.Add(arc); + + // finalé + Data = new PathGeometry { Figures = { figure } }; + + InvalidateArrange(); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/ProxyStatusControl.xaml b/TelegramClient.WP81/Views/Controls/ProxyStatusControl.xaml new file mode 100755 index 0000000..12426d3 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/ProxyStatusControl.xaml @@ -0,0 +1,127 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/ProxyStatusControl.xaml.cs b/TelegramClient.WP81/Views/Controls/ProxyStatusControl.xaml.cs new file mode 100755 index 0000000..46bb32e --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/ProxyStatusControl.xaml.cs @@ -0,0 +1,63 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; + +namespace TelegramClient.Views.Controls +{ + public partial class ProxyStatusControl + { + public static readonly DependencyProperty ConnectionTypeProperty = DependencyProperty.Register( + "ConnectionType", typeof(ConnectionType), typeof(ProxyStatusControl), new PropertyMetadata(default(ConnectionType), OnConnectionTypeChanged)); + + private static void OnConnectionTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var proxyStatusControl = d as ProxyStatusControl; + if (proxyStatusControl != null) + { + proxyStatusControl.Progress.Style = (ConnectionType) e.NewValue == ConnectionType.Direct + ? (Style) proxyStatusControl.Resources["DirectProgressBarStyle"] + : (Style) proxyStatusControl.Resources["ProxyProgressBarStyle"]; + } + } + + public ConnectionType ConnectionType + { + get { return (ConnectionType) GetValue(ConnectionTypeProperty); } + set { SetValue(ConnectionTypeProperty, value); } + } + + public static readonly DependencyProperty IsIndeterminateProperty = DependencyProperty.Register( + "IsIndeterminate", typeof(bool), typeof(ProxyStatusControl), new PropertyMetadata(true, OnIsIndeterminateChanged)); + + private static void OnIsIndeterminateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as ProxyStatusControl; + if (control != null) + { + control.Progress.IsIndeterminate = (bool)e.NewValue; + } + } + + public bool IsIndeterminate + { + get { return (bool) GetValue(IsIndeterminateProperty); } + set { SetValue(IsIndeterminateProperty, value); } + } + + public ProxyStatusControl() + { + InitializeComponent(); + } + } + + public enum ConnectionType + { + Proxy, + Direct + } +} diff --git a/TelegramClient.WP81/Views/Controls/RecordingControl.xaml b/TelegramClient.WP81/Views/Controls/RecordingControl.xaml new file mode 100755 index 0000000..069a3a8 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/RecordingControl.xaml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/RecordingControl.xaml.cs b/TelegramClient.WP81/Views/Controls/RecordingControl.xaml.cs new file mode 100755 index 0000000..bf0be1c --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/RecordingControl.xaml.cs @@ -0,0 +1,31 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace TelegramClient.Views.Controls +{ + public partial class RecordingControl + { + public RecordingControl() + { + InitializeComponent(); + + Loaded += (sender, args) => + { + Storyboard1.Begin(); + Storyboard2.Begin(); + Storyboard3.Begin(); + }; + + Unloaded += (sender, args) => + { + Storyboard1.Stop(); + Storyboard2.Stop(); + Storyboard3.Stop(); + }; + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/RibbonControl.xaml b/TelegramClient.WP81/Views/Controls/RibbonControl.xaml new file mode 100755 index 0000000..3885d8f --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/RibbonControl.xaml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/RibbonControl.xaml.cs b/TelegramClient.WP81/Views/Controls/RibbonControl.xaml.cs new file mode 100755 index 0000000..a0c6074 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/RibbonControl.xaml.cs @@ -0,0 +1,370 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Animation; +using Telegram.Api.Extensions; +using TelegramClient.Behaviors; + +namespace TelegramClient.Views.Controls +{ + public partial class RibbonControl + { + public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register( + "ItemTemplate", typeof(DataTemplate), typeof(RibbonControl), new PropertyMetadata(default(DataTemplate), OnItemTemplateChanged)); + + private static void OnItemTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as RibbonControl; + if (control != null) + { + control.Items.ItemTemplate = e.NewValue as DataTemplate; + } + } + + public DataTemplate ItemTemplate + { + get { return (DataTemplate) GetValue(ItemTemplateProperty); } + set { SetValue(ItemTemplateProperty, value); } + } + + public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register( + "ItemsSource", typeof(IList), typeof(RibbonControl), new PropertyMetadata(default(IList), OnItemsSourceChanged)); + + private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as RibbonControl; + if (control != null) + { + var collectionChangedOld = e.OldValue as INotifyCollectionChanged; + if (collectionChangedOld != null) + { + collectionChangedOld.CollectionChanged -= control.OnCollectionChanged; + } + + control.Items.ItemsSource = e.NewValue as IList; + control.Clear(); + + var collectionChangedNew = e.NewValue as INotifyCollectionChanged; + if (collectionChangedNew != null) + { + collectionChangedNew.CollectionChanged += control.OnCollectionChanged; + } + } + } + + private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) + { + Clear(); + } + + public IList ItemsSource + { + get { return (IList)GetValue(ItemsSourceProperty); } + set { SetValue(ItemsSourceProperty, value); } + } + + public RibbonControl() + { + InitializeComponent(); + + Items.PrepareContainerForItem = PrepareContainerForItem; + } + + private void PrepareContainerForItem(DependencyObject element, object item) + { + var contentPresenter = element as ContentPresenter; + if (contentPresenter != null) + { + var index = Items.Items.IndexOf(item); + contentPresenter.RenderTransform = new TranslateTransform { X = index * RibbonImageControl.MinExpandedWidth }; + + var ribbonImageControl = GetChild(contentPresenter); + if (ribbonImageControl != null) + { + ribbonImageControl.Prepare(); + } + } + } + + private int _selectedIndex = -1; + + private double _minTranslationX; + + private double _maxTranslationX; + + private double _translationX; + + private RibbonImageControl _previousImage; + + private ContentPresenter _previousContainer; + + private RibbonImageControl _currentImage; + + private ContentPresenter _currentContainer; + + private RibbonImageControl _nextImage; + + private ContentPresenter _nextContainer; + + public TranslateTransform Transform = new TranslateTransform(); + + private void Clear() + { + _selectedIndex = -1; + _minTranslationX = 0.0; + _maxTranslationX = 0.0; + _translationX = 0.0; + _previousImage = null; + _currentImage = null; + _nextImage = null; + } + + public bool ScrollTo(int index, double duration) + { + if (index == _selectedIndex) + { + AnimatePosition(_currentImage, _currentImage != null ? _currentImage.ExpandedWidth : RibbonImageControl.MinExpandedWidth, _toImage, RibbonImageControl.MinExpandedWidth, Transform, _translationX, duration); + + return true; + } + + ContentPresenter fromContainer; + ContentPresenter toContainer; + var fromItem = FindAtIndex(Items, _selectedIndex, out fromContainer); + var toItem = FindAtIndex(Items, index, out toContainer); + + if (toItem == null) + { + var translationX = index > _selectedIndex ? _minTranslationX : _maxTranslationX; + AnimatePosition(fromItem, RibbonImageControl.MinExpandedWidth, null, 0, Transform, translationX, duration); + + return false; + } + + _selectedIndex = index; + + _previousImage = FindAtIndex(Items, _selectedIndex - 1, out _previousContainer); + _currentImage = toItem; + _currentContainer = toContainer; + _nextImage = FindAtIndex(Items, _selectedIndex + 1, out _nextContainer); + + _minTranslationX = -(_selectedIndex + 1) * RibbonImageControl.MinExpandedWidth - (_nextImage != null ? _nextImage.ExpandedWidth / 2.0 : RibbonImageControl.MaxExpandedWidth / 2.0); + _maxTranslationX = -(_selectedIndex - 1) * RibbonImageControl.MinExpandedWidth - (_previousImage != null ? _previousImage.ExpandedWidth / 2.0 : RibbonImageControl.MinExpandedWidth - RibbonImageControl.MaxExpandedWidth / 2.0); + _translationX = -(RibbonImageControl.MinExpandedWidth * index + toItem.ExpandedWidth / 2.0); + + AnimatePosition(fromItem, RibbonImageControl.MinExpandedWidth, toItem, toItem.ExpandedWidth, Transform, -(RibbonImageControl.MinExpandedWidth * index + toItem.ExpandedWidth / 2.0), duration); + + return true; + } + + public bool ScrollNext(double duration) + { + return ScrollTo(_selectedIndex + 1, duration); + } + + public bool ScrollPrevious(double duration) + { + return ScrollTo(_selectedIndex - 1, duration); + } + + public bool ScrollBack(double duration) + { + return ScrollTo(_selectedIndex, duration); + } + + private void AnimatePosition(RibbonImageControl currentControl, double currentWidth, RibbonImageControl nextControl, double nextWidth, TranslateTransform transform, double translateXAll, double duration) + { + var storyboard = new Storyboard(); + +//#if EXTENDED_LENGTH + if (currentControl != null) + { + var currentWidthAnimation = new DoubleAnimation(); + currentWidthAnimation.To = currentWidth; + currentWidthAnimation.Duration = new Duration(TimeSpan.FromSeconds(duration)); + Storyboard.SetTarget(currentWidthAnimation, currentControl); + Storyboard.SetTargetProperty(currentWidthAnimation, new PropertyPath("Width")); + storyboard.Children.Add(currentWidthAnimation); + } + + if (nextControl != null && nextControl != currentControl) + { + var nextWidthAnimation = new DoubleAnimation(); + nextWidthAnimation.To = nextWidth; + nextWidthAnimation.Duration = new Duration(TimeSpan.FromSeconds(duration)); + Storyboard.SetTarget(nextWidthAnimation, nextControl); + Storyboard.SetTargetProperty(nextWidthAnimation, new PropertyPath("Width")); + storyboard.Children.Add(nextWidthAnimation); + } +//#endif + + //var translateXAnimation = new DoubleAnimation(); + //translateXAnimation.To = translateX; + //translateXAnimation.Duration = new Duration(TimeSpan.FromSeconds(duration)); + //Storyboard.SetTarget(translateXAnimation, transform); + //Storyboard.SetTargetProperty(translateXAnimation, new PropertyPath("X")); + //storyboard.Children.Add(translateXAnimation); + + var x = 0.0; + for (var i = 0; i < Items.Items.Count; i++) + { + ContentPresenter container; + var image = FindAtIndex(Items, i, out container); + if (container != null) + { + var animation = new DoubleAnimation(); + animation.To = x + translateXAll; + animation.Duration = new Duration(TimeSpan.FromSeconds(duration)); + Storyboard.SetTarget(animation, container.RenderTransform); + Storyboard.SetTargetProperty(animation, new PropertyPath("X")); + storyboard.Children.Add(animation); + + //container.RenderTransform = new TranslateTransform { X = x }; + //x += image.Width; + + if (image == currentControl) + { + x += currentWidth; + } + else if (image == nextControl) + { + x += nextWidth; + } + else if (image != null) + { + x += image.Width; + } + } + } + + + storyboard.Begin(); + } + + private RibbonImageControl _toImage; + + private ContentPresenter _toContainer; + + public void Move(double percent) + { + percent = PanAndZoomBehavior.Clamp(percent, -1.0, 1.0); + + var translateX = percent < 0.0 + ? _translationX - (_minTranslationX - _translationX) * percent + : _translationX + (_maxTranslationX - _translationX) * percent; + + //Transform.X = translateX; + + if (_currentImage != null) + { + _currentImage.Width = _currentImage.ExpandedWidth - (_currentImage.ExpandedWidth - RibbonImageControl.MinExpandedWidth) * Math.Abs(percent); + } + + _toImage = percent < 0.0 ? _nextImage : _previousImage; + if (_toImage != null) + { + _toImage.Width = RibbonImageControl.MinExpandedWidth + (_toImage.ExpandedWidth - RibbonImageControl.MinExpandedWidth) * Math.Abs(percent); + } + + _toContainer = percent < 0.0 ? _nextContainer : _previousContainer; + + var x = 0.0; + for (var i = 0; i < Items.Items.Count; i++) + { + ContentPresenter container; + var image = FindAtIndex(Items, i, out container); + if (container != null) + { + container.RenderTransform = new TranslateTransform { X = x + translateX }; + x += image.Width; + + //if (container == _toContainer) + //{ + // x += _toImage.Width; + //} + //else if (container == _currentContainer) + //{ + // x += _currentImage.Width; + //} + //else if (container != null) + //{ + // x += image.Width; + //} + } + } + } + + private static T FindAtIndex(ItemsControl itemsControl, int index, out ContentPresenter container) where T : DependencyObject + { + container = null; + var item = index >= 0 && index < itemsControl.Items.Count ? itemsControl.Items[index] : null; + if (item != null) + { + container = itemsControl.ItemContainerGenerator.ContainerFromIndex(index) as ContentPresenter; + if (container != null) + { + return GetChild(container); + } + } + return null; + } + + private static T GetChild(DependencyObject obj) where T : DependencyObject + { + int childrenCount = VisualTreeHelper.GetChildrenCount(obj); + for (int i = 0; i < childrenCount; i++) + { + var child = VisualTreeHelper.GetChild(obj, i); + var result = child as T; + if (result != null) + { + return result; + } + result = GetChild(child); + if (result != null) + { + return result; + } + } + return null; + } + } + public class CachingItemsControl : ItemsControl + { + private readonly Stack _cache = + new Stack(); + + protected override DependencyObject GetContainerForItemOverride() + { + return + _cache.Count > 0 + ? _cache.Pop() + : base.GetContainerForItemOverride(); + } + + protected override void ClearContainerForItemOverride(DependencyObject element, object item) + { + _cache.Push(element); + } + + public Action PrepareContainerForItem; + + protected override void PrepareContainerForItemOverride(DependencyObject element, object item) + { + PrepareContainerForItem.SafeInvoke(element, item); + + base.PrepareContainerForItemOverride(element, item); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/RibbonImageControl.xaml b/TelegramClient.WP81/Views/Controls/RibbonImageControl.xaml new file mode 100755 index 0000000..f4bfc5d --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/RibbonImageControl.xaml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/RibbonImageControl.xaml.cs b/TelegramClient.WP81/Views/Controls/RibbonImageControl.xaml.cs new file mode 100755 index 0000000..5b863d2 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/RibbonImageControl.xaml.cs @@ -0,0 +1,156 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +#define EXTENDED_LENGTH +using System; +using System.Windows; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; + +namespace TelegramClient.Views.Controls +{ + public partial class RibbonImageControl + { + public static readonly DependencyProperty PhotoWidthProperty = DependencyProperty.Register( + "PhotoWidth", typeof(double), typeof(RibbonImageControl), new PropertyMetadata(default(double), OnPhotoWidthChanged)); + + private static void OnPhotoWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as RibbonImageControl; + if (control != null) + { + control.SetPhotoDimenstion((double) e.NewValue, control.PhotoHeight); + } + } + + private void SetPhotoDimenstion(double width, double height) + { + if (height > 0.0 && width > 0.0) + { + var minWidth = _minExpandedWidth; + var maxWidth = 2 * _minExpandedWidth; + Photo.Width = _height / height * width; + + if (Photo.Width < minWidth) Photo.Width = minWidth; + if (Photo.Width > maxWidth) Photo.Width = maxWidth; + } + } + + public double PhotoWidth + { + get { return (double) GetValue(PhotoWidthProperty); } + set { SetValue(PhotoWidthProperty, value); } + } + + public static readonly DependencyProperty PhotoHeightProperty = DependencyProperty.Register( + "PhotoHeight", typeof(double), typeof(RibbonImageControl), new PropertyMetadata(default(double), OnPhotoHeightChanged)); + + private static void OnPhotoHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as RibbonImageControl; + if (control != null) + { + control.SetPhotoDimenstion(control.PhotoWidth, (double) e.NewValue); + } + } + + public double PhotoHeight + { + get { return (double) GetValue(PhotoHeightProperty); } + set { SetValue(PhotoHeightProperty, value); } + } + + public static readonly DependencyProperty SourceProperty = DependencyProperty.Register( + "Source", typeof(ImageSource), typeof(RibbonImageControl), new PropertyMetadata(default(ImageSource), OnSourceChanged)); + + private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as RibbonImageControl; + if (control != null) + { + control.Photo.Source = e.NewValue as ImageSource; + + var bitmapImage = control.Photo.Source as BitmapImage; + if (bitmapImage != null && (bitmapImage.PixelHeight > 0 || bitmapImage.PixelWidth > 0)) + { + control.Photo.Opacity = 1.0; + } + else + { + control.Photo.Opacity = 0.0; + } + } + } + + public ImageSource Source + { + get { return (ImageSource)GetValue(SourceProperty); } + set { SetValue(SourceProperty, value); } + } + + public RibbonImageControl() + { + InitializeComponent(); + + Photo.Width = MinExpandedWidth; + Photo.Height = _height; + } + + private void Photo_OnImageOpened(object sender, RoutedEventArgs e) + { + var storyboard = new Storyboard(); + + var opacityAnimation = new DoubleAnimation(); + opacityAnimation.To = 1.0; + opacityAnimation.Duration = TimeSpan.FromSeconds(.25); + + Storyboard.SetTarget(opacityAnimation, Photo); + Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath("Opacity")); + + storyboard.Children.Add(opacityAnimation); + + storyboard.Begin(); + } + + private double _height = 60.0; + + private static double _minExpandedWidth = 40.0; + + public static double MinExpandedWidth + { + get { return _minExpandedWidth; } + } + + public double ExpandedWidth + { + get + { +#if EXTENDED_LENGTH + var minWidth = MinExpandedWidth; + var maxWidth = MaxExpandedWidth; + return Photo.Width < minWidth ? minWidth : (Photo.Width > maxWidth) ? maxWidth : Photo.Width; +#else + return MinExpandedWidth; +#endif + } + } + + public static double MaxExpandedWidth + { + get { return _minExpandedWidth * 2.0; } + } + + public void Prepare() + { + if (Width > MinExpandedWidth) + { + Width = MinExpandedWidth; + } + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/SelectionControl.xaml b/TelegramClient.WP81/Views/Controls/SelectionControl.xaml new file mode 100755 index 0000000..ff7d9d7 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/SelectionControl.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/SelectionControl.xaml.cs b/TelegramClient.WP81/Views/Controls/SelectionControl.xaml.cs new file mode 100755 index 0000000..fe092f2 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/SelectionControl.xaml.cs @@ -0,0 +1,148 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Media; +using System.Windows.Media.Animation; + +namespace TelegramClient.Views.Controls +{ + public partial class SelectionControl + { + public static readonly DependencyProperty SelectedBorderBrushProperty = DependencyProperty.Register( + "SelectedBorderBrush", typeof(Brush), typeof(SelectionControl), new PropertyMetadata(default(Brush), OnSelectedBorderBrushChanged)); + + public Brush SelectedBorderBrush + { + get { return (Brush)GetValue(SelectedBorderBrushProperty); } + set { SetValue(SelectedBorderBrushProperty, value); } + } + + private static void OnSelectedBorderBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as SelectionControl; + if (control != null) + { + if (control.IsSelected) + { + control.Border.BorderBrush = e.NewValue as Brush; + } + } + } + + public static readonly DependencyProperty UnselectedBorderBrushProperty = DependencyProperty.Register( + "UnselectedBorderBrush", typeof(Brush), typeof(SelectionControl), new PropertyMetadata(default(Brush), OnUnselectedBorderBrushChanged)); + + public Brush UnselectedBorderBrush + { + get { return (Brush)GetValue(UnselectedBorderBrushProperty); } + set { SetValue(UnselectedBorderBrushProperty, value); } + } + + private static void OnUnselectedBorderBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as SelectionControl; + if (control != null) + { + if (!control.IsSelected) + { + control.Border.BorderBrush = e.NewValue as Brush; + } + } + } + + public static readonly DependencyProperty IndexProperty = DependencyProperty.Register( + "Index", typeof(int), typeof(SelectionControl), new PropertyMetadata(default(int), OnIndexChanged)); + + private static void OnIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as SelectionControl; + if (control != null) + { + var index = (int) e.NewValue; + + control.Label.Text = index.ToString(); + control.Label.Visibility = index > 0 ? Visibility.Visible : Visibility.Collapsed; + control.Path.Visibility = Visibility.Collapsed; + } + } + + public int Index + { + get { return (int) GetValue(IndexProperty); } + set { SetValue(IndexProperty, value); } + } + + public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register( + "IsSelected", typeof (bool), typeof (SelectionControl), new PropertyMetadata(default(bool), OnIsSelectedChanged)); + + private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var selectionControl = d as SelectionControl; + if (selectionControl != null) + { + var isSelected = (bool) e.NewValue; + + if (!selectionControl.SuppressAnimation) + { + var toValue = !isSelected ? 0.75 : 1.25; + var easingFunction = new ExponentialEase { Exponent = 2.0, EasingMode = EasingMode.EaseOut }; + var storyboard = new Storyboard(); + var scaleXAnimation = new DoubleAnimationUsingKeyFrames(); + scaleXAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.2), Value = toValue, EasingFunction = easingFunction }); + scaleXAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = 1.0, EasingFunction = easingFunction }); + Storyboard.SetTarget(scaleXAnimation, selectionControl.ScaleTransform); + Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath("ScaleX")); + storyboard.Children.Add(scaleXAnimation); + var scaleYAnimation = new DoubleAnimationUsingKeyFrames(); + scaleYAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.2), Value = toValue, EasingFunction = easingFunction }); + scaleYAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = 1.0, EasingFunction = easingFunction }); + Storyboard.SetTarget(scaleYAnimation, selectionControl.ScaleTransform); + Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath("ScaleY")); + storyboard.Children.Add(scaleYAnimation); + + storyboard.Begin(); + } + + selectionControl.Border.BorderBrush = isSelected + ? selectionControl.SelectedBorderBrush ?? selectionControl.Border.BorderBrush + : selectionControl.UnselectedBorderBrush ?? selectionControl.Border.BorderBrush; + + selectionControl.Border.Background = isSelected + ? (Brush) selectionControl.Resources["CustomAccentBrush"] + : null; + selectionControl.Path.Visibility = isSelected + ? Visibility.Visible + : Visibility.Collapsed; + } + } + + public bool IsSelected + { + get { return (bool) GetValue(IsSelectedProperty); } + set { SetValue(IsSelectedProperty, value); } + } + + public static readonly DependencyProperty SuppressAnimationProperty = DependencyProperty.Register( + "SuppressAnimation", typeof (bool), typeof (SelectionControl), new PropertyMetadata(default(bool))); + + public bool SuppressAnimation + { + get { return (bool) GetValue(SuppressAnimationProperty); } + set { SetValue(SuppressAnimationProperty, value); } + } + + public SelectionControl() + { + InitializeComponent(); + + Border.Background = null; + Path.Visibility = Visibility.Collapsed; + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/ShareMessagePicker.xaml b/TelegramClient.WP81/Views/Controls/ShareMessagePicker.xaml new file mode 100755 index 0000000..56049a6 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/ShareMessagePicker.xaml @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/ShareMessagePicker.xaml.cs b/TelegramClient.WP81/Views/Controls/ShareMessagePicker.xaml.cs new file mode 100755 index 0000000..5d6483a --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/ShareMessagePicker.xaml.cs @@ -0,0 +1,1361 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using Windows.UI.ViewManagement; +using Caliburn.Micro; +using Microsoft.Phone.Controls; +using Telegram.Api.Extensions; +using Telegram.Api.Services; +using Telegram.Api.Services.Cache; +using Telegram.Api.TL; +using Telegram.Controls; +using Telegram.Controls.Utils; +using TelegramClient.Services; +using TelegramClient.ViewModels.Dialogs; +using Action = System.Action; +using Execute = Telegram.Api.Helpers.Execute; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Controls +{ + public partial class ShareMessagePicker + { + public static readonly DependencyProperty CommentProperty = DependencyProperty.Register( + "Comment", typeof(string), typeof(ShareMessagePicker), new PropertyMetadata(default(string))); + + public string Comment + { + get { return (string) GetValue(CommentProperty); } + set { SetValue(CommentProperty, value); } + } + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register( + "Text", typeof(string), typeof(ShareMessagePicker), new PropertyMetadata(default(string), OnTextChanged)); + + private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var picker = d as ShareMessagePicker; + if (picker != null) + { + picker.Search(); + } + } + + public string Text + { + get { return (string) GetValue(TextProperty); } + set { SetValue(TextProperty, value); } + } + + private readonly Dictionary _selectedPictures = new Dictionary(); + + public TLDialogBase CurrentDialog { get; set; } + + public List DialogsSource { get; protected set; } + + public ShareMessagePicker() + { + InitializeComponent(); + + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + if (isLightTheme) + { + ((SolidColorBrush)Resources["BackgroundBrush"]).Color = ((SolidColorBrush)Resources["LightThemeBackgroundBrush"]).Color; + } + else + { + ((SolidColorBrush)Resources["BackgroundBrush"]).Color = ((SolidColorBrush)Resources["DarkThemeBackgroundBrush"]).Color; + } + + Rows = new BindableCollection(); + DialogsSource = new List(); + + InitilalizeDialogs(); + + Bar.Visibility = Visibility.Collapsed; + + Loaded += OnLoadedOnce; + Loaded += OnLoaded; + Unloaded += OnUnloaded; + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + InputPane.GetForCurrentView().Showing += InputPane_Showing; + InputPane.GetForCurrentView().Hiding += InputPane_Hiding; + } + + private void InputPane_Hiding(InputPane sender, InputPaneVisibilityEventArgs args) + { + KeyboardPlaceholder.Visibility = Visibility.Collapsed; + } + + private void InputPane_Showing(InputPane sender, InputPaneVisibilityEventArgs args) + { + var keyboardHeight = 480.0 / args.OccludedRect.Width * args.OccludedRect.Height - AppBar.ActualHeight + 18.0; + + KeyboardPlaceholder.Visibility = Visibility.Visible; + KeyboardPlaceholder.Height = keyboardHeight; + } + + private void OnUnloaded(object sender, RoutedEventArgs e) + { + InputPane.GetForCurrentView().Showing -= InputPane_Showing; + InputPane.GetForCurrentView().Hiding -= InputPane_Hiding; + } + + //~ShareMessagePicker() + //{ + + //} + + private void InitilalizeDialogs() + { + Execute.BeginOnThreadPool(() => + { + LoadDialogs(); + }); + } + + private static bool Skip(TLDialogBase d) + { + if (d is TLEncryptedDialog) + { + return true; + } + + var user = d.With as TLUser; + if (user != null && user.IsSelf) + { + return true; + } + + if (user != null && user.IsDeleted) + { + return true; + } + + var channel = d.With as TLChannel; + if (channel != null && channel.Left.Value) + { + return true; + } + + var chat = d.With as TLChat41; + if (chat != null && chat.IsMigrated) + { + return true; + } + + if (channel != null && !channel.IsMegaGroup && !(channel.IsEditor || channel.Creator)) + { + return true; + } + + var chatForbidden = d.With as TLChatForbidden; + if (chatForbidden != null) + { + return true; + } + + return false; + } + + public BindableCollection Rows { get; set; } + + private IList _dialogs; + + private void LoadDialogs() + { + TLDialogBase currentUserDialog = null; + _dialogs = IoC.Get().GetDialogs(); + + var clearedDialogs = new List(); + foreach (var d in _dialogs) + { + if (Skip(d)) + { + var user = d.With as TLUser; + if (user != null && user.IsSelf) + { + currentUserDialog = d; + } + + continue; + } + + clearedDialogs.Add(d); + } + + if (currentUserDialog != null) + { + clearedDialogs.Insert(0, currentUserDialog); + } + else + { + var currentUser = IoC.Get().GetUser(new TLInt(IoC.Get().CurrentUserId)); + + currentUserDialog = new TLDialog{ Peer = new TLPeerUser{ Id = currentUser.Id }, With = currentUser }; + clearedDialogs.Insert(0, currentUserDialog); + } + + _dialogsSource = clearedDialogs; + + DialogRow currentRow = null; + var rows = new Group("group"); + Rows = rows; + var groups = new ObservableCollection>{ rows }; + var secondSlice = new List(); + if (clearedDialogs.Count > 0) + { + var maxFirstSliceCount = 12; + var maxSecondSliceCount = 24; + for (var i = 0; i < clearedDialogs.Count; i++) + { + if (i % 4 == 0) + { + currentRow = new DialogRow(); + if (i < maxFirstSliceCount) + { + rows.Add(currentRow); + } + else if (i < maxSecondSliceCount) + { + secondSlice.Add(currentRow); + } + } + + var d = new DialogItem { Dialog = clearedDialogs[i], Row = currentRow }; + + DialogsSource.Add(d); + + currentRow.Add(d); + } + } + + var lastDialog = _dialogs.LastOrDefault(x => x is TLDialog) as TLDialog; + UpdateDialogsAsync(lastDialog); + + Execute.BeginOnUIThread(() => + { + SetListVerticalAlignment(Rows.Count); + Dialogs.ItemsSource = groups; + Dialogs.Visibility = Visibility.Visible; + Dialogs.Opacity = 0.0; + + Execute.BeginOnUIThread(() => + { + Dialogs.Opacity = 1.0; + var storyboard = new Storyboard(); + var translateAnimaiton = new DoubleAnimationUsingKeyFrames(); + translateAnimaiton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = Dialogs.ActualHeight }); + translateAnimaiton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = 0.0, EasingFunction = new ExponentialEase { Exponent = 5.0, EasingMode = EasingMode.EaseOut } }); + Storyboard.SetTarget(translateAnimaiton, Dialogs); + Storyboard.SetTargetProperty(translateAnimaiton, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateAnimaiton); + + storyboard.Begin(); + + if (secondSlice.Count > 0) + { + storyboard.Completed += (o, e) => + { + foreach (var item in secondSlice) + { + Rows.Add(item); + } + _secondSliceLoaded = true; + + LoadNextSlice(); + }; + } + else + { + _secondSliceLoaded = true; + + LoadNextSlice(); + } + }); + }); + } + + private bool _secondSliceLoaded; + + private void LoadLastSlice() + { + if (_lastSlice != null && _lastSlice.Count > 0) + { + var lastSlice = _lastSlice; + _lastSlice = null; + + LoadNextRows(lastSlice); + } + } + + private void LoadNextRows(List rows) + { + for (var i = 0; i < 5; i++) + { + var row = rows.FirstOrDefault(); + if (row != null) + { + rows.RemoveAt(0); + + Rows.Add(row); + } + else + { + return; + } + } + + if (rows.Count > 0) + { + Execute.BeginOnUIThread(() => + { + LoadNextRows(rows); + }); + } + } + + public void LoadNextSlice() + { + if (!string.IsNullOrEmpty(Text)) return; + if (!_secondSliceLoaded) return; + + var maxSliceCount = int.MaxValue; + var index = 0; + + var lastRow = Rows.LastOrDefault(); + if (lastRow != null) + { + var lastDialogItem = lastRow.GetLast(); + if (lastDialogItem != null) + { + index = DialogsSource.IndexOf(lastDialogItem); + } + } + + var currentRow = lastRow; + if (currentRow != null && currentRow.HasEmptyItem()) + { + for (index = index + 1; index < DialogsSource.Count; index++) + { + if (!currentRow.HasEmptyItem()) break; + + var d = DialogsSource[index]; + + d.Row = currentRow; + + currentRow.Add(d, true); + } + } + else + { + index++; + } + + _lastSlice = new List(); + for (var count = 0; index < DialogsSource.Count && count < maxSliceCount; index++, count++) + { + if (currentRow == null || !currentRow.HasEmptyItem()) + { + currentRow = new DialogRow(); + _lastSlice.Add(currentRow); + } + + var d = DialogsSource[index]; + d.Row = currentRow; + + currentRow.Add(d); + } + + if (_lastSlice.Count > 0 + && Rows.Count < 10) + { + for (var i = 0; i < 10 - Rows.Count; i++) + { + var row = _lastSlice.FirstOrDefault(); + if (row != null) + { + _lastSlice.RemoveAt(0); + Rows.Add(row); + } + else + { + return; + } + } + } + } + + private bool _lastSliceLoaded; + + private void UpdateDialogsAsync(TLDialog lastDialog) + { + if (_lastSliceLoaded) return; + + var offsetDate = 0; + var offsetId = 0; + TLInputPeerBase offsetPeer = new TLInputPeerEmpty(); + if (lastDialog != null) + { + var lastMessage = lastDialog.TopMessage as TLMessageCommon; + if (lastMessage != null) + { + offsetDate = lastMessage.DateIndex; + offsetId = lastMessage.Index; + if (lastMessage.ToId is TLPeerUser) + { + offsetPeer = !lastMessage.Out.Value + ? DialogDetailsViewModel.PeerToInputPeer(new TLPeerUser { Id = lastMessage.FromId }) + : DialogDetailsViewModel.PeerToInputPeer(lastMessage.ToId); + } + else + { + offsetPeer = DialogDetailsViewModel.PeerToInputPeer(lastMessage.ToId); + } + } + } + + var stopwatch = Stopwatch.StartNew(); + IoC.Get().GetDialogsAsync(stopwatch, + new TLInt(offsetDate), + new TLInt(offsetId), + offsetPeer, + new TLInt(int.MaxValue), + new TLInt(0), + result => Execute.BeginOnUIThread(() => + { + _lastSliceLoaded = true; + + var dialogs = result.Dialogs; + var clearedDialogs = new List(); + foreach (var d in dialogs) + { + if (Skip(d)) + { + continue; + } + + clearedDialogs.Add(d); + } + + foreach (var clearedDialog in clearedDialogs) + { + var d = new DialogItem { Dialog = clearedDialog }; + + DialogsSource.Add(d); + } + + LoadNextSlice(); + }), + error => Execute.BeginOnUIThread(() => + { + + })); + } + + private void SetListVerticalAlignment(int rowsCount) + { + Dialogs.VerticalAlignment = rowsCount < 3 ? VerticalAlignment.Bottom : VerticalAlignment.Stretch; + } + + private TelegramAppBarButton _selectButton; + + private void OnLoadedOnce(object sender, RoutedEventArgs e) + { + Loaded -= OnLoadedOnce; + + _selectButton = AppBar.Buttons[0] as TelegramAppBarButton; + + BeginOpenStoryboard(); + } + + private void BeginOpenCommentGridStoryboard() + { + if (CommentGrid.Visibility == Visibility.Visible) return; + + var rootFrameHeight = ((PhoneApplicationFrame)Application.Current.RootVisual).ActualHeight; + var translateYTo = rootFrameHeight; + + var storyboard = new Storyboard(); + var translateAnimaiton = new DoubleAnimationUsingKeyFrames(); + translateAnimaiton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = translateYTo }); + translateAnimaiton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = 0.0, EasingFunction = new ExponentialEase { Exponent = 5.0, EasingMode = EasingMode.EaseOut } }); + Storyboard.SetTarget(translateAnimaiton, CommentGrid); + Storyboard.SetTargetProperty(translateAnimaiton, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateAnimaiton); + + Execute.BeginOnUIThread(() => + { + CommentGrid.Visibility = Visibility.Visible; + storyboard.Begin(); + }); + } + + private void BeginCloseCommentGridStoryboard() + { + if (CommentGrid.Visibility == Visibility.Collapsed) return; + + var easingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 5.0 }; + + var storyboard = new Storyboard(); + + var rootFrameHeight = ((PhoneApplicationFrame)Application.Current.RootVisual).ActualHeight; + var translateYTo = rootFrameHeight; + + var translateCommentGridAniamtion = new DoubleAnimationUsingKeyFrames(); + translateCommentGridAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.15), Value = 0.0 }); + translateCommentGridAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = translateYTo, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateCommentGridAniamtion, CommentGrid); + Storyboard.SetTargetProperty(translateCommentGridAniamtion, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateCommentGridAniamtion); + + storyboard.Begin(); + storyboard.Completed += (sender, args) => + { + CommentGrid.Visibility = Visibility.Collapsed; + }; + } + + private void BeginOpenStoryboard() + { + Bar.Visibility = Visibility.Collapsed; + + var rootFrameHeight = ((PhoneApplicationFrame)Application.Current.RootVisual).ActualHeight; + var translateYTo = rootFrameHeight; + + var storyboard = new Storyboard(); + var translateAnimaiton = new DoubleAnimationUsingKeyFrames(); + translateAnimaiton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = translateYTo }); + translateAnimaiton.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = 0.0, EasingFunction = new ExponentialEase { Exponent = 5.0, EasingMode = EasingMode.EaseOut } }); + Storyboard.SetTarget(translateAnimaiton, Bar); + Storyboard.SetTargetProperty(translateAnimaiton, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateAnimaiton); + + Execute.BeginOnUIThread(() => + { + Bar.Visibility = Visibility.Visible; + storyboard.Begin(); + }); + } + + private void BeginCloseStoryboard(Action callback) + { + //LayoutRoot.Background = (Brush)Resources["BackgroundTransparentBrush"]; + + var duration = TimeSpan.FromSeconds(0.25); + var easingFunction = new ExponentialEase { EasingMode = EasingMode.EaseIn, Exponent = 5.0 }; + + var storyboard = new Storyboard(); + + var rootFrameHeight = ((PhoneApplicationFrame)Application.Current.RootVisual).ActualHeight; + var translateYTo = rootFrameHeight; + var translateImageAniamtion = new DoubleAnimationUsingKeyFrames(); + translateImageAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = duration, Value = translateYTo, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateImageAniamtion, Dialogs); + Storyboard.SetTargetProperty(translateImageAniamtion, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateImageAniamtion); + + var translateBarAniamtion = new DoubleAnimationUsingKeyFrames(); + translateBarAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.15), Value = 0.0 }); + translateBarAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = translateYTo, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateBarAniamtion, Bar); + Storyboard.SetTargetProperty(translateBarAniamtion, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateBarAniamtion); + + var translateCommentGridAniamtion = new DoubleAnimationUsingKeyFrames(); + translateCommentGridAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.15), Value = 0.0 }); + translateCommentGridAniamtion.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.4), Value = translateYTo, EasingFunction = easingFunction }); + Storyboard.SetTarget(translateCommentGridAniamtion, CommentGrid); + Storyboard.SetTargetProperty(translateCommentGridAniamtion, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)")); + storyboard.Children.Add(translateCommentGridAniamtion); + + storyboard.Begin(); + if (callback != null) + { + storyboard.Completed += (o, e) => callback(); + } + } + + public bool TryClose() + { + BeginCloseStoryboard(RaiseClose); + + return true; + } + + public bool ForceClose() + { + RaiseClose(); + + return true; + } + + public event EventHandler Close; + + protected virtual void RaiseClose() + { + var handler = Close; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler Pick; + + protected virtual void RaisePick(PickDialogEventArgs e) + { + var handler = Pick; + if (handler != null) handler(this, e); + } + + private void DialogControl_OnTap(object sender, GestureEventArgs e) + { + var control = sender as DialogControl; + if (control != null) + { + var dialogItem = control.DataContext as DialogItem; + if (dialogItem != null) + { + ChangeDialogSelection(dialogItem, !dialogItem.IsSelected); + } + } + } + + private DialogItem _previousDialog; + + private void ChangeDialogSelection(DialogItem dialogItem, bool isSelected) + { + if (isSelected) + { + _selectedPictures[dialogItem.Dialog.Index] = dialogItem; + } + else + { + _selectedPictures.Remove(dialogItem.Dialog.Index); + } + + dialogItem.SuppressAnimation = false; + dialogItem.IsSelected = isSelected; + dialogItem.RaisePropertyChanged("IsSelected"); + + if (_hasManipulatingDelta + && _previousDialog != null + && _previousDialog.Row == dialogItem.Row) + { + var row = dialogItem.Row; + var between = row.Between(_previousDialog, dialogItem).ToList(); + if (between.Count > 0) + { + if (isSelected) + { + foreach (var item in between) + { + _selectedPictures[item.Dialog.Index] = item; + } + } + else + { + foreach (var item in between) + { + _selectedPictures.Remove(item.Dialog.Index); + } + } + + foreach (var item in between) + { + item.SuppressAnimation = false; + item.IsSelected = isSelected; + item.RaisePropertyChanged("IsSelected"); + } + } + } + + _previousDialog = dialogItem; + + _selectButton.IsEnabled = _selectedPictures.Any(); + + if (_selectedPictures.Any()) + { + BeginOpenCommentGridStoryboard(); + } + else + { + BeginCloseCommentGridStoryboard(); + } + //if (IsSingleItem) + //{ + // ChooseButton_OnClick(null, null); + //} + } + + private bool _hasManipulatingDelta; + + private void Photos_OnManipulationStarted(object sender, ManipulationStartedEventArgs e) + { + _hasManipulatingDelta = false; + } + + private void Photos_OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e) + { + _hasManipulatingDelta = false; + } + + private bool _isSelected; + + private void Dialogs_OnManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + //Debug.Text = string.Format("{0}\n{1}\n{2}", Dialogs.Viewport.Viewport, Dialogs.Viewport.Bounds, e.CumulativeManipulation.Translation); + + if (!_hasManipulatingDelta) + { + var grid = e.OriginalSource as Grid; + + if (grid != null) + { + var control = grid.Parent as DialogControl; + if (control != null) + { + var file1 = control.DataContext as DialogItem; + if (file1 != null) + { + ChangeDialogSelection(file1, !file1.IsSelected); + _isSelected = file1.IsSelected; + } + } + } + } + + _hasManipulatingDelta = true; + } + + private void DialogControl_OnMouseEnter(object sender, MouseEventArgs e) + { + if (!_hasManipulatingDelta) return; + + var control = sender as DialogControl; + if (control != null) + { + var file1 = control.DataContext as DialogItem; + if (file1 != null) + { + ChangeDialogSelection(file1, _isSelected); + } + } + } + + private void ChooseButton_OnClick(object sender, RoutedEventArgs e) + { + var selectedDialogs = _selectedPictures.Values.Select(x => x.Dialog).ToList(); + if (selectedDialogs.Count == 0) return; + + RaisePick(new PickDialogEventArgs { Comment = Comment, Dialogs = new ReadOnlyCollection(selectedDialogs) }); + + Execute.BeginOnUIThread(() => + { + TryClose(); + }); + } + + public static readonly DependencyProperty LinkProperty = DependencyProperty.Register( + "Link", typeof(string), typeof(ShareMessagePicker), new PropertyMetadata(default(string), OnLinkChanged)); + + private static void OnLinkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var control = d as ShareMessagePicker; + if (control != null) + { + control.CopyLinkMenuItem.Visibility = !string.IsNullOrEmpty(e.NewValue as string) + ? Visibility.Visible + : Visibility.Collapsed; + } + } + + public string Link + { + get { return (string) GetValue(LinkProperty); } + set { SetValue(LinkProperty, value); } + } + + private void CopyLink_OnTap(object sender, GestureEventArgs e) + { + AppBar.Close(); + Execute.BeginOnUIThread(TimeSpan.FromSeconds(0.25), () => + { + if (string.IsNullOrEmpty(Link)) return; + + Clipboard.SetText(Link); + }); + } + + private void Dialogs_OnViewportChanged(object sender, ViewportChangedEventArgs e) + { + if (Dialogs.VerticalAlignment == VerticalAlignment.Stretch + && Dialogs.Viewport.Viewport.Height + Dialogs.Viewport.Viewport.Y >= Dialogs.Viewport.Bounds.Height + Dialogs.Viewport.Bounds.Y - 0.1 // scrolled to top + && Dialogs.Viewport.Viewport.Y - Dialogs.Viewport.Bounds.Y >= 300.0 - 0.1) // header not in view + { + Dialogs.Background = (Brush)Resources["BackgroundBrush"]; + //LayoutRoot.Background = (Brush) Resources["BackgroundBrush"]; + } + else + { + Dialogs.Background = null; + //LayoutRoot.Background = (Brush) Resources["TransparentBackgroundBrush"]; + } + + var watermarkTextBox = FocusManager.GetFocusedElement() as WatermarkedTextBox; + if (watermarkTextBox != null && string.Equals(watermarkTextBox.Tag, "Search")) + { + Dialogs.Background = (Brush)Resources["BackgroundBrush"]; + //LayoutRoot.Background = (Brush)Resources["BackgroundBrush"]; + } + + if (Dialogs.VerticalAlignment == VerticalAlignment.Stretch + && Dialogs.Viewport.Viewport.Height + Dialogs.Viewport.Viewport.Y >= Dialogs.Viewport.Bounds.Height + Dialogs.Viewport.Bounds.Y - 400.0) + { + LoadLastSlice(); + } + + Debug.Text = Dialogs.Viewport.Viewport + Environment.NewLine + Dialogs.Viewport.Bounds; + } + + private VerticalAlignment _previousAlignment; + + private List _previousRows; + + private List _dialogsSource; + + private SearchDialogRequest _lastRequest; + + private readonly LRUCache _searchResultsCache = new LRUCache(Constants.MaxCacheCapacity); + + private List _lastSlice; + + private void Search() + { + _previousRows = _previousRows ?? new List(Rows); + + var text = Text; + + var trimmedText = Text.Trim(); + if (string.IsNullOrEmpty(trimmedText)) + { + Execute.BeginOnUIThread(() => + { + if (!string.Equals(trimmedText, Text.Trim(), StringComparison.OrdinalIgnoreCase)) return; + + Rows.Clear(); + var firstSliceCount = 5; + var count = 0; + var secondSlice = new List(); + foreach (var item in _previousRows) + { + if (count < firstSliceCount) + { + Rows.Add(item); + count++; + } + else + { + secondSlice.Add(item); + } + } + if (secondSlice.Count > 0) + { + Execute.BeginOnUIThread(() => + { + if (!string.Equals(trimmedText, Text.Trim(), StringComparison.OrdinalIgnoreCase)) return; + + foreach (var item in secondSlice) + { + Rows.Add(item); + } + }); + } + }); + + return; + } + + //Search(Text); + //return; + + Execute.BeginOnUIThread(TimeSpan.FromSeconds(0.25), () => + { + if (!string.Equals(text, Text, StringComparison.OrdinalIgnoreCase)) return; + + Search(Text); + }); + } + + private void Search(string text) + { + if (!string.Equals(text, Text, StringComparison.OrdinalIgnoreCase)) return; + + if (_lastRequest != null) + { + _lastRequest.Cancel(); + } + + var trimmedText = Text.Trim(); + if (string.IsNullOrEmpty(trimmedText)) + { + Execute.BeginOnUIThread(() => + { + if (!string.Equals(trimmedText, Text.Trim(), StringComparison.OrdinalIgnoreCase)) return; + + Rows.Clear(); + var firstSliceCount = 5; + var count = 0; + var secondSlice = new List(); + foreach (var item in _previousRows) + { + if (count < firstSliceCount) + { + Rows.Add(item); + count++; + } + else + { + secondSlice.Add(item); + } + } + if (secondSlice.Count > 0) + { + Execute.BeginOnUIThread(() => + { + if (!string.Equals(trimmedText, Text.Trim(), StringComparison.OrdinalIgnoreCase)) return; + + foreach (var item in secondSlice) + { + Rows.Add(item); + } + }); + } + }); + + return; + } + + var nextRequest = GetNextRequest(text, DialogsSource); + + nextRequest.ProcessAsync(results => + { + if (nextRequest.IsCanceled) return; + if (!string.Equals(Text, nextRequest.Text, StringComparison.OrdinalIgnoreCase)) return; + + Rows.Clear(); + if (results.Count > 0) + { + DialogRow currentRow = null; + var secondSlice = new List(); + var maxCount = 16; + for (var i = 0; i < results.Count; i++) + { + var d = results[i]; + + if (i < maxCount) + { + if (i % 4 == 0) + { + currentRow = new DialogRow(); + Rows.Add(currentRow); + } + + currentRow.Add(d); + d.Row = currentRow; + } + else + { + secondSlice.Add(d); + } + } + + if (secondSlice.Count > 0) + { + Execute.BeginOnUIThread(() => + { + if (nextRequest.IsCanceled) return; + if (!string.Equals(Text, nextRequest.Text, StringComparison.OrdinalIgnoreCase)) return; + + for (var i = 0; i < secondSlice.Count; i++) + { + if (i % 4 == 0) + { + currentRow = new DialogRow(); + Rows.Add(currentRow); + } + + currentRow.Add(secondSlice[i]); + secondSlice[i].Row = currentRow; + } + }); + } + } + }); + + _searchResultsCache[nextRequest.Text] = nextRequest; + _lastRequest = nextRequest; + } + + private SearchDialogRequest GetNextRequest(string text, List dialogsSource) + { + SearchDialogRequest nextRequest; + if (!_searchResultsCache.TryGetValue(text, out nextRequest)) + { + foreach (var dialogItem in dialogsSource) + { + var dialog = dialogItem.Dialog; + + var chat = dialog.With as TLChatBase; + var user = dialog.With as TLUserBase; + if (chat != null && chat.FullNameWords == null) + { + chat.FullNameWords = chat.FullName.Split(' '); + } + else if (user != null && user.FullNameWords == null) + { + user.FullNameWords = user.FullName.Split(' '); + } + } + + nextRequest = new SearchDialogRequest(text, dialogsSource); + } + return nextRequest; + } + + private void UIElement_OnGotFocus(object sender, RoutedEventArgs e) + { + var header = Dialogs.ListHeader as Grid; + if (header != null) + { + header.Visibility = Visibility.Collapsed; + } + + Dialogs.VerticalAlignment = VerticalAlignment.Stretch; + Dialogs.Background = (Brush)Resources["BackgroundBrush"]; + + //LayoutRoot.Background = (Brush)Resources["BackgroundBrush"]; + } + + private void UIElement_OnLostFocus(object sender, RoutedEventArgs e) + { + var header = Dialogs.ListHeader as Grid; + if (header != null) + { + header.Visibility = Visibility.Visible; + } + + SetListVerticalAlignment(Rows.Count); + Dialogs_OnViewportChanged(null, null); + } + + private void Dialogs_OnCloseToEnd(object sender, System.EventArgs e) + { + //LoadNextSlice(); + } + + private void ListHeader_OnTap(object sender, GestureEventArgs e) + { + TryClose(); + } + } + + public class Group : BindableCollection + { + public string GroupName { get; private set; } + + public Group(string groupName) + { + GroupName = groupName; + } + } + + public class DialogRow : PropertyChangedBase + { + public DialogItem Dialog1 { get; set; } + public DialogItem Dialog2 { get; set; } + public DialogItem Dialog3 { get; set; } + public DialogItem Dialog4 { get; set; } + + public bool HasEmptyItem() + { + return Dialog4 == null; + } + + public void Add(DialogItem dialog, bool notify = false) + { + if (Dialog1 == null) + { + Dialog1 = dialog; + if (notify) NotifyOfPropertyChange(() => Dialog1); + } + else if (Dialog2 == null) + { + Dialog2 = dialog; + if (notify) NotifyOfPropertyChange(() => Dialog2); + } + else if (Dialog3 == null) + { + Dialog3 = dialog; + if (notify) NotifyOfPropertyChange(() => Dialog3); + } + else if (Dialog4 == null) + { + Dialog4 = dialog; + if (notify) NotifyOfPropertyChange(() => Dialog4); + } + } + + public IEnumerable Between(DialogItem item1, DialogItem item2) + { + if (item1 == Dialog1) + { + if (item2 == Dialog3) + { + yield return Dialog2; + } + else if (item2 == Dialog4) + { + yield return Dialog2; + yield return Dialog3; + } + } + else if (item1 == Dialog2) + { + if (item2 == Dialog4) + { + yield return Dialog3; + } + } + else if (item1 == Dialog3) + { + if (item2 == Dialog1) + { + yield return Dialog2; + } + } + else if (item1 == Dialog4) + { + if (item2 == Dialog2) + { + yield return Dialog3; + } + else if (item2 == Dialog1) + { + yield return Dialog2; + yield return Dialog3; + } + } + } + + public DialogItem GetLast() + { + if (Dialog4 != null) return Dialog4; + if (Dialog3 != null) return Dialog3; + if (Dialog2 != null) return Dialog2; + + return Dialog1; + } + } + + public class DialogItem : INotifyPropertyChanged + { + public bool IsSelected { get; set; } + public TLDialogBase Dialog { get; set; } + public DialogItem Self { get { return this; } } + public DialogRow Row { get; set; } + + public bool SuppressAnimation { get; set; } + + public event PropertyChangedEventHandler PropertyChanged; + + public virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChangedEventHandler handler = PropertyChanged; + if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); + } + } + + public class PickDialogEventArgs : System.EventArgs + { + public string Comment { get; set; } + + public IList Dialogs { get; set; } + } + + public class SearchDialogRequest + { + public bool IsCanceled; + + public string TransliterateText { get; private set; } + + public string Text { get; private set; } + + public IList DialogsSource { get; private set; } + + public IList Results { get; private set; } + + public int Offset { get; set; } + + public int Limit { get { return 20; } } + + public bool IsLastSliceLoaded { get; set; } + + public SearchDialogRequest(string text, IList dialogsSource) + { + Text = text; + TransliterateText = Language.Transliterate(text); + DialogsSource = dialogsSource; + } + + private static bool IsUserValid(TLUserBase contact, string text) + { + if (string.IsNullOrEmpty(text)) return false; + + return contact.FirstName.ToString().StartsWith(text, StringComparison.OrdinalIgnoreCase) + || contact.LastName.ToString().StartsWith(text, StringComparison.OrdinalIgnoreCase) + || contact.FullName.StartsWith(text, StringComparison.OrdinalIgnoreCase) + || (contact.FullNameWords != null && contact.FullNameWords.Any(x => x.StartsWith(text, StringComparison.OrdinalIgnoreCase))); + } + + private static bool IsChatValid(TLChatBase chat, string text, bool useFastSearch) + { + if (string.IsNullOrEmpty(text)) return false; + + if (!useFastSearch) + { + var fullName = chat.FullName; + + var i = fullName.IndexOf(text, StringComparison.OrdinalIgnoreCase); + if (i != -1) + { + while (i < fullName.Length && i != -1) + { + if (i == 0 || (i > 0 && fullName[i - 1] == ' ')) + { + return true; + } + if (fullName.Length > i + 1) + { + i = fullName.IndexOf(text, i + 1, StringComparison.OrdinalIgnoreCase); + } + else + { + break; + } + } + } + } + else + { + if (chat.FullNameWords != null + && chat.FullNameWords.Any(x => x.StartsWith(text, StringComparison.OrdinalIgnoreCase))) + { + return true; + } + } + + return false; + } + + private static bool IsUsernameValid(IUserName userNameContact, string text) + { + if (text.Length >= Constants.UsernameMinLength) + { + if (userNameContact != null) + { + var userName = userNameContact.UserName != null ? userNameContact.UserName.ToString() : string.Empty; + if (userName.StartsWith(text.TrimStart('@'), StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + } + + return false; + } + + public void ProcessAsync(Action> callback) + { + if (Results != null) + { + IsCanceled = false; + callback.SafeInvoke(Results); + return; + } + + var dialogsSource = DialogsSource; + + Execute.BeginOnThreadPool(() => + { + var useFastSearch = !Text.Contains(" "); + + var results = new List(dialogsSource.Count); + foreach (var dialogItem in dialogsSource) + { + var dialog = dialogItem.Dialog; + + var user = dialog.With as TLUser; + var chat = dialog.With as TLChatBase; + if (user != null) + { + if (IsUserValid(user, Text) + || IsUserValid(user, TransliterateText) + || IsUsernameValid(user, Text)) + { + results.Add(dialogItem); + } + } + else if (chat != null) + { + if (IsChatValid(chat, Text, useFastSearch) + || IsChatValid(chat, TransliterateText, useFastSearch) + || IsUsernameValid(chat as IUserName, Text)) + { + var channelForbidden = chat as TLChannelForbidden; + if (channelForbidden != null) + { + continue; + } + + var chat41 = chat as TLChat41; + if (chat41 != null && chat41.IsMigrated) + { + continue; + } + + results.Add(dialogItem); + } + } + } + + Results = results; + + Execute.BeginOnUIThread(() => callback.SafeInvoke(Results)); + }); + } + + public void Cancel() + { + IsCanceled = true; + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/StatusControl.xaml b/TelegramClient.WP81/Views/Controls/StatusControl.xaml new file mode 100755 index 0000000..76eb3c9 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/StatusControl.xaml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/StatusControl.xaml.cs b/TelegramClient.WP81/Views/Controls/StatusControl.xaml.cs new file mode 100755 index 0000000..33d15d7 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/StatusControl.xaml.cs @@ -0,0 +1,74 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Media; +using Telegram.Api.TL; + +namespace TelegramClient.Views.Controls +{ + public partial class StatusControl + { + public static readonly DependencyProperty StatusProperty = DependencyProperty.Register( + "Status", typeof (MessageStatus), typeof (StatusControl), new PropertyMetadata(default(MessageStatus), OnStatusChanged)); + + private static void OnStatusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var statusControl = d as StatusControl; + if (statusControl != null) + { + statusControl.Sending.Visibility = (MessageStatus)e.NewValue == MessageStatus.Sending || (MessageStatus)e.NewValue == MessageStatus.Compressing + ? Visibility.Visible + : Visibility.Collapsed; + statusControl.Confirmed.Visibility = (MessageStatus)e.NewValue == MessageStatus.Confirmed + ? Visibility.Visible + : Visibility.Collapsed; + statusControl.Read.Visibility = (MessageStatus)e.NewValue == MessageStatus.Read + ? Visibility.Visible + : Visibility.Collapsed; + statusControl.Failed.Visibility = (MessageStatus)e.NewValue == MessageStatus.Failed + ? Visibility.Visible + : Visibility.Collapsed; + } + } + + public static readonly DependencyProperty FillProperty = DependencyProperty.Register( + "Fill", typeof (Brush), typeof (StatusControl), new PropertyMetadata(default(Brush), OnFillChanged)); + + private static void OnFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var statusControl = d as StatusControl; + if (statusControl != null) + { + statusControl.SendingEllipse.Stroke = e.NewValue as Brush; + statusControl.SendingPolyline.Stroke = e.NewValue as Brush; + + statusControl.ReadPolyline1.Fill = e.NewValue as Brush; + statusControl.ReadPolyline2.Fill = e.NewValue as Brush; + + statusControl.Confirmed.Fill = e.NewValue as Brush; + } + } + + public Brush Fill + { + get { return (Brush) GetValue(FillProperty); } + set { SetValue(FillProperty, value); } + } + + public MessageStatus Status + { + get { return (MessageStatus) GetValue(StatusProperty); } + set { SetValue(StatusProperty, value); } + } + + public StatusControl() + { + InitializeComponent(); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/TelegramAppBarButton.xaml b/TelegramClient.WP81/Views/Controls/TelegramAppBarButton.xaml new file mode 100755 index 0000000..61b733a --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/TelegramAppBarButton.xaml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/TelegramAppBarButton.xaml.cs b/TelegramClient.WP81/Views/Controls/TelegramAppBarButton.xaml.cs new file mode 100755 index 0000000..ef1693e --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/TelegramAppBarButton.xaml.cs @@ -0,0 +1,173 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using System.Windows.Media; + +namespace TelegramClient.Views.Controls +{ + public partial class TelegramAppBarButton + { + public static readonly DependencyProperty LabelForegroundProperty = DependencyProperty.Register( + "LabelForeground", typeof(Brush), typeof(TelegramAppBarButton), new PropertyMetadata(default(Brush), OnLabelForegroundChanged)); + + private static void OnLabelForegroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var telegramApplicationBarButton = d as TelegramAppBarButton; + if (telegramApplicationBarButton != null) + { + telegramApplicationBarButton.LabelBlock.Foreground = (Brush)e.NewValue; + telegramApplicationBarButton.Button.Background = (Brush)e.NewValue; + } + } + + public Brush LabelForeground + { + get { return (Brush) GetValue(LabelForegroundProperty); } + set { SetValue(LabelForegroundProperty, value); } + } + + private static void SetDefaultValues() + { + var applicationBar = TelegramApplicationBar.ApplicationBar; + if (applicationBar.DefaultSize < TelegramApplicationBar.ApplicaitonBarDefaultSize1X) + { + var scaleFactor = applicationBar.DefaultSize / TelegramApplicationBar.ApplicaitonBarDefaultSize1X; + _iconMargin = 20.0 * scaleFactor; + _iconSize = applicationBar.DefaultSize - 2.0 * _iconMargin; + _iconLabelFontSize = 18.0 * scaleFactor; + } + else + { + _iconSize = 32.0; + _iconMargin = 20.0; + _iconLabelFontSize = 18.0; + } + } + + private static double? _iconLabelFontSize; + + public static double IconLabelFontSize + { + get + { + if (_iconLabelFontSize == null) + { + SetDefaultValues(); + } + + return _iconLabelFontSize.Value; + } + } + + private static double? _iconSize; + + public static double IconSize + { + get + { + if (_iconSize == null) + { + SetDefaultValues(); + } + + return _iconSize.Value; + } + } + + private static double? _iconMargin; + + public static double IconMargin + { + get + { + if (_iconMargin == null) + { + SetDefaultValues(); + } + + return _iconMargin.Value; + } + } + + public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register( + "ImageSource", typeof (ImageSource), typeof (TelegramAppBarButton), new PropertyMetadata(default(ImageSource), OnImageSourceChanged)); + + private static void OnImageSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var telegramApplicationBarButton = d as TelegramAppBarButton; + if (telegramApplicationBarButton != null) + { + telegramApplicationBarButton.ImageBrush.ImageSource = e.NewValue as ImageSource; + } + } + + public ImageSource ImageSource + { + get { return (ImageSource) GetValue(ImageSourceProperty); } + set { SetValue(ImageSourceProperty, value); } + } + + public static readonly DependencyProperty TextProperty = DependencyProperty.Register( + "Text", typeof (string), typeof (TelegramAppBarButton), new PropertyMetadata(default(string), OnTextChanged)); + + private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var telegramApplicationBarButton = d as TelegramAppBarButton; + if (telegramApplicationBarButton != null) + { + telegramApplicationBarButton.LabelBlock.Text = e.NewValue as string; + } + } + + public string Text + { + get { return (string) GetValue(TextProperty); } + set { SetValue(TextProperty, value); } + } + + public TelegramAppBarButton() + { + InitializeComponent(); + + Button.Margin = new Thickness(20.0, IconMargin, 20.0, IconMargin); + Button.Width = IconSize; + Button.Height = IconSize; + + LabelBlock.FontSize = IconLabelFontSize; + + IsEnabledChanged += OnIsEnabledChanged; + Loaded += OnLoaded; + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + Loaded -= OnLoaded; + if (!IsEnabled) + { + VisualStateManager.GoToState(this, "Disabled", false); + LayoutRoot.IsHitTestVisible = false; + } + } + + private void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) + { + VisualStateManager.GoToState(this, (bool) e.NewValue ? "Normal" : "Disabled", false); + LayoutRoot.IsHitTestVisible = (bool) e.NewValue; + } + + public void HideLabel() + { + VisualStateManager.GoToState(this, "Closed", false); + } + + public void ShowLabel() + { + VisualStateManager.GoToState(this, "Opened", false); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/TelegramApplicationBar.xaml b/TelegramClient.WP81/Views/Controls/TelegramApplicationBar.xaml new file mode 100755 index 0000000..fd2e825 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/TelegramApplicationBar.xaml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/TelegramApplicationBar.xaml.cs b/TelegramClient.WP81/Views/Controls/TelegramApplicationBar.xaml.cs new file mode 100755 index 0000000..3978857 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/TelegramApplicationBar.xaml.cs @@ -0,0 +1,403 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Animation; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; +using GestureEventArgs = System.Windows.Input.GestureEventArgs; + +namespace TelegramClient.Views.Controls +{ + public partial class TelegramApplicationBar + { + public Brush BackgroundBrush + { + get { return LayoutRoot.Background; } + set { LayoutRoot.Background = value; } + } + + public Brush MorePanelBackgroundBrush + { + get { return _morePanelBrush; } + set + { + _morePanelBrush = value; + if (MorePanel != null) + { + MorePanel.Background = _morePanelBrush; + } + } + } + + public event EventHandler PanelOpened; + + protected virtual void RaisePanelOpened() + { + var handler = PanelOpened; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + public event EventHandler PanelClosed; + + protected virtual void RaisePanelClosed() + { + EventHandler handler = PanelClosed; + if (handler != null) handler(this, System.EventArgs.Empty); + } + + private static ApplicationBar _applicationBar; + + public static ApplicationBar ApplicationBar + { + get + { + if (_applicationBar == null) + { + _applicationBar = new ApplicationBar(); + } + + return _applicationBar; + } + } + + public static double ApplicaitonBarDefaultSize1X + { + get { return 72.0; } + } + + public static readonly DependencyProperty ButtonsProperty = DependencyProperty.Register( + "Buttons", typeof(IList), typeof(TelegramApplicationBar), new PropertyMetadata(default(IList), OnButtonsChanged)); + + public IList Buttons + { + get { return (IList)GetValue(ButtonsProperty); } + set { SetValue(ButtonsProperty, value); } + } + + private static void OnButtonsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var telegramApplicationBar = d as TelegramApplicationBar; + if (telegramApplicationBar != null) + { + var oldButtons = e.OldValue as IList; + if (oldButtons != null) + { + for (var i = oldButtons.Count - 1; i >= 0; i--) + { + var button = oldButtons[i] as FrameworkElement; + if (button != null) + { + button.Tap -= telegramApplicationBar.Button_OnTap; + } + } + + var notifyCollectionChanged = oldButtons as INotifyCollectionChanged; + if (notifyCollectionChanged != null) + { + notifyCollectionChanged.CollectionChanged -= telegramApplicationBar.OnCollectionChanged; + } + } + + telegramApplicationBar.LayoutRoot.Children.Clear(); + var newButtons = e.NewValue as IList; + if (newButtons != null) + { + for (var i = 0; i < newButtons.Count && i < 4; i++) + { + var button = newButtons[i] as FrameworkElement; + if (button != null) + { + button.Tap += telegramApplicationBar.Button_OnTap; + + telegramApplicationBar.LayoutRoot.Children.Add(button); + } + } + + var notifyCollectionChanged = newButtons as INotifyCollectionChanged; + if (notifyCollectionChanged != null) + { + notifyCollectionChanged.CollectionChanged += telegramApplicationBar.OnCollectionChanged; + } + } + telegramApplicationBar.LayoutRoot.Children.Add(telegramApplicationBar.MoreButton); + } + } + + private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (e.Action == NotifyCollectionChangedAction.Reset) + { + foreach (var child in LayoutRoot.Children) + { + if (child == MoreButton) continue; + + var button = child as FrameworkElement; + if (button != null) + { + button.Tap -= Button_OnTap; + } + } + + LayoutRoot.Children.Clear(); + LayoutRoot.Children.Add(MoreButton); + } + + if (e.OldItems != null) + { + foreach (var oldItem in e.OldItems) + { + var button = oldItem as FrameworkElement; + if (button != null) + { + button.Tap -= Button_OnTap; + + LayoutRoot.Children.Remove(button); + } + } + } + if (e.NewItems != null) + { + foreach (var newItem in e.NewItems) + { + var button = newItem as FrameworkElement; + if (button != null) + { + button.Tap += Button_OnTap; + + LayoutRoot.Children.Add(button); + } + } + } + } + + public static readonly DependencyProperty MorePanelProperty = DependencyProperty.Register( + "MorePanel", typeof(Border), typeof(TelegramApplicationBar), new PropertyMetadata(default(Border), OnMorePanelChanged)); + + private static void OnMorePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var telegramApplicationBar = d as TelegramApplicationBar; + if (telegramApplicationBar != null) + { + var morePanel = e.NewValue as Border; + if (morePanel != null) + { + morePanel.Background = telegramApplicationBar._morePanelBrush; + } + } + } + + public Border MorePanel + { + get { return (Border)GetValue(MorePanelProperty); } + set { SetValue(MorePanelProperty, value); } + } + + private void Button_OnTap(object sender, GestureEventArgs e) + { + HideLabels(); + Transform.Y = 0.0; + if (MorePanel != null) + { + RaisePanelClosed(); + MorePanel.Visibility = Visibility.Collapsed; + } + } + + private void HideLabels() + { + foreach (var child in LayoutRoot.Children) + { + var button = child as TelegramAppBarButton; + if (button != null) + { + button.HideLabel(); + } + } + } + + private void ShowLabels() + { + foreach (var child in LayoutRoot.Children) + { + var button = child as TelegramAppBarButton; + if (button != null) + { + button.ShowLabel(); + } + } + } + + private Brush _morePanelBrush; + + public TelegramApplicationBar() + { + InitializeComponent(); + + SetValue(ButtonsProperty, new ObservableCollection()); + + var applicationBar = ApplicationBar; + if (applicationBar.DefaultSize < ApplicaitonBarDefaultSize1X) + { + Height = applicationBar.DefaultSize + 18.0; + } + + var isLightTheme = (Visibility)Application.Current.Resources["PhoneLightThemeVisibility"] == Visibility.Visible; + LayoutRoot.Background = isLightTheme ? (SolidColorBrush)Resources["AppBarPanelLight"] : (SolidColorBrush)Resources["AppBarPanelDark"]; + _morePanelBrush = isLightTheme ? (SolidColorBrush)Resources["MorePanelLight"] : (SolidColorBrush)Resources["MorePanelDark"]; + if (MorePanel != null) + { + + MorePanel.Background = _morePanelBrush; + } + + Loaded += OnApplicationBarLoaded; + Unloaded += OnApplicationBarUnloaded; + } + + private PhoneApplicationFrame _parentFrame; + + private void OnApplicationBarLoaded(object sender, RoutedEventArgs e) + { + _parentFrame = Application.Current.RootVisual as PhoneApplicationFrame; + if (_parentFrame != null) + { + _parentFrame.BackKeyPress += OnFrameBackKeyPressed; + } + } + + private void OnApplicationBarUnloaded(object sender, RoutedEventArgs e) + { + if (_parentFrame != null) + { + _parentFrame.BackKeyPress -= OnFrameBackKeyPressed; + } + } + + private void OnFrameBackKeyPressed(object sender, CancelEventArgs e) + { + if (MorePanel != null + && MorePanel.Visibility == Visibility.Visible) + { + Close(); + + e.Cancel = true; + return; + } + } + + private void More_OnTap(object sender, GestureEventArgs e) + { + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + if (MorePanel.Visibility == Visibility.Visible) + { + CloseMorePanel(); + } + else + { + OpenMorePanel(); + } + }); + } + + private void OpenMorePanel() + { + if (MorePanel != null && MorePanel.ActualHeight == 0.0) + { + MorePanel.Visibility = Visibility.Visible; + MorePanel.Opacity = 0.0; + MorePanel.IsHitTestVisible = false; + + Telegram.Api.Helpers.Execute.BeginOnUIThread(() => + { + MorePanel.Opacity = 1.0; + MorePanel.IsHitTestVisible = true; + + OpenMorePanelInternal(); + }); + } + else + { + OpenMorePanelInternal(); + } + } + + private void OpenMorePanelInternal() + { + RaisePanelOpened(); + + var storyboard = new Storyboard(); + + var translateAppBarPanelAnimation = new DoubleAnimationUsingKeyFrames(); + translateAppBarPanelAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.00), Value = 0.0 }); + translateAppBarPanelAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = -18.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(translateAppBarPanelAnimation, Transform); + Storyboard.SetTargetProperty(translateAppBarPanelAnimation, new PropertyPath("Y")); + storyboard.Children.Add(translateAppBarPanelAnimation); + + if (MorePanel != null) + { + MorePanel.Visibility = Visibility.Visible; + + var continuumLayoutRootY = new DoubleAnimationUsingKeyFrames(); + continuumLayoutRootY.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.0), Value = MorePanel.ActualHeight }); + continuumLayoutRootY.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = -18.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 3.0 } }); + Storyboard.SetTarget(continuumLayoutRootY, MorePanel); + Storyboard.SetTargetProperty(continuumLayoutRootY, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(continuumLayoutRootY); + } + + ShowLabels(); + storyboard.Begin(); + } + + private void CloseMorePanel() + { + RaisePanelClosed(); + + var storyboard = new Storyboard(); + + var translateAppBarPanelAnimation = new DoubleAnimationUsingKeyFrames(); + translateAppBarPanelAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = 0.0, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } }); + Storyboard.SetTarget(translateAppBarPanelAnimation, Transform); + Storyboard.SetTargetProperty(translateAppBarPanelAnimation, new PropertyPath("Y")); + storyboard.Children.Add(translateAppBarPanelAnimation); + + if (MorePanel != null) + { + var translateAnimation = new DoubleAnimationUsingKeyFrames(); + translateAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.00), Value = 0.0 }); + translateAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = TimeSpan.FromSeconds(0.25), Value = MorePanel.ActualHeight, EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 6.0 } }); + Storyboard.SetTarget(translateAnimation, MorePanel); + Storyboard.SetTargetProperty(translateAnimation, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)")); + storyboard.Children.Add(translateAnimation); + } + + storyboard.Begin(); + storyboard.Completed += (sender, args) => + { + HideLabels(); + if (MorePanel != null) MorePanel.Visibility = Visibility.Collapsed; + }; + } + + public void Close() + { + CloseMorePanel(); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/TelegramDatePickerPage.xaml b/TelegramClient.WP81/Views/Controls/TelegramDatePickerPage.xaml new file mode 100755 index 0000000..dd6842e --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/TelegramDatePickerPage.xaml @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/TelegramDatePickerPage.xaml.cs b/TelegramClient.WP81/Views/Controls/TelegramDatePickerPage.xaml.cs new file mode 100755 index 0000000..4a27ff1 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/TelegramDatePickerPage.xaml.cs @@ -0,0 +1,363 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Navigation; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Controls.LocalizedResources; +using Microsoft.Phone.Controls.Primitives; +using Microsoft.Phone.Shell; + +namespace TelegramClient.Views.Controls +{ + public partial class TelegramDatePickerPage + { + public TelegramDatePickerPage(YearDataSource yearDataSource) + { + InitializeComponent(); + PrimarySelector.DataSource = yearDataSource; + SecondarySelector.DataSource = new MonthDataSource(); + TertiarySelector.DataSource = new DayDataSource(); + InitializeDateTimePickerPage(PrimarySelector, SecondarySelector, TertiarySelector); + } + + protected override IEnumerable GetSelectorsOrderedByCulturePattern() + { + string pattern = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.ToUpperInvariant(); + if (DateShouldFlowRTL()) + { + char[] charArray = pattern.ToCharArray(); + Array.Reverse(charArray); + pattern = new string(charArray); + } + return DateTimePickerPageBase.GetSelectorsOrderedByCulturePattern(pattern, new[] + { + 'Y', + 'M', + 'D' + }, new [] + { + PrimarySelector, + SecondarySelector, + TertiarySelector + }); + } + + internal static bool DateShouldFlowRTL() + { + var letterIsoLanguageName = CultureInfo.CurrentCulture.TwoLetterISOLanguageName; + if (letterIsoLanguageName != "ar") + return letterIsoLanguageName == "fa"; + return true; + } + + public override void SetFlowDirection(FlowDirection flowDirection) + { + throw new NotImplementedException(); + } + } + public abstract class DateTimePickerPageBase : PhoneApplicationPage, IDateTimePickerPage + { + private const string VisibilityGroupName = "VisibilityStates"; + private const string OpenVisibilityStateName = "Open"; + private const string ClosedVisibilityStateName = "Closed"; + private const string StateKey_Value = "DateTimePickerPageBase_State_Value"; + private LoopingSelector _primarySelectorPart; + private LoopingSelector _secondarySelectorPart; + private LoopingSelector _tertiarySelectorPart; + private Storyboard _closedStoryboard; + private DateTime? _value; + + public DateTime? Value + { + get + { + return this._value; + } + set + { + this._value = value; + DateTimeWrapper dateTimeWrapper = new DateTimeWrapper(this._value.GetValueOrDefault(DateTime.Now)); + this._primarySelectorPart.DataSource.SelectedItem = (object)dateTimeWrapper; + this._secondarySelectorPart.DataSource.SelectedItem = (object)dateTimeWrapper; + this._tertiarySelectorPart.DataSource.SelectedItem = (object)dateTimeWrapper; + } + } + + protected void InitializeDateTimePickerPage(LoopingSelector primarySelector, LoopingSelector secondarySelector, LoopingSelector tertiarySelector) + { + if (primarySelector == null) + throw new ArgumentNullException("primarySelector"); + if (secondarySelector == null) + throw new ArgumentNullException("secondarySelector"); + if (tertiarySelector == null) + throw new ArgumentNullException("tertiarySelector"); + this._primarySelectorPart = primarySelector; + this._secondarySelectorPart = secondarySelector; + this._tertiarySelectorPart = tertiarySelector; + this._primarySelectorPart.DataSource.SelectionChanged += new EventHandler(this.OnDataSourceSelectionChanged); + this._secondarySelectorPart.DataSource.SelectionChanged += new EventHandler(this.OnDataSourceSelectionChanged); + this._tertiarySelectorPart.DataSource.SelectionChanged += new EventHandler(this.OnDataSourceSelectionChanged); + this._primarySelectorPart.IsExpandedChanged += new DependencyPropertyChangedEventHandler(this.OnSelectorIsExpandedChanged); + this._secondarySelectorPart.IsExpandedChanged += new DependencyPropertyChangedEventHandler(this.OnSelectorIsExpandedChanged); + this._tertiarySelectorPart.IsExpandedChanged += new DependencyPropertyChangedEventHandler(this.OnSelectorIsExpandedChanged); + this._primarySelectorPart.Visibility = Visibility.Collapsed; + this._secondarySelectorPart.Visibility = Visibility.Collapsed; + this._tertiarySelectorPart.Visibility = Visibility.Collapsed; + int num = 0; + foreach (LoopingSelector loopingSelector in this.GetSelectorsOrderedByCulturePattern()) + { + Grid.SetColumn((FrameworkElement)loopingSelector, num); + loopingSelector.Visibility = Visibility.Visible; + ++num; + } + FrameworkElement child = VisualTreeHelper.GetChild((DependencyObject)this, 0) as FrameworkElement; + if (child != null) + { + foreach (VisualStateGroup visualStateGroup in (IEnumerable)VisualStateManager.GetVisualStateGroups(child)) + { + if ("VisibilityStates" == visualStateGroup.Name) + { + foreach (VisualState state in (IEnumerable)visualStateGroup.States) + { + if ("Closed" == state.Name && state.Storyboard != null) + { + this._closedStoryboard = state.Storyboard; + this._closedStoryboard.Completed += new EventHandler(this.OnClosedStoryboardCompleted); + } + } + } + } + } + if (this.ApplicationBar != null) + { + foreach (object button in (IEnumerable)this.ApplicationBar.Buttons) + { + IApplicationBarIconButton applicationBarIconButton = button as IApplicationBarIconButton; + if (applicationBarIconButton != null) + { + if ("DONE" == applicationBarIconButton.Text) + { + applicationBarIconButton.Text = ControlResources.DateTimePickerDoneText; + applicationBarIconButton.Click += new EventHandler(this.OnDoneButtonClick); + } + else if ("CANCEL" == applicationBarIconButton.Text) + { + applicationBarIconButton.Text = ControlResources.DateTimePickerCancelText; + applicationBarIconButton.Click += new EventHandler(this.OnCancelButtonClick); + } + } + } + } + VisualStateManager.GoToState((Control)this, "Open", true); + } + + private void OnDataSourceSelectionChanged(object sender, SelectionChangedEventArgs e) + { + DataSource dataSource = (DataSource)sender; + this._primarySelectorPart.DataSource.SelectedItem = dataSource.SelectedItem; + this._secondarySelectorPart.DataSource.SelectedItem = dataSource.SelectedItem; + this._tertiarySelectorPart.DataSource.SelectedItem = dataSource.SelectedItem; + } + + private void OnSelectorIsExpandedChanged(object sender, DependencyPropertyChangedEventArgs e) + { + if (!(bool)e.NewValue) + return; + this._primarySelectorPart.IsExpanded = sender == this._primarySelectorPart; + this._secondarySelectorPart.IsExpanded = sender == this._secondarySelectorPart; + this._tertiarySelectorPart.IsExpanded = sender == this._tertiarySelectorPart; + } + + private void OnDoneButtonClick(object sender, System.EventArgs e) + { + this._value = new DateTime?(((DateTimeWrapper)this._primarySelectorPart.DataSource.SelectedItem).DateTime); + this.ClosePickerPage(); + } + + private void OnCancelButtonClick(object sender, System.EventArgs e) + { + this._value = new DateTime?(); + this.ClosePickerPage(); + } + + protected override void OnBackKeyPress(CancelEventArgs e) + { + if (e == null) + throw new ArgumentNullException("e"); + e.Cancel = true; + this.ClosePickerPage(); + } + + private void ClosePickerPage() + { + if (this._closedStoryboard != null) + VisualStateManager.GoToState((Control)this, "Closed", true); + else + this.OnClosedStoryboardCompleted((object)null, (System.EventArgs)null); + } + + private void OnClosedStoryboardCompleted(object sender, System.EventArgs e) + { + this.NavigationService.GoBack(); + } + + protected abstract IEnumerable GetSelectorsOrderedByCulturePattern(); + + protected static IEnumerable GetSelectorsOrderedByCulturePattern(string pattern, char[] patternCharacters, LoopingSelector[] selectors) + { + if (pattern == null) + throw new ArgumentNullException("pattern"); + if (patternCharacters == null) + throw new ArgumentNullException("patternCharacters"); + if (selectors == null) + throw new ArgumentNullException("selectors"); + if (patternCharacters.Length != selectors.Length) + throw new ArgumentException("Arrays must contain the same number of elements."); + List> source = new List>(patternCharacters.Length); + for (int index = 0; index < patternCharacters.Length; ++index) + source.Add(new Tuple(pattern.IndexOf(patternCharacters[index]), selectors[index])); + return source.Where>((Func, bool>)(p => -1 != p.Item1)).OrderBy, int>((Func, int>)(p => p.Item1)).Select, LoopingSelector>((Func, LoopingSelector>)(p => p.Item2)).Where((Func)(s => null != s)); + } + + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + if (e == null) + throw new ArgumentNullException("e"); + base.OnNavigatedFrom(e); + if (!("app://external/" == e.Uri.ToString())) + return; + this.State["DateTimePickerPageBase_State_Value"] = (object)this.Value; + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + if (e == null) + throw new ArgumentNullException("e"); + base.OnNavigatedTo(e); + if (!this.State.ContainsKey("DateTimePickerPageBase_State_Value")) + return; + this.Value = this.State["DateTimePickerPageBase_State_Value"] as DateTime?; + if (!this.NavigationService.CanGoBack) + return; + this.NavigationService.GoBack(); + } + + public abstract void SetFlowDirection(FlowDirection flowDirection); + } + + public abstract class DataSource : ILoopingSelectorDataSource + { + private DateTimeWrapper _selectedItem; + + public object SelectedItem + { + get + { + return (object)this._selectedItem; + } + set + { + if (value == this._selectedItem) + return; + DateTimeWrapper dateTimeWrapper = (DateTimeWrapper)value; + if (dateTimeWrapper != null && this._selectedItem != null && !(dateTimeWrapper.DateTime != this._selectedItem.DateTime)) + return; + object selectedItem = (object)this._selectedItem; + this._selectedItem = dateTimeWrapper; + EventHandler selectionChanged = this.SelectionChanged; + if (selectionChanged == null) + return; + selectionChanged((object)this, new SelectionChangedEventArgs((IList)new object[1] + { + selectedItem + }, (IList)new object[1] + { + (object) this._selectedItem + })); + } + } + + public event EventHandler SelectionChanged; + + public object GetNext(object relativeTo) + { + DateTime? relativeTo1 = this.GetRelativeTo(((DateTimeWrapper)relativeTo).DateTime, 1); + if (!relativeTo1.HasValue) + return (object)null; + return (object)new DateTimeWrapper(relativeTo1.Value); + } + + public object GetPrevious(object relativeTo) + { + DateTime? relativeTo1 = this.GetRelativeTo(((DateTimeWrapper)relativeTo).DateTime, -1); + if (!relativeTo1.HasValue) + return (object)null; + return (object)new DateTimeWrapper(relativeTo1.Value); + } + + protected abstract DateTime? GetRelativeTo(DateTime relativeDate, int delta); + } + + public class YearDataSource : DataSource + { + private int _maxYear = DateTime.Now.Year; + + public int MaxYear + { + get { return _maxYear; } + set { _maxYear = value; } + } + + private int _minYear = 1900; + + public int MinYear + { + get { return _minYear; } + set { _minYear = value; } + } + + protected override DateTime? GetRelativeTo(DateTime relativeDate, int delta) + { + if (MinYear == relativeDate.Year && delta < 0 || MaxYear == relativeDate.Year && delta > 0) + return new DateTime?(); + int year = relativeDate.Year + delta; + int day = Math.Min(relativeDate.Day, DateTime.DaysInMonth(year, relativeDate.Month)); + return new DateTime?(new DateTime(year, relativeDate.Month, day, relativeDate.Hour, relativeDate.Minute, relativeDate.Second)); + } + } + + public class MonthDataSource : DataSource + { + protected override DateTime? GetRelativeTo(DateTime relativeDate, int delta) + { + int num = 12; + int month = (num + relativeDate.Month - 1 + delta) % num + 1; + int day = Math.Min(relativeDate.Day, DateTime.DaysInMonth(relativeDate.Year, month)); + return new DateTime?(new DateTime(relativeDate.Year, month, day, relativeDate.Hour, relativeDate.Minute, relativeDate.Second)); + } + } + + public class DayDataSource : DataSource + { + protected override DateTime? GetRelativeTo(DateTime relativeDate, int delta) + { + int num = DateTime.DaysInMonth(relativeDate.Year, relativeDate.Month); + int day = (num + relativeDate.Day - 1 + delta) % num + 1; + return new DateTime?(new DateTime(relativeDate.Year, relativeDate.Month, day, relativeDate.Hour, relativeDate.Minute, relativeDate.Second)); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/TelegramPopup.cs b/TelegramClient.WP81/Views/Controls/TelegramPopup.cs new file mode 100755 index 0000000..f9c2413 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/TelegramPopup.cs @@ -0,0 +1,523 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Media; +using System.Windows.Shapes; +using Microsoft.Phone.Controls; +using Microsoft.Phone.Shell; + +namespace TelegramClient.Views.Controls +{ + public class TelegramMessageBox : ContentControl + { + /// + /// Holds a weak reference to the message box that is currently displayed. + /// + private static WeakReference _currentInstance; + + /// + /// The current screen width. + /// + private static readonly double _screenWidth = Application.Current.Host.Content.ActualWidth; + + /// + /// The current screen height. + /// + private static readonly double _screenHeight = Application.Current.Host.Content.ActualHeight; + + /// + /// The height of the system tray in pixels when the page + /// is in portrait mode. + /// + private const double _systemTrayHeightInPortrait = 32.0; + + /// + /// The width of the system tray in pixels when the page + /// is in landscape mode. + /// + private const double _systemTrayWidthInLandscape = 72.0; + + /// + /// Identifies whether the application bar and the system tray + /// must be restored after the message box is dismissed. + /// + private static bool _mustRestore = true; + + /// + /// Left button template part. + /// + private Button _leftButton; + + /// + /// Right button template part. + /// + private Button _rightButton; + + /// + /// The popup used to display the message box. + /// + private Popup _popup; + + /// + /// The child container of the popup. + /// + private Grid _container; + + /// + /// The root visual of the application. + /// + private PhoneApplicationFrame _frame; + + /// + /// The current application page. + /// + private PhoneApplicationPage _page; + + /// + /// Identifies whether the application bar is visible or not before + /// opening the message box. + /// + private bool _hasApplicationBar; + + /// + /// The current color of the system tray. + /// + private Color _systemTrayColor; + + /// + /// Called when the message is being dismissing. + /// + public event EventHandler Dismissing; + + /// + /// Called when the message box is dismissed. + /// + public event EventHandler Dismissed; + + #region IsFullScreen DependencyProperty + + /// + /// Gets or sets whether the message box occupies the whole screen. + /// + public bool IsFullScreen + { + get { return (bool)GetValue(IsFullScreenProperty); } + set { SetValue(IsFullScreenProperty, value); } + } + + /// + /// Identifies the IsFullScreen dependency property. + /// + public static readonly DependencyProperty IsFullScreenProperty = + DependencyProperty.Register("IsFullScreen", typeof(bool), typeof(TelegramMessageBox), new PropertyMetadata(false, OnIsFullScreenPropertyChanged)); + + /// + /// Modifies the vertical alignment of the message box depending + /// on whether it should occupy the full screen or not. + /// + /// + /// + private static void OnIsFullScreenPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) + { + var target = (TelegramMessageBox)obj; + + if ((bool)e.NewValue) + { + target.VerticalAlignment = VerticalAlignment.Stretch; + } + else + { + target.VerticalAlignment = VerticalAlignment.Top; + } + } + + #endregion + + /// + /// Called when the back key is pressed. This event handler cancels + /// the backward navigation and dismisses the message box. + /// + /// The event sender. + /// The event information. + private void OnBackKeyPress(object sender, System.ComponentModel.CancelEventArgs e) + { + e.Cancel = true; + Dismiss(CustomMessageBoxResult.None, true); + } + + /// + /// Called when the application frame is navigating. + /// This event handler dismisses the message box. + /// + /// The event sender. + /// The event information. + private void OnNavigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e) + { + Dismiss(CustomMessageBoxResult.None, false); + } + + /// + /// Initializes a new instance of the CustomMessageBox class. + /// + public TelegramMessageBox() + : base() + { + //DefaultStyleKey = typeof(TelegramMessageBox); + } + + /// + /// Reveals the message box by inserting it into a popup and opening it. + /// + public void Show() + { + if (_popup != null) + { + if (_popup.IsOpen) + { + return; + } + } + + LayoutUpdated += CustomMessageBox_LayoutUpdated; + + _frame = Application.Current.RootVisual as PhoneApplicationFrame; + _page = _frame.Content as PhoneApplicationPage; + + // Change the color of the system tray if necessary. + if (SystemTray.IsVisible) + { + // Cache the original color of the system tray. + _systemTrayColor = SystemTray.BackgroundColor; + + // Change the color of the system tray to match the message box. + if (Background is SolidColorBrush) + { + SystemTray.BackgroundColor = ((SolidColorBrush)Background).Color; + } + else + { + SystemTray.BackgroundColor = (Color)Application.Current.Resources["PhoneChromeColor"]; + } + } + + // Hide the application bar if necessary. + if (_page.ApplicationBar != null) + { + // Cache the original visibility of the system tray. + _hasApplicationBar = _page.ApplicationBar.IsVisible; + + // Hide it. + if (_hasApplicationBar) + { + _page.ApplicationBar.IsVisible = false; + } + } + else + { + _hasApplicationBar = false; + } + + // Dismiss the current message box if there is any. + if (_currentInstance != null) + { + _mustRestore = false; + + var target = _currentInstance.Target as TelegramMessageBox; + + if (target != null) + { + _systemTrayColor = target._systemTrayColor; + _hasApplicationBar = target._hasApplicationBar; + target.Dismiss(); + } + } + + _mustRestore = true; + + // Insert the overlay. + Rectangle overlay = new Rectangle(); + Color backgroundColor = (Color)Application.Current.Resources["PhoneBackgroundColor"]; + overlay.Fill = new SolidColorBrush(Color.FromArgb(0x99, backgroundColor.R, backgroundColor.G, backgroundColor.B)); + _container = new Grid(); + //_container.Children.Add(overlay); + + // Insert the message box. + _container.Children.Add(this); + + // Create and open the popup. + _popup = new Popup(); + _popup.Child = _container; + SetSizeAndOffset(); + _popup.IsOpen = true; + _currentInstance = new WeakReference(this); + + // Attach event handlers. + if (_page != null) + { + _page.BackKeyPress += OnBackKeyPress; + _page.OrientationChanged += OnOrientationChanged; + } + + if (_frame != null) + { + _frame.Navigating += OnNavigating; + } + } + + /// + /// Dismisses the message box. + /// + public void Dismiss() + { + Dismiss(CustomMessageBoxResult.None, true); + } + + /// + /// Dismisses the message box. + /// + /// + /// The source that caused the dismission. + /// + /// + /// If true, the message box is dismissed after swiveling + /// backward and out. + /// + private void Dismiss(CustomMessageBoxResult source, bool useTransition) + { + // Handle the dismissing event. + var handlerDismissing = Dismissing; + if (handlerDismissing != null) + { + DismissingEventArgs args = new DismissingEventArgs(source); + handlerDismissing(this, args); + + if (args.Cancel) + { + return; + } + } + + // Handle the dismissed event. + var handlerDismissed = Dismissed; + if (handlerDismissed != null) + { + DismissedEventArgs args = new DismissedEventArgs(source); + handlerDismissed(this, args); + } + + // Set the current instance to null. + _currentInstance = null; + + // Cache this variable to avoid a race condition. + bool restoreOriginalValues = _mustRestore; + + // Close popup. + if (useTransition) + { + SwivelTransition backwardOut = new SwivelTransition { Mode = SwivelTransitionMode.BackwardOut }; + ITransition swivelTransition = backwardOut.GetTransition(this); + swivelTransition.Completed += (s, e) => + { + swivelTransition.Stop(); + ClosePopup(restoreOriginalValues); + }; + Deployment.Current.Dispatcher.BeginInvoke(swivelTransition.Begin); + } + else + { + ClosePopup(restoreOriginalValues); + } + } + + /// + /// Closes the pop up. + /// + private void ClosePopup(bool restoreOriginalValues) + { + if (_popup == null) return; + + // Remove the popup. + _popup.IsOpen = false; + _popup = null; + + if (_container != null) + { + _container.Children.Remove(this); + } + + // If there is no other message box displayed. + if (restoreOriginalValues) + { + // Set the system tray back to its original + // color if necessary. + if (SystemTray.IsVisible) + { + SystemTray.BackgroundColor = _systemTrayColor; + } + + // Bring the application bar if necessary. + if (_hasApplicationBar) + { + _hasApplicationBar = false; + _page.ApplicationBar.IsVisible = true; + } + } + + // Dettach event handlers. + if (_page != null) + { + _page.BackKeyPress -= OnBackKeyPress; + _page.OrientationChanged -= OnOrientationChanged; + _page = null; + } + + if (_frame != null) + { + _frame.Navigating -= OnNavigating; + _frame = null; + } + } + + /// + /// Called when the visual layout changes. + /// + /// The event sender. + /// The event information. + private void CustomMessageBox_LayoutUpdated(object sender, System.EventArgs e) + { + SwivelTransition backwardIn = new SwivelTransition { Mode = SwivelTransitionMode.BackwardIn }; + ITransition swivelTransition = backwardIn.GetTransition(this); + swivelTransition.Completed += (s1, e1) => swivelTransition.Stop(); + swivelTransition.Begin(); + LayoutUpdated -= CustomMessageBox_LayoutUpdated; + } + + /// + /// Called when the current page changes orientation. + /// + /// The event sender. + /// The event information. + private void OnOrientationChanged(object sender, OrientationChangedEventArgs e) + { + return; + SetSizeAndOffset(); + } + + /// + /// Sets The vertical and horizontal offset of the popup, + /// as well as the size of its child container. + /// + private void SetSizeAndOffset() + { + // Set the size the container. + Rect client = GetTransformedRect(); + if (_container != null) + { + _container.RenderTransform = GetTransform(); + + _container.Width = client.Width; + _container.Height = client.Height; + } + + // Set the vertical and horizontal offset of the popup. + if (SystemTray.IsVisible && _popup != null) + { + PageOrientation orientation = GetPageOrientation(); + + switch (orientation) + { + case PageOrientation.PortraitUp: + _popup.HorizontalOffset = 0.0; + _popup.VerticalOffset = _systemTrayHeightInPortrait; + _container.Height -= _systemTrayHeightInPortrait; + break; + case PageOrientation.LandscapeLeft: + _popup.HorizontalOffset = 0.0; + _popup.VerticalOffset = _systemTrayWidthInLandscape; + break; + case PageOrientation.LandscapeRight: + _popup.HorizontalOffset = 0.0; + _popup.VerticalOffset = 0.0; + break; + } + } + } + + /// + /// Gets a rectangle that occupies the entire page. + /// + /// The width, height and location of the rectangle. + private static Rect GetTransformedRect() + { + bool isLandscape = IsLandscape(GetPageOrientation()); + + return new Rect(0, 0, + isLandscape ? _screenHeight : _screenWidth, + isLandscape ? _screenWidth : _screenHeight); + } + + /// + /// Determines whether the orientation is landscape. + /// + /// The orientation. + /// True if the orientation is landscape. + private static bool IsLandscape(PageOrientation orientation) + { + return (orientation == PageOrientation.Landscape) || (orientation == PageOrientation.LandscapeLeft) || (orientation == PageOrientation.LandscapeRight); + } + + /// + /// Gets a transform for popup elements based + /// on the current page orientation. + /// + /// + /// A composite transform determined by page orientation. + /// + private static Transform GetTransform() + { + PageOrientation orientation = GetPageOrientation(); + + switch (orientation) + { + case PageOrientation.LandscapeLeft: + case PageOrientation.Landscape: + return new CompositeTransform() { Rotation = 90, TranslateX = _screenWidth }; + case PageOrientation.LandscapeRight: + return new CompositeTransform() { Rotation = -90, TranslateY = _screenHeight }; + default: + return null; + } + } + + /// + /// Gets the current page orientation. + /// + /// + /// The current page orientation. + /// + private static PageOrientation GetPageOrientation() + { + PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame; + + if (frame != null) + { + PhoneApplicationPage page = frame.Content as PhoneApplicationPage; + + if (page != null) + { + return page.Orientation; + } + } + + return PageOrientation.None; + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/TextingControl.xaml b/TelegramClient.WP81/Views/Controls/TextingControl.xaml new file mode 100755 index 0000000..cdea617 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/TextingControl.xaml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/TextingControl.xaml.cs b/TelegramClient.WP81/Views/Controls/TextingControl.xaml.cs new file mode 100755 index 0000000..1e25815 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/TextingControl.xaml.cs @@ -0,0 +1,31 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +namespace TelegramClient.Views.Controls +{ + public partial class TextingControl + { + public TextingControl() + { + InitializeComponent(); + + Loaded += (sender, args) => + { + Storyboard1.Begin(); + Storyboard2.Begin(); + Storyboard3.Begin(); + }; + + Unloaded += (sender, args) => + { + Storyboard1.Stop(); + Storyboard2.Stop(); + Storyboard3.Stop(); + }; + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/TypingControl.xaml b/TelegramClient.WP81/Views/Controls/TypingControl.xaml new file mode 100755 index 0000000..8261817 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/TypingControl.xaml @@ -0,0 +1,11 @@ + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Controls/TypingControl.xaml.cs b/TelegramClient.WP81/Views/Controls/TypingControl.xaml.cs new file mode 100755 index 0000000..3c32f23 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/TypingControl.xaml.cs @@ -0,0 +1,60 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// +using System.Windows; +using Telegram.Api.TL; + +namespace TelegramClient.Views.Controls +{ + public partial class TypingControl + { + public static readonly DependencyProperty TypingProperty = DependencyProperty.Register( + "Typing", typeof(Typing), typeof(TypingControl), new PropertyMetadata(default(Typing), OnTypingChanged)); + + private static void OnTypingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var typingControl = d as TypingControl; + if (typingControl != null) + { + var oldTyping = e.OldValue as Typing; + var newTyping = e.NewValue as Typing; + if (Typing.Equals(oldTyping, newTyping)) return; + + if (newTyping == null) + { + typingControl.Content = null; + } + else + { + switch (newTyping.Type) + { + case TypingType.Record: + typingControl.Content = new RecordingControl { Height = 26.0 }; + break; + case TypingType.Upload: + typingControl.Content = new UploadingControl { Height = 26.0 }; + break; + default: + typingControl.Content = new TextingControl { Height = 26.0 }; + break; + } + } + } + } + + public Typing Typing + { + get { return (Typing)GetValue(TypingProperty); } + set { SetValue(TypingProperty, value); } + } + + public TypingControl() + { + InitializeComponent(); + } + } +} diff --git a/TelegramClient.WP81/Views/Controls/UpdateAppControl.xaml b/TelegramClient.WP81/Views/Controls/UpdateAppControl.xaml new file mode 100755 index 0000000..d5d7b28 --- /dev/null +++ b/TelegramClient.WP81/Views/Controls/UpdateAppControl.xaml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Passport/EmailView.xaml.cs b/TelegramClient.WP81/Views/Passport/EmailView.xaml.cs new file mode 100755 index 0000000..dbae75d --- /dev/null +++ b/TelegramClient.WP81/Views/Passport/EmailView.xaml.cs @@ -0,0 +1,33 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System.Windows.Input; +using TelegramClient.ViewModels.Passport; + +namespace TelegramClient.Views.Passport +{ + public partial class EmailView + { + public EmailViewModel ViewModel + { + get { return DataContext as EmailViewModel; } + } + + public EmailView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + } + + private void DoneIcon_OnTap(object sender, GestureEventArgs e) + { + ViewModel.Done(); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Passport/EnterPasswordView.xaml b/TelegramClient.WP81/Views/Passport/EnterPasswordView.xaml new file mode 100755 index 0000000..cf4304a --- /dev/null +++ b/TelegramClient.WP81/Views/Passport/EnterPasswordView.xaml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Passport/PassportView.xaml.cs b/TelegramClient.WP81/Views/Passport/PassportView.xaml.cs new file mode 100755 index 0000000..655ed02 --- /dev/null +++ b/TelegramClient.WP81/Views/Passport/PassportView.xaml.cs @@ -0,0 +1,94 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System.ComponentModel; +using System.Linq; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.ViewModels; +using TelegramClient.ViewModels.Passport; +using TelegramClient.Views.Payments; + +namespace TelegramClient.Views.Passport +{ + public partial class PassportView + { + public PassportViewModel ViewModel + { + get { return DataContext as PassportViewModel; } + } + + public PassportView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + + Loaded += (sender, args) => + { + ViewModel.PropertyChanged += OnViewModelPropertyChanged; + }; + Unloaded += (sender, args) => + { + ViewModel.PropertyChanged -= OnViewModelPropertyChanged; + }; + } + + private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.Error)) + { + if (ViewModel.Error != null) + { + switch (ViewModel.Error) + { + case "REQUIRED_TYPE": + var type = ViewModel.RequiredTypes.FirstOrDefault(x => !x.IsCompleted); + if (type != null) + { + var control = Types.ItemContainerGenerator.ContainerFromItem(type) as FrameworkElement; + if (control != null) + { + ShippingInfoView.Shake(control); + } + } + break; + } + } + } + } + + private void AboutIcon_OnTap(object sender, GestureEventArgs e) + { + ShellViewModel.ShowCustomMessageBox( + AppResources.PassportInfo, AppResources.PassportInfoTitle, + AppResources.Ok); + } + + private void PassportView_OnBackKeyPress(object sender, CancelEventArgs e) + { + var popups = VisualTreeHelper.GetOpenPopups().ToList(); + var popup = popups.FirstOrDefault(); + if (popup != null) + { + e.Cancel = true; + + return; + } + + if (!ViewModel.IsCancelConfirmed) + { + e.Cancel = true; + ViewModel.Cancel(); + } + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Passport/PasswordIntroView.xaml b/TelegramClient.WP81/Views/Passport/PasswordIntroView.xaml new file mode 100755 index 0000000..b27e32d --- /dev/null +++ b/TelegramClient.WP81/Views/Passport/PasswordIntroView.xaml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Passport/PersonalDetailsView.xaml.cs b/TelegramClient.WP81/Views/Passport/PersonalDetailsView.xaml.cs new file mode 100755 index 0000000..dbb4cae --- /dev/null +++ b/TelegramClient.WP81/Views/Passport/PersonalDetailsView.xaml.cs @@ -0,0 +1,203 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Windows; +using System.Windows.Data; +using System.Windows.Input; +using Telegram.Api.TL; +using Telegram.Controls.Extensions; +using TelegramClient.Helpers; +using TelegramClient.Resources; +using TelegramClient.ViewModels.Passport; +using TelegramClient.Views.Payments; + +namespace TelegramClient.Views.Passport +{ + public partial class PersonalDetailsView + { + public PersonalDetailsViewModel ViewModel + { + get { return DataContext as PersonalDetailsViewModel; } + } + + public PersonalDetailsView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + + Loaded += (sender, args) => + { + ViewModel.PropertyChanged += OnViewModelPropertyChanged; + }; + Unloaded += (sender, args) => + { + ViewModel.PropertyChanged -= OnViewModelPropertyChanged; + }; + } + + private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.ImageViewer) + && ViewModel.ImageViewer != null) + { + ViewModel.ImageViewer.PropertyChanged += OnImageViewerPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.Error)) + { + if (ViewModel.Error != null) + { + var type = ViewModel.Error.GetErrorType(); + switch (type) + { + case ErrorType.ADDRESS_COUNTRY_INVALID: + ScrollIntoViewAndShake(SelectCountry); + break; + case ErrorType.ADDRESS_RESIDENCE_COUNTRY_INVALID: + ScrollIntoViewAndShake(SelectResidenceCountry); + break; + case ErrorType.FIRSTNAME_INVALID: + ScrollIntoViewAndShake(FirstNameLabel); + break; + case ErrorType.MIDDLENAME_INVALID: + ScrollIntoViewAndShake(MiddleNameLabel); + break; + case ErrorType.LASTNAME_INVALID: + ScrollIntoViewAndShake(LastNameLabel); + break; + case ErrorType.BIRTHDATE_INVALID: + ScrollIntoViewAndShake(SelectBirthDate); + break; + case ErrorType.GENDER_INVALID: + ScrollIntoViewAndShake(SelectGender); + break; + case ErrorType.DOCUMENT_NUMBER_INVALID: + ScrollIntoViewAndShake(DocumentNumberLabel); + break; + case ErrorType.EXPIRYDATE_INVALID: + ScrollIntoViewAndShake(SelectExpiryDate); + break; + case ErrorType.FIRSTNAMENATIVE_INVALID: + ScrollIntoViewAndShake(FirstNameNativeLabel); + break; + case ErrorType.MIDDLENAMENATIVE_INVALID: + ScrollIntoViewAndShake(MiddleNameNativeLabel); + break; + case ErrorType.LASTNAMENATIVE_INVALID: + ScrollIntoViewAndShake(LastNameNativeLabel); + break; + case ErrorType.FRONT_SIDE_REQUIRED: + ScrollIntoViewAndShake(AttachFrontSide); + ScrollIntoViewAndShake(FrontSide); + break; + case ErrorType.REVERSE_SIDE_REQUIRED: + ScrollIntoViewAndShake(AttachReverseSide); + ScrollIntoViewAndShake(ReverseSide); + break; + case ErrorType.SELFIE_REQUIRED: + ScrollIntoViewAndShake(AttachSelfie); + ScrollIntoViewAndShake(Selfie); + break; + case ErrorType.FILE_ERROR: + var frontSide = ViewModel.FrontSide as ISecureFileError; + var reverseSide = ViewModel.ReverseSide as ISecureFileError; + var selfie = ViewModel.Selfie as ISecureFileError; + if (frontSide != null && !string.IsNullOrEmpty(frontSide.Error)) + { + ScrollIntoViewAndShake(FrontSide); + } + else if (reverseSide != null && !string.IsNullOrEmpty(reverseSide.Error)) + { + ScrollIntoViewAndShake(ReverseSide); + } + else if (selfie != null && !string.IsNullOrEmpty(selfie.Error)) + { + ScrollIntoViewAndShake(Selfie); + } + break; + case ErrorType.TRANSLATION_EMPTY: + ScrollIntoViewAndShake(AttachTranslation); + break; + case ErrorType.TRANSLATION_ERROR: + if (ViewModel.Translations != null) + { + var file = ViewModel.Translations.OfType().FirstOrDefault(x => !string.IsNullOrEmpty(x.Error)); + if (file != null) + { + var control = Translations.ItemContainerGenerator.ContainerFromItem(file) as FrameworkElement; + if (control != null) + { + ScrollIntoViewAndShake(control); + } + } + } + break; + } + } + } + } + + private void ScrollIntoViewAndShake(FrameworkElement element) + { + var duration = TimeSpan.FromSeconds(0.15); + + Scroll.ScrollIntoView(element, 0.0, 128.0, duration); + Telegram.Api.Helpers.Execute.BeginOnUIThread(duration, () => ShippingInfoView.Shake(element)); + } + + private void OnImageViewerPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.ImageViewer.IsOpen)) + { + Scroll.IsHitTestVisible = !ViewModel.ImageViewer.IsOpen; + } + } + + private void DoneIcon_OnTap(object sender, GestureEventArgs e) + { + ViewModel.Done(); + } + } + + public class GenderToStringConverter : IValueConverter + { + public static string Convert(string gender) + { + if (string.Equals(gender, "male", StringComparison.OrdinalIgnoreCase)) + { + return AppResources.PassportMale; + } + if (string.Equals(gender, "female", StringComparison.OrdinalIgnoreCase)) + { + return AppResources.PassportFemale; + } + + return gender; + } + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var gender = value as string; + if (gender != null) + { + return Convert(gender); + } + + return value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Passport/PhoneNumberCodeView.xaml b/TelegramClient.WP81/Views/Passport/PhoneNumberCodeView.xaml new file mode 100755 index 0000000..4610b3d --- /dev/null +++ b/TelegramClient.WP81/Views/Passport/PhoneNumberCodeView.xaml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Passport/PhoneNumberCodeView.xaml.cs b/TelegramClient.WP81/Views/Passport/PhoneNumberCodeView.xaml.cs new file mode 100755 index 0000000..71ed053 --- /dev/null +++ b/TelegramClient.WP81/Views/Passport/PhoneNumberCodeView.xaml.cs @@ -0,0 +1,43 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; +using System.Windows; +using System.Windows.Input; +using Telegram.Api.Helpers; +using TelegramClient.ViewModels.Passport; + +namespace TelegramClient.Views.Passport +{ + public partial class PhoneNumberCodeView + { + public PhoneNumberCodeViewModel ViewModel + { + get { return DataContext as PhoneNumberCodeViewModel; } + } + + public PhoneNumberCodeView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + + Loaded += (sender, args) => Execute.BeginOnUIThread(TimeSpan.FromSeconds(0.3), () => Code.Focus()); + } + + private void ResendCode_OnClick(object sender, RoutedEventArgs e) + { + ViewModel.Resend(); + } + + private void DoneIcon_OnTap(object sender, GestureEventArgs e) + { + ViewModel.Confirm(); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Passport/PhoneNumberView.xaml b/TelegramClient.WP81/Views/Passport/PhoneNumberView.xaml new file mode 100755 index 0000000..edc0f7b --- /dev/null +++ b/TelegramClient.WP81/Views/Passport/PhoneNumberView.xaml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Passport/PhoneNumberView.xaml.cs b/TelegramClient.WP81/Views/Passport/PhoneNumberView.xaml.cs new file mode 100755 index 0000000..268b602 --- /dev/null +++ b/TelegramClient.WP81/Views/Passport/PhoneNumberView.xaml.cs @@ -0,0 +1,100 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System.Linq; +using System.Windows.Input; +using TelegramClient.ViewModels.Additional; +using TelegramClient.ViewModels.Passport; + +namespace TelegramClient.Views.Passport +{ + public partial class PhoneNumberView + { + public PhoneNumberViewModel ViewModel + { + get { return DataContext as PhoneNumberViewModel; } + } + + public PhoneNumberView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + } + + private void DoneIcon_OnTap(object sender, GestureEventArgs e) + { + ViewModel.Done(); + } + + private void PhoneNumber_OnKeyDown(object sender, KeyEventArgs args) + { + if (args.Key == Key.D8 || + args.Key == Key.Unknown || + args.Key == Key.D3 || + args.Key == Key.A || + args.Key == Key.Space) + { + args.Handled = true; + } + + if (args.Key == Key.Back && PhoneNumber.Text.Length == 0) + { + args.Handled = true; + PCode.Focus(); + PCode.Select(PCode.Text.Length, 0); + } + } + + private void PCode_OnKeyDown(object sender, KeyEventArgs args) + { + if (args.Key == Key.D8 || // * + args.Key == Key.Unknown || // +(long tap on 0) or -/. + args.Key == Key.D3 || // # + args.Key == Key.A) + { + + args.Handled = true; + } + + if (args.Key == Key.Space) + { + args.Handled = true; + PhoneNumber.Focus(); + } + + if (args.Key >= Key.NumPad0 && args.Key <= Key.NumPad9 + && PCode.Text.Length == 3) + { + var codeTail = string.Empty; + if (ViewModel.IsPhoneCodeInvalid) + { + var countryCode2 = CountryUtils.CountriesSource.FirstOrDefault(x => x.PhoneCode == PCode.Text.Substring(0, 2)); + if (countryCode2 != null) + { + codeTail = PCode.Text.Substring(2, 1); + PCode.Text = PCode.Text.Substring(0, 2); + } + + var countryCode1 = CountryUtils.CountriesSource.FirstOrDefault(x => x.PhoneCode == PCode.Text.Substring(0, 1)); + if (countryCode1 != null) + { + codeTail = PCode.Text.Substring(1, 2); + PCode.Text = PCode.Text.Substring(0, 1); + } + } + + + args.Handled = true; + PhoneNumber.Text = codeTail + args.Key.ToString().Replace("NumPad", string.Empty) + PhoneNumber.Text; + PhoneNumber.SelectionStart = codeTail.Length + 1; + PhoneNumber.Focus(); + } + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Passport/ResidentialAddressView.xaml b/TelegramClient.WP81/Views/Passport/ResidentialAddressView.xaml new file mode 100755 index 0000000..b067b2c --- /dev/null +++ b/TelegramClient.WP81/Views/Passport/ResidentialAddressView.xaml @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Passport/ResidentialAddressView.xaml.cs b/TelegramClient.WP81/Views/Passport/ResidentialAddressView.xaml.cs new file mode 100755 index 0000000..e44eb05 --- /dev/null +++ b/TelegramClient.WP81/Views/Passport/ResidentialAddressView.xaml.cs @@ -0,0 +1,165 @@ +// +// This is the source code of Telegram for Windows Phone v. 3.x.x. +// It is licensed under GNU GPL v. 2 or later. +// You should have received a copy of the license in this archive (see LICENSE). +// +// Copyright Evgeny Nadymov, 2013-present. +// + +using System; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Input; +using Telegram.Api.TL; +using Telegram.Controls.Extensions; +using TelegramClient.Helpers; +using TelegramClient.ViewModels.Passport; +using TelegramClient.Views.Payments; + +namespace TelegramClient.Views.Passport +{ + public partial class ResidentialAddressView + { + public ResidentialAddressViewModel ViewModel + { + get { return DataContext as ResidentialAddressViewModel; } + } + + public ResidentialAddressView() + { + InitializeComponent(); + + Caption.Background = ShellView.CaptionBrush; + + Loaded += (sender, args) => + { + ViewModel.PropertyChanged += OnViewModelPropertyChanged; + }; + Unloaded += (sender, args) => + { + ViewModel.PropertyChanged -= OnViewModelPropertyChanged; + }; + } + + private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.ImageViewer) + && ViewModel.ImageViewer != null) + { + ViewModel.ImageViewer.PropertyChanged += OnImageViewerPropertyChanged; + } + else if (Property.NameEquals(e.PropertyName, () => ViewModel.Error)) + { + if (ViewModel.Error != null) + { + var type = ViewModel.Error.GetErrorType(); + switch (type) + { + case ErrorType.ADDRESS_COUNTRY_INVALID: + ScrollIntoViewAndShake(SelectCountry); + break; + case ErrorType.ADDRESS_CITY_INVALID: + ScrollIntoViewAndShake(CityLabel.Input, CityLabel.Input); + break; + case ErrorType.ADDRESS_POSTCODE_INVALID: + ScrollIntoViewAndShake(PostCodeLabel.Input, PostCodeLabel.Input); + break; + case ErrorType.ADDRESS_STATE_INVALID: + ScrollIntoViewAndShake(StateLabel.Input, StateLabel.Input); + break; + case ErrorType.ADDRESS_STREET_LINE2_INVALID: + ScrollIntoViewAndShake(StreetLine2Label.Input, StreetLine2Label.Input); + break; + case ErrorType.ADDRESS_STREET_LINE1_INVALID: + ScrollIntoViewAndShake(StreetLine1Label.Input, StreetLine1Label.Input); + break; + case ErrorType.FILES_EMPTY: + ScrollIntoViewAndShake(AttachDocument); + break; + case ErrorType.FILE_ERROR: + { + var file = ViewModel.Files.OfType().FirstOrDefault(x => !string.IsNullOrEmpty(x.Error)); + if (file != null) + { + var control = Files.ItemContainerGenerator.ContainerFromItem(file) as FrameworkElement; + if (control != null) + { + ScrollIntoViewAndShake(control); + } + } + break; + } + case ErrorType.TRANSLATION_EMPTY: + ScrollIntoViewAndShake(AttachTranslation); + break; + case ErrorType.TRANSLATION_ERROR: + if (ViewModel.Translations != null) + { + var file = ViewModel.Translations.OfType().FirstOrDefault(x => !string.IsNullOrEmpty(x.Error)); + if (file != null) + { + var control = Translations.ItemContainerGenerator.ContainerFromItem(file) as FrameworkElement; + if (control != null) + { + ScrollIntoViewAndShake(control); + } + } + } + break; + } + } + } + } + + private void ScrollIntoViewAndShake(FrameworkElement element) + { + var duration = TimeSpan.FromSeconds(0.15); + + Scroll.ScrollIntoView(element, 0.0, 128.0, duration); + Telegram.Api.Helpers.Execute.BeginOnUIThread(duration, () => ShippingInfoView.Shake(element)); + } + + private void ScrollIntoViewAndShake(FrameworkElement element, TextBox focusElement) + { + var duration = TimeSpan.FromSeconds(0.15); + + Scroll.ScrollIntoView(element, 0.0, 128.0, duration); + Telegram.Api.Helpers.Execute.BeginOnUIThread(duration, () => ShippingInfoView.Shake(element, focusElement)); + } + + private void OnImageViewerPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (Property.NameEquals(e.PropertyName, () => ViewModel.ImageViewer.IsOpen)) + { + Scroll.IsHitTestVisible = !ViewModel.ImageViewer.IsOpen; + } + } + + private void DoneIcon_OnTap(object sender, GestureEventArgs e) + { + ViewModel.Done(); + } + } + + public class FileUploadingToOpacityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is bool) + { + return (bool) value ? 0.5 : 1.0; + } + + return 1.0; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/TelegramClient.WP81/Views/Payments/CardInfoView.xaml b/TelegramClient.WP81/Views/Payments/CardInfoView.xaml new file mode 100755 index 0000000..af13946 --- /dev/null +++ b/TelegramClient.WP81/Views/Payments/CardInfoView.xaml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +